diff options
Diffstat (limited to 'tex')
538 files changed, 45603 insertions, 28083 deletions
diff --git a/tex/context/base/anch-bar.mkiv b/tex/context/base/anch-bar.mkiv index 9f9770fb6..c7c6190be 100644 --- a/tex/context/base/anch-bar.mkiv +++ b/tex/context/base/anch-bar.mkiv @@ -58,7 +58,9 @@ \installcommandhandler \??sidebar {sidebar} \??sidebar \newcount\c_anch_sidebars_n -\newdimen\c_anch_sidebars_distance +\newcount\c_anch_sidebars_current % local +\newdimen\d_anch_sidebars_distance +\newcount\c_anch_sidebars_level % \setupMPvariables % [mpos:sidebar] @@ -67,24 +69,60 @@ % distance=5pt] \setupsidebar - [\c!rulethickness=2pt, + [\c!rulethickness=\dimexpr\bodyfontsize/6\relax, % 2pt default \c!rulecolor=\s!black, \c!alternative=0, - \c!topoffset=0pt, - \c!bottomoffset=0pt, - \c!distance=.5\bodyfontsize] + \c!topoffset=\zeropoint, + \c!bottomoffset=\zeropoint, + \c!distance=.5\bodyfontsize, + \c!level=, + \c!leftmargindistance=\zeropoint] \let\setupsidebars\setupsidebar \unexpanded\def\startsidebar {\dosingleempty\anch_sidebars_start} -\def\anch_sidebars_start[#1]% +\unexpanded\def\startsidebar + {\dodoubleempty\anch_sidebars_start} + +\def\anch_sidebars_start[#1][#2]% {\bgroup - \def\currentsidebar{#1}% \dontleavehmode + \advance\c_anch_sidebars_level\plusone \global\advance\c_anch_sidebars_n\plusone - \advance\c_anch_sidebars_distance\sidebarparameter\c!distance + \c_anch_sidebars_current\c_anch_sidebars_n\relax % relax needed + \doifassignmentelse{#1} + {\edef\currentsidebar{\the\c_anch_sidebars_level}% + \checksidebarparent + \setupcurrentsidebar[#1]} + {\def\currentsidebar{#1}% + \setupcurrentsidebar[#2]}% + \scratchdistance\sidebarparameter\c!distance\relax + \edef\m_level{\sidebarparameter\c!level}% + \ifx\m_level\empty + \ifnum\c_anch_sidebars_level=\plusone + \scratchdimen\sidebarparameter\c!leftmargindistance\relax + \ifdim\scratchdimen=\zeropoint + \advance\d_anch_sidebars_distance\scratchdistance\relax + \else + \d_anch_sidebars_distance\scratchdimen + \fi + \else + \advance\d_anch_sidebars_distance\scratchdistance\relax + \fi + \else + \ifnum\m_level=\plusone + \scratchdimen\sidebarparameter\c!leftmargindistance\relax + \ifdim\scratchdimen=\zeropoint + \advance\d_anch_sidebars_distance\scratchdistance\relax + \else + \d_anch_sidebars_distance\scratchdimen + \fi + \else + \d_anch_sidebars_distance\dimexpr\scratchdimen+\numexpr\m_level-\plusone\relax\dimexpr\scratchdistance\relax\relax + \fi + \fi \startpositionoverlay{text-1}% \normalexpanded{\setMPpositiongraphicrange % maybe expand in definition {b:sidebar:\the\c_anch_sidebars_n}% @@ -94,15 +132,17 @@ linewidth=\sidebarparameter\c!rulethickness, linecolor=\sidebarparameter\c!rulecolor, alternative=\sidebarparameter\c!alternative, - topoffset=\sidebarparameter\c!topoffset, - bottomoffset=\sidebarparameter\c!bottomoffset, - distance=\the\c_anch_sidebars_distance}}% + topoffset=\the\dimexpr\sidebarparameter\c!topoffset, + bottomoffset=\the\dimexpr\sidebarparameter\c!bottomoffset, + distance=\the\d_anch_sidebars_distance}% + }% \stoppositionoverlay - \bpos{sidebar:\the\c_anch_sidebars_n}} + \bpos{sidebar:\the\c_anch_sidebars_current}% + \ignorespaces} \unexpanded\def\stopsidebar {\removelastspace - \epos{sidebar:\the\c_anch_sidebars_n} + \epos{sidebar:\the\c_anch_sidebars_current} \carryoverpar\egroup} %D Let's keep this nice and simple (okay, we could pass the 6 variables in @@ -121,49 +161,73 @@ \MPpositiongraphic{mpos:sidebar}{}% \stopMPpositionmethod -%D We now reimplement the margin rules handler defined in -%D \type {core-rul}: +%D We now reimplement the \MKII\ margin rules handler in a more +%D modern way. %D -%D \setupmarginrules[level=5] +%D \setupmarginrules +%D [rulecolor=darkred, +%D rulethickness=2pt] %D -%D \startmarginrule[1] -%D First we set the level at~5. Next we typeset this first -%D paragraph as a level~1 one. As expected no rule show up. -%D \stopmarginrule +%D \setupmarginrules % sidebar +%D [2] +%D [rulecolor=darkblue] %D -%D \startmarginrule[5] -%D The second paragraph is a level~5 one. As we can see here, -%D the marginal rule gets a width according to its level. +%D \startmarginrule[1] +%D \input ward +%D \startmarginrule[2] +%D \input ward +%D \startmarginrule[3] +%D \input ward +%D \startmarginrule[level=6,rulecolor=darkgreen] +%D \input ward +%D \stopmarginrule +%D \input ward +%D \stopmarginrule +%D \input ward +%D \stopmarginrule +%D \input ward %D \stopmarginrule %D -%D \startmarginrule[8] -%D It will of course be no surprise that this third paragraph -%D has a even thicker margin rule. This behavior can be -%D overruled by specifying the width explictly. -%D \stopmarginrule +%D Compared to the old mechanism we now can pass settings too. \definesidebar [\v!margin] - [\c!rulethickness=\@@karulethickness, - \c!distance=\dimexpr\leftmargindistance-\@@karulethickness/2\relax] + [\c!leftmargindistance=\dimexpr\leftmargindistance+\sidebarparameter\c!rulethickness/2\relax] -\definecomplexorsimple\startmarginrule +\dorecurse{5}{\definesidebar[\v!margin:#1][\v!margin]} % let's be nice and predefine 5 levels -\def\simplestartmarginrule - {\complexstartmarginrule[1]} +\unexpanded\def\setupmarginrule + {\dodoubleargument\anch_marginrules_setup} -\def\complexstartmarginrule[#1]% - {\bgroup - \ifnum#1<\@@kalevel\relax - \let\stopmarginrule\egroup +\def\anch_marginrules_setup[#1][#2]% + {\ifsecondargument + \setupsidebar[\v!margin:#1][#2]% \else - \def\@@kadefaultwidth{#1}% - \let\stopmarginrule\dostopmarginrule - \normalexpanded{\startsidebar[\v!margin]}% why expanded + \setupsidebar[\v!margin][#1]% \fi} -\def\dostopmarginrule - {\stopsidebar - \egroup} +\let\setupmarginrules\setupmarginrule + +\unexpanded\def\startmarginrule + {\dosingleempty\anch_marginrules_start} + +\unexpanded\def\startmarginrule + {\dosingleempty\anch_marginrules_start} + +\def\anch_marginrules_start[#1]% pretty inefficient checking + {\edef\m_anch_marginrules_kind{#1}% + \ifx\m_anch_marginrules_kind\empty + \anch_sidebars_start[\v!margin][]% + \else + \doifassignmentelse\m_anch_marginrules_kind + {\anch_sidebars_start[\v!margin][#1]}% + {\anch_marginrules_check{#1}% + \anch_sidebars_start[\v!margin:#1][\c!level=#1]}% + \fi} + +\def\anch_marginrules_check#1% + {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}} + +\let\stopmarginrule\stopsidebar \protect \endinput diff --git a/tex/context/base/anch-bck.mkvi b/tex/context/base/anch-bck.mkvi index 8ec056468..79e42dc0a 100644 --- a/tex/context/base/anch-bck.mkvi +++ b/tex/context/base/anch-bck.mkvi @@ -276,7 +276,7 @@ \kern\textbackgroundskip\nobreak \fi \fi \nobreak - \vskip-\dimexpr\lineheight+\parskip\relax + \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent \nobreak \endgroup \begingroup @@ -298,7 +298,7 @@ \endgraf % new \textbackgroundparameter\c!after} -\unexpanded\def\checkpositionoverlays +\unexpanded\def\checkpositionoverlays % overloads \relax in anch-pgr {\ifproductionrun \enabletextarearegistration \enablehiddenbackground @@ -307,7 +307,7 @@ \setuptextbackground [\c!mp=mpos:region:draw, - \c!method=mpos:region, + \c!method=mpos:region, % mpos:regionshape \c!state=\v!start, \c!location=\v!text, \c!leftoffset=\!!zeropoint, % 1em, @@ -397,6 +397,14 @@ \includeMPgraphic{mpos:region:anchor} ; \stopMPpositiongraphic +\startMPpositiongraphic{mpos:regionshape}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset} + \includeMPgraphic{mpos:region:setup} ; + \includeMPgraphic{mpos:region:extra} ; + \MPgetmultishapes{\MPvar{self}}{\MPanchorid} ; + \includeMPgraphic{\MPvar{mp}} ; + \includeMPgraphic{mpos:region:anchor} ; +\stopMPpositiongraphic + \startMPpositionmethod{mpos:region} \MPpositiongraphic{mpos:region}{}% \stopMPpositionmethod diff --git a/tex/context/base/anch-pgr.lua b/tex/context/base/anch-pgr.lua index bf4dcbe02..aba61794b 100644 --- a/tex/context/base/anch-pgr.lua +++ b/tex/context/base/anch-pgr.lua @@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['anch-pgr'] = { -- todo: we need to clean up lists (of previous pages) +local commands, context = commands, context + local format = string.format local abs = math.abs local concat, sort = table.concat, table.sort @@ -47,34 +49,48 @@ end local eps = 2 -local function add(t,x,y,last) +local function add(t,x,y,last,direction) local n = #t if n == 0 then t[n+1] = { x, y } - elseif n == 1 then - local tn = t[1] - if abs(tn[1]-x) <= eps or abs(tn[2]-y) <= eps then - t[n+1] = { x, y } - end else - local tm = t[n-1] local tn = t[n] local lx = tn[1] local ly = tn[2] - if abs(lx-tm[1]) <= eps and abs(lx-x) <= eps then - if abs(ly-y) > eps then - tn[2] = y + if x == lx and y == ly then + -- quick skip + elseif n == 1 then +-- if abs(lx-x) <= eps or abs(ly-y) <= eps then + if abs(lx-x) > eps or abs(ly-y) > eps then + t[n+1] = { x, y } end - elseif abs(ly-tm[2]) <= eps and abs(ly-y) <= eps then - if abs(lx-x) > eps then - tn[1] = x + else + local tm = t[n-1] + local px = tm[1] + local py = tm[2] +if (direction == "down" and y > ly) or (direction == "up" and y < ly) then + -- move back from too much hang +else + if abs(lx-px) <= eps and abs(lx-x) <= eps then + if abs(ly-y) > eps then + tn[2] = y + end + elseif abs(ly-py) <= eps and abs(ly-y) <= eps then + if abs(lx-x) > eps then + tn[1] = x + end + elseif not last then + t[n+1] = { x, y } end - elseif not last then - t[n+1] = { x, y } +end end end end +-- local function add(t,x,y,last) +-- t[#t+1] = { x, y } +-- end + local function finish(t) local n = #t if n > 1 then @@ -109,105 +125,103 @@ end -- todo: mark regions and free paragraphs in collected -local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot) +local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang) -- we assume that we only hang per page and not cross pages -- which makes sense as hanging is only uses in special cases -- -- we can remove data as soon as a page is done so we could -- remember per page and discard areas after each shipout local leftshape, rightshape --- leftshape = r.leftshape --- rightshape = r.rightshape --- if not leftshape then - leftshape = { { rx, rh } } - rightshape = { { rw, rh } } - local paragraphs = r.paragraphs - local extending = false - if paragraphs then - for i=1,#paragraphs do - local p = paragraphs[i] - local ha = p.ha - if ha and ha ~= 0 then + leftshape = { { rx, rh } } -- spikes get removed so we can start at the edge + rightshape = { { rw, rh } } -- even if we hang next + local paragraphs = r.paragraphs + local extending = false + if paragraphs then + for i=1,#paragraphs do + local p = paragraphs[i] + local ha = p.ha + if obeyhang and ha and ha ~= 0 then + local py = p.y + local ph = p.h + local pd = p.d + local hi = p.hi + local hang = ha * (ph + pd) + local py_ph = py + ph + -- ha < 0 hi < 0 : right top + -- ha < 0 hi > 0 : left top + if ha < 0 then + if hi < 0 then -- right + add(rightshape,rw, py_ph,"up") + add(rightshape,rw + hi,py_ph,"up") + add(rightshape,rw + hi,py_ph + hang,"up") + add(rightshape,rw, py_ph + hang,"up") + else + -- left + add(leftshape,rx,py_ph,"down") + add(leftshape,rx + hi,py_ph,"down") + add(leftshape,rx + hi,py_ph + hang,"down") + add(leftshape,rx,py_ph + hang,"down") + end + else + -- maybe some day + end + extending = true -- false + else -- we need to clip to the next par + local ps = p.ps + if ps then local py = p.y local ph = p.h local pd = p.d - local hi = p.hi - local hang = ha * (ph + pd) + local step = ph + pd + local size = #ps * step local py_ph = py + ph - -- ha < 0 hi < 0 : right top - -- ha < 0 hi > 0 : left top - if ha < 0 then - if hi < 0 then -- right - add(rightshape,rw , py_ph) - add(rightshape,rw + hi, py_ph) - add(rightshape,rw + hi, py_ph + hang) - add(rightshape,rw , py_ph + hang) - else - -- left - add(leftshape,rx, py_ph) - add(leftshape,rx + hi, py_ph) - add(leftshape,rx + hi, py_ph + hang) - add(leftshape,rx, py_ph + hang) - end - end -extending = false - else -- we need to clip to the next par - local ps = p.ps - if ps then - local py = p.y - local ph = p.h - local pd = p.d - local step = ph + pd - local size = #ps * step - local py_ph = py + ph - add(leftshape,rx,py_ph) - add(rightshape,rw,py_ph) - for i=1,#ps do - local p = ps[i] - local l = p[1] - local w = p[2] - add(leftshape,rx + l, py_ph) - add(rightshape,rx + l + w, py_ph) - py_ph = py_ph - step - add(leftshape,rx + l, py_ph) - add(rightshape,rx + l + w, py_ph) - end - extending = true --- add(left,rx,py_ph) --- add(right,rw,py_ph) - else - if extending then - local py = p.y - local ph = p.h - local pd = p.d - local py_ph = py + ph - local py_pd = py - pd - add(leftshape,leftshape[#leftshape][1],py_ph) - add(rightshape,rightshape[#rightshape][1],py_ph) - add(leftshape,rx,py_ph) - add(rightshape,rw,py_ph) -extending = false - end + add(leftshape,rx,py_ph,"up") + add(rightshape,rw,py_ph,"down") + for i=1,#ps do + local p = ps[i] + local l = p[1] + local w = p[2] + add(leftshape,rx + l, py_ph,"up") + add(rightshape,rx + l + w, py_ph,"down") + py_ph = py_ph - step + add(leftshape,rx + l, py_ph,"up") + add(rightshape,rx + l + w, py_ph,"down") end + extending = true + elseif extending then + local py = p.y + local ph = p.h + local pd = p.d + local py_ph = py + ph + local py_pd = py - pd + add(leftshape,leftshape[#leftshape][1],py_ph,"up") + add(rightshape,rightshape[#rightshape][1],py_ph,"down") + add(leftshape,rx,py_ph,"up") -- shouldn't this be py_pd + add(rightshape,rw,py_ph,"down") -- shouldn't this be py_pd + extending = false end end end - -- we can have a simple variant when no paragraphs - if extending then - -- not ok - leftshape[#leftshape][2] = rd - rightshape[#rightshape][2] = rw - else - add(leftshape,rx,rd) - add(rightshape,rw,rd) - end --- r.leftshape = leftshape --- r.rightshape = rightshape --- end + end + -- we can have a simple variant when no paragraphs + if extending then + -- not ok + leftshape[#leftshape][2] = rd + rightshape[#rightshape][2] = rw + else + add(leftshape,rx,rd,"up") + add(rightshape,rw,rd,"down") + end return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot) end -local function singlepart(b,e,r,left,right) +-- local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang) +-- local leftshape = { { rx, rh }, { rx, rd } } +-- local rightshape = { { rw, rh }, { rw, rd } } +-- return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot) +-- end + +local function singlepart(b,e,r,left,right,obeyhang) local bx, by = b.x, b.y local ex, ey = e.x, e.y local rx, ry = r.x, r.y @@ -238,7 +252,7 @@ local function singlepart(b,e,r,left,right) } else area = { } - local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh) + local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh,obeyhang) add(area,bx,bh-ry) for i=1,#rightshapes do local ri = rightshapes[i] @@ -265,7 +279,7 @@ local function singlepart(b,e,r,left,right) } end -local function firstpart(b,r,left,right) +local function firstpart(b,r,left,right,obeyhang) local bx, by = b.x, b.y local rx, ry = r.x, r.y local rw = rx + r.w @@ -278,7 +292,7 @@ local function firstpart(b,r,left,right) local bh = by + b.h local bd = by - b.d local area = { } - local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd) + local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd,obeyhang) add(area,bx,bh-ry) for i=1,#rightshapes do local ri = rightshapes[i] @@ -302,7 +316,7 @@ local function firstpart(b,r,left,right) } end -local function middlepart(r,left,right) +local function middlepart(r,left,right,obeyhang) local rx, ry = r.x, r.y local rw = rx + r.w local rh = ry + r.h @@ -312,7 +326,7 @@ local function middlepart(r,left,right) rw = rw - right end local area = { } - local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd) + local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd,obeyhang) for i=#leftshapes,1,-1 do local li = leftshapes[i] add(area,li[1],li[2]-ry) @@ -333,7 +347,7 @@ local function middlepart(r,left,right) } end -local function lastpart(e,r,left,right) +local function lastpart(e,r,left,right,obeyhang) local ex, ey = e.x, e.y local rx, ry = r.x, r.y local rw = rx + r.w @@ -347,7 +361,7 @@ local function lastpart(e,r,left,right) local ed = ey - e.d local area = { } -- two cases: till end and halfway e line - local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh) + local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh,obeyhang) for i=1,#rightshapes do local ri = rightshapes[i] add(area,ri[1],ri[2]-ry) @@ -375,7 +389,7 @@ local backgrounds = { } graphics.backgrounds = backgrounds -local function calculatemultipar(tag) +local function calculatemultipar(tag,obeyhang) local collected = jobpositions.collected local b = collected[format("b:%s",tag)] local e = collected[format("e:%s",tag)] @@ -429,13 +443,13 @@ local function calculatemultipar(tag) -- if bindex == eindex then return { - list = { [b.p] = { singlepart(b,e,collected[br],left,right) } }, + list = { [b.p] = { singlepart(b,e,collected[br],left,right,obeyhang) } }, bpos = b, epos = e, } else local list = { - [b.p] = { firstpart(b,collected[br],left,right) }, + [b.p] = { firstpart(b,collected[br],left,right,obeyhang) }, } for i=bindex+1,eindex-1 do br = format("%s:%s",btag,i) @@ -446,18 +460,18 @@ local function calculatemultipar(tag) local p = r.p local pp = list[p] if pp then - pp[#pp+1] = middlepart(r,left,right) + pp[#pp+1] = middlepart(r,left,right,obeyhang) else - list[p] = { middlepart(r,left,right) } + list[p] = { middlepart(r,left,right,obeyhang) } end end end local p = e.p local pp = list[p] if pp then - pp[#pp+1] = lastpart(e,collected[er],left,right) + pp[#pp+1] = lastpart(e,collected[er],left,right,obeyhang) else - list[p] = { lastpart(e,collected[er],left,right) } + list[p] = { lastpart(e,collected[er],left,right,obeyhang) } end return { list = list, @@ -537,10 +551,10 @@ local template_d = [[ setbounds currentpicture to multibox ; ]] -function backgrounds.fetchmultipar(n,anchor,page) +function backgrounds.fetchmultipar(n,anchor,page,obeyhang) local data = pbg[n] if not data then - data = calculatemultipar(n) + data = calculatemultipar(n,obeyhang) pbg[n] = data -- can be replaced by register -- register(data.list,n,anchor) end @@ -590,6 +604,10 @@ function commands.fetchmultipar(n,anchor,page) context(backgrounds.fetchmultipar(n,anchor,page)) end +function commands.fetchmultishape(n,anchor,page) + context(backgrounds.fetchmultipar(n,anchor,page,true)) +end + local template_a = [[ path posboxes[], posregions[] ; numeric pospages[] ; @@ -642,10 +660,10 @@ end local doifelse = commands.doifelse -function commands.doifelsemultipar(n,page) +function commands.doifelsemultipar(n,page,obeyhang) local data = pbg[n] if not data then - data = calculatemultipar(n) + data = calculatemultipar(n,obeyhang) pbg[n] = data end if page then diff --git a/tex/context/base/anch-pgr.mkiv b/tex/context/base/anch-pgr.mkiv index a417d26e3..01ef25dc4 100644 --- a/tex/context/base/anch-pgr.mkiv +++ b/tex/context/base/anch-pgr.mkiv @@ -33,7 +33,7 @@ \installcorenamespace{positionaction} \installcorenamespace{positioncleanup} -\unexpanded\def\dosetpositionaction#1% +\unexpanded\def\anch_positions_set_action#1% {\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces \unexpanded\def\doifpositionaction#1% @@ -111,7 +111,7 @@ {\begingroup \edef\currentpositionanchor {\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}% - \normalexpanded{\dosetpositionaction{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}% + \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}% \let#1\relax \ifcsname\??positioncleanup\currentpositionanchor\endcsname \setxvalue{\??positioncleanup\currentpositionanchor}% @@ -140,9 +140,6 @@ \fi \fi\fi} -% \def\anch_positions_register_page_indeed#1% -% {\setbox#1\hbox{\hpos\pageanchor{\box#1}}} - \def\anch_positions_register_page_indeed#1% maybe like text {\ifvbox#1\setbox#1\hbox{\box#1}\fi \anch_make_page_box{#1}} @@ -218,7 +215,6 @@ %D \typebuffer[graphic] \def\MPanchoridentifier{mpa} % {mp-anchor} -%def\MPoverlayposprefix{MO::} % not used %D The rest of the definitions concerning such overlays may %D look complicated, @@ -237,8 +233,8 @@ \def\textbackgroundoverlay#1{\v!text#1} \def\MPanchornumber {\the\realpageno} -\def\positionoverlay % the test prevents too many redundant positions - {\ifpositioning % in (not used) text* position layers +\unexpanded\def\positionoverlay % the test prevents too many redundant positions + {\ifpositioning % in (not used) text* position layers \expandafter\anch_positions_overlay_indeed \else % also \iftrialtypesetting test here? \expandafter\gobbleoneargument @@ -269,7 +265,7 @@ \box\scratchbox \vfill}} -\def\positionregionoverlay % shares regions +\unexpanded\def\positionregionoverlay % shares regions {\ifpositioning \expandafter\anch_positions_region_overlay_indeed \else % also \iftrialtypesetting test here? @@ -308,9 +304,15 @@ \expandafter\anch_positions_overlay_start_yes \fi} +\let\stoppositionoverlay\relax + \def\anch_positions_overlay_start_nop#1\stoppositionoverlay {} +\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi + +\let\currentpositionoverlay\empty + \def\anch_positions_overlay_start_yes#1% {\checkpositionoverlays \edef\currentpositionoverlay{#1}} @@ -318,9 +320,11 @@ \unexpanded\def\stoppositionoverlay {\let\currentpositionoverlay\empty} +% needs checking if still needed +% % \def\resetpositionoverlay#1% -% {\dosetpositionaction{#1::\MPanchoridentifier::}{}} - +% {\anch_positions_set_action{#1::\MPanchoridentifier::}{}} +% % \def\handlepositionboxes#1#2#3% % {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}} % @@ -332,15 +336,15 @@ % \appendtoks % \let\dohandlepositionboxes\doinsertpositionboxes % was handle ? % \to \everyinsertpositionaction - -\def\docleanpositionboxes#1#2#3% pos tag setups - {\ifnum\MPp{#1}<\realpageno \else - \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert - \fi} - -\appendtoks - \let\dohandlepositionboxes\docleanpositionboxes -\to \everycleanpositionaction +% +% \def\docleanpositionboxes#1#2#3% pos tag setups +% {\ifnum\MPp{#1}<\realpageno \else +% \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert +% \fi} +% +% \appendtoks +% \let\dohandlepositionboxes\docleanpositionboxes +% \to \everycleanpositionaction %D A position graphic is a normal (non||reused) \METAPOST\ %D graphic, used immediately, with zero dimensions, so that a @@ -350,7 +354,7 @@ \installcorenamespace{positionmethod} %installcorenamespace{graphicvariable} -\newbox\positiongraphicbox +\newbox\b_anch_positions_graphic \def\startMPpositiongraphic % id setups {\dodoublegroupempty\anch_positions_meta_graphic_start} @@ -361,11 +365,11 @@ \let\stopMPpositiongraphic\relax \def\anch_positions_meta_graphic_prepare - {\ifcsname\??gv\currentmpvariableclass:self\endcsname \else - \letvalue{\??gv\currentmpvariableclass:self}\currentposition + {\ifcsname\??graphicvariable\currentmpvariableclass:self\endcsname \else + \letvalue{\??graphicvariable\currentmpvariableclass:self}\currentposition \fi - \ifcsname\??gv\currentmpvariableclass:from\endcsname \else - \letvalue{\??gv\currentmpvariableclass:from}\currentposition + \ifcsname\??graphicvariable\currentmpvariableclass:from\endcsname \else + \letvalue{\??graphicvariable\currentmpvariableclass:from}\currentposition \fi} \def\anch_positions_meta_graphic_use#1#2#3% @@ -375,7 +379,7 @@ \startMPcode#3\stopMPcode \endgroup} -\def\MPpositiongraphic +\unexpanded\def\MPpositiongraphic {\dodoublegroupempty\anch_positions_meta_graphic_direct} \def\anch_positions_meta_graphic_direct#1% tag setups @@ -402,9 +406,9 @@ \anch_positions_meta_graphic_prepare \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments - \setbox\positiongraphicbox\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}% - \smashbox\positiongraphicbox - \box\positiongraphicbox + \setbox\b_anch_positions_graphic\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}% + \smashbox\b_anch_positions_graphic + \box\b_anch_positions_graphic \endgroup} \def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away) @@ -422,77 +426,77 @@ %D Simple one position graphics. -\def\setMPpositiongraphic - {\dotriplegroupempty\dosetMPpositiongraphic} +\unexpanded\def\setMPpositiongraphic + {\dotriplegroupempty\anch_positions_meta_graphic_set} -\def\dosetMPpositiongraphic#1#2#3% pos tag vars +\def\anch_positions_meta_graphic_set#1#2#3% pos tag vars {\ifx\currentpositionoverlay\empty - \dosetpositionaction{#1}{\MPpositiongraphic{#2}{#3}}% + \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}% \else % silly can be one - \handlepositiongraphics{#1}{#2}{#3}% + \anch_positions_meta_graphic_handle{#1}{#2}{#3}% \fi} -\def\handlepositiongraphics#1#2#3% combine with boxes - {\handlepositionaction\dohandleMPpositiongraphic\with{#1}{#2}{#3}\on{#2}} +\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes + {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}} -\def\doinsertMPpositiongraphic#1#2#3% pos tag setups +\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups {\ifnum\MPp{#1}=\realpageno\relax % extra saveguard \def\currentposition{#1}\MPpositiongraphic{#2}{#3}% \fi} \appendtoks - \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic + \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert \to \everyinsertpositionaction -\def\docleanMPpositiongraphic#1#2#3% pos tag setups +\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups {\ifnum\MPp{#1}<\realpageno \else - \noexpand\dohandleMPpositiongraphic{#1}{#2}{#3}% + \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}% \fi} \appendtoks - \let\dohandleMPpositiongraphic\docleanMPpositiongraphic + \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup \to \everycleanpositionaction %D Graphics that span two positions (beware, does not cross pages). \unexpanded\def\setMPpositiongraphicrange - {\doquadruplegroupempty\dosetMPpositiongraphicrange} + {\doquadruplegroupempty\anch_positions_meta_graphic_set_range} -\def\dosetMPpositiongraphicrange#1#2#3#4% bpos epos tag vars +\def\anch_positions_meta_graphic_set_range#1#2#3#4% bpos epos tag vars {\ifx\currentpositionoverlay\empty - \dosetpositionaction{#1}{\MPpositiongraphic{#3}{#4}}% + \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}% \else - \handlepositiongraphicsrange{#1}{#2}{#3}{#4}% + \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}% \fi} -\def\handlepositiongraphicsrange#1#2#3#4% - {\handlepositionaction\dohandleMPpositiongraphicrange\with{#1}{#2}{#3}{#4}\on{#2}} +\def\anch_positions_meta_graphic_handle_range#1#2#3#4% + {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}} -\def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups +\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups {\ctxcommand{doifelserangeonpage("#1","#2",\number\realpageno)}% - {%\writestatus{YES}{#1/#2 => #3}% - \def\currentposition{#1}% + {\def\currentposition{#1}% \MPpositiongraphic{#3}{#4}}% - {}}%\writestatus{NOP}{#1/#2 = #3}}} + {}} \appendtoks - \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange + \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range \to \everyinsertpositionaction -\def\docleanMPpositiongraphicrange#1#2#3#4% pos tag setups +\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups {\ifnum\MPp{#2}<\realpageno \else - \noexpand \dohandleMPpositiongraphicrange{#1}{#2}{#3}{#4}% + \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}% \fi} \appendtoks - \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange + \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range \to \everycleanpositionaction -\let\dohandleMPpositiongraphicrange\gobblefourarguments +\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments % Helpers: -\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}} -\def\MPgetmultipars#1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}} +\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}} +\def\MPgetmultipars #1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}} +\def\MPgetmultishapes#1#2{\ctxcommand{fetchmultishape("#1","#2",\the\realpageno)}} \protect \endinput diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua index 5d01a6e46..6fa916291 100644 --- a/tex/context/base/anch-pos.lua +++ b/tex/context/base/anch-pos.lua @@ -17,6 +17,8 @@ more efficient.</p> -- maybe replace texsp by our own converter (stay at the lua end) -- eventually mp will have large numbers so we can use sp there too +local commands, context = commands, context + local tostring, next, rawget, setmetatable = tostring, next, rawget, setmetatable local concat, sort = table.concat, table.sort local format, gmatch, match = string.format, string.gmatch, string.match @@ -969,35 +971,35 @@ function commands.MPxywhd(id) end end --- is testcase already defined? if so, then local +local doif, doifelse = commands.doif, commands.doifelse function commands.doifpositionelse(name) - commands.doifelse(collected[name]) + doifelse(collected[name]) end function commands.doifposition(name) - commands.doif(collected[name]) + doif(collected[name]) end function commands.doifpositiononpage(name,page) -- probably always realpageno local c = collected[name] - commands.testcase(c and c.p == page) + doifelse(c and c.p == page) end function commands.doifoverlappingelse(one,two,overlappingmargin) - commands.testcase(overlapping(one,two,overlappingmargin)) + doifelse(overlapping(one,two,overlappingmargin)) end function commands.doifpositionsonsamepageelse(list,page) - commands.testcase(onsamepage(list)) + doifelse(onsamepage(list)) end function commands.doifpositionsonthispageelse(list) - commands.testcase(onsamepage(list,tostring(tex.count.realpageno))) + doifelse(onsamepage(list,tostring(tex.count.realpageno))) end function commands.doifelsepositionsused() - commands.testcase(next(collected)) + doifelse(next(collected)) end commands.markcolumnbox = jobpositions.markcolumnbox diff --git a/tex/context/base/anch-pos.mkiv b/tex/context/base/anch-pos.mkiv index 2e13eeba2..7ecaa296e 100644 --- a/tex/context/base/anch-pos.mkiv +++ b/tex/context/base/anch-pos.mkiv @@ -361,9 +361,9 @@ \startcolor[blue]% \llap{\infofont\number\c_anch_positions_paragraph}% \vrule - \!!width 4\onepoint - \!!height2\onepoint - \!!depth 2\onepoint + \s!width 4\onepoint + \s!height2\onepoint + \s!depth 2\onepoint \stopcolor \hss}} @@ -377,7 +377,7 @@ {\smashedhbox {#1{\infofont#2#3}% \kern-\onepoint - \vrule\!!width2\onepoint\!!height\halfapoint\!!depth\halfapoint}} + \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}} \unexpanded\def\anch_positions_trace_left_indeed {\anch_positions_trace\llap\darkmagenta{\currentposition>}} diff --git a/tex/context/base/anch-tab.mkiv b/tex/context/base/anch-tab.mkiv index 4bdaa2ef9..2fb6938a2 100644 --- a/tex/context/base/anch-tab.mkiv +++ b/tex/context/base/anch-tab.mkiv @@ -13,6 +13,9 @@ \writestatus{loading}{ConTeXt Anchoring Macros / Table Extensions} +%D This is just a playground and functionality might change or even +%D dissappear in favour of better solutions. + \unprotect \newcount\c_anch_tabs @@ -57,23 +60,22 @@ \global\advance\c_anch_tabs\plusone \to \everytabulate -%D Beware, the following code is somewhat weird and experimental -%D and might be dropped or become a loadable module. +%D Beware, the following code is somewhat weird and experimental and might be +%D dropped or become a loadable module. %D \macros %D {GFC, GTC, GSC} %D -%D The next macros extend tables and tabulation with -%D backgrounds and position related features. Areas are -%D specified with symbolic names, and symbolic references to -%D the graphics involved. Each table has its own namespace. +%D The next macros extend tables and tabulation with backgrounds and position +%D related features. Areas are specified with symbolic names, and symbolic +%D references to the graphics involved. Each table has its own namespace. \newconditional\tablehaspositions -\newcount\noftabpositions -\newtoks \posXCtoks +\newcount \noftabpositions +\newtoks \posXCtoks -\def\dotablebpos{\bpos} -\def\dotableepos{\epos} +\def\anch_tabulate_bpos{\bpos} +\def\anch_tabulate_epos{\epos} \installcorenamespace{positiontables} @@ -85,74 +87,80 @@ \let\tabulatepos\tablepos -\def\dodododoGSC[#1:#2]% - {\remappositionframed{#2}{\tbPOSprefix#1}% - \dotablebpos{\tbPOSprefix#1}% - \doglobal\appendtoks\@EA\dotableepos\@EA{\tbPOSprefix#1}\to\posXCtoks} +\unexpanded\def\tbXC {\dosingleempty\anch_tables_XC } +\unexpanded\def\tbGSC{\dosingleempty\anch_tables_GSC} +\unexpanded\def\tbGFC{\dosingleempty\anch_tables_GFC} +\unexpanded\def\tbGTC{\dosingleempty\anch_tables_GTC} -\def\dododoGSC[#1:#2:#3]% - {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC} +\def\anch_table_check_state + {\iftrialtypesetting + \global\settrue\tablehaspositions + \firstargumentfalse + \fi} -\def\dodoGSC[#1]% - {\def\docommand##1{\dododoGSC[##1:##1]}% - \processcommalist[#1]\docommand} +\def\anch_tables_XC [#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_XC [#1]\else\expandafter\fi\NC} +\def\anch_tables_GSC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi} +\def\anch_tables_GFC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi} +\def\anch_tables_GTC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi} -\def\dodododoGFC[#1:#2:#3]% - {\remappositionframed{#2}{\tbPOSprefix#1}% - \dotablebpos{\tbPOSprefix#1}} +\def\anch_tables_indeed_XC[#1]% + {{\let\NC\relax\processcommalist[#1]\anch_tables_step_XC}} -\def\dododoGFC[#1]% - {\def\docommand##1{\dodododoGFC[##1:##1]}% - \processcommalist[#1]\docommand} +\def\anch_tables_step_XC#1% + {\anch_tables_step_indeed_XC[#1]} -\def\dodoGFC[#1]% - {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC} +\def\anch_tables_step_indeed_XC[#1#2]% + {\if#1>\anch_tables_indeed_GFC [#2:#2]\else + \if#1+\anch_tables_indeed_GFC [#2:#2]\else + \if#1<\anch_tables_indeed_GTC [#2:#2]\else + \if#1-\anch_tables_indeed_GTC [#2:#2]\else + \if#1=\anch_tables_indeed_GSC [#2:#2]\else + \anch_tables_indeed_GSC[#1#2:#1#2]\fi\fi\fi\fi\fi} -\def\dododododoGTC[#1:#2]% - {\dotableepos{\tbPOSprefix#1}} +\def\anch_tables_indeed_GSC[#1]% + {\processcommalist[#1]\anch_tables_step_GSC} -\def\dodododoGTC[#1]% - {\def\docommand##1{\dododododoGTC[##1:##1]}% - \processcommalist[#1]\docommand} +\def\anch_tables_step_GSC#1% + {\anch_tables_append_GSC[#1:#1]} -\def\dododoGTC[#1]% - {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks} +\def\anch_tables_append_GSC[#1:#2:#3]% + {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC} -\def\dodoGTC[#1]% - {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC} +\def\anch_tables_process_GSC[#1:#2]% + {\remappositionframed{#2}{\tbPOSprefix#1}% + \anch_tabulate_bpos{\tbPOSprefix#1}% + \doglobal\appendtoks\@EA\anch_tabulate_epos\@EA{\tbPOSprefix#1}\to\posXCtoks} -\def\dodododoXC[#1#2]% - {\if#1>\dodoGFC [#2:#2]\else - \if#1+\dodoGFC [#2:#2]\else - \if#1<\dodoGTC [#2:#2]\else - \if#1-\dodoGTC [#2:#2]\else - \if#1=\dodoGSC [#2:#2]\else - \dodoGSC[#1#2:#1#2]\fi\fi\fi\fi\fi} +\def\anch_tables_indeed_GFC[#1]% + {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC} -\def\dododoXC#1% - {\dodododoXC[#1]} +\def\anch_tables_delayed_GFC[#1]% + {\processcommalist[#1]\anch_tables_step_GFC} -\def\dodoXC[#1]% - {{\let\NC\relax\processcommalist[#1]\dododoXC}} +\def\anch_tables_step_GFC#1% + {\anch_tables_process_GFC[#1:#1]} -\def\@@checktablepositionstate - {\iftrialtypesetting - \global\settrue\tablehaspositions - \firstargumentfalse - \fi} +\def\anch_tables_process_GFC[#1:#2:#3]% + {\remappositionframed{#2}{\tbPOSprefix#1}% + \anch_tabulate_bpos{\tbPOSprefix#1}} + +\def\anch_tables_indeed_GTC[#1]% + {\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC} -\def\doGSC[#1]{\@@checktablepositionstate\iffirstargument\dodoGSC[#1]\else\expandafter\NC\fi} -\def\doGFC[#1]{\@@checktablepositionstate\iffirstargument\dodoGFC[#1]\else\expandafter\NC\fi} -\def\doGTC[#1]{\@@checktablepositionstate\iffirstargument\dodoGTC[#1]\else\expandafter\NC\fi} -\def\doXC [#1]{\@@checktablepositionstate\iffirstargument\dodoXC [#1]\else\expandafter\fi\NC} +\def\anch_tables_delayed_GTC[#1]% + {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks} -\def\tbGSC{\dosingleempty\doGSC} -\def\tbGFC{\dosingleempty\doGFC} -\def\tbGTC{\dosingleempty\doGTC} -\def\tbXC {\dosingleempty\doXC } +\def\anch_tables_process_GTC[#1]% + {\processcommalist[#1]\anch_tables_step_GTC} -%D The amount of code to support tables and tabulation is -%D rather minimalistic. +\def\anch_tables_step_GTC#1% + {\anch_tables_step_indeed_GTC[#1:#1]} + +\def\anch_tables_step_indeed_GTC[#1:#2]% + {\anch_tabulate_epos{\tbPOSprefix#1}} + +%D The amount of code to support tables and tabulation is rather +%D minimalistic. \let\tabulatepos\tablepos @@ -187,31 +195,30 @@ % We need to handle paragraphs as well. -\let\doflushtabulateepos\relax +\let\anch_tabulate_flush_epos\relax -\def\dotabulatebpos +\def\anch_tabulate_bpos_indeed {\bpos} -\def\dotabulateepos#1% +\def\anch_tabulate_epos_indeed#1% {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column \epos{#1}% - \glet\doflushtabulateepos\relax + \glet\anch_tabulate_flush_epos\relax \else - \gdef\doflushtabulateepos{\epos{#1}}% + \gdef\anch_tabulate_flush_epos{\epos{#1}}% \fi} \def\flushtabulatesplitbox {\box\b_tabl_tabulate - \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi} + \iftrialtypesetting\else\ifconditional\tablehaspositions\anch_tabulate_flush_epos\fi\fi} \appendtoks - \let\dotablebpos\dotabulatebpos % ? - \let\dotableepos\dotabulateepos % ? - \glet\doflushtabulateepos\relax + \let\anch_tabulate_bpos\anch_tabulate_bpos_indeed % ? + \let\anch_tabulate_epos\anch_tabulate_epos_indeed % ? + \glet\anch_tabulate_flush_epos\relax \to \everytabulate -%D In order to prevent potential clashes with abbreviations, -%D postpone the mapping. +%D In order to prevent potential clashes with abbreviations, postpone the mapping. \appendtoks \let\GSC\tbGSC @@ -223,8 +230,8 @@ %D \macros %D {definepositionframed} %D -%D The next example show how to provide backgrounds to table -%D cells. First we define some framed backgrounds. +%D The next example show how to provide backgrounds to table cells. First we define +%D some framed backgrounds. %D %D \startbuffer %D \definepositionframed[x][background=color,backgroundcolor=red] @@ -244,8 +251,7 @@ %D \stoptabulate %D \stopbuffer %D -%D The table itself defines three areas (a, b and~c) using -%D these frames. +%D The table itself defines three areas (a, b and~c) using these frames. %D %D \typebuffer %D % \getbuffer @@ -270,9 +276,8 @@ \let\XC \tbXC \to \everytable -%D In the previous example, we could have provided an overlay to -%D the framed definition. A more direct approach is demonstrated -%D below: +%D In the previous example, we could have provided an overlay to the framed definition. +%D A more direct approach is demonstrated below: %D %D \startbuffer %D \def\cw#1{\color[white]{#1}} @@ -291,8 +296,7 @@ %D %D \typebuffer \getbuffer %D -%D The definition of the table looks about the same as the -%D previous one: +%D The definition of the table looks about the same as the previous one: %D %D \startbuffer %D \starttable[|c|c|c|] @@ -347,22 +351,26 @@ % \definepositionframed[y][background=color,fillcolor=green] % \definepositionframed[z][background=color,fillcolor=blue] -\def\remappositionframed#1#2% from to +\unexpanded\def\remappositionframed#1#2% from to {\copyposition{b:#1}{b:#2}% \copyposition{e:#1}{e:#2}% - \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}} + \anch_positions_set_action{b:#2}{\dopositionaction{b:#1}}} \unexpanded\def\definepositionframed - {\dodoubleargument\dodefinepositionframed} + {\dodoubleargument\anch_framed_define} -\def\dodefinepositionframed[#1][#2]% - {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}} +\def\anch_framed_define[#1][#2]% + {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}} + +\unexpanded\def\anch_framed_handle + {\bgroup + \anch_framed_indeed} \unexpanded\def\positionframed {\bgroup - \dodoubleempty\dopositionframed} + \dodoubleempty\anch_framed_indeed} -\def\dopositionframed[#1][#2]% +\def\anch_framed_indeed[#1][#2]% {\setbox\scratchbox\hbox {\scratchwidth \dimexpr\MPx{e:#1}-\MPx{b:#1}\relax \scratchdepth \dimexpr\MPy{b:#1}-\MPy{e:#1}+\MPd{e:#1}\relax diff --git a/tex/context/base/attr-col.lua b/tex/context/base/attr-col.lua index c592d1dc1..18182ba85 100644 --- a/tex/context/base/attr-col.lua +++ b/tex/context/base/attr-col.lua @@ -15,8 +15,11 @@ if not modules then modules = { } end modules ['attr-col'] = { local type = type local format = string.format local concat = table.concat +local min, max, floor = math.min, math.max, math.floor -local attributes, nodes = attributes, nodes +local attributes, nodes, utilities, logs, backends, storage = attributes, nodes, utilities, logs, backends, storage +local commands, context, interfaces = commands, context, interfaces +local tex = tex local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -31,11 +34,13 @@ local report_transparencies = logs.reporter("transparencies","support") -- nb: attributes: color etc is much slower than normal (marks + literals) but ... -- nb. too many "0 g"s -local states = attributes.states -local tasks = nodes.tasks -local nodeinjections = backends.nodeinjections -local registrations = backends.registrations -local unsetvalue = attributes.unsetvalue +local states = attributes.states +local tasks = nodes.tasks +local nodeinjections = backends.nodeinjections +local registrations = backends.registrations +local unsetvalue = attributes.unsetvalue + +local registerstorage = storage.register -- We can distinguish between rules and glyphs but it's not worth the trouble. A -- first implementation did that and while it saves a bit for glyphs and rules, it @@ -63,7 +68,7 @@ local unsetvalue = attributes.unsetvalue -- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")" -- end -- --- storage.register("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated +-- registerstorage("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated -- -- We assume that only processcolors are defined in the format. @@ -83,9 +88,17 @@ colors.default = 1 colors.main = nil colors.triggering = true colors.supported = true +colors.model = "all" + +local data = colors.data +local values = colors.values +local registered = colors.registered -storage.register("attributes/colors/values", colors.values, "attributes.colors.values") -storage.register("attributes/colors/registered", colors.registered, "attributes.colors.registered") +local numbers = attributes.numbers +local list = attributes.list + +registerstorage("attributes/colors/values", values, "attributes.colors.values") +registerstorage("attributes/colors/registered", registered, "attributes.colors.registered") local templates = { rgb = "r:%s:%s:%s", @@ -104,17 +117,6 @@ local models = { cmyk = 4, } -colors.model = "all" - -local data = colors.data -local values = colors.values -local registered = colors.registered - -local numbers = attributes.numbers -local list = attributes.list - -local min, max, floor = math.min, math.max, math.floor - local function rgbtocmyk(r,g,b) -- we could reduce return 1-r, 1-g, 1-b, 0 end @@ -125,9 +127,9 @@ end local function rgbtogray(r,g,b) if colors.weightgray then - return .30*r+.59*g+.11*b + return .30*r + .59*g + .11*b else - return r/3+g/3+b/3 + return r/3 + g/3 + b/3 end end @@ -135,6 +137,17 @@ local function cmyktogray(c,m,y,k) return rgbtogray(cmyktorgb(c,m,y,k)) end +-- not critical so not needed: +-- +-- local function cmyktogray(c,m,y,k) +-- local r, g, b = 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k) +-- if colors.weightgray then +-- return .30*r + .59*g + .11*b +-- else +-- return r/3 + g/3 + b/3 +-- end +-- end + -- http://en.wikipedia.org/wiki/HSI_color_space -- http://nl.wikipedia.org/wiki/HSV_(kleurruimte) @@ -363,15 +376,15 @@ transparencies.triggering = true transparencies.attribute = a_transparency transparencies.supported = true -storage.register("attributes/transparencies/registered", transparencies.registered, "attributes.transparencies.registered") -storage.register("attributes/transparencies/values", transparencies.values, "attributes.transparencies.values") +local registered = transparencies.registered -- we could use a 2 dimensional table instead +local data = transparencies.data +local values = transparencies.values +local template = "%s:%s" -local registered = transparencies.registered -- we could use a 2 dimensional table instead -local data = transparencies.data -local values = transparencies.values -local template = "%s:%s" +registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered") +registerstorage("attributes/transparencies/values", values, "attributes.transparencies.values") -local function inject_transparency (...) +local function inject_transparency(...) inject_transparency = nodeinjections.transparency return inject_transparency(...) end diff --git a/tex/context/base/attr-eff.lua b/tex/context/base/attr-eff.lua index 023d1c51b..60e0c08ac 100644 --- a/tex/context/base/attr-eff.lua +++ b/tex/context/base/attr-eff.lua @@ -8,7 +8,9 @@ if not modules then modules = { } end modules ['attr-eff'] = { local format = string.format -local attributes, nodes = attributes, nodes +local commands, interfaces = commands, interfaces +local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities +local tex = tex local states = attributes.states local tasks = nodes.tasks @@ -17,6 +19,9 @@ local settexattribute = tex.setattribute local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex +local variables = interfaces.variables +local v_normal = variables.normal + attributes.effects = attributes.effects or { } local effects = attributes.effects @@ -27,14 +32,14 @@ effects.values = effects.values or { } effects.registered = effects.registered or { } effects.attribute = a_effect -storage.register("attributes/effects/registered", effects.registered, "attributes.effects.registered") -storage.register("attributes/effects/values", effects.values, "attributes.effects.values") +local data = effects.data +local registered = effects.registered +local values = effects.values -local template = "%s:%s:%s" +local template = "%s:%s:%s" -local data = effects.data -local registered = effects.registered -local values = effects.values +storage.register("attributes/effects/registered", registered, "attributes.effects.registered") +storage.register("attributes/effects/values", values, "attributes.effects.values") -- valid effects: normal inner outer both hidden (stretch,rulethickness,effect) @@ -66,12 +71,22 @@ effects.handler = nodes.installattributehandler { processor = states.process, } -local function register(effect,stretch,rulethickness) - local stamp = format(template,effect,stretch,rulethickness) +local function register(specification) + local alternative, stretch, rulethickness + if specification then + alternative = specification.alternative or v_normal + stretch = specification.stretch or 0 + rulethickness = specification.rulethickness or 0 + else + alternative = v_normal + stretch = 0 + rulethickness = 0 + end + local stamp = format(template,alternative,stretch,rulethickness) local n = registered[stamp] if not n then n = #values + 1 - values[n] = { effect, stretch, rulethickness } + values[n] = { alternative, stretch, rulethickness } registered[stamp] = n end return n @@ -88,10 +103,10 @@ effects.enable = enable local enabled = false -function commands.triggereffect(effect,stretch,rulethickness) +function commands.triggereffect(specification) if not enabled then enable() enabled = true end - settexattribute(a_effect,register(effect,stretch,rulethickness)) + settexattribute(a_effect,register(specification)) end diff --git a/tex/context/base/attr-eff.mkiv b/tex/context/base/attr-eff.mkiv index c5c94537c..43f575a7a 100644 --- a/tex/context/base/attr-eff.mkiv +++ b/tex/context/base/attr-eff.mkiv @@ -17,38 +17,39 @@ \unprotect -\gdef\dotriggereffect#1#2#3% - {\ctxcommand{triggereffect('#1',#2,\number\dimexpr#3\relax)}} +\installcorenamespace{effect} -\unexpanded\def\setupeffect - {\dodoubleargument\dosetupeffect} +\installcommandhandler \??effect {effect} \??effect -\def\dosetupeffect[#1][#2]% - {\getparameters[\??et#1][#2]} +\setupeffect + [\c!method=\v!none, + \c!stretch=\zerocount, + \c!rulethickness=\zeropoint, + \c!alternative=\v!normal] -\unexpanded\def\defineeffect - {\dodoubleargument\dodefineeffect} - -\def\dodefineeffect[#1][#2]% - {\getparameters[\??et#1][\c!method=\v!none,\c!stretch=0,\c!rulethickness=\zeropoint,\c!alternative=\v!normal,#2]% - \doif{\getvalue{\??et#1\c!method}}\v!command - {\setugvalue{\e!start#1}{\starteffect[#1]}% - \setugvalue{\e!stop #1}{\stopeffect}}} - -% yes or no grouped +\appendtoks + \edef\p_method{\effectparameter\c!method}% + \ifx\p_method\v!method + \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}% + \setuxvalue{\e!stop \currenteffect}{\stopeffect}% + \fi +\to \everydefineeffect \unexpanded\def\starteffect[#1]% - {\dotriggereffect - {\csname\??et#1\c!alternative \endcsname}% - {\csname\??et#1\c!stretch \endcsname}% - {\csname\??et#1\c!rulethickness\endcsname}} + {\ctxcommand{triggereffect{ + alternative = "\namedeffectparameter{#1}\c!alternative", + stretch = \number\namedeffectparameter{#1}\c!stretch, + rulethickness = \number\dimexpr\namedeffectparameter{#1}\c!rulethickness\relax + }}} \unexpanded\def\stopeffect % can be special - {\dotriggereffect\v!normal0\zeropoint} + {\ctxcommand{triggereffect()}} % v!normal 0 0 \unexpanded\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] diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua index f3714fcb4..5a3bafce3 100644 --- a/tex/context/base/attr-ini.lua +++ b/tex/context/base/attr-ini.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['attr-ini'] = { license = "see context related readme files" } +local commands, context, nodes, storage = commands, context, nodes, storage + local next, type = next, type --[[ldx-- @@ -13,11 +15,10 @@ local next, type = next, type symbolic names later on.</p> --ldx]]-- -attributes = attributes or { } - -local attributes, nodes = attributes, nodes +attributes = attributes or { } +local attributes = attributes --- todo: local and then gobals ... first loaded anyway +local sharedstorage = storage.shared attributes.names = attributes.names or { } attributes.numbers = attributes.numbers or { } @@ -26,15 +27,14 @@ attributes.states = attributes.states or { } attributes.handlers = attributes.handlers or { } attributes.unsetvalue = -0x7FFFFFFF -local names, numbers, list = attributes.names, attributes.numbers, attributes.list +local names = attributes.names +local numbers = attributes.numbers +local list = attributes.list storage.register("attributes/names", names, "attributes.names") storage.register("attributes/numbers", numbers, "attributes.numbers") storage.register("attributes/list", list, "attributes.list") -names [0] = "fontdynamic" -numbers["fontdynamic"] = 0 - function attributes.define(name,number) -- at the tex end if not numbers[name] then numbers[name] = number @@ -44,12 +44,18 @@ function attributes.define(name,number) -- at the tex end end --[[ldx-- +<p>We reserve this one as we really want it to be always set (faster).</p> +--ldx]]-- + +names[0], numbers["fontdynamic"] = "fontdynamic", 0 + +--[[ldx-- <p>We can use the attributes in the range 127-255 (outside user space). These are only used when no attribute is set at the \TEX\ end which normally happens in <l n='context'/>.</p> --ldx]]-- -storage.shared.attributes_last_private = storage.shared.attributes_last_private or 127 +sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127 -- to be considered (so that we can use an array access): -- @@ -57,10 +63,10 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private -- -- setmetatable(private, { -- __index = function(t,name) --- local number = storage.shared.attributes_last_private or 127 +-- local number = sharedstorage.attributes_last_private -- if number < 1023 then -- tex.count.minallocatedattribute - 1 -- number = number + 1 --- storage.shared.attributes_last_private = number +-- sharedstorage.attributes_last_private = number -- end -- numbers[name], names[number], list[number] = number, name, { } -- private[name] = number @@ -74,12 +80,12 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private function attributes.private(name) -- at the lua end (hidden from user) local number = numbers[name] if not number then - local last = storage.shared.attributes_last_private or 127 + local last = sharedstorage.attributes_last_private if last < 1023 then -- tex.count.minallocatedattribute - 1 last = last + 1 - storage.shared.attributes_last_private = last + sharedstorage.attributes_last_private = last else - report_attribute("no more room for private attributes") -- fatal + report_attribute("no more room for private attributes") os.exit() end number = last @@ -88,7 +94,7 @@ function attributes.private(name) -- at the lua end (hidden from user) return number end --- new (actually a tracer) +-- tracers local report_attribute = logs.reporter("attributes") diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv index a1550b4be..8a41dd427 100644 --- a/tex/context/base/attr-ini.mkiv +++ b/tex/context/base/attr-ini.mkiv @@ -14,8 +14,8 @@ \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 \newattribute will go away. +%D related to attributes. Housekeeping will move completely to \LUA\ +%D and \type {\newattribute} will go away. \unprotect @@ -27,14 +27,16 @@ \unexpanded\def\pushattribute#1% {\global\advance\csname\??attributestack\string#1\endcsname\plusone - \global\expandafter\mathchardef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\attribute#1} + \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}} \unexpanded\def\popattribute#1% - {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname + {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax \global\advance\csname\??attributestack\string#1\endcsname\minusone} \unexpanded\def\installattributestack#1% - {\expandafter\newcount\csname\??attributestack\string#1\endcsname} + {\ifcsname\??attributestack\string#1\endcsname \else + \expandafter\newcount\csname\??attributestack\string#1\endcsname + \fi} \newtoks \attributesresetlist diff --git a/tex/context/base/attr-lay.lua b/tex/context/base/attr-lay.lua index bcdc541f7..5e5e81ff1 100644 --- a/tex/context/base/attr-lay.lua +++ b/tex/context/base/attr-lay.lua @@ -10,9 +10,15 @@ if not modules then modules = { } end modules ['attr-lay'] = { -- but when we need it stacked layers might show up too; the next function based -- approach can be replaced by static (metatable driven) resolvers +-- maybe use backends.registrations here too + local type = type local format = string.format -local insert, remove = table.insert, table.remove +local insert, remove, concat = table.insert, table.remove, table.concat + +local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends +local commands, context, interfaces = commands, context, interfaces +local tex = tex local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -26,8 +32,6 @@ local report_viewerlayers = logs.reporter("viewerlayers") -- nb. too many "0 g"s -- nb: more local tables -local attributes, nodes = attributes, nodes - attributes.viewerlayers = attributes.viewerlayers or { } local viewerlayers = attributes.viewerlayers @@ -57,22 +61,42 @@ local texgetattribute = tex.getattribute local texsettokenlist = tex.settoks local unsetvalue = attributes.unsetvalue -storage.register("attributes/viewerlayers/registered", viewerlayers.registered, "attributes.viewerlayers.registered") -storage.register("attributes/viewerlayers/values", viewerlayers.values, "attributes.viewerlayers.values") -storage.register("attributes/viewerlayers/scopes", viewerlayers.scopes, "attributes.viewerlayers.scopes") +local nodepool = nodes.pool + +local data = viewerlayers.data +local values = viewerlayers.values +local listwise = viewerlayers.listwise +local registered = viewerlayers.registered +local scopes = viewerlayers.scopes + +local template = "%s" -local data = viewerlayers.data -local values = viewerlayers.values -local listwise = viewerlayers.listwise -local registered = viewerlayers.registered -local scopes = viewerlayers.scopes -local template = "%s" +storage.register("attributes/viewerlayers/registered", registered, "attributes.viewerlayers.registered") +storage.register("attributes/viewerlayers/values", values, "attributes.viewerlayers.values") +storage.register("attributes/viewerlayers/scopes", scopes, "attributes.viewerlayers.scopes") + +local layerstacker = utilities.stacker.new("layers") -- experiment + +layerstacker.mode = "stack" +layerstacker.unset = attributes.unsetvalue + +viewerlayers.resolve_begin = layerstacker.resolve_begin +viewerlayers.resolve_step = layerstacker.resolve_step +viewerlayers.resolve_end = layerstacker.resolve_end + +function commands.cleanuplayers() + layerstacker.clean() + -- todo +end -- stacked +local function startlayer(...) startlayer = nodeinjections.startlayer return startlayer(...) end +local function stoplayer (...) stoplayer = nodeinjections.stoplayer return stoplayer (...) end + local function extender(viewerlayers,key) if viewerlayers.supported and key == "none" then - local d = nodeinjections.stoplayer() + local d = stoplayer() viewerlayers.none = d return d end @@ -82,7 +106,7 @@ local function reviver(data,n) if viewerlayers.supported then local v = values[n] if v then - local d = nodeinjections.startlayer(v) + local d = startlayer(v) data[n] = d return d else @@ -91,8 +115,14 @@ local function reviver(data,n) end end -setmetatableindex(viewerlayers, extender) -setmetatableindex(viewerlayers.data, reviver) +setmetatableindex(viewerlayers,extender) +setmetatableindex(viewerlayers.data,reviver) + +-- !!!! TEST CODE !!!! + +layerstacker.start = function(...) local f = nodeinjections.startstackedlayer layerstacker.start = f return f(...) end +layerstacker.stop = function(...) local f = nodeinjections.stopstackedlayer layerstacker.stop = f return f(...) end +layerstacker.change = function(...) local f = nodeinjections.changestackedlayer layerstacker.change = f return f(...) end local function initializer(...) return states.initialize(...) @@ -103,7 +133,8 @@ attributes.viewerlayers.handler = nodes.installattributehandler { namespace = viewerlayers, initializer = initializer, finalizer = states.finalize, - processor = states.stacked, + -- processor = states.stacked, + processor = states.stacker, } local stack, enabled, global = { }, false, false @@ -149,12 +180,16 @@ function viewerlayers.setfeatures(hasorder) viewerlayers.hasorder = hasorder end +local usestacker = true -- new, experimental + function viewerlayers.start(name) --- if not enabled then --- viewerlayers.enable(true) --- end - insert(stack,texgetattribute(a_viewerlayer)) - local a = register(name) or unsetvalue + local a + if usestacker then + a = layerstacker.push(register(name) or unsetvalue) + else + insert(stack,texgetattribute(a_viewerlayer)) + a = register(name) or unsetvalue + end if global or scopes[name] == v_global then scopes[a] = v_global -- messy but we don't know the attributes yet texsetattribute("global",a_viewerlayer,a) @@ -165,14 +200,21 @@ function viewerlayers.start(name) end function viewerlayers.stop() - local a = remove(stack) - if a >= 0 then + local a + if usestacker then + a = layerstacker.pop() + else + a = remove(stack) + end + if not a then + -- error + elseif a >= 0 then if global or scopes[a] == v_global then texsetattribute("global",a_viewerlayer,a) else texsetattribute(a_viewerlayer,a) end - texsettokenlist("currentviewerlayertoks",values[a]) + texsettokenlist("currentviewerlayertoks",values[a] or "") else if global or scopes[a] == v_global then texsetattribute("global",a_viewerlayer,unsetvalue) @@ -197,9 +239,9 @@ function viewerlayers.define(settings) end end -commands.defineviewerlayer = viewerlayers.define -commands.startviewerlayer = viewerlayers.start -commands.stopviewerlayer = viewerlayers.stop +commands.defineviewerlayer = viewerlayers.define +commands.startviewerlayer = viewerlayers.start +commands.stopviewerlayer = viewerlayers.stop function commands.definedviewerlayer(settings) viewerlayers.define(settings) diff --git a/tex/context/base/attr-lay.mkiv b/tex/context/base/attr-lay.mkiv index 67cd204e2..9c9c3318e 100644 --- a/tex/context/base/attr-lay.mkiv +++ b/tex/context/base/attr-lay.mkiv @@ -13,51 +13,51 @@ \writestatus{loading}{ConTeXt Attribute Macros / Viewerlayers} +%D Currently there is a limitation in mixed inline usage. This has to do with the fact +%D that we have a stacked model but cannot determine where to revert to (as we can +%D have AABBCCAA ranges). Maybe I'll solve that one day. It only affects nested inline +%D layers and these make not much sense anyway. We'd have to store the complete nesting +%D stack in the attribute in order to be able to cross pages and that demands a new +%D mechanism. + \unprotect \registerctxluafile{attr-lay}{1.001} % needs to work over stopitemize grouping etc -% \def\registerviewerlayer#1#2% global ! -% {\setxvalue{\??ql:#1}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(attributes.viewerlayers.register('#2'))} }} -% -% \setevalue{\??ql:}{\global\attribute\viewerlayerattribute\attributeunsetvalue} +\installcorenamespace{viewerlayer} + +\installcommandhandler \??viewerlayer {viewerlayer} \??viewerlayer -\getparameters - [\??lr] +\setupviewerlayer [\c!state=\v!start, \c!title=, \c!printable=\v!yes, \c!scope=\v!local, % maybe global but needs checking with layout \c!method=\v!none] -\def\defineviewerlayer - {\dodoubleargument\dodefineviewerlayer} - -\def\dodefineviewerlayer[#1][#2]% document wide properties - {\begingroup - \getparameters[\??lr][#2]% - \ctxcommand{defineviewerlayer{ - tag = "#1", - title = "\@@lrtitle", - visible = "\@@lrstate", - editable = "\v!yes", - printable = "\@@lrprintable", - scope = "\@@lrscope" - }}% - \doif\@@lrmethod\v!command - {\setugvalue{\e!start#1}{\startviewerlayer[#1]}% - \setugvalue{\e!stop #1}{\stopviewerlayer }}% - \endgroup} - -\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped -\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped +\appendtoks + \ctxcommand{defineviewerlayer{ + tag = "\currentviewerlayer", + title = "\viewerlayerparameter\c!title", + visible = "\viewerlayerparameter\c!state", + editable = "\v!yes", + printable = "\viewerlayerparameter\c!printable", + scope = "\viewerlayerparameter\c!scope" + }}% + \doif{\viewerlayerparameter\c!method}\v!command + {\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}% + \setuxvalue{\e!stop #1}{\stopviewerlayer}}% +\to \everydefineviewerlayer + +\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped +\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped \unexpanded\def\viewerlayer [#1]{\groupedcommand{\startviewerlayer[#1]}{\stopviewerlayer}} % grouped % some day we will keep this at the lua end as the info is only needed there -\let\currentviewerlayer\empty \newtoks\currentviewerlayertoks % soon we can set macros at the lua end +\newtoks\currentviewerlayertoks % soon we can set macros at the lua end \def\currentviewerlayer{\the\currentviewerlayertoks} @@ -67,7 +67,9 @@ % layout components are implemented rather directly (speed) -\def\doinitializelayoutcomponent#1% +\installcorenamespace{layoutcomponentattribute} + +\def\attr_layoutcomponent_initialize#1% {\edef\layoutcomponentboxattribute{\ctxcommand{definedviewerlayer{% tag = "#1", title = utilities.strings.nice("#1"), % only here as in steps we have step:<number> @@ -76,24 +78,28 @@ printable = "\v!yes" }}}% \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}% - \expandafter\glet\csname\??lr:a:#1\endcsname\layoutcomponentboxattribute} + \expandafter\glet\csname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute} -\def\dosetlayoutcomponentattribute#1% make this faster - {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??lr:a:#1\endcsname +\def\attr_layoutcomponent_set#1% make this faster + {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??layoutcomponentattribute#1\endcsname \ifx\layoutcomponentboxattribute\relax - \doinitializelayoutcomponent{#1}% get rid of { } + \attr_layoutcomponent_initialize{#1}% get rid of { } \fi} -\def\doresetlayoutcomponentattribute +\def\attr_layoutcomponent_reset {\let\layoutcomponentboxattribute\empty} \let\setlayoutcomponentattribute \gobbleoneargument \let\resetlayoutcomponentattribute\relax \let\layoutcomponentboxattribute \empty -\def\showlayoutcomponents - {\ctxlua{attributes.viewerlayers.enable()}% will go - \let\setlayoutcomponentattribute \dosetlayoutcomponentattribute - \let\resetlayoutcomponentattribute\doresetlayoutcomponentattribute} +\unexpanded\def\showlayoutcomponents + {%\ctxlua{attributes.viewerlayers.enable()}% automatic + \let\setlayoutcomponentattribute \attr_layoutcomponent_set + \let\resetlayoutcomponentattribute\attr_layoutcomponent_reset} + +\appendtoks + \ctxcommand{cleanuplayers()}% +\to \everyshipout \protect \endinput diff --git a/tex/context/base/attr-neg.lua b/tex/context/base/attr-neg.lua index 4d89cb49b..c32cec956 100644 --- a/tex/context/base/attr-neg.lua +++ b/tex/context/base/attr-neg.lua @@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['attr-neg'] = { local format = string.format - -local attributes, nodes = attributes, nodes +local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends +local commands, context, interfaces = commands, context, interfaces +local tex = tex local states = attributes.states local tasks = nodes.tasks diff --git a/tex/context/base/attr-neg.mkiv b/tex/context/base/attr-neg.mkiv index 0fc5070f1..102b220ba 100644 --- a/tex/context/base/attr-neg.mkiv +++ b/tex/context/base/attr-neg.mkiv @@ -19,12 +19,12 @@ % positive and negative are preregistered -\def\dotriggernegative#1{\ctxcommand{triggernegative('#1')}} +\unexpanded\def\startnegative{\attr_trigger_negative\v!negative} +\unexpanded\def\stopnegative {\attr_trigger_negative\v!positive} -\unexpanded\def\startnegative{\dotriggernegative\v!negative} -\unexpanded\def\stopnegative {\dotriggernegative\v!positive} +\unexpanded\def\startpositive{\attr_trigger_negative\v!positive} +\unexpanded\def\stoppositive {\attr_trigger_negative\v!negative} -\unexpanded\def\startpositive{\dotriggernegative\v!positive} -\unexpanded\def\stoppositive {\dotriggernegative\v!negative} +\def\attr_trigger_negative#1{\ctxcommand{triggernegative('#1')}} \protect \endinput diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua index 3ce40a6c5..46ce4f96c 100644 --- a/tex/context/base/back-exp.lua +++ b/tex/context/base/back-exp.lua @@ -20,8 +20,9 @@ if not modules then modules = { } end modules ['back-exp'] = { local next, type = next, type local format, match, concat, rep, sub, gsub, gmatch, find = string.format, string.match, table.concat, string.rep, string.sub, string.gsub, string.gmatch, string.find +local validstring = string.valid local lpegmatch = lpeg.match -local utfchar, utfbyte, utfsub, utfgsub = utf.char, utf.byte, utf.sub, utf.gsub +local utfchar, utfbyte = utf.char, utf.byte local insert, remove = table.insert, table.remove local topoints = number.topoints local utfvalues = string.utfvalues @@ -154,6 +155,8 @@ local somespace = { [0x20] = true, [" "] = true } -- for testing local entities = { ["&"] = "&", [">"] = ">", ["<"] = "<" } local attribentities = { ["&"] = "&", [">"] = ">", ["<"] = "<", ['"'] = "quot;" } +local entityremapper = utf.remapper(entities) + local alignmapping = { flushright = "right", middle = "center", @@ -300,7 +303,7 @@ local usedstyles = { } local documenttemplate = [[ document { - font-size : %s !important ; + font-size : %s !important ; max-width : %s !important ; text-align : %s !important ; hyphens : %s !important ; @@ -382,7 +385,7 @@ local function allusedimages(xmlfile) for element, details in sortedhash(usedimages) do for detail, data in sortedhash(details) do local name = data.name - if file.extname(name) == "pdf" then + if file.suffix(name) == "pdf" then -- temp hack .. we will have a remapper name = file.replacesuffix(name,"svg") end @@ -397,7 +400,7 @@ local function uniqueusedimages() for element, details in next, usedimages do for detail, data in next, details do local name = data.name - if file.extname(name) == "pdf" then + if file.suffix(name) == "pdf" then unique[file.replacesuffix(name,"svg")] = name else unique[name] = name @@ -1351,7 +1354,7 @@ local function begintag(result,element,nature,depth,di,skip) end result[#result+1] = format("%s<metadata>\n",spaces[depth]) for k, v in table.sortedpairs(metadata) do - v = utfgsub(v,".",entities) + v = entityremapper(v) result[#result+1] = format("%s<metavariable name=%q>%s</metavariable>\n",spaces[depth+1],k,v) end result[#result+1] = format("%s</metadata>\n",spaces[depth]) @@ -1409,7 +1412,7 @@ local function flushtree(result,data,nature,depth) -- whatever elseif di.content then -- already has breaks - local content = utfgsub(di.content,".",entities) + local content = entityremapper(di.content) if i == nofdata and sub(content,-1) == "\n" then -- move check -- can be an end of line in par but can also be the last line if trace_spacing then @@ -2362,12 +2365,21 @@ local function stopexport(v) report_export("saving xhtml variant in '%s",xhtmlfile) local xmltree = cleanxhtmltree(xml.convert(results)) xml.save(xmltree,xhtmlfile) + -- looking at identity is somewhat redundant as we also inherit from interaction + -- at the tex end + local identity = interactions.general.getidentity() local specification = { name = file.removesuffix(v), identifier = os.uuid(), images = uniqueusedimages(), root = xhtmlfile, files = files, + language = languagenames[tex.count.mainlanguagenumber], + title = validstring(finetuning.title) or validstring(identity.title), + subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle), + author = validstring(finetuning.author) or validstring(identity.author), + firstpage = validstring(finetuning.firstpage), + lastpage = validstring(finetuning.lastpage), } report_export("saving specification in '%s' (mtxrun --script epub --make %s)",specificationfilename,specificationfilename) io.savedata(specificationfilename,table.serialize(specification,true)) diff --git a/tex/context/base/back-exp.mkiv b/tex/context/base/back-exp.mkiv index 871d08b19..9e65633d4 100644 --- a/tex/context/base/back-exp.mkiv +++ b/tex/context/base/back-exp.mkiv @@ -132,6 +132,11 @@ [\c!align=\number\raggedstatus, \c!bodyfont=\bodyfontsize, \c!width=\textwidth, + \c!title={\directinteractionparameter\c!title}, + \c!subtitle={\directinteractionparameter\c!subtitle}, + \c!author={\directinteractionparameter\c!author}, + % \c!firstpage=, % imagename + % \c!lastpage=, % imagename \c!hyphen=\v!no] \def\dosynchronizeexport @@ -141,13 +146,22 @@ bodyfont = \number\dimexpr\exportparameter\c!bodyfont, width = \number\dimexpr\exportparameter\c!width, hyphen = "\exportparameter\c!hyphen", + title = \!!bs\exportparameter\c!title\!!es, + subtitle = \!!bs\exportparameter\c!subtitle\!!es, + author = \!!bs\exportparameter\c!author\!!es, + firstpage = "\exportparameter\c!firstpage", + lastpage = "\exportparameter\c!lastpage", }}} \appendtoks - \doifsomething{\backendparameter\c!export}{\dosynchronizeexport}% + \doifsomething{\backendparameter\c!export}\dosynchronizeexport \to \everystarttext \appendtoks + \doifsomething{\backendparameter\c!export}\dosynchronizeexport % in case it is done inside \starttext +\to \everysetupdocument + +\appendtoks \doifsomething{\backendparameter\c!xhtml} {\enabledirectives[backend.export.xhtml=\backendparameter\c!xhtml]}% \doifsomething{\backendparameter\c!css} @@ -155,11 +169,11 @@ \to \everysetupbackend \appendtoks - \doifsomething{\backendparameter\c!export} - {\setuptagging - [\c!state=\v!start]% - \enabledirectives - [backend.export=\backendparameter\c!export]}% + \doifelsenothing{\backendparameter\c!export} + {\resetsystemmode\v!export} + {\setuptagging[\c!state=\v!start]% + \enabledirectives[backend.export=\backendparameter\c!export]% + \setsystemmode\v!export}% \to \everysetupbackend \protect \endinput diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua index 0c02e201a..f76b85438 100644 --- a/tex/context/base/back-ini.lua +++ b/tex/context/base/back-ini.lua @@ -93,9 +93,9 @@ tables.vfspecials = allocate { stopslant = comment, } --- -- experimental code -- +-- experimental code -- -function commands.pdfrotation(a) +function commands.pdfrotation(a) -- somewhat weird here local s, c = sind(a), cosd(a) context("%s %s %s %s",c,s,-s,c) end diff --git a/tex/context/base/back-ini.mkiv b/tex/context/base/back-ini.mkiv index 8ece8f6e1..fc8759c14 100644 --- a/tex/context/base/back-ini.mkiv +++ b/tex/context/base/back-ini.mkiv @@ -61,13 +61,13 @@ \let \dotransformnextbox\gobblesixarguments % and pass last box %D \macros -%D {doovalbox} +%D {back_ovalbox} %D %D When we look at the implementation, this is a complicated %D one. There are seven arguments. %D %D \starttyping -%D \doovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant} +%D \back_ovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant} %D \stoptyping %D %D This command has to return a \type{\vbox} which can be used @@ -75,7 +75,7 @@ %D degrees, the stroke and fill are~\type{1} (true) of~\type{0} %D (false). -\let \doovalbox \gobbleeightarguments +\let\back_ovalbox \gobbleeightarguments %D \macros %D {dostartclipping,dostopclipping} diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv index 9e441e224..7e910f07f 100644 --- a/tex/context/base/back-pdf.mkiv +++ b/tex/context/base/back-pdf.mkiv @@ -68,16 +68,17 @@ {\ctxcommand{setxmpfile("\backendparameter{xmpfile}")}}% \to \everysetupbackend +% \doifsomething{\backendparameter\c!format} .. at the lua end + \appendtoks - \doifsomething{\backendparameter\c!format} - {\ctxcommand{setformat { + \ctxcommand{setformat { format = "\backendparameter\c!format", level = "\backendparameter\c!level", option = "\backendparameter\c!option", profile = "\backendparameter\c!profile", intent = "\backendparameter\c!intent", file = "\backendparameter\c!file", - }}}% + }}% \to \everysetupbackend %D For the moment we keep these. @@ -220,12 +221,12 @@ \newbox\objectbox -\def\dostartobject#1#2#3#4#5% +\unexpanded\def\dostartobject#1#2#3#4#5% needs to be \unexpanded {\bgroup \setbox\objectbox\vbox\bgroup \def\back_object_stop{\egroup\back_object_register{#1}{#2}}} -\def\dostopobject +\unexpanded\def\dostopobject % needs to be \unexpanded {\back_object_stop \egroup} @@ -237,9 +238,6 @@ \immediate\pdfxform resources {\pdfbackendcurrentresources}\objectbox \dosetobjectreference{#1}{#2}{\the\pdflastxform}} -\def\doresetobjects - {} - \let\m_back_object_reference\empty \def\doinsertobject#1#2% @@ -263,7 +261,7 @@ % for the moment here %D \macros -%D {doovalbox} +%D {back_ovalbox} %D %D Drawing frames with round corners is inherited from the %D main module. @@ -276,7 +274,7 @@ % \def\back_oval_calculate#1#2#3% % {\PointsToBigPoints{\dimexpr#2+#3\relax}#1} -\unexpanded\def\doovalbox#1#2#3#4#5#6#7#8% +\unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8% {\forcecolorhack \bgroup % \scratchdimen#4% @@ -306,16 +304,16 @@ \PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin % - \edef\dostroke{#6}% - \edef\dofill{#7}% - \edef\mode{\number#8 \space}% + \edef\dostroke{\number#6}% + \edef\dofill{\number#7}% + \edef\mode{\number#8}% % no \ifcase, else \relax in pdfcode \setbox\scratchbox\hbox {\ifnum\dostroke\dofill>\zerocount \pdfliteral {q \stroke\space w - \ifcase\mode + \ifcase\mode\space \xxmin\space \ymin \space m \xxmax\space \ymin \space l \xmax \space \ymin \space \xmax \space \yymin\space y @@ -495,7 +493,7 @@ \xmin \space \ymin \space \xmin \space \yymin\space y \or % 28 \fi - \ifnum\mode>8 + \ifnum\mode>8\space S \else \ifnum\dostroke=\plusone S \fi diff --git a/tex/context/base/back-swf.mkiv b/tex/context/base/back-swf.mkiv index 1d225b550..09745e0f9 100644 --- a/tex/context/base/back-swf.mkiv +++ b/tex/context/base/back-swf.mkiv @@ -11,12 +11,12 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% This is only a placeholder that demonstrates the usage of swf -% resources. - -%D \starttyping -%D \starttext +%D This is only a placeholder that demonstrates the usage of swf resources. +%D There is no need to include this file into the format. The module was +%D tested by Luigi and Willi and based on their suggestions the functionality +%D was improved. %D +%D \starttyping %D \enabletrackers[graphics.locating] %D \enabletrackers[backend.swf] %D @@ -41,8 +41,6 @@ %D \stopTEXpage %D \stoptyping -\stoptext - \endinput \starttext @@ -72,8 +70,6 @@ }, \stopluaparameterset -\starttext - % preview=swf:myset:display:1 % controls=swf:myset:controls:1 % resources=swf:myset:resources:1 diff --git a/tex/context/base/back-u3d.mkiv b/tex/context/base/back-u3d.mkiv index dfe8a90c2..89d26ee41 100644 --- a/tex/context/base/back-u3d.mkiv +++ b/tex/context/base/back-u3d.mkiv @@ -11,10 +11,9 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% This is only a placeholder that demonstrates the usage of u3d -% resources. The user interface is rather messy an might be -% improved. The files and setup is derived from an example by -% Michael Vidiassov. +%D This is only a placeholder that demonstrates the usage of u3d resources. The +%D user interface is rather messy an might be improved. The files and setup is +%D derived from an example by Michael Vidiassov. \endinput diff --git a/tex/context/base/bibl-bib.mkiv b/tex/context/base/bibl-bib.mkiv index 56007d21c..7ca6799cf 100644 --- a/tex/context/base/bibl-bib.mkiv +++ b/tex/context/base/bibl-bib.mkiv @@ -626,7 +626,7 @@ \doifelse{\bibtexpublicationsparameter\c!method}\v!local {\ctxlua{bibtex.hacks.reset(1)}}% function can take method {\ctxlua{bibtex.hacks.reset(2)}}% - \doplacestructurelist + \strc_lists_place_current {\currentbibtexsession} {\currentbibtexcriterium} {\namedlistparameter\currentbibtexsession\c!number}% diff --git a/tex/context/base/bibl-tra.lua b/tex/context/base/bibl-tra.lua index 6341898ee..ca6403c44 100644 --- a/tex/context/base/bibl-tra.lua +++ b/tex/context/base/bibl-tra.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['bibl-bib'] = { +if not modules then modules = { } end modules ['bibl-tra'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -115,7 +115,7 @@ function hacks.registerplaced(str) end function hacks.doifalreadyplaced(str) - commands.testcase(used[str]) + commands.doifelse(used[str]) end -- we ask for <n>:tag but when we can't find it we go back diff --git a/tex/context/base/bibl-tra.mkiv b/tex/context/base/bibl-tra.mkiv index 3531703ad..08d8eb6fe 100644 --- a/tex/context/base/bibl-tra.mkiv +++ b/tex/context/base/bibl-tra.mkiv @@ -755,7 +755,7 @@ \ctxlua{bibtex.hacks.filterall()}} {\doif{\listparameter\c!criterium}\v!cite {\setuplist[pubs][\c!criterium=\v!here]}% - \doplacestructurelist + \strc_lists_place_current {pubs}% {\listparameter\c!criterium}% {\listparameter\c!number}% @@ -1244,7 +1244,7 @@ %D \type{\ixbibauthoryearref} stores the data in the macros %D \type{\currentbibauthor} and \type{\currentbibyear}. -\def\ifbibinteractionelse +\def\doifbibinteractionelse {\iflocation \edef\test{\bibalternative\c!interaction}% \ifx\test\v!stop @@ -1256,20 +1256,11 @@ \@EA\secondoftwoarguments \fi} -\def\ifbibinteractionelse - {\iflocation - \doifelse{\bibalternative\c!interaction}\v!stop - {\@EA\secondoftwoarguments} - {\@EA\firstoftwoarguments}% - \else - \@EA\secondoftwoarguments - \fi} - \def\bibmaybeinteractive#1#2% {\ifbibcitecompress #2% \else - \ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}% + \doifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}% \fi} \def\bibauthoryearref[#1]% @@ -1360,7 +1351,7 @@ \gotobiblink{#1}[#1]} \def\bibgotoDOI#1#2% - {\ifbibinteractionelse + {\doifbibinteractionelse {\useURL[bibfooDoi#1][#2]% \useURL[bibfoo#1][http://dx.doi.org/#2]% \goto{\url[bibfooDoi#1]}[url(bibfoo#1)]} @@ -1383,7 +1374,7 @@ \bibalternative\v!right} \def\bibgotoURL#1#2% - {\ifbibinteractionelse + {\doifbibinteractionelse {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]} {\hyphenatedurl{#2}}} @@ -1411,7 +1402,7 @@ \def\dobibpageref#1% {\bibinsertrefsep - \ifbibinteractionelse + \doifbibinteractionelse {\atbiblink[#1]} {{\referencingfalse\at[#1]}}} @@ -1484,8 +1475,6 @@ %D And some defaults are loaded from bibl-apa: -\def\c!monthconversion{monthconversion} % todo - \setuppublications [\c!monthconversion=, \c!alternative=apa, @@ -1502,4 +1491,6 @@ % \appendtoks \preloadbiblist \to \everysetuppublications % \appendtoks \preloadbiblist \to \everystarttext +\let\ifbibinteractionelse\doifbibinteractionelse + \protect \endinput diff --git a/tex/context/base/blob-ini.lua b/tex/context/base/blob-ini.lua index b97485b1b..4debaf94c 100644 --- a/tex/context/base/blob-ini.lua +++ b/tex/context/base/blob-ini.lua @@ -74,7 +74,7 @@ function blobs.dispose(t) end end -function blobs.append(t,str) -- will be link nodes.link +function blobs.append(t,str) -- compare concat and link local typ = type(str) local dummy = nil if typ == "number" then diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua index 7098679ca..11d7cc9f6 100644 --- a/tex/context/base/buff-ini.lua +++ b/tex/context/base/buff-ini.lua @@ -13,21 +13,23 @@ local trace_visualize = false trackers.register("buffers.visualize", function(v local report_buffers = logs.reporter("buffers","usage") local report_grabbing = logs.reporter("buffers","grabbing") +local context, commands = context, commands + local concat = table.concat local type, next = type, next local sub, format, match, find = string.sub, string.format, string.match, string.find -local count, splitlines = string.count, string.splitlines +local count, splitlines, validstring = string.count, string.splitlines, string.valid -local variables = interfaces.variables +local variables = interfaces.variables local settings_to_array = utilities.parsers.settings_to_array -local ctxcatcodes = tex.ctxcatcodes -local txtcatcodes = tex.txtcatcodes +local catcodenumbers = catcodes.numbers -buffers = { } +local ctxcatcodes = catcodenumbers.ctxcatcodes +local txtcatcodes = catcodenumbers.txtcatcodes +buffers = buffers or { } local buffers = buffers -local context = context local cache = { } @@ -100,14 +102,17 @@ commands.assignbuffer = assign local P, patterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match +local anything = patterns.anything +local alwaysmatched = patterns.alwaysmatched + local function countnesting(b,e) local n local g = P(b) / function() n = n + 1 end + P(e) / function() n = n - 1 end - + patterns.anything - local p = patterns.alwaysmatched / function() n = 0 end + + anything + local p = alwaysmatched / function() n = 0 end * g^0 - * patterns.alwaysmatched / function() return n end + * alwaysmatched / function() return n end return p end @@ -150,12 +155,10 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe else if continue then dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic + elseif dn == "" then + dn = sub(bufferdata,2,-2) else - if dn == "" then - dn = sub(bufferdata,2,-2) - else - dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic - end + dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic end local last = sub(dn,-1) if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar @@ -184,7 +187,7 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe end end assign(name,dn,catcodes) - commands.testcase(more) + commands.doifelse(more) end -- The optional prefix hack is there for the typesetbuffer feature and @@ -232,12 +235,12 @@ end function commands.getbuffer(name) local str = getcontent(name) if str ~= "" then - context.viafile(str) + context.viafile(str,format("buffer.%s",validstring(name,"noname"))) end end function commands.getbuffermkvi(name) -- rather direct ! - context.viafile(resolvers.macros.preprocessed(getcontent(name))) + context.viafile(resolvers.macros.preprocessed(getcontent(name)),format("buffer.%s.mkiv",validstring(name,"noname"))) end function commands.gettexbuffer(name) @@ -265,7 +268,7 @@ function commands.getbufferctxlua(name) end function commands.doifelsebuffer(name) - commands.testcase(exists(name)) + commands.doifelse(exists(name)) end -- This only used for mp buffers and is a kludge. Don't change the diff --git a/tex/context/base/buff-ini.mkiv b/tex/context/base/buff-ini.mkiv index 239a274c0..5f9d1d1e6 100644 --- a/tex/context/base/buff-ini.mkiv +++ b/tex/context/base/buff-ini.mkiv @@ -199,4 +199,28 @@ \def\getbufferdata[#1]{\buff_get_stored_indeed{#1}} +%D This is a weird one, moved from cont-new. Do we really need it? If not +%D it will go away. + +\bgroup \permitcircumflexescape + +\obeylines % don't remove %'s ! + +\gdef\collapsedspace#1% + {\ifx#1^^M% + \expandafter\collapsedspace + \else + \space + \expandafter#1% + \fi} + +\unexpanded\gdef\collapsespaces + {\prependtoksonce\relax\to\everyeof% + \ignorelines% + \ignoretabs% + \let\obeyedspace\collapsedspace% + \obeyspaces} + +\egroup + \protect \endinput diff --git a/tex/context/base/buff-par.lua b/tex/context/base/buff-par.lua index 2015b0bc0..29742f497 100644 --- a/tex/context/base/buff-par.lua +++ b/tex/context/base/buff-par.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['buff-ini'] = { +if not modules then modules = { } end modules ['buff-par'] = { version = 1.001, comment = "companion to buff-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -6,21 +6,26 @@ if not modules then modules = { } end modules ['buff-ini'] = { license = "see context related readme files" } -local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end) - -local report_parallel = logs.reporter("buffers","parallel") +local context, commands = context, commands local insert, remove, find, gmatch = table.insert, table.remove, string.find, string.gmatch local strip, format = string.strip, string.format -local variables = interfaces.variables +local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end) + +local report_parallel = logs.reporter("buffers","parallel") + +local variables = interfaces.variables + +local parallel = buffers.parallel or { } +buffers.parallel = parallel -buffers.parallel = { } local parallel = buffers.parallel +local settings_to_array = utilities.parsers.settings_to_array -local data = { } +local data = { } function parallel.define(category,tags) - local tags = utilities.parsers.settings_to_array(tags) + local tags = settings_to_array(tags) local entries = { } data[category] = { tags = tags, @@ -38,7 +43,7 @@ function parallel.reset(category,tags) if not tags or tags == "" or tags == variables.all then tags = table.keys(entries) else - tags = utilities.parsers.settings_to_array(tags) + tags = settings_to_array(tags) end for i=1,#tags do entries[tags[i]] = { @@ -76,7 +81,7 @@ function parallel.save(category,tag,content) end -- maybe no strip -- use lpeg - if find(content,"^%s*%[") then + if find(content,"%s*%[") then local done = false for label, content in gmatch(content,"%s*%[(.-)%]%s*([^%[]+)") do if done then @@ -175,5 +180,5 @@ commands.placeparallel = parallel.place commands.resetparallel = parallel.reset function commands.doifelseparallel(category,tags) - commands.testcase(parallel.hassomecontent(category,tags)) + commands.doifelse(parallel.hassomecontent(category,tags)) end diff --git a/tex/context/base/buff-par.mkiv b/tex/context/base/buff-par.mkiv deleted file mode 100644 index 7d35676bd..000000000 --- a/tex/context/base/buff-par.mkiv +++ /dev/null @@ -1,151 +0,0 @@ -%D \module -%D [ file=buff-par, -%D version=2010.12.05, -%D title=\CONTEXT\ Buffer Macros, -%D subtitle=Parallel, -%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 Buffer Macros / Parallel} - -\registerctxluafile{buff-par}{1.001} - -%D This module is developped for Thomas Schmitz as part of -%D a project. - -\unprotect - -\letvalue{\??px:}\empty - -\def\parallelparameter#1% - {\csname\??px:% - \ifcsname\??px:\currentparallel:\currentparallelinstance:#1\endcsname - \currentparallel:\currentparallelinstance:#1% - \else\ifcsname\??px:\currentparallel:#1\endcsname - \currentparallel:#1% - \else\ifcsname\??px:#1\endcsname - #1% - \fi\fi\fi - \endcsname} - -\unexpanded\def\defineparallel - {\dodoubleargument\dodefineparallel} - -\def\dodefineparallel[#1][#2]% - {\ctxcommand{defineparallel("#1","#2")}% - \processcommalist[#2]\dododefineparallel - \setuvalue{\e!start#1}{\dostartparallelset{#1}}% - \setuvalue{\e!stop #1}{\dostopparallelset}} - -\def\dododefineparallel#1% - {\definebuffer[#1]%% - \setuvalue{\e!stop#1}{\dowithparallel{#1}}} - -\def\dostartparallelset#1% - {\def\currentparallel{#1}% - \ctxcommand{nextparallel("\currentparallel")}} - -\def\dostopparallelset#1% - {} - -\def\dowithparallel#1% defined moet ook aan de lua kant kunnen - {\ctxcommand{saveparallel("\currentparallel","#1",buffers.raw("\thedefinedbuffer{#1}"))}} - -\unexpanded\def\placeparallel - {\dotripleempty\doplaceparallel} - -\def\doplaceparallel[#1][#2][#3]% - {\begingroup - \def\currentparallel{#1}% - \ctxcommand{placeparallel("\currentparallel","#2","#3")}% - \endgroup} - -% was: \parallelparameter\c!command} - -\def\doflushparallel#1#2#3#4#5% {instance}{status}{line}{label}{content} - {\begingroup - \def\currentparallelinstance{#1}% - \def\currentparallelnumber {#2}% - \def\currentparallelline {#3}% - \def\currentparallellabel {#4}% - \def\currentparallelcontent {#5}% - \ifcase#2\relax - \expandafter\noflushparalleldefault - \or - \expandafter\doflushparalleldefault - \fi - \endgroup} - -\def\noflushparalleldefault{} -\def\doflushparalleldefault{\directsetup{\parallelparameter\c!setups}} - -\startsetups parallel:place:default - \hangafter\plusone - \hangindent4em - \dontleavehmode - \hbox to 3em \bgroup - \hss - \bf - \doifsomething \currentparallellabel { - \textreference[\currentparallellabel]{\currentparallelline} - } - \currentparallelline - \quad - \egroup - \currentparallelcontent - \par -\stopsetups - -\unexpanded\def\setupparallel - {\dotripleempty\dosetupparallel} - -\def\dosetupparallel[#1][#2][#3]% - {\ifthirdargument - \getparameters[\??px:#1:#2:][#3]% - \else\ifsecondargument - \getparameters[\??px:#1:][#2]% - \else - \getparameters[\??px:][#1]% maybe no : here - \fi\fi} - -\setupparallel -% [\c!command=\doflushparalleldefault] - [\c!setups=parallel:place:default] - -\def\doifelseparallel#1#2% - {\cldcontext{commands.doifelseparallel("#1","#2")}} - -\def\resetparallel - {\dodoubleempty\doresetparallel} - -\def\resetparallel[#1][#2]% - {\ctxcommand{resetparallel("#1","#2"))}} - -% default - -% \def\doflushparalleldefault#1#2#3#4% todo: setups instead -% {\ifcase#1\or -% \begingroup -% \hangafter1 -% \hangindent4em -% \dontleavehmode -% \hbox to 3em{\hss\bf\doifsomething{#3}{\textreference[#3]{#2}}#2\quad}#4\par -% \endgroup -% \fi} - -\protect \endinput - -% \def\dododefineparallel#1% -% {\setuvalue{\e!stop #1}{}% -% \setuvalue{\e!start#1}{\dostartparallel{#1}}} -% -% \def\dostartparallel#1% -% {\grabuntil{\e!stop#1}{\dododostartparallel{#1}}} -% -% \def\dododostartparallel#1#2% -% {\ctxcommand{saveparallel("\currentparallel","#1",\!!bs\detokenize{#2}\!!es)}} diff --git a/tex/context/base/buff-par.mkvi b/tex/context/base/buff-par.mkvi new file mode 100644 index 000000000..404fa8ef3 --- /dev/null +++ b/tex/context/base/buff-par.mkvi @@ -0,0 +1,131 @@ +%D \module +%D [ file=buff-par, +%D version=2010.12.05, +%D title=\CONTEXT\ Buffer Macros, +%D subtitle=Parallel, +%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 Buffer Macros / Parallel} + +\registerctxluafile{buff-par}{1.001} + +%D This module is developped for Thomas Schmitz as part of a project. There is +%D no documentation yet. +%D +%D \starttyping +%D \defineparallel[main][one,two] +%D +%D \startmain +%D \startone +%D first 1 +%D [reference] first 2 +%D first 3 +%D \stopone +%D \starttwo +%D second 1 +%D \stoptwo +%D \stopmain +%D +%D \placeparallel[main][one,two][criterium=all] + +%D criterium=all start=<number> n=<number> + +\unprotect + +\installcorenamespace{parallel} + +\installcommandhandler \??parallel {parallel} \??parallel + +\setupparallel + [\c!setups=parallel:place:default] + +\let\buff_parallel_define_saved\defineparallel + +\unexpanded\def\defineparallel + {\dodoubleargument\buff_parallel_define} + +\def\buff_parallel_define[#name][#instances]% + {\buff_parallel_define_saved[#name] + \ctxcommand{defineparallel("#name","#instances")}% + \processcommalist[#instances]\buff_parallel_define_instance + \setuevalue{\e!start#name}{\buff_parallel_start{#name}}% + \setuevalue{\e!stop #name}{\buff_parallel_stop}} + +\def\buff_parallel_define_instance#instance% + {\normalexpanded{\buff_parallel_define_saved[#instance][\currentparallel]}% + \definebuffer[#instance]% + \setuevalue{\e!stop#instance}{\buff_parallel_save{#instance}}} + +\unexpanded\def\buff_parallel_start#name% + {\pushmacro\currentparallel + \edef\currentparallel{#name}% + \ctxcommand{nextparallel("\currentparallel")}} + +\unexpanded\def\buff_parallel_stop + {\popmacro\currentparallel} + +\unexpanded\def\buff_parallel_save#instance% defined moet ook aan de lua kant kunnen + {\ctxcommand{saveparallel("\currentparallel","#instance",buffers.raw("\thedefinedbuffer{#instance}"))}} + +\unexpanded\def\placeparallel + {\dotripleempty\buff_parallel_place} + +\def\buff_parallel_place[#name][#instance][#settings]% + {\begingroup + \edef\currentparallel{#name}% + \ctxcommand{placeparallel("\currentparallel","#instance","#settings")}% -- todo: pass options as k/v + \endgroup} + +\def\doflushparallel#instance#status#line#label#content% called at lua end + {\begingroup + \def\currentparallelinstance{#instance}% + \def\currentparallelnumber {#status}% + \def\currentparallelline {#line}% + \def\currentparallellabel {#label}% + \def\currentparallelcontent {#content}% + \ifcase#status\relax + \expandafter\buff_parallel_flush_nop + \or + \expandafter\buff_parallel_flush_yes + \fi + \endgroup} + +\def\buff_parallel_flush_nop + {} + +\def\buff_parallel_flush_yes + {\directsetup{\namedparallelparameter\currentparallelinstance\c!setups}} + +\unexpanded\def\doifelseparallel#name#instance% + {\ctxcommand{doifelseparallel("#name","#instance")}} + +\unexpanded\def\resetparallel + {\dodoubleempty\buff_parallel_reset} + +\def\buff_parallel_reset[#name][#instance]% + {\ctxcommand{resetparallel("#name","#instance"))}} + +\startsetups parallel:place:default + \hangafter\plusone + \hangindent4em + \dontleavehmode + \hbox to 3em \bgroup + \hss + \bf + \doifsomething \currentparallellabel { + \textreference[\currentparallellabel]{\currentparallelline} + } + \currentparallelline + \quad + \egroup + \currentparallelcontent + \par +\stopsetups + +\protect \endinput diff --git a/tex/context/base/buff-ver.lua b/tex/context/base/buff-ver.lua index 004d89858..5748d9298 100644 --- a/tex/context/base/buff-ver.lua +++ b/tex/context/base/buff-ver.lua @@ -18,6 +18,8 @@ local concat = table.concat local C, P, R, S, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs local patterns, lpegmatch, is_lpeg = lpeg.patterns, lpeg.match, lpeg.is_lpeg +local context, commands = context, commands + local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end) local report_visualizers = logs.reporter("buffers","visualizers") @@ -30,7 +32,6 @@ visualizers.specifications = specifications local tabtospace = utilities.strings.tabtospace local variables = interfaces.variables local settings_to_array = utilities.parsers.settings_to_array -local verbatim = context.verbatim local variables = interfaces.variables local findfile = resolvers.findfile local addsuffix = file.addsuffix @@ -52,6 +53,7 @@ local dodisplayverbatimemptyline = context.dodisplayverbatimemptyline local dodisplayverbatimstart = context.dodisplayverbatimstart local dodisplayverbatimstop = context.dodisplayverbatimstop +local verbatim = context.verbatim local doverbatimspace = context.doverbatimspace local CargOne = Carg(1) @@ -688,7 +690,7 @@ local getlines = buffers.getlines -- interface function commands.doifelsevisualizer(name) - commands.testcase(specifications[lower(name)]) + commands.doifelse(specifications[lower(name)]) end commands.loadvisualizer = visualizers.load diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv index 5336c4458..d18883faf 100644 --- a/tex/context/base/buff-ver.mkiv +++ b/tex/context/base/buff-ver.mkiv @@ -70,21 +70,22 @@ \csname\??typingspace\typeparameter\c!space\endcsname \relax\the\everyinitializeverbatim\relax} +\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini) + {\buff_verbatim_initialize_type_one + \buff_verbatim_initialize_type_two} + \let\buff_verbatim_set_line_margin\relax \def\buff_verbatim_set_line_margin_indeed - {\getpagestatus - \hskip\ifrightpage\typingparameter\c!oddmargin\else\typingparameter\c!evenmargin\fi\relax} + {\hskip\doifoddpageelse{\typingparameter\c!oddmargin}{\typingparameter\c!evenmargin}\relax} \def\buff_verbatim_check_margins {\scratchskip\typingparameter\c!oddmargin\relax - \ifzeropt\scratchskip - \else + \ifzeropt\scratchskip \else \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed \fi \scratchskip\typingparameter\c!evenmargin\relax - \ifzeropt\scratchskip - \else + \ifzeropt\scratchskip \else \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed \fi \ifx\buff_verbatim_set_line_margin\relax @@ -331,7 +332,7 @@ \unexpanded\def\specialfixedspace {\kern\interwordspace\relax} \unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip -\unexpanded\def\specialstretchedspace{\hskip.5\interwordspace\!!plus.125\interwordstretch\relax} % more but not less +\unexpanded\def\specialstretchedspace{\hskip.5\interwordspace\s!plus.125\interwordstretch\relax} % more but not less \unexpanded\def\specialcontrolspace {\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax} \unexpanded\def\obeyhyphens @@ -369,7 +370,7 @@ \let\inlinemathmarker \textdollar \def\displaymathmarker{\textdollar\textdollar} -\def\buff_verbatim_special_type#1#2% +\def\buff_verbatim_special_type#1#2#% # gobbles spaces {\dontleavehmode\bgroup \buff_verbatim_initialize_type_one \catcode\leftbraceasciicode \begingroupcatcode @@ -390,6 +391,8 @@ \unexpanded\def\astype{\bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken} +\unexpanded\def\asciistr#1{\dontleavehmode{\verbatimfont\detokenize{#1}}} % use in some old styles + %D The basic display verbatim commands are defined in an indirect way. As we %D will see, they are a specific case of a more general mechanism. @@ -641,9 +644,9 @@ \c!text=\v!no, \c!style=\tt, \c!indentnext=\v!yes, - \c!margin=\!!zeropoint, - \c!evenmargin=\!!zeropoint, - \c!oddmargin=\!!zeropoint, + \c!margin=\zeropoint, + \c!evenmargin=\zeropoint, + \c!oddmargin=\zeropoint, \c!blank=\v!line, %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX} \c!numbering=\v!no, @@ -836,4 +839,9 @@ % \usevisualizerstyleandcolor\c!style\c!color % \let\next} +\appendtoks + \def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize + \def\tex #1{\letterbackslash#1}% +\to \everysimplifycommands + \protect \endinput diff --git a/tex/context/base/catc-ctx.mkiv b/tex/context/base/catc-ctx.mkiv index bd5c16d69..ddade7f52 100644 --- a/tex/context/base/catc-ctx.mkiv +++ b/tex/context/base/catc-ctx.mkiv @@ -128,11 +128,18 @@ % for the moment here: -\def\starttexcode +\normalprotected\def\starttexcode {\pushcatcodetable \catcodetable\prtcatcodes} -\def\stoptexcode +\normalprotected\def\stoptexcode + {\popcatcodetable} + +\normalprotected\def\startcontextcode + {\pushcatcodetable + \catcodetable\ctxcatcodes} + +\normalprotected\def\stopcontextcode {\popcatcodetable} \endinput diff --git a/tex/context/base/catc-def.mkiv b/tex/context/base/catc-def.mkiv index 26e8cb11e..cfbaed171 100644 --- a/tex/context/base/catc-def.mkiv +++ b/tex/context/base/catc-def.mkiv @@ -123,7 +123,7 @@ %D shortcuts to their character representation. \chardef \^ = \circumflexasciicode -\chardef \_ = \underscoreasciicode % but way too wide in lm, so ... until that's fixed: +\chardef \_ = \underscoreasciicode \chardef \& = \ampersandasciicode \chardef \% = \commentasciicode \chardef \# = \hashasciicode @@ -133,8 +133,9 @@ \chardef \\ = \backslashasciicode \chardef \| = \barasciicode -%def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}} -\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef +% way too wide in lm, so one can also use: +% +% \def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef %D From now on we can use the protection mechanisms. diff --git a/tex/context/base/catc-ini.lua b/tex/context/base/catc-ini.lua index b2c793a6a..d4f9b65af 100644 --- a/tex/context/base/catc-ini.lua +++ b/tex/context/base/catc-ini.lua @@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['catc-ini'] = { license = "see context related readme files" } --- todo: everywhere replace tex.ctxcatcodes -> catcodes.numbers.ctxcatcodes - catcodes = catcodes or { } catcodes.numbers = catcodes.numbers or { } catcodes.names = catcodes.names or { } @@ -15,26 +13,29 @@ catcodes.names = catcodes.names or { } storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers") storage.register("catcodes/names", catcodes.names, "catcodes.names") +local numbers = catcodes.numbers +local names = catcodes.names + -- this only happens at initime function catcodes.register(name,number) - catcodes.numbers[name] = number - local cnn = catcodes.names[number] + numbers[name] = number + local cnn = names[number] if cnn then cnn[#cnn+1] = name else - catcodes.names[number] = { name } + names[number] = { name } end - tex[name] = number + tex[name] = number -- downward compatible end -- this only happens at runtime -for k, v in next, catcodes.numbers do - tex[k] = v +for k, v in next, numbers do + tex[k] = v -- downward compatible end -- nasty -table.setmetatableindex(catcodes.numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end) -table.setmetatableindex(catcodes.names, function(t,k) if type(k) == "string" then t[k] = k return k end end) +table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end) +table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end) diff --git a/tex/context/base/catc-ini.mkiv b/tex/context/base/catc-ini.mkiv index 26c3ceee9..791ce31c4 100644 --- a/tex/context/base/catc-ini.mkiv +++ b/tex/context/base/catc-ini.mkiv @@ -87,6 +87,17 @@ \xdef\outputnewlinechar{^^J}% \endgroup} +%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots +%D for catcodes. + +\def\??catcodelet {1>>} % let : \let +\def\??catcodedef {2>>} % def : \def +\def\??catcodeued {3>>} % ued : \unexpanded\def +\def\??catcodeget {4>>} % \meaning + +\def\??catcodetablet{5>>} +\def\??catcodetablen{6>>} + \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 @@ -94,7 +105,7 @@ \normalprotected\def\newcatcodetable#1% we could move the cctdefcounter to lua {\global\advance\c_syst_catcodes_n\plusone - \expandafter\xdef\csname\??qm:n:\number\c_syst_catcodes_n\endcsname{\string#1}% logging + \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging \newconstant#1% #1\c_syst_catcodes_n \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}} @@ -151,12 +162,7 @@ \setnewconstant\c_syst_catcodes_hack\tildeasciicode %D Once a catcode is assigned, the next assignments will happen -%D faster. We predefine some prefixes ahead of mult-sys. - -\def\??ql{@@ql} % let : \let -\def\??qd{@@qd} % def : \def -\def\??qu{@@qu} % ued : \unexpanded\def -\def\??qm{@@qm} % \meaning +%D faster. \def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a} \def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a} @@ -167,46 +173,46 @@ \def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b} \def\syst_catcodes_let_b % each time - {\ifcsname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname \else \expandafter\syst_catcodes_let_c \fi} \def\syst_catcodes_def_b % each time - {\ifcsname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname \else \expandafter\syst_catcodes_def_c \fi} \def\syst_catcodes_ued_b % each time - {\ifcsname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname - \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname \else \expandafter\syst_catcodes_ued_c \fi} \def\syst_catcodes_let_c % only first time - {\expandafter\gdef\csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter - {\expandafter\let\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}% + {\expandafter\gdef\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter + {\expandafter\let\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}% \syst_catcodes_reinstate_unexpanded - \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + \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) - {\expandafter\gdef\csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + {\expandafter\gdef\csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname \expandafter##\expandafter1\expandafter - {\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + {\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% \syst_catcodes_reinstate_normal - \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} \def\syst_catcodes_ued_c % only first time - {\expandafter\gdef\csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + {\expandafter\gdef\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname \expandafter##\expandafter1\expandafter - {\expandafter\normalprotected\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + {\expandafter\normalprotected\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% \syst_catcodes_reinstate_unexpanded - \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} \def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b} @@ -227,8 +233,8 @@ \newconstant\defaultcatcodetable \def\catcodecommand#1% - {\csname\??qm:\number - \ifcsname\??qm:\number\currentcatcodetable:\number#1\endcsname + {\csname\??catcodeget\number + \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname \currentcatcodetable \else \defaultcatcodetable \fi :\number#1\endcsname} @@ -251,13 +257,13 @@ \normalprotected\def\pushcatcodetable {\advance\c_syst_catcodes_level\plusone \syst_catcodes_trace_push - \expandafter\chardef\csname\??qm:t:\number\c_syst_catcodes_level\endcsname\currentcatcodetable} + \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable} \normalprotected\def\popcatcodetable {\ifcase\c_syst_catcodes_level \syst_catcodes_trace_nesting_error \else - \expandafter\catcodetable\csname\??qm:t:\number\c_syst_catcodes_level\endcsname + \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname \syst_catcodes_trace_pop \advance\c_syst_catcodes_level\minusone \fi} @@ -269,7 +275,7 @@ \normalprotected\def\restorecatcodes % takes previous level {\ifnum\c_syst_catcodes_level>\plusone - \expandafter\catcodetable\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname + \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname \fi} % \newtoks\everycatcodetable @@ -294,14 +300,14 @@ \def\syst_catcodes_prev {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount - \csname\??qm:n:\number\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname + \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname \else -% \fi} \def\catcodetablename {\ifnum\currentcatcodetable>\zerocount - \csname\??qm:n:\number\currentcatcodetable\endcsname + \csname\??catcodetablen\number\currentcatcodetable\endcsname \else -% \fi} diff --git a/tex/context/base/char-cjk.lua b/tex/context/base/char-cjk.lua index b077f4a3e..3d7de1423 100644 --- a/tex/context/base/char-cjk.lua +++ b/tex/context/base/char-cjk.lua @@ -12,7 +12,8 @@ local floor = math.floor local format = string.format local utfchar = utf.char -local ranges = characters.ranges +local ranges = characters.ranges +local allocate = utilities.storage.allocate -- Hangul Syllable @@ -209,7 +210,7 @@ local remapped = { -- this might be merged into char-def.lua [0x11C2] = 0x314E, -- H } -characters.hangul = { +characters.hangul = allocate { decomposed = decomposed, description = description, leadconsonant = leadconsonant, @@ -226,24 +227,6 @@ local hangul_syllable_basetable = { linebreak = "h2", } ---~ local hangul_syllable_metatable = { ---~ __index = function(t,k) ---~ local u = t.unicodeslot ---~ if k == "fscode" then ---~ -- no need to cache this as we normally use fscodes ---~ return leadconsonant(u) ---~ elseif k == "shcode" then ---~ return { decomposed(u) } ---~ elseif k == "specials" then ---~ return { "char", decomposed(u) } ---~ elseif k == "description" then ---~ return description(u) ---~ else ---~ return hangul_syllable_basetable[k] ---~ end ---~ end ---~ } - local hangul_syllable_metatable = { __index = function(t,k) local u = t.unicodeslot diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 804468c2d..6c73cf008 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['char-def'] = { comment = "companion to char-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } --[[ @@ -56832,6 +56833,16 @@ characters.data={ description="OVERLINE", direction="on", linebreak="al", + mathspec={ + { + class="topaccent", + name="overbar", + }, + { + class="botaccent", + name="underbar", + }, + }, specials={ "compat", 0x0020, 0x0305 }, unicodeslot=0x203E, }, @@ -57244,6 +57255,8 @@ characters.data={ description="SUPERSCRIPT PLUS SIGN", direction="es", linebreak="al", + mathclass="binary", + mathname ="positivesign", specials={ "super", 0x002B }, unicodeslot=0x207A, }, @@ -57252,6 +57265,8 @@ characters.data={ description="SUPERSCRIPT MINUS", direction="es", linebreak="al", + mathclass="binary", + mathname ="negativesign", specials={ "super", 0x2212 }, unicodeslot=0x207B, }, @@ -58669,7 +58684,7 @@ characters.data={ description="TURNED AMPERSAND", direction="on", linebreak="al", - mathclass="bin", + mathclass="binary", mathname="upand", unicodeslot=0x214B, }, @@ -60887,11 +60902,11 @@ characters.data={ linebreak="ai", mathspec={ { - class="bin", + class="binary", name="vee", }, { - class="bin", + class="binary", name="lor", }, }, @@ -60932,15 +60947,16 @@ characters.data={ description="INTEGRAL", direction="on", linebreak="ai", + mathclass="limop", mathspec={ { - class="nothing", - name="intop", - }, - { class="limop", name="int", }, + { + class="nothing", + name="intop", + }, }, unicodeslot=0x222B, }, @@ -60951,15 +60967,16 @@ characters.data={ description="DOUBLE INTEGRAL", direction="on", linebreak="ai", + mathclass="limop", mathspec={ { - class="nothing", - name="iintop", - }, - { class="limop", name="iint", }, + { + class="nothing", + name="iintop", + }, }, specials={ "compat", 0x222B, 0x222B }, unicodeslot=0x222C, @@ -60969,15 +60986,16 @@ characters.data={ description="TRIPLE INTEGRAL", direction="on", linebreak="al", + mathclass="limop", mathspec={ { - class="nothing", - name="iiintop", - }, - { class="limop", name="iiint", }, + { + class="nothing", + name="iiintop", + }, }, specials={ "compat", 0x222B, 0x222B, 0x222B }, unicodeslot=0x222D, @@ -62402,7 +62420,7 @@ characters.data={ description="NORMAL SUBGROUP OF", direction="on", linebreak="al", - mathclass="bin", + mathclass="binary", mirror=0x22B3, unicodeslot=0x22B2, }, @@ -62412,7 +62430,7 @@ characters.data={ description="CONTAINS AS NORMAL SUBGROUP", direction="on", linebreak="al", - mathclass="bin", + mathclass="binary", mirror=0x22B2, unicodeslot=0x22B3, }, @@ -68388,6 +68406,8 @@ characters.data={ description="BLACK UP-POINTING TRIANGLE", direction="on", linebreak="ai", + mathclass="binary", + mathname="blacktriangle", unicodeslot=0x25B2, }, [0x25B3]={ @@ -68432,7 +68452,7 @@ characters.data={ description="BLACK RIGHT-POINTING TRIANGLE", direction="on", linebreak="ai", - mathclass="bin", + mathclass="binary", mathname="blacktriangleright", unicodeslot=0x25B6, }, @@ -68443,7 +68463,7 @@ characters.data={ description="WHITE RIGHT-POINTING TRIANGLE", direction="on", linebreak="ai", - mathclass="bin", + mathclass="binary", mathname="triangleright", unicodeslot=0x25B7, }, @@ -68452,8 +68472,6 @@ characters.data={ description="BLACK RIGHT-POINTING SMALL TRIANGLE", direction="on", linebreak="al", - mathclass="bin", - mathname="blacktriangleleft", unicodeslot=0x25B8, }, [0x25B9]={ @@ -68486,6 +68504,8 @@ characters.data={ description="BLACK DOWN-POINTING TRIANGLE", direction="on", linebreak="ai", + mathclass="binary", + mathname="blacktriangledown", unicodeslot=0x25BC, }, [0x25BD]={ @@ -68495,8 +68515,16 @@ characters.data={ description="WHITE DOWN-POINTING TRIANGLE", direction="on", linebreak="ai", - mathclass="binary", - mathname="bigtriangledown", + mathspec={ + { + class="binary", + name="triangledown", + }, + { + class="binary", + name="bigtriangledown", + }, + }, unicodeslot=0x25BD, }, [0x25BE]={ @@ -68521,6 +68549,8 @@ characters.data={ description="BLACK LEFT-POINTING TRIANGLE", direction="on", linebreak="ai", + mathclass="binary", + mathname="blacktriangleleft", unicodeslot=0x25C0, }, [0x25C1]={ @@ -68530,7 +68560,7 @@ characters.data={ description="WHITE LEFT-POINTING TRIANGLE", direction="on", linebreak="ai", - mathclass="bin", + mathclass="binary", mathname="triangleleft", unicodeslot=0x25C1, }, diff --git a/tex/context/base/char-enc.lua b/tex/context/base/char-enc.lua index ef6805e54..048837eec 100644 --- a/tex/context/base/char-enc.lua +++ b/tex/context/base/char-enc.lua @@ -1,9 +1,10 @@ -if not modules then modules = { } end modules ['char-syn'] = { +if not modules then modules = { } end modules ['char-enc'] = { version = 1.001, comment = "companion to char-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" + -- dataonly = true, } -- Thanks to tex4ht for these mappings. @@ -144,25 +145,25 @@ characters.synonyms = allocate { -- afm mess Yen = 0x00A5, } ---~ if not characters.enccodes then ---~ ---~ local enccodes = { } characters.enccodes = enccodes ---~ ---~ for unicode, data in next, characters.data do ---~ local encname = data.adobename or data.contextname ---~ if encname then ---~ enccodes[encname] = unicode ---~ end ---~ end ---~ ---~ for name, unicode in next, characters.synonyms do ---~ if not enccodes[name] then enccodes[name] = unicode end ---~ end ---~ ---~ ---~ end ---~ ---~ storage.register("characters.enccodes", characters.enccodes, "characters.enccodes") +-- if not characters.enccodes then +-- +-- local enccodes = { } characters.enccodes = enccodes +-- +-- for unicode, data in next, characters.data do +-- local encname = data.adobename or data.contextname +-- if encname then +-- enccodes[encname] = unicode +-- end +-- end +-- +-- for name, unicode in next, characters.synonyms do +-- if not enccodes[name] then enccodes[name] = unicode end +-- end +-- +-- +-- end +-- +-- storage.register("characters.enccodes", characters.enccodes, "characters.enccodes") -- As this table is seldom used, we can delay its definition. Beware, this means -- that table.print would not work on this file unless it is accessed once. This diff --git a/tex/context/base/char-ent.lua b/tex/context/base/char-ent.lua index d2ac22bbf..ef55be7e4 100644 --- a/tex/context/base/char-ent.lua +++ b/tex/context/base/char-ent.lua @@ -1,15 +1,14 @@ -if not modules then modules = { } end modules ['math-ent'] = { +if not modules then modules = { } end modules ['char-ent'] = { version = 1.001, comment = "companion to math-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "derived from the mathml 2.0 specification", + dataonly = true, } -- http://www.w3.org/2003/entities/2007/w3centities-f.ent -- http://www.w3.org/2003/entities/2007/htmlmathml-f.ent --- this might go into char-def - local entities = utilities.storage.allocate { ["AElig"] = "Æ", -- U+000C6 ["AMP"] = "&", -- U+00026 diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua index 244b8d2a7..778035ff4 100644 --- a/tex/context/base/char-ini.lua +++ b/tex/context/base/char-ini.lua @@ -11,10 +11,9 @@ if not modules then modules = { } end modules ['char-ini'] = { -- we can remove the tag range starting at 0xE0000 (special applications) local tex = tex -local utf = unicode.utf8 local utfchar, utfbyte, utfvalues = utf.char, utf.byte, string.utfvalues -local ustring = unicode.ustring +local ustring, utf = unicode.ustring, unicode.utf8 local concat, unpack, tohash = table.concat, table.unpack, table.tohash local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch @@ -28,8 +27,8 @@ local texsetsfcode = tex.setsfcode local texsetcatcode = tex.setcatcode local contextsprint = context.sprint -local ctxcatcodes = tex.ctxcatcodes -local texcatcodes = tex.texcatcodes +local ctxcatcodes = catcodes.numbers.ctxcatcodes +local texcatcodes = catcodes.numbers.texcatcodes local setmetatableindex = table.setmetatableindex @@ -48,7 +47,6 @@ loaded!</p> characters = characters or { } local characters = characters - local data = characters.data if data then @@ -455,28 +453,39 @@ table we derive a few more.</p> if not characters.fallbacks then - -- we could the definition by using a metatable - - characters.fallbacks = { } - characters.directions = { } + characters.fallbacks = { } -- not than many - local fallbacks = characters.fallbacks - local directions = characters.directions + local fallbacks = characters.fallbacks - for k,v in next, data do - local specials = v.specials - if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then + for k, d in next, data do + local specials = d.specials + if specials and specials[1] == "compat" and specials[2] == 0x0020 then local s = specials[3] - fallbacks[k] = s - fallbacks[s] = k + if s then + fallbacks[k] = s + fallbacks[s] = k + end end - directions[k] = v.direction end end -storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such -storage.register("characters/directions", characters.directions, "characters.directions") +storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such + +characters.directions = { } + +setmetatableindex(characters.directions,function(t,k) + local d = data[k] + if d then + local v = d.direction + if v then + t[k] = v + return v + end + end + t[k] = false -- maybe 'l' + return v +end) --[[ldx-- <p>The <type>context</type> namespace is used to store methods and data @@ -488,7 +497,7 @@ which is rather specific to <l n='context'/>.</p> use the table. After all, we have this information available anyway.</p> --ldx]]-- -function characters.makeactive(n,name) -- let ? +function characters.makeactive(n,name) -- contextsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)) -- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name) end @@ -503,7 +512,7 @@ function tex.uprint(c,n) end end -local temphack = tohash { +local forbidden = tohash { -- at least now 0x00A0, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x202F, @@ -539,12 +548,10 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables else contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s end - elseif is_command[category] then -if not temphack[u] then + elseif is_command[category] and not forbidden[u] then contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") a = a + 1 activated[a] = u -end end end end @@ -632,15 +639,17 @@ function characters.setcodes() end else local lc, uc = chr.lccode, chr.uccode - if not lc then chr.lccode, lc = code, code end - if not uc then chr.uccode, uc = code, code end - texsetcatcode(code,11) -- letter - if type(lc) == "table" then + if not lc then + chr.lccode, lc = code, code + elseif type(lc) == "table" then lc = code end - if type(uc) == "table" then + if not uc then + chr.uccode, uc = code, code + elseif type(uc) == "table" then uc = code end + texsetcatcode(code,11) -- letter texsetlccode(code,lc,uc) if cc == "lu" then texsetsfcode(code,999) @@ -815,8 +824,7 @@ function characters.unicodechar(asked) if n then return n elseif type(asked) == "string" then - asked = gsub(asked," ","") - return descriptions[asked] + return descriptions[asked] or descriptions[gsub(asked," ","")] end end @@ -882,17 +890,21 @@ end function characters.uccode(n) return uccodes[n] end -- obsolete function characters.lccode(n) return lccodes[n] end -- obsolete -function characters.flush(n,direct) +function characters.safechar(n) local c = data[n] if c and c.contextname then - c = "\\" .. c.contextname + return "\\" .. c.contextname else - c = utfchar(n) + return utfchar(n) end - if direct then - return c +end + +function commands.safechar(n) + local c = data[n] + if c and c.contextname then + contextsprint("\\" .. c.contextname) -- context[c.contextname]() else - contextsprint(c) + contextsprint(utfchar(n)) end end diff --git a/tex/context/base/char-map.lua b/tex/context/base/char-map.lua index 376ebf343..749da5289 100644 --- a/tex/context/base/char-map.lua +++ b/tex/context/base/char-map.lua @@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['char-map'] = { comment = "companion to char-ini.mkiv", author = "Hans Hagen & Arthur Reutenauer", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } -- not yet used diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua index a411c2d82..52fdfc0d0 100644 --- a/tex/context/base/char-utf.lua +++ b/tex/context/base/char-utf.lua @@ -19,7 +19,7 @@ in special kinds of output (for instance <l n='pdf'/>).</p> over a string.</p> --ldx]]-- -local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub +local utfchar, utfbyte = utf.char, utf.byte local concat, gmatch, gsub, find = table.concat, string.gmatch, string.gsub, string.find local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues local allocate = utilities.storage.allocate @@ -76,6 +76,7 @@ local decomposed = allocate { ["ﬖ"] = "վն", ["ﬗ"] = "մխ", } + characters.decomposed = decomposed local function initialize() -- maybe only 'mn' @@ -209,9 +210,13 @@ end private.set = set -function private.escape (str) return gsub(str,"(.)", escapes) end -function private.replace(str) return utfgsub(str,"(.)", low ) end -function private.revert (str) return utfgsub(str,"(.)", high ) end +-- function private.escape (str) return gsub(str,"(.)", escapes) end +-- function private.replace(str) return utfgsub(str,"(.)", low ) end +-- function private.revert (str) return utfgsub(str,"(.)", high ) end + +private.escape = utf.remapper(escapes) +private.replace = utf.remapper(low) +private.revert = utf.remapper(high) for ch in gmatch(special,".") do set(ch) end @@ -481,6 +486,14 @@ if sequencers then sequencers.enableaction(textfileactions,"characters.filters.utf.decompose") end + directives.register("filters.utf.collapse", function(v) + sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.collapse") + end) + + directives.register("filters.utf.decompose", function(v) + sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.decompose") + end) + end --[[ldx-- diff --git a/tex/context/base/chem-ini.lua b/tex/context/base/chem-ini.lua index 4d47982a2..192953ec9 100644 --- a/tex/context/base/chem-ini.lua +++ b/tex/context/base/chem-ini.lua @@ -17,8 +17,8 @@ local report_chemistry = logs.reporter("chemistry") local context = context -chemicals = chemicals or { } -local chemicals = chemicals +chemistry = chemistry or { } +local chemistry = chemistry --[[ <p>The next code is an adaptation of code from Wolfgang Schuster @@ -62,9 +62,9 @@ local high = Cc("\\high{%s}") * superscript * content local justtext = (1 - somescript)^1 local parser = Cs((csname + lowhigh + highlow + low + high + sign + any)^0) -chemicals.moleculeparser = parser -- can be used to avoid functioncall +chemistry.moleculeparser = parser -- can be used to avoid functioncall -function chemicals.molecule(str) +function chemistry.molecule(str) return lpegmatch(parser,str) end diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua index fb325ccea..db1849c5a 100644 --- a/tex/context/base/chem-str.lua +++ b/tex/context/base/chem-str.lua @@ -1,12 +1,15 @@ if not modules then modules = { } end modules ['chem-str'] = { version = 1.001, comment = "companion to chem-str.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + author = "Hans Hagen and Alan Braslau", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } --- This module in incomplete and experimental. +-- The original \PPCHTEX\ code was written in pure \TEX\, although later we made +-- the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between +-- \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible +-- but better implementation, later versions might provide more, -- We can push snippets into an mp instance. @@ -26,12 +29,12 @@ local P, R, S, C, Cs, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, local variables = interfaces.variables local context = context -chemicals = chemicals or { } -local chemicals = chemicals +chemistry = chemistry or { } +local chemistry = chemistry -chemicals.instance = "metafun" -- "ppchtex" -chemicals.format = "metafun" -chemicals.structures = 0 +chemistry.instance = "metafun" -- "ppchtex" +chemistry.format = "metafun" +chemistry.structures = 0 local remapper = { ["+"] = "p", @@ -52,7 +55,9 @@ local common_keys = { mid = "fixed", mids = "fixed", midz = "text", z = "text", rz = "text", mrz = "text", prz = "text", crz = "text", rt = "text", rtt = "text", rbt = "text", zt = "text", zn = "number", - mov = "transform", rot = "transform", adj = "transform", dir = "transform", sub = "transform", + zbt = "text", zbn = "number", ztt = "text", ztn = "number", + mov = "transform", rot = "transform", adj = "transform", sub = "transform", + off = "transform", } local front_keys = { @@ -60,9 +65,11 @@ local front_keys = { sb = "line", msb = "line", psb = "line", r = "line", pr = "line", mr = "line", z = "text", mrz = "text", prz = "text", + zt = "text", zn = "number", } local one_keys = { + b = "line", msb = "line", psb = "line", sb = "line", db = "line", tb = "line", ep = "line", es = "line", ed = "line", et = "line", sd = "line", ldd = "line", rdd = "line", @@ -81,15 +88,16 @@ local syntax = { one = { n = 1, max = 8, keys = one_keys, align = { - z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } }, ---~ z = { { "r", "r", "b", "l", "l", "l", "t", "r" } }, + -- z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } }, + -- z = { { "r", "r", "b", "l", "l", "l", "t", "r" } }, } }, three = { n = 3, max = 3, keys = common_keys, align = { mrz = { { "r","b","l" }, { "b","l","t" }, { "l","t","r" }, { "t","r","b" } }, - rz = { { "r","l_b","l_t" }, { "b","l_t","r_t" }, { "l","r_t","r_b" }, { "t","r_b","l_b" } }, + rz = { { "auto","auto","auto" }, { "auto","auto","auto" }, { "auto","auto","auto" }, { "auto","auto","auto" } }, + -- rz = { { "r_t","r_b","l" }, { "r_b","l_b","t" }, { "l_b","l_t","r" }, { "l_t","r_t","b" } }, prz = { { "r","l","t" }, { "b","t","r" }, { "l","r","b" }, { "t","b","l" } }, } }, @@ -97,7 +105,8 @@ local syntax = { n = 4, max = 4, keys = common_keys, align = { mrz = { { "t","r","b","l" }, { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" } }, - rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } }, + rz = { { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" } }, + -- rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } }, prz = { { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" }, { "t","r","b","l" } }, } }, @@ -105,7 +114,8 @@ local syntax = { n = 5, max = 5, keys = common_keys, align = { mrz = { { "t","r","b","b","l" }, { "r","b","l","l","t" }, { "b","l","t","r","r" }, { "l","t","r","r","b" } }, - rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } }, + rz = { { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" } }, + -- rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } }, prz = { { "r","b","l","t","t" }, { "b","l","t","r","r" }, { "l","t","r","b","b" }, { "t","r","b","l","l" } }, } }, @@ -113,7 +123,8 @@ local syntax = { n = 6, max = 6, keys = common_keys, align = { mrz = { { "t","t","r","b","b","l" }, { "r","b","b","l","t","t" }, { "b","b","l","t","t","r" }, { "l","t","t","r","b","b" } }, - rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } }, + rz = { { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" } }, + -- rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } }, prz = { { "r","b","l","l","t","r" }, { "b","l","t","t","r","b" }, { "l","t","r","r","b","l" }, { "t","r","b","b","l","t" } }, } }, @@ -121,7 +132,8 @@ local syntax = { n = 8, max = 8, keys = common_keys, align = { -- todo mrz = { { "t","r","r","b","b","l","l","t" }, { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" } }, - rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } }, + rz = { { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" } }, + -- rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } }, prz = { { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" }, { "t","r","r","b","b","l","l","t" } }, } }, @@ -147,11 +159,11 @@ local syntax = { local definitions = { } -function chemicals.undefine(name) +function chemistry.undefine(name) definitions[lower(name)] = nil end -function chemicals.define(name,spec,text) +function chemistry.define(name,spec,text) name = lower(name) local dn = definitions[name] if not dn then dn = { } definitions[name] = dn end @@ -162,7 +174,7 @@ function chemicals.define(name,spec,text) end local metacode, variant, keys, bonds, max, txt, textsize, rot, pstack -local molecule = chemicals.molecule -- or use lpegmatch(chemicals.moleculeparser,...) +local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...) local function fetch(txt) local st = stack[txt] @@ -196,35 +208,46 @@ local text = (equal * C(P(1)^0)) + Cc(false) local pattern = (amount + Cc(1)) * - operation * - special * ( + Cs(operation/lower) * + Cs(special/lower) * ( +-- operation * +-- special * ( range * Cc(false) * text + Cc(false) * Cc(false) * set * text + single * Cc(false) * Cc(false) * text + Cc(false) * Cc(false) * Cc(false) * text ) ---~ local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357") +-- local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357") ---~ print(lpegmatch(pattern,"RZ=x")) 1 RZ false false false x ---~ print(lpegmatch(pattern,"RZ1=x")) 1 RZ 1 false false x ---~ print(lpegmatch(pattern,"RZ1..3=x")) 1 RZ 1 3 false x ---~ print(lpegmatch(pattern,"RZ13=x")) 1 RZ false false table x +-- print(lpegmatch(pattern,"RZ=x")) -- 1 RZ false false false x +-- print(lpegmatch(pattern,"RZ1=x")) -- 1 RZ 1 false false x +-- print(lpegmatch(pattern,"RZ1..3=x")) -- 1 RZ 1 3 false x +-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x local function process(spec,text,n,rulethickness,rulecolor,offset) insert(stack,{ spec=spec, text=text, n=n }) local txt = #stack local m = #metacode for i=1,#spec do - local s = spec[i] + local step = spec[i] + local s = lower(step) local d = definitions[s] if d then + if trace_structure then + report_chemistry("%s => definition: %s",step,s) + end for i=1,#d do local di = d[i] process(di.spec,di.text,1,rulethickness,rulecolor) end else - local rep, operation, special, index, upto, set, text = lpegmatch(pattern,s) + local rep, operation, special, index, upto, set, text = lpegmatch(pattern,step) + if trace_structure then + local set = set and concat(set," ") or "-" + report_chemistry("%s => rep: %s, operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s", + step,rep or "-",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-") + end if operation == "pb" then insert(pstack,variant) m = m + 1 ; metacode[m] = syntax.pb.direct @@ -339,7 +362,8 @@ local function process(spec,text,n,rulethickness,rulecolor,offset) if not t then txt, t = fetch(txt) end if t then t = molecule(processor_tostring(t)) - m = m + 1 ; metacode[m] = format('chem_%s_zero("\\chemicaltext{%s}");',operation,t) + m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,index,t) + -- m = m + 1 ; metacode[m] = format('chem_%s_zero("\\chemicaltext{%s}");',operation,t) end elseif index then local t = text @@ -388,8 +412,8 @@ end -- -- rulethickness in points -function chemicals.start(settings) - chemicals.structures = chemicals.structures + 1 +function chemistry.start(settings) + chemistry.structures = chemistry.structures + 1 local textsize, rulethickness, rulecolor = settings.size, settings.rulethickness, settings.rulecolor local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "medium", settings.offset or 0 local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0 @@ -445,63 +469,73 @@ function chemicals.start(settings) scale = 0.75 * scale/625 -- metacode[#metacode+1] = format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;", - chemicals.structures, + chemistry.structures, l/25, r/25, t/25, b/25, scale, tostring(settings.axis == variables.on), tostring(width), tostring(height), tostring(offset) ) -- - variant, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { } + -- variant, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { } + variant, keys, bonds, stack, rot, pstack = "one", { }, 1, { }, 1, { } end -function chemicals.stop() +function chemistry.stop() metacode[#metacode+1] = "chem_stop_structure ;" -- local mpcode = concat(metacode,"\n") if trace_structure then report_chemistry("metapost code:\n%s", mpcode) end - metapost.graphic(chemicals.instance,chemicals.format,mpcode) + metapost.graphic(chemistry.instance,chemistry.format,mpcode) metacode = nil end -function chemicals.component(spec,text,settings) +function chemistry.component(spec,text,settings) rulethickness, rulecolor, offset = settings.rulethickness, settings.rulecolor - local spec = settings_to_array(lower(spec)) +-- local spec = settings_to_array(lower(spec)) + local spec = settings_to_array(spec) local text = settings_to_array(text) metacode[#metacode+1] = "chem_start_component ;" process(spec,text,1,rulethickness,rulecolor) metacode[#metacode+1] = "chem_stop_component ;" end +statistics.register("chemical formulas", function() + if chemistry.structures > 0 then + return format("%s chemical structure formulas",chemistry.structures) -- no timing needed, part of metapost + end +end) + +-- interfaces + +commands.undefinechemical = chemistry.undefine +commands.definechemical = chemistry.define +commands.startchemical = chemistry.start +commands.stopchemical = chemistry.stop +commands.chemicalcomponent = chemistry.component + +-- todo: top / bottom + local inline = { ["single"] = "\\chemicalsinglebond", ["-"] = "\\chemicalsinglebond", - ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond", + ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond", -- also =? and unicode triple? ["triple"] = "\\chemicaltriplebond", ["---"] = "\\chemicaltriplebond", ["gives"] = "\\chemicalgives", ["->"] = "\\chemicalgives", ["equilibrium"] = "\\chemicalequilibrium", ["<->"] = "\\chemicalequilibrium", ["mesomeric"] = "\\chemicalmesomeric", ["<>"] = "\\chemicalmesomeric", - ["plus"] = "\\chemicalsplus", ["+"] = "\\chemicalsplus", - ["minus"] = "\\chemicalsminus", - ["space"] = "\\chemicalsspace", + ["plus"] = "\\chemicalplus", ["+"] = "\\chemicalplus", + ["minus"] = "\\chemicalminus", + ["space"] = "\\chemicalspace", } --- todo: top / bottom - -function chemicals.inline(spec) +function commands.inlinechemical(spec) local spec = settings_to_array(spec) for i=1,#spec do local s = spec[i] local inl = inline[lower(s)] if inl then - context(inl) + context(inl) -- could be a fast context.sprint else context.chemicalinline(molecule(s)) end end end - -statistics.register("chemical formulas", function() - if chemicals.structures > 0 then - return format("%s chemical structure formulas",chemicals.structures) -- no timing needed, part of metapost - end -end) diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv index 1d60a293e..c4b03dd1e 100644 --- a/tex/context/base/chem-str.mkiv +++ b/tex/context/base/chem-str.mkiv @@ -2,7 +2,7 @@ %D [ file=chem-ini, %D version=2009.05.13, %D subtitle=Chemistry, -%D author=Hans Hagen, +%D author=Hans Hagen \& Alan Braslau, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C @@ -10,8 +10,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This module in incomplete and experimental. Eventually this code -%D will replace \PPCHTEX. +%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, \writestatus{loading}{ConTeXt Chemistry Macros / Structure} @@ -26,24 +28,24 @@ % Here we use chemicalformula instead, so no longer a mix: % % \startchemicalformula -% \chemical{H_2}{top}{bottom} +% \chemical{2H_2}{top}{bottom} % \chemical{PLUS}{top}{bottom} -% \chemical{O}{top}{bottom} +% \chemical{O_2}{top}{bottom} % \chemical{GIVES}{top}{bottom} -% \chemical{H_2O}{top}{bottom} +% \chemical{2H_2O}{top}{bottom} % \stopchemicalformula % % \startchemicalformula -% \chemical{H_2} +% \chemical{2H_2} % \chemical{PLUS} -% \chemical{O} +% \chemical{O_2} % \chemical{GIVES} -% \chemical{H_2O} +% \chemical{2H_2O} % \stopchemicalformula % % The inline variant has only one argument: % -% \chemical{H_2,PLUS,O,GIVES,H_2O} +% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O} % todo: seven | eight | frontsix | fontfive | carbon | newmans | chair @@ -58,11 +60,17 @@ \let\setupchemicals\setupchemical -\unexpanded\def\setupchemicalframed - {\dosingleempty\dosetupchemicalframed} +%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). + +\defineframed + [\??chemicalframed] + [\c!align=\v!normal, + \c!strut=\v!no] -\def\dosetupchemicalframed - {\getparameters[\??chemicalframed]} +\unexpanded\def\setupchemicalframed + {\setupframed[\??chemicalframed]} \unexpanded\def\definechemical % is global (so we don't use the commandhandler) {\dosingleargument\chem_define} @@ -71,7 +79,7 @@ {\startnointerference \edef\currentdefinedchemical{#1}% \let\chemical\chem_chemical_nested - \ctxlua{chemicals.undefine("#1")}% + \ctxcommand{undefinechemical("#1")}% #2% flush \stopnointerference} @@ -79,7 +87,7 @@ {\dodoubleempty\chem_chemical_nested_indeed} \def\chem_chemical_nested_indeed[#1][#2]% - {\ctxlua{chemicals.define("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}} + {\ctxcommand{definechemical("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}} % chemical symbols @@ -90,20 +98,15 @@ {\setvalue{\??chemicalsymbol#1}{#2}} \unexpanded\def\chemicalsymbol[#1]% - {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname\s!unknown\else#1\fi\endcsname} + {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname} -\definechemicalsymbol[\s!unknown][] % empty +\definechemicalsymbol[\s!unknown][] % \char"FFFD empty % size (small medium big) \edef\chemicaltoplocation{t} \edef\chemicalbotlocation{b} -% \unexpanded\def\chemicaltext#1% in ppchtex we had a more clever alignment -% {\usechemicalstyleandcolor\c!style\c!color -% \strut -% #1} % maybe also \setstrut - \unexpanded\def\chemicaltext#1% {\mathematics {\usechemicalstyleandcolor\c!style\c!color @@ -147,7 +150,7 @@ \fi\fi \the\everystructurechemical \setbox\b_chem_result\hbox\bgroup - \ctxlua{chemicals.start { + \ctxcommand{startchemical { width = "\chemicalparameter\c!width", height = "\chemicalparameter\c!height", left = \chemicalparameter\c!left, @@ -162,7 +165,7 @@ \unexpanded\def\stopchemical {\stopnointerference - \ctxlua{chemicals.stop()}% + \ctxcommand{stopchemical()}% \egroup \d_chem_width \wd\b_chem_result \d_chem_height\ht\b_chem_result @@ -171,15 +174,16 @@ \doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes \egroup} -\def\chem_framed_yes - {\localframed% +\unexpanded\def\chem_framed_yes + {\localframedwithsettings [\??chemicalframed]% - [\c!frame=\chemicalparameter\c!frame,\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth + [\c!frame=\chemicalparameter\c!frame]% + {\vbox{\box\b_chem_result\vss}}} % remove depth -\def\chem_framed_nop - {\localframed% +\unexpanded\def\chem_framed_nop + {\directlocalframed [\??chemicalframed]% - [\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth + {\vbox{\box\b_chem_result\vss}}} % remove depth \let\startstructurechemical\startchemical \let\stopstructurechemical \stopchemical @@ -200,14 +204,14 @@ \def\strc_chem_indeed_three[#1][#2][#3]% {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored - \ctxlua{chemicals.component(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way + \ctxcommand{chemicalcomponent(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup } ) }% \ignorespaces} \def\strc_chem_indeed_two[#1][#2]% - {\ctxlua{chemicals.component(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way + {\ctxcommand{chemicalcomponent(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup } ) }% @@ -289,8 +293,8 @@ \def\chem_arrow_construct#1#2#3% {\enspace \mathematics{#1% - {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#2\!!es)}\hss}}% {\strut\hbox \!!spread 2em{\hss#2\hss}}% - {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#3\!!es)}\hss}}}% {\strut\hbox \!!spread 2em{\hss#3\hss}}}% + {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#3\!!es)}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}% + {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#2\!!es)}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}% \enspace} % special macros (probably needs some more work) @@ -428,9 +432,9 @@ \usechemicalstyleandcolor\c!style\c!color \ifthirdargument \ifsecondargument - \halign{&\hss##\hss\cr#2\cr\molecule{#1}\cr#3\cr}% + \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}% \else - \halign{&\hss##\hss\cr\molecule{#1}\cr#2\cr}% + \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}% \fi \else \hbox{\molecule{#1}}% @@ -440,30 +444,30 @@ \unexpanded\def\inlinechemical#1% {\dontleavehmode - \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxlua{chemicals.inline(\!!bs#1\!!es)}}} + \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxcommand{inlinechemical(\!!bs#1\!!es)}}} \unexpanded\def\chemicalbondrule - {\hbox{\vrule\!!height.75ex\!!depth-\dimexpr.75ex-\linewidth\relax\!!width1em\relax}} + {\hbox{\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:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace] -\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightpverleftarrow{}{}}\enspace] +\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace] \definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace] \definechemicalsymbol[i:single] [\chemicalbondrule] -\definechemicalsymbol[i:tripple] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] -\definechemicalsymbol[i:double] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] +\definechemicalsymbol[i:double] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] +\definechemicalsymbol[i:triple] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] \unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]} -\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:tripple]} -\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:double]} +\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\chemicalsplus {\chemicalsymbol[i:plus]} -\unexpanded\def\chemicalsminus {\chemicalsymbol[i:minus]} -\unexpanded\def\chemicalsspace {\chemicalsymbol[i:space]} +\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]} +\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]} +\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]} \unexpanded\def\chemicalinline #1{#1} % display @@ -491,61 +495,133 @@ \setfalse\c_chem_has_bot} \unexpanded\def\stopchemicalformula - {\tabskip1em\relax + {\tabskip\emwidth\relax \nointerlineskip \ifconditional\c_chem_has_top \ifconditional\c_chem_has_bot - \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}% + \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{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}% + \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{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}% + \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}% \else - \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr}% + \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:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow +\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow +\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow +\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:GIVES] [{\chemicalsymbol[d:gives]}] +\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}] +\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}] +\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 +% {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname +% \t_chem_mid\expandafter{\the\t_chem_mid\chem_formula_mid{#1}{#2}{#3}}% +% \else +% \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 +% \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}% +% \fi} + \def\chem_formula#1#2#3% we could do hboxes and measure - {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname - \t_chem_mid\expandafter{\the\t_chem_mid\chem_formula_mid{#1}{#2}{#3}}% + {\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 - \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 - \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}&}% + \chem_formula_top_nop + \chem_formula_bot_nop + \fi\fi + \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname + \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}% + \else + \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}% \fi} \def\chem_formula_mid#1% {\csname\??chemicalsymbol\detokenize{#1}\endcsname} -\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top&}} -\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot&}} -\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}&}\settrue\c_chem_has_top} -\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}&}\settrue\c_chem_has_bot} +\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top\aligntab}} +\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot\aligntab}} +\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} +\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\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=off] + \c!frame=\v!off] \setupchemical [\c!frame=, diff --git a/tex/context/base/cldf-bas.lua b/tex/context/base/cldf-bas.lua index 30a9265bc..9cf8dcd4a 100644 --- a/tex/context/base/cldf-bas.lua +++ b/tex/context/base/cldf-bas.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['cldf-ini'] = { +if not modules then modules = { } end modules ['cldf-bas'] = { version = 1.001, comment = "companion to cldf-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -22,6 +22,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- flush(ctxcatcodes,"}") -- end +-- maybe use context.generics + local type = type local format = string.format local utfchar = utf.char @@ -32,13 +34,16 @@ local generics = context.generics local variables = interfaces.variables local new_rule = nodes.pool.rule +local texcount = tex.count function context.char(k) -- used as escape too, so don't change to utf if type(k) == "table" then - -- for i=1,#k do - -- context(format([[\char%s\relax]],k[i])) - -- end - context([[\char%s\relax]],concat(k,[[\relax\char]])) + local n = #k + if n == 1 then + context([[\char%s\relax]],k[1]) + elseif n > 0 then + context([[\char%s\relax]],concat(k,[[\relax\char]])) + end elseif k then context([[\char%s\relax]],k) end @@ -98,22 +103,22 @@ context.vrule = context.hrule -- not yet used ... but will get variant at the tex end as well -function context.sethboxregister (n) context("\\setbox %s\\hbox",n) end -function context.setvboxregister (n) context("\\setbox %s\\vbox",n) end +function context.sethboxregister(n) context([[\setbox %s\hbox]],n) end +function context.setvboxregister(n) context([[\setbox %s\vbox]],n) end function context.starthboxregister(n) if type(n) == "number" then - context("\\setbox%s\\hbox\\bgroup",n) + context([[\setbox%s\hbox{]],n) else - context("\\setbox\\%s\\hbox\\bgroup",n) + context([[\setbox\%s\hbox{]],n) end end function context.startvboxregister(n) if type(n) == "number" then - context("\\setbox%s\\vbox\\bgroup",n) + context([[\setbox%s\vbox{]],n) else - context("\\setbox\\%s\\vbox\\bgroup",n) + context([[\setbox\%s\vbox{]],n) end end @@ -122,19 +127,36 @@ context.stopvboxregister = context.egroup function context.flushboxregister(n) if type(n) == "number" then - context("\\box%s ",n) + context([[\box%s ]],n) else - context("\\box\\%s",n) + context([[\box\%s]],n) end end function context.beginvbox() - context("\\vbox\\bgroup") -- we can do \bvbox ... \evbox (less tokens) + context([[\vbox{]]) -- we can do \bvbox ... \evbox (less tokens) end function context.beginhbox() - context("\\hbox\\bgroup") -- todo: use fast one + context([[\hbox{]]) -- todo: use fast one end context.endvbox = context.egroup context.endhbox = context.egroup + +local function allocate(name,what,cmd) + local a = format("c_syst_last_allocated_%s",what) + local n = texcount[a] + 1 + if n <= texcount.c_syst_max_allocated_register then + texcount[a] = n + end + context("\\global\\expandafter\\%sdef\\csname %s\\endcsname %s\\relax",cmd or what,name,n) + return n +end + +function context.newdimen (name) return allocate(name,"dimen") end +function context.newskip (name) return allocate(name,"skip") end +function context.newcount (name) return allocate(name,"count") end +function context.newmuskip(name) return allocate(name,"muskip") end +function context.newtoks (name) return allocate(name,"toks") end +function context.newbox (name) return allocate(name,"box","mathchar") end diff --git a/tex/context/base/cldf-com.lua b/tex/context/base/cldf-com.lua index bacbbeafd..d9062594e 100644 --- a/tex/context/base/cldf-com.lua +++ b/tex/context/base/cldf-com.lua @@ -11,8 +11,8 @@ local context = context local generics = context.generics -- needs documentation local variables = interfaces.variables -generics.starttabulate = "start" .. variables.tabulate -- todo: e!start -generics.stoptabulate = "stop" .. variables.tabulate -- todo: e!stop +generics.starttabulate = "starttabulate" -- "start" .. variables.tabulate -- todo: e!start +generics.stoptabulate = "stoptabulate" -- "stop" .. variables.tabulate -- todo: e!stop local NC, NR = context.NC, context.NR diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua index ed86c2923..ad5f14855 100644 --- a/tex/context/base/cldf-ini.lua +++ b/tex/context/base/cldf-ini.lua @@ -25,7 +25,7 @@ local tex = tex context = context or { } local context = context -local format, find, gmatch, gsub = string.format, string.find, string.gmatch, string.gsub +local format, find, gmatch, gsub, validstring = string.format, string.find, string.gmatch, string.gsub, string.valid local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable local insert, remove, concat = table.insert, table.remove, table.concat local lpegmatch, lpegC, lpegS, lpegP, lpegCc = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc @@ -40,12 +40,14 @@ local isnode = node.is_node -- after 0.65 just node.type local writenode = node.write local copynodelist = node.copy_list -local ctxcatcodes = tex.ctxcatcodes -local prtcatcodes = tex.prtcatcodes -local texcatcodes = tex.texcatcodes -local txtcatcodes = tex.txtcatcodes -local vrbcatcodes = tex.vrbcatcodes -local xmlcatcodes = tex.xmlcatcodes +local catcodenumbers = catcodes.numbers + +local ctxcatcodes = catcodenumbers.ctxcatcodes +local prtcatcodes = catcodenumbers.prtcatcodes +local texcatcodes = catcodenumbers.texcatcodes +local txtcatcodes = catcodenumbers.txtcatcodes +local vrbcatcodes = catcodenumbers.vrbcatcodes +local xmlcatcodes = catcodenumbers.xmlcatcodes local flush = texsprint local flushdirect = texprint @@ -344,9 +346,9 @@ end local methodhandler = resolvers.methodhandler -function context.viafile(data) +function context.viafile(data,tag) if data and data ~= "" then - local filename = resolvers.savers.byscheme("virtual","viafile",data) + local filename = resolvers.savers.byscheme("virtual",validstring(tag,"viafile"),data) -- context.startregime { "utf" } context.input(filename) -- context.stopregime() @@ -410,7 +412,11 @@ local function writer(parent,command,first,...) -- already optimized before call done = true end end - flush(currentcatcodes,"]") + if done then + flush(currentcatcodes,"]") + else + flush(currentcatcodes,"[]") + end elseif tn == 1 then -- some 20% faster than the next loop local tj = ti[1] if type(tj) == "function" then diff --git a/tex/context/base/cldf-int.lua b/tex/context/base/cldf-int.lua index 55db9fa0b..6cbfd666f 100644 --- a/tex/context/base/cldf-int.lua +++ b/tex/context/base/cldf-int.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['mult-clm'] = { +if not modules then modules = { } end modules ['cldf-int'] = { version = 1.001, comment = "companion to mult-clm.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -14,9 +14,12 @@ if not modules then modules = { } end modules ['mult-clm'] = { local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat local unpack = unpack or table.unpack -local contextsprint = context.sprint -local ctxcatcodes = tex.ctxcatcodes -local vrbcatcodes = tex.vrbcatcodes +local catcodenumbers = catcodes.numbers + +local ctxcatcodes = catcodenumbers.ctxcatcodes +local vrbcatcodes = catcodenumbers.vrbcatcodes + +local contextsprint = context.sprint local trace_define = false trackers.register("context.define", function(v) trace_define = v end) diff --git a/tex/context/base/cldf-ver.lua b/tex/context/base/cldf-ver.lua index 237078157..b48fd253a 100644 --- a/tex/context/base/cldf-ver.lua +++ b/tex/context/base/cldf-ver.lua @@ -6,6 +6,10 @@ if not modules then modules = { } end modules ['cldf-ver'] = { license = "see context related readme files" } +-- We have better verbatim: context.verbatim so that needs to be looked +-- into. We can also directly store in buffers although this variant works +-- better when used mixed with other code (synchronization issue). + local concat, tohandle = table.concat, table.tohandle local find, splitlines = string.find, string.splitlines local tostring, type = tostring, type @@ -41,7 +45,7 @@ table .tocontext = t_tocontext string .tocontext = s_tocontext boolean.tocontext = b_tocontext -function tocontext(first,...) +function context.tocontext(first,...) local t = type(first) if t == "string" then s_tocontext(first,...) diff --git a/tex/context/base/colo-ext.mkiv b/tex/context/base/colo-ext.mkiv index af6c3830e..8878da485 100644 --- a/tex/context/base/colo-ext.mkiv +++ b/tex/context/base/colo-ext.mkiv @@ -29,18 +29,10 @@ %D %D will negate the colors in box zero. -% \unexpanded\def\negatecolorbox#1% -% {\setbox#1\hbox -% {\startnegative % might change -% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor -% \hskip-\wd#1% -% \box#1% -% \stopnegative}} - \unexpanded\def\negatecolorbox#1% {\setbox#1\hbox {\startnegative % might change -% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor + % \startcolor[\s!white]\vrule\s!height\ht#1\s!depth\dp#1\s!width\wd#1\stopcolor \blackrule[\c!color=\s!white,\c!height=\ht#1,\c!depth=\dp#1,\c!width=\wd#1]% \hskip-\wd#1% \box#1% diff --git a/tex/context/base/colo-icc.lua b/tex/context/base/colo-icc.lua index 904d42143..4ab28eb68 100644 --- a/tex/context/base/colo-icc.lua +++ b/tex/context/base/colo-icc.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['colo-ini'] = { +if not modules then modules = { } end modules ['colo-icc'] = { version = 1.000, comment = "companion to colo-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua index 747e2116f..e08f3d387 100644 --- a/tex/context/base/colo-ini.lua +++ b/tex/context/base/colo-ini.lua @@ -16,7 +16,8 @@ local trace_define = false trackers.register("colors.define",function(v) trace_ local report_colors = logs.reporter("colors","defining") -local attributes, context, commands = attributes, context, commands +local attributes, backends, storage = attributes, backends, storage +local context, commands = context, commands local settings_to_hash_strict = utilities.parsers.settings_to_hash_strict @@ -666,83 +667,51 @@ function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,sp end end ---~ local function f(one,two,i,fraction_one,fraction_two) ---~ local otf = fraction_one * one[i] + fraction_two * two[i] ---~ if otf > 1 then ---~ otf = 1 ---~ end ---~ return otf ---~ end - ---~ function colors.defineduocolor(name,fraction_one,c_one,fraction_two,c_two,global,freeze) ---~ local one, two = colorvalues[c_one], colorvalues[c_two] ---~ if one and two then ---~ fraction_one = tonumber(fraction_one) or 1 ---~ fraction_two = tonumber(fraction_two) or 1 ---~ local csone, cstwo = one[1], two[1] ---~ local ca ---~ if csone == 2 then ---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two)) ---~ elseif csone == 3 then ---~ ca = register_color(name,'rgb', f(one,two,3,fraction_one,fraction_two), ---~ f(one,two,4,fraction_one,fraction_two), ---~ f(one,two,5,fraction_one,fraction_two)) ---~ elseif csone == 4 then ---~ ca = register_color(name,'cmyk',f(one,two,6,fraction_one,fraction_two), ---~ f(one,two,7,fraction_one,fraction_two), ---~ f(one,two,8,fraction_one,fraction_two), ---~ f(one,two,9,fraction_one,fraction_two)) ---~ else ---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two)) ---~ end ---~ definecolor(name,ca,global,freeze) ---~ end ---~ end - - local function f(i,colors,fraction) - local otf = 0 - for c=1,#colors do - otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i] - end - if otf > 1 then - otf = 1 - end - return otf +local function f(i,colors,fraction) + local otf = 0 + for c=1,#colors do + otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i] + end + if otf > 1 then + otf = 1 end + return otf +end - function colors.definemixcolor(name,fractions,cs,global,freeze) - local values = { } - for i=1,#cs do -- do fraction in here - local v = colorvalues[cs[i]] - if not v then - return - end - values[i] = v - end - local csone = values[1][1] - local ca - if csone == 2 then - ca = register_color(name,'gray',f(2,values,fractions)) - elseif csone == 3 then - ca = register_color(name,'rgb', f(3,values,fractions), - f(4,values,fractions), - f(5,values,fractions)) - elseif csone == 4 then - ca = register_color(name,'cmyk',f(6,values,fractions), - f(7,values,fractions), - f(8,values,fractions), - f(9,values,fractions)) - else - ca = register_color(name,'gray',f(2,values,fractions)) +function colors.definemixcolor(name,fractions,cs,global,freeze) + local values = { } + for i=1,#cs do -- do fraction in here + local v = colorvalues[cs[i]] + if not v then + return end - definecolor(name,ca,global,freeze) + values[i] = v end + local csone = values[1][1] + local ca + if csone == 2 then + ca = register_color(name,'gray',f(2,values,fractions)) + elseif csone == 3 then + ca = register_color(name,'rgb', f(3,values,fractions), + f(4,values,fractions), + f(5,values,fractions)) + elseif csone == 4 then + ca = register_color(name,'cmyk',f(6,values,fractions), + f(7,values,fractions), + f(8,values,fractions), + f(9,values,fractions)) + else + ca = register_color(name,'gray',f(2,values,fractions)) + end + definecolor(name,ca,global,freeze) +end -- for the moment downward compatible local patterns = { "colo-imp-%s.mkiv", "colo-imp-%s.tex", "colo-%s.mkiv", "colo-%s.tex" } local function action(name,foundname) + -- could be one command context.startreadingfile() context.startcolorset { name } context.input(foundname) @@ -877,3 +846,22 @@ end -- context.popcatcodes() -- end +-- handy + +local models = storage.allocate { "all", "gray", "rgb", "cmyk", "spot" } + +colors.models = models -- check for usage elsewhere + +function colors.spec(name) + local l = attributes_list[a_color] + local t = colorvalues[l[name]] or colorvalues[l.black] + return { + model = models[t[1]] or models[1], + s = t[2], + r = t[3], g = t[4], b = t[5], + c = t[6], m = t[7], y = t[8], k = t[9], + } +end + +-- inspect(attributes.colors.spec("red")) +-- inspect(attributes.colors.spec("red socks")) diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv index 5721bb513..629f2b96a 100644 --- a/tex/context/base/colo-ini.mkiv +++ b/tex/context/base/colo-ini.mkiv @@ -242,8 +242,8 @@ \setfalse\c_colo_convert_gray \getvalue{\??colorconversions\directcolorsparameter\c!conversion}% could be a nice \ifcsname % too often: - \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors9\v!rgb \fi - \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors9\v!cmyk\fi + \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi + \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi \colo_helpers_set_current_model \ifproductionrun \edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}% @@ -357,16 +357,26 @@ \normalexpanded{\colo_palets_define[#1][\csname\??colorpaletspecification#2\endcsname]}% \fi}} -\def\colo_palets_define_one#1#2% get rid of { } in #2 - {\colo_palets_define_two{#1}[#2]}% +% \def\colo_palets_define_one#1#2% get rid of { } in #2 +% {\colo_palets_define_two{#1}[#2]}% + +\def\colo_palets_define_one#1#2% get rid of { } + {\doifassignmentelse{#2} % catch empty entries + {\colo_palets_define_two{#1}[#2]} + {\colo_palets_define_three{#1}{#2}}} \def\colo_palets_define_two#1[#2=#3]% {\edef\m_colo_palets_tmp{\ifx\m_colo_palets_tmp\empty\else\m_colo_palets_tmp,\fi#2}% \colo_palets_define_set{#1}{#2}{#3}}% +\def\colo_palets_define_three#1#2% + {\ifcsname\??colorpaletspecification#2\endcsname + \processcommacommand[\csname\??colorpaletspecification#2\endcsname]{\colo_palets_define_one{#1}}% + \fi} + \let\paletsize\!!zerocount -\def\getpaletsize[#1]% +\unexpanded\def\getpaletsize[#1]% only works for valid k=v definitions {\getcommacommandsize[\csname\??colorpaletspecification#1\endcsname]% \edef\paletsize{\number\commalistsize}} @@ -802,9 +812,19 @@ \def\defaulttextcolor {black} \def\s!themaintextcolor{themaintextcolor} +\unexpanded\def\inheritmaintextcolor + {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi} + +\unexpanded\def\onlyinheritmaintextcolor + {\ifx\maintextcolor\empty + \deactivatecolor + \else + \colo_helpers_activate\maintextcolor + \fi} + \appendtoks \deactivatecolor % public? - \ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi + \inheritmaintextcolor \to \everybeforeoutput \def\colo_helpers_switch_to_maintextcolor#1% @@ -961,7 +981,7 @@ % ignores in attribute handler % -% \def\forcecolorhack{\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint} +% \def\forcecolorhack{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} % \normal added else fails in metafun manual (leaders do a hard scan) diff --git a/tex/context/base/colo-run.lua b/tex/context/base/colo-run.lua index 4f1916d5a..27f7c6b12 100644 --- a/tex/context/base/colo-run.lua +++ b/tex/context/base/colo-run.lua @@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['colo-run'] = { license = "see context related readme files" } --- For historic reasons the core has a couple of tracing --- features. Nowadays these would end up in modules. +-- For historic reasons the core has a couple of tracing features. Nowadays +-- these would end up in modules. + +local colors, commands, context, utilities = colors, commands, context, utilities local colors= attributes.colors diff --git a/tex/context/base/colo-run.mkiv b/tex/context/base/colo-run.mkiv index c330accf3..5084fdd35 100644 --- a/tex/context/base/colo-run.mkiv +++ b/tex/context/base/colo-run.mkiv @@ -42,9 +42,9 @@ %D Palets \unexpanded\gdef\showpalet - {\dodoubleargument\doshowpalet} + {\dodoubleargument\colo_show_palet} -\gdef\doshowpalet[#1][#2]% +\gdef\colo_show_palet[#1][#2]% {\ifcsname\??colorpalet#1\endcsname \doifinsetelse\v!vertical{#2} \colo_palets_show_vertical \colo_palets_show_horizontal [#1][#2]% \fi} @@ -59,8 +59,8 @@ \tabskip\zeropoint \def\colo_palets_show_palet##1% {\doifinsetelse\v!number{#2}{##1\hskip.5em}{}& - \color[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}% - \graycolor[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}& + \color[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}% + \graycolor[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}& \doifinset\v!value{#2}{\hskip.5em\colorvalue{##1}}\crcr} \halign {\hss##&\hss##\hss&##\cr @@ -92,11 +92,11 @@ \colo_palets_process[#1]\colo_palets_show_palet}\cr \doifinset\v!name{#2}{#1\hskip.5em}% \def\colo_palets_show_palet##1% - {&\strut\color[##1]{\vrule\!!width\!!widtha\!!height\strutht\!!depth\zeropoint}}% + {&\strut\color[##1]{\vrule\s!width\!!widtha\s!height\strutht\s!depth\zeropoint}}% \colo_palets_process[#1]\colo_palets_show_palet\crcr \noalign{\vskip-\strutdepth}% \def\colo_palets_show_palet##1% - {&\graycolor[##1]{\vrule\!!width\!!widtha\!!height\zeropoint\!!depth\strutdp}}% + {&\graycolor[##1]{\vrule\s!width\!!widtha\s!height\zeropoint\s!depth\strutdp}}% \colo_palets_process[#1]\colo_palets_show_palet\crcr \doifinset\v!value{#2} {\def\colo_palets_show_palet##1% @@ -137,13 +137,13 @@ \def\colo_palets_compare##1% {\hbox {\setbox0\hbox - {#1[##1]{\vrule\!!width\hsize\!!height3ex}}% + {#1[##1]{\vrule\s!width\hsize\s!height3ex}}% \wd0\zeropoint \box0 \hbox to \hsize {\def\colo_palets_compare####1% {\hbox to \!!widtha - {\hss#1[####1]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}% + {\hss#1[####1]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}% \processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}} \endgraf} \processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}} @@ -171,8 +171,8 @@ {\halign {\hss####\hss\cr \doifinset\v!number{#2}{\strut##1}\cr - \color[#1:##1]{\vrule\!!width4em\!!height\strutht\!!depth\zeropoint}\cr - \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr + \color[#1:##1]{\vrule\s!width4em\s!height\strutht\s!depth\zeropoint}\cr + \graycolor[#1:##1]{\vrule\s!width4em\s!height\zeropoint\s!depth\strutdp}\cr \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}}}% \hbox {\doifinset\v!name{#2} @@ -195,8 +195,8 @@ \def\colo_groups_show_group##1% {\doifcolor{#1:##1} {\doifinset\v!number{#2}{##1\hskip.5em}& - \color[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}% - \graycolor[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}& + \color[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}% + \graycolor[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}& \doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}% \halign {\hss##&\hss##\hss&##\hss\cr @@ -228,11 +228,11 @@ \def\colo_groups_compare_step#1#2#3% {\hbox to \hsize {\setbox0\hbox - {#1[#2:#3]{\vrule\!!width\hsize\!!height3ex}}% + {#1[#2:#3]{\vrule\s!width\hsize\s!height3ex}}% \wd0\zeropoint \box0 \hbox to \hsize - {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}} + {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}} \endgraf} \protect \endinput diff --git a/tex/context/base/cont-log.mkiv b/tex/context/base/cont-log.mkiv index 67647920d..5d4133143 100644 --- a/tex/context/base/cont-log.mkiv +++ b/tex/context/base/cont-log.mkiv @@ -118,7 +118,7 @@ \logofont} \def\syst_logos_meta_hyphen % there is no hyphenchar in this font - {\discretionary{\vrule\!!height.33em\!!depth-.27em\!!width.33em}{}{}} + {\discretionary{\vrule\s!height.33em\s!depth-.27em\s!width.33em}{}{}} \unexpanded\def\MetaFont {\dontleavehmode @@ -270,4 +270,12 @@ \unexpanded\def\MPII{MpII} \unexpanded\def\MPIV{MpIV} +\appendtoks + \def\ConTeXt {ConTeXt}% + \def\MetaPost{MetaPost}% + \def\MetaFont{MetaFont}% + \def\MetaFun {MetaFun}% + \def\TeX {TeX}% +\to \everysimplifycommands + \protect \endinput diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index b4958762f..2c07401d8 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2012.05.30 11:26} +\newcontextversion{2012.10.19 00:06} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 5a28f8e29..e791d3ba8 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,515 +11,60 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2012.05.30 11:26} +\newcontextversion{2012.10.19 00:06} -%D This file is loaded at runtime, thereby providing an -%D excellent place for hacks, patches, extensions and new -%D features. +%D This file is loaded at runtime, thereby providing an excellent place for +%D hacks, patches, extensions and new features. \unprotect \writestatus\m!system{beware: some patches loaded from cont-new.mkiv} -\def\dividedsize#1#2#3% size gap n - {\dimexpr - \ifnum\dimexpr#1\relax>\plusone - (\dimexpr#1\relax-\numexpr#3-1\relax\dimexpr#2\relax)/#3\else#1% - \fi - \relax} - -\def\singlewidened #1{\hbox spread 1em{\hss#1\hss}} -\def\complexwidened[#1]#2{\hbox spread #1{\hss#2\hss}} +%D Maybe: -\definecomplexorsimple\widened - -\let\active\activecatcode % for a while (tikz) - -% todo -% -% \def\definelocation{\dodoubleargument\dodefinelocation} -% \def\dodefinelocation[#1][#2]{\setvalue{loc:#1}{#2}} -% -% \definelocation[lt] [\v!left\v!top] -% \definelocation[tl] [\v!left\v!top] -% \definelocation[\v!top\v!left][\v!left\v!top] -% -% \def\getlocation#1{\executeifdefined{loc:#1}{#1}} - -% \let\cs\getvalue % no, we want \cs to be czech - -% experimental so this may change +\unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox} +\unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop} -\def\startdescriptions - {\dosingleempty\dostartdescriptions} +%D Needs some work: -\def\dostartdescriptions[#1]% - {\begingroup - \def\item{\getvalue{#1}}% - \let\dostoppairdescription \donothing - \let\@@description \dostartpairdescription - \let\@@startsomedescription\dostartsomedescription} +\unexpanded\def\startgridcorrection + {\dosingleempty\spac_grid_correction_start} -\def\stopdescriptions - {\dostoppairdescription - \endgroup} - -\def\dostartpairdescription[#1][#2]% - {\dostoppairdescription - \def\dostoppairdescription{\@@stopdescription{#1}}% - \bgroup - \def\currentdescription{#1}% - \doifelse{\descriptionparameter{\s!do\c!state}}\v!start - {\@@makedescription{#1}[#2]{}} - {\@@makedescription{#1}[#2]}} - -\def\dostartsomedescription% #1[#2]#3% - {\bgroup - \@@makedescription} % {#1}[#2]{#3}} - -% \starttext -% -% \definedescription[test] -% -% \startdescriptions -% \test{Foo} Bar bar bar -% \test{Foo} Bar bar bar -% \test{Foo} Bar bar bar -% \stopdescriptions -% -% \startdescriptions[test] -% \item{Foo} Bar bar bar -% \item{Foo} Bar bar bar -% \item{Foo} Bar bar bar -% \stopdescriptions -% -% \startdescriptions -% \starttest{Foo} Bar bar bar \stoptest -% \starttest{Foo} Bar bar bar \stoptest -% \starttest{Foo} Bar bar bar \stoptest -% \stopdescriptions -% -% \startdescriptions[test] -% \item{Foo} Bar bar bar -% \item{Foo} Bar bar bar -% \item{Foo} Bar bar bar -% \stopdescriptions -% -% \stoptext - -% this will be activated when -% -% \newinsert\thispageinsert % <- installinsertion -% -% \def\flushatthispage -% {\bgroup -% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}% -% \hbox} -% -% \appendtoks -% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi -% \to \everyshipout - -% \definemarkedpage[nobackgrounds] -% \markpage[nobackgrounds] -% \doifmarkedpageelse{nobackgrounds} - -% Just a simple and fast hanger, for usage in macros. - -\def\setuphanging - {\dodoubleempty\getparameters[\??ha]} - -\setuphanging - [\c!distance=.5em] - -\def\starthanging - {\noindent\bgroup - \dowithnextbox - {\setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}% - \hangindent\nextboxwd - \hangafter\plusone - \flushnextbox\ignorespaces} - \hbox} - -\def\stophanging - {\endgraf - \egroup} - -% experimental - -\def\stophangaround - {\endgraf - \egroup} - -\def\starthangaround - {\noindent\bgroup - \dowithnextbox - {\ifdim\nextboxht>\strutht\setbox\nextbox\tbox{\flushnextbox}\fi - \setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}% - \getboxheight\scratchdimen\of\box\nextbox - \getnoflines\scratchdimen - \nextboxht\strutht - \nextboxdp\strutdp - \hangindent\nextboxwd - \hangafter-\noflines - \llap{\flushnextbox}\ignorespaces} - \hbox} - -\def\modevalue#1#2#3% - {\@EA\ifx\csname\@mode@\systemmodeprefix#1\endcsname\endcsname\enabledmode#2\else#2\fi} - -\def\systemmodevalue#1% - {\modevalue{\systemmodeprefix#1}} - -% new, still to be improved -% -% \dorecurse{10} -% {\input thuan -% \placefigure{}{\framed[height=1.5cm]{test}} -% \placefloatplaceholder} - -\def\placefloatplaceholder - {\ifroomforfloat \else - \scratchdimen\pagegoal - \advance\scratchdimen-\pagetotal - \advance\scratchdimen-3\lineheight - \ifdim\scratchdimen>\zeropoint - \startlinecorrection[blank] - \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}% - \stoplinecorrection - \else - \allowbreak - \fi - \fi} - -\setuplabeltext - [placeholder={, moved}] - -% move to support module, and then use context(...) - -\startluacode - function commands.percentageof(str,dim) - local n = str:match("^(.*)%%$") - context.sprint(tex.ctxcatcodes,(n and (tonumber(n)/100)*dim .. "sp") or str) - end -\stopluacode - -\gdef\setpercentdimen#1#2% - {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} - -% \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent} \the\scratchdimen -% \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt} \the\scratchdimen - -\bgroup \permitcircumflexescape - -\obeylines % don't remove %'s ! - -\gdef\collapsedspace#1% - {\ifx#1^^M% - \expandafter\collapsedspace - \else - \space - \expandafter#1% - \fi} - -\gdef\collapsespaces - {\prependtoksonce\relax\to\everyeof% - \ignorelines% - \ignoretabs% - \let\obeyedspace\collapsedspace% - \obeyspaces} - -\egroup - -\def\inlinedbox - {\bgroup - \dowithnextbox - {\scratchdimen\nextboxht - \advance\scratchdimen\nextboxdp - \advance\scratchdimen-\lineheight - \divide\scratchdimen\plustwo - \advance\scratchdimen\strutdepth - \setbox\nextbox\hbox{\lower\scratchdimen\flushnextbox}% - \nextboxht\strutht - \nextboxdp\strutdp - \flushnextbox - \egroup}% - \hbox} - -\def\dimenratio#1#2% etex only - {\withoutpt\the\dimexpr2\dimexpr(#1)/\dimexpr(#2)/32768\relax\relax} - -\def\doxprecurse#1#2% - {\ifnum#1=\zerocount % no \ifcase - \expandafter\gobblethreearguments - \else - #2\expandafter\expandafter\expandafter\doxprecurse\expandafter - \fi\expandafter{\the\numexpr#1-1\relax}{#2}} - -\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie - -\unexpanded\def\asciistr#1{\dontleavehmode{\defconvertedargument\ascii{#1}\verbatimfont\ascii}} - -\def\shapefill{\vskip\zeropoint\!!plus\lineheight\!!minus\lineheight\relax} - -% \ruledhbox -% {\startignorespaces -% \def\oeps{a} -% \startignorespaces -% \def\oeps{a} -% \stopignorespaces -% \def\oeps{a} -% \stopignorespaces -% \oeps} - -\newsignal\boissignal -\newcount \boislevel - -\long\def\startignorespaces - {\advance\boislevel\plusone - \ifcase\boislevel\or \ifhmode - \hskip\boissignal - \fi \fi - \ignorespaces} - -\long\def\stopignorespaces - {\ifcase\boislevel\or \ifhmode - \doloop - {\ifdim\lastskip=\zeropoint - \exitloop - \else\ifdim\lastskip=\boissignal - \unskip - \exitloop - \else - \unskip - \fi\fi}% - \fi \fi - \advance\boislevel\minusone} - -\def\minimalhbox#1#% - {\dowithnextbox - {\bgroup - \setbox\scratchbox\hbox#1{\hss}% - \ifdim\nextboxwd<\wd\scratchbox\nextboxwd\wd\scratchbox\fi - \flushnextbox - \egroup} - \hbox} - -\def\gobbleuntilempty#1\empty{} - -\def\dodimchoice#1#2#3% - {\ifdim#1#2% - #3\@EA\gobbleuntilempty - \else - \@EA\dodimchoice - \fi{#1}} - -\def\donumchoice#1#2#3% - {\ifnum#1#2% - #3\@EA\gobbleuntilempty - \else - \@EA\dodimchoice - \fi{#1}} - -\def\dimchoice#1#2{\dodimchoice{#1}#2{=#1}{#1}\empty} -\def\numchoice#1#2{\donumchoice{#1}#2{=#1}{#1}\empty} - -% \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) -% \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) -% \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) - -\def\tabulaterule % to be redone, not correct - {\dotabulaterule - {\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax - \doifvalue{\??tt\currenttabulate\c!distance}\v!grid - {\kern-\scratchdimen}}} % experimental tm-prikkels -% so far - -% between alignment lines certain rules apply, and even a -% simple test can mess up a table, which is why we have a -% special test facility -% -% \ruledvbox -% {\starttabulate[|l|p|] -% \NC 1test \NC test \NC \NR -% \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}% -% \stoptabulate} - -\long\def\tableifelse#1% - {\tablenoalign - {#1% - {\aftergroup \firstoftwoarguments}% - {\aftergroup\secondoftwoarguments}}} - -\long \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}} - -\def\tightvbox{\dowithnextbox{\nextboxdp\zeropoint\flushnextbox}\vbox} -\def\tightvtop{\dowithnextbox{\nextboxht\zeropoint\flushnextbox}\vtop} - -% what is this stupid macro meant for: - -\def\hyphenationpoint - {\hskip\zeropoint} - -\def\hyphenated#1% - {\bgroup - \!!counta\zerocount - \def\hyphenated##1{\advance\!!counta\plusone}% - \handletokens#1\with\hyphenated - \!!countb\plusone - \def\hyphenated##1% - {##1% - \advance\!!countb\plusone\relax - \ifnum\!!countb>2 \ifnum\!!countb<\!!counta - \hyphenationpoint - \fi\fi}% - \handletokens#1\with\hyphenated - \egroup} - -\def\obeysupersubletters - {\let\super\normalsuper - \let\suber\normalsuber - \let\normalsuper\letterhat - \let\normalsuber\letterunderscore - \enablesupersub} - -\def\obeysupersubmath - {\let\normalsuper\letterhat - \let\normalsuber\letterunderscore - \enablesupersub} - -\def\startgridcorrection - {\dosingleempty\dostartgridcorrection} - -\def\dostartgridcorrection[#1]% +\def\spac_grid_correction_start[#1]% {\ifgridsnapping \snaptogrid[#1]\vbox\bgroup \else \startbaselinecorrection \fi} -\def\stopgridcorrection +\unexpanded\def\stopgridcorrection {\ifgridsnapping \egroup \else \stopbaselinecorrection \fi} - -\def\checkgridsnapping + +\unexpanded\def\checkgridsnapping {\lineskip\ifgridsnapping\zeropoint\else\normallineskip\fi} - -\def\startplaatsen - {\dosingleempty\dostartplaatsen} -\def\dostartplaatsen[#1]% tzt n*links etc - {\endgraf - \noindent\bgroup - \setlocalhsize - \hbox to \localhsize\bgroup - \doifnot{#1}\v!left\hss - \def\stopplaatsen - {\unskip\unskip\unskip - \doifnot{#1}\v!right\hss - \egroup - \egroup - \endgraf}% - \gobblespacetokens} +%D Probably obsolete: -% \startplaatsen[links] bla \stopplaatsen - -\def\startcolumnmakeup % don't change +\unexpanded\def\startcolumnmakeup % don't change {\bgroup - \getrawnoflines\textheight % teksthoogte kan topskip hebben, dus raw - \scratchdimen\noflines\lineheight - \advance\scratchdimen-\lineheight - \advance\scratchdimen\topskip - \setbox\scratchbox - \ifcase\showgridstate\vbox\else\ruledvbox\fi to \scratchdimen\bgroup - \forgetall} % ! don't change + \getrawnoflines\textheight % raw as we cna have topskip + \setbox\scratchbox\vbox to \dimexpr\noflines\lineheight-\lineheight+\topskip\relax + \bgroup + \forgetall} -\def\stopcolumnmakeup +\unexpanded\def\stopcolumnmakeup {\egroup \dp\scratchbox\zeropoint \wd\scratchbox\textwidth \box\scratchbox \egroup \page_otr_command_synchronize_hsize} - -\long\def\startexternalfigure - {\dotripleempty\dostartexternalfigure} - -\long\def\dostartexternalfigure[#1][#2][#3]#4\stopexternalfigure - {\gdef\figuredescription{#4}% - \externalfigure[#1][#2][#3]% - \globallet\figuredescription\empty} - -\let\figuredescription\empty - -% incomplete, will be a special case of float placement - -\def\startfixed{\dosingleempty\dostartfixed} - -\def\dostartfixed[#1]% - {\expanded{\dowithnextbox{\noexpand\dodofixed{\ifhmode0\else1\fi}{#1}}}% - \vbox\bgroup - \setlocalhsize} - -\def\stopfixed - {\egroup} - -\def\dodofixed#1#2% - {\ifcase#1\relax - \processaction - [#2] - [ \v!high=>\bbox {\flushnextbox}, - \v!low=>\tbox {\flushnextbox}, - \v!middle=>\vcenter{\flushnextbox}, - \v!lohi=>\vcenter{\flushnextbox}, - \s!unknown=>\tbox {\flushnextbox}, - \s!default=>\tbox {\flushnextbox}]% - \else - \startbaselinecorrection - \noindent\flushnextbox - \stopbaselinecorrection - \fi} - -% \startitemize -% -% \item \externalfigure[koe][height=2cm] -% \item \externalfigure[koe][height=2cm] -% \item \externalfigure[koe][height=2cm] -% \item \externalfigure[koe][height=2cm] -% -% \page -% -% \item \startfixed \externalfigure[koe][height=2cm]\stopfixed -% \item \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed -% \item \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed -% \item \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed -% -% \page -% -% \item test \startfixed \externalfigure[koe][height=2cm]\stopfixed -% \item test \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed -% \item test \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed -% \item test \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed -% -% \page -% -% \item test \par \startfixed \externalfigure[koe][height=2cm]\stopfixed -% \item test \par \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed -% \item test \par \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed -% \item test \par \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed -% -% \stopitemize - -\def\obeyfollowingtoken{{}} % end \cs scanning - -% potential new defaults: -% -% \setbreakpoints[compound] -% till we fixed all styles: +%D Till we fixed all styles: \let\\=\crlf diff --git a/tex/context/base/cont-nop.mkiv b/tex/context/base/cont-nop.mkiv new file mode 100644 index 000000000..c8188503e --- /dev/null +++ b/tex/context/base/cont-nop.mkiv @@ -0,0 +1,22 @@ +%D \module +%D [ file=cont-nop, +%D version=2012.06.01, +%D title=\CONTEXT\ Miscellaneous Macros, +%D subtitle=Startup Dummy, +%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. + +\unprotect + +\writestatus\m!system{loading dummy replacement for jobname} + +\protect + +\finishjob + +\endinput diff --git a/tex/context/base/cont-yes.mkiv b/tex/context/base/cont-yes.mkiv new file mode 100644 index 000000000..2a032fc0b --- /dev/null +++ b/tex/context/base/cont-yes.mkiv @@ -0,0 +1,80 @@ +%D \module +%D [ file=cont-yes, +%D version=2012.06.01, +%D title=\CONTEXT\ Miscellaneous Macros, +%D subtitle=Startup Stub, +%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. + +% At some point I will reconsider the \starttext .. \stoptext +% wraping as we can assume proper styling. It's a left-over from +% mkii that we need to get rid of. + +\startluacode + + -- When a style is loaded there is a good change that we never enter + -- this code. + + environment.initializefilenames() + + local arguments = environment.arguments + local suffix = environment.suffix + local filename = environment.filename + + if suffix == "xml" or arguments.forcexml then + + -- Maybe we should move the preamble parsing here as it + -- can be part of (any) loaded (sub) file. The \starttext + -- wrapping might go away. + + context.starttext() + context.xmlprocess("main",filename,"") + context.stoptext() + + elseif suffix == "cld" or arguments.forcecld then + + context.runfile(filename) + + elseif suffix == "lua" or arguments.forcelua then + + -- The wrapping might go away. Why is is it there in the + -- first place. + + context.starttext() + context.ctxlua(string.format('dofile("%s")',filename)) + context.stoptext() + + elseif suffix == "mp" or arguments.forcemp then + + context.starttext() + context.processMPfigurefile(filename) + context.stoptext() + + -- elseif suffix == "prep" then + -- + -- -- Why do we wrap here. Because it can be xml? Let's get rid + -- -- of prepping in general. + -- + -- context.starttext() + -- context.input(filename) + -- context.stoptext() + + else + + -- We have a regular tex file so no \starttext yet as we can + -- load fonts. + + context.input(filename) + + end + + context.finishjob() + +\stopluacode + +\endinput diff --git a/tex/context/base/context-base.lmx b/tex/context/base/context-base.lmx index 09817463b..2b093c3e1 100644 --- a/tex/context/base/context-base.lmx +++ b/tex/context/base/context-base.lmx @@ -19,7 +19,9 @@ <?lua end ?> <style type="text/css"> <?lmx-include context.css ?> - </style> + <?lua if v('cssdata') then ?> +<?lua pv('cssdata') ?> + <?lua end ?> </style> <?lua if v('styles') then for k, v in ipairs(v('styles')) do ?> <link rel="StyleSheet" href="<?lua p(v) ?>" type="text/css" /> <?lua end end ?> diff --git a/tex/context/base/context-help.lmx b/tex/context/base/context-help.lmx index 5401fb65d..939b70cb6 100644 --- a/tex/context/base/context-help.lmx +++ b/tex/context/base/context-help.lmx @@ -19,6 +19,7 @@ </script> <title><?lua pv('title') ?></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <!-- <base target="context-help" /> --> <style type="text/css"> <!-- <?lmx-include context.css ?> diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex 7b8733c88..5b6793083 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex bb280817c..2df1bdb1b 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 8cd02fd9e..3163097b0 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2012.05.30 11:26} +\edef\contextversion{2012.10.19 00:06} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 5044edae1..3d93b64c3 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -19,11 +19,13 @@ %D 2004.8.30 the low level interface is english. Watch out and adapt %D your styles an modules. +% \everypar{\writestatus{!!!!}{some spurious input in line \the\inputlineno}\wait} + %D The order of loading will change when all modules have been cleaned %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2012.05.30 11:26} +\edef\contextversion{2012.10.19 00:06} %D For those who want to use this: @@ -107,9 +109,10 @@ \loadmarkfile{mult-ini} \loadmarkfile{mult-sys} +\loadmarkfile{mult-aux} \loadmarkfile{mult-def} \loadmarkfile{mult-chk} -\loadmarkfile{mult-aux} +%loadmarkfile{mult-aux} % moved up \loadmkvifile{mult-dim} \loadmarkfile{cldf-int} % interface @@ -120,7 +123,7 @@ \loadmarkfile{attr-ini} -\loadmarkfile{core-var} +\loadmarkfile{core-ini} \loadmarkfile{core-env} \loadmarkfile{layo-ini} @@ -131,7 +134,7 @@ \loadmarkfile{node-fin} \loadmarkfile{node-mig} -\loadmarkfile{node-par} +\loadmarkfile{typo-bld} % par builders %loadmarkfile{node-pag} \loadmarkfile{back-ini} @@ -142,24 +145,23 @@ \loadmarkfile{attr-eff} \loadmarkfile{trac-tex} -\loadmarkfile{trac-deb} +\loadmarkfile{trac-deb} % will move up +\loadmarkfile{trac-ctx} % maybe move up %loadmarkfile{blob-ini} % not to be used, we only use a helper \loadmarkfile{supp-box} -\loadmarkfile{supp-vis} -\loadmarkfile{supp-fun} % close to obsolete +%loadmarkfile{supp-vis} % replaced by trac-vis +%loadmarkfile{supp-fun} % mostly replaced \loadmarkfile{supp-ran} \loadmarkfile{supp-mat} -\loadmarkfile{supp-ali} -\loadmarkfile{supp-num} % replaced +\loadmarkfile{spac-cha} +%loadmarkfile{supp-num} % obsolete \loadmarkfile{typo-ini} -\loadmarkfile{page-ins} - \loadmkvifile{file-syn} \loadmkvifile{file-mod} @@ -186,7 +188,7 @@ \loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented) -\loadmarkfile{trac-vis} +\loadmarkfile{pack-cut} % leftovers from trac-vis \loadmarkfile{lang-mis} \loadmarkfile{lang-url} @@ -258,6 +260,7 @@ \loadmarkfile{page-var} \loadmkvifile{page-otr} \loadmarkfile{page-ini} +\loadmarkfile{page-ins} \loadmarkfile{page-fac} \loadmarkfile{page-brk} \loadmarkfile{page-col} @@ -274,9 +277,10 @@ \loadmkvifile{strc-flt} -\loadmarkfile{page-mis} +\loadmarkfile{page-pst} \loadmkvifile{page-mbk} -\loadmarkfile{page-mul} +\loadmarkfile{page-mul} % partly overloaded +\loadmarkfile{page-mix} % new \loadmarkfile{page-set} \loadmarkfile{pack-lyr} \loadmarkfile{pack-pos} @@ -286,10 +290,11 @@ \loadmarkfile{page-par} \loadmarkfile{typo-pag} \loadmarkfile{typo-mar} +\loadmarkfile{typo-itm} \loadmarkfile{buff-ini} \loadmarkfile{buff-ver} -\loadmarkfile{buff-par} +\loadmkvifile{buff-par} \loadmarkfile{buff-imp-tex} % optional as also runtime if not loaded \loadmarkfile{buff-imp-mp} % optional as also runtime if not loaded @@ -302,14 +307,15 @@ \loadmarkfile{strc-blk} \loadmarkfile{page-imp} -\loadmarkfile{page-sel} % optional -\loadmarkfile{page-com} % optional +\loadmkvifile{page-sel} % optional \loadmkvifile{scrn-pag} \loadmkvifile{scrn-wid} \loadmkvifile{scrn-but} \loadmkvifile{scrn-bar} +\loadmarkfile{page-com} % optional (after scrn-pag) + \loadmarkfile{strc-bkm} % bookmarks \loadmarkfile{tabl-com} @@ -323,6 +329,7 @@ \loadmarkfile{tabl-ltb} \loadmarkfile{tabl-tsp} \loadmkvifile{tabl-xtb} +\loadmarkfile{tabl-mis} \loadmarkfile{java-ini} @@ -345,9 +352,11 @@ \loadmarkfile{font-pre} \loadmarkfile{font-unk} \loadmarkfile{font-tra} +\loadmarkfile{font-chk} \loadmarkfile{font-uni} \loadmkvifile{font-col} -\loadmarkfile{font-gds} +\loadmkvifile{font-gds} +\loadmkvifile{font-aux} \loadmarkfile{lxml-css} @@ -355,6 +364,8 @@ \loadmarkfile{blob-ini} % not to be used, we only use a helper +\loadmarkfile{trac-vis} + \loadmarkfile{typo-cln} \loadmarkfile{typo-spa} \loadmarkfile{typo-krn} @@ -380,6 +391,7 @@ \loadmarkfile{meta-tex} \loadmarkfile{meta-fun} \loadmarkfile{meta-pag} +\loadmarkfile{meta-grd} \loadmarkfile{page-mrk} % depends on mp @@ -417,14 +429,12 @@ \loadmarkfile{typo-scr} -\loadmarkfile{core-fnt} \loadmarkfile{node-rul} -\loadmarkfile{node-spl} +\loadmkvifile{font-sol} % font solutions \loadmkvifile{strc-not} \loadmkvifile{strc-lnt} -\loadmarkfile{core-mis} \loadmarkfile{pack-com} \loadmarkfile{typo-del} @@ -454,9 +464,8 @@ \loadmarkfile{cldf-ver} % verbatim, this can come late \loadmarkfile{cldf-com} % commands, this can come late -\loadmarkfile{core-ctx} +\loadmarkfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace -\loadmarkfile{core-ini} \loadmarkfile{core-def} %usemodule[x][res-04] % xml resource libraries @@ -465,7 +474,7 @@ % now we hook in backend code (needs checking) -\loadmarkfile{back-pdf} % actually, this one should load the next three +\loadmarkfile{back-pdf} % actually, this one should load the next three using document.arguments.backend \loadmarkfile{mlib-pdf} \loadmarkfile{mlib-pps} \loadmarkfile{meta-pdf} diff --git a/tex/context/base/context.rme b/tex/context/base/context.rme index 1ce6b25c0..ff9ffb8ac 100644 --- a/tex/context/base/context.rme +++ b/tex/context/base/context.rme @@ -14,7 +14,10 @@ real problem as the engines don't change much either. Early 2011 the code base between MkII and MkIV got split completely and there is no shared code any longer, apart from some styles and -modules. +modules. From the perspective of ConteXt we now consider XeTeX to be +obsolete although we will keep supporting it in MkII. As pdftex is +still used in older workflows we will support that as long as it's +around. The main files context.mkii and context.mkiv are normally not used directly but instead we use the interface specific formats: @@ -76,4 +79,4 @@ Don't hesitate to ask questions. ConTeXt can do a lot, but the manuals always lag behind and can be incomplete. ------------------------- -Hans Hagen, pragma@wxs.nl +Hans Hagen, pragma @ wxs . nl diff --git a/tex/context/base/context.todo b/tex/context/base/context.todo deleted file mode 100644 index 27d914a7b..000000000 --- a/tex/context/base/context.todo +++ /dev/null @@ -1,6 +0,0 @@ -% marginrules - -% consistently use label/name/tag -% consistently use type/kind - -% option vs options diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua index e4b516e3b..641aea4ba 100644 --- a/tex/context/base/core-con.lua +++ b/tex/context/base/core-con.lua @@ -14,6 +14,8 @@ slower but look nicer this way.</p> <p>Some code may move to a module in the language namespace.</p> --ldx]]-- +local command, context = commands, context + local utf = unicode.utf8 local floor, date, time, concat = math.floor, os.date, os.time, table.concat @@ -22,30 +24,29 @@ local utfchar, utfbyte = utf.char, utf.byte local tonumber, tostring = tonumber, tostring local settings_to_array = utilities.parsers.settings_to_array -local allocate = utilities.storage.allocate - -local context = context +local allocate = utilities.storage.allocate -local variables = interfaces.variables +local context = context -converters = converters or { } -local converters = converters +local variables = interfaces.variables -languages = languages or { } -local languages = languages +converters = converters or { } +local converters = converters -local function number(n) - return tonumber(n) -end +languages = languages or { } +local languages = languages -converters.number = number +converters.number = tonumber +converters.numbers = tonumber function commands.number(n) context(n) end +commands.numbers = commands.number + -- to be reconsidered ... languages namespace here, might become local plus a register command local counters = allocate { - ['**'] = { + ['default'] = { -- no metatable as we do a test on keys 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, @@ -135,7 +136,7 @@ counters['kr'] = counters['korean'] counters['kr-p'] = counters['korean-parent'] counters['kr-c'] = counters['korean-circle'] -local fallback = utf.byte('0') +local fallback = utfbyte('0') local function chr(n,m) return (n > 0 and n < 27 and utfchar(n+m)) or "" @@ -197,32 +198,28 @@ local function do_alphabetic(n,mapping,mapper,t) end end -local function alphabetic(n,code) - return do_alphabetic(n,counters[code] or counters['**'],lowercharacter) +function converters.alphabetic(n,code) + return do_alphabetic(n,counters[code] or counters.default,lowercharacter) end -local function Alphabetic(n,code) - return do_alphabetic(n,counters[code] or counters['**'],uppercharacter) +function converters.Alphabetic(n,code) + return do_alphabetic(n,counters[code] or counters.default,uppercharacter) end -local function character (n) return chr (n,96) end -local function Character (n) return chr (n,64) end -local function characters(n) return chrs(n,96) end -local function Characters(n) return chrs(n,64) end - -converters.alphabetic = alphabetic -converters.Alphabetic = Alphabetic -converters.character = character -converters.Character = Character -converters.characters = characters -converters.Characters = Characters - -function commands.alphabetic(n,c) context(alphabetic(n,c)) end -function commands.Alphabetic(n,c) context(Alphabetic(n,c)) end -function commands.character (n) context(character (n)) end -function commands.Character (n) context(Character (n)) end -function commands.characters(n) context(characters(n)) end -function commands.Characters(n) context(Characters(n)) end +local lower_offset = 96 +local upper_offset = 64 + +function converters.character (n) return chr (n,lower_offset) end +function converters.Character (n) return chr (n,upper_offset) end +function converters.characters(n) return chrs(n,lower_offset) end +function converters.Characters(n) return chrs(n,upper_offset) end + +function commands.alphabetic(n,c) context(do_alphabetic(n,counters[c],lowercharacter)) end +function commands.Alphabetic(n,c) context(do_alphabetic(n,counters[c],uppercharacter)) end +function commands.character (n) context(chr (n,lower_offset)) end +function commands.Character (n) context(chr (n,upper_offset)) end +function commands.characters(n) context(chrs(n,lower_offset)) end +function commands.Characters(n) context(chrs(n,upper_offset)) end local days = { [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, @@ -245,52 +242,35 @@ local function nofdays(year,month) return days[isleapyear(year)][month] end -local function year () return date("%Y") end -local function month () return date("%m") end -local function hour () return date("%H") end -local function minute() return date("%M") end -local function second() return date("%S") end - local function textime() return tonumber(date("%H")) * 60 + tonumber(date("%M")) end +function converters.year () return date("%Y") end +function converters.month () return date("%m") end +function converters.hour () return date("%H") end +function converters.minute() return date("%M") end +function converters.second() return date("%S") end + converters.weekday = weekday converters.isleapyear = isleapyear converters.leapyear = leapyear converters.nofdays = nofdays -converters.year = year -converters.month = month -converters.hour = hour -converters.minute = minute -converters.second = second converters.textime = textime -function commands.weekday(day,month,year) - context(weekday(day,month,year)) -end - -function commands.isleapyear(year) - context(isleapyear(year)) -end - -function commands.leapyear(year) - context(leapyear(year)) -end - -function commands.nofdays(year,month) - context(nofdays(year,month)) -end +function commands.weekday (day,month,year) context(weekday (day,month,year)) end +function commands.leapyear(year) context(leapyear(year)) end -- rather useless +function commands.nofdays (year,month) context(nofdays (year,month)) end -function commands.year () context(year ()) end -function commands.month () context(month ()) end -function commands.hour () context(hour ()) end -function commands.minute () context(minute ()) end -function commands.second () context(second ()) end +function commands.year () context(date("%Y")) end +function commands.month () context(date("%m")) end +function commands.hour () context(date("%H")) end +function commands.minute () context(date("%M")) end +function commands.second () context(date("%S")) end function commands.textime() context(textime()) end function commands.doifleapyearelse(year) - commands.testcase(leapyear(year)) + commands.doifelse(isleapyear(year)) end local roman = { @@ -307,13 +287,9 @@ local function toroman(n) end end -local Romannumerals = toroman - -local function romannumerals(n) return lower(toroman(n)) end - converters.toroman = toroman converters.Romannumerals = toroman -converters.romannumerals = romannumerals +converters.romannumerals = function(n) return lower(toroman(n)) end function commands.romannumerals(n) context(lower(toroman(n))) end function commands.Romannumerals(n) context( toroman(n)) end @@ -366,11 +342,8 @@ end converters.toabjad = toabjad -local function abjadnumerals (n) return toabjad(n,false) end -local function abjadnodotnumerals(n) return toabjad(n,true ) end - -converters.abjadnumerals = abjadnumerals -converters.abjadnodotnumerals = abjadnodotnumerals +function converters.abjadnumerals (n) return toabjad(n,false) end +function converters.abjadnodotnumerals(n) return toabjad(n,true ) end function commands.abjadnumerals (n) context(toabjad(n,false)) end function commands.abjadnodotnumerals(n) context(toabjad(n,true )) end @@ -515,23 +488,18 @@ end converters.tochinese = tochinese -local function chinesenumerals (n) return tochinese(n,"normal") end -local function chinesecapnumerals(n) return tochinese(n,"cap" ) end -local function chineseallnumerals(n) return tochinese(n,"all" ) end - -converters.chinesenumerals = chinesenumerals -converters.chinesecapnumerals = chinesecapnumerals -converters.chineseallnumerals = chineseallnumerals +function converters.chinesenumerals (n) return tochinese(n,"normal") end +function converters.chinesecapnumerals(n) return tochinese(n,"cap" ) end +function converters.chineseallnumerals(n) return tochinese(n,"all" ) end function commands.chinesenumerals (n) context(tochinese(n,"normal")) end function commands.chinesecapnumerals(n) context(tochinese(n,"cap" )) end function commands.chineseallnumerals(n) context(tochinese(n,"all" )) end converters.sequences = converters.sequences or { } +local sequences = converters.sequences -storage.register("converters/sequences", converters.sequences, "converters.sequences") - -local sequences = converters.sequences +storage.register("converters/sequences", sequences, "converters.sequences") function converters.define(name,set) sequences[name] = settings_to_array(set) @@ -683,7 +651,7 @@ end -- context(escapes[n] or utfchar(n)) -- end -- --- local lccodes, uccodes = characters.lccode, characters.uccode +-- local lccodes, uccodes, safechar = characters.lccode, characters.uccode, commands.safechar -- -- local function do_alphabetic(n,mapping,chr) -- local max = #mapping @@ -691,7 +659,7 @@ end -- do_alphabetic(floor((n-1)/max),mapping,chr) -- n = (n-1)%max+1 -- end --- characters.flush(chr(n,mapping)) +-- safechar(chr(n,mapping)) -- end -- -- local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end @@ -705,8 +673,6 @@ end -- do_alphabetic(n,counters[code] or counters['**'],uppercased) -- end --- -- - local ordinals = { english = function(n) local two = n % 100 @@ -813,11 +779,12 @@ end function commands.currentdate(str,currentlanguage) -- second argument false : no label local list = utilities.parsers.settings_to_array(str) + local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right local year, month, day = tex.year, tex.month, tex.day local auto = true for i=1,#list do local entry = list[i] - local tag, plus = languages.labels.split(entry) + local tag, plus = splitlabel(entry) local ordinal, mnemonic, whatordinal = false, false, nil if not tag then tag = entry diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv index 241d43165..cdc51eb23 100644 --- a/tex/context/base/core-con.mkiv +++ b/tex/context/base/core-con.mkiv @@ -20,35 +20,27 @@ \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 -%D and dates. I considered splitting this module in a support -%D one and a core one, but to keep things simple as well as -%D preserve the overview, I decided against splitting. +%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 -% cleaner, some day: -% -% \def\isolateseparators % etex only, even works with list separator overloading -% {\unexpanded\def\spr##1{{##1}}% -% \unexpanded\def\stp##1{{##1}}} - -% needed for arab : +% needed for arab: \unexpanded\def\isolateseparators % even works with list separator overloading - {\def\spr##1{{##1}}% - \def\stp##1{{##1}}} + {\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 -%D \TEX\ primitive \type{\number}. The uppercase alternative is -%D only there for compatibility with the other conversion -%D macros. We could do without \type{#1} but this way we get -%D rid of unwanted braces. For the savety we also define a -%D non||sence uppercase alternative. +%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 @@ -57,8 +49,8 @@ %D \def\Numbers#1{\number#1} %D \stoptyping %D -%D Due to read ahead, as in \type{[\pagenumber\space]} the space will -%D disappear, unless we use: +%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear, +%D unless we use: \def\numbers#1{\purenumber{#1}} \def\Numbers#1{\purenumber{#1}} @@ -66,10 +58,9 @@ %D \macros %D {romannumerals,Romannumerals} %D -%D \TEX\ the program uses a rather tricky conversion from -%D numbers to their roman counterparts. This conversion could -%D of course be programmed in \TEX\ itself, but I guess Knuth -%D found the programming trick worth presenting. +%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} @@ -113,9 +104,9 @@ %D \macros %D {character,Character} %D -%D Converting a number into a character can of course only -%D be done with numbers less or equal to~26. At the cost of -%D much more macros a faster conversion is possible, using: +%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}} @@ -134,9 +125,8 @@ %D \macros %D {characters,Characters} %D -%D Converting large numbers is supported by the next two -%D macros. This time we just count on: $\cdots$~x, y, z, aa, -%D ab, ac~$\cdots$. +%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} @@ -163,20 +153,25 @@ \endgroup} \unexpanded\def\oldstyleromannumerals#1% will become obsolete - {\begingroup - \leftrulefalse - \rightrulefalse + {\dontleavehmode + \hbox\bgroup \ss\txx - \boxrulewidth.15ex - \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}% - \endgroup} + \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 -%D passed to \type{\write} en \type{\message}. That's why we -%D introduce: +%D The previous two commands are not robust enough to be passed to \type +%D {\write} en \type{\message}. That's why we introduce: \unexpanded\def\protectconversion {\let\doconvertcharacters\firstofoneargument} @@ -184,10 +179,9 @@ %D \macros %D {normaltime,normalyear,normalmonth,normalday} %D -%D The last part of this module is dedicated to converting -%D dates. Because we want to use as meaningful commands as -%D possible, and because \TEX\ already uses up some of those, -%D we save the original meanings. +%D The last part of this module is dedicated to converting dates. Because we +%D want to use as meaningful commands as possible, and because \TEX\ already +%D uses up some of those, we save the original meanings. \savenormalmeaning\time \savenormalmeaning\year @@ -197,10 +191,9 @@ %D \macros %D {month,MONTH} %D -%D Converting the month number into a month name is done -%D using a case statement, abstact values and the label -%D mechanism. This way users can easily redefine a label from -%D for instance german into austrian. +%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] @@ -224,11 +217,9 @@ \def\MONTHLONG #1{\WORD{\monthlong {#1}}} \def\MONTHSHORT#1{\WORD{\monthshort{#1}}} -%D We never explicitly needed this, but Tobias Burnus pointed -%D out that it would be handy to convert to the day of the -%D week. In doing so, we have to calculate the total number of -%D days, taking leapyears into account. For those who are -%D curious: +%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 @@ -239,8 +230,7 @@ %D \macros %D {weekday,WEEKDAY} %D -%D The first one is sort of redundant. It takes the day -%D number argument. +%D The first one is sort of redundant. It takes the day number argument. %D %D \showsetup{weekday} %D \showsetup{WEEKDAY} @@ -277,15 +267,15 @@ %D \getbuffer %D \stoplines %D -%D The macro \type {\getdayoftheweek} can be used to calculate -%D the number \type {\normalweekday}. +%D The macro \type {\getdayoftheweek} can be used to calculate the number +%D \type {\normalweekday}. %D \macros %D {doifleapyearelse, %D getdayspermonth} %D -%D Sometimes we need to know if we're dealing with a -%D leapyear, so here is a testmacro: +%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} @@ -297,8 +287,7 @@ %D \getdayspermonth{year}{month} %D \stoptyping %D -%D The number of days is available in the macro \type -%D {\numberofdays}. +%D The number of days is available in the macro \type {\numberofdays}. \def\doifleapyearelse#1% {\ctxcommand{doifleapyearelse(\number#1)}} @@ -320,13 +309,11 @@ %D \macros %D {currentdate, rawdate, date} %D -%D We use these conversion macros in the date formatting -%D macro: +%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 -%D instance: +%D This macro takes care of proper spacing and delivers for instance: %D %D \startbuffer %D \currentdate[weekday,day,month,year] % still dutch example @@ -351,8 +338,8 @@ %D %D or typeset: \getbuffer. %D -%D When no argument is passed, the current date is given as -%D specified per language (using \type{\installlanguage}). +%D When no argument is passed, the current date is given as specified per +%D language (using \type{\installlanguage}). %D %D \showsetup{currentdate} %D @@ -367,8 +354,8 @@ %D %D \typebuffer %D -%D The date is specified by one character keys. When no date -%D is given, we get the current date. +%D The date is specified by one character keys. When no date is given, we +%D get the current date. %D %D \startlines %D \getbuffer @@ -430,10 +417,13 @@ \def\syst_converters_date[#1][#2]% {\begingroup \iffirstargument - \getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]% - \normalday \@@dad\relax - \normalmonth\@@dam\relax - \normalyear \@@day\relax + \letdummyparameter\c!d\normalday + \letdummyparameter\c!m\normalmonth + \letdummyparameter\c!y\normalyear + \getdummyparameters[#1]% + \normalday \directdummyparameter\c!d\relax + \normalmonth\directdummyparameter\c!m\relax + \normalyear \directdummyparameter\c!y\relax \fi \syst_converters_current_date[#2]% \endgroup} @@ -444,9 +434,8 @@ %D \macros %D {currenttime} %D -%D The currenttime is actually the jobtime. You can specify -%D a pattern similar to the previous date macro using the -%D keys \type {h}, \type {m} and a separator. +%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. \unexpanded\def\calculatecurrenttime {\edef\currenthour {\ctxcommand{hour ()}}% @@ -462,7 +451,6 @@ \unexpanded\def\currenttime {\doifnextoptionalelse\syst_converters_current_time_yes\syst_converters_current_time_nop} - \unexpanded\def\syst_converters_current_time_yes[#1]% {\calculatecurrenttime \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} @@ -471,16 +459,15 @@ {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}} -%D Because we're dealing with dates, we also introduce a few -%D day loops: +%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 -%D \type{\normalday} can be used for for date manipulations. +%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday} +%D can be used for for date manipulations. \unexpanded\def\processmonth#1#2#3% year month command {\begingroup @@ -505,15 +492,13 @@ %D \macros %D {defineconversion, convertnumber} %D -%D Conversion involves the macros that we implemented earlier -%D in this module. +%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 -%D a set of conversion symbols. Both need a bit different -%D treatment. +%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] @@ -549,9 +534,9 @@ \def\syst_converters_checked_conversion#1#2% {\ctxcommand{checkedconversion("#1",#2)}} -%D If a conversion is just a font switch then we need to make sure -%D that the number is indeed end up as number in the input, so we -%D need to handle the second argument. +%D If a conversion is just a font switch then we need to make sure that the +%D number is indeed ends up as number in the input, so we need to handle the +%D second argument. \def\convertnumber#1#2% expandable {\csname\??conversionarguments @@ -600,19 +585,17 @@ %D \macros %D {ordinaldaynumber, highordinalstr, ordinalstr} %D -%D Efficient general ordinal number converters are sometimes -%D difficult to implement. Fortunately dates never exceed the -%D number~31. +%D Efficient general ordinal number converters are sometimes difficult to +%D implement. Fortunately dates never exceed the number~31. \def\highordinalstr #1{\high{\notsmallcapped{#1}}} \def\ordinalstr #1{\notsmallcapped{#1}} \def\ordinaldaynumber #1{\ctxcommand{ordinal(#1,"\currentlanguage")}} -%D As longs as symbols are linked to levels or numbers, we can -%D also use the conversion mechanism, but in for instance the -%D itemization macros, we prefer symbols because they can more -%D easier be (partially) redefined. Symbols are implemented -%D in another module. +%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. \def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}} \def\smallcappedcharacters #1{\smallcapped{\characters {#1}}} diff --git a/tex/context/base/core-ctx.ctx b/tex/context/base/core-ctx.ctx new file mode 100644 index 000000000..5126ad2d2 --- /dev/null +++ b/tex/context/base/core-ctx.ctx @@ -0,0 +1,23 @@ +<?xml version='1.0' standalone='yes'?> + +<ctx:job> + <ctx:message>demo file</ctx:message> + <ctx:preprocess suffix='prep'> + <ctx:processors> + <ctx:processor name='step-1' suffix='one' >dummy-prep-command-1 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor> + <ctx:processor name='step-2' suffix='prep'>dummy-prep-command-2 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor> + </ctx:processors> + <ctx:files> + <ctx:file processor='step-1' >one*.xml</ctx:file> + <ctx:file processor='step-2' >two*.xml</ctx:file> + <ctx:file processor='step-1,step-2'>all*.xml</ctx:file> + </ctx:files> + </ctx:preprocess> + <ctx:process> + <ctx:resources> + <ctx:environment>step-1-step-2.tex</ctx:environment> + </ctx:resources> + </ctx:process> + <ctx:postprocess> + </ctx:postprocess> +</ctx:job> diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua index e6fb7bb5f..0dfb21ce9 100644 --- a/tex/context/base/core-ctx.lua +++ b/tex/context/base/core-ctx.lua @@ -6,72 +6,290 @@ if not modules then modules = { } end modules ['core-ctx'] = { license = "see context related readme files" } +--[[ +Job control files aka ctx files are rather old and date from the mkii times. +They were handled in texexec and mtx-context and deals with modes, modules, +environments and preprocessing in projects where one such file drives the +processing of lots of files without the need to provide command line +arguments. + +In mkiv this concept was of course supported as well. The first implementation +of mtx-context took much of the approach of texexec, but by now we have gotten +rid of the option file (for passing modes, modules and environments), the stubs +(for directly processing cld and xml) as well as the preprocessing component +of the ctx files. Special helper features, like typesetting listings, were +already moved to the extras (a direct side effect of the ability to pass along +command line arguments.) All this made mtx-context more simple than its ancestor +texexec. + +Because some of the modes might affect the mtx-context end, the ctx file is +still loaded there but only for getting the modes. The file is loaded again +during the run but as loading and basic processing takes less than a +millisecond it's not that much of a burden. +--]] + +-- the ctxrunner tabel might either become private or move to the job namespace +-- which also affects the loading order + local trace_prepfiles = false trackers.register("system.prepfiles", function(v) trace_prepfiles = v end) +local gsub, find, match, validstring = string.gsub, string.find, string.match, string.valid +local concat = table.concat +local xmltext = xml.text + local report_prepfiles = logs.reporter("system","prepfiles") commands = commands or { } local commands = commands -local list, suffix, islocal, found = { }, "prep", false, false - -function commands.loadctxpreplist() - local ctlname = file.replacesuffix(tex.jobname,"ctl") - if lfs.isfile(ctlname) then - local x = xml.load(ctlname) - if x then - islocal = xml.found(x,"ctx:preplist[@local=='yes']") ---~ if trace_prepfiles then - if islocal then - report_prepfiles("loading ctx log file (local)") -- todo: m!system - else - report_prepfiles("loading ctx log file (specified)") -- todo: m!system +ctxrunner = ctxrunner or { } + +ctxrunner.prepfiles = utilities.storage.allocate() + +local function dontpreparefile(t,k) + return k -- we only store when we have a prepper +end + +table.setmetatableindex(ctxrunner.prepfiles,dontpreparefile) + +local function filtered(str,method) -- in resolvers? + str = tostring(str) + if method == 'name' then str = file.nameonly(str) + elseif method == 'path' then str = file.dirname(str) + elseif method == 'suffix' then str = file.suffix(str) + elseif method == 'nosuffix' then str = file.removesuffix(str) + elseif method == 'nopath' then str = file.basename(str) + elseif method == 'base' then str = file.basename(str) +-- elseif method == 'full' then +-- elseif method == 'complete' then +-- elseif method == 'expand' then -- str = file.expandpath(str) + end + return (gsub(str,"\\","/")) +end + +-- local function substitute(e,str) +-- local attributes = e.at +-- if str and attributes then +-- if attributes['method'] then +-- str = filtered(str,attributes['method']) +-- end +-- if str == "" and attributes['default'] then +-- str = attributes['default'] +-- end +-- end +-- return str +-- end + +local function substitute(str) + return str +end + +local function justtext(str) + str = xml.unescaped(tostring(str)) + str = xml.cleansed(str) + str = gsub(str,"\\+",'/') + str = gsub(str,"%s+",' ') + return str +end + +function ctxrunner.load(ctxname) + + local xmldata = xml.load(ctxname) + + local jobname = tex.jobname -- todo + + local variables = { job = jobname } + local commands = { } + local flags = { } + local paths = { } -- todo + local treatments = { } + local suffix = "prep" + + xml.include(xmldata,'ctx:include','name', {'.', file.dirname(ctxname), "..", "../.." }) + + for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do + local flag = xmltext(e) + local key, value = match(flag,"^(.-)=(.+)$") + if key and value then + environment.setargument(key,value) + else + environment.setargument(flag,true) + end + end + + -- add to document.options.ctxfile[...] + + local ctxfile = document.options.ctxfile + + local modes = ctxfile.modes + local modules = ctxfile.modules + local environments = ctxfile.environments + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode") do + modes[#modes+1] = xmltext(e) + -- context.enablemode { xmltext(e) } + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module") do + modules[#modules+1] = xmltext(e) + -- context.module { xmltext(e) } + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do + environments[#environments+1] = xmltext(e) + -- context.environment { xmltext(e) } + end + + for e in xml.collected(xmldata,"ctx:message") do + report_prepfiles("ctx comment: %s", xmltext(e)) + end + + for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do + d[k] = variables['job'] or "" + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do + commands[e.at and e.at['name'] or "unknown"] = e + end + + local suffix = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/attribute('suffix')") -- or ... + local runlocal = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local')") + + runlocal = toboolean(runlocal) + + -- todo: only collect, then plug into file handler + + local inputfile = validstring(environment.arguments.input) or jobname + + variables.old = inputfile + + for files in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:files") do + for pattern in xml.collected(files,"ctx:file") do + local preprocessor = pattern.at['processor'] or "" + for r, d, k in xml.elements(pattern,"/ctx:old") do + d[k] = jobname + end + for r, d, k in xml.elements(pattern,"/ctx:value[@name='old'") do + d[k] = jobname + end + pattern =justtext(xml.tostring(pattern)) + if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then + local noftreatments = #treatments + 1 + local findpattern = string.topattern(pattern) + local preprocessors = utilities.parsers.settings_to_array(preprocessor) + treatments[noftreatments] = { + pattern = findpattern, + preprocessors = preprocessors, + } + report_prepfiles("step: %s, pattern: %q, preprocessor: %q",noftreatments,findpattern,concat(preprocessors," ")) + end + end + end + + local function needstreatment(oldfile) + for i=1,#treatments do + local treatment = treatments[i] + local pattern = treatment.pattern + if find(oldfile,pattern) then + return treatment + end + end + end + + local preparefile = #treatments > 0 and function(prepfiles,filename) + + local treatment = needstreatment(filename) + if treatment then + local oldfile = filename + -- newfile = oldfile .. "." .. suffix + newfile = oldfile .. ".prep" + if runlocal then + newfile = file.basename(newfile) + end + + if file.needsupdating(oldfile,newfile) then + local preprocessors = treatment.preprocessors + local runners = { } + for i=1,#preprocessors do + local preprocessor = preprocessors[i] + local command = commands[preprocessor] + if command then + command = xml.copy(command) + local suf = command.at and command.at['suffix'] or suffix + if suf then + newfile = oldfile .. "." .. suf + end + if runlocal then + newfile = file.basename(newfile) + end + for r, d, k in xml.elements(command,"ctx:old") do + d[k] = substitute(oldfile) + end + for r, d, k in xml.elements(command,"ctx:new") do + d[k] = substitute(newfile) + end + variables.old = oldfile + variables.new = newfile + for r, d, k in xml.elements(command,"ctx:value") do + local ek = d[k] + local ekat = ek.at and ek.at['name'] + if ekat then + d[k] = substitute(variables[ekat] or "") + end + end + command = xml.content(command) + runners[#runners+1] = justtext(command) + oldfile = newfile + if runlocal then + oldfile = file.basename(oldfile) + end + end end ---~ end - for e in xml.collected(x,"ctx:prepfile") do - local name = xml.text(e) - if islocal then - name = file.basename(name) + -- for tracing we have collected commands first + for i=1,#runners do + report_prepfiles("step %i: %s",i,runners[i]) end - local done = e.at['done'] or 'no' - if trace_prepfiles then - report_prepfiles("registering %s -> %s",done) + -- + for i=1,#runners do + local command = runners[i] + report_prepfiles("command: %s",command) + local result = os.spawn(command) or 0 + -- if result > 0 then + -- report_prepfiles("error, return code: %s",result) + -- end end - found = true - list[name] = done -- 'yes' or 'no' + if lfs.isfile(newfile) then + file.syncmtimes(filename,newfile) + report_prepfiles("%q is converted to %q",filename,newfile) + else + report_prepfiles("%q is not converted to %q",filename,newfile) + newfile = filename + end + elseif lfs.isfile(newfile) then + report_prepfiles("%q is already converted to %q",filename,newfile) + else + -- report_prepfiles("%q is not converted to %q",filename,newfile) + newfile = filename end + else + newfile = filename end - end -end + prepfiles[filename] = newfile --- -- -- + return newfile -local function found(name) -- used in resolve - local prepname = name .. "." .. suffix - if list[name] and lfs.isfile(prepname) then - if trace_prepfiles then - report_prepfiles("preprocessing: using %s",prepname) - end - return prepname end - return false + + table.setmetatableindex(ctxrunner.prepfiles,preparefile or dontpreparefile) + + -- we need to deal with the input filename as it has already be resolved + end local function resolve(name) -- used a few times later on - local filename = file.collapsepath(name) - local prepname = islocal and found(file.basename(name)) - if prepname then - return prepname - end - prepname = found(filename) - if prepname then - return prepname - end - return false + return ctxrunner.prepfiles[file.collapsepath(name)] or false end ---~ support.doiffileexistelse(name) - local processfile = commands.processfile local doifinputfileelse = commands.doifinputfileelse @@ -94,3 +312,24 @@ end function commands.preparedfile(name) return resolve(name) or name end + +function commands.getctxfile() + local ctxfile = document.arguments.ctx or "" + if ctxfile ~= "" then + ctxrunner.load(ctxfile) -- do we need to locate it? + end +end + +function ctxrunner.resolve(name) -- used a few times later on + return ctxrunner.prepfiles[file.collapsepath(name)] or name +end + +-- ctxrunner.load("t:/sources/core-ctx.ctx") +-- +-- context(ctxrunner.prepfiles["one-a.xml"]) context.par() +-- context(ctxrunner.prepfiles["one-b.xml"]) context.par() +-- context(ctxrunner.prepfiles["two-c.xml"]) context.par() +-- context(ctxrunner.prepfiles["two-d.xml"]) context.par() +-- context(ctxrunner.prepfiles["all-x.xml"]) context.par() +-- +-- inspect(ctxrunner.prepfiles) diff --git a/tex/context/base/core-ctx.mkiv b/tex/context/base/core-ctx.mkiv index e178ee21b..50b3ae4a2 100644 --- a/tex/context/base/core-ctx.mkiv +++ b/tex/context/base/core-ctx.mkiv @@ -13,18 +13,16 @@ \writestatus{loading}{ConTeXt Core Macros / Job Control} -\unprotect - -\setnewconstant\preprocessmethod\plustwo % always check in mkiv - \registerctxluafile{core-ctx}{1.000} -\def\loadctxpreplist - {\ctxcommand{loadctxpreplist()}% - \glet\loadctxpreplist\relax} +\unprotect -\appendtoks - \loadctxpreplist -\to \everystarttext % maybe too late but don't change it now +\unexpanded\def\job_options_get_commandline {\ctxcommand{getcommandline()}} +\unexpanded\def\job_options_get_ctxfile {\ctxcommand{getctxfile()}} +\unexpanded\def\job_options_log {\ctxcommand{logoptions()}} +\unexpanded\def\job_options_set_modes {\ctxcommand{setdocumentmodes()}} +\unexpanded\def\job_options_set_modules {\ctxcommand{setdocumentmodules()}} +\unexpanded\def\job_options_set_environments{\ctxcommand{setdocumentenvironments()}} +\unexpanded\def\job_options_set_filenames {\ctxcommand{setdocumentfilenames()}} \protect \endinput diff --git a/tex/context/base/core-dat.lua b/tex/context/base/core-dat.lua index 071a3fe0b..879ff6130 100644 --- a/tex/context/base/core-dat.lua +++ b/tex/context/base/core-dat.lua @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['core-dat'] = { replaces the twopass data mechanism.</p> --ldx]]-- -local tonumber = tonumber +local tonumber, type = tonumber, type local context, commands = context, commands @@ -69,7 +69,12 @@ local function setdata(settings) local tag = settings.tag local data = settings.data local list = tobesaved[name] - data = settings_to_hash(data) or { } + if settings.convert and type(data) == "string" then + data = settings_to_hash(data) + end + if type(data) ~= "table" then + data = { data = settings.data } + end if not tag then tag = #list + 1 else @@ -109,25 +114,30 @@ end function datasets.getdata(name,tag,key,default) local t = collected[name] - if t then + if t == nil then + if trace_datasets then + report_dataset("unknown: name %s",name) + end + elseif type(t) ~= "table" then + return t + else t = t[tag] or t[tonumber(tag)] - if t then - if key then - return t[key] or default - else - return t + if not t then + if trace_datasets then + report_dataset("unknown: name %s, tag %s",name,tag) end - elseif trace_datasets then - report_dataset("unknown: name %s, tag %s",name,tag) + elseif key then + return t[key] or default + else + return t end - elseif trace_datasets then - report_dataset("unknown: name %s",name) end return default end function commands.setdataset(settings) - local name, tag, data = setdata(settings) + settings.convert = true + local name, tag = setdata(settings) if settings.delay ~= v_yes then -- elseif type(tag) == "number" then @@ -139,11 +149,25 @@ end function commands.datasetvariable(name,tag,key) local t = collected[name] - t = t and (t[tag] or t[tonumber(tag)]) - if t then - local s = t[key] - if s then - context(s) + if t == nil then + if trace_datasets then + report_dataset("unknown: name %s (not passed to tex)",name) + end + elseif type(t) ~= "table" then + context(tostring(t)) + else + t = t and (t[tag] or t[tonumber(tag)]) + if not t then + if trace_datasets then + report_dataset("unknown: name %s with tag %s (not passed to tex)",name,tag) + end + elseif type(t) ~= "table" then + local s = t[key] + if type(s) ~= "table" then + context(tostring(s)) + elseif trace_datasets then + report_dataset("table: name %s, tag %s (not passed to tex)",name,tag) + end end end end diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv index 4f856f996..d1c774f40 100644 --- a/tex/context/base/core-def.mkiv +++ b/tex/context/base/core-def.mkiv @@ -24,44 +24,116 @@ \setupinteraction[\c!symbolset=navigation 1] +% what a mess + +\everypar \emptytoks +\neverypar \emptytoks + +\appendtoks + % \flushnotes + \page_otr_command_synchronize_side_floats % an otr specific command + \checkindentation + \showparagraphnumber + \restoreinterlinepenalty + % \flushmargincontents + % \flushcommentanchors + \flushnotes + \synchronizenotes + \OTRSETshowstatus + \registerparoptions + % \flushsyncpositions + \flushpostponednodedata + \typo_delimited_repeat + \insertparagraphintro +\to \everypar + +\appendtoks + \flushnotes +\to \everydisplay + +\appendtoks + \adjustsidefloatdisplaylines +\to \everydisplay + +% \appendtoks +% \flushsyncpositions +% \to \everyheadstart + +% \appendtoks +% \flushsyncresets +% \to \everyendoftextbody + +\appendtoks + \ignorespaces +\to \everybeginofpar + +\appendtoks + \removeunwantedspaces + % \strut % option ? + % \flushsyncresets + % \setlastlinewidth % gone, will be done in lua + \endgraf +\to \everyendofpar + % initialization order: \ifdefined\font_preloads_at_every_job \else \let\font_preloads_at_every_job \relax \fi \ifdefined\font_preloads_at_start_text \else \let\font_preloads_at_start_text\relax \fi \ifdefined\font_preloads_at_stop_text \else \let\font_preloads_at_stop_text \relax \fi -\appendtoks \font_preloads_at_start_text \to \everystarttext -\appendtoks \font_preloads_at_stop_text \to \everystoptext +\appendtoks + \font_preloads_at_start_text +\to \everystarttext + +\appendtoks + \font_preloads_at_stop_text +\to \everystoptext + +\appendtoks + \showcontextbanner + \initializenewlinechar + \calculatecurrenttime + \loadsystemfiles + % \loadoptionfile % obsolete, but nice to keep as reference of when/how + \job_options_get_commandline % expands some commands + \job_options_get_ctxfile % might expand some commands + \job_options_set_filenames + \font_preloads_at_every_job + \settopskip % brrr + \initializemainlanguage + \initializexmlprocessing % is this still needed? + \initializepagebackgrounds + \initializepagecounters + % \directsetup{*runtime:options}% % obsolete as the option file is replaced by a more direct mechanism + % \directsetup{*runtime:modules}% % obsolete as the option file is replaced by a more direct mechanism + \job_options_set_modes + \job_options_set_modules + \job_options_set_environments +\to \everyjob -%prependtoks \preloadtypescript \to \everyjob -\appendtoks \showcontextbanner \to \everyjob -\appendtoks \initializenewlinechar \to \everyjob -\appendtoks \calculatecurrenttime \to \everyjob -\appendtoks \loadsystemfiles \to \everyjob -\appendtoks \loadoptionfile \to \everyjob % can load files ! -\appendtoks \font_preloads_at_every_job \to \everyjob -\appendtoks \settopskip \to \everyjob -\appendtoks \initializemainlanguage \to \everyjob -%appendtoks \MPLIBregister \to \everyjob -\appendtoks \xmlinitialize \to \everyjob -\appendtoks \setfalse\c_page_backgrounds_new \to \everyjob -\appendtoks \setfalse\c_page_backgrounds_some \to \everyjob -\appendtoks \initializepagecounters \to \everyjob -\appendtoks \directsetup{*runtime:options} \to \everyjob % we could erase them afterwards % order can change -\appendtoks \directsetup{*runtime:modules} \to \everyjob % we could erase them afterwards % order can change +\appendtoks + \job_options_log +\to \everystarttext -%appendtoks \page[\v!last] \page \to \everybye % moved to core-job, we need to do this cleaner -\appendtoks \ifarrangingpages\poparrangedpages\fi \to \everybye -%appendtoks \registerfileinfo[end]\jobfilename \to \everybye +\appendtoks + \ifarrangingpages\poparrangedpages\fi +\to \everybye -%appendtoks \MPLIBallocate{1000} \to \everydump +\prependtoks + \resetallattributes +\to \everybeforeoutput -\prependtoks \resetallattributes \to \everybeforeoutput +\appendtoks + \the\everybackendshipout +\to \everyshipout -\appendtoks \the\everybackendshipout \to \everyshipout -\prependtoks \the\everylastbackendshipout \to \everylastshipout +\prependtoks + \the\everylastbackendshipout +\to \everylastshipout -\prependtoks \lefttoright \to \everybeforeoutput +\prependtoks + \lefttoright +\to \everybeforeoutput % temporary here: @@ -88,4 +160,6 @@ % \resetcharacterspacing % \to \everyhyphenatedurl +% \setbreakpoints[compound] + \protect \endinput diff --git a/tex/context/base/core-env.lua b/tex/context/base/core-env.lua index c31df929e..8b9ae172b 100644 --- a/tex/context/base/core-env.lua +++ b/tex/context/base/core-env.lua @@ -37,7 +37,7 @@ setmetatableindex(tex.modes, function(t,k) if m then return m() else - local n = "mode" .. k + local n = "mode>" .. k if csname_id(n) == undefined then return false else @@ -52,7 +52,7 @@ setmetatableindex(tex.systemmodes, function(t,k) if m then return m() else - local n = "mode*" .. k + local n = "mode>*" .. k if csname_id(n) == undefined then return false else @@ -122,12 +122,15 @@ local types = { function tex.isdimen(name) return lookuptoken(name)[1] == dimencode end + function tex.iscount(name) return lookuptoken(name)[1] == countcode end + function tex.istoken(name) return lookuptoken(name)[1] == tokencode end + function tex.isskip(name) return lookuptoken(name)[1] == skipcode end diff --git a/tex/context/base/core-env.mkiv b/tex/context/base/core-env.mkiv index 1819d084d..38d3b1b29 100644 --- a/tex/context/base/core-env.mkiv +++ b/tex/context/base/core-env.mkiv @@ -54,42 +54,44 @@ % fast internal ones +\def\??mode{mode>} % special namespace, also used at lua end + \def\syst_modes_new#1% - {\expandafter\newcount\csname\s!mode#1\endcsname} + {\expandafter\newcount\csname\??mode#1\endcsname} \unexpanded\def\newmode#1% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi} + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi} \unexpanded\def\setmode#1% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \csname\s!mode#1\endcsname\enabledmode} + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \csname\??mode#1\endcsname\enabledmode} \unexpanded\def\resetmode#1% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \csname\s!mode#1\endcsname\disabledmode} + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \csname\??mode#1\endcsname\disabledmode} \unexpanded\def\newsystemmode#1% - {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi} + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi} \unexpanded\def\setsystemmode#1% - {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi - \csname\s!mode\systemmodeprefix#1\endcsname\enabledmode} + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi + \csname\??mode\systemmodeprefix#1\endcsname\enabledmode} \unexpanded\def\resetsystemmode#1% - {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi - \csname\s!mode\systemmodeprefix#1\endcsname\disabledmode} + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi + \csname\??mode\systemmodeprefix#1\endcsname\disabledmode} % \def\dosetsystemmode#1% -% {\csname\s!mode\systemmodeprefix#1\endcsname\enabledmode} +% {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode} % % \def\doresetsystemmode#1% -% {\csname\s!mode\systemmodeprefix#1\endcsname\disabledmode} +% {\csname\??mode\systemmodeprefix#1\endcsname\disabledmode} % demo: trialtypesetting is a systemmode as well as an if \newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end) -\expandafter\let\expandafter\@@trialtypesetting\csname\s!mode\systemmodeprefix trialtypesetting\endcsname % private ! +\expandafter\let\expandafter\@@trialtypesetting\csname\??mode\systemmodeprefix trialtypesetting\endcsname % private ! \appendtoks \@@trialtypesetting\enabledmode @@ -112,25 +114,25 @@ \def\syst_modes_disable[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_disable_indeed} \def\syst_modes_prevent_indeed#1% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \csname\s!mode#1\endcsname\preventedmode} + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \csname\??mode#1\endcsname\preventedmode} \def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \ifnum\csname\s!mode#1\endcsname=\preventedmode \else - \csname\s!mode#1\endcsname\enabledmode + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \ifnum\csname\??mode#1\endcsname=\preventedmode \else + \csname\??mode#1\endcsname\enabledmode \fi} \def\syst_modes_disable_indeed#1% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \ifnum\csname\s!mode#1\endcsname=\preventedmode \else - \csname\s!mode#1\endcsname\disabledmode + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \ifnum\csname\??mode#1\endcsname=\preventedmode \else + \csname\??mode#1\endcsname\disabledmode \fi} % handy for mp \def\booleanmodevalue#1% - {\ifcsname\s!mode#1\endcsname\ifcase\csname\s!mode#1\endcsname\s!false\else\s!true\fi\else\s!false\fi} + {\ifcsname\??mode#1\endcsname\ifcase\csname\??mode#1\endcsname\s!false\else\s!true\fi\else\s!false\fi} % check macros @@ -141,8 +143,8 @@ \newconditional\c_checked_mode \def\syst_modes_check_indeed#1% - {\ifcsname\s!mode#1\endcsname - \ifcase\csname\s!mode#1\endcsname\else + {\ifcsname\??mode#1\endcsname + \ifcase\csname\??mode#1\endcsname\else \let\syst_modes_check_step\gobbleoneargument \fi \fi} @@ -157,8 +159,8 @@ \fi} \def\syst_modes_check_all_indeed#1% - {\ifcsname\s!mode#1\endcsname - \ifcase\csname\s!mode#1\endcsname + {\ifcsname\??mode#1\endcsname + \ifcase\csname\??mode#1\endcsname \let\syst_modes_check_all_step\gobbleoneargument \fi \else @@ -198,25 +200,25 @@ %D Pushing/popping: \unexpanded\def\pushmode[#1]% - {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi - \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\s!mode#1\endcsname}% + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\??mode#1\endcsname}% \expandafter\pushmacro\csname\??modestack#1\endcsname} \unexpanded\def\popmode[#1]% {\ifcsname\??modestack#1\endcsname \expandafter\popmacro\csname\??modestack#1\endcsname - \csname\s!mode#1\endcsname\csname\??modestack#1\endcsname\relax + \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax \fi} \def\pushsystemmode#1% - {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi - \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\s!mode\systemmodeprefix#1\endcsname}% + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi + \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\??mode\systemmodeprefix#1\endcsname}% \expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname} \def\popsystemmode#1% {\ifcsname\??modestack\systemmodeprefix#1\endcsname \expandafter\popmacro\csname\??modestack\systemmodeprefix#1\endcsname - \csname\s!mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax + \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax \fi} %D Here is a relatively new variant of mode checking: @@ -625,4 +627,51 @@ \def\env {\getvariable \s!environment} \def\envvar {\getvariabledefault\s!environment} +%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} + +\unexpanded\def\defineselector{\dodoubleargument\syst_selectors_define} +\unexpanded\def\setupselector {\dodoubleargument\syst_selectors_setup} + +% \def\syst_selectors_define[#1][#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]} +% \def\syst_selectors_setup [#1][#2]{\getparameters[\??selector#1][#2]} + +\def\syst_selectors_define[#1][{\getparameters[\??selector#1][\c!max=\plustwo,\c!n=\plusone,} +\def\syst_selectors_setup [#1][{\getparameters[\??selector#1][} + +\unexpanded\def\select % unexpandable + {\directselect} + +% \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): + +\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 +\letvalue{\??selector\c!n }\plusone + \protect \endinput diff --git a/tex/context/base/core-fnt.mkiv b/tex/context/base/core-fnt.mkiv deleted file mode 100644 index 980f1a85c..000000000 --- a/tex/context/base/core-fnt.mkiv +++ /dev/null @@ -1,158 +0,0 @@ -%D \module -%D [ file=core-fnt, -%D version=1995.10.10, -%D title=\CONTEXT\ Core Macros, -%D subtitle=Fonts, -%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 / Fonts} - -\unprotect - -%D \macros -%D {compound} -%D -%D We will overload the already active \type {|} so we have -%D to save its meaning in order to be able to use this handy -%D macro. -%D -%D \starttyping -%D so test\compound{}test can be used instead of test||test -%D \stoptyping - -\bgroup \catcode\barasciicode\activecatcode \gdef\compound#1{|#1|} \egroup - -%D Here we hook some code into the clean up mechanism needed -%D for verbatim data. - -\appendtoks - \disablecompoundcharacters - \disablediscretionaries -\to \everycleanupfeatures - -%D The following code will me mkiv'd when needed. It's rather easy to -%D extend the kerner with glue. - -%D \macros -%D {stretched} -%D -%D Stretching characters in a word is a sort of typographical -%D murder. Nevertheless we support this manipulation for use in -%D for instance titles. -%D -%D \starttyping -%D \hbox to 5cm{\stretched{murder}} -%D \stoptyping -%D -%D \typebuffer -%D -%D or -%D -%D \startexample -%D \getbuffer -%D \stopexample -%D -%D \showsetup{stretched} - -\unexpanded\def\stretched#1% - {\ifvmode\hbox to \hsize\else\ifinner\else\hbox\fi\fi - \bgroup\processtokens\relax\hss\relax{\hss\hss}{#1}\egroup} - -%D \startbuffer -%D \stretched{Unknown Box} -%D \hbox to .5\hsize{\stretched{A Horizontal Box}} -%D \vbox to 2cm{\stretched{A Vertical Box}} -%D \hbox to 3cm{\stretched{sp{\'e}c{\`\i}{\"a}l}} -%D \stopbuffer -%D -%D \getbuffer -%D -%D The first line of this macros takes care of boxing. Normally -%D one will use an \type{\hbox} specification. The last line -%D shows how special characters should be passed. -%D -%D \typebuffer - -%D \macros -%D {stretchednormalcase, stretcheduppercase, stretchedlowercase} -%D -%D A convenient alternative is: -%D -%D \starttyping -%D \stretcheduppercase{Is this what you like?} -%D \stoptyping -%D -%D \typebuffer -%D -%D this one uses fixed skips and kerns. -%D -%D \startexample -%D \getbuffer -%D \stopexample -%D -%D The default skip can be set with: - -%D Given the following settings, the space is 1em by default: - -%D OBSOLETE: - -\def\stretchedspacefactor{4} -\def\stretchedspaceamount{.25em} -\def\stretchedbreaktokens{.@/} - -\unexpanded\def\stretchednormalcase - {\stretchedsomecase\firstofoneargument} - -\unexpanded\def\stretcheduppercase - {\stretchedsomecase{\the\everyuppercase\uppercase}} - -\unexpanded\def\stretchedlowercase - {\stretchedsomecase{\the\everylowercase\lowercase}} - -\def\stretchedsomecase#1#2% - {\bgroup - #1{\def\textstring{#2}}% - \ifdim\stretchedspaceamount=\zeropoint - \textstring - \else - \def\textkern##1% - {% beware: ##1 may not be \box\somebox -) - \determinemidwordbreak{##1}{\stretchedbreaktokens}% - \kern\stretchedspaceamount##1\domidwordbreak}% - \def\textskip - {\scratchdimen\stretchedspaceamount - \hskip\stretchedspacefactor\scratchdimen}% - \@EA\processtokens\@EA\relax\@EA\textkern\@EA\relax\@EA\textskip\@EA{\textstring}% - \fi - \egroup} - -%D An auxiliary macro, see for usage \type {\stretcheduppercase}. - -\let\domidwordbreak\relax - -\def\setmidwordbreaktoken#1% - {\sfcode`#1=5000\relax} - -\def\determinemidwordbreak#1#2% - {\edef\midwordbreaktokens{#2}% - \ifx\midwordbreaktokens\empty - \global\let\domidwordbreak\relax - \else - \setbox\scratchbox\hbox - {\expandafter\handletokens\midwordbreaktokens\with\setmidwordbreaktoken - a\space \!!dimena\lastskip - #1\space\!!dimenb\lastskip \relax % needed - \ifdim\!!dimena=\!!dimenb - \globallet\domidwordbreak\relax - \else - \globallet\domidwordbreak\allowbreak - \fi}% - \fi} - -\protect \endinput diff --git a/tex/context/base/core-ini.mkiv b/tex/context/base/core-ini.mkiv index de37bf08f..7b32cb3a2 100644 --- a/tex/context/base/core-ini.mkiv +++ b/tex/context/base/core-ini.mkiv @@ -13,67 +13,199 @@ \writestatus{loading}{ConTeXt Core Macros / Additional Initialization} -%D We will move more code to here, so that we become less dependent of the -%D orde in which modules are loaded. - \unprotect -\everypar \emptytoks -\neverypar \emptytoks +%D We introduce a couple of variables that are used all over \CONTEXT. Alternatively +%D we could define them in each module but as they are part of the bigger picture we +%D prefer to do it here. Ideally we should hav ea proper dependency tree but it might +%D be that we want to make versions with a smaller footprints in which case one would +%D still need to define the token list registers (unless we could do that runtime). -\appendtoks - %flushnotes - \page_otr_command_synchronize_side_floats % an otr specific command - \checkindentation - \showparagraphnumber - \restoreinterlinepenalty - %flushmargincontents - %flushcommentanchors - \flushnotes - \synchronizenotes - \OTRSETshowstatus - \flushpostponedbookmark - \registerparoptions - %\flushsyncpositions - \flushpostponednodedata - \typo_delimited_repeat - \insertparagraphintro -\to \everypar +%D \macros +%D {every...} +%D +%D A few every's. -\appendtoks - \flushpostponedbookmark -\to \neverypar +%D Output routine: -\appendtoks - \flushpostponedbookmark -\to \everylistentry +\newtoks \everybeforeoutput +\newtoks \everyafteroutput -\appendtoks - \flushnotes -\to \everydisplay +%D Shipout: + +\newtoks \everyshipout +\newtoks \everybeforeshipout +\newtoks \everyaftershipout +\newtoks \everyfirstshipout +\newtoks \everylastshipout + +%D End of run: + +\newtoks \everybye +\newtoks \everygoodbye +\newtoks \everynotabene + +%D Document: + +\newtoks \everysetupdocument +\newtoks \everyendoftextbody + +\newtoks \everystarttext +\newtoks \everystoptext + +%D Purity: + +\newtoks \everyforgetall +\newtoks \everycleanupfeatures +\newtoks \everysimplifycommands + +\let\simplifiedcommands\everysimplifycommands % backward compatible, will stay as it's used in styles + +\unexpanded\def\forgetall {\the\everyforgetall} +\unexpanded\def\cleanupfeatures {\the\everycleanupfeatures} +\unexpanded\def\simplifycommands{\the\everysimplifycommands} \appendtoks - \adjustsidefloatdisplaylines -\to \everydisplay + \everypar\emptytoks % pretty important +\to \everyforgetall + +%D Page building: + +\newtoks \everybeforepagebody +\newtoks \everyafterpagebody + +\let\everypagebody\everybeforepagebody % backward compatible, will become obsolete + +%D Floats: + +\newtoks \everyinsidefloat + +%D Sectioning: + +\newtoks \everyheadstart + +%D Par building (experimental, used in xml <p> .. </p>) + +\newtoks \everybeginofpar +\newtoks \everyendofpar +%newtoks \everyparflush + +\unexpanded\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar +\unexpanded\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar + +%D Lists: + +\newtoks \everylistentry +\newtoks \everysavesortkeys + +%D Marks: -% \appendtoks -% \flushsyncpositions -% \to \everyheadstart +\newtoks \everymarking -% \appendtoks -% \flushsyncresets -% \to \everyendoftextbody +%D Fonts: + +\newtoks \everyfont +\newtoks \everyglobalbodyfont +\newtoks \everydefinedfont + +\newevery \everybodyfont \EveryBodyFont +\newevery \everyfontswitch \EveryFontSwitch + +\newtoks \everysetupbodyfont +\newtoks \everyswitchtobodyfont + +%D Math: + +\newtoks \everybeforedisplayformula +\newtoks \everymathematics + +\prependtoks \the\everymathematics \to \everymath +\prependtoks \the\everymathematics \to \everydisplay + +%D Tables: + +\newtoks \everytable % we need to disstinguish kinds + +%D State mess: + +\newtoks \everypushsomestate +\newtoks \everypopsomestate + +\unexpanded\def\pushsomestates{\the\everypushsomestate} +\unexpanded\def\popsomestates {\the\everypopsomestate } + +%D More generic (used to be pushcolor etc) + +\newtoks\everystarttextproperties +\newtoks\everystoptextproperties + +\unexpanded\def\starttextproperties{\the\everystarttextproperties} +\unexpanded\def\stoptextproperties {\the\everystoptextproperties} + +%D \macros +%D {trialtypesetting} +%D +%D We disable trial typesetting in the output routine, +%D just to be sure. + +\prependtoks + \resettrialtypesetting +\to \everybeforepagebody + +%D \macros +%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided} +%D +%D These will become system modes and conditionals + +\newif \ifinpagebody +\newif \ifinsidecolumns +\newif \ifdoublesided \doublesidedfalse +\newif \ifsinglesided \singlesidedtrue +\newif \ifinsidefloat +\newif \ifdoingblocks +\newif \ifgridsnapping + +%D \macros +%D {ifproductionrun} +%D +%D This boolean can be used to bypass certain initializations. + +\newif\ifproductionrun \appendtoks - \ignorespaces -\to \everybeginofpar + \productionruntrue +\to \everydump + +%D \macros +%D {everyboxedcontent, ifboxedcontent, +%D startboxedcontent, stopboxedcontent} +%D +%D This one is relatively new and will be used as a more robust test for inner +%D situations. + +\newif \ifboxedcontent +\newtoks\everyboxedcontent \appendtoks - \removeunwantedspaces - %strut % option ? - % \flushsyncresets - %setlastlinewidth % gone, will be done in lua - \endgraf -\to \everyendofpar + \boxedcontenttrue +\to \everyboxedcontent + +\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent} + +\let\stopboxedcontent\egroup + +%D We store some original meanings, maybe in \type {math-ini}. + +\let\normalat \at +\let\normalin \in +\let\normalfrom \from +%let\normalover \over +\let\normalabout\about + +%D This will be implemented way later: + +\let\setlayoutcomponentattribute \gobbleoneargument +\let\resetlayoutcomponentattribute\relax +\let\layoutcomponentboxattribute \empty \protect \endinput diff --git a/tex/context/base/core-mis.mkiv b/tex/context/base/core-mis.mkiv deleted file mode 100644 index 5c364f3c4..000000000 --- a/tex/context/base/core-mis.mkiv +++ /dev/null @@ -1,738 +0,0 @@ -%D \module -%D [ file=core-mis, -%D version=1998.01.29, -%D title=\CONTEXT\ Core Macros, -%D subtitle=Miscelaneous, -%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 / Misc Commands} - -% needs to be redone - -\unprotect - -%D Sometimes (for instance in bookmarks) we need to simplify macro -%D behaviour, so here is the hook. - -\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi - -\def\simplifycommands{\the\simplifiedcommands} - -%D A possibly growing list: - -%appendtoks \def\executesynonym#1#2#3#4{#3}\to\simplifiedcommands -%appendtoks \def\executesort#1#2#3{#3}\to\simplifiedcommands - -\appendtoks \def\ { }\to\simplifiedcommands -\appendtoks \def\type#1{\letterbackslash\checkedstrippedcsname#1}\to\simplifiedcommands -\appendtoks \def\tex#1{\letterbackslash#1}\to\simplifiedcommands -\appendtoks \def\TeX{TeX}\to\simplifiedcommands -\appendtoks \def\ConTeXt{ConTeXt}\to\simplifiedcommands -\appendtoks \def\MetaPost{MetaPost}\to\simplifiedcommands -\appendtoks \def\MetaFont{MetaFont}\to\simplifiedcommands -\appendtoks \def\MetaFun{MetaFun}\to\simplifiedcommands -%appendtoks \def||{-}\to\simplifiedcommands -\appendtoks \def|#1|{\ifx#1\empty\empty-\else#1\fi}\to\simplifiedcommands - -\appendtoks\let\buildtextaccent\secondoftwoarguments\to\simplifiedcommands - -% THIS WAS MAIN-002.TEX - -\def\horitems#1#2% #1=breedte #2=commandos - {\scratchdimen#1% - \divide\scratchdimen \nofitems - \!!counta\zerocount - \def\docommand##1% - {\advance\!!counta \plusone - \processaction - [\@@isalign] - [ \v!left=>\hbox to \scratchdimen{\strut##1\hss}, - \v!right=>\hbox to \scratchdimen{\hss\strut##1}, - \v!middle=>\hbox to \scratchdimen{\hss\strut##1\hss}, - \v!margin=>\ifnum\!!counta=\plusone\hss\else\hfill\fi - \strut##1% - \ifnum\!!counta=\nofitems\hss\else\hfill\fi, - \s!default=>\hbox to \scratchdimen{\hss\strut##1\hss}, % midden - \s!unknown=>\hbox to \scratchdimen{\strut##1\hss}]}% % links - \hbox to #1{\hss#2\hss}} - -\def\veritems#1#2% #1=breedte #2=commandos - {\scratchdimen#1% - \def\docommand##1% - {\ifdim\scratchdimen<\zeropoint % the - was a signal - \hbox to -\scratchdimen{\hss\strut##1}% - \else\ifdim\scratchdimen>\zeropoint - \hbox to \scratchdimen{\strut##1\hss}% - \else - \hbox{\strut##1}% - \fi\fi}% - \vbox{#2}} - -\def\dosetupitems[#1]% - {\getparameters[\??is][#1]% - \doif\@@iswidth\v!unknown - {\def\@@iswidth{\hsize}}% - \doifconversiondefinedelse\@@issymbol - {\def\doitembullet##1{\convertnumber{\@@issymbol}{##1}}} - {\doifsymboldefinedelse\@@issymbol - {\def\doitembullet##1{\symbol[\@@issymbol]}}{}}} - -\def\makeitemsandbullets#1% - {\doifelse\@@isn\v!unknown - {\getcommalistsize[#1]% - \edef\nofitems{\commalistsize}} - {\edef\nofitems{\@@isn}}% - \setbox0\hbox - {\doitems \@@iswidth - {\processcommalist[#1]\docommand}}% - \setbox2\hbox - {\doitems \@@isbulletbreedte - {\dorecurse\nofitems - {\docommand{\strut\doitembullet\recurselevel}}}}} - -\def\dostartitems#1#2#3% - {\let\doitems#2% - \def\@@isbulletbreedte{#3}% - \makeitemsandbullets{#1}% - \@@isbefore} - -\def\dostopitems - {\@@isafter - \egroup} - -\setvalue{doitems\v!top}#1% - {\dostartitems{#1}\horitems\@@iswidth - \noindent\vbox - {\forgetall - \doifsomething\@@issymbol - {\doifnot\@@issymbol\v!none - {\box2 - \@@isinbetween - \nointerlineskip}}% - \box0}% - \dostopitems} - -\setvalue{doitems\v!bottom}#1% - {\dostartitems{#1}\horitems\@@iswidth - \noindent\vbox - {\forgetall - \box0 - \doifsomething\@@issymbol - {\@@isinbetween - \nointerlineskip - \box2}}% - \dostopitems} - -\setvalue{doitems\v!inmargin}#1% - {\dostartitems{#1}\veritems{-1.5em}% - is a signal - \noindent\hbox{\llap{\box2\hskip\leftmargindistance}\box0}% - \dostopitems} - -\setvalue{doitems\v!left}#1% - {\advance\hsize -1.5em% - \dostartitems{#1}\veritems{1.5em}% - \noindent\hbox{\box2\box0}% - \dostopitems} - -\setvalue{doitems\v!right}#1% - {\dostartitems{#1}\veritems{0em}% - \noindent\hbox{\box0\hskip-\wd2\box2}% - \dostopitems} - -\unexpanded\def\setupitems - {\dosingleargument\dosetupitems} - -\def\complexitems[#1]% - {\bgroup - \setupitems[#1]% - \parindent\zeropoint - \setlocalhsize - \hsize\localhsize - \dontcomplain - \executeifdefined{doitems\@@islocation}{\getvalue{doitems\v!left}}} - -\definecomplexorsimpleempty\items - -\setupitems - [\c!location=\v!left, - \c!symbol=5, - \c!width=\hsize, - \c!align=\v!middle, - \c!n=\v!unknown, - \c!before=\blank, - \c!inbetween={\blank[\v!medium]}, - \c!after=\blank] - -% there is quite some historic balast in this mechanism, the next variant -% is a first cleanup - -\let\currentparagraph\empty - -\newcount\alcounter \newcount\alnsize \newdimen\alhsize - -\def\paragraphparameter#1% \checkedparameter\??al\currentparagraph#1 - {\executeifdefined{\??al\currentparagraph#1}{\executeifdefined{\??al#1}\empty}} - -\def\paragraphcellmeter#1#2% \checkedparameter\??al\currentparagraph#1 - {\executeifdefined{\??al\currentparagraph\number#1#2}{\paragraphparameter{#2}}} - -\def\dodefineparagraphs[#1][#2]% - {\edef\currentparagraph{#1}% - \setvalue{\s!do\s!next\currentparagraph}% - {\def\\{\getvalue\currentparagraph}}% - \setvalue\currentparagraph - {\getvalue{\s!do\s!next#1}% - \dostartparagraphs{#1}}% - \setvalue{\e!next\currentparagraph}% - {\getvalue{#1}}% - \setvalue{\e!start\currentparagraph}% - {\bgroup - \edef\currentparagraph{#1}% - \letvalueempty{\s!do\s!next\currentparagraph}% - \setvalue{\e!stop\currentparagraph}{\getvalue\currentparagraph\egroup}% - \getvalue\currentparagraph}% - \getparameters[\??al\currentparagraph]% - [%\c!n=3, - %\c!before=\blank, - %\c!after=\blank, - %\c!distance=1em, - %\c!height=\v!fit, - %\c!rule=\v!off, - %\c!command=, - %\c!align=, - %\c!tolerance=\v!tolerant, - %\c!rulethickness=\linewidth, - %\c!rulecolor=, - %\c!style=, - %\c!color=, - %\c!top=, - %\c!top=\vss, - %\c!bottom=\vfill, - #2]% - \setvalue{\e!setup#1\e!endsetup}% - {\setupparagraphs[#1]}% - \dorecurse - {\paragraphparameter\c!n} - {\setupparagraphs - [\currentparagraph] - [\recurselevel] - [\c!width=, - %\c!bottom=\paragraphparameter\c!bottom, - %\c!top=\paragraphparameter\c!top, - %\c!height=\paragraphparameter\c!height, - %\c!rule=\paragraphparameter\c!rule, - %\c!rulethickness=\paragraphparameter\c!rulethickness, - %\c!rulecolor=\paragraphparameter\c!rulecolor, - %\c!align=\paragraphparameter\c!align, - %\c!tolerance=\paragraphparameter\c!tolerance, % obsolete - %\c!distance=\paragraphparameter\c!distance, - \c!style=\paragraphparameter\c!style, - \c!color=\paragraphparameter\c!color]}% - \setupparagraphs[\currentparagraph][1][\c!distance=\zeropoint]} - -\unexpanded\def\defineparagraphs - {\dodoubleargument\dodefineparagraphs} - -\def\dosetupparagraphs[#1][#2][#3]% - {\edef\currentparagraph{#1}% - \ifsecondargument - \doifelse{#2}\v!each - {\dorecurse - {\paragraphparameter\c!n} - {\getparameters[\??al\currentparagraph\recurselevel][#3]}} - {\doifelsenothing{#3} - {\getparameters[\??al\currentparagraph][#2]} - {\def\docommand##1{\getparameters[\??al\currentparagraph##1][#3]}% - \processcommalist[#2]\docommand}}% - \else - \getparameters[\??al][#1]% - \fi} - -\unexpanded\def\setupparagraphs - {\dotripleempty\dosetupparagraphs} - -\setupparagraphs - [\c!n=3, - \c!before=\blank, - \c!after=\blank, - \c!distance=1em, - \c!height=\v!fit, - \c!rule=\v!off, - \c!command=, - \c!align=, - \c!tolerance=\v!tolerant, % obsolete - \c!rulethickness=\linewidth, - \c!rulecolor=, - \c!style=, - \c!color=, - \c!top=, - \c!top=\vss, - \c!bottom=\vfill] - -\def\doparagraphrule - {\doifelse{\paragraphcellmeter\alcounter\c!rule}\v!on - {\linewidth\paragraphcellmeter\alcounter\c!rulethickness - \scratchdimen\dimexpr(\paragraphcellmeter\alcounter\c!distance-\linewidth)/2\relax - \hskip\scratchdimen - \color[\paragraphcellmeter\alcounter\c!rulecolor]{\vrule\!!width\linewidth}% - \hskip\scratchdimen} - {\hskip\paragraphcellmeter\alcounter\c!distance}} - -\def\dostartparagraph - {\doifelsenothing{\paragraphcellmeter\alcounter\c!width} - {\!!widtha\alhsize - \divide\!!widtha \alnsize} - {\!!widtha\paragraphcellmeter\alcounter\c!width}% - \begingroup - \dousestylehashparameter{\??al\currentparagraph\number\alcounter}\c!style - \dousecolorhashparameter{\??al\currentparagraph\number\alcounter}\c!color - \doifelse{\paragraphcellmeter\alcounter\c!height}\v!fit - {\setbox\scratchbox\vtop} - {\setbox\scratchbox\vtop to \paragraphcellmeter\alcounter\c!height}% - \bgroup - \blank[\v!disable]% - \forgetall - \paragraphcellmeter\alcounter\c!top - \paragraphparameter\c!inner - \hsize\!!widtha % setting \wd afterwards removed - \paragraphcellmeter\alcounter\c!inner % twice - \expanded{\setupalign [\paragraphcellmeter\alcounter\c!align ]}% {normal,verytolerant,stretch} - \expanded{\setuptolerance[\paragraphcellmeter\alcounter\c!tolerance]}% obsolete - \ignorespaces - \endgraf - \ignorespaces - % - % Nadeel van de onderstaande constructie is dat \everypar - % binnen een groep kan staan en zo steeds \begstruts - % worden geplaatst. Mooi is anders dus moet het anders! - % - % Hier is \Everypar niet nodig. - % - \everypar{\begstrut\everypar\emptytoks}% - % - \nospace % remove + ignore - \paragraphcellmeter\alcounter\c!command} - -\def\dostopparagraph - {\ifvmode - \removelastskip - \else - \unskip\endstrut\endgraf - \fi - \paragraphcellmeter\alcounter\c!bottom - \egroup - \ifdim\wd\scratchbox=\zeropoint % no data - \wd\scratchbox\!!widtha - \fi - \box\scratchbox - \endgroup - \ifnum\alcounter<\paragraphparameter\c!n\relax - \@EA\doparagraphcell - \else - \@EA\dostopparagraphs - \fi} - -\def\doparagraphcell - {\global\advance\alcounter \plusone - \doifelsenothing{\paragraphcellmeter\alcounter\c!distance} - {\ifnum\alcounter=\plusone\else - \hskip\paragraphparameter\c!distance - \fi} - {\ifnum\alcounter=\plusone - \hskip\paragraphcellmeter\alcounter\c!distance - \else - \doparagraphrule - \fi}% - \letvalue\currentparagraph\dostopparagraph - \dostartparagraph} - -\def\dostartparagraphs#1% - {\bgroup - \edef\currentparagraph{#1}% - \global\alcounter\zerocount - \parindent\zeropoint - \setlocalhsize - \alhsize\localhsize - \alnsize\paragraphparameter\c!n\relax - \dorecurse \alnsize - {\doifelsenothing{\paragraphcellmeter\recurselevel\c!distance} - {\ifnum\recurselevel=\plusone\else - \global\advance\alhsize -\paragraphparameter\c!distance - \fi} - {\global\advance\alhsize -\paragraphcellmeter\recurselevel\c!distance}% - \doifsomething{\paragraphcellmeter\recurselevel\c!width} - {\global\advance\alnsize \minusone - \global\advance\alhsize -\paragraphcellmeter\recurselevel\c!width}}% - %whitespace % gaat fout bij \framed - \paragraphparameter\c!before - \leavevmode % gaat wel goed bij \framed, brrr - \setbox\scratchbox\vbox\bgroup\hbox\bgroup\doparagraphcell} - -\def\dostopparagraphs - {\egroup - \egroup - \iftrue - \hbox{\raise\strutheight\box\scratchbox}% new - \else - \box\scratchbox % old - \fi - \par - \paragraphparameter\c!after - \egroup} - -% Is this used at all? - -\def\dosetuptab[#1]% - {\getparameters[\??ta] - [\c!headstyle=\v!normal, - \c!headcolor=, - \c!style=\v!normal, - \c!color=, - \c!width=\v!broad, - \c!sample={\hskip4em}, - \c!before=, - \c!after=, - #1]% - \definedescription - [tab] - [\c!headstyle=\@@taheadstyle, - \c!headcolor=\@@tacolor, - \c!sample=\@@tasample, - \c!width=\@@tawidth, - \c!before=\@@tabefore, - \c!after=\@@taafter]} - -\unexpanded\def\setuptab - {\dosingleargument\dosetuptab} - -\setuptab - [\c!location=\v!left] - -% seldom used, move from kernel to run time module - -\ifx\tfx\undefined \let\tfx\relax \fi - -\def\basegrid - {\dosingleempty\dobasegrid} - -\def\dobasegrid[#1]% - {\begingroup - \getparameters[\??rt] - [\c!x=0,\c!y=0, - \c!nx=10,\c!ny=10, - \c!dx=.5,\c!dy=.5, - \c!xstep=0,\c!ystep=0, - \c!unit=\s!cm, - \c!scale=1, - \c!factor=1, - \c!offset=\v!yes, - \c!location=\v!left, - #1]% - \startpositioning - \dimen0=\@@rtdx\@@rtunit\relax - \dimen0=\@@rtscale\dimen0\relax - \dimen0=\@@rtfactor\dimen0\relax - \multiply\dimen0 \@@rtnx\relax - \dimen2=\@@rtdy\@@rtunit\relax - \dimen2=\@@rtscale\dimen2\relax - \dimen2=\@@rtfactor\dimen2\relax - \multiply\dimen2 \@@rtny\relax - \def\horline - {\vbox - {\hrule - \!!width \dimen0 - \!!height \linewidth - \!!depth \!!zeropoint}}% - \def\verline% - {\vrule - \!!width \linewidth - \!!height \dimen2 - \!!depth \!!zeropoint}% - \doglobal\newcounter\@@gridc - \doglobal\newcounter\@@gridd - \doglobal\newcounter\@@gride - \def\setlegend##1##2##3% - {\gdef\@@gridc{0}% - \dimen0=2em\relax - \dimen2=##2\@@rtunit\relax - \dimen2=\@@rtscale\dimen2\relax - \dimen2=\@@rtfactor\dimen2\relax - \divide\dimen0 \dimen2\relax - \xdef\@@gride{\number\dimen0}% - \ifnum\@@gride>50 - \gdef\@@gride{100}% - \else\ifnum\@@gride>10 - \gdef\@@gride{50}% - \else\ifnum\@@gride>5 - \gdef\@@gride{10}% - \else\ifnum\@@gride>1 - \gdef\@@gride{5}% - \else - \gdef\@@gride{1}% - \fi\fi\fi\fi - \gdef\@@gridd{0}% - \def\legend - {\ifnum\@@gridd=\zerocount - \vbox - {\increment(\@@gridc,##1)% - \hbox to 2em{\hss\@@gridc\hss}}% - \global\let\@@gridd=\@@gride - \fi - \doglobal\decrement\@@gridd - \doglobal\increment(\@@gridc,##1)}}% - \def\draw##1##2##3##4##5##6##7##8##9% - {\setuppositioning - [\c!state=##8, - \c!xstep=\v!absolute, - \c!ystep=\v!absolute, - \c!unit=\@@rtunit, - \c!scale=\@@rtscale, - \c!factor=\@@rtfactor, - \c!offset=\@@rtoffset, - \c!xoffset=##6, - \c!yoffset=##7]% - \doifelse{##9}\v!middle - {\scratchdimen##3pt\scratchdimen.5\scratchdimen - \edef\@@psxx{\withoutpt\the\scratchdimen}% - \scratchdimen##4pt\scratchdimen.5\scratchdimen - \edef\@@psyy{\withoutpt\the\scratchdimen}% - \scratchcounter##2\advance\scratchcounter -1 - \edef\@@pszz{\the\scratchcounter}} - {\edef\@@psxx{0}\edef\@@psyy{0}\edef\@@pszz{##2}}% - \position(\@@psxx,\@@psyy){##1}% - \setuppositioning - [\c!state=##8, - \c!xstep=\v!relative, - \c!ystep=\v!relative, - \c!scale=\@@rtscale, - \c!factor=\@@rtfactor, - \c!offset=\@@rtoffset, - \c!unit=\@@rtunit]% - \dorecurse\@@pszz{\position(##3,##4){##5}}}% - \draw - \verline\@@rtnx\@@rtdx0\verline\!!zeropoint\!!zeropoint\v!start\empty - \draw - \horline\@@rtny0\@@rtdy\horline\!!zeropoint\!!zeropoint\v!start\empty - \tfx - \doifnot\@@rtxstep{0} - {\setlegend\@@rtxstep\@@rtdx\@@rtx - \draw\legend\@@rtnx\@@rtdx0\legend{-1em}{-1.5em}\v!overlay\@@rtlocation}% - \doifnot\@@rtystep{0} - {\setlegend\@@rtystep\@@rtdy\@@rty - \draw\legend\@@rtny0\@@rtdy\legend{-2em}{-.75ex}\v!overlay\@@rtlocation}% - \stoppositioning - \endgroup} - -\let\grid\basegrid - -\definetabulate - [\v!legend] - [|emj1|i1|mR|] - -\setuptabulate - [\v!legend] - [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}] - -\definetabulate - [\v!legend][\v!two] - [|emj1|emk1|i1|mR|] - -\definetabulate - [\v!fact] - [|R|ecmj1|i1mR|] - -\setuptabulate - [\v!fact] - [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}] - -\unexpanded\def\xbox - {\bgroup\aftergroup\egroup\hbox\bgroup\tx\let\next=} - -\unexpanded\def\xxbox - {\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=} - -%D This one is for Daniel Pittman, who wanted tight fractions. We show -%D three versions. First the simple one using \type {\low} and \type {high}: -%D -%D \startbuffer -%D \def\vfrac#1#2% -%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}} -%D -%D test \vfrac{1}{2} test \vfrac{123}{456} test -%D \stopbuffer -%D -%D \typebuffer {\showmakeup\getbuffer} -%D -%D A better way to handle the kerning is the following, here -%D we kind of assume that tye slash is symmetrical and has -%D nearly zero width. -%D -%D \startbuffer -%D \def\vfract#1#2% -%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}} -%D \stopbuffer -%D -%D \typebuffer {\showmakeup\getbuffer} -%D -%D The third and best alternative is the following: -%D -%D {\showmakeup\getbuffer}\crlf\getbuffer -%D -%D This time we measure the height of the \type {/} and -%D shift over the maximum height and depths of this -%D character and the fractional digits (we use 57 as -%D sample). Here we combine all methods in one macros. - -\setnewconstant\vulgarfractionmethod\plusthree - -\definehspace[vulgarfraction][.25em] % [.15em] -\definesymbol[vulgarfraction][/] % [\raise.2ex\hbox{/}] - -\unexpanded\def\vulgarfraction#1#2% - {\dontleavehmode - \hbox - {\def\vulgarfraction{vulgarfraction}% - \ifcase\vulgarfractionmethod - #1\symbol[\vulgarfraction]#2% - \or - \high{\tx#1\kern-\hspaceamount\empty\vulgarfraction}% - \symbol[\vulgarfraction]% - \low {\kern-\hspaceamount\empty\vulgarfraction\tx#2}% - \or - \high{\tx#1}% - \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}% - \low{\tx#2}% - \or - \setbox0\hbox{\symbol[\vulgarfraction]}% - \setbox2\hbox{\txx57}% - \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}% - \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}% - \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}% - \fi}} - -\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi - -%D \starttabulate -%D \HL -%D \NC \bf method \NC \bf visualization \NC\NR -%D \HL -%D \NC 0 \NC \vulgarfractionmethod0 \vulgarfraction{1}{2} \NC\NR -%D \NC 1 \NC \vulgarfractionmethod1 \vulgarfraction{1}{2} \NC\NR -%D \NC 2 \NC \vulgarfractionmethod2 \vulgarfraction{1}{2} \NC\NR -%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR -%D \HL -%D \stoptabulate - -%D Under construction: -%D -%D \starttyping -%D \commalistsentence[aap,noot,mies] -%D \commalistsentence[aap,noot] -%D \commalistsentence[aap] -%D \commalistsentence[a,b,c] -%D \commalistsentence[a,b,c][{ \& },{ and }] -%D \commalistsentence[a,b,c][+,-] -%D \stoptyping - -% obsolete .. use lua instead - -\let\handlecommalistsentence\firstofoneargument - -\def\commalistsentenceone{and-1} -\def\commalistsentencetwo{and-2} - -\def\commalistsentence - {\dodoubleempty\docommalistsentence} - -\def\docommalistsentence[#1][#2]% - {\bgroup - \getfromcommalist[#2][1]% - \ifx\commalistelement\empty - \def\@@commalistsentenceone{\labeltext\commalistsentenceone}% - \else - \let\@@commalistsentenceone\commalistelement - \fi - \getfromcommalist[#2][2]% - \ifx\commalistelement\empty - \def\@@commalistsentencetwo{\labeltext\commalistsentencetwo}% - \else - \let\@@commalistsentencetwo\commalistelement - \fi - \getcommalistsize[#1]% - \ifcase\commalistsize\relax - \def\serializedcommalist{#1}% - \else - \let\serializedcommalist\empty - \scratchcounter\zerocount - \def\docommand##1% - {\advance\scratchcounter \plusone - \ifnum\scratchcounter=\plusone - \scratchtoks{\handlecommalistsentence{##1}}% - \else - \ifnum\scratchcounter=\commalistsize - \appendtoks\@@commalistsentencetwo\handlecommalistsentence{##1}\to\scratchtoks - \else - \appendtoks\@@commalistsentenceone\handlecommalistsentence{##1}\to\scratchtoks - \fi - \fi}% - \processcommacommand[#1]\docommand - \edef\serializedcommalist{\the\scratchtoks}% - \fi - \serializedcommalist - \egroup} - -\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]} - -\setuplabeltext [\s!nl] [and-1={,} , and-2= en ] % 1, 2 en 3 -\setuplabeltext [\s!en] [and-1={,} , and-2={,} ] % 1, 2, 3 -\setuplabeltext [\s!de] [and-1={,} , and-2= und ] % 1, 2 und 3 -\setuplabeltext [\s!hr] [and-1={,} , and-2= i ] % 1, 2 i 3 - -%D \macros -%D {somekindoftab} -%D -%D This macro can be used to create tabs: -%D -%D \starttyping -%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\realfolio}}}] -%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\realfolio}}}] -%D -%D \starttext -%D \showframe \dorecurse{10}{test\page} -%D \stoptext -%D \stoptyping - -\def\somekindoftab - {\dosingleempty\dosomekindoftab} - -\def\dosomekindoftab[#1]% - {\bgroup - \getparameters[xx] - [\c!alternative=\v!vertical, - \c!width=\textwidth,\c!height=\textheight, - \c!n=\lastpage,\c!m=\realpageno, - #1]% - \doifelse\xxalternative\v!vertical - {\dodosomekindoftab\vbox\vskip\xxheight} - {\dodosomekindoftab\hbox\hskip\xxwidth }} - -\def\dodosomekindoftab#1#2#3#4% - {#1 to #3 \bgroup - \forgetall - \ifnum\xxm>\plusone - #2\zeropoint \!!plus \the\numexpr\xxm -1\relax fill\relax - \fi - #4% - \ifnum\xxm<\xxn\relax - #2\zeropoint \!!plus \the\numexpr\xxn-\xxm\relax fill\relax - \fi - \egroup - \egroup} - -\protect \endinput diff --git a/tex/context/base/core-sys.lua b/tex/context/base/core-sys.lua index 0be9fd588..e25c9b8f1 100644 --- a/tex/context/base/core-sys.lua +++ b/tex/context/base/core-sys.lua @@ -6,21 +6,93 @@ if not modules then modules = { } end modules ['core-sys'] = { license = "see context related readme files" } -local lower, format = string.lower, string.format -local extname, basename, removesuffix = file.extname, file.basename, file.removesuffix +local lower, format, gsub = string.lower, string.format, string.gsub +local suffixonly, basename, removesuffix = file.suffix, file.basename, file.removesuffix local environment = environment -function commands.updatefilenames(inputfilename,outputfilename) - environment.inputfilename = inputfilename or "" - environment.outputfilename = outputfilename or "" - environment.jobfilename = inputfilename or tex.jobname or "" - environment.jobfilesuffix = lower(extname(environment.jobfilename)) +local report_files = logs.reporter("system","files") + +-- function commands.updatefilenames(jobname,fulljobname,inputfilename,outputfilename) +-- -- +-- environment.jobname = jobname +-- -- +-- local jobfilename = gsub(fulljobname or jobname or inputfilename or tex.jobname or "","%./","") +-- -- +-- environment.jobfilename = jobfilename +-- environment.jobfilesuffix = lower(suffixonly(environment.jobfilename)) +-- -- +-- local inputfilename = gsub(inputfilename or "","%./","") +-- environment.inputfilename = inputfilename +-- environment.inputfilebarename = removesuffix(basename(inputfilename)) +-- -- +-- local inputfilerealsuffix = suffixonly(inputfilename) +-- environment.inputfilerealsuffix = inputfilerealsuffix +-- -- +-- local inputfilesuffix = inputfilerealsuffix == "" and "tex" or lower(inputfilerealsuffix) +-- environment.inputfilesuffix = inputfilesuffix +-- -- +-- local outputfilename = outputfilename or environment.inputfilebarename or "" +-- environment.outputfilename = outputfilename +-- -- +-- local runpath = resolvers.cleanpath(lfs.currentdir()) +-- environment.runpath = runpath +-- -- +-- statistics.register("running on path", function() +-- return environment.runpath +-- end) +-- -- +-- statistics.register("job file properties", function() +-- return format("jobname: %s, input: %s, suffix: %s",jobfilename,inputfilename,inputfilesuffix) +-- end) +-- -- +-- end + +function environment.initializefilenames() -- commands.updatefilenames(jobname,fulljobname,input,result) + + local arguments = environment.arguments + + local jobname = arguments.jobname or tex.jobname + local fulljobname = arguments.fulljobname or jobname + local inputfilename = arguments.input or fulljobname + local outputfilename = arguments.result or removesuffix(jobname) + + local inputfilename = suffixonly(inputfilename) == "tex" and removesuffix(inputfilename) or inputfilename or "" + + local filename = fulljobname + local suffix = suffixonly(filename) + + local filename = ctxrunner.resolve(filename) -- in case we're prepped + + local jobfilename = jobname or inputfilename or tex.jobname or "" + local inputfilename = inputfilename or "" + + jobfilename = gsub(jobfilename, "^./","") + inputfilename = gsub(inputfilename,"^./","") + + environment.jobfilename = jobfilename + environment.jobfilesuffix = lower(suffixonly(jobfilename)) + + environment.inputfilename = inputfilename environment.inputfilebarename = removesuffix(basename(inputfilename)) - environment.inputfilesuffix = lower(extname(inputfilename)) + environment.inputfilesuffix = lower(suffixonly(inputfilename)) + + environment.outputfilename = outputfilename or environment.inputfilebarename or "" + + environment.filename = filename + environment.suffix = suffix + + report_files("jobname: %s, input: %s, result: %s",jobfilename,inputfilename,outputfilename) + + function environment.initializefilenames() end end statistics.register("result saved in file", function() -- suffix will be fetched from backend - return format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi") + local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "<unset>" + if tex.pdfoutput > 0 then + return format( "%s.%s, compresslevel %s, objectcompreslevel %s",outputfilename,"pdf",tex.pdfcompresslevel, tex.pdfobjcompresslevel) + else + return format( "%s.%s",outputfilename,"dvi") -- hard to imagine + end end) diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv index 66f2a4380..249500e0a 100644 --- a/tex/context/base/core-sys.mkiv +++ b/tex/context/base/core-sys.mkiv @@ -36,21 +36,31 @@ %D line ending. I hate this mess. \edef\operatingsystem {\cldcontext{os.platform}} -\def \jobfilename {\cldcontext{environment.jobfilename or ""}} -\def \jobfilesuffix {\cldcontext{environment.jobfilesuffix or ""}} -\def \inputfilebarename{\cldcontext{environment.inputfilebarename or ""}} -\def \inputfilesuffix {\cldcontext{environment.inputfilesuffix or ""}} -\def \inputfilename {\cldcontext{environment.inputfilename or ""}} -\def \outputfilename {\cldcontext{environment.outputfilename or ""}} + +%D The jobname is what gets loaded by the cont-yes stub file. This name +%D also determines the name of tuc etc files. + +\def \jobfilename {\cldcontext{environment.jobfilename or ""}} +\def \jobfilesuffix {\cldcontext{environment.jobfilesuffix or ""}} + +%D However, that one can itself load another file. + +\def \inputfilebarename {\cldcontext{environment.inputfilebarename or ""}} +\def \inputfilerealsuffix{\cldcontext{environment.inputfilerealsuffix or ""}} +\def \inputfilesuffix {\cldcontext{environment.inputfilesuffix or ""}} +\def \inputfilename {\cldcontext{environment.inputfilename or ""}} + +%D The output name is only used for some checking. + +\def \outputfilename {\cldcontext{environment.outputfilename or ""}} \installcorenamespace{system} \installdirectcommandhandler \??system {system} \appendtoks - \edef\outputresolution{\directsystemparameter\c!resolution}% - \edef\outputfilename {\directsystemparameter\c!file }% - \edef\inputfilename {\directsystemparameter\c!inputfile }% +% \edef\outputfilename {\directsystemparameter\c!file }% +% \edef\inputfilename {\directsystemparameter\c!inputfile }% \to \everysetupsystem \appendtoks @@ -75,9 +85,9 @@ \setsystemmode{suffix-\m_system_job_suffix}% \to \everysetupsystem -\appendtoks - \ctxcommand{updatefilenames("\inputfilename","\outputfilename")}% -\to \everysetupsystem +% \appendtoks +% \ctxcommand{updatefilenames("\jobame","\inputfilename","\outputfilename")}% +% \to \everysetupsystem % Some mechanisms (see x-res-01) use either \jobfilename or % \jobfilename.somesuffix, in which case we need to use the @@ -104,6 +114,10 @@ %D \NC \type{\operatingsystem} \NC \operatingsystem \NC \NR %D \stoptabulate +\appendtoks + \edef\outputresolution{\directsystemparameter\c!resolution}% +\to \everysetupsystem + %D The system modes set by the setup command can be used in %D situations like: %D @@ -138,9 +152,9 @@ [\c!directory=, \c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run \c!resolution=600,% in dpi, no unit in mkiv - %c!random=, % obsolete here - \c!file=\jobname, - \c!inputfile=\outputfilename, + % \c!random=, % obsolete here + % \c!file=\jobname, + % \c!inputfile=\outputfilename, \c!type=unix, % windows is normally less sensitive to handle \c!bodyfont=\normalizedlocalbodyfontsize] % of iets anders @@ -150,14 +164,34 @@ %D But anyway, in \MKIV\ we avoid most of the complications anyway as we %D deal with much at the \LUA\ end. -\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}} -\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup} - -\let\simplestart\bgroup -\let\simplestop \egroup - -\definecomplexorsimple\start -\definecomplexorsimple\stop +\unexpanded\def\start + {\dosingleempty\syst_start} + +\def\syst_start + {\bgroup + \iffirstargument + \expandafter\syst_start_yes + \else + \expandafter\syst_start_nop + \fi} + +\def\syst_start_yes[#1]% + {\edef\m_syst_start_stop{#1}% + \ifx\m_syst_start_stop\empty + \let\syst_stop_indeed\donothing + \else\ifcsname\e!start\m_syst_start_stop\endcsname + \let\expandafter\syst_stop_indeed\csname\e!stop\m_syst_start_stop\endcsname + \csname\e!start\currentstartstop\expandafter\expandafter\expandafter\endcsname + \else + \let\syst_stop_indeed\donothing + \fi\fi} + +\def\syst_start_nop[#1]% + {\let\syst_stop_indeed\donothing} + +\unexpanded\def\stop + {\syst_stop_indeed + \egroup} % \c!before \c!after \c!inbetween \c!commands \c!style \c!color diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua index f94b102bc..d6e006e04 100644 --- a/tex/context/base/core-two.lua +++ b/tex/context/base/core-two.lua @@ -153,5 +153,5 @@ commands.savetwopassdata = jobpasses.save commands.savetaggedtwopassdata = jobpasses.savetagged function commands.doifelseintwopassdata(id,str) - commands.testcase(inlist(id,str)) + commands.doifelse(inlist(id,str)) end diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index 1657a75e2..141f20cd3 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -20,6 +20,7 @@ saves much runtime but at the cost of more memory usage.</p> local format, match = string.format, string.match local next, type, tostring = next, type, tostring local concat = table.concat +local texcount = tex.count local definetable = utilities.tables.definetable local accesstable = utilities.tables.accesstable @@ -29,7 +30,7 @@ local packers = utilities.packers local allocate = utilities.storage.allocate local mark = utilities.storage.mark -local report_jobcontrol = logs.reporter("jobcontrol") +local report_passes = logs.reporter("job","passes") job = job or { } local job = job @@ -146,9 +147,7 @@ function job.save(filename) -- we could return a table but it can get pretty lar for c=1,#comment do f:write("-- ",comment[c],"\n") end - f:write("\n") - f:write("local utilitydata = { }\n") - f:write("\n") + f:write("\nlocal utilitydata = { }\n\n") for l=1,#savelist do local list = savelist[l] local target = format("utilitydata.%s",list[1]) @@ -160,16 +159,13 @@ function job.save(filename) -- we could return a table but it can get pretty lar if job.pack then packers.pack(data,jobpacker,true) end - f:write(definetable(target),"\n") - f:write(serialize(data,target,true,true),"\n") + f:write(definetable(target),"\n",serialize(data,target,true,true),"\n") end if job.pack then packers.strip(jobpacker) f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n") end - f:write("\n") - f:write("return utilitydata\n") - f:write("\n") + f:write("\nreturn utilitydata\n\n") f:close() end statistics.stoptiming(_save_) @@ -180,7 +176,7 @@ local function load(filename) if data and data ~= "" then local version = tonumber(match(data,"^-- version: ([%d%.]+)")) if version ~= job.version then - report_jobcontrol("version mismatch with jobfile: %s <> %s", version or "?", job.version) + report_passes("version mismatch: %s <> %s", version or "?", job.version) else local data = loadstring(data) return data and data() @@ -252,7 +248,7 @@ end) statistics.register("callbacks", function() local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0 - local pages = tex.count['realpageno'] - 1 + local pages = texcount['realpageno'] - 1 if pages > 1 then return format("direct: %s, indirect: %s, total: %s (%i per page)", total-indirect, indirect, total, total/pages) else @@ -268,8 +264,8 @@ end) function statistics.formatruntime(runtime) if not environment.initex then -- else error when testing as not counters yet - local shipped = tex.count['nofshipouts'] - local pages = tex.count['realpageno'] - 1 + local shipped = texcount['nofshipouts'] + local pages = texcount['realpageno'] - 1 if shipped > 0 or pages > 0 then local persecond = shipped / runtime if pages == 0 then pages = shipped end diff --git a/tex/context/base/core-var.mkiv b/tex/context/base/core-var.mkiv deleted file mode 100644 index 26559f246..000000000 --- a/tex/context/base/core-var.mkiv +++ /dev/null @@ -1,239 +0,0 @@ -%D \module -%D [ file=core-var, -%D version=1998.02.21, -%D title=\CONTEXT\ Core Macros, -%D subtitle=Variables, -%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 / Variables} - -\unprotect - -%D Much of this will move to *-ini files. - -%D We introduce a couple of variables that are used all over -%D \CONTEXT. Alternatively we could define them in each module -%D but as they are part of the bigger picture we prefer to do -%D it here. - -%D \macros -%D {every...} -%D -%D A few every's. Some are only used in \MKII\ or \MKIV. - -%D Output routine: - -\newtoks \everybeforeoutput -\newtoks \everyafteroutput - -%D Shipout: - -\newtoks \everyshipout -\newtoks \everybeforeshipout -\newtoks \everyaftershipout -\newtoks \everyfirstshipout -\newtoks \everylastshipout - -%D End of run: - -\newtoks \everybye -\newtoks \everygoodbye -\newtoks \everynotabene - -%D Document - -\newtoks \everysetupdocument -\newtoks \everyendoftextbody - -\newtoks \everystarttext -\newtoks \everystoptext - -%D Purity: - -\newtoks \everyforgetall -\newtoks \everycleanupfeatures - -\def\cleanupfeatures{\the\everycleanupfeatures} -\def\forgetall {\the\everyforgetall} - -%D Page building: - -\newtoks \everybeforepagebody -\newtoks \everyafterpagebody - -\let \everypagebody \everybeforepagebody % backward compatible, will become obsolete - -%D Floats: - -\newtoks \everyinsidefloat - -%D Sectioning: - -\newtoks \everyheadstart - -%D Par building (experimental, used in xml <p> .. </p>) - -\newtoks \everybeginofpar -\newtoks \everyendofpar -%newtoks \everyparflush - -\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\the\everybeginofpar\ignorespaces} % may interfere with \everypar -\unexpanded\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi\dostoptagged } % test prevents problems with \bpar\epar - -%D Lists: - -\newtoks \everylistentry -\newtoks \everysavesortkeys - -%D Marks: - -\newtoks \everymarking - -%D Fonts: - -\newtoks \everyfont -\newtoks \everyglobalbodyfont -\newtoks \everydefinedfont - -\newevery \everybodyfont \EveryBodyFont -\newevery \everyfontswitch \EveryFontSwitch - -\newtoks \everysetupbodyfont -\newtoks \everyswitchtobodyfont - -%D Math: - -\newtoks \everybeforedisplayformula -\newtoks \everymathematics - -\prependtoks \the\everymathematics \to \everymath -\prependtoks \the\everymathematics \to \everydisplay - -%D Tables - -\newtoks \everytable - -%D State mess: - -\newtoks \everypushsomestate -\newtoks \everypopsomestate - -\def\pushsomestates{\the\everypushsomestate} -\def\popsomestates {\the\everypopsomestate } - -%D More generic (used to be pushcolor etc) - -\newtoks\everystarttextproperties -\newtoks\everystoptextproperties - -\unexpanded\def\starttextproperties{\the\everystarttextproperties} -\unexpanded\def\stoptextproperties {\the\everystoptextproperties} - -%D \macros -%D {trialtypesetting} -%D -%D We disable trial typesetting in the output routine, -%D just to be sure. - -\prependtoks \resettrialtypesetting \to \everybeforepagebody - -%D \macros -%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided} - -\newif \ifinpagebody -\newif \ifinsidecolumns -\newif \ifdoublesided \doublesidedfalse -\newif \ifsinglesided \singlesidedtrue -\newif \ifinsidefloat -\newif \ifdoingblocks -\newif \ifgridsnapping - -%D \macros -%D {ifprocessingXML} -%D -%D We need this one even if no \XML\ is supported. - -% \newif\ifprocessingXML % old way - -%D \macros -%D {ifproductionrun} -%D -%D This boolean can be used to bypass certain -%D initializations. - -\newif\ifproductionrun \appendtoks \productionruntrue \to \everydump - -%D \macros -%D {everyboxedcontent, ifboxedcontent, -%D startboxedcontent, stopboxedcontent} -%D -%D This one is relatively new and will be used as a more -%D robust test for inner situations. - -\newif \ifboxedcontent -\newtoks\everyboxedcontent - -\appendtoks \boxedcontenttrue \to \everyboxedcontent - -\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent} -\let\stopboxedcontent \egroup - -%D \macros -%D {fastmode,silentmode} -%D -%D These commands are obsolete. - -\let\fastmode \relax -\let\silentmode\relax - -%D \macros -%D {defineselector,setupselector} -%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 - -\unexpanded\def\defineselector{\dodoubleargument\dodefineselector} -\unexpanded\def\setupselector {\dodoubleargument\dosetupselector} - -\def\dodefineselector[#1][#2]{\getparameters[\??sx#1][\c!max=2,\c!n=1,#2]} -\def\dosetupselector [#1][#2]{\getparameters[\??sx#1][#2]} - -\unexpanded\def\select#1% - {\filterfromnext - {\executeifdefined{\??sx#1\c!max}1} - {\executeifdefined{\??sx#1\c!n }1}} - -%D We store some original meanings, maybe in \type -%D {math-ini}. - -\let\normalat \at -\let\normalin \in -\let\normalfrom \from -%let\normalover \over -\let\normalabout\about - -%D Add-ons: - -\let\setlayoutcomponentattribute \gobbleoneargument -\let\resetlayoutcomponentattribute\relax -\let\layoutcomponentboxattribute \empty - -\protect \endinput diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua index 2d9787b91..f016881b5 100644 --- a/tex/context/base/data-env.lua +++ b/tex/context/base/data-env.lua @@ -12,7 +12,7 @@ local resolvers = resolvers local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex -local fileextname = file.extname +local suffixonly = file.suffixonly local formats = allocate() local suffixes = allocate() @@ -268,7 +268,7 @@ function resolvers.formatofvariable(str) end function resolvers.formatofsuffix(str) -- of file - return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc) + return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc) end function resolvers.variableofformat(str) @@ -280,7 +280,7 @@ function resolvers.variableofformatorsuffix(str) if v then return v end - v = suffixmap[fileextname(str)] + v = suffixmap[suffixonly(str)] if v then return formats[v] end diff --git a/tex/context/base/data-exp.lua b/tex/context/base/data-exp.lua index 66bbb56cb..550b61689 100644 --- a/tex/context/base/data-exp.lua +++ b/tex/context/base/data-exp.lua @@ -114,12 +114,14 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi for s in gmatch(str,"[^,]+") do s = validate(s) if s then - n = n + 1 ; t[n] = s + n = n + 1 + t[n] = s end end else for s in gmatch(str,"[^,]+") do - n = n + 1 ; t[n] = s + n = n + 1 + t[n] = s end end if trace_expansions then @@ -133,7 +135,7 @@ end -- We could make the previous one public. local function validate(s) - s = collapsepath(s) -- already keeps the // + s = collapsepath(s) -- already keeps the trailing / and // return s ~= "" and not find(s,"^!*unset/*$") and s end diff --git a/tex/context/base/data-ini.lua b/tex/context/base/data-ini.lua index 2c263aada..773490785 100644 --- a/tex/context/base/data-ini.lua +++ b/tex/context/base/data-ini.lua @@ -10,7 +10,7 @@ local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string local concat = table.concat local next, type = next, type -local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join +local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end) diff --git a/tex/context/base/data-lua.lua b/tex/context/base/data-lua.lua index 906a611ee..fec5856ea 100644 --- a/tex/context/base/data-lua.lua +++ b/tex/context/base/data-lua.lua @@ -6,167 +6,196 @@ if not modules then modules = { } end modules ['data-lua'] = { license = "see context related readme files" } --- some loading stuff ... we might move this one to slot 2 depending --- on the developments (the loaders must not trigger kpse); we could --- of course use a more extensive lib path spec +-- We overload the regular loader. We do so because we operate mostly in +-- tds and use our own loader code. Alternatively we could use a more +-- extensive definition of package.path and package.cpath but even then +-- we're not done. Also, we now have better tracing. +-- +-- -- local mylib = require("libtest") +-- -- local mysql = require("luasql.mysql") -local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) +local concat = table.concat + +local trace_libraries = false + +trackers.register("resolvers.libraries", function(v) trace_libraries = v end) +trackers.register("resolvers.locating", function(v) trace_libraries = v end) local report_libraries = logs.reporter("resolvers","libraries") local gsub, insert = string.gsub, table.insert +local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match local unpack = unpack or table.unpack +local is_readable = file.is_readable local resolvers, package = resolvers, package -local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs' -local clibformats = { 'lib' } +local libsuffixes = { 'tex', 'lua' } +local clibsuffixes = { 'lib' } +local libformats = { 'TEXINPUTS', 'LUAINPUTS' } +local clibformats = { 'CLUAINPUTS' } + +local libpaths = nil +local clibpaths = nil +local libhash = { } +local clibhash = { } +local libextras = { } +local clibextras = { } -local _path_, libpaths, _cpath_, clibpaths +local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0) -function package.libpaths() - if not _path_ or package.path ~= _path_ then - _path_ = package.path - libpaths = file.splitpath(_path_,";") +local function cleanpath(path) --hm, don't we have a helper for this? + return resolvers.resolve(lpegmatch(pattern,path)) +end + +local function getlibpaths() + if not libpaths then + libpaths = { } + for i=1,#libformats do + local paths = resolvers.expandedpathlistfromvariable(libformats[i]) + for i=1,#paths do + local path = cleanpath(paths[i]) + if not libhash[path] then + libpaths[#libpaths+1] = path + libhash[path] = true + end + end + end end return libpaths end -function package.clibpaths() - if not _cpath_ or package.cpath ~= _cpath_ then - _cpath_ = package.cpath - clibpaths = file.splitpath(_cpath_,";") +local function getclibpaths() + if not clibpaths then + clibpaths = { } + for i=1,#clibformats do + local paths = resolvers.expandedpathlistfromvariable(clibformats[i]) + for i=1,#paths do + local path = cleanpath(paths[i]) + if not clibhash[path] then + clibpaths[#clibpaths+1] = path + clibhash[path] = true + end + end + end end return clibpaths end -local function thepath(...) - local t = { ... } t[#t+1] = "?.lua" - local path = file.join(unpack(t)) - if trace_locating then - report_libraries("! appending '%s' to 'package.path'",path) +package.libpaths = getlibpaths +package.clibpaths = getclibpaths + +function package.extralibpath(...) + local paths = { ... } + for i=1,#paths do + local path = cleanpath(paths[i]) + if not libhash[path] then + if trace_libraries then + report_libraries("! extra lua path '%s'",path) + end + libextras[#libextras+1] = path + libpaths[#libpaths +1] = path + end end - return path end -local p_libpaths, a_libpaths = { }, { } - -function package.appendtolibpath(...) - insert(a_libpath,thepath(...)) +function package.extraclibpath(...) + local paths = { ... } + for i=1,#paths do + local path = cleanpath(paths[i]) + if not clibhash[path] then + if trace_libraries then + report_libraries("! extra lib path '%s'",path) + end + clibextras[#clibextras+1] = path + clibpaths[#clibpaths +1] = path + end + end end -function package.prependtolibpath(...) - insert(p_libpaths,1,thepath(...)) +if not package.loaders[-2] then + -- use package-path and package-cpath + package.loaders[-2] = package.loaders[2] end --- beware, we need to return a loadfile result ! +local function loadedaslib(resolved,rawname) + return package.loadlib(resolved,"luaopen_" .. gsub(rawname,"%.","_")) +end -local function loaded(libpaths,name,simple) - for i=1,#libpaths do -- package.path, might become option - local libpath = libpaths[i] - local resolved = gsub(libpath,"%?",simple) - if trace_locating then -- more detail - report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved) - end - if file.is_readable(resolved) then - if trace_locating then - report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved) - end - return loadfile(resolved) - end +local function loadedbylua(name) + if trace_libraries then + report_libraries("! locating %q using normal loader",name) end + local resolved = package.loaders[-2](name) end -package.loaders[2] = function(name) -- was [#package.loaders+1] - if file.suffix(name) == "" then - name = file.addsuffix(name,"lua") -- maybe a list - if trace_locating then -- mode detail - report_libraries("! locating '%s' with forced suffix",name) - end - else - if trace_locating then -- mode detail - report_libraries("! locating '%s'",name) - end +local function loadedbyformat(name,rawname,suffixes,islib) + if trace_libraries then + report_libraries("! locating %q as %q using formats %q",rawname,name,concat(suffixes)) end - for i=1,#libformats do - local format = libformats[i] + for i=1,#suffixes do -- so we use findfile and not a lookup loop + local format = suffixes[i] local resolved = resolvers.findfile(name,format) or "" - if trace_locating then -- mode detail - report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format) + if trace_libraries then + report_libraries("! checking for %q' using format %q",name,format) end if resolved ~= "" then - if trace_locating then - report_libraries("! lib '%s' located via environment: '%s'",name,resolved) + if trace_libraries then + report_libraries("! lib %q located on %q",name,resolved) end - return loadfile(resolved) - end - end - -- libpaths - local libpaths, clibpaths = package.libpaths(), package.clibpaths() - local simple = gsub(name,"%.lua$","") - local simple = gsub(simple,"%.","/") - local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple) - if resolved then - return resolved - end - -- - local libname = file.addsuffix(simple,os.libsuffix) - for i=1,#clibformats do - -- better have a dedicated loop - local format = clibformats[i] - local paths = resolvers.expandedpathlistfromvariable(format) - for p=1,#paths do - local path = paths[p] - local resolved = file.join(path,libname) - if trace_locating then -- mode detail - report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path) - end - if file.is_readable(resolved) then - if trace_locating then - report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved) - end - return package.loadlib(resolved,name) + if islib then + return loadedaslib(resolved,rawname) + else + return loadfile(resolved) end end end - for i=1,#clibpaths do -- package.path, might become option - local libpath = clibpaths[i] - local resolved = gsub(libpath,"?",simple) - if trace_locating then -- more detail - report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath) +end + +local function loadedbypath(name,rawname,paths,islib,what) + if trace_libraries then + report_libraries("! locating %q as %q on %q paths",rawname,name,what) + end + for p=1,#paths do + local path = paths[p] + local resolved = file.join(path,name) + if trace_libraries then -- mode detail + report_libraries("! checking for %q using %q path %q",name,what,path) end - if file.is_readable(resolved) then - if trace_locating then - report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved) + if is_readable(resolved) then + if trace_libraries then + report_libraries("! lib %q located on %q",name,resolved) + end + if islib then + return loadedaslib(resolved,rawname) + else + return loadfile(resolved) end - return package.loadlib(resolved,name) - end - end - -- just in case the distribution is messed up - if trace_loading then -- more detail - report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name) - end - local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or "" - if resolved ~= "" then - if trace_locating then - report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved) end - return loadfile(resolved) end - if trace_locating then - report_libraries('? unable to locate lib: %s',name) - end --- return "unable to locate " .. name end -resolvers.loadlualib = require - --- -- -- -- +local function notloaded(name) + if trace_libraries then + report_libraries("? unable to locate library %q",name) + end +end -package.obsolete = package.obsolete or { } +package.loaders[2] = function(name) + local thename = gsub(name,"%.","/") + local luaname = file.addsuffix(thename,"lua") + local libname = file.addsuffix(thename,os.libsuffix) + return + loadedbyformat(luaname,name,libsuffixes, false) + or loadedbyformat(libname,name,clibsuffixes, true) + or loadedbypath (luaname,name,getlibpaths (),false,"lua") + or loadedbypath (luaname,name,getclibpaths(),false,"lua") + or loadedbypath (libname,name,getclibpaths(),true, "lib") + or loadedbylua (name) + or notloaded (name) +end -package.append_libpath = appendtolibpath -- will become obsolete -package.prepend_libpath = prependtolibpath -- will become obsolete +-- package.loaders[3] = nil +-- package.loaders[4] = nil -package.obsolete.append_libpath = appendtolibpath -- will become obsolete -package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete +resolvers.loadlualib = require diff --git a/tex/context/base/data-pre.lua b/tex/context/base/data-pre.lua index 5b25c5f87..40b430bf2 100644 --- a/tex/context/base/data-pre.lua +++ b/tex/context/base/data-pre.lua @@ -23,6 +23,8 @@ local gsub = string.gsub local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion local getenv = resolvers.getenv -- we can probably also use resolvers.expansion local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match +local joinpath, basename, dirname = file.join, file.basename, file.dirname +local getmetatable, rawset, type = getmetatable, rawset, type -- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on) @@ -64,28 +66,43 @@ end prefixes.filename = function(str) local fullname = findgivenfile(str) or "" - return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here + return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here end prefixes.pathname = function(str) local fullname = findgivenfile(str) or "" - return cleanpath(file.dirname((fullname ~= "" and fullname) or str)) + return cleanpath(dirname((fullname ~= "" and fullname) or str)) end prefixes.selfautoloc = function(str) - return cleanpath(file.join(getenv('SELFAUTOLOC'),str)) + return cleanpath(joinpath(getenv('SELFAUTOLOC'),str)) end prefixes.selfautoparent = function(str) - return cleanpath(file.join(getenv('SELFAUTOPARENT'),str)) + return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str)) end prefixes.selfautodir = function(str) - return cleanpath(file.join(getenv('SELFAUTODIR'),str)) + return cleanpath(joinpath(getenv('SELFAUTODIR'),str)) end prefixes.home = function(str) - return cleanpath(file.join(getenv('HOME'),str)) + return cleanpath(joinpath(getenv('HOME'),str)) +end + +local function toppath() + local pathname = dirname(inputstack[#inputstack] or "") + if pathname == "" then + return "." + else + return pathname + end +end + +resolvers.toppath = toppath + +prefixes.toppath = function(str) + return cleanpath(joinpath(toppath(),str)) end prefixes.env = prefixes.environment @@ -121,6 +138,8 @@ function resolvers.resetresolve(str) resolved, abstract = { }, { } end +-- todo: use an lpeg (see data-lua for !! / stripper) + local function resolve(str) -- use schemes, this one is then for the commandline only if type(str) == "table" then local t = { } @@ -146,7 +165,7 @@ end resolvers.resolve = resolve resolvers.unresolve = unresolve -if os.uname then +if type(os.uname) == "function" then for k, v in next, os.uname() do if not prefixes[k] then @@ -158,11 +177,17 @@ end if os.type == "unix" then + -- We need to distringuish between a prefix and something else : so we + -- have a special repath variant for linux. Also, when a new prefix is + -- defined, we need to remake the matcher. + local pattern local function makepattern(t,k,v) + if t then + rawset(t,k,v) + end local colon = P(":") - local p for k, v in table.sortedpairs(prefixes) do if p then p = P(k) + p @@ -171,9 +196,6 @@ if os.type == "unix" then end end pattern = Cs((p * colon + colon/";" + P(1))^0) - if t then - t[k] = v - end end makepattern() diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua index 7206c0d78..9236cbe02 100644 --- a/tex/context/base/data-res.lua +++ b/tex/context/base/data-res.lua @@ -24,11 +24,12 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns local filedirname = file.dirname local filebasename = file.basename -local fileextname = file.extname +local suffixonly = file.suffixonly local filejoin = file.join local collapsepath = file.collapsepath local joinpath = file.joinpath local allocate = utilities.storage.allocate +local settings_to_array = utilities.parsers.settings_to_array local setmetatableindex = table.setmetatableindex local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) @@ -52,7 +53,7 @@ resolvers.cacheversion = '1.0.1' resolvers.configbanner = '' resolvers.homedir = environment.homedir resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" } -resolvers.luacnfname = 'texmfcnf.lua' +resolvers.luacnfname = "texmfcnf.lua" resolvers.luacnfstate = "unknown" -- The web2c tex binaries as well as kpse have built in paths for the configuration @@ -332,7 +333,7 @@ end local function identify_configuration_files() local specification = instance.specification if #specification == 0 then - local cnfspec = getenv('TEXMFCNF') + local cnfspec = getenv("TEXMFCNF") if cnfspec == "" then cnfspec = resolvers.luacnfspec resolvers.luacnfstate = "default" @@ -420,7 +421,7 @@ local function load_configuration_files() -- we push the value into the main environment (osenv) so -- that it takes precedence over the default one and therefore -- also over following definitions - resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes + resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes -- we now identify and load the specified configuration files instance.specification = { } identify_configuration_files() @@ -468,10 +469,11 @@ end local function locate_file_databases() -- todo: cache:// and tree:// (runtime) - local texmfpaths = resolvers.expandedpathlist('TEXMF') + local texmfpaths = resolvers.expandedpathlist("TEXMF") if #texmfpaths > 0 then for i=1,#texmfpaths do local path = collapsepath(texmfpaths[i]) + path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing / local stripped = lpegmatch(inhibitstripper,path) -- the !! thing if stripped ~= "" then local runtime = stripped == path @@ -600,9 +602,9 @@ function resolvers.prependhash(type,name,cache) end function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash - local t = resolvers.splitpath(getenv('TEXMF')) + local t = resolvers.splitpath(getenv("TEXMF")) -- okay? insert(t,1,specification) - local newspec = concat(t,";") + local newspec = concat(t,",") -- not ; if instance.environment["TEXMF"] then instance.environment["TEXMF"] = newspec elseif instance.variables["TEXMF"] then @@ -677,14 +679,19 @@ function resolvers.resetextrapath() end function resolvers.registerextrapath(paths,subpaths) + paths = settings_to_array(paths) + subpaths = settings_to_array(subpaths) local ep = instance.extra_paths or { } local oldn = #ep local newn = oldn - if paths and paths ~= "" then - if subpaths and subpaths ~= "" then - for p in gmatch(paths,"[^,]+") do - -- we gmatch each step again, not that fast, but used seldom - for s in gmatch(subpaths,"[^,]+") do + local nofpaths = #paths + local nofsubpaths = #subpaths + if nofpaths > 0 then + if nofsubpaths > 0 then + for i=1,nofpaths do + local p = paths[i] + for j=1,nofsubpaths do + local s = subpaths[j] local ps = p .. "/" .. s if not done[ps] then newn = newn + 1 @@ -694,7 +701,8 @@ function resolvers.registerextrapath(paths,subpaths) end end else - for p in gmatch(paths,"[^,]+") do + for i=1,nofpaths do + local p = paths[i] if not done[p] then newn = newn + 1 ep[newn] = resolvers.cleanpath(p) @@ -702,10 +710,10 @@ function resolvers.registerextrapath(paths,subpaths) end end end - elseif subpaths and subpaths ~= "" then + elseif nofsubpaths > 0 then for i=1,oldn do - -- we gmatch each step again, not that fast, but used seldom - for s in gmatch(subpaths,"[^,]+") do + for j=1,nofsubpaths do + local s = subpaths[j] local ps = ep[i] .. "/" .. s if not done[ps] then newn = newn + 1 @@ -783,18 +791,21 @@ function resolvers.expandedpathlist(str) return { } elseif instance.savelists then str = lpegmatch(dollarstripper,str) - if not instance.lists[str] then -- cached - local lst = made_list(instance,resolvers.splitpath(resolvers.expansion(str))) - instance.lists[str] = expandedpathfromlist(lst) - end - return instance.lists[str] + local lists = instance.lists + local lst = lists[str] + if not lst then + local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str))) + lst = expandedpathfromlist(l) + lists[str] = lst + end + return lst else local lst = resolvers.splitpath(resolvers.expansion(str)) return made_list(instance,expandedpathfromlist(lst)) end end -function resolvers.expandedpathlistfromvariable(str) -- brrr +function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ // str = lpegmatch(dollarstripper,str) local tmp = resolvers.variableofformatorsuffix(str) return resolvers.expandedpathlist(tmp ~= "" and tmp or str) @@ -951,7 +962,7 @@ local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$")) local collect_instance_files local function find_analyze(filename,askedformat,allresults) - local filetype, wantedfiles, ext = '', { }, fileextname(filename) + local filetype, wantedfiles, ext = '', { }, suffixonly(filename) -- too tricky as filename can be bla.1.2.3: -- -- if not suffixmap[ext] then @@ -1029,7 +1040,7 @@ local function find_qualified(filename,allresults) -- this one will be split too if trace_detail then report_resolving("locating qualified file '%s'", filename) end - local forcedname, suffix = "", fileextname(filename) + local forcedname, suffix = "", suffixonly(filename) if suffix == "" then -- why local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat] if format_suffixes then diff --git a/tex/context/base/data-sch.lua b/tex/context/base/data-sch.lua index 253adb9f6..569fa5c94 100644 --- a/tex/context/base/data-sch.lua +++ b/tex/context/base/data-sch.lua @@ -6,26 +6,26 @@ if not modules then modules = { } end modules ['data-sch'] = { license = "see context related readme files" } -local http = require("socket.http") -local ltn12 = require("ltn12") +local loadstring = loadstring local gsub, concat, format = string.gsub, table.concat, string.format local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders -local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end) - +local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end) local report_schemes = logs.reporter("resolvers","schemes") -local resolvers = resolvers +local http = require("socket.http") +local ltn12 = require("ltn12") -resolvers.schemes = resolvers.schemes or { } -local schemes = resolvers.schemes -schemes.threshold = 24 * 60 * 60 +local resolvers = resolvers +local schemes = resolvers.schemes or { } +resolvers.schemes = schemes -directives.register("schemes.threshold", function(v) schemes.threshold = tonumber(v) or schemes.threshold end) +local cleaners = { } +schemes.cleaners = cleaners -local cleaners = { } +local threshold = 24 * 60 * 60 -schemes.cleaners = cleaners +directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end) function cleaners.none(specification) return specification.original @@ -53,7 +53,7 @@ end local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { } -local function runcurl(name,cachename) -- will use sockets instead or the curl library +local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name os.spawn(command) end @@ -65,8 +65,7 @@ local function fetch(specification) local cachename = caches.setfirstwritablefile(cleanname,"schemes") if not cached[original] then statistics.starttiming(schemes) - if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > - (thresholds[protocol] or schemes.threshold)) then + if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then cached[original] = cachename local handler = handlers[scheme] if handler then @@ -112,14 +111,14 @@ end local opener = openers.file local loader = loaders.file -local function install(scheme,handler,threshold) +local function install(scheme,handler,newthreshold) handlers [scheme] = handler loaded [scheme] = 0 reused [scheme] = 0 finders [scheme] = finder openers [scheme] = opener loaders [scheme] = loader - thresholds[scheme] = threshold or schemes.threshold + thresholds[scheme] = newthreshold or threshold end schemes.install = install @@ -160,11 +159,42 @@ statistics.register("scheme handling time", function() end local n = nl + nr if n > 0 then - l = (nl > 0 and concat(l)) or "none" - r = (nr > 0 and concat(r)) or "none" + l = nl > 0 and concat(l) or "none" + r = nr > 0 and concat(r) or "none" return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s", - statistics.elapsedtime(schemes), n, schemes.threshold, l, r) + statistics.elapsedtime(schemes), n, threshold, l, r) else return nil end end) + +-- We provide a few more helpers: + +----- http = require("socket.http") +local httprequest = http.request +local toquery = url.toquery + +-- local function httprequest(url) +-- return os.resultof(format("curl --silent %q", url)) +-- end + +local function fetchstring(url,data) + local q = data and toquery(data) + if q then + url = url .. "?" .. q + end + local reply = httprequest(url) + return reply -- just one argument +end + +schemes.fetchstring = fetchstring + +function schemes.fetchtable(url,data) + local reply = fetchstring(url,data) + if reply then + local s = loadstring("return " .. reply) + if s then + return s() + end + end +end diff --git a/tex/context/base/data-tex.lua b/tex/context/base/data-tex.lua index 6cb361699..2105f29f4 100644 --- a/tex/context/base/data-tex.lua +++ b/tex/context/base/data-tex.lua @@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['data-tex'] = { } local char = string.char +local insert, remove = table.insert, table.remove local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) @@ -51,6 +52,10 @@ appendgroup(textlineactions,"after" ) -- user local ctrl_d = char( 4) -- unix local ctrl_z = char(26) -- windows +resolvers.inputstack = resolvers.inputstack or { } + +local inputstack = resolvers.inputstack + function helpers.textopener(tag,filename,filehandle,coding) local lines local t_filehandle = type(filehandle) @@ -92,6 +97,7 @@ function helpers.textopener(tag,filename,filehandle,coding) lines[noflines] = nil end logs.show_open(filename) + insert(inputstack,filename) return { filename = filename, noflines = noflines, @@ -101,6 +107,7 @@ function helpers.textopener(tag,filename,filehandle,coding) report_tex("%s closer, '%s' closed",tag,filename) end logs.show_close(filename) + remove(inputstack) t = nil end, reader = function(self) diff --git a/tex/context/base/data-vir.lua b/tex/context/base/data-vir.lua index 89359c19a..dff780fc7 100644 --- a/tex/context/base/data-vir.lua +++ b/tex/context/base/data-vir.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['data-vir'] = { license = "see context related readme files" } -local format = string.format +local format, validstrings = string.format, string.valid local trace_virtual = false local report_virtual = logs.reporter("resolvers","virtual") @@ -18,7 +18,9 @@ local resolvers = resolvers local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers -local data, n, template = { }, 0, "virtual://%s.%s" -- hm, number can be query +local data = { } +local n = 0 -- hm, number can be query +local template = "virtual://%s.%s" function savers.virtual(specification,content) n = n + 1 -- one number for all namespaces @@ -54,7 +56,7 @@ function openers.virtual(specification) if trace_virtual then report_virtual("opener, file '%s' opened",original) end - data[original] = nil + data[original] = nil -- when we comment this we can have error messages -- With utf-8 we signal that no regime is to be applied! return openers.helpers.textopener("virtual",original,d,"utf-8") else diff --git a/tex/context/base/data-zip.lua b/tex/context/base/data-zip.lua index 676a2df96..7e8ea3a39 100644 --- a/tex/context/base/data-zip.lua +++ b/tex/context/base/data-zip.lua @@ -14,11 +14,17 @@ local trace_locating = false trackers.register("resolvers.locating", function(v local report_zip = logs.reporter("resolvers","zip") --- zip:///oeps.zip?name=bla/bla.tex --- zip:///oeps.zip?tree=tex/texmf-local --- zip:///texmf.zip?tree=/tex/texmf --- zip:///texmf.zip?tree=/tex/texmf-local --- zip:///texmf-mine.zip?tree=/tex/texmf-projects +--[[ldx-- +<p>We use a url syntax for accessing the zip file itself and file in it:</p> + +<typing> +zip:///oeps.zip?name=bla/bla.tex +zip:///oeps.zip?tree=tex/texmf-local +zip:///texmf.zip?tree=/tex/texmf +zip:///texmf.zip?tree=/tex/texmf-local +zip:///texmf-mine.zip?tree=/tex/texmf-projects +</typing> +--ldx]]-- local resolvers = resolvers diff --git a/tex/context/base/enco-ini.mkiv b/tex/context/base/enco-ini.mkiv index a942d5110..3b0cbc9fc 100644 --- a/tex/context/base/enco-ini.mkiv +++ b/tex/context/base/enco-ini.mkiv @@ -43,22 +43,32 @@ %D \macros %D {defineaccent, definecharacter, definecommand} -\unexpanded\def\dodefineaccentcommand#1% - {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}} - -\unexpanded\def\dodefineaccent#1#2#3% no spaces, used low level - {\setvalue{\??ac\string#1\string#2\empty}{#3}} +\installcorenamespace{accents} \unexpanded\def\defineaccent#1 #2 #3 % - {\dodefineaccentcommand{#1}% - \dodefineaccent{#1}{#2}{#3}} - -\def\dohandleaccent#1#2% - {\ifcsname\??ac\string#1#2\empty\endcsname - \csname\??ac\string#1#2\empty\endcsname - \else\ifcsname\??ac\string#1\string#2\empty\endcsname - \csname\??ac\string#1\string#2\empty\endcsname - \fi\fi} + {\enco_define_accent_command{#1}% + \enco_define_accent{#1}{#2}{#3}} + +\unexpanded\def\enco_define_accent_command#1% + {\setevalue{\string#1}{\noexpand\enco_handle_accent{\string#1}}} + +\unexpanded\def\enco_define_accent#1#2#3% no spaces, used low level + {\setvalue{\??accents\string#1\string#2\empty}{#3}} + +\def\enco_handle_accent#1#2% expandable because we want them in the tuc file + {\csname\??accents + \ifcsname\??accents\string#1#2\empty\endcsname + \string#1#2\empty + \else\ifcsname\??accents\string#1\string#2\empty\endcsname + \string#1\string#2\empty + \else + \empty + \fi\fi + \endcsname} + +\let\dohandleaccent \enco_handle_accent % maybe useful +\let\dodefineaccent \enco_define_accent % used at the lua end +\let\dodefineaccentcommand\enco_define_accent_command % used at the lua end \unexpanded\def\definecharacter#1 #2 % {\doifnumberelse{\string#2} @@ -77,15 +87,15 @@ %D Accent handling (try to avoid this): -\newbox\accenttestbox % no longer global so we could use \scratchbox +\newbox\b_enco_accent \def\buildmathaccent#1% {\mathaccent#1 } \unexpanded\def\buildtextaccent#1#2% we could do all at the lua end {\begingroup % but that's no fun (yet) - \setbox\accenttestbox\hbox{#1}% - \scratchcounter\cldcontext{nodes.firstcharinbox(\number\accenttestbox)}\relax + \setbox\b_enco_accent\hbox{#1}% + \scratchcounter\cldcontext{nodes.firstcharinbox(\number\b_enco_accent)}\relax \ifcase\scratchcounter\else\accent\scratchcounter\fi \relax#2% \endgroup} @@ -105,7 +115,7 @@ \hidewidth \hskip#2\wd0 \hskip-#3\slantperpoint % in plain 1ex * dimenless value - \vbox to .2ex{\box0\vss}\hidewidth + \vbox to .2\exheight{\box0\vss}\hidewidth \crcr}}} \unexpanded\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}} @@ -128,7 +138,8 @@ \egroup \egroup} -\def\buildtextgrave{\topaccent{0pt}{0}{15}{\textgrave}} % e.g. +\unexpanded\def\buildtextgrave + {\topaccent{0pt}{0}{15}{\textgrave}} % e.g. \unexpanded\def\definemathaccent#1 #2% {\setvalue{#1}{\mathaccent#2 }} @@ -224,7 +235,7 @@ % left-overs (some day in private unicode space, so that we can roundtrip) -\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\!!width.3\s!em\!!height.4\s!em\!!depth-.1\s!em}} +\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\schwagrave {\buildtextgrave\schwa} @@ -244,28 +255,28 @@ \let\textvisiblespace\normalcontrolspace \unexpanded\def\fastcontrolspace % no glyph resolving after first (use grouped) - {\dofastcontrolspace} + {\enco_fast_control_space} -\def\dofastcontrolspace +\def\enco_fast_control_space {\iffontchar\font\textcontrolspace - \nofastfallbackcontrolspace + \enco_fast_control_space_nop \else - \dofastfallbackcontrolspace + \enco_fast_control_space_yes \fi - \dofastcontrolspace} + \enco_fast_control_space} -\newbox\controlspacebox +\newbox\b_enco_control_space -\def\nofastfallbackcontrolspace - {\let\dofastcontrolspace\textcontrolspace} +\def\enco_fast_control_space_nop + {\let\enco_fast_control_space\textcontrolspace} -\def\dofastfallbackcontrolspace - {\setbox\controlspacebox\hbox{\space}% - \setbox\controlspacebox\hbox to \wd\controlspacebox{\hss\fallbackcontrolspace\hss}% - \let\dofastcontrolspace\flushcontrolspacebox} +\def\enco_fast_control_space_yes + {\setbox\b_enco_control_space\hbox{\space}% + \setbox\b_enco_control_space\hbox to \wd\b_enco_control_space{\hss\fallbackcontrolspace\hss}% + \let\enco_fast_control_space\flushcontrolspacebox} \def\flushcontrolspacebox - {\copy\controlspacebox} + {\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 @@ -289,39 +300,39 @@ % from enco-mis: -\def\fakepercent - {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25em/\kern-.2em\normalsubscript{\scriptscriptstyle0}}} +\unexpanded\def\fakepercent + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}} -\def\fakeperthousand - {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25em/\kern-.2em\normalsubscript{\scriptscriptstyle00}}} +\unexpanded\def\fakeperthousand + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}} -\def\fakepermine +\unexpanded\def\fakepermine {\dontleavehmode \bgroup \setbox\scratchbox\hbox {\mathematics{+}}% \hbox to \wd\scratchbox {\hss - \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4em/\kern-.3em\normalsubscript{\scriptscriptstyle-}}% + \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}% \hss}% \egroup} %D A smaller and bolder variant, more like the math and monospaced ones. -\def\fakeunderscore +\unexpanded\def\fakeunderscore {\relax\ifmmode - \vrule\!!depth .12\fontexheight\mathstylefont\normalmathstyle\!!width \fontinterwordspace\mathstylefont\normalmathstyle\!!height\zeropoint\relax + \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax \else - \dontleavehmode\hbox{\vrule\!!depth .12\fontexheight\font\!!width \fontinterwordspace\font\!!height\zeropoint}% + \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}% \fi} -\def\fakeunderscores{\let\_\fakeunderscore} -\def\textunderscores{\let\_\textunderscore} +\unexpanded\def\fakeunderscores{\let\_\fakeunderscore} +\unexpanded\def\textunderscores{\let\_\textunderscore} \textunderscores -\ifx\mathunderscore\undefined \let\mathunderscore\fakeunderscore \fi -\ifx\textunderscore\undefined \let\textunderscore\fakeunderscore \fi +\ifdefined\mathunderscore \else \let\mathunderscore\fakeunderscore \fi +\ifdefined\textunderscore \else \let\textunderscore\fakeunderscore \fi \unexpanded\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi} @@ -349,7 +360,7 @@ \def\periodsdefault{3} % was 5, but now it's like \unknown \unexpanded\def\periods - {\dosingleempty\doperiods} + {\dosingleempty\enco_periods} % \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2 % {\dontleavehmode @@ -361,7 +372,7 @@ % % better for export: -\unexpanded\def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2 +\unexpanded\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2 {\dontleavehmode \hbox\bgroup \setbox\scratchbox\hbox to \periodswidth{\hss.\hss}% @@ -377,4 +388,8 @@ % % Hello\fourdots\ World\fourdots \par Hello\fourdots\ World. +\appendtoks + \let\buildtextaccent\secondoftwoarguments +\to \everysimplifycommands + \protect \endinput diff --git a/tex/context/base/file-ini.lua b/tex/context/base/file-ini.lua index 4f8b5b6e3..1872ed3d3 100644 --- a/tex/context/base/file-ini.lua +++ b/tex/context/base/file-ini.lua @@ -7,9 +7,8 @@ if not modules then modules = { } end modules ['file-ini'] = { } --[[ldx-- -<p>It's more convenient to manipulate filenames (paths) in -<l n='lua'/> than in <l n='tex'/>. These methods have counterparts -at the <l n='tex'/> side.</p> +<p>It's more convenient to manipulate filenames (paths) in <l n='lua'/> than in +<l n='tex'/>. These methods have counterparts at the <l n='tex'/> end.</p> --ldx]]-- resolvers.jobs = resolvers.jobs or { } diff --git a/tex/context/base/file-ini.mkvi b/tex/context/base/file-ini.mkvi index b0f6244aa..989241dd1 100644 --- a/tex/context/base/file-ini.mkvi +++ b/tex/context/base/file-ini.mkvi @@ -73,15 +73,17 @@ %D \popendofline %D \stoptyping +\installsystemnamespace{eolstack} + \newcount\c_system_files_eol_level \unexpanded\def\pushendofline {\advance\c_system_files_eol_level\plusone - \expandafter\chardef\csname\??fi:eol:\number\c_system_files_eol_level\endcsname\catcode\endoflineasciicode + \expandafter\chardef\csname\??eolstack\number\c_system_files_eol_level\endcsname\catcode\endoflineasciicode \catcode\endoflineasciicode\commentcatcode} \unexpanded\def\popendofline - {\catcode\endoflineasciicode\csname\??fi:eol:\number\c_system_files_eol_level\endcsname + {\catcode\endoflineasciicode\csname\??eolstack\number\c_system_files_eol_level\endcsname \advance\c_system_files_eol_level\minusone} \unexpanded\def\restoreendofline @@ -101,11 +103,11 @@ \the\everystartreadingfile \pushcatcodetable % saveguard \setcatcodetable\ctxcatcodes - \ctxlua{regimes.push()}}% temporarily this way + \ctxcommand{pushregime()}}% temporarily this way \unexpanded\def\stopreadingfile {\popcatcodetable % saveguard - \ctxlua{regimes.pop()}% temporarily this way + \ctxcommand{popregime()}% temporarily this way \the\everystopreadingfile \global\advance\readingfilelevel\minusone} @@ -203,11 +205,13 @@ %D This command obeys the standard method for locating files. We could %D move this function to the \LUA\ end. +\installsystemnamespace {fileonce} + \unexpanded\def\doonlyonce#whatever% - {\ifcsname\??fi:#whatever\endcsname + {\ifcsname\??fileonce#whatever\endcsname \expandafter\gobbleoneargument \else - \letgvalue{\??fi:#whatever}\relax + \letgvalue{\??fileonce#whatever}\relax \expandafter\firstofoneargument \fi} @@ -215,11 +219,11 @@ {\doonlyonce{#name}{\doiffileelse{#name}{\inputgivenfile{#name}}\donothing}} \unexpanded\def\doendinputonce#name% - {\ifcsname\??fi:#name\endcsname + {\ifcsname\??fileonce#name\endcsname \expandafter\endinput \fi} \unexpanded\def\forgetdoingonce#whatever% - {\global\letbeundefined{\??fi:#whatever}} + {\global\letbeundefined{\??fileonce#whatever}} \protect \endinput diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua index 992e4b7ec..6be901a9f 100644 --- a/tex/context/base/file-job.lua +++ b/tex/context/base/file-job.lua @@ -9,8 +9,9 @@ if not modules then modules = { } end modules ['file-job'] = { -- in retrospect dealing it's not that bad to deal with the nesting -- and push/poppign at the tex end -local format, gsub, match = string.format, string.gsub, string.match +local format, gsub, match, find = string.format, string.gsub, string.match, string.find local insert, remove, concat = table.insert, table.remove, table.concat +local validstring = string.valid local commands, resolvers, context = commands, resolvers, context @@ -18,25 +19,41 @@ local trace_jobfiles = false trackers.register("system.jobfiles", function(v) local report_jobfiles = logs.reporter("system","jobfiles") -local texsetcount = tex.setcount -local elements = interfaces.elements -local variables = interfaces.variables -local logsnewline = logs.newline -local logspushtarget = logs.pushtarget -local logspoptarget = logs.poptarget - -local v_outer = variables.outer -local v_text = variables.text -local v_project = variables.project -local v_environment = variables.environment -local v_product = variables.product -local v_component = variables.component -local c_prefix = variables.prefix +local texsetcount = tex.setcount +local elements = interfaces.elements +local constants = interfaces.constants +local variables = interfaces.variables +local logsnewline = logs.newline +local logspushtarget = logs.pushtarget +local logspoptarget = logs.poptarget +local settings_to_array = utilities.parsers.settings_to_array +local write_nl = texio.write_nl +local allocate = utilities.storage.allocate + +local nameonly = file.nameonly +local suffixonly = file.suffix +local basename = file.basename +local addsuffix = file.addsuffix +local removesuffix = file.removesuffix +local dirname = file.dirname +local joinpath = file.join +local is_qualified_path = file.is_qualified_path + +local cleanpath = resolvers.cleanpath +local inputstack = resolvers.inputstack + +local v_outer = variables.outer +local v_text = variables.text +local v_project = variables.project +local v_environment = variables.environment +local v_product = variables.product +local v_component = variables.component +local c_prefix = variables.prefix -- main code .. there is some overlap .. here we have loc:// local function findctxfile(name) -- loc ? any ? - if file.is_qualified_path(name) then -- maybe when no suffix do some test for tex + if is_qualified_path(name) then -- maybe when no suffix do some test for tex return name elseif not url.hasscheme(name) then return resolvers.finders.byscheme("loc",name) or "" @@ -59,7 +76,7 @@ function commands.doifinputfileelse(name) end function commands.locatefilepath(name) - context(file.dirname(findctxfile(name))) + context(dirname(findctxfile(name))) end function commands.usepath(paths) @@ -74,6 +91,10 @@ function commands.allinputpaths() context(concat(resolvers.instance.extra_paths or { },",")) end +function commands.setdocumentfilenames() + environment.initializefilenames() +end + function commands.usezipfile(name,tree) if tree and tree ~= "" then resolvers.usezipfile(format("zip:///%s?tree=%s",name,tree)) @@ -156,7 +177,7 @@ end -- local action = function(name,foundname) input(foundname) end -local failure = function(name,foundname) end +local failure = function(name,foundname) report_jobfiles("unknown tex file %q",name) end local function usetexfile(name,onlyonce,notext) startprocessing(name,notext) @@ -171,7 +192,7 @@ local function usetexfile(name,onlyonce,notext) end local action = function(name,foundname) dofile(foundname) end -local failure = function(name,foundname) end +local failure = function(name,foundname) report_jobfiles("unknown lua file %q",name) end local function useluafile(name,onlyonce,notext) uselibrary { @@ -184,7 +205,7 @@ local function useluafile(name,onlyonce,notext) end local action = function(name,foundname) dofile(foundname) end -local failure = function(name,foundname) end +local failure = function(name,foundname) report_jobfiles("unknown cld file %q",name) end local function usecldfile(name,onlyonce,notext) startprocessing(name,notext) @@ -199,7 +220,7 @@ local function usecldfile(name,onlyonce,notext) end local action = function(name,foundname) context.xmlprocess(foundname,"main","") end -local failure = function(name,foundname) end +local failure = function(name,foundname) report_jobfiles("unknown xml file %q",name) end local function usexmlfile(name,onlyonce,notext) startprocessing(name,notext) @@ -232,7 +253,7 @@ local suffixes = { local function useanyfile(name,onlyonce) local s = suffixes[file.suffix(name)] if s then - s(file.removesuffix(name),onlyonce) + s(removesuffix(name),onlyonce) else usetexfile(name,onlyonce) -- e.g. ctx file --~ resolvers.readfilename(name) @@ -244,7 +265,7 @@ commands.useanyfile = useanyfile function resolvers.jobs.usefile(name,onlyonce,notext) local s = suffixes[file.suffix(name)] if s then - s(file.removesuffix(name),onlyonce,notext) + s(removesuffix(name),onlyonce,notext) end end @@ -429,48 +450,52 @@ job.register('job.structure.collected',root,initialize) -- component: small unit, either or not components itself -- product : combination of components +local context_processfilemany = context.processfilemany +local context_processfileonce = context.processfileonce +local context_processfilenone = context.processfilenone + local processors = utilities.storage.allocate { -- [v_outer] = { - -- [v_text] = { "many", context.processfilemany }, - -- [v_project] = { "once", context.processfileonce }, - -- [v_environment] = { "once", context.processfileonce }, - -- [v_product] = { "many", context.processfileonce }, - -- [v_component] = { "many", context.processfilemany }, + -- [v_text] = { "many", context_processfilemany }, + -- [v_project] = { "once", context_processfileonce }, + -- [v_environment] = { "once", context_processfileonce }, + -- [v_product] = { "once", context_processfileonce }, + -- [v_component] = { "many", context_processfilemany }, -- }, [v_text] = { - [v_text] = { "many", context.processfilemany }, - [v_project] = { "none", context.processfileonce }, -- none - [v_environment] = { "once", context.processfileonce }, -- once - [v_product] = { "none", context.processfileonce }, -- none - [v_component] = { "many", context.processfilemany }, -- many + [v_text] = { "many", context_processfilemany }, + [v_project] = { "once", context_processfileonce }, -- dubious + [v_environment] = { "once", context_processfileonce }, + [v_product] = { "many", context_processfilemany }, -- dubious + [v_component] = { "many", context_processfilemany }, }, [v_project] = { - [v_text] = { "many", context.processfilemany }, - [v_project] = { "none", context.processfilenone }, -- none - [v_environment] = { "once", context.processfileonce }, -- once - [v_product] = { "once", context.processfilenone }, -- once - [v_component] = { "none", context.processfilenone }, -- many * + [v_text] = { "many", context_processfilemany }, + [v_project] = { "none", context_processfilenone }, + [v_environment] = { "once", context_processfileonce }, + [v_product] = { "none", context_processfilenone }, + [v_component] = { "none", context_processfilenone }, }, [v_environment] = { - [v_text] = { "many", context.processfilemany }, - [v_project] = { "none", context.processfilenone }, -- none - [v_environment] = { "once", context.processfileonce }, -- once - [v_product] = { "none", context.processfilenone }, -- none - [v_component] = { "none", context.processfilenone }, -- none + [v_text] = { "many", context_processfilemany }, + [v_project] = { "none", context_processfilenone }, + [v_environment] = { "once", context_processfileonce }, + [v_product] = { "none", context_processfilenone }, + [v_component] = { "none", context_processfilenone }, }, [v_product] = { - [v_text] = { "many", context.processfilemany }, - [v_project] = { "once", context.processfileonce }, -- once - [v_environment] = { "once", context.processfileonce }, -- once - [v_product] = { "none", context.processfilemany }, -- none - [v_component] = { "many", context.processfilemany }, -- many + [v_text] = { "many", context_processfilemany }, + [v_project] = { "once", context_processfileonce }, + [v_environment] = { "once", context_processfileonce }, + [v_product] = { "many", context_processfilemany }, + [v_component] = { "many", context_processfilemany }, }, [v_component] = { - [v_text] = { "many", context.processfilemany }, - [v_project] = { "once", context.processfileonce }, -- once - [v_environment] = { "once", context.processfileonce }, -- once - [v_product] = { "none", context.processfilenone }, -- none - [v_component] = { "many", context.processfilemany }, -- many + [v_text] = { "many", context_processfilemany }, + [v_project] = { "once", context_processfileonce }, + [v_environment] = { "once", context_processfileonce }, + [v_product] = { "none", context_processfilenone }, + [v_component] = { "many", context_processfilemany }, } } @@ -531,6 +556,9 @@ local tolerant = false -- too messy, mkii user with the wrong sructure should ad local function process(what,name) local depth = #typestack local process + -- + name = resolvers.resolve(name) + -- -- if not tolerant then -- okay, would be best but not compatible with mkii process = processors[currenttype][what] @@ -610,7 +638,7 @@ local function gotonextlevel(what,name) -- todo: something with suffix name insert(typestack,currenttype) insert(pathstack,currentpath) currenttype = what - currentpath = file.dirname(name) + currentpath = dirname(name) pushtree(what,name) if start[what] then start[what]() @@ -629,10 +657,17 @@ local function gotopreviouslevel(what) context.signalendofinput(what) end -function commands.startproject (name) gotonextlevel(v_project, name) end -function commands.startproduct (name) gotonextlevel(v_product, name) end -function commands.startcomponent (name) gotonextlevel(v_component, name) end -function commands.startenvironment(name) gotonextlevel(v_environment,name) end +local function autoname(name) + if name == "*" then + name = nameonly(inputstack[#inputstack] or name) + end + return name +end + +function commands.startproject (name) gotonextlevel(v_project, autoname(name)) end +function commands.startproduct (name) gotonextlevel(v_product, autoname(name)) end +function commands.startcomponent (name) gotonextlevel(v_component, autoname(name)) end +function commands.startenvironment(name) gotonextlevel(v_environment,autoname(name)) end function commands.stopproject () gotopreviouslevel(v_project ) end function commands.stopproduct () gotopreviouslevel(v_product ) end @@ -673,9 +708,9 @@ end function commands.loadexamodes(filename) if not filename or filename == "" then - filename = file.removesuffix(tex.jobname) + filename = removesuffix(tex.jobname) end - filename = resolvers.findfile(file.addsuffix(filename,'ctm')) or "" + filename = resolvers.findfile(addsuffix(filename,'ctm')) or "" if filename ~= "" then report_examodes("loading %s",filename) -- todo: message system convertexamodes(io.loaddata(filename)) @@ -683,3 +718,196 @@ function commands.loadexamodes(filename) report_examodes("no mode file %s",filename) -- todo: message system end end + +-- changed in mtx-context +-- code moved from luat-ini + +-- todo: locals when mtx-context is changed + +document = document or { + arguments = allocate(), + files = allocate(), + variables = allocate(), -- for templates + options = { + commandline = { + environments = allocate(), + modules = allocate(), + modes = allocate(), + }, + ctxfile = { + environments = allocate(), + modules = allocate(), + modes = allocate(), + }, + }, +} + +function document.setargument(key,value) + document.arguments[key] = value +end + +function document.setdefaultargument(key,default) + local v = document.arguments[key] + if v == nil or v == "" then + document.arguments[key] = default + end +end + +function document.setfilename(i,name) + if name then + document.files[tonumber(i)] = name + else + document.files[#document.files+1] = tostring(i) + end +end + +function document.getargument(key,default) -- commands + local v = document.arguments[key] + if type(v) == "boolean" then + v = (v and "yes") or "no" + document.arguments[key] = v + end + context(v or default or "") +end + +function document.getfilename(i) -- commands + context(document.files[i] or "") +end + +function commands.getcommandline() -- has to happen at the tex end in order to expand + + -- the document[arguments|files] tables are copies + + local arguments = document.arguments + local files = document.files + local options = document.options + + for k, v in next, environment.arguments do + k = gsub(k,"^c:","") -- already done, but better be safe than sorry + if arguments[k] == nil then + arguments[k] = v + end + end + + -- in the new mtx=context approach we always pass a stub file so we need to + -- to trick the files table which actually only has one entry in a tex job + + if arguments.timing then + context.usemodule("timing") + end + + if arguments.batchmode then + context.batchmode(false) + end + + if arguments.nonstopmode then + context.nonstopmode(false) + end + + if arguments.nostatistics then + directives.enable("system.nostatistics") + end + + if arguments.paranoid then + context.setvalue("maxreadlevel",1) + end + + if validstring(arguments.path) then + context.usepath { arguments.path } + end + + local inputfile = validstring(arguments.input) + + if inputfile and dirname(inputfile) == "." and lfs.isfile(inputfile) then + -- nicer in checks + inputfile = basename(inputfile) + end + + context.setupsystem { + [constants.directory] = validstring(arguments.setuppath), + [constants.inputfile] = inputfile, + [constants.file] = validstring(arguments.result), + [constants.random] = validstring(arguments.randomseed), + [constants.n] = validstring(arguments.kindofrun), + [constants.m] = validstring(arguments.currentrun), + } + + if validstring(arguments.arguments) then + context.setupenv { arguments.arguments } + end + + if arguments.once then + directives.enable("system.runonce") + end + + if arguments.noarrange then + context.setuparranging { variables.disable } + end + + -- + + local commandline = options.commandline + + commandline.environments = table.append(commandline.environments,settings_to_array(validstring(arguments.environment))) + commandline.modules = table.append(commandline.modules, settings_to_array(validstring(arguments.usemodule))) + commandline.modes = table.append(commandline.modes, settings_to_array(validstring(arguments.mode))) + + -- + + if #files == 0 then + local list = settings_to_array(validstring(arguments.files)) + if list and #list > 0 then + files = list + end + end + + if #files == 0 then + files = { validstring(arguments.input) } + end + + -- + + document.arguments = arguments + document.files = files + +end + +-- commandline wins over ctxfile + +local function apply(list,action) + if list then + for i=1,#list do + action { list[i] } + end + end +end + +function commands.setdocumentmodes() -- was setup: *runtime:modes + apply(document.options.ctxfile .modes,context.enablemode) + apply(document.options.commandline.modes,context.enablemode) +end + +function commands.setdocumentmodules() -- was setup: *runtime:modules + apply(document.options.ctxfile .modules,context.usemodule) + apply(document.options.commandline.modules,context.usemodule) +end + +function commands.setdocumentenvironments() -- was setup: *runtime:environments + apply(document.options.ctxfile .environments,context.environment) + apply(document.options.commandline.environments,context.environment) +end + +function commands.logoptions() + local arguments = document.arguments + local files = document.files + write_nl("log","\n% begin of command line arguments\n%\n") + for k, v in next, arguments do + write_nl("log",format("%% %-20s = %s",k,tostring(v))) + end + write_nl("log","%\n% end of command line arguments\n") + write_nl("log","\n% begin of command line files\n%\n") + for i=1,#files do + write_nl("log",format("%% %i %s",i,files[i])) + end + write_nl("log","%\n% end of command line files\n\n") +end diff --git a/tex/context/base/file-job.mkvi b/tex/context/base/file-job.mkvi index 112400cbd..b488ee4eb 100644 --- a/tex/context/base/file-job.mkvi +++ b/tex/context/base/file-job.mkvi @@ -75,15 +75,18 @@ \def\syst_files_load#name% only mkiv files {\readsysfile{#name.\mksuffix}{\showmessage\m!system2{#name.\mksuffix}}\donothing} -\unexpanded\def\loadoptionfile - {\readjobfile{\jobname.\f!optionextension} - {\writestatus\m!system{\jobname.\f!optionextension\space loaded}% - \ctxcommand{copyfiletolog("\jobname.\f!optionextension")}}% - {\writestatus\m!system{no \jobname.\f!optionextension}}} +% obsolete, but we keep it as reference of what happened +% +% \unexpanded\def\loadoptionfile +% {\readjobfile{\jobname.\f!optionextension} +% {\writestatus\m!system{\jobname.\f!optionextension\space loaded}% +% \ctxcommand{copyfiletolog("\jobname.\f!optionextension")}}% +% {\writestatus\m!system{no \jobname.\f!optionextension}}} % document structure -\ifdefined\textlevel\else \newcount\textlevel \fi % might go away +\ifdefined\textlevel \else \newcount\textlevel \fi % might go away +\ifdefined\strc_pagenumbers_flush_final_page \else \let\strc_pagenumbers_flush_final_page\relax \fi % ugly \unexpanded\def\dostarttext {\glet\dostarttext\relax @@ -92,8 +95,8 @@ \unexpanded\def\dostoptext {\glet\dostoptext\relax - \flushfinallayoutpage % optional - \page % anyway + \strc_pagenumbers_flush_final_page + \page % hm, bonus \the\everystoptext \global\everystoptext\emptytoks \the\everybye @@ -110,6 +113,8 @@ \unexpanded\def\autostarttext{\ctxcommand{autostarttext()}} \unexpanded\def\autostoptext {\ctxcommand{autostoptext()}} +\unexpanded\def\finishjob{\stoptext} % nicer in luatex call commandline + \newtoks\everystartnotext \newtoks\everystopnotext @@ -190,7 +195,7 @@ %D Handy for modules that have a test/demo appended. -\def\continueifinputfile#name{\doifnot\inputfilename{#name}\endinput} +\def\continueifinputfile#name{\doifnot\inputfilename{#name}\endinput} % will be lua call ./ check %def\processifinputfile #name{\doif \inputfilename{#name}} % \startproject test @@ -290,6 +295,8 @@ {\setvariables[\s!document][#settings]% \the\everysetupdocument\relax} +% metadata:author metadata:title metadata:subject + \setvariables [document] [\c!before=\directsetup{\s!document:start}, diff --git a/tex/context/base/file-lib.lua b/tex/context/base/file-lib.lua index 92dacbf5c..c99c2ac41 100644 --- a/tex/context/base/file-lib.lua +++ b/tex/context/base/file-lib.lua @@ -33,6 +33,7 @@ function commands.uselibrary(specification) -- todo; reporter local failure = specification.failure or defaultfailure local onlyonce = specification.onlyonce local files = utilities.parsers.settings_to_array(name) + local truename = environment.truefilename local done = false for i=1,#files do local filename = files[i] @@ -42,9 +43,9 @@ function commands.uselibrary(specification) -- todo; reporter end for i=1,#patterns do local somename = format(patterns[i],filename) -if environment.truefilename then - somename = environment.truefilename(somename) -end + if truename then + somename = truename(somename) + end local foundname = resolvers.getreadfilename("any",".",somename) or "" if foundname ~= "" then action(name,foundname) diff --git a/tex/context/base/file-mod.lua b/tex/context/base/file-mod.lua index e6592f0f0..4a520e998 100644 --- a/tex/context/base/file-mod.lua +++ b/tex/context/base/file-mod.lua @@ -20,14 +20,14 @@ at the <l n='tex'/> side.</p> local format, concat, tonumber = string.format, table.concat, tonumber -local trace_modules = false trackers.register("modules.loading", function(v) trace_modules = v end) +local trace_modules = false trackers.register("modules.loading", function(v) trace_modules = v end) local report_modules = logs.reporter("resolvers","modules") -commands = commands or { } -local commands = commands +commands = commands or { } +local commands = commands -local findbyscheme = resolvers.finders.byscheme -- use different one +local findbyscheme = resolvers.finders.byscheme -- use different one -- modules can have a specific suffix or can specify one @@ -45,7 +45,7 @@ local function usemodule(name,hasscheme) report_modules("checking url: '%s'",fullname) end foundname = resolvers.findtexfile(fullname) or "" - elseif file.extname(name) ~= "" then + elseif file.suffix(name) ~= "" then if trace_modules then report_modules("checking file: '%s'",name) end @@ -144,8 +144,8 @@ statistics.register("loaded tex modules", function() t[nt] = k end end - local ts = (nt>0 and format(" (%s)",concat(t," "))) or "" - local fs = (nf>0 and format(" (%s)",concat(f," "))) or "" + local ts = nt > 0 and format(" (%s)",concat(t," ")) or "" + local fs = nf > 0 and format(" (%s)",concat(f," ")) or "" return format("%s requested, %s found%s, %s missing%s",nt+nf,nt,ts,nf,fs) else return nil @@ -166,5 +166,5 @@ function commands.doifolderversionelse(one,two) -- one >= two two = lpeg.match(splitter,two) one = (one[1] or 0) * 10000 + (one[2] or 0) * 100 + (one[3] or 0) two = (two[1] or 0) * 10000 + (two[2] or 0) * 100 + (two[3] or 0) - commands.testcase(one>=two) + commands.doifelse(one>=two) end diff --git a/tex/context/base/file-res.lua b/tex/context/base/file-res.lua index 4687e140e..6726f71ee 100644 --- a/tex/context/base/file-res.lua +++ b/tex/context/base/file-res.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['supp-fil'] = { +if not modules then modules = { } end modules ['file-res'] = { version = 1.001, comment = "companion to supp-fil.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -76,9 +76,9 @@ local function readfilename(specification,backtrack,treetoo) local fname = paths[i] .. "/" .. names[i] if isfile(fname) then if trace_files then - report_files("found on extra path: %s",name) + report_files("found on extra path: %s",fname) end - fnd = name + fnd = fname break end end diff --git a/tex/context/base/file-syn.lua b/tex/context/base/file-syn.lua index 1be9fb4b1..8d913bb37 100644 --- a/tex/context/base/file-syn.lua +++ b/tex/context/base/file-syn.lua @@ -11,6 +11,9 @@ local report_files = logs.reporter("files") environment.filesynonyms = environment.filesynonyms or { } local filesynonyms = environment.filesynonyms +local settings_to_array = utilities.parsers.settings_to_array +local findfile = resolvers.findfile + storage.register("environment/filesynonyms", filesynonyms, "environment.filesynonyms") local function truefilename(name) @@ -37,9 +40,9 @@ function commands.definefilesynonym(name,realname) end function commands.definefilefallback(name,alternatives) - local names = utilities.parser.settings_to_array(alternatives) + local names = settings_to_array(alternatives) for i=1,#names do - local realname = resolvers.findfile(names[i]) + local realname = findfile(names[i]) if realname ~= "" then filesynonyms[name] = realname break diff --git a/tex/context/base/font-afk.lua b/tex/context/base/font-afk.lua new file mode 100644 index 000000000..8b65b0631 --- /dev/null +++ b/tex/context/base/font-afk.lua @@ -0,0 +1,200 @@ +if not modules then modules = { } end modules ['font-afk'] = { + version = 1.001, + comment = "companion to font-afm.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", + dataonly = true, +} + +--[[ldx-- +<p>For ligatures, only characters with a code smaller than 128 make sense, +anything larger is encoding dependent. An interesting complication is that a +character can be in an encoding twice but is hashed once.</p> +--ldx]]-- + +local allocate = utilities.storage.allocate + +fonts.handlers.afm.helpdata = { + ligatures = allocate { -- okay, nowadays we could parse the name but type 1 fonts + ['f'] = { -- don't have that many ligatures anyway + { 'f', 'ff' }, + { 'i', 'fi' }, + { 'l', 'fl' }, + }, + ['ff'] = { + { 'i', 'ffi' } + }, + ['fi'] = { + { 'i', 'fii' } + }, + ['fl'] = { + { 'i', 'fli' } + }, + ['s'] = { + { 't', 'st' } + }, + ['i'] = { + { 'j', 'ij' } + }, + }, + texligatures = allocate { + -- ['space'] = { + -- { 'L', 'Lslash' }, + -- { 'l', 'lslash' } + -- }, + -- ['question'] = { + -- { 'quoteleft', 'questiondown' } + -- }, + -- ['exclam'] = { + -- { 'quoteleft', 'exclamdown' } + -- }, + ['quoteleft'] = { + { 'quoteleft', 'quotedblleft' } + }, + ['quoteright'] = { + { 'quoteright', 'quotedblright' } + }, + ['hyphen'] = { + { 'hyphen', 'endash' } + }, + ['endash'] = { + { 'hyphen', 'emdash' } + } + }, + leftkerned = allocate { + AEligature = "A", aeligature = "a", + OEligature = "O", oeligature = "o", + IJligature = "I", ijligature = "i", + AE = "A", ae = "a", + OE = "O", oe = "o", + IJ = "I", ij = "i", + Ssharp = "S", ssharp = "s", + }, + rightkerned = allocate { + AEligature = "E", aeligature = "e", + OEligature = "E", oeligature = "e", + IJligature = "J", ijligature = "j", + AE = "E", ae = "e", + OE = "E", oe = "e", + IJ = "J", ij = "j", + Ssharp = "S", ssharp = "s", + }, + bothkerned = allocate { + Acircumflex = "A", acircumflex = "a", + Ccircumflex = "C", ccircumflex = "c", + Ecircumflex = "E", ecircumflex = "e", + Gcircumflex = "G", gcircumflex = "g", + Hcircumflex = "H", hcircumflex = "h", + Icircumflex = "I", icircumflex = "i", + Jcircumflex = "J", jcircumflex = "j", + Ocircumflex = "O", ocircumflex = "o", + Scircumflex = "S", scircumflex = "s", + Ucircumflex = "U", ucircumflex = "u", + Wcircumflex = "W", wcircumflex = "w", + Ycircumflex = "Y", ycircumflex = "y", + + Agrave = "A", agrave = "a", + Egrave = "E", egrave = "e", + Igrave = "I", igrave = "i", + Ograve = "O", ograve = "o", + Ugrave = "U", ugrave = "u", + Ygrave = "Y", ygrave = "y", + + Atilde = "A", atilde = "a", + Itilde = "I", itilde = "i", + Otilde = "O", otilde = "o", + Utilde = "U", utilde = "u", + Ntilde = "N", ntilde = "n", + + Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a", + Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e", + Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i", + Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o", + Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u", + Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y", + + Aacute = "A", aacute = "a", + Cacute = "C", cacute = "c", + Eacute = "E", eacute = "e", + Iacute = "I", iacute = "i", + Lacute = "L", lacute = "l", + Nacute = "N", nacute = "n", + Oacute = "O", oacute = "o", + Racute = "R", racute = "r", + Sacute = "S", sacute = "s", + Uacute = "U", uacute = "u", + Yacute = "Y", yacute = "y", + Zacute = "Z", zacute = "z", + + Dstroke = "D", dstroke = "d", + Hstroke = "H", hstroke = "h", + Tstroke = "T", tstroke = "t", + + Cdotaccent = "C", cdotaccent = "c", + Edotaccent = "E", edotaccent = "e", + Gdotaccent = "G", gdotaccent = "g", + Idotaccent = "I", idotaccent = "i", + Zdotaccent = "Z", zdotaccent = "z", + + Amacron = "A", amacron = "a", + Emacron = "E", emacron = "e", + Imacron = "I", imacron = "i", + Omacron = "O", omacron = "o", + Umacron = "U", umacron = "u", + + Ccedilla = "C", ccedilla = "c", + Kcedilla = "K", kcedilla = "k", + Lcedilla = "L", lcedilla = "l", + Ncedilla = "N", ncedilla = "n", + Rcedilla = "R", rcedilla = "r", + Scedilla = "S", scedilla = "s", + Tcedilla = "T", tcedilla = "t", + + Ohungarumlaut = "O", ohungarumlaut = "o", + Uhungarumlaut = "U", uhungarumlaut = "u", + + Aogonek = "A", aogonek = "a", + Eogonek = "E", eogonek = "e", + Iogonek = "I", iogonek = "i", + Uogonek = "U", uogonek = "u", + + Aring = "A", aring = "a", + Uring = "U", uring = "u", + + Abreve = "A", abreve = "a", + Ebreve = "E", ebreve = "e", + Gbreve = "G", gbreve = "g", + Ibreve = "I", ibreve = "i", + Obreve = "O", obreve = "o", + Ubreve = "U", ubreve = "u", + + Ccaron = "C", ccaron = "c", + Dcaron = "D", dcaron = "d", + Ecaron = "E", ecaron = "e", + Lcaron = "L", lcaron = "l", + Ncaron = "N", ncaron = "n", + Rcaron = "R", rcaron = "r", + Scaron = "S", scaron = "s", + Tcaron = "T", tcaron = "t", + Zcaron = "Z", zcaron = "z", + + dotlessI = "I", dotlessi = "i", + dotlessJ = "J", dotlessj = "j", + + AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae", + OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe", + IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij", + + Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l", + Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o", + + Ssharp = "SS", ssharp = "ss", + + Aumlaut = "A", aumlaut = "a", + Eumlaut = "E", eumlaut = "e", + Iumlaut = "I", iumlaut = "i", + Oumlaut = "O", oumlaut = "o", + Uumlaut = "U", uumlaut = "u", + } +} diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua index 9d3d8ddd7..dab948b32 100644 --- a/tex/context/base/font-afm.lua +++ b/tex/context/base/font-afm.lua @@ -17,12 +17,7 @@ where we handles font encodings. Eventually font encoding goes away.</p> --ldx]]-- -local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) -local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) -local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) -local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) - -local report_afm = logs.reporter("fonts","afm loading") +local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers local next, type, tonumber = next, type, tonumber local format, match, gmatch, lower, gsub, strip = string.format, string.match, string.gmatch, string.lower, string.gsub, string.strip @@ -30,30 +25,35 @@ local abs = math.abs local P, S, C, R, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.match, lpeg.patterns local derivetable = table.derive -local fonts = fonts -local afm = { } -local pfb = { } -fonts.handlers.afm = afm -fonts.handlers.pfb = pfb +local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) +local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) +local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) +local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) -afm.version = 1.410 -- incrementing this number one up will force a re-cache -afm.cache = containers.define("fonts", "afm", afm.version, true) -afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) +local report_afm = logs.reporter("fonts","afm loading") -afm.syncspace = true -- when true, nicer stretch values -afm.addligatures = true -- best leave this set to true -afm.addtexligatures = true -- best leave this set to true -afm.addkerns = true -- best leave this set to true +local findbinfile = resolvers.findbinfile local definers = fonts.definers local readers = fonts.readers local constructors = fonts.constructors -local findbinfile = resolvers.findbinfile +local afm = constructors.newhandler("afm") +local pfb = constructors.newhandler("pfb") local afmfeatures = constructors.newfeatures("afm") local registerafmfeature = afmfeatures.register +afm.version = 1.410 -- incrementing this number one up will force a re-cache +afm.cache = containers.define("fonts", "afm", afm.version, true) +afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) + +afm.helpdata = { } -- set later on so no local for this +afm.syncspace = true -- when true, nicer stretch values +afm.addligatures = true -- best leave this set to true +afm.addtexligatures = true -- best leave this set to true +afm.addkerns = true -- best leave this set to true + local function setmode(tfmdata,value) if value then tfmdata.properties.mode = lower(value) @@ -429,79 +429,26 @@ end and extra kerns. This saves quite some lookups later.</p> --ldx]]-- ---[[ldx-- -<p>Only characters with a code smaller than 128 make sense, -anything larger is encoding dependent. An interesting complication -is that a character can be in an encoding twice but is hashed -once.</p> ---ldx]]-- - -local ligatures = { -- okay, nowadays we could parse the name but type 1 fonts - ['f'] = { -- don't have that many ligatures anyway - { 'f', 'ff' }, - { 'i', 'fi' }, - { 'l', 'fl' }, - }, - ['ff'] = { - { 'i', 'ffi' } - }, - ['fi'] = { - { 'i', 'fii' } - }, - ['fl'] = { - { 'i', 'fli' } - }, - ['s'] = { - { 't', 'st' } - }, - ['i'] = { - { 'j', 'ij' } - }, -} - -local texligatures = { - -- ['space'] = { - -- { 'L', 'Lslash' }, - -- { 'l', 'lslash' } - -- }, - -- ['question'] = { - -- { 'quoteleft', 'questiondown' } - -- }, - -- ['exclam'] = { - -- { 'quoteleft', 'exclamdown' } - -- }, - ['quoteleft'] = { - { 'quoteleft', 'quotedblleft' } - }, - ['quoteright'] = { - { 'quoteright', 'quotedblright' } - }, - ['hyphen'] = { - { 'hyphen', 'endash' } - }, - ['endash'] = { - { 'hyphen', 'emdash' } - } -} - local addthem = function(rawdata,ligatures) - local descriptions = rawdata.descriptions - local resources = rawdata.resources - local unicodes = resources.unicodes - local names = resources.names - for ligname, ligdata in next, ligatures do - local one = descriptions[unicodes[ligname]] - if one then - for _, pair in next, ligdata do - local two, three = unicodes[pair[1]], unicodes[pair[2]] - if two and three then - local ol = one.ligatures - if ol then - if not ol[two] then - ol[two] = three + if ligatures then + local descriptions = rawdata.descriptions + local resources = rawdata.resources + local unicodes = resources.unicodes + local names = resources.names + for ligname, ligdata in next, ligatures do + local one = descriptions[unicodes[ligname]] + if one then + for _, pair in next, ligdata do + local two, three = unicodes[pair[1]], unicodes[pair[2]] + if two and three then + local ol = one.ligatures + if ol then + if not ol[two] then + ol[two] = three + end + else + one.ligatures = { [two] = three } end - else - one.ligatures = { [two] = three } end end end @@ -509,8 +456,8 @@ local addthem = function(rawdata,ligatures) end end -addligatures = function(rawdata) addthem(rawdata,ligatures ) end -addtexligatures = function(rawdata) addthem(rawdata,texligatures) end +addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end +addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end --[[ldx-- <p>We keep the extra kerns in separate kerning tables so that we can use @@ -524,208 +471,71 @@ them selectively.</p> -- we don't use the character database. (Ok, we can have a context specific -- variant). --- we can make them numbers - -local left = { - AEligature = "A", aeligature = "a", - OEligature = "O", oeligature = "o", - IJligature = "I", ijligature = "i", - AE = "A", ae = "a", - OE = "O", oe = "o", - IJ = "I", ij = "i", - Ssharp = "S", ssharp = "s", -} - -local right = { - AEligature = "E", aeligature = "e", - OEligature = "E", oeligature = "e", - IJligature = "J", ijligature = "j", - AE = "E", ae = "e", - OE = "E", oe = "e", - IJ = "J", ij = "j", - Ssharp = "S", ssharp = "s", -} - -local both = { - Acircumflex = "A", acircumflex = "a", - Ccircumflex = "C", ccircumflex = "c", - Ecircumflex = "E", ecircumflex = "e", - Gcircumflex = "G", gcircumflex = "g", - Hcircumflex = "H", hcircumflex = "h", - Icircumflex = "I", icircumflex = "i", - Jcircumflex = "J", jcircumflex = "j", - Ocircumflex = "O", ocircumflex = "o", - Scircumflex = "S", scircumflex = "s", - Ucircumflex = "U", ucircumflex = "u", - Wcircumflex = "W", wcircumflex = "w", - Ycircumflex = "Y", ycircumflex = "y", - - Agrave = "A", agrave = "a", - Egrave = "E", egrave = "e", - Igrave = "I", igrave = "i", - Ograve = "O", ograve = "o", - Ugrave = "U", ugrave = "u", - Ygrave = "Y", ygrave = "y", - - Atilde = "A", atilde = "a", - Itilde = "I", itilde = "i", - Otilde = "O", otilde = "o", - Utilde = "U", utilde = "u", - Ntilde = "N", ntilde = "n", - - Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a", - Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e", - Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i", - Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o", - Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u", - Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y", - - Aacute = "A", aacute = "a", - Cacute = "C", cacute = "c", - Eacute = "E", eacute = "e", - Iacute = "I", iacute = "i", - Lacute = "L", lacute = "l", - Nacute = "N", nacute = "n", - Oacute = "O", oacute = "o", - Racute = "R", racute = "r", - Sacute = "S", sacute = "s", - Uacute = "U", uacute = "u", - Yacute = "Y", yacute = "y", - Zacute = "Z", zacute = "z", - - Dstroke = "D", dstroke = "d", - Hstroke = "H", hstroke = "h", - Tstroke = "T", tstroke = "t", - - Cdotaccent = "C", cdotaccent = "c", - Edotaccent = "E", edotaccent = "e", - Gdotaccent = "G", gdotaccent = "g", - Idotaccent = "I", idotaccent = "i", - Zdotaccent = "Z", zdotaccent = "z", - - Amacron = "A", amacron = "a", - Emacron = "E", emacron = "e", - Imacron = "I", imacron = "i", - Omacron = "O", omacron = "o", - Umacron = "U", umacron = "u", - - Ccedilla = "C", ccedilla = "c", - Kcedilla = "K", kcedilla = "k", - Lcedilla = "L", lcedilla = "l", - Ncedilla = "N", ncedilla = "n", - Rcedilla = "R", rcedilla = "r", - Scedilla = "S", scedilla = "s", - Tcedilla = "T", tcedilla = "t", - - Ohungarumlaut = "O", ohungarumlaut = "o", - Uhungarumlaut = "U", uhungarumlaut = "u", - - Aogonek = "A", aogonek = "a", - Eogonek = "E", eogonek = "e", - Iogonek = "I", iogonek = "i", - Uogonek = "U", uogonek = "u", - - Aring = "A", aring = "a", - Uring = "U", uring = "u", - - Abreve = "A", abreve = "a", - Ebreve = "E", ebreve = "e", - Gbreve = "G", gbreve = "g", - Ibreve = "I", ibreve = "i", - Obreve = "O", obreve = "o", - Ubreve = "U", ubreve = "u", - - Ccaron = "C", ccaron = "c", - Dcaron = "D", dcaron = "d", - Ecaron = "E", ecaron = "e", - Lcaron = "L", lcaron = "l", - Ncaron = "N", ncaron = "n", - Rcaron = "R", rcaron = "r", - Scaron = "S", scaron = "s", - Tcaron = "T", tcaron = "t", - Zcaron = "Z", zcaron = "z", - - dotlessI = "I", dotlessi = "i", - dotlessJ = "J", dotlessj = "j", - - AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae", - OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe", - IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij", - - Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l", - Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o", - - Ssharp = "SS", ssharp = "ss", - - Aumlaut = "A", aumlaut = "a", - Eumlaut = "E", eumlaut = "e", - Iumlaut = "I", iumlaut = "i", - Oumlaut = "O", oumlaut = "o", - Uumlaut = "U", uumlaut = "u", - -} - addkerns = function(rawdata) -- using shcodes is not robust here local descriptions = rawdata.descriptions local resources = rawdata.resources local unicodes = resources.unicodes local function do_it_left(what) - for unicode, description in next, descriptions do - local kerns = description.kerns - if kerns then - local extrakerns - for complex, simple in next, what do - complex = unicodes[complex] - simple = unicodes[simple] - if complex and simple then - local ks = kerns[simple] - if ks and not kerns[complex] then - if extrakerns then - extrakerns[complex] = ks - else - extrakerns = { [complex] = ks } + if what then + for unicode, description in next, descriptions do + local kerns = description.kerns + if kerns then + local extrakerns + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then + local ks = kerns[simple] + if ks and not kerns[complex] then + if extrakerns then + extrakerns[complex] = ks + else + extrakerns = { [complex] = ks } + end end end end - end - if extrakerns then - description.extrakerns = extrakerns + if extrakerns then + description.extrakerns = extrakerns + end end end end end local function do_it_copy(what) - for complex, simple in next, what do - complex = unicodes[complex] - simple = unicodes[simple] - if complex and simple then - local complexdescription = descriptions[complex] - if complexdescription then -- optional - local simpledescription = descriptions[complex] - if simpledescription then - local extrakerns - local kerns = simpledescription.kerns - if kerns then - for unicode, kern in next, kerns do - if extrakerns then - extrakerns[unicode] = kern - else - extrakerns = { [unicode] = kern } + if what then + for complex, simple in next, what do + complex = unicodes[complex] + simple = unicodes[simple] + if complex and simple then + local complexdescription = descriptions[complex] + if complexdescription then -- optional + local simpledescription = descriptions[complex] + if simpledescription then + local extrakerns + local kerns = simpledescription.kerns + if kerns then + for unicode, kern in next, kerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end end end - end - local extrakerns = simpledescription.extrakerns - if extrakerns then - for unicode, kern in next, extrakerns do - if extrakerns then - extrakerns[unicode] = kern - else - extrakerns = { [unicode] = kern } + local extrakerns = simpledescription.extrakerns + if extrakerns then + for unicode, kern in next, extrakerns do + if extrakerns then + extrakerns[unicode] = kern + else + extrakerns = { [unicode] = kern } + end end end - end - if extrakerns then - complexdescription.extrakerns = extrakerns + if extrakerns then + complexdescription.extrakerns = extrakerns + end end end end @@ -733,11 +543,11 @@ addkerns = function(rawdata) -- using shcodes is not robust here end end -- add complex with values of simplified when present - do_it_left(left) - do_it_left(both) + do_it_left(afm.helpdata.leftkerned) + do_it_left(afm.helpdata.bothkerned) -- copy kerns from simple char to complex char unless set - do_it_copy(both) - do_it_copy(right) + do_it_copy(afm.helpdata.bothkerned) + do_it_copy(afm.helpdata.rightkerned) end --[[ldx-- diff --git a/tex/context/base/font-age.lua b/tex/context/base/font-age.lua index 741bb475a..36647c3a6 100644 --- a/tex/context/base/font-age.lua +++ b/tex/context/base/font-age.lua @@ -4,6 +4,7 @@ if not modules then modules = { } end modules ['font-age'] = { author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "derived from http://www.adobe.com/devnet/opentype/archives/glyphlist.txt", original = "Adobe Glyph List, version 2.0, September 20, 2002", + dataonly = true, } if context then diff --git a/tex/context/base/font-agl.lua b/tex/context/base/font-agl.lua index 6c1f387ba..ca7fb61cb 100644 --- a/tex/context/base/font-agl.lua +++ b/tex/context/base/font-agl.lua @@ -271,7 +271,7 @@ for a, u in next, extras do end end --- We load this table only when needed. We coul duse a loading mechanism +-- We load this table only when needed. We could use a loading mechanism -- return the table but there are no more vectors like this so why bother. fonts.encodings = fonts.encodings or { } diff --git a/tex/context/base/font-aux.lua b/tex/context/base/font-aux.lua index 0396554ad..5e938ceb9 100644 --- a/tex/context/base/font-aux.lua +++ b/tex/context/base/font-aux.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['font-aux'] = { license = "see context related readme files" } -local number = tonumber +local tonumber, type = tonumber, type local wrap, yield = coroutine.wrap, coroutine.yield local fonts, font = fonts, font diff --git a/tex/context/base/font-aux.mkvi b/tex/context/base/font-aux.mkvi new file mode 100644 index 000000000..bd655e41c --- /dev/null +++ b/tex/context/base/font-aux.mkvi @@ -0,0 +1,26 @@ +%D \module +%D [ file=font-gds, +%D version=2012.06.26, +%D title=\CONTEXT\ Font Support, +%D subtitle=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. + +\writestatus{loading}{ConTeXt Font Support / Helpers} + +%D Here we collect code moved from other files, like some of the +%D support modules. + +\unprotect + +%D Leftovers: + +\unexpanded\def\xbox {\bgroup\aftergroup\egroup\hbox\bgroup\tx \let\next=} +\unexpanded\def\xxbox{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=} + +\protect \endinput diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua index 04b49b02c..7536a3e09 100644 --- a/tex/context/base/font-chk.lua +++ b/tex/context/base/font-chk.lua @@ -149,7 +149,7 @@ local package = "q %0.6f 0 0 %0.6f 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0 local cache = { } -- saves some tables but not that impressive -local function addmissingsymbols(tfmdata) +local function addmissingsymbols(tfmdata) -- we can have an alternative with rules local characters = tfmdata.characters local size = tfmdata.parameters.size local privates = tfmdata.properties.privates diff --git a/tex/context/base/font-chk.mkiv b/tex/context/base/font-chk.mkiv new file mode 100644 index 000000000..d436388de --- /dev/null +++ b/tex/context/base/font-chk.mkiv @@ -0,0 +1,22 @@ +%D \module +%D [ file=font-chk, +%D version=2009.01.02, % moved from font-tra +%D title=\CONTEXT\ Font Macros, +%D subtitle=Checking, +%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 / Checking} + +\registerctxluafile{font-chk}{1.001} + +\unexpanded\def\checkcharactersinfont {\ctxcommand{checkcharactersinfont()}} +\unexpanded\def\removemissingcharacters {\ctxcommand{removemissingcharacters()}} +\unexpanded\def\replacemissingcharacters{\ctxcommand{replacemissingcharacters()}} + +\endinput diff --git a/tex/context/base/font-cid.lua b/tex/context/base/font-cid.lua index 4a4c4d209..bf186d885 100644 --- a/tex/context/base/font-cid.lua +++ b/tex/context/base/font-cid.lua @@ -10,17 +10,17 @@ local format, match, lower = string.format, string.match, string.lower local tonumber = tonumber local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match -local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) +local fonts, logs, trackers = fonts, logs, trackers -local report_otf = logs.reporter("fonts","otf loading") +local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) -local fonts = fonts +local report_otf = logs.reporter("fonts","otf loading") -local cid = { } -fonts.cid = cid +local cid = { } +fonts.cid = cid -local cidmap = { } -local cidmax = 10 +local cidmap = { } +local cidmax = 10 -- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap -- @@ -79,8 +79,7 @@ local function loadcidfile(filename) end end -cid.loadfile = loadcidfile -- we use the frozen variant - +cid.loadfile = loadcidfile -- we use the frozen variant local template = "%s-%s-%s.cidmap" local function locate(registry,ordering,supplement) diff --git a/tex/context/base/font-col.lua b/tex/context/base/font-col.lua index f8add1e4e..4b96cca31 100644 --- a/tex/context/base/font-col.lua +++ b/tex/context/base/font-col.lua @@ -8,32 +8,40 @@ if not modules then modules = { } end modules ['font-col'] = { -- possible optimization: delayed initialization of vectors -local gmatch, type = string.gmatch, type -local traverse_id = node.traverse_id -local lpegmatch = lpeg.match +local context, commands, trackers, logs = context, commands, trackers, logs +local node, nodes, fonts, characters = node, nodes, fonts, characters +local file, lpeg, table, string = file, lpeg, table, string + +local type, next, toboolean = type, next, toboolean +local gmatch = string.gmatch local fastcopy = table.fastcopy -local settings_to_hash = utilities.parsers.settings_to_hash +----- P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match + +local traverse_id = node.traverse_id +local settings_to_hash = utilities.parsers.settings_to_hash -local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end) +local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end) -local report_fonts = logs.reporter("fonts","collections") +local report_fonts = logs.reporter("fonts","collections") -local fonts, context = fonts, context +fonts.collections = fonts.collections or { } +local collections = fonts.collections -fonts.collections = fonts.collections or { } -local collections = fonts.collections +collections.definitions = collections.definitions or { } +local definitions = collections.definitions -collections.definitions = collections.definitions or { } -local definitions = collections.definitions +collections.vectors = collections.vectors or { } +local vectors = collections.vectors -collections.vectors = collections.vectors or { } -local vectors = collections.vectors +local fontdata = fonts.hashes.identifiers -local fontdata = fonts.hashes.identifiers +local glyph_code = nodes.nodecodes.glyph -local glyph = node.id('glyph') +local fontpatternhassize = fonts.helpers.fontpatternhassize -local list, current, active = { }, 0, false +local list = { } +local current = 0 +local enabled = false -- maybe also a copy @@ -145,17 +153,19 @@ function collections.clonevector(name) if trace_collecting then report_fonts("def: activating collection %s for font %s",name,current) end - active = true + if not enabled then + nodes.tasks.enableaction("processors","fonts.collections.process") + enabled = true + end statistics.stoptiming(fonts) end -- we already have this parser - -local P, Cc = lpeg.P, lpeg.Cc -local spec = (P("sa") + P("at") + P("scaled") + P("at") + P("mo")) * P(" ")^1 * (1-P(" "))^1 * P(" ")^0 * -1 -local okay = ((1-spec)^1 * spec * Cc(true)) + Cc(false) - --- todo: check for already done +-- +-- local spec = (P("sa") + P("at") + P("scaled") + P("at") + P("mo")) * P(" ")^1 * (1-P(" "))^1 * P(" ")^0 * -1 +-- local okay = ((1-spec)^1 * spec * Cc(true)) + Cc(false) +-- +-- if lpegmatch(okay,name) then function collections.prepare(name) current = font.current() @@ -175,7 +185,7 @@ function collections.prepare(name) local f = d[i] local name = f.font local scale = f.rscale or 1 - if lpegmatch(okay,name) then + if fontpatternhassize(name) then context.font_fallbacks_clone_unique(name,scale) else context.font_fallbacks_clone_inherited(name,scale) @@ -198,32 +208,28 @@ function collections.report(message) end function collections.process(head) -- this way we keep feature processing - if active then - local done = false - for n in traverse_id(glyph,head) do - local v = vectors[n.font] - if v then - local id = v[n.char] - if id then - if type(id) == "table" then - local newid, newchar = id[1], id[2] - if trace_collecting then - report_fonts("lst: remapping character %s in font %s to character %s in font %s",n.char,n.font,newchar,newid) - end - n.font, n.char = newid, newchar - else - if trace_collecting then - report_fonts("lst: remapping font %s to %s for character %s",n.font,id,n.char) - end - n.font = id + local done = false + for n in traverse_id(glyph_code,head) do + local v = vectors[n.font] + if v then + local id = v[n.char] + if id then + if type(id) == "table" then + local newid, newchar = id[1], id[2] + if trace_collecting then + report_fonts("lst: remapping character %s in font %s to character %s in font %s",n.char,n.font,newchar,newid) end + n.font, n.char = newid, newchar + else + if trace_collecting then + report_fonts("lst: remapping font %s to %s for character %s",n.font,id,n.char) + end + n.font = id end end end - return head, done - else - return head, false end + return head, done end -- interface diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua index 928099688..6074bab18 100644 --- a/tex/context/base/font-con.lua +++ b/tex/context/base/font-con.lua @@ -29,9 +29,9 @@ local report_defining = logs.reporter("fonts","defining") --ldx]]-- local fonts = fonts -local constructors = { } +local constructors = fonts.constructors or { } fonts.constructors = constructors -local handlers = { } +local handlers = fonts.handlers or { } -- can have preloaded tables fonts.handlers = handlers local specifiers = fonts.specifiers @@ -358,6 +358,10 @@ function constructors.scale(tfmdata,specification) elseif forcedsize > 1000 then -- safeguard scaledpoints = forcedsize end + targetparameters.mathsize = mathsize -- context specific + targetparameters.textsize = textsize -- context specific + targetparameters.forcedsize = forcedsize -- context specific + targetparameters.extrafactor = extrafactor -- context specific -- local tounicode = resources.tounicode local defaultwidth = resources.defaultwidth or 0 @@ -1069,7 +1073,7 @@ setmetatableindex(formats, function(t,k) t[k] = l return l end - return rawget(t,file.extname(l)) + return rawget(t,file.suffix(l)) end) local locations = { } @@ -1166,19 +1170,31 @@ function constructors.getfeatureaction(what,where,mode,name) end end -function constructors.newfeatures(what) - local features = handlers[what].features +function constructors.newhandler(what) -- could be a metatable newindex + local handler = handlers[what] + if not handler then + handler = { } + handlers[what] = handler + end + return handler +end + +function constructors.newfeatures(what) -- could be a metatable newindex + local handler = handlers[what] + local features = handler.features if not features then - local tables = handlers[what].tables -- can be preloaded + local tables = handler.tables -- can be preloaded + local statistics = handler.statistics -- can be preloaded features = allocate { defaults = { }, descriptions = tables and tables.features or { }, + used = statistics and statistics.usedfeatures or { }, initializers = { base = { }, node = { } }, processors = { base = { }, node = { } }, manipulators = { base = { }, node = { } }, } features.register = function(specification) return register(features,specification) end - handlers[what].features = features -- will also become hidden + handler.features = features -- will also become hidden end return features end diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index 4b324a6db..1b3384833 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['font-ctx'] = { -- At some point I will clean up the code here so that at the tex end -- the table interface is used. +-- +-- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true' +-- in virtual fonts indices is implemented. + +local context, commands = context, commands local texcount, texsetcount = tex.count, tex.setcount local format, gmatch, match, find, lower, gsub, byte = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte @@ -53,7 +58,7 @@ local texattribute = tex.attribute local designsizefilename = fontgoodies.designsizes.filename -local otffeatures = fonts.constructors.newfeatures("otf") +local otffeatures = handlers.otf.features local registerotffeature = otffeatures.register local baseprocessors = otffeatures.processors.base local baseinitializers = otffeatures.initializers.base @@ -141,10 +146,11 @@ local parameters = allocate() local properties = allocate() local resources = allocate() local quaddata = allocate() -- maybe also spacedata -local markdata = allocate() local xheightdata = allocate() local csnames = allocate() -- namedata +local markdata = allocate() local italicsdata = allocate() +local lastmathids = allocate() hashes.characters = chardata hashes.descriptions = descriptions @@ -152,74 +158,113 @@ hashes.parameters = parameters hashes.properties = properties hashes.resources = resources hashes.quads = quaddata -hashes.marks = markdata +hashes.emwidths = quaddata hashes.xheights = xheightdata +hashes.exheights = xheightdata hashes.csnames = csnames +hashes.marks = markdata hashes.italics = italicsdata +hashes.lastmathids = lastmathids -setmetatableindex(chardata, function(t,k) - local characters = fontdata[k].characters - t[k] = characters - return characters +setmetatableindex(chardata, function(t,k) + if k == true then + return chardata[currentfont()] + else + local characters = fontdata[k].characters + t[k] = characters + return characters + end end) -setmetatableindex(descriptions, function(t,k) - local descriptions = fontdata[k].descriptions - t[k] = descriptions - return descriptions +setmetatableindex(descriptions, function(t,k) + if k == true then + return descriptions[currentfont()] + else + local descriptions = fontdata[k].descriptions + t[k] = descriptions + return descriptions + end end) setmetatableindex(parameters, function(t,k) - local parameters = fontdata[k].parameters - t[k] = parameters - return parameters + if k == true then + return parameters[currentfont()] + else + local parameters = fontdata[k].parameters + t[k] = parameters + return parameters + end end) setmetatableindex(properties, function(t,k) - local properties = fontdata[k].properties - t[k] = properties - return properties + if k == true then + return properties[currentfont()] + else + local properties = fontdata[k].properties + t[k] = properties + return properties + end end) setmetatableindex(resources, function(t,k) - local shared = fontdata[k].shared - local rawdata = shared and shared.rawdata - local resources = rawdata and rawdata.resources - t[k] = resources or false -- better than resolving each time - return resources + if k == true then + return resources[currentfont()] + else + local shared = fontdata[k].shared + local rawdata = shared and shared.rawdata + local resources = rawdata and rawdata.resources + t[k] = resources or false -- better than resolving each time + return resources + end end) setmetatableindex(quaddata, function(t,k) - local parameters = parameters[k] - local quad = parameters and parameters.quad or 0 - t[k] = quad - return quad + if k == true then + return quaddata[currentfont()] + else + local parameters = parameters[k] + local quad = parameters and parameters.quad or 0 + t[k] = quad + return quad + end end) setmetatableindex(markdata, function(t,k) - local resources = fontdata[k].resources or { } - local marks = resources.marks or { } - t[k] = marks - return marks + if k == true then + return markdata[currentfont()] + else + local resources = fontdata[k].resources or { } + local marks = resources.marks or { } + t[k] = marks + return marks + end end) setmetatableindex(xheightdata, function(t,k) - local parameters = parameters[k] - local xheight = parameters and parameters.xheight or 0 - t[k] = xheight - return quad + if k == true then + return xheightdata[currentfont()] + else + local parameters = parameters[k] + local xheight = parameters and parameters.xheight or 0 + t[k] = xheight + return xheight + end end) setmetatableindex(italicsdata, function(t,k) -- is test ! - local properties = fontdata[k].properties - local hasitalics = properties and properties.hasitalics - if hasitalics then - hasitalics = chardata[k] -- convenient return + if k == true then + return italicsdata[currentfont()] else - hasitalics = false + local properties = fontdata[k].properties + local hasitalics = properties and properties.hasitalics + if hasitalics then + hasitalics = chardata[k] -- convenient return + else + hasitalics = false + end + t[k] = hasitalics + return hasitalics end - t[k] = hasitalics - return hasitalics end) -- this cannot be a feature initializer as there is no auto namespace @@ -750,6 +795,18 @@ local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- value local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_scaled + scale_none) local splitpattern = spaces * value * spaces * rest +function helpers.splitfontpattern(str) + local name, size = lpegmatch(splitpattern,str) + local kind, size = lpegmatch(sizepattern,size) + return name, kind, size +end + +function helpers.fontpatternhassize(str) + local name, size = lpegmatch(splitpattern,str) + local kind, size = lpegmatch(sizepattern,size) + return size or false +end + local specification -- still needed as local ? local getspecification = definers.getspecification @@ -761,6 +818,7 @@ local setdefaultfontname = context.fntsetdefname local setsomefontname = context.fntsetsomename local setemptyfontsize = context.fntsetnopsize local setsomefontsize = context.fntsetsomesize +local letvaluerelax = context.letvaluerelax function commands.definefont_one(str) statistics.starttiming(fonts) @@ -905,10 +963,12 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature end end local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?) + -- + local lastfontid = 0 if not tfmdata then report_defining("unable to define %s as [%s]",name,nice_cs(cs)) - texsetcount("global","lastfontid",-1) - context.letvaluerelax(cs) -- otherwise the current definition takes the previous one + lastfontid = -1 + letvaluerelax(cs) -- otherwise the current definition takes the previous one elseif type(tfmdata) == "number" then if trace_defining then report_defining("reusing %s with id %s as [%s] (features: %s/%s, fallbacks: %s/%s, goodies: %s/%s, designsize: %s/%s)", @@ -918,14 +978,13 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature tex.definefont(global,cs,tfmdata) -- resolved (when designsize is used): setsomefontsize(fontdata[tfmdata].parameters.size .. "sp") - texsetcount("global","lastfontid",tfmdata) + lastfontid = tfmdata else -- setting the extra characters will move elsewhere local characters = tfmdata.characters local parameters = tfmdata.parameters - -- we use char0 as signal + -- we use char0 as signal; cf the spec pdf can handle this (no char in slot) characters[0] = nil - -- cf the spec pdf can handle this (no char in slot) -- characters[0x00A0] = { width = parameters.space } -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period @@ -943,15 +1002,22 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature end -- resolved (when designsize is used): setsomefontsize((tfmdata.parameters.size or 655360) .. "sp") - --~ if specification.fallbacks then - --~ fonts.collections.prepare(specification.fallbacks) - --~ end - texsetcount("global","lastfontid",id) + lastfontid = id end if trace_defining then report_defining("memory usage after: %s",statistics.memused()) report_defining("stop stage two") end + -- + texsetcount("global","lastfontid",lastfontid) + if not mathsize then + -- forget about it + elseif mathsize == 0 then + lastmathids[1] = lastfontid + else + lastmathids[mathsize] = lastfontid + end + -- statistics.stoptiming(fonts) end @@ -1384,7 +1450,8 @@ function helpers.dimenfactor(unit,tfmdata) -- could be a method of a font instan elseif unit == "em" then return (tfmdata and tfmdata.parameters.em_width) or 655360 else - return dimenfactors[unit] or unit + local du = dimenfactors[unit] + return du and 1/du or tonumber(unit) or 1 end end @@ -1541,3 +1608,106 @@ commands.definefontfeature = fonts.specifiers.presetcontext function commands.featurelist(...) context(fonts.specifiers.contexttostring(...)) end + +-- a fontkern plug: + +local copy_node = node.copy +local kern = nodes.pool.register(nodes.pool.kern()) + +node.set_attribute(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared + +nodes.injections.installnewkern(function(k) + local c = copy_node(kern) + c.kern = k + return c +end) + +directives.register("nodes.injections.fontkern", function(v) kern.subtype = v and 0 or 1 end) + +-- here + +local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) + +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register + +local analyzers = fonts.analyzers +local methods = analyzers.methods + +local get_attribute = node.has_attribute +local set_attribute = node.set_attribute +local unset_attribute = node.unset_attribute +local traverse_by_id = node.traverse_id + +local a_color = attributes.private('color') +local a_colormodel = attributes.private('colormodel') +local a_state = attributes.private('state') +local m_color = attributes.list[a_color] or { } + +local glyph_code = nodes.nodecodes.glyph + +local names = { + "font:1", "font:2", "font:3", "font:3", -- arabic + "font:4", "font:5", "font:6", "font:7", "font:8", "font:9", -- devanagary +} + +local function markstates(head) + if head then + local model = get_attribute(head,a_colormodel) or 1 + for glyph in traverse_by_id(glyph_code,head) do + local a = get_attribute(glyph,a_state) + if a then + local name = names[a] + if name then + local color = m_color[name] + if color then + set_attribute(glyph,a_colormodel,model) + set_attribute(glyph,a_color,color) + end + end + end + end + end +end + +local function analyzeprocessor(head,font,attr) + local tfmdata = fontdata[font] + local script, language = otf.scriptandlanguage(tfmdata,attr) + local action = methods[script] + if not action then + return head, false + end + if type(action) == "function" then + local head, done = action(head,font,attr) + if done and trace_analyzing then + markstates(head) + end + return head, done + end + action = action[language] + if action then + local head, done = action(head,font,attr) + if done and trace_analyzing then + markstates(head) + end + return head, done + else + return head, false + end +end + +registerotffeature { -- adapts + name = "analyze", + processors = { + node = analyzeprocessor, + } +} + +function methods.nocolor(head,font,attr) + for n in traverse_by_id(glyph_code,head) do + if not font or n.font == font then + unset_attribute(n,a_color) + end + end + return head, true +end diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index 96de480ac..864e5bd16 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-def'] = { license = "see context related readme files" } +-- We can overload some of the definers.functions so we don't local them. + local concat = table.concat local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub local tostring, next = tostring, next @@ -42,7 +44,6 @@ definers.methods = definers.methods or { } local internalized = allocate() -- internal tex numbers (private) - local loadedfonts = constructors.loadedfonts local designsizes = constructors.designsizes @@ -72,7 +73,7 @@ and prepares a table that will move along as we proceed.</p> -- name name(sub) name(sub)*spec name*spec -- name@spec*oeps -local splitter, splitspecifiers = nil, "" +local splitter, splitspecifiers = nil, "" -- not so nice local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc @@ -83,7 +84,7 @@ local space = P(" ") definers.defaultlookup = "file" -local prefixpattern = P(false) +local prefixpattern = P(false) local function addspecifier(symbol) splitspecifiers = splitspecifiers .. symbol @@ -119,12 +120,12 @@ function definers.registersplit(symbol,action,verbosename) end end -function definers.makespecification(specification,lookup,name,sub,method,detail,size) +local function makespecification(specification,lookup,name,sub,method,detail,size) size = size or 655360 if trace_defining then report_defining("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s", - specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-", - (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-") + specification, lookup ~= "" and lookup or "[file]", name ~= "" and name or "-", + sub ~= "" and sub or "-", method ~= "" and method or "-", detail ~= "" and detail or "-") end if not lookup or lookup == "" then lookup = definers.defaultlookup @@ -144,10 +145,13 @@ function definers.makespecification(specification,lookup,name,sub,method,detail, return t end + +definers.makespecification = makespecification + function definers.analyze(specification, size) -- can be optimized with locals local lookup, name, sub, method, detail = getspecification(specification or "") - return definers.makespecification(specification, lookup, name, sub, method, detail, size) + return makespecification(specification, lookup, name, sub, method, detail, size) end --[[ldx-- @@ -194,7 +198,7 @@ function resolvers.spec(specification) if resolved then specification.resolved = resolved specification.sub = sub - specification.forced = file.extname(resolved) + specification.forced = file.suffix(resolved) specification.name = file.removesuffix(resolved) end else @@ -242,12 +246,13 @@ specification yet.</p> function definers.applypostprocessors(tfmdata) local postprocessors = tfmdata.postprocessors if postprocessors then + local properties = tfmdata.properties for i=1,#postprocessors do local extrahash = postprocessors[i](tfmdata) -- after scaling etc if type(extrahash) == "string" and extrahash ~= "" then -- e.g. a reencoding needs this extrahash = gsub(lower(extrahash),"[^a-z]","-") - tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash) + properties.fullname = format("%s-%s",properties.fullname,extrahash) end end end diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua index 331ffbdfa..560cf23ee 100644 --- a/tex/context/base/font-ext.lua +++ b/tex/context/base/font-ext.lua @@ -10,7 +10,9 @@ local utf = unicode.utf8 local next, type, byte = next, type, string.byte local gmatch, concat, format = string.gmatch, table.concat, string.format local utfchar = utf.char -local getparameters = utilities.parsers.getparameters + +local commands, context = commands, context +local fonts, utilities = fonts, utilities local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end) local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end) @@ -26,17 +28,18 @@ will depend of the font format. Here we define the few that are kind of neutral.</p> --ldx]]-- -local fonts = fonts -local fontdata = fonts.hashes.identifiers +local handlers = fonts.handlers +local hashes = fonts.hashes -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local registerotffeature = handlers.otf.features.register +local registerafmfeature = handlers.afm.features.register -local afmfeatures = fonts.constructors.newfeatures("afm") -local registerafmfeature = afmfeatures.register +local fontdata = hashes.identifiers local allocate = utilities.storage.allocate local settings_to_array = utilities.parsers.settings_to_array +local getparameters = utilities.parsers.getparameters + local setmetatableindex = table.setmetatableindex -- -- -- -- -- -- @@ -62,14 +65,15 @@ end -- expansion (hz) -- -- -- -- -- -- -fonts.expansions = allocate() -local expansions = fonts.expansions +local expansions = fonts.expansions or allocate() -expansions.classes = allocate() -local classes = expansions.classes +fonts.expansions = expansions -expansions.vectors = allocate() -local vectors = expansions.vectors +local classes = expansions.classes or allocate() +local vectors = expansions.vectors or allocate() + +expansions.classes = classes +expansions.vectors = vectors -- beware, pdftex itself uses percentages * 10 @@ -880,8 +884,8 @@ local new_glyph = nodes.pool.glyph local hpack_node = node.hpack function fonts.helpers.addprivate(tfmdata,name,characterdata) - local properties = tfmdata.properties - local privates = properties.privates + local properties = tfmdata.properties + local privates = properties.privates local lastprivate = properties.lastprivate if lastprivate then lastprivate = lastprivate + 1 @@ -903,7 +907,7 @@ end function fonts.helpers.getprivatenode(tfmdata,name) local properties = tfmdata.properties - local privates = properties and properties.privates + local privates = properties and properties.privates if privates then local p = privates[name] if p then @@ -925,7 +929,7 @@ end function fonts.helpers.hasprivate(tfmdata,name) local properties = tfmdata.properties - local privates = properties and properties.privates + local privates = properties and properties.privates return privates and privates[name] or false end diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua index 89831e7c2..69b45811a 100644 --- a/tex/context/base/font-fbk.lua +++ b/tex/context/base/font-fbk.lua @@ -9,40 +9,39 @@ if not modules then modules = { } end modules ['font-fbk'] = { local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format local utfbyte, utfchar = utf.byte, utf.char +--[[ldx-- +<p>This is very experimental code!</p> +--ldx]]-- + local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end) local trace_combining_all = false trackers.register("fonts.combining.all", function(v) trace_combining = v trace_combining_all = v end) -local force_combining = false -- just for demo purposes (see mk) trackers.register("fonts.composing", "fonts.combining") trackers.register("fonts.composing.all", "fonts.combining.all") local report_combining = logs.reporter("fonts","combining") -local allocate = utilities.storage.allocate +local force_combining = false -- just for demo purposes (see mk) ---[[ldx-- -<p>This is very experimental code!</p> ---ldx]]-- +local allocate = utilities.storage.allocate local fonts = fonts local handlers = fonts.handlers local constructors = fonts.constructors -local vf = handlers.vf -local commands = vf.combiner.commands - -local otffeatures = constructors.newfeatures("otf") -local registerotffeature = otffeatures.register -local afmfeatures = constructors.newfeatures("afm") -local registerafmfeature = afmfeatures.register +local registerotffeature = handlers.otf.features.register +local registerafmfeature = handlers.afm.features.register local unicodecharacters = characters.data local unicodefallbacks = characters.fallbacks +local vf = handlers.vf +local commands = vf.combiner.commands local push = vf.predefined.push local pop = vf.predefined.pop + local force_composed = false local cache = { } -- we could make these weak local fraction = 0.15 -- 30 units for lucida diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua index 3b87e4c77..b4b073433 100644 --- a/tex/context/base/font-gds.lua +++ b/tex/context/base/font-gds.lua @@ -8,44 +8,39 @@ if not modules then modules = { } end modules ['font-gds'] = { -- depends on ctx -local type, next = type, next +local type, next, tonumber = type, next, tonumber local gmatch, format, lower, find, splitup = string.gmatch, string.format, string.lower, string.find, string.splitup local texsp = tex.sp local fonts, nodes, attributes, node = fonts, nodes, attributes, node -local trace_goodies = false - -trackers.register("fonts.goodies", function(v) trace_goodies = v end) - +local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) local report_goodies = logs.reporter("fonts","goodies") local allocate = utilities.storage.allocate local otf = fonts.handlers.otf -local addotffeature = otf.enhancers.addfeature - -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register - -local afmfeatures = fonts.constructors.newfeatures("afm") -local registerafmfeature = afmfeatures.register +local afm = fonts.handlers.afm +local tfm = fonts.handlers.tfm -local tfmfeatures = fonts.constructors.newfeatures("tfm") -local registertfmfeature = tfmfeatures.register +local registerotffeature = otf.features.register +local registerafmfeature = afm.features.register +local registertfmfeature = tfm.features.register -local fontgoodies = { } +local fontgoodies = fonts.goodies or { } fonts.goodies = fontgoodies -local typefaces = allocate() +local typefaces = fonts.typefaces or allocate() fonts.typefaces = typefaces -local data = allocate() -fontgoodies.data = fontgoodies.data +local data = fontgoodies.data or allocate() +fontgoodies.data = data -local list = { } +local list = fontgoodies.list or { } fontgoodies.list = list -- no allocate as we want to see what is there +local addotffeature = otf.enhancers.addfeature + function fontgoodies.report(what,trace,goodies) if trace_goodies or trace then local whatever = goodies[what] @@ -141,7 +136,7 @@ end -- fonts.features.flattened = flattenedfeatures -function fontgoodies.prepare_features(goodies,name,set) +local function prepare_features(goodies,name,set) if set then local ff = flattenedfeatures(set) local fullname = goodies.name .. "::" .. name @@ -154,6 +149,8 @@ function fontgoodies.prepare_features(goodies,name,set) end end +fontgoodies.prepare_features = prepare_features + local function initialize(goodies,tfmdata) local featuresets = goodies.featuresets local goodiesname = goodies.name @@ -162,7 +159,7 @@ local function initialize(goodies,tfmdata) report_goodies("checking featuresets in '%s'",goodies.name) end for name, set in next, featuresets do - fontgoodies.prepare_features(goodies,name,set) + prepare_features(goodies,name,set) end end end @@ -177,7 +174,7 @@ local function setfeatureset(tfmdata,set,features) for i=1,#goodies do -- last one wins local g = goodies[i] - what = (g.featuresets and g.featuresets[set]) or what + what = g.featuresets and g.featuresets[set] or what end if what then for feature, value in next, what do @@ -193,12 +190,13 @@ end -- postprocessors (we could hash processor and share code) function fontgoodies.registerpostprocessor(tfmdata,f,prepend) - if not tfmdata.postprocessors then + local postprocessors = tfmdata.postprocessors + if not postprocessors then tfmdata.postprocessors = { f } elseif prepend then - table.insert(tfmdata.postprocessors,f,1) + table.insert(postprocessors,f,1) else - table.insert(tfmdata.postprocessors,f) + table.insert(postprocessors,f) end end @@ -236,9 +234,9 @@ end -- colorschemes -local colorschemes = { } +local colorschemes = fontgoodies.colorschemes or allocate { } fontgoodies.colorschemes = colorschemes -colorschemes.data = { } +colorschemes.data = colorschemes.data or { } local function setcolorscheme(tfmdata,scheme) if type(scheme) == "string" then @@ -249,7 +247,7 @@ local function setcolorscheme(tfmdata,scheme) for i=1,#goodies do -- last one counts local g = goodies[i] - what = (g.colorschemes and g.colorschemes[scheme]) or what + what = g.colorschemes and g.colorschemes[scheme] or what end if type(what) == "table" then -- this is font bound but we can share them if needed @@ -605,9 +603,10 @@ end fontgoodies.register("compositions", initialize) -local designsizes = { } +local designsizes = fontgoodies.designsizes or allocate() fontgoodies.designsizes = designsizes -local designdata = allocate() + +local designdata = designsizes.data or allocate() designsizes.data = designdata local function initialize(goodies) -- design sizes are registered global diff --git a/tex/context/base/font-gds.mkiv b/tex/context/base/font-gds.mkvi index 2305a0edd..d4760a470 100644 --- a/tex/context/base/font-gds.mkiv +++ b/tex/context/base/font-gds.mkvi @@ -37,8 +37,8 @@ \definesystemattribute[colorscheme][public] -\unexpanded\def\loadfontgoodies[#1]% - {\ctxcommand{loadfontgoodies("#1")}} +\unexpanded\def\loadfontgoodies[#filename]% + {\ctxcommand{loadfontgoodies("#filename")}} \unexpanded\def\setfontcolorscheme % will move to the lua end {\ctxcommand{enablefontcolorschemes()}% diff --git a/tex/context/base/font-ini.lua b/tex/context/base/font-ini.lua index 8eeba0ce7..884b22474 100644 --- a/tex/context/base/font-ini.lua +++ b/tex/context/base/font-ini.lua @@ -6,33 +6,27 @@ if not modules then modules = { } end modules ['font-ini'] = { license = "see context related readme files" } --- basemethods -> can also be in list --- presetcontext -> defaults --- hashfeatures -> ctx version - --[[ldx-- <p>Not much is happening here.</p> --ldx]]-- -local lower = string.lower -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate local report_defining = logs.reporter("fonts","defining") -fontloader.totable = fontloader.to_table - -fonts = fonts or { } -- already defined in context +fonts = fonts or { } local fonts = fonts --- some of these might move to where they are used first: - fonts.hashes = { identifiers = allocate() } + +fonts.tables = fonts.tables or { } +fonts.helpers = fonts.helpers or { } +fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata +fonts.specifiers = fonts.specifiers or { } -- in format ! + fonts.analyzers = { } -- not needed here fonts.readers = { } -fonts.tables = { } fonts.definers = { methods = { } } -fonts.specifiers = fonts.specifiers or { } -- in format ! fonts.loggers = { register = function() end } -fonts.helpers = { } -fonts.tracers = { } -- for the moment till we have move to moduledata +fontloader.totable = fontloader.to_table diff --git a/tex/context/base/font-ldr.lua b/tex/context/base/font-ldr.lua index ca4e3f98a..175b4d0cc 100644 --- a/tex/context/base/font-ldr.lua +++ b/tex/context/base/font-ldr.lua @@ -6,8 +6,8 @@ if not modules then modules = { } end modules ['font-ldr'] = { license = "see context related readme files" } --- This module provides a replacement for fontloader.to_table --- and will be loaded in due time. +-- This module provides an experimental replacement for fontloader.to_table +-- but is not used that much. local fields = fontloader.fields diff --git a/tex/context/base/font-lib.mkvi b/tex/context/base/font-lib.mkvi index d9c04f0a2..4ccb6057c 100644 --- a/tex/context/base/font-lib.mkvi +++ b/tex/context/base/font-lib.mkvi @@ -27,15 +27,16 @@ \registerctxluafile{font-tfm}{1.001} \registerctxluafile{font-afm}{1.001} +\registerctxluafile{font-afk}{1.001} \registerctxluafile{font-oti}{1.001} % otf initialization \registerctxluafile{font-ott}{1.001} % otf tables (first) \registerctxluafile{font-otf}{1.001} % otf main \registerctxluafile{font-otb}{1.001} % otf main base \registerctxluafile{node-inj}{1.001} % we might split it off +\registerctxluafile{font-ota}{1.001} % otf analyzers \registerctxluafile{font-otn}{1.001} % otf main node \registerctxluafile{font-otd}{1.001} % otf dynamics (does an overload) -\registerctxluafile{font-ota}{1.001} % otf analyzers (needs dynamics) \registerctxluafile{font-otp}{1.001} % otf pack \registerctxluafile{font-otc}{1.001} % otf context \registerctxluafile{font-oth}{1.001} % otf helpers @@ -56,7 +57,6 @@ \registerctxluafile{font-ext}{1.001} \registerctxluafile{font-fbk}{1.001} -\registerctxluafile{font-chk}{1.001} \registerctxluafile{font-aux}{1.001} diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua index 7f5305f9a..685f9beea 100644 --- a/tex/context/base/font-map.lua +++ b/tex/context/base/font-map.lua @@ -6,18 +6,20 @@ if not modules then modules = { } end modules ['font-map'] = { license = "see context related readme files" } +local tonumber = tonumber + local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match local utfbyte = utf.byte -local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) +local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end) local report_fonts = logs.reporter("fonts","loading") -- not otf only -local fonts = fonts -local mappings = { } -fonts.mappings = mappings +local fonts = fonts +local mappings = fonts.mappings or { } +fonts.mappings = mappings --[[ldx-- <p>Eventually this code will disappear because map files are kind @@ -40,7 +42,7 @@ end local hex = R("AF","09") local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end local hexsix = (hex^1) / function(s) return tonumber(s,16) end -local dec = (R("09")^1) / tonumber +local dec = (R("09")^1) / tonumber local period = P(".") local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) diff --git a/tex/context/base/font-mat.mkvi b/tex/context/base/font-mat.mkvi index c8ab45b75..2a4abbff0 100644 --- a/tex/context/base/font-mat.mkvi +++ b/tex/context/base/font-mat.mkvi @@ -106,6 +106,7 @@ \def\font_helpers_set_math_family_indeed#mrtag#family% \fontface etc are also used later on {\let\savedfontbody\fontbody \let\fontfamily#family% + % the order is important as we depend on known id's when completing fonts \let\fontface\!!plusthree\font_helpers_set_math_family_a\scriptscriptfont#mrtag\font \let\fontface\!!plustwo \font_helpers_set_math_family_a\scriptfont #mrtag\font \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua index 9ca357751..c0ee7dec4 100644 --- a/tex/context/base/font-mis.lua +++ b/tex/context/base/font-mis.lua @@ -46,7 +46,7 @@ end local featuregroups = { "gsub", "gpos" } function fonts.helpers.getfeatures(name,t,script,language) -- maybe per font type - local t = lower(t or (name and file.extname(name)) or "") + local t = lower(t or (name and file.suffix(name)) or "") if t == "otf" or t == "ttf" or t == "ttc" or t == "dfont" then local filename = resolvers.findfile(name,t) or "" if filename ~= "" then diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua index edf5996b3..8262f983e 100644 --- a/tex/context/base/font-ota.lua +++ b/tex/context/base/font-ota.lua @@ -40,11 +40,6 @@ local fontdata = fonts.hashes.identifiers local state = attributes.private('state') local categories = characters and characters.categories or { } -- sorry, only in context -local tracers = nodes.tracers -local colortracers = tracers and tracers.colors -local setnodecolor = colortracers and colortracers.set or function() end -local resetnodecolor = colortracers and colortracers.reset or function() end - local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -53,11 +48,22 @@ local registerotffeature = otffeatures.register process features right.</p> --ldx]]-- +analyzers.constants = { + init = 1, + medi = 2, + fina = 3, + isol = 4, + -- devanagari + rphf = 5, + half = 6, + pref = 7, + blwf = 8, + pstf = 9, +} + -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace -local state = attributes.private('state') - function analyzers.setstate(head,font) local useunicodemarks = analyzers.useunicodemarks local tfmdata = fontdata[font] @@ -117,14 +123,14 @@ end local function analyzeinitializer(tfmdata,value) -- attr local script, language = otf.scriptandlanguage(tfmdata) -- attr local action = initializers[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(tfmdata,value) + else + local action = action[language] + if action then return action(tfmdata,value) - else - local action = action[language] - if action then - return action(tfmdata,value) - end end end end @@ -133,14 +139,14 @@ local function analyzeprocessor(head,font,attr) local tfmdata = fontdata[font] local script, language = otf.scriptandlanguage(tfmdata,attr) local action = methods[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(head,font,attr) + else + action = action[language] + if action then return action(head,font,attr) - else - action = action[language] - if action then - return action(head,font,attr) - end end end return head, false @@ -239,11 +245,11 @@ local isol_fina_medi_init = { -- syriac - [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true, - [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true, - [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true, - [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true, - [0x0729] = true, [0x072B] = true, + [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true, + [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true, + [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true, + [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true, + [0x0729] = true, [0x072B] = true, -- also @@ -252,7 +258,6 @@ local isol_fina_medi_init = { local arab_warned = { } - -- todo: gref local function warning(current,what) @@ -263,37 +268,24 @@ local function warning(current,what) end end -function methods.nocolor(head,font,attr) - for n in traverse_id(glyph_code,head) do - if not font or n.font == font then - resetnodecolor(n) - end - end - return head, true -end - local function finish(first,last) if last then if first == last then local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end else local lc = last.char if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? -- if laststate == 1 or laststate == 2 or laststate == 4 then set_attribute(last,state,3) -- fina - if trace_analyzing then setnodecolor(last,"font:fina") end else warning(last,"fina") set_attribute(last,state,0) -- error - if trace_analyzing then resetnodecolor(last) end end end first, last = nil, nil @@ -302,11 +294,9 @@ local function finish(first,last) local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end first = nil end @@ -324,20 +314,16 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr local char = current.char if marks[char] or (useunicodemarks and categories[char] == "mn") then set_attribute(current,state,5) -- mark - if trace_analyzing then setnodecolor(current,"font:mark") end elseif isol[char] then -- can be zwj or zwnj too first, last = finish(first,last) set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil elseif not first then if isol_fina_medi_init[char] then set_attribute(current,state,1) -- init - if trace_analyzing then setnodecolor(current,"font:init") end first, last = first or current, current elseif isol_fina[char] then set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil else -- no arab first, last = finish(first,last) @@ -345,18 +331,15 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr elseif isol_fina_medi_init[char] then first, last = first or current, current set_attribute(current,state,2) -- medi - if trace_analyzing then setnodecolor(current,"font:medi") end elseif isol_fina[char] then if not has_attribute(last,state,1) then -- tricky, we need to check what last may be ! set_attribute(last,state,2) -- medi - if trace_analyzing then setnodecolor(last,"font:medi") end end set_attribute(current,state,3) -- fina - if trace_analyzing then setnodecolor(current,"font:fina") end first, last = nil, nil elseif char >= 0x0600 and char <= 0x06FF then - if trace_analyzing then setnodecolor(current,"font:rest") end + set_attribute(current,state,6) -- rest first, last = finish(first,last) else --no first, last = finish(first,last) diff --git a/tex/context/base/font-otb.lua b/tex/context/base/font-otb.lua index 44639a80a..04e289ba9 100644 --- a/tex/context/base/font-otb.lua +++ b/tex/context/base/font-otb.lua @@ -11,26 +11,27 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring local lpegmatch = lpeg.match local utfchar = utf.char -local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end) -local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end) -local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end) -local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end) -local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end) -local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end) -local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end) +local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end) +local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end) +local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end) +local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end) +local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end) +local trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end) +local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end) +local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end) -local report_prepare = logs.reporter("fonts","otf prepare") +local report_prepare = logs.reporter("fonts","otf prepare") -local fonts = fonts -local otf = fonts.handlers.otf +local fonts = fonts +local otf = fonts.handlers.otf -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local otffeatures = otf.features +local registerotffeature = otffeatures.register -otf.defaultbasealternate = "none" -- first last +otf.defaultbasealternate = "none" -- first last -local wildcard = "*" -local default = "dflt" +local wildcard = "*" +local default = "dflt" local function gref(descriptions,n) if type(n) == "number" then @@ -165,7 +166,7 @@ local function finalize_ligatures(tfmdata,ligatures) if ligature then local unicode, lookupdata = ligature[1], ligature[2] if trace then - print("BUILDING",concat(lookupdata," "),unicode) + trace_ligatures_detail("building %q into %q",concat(lookupdata," "),unicode) end local size = #lookupdata local firstcode = lookupdata[1] -- [2] @@ -178,7 +179,7 @@ local function finalize_ligatures(tfmdata,ligatures) if not firstdata then firstcode = private if trace then - print(" DEFINING",firstname,firstcode) + trace_ligatures_detail("defining %q as %q",firstname,firstcode) end unicodes[firstname] = firstcode firstdata = { intermediate = true, ligatures = { } } @@ -202,7 +203,7 @@ local function finalize_ligatures(tfmdata,ligatures) end end if trace then - print("CODES",firstname,firstcode,secondname,secondcode,target) + trace_ligatures_detail("codes (%s,%s) + (%s,%s) -> %s",firstname,firstcode,secondname,secondcode,target) end local firstligs = firstdata.ligatures if firstligs then diff --git a/tex/context/base/font-otc.lua b/tex/context/base/font-otc.lua index ae463e750..777267254 100644 --- a/tex/context/base/font-otc.lua +++ b/tex/context/base/font-otc.lua @@ -17,8 +17,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local registerotffeature = otf.features.register local setmetatableindex = table.setmetatableindex -- In the userdata interface we can not longer tweak the loaded font as diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index ebd487959..0bc8225de 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['font-otd'] = { license = "see context related readme files" } +local type = type local match = string.match local sequenced = table.sequenced @@ -115,16 +116,11 @@ end -- we reimplement the dataset resolver -local special_attributes = { - init = 1, - medi = 2, - fina = 3, - isol = 4 -} +local constants = fonts.analyzers.constants -local resolved = { } -- we only resolve a font,script,language,attribute pair once -local wildcard = "*" -local default = "dflt" +local resolved = { } -- we only resolve a font,script,language,attribute pair once +local wildcard = "*" +local default = "dflt" local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic) local features = sequence.features @@ -151,7 +147,7 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr what = wildcard end if valid then - local attribute = special_attributes[kind] or false + local attribute = constants[kind] or false if a_e and dynamic < 0 then valid = false end @@ -180,7 +176,7 @@ end -- return v -- end) -function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as in special parbuilder) +function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder) local script, language, s_enabled, a_enabled, dynamic @@ -220,12 +216,17 @@ function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as end local ra = rl[attr] if ra == nil then -- attr can be false - ra = { } + ra = { + -- indexed but we can also add specific data by key in: + } rl[attr] = ra + local sequences = tfmdata.resources.sequences setmetatableindex(ra, function(t,k) - local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) - t[k] = v or false - return v + if type(k) == "number" then + local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) + t[k] = v or false + return v + end end) end diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index e1339aec9..9f0fb6657 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -1114,7 +1114,7 @@ actions["prepare lookups"] = function(data,filename,raw) end -- The reverse handler does a bit redundant splitting but it's seldom --- seen so we don' tbother too much. We could store the replacement +-- seen so we don't bother too much. We could store the replacement -- in the current list (value instead of true) but it makes other code -- uglier. Maybe some day. @@ -1132,6 +1132,22 @@ local function t_uncover(splitter,cache,covers) return result end +local function s_uncover(splitter,cache,cover) + if cover == "" then + return nil + else + local uncovered = cache[cover] + if not uncovered then + uncovered = lpegmatch(splitter,cover) +-- for i=1,#uncovered do +-- uncovered[i] = { [uncovered[i]] = true } +-- end + cache[cover] = uncovered + end + return { uncovered } + end +end + local function t_hashed(t,cache) if t then local ht = { } @@ -1153,22 +1169,6 @@ local function t_hashed(t,cache) end end -local function s_uncover(splitter,cache,cover) - if cover == "" then - return nil - else - local uncovered = cache[cover] - if not uncovered then - uncovered = lpegmatch(splitter,cover) - for i=1,#uncovered do - uncovered[i] = { [uncovered[i]] = true } - end - cache[cover] = uncovered - end - return uncovered - end -end - local s_hashed = t_hashed local function r_uncover(splitter,cache,cover,replacements) @@ -1193,11 +1193,15 @@ local function r_uncover(splitter,cache,cover,replacements) end end -actions["reorganize lookups"] = function(data,filename,raw) +actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0 -- we prefer the before lookups in a normal order if data.lookups then local splitter = data.helpers.tounicodetable - local cache, h_cache = { }, { } + local t_u_cache = { } + local s_u_cache = t_u_cache -- string keys + local t_h_cache = { } + local s_h_cache = t_h_cache -- table keys (so we could use one cache) + local r_u_cache = { } -- maybe shared for _, lookup in next, data.lookups do local rules = lookup.rules if rules then @@ -1205,15 +1209,15 @@ actions["reorganize lookups"] = function(data,filename,raw) if format == "class" then local before_class = lookup.before_class if before_class then - before_class = t_uncover(splitter,cache,reversed(before_class)) + before_class = t_uncover(splitter,t_u_cache,reversed(before_class)) end local current_class = lookup.current_class if current_class then - current_class = t_uncover(splitter,cache,current_class) + current_class = t_uncover(splitter,t_u_cache,current_class) end local after_class = lookup.after_class if after_class then - after_class = t_uncover(splitter,cache,after_class) + after_class = t_uncover(splitter,t_u_cache,after_class) end for i=1,#rules do local rule = rules[i] @@ -1223,7 +1227,7 @@ actions["reorganize lookups"] = function(data,filename,raw) for i=1,#before do before[i] = before_class[before[i]] or { } end - rule.before = t_hashed(before,h_cache) + rule.before = t_hashed(before,t_h_cache) end local current = class.current local lookups = rule.lookups @@ -1234,14 +1238,14 @@ actions["reorganize lookups"] = function(data,filename,raw) lookups[i] = false -- e.g. we can have two lookups and one replacement end end - rule.current = t_hashed(current,h_cache) + rule.current = t_hashed(current,t_h_cache) end local after = class.after if after then for i=1,#after do after[i] = after_class[after[i]] or { } end - rule.after = t_hashed(after,h_cache) + rule.after = t_hashed(after,t_h_cache) end rule.class = nil end @@ -1256,18 +1260,18 @@ actions["reorganize lookups"] = function(data,filename,raw) if coverage then local before = coverage.before if before then - before = t_uncover(splitter,cache,reversed(before)) - rule.before = t_hashed(before,h_cache) + before = t_uncover(splitter,t_u_cache,reversed(before)) + rule.before = t_hashed(before,t_h_cache) end local current = coverage.current if current then - current = t_uncover(splitter,cache,current) - rule.current = t_hashed(current,h_cache) + current = t_uncover(splitter,t_u_cache,current) + rule.current = t_hashed(current,t_h_cache) end local after = coverage.after if after then - after = t_uncover(splitter,cache,after) - rule.after = t_hashed(after,h_cache) + after = t_uncover(splitter,t_u_cache,after) + rule.after = t_hashed(after,t_h_cache) end rule.coverage = nil end @@ -1279,22 +1283,22 @@ actions["reorganize lookups"] = function(data,filename,raw) if reversecoverage then local before = reversecoverage.before if before then - before = t_uncover(splitter,cache,reversed(before)) - rule.before = t_hashed(before,h_cache) + before = t_uncover(splitter,t_u_cache,reversed(before)) + rule.before = t_hashed(before,t_h_cache) end local current = reversecoverage.current if current then - current = t_uncover(splitter,cache,current) - rule.current = t_hashed(current,h_cache) + current = t_uncover(splitter,t_u_cache,current) + rule.current = t_hashed(current,t_h_cache) end local after = reversecoverage.after if after then - after = t_uncover(splitter,cache,after) - rule.after = t_hashed(after,h_cache) + after = t_uncover(splitter,t_u_cache,after) + rule.after = t_hashed(after,t_h_cache) end local replacements = reversecoverage.replacements if replacements then - rule.replacements = r_uncover(splitter,cache,current,replacements) + rule.replacements = r_uncover(splitter,r_u_cache,current,replacements) end rule.reversecoverage = nil end @@ -1305,19 +1309,19 @@ actions["reorganize lookups"] = function(data,filename,raw) local glyphs = rule.glyphs if glyphs then local fore = glyphs.fore - if fore then - fore = s_uncover(splitter,cache,fore) - rule.before = s_hashed(fore,h_cache) + if fore and fore ~= "" then + fore = s_uncover(splitter,s_u_cache,fore) + rule.before = s_hashed(fore,s_h_cache) end local back = glyphs.back if back then - back = s_uncover(splitter,cache,back) - rule.after = s_hashed(back,h_cache) + back = s_uncover(splitter,s_u_cache,back) + rule.after = s_hashed(back,s_h_cache) end local names = glyphs.names if names then - names = s_uncover(splitter,cache,names) - rule.current = s_hashed(names,h_cache) + names = s_uncover(splitter,s_u_cache,names) + rule.current = s_hashed(names,s_h_cache) end rule.glyphs = nil end @@ -1972,7 +1976,7 @@ local function read_from_otf(specification) local allfeatures = tfmdata.shared.features or specification.features.normal constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf) constructors.setname(tfmdata,specification) -- only otf? - fonts.loggers.register(tfmdata,file.extname(specification.filename),specification) + fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification) end return tfmdata end diff --git a/tex/context/base/font-oti.lua b/tex/context/base/font-oti.lua index d6853db31..06c2a42fa 100644 --- a/tex/context/base/font-oti.lua +++ b/tex/context/base/font-oti.lua @@ -8,15 +8,16 @@ if not modules then modules = { } end modules ['font-oti'] = { local lower = string.lower -local allocate = utilities.storage.allocate - local fonts = fonts -local otf = { } -fonts.handlers.otf = otf +local constructors = fonts.constructors -local otffeatures = fonts.constructors.newfeatures("otf") +local otf = constructors.newhandler("otf") +local otffeatures = constructors.newfeatures("otf") +local otftables = otf.tables local registerotffeature = otffeatures.register +local allocate = utilities.storage.allocate + registerotffeature { name = "features", description = "initialization of feature handler", @@ -25,8 +26,6 @@ registerotffeature { -- these are later hooked into node and base initializaters -local otftables = otf.tables -- not always defined - local function setmode(tfmdata,value) if value then tfmdata.properties.mode = lower(value) diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index d97ef7363..2c670825a 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -116,6 +116,8 @@ results in different tables.</p> -- we now use only one hash. If needed we can have multiple again but in that -- case I will probably prefix (i.e. rename) the lookups in the cached font file. +-- Todo: make plugin feature that operates on char/glyphnode arrays + local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip local type, next, tonumber, tostring = type, next, tonumber, tostring @@ -151,6 +153,7 @@ local report_subchain = logs.reporter("fonts","otf subchain") local report_chain = logs.reporter("fonts","otf chain") local report_process = logs.reporter("fonts","otf process") local report_prepare = logs.reporter("fonts","otf prepare") +local report_warning = logs.reporter("fonts","otf warning") registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) @@ -310,105 +313,229 @@ local function pref(kind,lookupname) return format("feature %s, lookup %s",kind,lookupname) end --- we can assume that languages that use marks are not hyphenated --- we can also assume that at most one discretionary is present - -local function markstoligature(kind,lookupname,start,stop,char) - local n = copy_node(start) - local keep = start - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current +-- We can assume that languages that use marks are not hyphenated. We can also assume +-- that at most one discretionary is present. + +-- We do need components in funny kerning mode but maybe I can better reconstruct then +-- as we do have the font components info available; removing components makes the +-- previous code much simpler. Also, later on copying and freeing becomes easier. +-- However, for arabic we need to keep them around for the sake of mark placement +-- and indices. + +local function copy_glyph(g) -- next and prev are untouched ! + local components = g.components + if components then + g.components = nil + local n = copy_node(g) + g.components = components + return n + else + return copy_node(g) end - start.prev, stop.next = nil, nil - current.char, current.subtype, current.components = char, ligature_code, start - return keep end -local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head - if start == stop then - start.char = char +-- start is a mark and we need to keep that one + +-- local function markstoligature(kind,lookupname,start,stop,char) +-- -- [start]..[stop] +-- local keep = start +-- local prev = start.prev +-- local next = stop.next +-- local base = copy_glyph(start) +-- local current, start = insert_node_after(start,start,base) +-- -- [current][start]..[stop] +-- current.next = next +-- if next then +-- next.prev = current +-- end +-- start.prev = nil +-- stop.next = nil +-- current.char = char +-- current.subtype = ligature_code +-- current.components = start +-- return keep +-- end + +local function markstoligature(kind,lookupname,start,stop,char) + if start == stop and start.char == char then return start - elseif discfound then - -- print("start->stop",nodes.tosequence(start,stop)) - local components = start.components - if components then - flush_node_list(components) - start.components = nil - end - local lignode = copy_node(start) - lignode.font = start.font - lignode.char = char - lignode.subtype = ligature_code - local next = stop.next + else local prev = start.prev - stop.next = nil + local next = stop.next start.prev = nil - lignode.components = start - -- print("lignode",nodes.tosequence(lignode)) - -- print("components",nodes.tosequence(lignode.components)) - prev.next = lignode + stop.next = nil + local base = copy_glyph(start) + base.char = char + base.subtype = ligature_code + base.components = start + if prev then + prev.next = base + end if next then - next.prev = lignode + next.prev = base end - lignode.next = next - lignode.prev = prev - -- print("start->end",nodes.tosequence(start)) - return lignode + base.next = next + base.prev = prev + return base + end +end + +-- The next code is somewhat complicated by the fact that some fonts can have ligatures made +-- from ligatures that themselves have marks. This was identified by Kai in for instance +-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes +-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next +-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the +-- third component. + +local function getcomponentindex(start) + if start.id ~= glyph_code then + return 0 + elseif start.subtype == ligature_code then + local i = 0 + local components = start.components + while components do + i = i + getcomponentindex(components) + components = components.next + end + return i + elseif not marks[start.char] then + return 1 else - -- start is the ligature + return 0 + end +end + +-- local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head +-- if start == stop and start.char == char then +-- start.char = char +-- return start +-- elseif discfound then +-- local prev = start.prev +-- local next = stop.next +-- start.prev = nil +-- stop.next = nil +-- local base = copy_glyph(start) +-- base.char = char +-- base.subtype = ligature_code +-- base.components = start -- start can have components +-- if prev then +-- prev.next = base +-- end +-- if next then +-- next.prev = base +-- end +-- base.next = next +-- base.prev = prev +-- return base +-- else +-- -- start is the ligature +-- local deletemarks = markflag ~= "mark" +-- local prev = start.prev +-- local next = stop.next +-- local base = copy_glyph(start) +-- local current, start = insert_node_after(start,start,base) +-- -- [start->current][copyofstart->start]...[stop] +-- current.next = next +-- if next then +-- next.prev = current +-- end +-- start.prev = nil +-- stop.next = nil +-- current.char = char +-- current.subtype = ligature_code +-- current.components = start +-- local head = current +-- -- this is messy ... we should get rid of the components eventually +-- local baseindex = 0 +-- local componentindex = 0 +-- while start do +-- local char = start.char +-- if not marks[char] then +-- baseindex = baseindex + componentindex +-- componentindex = getcomponentindex(start) +-- elseif not deletemarks then -- quite fishy +-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) +-- if trace_marks then +-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) +-- end +-- head, current = insert_node_after(head,current,copy_glyph(start)) -- unlikely that mark has components +-- end +-- start = start.next +-- end +-- start = current.next +-- while start and start.id == glyph_code do -- hm, is id test needed ? +-- local char = start.char +-- if marks[char] then +-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) +-- if trace_marks then +-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) +-- end +-- else +-- break +-- end +-- start = start.next +-- end +-- return head +-- end +-- end + +local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head + if start == stop and start.char == char then + start.char = char + return start + end + local prev = start.prev + local next = stop.next + start.prev = nil + stop.next = nil + local base = copy_glyph(start) + base.char = char + base.subtype = ligature_code + base.components = start -- start can have components + if prev then + prev.next = base + end + if next then + next.prev = base + end + base.next = next + base.prev = prev + if not discfound then local deletemarks = markflag ~= "mark" - local n = copy_node(start) - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current - end - start.prev = nil - stop.next = nil - current.char = char - current.subtype = ligature_code - current.components = start - local head = current - -- this is messy ... we should get rid of the components eventually - local i = 0 -- is index of base + local components = start + local baseindex = 0 + local componentindex = 0 + local head = base + local current = base while start do - if not marks[start.char] then - i = i + 1 + local char = start.char + if not marks[char] then + baseindex = baseindex + componentindex + componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - set_attribute(start,ligacomp,i) + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end - head, current = insert_node_after(head,current,copy_node(start)) + head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components end start = start.next end - start = current.next - while start and start.id == glyph_code do - if marks[start.char] then - set_attribute(start,ligacomp,i) + local start = components + while start and start.id == glyph_code do -- hm, is id test needed ? + local char = start.char + if marks[char] then + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end else break end start = start.next end - -- - -- we do need components in funny kerning mode but maybe I can better reconstruct then - -- as we do have the font components info available; removing components makes the - -- previous code much simpler - -- - -- flush_node_list(head.components) - return head end + return base end function handlers.gsub_single(start,kind,lookupname,replacement) @@ -463,7 +590,7 @@ local function multiple_glyphs(start,multiple) -- marks ? if nofmultiples > 1 then local sn = start.next for k=2,nofmultiples do -- todo: use insert_node - local n = copy_node(start) + local n = copy_node(start) -- ignore components n.char = multiple[k] n.next = sn n.prev = start @@ -488,12 +615,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) local choice = get_alternative_glyph(start,alternative,value) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice) + logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),choice) end start.char = choice else if trace_alternatives then - logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char)) + logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char)) end end return start, true @@ -987,6 +1114,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start repeat -- start x x m x x stop => start m local next = start.next if not marks[next.char] then +local components = next.components +if components then -- probably not needed + flush_node_list(components) +end delete_node(start,next) end n = n + 1 @@ -994,6 +1125,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start else -- start x x x stop => start repeat local next = start.next +local components = next.components +if components then -- probably not needed + flush_node_list(components) +end delete_node(start,next) n = n + 1 until next == stop @@ -1722,7 +1857,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence break end prev = prev.prev - elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces + elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces n = n -1 else match = false @@ -1962,12 +2097,7 @@ end) -- fonts.hashes.lookups = lookuphashes -local special_attributes = { - init = 1, - medi = 2, - fina = 3, - isol = 4 -} +local constants = fonts.analyzers.constants local function initialize(sequence,script,language,enabled) local features = sequence.features @@ -1977,7 +2107,7 @@ local function initialize(sequence,script,language,enabled) if valid then local languages = scripts[script] or scripts[wildcard] if languages and (languages[language] or languages[wildcard]) then - return { valid, special_attributes[kind] or false, sequence.chain or 0, kind, sequence } + return { valid, constants[kind] or false, sequence.chain or 0, kind, sequence } end end end @@ -1985,7 +2115,7 @@ local function initialize(sequence,script,language,enabled) return false end -function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context +function otf.dataset(tfmdata,font) -- generic variant, overloaded in context local shared = tfmdata.shared local properties = tfmdata.properties local language = properties.language or "dflt" @@ -2003,12 +2133,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c end local rl = rs[language] if not rl then - rl = { } + rl = { + -- indexed but we can also add specific data by key + } rs[language] = rl + local sequences = tfmdata.resources.sequences setmetatableindex(rl, function(t,k) - local v = enabled and initialize(sequences[k],script,language,enabled) - t[k] = v - return v + if type(k) == "number" then + local v = enabled and initialize(sequences[k],script,language,enabled) + t[k] = v + return v + end end) end return rl @@ -2030,6 +2165,8 @@ end -- start = start.next -- end +-- there will be a new direction parser (pre-parsed etc) + local function featuresprocessor(head,font,attr) local lookuphash = lookuphashes[font] -- we can also check sequences here @@ -2057,7 +2194,7 @@ local function featuresprocessor(head,font,attr) local sequences = resources.sequences local done = false - local datasets = otf.dataset(tfmdata,sequences,font,attr) + local datasets = otf.dataset(tfmdata,font,attr) local dirstack = { } -- could move outside function @@ -2066,6 +2203,9 @@ local function featuresprocessor(head,font,attr) -- to keep track of directions anyway. Also at some point I want to play with -- font interactions and then we do need the full sweeps. + -- Keeping track of the headnode is needed for devanagari (I generalized it a bit + -- so that multiple cases are also covered. + for s=1,#sequences do local dataset = datasets[s] if dataset then @@ -2101,8 +2241,12 @@ local function featuresprocessor(head,font,attr) if lookupcache then local lookupmatch = lookupcache[start.char] if lookupmatch then + local headnode = start == head start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then + if headnode then + head = start + end break end end @@ -2146,10 +2290,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then success = true + if headnode then + head = start + end end end if start then start = start.next end @@ -2219,10 +2367,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then success = true + if headnode then + head = start + end break end end @@ -2548,3 +2700,7 @@ registerotffeature { node = featuresprocessor, } } + +-- this will change but is needed for an experiment: + +otf.handlers = handlers diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua index f019ade7f..6c9827de8 100644 --- a/tex/context/base/font-otp.lua +++ b/tex/context/base/font-otp.lua @@ -17,14 +17,18 @@ local report_otf = logs.reporter("fonts","otf loading") -- also used in other scripts so we need to check some tables: fonts = fonts or { } -fonts.handlers = fonts.handlers or { } -local handlers = fonts.handlers -handlers.otf = handlers.otf or { } -local otf = handlers.otf -otf.enhancers = otf.enhancers or { } -local enhancers = otf.enhancers -otf.glists = otf.glists or { "gsub", "gpos" } -local glists = otf.glists + +local handlers = fonts.handlers or { } +fonts.handlers = handlers + +local otf = handlers.otf or { } +handlers.otf = otf + +local enhancers = otf.enhancers or { } +otf.enhancers = enhancers + +local glists = otf.glists or { "gsub", "gpos" } +otf.glists = glists local criterium = 1 local threshold = 0 @@ -43,12 +47,30 @@ local function tabstr(t) s[n] = k .. "=false" end end - sort(s) - return concat(s,",") + if n == 1 then + return s[1] + else + sort(s) + return concat(s,",") + end end + +-- -- saves only a few tens of bytes +-- +-- local function stripdata(data) +-- for k, v in next, data do +-- if not v or v == "" then +-- data[k] = nil +-- elseif type(v) == "table" then +-- stripdata(v) -- keep empty tables +-- end +-- end +-- end + local function packdata(data) if data then + -- stripdata(data) local h, t, c = { }, { }, { } local hh, tt, cc = { }, { }, { } local nt, ntt = 0, 0 @@ -202,21 +224,10 @@ local function packdata(data) if rules then for i=1,#rules do -- was next loop local rule = rules[i] ---~ local r = rule.before if r then for i=1,#r do r[i] = pack(r[i],true) end end ---~ local r = rule.after if r then for i=1,#r do r[i] = pack(r[i],true) end end ---~ local r = rule.current if r then for i=1,#r do r[i] = pack(r[i],true) end end ---~ local r = rule.replacements if r then rule.replacements = pack(r, true) end ---~ local r = rule.fore if r then rule.fore = pack(r, true) end ---~ local r = rule.back if r then rule.back = pack(r, true) end ---~ local r = rule.names if r then rule.names = pack(r, true) end ---~ local r = rule.lookups if r then rule.lookups = pack(r) end local r = rule.before if r then for i=1,#r do r[i] = pack(r[i]) end end local r = rule.after if r then for i=1,#r do r[i] = pack(r[i]) end end local r = rule.current if r then for i=1,#r do r[i] = pack(r[i]) end end local r = rule.replacements if r then rule.replacements = pack(r) end - -- local r = rule.fore if r then rule.fore = pack(r) end - -- local r = rule.back if r then rule.back = pack(r) end - -- local r = rule.names if r then rule.names = pack(r) end local r = rule.lookups if r then rule.lookups = pack(r) end end end diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 6c671d76f..c0a6c4d27 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -1,9 +1,10 @@ -if not modules then modules = { } end modules ['font-otf'] = { +if not modules then modules = { } end modules ['font-ott'] = { version = 1.001, comment = "companion to font-otf.lua (tables)", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + -- dataonly = true, } local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset @@ -16,11 +17,14 @@ local allocate = utilities.storage.allocate local fonts = fonts local otf = fonts.handlers.otf -local tables = { } +local otffeatures = otf.features +local registerotffeature = otffeatures.register + +local tables = otf.tables or { } otf.tables = tables -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local statistics = otf.statistics or { } +otf.statistics = statistics local scripts = allocate { ['arab'] = 'arabic', @@ -577,26 +581,26 @@ local features = allocate { ['size'] = 'optical size', ['smcp'] = 'small capitals', ['smpl'] = 'simplified forms', - ['ss01'] = 'stylistic set 1', - ['ss02'] = 'stylistic set 2', - ['ss03'] = 'stylistic set 3', - ['ss04'] = 'stylistic set 4', - ['ss05'] = 'stylistic set 5', - ['ss06'] = 'stylistic set 6', - ['ss07'] = 'stylistic set 7', - ['ss08'] = 'stylistic set 8', - ['ss09'] = 'stylistic set 9', - ['ss10'] = 'stylistic set 10', - ['ss11'] = 'stylistic set 11', - ['ss12'] = 'stylistic set 12', - ['ss13'] = 'stylistic set 13', - ['ss14'] = 'stylistic set 14', - ['ss15'] = 'stylistic set 15', - ['ss16'] = 'stylistic set 16', - ['ss17'] = 'stylistic set 17', - ['ss18'] = 'stylistic set 18', - ['ss19'] = 'stylistic set 19', - ['ss20'] = 'stylistic set 20', + -- ['ss01'] = 'stylistic set 1', + -- ['ss02'] = 'stylistic set 2', + -- ['ss03'] = 'stylistic set 3', + -- ['ss04'] = 'stylistic set 4', + -- ['ss05'] = 'stylistic set 5', + -- ['ss06'] = 'stylistic set 6', + -- ['ss07'] = 'stylistic set 7', + -- ['ss08'] = 'stylistic set 8', + -- ['ss09'] = 'stylistic set 9', + -- ['ss10'] = 'stylistic set 10', + -- ['ss11'] = 'stylistic set 11', + -- ['ss12'] = 'stylistic set 12', + -- ['ss13'] = 'stylistic set 13', + -- ['ss14'] = 'stylistic set 14', + -- ['ss15'] = 'stylistic set 15', + -- ['ss16'] = 'stylistic set 16', + -- ['ss17'] = 'stylistic set 17', + -- ['ss18'] = 'stylistic set 18', + -- ['ss19'] = 'stylistic set 19', + -- ['ss20'] = 'stylistic set 20', ['ssty'] = 'script style', -- math ['subs'] = 'subscript', ['sups'] = 'superscript', @@ -622,7 +626,11 @@ local features = allocate { ['trep'] = 'traditional tex replacements', ['tlig'] = 'traditional tex ligatures', - ['ss'] = 'stylistic set %s', + ['ss..'] = 'stylistic set ..', + ['cv..'] = 'character variant ..', + ['js..'] = 'justification ..', + + ["dv.."] = "devanagari ..", } local baselines = allocate { @@ -635,16 +643,16 @@ local baselines = allocate { ['romn'] = 'roman baseline' } -local acceptscripts = true directives.register("otf.acceptscripts", function(v) acceptscripts = v end) -local acceptlanguages = true directives.register("otf.acceptlanguages", function(v) acceptlanguages = v end) - -local report_checks = logs.reporter("fonts","checks") - tables.scripts = scripts tables.languages = languages tables.features = features tables.baselines = baselines +local acceptscripts = true directives.register("otf.acceptscripts", function(v) acceptscripts = v end) +local acceptlanguages = true directives.register("otf.acceptlanguages", function(v) acceptlanguages = v end) + +local report_checks = logs.reporter("fonts","checks") + -- hm, we overload the metatables if otffeatures.features then @@ -684,6 +692,10 @@ setmetatableindex(verboselanguages, resolve) setmetatableindex(verbosefeatures, resolve) setmetatableindex(verbosebaselines, resolve) +-- We could optimize the next lookups by using an extra metatable and storing +-- already found values but in practice there are not that many lookups so +-- it's never a bottleneck. + setmetatableindex(scripts, function(t,k) if k then k = lower(k) @@ -750,7 +762,12 @@ local function resolve(t,k) if tag and dd then local v = rawget(t,tag) if v then - return format(v,tonumber(dd)) + return v -- return format(v,tonumber(dd)) -- old way + else + local v = rawget(t,tag.."..") -- nicer in overview + if v then + return (gsub(v,"%.%.",tonumber(dd))) -- new way + end end end end @@ -760,10 +777,10 @@ end setmetatableindex(features, resolve) local function assign(t,k,v) - if k then + if k and v then v = lower(v) - rawset(t,k,v) - rawset(features,gsub(v,"[^a-z0-9]",""),k) + rawset(t,k,v) -- rawset ? + -- rawset(features,gsub(v,"[^a-z0-9]",""),k) -- why ? old code end end @@ -775,31 +792,85 @@ local checkers = { end } -function otf.features.normalize(features) -- no longer 'lang' +-- Keep this: +-- +-- function otf.features.normalize(features) +-- if features then +-- local h = { } +-- for k, v in next, features do +-- k = lower(k) +-- if k == "language" then +-- v = gsub(lower(v),"[^a-z0-9]","") +-- h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds +-- elseif k == "script" then +-- v = gsub(lower(v),"[^a-z0-9]","") +-- h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds +-- else +-- if type(v) == "string" then +-- local b = is_boolean(v) +-- if type(b) == "nil" then +-- v = tonumber(v) or lower(v) +-- else +-- v = b +-- end +-- end +-- if not rawget(features,k) then +-- k = rawget(verbosefeatures,k) or k +-- end +-- local c = checkers[k] +-- h[k] = c and c(v) or v +-- end +-- end +-- return h +-- end +-- end + +-- inspect(fonts.handlers.otf.statistics.usedfeatures) + +local usedfeatures = statistics.usedfeatures or { } +statistics.usedfeatures = usedfeatures + +table.setmetatableindex(usedfeatures, function(t,k) if k then local v = { } t[k] = v return v end end) -- table.autotable + +storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.statistics.usedfeatures" ) + +function otf.features.normalize(features) if features then local h = { } - for k, v in next, features do - k = lower(k) + for key, value in next, features do + local k = lower(key) if k == "language" then - v = gsub(lower(v),"[^a-z0-9]","") + local v = gsub(lower(value),"[^a-z0-9]","") h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds elseif k == "script" then - v = gsub(lower(v),"[^a-z0-9]","") + local v = gsub(lower(value),"[^a-z0-9]","") h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds else - if type(v) == "string" then - local b = is_boolean(v) - if type(b) == "nil" then - v = tonumber(v) or lower(v) + local uk = usedfeatures[key] + local uv = uk[value] + if uv then + -- report_checks("feature value %q first seen at %q",value,key) + else + if type(value) == "string" then + local b = is_boolean(value) + if type(b) == "nil" then + uv = tonumber(value) or lower(value) + else + uv = b + end else - v = b + uv = v end + if not rawget(features,k) then + k = rawget(verbosefeatures,k) or k + end + local c = checkers[k] + if c then + uv = c(uv) or vc + end + uk[value] = uv end - if not rawget(features,k) then - k = rawget(verbosefeatures,k) or k - end - local c = checkers[k] - h[k] = c and c(v) or v + h[k] = uv end end return h diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua index b91502c74..50d99f668 100644 --- a/tex/context/base/font-pat.lua +++ b/tex/context/base/font-pat.lua @@ -6,11 +6,13 @@ if not modules then modules = { } end modules ['font-pat'] = { license = "see context related readme files" } +-- This functiononality is nowadays provided via lfg files so what you see here +-- is more an example. + local match, lower = string.match, string.lower --- older versions of latin modern didn't have the designsize set --- so for them we get it from the name --- reporter moved to elsewhere +-- Older versions of latin modern didn't have the designsize set so for them we +-- get it from the name reporter moved to elsewhere. local fonts = fonts local otf = fonts.handlers.otf @@ -32,9 +34,9 @@ register("after","migrate metadata","^lmroman", patch) register("after","migrate metadata","^lmsans", patch) register("after","migrate metadata","^lmtypewriter",patch) --- for some reason (either it's a bug in the font, or it's --- a problem in the library) the palatino arabic fonts don't --- have the mkmk features properly set up +-- For some reason (either it's a bug in the font, or it's a problem in the +-- library) the palatino arabic fonts don't have the mkmk features properly +-- set up. local function patch(data,filename) local gpos = data.gpos diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv index 141bfd2ff..8d3edb9ec 100644 --- a/tex/context/base/font-pre.mkiv +++ b/tex/context/base/font-pre.mkiv @@ -169,7 +169,35 @@ \definecolor[font:fina][b=.75] \definecolor[font:isol][r=.75,g=.75] % [y=.75] \definecolor[font:mark][r=.75,b=.75] % [m=.75] -\definecolor[font:rest][g=.75,b=.75] % [c=.75] +\definecolor[font:rest][b=.75,g=.75] % [c=.75] + +\definecolor[trace:r][r=.75,t=.5,a=1] +\definecolor[trace:g][g=.75,t=.5,a=1] +\definecolor[trace:b][b=.75,t=.5,a=1] +\definecolor[trace:c][c=.75,t=.5,a=1] +\definecolor[trace:m][m=.75,t=.5,a=1] +\definecolor[trace:y][y=.75,t=.5,a=1] +\definecolor[trace:s][s=.75,t=.5,a=1] +\definecolor[trace:o][r=1,g=.6,b=.1,t=.5,a=1] + +\definecolor[trace:dr][r=.75,t=.75,a=1] +\definecolor[trace:dg][g=.75,t=.75,a=1] +\definecolor[trace:db][b=.75,t=.75,a=1] +\definecolor[trace:dc][c=.75,t=.75,a=1] +\definecolor[trace:dm][m=.75,t=.75,a=1] +\definecolor[trace:dy][y=.75,t=.75,a=1] +\definecolor[trace:ds][s=.75,t=.75,a=1] +\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1] + +\definecolor[font:1] [r=.75] +\definecolor[font:2] [g=.75] +\definecolor[font:3] [b=.75] +\definecolor[font:4] [r=.75,g=.75] +\definecolor[font:5] [r=.75,b=.75] +\definecolor[font:6] [b=.75,g=.75] +\definecolor[font:7] [r=.75] +\definecolor[font:8] [g=.75] +\definecolor[font:9] [b=.75] %D Now we're up to some definitions. diff --git a/tex/context/base/font-run.mkiv b/tex/context/base/font-run.mkiv index b346de5e1..66f1acc91 100644 --- a/tex/context/base/font-run.mkiv +++ b/tex/context/base/font-run.mkiv @@ -13,7 +13,7 @@ %C details. %D [This code is hooked into the core macros and saves some -%D format space.] +%D format space. It needs a cleanup.] \unprotect @@ -31,7 +31,7 @@ {\doifnot{[\fontclass]}\title {\edef\title{[\fontclass]\space\title}}}} -\gdef\showbodyfont +\unexpanded\gdef\showbodyfont {\dosingleempty\doshowbodyfont} \gdef\doshowbodyfont[#1]% @@ -40,9 +40,9 @@ {\dosetshowfonttitle{#1}% \def\bigstrut##1##2% {\hbox{\vrule - \!!height##1\strutht - \!!depth ##2\strutdp - \!!width \zeropoint}} + \s!height##1\strutht + \s!depth ##2\strutdp + \s!width \zeropoint}} \def\next##1##2##3% {&&##1&&##2\tf##3&&##2\sc##3% &&##2\sl##3&&##2\it##3&&##2\bf##3&&##2\bs##3&&##2\bi##3% @@ -50,7 +50,7 @@ &&##2\tfa##3&&##2\tfb##3&&##2\tfc##3&&##2\tfd##3&\cr}% \halign to \localhsize {\bigstrut{1.5}{2}##&\vrule## - \tabskip=\!!zeropoint \!!plus 1fill + \tabskip\zeropoint \s!plus 1\s!fill &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## @@ -58,7 +58,7 @@ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule - \tabskip=\!!zeropoint\cr + \tabskip=\zeropoint\cr \noalign{\hrule} &\multispan{29}{\vrule\hfil\tttf\strut\title\hfil \llap{\string\mr\hbox to 1em{\hss:\hss}$\mr \languageparameter\c!text$\quad}\vrule}\cr @@ -69,7 +69,7 @@ \noalign{\hrule}}} \ifinsidefloat\else\stopbaselinecorrection\fi} -\gdef\showbodyfontenvironment +\unexpanded\gdef\showbodyfontenvironment {\dosingleempty\doshowbodyfontenvironment} \gdef\doshowbodyfontenvironment[#1]% @@ -89,7 +89,7 @@ \noalign{\hrule}} \halign to \localhsize {##&\vrule##\strut - \tabskip=\!!zeropoint \!!plus 1fill + \tabskip=\zeropoint \s!plus 1\s!fill &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule## &\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule @@ -104,7 +104,7 @@ \@EA\globalprocesscommalist\@EA[\bodyfontenvironmentlist]\next}} \ifinsidefloat\else\stopbaselinecorrection\fi} -\gdef\showfont +\unexpanded\gdef\showfont {\dodoubleempty\doshowfont} \gdef\doshowfont[#1][#2]% @@ -132,7 +132,6 @@ \gdef\dodoshowfont#1#2% {\bgroup \edef\charplane{\number#2}% - \boxrulewidth=.1pt \iffirstargument % \definefont[\s!dummy][#1]\dummy \else\ifdim2.5em>.05\hsize \tx @@ -159,7 +158,7 @@ \donetrue \else \donefalse \fi \else - \setbox\scratchbox\hbox{\gray\vrule\!!width1ex\!!height.5ex\!!depth.5ex}% + \setbox\scratchbox\hbox{\gray\vrule\s!width1ex\s!height.5ex\s!depth.5ex}% \fi \startoverlay {\tf\vbox to 2.5em @@ -206,9 +205,9 @@ % \showfontstyle[modern][rm][tf][all] % #2, #3 and #4 can be 'all' -\gdef\showfontstyle {\dodoubleempty \dodoshowfontstyle} -\gdef\redoshowfontstyle {\dotripleempty \dododoshowfontstyle} -\gdef\redodoshowfontstyle{\doquadrupleempty\dodododoshowfontstyle} +\unexpanded\gdef\showfontstyle {\dodoubleempty \dodoshowfontstyle} +\unexpanded\gdef\redoshowfontstyle {\dotripleempty \dododoshowfontstyle} +\unexpanded\gdef\redodoshowfontstyle{\doquadrupleempty\dodododoshowfontstyle} % no lists any more, so no 'all' any longer @@ -254,10 +253,10 @@ \processcommalist[#2]\docommand \egroup} -\gdef\showligature#1% +\unexpanded\gdef\showligature#1% {\hbox{\type{#1}\enspace\red\ruledhbox{\black#1}}} -\gdef\showligatures[#1]% +\unexpanded\gdef\showligatures[#1]% {\ifx\starttabulate\undefined \@@onlyenglish\showligatures \else @@ -273,7 +272,7 @@ \egroup \fi} -\gdef\showfontstrip +\unexpanded\gdef\showfontstrip {\dosingleempty\doshowfontstrip} \gdef\doshowfontstrip[#1]% @@ -310,9 +309,9 @@ \egroup \fi} -\ifx\databox\undefined \newbox\databox \fi +\ifdefined\databox \else \newbox\databox \fi -\gdef\testminimalbaseline#1% +\unexpanded\gdef\testminimalbaseline#1% {\setbox\databox\ruledhbox{#1}% \scratchdimen\ht\databox \advance\scratchdimen\dp\databox @@ -332,7 +331,7 @@ \noexpand \NC (\ifdim\scratchdimen>\baselineskip not \fi ok) \noexpand \NC \noexpand \NR }} -\gdef\showminimalbaseline +\unexpanded\gdef\showminimalbaseline {\ifx\starttabulate\undefined \@@onlyenglish\showminimalbaseline \else @@ -343,20 +342,20 @@ \stoptabulate \fi} -\gdef\showkerning#1% +\unexpanded\gdef\showkerning#1% {\bgroup \let\MPfshowcommand\ruledhbox \setMPtext\s!dummy{#1}% \startMPcode draw textext(\MPstring\s!dummy);\stopMPcode \egroup} -\gdef\showcharratio +\unexpanded\gdef\showcharratio {\dowithnextboxcontent {\switchtobodyfont[10pt]}% {(\withoutpt\the\nextboxht,\withoutpt\the\nextboxdp)}% \hbox} -\gdef\showfontparameters +\unexpanded\gdef\showfontparameters {\starttabulate[|tl|l|] \NC slantperpoint \NC \the\fontslantperpoint \font \NC\NR \NC interwordspace \NC \the\fontinterwordspace \font \NC\NR diff --git a/tex/context/base/font-set.mkvi b/tex/context/base/font-set.mkvi index 8e4044267..c5450a152 100644 --- a/tex/context/base/font-set.mkvi +++ b/tex/context/base/font-set.mkvi @@ -121,7 +121,7 @@ \unexpanded\def\font_preloads_fourth_stage {\begingroup %ifzeropt\fontcharwd\font\number`!\relax - \setbox\scratchbox\hbox{context}% + \setbox\scratchbox\hbox{checking fonts}% \ifzeropt\wd\scratchbox \writeline \writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}% diff --git a/tex/context/base/font-sol.lua b/tex/context/base/font-sol.lua new file mode 100644 index 000000000..b44594349 --- /dev/null +++ b/tex/context/base/font-sol.lua @@ -0,0 +1,898 @@ +if not modules then modules = { } end modules ['font-sol'] = { -- this was: node-spl + version = 1.001, + comment = "companion to font-sol.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This module is dedicated to the oriental tex project and for +-- the moment is too experimental to be publicly supported. +-- +-- We could cache solutions: say that we store the featureset and +-- all 'words' -> replacement ... so we create a large solution +-- database (per font) +-- +-- This module can be optimized by using a dedicated dynamics handler +-- but I'll only do that when the rest of the code is stable. +-- +-- Todo: bind setups to paragraph. + +local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove +local next, tostring, tonumber = next, tostring, tonumber +local insert, remove = table.insert, table.remove +local utfchar = utf.char +local random = math.random + +local utilities, logs, statistics, fonts, trackers = utilities, logs, statistics, fonts, trackers +local interfaces, commands, attributes = interfaces, commands, attributes +local nodes, node, tex = nodes, node, tex + +local trace_split = false trackers.register("builders.paragraphs.solutions.splitters.splitter", function(v) trace_split = v end) +local trace_optimize = false trackers.register("builders.paragraphs.solutions.splitters.optimizer", function(v) trace_optimize = v end) +local trace_colors = false trackers.register("builders.paragraphs.solutions.splitters.colors", function(v) trace_colors = v end) +local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) + +local report_solutions = logs.reporter("fonts","solutions") +local report_splitters = logs.reporter("fonts","splitters") +local report_optimizers = logs.reporter("fonts","optimizers") + +local variables = interfaces.variables + +local v_normal = variables.normal +local v_reverse = variables.reverse +local v_preroll = variables.preroll +local v_random = variables.random +local v_split = variables.split + +local settings_to_array = utilities.parsers.settings_to_array +local settings_to_hash = utilities.parsers.settings_to_hash + +local find_node_tail = node.tail or node.slide +local free_node = node.free +local free_nodelist = node.flush_list +local has_attribute = node.has_attribute +local set_attribute = node.set_attribute +local copy_nodelist = node.copy_list +local traverse_nodes = node.traverse +local traverse_ids = node.traverse_id +local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs +local hpack_nodes = node.hpack +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local repack_hlist = nodes.repackhlist +local nodes_to_utf = nodes.listtoutf + +local setnodecolor = nodes.tracers.colors.set + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local kerncodes = nodes.kerncodes + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local kern_code = nodecodes.kern +local hlist_code = nodecodes.hlist +local whatsit_code = nodecodes.whatsit + +local fontkern_code = kerncodes.fontkern + +local localpar_code = whatsitcodes.localpar +local dir_code = whatsitcodes.dir +local userdefined_code = whatsitcodes.userdefined + +local nodepool = nodes.pool +local tasks = nodes.tasks +local usernodeids = nodepool.userids + +local new_textdir = nodepool.textdir +local new_usernumber = nodepool.usernumber +local new_glue = nodepool.glue +local new_leftskip = nodepool.leftskip + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local process_characters = nodes.handlers.characters +local inject_kerns = nodes.injections.handler + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local setfontdynamics = fonthashes.setdynamics +local fontprocesses = fonthashes.processes + +local texsetattribute = tex.setattribute +local unsetvalue = attributes.unsetvalue + +local parbuilders = builders.paragraphs +parbuilders.solutions = parbuilders.solutions or { } +local parsolutions = parbuilders.solutions +parsolutions.splitters = parsolutions.splitters or { } +local splitters = parsolutions.splitters + +local solutions = { } -- attribute sets +local registered = { } -- backmapping +splitters.registered = registered + +local a_split = attributes.private('splitter') + +local preroll = true +local criterium = 0 +local randomseed = nil +local optimize = nil -- set later +local variant = v_normal +local splitwords = true + +local cache = { } +local variants = { } +local max_less = 0 +local max_more = 0 + +local stack = { } + +local dummy = { + attribute = unsetvalue, + randomseed = 0, + criterium = 0, + preroll = false, + optimize = nil, + splitwords = false, + variant = v_normal, +} + +local function checksettings(r,settings) + local s = r.settings + local method = settings_to_hash(settings.method or "") + local optimize, preroll, splitwords + for k, v in next, method do + if k == v_preroll then + preroll = true + elseif k == v_split then + splitwords = true + elseif variants[k] then + variant = k + optimize = variants[k] -- last one wins + end + end + r.randomseed = tonumber(settings.randomseed) or s.randomseed or r.randomseed or 0 + r.criterium = tonumber(settings.criterium ) or s.criterium or r.criterium or 0 + r.preroll = preroll or false + r.splitwords = splitwords or false + r.optimize = optimize or s.optimize or r.optimize or variants[v_normal] +end + +local function pushsplitter(name,settings) + local r = name and registered[name] + if r then + if settings then + checksettings(r,settings) + end + else + r = dummy + end + insert(stack,r) + -- brr + randomseed = r.randomseed or 0 + criterium = r.criterium or 0 + preroll = r.preroll or false + optimize = r.optimize or nil + splitwords = r.splitwords or nil + -- + texsetattribute(a_split,r.attribute) + return #stack +end + +local function popsplitter() + remove(stack) + local n = #stack + local r = stack[n] or dummy + -- + randomseed = r.randomseed or 0 + criterium = r.criterium or 0 + preroll = r.preroll or false + optimize = r.optimize or nil + -- + texsetattribute(a_split,r.attribute) + return n +end + +local contextsetups = fonts.specifiers.contextsetups + +local function convert(featuresets,name,list) + if list then + local numbers = { } + local nofnumbers = 0 + for i=1,#list do + local feature = list[i] + local fs = featuresets[feature] + local fn = fs and fs.number + if not fn then + -- fall back on global features + fs = contextsetups[feature] + fn = fs and fs.number + end + if fn then + nofnumbers = nofnumbers + 1 + numbers[nofnumbers] = fn + if trace_goodies or trace_optimize then + report_solutions("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn) + end + else + report_solutions("solution %s has an invalid feature reference '%s'",i,name,tostring(feature)) + end + end + return nofnumbers > 0 and numbers + end +end + +local function initialize(goodies) + local solutions = goodies.solutions + if solutions then + local featuresets = goodies.featuresets + local goodiesname = goodies.name + if trace_goodies or trace_optimize then + report_solutions("checking solutions in '%s'",goodiesname) + end + for name, set in next, solutions do + set.less = convert(featuresets,name,set.less) + set.more = convert(featuresets,name,set.more) + end + end +end + +fonts.goodies.register("solutions",initialize) + +function splitters.define(name,settings) + local goodies = settings.goodies + local solution = settings.solution + local less = settings.less + local more = settings.more + local less_set, more_set + local l = less and settings_to_array(less) + local m = more and settings_to_array(more) + if goodies then + goodies = fonts.goodies.load(goodies) -- also in tfmdata + if goodies then + local featuresets = goodies.featuresets + local solution = solution and goodies.solutions[solution] + if l and #l > 0 then + less_set = convert(featuresets,name,less) -- take from settings + else + less_set = solution and solution.less -- take from goodies + end + if m and #m > 0 then + more_set = convert(featuresets,name,more) -- take from settings + else + more_set = solution and solution.more -- take from goodies + end + end + else + if l then + local n = #less_set + for i=1,#l do + local ss = contextsetups[l[i]] + if ss then + n = n + 1 + less_set[n] = ss.number + end + end + end + if m then + local n = #more_set + for i=1,#m do + local ss = contextsetups[m[i]] + if ss then + n = n + 1 + more_set[n] = ss.number + end + end + end + end + if trace_optimize then + report_solutions("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," ")) + end + local nofsolutions = #solutions + 1 + local t = { + solution = solution, + less = less_set or { }, + more = more_set or { }, + settings = settings, -- for tracing + attribute = nofsolutions, + } + solutions[nofsolutions] = t + registered[name] = t + return nofsolutions +end + +local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0 + +local splitter_one = usernodeids["splitters.one"] +local splitter_two = usernodeids["splitters.two"] + +local a_word = attributes.private('word') +local a_fontkern = attributes.private('fontkern') + +local encapsulate = false + +directives.register("builders.paragraphs.solutions.splitters.encapsulate", function(v) + encapsulate = v +end) + +function splitters.split(head) + -- quite fast + local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 + cache, max_less, max_more = { }, 0, 0 + local function flush() -- we can move this + local font = start.font + local last = stop.next + local list = last and copy_nodelist(start,last) or copy_nodelist(start) + local n = #cache + 1 + if encapsulate then + local user_one = new_usernumber(splitter_one,n) + local user_two = new_usernumber(splitter_two,n) + head, start = insert_node_before(head,start,user_one) + insert_node_after(head,stop,user_two) + else + local current = start + while true do + set_attribute(current,a_word,n) + if current == stop then + break + else + current = current.next + end + end + end + if rlmode == "TRT" or rlmode == "+TRT" then + local dirnode = new_textdir("+TRT") + list.prev = dirnode + dirnode.next = list + list = dirnode + end + local c = { + original = list, + attribute = attribute, + direction = rlmode, + font = font + } + if trace_split then + report_splitters("cached %4i: font: %s, attribute: %s, direction: %s, word: %s", + n, font, attribute, nodes_to_utf(list,true), rlmode and "r2l" or "l2r") + end + cache[n] = c + local solution = solutions[attribute] + local l, m = #solution.less, #solution.more + if l > max_less then max_less = l end + if m > max_more then max_more = m end + start, stop, done = nil, nil, true + end + while current do -- also nextid + local next = current.next + local id = current.id + if id == glyph_code then + if current.subtype < 256 then + local a = has_attribute(current,a_split) + if not a then + start, stop = nil, nil + elseif not start then + start, stop, attribute = current, current, a + elseif a ~= attribute then + start, stop = nil, nil + else + stop = current + end + end + elseif id == disc_code then + if splitwords then + if start then + flush() + end + elseif start and next and next.id == glyph_code and next.subtype < 256 then + -- beware: we can cross future lines + stop = next + else + start, stop = nil, nil + end + elseif id == whatsit_code then + if start then + flush() + end + local subtype = current.subtype + if subtype == dir_code or subtype == localpar_code then + rlmode = current.dir + end + else + if start then + flush() + end + end + current = next + end + if start then + flush() + end + nofparagraphs = nofparagraphs + 1 + nofwords = nofwords + #cache + return head, done +end + +local function collect_words(list) -- can be made faster for attributes + local words, w, word = { }, 0, nil + if encapsulate then + for current in traverse_ids(whatsit_code,list) do + if current.subtype == userdefined_code then -- hm + local user_id = current.user_id + if user_id == splitter_one then + word = { current.value, current, current } + w = w + 1 + words[w] = word + elseif user_id == splitter_two then + if word then + word[3] = current + else + -- something is wrong + end + end + end + end + else + local current, first, last, index = list, nil, nil, nil + while current do + -- todo: disc and kern + local id = current.id + if id == glyph_code or id == disc_code then + local a = has_attribute(current,a_word) + if a then + if a == index then + -- same word + last = current + elseif index then + w = w + 1 + words[w] = { index, first, last } + first = current + last = current + index = a + elseif first then + last = current + index = a + else + first = current + last = current + index = a + end + elseif index then + if first then + w = w + 1 + words[w] = { index, first, last } + end + index = nil + first = nil + elseif trace_split then + if id == disc_code then + report_splitters("skipped: disc node") + else + report_splitters("skipped: %s",utfchar(current.char)) + end + end + elseif id == kern_code and (current.subtype == fontkern_code or has_attribute(current,a_fontkern)) then + if first then + last = current + else + first = current + last = current + end + elseif index then + w = w + 1 + words[w] = { index, first, last } + index = nil + first = nil + if id == disc_node then + if trace_split then + report_splitters("skipped disc node") + end + end + end + current = current.next + end + if index then + w = w + 1 + words[w] = { index, first, last } + end + if trace_split then + for i=1,#words do + local w = words[i] + local n, f, l = w[1], w[2], w[3] + local c = cache[n] + if c then + report_splitters("found %4i: word: %s, cached: %s",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true)) + else + report_splitters("found %4i: word: %s, not in cache",n,nodes_to_utf(f,true,true,l)) + end + end + end + end + return words, list -- check for empty (elsewhere) +end + +-- we could avoid a hpack but hpack is not that slow + +local function doit(word,list,best,width,badness,line,set,listdir) + local changed = 0 + local n = word[1] + local found = cache[n] + if found then + local h, t + if encapsulate then + h = word[2].next -- head of current word + t = word[3].prev -- tail of current word + else + h = word[2] + t = word[3] + end + if splitwords then + -- there are no lines crossed in a word + else + local ok = false + local c = h + while c do + if c == t then + ok = true + break + else + c = c.next + end + end + if not ok then + report_solutions("skipping hyphenated word (for now)") + -- todo: mark in words as skipped, saves a bit runtime + return false, changed + end + end + local original, attribute, direction = found.original, found.attribute, found.direction + local solution = solutions[attribute] + local features = solution and solution[set] + if features then + local featurenumber = features[best] -- not ok probably + if featurenumber then + noftries = noftries + 1 + local first = copy_nodelist(original) + if not trace_colors then + for n in traverse_nodes(first) do -- maybe fast force so no attr needed + set_attribute(n,0,featurenumber) -- this forces dynamics + end + elseif set == "less" then + for n in traverse_nodes(first) do + setnodecolor(n,"font:isol") -- yellow + set_attribute(n,0,featurenumber) + end + else + for n in traverse_nodes(first) do + setnodecolor(n,"font:medi") -- green + set_attribute(n,0,featurenumber) + end + end + local font = found.font + -- local dynamics = found.dynamics + -- local shared = fontdata[font].shared + -- if not dynamics then -- we cache this + -- dynamics = shared.dynamics + -- found.dynamics = dynamics + -- end + -- local processors = found[featurenumber] + -- if not processors then -- we cache this too + -- processors = fonts.handlers.otf.setdynamics(font,featurenumber) + -- found[featurenumber] = processors + -- end + local setdynamics = setfontdynamics[font] + if setdynamics then + local processes = setdynamics(font,featurenumber) + for i=1,#processes do -- often more than 1 + first = processes[i](first,font,featurenumber) + end + else + report_solutions("fatal error, no dynamics for font %s",font) + end + first = inject_kerns(first) + if first.id == whatsit_code then + local temp = first + first = first.next + free_node(temp) + end + local last = find_node_tail(first) + -- replace [u]h->t by [u]first->last + local prev = h.prev + local next = t.next + prev.next = first + first.prev = prev + if next then + last.next = next + next.prev = last + end + -- check new pack + local temp, b = repack_hlist(list,width,'exactly',listdir) + if b > badness then + if trace_optimize then + report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> quit",line,badness,b,criterium) + end + -- remove last insert + prev.next = h + h.prev = prev + if next then + t.next = next + next.prev = t + else + t.next = nil + end + last.next = nil + free_nodelist(first) + else + if trace_optimize then + report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> continue",line,badness,b,criterium) + end + -- free old h->t + t.next = nil + free_nodelist(h) -- somhow fails + if not encapsulate then + word[2] = first + word[3] = last + end + changed, badness = changed + 1, b + end + if b <= criterium then + return true, changed + end + end + end + end + return false, changed +end + +-- We repeat some code but adding yet another layer of indirectness is not +-- making things better. + +variants[v_normal] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + for i=1,#words do + local done, c = doit(words[i],list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +variants[v_reverse] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + for i=#words,1,-1 do + local done, c = doit(words[i],list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +variants[v_random] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + while #words > 0 do + local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +local function show_quality(current,what,line) + local set = current.glue_set + local sign = current.glue_sign + local order = current.glue_order + local amount = set * ((sign == 2 and -1) or 1) + report_optimizers("line %s, %s, amount %s, set %s, sign %s (%s), order %s",line,what,amount,set,sign,how,order) +end + +function splitters.optimize(head) + if not optimize then + report_optimizers("no optimizer set") + return + end + local nc = #cache + if nc == 0 then + return + end + starttiming(splitters) + local listdir = nil -- todo ! ! ! + if randomseed then + math.setrandomseedi(randomseed) + randomseed = nil + end + local line = 0 + local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz + tex.hbadness, tex.hfuzz = 10000, number.maxdimen + if trace_optimize then + report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s", + tostring(preroll),variant,criterium,nc) + end + for current in traverse_ids(hlist_code,head) do + -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil)) + line = line + 1 + local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width +if not encapsulate and list.id == glyph_code then + -- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set + -- current.list, list = insert_node_before(list,list,new_glue(0)) + current.list, list = insert_node_before(list,list,new_leftskip(0)) +end + local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node + if badness > 0 then + if sign == 0 then + if trace_optimize then + report_optimizers("line %s, badness %s, okay",line,badness) + end + else + local set, max + if sign == 1 then + if trace_optimize then + report_optimizers("line %s, badness %s, underfull, trying more",line,badness) + end + set, max = "more", max_more + else + if trace_optimize then + report_optimizers("line %s, badness %s, overfull, trying less",line,badness) + end + set, max = "less", max_less + end + -- we can keep the best variants + local lastbest, lastbadness = nil, badness + if preroll then + local bb, base + for i=1,max do + if base then + free_nodelist(base) + end + base = copy_nodelist(list) + local words = collect_words(base) -- beware: words is adapted + for j=i,max do + local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir) + base = temp + if trace_optimize then + report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b) + end + bb = b + if b <= criterium then + break + end + -- if done then + -- break + -- end + end + if bb and bb > criterium then -- needs checking + if not lastbest then + lastbest, lastbadness = i, bb + elseif bb > lastbadness then + lastbest, lastbadness = i, bb + end + else + break + end + end + free_nodelist(base) + end + local words = collect_words(list) + for best=lastbest or 1,max do + local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir) + current.list = temp + if trace_optimize then + report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b) + end + if done then + if b <= criterium then -- was == 0 + protect_glyphs(list) + break + end + end + end + end + else + if trace_optimize then + report_optimizers("line %s, not bad enough",line) + end + end + -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus + current.list = hpack_nodes(current.list,width,'exactly',listdir) + -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil)) + end + for i=1,nc do + local ci = cache[i] + free_nodelist(ci.original) + end + cache = { } + tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz + stoptiming(splitters) +end + +statistics.register("optimizer statistics", function() + if nofwords > 0 then + local elapsed = statistics.elapsedtime(splitters) + local average = noftries/elapsed + return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second", + nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average) + end +end) + +-- we could use a stack + +local enableaction = tasks.enableaction +local disableaction = tasks.disableaction + +local function enable() + enableaction("processors", "builders.paragraphs.solutions.splitters.split") + enableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") +end + +local function disable() + disableaction("processors", "builders.paragraphs.solutions.splitters.split") + disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") +end + +function splitters.start(name,settings) + if pushsplitter(name,settings) == 1 then + enable() + end +end + +function splitters.stop() + if popsplitter() == 0 then + disable() + end +end + +function splitters.set(name,settings) + if #stack > 0 then + stack = { } + else + enable() + end + pushsplitter(name,settings) -- sets attribute etc +end + +function splitters.reset() + if #stack > 0 then + stack = { } + popsplitter() -- resets attribute etc + disable() + end +end + +-- interface + +commands.definefontsolution = splitters.define +commands.startfontsolution = splitters.start +commands.stopfontsolution = splitters.stop +commands.setfontsolution = splitters.set +commands.resetfontsolution = splitters.reset diff --git a/tex/context/base/node-spl.mkiv b/tex/context/base/font-sol.mkvi index 3630212af..b40e37ced 100644 --- a/tex/context/base/node-spl.mkiv +++ b/tex/context/base/font-sol.mkvi @@ -1,8 +1,8 @@ %D \module -%D [ file=node-spl, +%D [ file=font-sol, %D version=2009.05.19, -%D title=\CONTEXT\ Node Macros, -%D subtitle=Splitters, +%D title=\CONTEXT\ Font Macros, +%D subtitle=Solutions, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -13,9 +13,7 @@ \writestatus{loading}{ConTeXt Node Support / Splitters} -\registerctxluafile{node-spl}{1.001} - -\definesystemattribute[splitter][public] +% todo: pass color for tracing %D This module is specially made for the oriental \TEX\ project. The working is as %D follows (and tuned for fonts like Idris' Husayni. The following method came to @@ -74,36 +72,47 @@ %D \disabletrackers[parbuilders.solutions.splitters.colors] %D \stoptyping +\registerctxluafile{font-sol}{1.001} + \unprotect -\newtoks\everysetupfontsolutions +\definesystemattribute[splitter][public] -\unexpanded\def\definefontsolution - {\dodoubleargument\dodefinefontsolution} +\installcorenamespace{fontsolution} -\def\dodefinefontsolution[#1][#2]% we could set the attribute at the lua end - {\setxvalue{\??fu:#1}{\attribute\splitterattribute\ctxlua{builders.paragraphs.solutions.splitters.define("#1","#2")}\relax}} +\installcommandhandler \??fontsolution {fontsolution} \??fontsolution -\unexpanded\def\setfontsolution[#1]% - {\ctxlua{builders.paragraphs.solutions.splitters.enable()}% - \csname\??fu:#1\endcsname} +\let\setupfontsolutions\setupfontsolution -\unexpanded\def\resetfontsolution - {\ctxlua{builders.paragraphs.solutions.splitters.disable()}% - \attribute\splitterattribute\attributeunsetvalue} +\appendtoks + \ctxcommand{definefontsolution("\currentfontsolution",{ % these are frozen + goodies = "\fontsolutionparameter\s!goodies", + solution = "\fontsolutionparameter\c!solution", + less = "\fontsolutionparameter\c!less", + more = "\fontsolutionparameter\c!more", + })} +\to \everydefinefontsolution -\letvalue{\??fu:\v!reset}\resetfontsolution +\unexpanded\def\setfontsolution[#solution]% just one + {\edef\currentfontsolution{#solution}% + \ctxcommand{setfontsolution("\currentfontsolution",{ + method = "\fontsolutionparameter\c!method", + criterium = "\fontsolutionparameter\c!criterium", + % randomseed = "\fontsolutionparameter\c!random", + })}} -\unexpanded\def\setupfontsolutions[#1]% - {\getparameters[\??fu][#1]% - \the\everysetupfontsolutions} +\unexpanded\def\resetfontsolution % resets all + {\ctxcommand{resetfontsolution()}% + \let\currentfontsolution\empty} -\appendtoks - \ctxlua{builders.paragraphs.solutions.splitters.setup { - method = "\@@fumethod", - criterium = "\@@fucriterium", - }}% -\to \everysetupfontsolutions +\unexpanded\def\startfontsolution % [#1] + {\pushmacro\currentfontsolution + \setfontsolution} + +\unexpanded\def\stopfontsolution + {\ifhmode\par\fi + \ctxcommand{stopfontsolution()}% + \popmacro\currentfontsolution} % We initialize this module at the \LUA\ end. % diff --git a/tex/context/base/font-sty.mkvi b/tex/context/base/font-sty.mkvi index d8f01afa7..732d2b027 100644 --- a/tex/context/base/font-sty.mkvi +++ b/tex/context/base/font-sty.mkvi @@ -84,7 +84,7 @@ % \appendtoks % \let\groupedcommand\thirdofthreearguments -% \to \simplifiedcommands +% \to \everysimplifycommands %D This command also defines the keyword as command. This means %D that the example definition of \type{bold} we gave before, @@ -216,11 +216,19 @@ \installcommandhandler \??style {style} \??style +\setupstyle + [%\c!style=, + %\c!color=, + \c!method=\v!command] + \appendtoks \letvalue{\??stylecheck\currentstyle}\relax - \setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}% - \setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}% - \setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here + \edef\p_method{\styleparameter\c!method}% + \ifx\p_method\v!command + \setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}% + \setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}% + \setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here + \fi \to \everydefinestyle \unexpanded\def\font_styles_apply_start#name% @@ -242,7 +250,9 @@ \unexpanded\def\font_styles_use_generic#specification% {\let\currentstyle\s!unknown % reasonable generic tag - \setupcurrentstyle[\c!style=,\c!color=,#specification]% + \letstyleparameter\c!style\empty + \letstyleparameter\c!color\empty + \setupcurrentstyle[#specification]% \usestylestyleandcolor\c!style\c!color} % commands @@ -251,14 +261,20 @@ \unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand {\csname\??styleargument - \ifcsname#name\endcsname1\else\ifcsname\??stylecheck#name\endcsname2\else3\fi\fi + \ifcsname\??stylecheck#name\endcsname + 2% defined as style + \else\ifcsname#name\endcsname + 1% defined as command + \else + 3% specification + \fi\fi \endcsname{#name}} \setvalue{\??styleargument1}#name% - {\csname#name\endcsname} + {\groupedcommand{\csname#name\endcsname}{}} \setvalue{\??styleargument2}#name% - {\groupedcommand{\font_styles_use_defined{#name}}{}} + {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}} \setvalue{\??styleargument3}#specification% {\doifassignmentelse{#specification}\font_styles_assignment\font_styles_direct{#specification}} @@ -273,7 +289,13 @@ \unexpanded\def\startstyle[#name]% {\begingroup \csname\??styleenvironment - \ifcsname#name\endcsname1\else\ifcsname\??stylecheck#name\endcsname2\else3\fi\fi + \ifcsname\??stylecheck#name\endcsname + 2% defined as style + \else\ifcsname#name\endcsname + 1% defined as command + \else + 3% specification + \fi\fi \endcsname{#name}} \unexpanded\def\stopstyle @@ -289,7 +311,7 @@ \setvalue{\??styleenvironment3}#specification% {\doifassignmentelse{#specification}\font_styles_start_assignment\font_styles_start_direct{#specification}} -\def\font_styles_start_assignment#specification{\usegenericstyle{#specification}} +\def\font_styles_start_assignment#specification{\font_styles_use_generic{#specification}} \def\font_styles_start_direct #specification{\definedfont[#specification]\relax} %D Still experimental (might even go away). diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index c4f0e948b..d99114998 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -15,7 +15,6 @@ local find, gmatch = string.find, string.gmatch local concat, sort, format = table.concat, table.sort, string.format local serialize = table.serialize local lpegmatch = lpeg.match -local utfgsub, utflower = utf.gsub, utf.lower local unpack = unpack or table.unpack local allocate = utilities.storage.allocate @@ -34,13 +33,13 @@ using a table that has keys filtered from the font related files.</p> fonts = fonts or { } -- also used elsewhere -local names = { } +local names = font.names or allocate { } fonts.names = names -names.filters = names.filters or { } -local filters = names.filters +local filters = names.filters or { } +names.filters = filters -names.data = names.data or { } +names.data = names.data or allocate { } names.version = 1.110 names.basename = "names" @@ -310,8 +309,6 @@ end local function cleanname(name) return (gsub(lower(name),"[^%a%d]","")) - -- once we can load files with utf names, we can play with the following: - -- return (utfgsub(utfgsub(lower(str),"[^%a%A%d]",""),"%s","")) end local function cleanfilename(fullname,defaultsuffix) diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index b1ec7c1de..53ef8dd99 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -15,22 +15,21 @@ local trace_features = false trackers.register("tfm.features", func local report_defining = logs.reporter("fonts","defining") local report_tfm = logs.reporter("fonts","tfm loading") +local findbinfile = resolvers.findbinfile + local fonts = fonts local handlers = fonts.handlers local readers = fonts.readers local constructors = fonts.constructors local encodings = fonts.encodings -local tfm = { } -handlers.tfm = tfm - -constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua - -local findbinfile = resolvers.findbinfile +local tfm = constructors.newhandler("tfm") -local tfmfeatures = fonts.constructors.newfeatures("tfm") +local tfmfeatures = constructors.newfeatures("tfm") local registertfmfeature = tfmfeatures.register +constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua + fonts.formats.tfm = "type1" -- we need to have at least a value here --[[ldx-- @@ -92,7 +91,7 @@ local function read_from_tfm(specification) constructors.enhanceparameters(parameters) -- official copies for us -- if constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.extname(filename),specification) -- strange, why here + fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here local vfname = findbinfile(specification.name, 'ovf') if vfname and vfname ~= "" then local vfdata = font.read_vf(vfname,size) -- not cached, fast enough diff --git a/tex/context/base/font-tra.mkiv b/tex/context/base/font-tra.mkiv index 06b861378..e838d4938 100644 --- a/tex/context/base/font-tra.mkiv +++ b/tex/context/base/font-tra.mkiv @@ -13,6 +13,8 @@ \unprotect +\writestatus{loading}{ConTeXt Font Macros / Tracing} + %D \macros %D {showbodyfont} %D @@ -82,10 +84,8 @@ \fetchruntimecommand \showcharratio {\f!fontprefix\s!run} \fetchruntimecommand \showfontparameters {\f!fontprefix\s!run} -\unexpanded\def\checkcharactersinfont {\ctxcommand{checkcharactersinfont()}} -\unexpanded\def\removemissingcharacters{\ctxcommand{removemissingcharacters()}} -\unexpanded\def\showchardata #1{\ctxcommand{showchardata("#1")}} -\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}} +\unexpanded\def\showchardata #1{\ctxcommand{showchardata("#1")}} +\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}} %D \macros %D {doiffontpresentelse} @@ -95,7 +95,7 @@ %D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO} %D \stoptyping -\def\doiffontpresentelse#1{\ctxcommand{doifelse(fonts.names.exists("#1"))}} +\unexpanded\def\doiffontpresentelse#1{\ctxcommand{doifelse(fonts.names.exists("#1"))}} % experimental, maybe this becomes a module @@ -103,46 +103,46 @@ \unexpanded\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}} \unexpanded\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}} -\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}} +\unexpanded\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}} % Rather experimental: % % \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page % \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page -\def\showotfstepglyphs#1% +\unexpanded\def\showotfstepglyphs#1% {\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}% \unhbox\otfcollector} -\def\otfstepcharcommand#1#2#3% font char class +\unexpanded\def\otfstepcharcommand#1#2#3% font char class {\removeunwantedspaces - \hskip.5em plus .125em\relax + \hskip.5\emwidth \s!plus .125\emwidth\relax \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}% - \hskip.5em plus .125em\relax} + \hskip.5\emwidth \s!plus .125\emwidth\relax} -\def\otfstepmessagecommand#1#2% +\unexpanded\def\otfstepmessagecommand#1#2% {\begingroup \tttf\language\minusone \veryraggedright \forgetparindent \forgeteverypar - \hangindent1em + \hangindent\emwidth \hangafter\plusone \dontleavehmode\hbox{\detokenize{#1}}\removeunwantedspaces \doifsomething{#2}{\break\detokenize{#2}}\endgraf \endgroup \blank} -\def\showotfstepchars#1% +\unexpanded\def\showotfstepchars#1% {\ctxlua{nodes.tracers.steppers.codes(#1,"otfstepcharcommand")}} -\def\showotfstepmessages#1% +\unexpanded\def\showotfstepmessages#1% {\ctxlua{nodes.tracers.steppers.messages(#1,"otfstepmessagecommand",true)}} -\def\showotfstepfeatures +\unexpanded\def\showotfstepfeatures {\ctxlua{nodes.tracers.steppers.features()}} -\def\showotfsteps +\unexpanded\def\showotfsteps {\begingroup \veryraggedright \forgetparindent @@ -186,14 +186,24 @@ \newbox\otfcompositionbox -\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text +% this should go in spac-ali: + +\installcorenamespace{otfcompositiondir} + +\letvalue{\??otfcompositiondir -1}\righttoleft +\letvalue{\??otfcompositiondir r2l}\righttoleft +\letvalue{\??otfcompositiondir l2r}\lefttoright +\letvalue{\??otfcompositiondir +1}\lefttoright +\letvalue{\??otfcompositiondir 1}\lefttoright + +\unexpanded\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text {\begingroup \veryraggedright \forgetparindent \forgeteverypar \setupcolors[\c!state=\v!start]% can be option \startotfsample - \global\setbox\otfcompositionbox\hbox{\definedfont[#1]\ifnum#2<0 \textdir TRT\else\ifnum#2>0 \textdir TLT\fi\fi\relax#3}% + \global\setbox\otfcompositionbox\hbox{\definedfont[#1]\relax\getvalue{\??otfcompositiondir#2}\relax#3}% \stopotfsample \endgroup} diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua index 287d073d6..01d5289f8 100644 --- a/tex/context/base/font-vf.lua +++ b/tex/context/base/font-vf.lua @@ -19,8 +19,7 @@ local fastcopy = table.fastcopy local fonts = fonts local constructors = fonts.constructors -local vf = { } -fonts.handlers.vf = vf +local vf = constructors.newhandler("vf") -- general code diff --git a/tex/context/base/grph-epd.lua b/tex/context/base/grph-epd.lua index 130907d4e..4f9d46097 100644 --- a/tex/context/base/grph-epd.lua +++ b/tex/context/base/grph-epd.lua @@ -22,5 +22,4 @@ function figures.mergegoodies(optionlist) if all or options[variables.layer] then codeinjections.mergeviewerlayers() end - end diff --git a/tex/context/base/grph-epd.mkiv b/tex/context/base/grph-epd.mkiv index 947128b6b..26c07e731 100644 --- a/tex/context/base/grph-epd.mkiv +++ b/tex/context/base/grph-epd.mkiv @@ -22,18 +22,24 @@ \defineoverlay[system:graphics:epdf][\directsetup{system:graphics:epdf}] \startsetups system:graphics:epdf - \ctxlua{figures.mergegoodies("\@@efinteraction")}% + \ctxlua{figures.mergegoodies("\externalfigureparameter\c!interaction")}% \reference[\figurereference]{}% todo: dest area \stopsetups +\defineframed + [system_graphics_epdf] + [\c!frame=\v!off, + \c!offset=\v!overlay, + \c!background={\v!foreground,system:graphics:epdf}] + \def\grph_epdf_add_overlay {\global\setbox\foundexternalfigure\vbox\bgroup - \framed[\c!offset=\v!overlay,\c!background={\v!foreground,system:graphics:epdf}]{\box\foundexternalfigure}% + \system_graphics_epdf{\box\foundexternalfigure}% \egroup} \appendtoks \iflocation - \doif\figurefiletype{pdf}{\doifnot\@@efinteraction\v!none\grph_epdf_add_overlay}% + \doif\figurefiletype{pdf}{\doifnot{\externalfigureparameter\c!interaction}\v!none\grph_epdf_add_overlay}% \fi \to \externalfigurepostprocessors diff --git a/tex/context/base/grph-fig.mkiv b/tex/context/base/grph-fig.mkiv index 1908e6445..864bd29fb 100644 --- a/tex/context/base/grph-fig.mkiv +++ b/tex/context/base/grph-fig.mkiv @@ -11,351 +11,198 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% ex => ef with proper parent - -\writestatus{loading}{ConTeXt Graphic Macros / Figure Handling} - \unprotect -\unexpanded\def\setupexternalfigures - {\dosingleempty\dosetupexternalfigures} - -\def\dosetupexternalfigures[#1]% - {\getparameters[\??ef][#1]% local settings - \getparameters[\??ex][#1]% global settings - \setfigurepathlist} % the path may be used elsewhere too (as in x-res-04) - -\presetlocalframed[\??ef] - -\newconditional\externalfigurelevel % true=background false=normal -\newconditional\externalfigureflush % true=place false=ignore +%D Used in the styledesign manual: +% +% beware in mkiv we don't have the typeset- prefix +% +% \setbuffer[typeset-b]\endbuffer +% \setbuffer[typeset-a]\endbuffer +% +% todo: +% +% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext +% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext -\setfalse\externalfigurelevel -\settrue \externalfigureflush +\newcount\c_grph_buffers_n -\installcorenamespace{externalfigures} +\let\m_grph_buffers_filename\empty -\def\doplaceexternalfigure[#1][#2][#3][#4][#5]% - {\doifsomething{#2}% catches \defineexternalfigure dummies - {\ifcsname\??externalfigures#2\endcsname - \doifelse{#1}{#2} - {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]} - {\getvalue{\??externalfigures#2}[#5]}% - \else - \dodoplaceexternalfigure[#1][#2][#3][#4][#5]% - \fi}} +\unexpanded\def\typesetbuffer + {\dodoubleempty\grph_buffers_typeset} -\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi +\def\grph_buffers_typeset[#1][#2]% beware: this will mix up the mp graphics + {\ifsecondargument + \grph_buffers_typeset_indeed[#1][#2]% + \else\iffirstargument + \doifassignmentelse{#1} + {\grph_buffers_typeset_indeed[\jobname][#1]}% + {\grph_buffers_typeset_indeed[#1][]}% + \else + \grph_buffers_typeset_indeed[\jobname][] + \fi\fi} -\def\dodoplaceexternalfigure[#1][#2][#3][#4][#5]% +\def\grph_buffers_typeset_indeed[#1][#2]% we could use the via files {\bgroup - \dostarttagged\t!image\empty - \let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode - \calculateexternalfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp - \dotagfigure - \naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}% - \dostoptagged + \global\advance\c_grph_buffers_n\plusone + \edef\m_grph_buffers_filename{\jobname-buffer-\the\c_grph_buffers_n}% + \ctxcommand{runbuffer("\m_grph_buffers_filename.tmp","#1",true)}% + \externalfigure[\m_grph_buffers_filename.pdf][#2]% \egroup} -\def\externalfigurereplacement#1#2#3% - {\normalexpanded{\localframed - [\??ef] - [\c!width=\figurewidth, - \c!height=\figureheight, - \c!background=\v!color, - \c!backgroundcolor=missingfigurecolor, - \c!frame=\@@efframe]}% we need to expand this in order to prevent a loop - {\tt\tfxx \nohyphens - name: \expanded{\verbatimstring{#1}}\\% - file: \expanded{\verbatimstring{#2}}\\% - state: \expanded{\verbatimstring{#3}}}} - -\definecolor[missingfigurecolor][s=.8] - -\def\externalfigureplaceholder#1#2#3% - {\localframed - [\??ef] - [\c!width=#2, - \c!height=#3, - \c!frame=\v!on]% - {\tt\tfxx \nohyphens - name: \expanded{\verbatimstring{#1}}\\% - state: \expanded{\verbatimstring{placeholder}}}} - -% new: more convenient/efficient than -% -% \use..[a][a][setting] \externalfigure[b][a] -% -% is equivalent to: +% For manuals and such: % -% \def..[a][setting] \externalfigure[b][a] -% -% see x-res modules for usage: +% \definetypesetting [name] [options] [settings-a] % -% \defineexternalfigure[name][settings] - -\unexpanded\def\defineexternalfigure - {\dodoubleargument\dodefineexternalfigure} - -\def\dodefineexternalfigure[#1][#2]% - {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][][][#2]}} - -% \useexternalfigure[alpha][koe] -% \useexternalfigure[beta] [koe] [breedte=1cm] -% \useexternalfigure[gamma][koe][alpha] -% \useexternalfigure[delta][koe][alpha][breedte=2cm] +% \typesetfile [name] [file] [settings-b] +% \typesetfile [file] [options] [settings-b] +% \typesetfile [file] [settings-b] +% \typesetfile [file] % -% volle breedte: \externalfigure[koe] \par -% 3cm breed: \externalfigure[koe] [breedte=3cm] \par -% volle breedte: \externalfigure[alpha] \par -% 1cm breed: \externalfigure[beta] \par -% volle breedte: \externalfigure[gamma] \par -% 2cm breed: \externalfigure[delta] \par -% 4cm breed: \externalfigure[beta] [breedte=4cm] \par -% 5cm breed: \externalfigure[gamma][breedte=5cm] \par - -% \defineexternalfigure[a][width=10cm] -% \defineexternalfigure[b][width=5cm] -% \externalfigure[cow][a] -% \externalfigure[cow][b][height=8cm] - -% \useexternalfigure[x][cow][width=10cm,height=1cm] -% \externalfigure[x] -% \externalfigure[x][width=3cm] - -\def\useexternalfigure - {\doquadrupleempty\douseexternalfigure} - -% [label] [filename] -% [label] [filename] [parent] -% [label] [filename] [parent] [settings] -% [label] [filename] [settings] - -\def\useexternalfigure - {\doquadrupleempty\douseexternalfigure} - -\def\douseexternalfigure[#1][#2][#3][#4]% - {\doifelsenothing{#1} - {\doifsomething{#2} - {\doifassignmentelse{#3} - {\dodouseexternalfigure{#2}{#2}{#3}{#4}} - {\dodouseexternalfigure{#2}{#2}{}{#4}}}} - {\doifelsenothing{#2} - {\doifassignmentelse{#3} - {\dodouseexternalfigure{#1}{#1}{}{#3}} - {\dodouseexternalfigure{#1}{#1}{#3}{#4}}} - {\doifassignmentelse{#3} - {\dodouseexternalfigure{#1}{#2}{}{#3}} - {\dodouseexternalfigure{#1}{#2}{#3}{#4}}}}} - -\def\dodouseexternalfigure#1#2#3#4% - {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][#2][#3][#4]}% - \doanalyzeexternalfigurecollection[#2][#4]} - -\newconditional\inexternalfigurecollection -\newdimen\xexternalfigurecollectionminwidth -\newdimen\xexternalfigurecollectionmaxwidth -\newdimen\xexternalfigurecollectionminheight -\newdimen\xexternalfigurecollectionmaxheight - -\def\doanalyzeexternalfigurecollection[#1][#2]% - {\ifconditional\inexternalfigurecollection - \setfalse\inexternalfigurecollection - \getfiguredimensions[#1][#2]% - \settrue\inexternalfigurecollection - \scratchdimen\naturalfigurewidth - \ifdim\scratchdimen>\xexternalfigurecollectionmaxwidth \xexternalfigurecollectionmaxwidth \scratchdimen \fi - \ifdim\scratchdimen<\xexternalfigurecollectionminwidth \xexternalfigurecollectionminwidth \scratchdimen \fi - \scratchdimen\naturalfigureheight - \ifdim\scratchdimen>\xexternalfigurecollectionmaxheight \xexternalfigurecollectionmaxheight\scratchdimen \fi - \ifdim\scratchdimen<\xexternalfigurecollectionminheight \xexternalfigurecollectionminheight\scratchdimen \fi - \fi} - -\unexpanded\def\startexternalfigurecollection[#1]% - {\begingroup - \def\currentexternalfigurecollection{#1}% - \settrue\inexternalfigurecollection - \xexternalfigurecollectionminwidth \maxdimen - \xexternalfigurecollectionmaxwidth \zeropoint - \xexternalfigurecollectionminheight\maxdimen - \xexternalfigurecollectionmaxheight\zeropoint} - -\unexpanded\def\stopexternalfigurecollection - {\setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minwidth }{\the\xexternalfigurecollectionminwidth }% - \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxwidth }{\the\xexternalfigurecollectionmaxwidth }% - \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minheight}{\the\xexternalfigurecollectionminheight}% - \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxheight}{\the\xexternalfigurecollectionmaxheight}% - \endgroup} - -\def\externalfigurecollectionparameter#1#2% - {\csname\ifcsname\??ef:c:#1:#2\endcsname\??ef:c:#1:#2\else\s!empty\fi\endcsname} - -\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth } -\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth } -\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight} -\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight} - -\let\efcparameter\externalfigurecollectionparameter -\let\efcminwidth \externalfigurecollectionminwidth -\let\efcmaxwidth \externalfigurecollectionmaxwidth -\let\efcminheight\externalfigurecollectionminheight -\let\efcmaxheight\externalfigurecollectionmaxheight - -% \startexternalfigurecollection[name] -% \useexternalfigure[cow] [cow.pdf] -% \useexternalfigure[mill][mill.png] -% \stopexternalfigurecollection +% \enabletrackers[files.run] % \starttext -% \bTABLE -% \bTR -% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD -% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD -% \eTR -% \eTABLE +% \typesetfile[oepsoeps.tex][width=10cm,frame=on] % \stoptext -\def\dosetefparameters#1#2#3% parent_id use_settings current_settings - {\doifelsenothing{#1} % inherit from parent - {\getparameters[\??ef][#2,#3]} - {\ifcsname\??externalfigures#1\endcsname - \pushmacro\doplaceexternalfigure - \def\doplaceexternalfigure[##1][##2][##3][##4]{\getparameters[\??ef][##4,#2,#3]}% - \getvalue{\??externalfigures#1}% - \popmacro\doplaceexternalfigure - \else - \getparameters[\??ef][#2,#3]% - \fi}} - -\unexpanded\def\externalfigure - {\dotripleempty\doexternalfigure} - -% \def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings] -% {\bgroup -% \doifelsenothing{#1} -% {\framed[\c!width=\defaultfigurewidth,\c!height=\defaultfigureheight]{external\\figure\\no name}} -% {\ifcsname\??externalfigures#1\endcsname -% \doifassignmentelse{#2} -% {\getvalue{\??externalfigures#1}[#2]}% -% {\getvalue{\??externalfigures#1}[#3]}% -% \else -% \useexternalfigure[\s!dummy][#1][#2][#3]% -% \getvalue{\??externalfigures\s!dummy}[]% [] is dummy arg 5 -% \fi}% -% \globallet\currentresourcecomment\empty -% \egroup} - -\def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings] - {\bgroup % also catched #1 == empty ... scales nicer now - \ifcsname\??externalfigures#1\endcsname - \doifassignmentelse{#2} - {\getvalue{\??externalfigures#1}[#2]}% - {\getvalue{\??externalfigures#1}[#3]}% - \else - \useexternalfigure[\s!dummy][#1][#2][#3]% - \getvalue{\??externalfigures\s!dummy}[]% [] is dummy arg 5 - \fi - \globallet\currentresourcecomment\empty - \egroup} - -\def\resourcecomment#1% - {\gdef\currentresourcecomment{#1}} +\installcorenamespace{typesettingfile} -\unexpanded\def\startresourcecomment#1\stopresourcecomment - {\gdef\currentresourcecomment{#1}} +\unexpanded\def\definetypesetting{\dotripleempty\grph_typesetting_define} +\unexpanded\def\typesetfile {\dotripleempty\grph_typesetting_process} -\let\currentresourcecomment\empty +\def\grph_typesetting_define[#1][#2][#3]% <name> options settings-a + {\doifsomething{#1}{\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}}} -\unexpanded\def\showexternalfigures % maybe run time command is better, but no core-run, unless figs-run ... - {%\writestatus\m!system{for \string\showexternalfigures\space see \truefilename{x-res-20}.tex} - \usemodule[res-20]% - \showexternalfigures} % so for the moment we do it this way +\def\grph_typesetting_process[#1][#2][#3]% <name> filename settings-b | filename options settings + {\ifcsname\??typesettingfile#1\endcsname + \csname\??typesettingfile#1\endcsname{#2}{#3}% + \else\ifthirdargument % filename options settings + \grph_typesetting_process_indeed{#2}{#3}{#1}{}% + \else\ifsecondargument % filename settings + \grph_typesetting_process_indeed{}{#2}{#1}{}% + \fi\fi\fi} -\unexpanded\def\overlayfigure#1% - {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]} +\def\grph_typesetting_process_indeed#1#2#3#4% options settings-a filename settings-b + {\begingroup + \edef\m_typesetting_name{\cldcontext{job.files.context("#3","#1")}}% + \ifx\m_typesetting_name\empty \else + \expanded{\externalfigure[\m_typesetting_name]}[#2,#4]% + \fi + \endgroup} -%D Whatever +%D Whatever ... hardly used ... but historic ... needs checking ... +%D will probably become m-fig-nn.mkiv .. or I will extend it cq. clean +%D it up when I needed it. After all, it's documented in old manuals. -\newbox\colorbarbox +\newcount\c_grph_steps_reference +\newdimen\d_grph_steps_x +\newdimen\d_grph_steps_y +\newbox \b_grph_steps_colorbar -\unexpanded\def\makecolorbar[#1]% - {\def\docommand##1% - {\color[##1] - {\blackrule - [\c!width=2em, - \c!height=1ex, - \c!depth=\!!zeropoint]}% - \endgraf}% - \global\setbox\colorbarbox\vbox - {\forgetall - \processcommalist[#1]\docommand}% - \global\setbox\colorbarbox\vbox - {\hskip2em\box\colorbarbox}% - \wd\colorbarbox\zeropoint} +\let\placestopfigure\relax \unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]% {\hbox - {\setbox0\hbox + {\setbox\scratchbox\hbox {\useexternalfigure[\s!dummy][#2][#3,#5]% \externalfigure[\s!dummy]}% - \calculateefsteps + \grph_steps_calculate \startpositioning - \def\referring(##1,##2)##3(##4,##5)##6[##7]% - {\position(##1,##2){\efgoto(##4,##5){\@@exframes}[##7]}}% - \def\marking(##1,##2)##3(##4,##5)##6[##7]% - {\position(##1,##2){\efthisis(##4,##5){\@@exframes}[##7]}}% - \def\remark{\efnocomment}% - \def\colorbar##1[##2]{}% - \position(0,0){\box0}% + \let\referring\grph_steps_one_referring + \let\marking \grph_steps_one_marking + \let\remark \grph_steps_one_remark + \let\colorbar \grph_steps_one_colorbar + \position(0,0){\box\scratchbox}% \linewidth\onepoint \setuppositioning [\c!unit=pt, - \c!xscale=\withoutpt\the\efxsteps, - \c!yscale=\withoutpt\the\efysteps, + \c!xscale=\withoutpt\the\d_grph_steps_x, + \c!yscale=\withoutpt\the\d_grph_steps_y, \c!factor=1]% \ignorespaces#4% - \def\referring(##1,##2)##3(##4,##5)##6[##7]% - {}% - \let\marking\referring - \def\remark{\efcomment\v!no}% - \def\colorbar##1[##2]{\makecolorbar[##2]}% + \let\referring\grph_steps_two_referring + \let\marking \grph_steps_two_marking + \let\remark \grph_steps_two_remark + \let\colorbar \grph_steps_two_colorbar \ignorespaces#4% \stoppositioning - \box\colorbarbox}} + \ifvoid\b_grph_steps_colorbar\else\box\b_grph_steps_colorbar\fi}} % not really needed + +\unexpanded\def\grph_steps_one_referring(#1,#2)#3(#4,#5)#6[#7]% + {\position(#1,#2){\grph_steps_goto(#4,#5){\externalfigureparameter\c!frames}[#7]}} + +\unexpanded\def\grph_steps_one_marking(#1,#2)#3(#4,#5)#6[#7]% + {\position(#1,#2){\grph_steps_this_is(#4,#5){\externalfigureparameter\c!frames}[#7]}} + +\unexpanded\def\grph_steps_one_remark(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst} + {\def\grph_steps_no_comment_indeed[##1]##2{}% + \dosingleempty\grph_steps_no_comment_indeed} + +\unexpanded\def\grph_steps_one_colorbar#1[#2]% + {} + +\unexpanded\def\grph_steps_two_referring(#1,#2)#3(#4,#5)#6[#7]% + {} + +\let\grph_steps_two_marking\grph_steps_two_referring + +\unexpanded\def\grph_steps_two_remark + {\grph_steps_comment\v!no} + +\unexpanded\def\grph_steps_two_colorbar#1[#2] + {\begingroup + \global\setbox\b_grph_steps_colorbar\vbox + {\forgetall + \processcommalist[#2]\grph_colorbar_make_step}% + \global\setbox\b_grph_steps_colorbar\vbox + {\hskip2\emwidth\box\b_grph_steps_colorbar}% + \global\wd\b_grph_steps_colorbar\zeropoint + \endgroup} -\def\dodostartfigure[#1][#2][#3]#4\stopfigure - {\doifelse\v!test\@@exoption +\unexpanded\def\grph_colorbar_make_step#1% + {\blackrule[\c!color=#1,\c!width=2\emwidth,\c!height=\exheight,\c!depth=\zeropoint]% + \endgraf} + +\unexpanded\def\startfigure % could be done nicer + {\grabuntil{\e!stop\v!figure}\grph_steps_figure_process} + +\let\stopfigure\relax + +\def\grph_steps_figure_process#1% + {\dotripleargument\grph_steps_figure_process_indeed#1\stopfigure} + +\def\grph_steps_figure_process_indeed[#1][#2][#3]#4\stopfigure + {\doifelse{\externalfigureparameter\c!option}\v!test {\teststartfigure[#1][#2][#3]#4\teststopfigure - \let\@@exframes\v!on} - {\let\@@exframes\v!off}% - \setvalue{\??externalfigures#1}% - {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}% - }% no longer \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}} + \letexternalfigureparameter\c!frames\v!on} + {\letexternalfigureparameter\c!frames\v!off}% + \setvalue{\??externalfigureinstance#1}% + {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}} -% De onderstaande macro mag niet zondermeer worden aangepast -% en is afgestemd op gebruik in de handleiding. +\let\teststopfigure\relax -\def\teststartfigure[#1][#2][#3]#4\teststopfigure% +\unexpanded\def\teststartfigure[#1][#2][#3]#4\teststopfigure {\begingroup - \setbox0\hbox + \setbox\scratchbox\hbox {\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]% \externalfigure[\s!dummy]}% - \def\referring{\efmark}% - \def\marking{\efmark}% - \def\remark{\efcomment\v!yes}% - \def\colorbar##1[##2]{}% - \efreference\zerocount + \let\referring\grph_steps_three_referring + \let\marking \grph_steps_three_marking + \let\remark \grph_steps_three_remark + \let\colorbar \grph_steps_three_colorbar + \c_grph_steps_reference\zerocount \setbox0\vbox - {\hsize240pt + {\hsize240\points \startpositioning - \calculateefsteps + \grph_steps_calculate \position(0,0) - {\box0}% + {\box\scratchbox}% \position(0,0) {\basegrid - [\c!nx=\@@exxmax, - \c!dx=\withoutpt\the\efxsteps, - \c!ny=\@@exymax, - \c!dy=\withoutpt\the\efysteps, + [\c!nx=\externalfigureparameter\c!xmax, + \c!dx=\withoutpt\the\d_grph_steps_x, + \c!ny=\externalfigureparameter\c!ymax, + \c!dy=\withoutpt\the\d_grph_steps_y, \c!xstep=1, \c!ystep=1, \c!scale=1, @@ -363,18 +210,18 @@ \c!unit=pt]}% \setuppositioning [\c!unit=pt, - \c!xscale=\withoutpt\the\efxsteps, - \c!yscale=\withoutpt\the\efysteps, + \c!xscale=\withoutpt\the\d_grph_steps_x, + \c!yscale=\withoutpt\the\d_grph_steps_y, \c!factor=1]% \linewidth\onepoint \ignorespaces#4\relax \stoppositioning \vfill}% - \efreference\zerocount - \def\referring{\eftext{$\rightarrow$}}% - \def\marking{\eftext{$\leftarrow$}}% - \def\remark{\efnocomment}% - \def\colorbar##1[##2]{}% + \c_grph_steps_reference\zerocount + \let\referring\grph_steps_four_referring + \let\marking \grph_steps_four_marking + \let\remark \grph_steps_four_remark + \let\colorbar \grph_steps_four_colorbar \setbox2\vbox {{\tfa\doifelsenothing{#1}{#2}{#1}} \blank @@ -386,165 +233,149 @@ \ht0\ht2 \fi \hbox - {\hskip3em - \vtop{\vskip12pt\box0\vskip6pt}% - \vtop{\vskip12pt\box2\vskip6pt}}% + {\hskip3\emwidth + \vtop{\vskip12\points\box0\vskip6\points}% + \vtop{\vskip12\points\box2\vskip6\points}}% \endgroup} -\def\dodostartfigure[#1][#2][#3]#4\stopfigure - {\doifelse\v!test\@@exoption - {\teststartfigure[#1][#2][#3]#4\teststopfigure - \let\@@exframe\v!on} - {\let\@@exframe\v!off}% - \setvalue{\??externalfigures#1}% - {\def\next{\placestartfigure[#1][#2][#3]#4\placestopfigure}% - \dosingleempty\next}% - }% no longer: \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}} +\unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]% + {\advance\c_grph_steps_reference\plusone + \position(#1,#2) + {\hbox{\the\c_grph_steps_reference}}% + \position(#1,#2) + {\gotosomeinternal\s!vwb{#7}\realfolio + {\grph_steps_marker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}} -\long\def\dostartfigure#1% - {\dotripleargument\dodostartfigure#1\stopfigure} +\unexpanded\def\grph_steps_three_remark + {\grph_steps_comment\v!yes} -\unexpanded\def\startfigure - {\grabuntil{\e!stop\v!figure}\dostartfigure} - -%D NEW: used in styledesign manual +\let\grph_steps_three_marking \grph_steps_three_referring +\let\grph_steps_three_colorbar\grph_steps_one_colorbar -% beware in mkiv we don't have the typeset- prefix -% -% \setbuffer[typeset-b]\endbuffer -% \setbuffer[typeset-a]\endbuffer -% -% todo: -% -% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext -% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext +\unexpanded\def\grph_steps_four_referring + {\grph_steps_text{$\rightarrow$}} -\newcount\noftypesetbuffers +\unexpanded\def\grph_steps_four_marking + {\grph_steps_text{$\leftarrow$}} -\def\typesetbuffer - {\dodoubleempty\dotypesetbuffer} +\let\grph_steps_four_remark \grph_steps_one_remark +\let\grph_steps_four_colorbar\grph_steps_one_colorbar -\def\dotypesetbuffer[#1][#2]% beware: this will mix up the mp graphics - {\ifsecondargument - \dodotypesetbuffer[#1][#2]% - \else\iffirstargument - \doifassignmentelse{#1} - {\dodotypesetbuffer[\jobname][#1]}% - {\dodotypesetbuffer[#1][]}% +% Helpers: + +\def\grph_steps_calculate + {\ifnum0\externalfigureparameter\c!xmax=\zerocount + \ifnum0\externalfigureparameter\c!ymax=\zerocount + \setexternalfigureparameter\c!ymax{24}% + \fi + \d_grph_steps_y\figureheight + \divide\d_grph_steps_y \externalfigureparameter\c!ymax + \d_grph_steps_x\d_grph_steps_y + \scratchdimen\figurewidth + \advance\scratchdimen\d_grph_steps_y + \divide \scratchdimen\d_grph_steps_y + \setexternalfigureparameter\c!xmax{\number\scratchdimen}% \else - \dodotypesetbuffer[\jobname][] - \fi\fi} + \d_grph_steps_x\figurewidth \divide\d_grph_steps_x \externalfigureparameter\c!xmax\relax + \d_grph_steps_y\figureheight \divide\d_grph_steps_y \externalfigureparameter\c!ymax\relax + \fi} -\def\dodotypesetbuffer[#1][#2]% +\def\grph_steps_comment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst} + {\def\grph_steps_comment_indeed[##1]##2% + {\position(#2,#3)% + {\setnostrut + \framed + [\c!width=#5\d_grph_steps_x, + \c!height=#6\d_grph_steps_y, + \c!offset=\v!none, + \c!frame=#1, + ##1]% + {##2}}}% + \dosingleempty\grph_steps_comment_indeed} + +% \def\grph_steps_figure#1% +% {\position(0,0){\getvalue{#1}}} + +\def\grph_steps_goto(#1,#2)#3[#4]% (h,b)kader[ref] + {\gotobox{\vbox{\grph_steps_area(#1,#2)#3{}}}[#4]} + +\def\grph_steps_text#1(#2,#3)#4(#5,#6)#7[#8]% + {\advance\c_grph_steps_reference\plusone + \hbox + {\quad + \thisissomeinternal\s!vwb + {#8}% + \gotosomeinternal\s!vwa{#8}\realfolio + {\hbox to 1.5em{\the\c_grph_steps_reference\presetgoto\hfill}}% + \quad#1 (#2,#3) (#5,#6) [#8]\hfill}% + \endgraf} + +\def\grph_steps_this_is(#1,#2)#3[#4]% + {\grph_steps_area(#1,#2){#3}{\pagereference[#4]}} + +\def\grph_steps_area(#1,#2)#3#4% (h,b){kader}{tekst} {\bgroup - \global\advance\noftypesetbuffers\plusone - \edef\bufferfilename{\jobname-buffer-\the\noftypesetbuffers}% - \ctxcommand{runbuffer("\bufferfilename.tmp","#1",true)}% - \externalfigure[\bufferfilename.pdf][#2]% + \setnostrut + \framed + [\c!width=#1\d_grph_steps_x, + \c!height=#2\d_grph_steps_y, + \c!offset=\zeropoint, + \c!frame=#3] + {#4}% \egroup} -\def\dodotypesetbufferindeed#1% - {} +\def\grph_steps_marker(#1,#2)#3#4% (h,b){kader}{tekst} + {\framed + [\c!width=#1\d_grph_steps_x, + \c!height=#2\d_grph_steps_y, + \c!offset=\v!none, + \c!frame=#3]% + {#4}} -% for me only (manuals and such) +\protect \endinput + +% \startbuffer +% \definecolor [blue] [c=1,m=.38,y=0,k=.64] +% \definecolor [yellow] [c=0,m=.28,y=1,k=.06] % -% \definetypesetting [name] [options] [settings-a] +% \definespotcolor [blue-100] [blue] [p=1] +% \definespotcolor [yellow-100] [yellow] [p=1] % -% \typesetfile [name] [file] [settings-b] -% \typesetfile [file] [options] [settings-b] -% \typesetfile [file] [settings-b] -% \typesetfile [file] +% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1] % -% \enabletrackers[files.run] -% \starttext -% \typesetfile[oepsoeps.tex][width=10cm,frame=on] -% \stoptext - -\installcorenamespace{typesettingfile} - -\unexpanded\def\definetypesetting{\dotripleempty\dodefinetypesetting} -\unexpanded\def\typesetfile {\dotripleempty\dotypesetfile} - -\def\dodefinetypesetting[#1][#2][#3]% <name> options settings-a - {\doifsomething{#1}{\setvalue{\??typesettingfile#1}{\dodotypesetfile{#2}{#3}}}} - -\def\dotypesetfile[#1][#2][#3]% <name> filename settings-b | filename options settings - {\ifcsname\??typesettingfile#1\endcsname - \csname\??typesettingfile#1\endcsname{#2}{#3}% - \else\ifthirdargument % filename options settings - \dodotypesetfile{#2}{#3}{#1}{}% - \else\ifsecondargument % filename settings - \dodotypesetfile{}{#2}{#1}{}% - \fi\fi\fi} - -\def\dodotypesetfile#1#2#3#4% options settings-a filename settings-b - {\edef\typesetfilename{\ctxlua{tex.write(job.files.context("#3","#1"))}}% - \expanded{\externalfigure[\typesetfilename]}[#2,#4]} - -\setupexternalfigures - [\c!option=, - \c!object=\v!yes, % we only check for no - \c!reset=\v!no, - \c!interaction=\v!none, - \c!maxwidth=\@@efwidth, - \c!maxheight=\@@efheight, - \c!bodyfont=\bodyfontsize, - \c!directory=, - \c!radius=.5\bodyfontsize, - \c!corner=\v!rectangular, - \c!frame=\v!off, - \c!background=, % new - \c!splitcolor=\s!white, - \c!conversion=, - \c!resolution=, - \c!prefix=, - \c!cache=, -% \c!grid=, - \c!equalwidth=, - \c!equalheight=, - \c!location={\v!local,\v!global}] - -\setupexternalfigures - [\c!frames=\v!off, - \c!ymax=24, - \c!xmax=] - -\useexternalfigure - [buffer] [\jobname.buffer] [\c!object=\v!no] - -\protect \endinput - -% alternative for positioning - -% \definelayer[figure][width=\overlaywidth,height=\overlayheight] -% \defineoverlay[figure][{\directsetup{figure}\tightlayer[figure]}] - -% \setupcolors[state=start] - -% \starttext - -% \startsetups figure -% \setlayerframed[figure][preset=rightbottom,x=.25\layerwidth,y=.25\layerheight]{HERE} -% \setlayerframed[figure][preset=leftbottom, x=.15\layerwidth,y=.35\layerheight]{THERE} -% \stopsetups - -% \externalfigure[cow][background={foreground,figure},width=4cm,height=8cm] - -% \startsetups figure -% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{MORE} -% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE} -% \stopsetups - -% \externalfigure[cow][background={foreground,figure},width=14cm,height=2cm] - -% \defineexternalfigure[whatever][background={foreground,figure}] - -% \startsetups figure -% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{\red MORE} -% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE} -% \stopsetups - -% \externalfigure[cow][whatever][width=14cm,height=4cm] - -% \stoptext - +% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone +% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone +% +% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth] +% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth] +% +% \startbaselinecorrection \startcombination[4*1] +% {\externalfigure[demo-a]} {no color} +% {\externalfigure[demo-a][color=combicolor]} {indexed duotone} +% {\externalfigure[demo-a][color=combicolor-b]} {spot color} +% {\externalfigure[demo-a][color=combicolor-y]} {spot color} +% \stopcombination \stopbaselinecorrection +% +% \startbaselinecorrection \startcombination[4*1] +% {\externalfigure[demo-b]} {no color} +% {\externalfigure[demo-b][color=combicolor]} {indexed duotone} +% {\externalfigure[demo-b][color=combicolor-b]} {spot color} +% {\externalfigure[demo-b][color=combicolor-y]} {spot color} +% \stopcombination \stopbaselinecorrection +% +% \startbaselinecorrection \startcombination[4*1] +% {\externalfigure[demo-a]} {no color} +% {\externalfigure[demo-a][color=combicolor]} {indexed duotone} +% {\externalfigure[demo-a][color=blue-100]} {spot color} +% {\externalfigure[demo-a][color=yellow-100]} {spot color} +% \stopcombination \stopbaselinecorrection +% +% \startbaselinecorrection \startcombination[4*1] +% {\externalfigure[demo-b]} {no color} +% {\externalfigure[demo-b][color=combicolor]} {indexed duotone} +% {\externalfigure[demo-b][color=blue-100]} {spot color} +% {\externalfigure[demo-b][color=yellow-100]} {spot color} +% \stopcombination \stopbaselinecorrection +% \stopbuffer +% +% \getbuffer \typebuffer diff --git a/tex/context/base/grph-fil.lua b/tex/context/base/grph-fil.lua index 1ec88b487..9cdda13e0 100644 --- a/tex/context/base/grph-fil.lua +++ b/tex/context/base/grph-fil.lua @@ -6,13 +6,13 @@ if not modules then modules = { } end modules ['grph-fil'] = { license = "see context related readme files" } -local format, concat = string.format, table.concat - -local trace_run = false trackers.register("graphic.runfile",function(v) trace_run = v end) +local type = type +local trace_run = false trackers.register("graphic.runfile",function(v) trace_run = v end) local report_run = logs.reporter("graphics","run") --- this code will move +-- Historically running files is part of graphics processing, so this is why it +-- sits here but is part of the job namespace. local allocate = utilities.storage.allocate @@ -22,6 +22,7 @@ local tobesaved = allocate() local jobfiles = { collected = collected, tobesaved = tobesaved, + forcerun = false, -- maybe a directive some day } job.files = jobfiles @@ -33,8 +34,6 @@ end job.register('job.files.collected', tobesaved, initializer) -jobfiles.forcerun = false - function jobfiles.run(name,action) local oldchecksum = collected[name] local newchecksum = file.checksum(name) diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index 33dd0766d..f8c9a5134 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -15,6 +15,7 @@ if not modules then modules = { } end modules ['grph-inc'] = { -- partly qualified -- dimensions -- consult rlx +-- use metatables -- figures.boxnumber can go as we now can use names @@ -68,7 +69,7 @@ local report_inclusion = logs.reporter("graphics","inclusion") local context, img = context, img ---- some extra img functions --- +--- some extra img functions --- can become luat-img.lua local imgkeys = img.keys() @@ -154,16 +155,16 @@ figures.cachepaths = allocate { figures.paths = allocate(table.copy(figures.localpaths)) -figures.order = allocate{ +local lookuporder = allocate { "pdf", "mps", "jpg", "png", "jp2", "jbig", "svg", "eps", "tif", "gif", "mov", "buffer", "tex", "cld", "auto", } -local formats = allocate { +local formats = allocate { -- magic and order will move here ["pdf"] = { list = { "pdf" } }, ["mps"] = { patterns = { "mps", "%d+" } }, ["jpg"] = { list = { "jpg", "jpeg" } }, - ["jp2"] = { list = { "jp2" } }, ["png"] = { list = { "png" } }, + ["jp2"] = { list = { "jp2" } }, ["jbig"] = { list = { "jbig", "jbig2", "jb2" } }, ["svg"] = { list = { "svg", "svgz" } }, ["eps"] = { list = { "eps", "ai" } }, @@ -187,19 +188,44 @@ local magics = allocate { figures.formats = formats -- frozen figures.magics = magics -- frozen +-- We can set the order but only indirectly so that we can check for support. + +function figures.setorder(list) -- can be table or string + if type(list) == "string" then + list = settings_to_array(list) + end + if list and #list > 0 then + lookuporder = allocate() + figures.order = lookuporder + local done = { } -- just to be sure in case the list is generated + for i=1,#list do + local l = lower(list[i]) + if formats[l] and not done[l] then + lookuporder[#lookuporder+1] = l + done[l] = true + end + end + report_inclusion("lookup order: %s",concat(lookuporder," ")) + else + -- invalid list + end +end + function figures.guess(filename) local f = io.open(filename,'rb') if f then local str = f:read(100) f:close() - for i=1,#magics do - local pattern = magics[i] - if pattern.pattern:match(str) then - local format = pattern.format - if trace_figures then - report_inclusion("file %q has format %s",filename,format) + if str then + for i=1,#magics do + local pattern = magics[i] + if pattern.pattern:match(str) then + local format = pattern.format + if trace_figures then + report_inclusion("file %q has format %s",filename,format) + end + return format end - return format end end end @@ -208,7 +234,7 @@ end function figures.setlookups() -- tobe redone .. just set locals local fs, fp = allocate(), allocate() figures.suffixes, figures.patterns = fs, fp - for _, format in next, figures.order do + for _, format in next, lookuporder do local data = formats[format] local list = data.list if list then @@ -247,8 +273,8 @@ local function register(tag,target,what) else data[tag] = { what } end - if not contains(figures.order,target) then - figures.order[#figures.order+1] = target + if not contains(lookuporder,target) then + lookuporder[#lookuporder+1] = target end figures.setlookups() end @@ -610,7 +636,7 @@ local function locate(request) -- name, format, cache -- we could use the hashed data instead local askedpath= file.is_rootbased_path(askedname) local askedbase = file.basename(askedname) - local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.extname(askedname) or "" + local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.suffix(askedname) or "" local askedcache = request.cache local askedconversion = request.conversion local askedresolution = request.resolution @@ -699,9 +725,8 @@ local function locate(request) -- name, format, cache if trace_figures then report_inclusion("strategy: rootbased path") end - local figureorder = figures.order - for i=1,#figureorder do - local format = figureorder[i] + for i=1,#lookuporder do + local format = lookuporder[i] local list = formats[format].list or { format } for j=1,#list do local suffix = list[j] @@ -725,9 +750,8 @@ local function locate(request) -- name, format, cache report_inclusion("strategy: unknown format, prefer quality") end local figurepaths = figures.paths - local figureorder = figures.order - for j=1,#figureorder do - local format = figureorder[j] + for j=1,#lookuporder do + local format = lookuporder[j] local list = formats[format].list or { format } for k=1,#list do local suffix = list[k] @@ -762,11 +786,10 @@ local function locate(request) -- name, format, cache report_inclusion("strategy: unknown format, prefer path") end local figurepaths = figures.paths - local figureorder = figures.order for i=1,#figurepaths do local path = figurepaths[i] - for j=1,#figureorder do - local format = figureorder[j] + for j=1,#lookuporder do + local format = lookuporder[j] local list = formats[format].list or { format } for k=1,#list do local suffix = list[k] @@ -790,9 +813,8 @@ local function locate(request) -- name, format, cache if trace_figures then report_inclusion("strategy: default tex path") end - local figureorder = figures.order - for j=1,#figureorder do - local format = figureorder[j] + for j=1,#lookuporder do + local format = lookuporder[j] local list = formats[format].list or { format } for k=1,#list do local suffix = list[k] @@ -1151,6 +1173,8 @@ local function makeoptions(options) return (to == "table" and concat(options," ")) or (to == "string" and options) or "" end +-- programs.makeoptions = makeoptions + local function runprogram(template,binary,...) local command = format(template,binary,...) local binary = match(binary,"[%S]+") -- to be sure @@ -1168,6 +1192,7 @@ end local epsconverter = { } converters.eps = epsconverter +converters.ps = epsconverter programs.gs = { resolutions = { @@ -1433,7 +1458,7 @@ function figures.applyratio(width,height,w,h) -- width and height are strings an end end --- example of a simple plugin: +-- example of simple plugins: -- -- figures.converters.png = { -- png = function(oldname,newname,resolution) @@ -1443,9 +1468,18 @@ end -- end, -- } +-- figures.converters.bmp = { +-- pdf = function(oldname,newname) +-- os.execute(string.format("gm convert %s %s",oldname,newname)) +-- end +-- } + +-- local fig = figures.push { name = pdffile } +-- figures.identify() +-- figures.check() +-- local nofpages = fig.used.pages +-- figures.pop() + +-- interfacing --- local fig = figures.push { name = pdffile } --- figures.identify() --- figures.check() --- local nofpages = fig.used.pages --- figures.pop() +commands.setfigurelookuporder = figures.setorder diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv index 633130ea9..f96812d26 100644 --- a/tex/context/base/grph-inc.mkiv +++ b/tex/context/base/grph-inc.mkiv @@ -11,15 +11,9 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion} - -%D todo: -%D -%D - color conversion -%D - alternative images -%D - a few more obscure things +% todo: messages -% use framedcommandhandler +\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion} \registerctxluafile{grph-inc}{1.001} \registerctxluafile{grph-fil}{1.001} @@ -28,25 +22,377 @@ \unprotect -%D The following registers are used (if only to be downward compatible). +%D Including graphics is complicated by the fact that we need to locate them first, +%D optionally manipulate them and scale then next. Lookups are to be done as efficient +%D as possible and inclusion of the data might happens only once. In \MKIV\ much of this +%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's +%D more powerful, flexible, pluggable and some of the extended functionality has been +%D moved from modules to the core. The overall functionality is rather stable and has +%D not changed much over the years. + +\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi + +\installcorenamespace{externalfigure} +\installcorenamespace{externalfigureinstance} +\installcorenamespace{externalfigurecollection} + +\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure + +\let\setupexternalfigures\setupexternalfigure + +\setupexternalfigures[% we really need the defaults + \c!method =, + \c!label =, + \c!size =, + \c!conversion =, + \c!resolution =, + \c!prefix =, + \c!cache =, + \c!page =\zerocount, + \c!display =, + \c!mask =, + \c!preset =\v!yes, + \c!split =, + \c!color =, + \c!symbol =\v!no, + \c!controls =\v!no, + \c!resources =, + \c!preview =\v!no + \c!repeat =\v!no + \c!foregroundcolor=, + \c!interaction =\v!none, + \c!hfactor =, + \c!wfactor =, + \c!factor =, + \c!maxwidth =\externalfigureparameter\c!width, + \c!maxheight =\externalfigureparameter\c!height, + \c!xscale =, + \c!yscale =, + \c!scale =, + \c!sx =\externalfigureparameter\c!s, + \c!sy =\externalfigureparameter\c!s, + \c!s =1, + \c!width =, + \c!height =, + \c!lines =, + \c!grid =, + \c!bodyfont =\bodyfontsize, + \c!object =\v!yes, + \c!corner =\v!rectangular, + \c!frame =\v!off, + \c!option =, + \c!reset =\v!no, + \c!directory =, + \c!radius =.5\bodyfontsize, + \c!background =, + \c!splitcolor =\s!white, + \c!order =, + \c!equalwidth =, + \c!equalheight =, + \c!location ={\v!local,\v!global}, + \c!frames =\v!off, + \c!ymax =24, + \c!xmax =, + ] + +%D Defining figures. + +\newcount\c_grph_include_nesting + +\newtoks \everyexternalfigureresets % for the moment still public +\newtoks \everyexternalfigurechecks % for the moment still public + +% \useexternalfigure[alpha][koe] +% \useexternalfigure[beta] [koe] [breedte=1cm] +% \useexternalfigure[gamma][koe][alpha] +% \useexternalfigure[delta][koe][alpha][breedte=2cm] +% +% volle breedte: \externalfigure[koe] \par +% 3cm breed: \externalfigure[koe] [breedte=3cm] \par +% volle breedte: \externalfigure[alpha] \par +% 1cm breed: \externalfigure[beta] \par +% volle breedte: \externalfigure[gamma] \par +% 2cm breed: \externalfigure[delta] \par +% 4cm breed: \externalfigure[beta] [breedte=4cm] \par +% 5cm breed: \externalfigure[gamma][breedte=5cm] \par +% +% \defineexternalfigure[a][width=10cm] +% \defineexternalfigure[b][width=5cm] +% \externalfigure[cow][a] +% \externalfigure[cow][b][height=8cm] +% +% \useexternalfigure[x][cow][width=10cm,height=1cm] +% \externalfigure[x] +% \externalfigure[x][width=3cm] +% +% [label] [filename] +% [label] [filename] [parent] +% [label] [filename] [parent] [settings] +% [label] [filename] [settings] +% +% new: more convenient/efficient than +% +% \use..[a][a][setting] \externalfigure[b][a] +% +% is equivalent to: +% +% \def..[a][setting] \externalfigure[b][a] +% +% see x-res modules for usage: +% +% \defineexternalfigure[name][settings] + +%D Defining is persistent, i.e.\ when you redefine an instance, +%D the already set parameters need to be set again or otherwise +%D the old values will be used. + +\newconditional\c_grph_include_trace_inheritance + +\installtextracker + {graphics.inheritance} + {\settrue \c_grph_include_trace_inheritance} + {\setfalse\c_grph_include_trace_inheritance} + +\installcorenamespace{externalfiguredefinition} + +% \unexpanded\def\defineexternalfigure +% {\dodoubleargument\grph_include_define} +% +% \def\grph_include_define[#1][#2]% +% {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}} + +\let\defineexternalfigures\defineexternalfigure + +\unexpanded\def\useexternalfigure + {\doquadrupleempty\grph_include_use} + +% label file parent settings +% label file settings +% label file parent + +\def\grph_include_use[#1][#2][#3][#4]% + {\doifelsenothing{#1} + {\doifsomething{#2} + {\doifassignmentelse{#3} + {\grph_include_use_indeed{#2}{#2}{#3}{#4}} + {\grph_include_use_indeed{#2}{#2}\empty{#4}}}} + {\doifelsenothing{#2} + {\doifassignmentelse{#3} + {\grph_include_use_indeed{#1}{#1}\empty{#3}} + {\grph_include_use_indeed{#1}{#1}{#3}{#4}}} + {\doifassignmentelse{#3} + {\grph_include_use_indeed{#1}{#2}\empty{#3}} + {\grph_include_use_indeed{#1}{#2}{#3}{#4}}}}} + +\def\grph_include_use_indeed#1#2#3#4% + {\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}% + \grph_include_analyze_collection[#2][#4]} + +% inclusion + +\unexpanded\def\externalfigure + {\dotripleempty\grph_include_figure} + +\def\grph_include_figure[#1][#2][#3]% + {\docheckassignment{#2}% + \ifassignment + \grph_include_place[#1][][#2]% + \else + \grph_include_place[#1][#2][#3]% + \fi} -\newbox \foundexternalfigure -\newif \ifskipexternalfigures -\newtoks \everyexternalfigureresets -\newtoks \everyexternalfigurechecks -\newtoks \externalfigurepostprocessors +% todo: chain them -\def\resetfigurevariables {\the\everyexternalfigureresets} -\def\checkfigurevariables {\the\everyexternalfigurechecks} +\def\grph_include_setup#1#2#3% name parent settings + {\edef\m_grph_include_name {#1}% + \edef\m_grph_include_parent{#2}% + \ifx\m_grph_include_name\empty \else + \let\p_grph_include_name\m_grph_include_name + \fi + \ifx\m_grph_include_parent\empty \else + \grph_include_inherit_from_parent\m_grph_include_parent + \fi + \setupcurrentexternalfigure[#3]} + +% \def\grph_include_inherit_from_parent#1% +% {\ifcsname\??externalfiguredefinition#1\endcsname +% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi +% \csname\??externalfiguredefinition#1\endcsname +% \fi +% \ifcsname\??externalfigureinstance#1\endcsname +% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi +% \csname\??externalfigureinstance#1\endcsname +% \fi} -%D Historic feature: +\def\grph_include_inherit_from_parent#1% + {%\ifcsname\??externalfiguredefinition#1\endcsname + % \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi + % \csname\??externalfiguredefinition#1\endcsname + %\fi + \ifcsname\??externalfigure#1:\s!parent\endcsname + \let\currentexternalfigure#1% + \fi + \ifcsname\??externalfigureinstance#1\endcsname + \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi + \csname\??externalfigureinstance#1\endcsname + \fi} + +\newtoks\t_grph_include_local_settings \appendtoks - \global\let\externalfigurelog\empty -\to \everyexternalfigureresets + \let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode (probably no longer needed) + % + \dontcomplain + \restorecatcodes + \forgetall +\to \t_grph_include_local_settings + +\def\grph_include_place_inherit + {\ifconditional\c_grph_include_trace_inheritance + \writestatus\m!figures{label: \p_grph_include_label, name: \p_grph_include_name, parent: \p_grph_include_parent}% + \fi + \ifx\p_grph_include_parent\empty + % nothing to be done + \else\ifx\p_grph_include_parent\p_grph_include_label + % redundant + \else + \grph_include_inherit_from_parent\p_grph_include_parent + \fi\fi + \ifx\p_grph_include_label\empty + % nothing to be done + \else + \grph_include_inherit_from_parent\p_grph_include_label + \fi} + +\def\grph_include_place[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings] + {\bgroup + \advance\c_grph_include_nesting\plusone + \edef\currentexternalfigure{\the\c_grph_include_nesting}% + \checkexternalfigureparent % each inherits from the root + % + \the\everyexternalfigureresets + % + \edef\p_grph_include_label{#1}% + \let\p_grph_include_name\p_grph_include_label + \docheckassignment{#2}% + \ifassignment + % [label] [settings] + \let\p_grph_include_parent\p_grph_include_label + \grph_include_place_inherit + \setupcurrentexternalfigure[#2]% + \else + % [label] [parent] [settings] + \edef\p_grph_include_parent{#2}% + \ifx\p_grph_include_parent\empty + \let\p_grph_include_parent\p_grph_include_label + \fi + \grph_include_place_inherit + \setupcurrentexternalfigure[#3]% + \fi + % + \the\everyexternalfigurechecks + % + \the\t_grph_include_local_settings + \dostarttagged\t!image\empty + \ctxlua{figures.push { + name = "\p_grph_include_name", + label = "\p_grph_include_label", + page = "\externalfigureparameter\c!page", + size = "\externalfigureparameter\c!size", + object = "\externalfigureparameter\c!object", + prefix = "\externalfigureparameter\c!prefix", + cache = "\externalfigureparameter\c!cache", + format = "\externalfigureparameter\c!method", + preset = "\externalfigureparameter\c!prefix", + controls = "\externalfigureparameter\c!controls", + resources = "\externalfigureparameter\c!resources", + preview = "\externalfigureparameter\c!preview", + display = "\externalfigureparameter\c!display", + mask = "\externalfigureparameter\c!mask", + conversion = "\externalfigureparameter\c!conversion", + resolution = "\externalfigureparameter\c!resolution", + color = "\internalspotcolorparent{\externalfigureparameter\c!color}", % hack is needed + ["repeat"] = "\externalfigureparameter\c!repeat", + width = "\externalfigureparameter\c!width", % can be crap + height = "\externalfigureparameter\c!height", % can be crap + } }% + \ctxlua{figures.identify()}% + % also mode: checkpresense only + \ifconditional\c_grph_include_test_only + \ifcase\figurestatus \else + \ctxlua{figures.check()}% + \ctxlua{figures.dummy()}% + \ctxlua{figures.scale()}% + \ctxlua{figures.done()}% + \fi + \grph_include_set_mode + \else + \ifcase\figurestatus + \ctxlua{figures.dummy()}% + \ctxlua{figures.scale()}% + \else + \ctxlua{figures.check()}% + \ctxlua{figures.include()}% + \ctxlua{figures.scale()}% + \fi + \ctxlua{figures.done()}% + \grph_include_set_mode + \grph_include_finalize + \fi + \ctxlua{figures.pop()}% + \dotagfigure + \naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}% + \dostoptagged + \egroup} + +%D Scaling: + +\let\dowithfigure\relax % name might change (into a proper hook) -\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax -\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax +\unexpanded\def\doscalefigure % used at lua end + {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}} + +\definescale % some day we will inherit + [\v!figure] + [\c!hfactor =\externalfigureparameter\c!hfactor, + \c!wfactor =\externalfigureparameter\c!wfactor, + \c!factor =\externalfigureparameter\c!factor, + \c!maxwidth =\externalfigureparameter\c!maxwidth , + \c!maxheight =\externalfigureparameter\c!maxheight, + \c!equalwidth =\externalfigureparameter\c!equalwidth , + \c!equalheight=\externalfigureparameter\c!equalheight, + \c!xscale =\externalfigureparameter\c!xscale, + \c!yscale =\externalfigureparameter\c!yscale, + \c!scale =\externalfigureparameter\c!scale, + \c!sx =\externalfigureparameter\c!sx, + \c!sy =\externalfigureparameter\c!sy, + \c!s =\externalfigureparameter\c!s, + \c!width =\externalfigureparameter\c!width, + \c!height =\externalfigureparameter\c!height, + \c!lines =\externalfigureparameter\c!lines] + +% % this will become: +% +% \unexpanded\def\doscalefigure % used at lua end +% {\global\setbox\foundexternalfigure\vbox\bgroup +% \bgroup +% \let\currentscale\currentexternalfigure +% \let\scaleparameter\externalfigureparameter +% \dowithnextboxcs\grph_scale_finish\hbox{\dowithfigure{\box\foundexternalfigure}}% +% \egroup} +% +% % or even better: +% +% \def\grph_scale_inherited#1% +% {\bgroup +% \expandafter\let\expandafter\currentscale \csname current#1\endcsname +% \expandafter\let\expandafter\scaleparameter\csname #1parameter\endcsname +% \dowithnextboxcs\grph_scale_finish\hbox} +% +% \unexpanded\def\doscalefigure % used at lua end +% {\global\setbox\foundexternalfigure\vbox\bgroup +% \grph_scale_inherited{externalfigure}{\dowithfigure{\box\foundexternalfigure}}% +% \egroup} %D You can register additional suffixes with the following command: %D @@ -57,19 +403,22 @@ %D \stoptyping \unexpanded\def\definegraphictypesynonym - {\dodoubleargument\dodefinegraphictypesynonym} + {\dodoubleargument\grph_include_set_type_synonym} -\def\dodefinegraphictypesynonym[#1][#2]% +\def\grph_include_set_type_synonym[#1][#2]% {\ctxlua{figures.registersuffix("#1","#2")}} %D Additional paths can be installed with the regular setup command. The next %D macro picks up the list. -\def\setfigurepathlist - {\ctxlua{figures.setpaths("\@@exlocation",\!!bs\@@exdirectory\!!es)}} +\unexpanded\def\setfigurepathlist + {\ctxlua{figures.setpaths("\externalfigureparameter\c!location",\!!bs\externalfigureparameter\c!directory\!!es)}} %D Variables: +\newbox \foundexternalfigure +\newtoks\externalfigurepostprocessors + \def\defaultfigurewidth {8\lineheight} \def\defaultfigureheight {6\lineheight} @@ -112,209 +461,84 @@ \let\figurescalexscale \figurexscale \let\figurescaleyscale \figureyscale +%D Abuse: +%D +%D \starttyping +%D \externalfigure[rubish.pdf] \ifcase\figurestatus\relax \ctxlua{os.exit(999)} \fi +%D \stoptyping + +%D Calculating: + +% \enabletrackers[figures.conversion] +% \externalfigure[demo.svg] +% \externalfigure[demo.svg][conversion=png] + +%D The following registers are used (if only to be downward compatible). + +\newconditional\c_grph_include_skip +\newconditional\c_grph_include_test_only +\newconditional\c_grph_include_level \setfalse\c_grph_include_level % true=background false=normal +\newconditional\c_grph_include_flush \settrue \c_grph_include_flush % true=place false=ignore + +\newsystemmode\v!figure + +\def\grph_include_set_mode + {\ifcase\figurestatus + \global\resetsystemmode\v!figure % todo, also: \v!resource + \else + \global\setsystemmode \v!figure % todo, also: \v!resource + \fi} + \appendtoks - \ctxlua { % figures.defaultwidth .. why not dimen - figures.setpaths("\@@exlocation","\@@exdirectory") ; + \ctxlua { % figures.defaultwidth .. maybe a dimen some day + figures.setpaths("\externalfigureparameter\c!location","\externalfigureparameter\c!directory") ; figures.defaultwidth = \number\dimexpr\defaultfigurewidth \relax ; figures.defaultheight = \number\dimexpr\defaultfigureheight\relax ; figures.boxnumber = \number\foundexternalfigure ; }% \to \everyexternalfigureresets -%D In some situations we need to make sure that the figure related variables -%D are reset. This is especially important when we are nesting. Is this still -%D needed in \MKIV. - -\def\resetexternalfigures - {\let\@@efoption \empty % \let\@@efprefix\empty - \let\@@efmaxwidth \empty % \let\@@efcache \empty - \let\@@efmaxheight \empty % \let\@@efframe \v!off - \let\@@efforegroundcolor\empty - \let\@@efcolor \empty - \let\@@efconversion \empty - \let\@@efbackground \empty - \let\@@efresolution \empty} - -\appendtoks \resetexternalfigures \to \everyoverlay -\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed - -\def\resetfigureusersettings % if we use a command handler we can simply define a new instance - {% - \let\@@efmethod \empty - \let\@@eflabel \empty - \let\@@efsize \empty - \let\@@efconversion\@@exconversion - \let\@@efresolution\@@exresolution - \let\@@efprefix \@@exprefix - \let\@@efcache \@@excache - \let\@@efpage \!!zerocount - \let\@@efobject \@@exobject - \let\@@efdisplay \empty - \let\@@efmask \empty - % - \let\@@efpreset \v!yes - \let\@@efsplit \empty - \let\@@efcolor \empty - % - \let\@@efsymbol \v!no - % - \let\@@efcontrols \v!no - \let\@@efresources \empty - \let\@@efpreview \v!no - \let\@@efrepeat \v!no - % - \let\@@efforegroundcolor\empty - % - \let\@@efinteraction\@@exinteraction - % - \let\@@efhfactor \empty - \let\@@efwfactor \empty - \let\@@effactor \empty - \let\@@efmaxwidth \@@exmaxwidth - \let\@@efmaxheight \@@exmaxheight - \let\@@efxscale \empty - \let\@@efyscale \empty - \let\@@efscale \empty - \let\@@efsx \!!plusone - \let\@@efsy \!!plusone - \let\@@efwidth \empty - \let\@@efheight \empty - \let\@@eflines \empty - \let\@@efgrid \empty} - -\resetfigureusersettings - -\appendtoks - \resetfigureusersettings -\to \everyexternalfigureresets - -\def\checkfigureusersettings - {% old features - \doif\@@exoption\v!frame - {\let\@@efframe\v!on}% - \doif\@@exoption\v!empty - {\skipexternalfigurestrue - \let\@@efframe\v!off}% - \doifsomething\@@efwidth {\doifdimensionelse\@@efwidth {\edef\@@efwidth {\the\dimexpr\@@efwidth }}\donothing}% - \doifsomething\@@efheight{\doifdimensionelse\@@efheight{\edef\@@efheight{\the\dimexpr\@@efheight}}\donothing}% - % fake color in gray bitmaps, assumes that - % a transparent color is used - \doifsomething\@@efforegroundcolor - {\def\@@efbackground{\v!foreground,\v!color}% - \def\@@efbackgroundcolor{\@@efforegroundcolor}}} - \appendtoks - \checkfigureusersettings + \edef\p_option{\externalfigureparameter\c!option}% + \ifx\p_option\v!frame + \setfalse\c_grph_include_skip + \letexternalfigureparameter\c!frame\v!on + \else\ifx\p_option\v!empty + \settrue\c_grph_include_skip + \letexternalfigureparameter\c!frame\v!off + \else + \setfalse\c_grph_include_skip + \fi\fi + % fake color in gray bitmaps, assumes that + % a transparent color is used + \edef\p_foregroundcolor{\externalfigureparameter\c!foregroundcolor}% + \ifx\p_foregroundcolor\empty \else + \setexternalfigureparameter\c!background{\v!foreground,\v!color}% + \letexternalfigureparameter\c!backgroundcolor\p_foregroundcolor + \fi \to \everyexternalfigurechecks %D Internal graphics are handled at the \TEX\ end: -\def\doprocesstexlikefigure#1% retrofit into mkii +\def\grph_include_process_tex#1% {\global\setbox\foundexternalfigure\vbox\framed [\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off, \c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit] {\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here! -\def\doprocessmpslikefigure#1% retrofit into mkii +\def\grph_include_process_mps#1% retrofit into mkii {\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}} -\def\doprocesscldlikefigure#1% +\def\grph_include_process_cld#1% {\global\setbox\foundexternalfigure\vbox{\cldprocessfile{#1}}} -\def\docheckfigurebuffer #1{\doprocesstexlikefigure{\getbuffer[#1]}} -\def\docheckfiguretex #1{\doprocesstexlikefigure{\input{#1}}} -\def\docheckfigurecld #1{\doprocesscldlikefigure{#1}} % we can always add cldrun -\def\docheckfiguremps #1{\doprocessmpslikefigure{#1}} -\def\docheckfiguremprun #1#2{\doprocesstexlikefigure{\useMPrun{#1}{#2}}} - -% \def\doscalefigure -% {\global\setbox\foundexternalfigure\vbox{\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}} - -\def\doscalefigure - {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}} - -% quick hack: chaining \??ef via \s!parent happens when this is also a commandhandler - -\definescale - [\v!figure] - [\c!hfactor =\@@efhfactor , - \c!wfactor =\@@efwfactor , - \c!factor =\@@effactor , - \c!maxwidth =\@@efmaxwidth , - \c!maxheight=\@@efmaxheight, - \c!xscale =\@@efxscale , - \c!yscale =\@@efyscale , - \c!scale =\@@efscale , - \c!sx =\@@efsx , - \c!sy =\@@efsy , - \c!width =\@@efwidth , - \c!height =\@@efheight , - \c!lines =\@@eflines ] - -\newconditional\testexternalfigureonly - -% \enabletrackers[figures.conversion] -% \externalfigure[demo.svg] -% \externalfigure[demo.svg][conversion=png] - -\unexpanded\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current - {\dontcomplain - \restorecatcodes - \forgetall - \resetfigurevariables - \dosetefparameters{#4}{#5}{#6}% - \checkfigurevariables -% \begingroup -% \color[\@@efcolor]{\xdef\globcolorattr{\internalspotcolorname}} -% \endgroup - \ctxlua{figures.push { - name = "#3", - label = "#2", % todo: \@eflabel - page = "\@@efpage", - size = "\@@efsize", - object = "\@@efobject", - prefix = "\@@efprefix", - cache = "\@@efcache", - format = "\@@efmethod", - preset = "\@@efprefix", - controls = "\@@efcontrols", - resources = "\@@efresources", - preview = "\@@efpreview", - display = "\@@efdisplay", - mask = "\@@efmask", - conversion = "\@@efconversion", - resolution = "\@@efresolution", - color = "\internalspotcolorparent\@@efcolor", % hack is needed - ["repeat"] = "\@@efrepeat", - width = "\@@efwidth", % can be crap - height = "\@@efheight", % can be crap - } }% - \ctxlua{figures.identify()}% - % also mode: checkpresense only - \ifconditional\testexternalfigureonly - \ifcase\figurestatus \else - \ctxlua{figures.check()}% - \ctxlua{figures.dummy()}% - \ctxlua{figures.scale()}% - \ctxlua{figures.done()}% - \fi - \signalexternalfigure - \else - \ifcase\figurestatus - \ctxlua{figures.dummy()}% - \ctxlua{figures.scale()}% - \else - \ctxlua{figures.check()}% - \ctxlua{figures.include()}% - \ctxlua{figures.scale()}% - \fi - \ctxlua{figures.done()}% - \signalexternalfigure - \finishexternalfigure - \fi - \ctxlua{figures.pop()}} +\unexpanded\def\docheckfigurebuffer #1{\grph_include_process_tex{\getbuffer[#1]}} % used al lua end +\unexpanded\def\docheckfiguretex #1{\grph_include_process_tex{\input{#1}}} % used al lua end +\unexpanded\def\docheckfigurecld #1{\grph_include_process_cld{#1}} % used al lua end +\unexpanded\def\docheckfiguremps #1{\grph_include_process_mps{#1}} % used al lua end +\unexpanded\def\docheckfiguremprun #1#2{\grph_include_process_tex{\useMPrun{#1}{#2}}} % used al lua end -\def\relocateexternalfigure % easier here than in lua +\unexpanded\def\relocateexternalfigure % easier here than in lua {\global\setbox\foundexternalfigure\vbox to \ht\foundexternalfigure\bgroup \vss \ht\foundexternalfigure\zeropoint @@ -324,33 +548,24 @@ \egroup \egroup} -\newsystemmode\v!figure - -\def\signalexternalfigure % global (dup call to status) - {\ifcase\figurestatus - \global\resetsystemmode\v!figure % todo, also: \v!resource - \else - \global\setsystemmode \v!figure % todo, also: \v!resource - \fi} - \unexpanded\def\startfoundexternalfigure#1#2% ht wd {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup} \unexpanded\def\stopfoundexternalfigure {\hss\egroup\egroup} -\def\emptyfoundexternalfigure +\unexpanded\def\emptyfoundexternalfigure % sort of obsolete {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight \stopfoundexternalfigure} -\def\finishexternalfigure % here we use \figurevariables +\def\grph_include_finalize {\global\setbox\foundexternalfigure\vbox {\ifcase\figurestatus - \let\@@efframe\v!on + \letexternalfigureparameter\c!frame\v!on \fi - \ifconditional\externalfigureflush - \ifconditional\externalfigurelevel % probably background - \ifskipexternalfigures + \ifconditional\c_grph_include_flush + \ifconditional\c_grph_include_level % probably background + \ifconditional\c_grph_include_skip % nothing \fakebox\foundexternalfigure \else\ifcase\figurestatus @@ -361,28 +576,29 @@ \fi\fi \else \iftrialtypesetting \else \feedbackexternalfigure \fi - \settrue\externalfigurelevel - \ifskipexternalfigures + \settrue\c_grph_include_level + \ifconditional\c_grph_include_skip \ifcase\figurestatus - \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}% + \grph_include_replacement\figurelabel\figurefileoriginal{unknown}% \else - \externalfigurereplacement\figurelabel\figurefullname{skipped}% + \grph_include_replacement\figurelabel\figurefullname{skipped}% \fi \else\ifcase\figurestatus - \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}% + \grph_include_replacement\figurelabel\figurefileoriginal{unknown}% \else \the\externalfigurepostprocessors - \doifelse\@@efreset\v!yes - {\wd\foundexternalfigure\figurewidth - \ht\foundexternalfigure\figureheight - \dp\foundexternalfigure\zeropoint - \box\foundexternalfigure} - {\localframed % should also be applied to high res ! - [\??ef] - [\c!offset=\v!overlay, - \c!width=\figurewidth, - \c!height=\figureheight] - {\vfilll\box\foundexternalfigure}}% + \edef\p_reset{\externalfigureparameter\c!reset}% + \ifx\p_reset\v!yes + \wd\foundexternalfigure\figurewidth + \ht\foundexternalfigure\figureheight + \dp\foundexternalfigure\zeropoint + \box\foundexternalfigure + \else + \letexternalfigureparameter\c!offset\v!overlay + \letexternalfigureparameter\c!width \figurewidth + \letexternalfigureparameter\c!height\figureheight + \inheritedexternalfigureframed{\vfilll\box\foundexternalfigure}% + \fi \fi\fi \fi \else @@ -390,35 +606,17 @@ \iftrialtypesetting \else \feedbackexternalfigure \fi \fi}} -\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethreearguments\fi -\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethreearguments\fi +\let\feedbackexternalfigure\relax % hook -\let\feedbackexternalfigure\relax % \gobblefourarguments -\let\dowithfigure \relax +\unexpanded\def\getfiguredimensions + {\dodoubleempty\grph_include_get_dimensions} -\def\getfiguredimensions - {\dodoubleempty\dogetfiguredimensions} - -\def\dogetfiguredimensions[#1][#2]% +\def\grph_include_get_dimensions[#1][#2]% {\startnointerference - \settrue\testexternalfigureonly + \settrue\c_grph_include_test_only \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]% \stopnointerference} -\let\getfiguredimensionsonly\getfiguredimensions - -% \unexpanded\def\doiffigureelse#1% -% {\getfiguredimensions[#1]% so data is available ! -% \ifdim\figurewidth=\zeropoint % todo: \figurestatus -% \expandafter\secondoftwoarguments -% \else -% \expandafter\firstoftwoarguments -% \fi} - -% \unexpanded\def\doiffigureelse#1% just low level call -% {\getfiguredimensions[#1]% so data is available ! ... grouped so status is local -% \doifmodeelse{*\v!figure}\firstoftwoarguments\secondoftwoarguments} % mode is set global - \unexpanded\def\doiffigureelse#1% {\getfiguredimensions[#1]% so data is available ! \ifcase\figurestatus @@ -427,74 +625,137 @@ \expandafter\firstoftwoarguments \fi} -\def\registerexternalfigure % no placement, handy for preprocessing - {\dotripleempty\doregisterexternalfigure} +% No placement, handy for preprocessing: -\def\doregisterexternalfigure[#1][#2][#3]% +\unexpanded\def\registerexternalfigure + {\dotripleempty\grph_include_register} + +\def\grph_include_register[#1][#2][#3]% {\startnointerference - \testexternalfigureonly - \setfalse\externalfigureflush % == test ? - \externalfigure[#1][#2][#3]% or \doexternalfigure + \c_grph_include_test_only + \setfalse\c_grph_include_flush % == test ? + \externalfigure[#1][#2][#3]% or \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]% \stopnointerference} -% helpers (will be replaced when xforms are accessible at the lua end) +% Helpers (will be replaced when xforms are accessible at the lua end) -\def\dosetfigureobject#1% +\unexpanded\def\dosetfigureobject#1% {\setobject{FIG}{#1}\vbox{\box\foundexternalfigure}} -\def\doboxfigureobject#1% +\unexpanded\def\doboxfigureobject#1% {\global\setbox\foundexternalfigure\vbox{\getobject{FIG}{#1}}} % probably one vbox too many -% figurebases +% Figure bases -\def\usefigurebase[#1]% +\unexpanded\def\usefigurebase[#1]% {\ctxlua{figures.bases.use("#1")}} -\protect \endinput +\appendtoks + \setfigurepathlist % the path may be used elsewhere too (as in x-res-04) +\to \everysetupexternalfigure -% \startbuffer -% \definecolor [blue] [c=1,m=.38,y=0,k=.64] -% \definecolor [yellow] [c=0,m=.28,y=1,k=.06] -% -% \definespotcolor [blue-100] [blue] [p=1] -% \definespotcolor [yellow-100] [yellow] [p=1] -% -% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1] -% -% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone -% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone -% -% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth] -% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth] -% -% \startbaselinecorrection \startcombination[4*1] -% {\externalfigure[demo-a]} {no color} -% {\externalfigure[demo-a][color=combicolor]} {indexed duotone} -% {\externalfigure[demo-a][color=combicolor-b]} {spot color} -% {\externalfigure[demo-a][color=combicolor-y]} {spot color} -% \stopcombination \stopbaselinecorrection -% -% \startbaselinecorrection \startcombination[4*1] -% {\externalfigure[demo-b]} {no color} -% {\externalfigure[demo-b][color=combicolor]} {indexed duotone} -% {\externalfigure[demo-b][color=combicolor-b]} {spot color} -% {\externalfigure[demo-b][color=combicolor-y]} {spot color} -% \stopcombination \stopbaselinecorrection -% -% \startbaselinecorrection \startcombination[4*1] -% {\externalfigure[demo-a]} {no color} -% {\externalfigure[demo-a][color=combicolor]} {indexed duotone} -% {\externalfigure[demo-a][color=blue-100]} {spot color} -% {\externalfigure[demo-a][color=yellow-100]} {spot color} -% \stopcombination \stopbaselinecorrection -% -% \startbaselinecorrection \startcombination[4*1] -% {\externalfigure[demo-b]} {no color} -% {\externalfigure[demo-b][color=combicolor]} {indexed duotone} -% {\externalfigure[demo-b][color=blue-100]} {spot color} -% {\externalfigure[demo-b][color=yellow-100]} {spot color} -% \stopcombination \stopbaselinecorrection -% \stopbuffer -% -% \getbuffer \typebuffer +\appendtoks + \ctxcommand{setfigurelookuporder("\externalfigureparameter\c!order")}% +\to \everysetupexternalfigure + +\definecolor[missingfigurecolor][s=.8] + +\def\grph_include_replacement#1#2#3% + {\bgroup + \letexternalfigureparameter\c!width\figurewidth + \letexternalfigureparameter\c!height\figureheight + \letexternalfigureparameter\c!background\v!color + \setexternalfigureparameter\c!backgroundcolor{missingfigurecolor}% + \inheritedexternalfigureframed + {\tt\tfxx \nohyphens + name: \expanded{\verbatimstring{#1}}\\% + file: \expanded{\verbatimstring{#2}}\\% + state: \expanded{\verbatimstring{#3}}}% + \egroup} + +% maybe setuphandler + +\newconditional\c_grph_include_in_collection + +\newdimen\d_grph_include_collection_minwidth +\newdimen\d_grph_include_collection_maxwidth +\newdimen\d_grph_include_collection_minheight +\newdimen\d_grph_include_collection_maxheight + +\def\grph_include_analyze_collection[#1][#2]% + {\ifconditional\c_grph_include_in_collection + \setfalse\c_grph_include_in_collection + \getfiguredimensions[#1][#2]% + \settrue\c_grph_include_in_collection + \scratchdimen\naturalfigurewidth + \ifdim\scratchdimen>\d_grph_include_collection_maxwidth \d_grph_include_collection_maxwidth \scratchdimen \fi + \ifdim\scratchdimen<\d_grph_include_collection_minwidth \d_grph_include_collection_minwidth \scratchdimen \fi + \scratchdimen\naturalfigureheight + \ifdim\scratchdimen>\d_grph_include_collection_maxheight \d_grph_include_collection_maxheight\scratchdimen \fi + \ifdim\scratchdimen<\d_grph_include_collection_minheight \d_grph_include_collection_minheight\scratchdimen \fi + \fi} + +\unexpanded\def\startexternalfigurecollection[#1]% + {\begingroup + \def\currentexternalfigurecollection{#1}% + \settrue\c_grph_include_in_collection + \d_grph_include_collection_minwidth \maxdimen + \d_grph_include_collection_maxwidth \zeropoint + \d_grph_include_collection_minheight\maxdimen + \d_grph_include_collection_maxheight\zeropoint} + +\unexpanded\def\stopexternalfigurecollection + {\setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minwidth }{\the\d_grph_include_collection_minwidth }% + \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxwidth }{\the\d_grph_include_collection_maxwidth }% + \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minheight}{\the\d_grph_include_collection_minheight}% + \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxheight}{\the\d_grph_include_collection_maxheight}% + \endgroup} + +\def\externalfigurecollectionparameter#1#2% + {\csname + \ifcsname\??externalfigurecollection#1:#2\endcsname + \??externalfigurecollection#1:#2% + \else + \s!empty + \fi + \endcsname} + +\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth } +\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth } +\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight} +\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight} + +\let\efcparameter\externalfigurecollectionparameter % still needed ? +\let\efcminwidth \externalfigurecollectionminwidth % still needed ? +\let\efcmaxwidth \externalfigurecollectionmaxwidth % still needed ? +\let\efcminheight\externalfigurecollectionminheight % still needed ? +\let\efcmaxheight\externalfigurecollectionmaxheight % still needed ? + +% \startexternalfigurecollection[name] +% \useexternalfigure[cow] [cow.pdf] +% \useexternalfigure[mill][mill.png] +% \stopexternalfigurecollection +% \starttext +% \bTABLE +% \bTR +% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD +% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD +% \eTR +% \eTABLE +% \stoptext + +\unexpanded\def\showexternalfigures + {\writestatus\m!system{the \string\showexternalfigures\space command is not (yet) implemented in mkiv}} + +\unexpanded\def\overlayfigure#1% + {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]} + +% Bonus: + +\useexternalfigure + [buffer] + [\jobname.buffer] + [\c!object=\v!no] + +\protect \endinput diff --git a/tex/context/base/grph-raw.lua b/tex/context/base/grph-raw.lua index 361f6944d..4c5b031ea 100644 --- a/tex/context/base/grph-raw.lua +++ b/tex/context/base/grph-raw.lua @@ -10,9 +10,12 @@ if not modules then modules = { } end modules ['grph-raw'] = { -- her gnuplot project. It's somewhat premliminary code but it -- works ok for that purpose. +local tonumber = tonumber + local report_bitmap = logs.reporter("graphics","bitmaps") -local texsp = tex.sp +local context = context +local texsp = tex.sp function figures.bitmapimage(t) local data = t.data diff --git a/tex/context/base/grph-raw.mkiv b/tex/context/base/grph-raw.mkiv index 5b488cf58..1c6835564 100644 --- a/tex/context/base/grph-raw.mkiv +++ b/tex/context/base/grph-raw.mkiv @@ -45,14 +45,14 @@ \unexpanded\def\bitmapimage[#1]#2% {\hbox\bgroup - \getparameters[\??gb][\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]% - \ctxlua{figures.bitmapimage { + \getdummyparameters[\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]% + \ctxlua{figures.bitmapimage { % we could pass #1 directly ... todo data = \!!bs#2\!!es, - xresolution = "\@@gbx", - yresolution = "\@@gby", - colorspace = "\@@gbcolor", - width = "\@@gbwidth", - height = "\@@gbheight" + colorspace = "\directdummyparameter\c!color", + width = "\directdummyparameter\c!width", + height = "\directdummyparameter\c!height", + xresolution = "\directdummyparameter\c!x", + yresolution = "\directdummyparameter\c!y", }}% \egroup} diff --git a/tex/context/base/grph-swf.lua b/tex/context/base/grph-swf.lua index 88eed021a..0d33d89aa 100644 --- a/tex/context/base/grph-swf.lua +++ b/tex/context/base/grph-swf.lua @@ -6,19 +6,20 @@ if not modules then modules = { } end modules ['grph-swf'] = { license = "see context related readme files" } +-- maybe: backends.codeinjections.insertswf + local sub, format, match, byte = string.sub, string.format, string.match, string.byte -local readstring, readnumber = io.readstring, io.readnumber local concat = table.concat local floor = math.floor local tonumber = tonumber -local tobitstring = number.tobitstring - -local todimen = number.todimen +local readstringr = io.readstring, io.readnumber +local readnumber = io.readstring, io.readnumber +local tobitstring = number.tobitstring +local todimen = number.todimen local nodeinjections = backends.nodeinjections - -local figures = figures -local context = context +local figures = figures +local context = context local function getheader(name) local f = io.open(name,"rb") diff --git a/tex/context/base/grph-trf.mkiv b/tex/context/base/grph-trf.mkiv index 5984c8a06..d907c1b0c 100644 --- a/tex/context/base/grph-trf.mkiv +++ b/tex/context/base/grph-trf.mkiv @@ -52,6 +52,9 @@ \newcount\c_grph_scale_used_x_scale \newcount\c_grph_scale_used_y_scale +\let \m_grph_scale_used_x_scale\!!plusone +\let \m_grph_scale_used_y_scale\!!plusone + \newdimen\d_grph_scale_outer_v_size % we cannot manipulate any global vsize ! % scratch: @@ -66,8 +69,6 @@ \let\finalscaleboxyscale \!!plusone \let\finalscaleboxwidth \!!zeropoint \let\finalscaleboxheight \!!zeropoint -\let\finalscaleboxxfactor\!!hundred -\let\finalscaleboxyfactor\!!hundred % we can let sx/sy win (first check) @@ -78,8 +79,9 @@ \installcommandhandler \??scale {scale} \??scale % we can have instances \setupscale - [\c!sx=1, - \c!sy=1, + [\c!sx=\scaleparameter\c!s, + \c!sy=\scaleparameter\c!s, + \c!s=1, %\c!scale=, %\c!xscale=, %\c!yscale=, @@ -149,8 +151,6 @@ \global\let\finalscaleboxyscale \!!plusone \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}% \xdef \finalscaleboxheight{\the\d_grph_scale_ht}% - \global\let\finalscaleboxxfactor\!!hundred - \global\let\finalscaleboxyfactor\!!hundred % \forgetall \dontcomplain @@ -208,7 +208,7 @@ \def\grph_scale_rounded#1% {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed - \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax} + \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax} \def\grph_scale_rounded_indeed#1.#2\relax{#1} @@ -219,9 +219,45 @@ \glet\finalscaleboxxscale\p_sx \glet\finalscaleboxyscale\p_sy \ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi - \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi - \xdef\finalscaleboxxfactor{\grph_scale_rounded\finalscaleboxxscale}% - \xdef\finalscaleboxyfactor{\grph_scale_rounded\finalscaleboxyscale}} + \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi} + +\let\grph_scale_calculations_report\relax + +% \def\grph_scale_calculations_report +% {\writestatus +% {scaled}% +% {wd:\finalscaleboxwidth,ht:\finalscaleboxheight +% ,xscale:\finalscaleboxxscale,yscale:\finalscaleboxyscale}} + +% \def\grph_scale_calculations_yes +% {\settrue\c_grph_scale_done +% % initial values +% \d_grph_scale_x_offset\zeropoint +% \d_grph_scale_y_offset\zeropoint +% \d_grph_scale_x_size \d_grph_scale_wd +% \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald! +% % final values +% \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig) +% \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig) +% \c_grph_scale_used_x_scale \plusone % see note * (core-fig) +% \c_grph_scale_used_y_scale \plusone % see note * (core-fig) +% \let\m_grph_scale_used_x_scale \!!plusone +% \let\m_grph_scale_used_y_scale \!!plusone +% % preparations +% \setfalse\c_grph_scale_scaling_done +% \grph_scale_check_parameters +% % calculators +% % beware, they operate in sequence, and calculate missing dimensions / messy +% % grph_scale_by_nature % when? needed? +% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi +% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi +% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi +% % used in actual scaling +% \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}% +% \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}% +% \xdef\finalscaleboxxscale {\luaexpr{\number\c_grph_scale_used_x_scale/1000}}% +% \xdef\finalscaleboxyscale {\luaexpr{\number\c_grph_scale_used_y_scale/1000}}% +% \grph_scale_calculations_report} \def\grph_scale_calculations_yes {\settrue\c_grph_scale_done @@ -235,25 +271,23 @@ \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig) \c_grph_scale_used_x_scale \plusone % see note * (core-fig) \c_grph_scale_used_y_scale \plusone % see note * (core-fig) + \let\m_grph_scale_used_x_scale \!!plusone + \let\m_grph_scale_used_y_scale \!!plusone % preparations \setfalse\c_grph_scale_scaling_done \grph_scale_check_parameters % calculators % beware, they operate in sequence, and calculate missing dimensions / messy - %grph_scale_by_nature % when? needed? + % grph_scale_by_nature % when? needed? \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi - % finalizers / to be done (no longer needed this way, clean up) - \grph_scale_convert_large_scale\d_grph_scale_h_size\figx\c_grph_scale_used_x_scale\m_grph_scale_temp_x - \grph_scale_convert_large_scale\d_grph_scale_v_size\figy\c_grph_scale_used_y_scale\m_grph_scale_temp_y % used in actual scaling \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}% \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}% - \xdef\finalscaleboxxfactor{\the\c_grph_scale_used_x_scale}% - \xdef\finalscaleboxyfactor{\the\c_grph_scale_used_y_scale}% - \xdef\finalscaleboxxscale {\withoutpt\the\dimexpr\m_grph_scale_temp_x\points/\plushundred\relax}% - \xdef\finalscaleboxyscale {\withoutpt\the\dimexpr\m_grph_scale_temp_y\points/\plushundred\relax}} + \glet\finalscaleboxxscale \m_grph_scale_used_x_scale + \glet\finalscaleboxyscale \m_grph_scale_used_y_scale + \grph_scale_calculations_report} \setvalue{\??scalegrid\v!yes }{\getnoflines \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}} \setvalue{\??scalegrid\v!height }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}} @@ -292,27 +326,59 @@ \grph_scale_by_factor_c \grph_scale_by_factor_d}}} +% \def\grph_scale_by_factor_a +% {\grph_scale_apply_size +% \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size +% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size +% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size +% \else +% \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size +% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size +% \fi +% \grph_scale_by_factor_indeed} +% +% \def\grph_scale_by_factor_b +% {\grph_scale_apply_size +% \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size +% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size +% \grph_scale_by_factor_indeed} +% +% \def\grph_scale_by_factor_c +% {\grph_scale_apply_size +% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size +% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size +% \grph_scale_by_factor_indeed} +% +% \def\grph_scale_by_factor_d +% {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size +% \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size +% \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize} + \def\grph_scale_by_factor_a {\grph_scale_apply_size \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size - \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size + \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size \else \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size - \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size + \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size \fi \grph_scale_by_factor_indeed} \def\grph_scale_by_factor_b {\grph_scale_apply_size \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size - \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size + \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size \grph_scale_by_factor_indeed} \def\grph_scale_by_factor_c {\grph_scale_apply_size \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size - \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size + \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size \grph_scale_by_factor_indeed} \def\grph_scale_by_factor_d @@ -333,13 +399,38 @@ \fi \grph_scale_by_dimension} +% \def\grph_scale_by_scale +% {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}% +% \ifx\m_grph_scale_temp\empty \else +% \grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale +% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale +% \global\d_grph_scale_used_x_size\zeropoint +% \global\d_grph_scale_used_y_size\zeropoint +% \ifx\p_maxwidth\empty +% \ifx\p_maxheight\empty +% \else +% \ifdim\d_grph_scale_y_size>\p_maxheight\relax +% \global\d_grph_scale_used_y_size\p_maxheight +% \fi +% \fi +% \else +% \ifdim\d_grph_scale_x_size>\p_maxwidth\relax +% \global\d_grph_scale_used_x_size\p_maxwidth +% \fi +% \fi +% \fi} + \def\grph_scale_by_scale {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}% \ifx\m_grph_scale_temp\empty \else - \grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale - \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale + \grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale + \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale + % \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size\relax % no global needed here + % \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size\relax % no global needed here + % wrong: we need to recalculate the scale \global\d_grph_scale_used_x_size\zeropoint \global\d_grph_scale_used_y_size\zeropoint + % \ifx\p_maxwidth\empty \ifx\p_maxheight\empty \else @@ -369,33 +460,71 @@ \fi \fi} +% \def\grph_scale_by_dimension_a +% {\grph_scale_by_dimension_indeed +% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale +% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}% +% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale +% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}% +% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale +% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}} +% +% \def\grph_scale_by_dimension_b +% {\grph_scale_by_dimension_indeed +% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% +% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% +% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}} +% +% \def\grph_scale_by_dimension_c +% {\grph_scale_by_dimension_indeed +% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}% +% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}% +% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}} +% +% \def\grph_scale_by_dimension_d +% {\grph_scale_by_dimension_indeed +% {\grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale +% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale}% +% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% +% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}} + \def\grph_scale_by_dimension_a {\grph_scale_by_dimension_indeed - {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale - \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}% - {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale - \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}% - {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale - \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}} + {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size + \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}% + {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size + \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}% + {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size + \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}} \def\grph_scale_by_dimension_b {\grph_scale_by_dimension_indeed - {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% - {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% - {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}} + {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}} \def\grph_scale_by_dimension_c - {\grph_scale_by_dimension_indeed - {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}% - {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}% - {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}} + {\grph_scale_by_dimension_indeed % weird .. three same cases + {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}} \def\grph_scale_by_dimension_d {\grph_scale_by_dimension_indeed - {\grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale - \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale}% - {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}% - {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}} + {\grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale + \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale + \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size + \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size + \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}% + {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size + \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}} \def\grph_scale_by_dimension_indeed#1#2#3% {#1\relax @@ -417,34 +546,63 @@ \setvalue{\??scalenorm\v!max }#1#2#3#4#5{\global#1#4} \setvalue{\??scalenorm\v!fit }#1#2#3#4#5{\global#1#5} -\setvalue{\??scalenorm\v!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\@@exbodyfont\relax} -\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\@@exbodyfont/10\relax\relax} % brr ex +\setvalue{\??scalenorm\v!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\externalfigureparameter\c!bodyfont\relax} +\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/10\relax\relax} % brr ex \setvalue{\??scalenorm\v!auto }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi} \setvalue{\??scalenorm\empty }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi} \setvalue{\??scalenorm\s!default}#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi} -\def\grph_scale_calculate_scales#1#2#3#4% - {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax - \c_grph_scale_used_x_scale\scratchdimen - \c_grph_scale_used_y_scale\scratchdimen - #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax} +% \def\grph_scale_calculate_scales#1#2#3#4% +% {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax +% \c_grph_scale_used_x_scale\scratchdimen +% \c_grph_scale_used_y_scale\scratchdimen +% %\writestatus{!!!!}{\the#3/\luaexpr{\number\dimexpr#1\relax/\number\dimexpr#2/1000}}% +% #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax} +% +% \def\grph_scale_calculate_scale#1#2#3% +% {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax} +% +% \def\grph_scale_apply_scale#1#2#3#4% #4 = parameter / scale can be empty +% {\ifcase0#4\relax +% \ifcase0\p_scale\relax +% #3=\plusthousand +% \else +% #3=\p_scale +% \fi +% \else +% #3=#4% +% \fi +% \relax % important ! still ? +% \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi +% \relax} + +\def\grph_scale_calculate_scales#1#2% + {\edef\m_grph_scale_used_x_scale{\luaexpr{\number#1/\number#2}}% + \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale} + +% we could inline this: +% +% \grph_scale_calculate_scale\m_grph_scale_used_x_scale#1#2 +% \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale \def\grph_scale_calculate_scale#1#2#3% - {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax} - -\def\grph_scale_apply_scale#1#2#3#4% #4 = parameter / scale can be empty - {\ifcase0#4\relax - \ifcase0\p_scale\relax - #3=\plusthousand - \else - #3=\p_scale - \fi - \else - #3=#4% - \fi - \relax % important ! still ? - \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi - \relax} + {\edef#1{\luaexpr{\number#2/\number#3}}} + +\def\grph_scale_apply_scale#1#2% #1 = parameter / scale can be empty + {\edef#1{\luaexpr + {\number + \ifx#2\empty + \ifx \p_scale \empty \plusthousand \else + \ifnum\p_scale=\zerocount \plusthousand \else + \p_scale \fi\fi + \else\ifnum#2=\zerocount + \ifx \p_scale \empty \plusthousand \else + \ifnum\p_scale=\zerocount \plusthousand \else + \p_scale \fi\fi + \else + #2% + \fi\fi + /1000}}} \def\grph_scale_apply_size {\ifx\p_maxheight\empty @@ -484,30 +642,34 @@ \d_grph_scale_h_size\p_width \fi} -\def\grph_scale_convert_large_scale#1#2#3#4% - {\scratchdimen#1\relax - \ifnum#3=\plusthousand - % == scale 1 - \else - % better 1000 100 10 ranges, evt round 2sp - \divide\scratchdimen \plusthousand - \multiply\scratchdimen #3\relax - \fi - \scratchdimen-\scratchdimen % beter hier - dan in driver - \edef#2{\the\scratchdimen}% - \scratchcounter#3\relax - \ifnum\scratchcounter>\plustenthousand - \divide\scratchcounter\plusten - \scratchdimen\the\scratchcounter\points - \else - \scratchdimen\the\scratchcounter\points - \divide\scratchdimen\plusten - \fi - \edef#4{\withoutpt\the\scratchdimen}} +%\def\grph_scale_convert_large_scale#1#2#3#4% +% {\scratchdimen#1\relax +% \ifnum#3=\plusthousand +% % == scale 1 +% \else +% % better 1000 100 10 ranges, evt round 2sp +% \divide\scratchdimen \plusthousand +% \multiply\scratchdimen #3\relax +% \fi +% \scratchdimen-\scratchdimen % beter hier - dan in driver +% \edef#2{\the\scratchdimen}% +% \scratchcounter#3\relax +% \ifnum\scratchcounter>\plustenthousand +% \divide\scratchcounter\plusten +% \scratchdimen\the\scratchcounter\points % \the ? +% \else +% \scratchdimen\the\scratchcounter\points % \the ? +% \divide\scratchdimen\plusten +% \fi +% \edef#4{\withoutpt\the\scratchdimen}} +% +% \def\grph_scale_convert_large_scale#1#2#3#4% less overflow +% {\edef#2{\ifnum#3=\plusthousand-\the\dimexpr#1\else\luaexpr{-\number#3*\number\dimexpr#1/1000}sp\fi}% +% \edef#4{\luaexpr{\number#3/10}}} % \startcombination -% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {} -% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {} +% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow} +% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill} % \stopcombination \def\grph_scale_position @@ -535,7 +697,7 @@ {\hbox} \def\grph_scale_fast_yes#1% - {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1pt/1000\relax}% brrr + {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1\onepoint/1000\relax}% brrr \let\finalscaleboxyscale\finalscaleboxxscale \dowithnextboxcs\grph_scale_fast_finish\hbox} @@ -544,6 +706,19 @@ \box\nextbox \endgroup} +\unexpanded\def\fastsxsy#1#2% + {\bgroup + \edef\p_sx{#1}% + \edef\p_sy{#2}% + \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox} + +\def\grph_scale_fast_sx_xy_finish + {\grph_scale_check_sx_sy + \grph_scale_calculations_nop + \grph_scale_apply + \box\nextbox + \egroup} + %D \macros %D {clip, setupclipping} %D @@ -575,8 +750,9 @@ %D %D \showsetup{setupclipping} -\unexpanded\def\setupclipping - {\dodoubleargument\getparameters[\??cp]} +\installcorenamespace{clipping} + +\installdirectcommandhandler \??clipping {clipping} \unexpanded\def\clip {\dosingleempty\grph_clip} @@ -584,62 +760,106 @@ \def\grph_clip[#1]% nb top->bottom left->right {\bgroup \iffirstargument - \getparameters[\??cp][#1]% + \setupcurrentclipping[#1]% \fi \dowithnextboxcs\grph_clip_finish\hbox} \def\grph_clip_finish - {\doifelse\@@cpstate\v!start + {\doifelse{\clippingparameter\c!state}\v!start \grph_clip_yes_finish \grph_clip_nop_finish} +% \def\grph_clip_yes_finish +% {\ifdim\@@cpwidth>\zeropoint +% \!!dimena\@@cpwidth +% \!!dimenc\@@cphoffset +% \else +% \!!dimena\wd\nextbox +% \divide\!!dimena \@@cpnx +% \!!dimenc\@@cpx\!!dimena +% \advance\!!dimenc -\!!dimena +% \!!dimena\@@cpsx\!!dimena +% \fi +% \relax % sure +% \ifdim\@@cpheight>\zeropoint +% \!!dimenb\@@cpheight +% \!!dimend\ht\nextbox +% \advance\!!dimend -\@@cpvoffset +% \advance\!!dimend -\!!dimenb +% \else +% \!!dimenb\ht\nextbox +% \divide\!!dimenb \@@cpny +% \!!dimend-\@@cpy\!!dimenb +% \advance\!!dimend -\@@cpsy\!!dimenb +% \advance\!!dimend \!!dimenb +% \!!dimenb\@@cpsy\!!dimenb +% \advance\!!dimend \ht\nextbox % dimend ! +% \fi +% \setbox\nextbox\hbox % old +% {\advance\!!dimenc -\@@cpleftoffset % new ! +% \advance\!!dimend -\@@cpbottomoffset % new ! % - added +% \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old +% \wd\nextbox\zeropoint +% \ht\nextbox\zeropoint +% \dp\nextbox\zeropoint +% \setbox\nextbox\hbox +% {\advance\!!dimena \@@cpleftoffset % new ! +% \advance\!!dimena \@@cprightoffset % new ! +% \advance\!!dimenb \@@cpbottomoffset % new ! +% \advance\!!dimenb \@@cptopoffset % new ! +% \dostartclipping\@@cpmp\!!dimena\!!dimenb % old +% \box\nextbox +% \dostopclipping}% +% \setbox\nextbox\hbox % new ! +% {\!!dimena-\@@cpleftoffset % new ! +% \!!dimenb \@@cpbottomoffset % new ! % - removed +% \hskip\!!dimena\lower\!!dimenb\box\nextbox}% new ! +% \wd\nextbox\!!dimena +% \ht\nextbox\!!dimenb +% \dp\nextbox\zeropoint +% \box\nextbox +% \egroup} + \def\grph_clip_yes_finish - {\ifdim\@@cpwidth>\zeropoint - \!!dimena\@@cpwidth - \!!dimenc\@@cphoffset + {\ifdim\clippingparameter\c!width>\zeropoint + \scratchwidth \clippingparameter\c!width + \scratchxoffset\clippingparameter\c!hoffset \else - \!!dimena\wd\nextbox - \divide\!!dimena \@@cpnx - \!!dimenc\@@cpx\!!dimena - \advance\!!dimenc -\!!dimena - \!!dimena\@@cpsx\!!dimena + \scratchwidth\dimexpr\wd\nextbox/\clippingparameter\c!nx\relax + \scratchxoffset\dimexpr\clippingparameter\c!x\scratchwidth-\scratchwidth\relax + \scratchwidth\clippingparameter\c!sx\scratchwidth \fi \relax % sure - \ifdim\@@cpheight>\zeropoint - \!!dimenb\@@cpheight - \!!dimend\ht\nextbox - \advance\!!dimend -\@@cpvoffset - \advance\!!dimend -\!!dimenb + \ifdim\clippingparameter\c!height>\zeropoint + \scratchheight\clippingparameter\c!height + \scratchyoffset\dimexpr\ht\nextbox-\clippingparameter\c!voffset-\scratchheight\relax \else - \!!dimenb\ht\nextbox - \divide\!!dimenb \@@cpny - \!!dimend-\@@cpy\!!dimenb - \advance\!!dimend -\@@cpsy\!!dimenb - \advance\!!dimend \!!dimenb - \!!dimenb\@@cpsy\!!dimenb - \advance\!!dimend \ht\nextbox % dimend ! + \scratchheight\dimexpr\ht\nextbox/\clippingparameter\c!ny\relax + \scratchyoffset\dimexpr-\clippingparameter\c!y\scratchheight-\clippingparameter\c!sy\scratchheight+\scratchheight\relax + \scratchheight\clippingparameter\c!sy\scratchheight + \advance\scratchyoffset \ht\nextbox \fi - \setbox\nextbox\hbox % old - {\advance\!!dimenc -\@@cpleftoffset % new ! - \advance\!!dimend -\@@cpbottomoffset % new ! % - added - \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old + \setbox\nextbox\hbox + {\advance\scratchxoffset -\clippingparameter\c!leftoffset \relax + \advance\scratchyoffset -\clippingparameter\c!bottomoffset\relax + \hskip-\scratchxoffset + \lower\scratchyoffset + \box\nextbox}% \wd\nextbox\zeropoint \ht\nextbox\zeropoint \dp\nextbox\zeropoint \setbox\nextbox\hbox - {\advance\!!dimena \@@cpleftoffset % new ! - \advance\!!dimena \@@cprightoffset % new ! - \advance\!!dimenb \@@cpbottomoffset % new ! - \advance\!!dimenb \@@cptopoffset % new ! - \dostartclipping\@@cpmp\!!dimena\!!dimenb % old + {\advance\scratchwidth \dimexpr\clippingparameter\c!leftoffset +\clippingparameter\c!rightoffset\relax + \advance\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset \relax + \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight \box\nextbox \dostopclipping}% - \setbox\nextbox\hbox % new ! - {\!!dimena-\@@cpleftoffset % new ! - \!!dimenb \@@cpbottomoffset % new ! % - removed - \hskip\!!dimena\lower\!!dimenb\box\nextbox}% new ! - \wd\nextbox\!!dimena - \ht\nextbox\!!dimenb + \setbox\nextbox\hbox + {\hskip-\clippingparameter\c!leftoffset + \lower \clippingparameter\c!bottomoffset + \box\nextbox}% + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight \dp\nextbox\zeropoint \box\nextbox \egroup} @@ -650,18 +870,18 @@ \setupclipping [\c!state=\v!start, - \c!n=1, % was 2 - \c!nx=\@@cpn,\c!x=1,\c!sx=1, - \c!ny=\@@cpn,\c!y=1,\c!sy=1, - \c!width=\!!zeropoint, - \c!height=\!!zeropoint, - \c!hoffset=\!!zeropoint, - \c!voffset=\!!zeropoint, + \c!n=\plusone, % was \plustwo + \c!nx=\clippingparameter\c!n,\c!x=\plusone,\c!sx=\plusone, + \c!ny=\clippingparameter\c!n,\c!y=\plusone,\c!sy=\plusone, + \c!width=\zeropoint, + \c!height=\zeropoint, + \c!hoffset=\zeropoint, + \c!voffset=\zeropoint, \c!offset=\zeropoint, - \c!leftoffset=\@@cpoffset, % \zeropoint, - \c!rightoffset=\@@cpoffset, % \zeropoint, - \c!topoffset=\@@cpoffset, % \zeropoint, - \c!bottomoffset=\@@cpoffset,% \zeropoint, + \c!leftoffset=\clippingparameter\c!offset, + \c!rightoffset=\clippingparameter\c!offset, + \c!topoffset=\clippingparameter\c!offset, + \c!bottomoffset=\clippingparameter\c!offset, \c!mp=] %D \startbuffer diff --git a/tex/context/base/grph-u3d.lua b/tex/context/base/grph-u3d.lua index f2baac2f3..529cd6188 100644 --- a/tex/context/base/grph-u3d.lua +++ b/tex/context/base/grph-u3d.lua @@ -8,17 +8,17 @@ if not modules then modules = { } end modules ['grph-u3d'] = { -- see lpdf-u3d.lua for comment +-- maybe: backends.codeinjections.insertu3d + local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end) local report_u3d = logs.reporter("graphics","u3d") -local figures = figures - +local figures = figures +local context = context local nodeinjections = backends.nodeinjections local todimen = string.todimen --- maybe todo: backends.codeinjections.insertu3d - function figures.checkers.u3d(data) local dr, du, ds = data.request, data.used, data.status local width = todimen(dr.width or figures.defaultwidth) diff --git a/tex/context/base/java-ini.lua b/tex/context/base/java-ini.lua index 1e98de717..b431a965c 100644 --- a/tex/context/base/java-ini.lua +++ b/tex/context/base/java-ini.lua @@ -8,9 +8,10 @@ if not modules then modules = { } end modules ['java-ini'] = { local format = string.format local concat = table.concat -local lpegmatch, lpegP, lpegR, lpegS, lpegC, lpegCarg = lpeg.match, lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Carg +local lpegmatch, P, S, C, Carg, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Carg, lpeg.Cc local allocate = utilities.storage.allocate +local settings_to_array = utilities.parsers.settings_to_array local variables = interfaces.variables -- todo: don't flush scripts if no JS key @@ -38,24 +39,24 @@ local function storefunction(s,preamble) functions[s] = preamble end -local uses = lpegP("uses") -local used = lpegP("used") -local left = lpegP("{") -local right = lpegP("}") -local space = lpegS(" \r\n") +local uses = P("uses") +local used = P("used") +local left = P("{") +local right = P("}") +local space = S(" \r\n") local spaces = space^0 -local braced = left * lpegC((1-right-space)^1) * right -local unbraced = lpegC((1-space)^1) +local braced = left * C((1-right-space)^1) * right +local unbraced = C((1-space)^1) local name = spaces * (braced + unbraced) * spaces -local any = lpegP(1) -local script = lpegC(any^1) -local funct = lpegP("function") -local leftp = lpegP("(") -local rightp = lpegP(")") -local fname = spaces * funct * spaces * (lpegC((1-space-left-leftp)^1) * lpegCarg(1) / storefunction) * spaces * leftp - -local parsecode = name * ((uses * name) + lpeg.Cc("")) * spaces * script -local parsepreamble = name * ((used * name) + lpeg.Cc("")) * spaces * script +local any = P(1) +local script = C(any^1) +local funct = P("function") +local leftp = P("(") +local rightp = P(")") +local fname = spaces * funct * spaces * (C((1-space-left-leftp)^1) * Carg(1) / storefunction) * spaces * leftp + +local parsecode = name * ((uses * name) + Cc("")) * spaces * script +local parsepreamble = name * ((used * name) + Cc("")) * spaces * script local parsefunctions = (fname + any)^0 function javascripts.storecode(str) @@ -112,7 +113,7 @@ end function javascripts.usepreamblenow(name) -- now later if name and name ~= "" and name ~= variables.reset then -- todo: reset - local names = utilities.parsers.settings_to_array(name) + local names = settings_to_array(name) for i=1,#names do local somename = names[i] if not preambled[somename] then diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua index 2d502f164..2b94de76b 100644 --- a/tex/context/base/l-boolean.lua +++ b/tex/context/base/l-boolean.lua @@ -16,28 +16,49 @@ function boolean.tonumber(b) end function toboolean(str,tolerant) - if tolerant then - local tstr = type(str) - if tstr == "string" then - return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t" - elseif tstr == "number" then - return tonumber(str) ~= 0 - elseif tstr == "nil" then - return false - else - return str - end + if str == nil then + return false + elseif str == false then + return false + elseif str == true then + return true elseif str == "true" then return true elseif str == "false" then return false + elseif not tolerant then + return false + elseif str == 0 then + return false + elseif (tonumber(str) or 0) > 0 then + return true else - return str + return str == "yes" or str == "on" or str == "t" end end string.toboolean = toboolean +function string.booleanstring(str) + if str == nil then + return false + elseif str == false then + return false + elseif str == true then + return true + elseif str == "true" then + return true + elseif str == "false" then + return false + elseif str == 0 then + return false + elseif (tonumber(str) or 0) > 0 then + return true + else + return str == "yes" or str == "on" or str == "t" + end +end + function string.is_boolean(str,default) if type(str) == "string" then if str == "true" or str == "yes" or str == "on" or str == "t" then diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua index 71de3114e..3deb660ce 100644 --- a/tex/context/base/l-dir.lua +++ b/tex/context/base/l-dir.lua @@ -25,6 +25,24 @@ local isdir = lfs.isdir local isfile = lfs.isfile local currentdir = lfs.currentdir +-- in case we load outside luatex + +if not isdir then + function isdir(name) + local a = attributes(name) + return a and a.mode == "directory" + end + lfs.isdir = isdir +end + +if not isfile then + function isfile(name) + local a = attributes(name) + return a and a.mode == "file" + end + lfs.isfile = isfile +end + -- handy function dir.current() diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index edfbc0f92..bea4ef0aa 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -34,7 +34,7 @@ local function nameonly(name) return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$","")) end -local function extname(name,default) +local function suffixonly(name,default) return match(name,"^.+%.([^/\\]-)$") or default or "" end @@ -43,11 +43,16 @@ local function splitname(name) return n or name, s or "" end -file.basename = basename -file.dirname = dirname -file.nameonly = nameonly -file.extname = extname -file.suffix = extname +file.basename = basename + +file.pathpart = dirname +file.dirname = dirname + +file.nameonly = nameonly + +file.suffixonly = suffixonly +file.extname = suffixonly -- obsolete +file.suffix = suffixonly function file.removesuffix(filename) return (gsub(filename,"%.[%a%d]+$","")) @@ -193,6 +198,11 @@ end file.isreadable = file.is_readable -- depricated file.iswritable = file.is_writable -- depricated +function file.size(name) + local a = attributes(name) + return a and a.size or 0 +end + -- todo: lpeg \\ / .. does not save much local checkedsplit = string.checkedsplit @@ -323,7 +333,7 @@ end --~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 ---~ function file.extname(name) +--~ function file.suffixonly(name) --~ return lpegmatch(pattern,name) or "" --~ end @@ -385,7 +395,7 @@ end --~ end --~ end ---~ local test = file.extname +--~ local test = file.suffixonly --~ local test = file.basename --~ local test = file.dirname --~ local test = file.addsuffix @@ -431,6 +441,7 @@ local drive = C(R("az","AZ")) * P(":") local path = C(((1-slash)^0 * slash)^0) local suffix = period * C(P(1-period)^0 * P(-1)) local base = C((1-suffix)^0) +local rest = C(P(1)^0) drive = drive + Cc("") path = path + Cc("") @@ -439,7 +450,8 @@ suffix = suffix + Cc("") local pattern_a = drive * path * base * suffix local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) +local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures +local pattern_d = path * rest function file.splitname(str,splitdrive) if splitdrive then @@ -449,6 +461,10 @@ function file.splitname(str,splitdrive) end end +function file.splitbase(str) + return lpegmatch(pattern_d,str) -- returns path, base+suffix +end + function file.nametotable(str,splitdrive) -- returns table local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str) if splitdrive then @@ -470,6 +486,8 @@ function file.nametotable(str,splitdrive) -- returns table end end +-- print(file.splitbase("a/b/c.txt")) + -- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end -- -- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua index 4f27dc1dc..657b755b8 100644 --- a/tex/context/base/l-io.lua +++ b/tex/context/base/l-io.lua @@ -17,14 +17,14 @@ else io.fileseparator, io.pathseparator = "/" , ":" end -function io.loaddata(filename,textmode) +function io.loaddata(filename,textmode) -- return nil if empty local f = io.open(filename,(textmode and 'r') or 'rb') if f then local data = f:read('*all') f:close() - return data - else - return nil + if #data > 0 then + return data + end end end @@ -46,6 +46,45 @@ function io.savedata(filename,data,joiner) end end +function io.loadlines(filename,n) -- return nil if empty + local f = io.open(filename,'r') + if f then + if n then + local lines = { } + for i=1,n do + local line = f:read("*lines") + if line then + lines[#lines+1] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = f:read("*line") or "" + assert(f:close()) + if #line > 0 then + return line + end + end + end +end + +function io.loadchunk(filename,n) + local f = io.open(filename,'rb') + if f then + local data = f:read(n or 1024) + f:close() + if #data > 0 then + return data + end + end +end + function io.exists(filename) local f = io.open(filename) if f == nil then diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index 13294ab0d..d92b722ed 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -13,6 +13,8 @@ local lpeg = require("lpeg") -- tracing (only used when we encounter a problem in integration of lpeg in luatex) +-- some code will move to unicode and string + local report = texio and texio.write_nl or print -- local lpmatch = lpeg.match @@ -49,8 +51,8 @@ local report = texio and texio.write_nl or print -- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end -- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end -local type = type -local byte, char, gmatch = string.byte, string.char, string.gmatch +local type, next = type, next +local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format -- Beware, we predefine a bunch of patterns here and one reason for doing so -- is that we get consistent behaviour in some of the visualizers. @@ -58,9 +60,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch lpeg.patterns = lpeg.patterns or { } -- so that we can share local patterns = lpeg.patterns -local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match -local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc -local lpegtype = lpeg.type +local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp +local lpegtype, lpegmatch = lpeg.type, lpeg.match local utfcharacters = string.utfcharacters local utfgmatch = unicode and unicode.utf8.gmatch @@ -111,6 +112,10 @@ patterns.utf8char = utf8char patterns.validutf8 = validutf8char patterns.validutf8char = validutf8char +local eol = S("\n\r") +local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) +local whitespace = eol + spacer + patterns.digit = digit patterns.sign = sign patterns.cardinal = sign^0 * digit^1 @@ -130,16 +135,16 @@ patterns.letter = patterns.lowercase + patterns.uppercase patterns.space = space patterns.tab = P("\t") patterns.spaceortab = patterns.space + patterns.tab -patterns.eol = S("\n\r") -patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) +patterns.eol = eol +patterns.spacer = spacer +patterns.whitespace = whitespace patterns.newline = newline patterns.emptyline = newline^1 -patterns.nonspacer = 1 - patterns.spacer -patterns.whitespace = patterns.eol + patterns.spacer -patterns.nonwhitespace = 1 - patterns.whitespace +patterns.nonspacer = 1 - spacer +patterns.nonwhitespace = 1 - whitespace patterns.equal = P("=") patterns.comma = P(",") -patterns.commaspacer = P(",") * patterns.spacer^0 +patterns.commaspacer = P(",") * spacer^0 patterns.period = P(".") patterns.colon = P(":") patterns.semicolon = P(";") @@ -154,6 +159,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble patterns.unspacer = ((patterns.spacer^1)/"")^0 +patterns.singlequoted = squote * patterns.nosquote * squote +patterns.doublequoted = dquote * patterns.nodquote * dquote +patterns.quoted = patterns.doublequoted + patterns.singlequoted + patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1 patterns.beginline = #(1-newline) @@ -164,8 +173,17 @@ patterns.beginline = #(1-newline) -- print(string.unquoted('"test"')) -- print(string.unquoted('"test"')) -function lpeg.anywhere(pattern) --slightly adapted from website - return P { P(pattern) + 1 * V(1) } -- why so complex? +local function anywhere(pattern) --slightly adapted from website + return P { P(pattern) + 1 * V(1) } +end + +lpeg.anywhere = anywhere + +function lpeg.instringchecker(p) + p = anywhere(p) + return function(str) + return lpegmatch(p,str) and true or false + end end function lpeg.splitter(pattern, action) @@ -214,13 +232,13 @@ function string.splitup(str,separator) if not separator then separator = "," end - return match(splitters_m[separator] or splitat(separator),str) + return lpegmatch(splitters_m[separator] or splitat(separator),str) end ---~ local p = splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more ---~ local p = splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more ---~ local p = splitat("->",false) print(match(p,"oeps")) -- oeps ---~ local p = splitat("->",true) print(match(p,"oeps")) -- oeps +--~ local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more +--~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more +--~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps +--~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps local cache = { } @@ -230,16 +248,20 @@ function lpeg.split(separator,str) c = tsplitat(separator) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end function string.split(str,separator) - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c + if separator then + local c = cache[separator] + if not c then + c = tsplitat(separator) + cache[separator] = c + end + return lpegmatch(c,str) + else + return { str } end - return match(c,str) end local spacing = patterns.spacer^0 * newline -- sort of strip @@ -252,7 +274,7 @@ patterns.textline = content --~ local linesplitter = Ct(content^0) --~ --~ function string.splitlines(str) ---~ return match(linesplitter,str) +--~ return lpegmatch(linesplitter,str) --~ end local linesplitter = tsplitat(newline) @@ -260,7 +282,7 @@ local linesplitter = tsplitat(newline) patterns.linesplitter = linesplitter function string.splitlines(str) - return match(linesplitter,str) + return lpegmatch(linesplitter,str) end local utflinesplitter = utfbom^-1 * tsplitat(newline) @@ -268,7 +290,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline) patterns.utflinesplitter = utflinesplitter function string.utfsplitlines(str) - return match(utflinesplitter,str or "") + return lpegmatch(utflinesplitter,str or "") +end + +local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0) +local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0) + +function string.utfsplit(str,ignorewhitespace) -- new + if ignorewhitespace then + return lpegmatch(utfcharsplitter_iws,str or "") + else + return lpegmatch(utfcharsplitter_ows,str or "") + end +end + +-- inspect(string.utfsplit("a b c d")) +-- inspect(string.utfsplit("a b c d",true)) + +-- -- alternative 1: 0.77 +-- +-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0) +-- +-- function string.utflength(str) +-- return #lpegmatch(utfcharcounter,str or "") +-- end +-- +-- -- alternative 2: 1.70 +-- +-- local n = 0 +-- +-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow +-- +-- function string.utflength(str) +-- n = 0 +-- lpegmatch(utfcharcounter,str or "") +-- return n +-- end +-- +-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047) + +local n = 0 + +local utfcharcounter = utfbom^-1 * Cs ( ( + Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end + + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end + + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end + + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end +)^0 ) + +function string.utflength(str) + n = 0 + lpegmatch(utfcharcounter,str or "") + return n end --~ lpeg.splitters = cache -- no longer public @@ -283,7 +356,7 @@ function lpeg.checkedsplit(separator,str) c = Ct(separator^0 * other * (separator^1 * other)^0) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end function string.checkedsplit(str,separator) @@ -294,7 +367,7 @@ function string.checkedsplit(str,separator) c = Ct(separator^0 * other * (separator^1 * other)^0) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end --~ from roberto's site: @@ -309,10 +382,10 @@ patterns.utf8byte = utf8byte --~ local str = " a b c d " ---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.stripper("ab") print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.keeper("ab") print("["..lpeg.match(s,str).."]") +--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]") local cache = { } @@ -345,11 +418,11 @@ function lpeg.keeper(str) end function lpeg.frontstripper(str) -- or pattern (yet undocumented) - return (P(str) + P(true)) * Cs(P(1)^0) + return (P(str) + P(true)) * Cs(anything^0) end function lpeg.endstripper(str) -- or pattern (yet undocumented) - return Cs((1 - P(str) * P(-1))^0) + return Cs((1 - P(str) * endofstring)^0) end -- Just for fun I looked at the used bytecode and @@ -358,8 +431,22 @@ end function lpeg.replacer(one,two) if type(one) == "table" then local no = #one - if no > 0 then - local p + local p + if no == 0 then + for k, v in next, one do + local pp = P(k) / v + if p then + p = p + pp + else + p = pp + end + end + return Cs((p + 1)^0) + elseif no == 1 then + local o = one[1] + one, two = P(o[1]), o[2] + return Cs(((1-one)^1 + one/two)^0) + else for i=1,no do local o = one[i] local pp = P(o[1]) / o[2] @@ -372,11 +459,16 @@ function lpeg.replacer(one,two) return Cs((p + 1)^0) end else + one = P(one) two = two or "" - return Cs((P(one)/two + 1)^0) + return Cs(((1-one)^1 + one/two)^0) end end +-- print(lpeg.match(lpeg.replacer("e","a"),"test test")) +-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test")) +-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test")) + local splitters_f, splitters_s = { }, { } function lpeg.firstofsplit(separator) -- always return value @@ -404,14 +496,14 @@ function lpeg.balancer(left,right) return P { left * ((1 - left - right) + V(1))^0 * right } end ---~ print(1,match(lpeg.firstofsplit(":"),"bc:de")) ---~ print(2,match(lpeg.firstofsplit(":"),":de")) -- empty ---~ print(3,match(lpeg.firstofsplit(":"),"bc")) ---~ print(4,match(lpeg.secondofsplit(":"),"bc:de")) ---~ print(5,match(lpeg.secondofsplit(":"),"bc:")) -- empty ---~ print(6,match(lpeg.secondofsplit(":",""),"bc")) ---~ print(7,match(lpeg.secondofsplit(":"),"bc")) ---~ print(9,match(lpeg.secondofsplit(":","123"),"bc")) +--~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de")) +--~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty +--~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc")) +--~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de")) +--~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty +--~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc")) +--~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc")) +--~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc")) --~ -- slower: --~ @@ -425,7 +517,7 @@ local nany = utf8char/"" function lpeg.counter(pattern) pattern = Cs((P(pattern)/" " + nany)^0) return function(str) - return #match(pattern,str) + return #lpegmatch(pattern,str) end end @@ -439,7 +531,7 @@ if utfgmatch then end return n else -- 4 times slower but still faster than / function - return #match(Cs((P(what)/" " + nany)^0),str) + return #lpegmatch(Cs((P(what)/" " + nany)^0),str) end end @@ -454,9 +546,9 @@ else p = Cs((P(what)/" " + nany)^0) cache[p] = p end - return #match(p,str) + return #lpegmatch(p,str) else -- 4 times slower but still faster than / function - return #match(Cs((P(what)/" " + nany)^0),str) + return #lpegmatch(Cs((P(what)/" " + nany)^0),str) end end @@ -483,7 +575,7 @@ local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0) local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0) function string.escapedpattern(str,simple) - return match(simple and s or p,str) + return lpegmatch(simple and s or p,str) end -- utf extensies @@ -530,7 +622,7 @@ else p = P(uc) end end - match((utf8char/f)^0,str) + lpegmatch((utf8char/f)^0,str) return p end @@ -546,7 +638,7 @@ function lpeg.UR(str,more) first = str last = more or first else - first, last = match(range,str) + first, last = lpegmatch(range,str) if not last then return P(str) end @@ -582,11 +674,15 @@ end --~ print(lpeg.count("äáàa",lpeg.UR("àá"))) --~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF))) -function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") +function lpeg.is_lpeg(p) + return p and lpegtype(p) == "pattern" +end + +function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order if type(list) ~= "table" then list = { list, ... } end - -- sort(list) -- longest match first + -- table.sort(list) -- longest match first local p = P(list[1]) for l=2,#list do p = p + P(list[l]) @@ -594,10 +690,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") return p end -function lpeg.is_lpeg(p) - return p and lpegtype(p) == "pattern" -end - -- For the moment here, but it might move to utilities. Beware, we need to -- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we -- loop back from the end cq. prepend. @@ -754,3 +846,21 @@ end -- utfchar(0x202F), -- narrownobreakspace -- utfchar(0x205F), -- math thinspace -- } ) + +-- handy from within tex: + +local lpegmatch = lpeg.match + +local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg! + +function string.tformat(fmt,...) + return format(lpegmatch(replacer,fmt),...) +end + +-- strips leading and trailing spaces and collapsed all other spaces + +local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0) + +function string.collapsespaces(str) + return lpegmatch(pattern,str) +end diff --git a/tex/context/base/l-md5.lua b/tex/context/base/l-md5.lua index 1d471c966..6abf2e17d 100644 --- a/tex/context/base/l-md5.lua +++ b/tex/context/base/l-md5.lua @@ -31,15 +31,30 @@ if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end --~ function md5.dec(str) return (gsub(md5.sum(str),".",remap)) end --~ end -function file.needs_updating(oldname,newname,threshold) -- size modification access change - local oldtime = lfs.attributes(oldname, modification) - local newtime = lfs.attributes(newname, modification) - if newtime >= oldtime then - return false - elseif oldtime - newtime < (threshold or 1) then - return false +function file.needsupdating(oldname,newname,threshold) -- size modification access change + local oldtime = lfs.attributes(oldname,"modification") + if oldtime then + local newtime = lfs.attributes(newname,"modification") + if not newtime then + return true -- no new file, so no updating needed + elseif newtime >= oldtime then + return false -- new file definitely needs updating + elseif oldtime - newtime < (threshold or 1) then + return false -- new file is probably still okay + else + return true -- new file has to be updated + end else - return true + return false -- no old file, so no updating needed + end +end + +file.needs_updating = file.needsupdating + +function file.syncmtimes(oldname,newname) + local oldtime = lfs.attributes(oldname,"modification") + if oldtime and lfs.isfile(newname) then + lfs.touch(newname,oldtime,oldtime) end end @@ -61,7 +76,7 @@ function file.loadchecksum(name) return nil end -function file.savechecksum(name, checksum) +function file.savechecksum(name,checksum) if not checksum then checksum = file.checksum(name) end if checksum then io.savedata(name .. ".md5",checksum) diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua index b1ffb9ca9..a4dbe3bdf 100644 --- a/tex/context/base/l-number.lua +++ b/tex/context/base/l-number.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-number'] = { -- this module will be replaced when we have the bit library -local tostring = tostring +local tostring, tonumber = tostring, tonumber local format, floor, match, rep = string.format, math.floor, string.match, string.rep local concat, insert = table.concat, table.insert local lpegmatch = lpeg.match @@ -72,11 +72,11 @@ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ... end function number.setbit(x, p) - return hasbit(x, p) and x or x + p + return (x % (p + p) >= p) and x or x + p end function number.clearbit(x, p) - return hasbit(x, p) and x - p or x + return (x % (p + p) >= p) and x - p or x end --~ function number.tobitstring(n) @@ -128,3 +128,7 @@ end --~ print(number.tobitstring(0xFF)) --~ print(number.tobitstring(46260767936,8)) --~ print(#number.tobitstring(46260767936,6)) + +function number.valid(str,default) + return tonumber(str) or default or nil +end diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua index f9bd46e51..799f44957 100644 --- a/tex/context/base/l-os.lua +++ b/tex/context/base/l-os.lua @@ -22,17 +22,28 @@ if not modules then modules = { } end modules ['l-os'] = { -- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new) -- os.platform : extended os.name with architecture +-- os.sleep() => socket.sleep() +-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6))) + -- maybe build io.flush in os.execute local os = os +local date, time = os.date, os.time local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch local concat = table.concat -local random, ceil = math.random, math.ceil -local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber +local random, ceil, randomseed = math.random, math.ceil, math.randomseed +local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring -- The following code permits traversing the environment table, at least -- in luatex. Internally all environment names are uppercase. +-- The randomseed in Lua is not that random, although this depends on the operating system as well +-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway. + +math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) + +randomseed(math.initialseed) + if not os.__getenv__ then os.__getenv__ = os.getenv @@ -136,12 +147,14 @@ else os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' } end +local launchers = { + windows = "start %s", + macosx = "open %s", + unix = "$BROWSER %s &> /dev/null &", +} + function os.launch(str) - if os.type == "windows" then - os.execute("start " .. str) -- os.spawn ? - else - os.execute(str .. " &") -- os.spawn ? - end + os.execute(format(launchers[os.name] or launchers.unix,str)) end if not os.times then @@ -357,7 +370,7 @@ end local d function os.timezone(delta) - d = d or tonumber(tonumber(os.date("%H")-os.date("!%H"))) + d = d or tonumber(tonumber(date("%H")-date("!%H"))) if delta then if d > 0 then return format("+%02i:00",d) @@ -369,6 +382,44 @@ function os.timezone(delta) end end +local timeformat = format("%%s%s",os.timezone(true)) +local dateformat = "!%Y-%m-%d %H:%M:%S" + +function os.fulltime(t,default) + t = tonumber(t) or 0 + if t > 0 then + -- valid time + elseif default then + return default + else + t = nil + end + return format(timeformat,date(dateformat,t)) +end + +local dateformat = "%Y-%m-%d %H:%M:%S" + +function os.localtime(t,default) + t = tonumber(t) or 0 + if t > 0 then + -- valid time + elseif default then + return default + else + t = nil + end + return date(dateformat,t) +end + +function os.converttime(t,default) + local t = tonumber(t) + if t and t > 0 then + return date(dateformat,t) + else + return default or "-" + end +end + local memory = { } local function which(filename) diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua index 989e57f75..03616aa19 100644 --- a/tex/context/base/l-string.lua +++ b/tex/context/base/l-string.lua @@ -112,7 +112,24 @@ function string.topattern(str,lowercase,strict) end end + +function string.valid(str,default) + return (type(str) == "string" and str ~= "" and str) or default or nil +end + -- obsolete names: string.quote = string.quoted string.unquote = string.unquoted + +-- handy fallback + +string.itself = function(s) return s end + +-- also handy (see utf variant) + +local pattern = Ct(C(1)^0) + +function string.totable(str) + return lpegmatch(pattern,str) +end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 337ce054a..80f28c2cd 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -6,7 +6,8 @@ if not modules then modules = { } end modules ['l-table'] = { license = "see context related readme files" } -local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string +local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs +local table, string = table, string local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match local getmetatable, setmetatable = getmetatable, setmetatable @@ -17,6 +18,8 @@ local getinfo = debug.getinfo -- impact on ConTeXt was not that large; the remaining ipairs already -- have been replaced. In a similar fashion we also hardly used pairs. -- +-- Hm, actually ipairs was retained, but we no longer use it anyway. +-- -- Just in case, we provide the fallbacks as discussed in Programming -- in Lua (http://www.lua.org/pil/7.3.html): @@ -76,12 +79,16 @@ function table.strip(tab) end function table.keys(t) - local keys, k = { }, 0 - for key, _ in next, t do - k = k + 1 - keys[k] = key + if t then + local keys, k = { }, 0 + for key, _ in next, t do + k = k + 1 + keys[k] = key + end + return keys + else + return { } end - return keys end local function compare(a,b) @@ -94,41 +101,49 @@ local function compare(a,b) end local function sortedkeys(tab) - local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed - for key,_ in next, tab do - s = s + 1 - srt[s] = key - if category == 3 then - -- no further check - else - local tkey = type(key) - if tkey == "string" then - category = (category == 2 and 3) or 1 - elseif tkey == "number" then - category = (category == 1 and 3) or 2 + if tab then + local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed + for key,_ in next, tab do + s = s + 1 + srt[s] = key + if category == 3 then + -- no further check else - category = 3 + local tkey = type(key) + if tkey == "string" then + category = (category == 2 and 3) or 1 + elseif tkey == "number" then + category = (category == 1 and 3) or 2 + else + category = 3 + end end end - end - if category == 0 or category == 3 then - sort(srt,compare) + if category == 0 or category == 3 then + sort(srt,compare) + else + sort(srt) + end + return srt else - sort(srt) + return { } end - return srt end local function sortedhashkeys(tab) -- fast one - local srt, s = { }, 0 - for key,_ in next, tab do - if key then - s= s + 1 - srt[s] = key + if tab then + local srt, s = { }, 0 + for key,_ in next, tab do + if key then + s= s + 1 + srt[s] = key + end end + sort(srt) + return srt + else + return { } end - sort(srt) - return srt end table.sortedkeys = sortedkeys @@ -153,7 +168,7 @@ end table.sortedhash = sortedhash table.sortedpairs = sortedhash -function table.append(t, list) +function table.append(t,list) local n = #t for i=1,#list do n = n + 1 @@ -388,12 +403,26 @@ local function do_serialize(root,name,depth,level,indexed) end -- we could check for k (index) being number (cardinal) if root and next(root) then - local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) + -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) + -- if compact then + -- -- NOT: for k=1,#root do (we need to quit at nil) + -- for k,v in ipairs(root) do -- can we use next? + -- if not first then first = k end + -- last = last + 1 + -- end + -- end + local first, last = nil, 0 if compact then - -- NOT: for k=1,#root do (we need to quit at nil) - for k,v in ipairs(root) do -- can we use next? - if not first then first = k end - last = last + 1 + last = #root + for k=1,last do +-- if not root[k] then + if root[k] == nil then + last = k - 1 + break + end + end + if last > 0 then + first = 1 end end local sk = sortedkeys(root) @@ -885,23 +914,27 @@ function table.reversed(t) end end -function table.sequenced(t,sep,simple) -- hash only - local s, n = { }, 0 - for k, v in sortedhash(t) do - if simple then - if v == true then - n = n + 1 - s[n] = k - elseif v and v~= "" then +function table.sequenced(t,sep) -- hash only + if t then + local s, n = { }, 0 + for k, v in sortedhash(t) do + if simple then + if v == true then + n = n + 1 + s[n] = k + elseif v and v~= "" then + n = n + 1 + s[n] = k .. "=" .. tostring(v) + end + else n = n + 1 s[n] = k .. "=" .. tostring(v) end - else - n = n + 1 - s[n] = k .. "=" .. tostring(v) end + return concat(s, sep or " | ") + else + return "" end - return concat(s, sep or " | ") end function table.print(t,...) diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua index f4480e93c..630c34960 100644 --- a/tex/context/base/l-unicode.lua +++ b/tex/context/base/l-unicode.lua @@ -6,57 +6,253 @@ if not modules then modules = { } end modules ['l-unicode'] = { license = "see context related readme files" } +-- this module will be reorganized + +-- todo: utf.sub replacement (used in syst-aux) + +local concat = table.concat +local type = type +local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct +local lpegmatch, patterns = lpeg.match, lpeg.patterns +local utftype = patterns.utftype +local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format +local utfsplitlines = string.utfsplitlines + if not unicode then - unicode = { utf8 = { } } + unicode = { } + +end + +local unicode = unicode + +utf = utf or unicode.utf8 + +if not utf then + + utf8 = { } + unicode.utf8 = utf8 + utf = utf8 + +end + +if not utf.char then local floor, char = math.floor, string.char - function unicode.utf8.utfchar(n) + function utf.char(n) if n < 0x80 then + -- 0aaaaaaa : 0x80 return char(n) elseif n < 0x800 then + -- 110bbbaa : 0xC0 : n >> 6 + -- 10aaaaaa : 0x80 : n & 0x3F return char( 0xC0 + floor(n/0x40), 0x80 + (n % 0x40) ) elseif n < 0x10000 then + -- 1110bbbb : 0xE0 : n >> 12 + -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F + -- 10aaaaaa : 0x80 : n & 0x3F return char( 0xE0 + floor(n/0x1000), 0x80 + (floor(n/0x40) % 0x40), 0x80 + (n % 0x40) ) - elseif n < 0x40000 then + elseif n < 0x200000 then + -- 11110ccc : 0xF0 : n >> 18 + -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F + -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F + -- 10aaaaaa : 0x80 : n & 0x3F + -- dddd : ccccc - 1 return char( - 0xF0 + floor(n/0x40000), - 0x80 + floor(n/0x1000), + 0xF0 + floor(n/0x40000), + 0x80 + (floor(n/0x1000) % 0x40), 0x80 + (floor(n/0x40) % 0x40), 0x80 + (n % 0x40) ) else - -- return char( - -- 0xF1 + floor(n/0x1000000), - -- 0x80 + floor(n/0x40000), - -- 0x80 + floor(n/0x1000), - -- 0x80 + (floor(n/0x40) % 0x40), - -- 0x80 + (n % 0x40) - -- ) - return "?" + return "" end end end -local unicode = unicode +if not utf.byte then -utf = utf or unicode.utf8 + local utf8byte = patterns.utf8byte -local concat = table.concat -local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub -local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format -local type = type + function utf.byte(c) + return lpegmatch(utf8byte,c) + end -local utfsplitlines = string.utfsplitlines +end + +local utfchar, utfbyte = utf.char, utf.byte + +-- As we want to get rid of the (unmaintained) utf library we implement our own +-- variants (in due time an independent module): + +function unicode.filetype(data) + return data and lpegmatch(utftype,data) or "unknown" +end + +local toentities = Cs ( + ( + patterns.utf8one + + ( + patterns.utf8two + + patterns.utf8three + + patterns.utf8four + ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end + )^0 +) + +patterns.toentities = toentities + +function utf.toentities(str) + return lpegmatch(toentities,str) +end + +--~ local utfchr = { } -- 60K -> 2.638 M extra mem but currently not called that often (on latin) +--~ +--~ setmetatable(utfchr, { __index = function(t,k) local v = utfchar(k) t[k] = v return v end } ) +--~ +--~ collectgarbage("collect") +--~ local u = collectgarbage("count")*1024 +--~ local t = os.clock() +--~ for i=1,1000 do +--~ for i=1,600 do +--~ local a = utfchr[i] +--~ end +--~ end +--~ print(os.clock()-t,collectgarbage("count")*1024-u) + +--~ collectgarbage("collect") +--~ local t = os.clock() +--~ for i=1,1000 do +--~ for i=1,600 do +--~ local a = utfchar(i) +--~ end +--~ end +--~ print(os.clock()-t,collectgarbage("count")*1024-u) + +--~ local byte = string.byte +--~ local utfchar = utf.char +--~ local lpegmatch = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.Cs + +local one = P(1) +local two = C(1) * C(1) +local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1) + +-- actually one of them is already utf ... sort of useless this one + +-- function utf.char(n) +-- if n < 0x80 then +-- return char(n) +-- elseif n < 0x800 then +-- return char( +-- 0xC0 + floor(n/0x40), +-- 0x80 + (n % 0x40) +-- ) +-- elseif n < 0x10000 then +-- return char( +-- 0xE0 + floor(n/0x1000), +-- 0x80 + (floor(n/0x40) % 0x40), +-- 0x80 + (n % 0x40) +-- ) +-- elseif n < 0x40000 then +-- return char( +-- 0xF0 + floor(n/0x40000), +-- 0x80 + floor(n/0x1000), +-- 0x80 + (floor(n/0x40) % 0x40), +-- 0x80 + (n % 0x40) +-- ) +-- else +-- -- return char( +-- -- 0xF1 + floor(n/0x1000000), +-- -- 0x80 + floor(n/0x40000), +-- -- 0x80 + floor(n/0x1000), +-- -- 0x80 + (floor(n/0x40) % 0x40), +-- -- 0x80 + (n % 0x40) +-- -- ) +-- return "?" +-- end +-- end +-- +-- merge into: + +local pattern = P("\254\255") * Cs( ( + four / function(a,b,c,d) + local ab = 0xFF * byte(a) + byte(b) + local cd = 0xFF * byte(c) + byte(d) + return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) + end + + two / function(a,b) + return utfchar(byte(a)*256 + byte(b)) + end + + one + )^1 ) + + P("\255\254") * Cs( ( + four / function(b,a,d,c) + local ab = 0xFF * byte(a) + byte(b) + local cd = 0xFF * byte(c) + byte(d) + return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) + end + + two / function(b,a) + return utfchar(byte(a)*256 + byte(b)) + end + + one + )^1 ) + +function string.toutf(s) + return lpegmatch(pattern,s) or s -- todo: utf32 +end + +local validatedutf = Cs ( + ( + patterns.utf8one + + patterns.utf8two + + patterns.utf8three + + patterns.utf8four + + P(1) / "�" + )^0 +) + +patterns.validatedutf = validatedutf + +function string.validutf(str) + return lpegmatch(validatedutf,str) +end + + +utf.length = string.utflength +utf.split = string.utfsplit +utf.splitines = string.utfsplitlines +utf.valid = string.validutf + +if not utf.len then + utf.len = utf.length +end + +-- a replacement for simple gsubs: + +local utf8char = patterns.utf8char + +function utf.remapper(mapping) + local pattern = Cs((utf8char/mapping)^0) + return function(str) + if not str or str == "" then + return "" + else + return lpegmatch(pattern,str) + end + end, pattern +end + +-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" } +-- print(remap("abcd 1234 abcd")) -- 0 EF BB BF UTF-8 -- 1 FF FE UTF-16-little-endian @@ -352,11 +548,22 @@ local function big(c) end end +-- function unicode.utf8_to_utf16(str,littleendian) +-- if littleendian then +-- return char(255,254) .. utfgsub(str,".",little) +-- else +-- return char(254,255) .. utfgsub(str,".",big) +-- end +-- end + +local _, l_remap = utf.remapper(little) +local _, b_remap = utf.remapper(big) + function unicode.utf8_to_utf16(str,littleendian) if littleendian then - return char(255,254) .. utfgsub(str,".",little) + return char(255,254) .. lpegmatch(l_remap,str) else - return char(254,255) .. utfgsub(str,".",big) + return char(254,255) .. lpegmatch(b_remap,str) end end @@ -377,107 +584,10 @@ function unicode.xstring(s) return format("0x%05X",type(s) == "number" and s or utfbyte(s)) end ---~ print(unicode.utfcodes(str)) +-- -local lpegmatch = lpeg.match -local patterns = lpeg.patterns -local utftype = patterns.utftype +local pattern = Ct(C(patterns.utf8char)^0) -function unicode.filetype(data) - return data and lpegmatch(utftype,data) or "unknown" -end - -local toentities = lpeg.Cs ( - ( - patterns.utf8one - + ( - patterns.utf8two - + patterns.utf8three - + patterns.utf8four - ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end - )^0 -) - -patterns.toentities = toentities - -function utf.toentities(str) - return lpegmatch(toentities,str) -end - ---~ local utfchr = { } -- 60K -> 2.638 M extra mem but currently not called that often (on latin) ---~ ---~ setmetatable(utfchr, { __index = function(t,k) local v = utfchar(k) t[k] = v return v end } ) ---~ ---~ collectgarbage("collect") ---~ local u = collectgarbage("count")*1024 ---~ local t = os.clock() ---~ for i=1,1000 do ---~ for i=1,600 do ---~ local a = utfchr[i] ---~ end ---~ end ---~ print(os.clock()-t,collectgarbage("count")*1024-u) - ---~ collectgarbage("collect") ---~ local t = os.clock() ---~ for i=1,1000 do ---~ for i=1,600 do ---~ local a = utfchar(i) ---~ end ---~ end ---~ print(os.clock()-t,collectgarbage("count")*1024-u) - ---~ local byte = string.byte ---~ local utfchar = utf.char ---~ local lpegmatch = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.Cs - -local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs - -local one = P(1) -local two = C(1) * C(1) -local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1) - --- actually one of them is already utf ... sort of useless this one - -local pattern = P("\254\255") * Cs( ( - four / function(a,b,c,d) - local ab = 0xFF * byte(a) + byte(b) - local cd = 0xFF * byte(c) + byte(d) - return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) - end - + two / function(a,b) - return utfchar(byte(a)*256 + byte(b)) - end - + one - )^1 ) - + P("\255\254") * Cs( ( - four / function(b,a,d,c) - local ab = 0xFF * byte(a) + byte(b) - local cd = 0xFF * byte(c) + byte(d) - return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000) - end - + two / function(b,a) - return utfchar(byte(a)*256 + byte(b)) - end - + one - )^1 ) - -function string.toutf(s) - return lpegmatch(pattern,s) or s -- todo: utf32 -end - -local validatedutf = Cs ( - ( - patterns.utf8one - + patterns.utf8two - + patterns.utf8three - + patterns.utf8four - + P(1) / "�" - )^0 -) - -patterns.validatedutf = validatedutf - -function string.validutf(str) - return lpegmatch(validatedutf,str) +function utf.totable(str) + return lpegmatch(pattern,str) end diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua index 69f32cc39..ab5002881 100644 --- a/tex/context/base/l-url.lua +++ b/tex/context/base/l-url.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['l-url'] = { local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find local concat = table.concat local tonumber, type = tonumber, type -local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct +local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer -- from wikipedia: @@ -42,15 +42,19 @@ local endofstring = P(-1) local hexdigit = R("09","AF","af") local plus = P("+") local nothing = Cc("") -local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar) +local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar +local escaped = (plus / " ") + escapedchar -- we assume schemes with more than 1 character (in order to avoid problems with windows disks) -- we also assume that when we have a scheme, we also have an authority +-- +-- maybe we should already split the query (better for unescaping as = & can be part of a value local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2) local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0) local pathstr = Cs((escaped+(1- qmark-hash))^0) -local querystr = Cs((escaped+(1- hash))^0) +----- querystr = Cs((escaped+(1- hash))^0) +local querystr = Cs(( (1- hash))^0) local fragmentstr = Cs((escaped+(1- endofstring))^0) local scheme = schemestr * colon + nothing @@ -65,11 +69,20 @@ local parser = Ct(validurl) lpegpatterns.url = validurl lpegpatterns.urlsplitter = parser -local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end +local escapes = { } + +setmetatable(escapes, { __index = function(t,k) + local v = format("%%%02X",byte(k)) + t[k] = v + return v +end }) -local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0) +local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most +local unescaper = Cs((escapedchar + 1)^0) -lpegpatterns.urlescaper = escaper +lpegpatterns.urlunescaped = escapedchar +lpegpatterns.urlescaper = escaper +lpegpatterns.urlunescaper = unescaper -- todo: reconsider Ct as we can as well have five return values (saves a table) -- so we can have two parsers, one with and one without @@ -81,8 +94,12 @@ end local isscheme = schemestr * colon * slash * slash -- this test also assumes authority local function hasscheme(str) - local scheme = lpegmatch(isscheme,str) -- at least one character - return scheme ~= "" and scheme or false + if str then + local scheme = lpegmatch(isscheme,str) -- at least one character + return scheme ~= "" and scheme or false + else + return false + end end --~ print(hasscheme("home:")) @@ -103,10 +120,32 @@ local rootbased = P("/") local barswapper = replacer("|",":") local backslashswapper = replacer("\\","/") +-- queries: + +local equal = P("=") +local amp = P("&") +local key = Cs(((escapedchar+1)-equal )^0) +local value = Cs(((escapedchar+1)-amp -endofstring)^0) + +local splitquery = Cf ( Ct("") * P { "sequence", + sequence = V("pair") * (amp * V("pair"))^0, + pair = Cg(key * equal * value), +}, rawset) + +-- hasher + local function hashed(str) -- not yet ok (/test?test) + if str == "" then + return { + scheme = "invalid", + original = str, + } + end local s = split(str) - local somescheme = s[1] ~= "" - local somequery = s[4] ~= "" + local rawscheme = s[1] + local rawquery = s[4] + local somescheme = rawscheme ~= "" + local somequery = rawquery ~= "" if not somescheme and not somequery then s = { scheme = "file", @@ -122,14 +161,17 @@ local function hashed(str) -- not yet ok (/test?test) local authority, path, filename = s[2], s[3] if authority == "" then filename = path + elseif path == "" then + filename = "" else filename = authority .. "/" .. path end s = { - scheme = s[1], + scheme = rawscheme, authority = authority, path = path, - query = s[4], + query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and = + queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped fragment = s[5], original = str, noscheme = false, @@ -139,6 +181,8 @@ local function hashed(str) -- not yet ok (/test?test) return s end +-- inspect(hashed("template://test")) + -- Here we assume: -- -- files: /// = relative @@ -189,23 +233,64 @@ function url.construct(hash) -- dodo: we need to escape ! return lpegmatch(escaper,concat(fullurl)) end -function url.filename(filename) +function url.filename(filename) -- why no lpeg here ? local t = hashed(filename) return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename end +local function escapestring(str) + return lpegmatch(escaper,str) +end + +url.escape = escapestring + +-- function url.query(str) -- separator could be an option +-- if type(str) == "string" then +-- local t = { } +-- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do +-- t[k] = v +-- end +-- return t +-- else +-- return str +-- end +-- end + function url.query(str) if type(str) == "string" then - local t = { } - for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do - t[k] = v - end - return t + return lpegmatch(splitquery,str) or "" else return str end end +function url.toquery(data) + local td = type(data) + if td == "string" then + return #str and escape(data) or nil -- beware of double escaping + elseif td == "table" then + if next(data) then + local t = { } + for k, v in next, data do + t[#t+1] = format("%s=%s",k,escapestring(v)) + end + return concat(t,"&") + end + else + -- nil is a signal that no query + end +end + +-- /test/ | /test | test/ | test => test + +function url.barepath(path) + if not path or path == "" then + return "" + else + return (gsub(path,"^/?(.-)/?$","%1")) + end +end + --~ print(url.filename("file:///c:/oeps.txt")) --~ print(url.filename("c:/oeps.txt")) --~ print(url.filename("file:///oeps.txt")) @@ -220,6 +305,9 @@ end --~ print(table.serialize(t)) --~ end +--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45")) +--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45")) + --~ test("sys:///./colo-rgb") --~ test("/data/site/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733/figuur-cow.jpg") diff --git a/tex/context/base/lang-def.lua b/tex/context/base/lang-def.lua index 80ff13beb..c6bbcf3ae 100644 --- a/tex/context/base/lang-def.lua +++ b/tex/context/base/lang-def.lua @@ -1,15 +1,18 @@ -if not modules then modules = { } end modules ['lang-ini'] = { +if not modules then modules = { } end modules ['lang-def'] = { 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" + -- dataonly = true, -- saves 10K } +local rawget = rawget local lower = string.lower languages = languages or { } local languages = languages +languages.data = languages.data or { } local data = languages.data local allocate = utilities.storage.allocate @@ -376,50 +379,54 @@ local contexts = { } data.contexts = contexts local records = { } data.records = records for k=1,#specifications do - local v = specifications[k] - if v.variant then - variants[v.variant] = v + local specification = specifications[k] + local variant = specification.variant + if variant then + variants[lower(variant)] = specification end - if v.opentype then - opentypes[v.opentype] = v + local opentype = specification.opentype + if opentype then + opentypes[lower(opentype)] = specification end - local vc = v.context - if vc then - if type(vc) == "table" then - for k=1,#vc do - contexts[v] = vc[k] + local context = context + if context then + if type(context) == "table" then + for k=1,#context do + contexts[context[k]] = specification end else - contexts[vc] = v + contexts[context] = specification end end end +local defaultvariant = variants["en-us"] + setmetatableindex(variants, function(t,k) - str = lower(str) - local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).language + k = lower(k) + local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).language t[k] = v return v end) setmetatableindex(opentypes, function(t,k) - str = lower(str) - local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).opentype + k = lower(k) + local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).opentype t[k] = v return v end) setmetatableindex(contexts, function(t,k) - str = lower(str) - local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant[languages.default]).context + k = lower(str) + local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).context v = (type(v) == "table" and v[1]) or v t[k] = v return v end) setmetatableindex(records, function(t,k) -- how useful is this one? - str = lower(str) - local v = variants[str] or opentypes[str] or contexts[str] or variants.en + k = lower(k) + local v = rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant t[k] = v return v end) diff --git a/tex/context/base/lang-def.mkiv b/tex/context/base/lang-def.mkiv index e838f60e1..d4e40dad1 100644 --- a/tex/context/base/lang-def.mkiv +++ b/tex/context/base/lang-def.mkiv @@ -211,28 +211,34 @@ \installlanguage [\s!cs] [\c!spacing=\v!packed, - \c!leftsentence={\thickglue\endash\thickglue\penalty-20\relax}, - \c!rightsentence={\thickglue\endash\thickglue\penalty-20\relax}, - \c!leftsubsentence={\nobreakspace\emdash\nobreakspace\penalty-20\relax}, - \c!rightsubsentence={\nobreakspace\emdash\nobreakspace\penalty-20\relax}, + \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax}, + \c!rightsentence=\c!leftsentence, + \c!leftsubsentence=\c!leftsentence, + \c!rightsubsentence=\c!rightsentence, \c!leftquote=\lowerleftsingleninequote, \c!rightquote=\upperrightsinglesixquote, \c!leftquotation=\lowerleftdoubleninequote, \c!rightquotation=\upperrightdoublesixquote, - \c!date={\v!day,{.\thinspace},\v!month,\space,\v!year}] + \c!date={\v!day,\fourperemspace,\v!month,\space,\v!year} + \s!lefthyphenmin=2, + \s!righthyphenmin=3 +] \installlanguage [\s!sk] [\c!spacing=\v!packed, - \c!leftsentence=\emdash, - \c!rightsentence=\emdash, - \c!leftsubsentence=\emdash, - \c!rightsubsentence=\emdash, - \c!leftquote=\upperleftsinglesixquote, - \c!rightquote=\upperrightsingleninequote, - \c!leftquotation=\upperleftdoublesixquote, - \c!rightquotation=\upperrightdoubleninequote, - \c!date={\v!day,{.\thinspace},\v!month,\space,\v!year}] + \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax}, + \c!rightsentence=\c!leftsentence, + \c!leftsubsentence=\c!leftsentence, + \c!rightsubsentence=\c!rightsentence, + \c!leftquote=\lowerleftsingleninequote, + \c!rightquote=\upperrightsinglesixquote, + \c!leftquotation=\lowerleftdoubleninequote, + \c!rightquotation=\upperrightdoublesixquote, + \c!date={\v!day,\fourperemspace,\v!month,\space,\v!year} + \s!lefthyphenmin=2, + \s!righthyphenmin=3 +] \installlanguage [\s!hr] diff --git a/tex/context/base/lang-frd.mkiv b/tex/context/base/lang-frd.mkiv new file mode 100644 index 000000000..716ff257d --- /dev/null +++ b/tex/context/base/lang-frd.mkiv @@ -0,0 +1,141 @@ +%D \module +%D [ file=lang-frd, +%D version=2004.01.15, +%D title=\CONTEXT\ Language Macros, +%D subtitle=Language Frequency Table Data, +%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 experimental work! Old stuff, whenever I need it I might +%D do it in \LUA. + +% http://www.onzetaal.nl/advies/letterfreq.html + +\startcharactertable[nl] + \charfreq a 7.47 + \charfreq b 1.58 + \charfreq c 1.24 + \charfreq d 5.93 + \charfreq e 18.91 + \charfreq f .81 + \charfreq g 3.4 + \charfreq h 2.38 + \charfreq i 6.5 + \charfreq j 1.46 + \charfreq k 2.25 + \charfreq l 3.57 + \charfreq m 2.21 + \charfreq n 10.03 + \charfreq o 6.06 + \charfreq p 1.57 + \charfreq q .009 + \charfreq r 6.41 + \charfreq s 3.73 + \charfreq t 6.79 + \charfreq u 1.99 + \charfreq v 2.85 + \charfreq w 1.52 + \charfreq x .04 + \charfreq y .035 + \charfreq z 1.39 +\stopcharactertable + +% http://caislab.icu.ac.kr/course/2001/spring/ice605/down/010306.pdf + +% \startcharactertable[en] +% \charfreq a 8.2 +% \charfreq b 1.5 +% \charfreq c 2.8 +% \charfreq d 4.3 +% \charfreq e 12.7 +% \charfreq f 2.2 +% \charfreq g 2 +% \charfreq h 6.1 +% \charfreq i 7 +% \charfreq j .2 +% \charfreq k .8 +% \charfreq l 4 +% \charfreq m 2.4 +% \charfreq n 6.7 +% \charfreq o 7.5 +% \charfreq p 1.9 +% \charfreq q .1 +% \charfreq r 6 +% \charfreq s 6.3 +% \charfreq t 9.1 +% \charfreq u 2.8 +% \charfreq v 1 +% \charfreq w 2.3 +% \charfreq x .1 +% \charfreq y 2 +% \charfreq z .1 +% \stopcharactertable + +% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm + +\startcharactertable[en] + \charfreq a 8.04 + \charfreq b 1.54 + \charfreq c 3.06 + \charfreq d 3.99 + \charfreq e 12.51 + \charfreq f 2.3 + \charfreq g 1.96 + \charfreq h 5.49 + \charfreq i 7.26 + \charfreq j .16 + \charfreq k .67 + \charfreq l 4.14 + \charfreq m 2.53 + \charfreq n 7.09 + \charfreq o 7.6 + \charfreq p 2 + \charfreq q .11 + \charfreq r 6.12 + \charfreq s 6.54 + \charfreq t 9.25 + \charfreq u 2.71 + \charfreq v .99 + \charfreq w 1.92 + \charfreq x .19 + \charfreq y 1.73 + \charfreq z .09 +\stopcharactertable + +% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm + +\startcharactertable[de] + \charfreq a 6.47 + \charfreq b 1.93 + \charfreq c 2.68 + \charfreq d 4.83 + \charfreq e 17.48 + \charfreq f 1.65 + \charfreq g 3.06 + \charfreq h 4.23 + \charfreq i 7.73 + \charfreq j .27 + \charfreq k 1.46 + \charfreq l 3.49 + \charfreq m 2.58 + \charfreq n 9.84 + \charfreq o 2.98 + \charfreq p .96 + \charfreq q .02 + \charfreq r 7.54 + \charfreq s 6.83 + \charfreq t 6.13 + \charfreq u 4.17 + \charfreq v .94 + \charfreq w 1.48 + \charfreq x .04 + \charfreq y .08 + \charfreq z 1.14 +\stopcharactertable + +\endinput diff --git a/tex/context/base/lang-frq.mkiv b/tex/context/base/lang-frq.mkiv new file mode 100644 index 000000000..24f535296 --- /dev/null +++ b/tex/context/base/lang-frq.mkiv @@ -0,0 +1,233 @@ +%D \module +%D [ file=lang-frq, +%D version=2004.01.15, +%D title=\CONTEXT\ Language Macros, +%D subtitle=Frequency 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 Language Macros / Frequency Tables} + +%D Some day I might redo this \LUA. But anyway, who uses it. It's rather +%D old code. + +\unprotect + +%M \usemodule[layout] + +%D \macros +%D {charwidthmethod} +%D +%D This module implements a method for determining the width of an +%D average character in a language. It uses the dimensions of the +%D current fonts. +%D +%D \def\ShwChrWd#1#2#3% +%D {\chardef\charwidthmethod#1\relax +%D \mainlanguage[#2#3]\the\dimexpr(\averagecharwidth)} +%D +%D \starttabulate[|c|c|c|c|c|c|] +%D \HL +%D \NC \NC\bf0=amount\NC\bf1=.5em\NC2=ex\NC\bf3=frequency\NC\bf4=list\NC\NR +%D \HL +%D \NC\bf en\NC\ShwChrWd0en\NC\ShwChrWd1en\NC\ShwChrWd2en\NC\ShwChrWd3en\NC\ShwChrWd4en\NC\NR +%D \NC\bf nl\NC\ShwChrWd0nl\NC\ShwChrWd1nl\NC\ShwChrWd2nl\NC\ShwChrWd3nl\NC\ShwChrWd4nl\NC\NR +%D \NC\bf de\NC\ShwChrWd0de\NC\ShwChrWd1de\NC\ShwChrWd2de\NC\ShwChrWd3de\NC\ShwChrWd4de\NC\NR +%D \HL +%D \stoptabulate +%D +%D Method~1 ignores the widths and assumes that each character has a +%D width of .5em, which is true for most monospaced fonts. Method~2 +%D takes the x as starting point, and assumes that it's height kind of +%D matches its width. Method~3 is the best one, and determines the +%D average width based on the language specific character table. +%D Method~4 is a mixture between the first two methods: character +%D specific widths applied to an equal distribution. Method~0 reports +%D the total count, which normally is~100. + +\chardef\charwidthmethod=3 % 0=amount 1=em 2=ex 3=frequency 4=flattened >4=ex + +%D \macros +%D {charwidthlanguage} +%D +%D The language used for the calculations is defined as: + +\def\charwidthlanguage{\currentmainlanguage} + +%D \macros +%D {charfreq} +%D +%D This method comes into action in the following macro: + +\def\charfreq#1 #2 % character fraction + {+(\ifcase\charwidthmethod + #2\dimexpr100\onepoint\relax + \or + #2\dimexpr\emwidth/2\relax + \or + #2\dimexpr\exheight\relax + \or + #2\fontcharwd\font`#1% + \or + \dimexpr100\fontcharwd\font`#1/\charactertsize\charwidthlanguage\relax % ugly hack + \else + #2\dimexpr\exheight\relax + \fi)} + +%D \macros +%D {startcharactertable} +%D +%D A frequency table is defined with the following macro. The \type +%D {charfreq} macro is used in this table. + +\installcorenamespace{frequencywidths} +\installcorenamespace{frequencycounts} + +\let\stopcharactertable\relax + +\unexpanded\def\startcharactertable[#1]#2\stopcharactertable % \dimexpr has fuzzy lookahead + {\startnointerference + \setgvalue{\??frequencywidths#1}{#2}% the width vector + \scratchcounter\zerocount \def\charfreq##1 ##2 {\advance\scratchcounter\plusone} #2% + \setxvalue{\??frequencycounts#1}{\the\scratchcounter}% the character count + \stopnointerference} + +%D \macros +%D {charactertable,charactertsize} +%D +%D The table content as well as the number of entries can be fetched with +%D the following two macros. The architecture of the table and calling +%D macro permits a fully expandable application. + +\def\charactertable#1% + {\csname\??frequencywidths\ifcsname\??frequencywidths#1\endcsname#1\else\s!en\fi\endcsname} + +\def\charactertsize#1% + {\csname\??frequencycounts\ifcsname\??frequencycounts#1\endcsname#1\else\s!en\fi\endcsname} + +%D Although it is of hardly any use, you can inherit a character table: +%D +%D \starttyping +%D \startcharactertable[cz] \charactertable{en} \stopcharactertable +%D \stoptyping + +\startcharactertable[en] + % empty +\stopcharactertable % kind of default + +%D \macros +%D {averagecharwidth} +%D +%D This macro reports the average width for the current main +%D language (\the \dimexpr (\averagecharwidth)). + +\def\averagecharwidth{\dimexpr(\zeropoint\charactertable\charwidthlanguage)/100\relax} + +\unexpanded\def\showcharfreq + {\hbox\bgroup + \charwidthlanguage:% + \dostepwiserecurse\zerocount\plusfour\plusone + {\chardef\charwidthmethod\recurselevel\relax + \enspace\recurselevel/\the\dimexpr(\averagecharwidth)}% + \egroup} + +%D Just for fun, we show a few frequency tables as graphic (\in {figure} +%D [fig:charfreq]). +%D +%D \startbuffer +%D \definepalet [charfreq] [en=darkred, nl=darkgreen, de=darkblue] +%D +%D \def\charfreq#1 #2 % +%D {\startMPdrawing +%D interim linejoin := butt ; +%D a := ASCII "#1" ; +%D if (a >= (ASCII "a")) and (a <= (ASCII "z")) : +%D draw ((0,#2*.25cm)--origin--(0,#2*.5cm)) +%D shifted (a*4mm+o,0) +%D withpen pencircle scaled .5mm +%D withcolor c; +%D fi ; +%D \stopMPdrawing} +%D +%D \resetMPdrawing +%D \startMPdrawing +%D numeric a, o ; a := o := 0 ; +%D color c ; c := .5white ; +%D string s ; s := "" ; +%D \stopMPdrawing +%D +%D \startMPdrawing o := 0mm ; c := \MPcolor{charfreq:en} ; \stopMPdrawing +%D \charactertable{en} +%D +%D \startMPdrawing o := 1mm ; c := \MPcolor{charfreq:nl} ; \stopMPdrawing +%D \charactertable{nl} +%D +%D \startMPdrawing o := 2mm ; c := \MPcolor{charfreq:de} ; \stopMPdrawing +%D \charactertable{de} +%D +%D \startMPdrawing +%D for a := ASCII "a" upto ASCII "z" : +%D draw textext.bot("\strut\tttf " & char a) shifted (a*4mm+1mm,-1mm) ; +%D endfor ; +%D \stopMPdrawing +%D +%D \MPdrawingdonetrue \getMPdrawing \resetMPdrawing +%D \stopbuffer +%D +%D \placefigure +%D [here] +%D [fig:charfreq] +%D {The character distributions for English, Dutch and German.} +%D {\getbuffer} +%D +%D A few samples of usage of this mechanism are shown below: +%D +%D \startbuffer +%D {\mainlanguage[en]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank} +%D {\mainlanguage[nl]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank} +%D {\mainlanguage[de]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank} +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Although the widthts differ, the consequenes for breaking the paragraph +%D into lines are minimal. + +%D \macros +%D {freezeaveragecharacterwidth} +%D +%D This macro can be used to make sure that the width does not change during a +%D page break when another font is used. + +\let\normalaveragecharacterwidth\averagecharacterwidth + +\unexpanded\def\freezeaveragecharacterwidth % global + {\xdef\averagecharacterwidth{\dimexpr\the\normalaveragecharacterwidth\relax}} + +%D Example: +%D +%D \starttyping +%D \input lang-frq.mkiv +%D \input lang-frd.mkiv +%D +%D \setupbodyfont +%D [dejavu] +%D +%D \setemeasure{textwidth}{\the\dimexpr70\averagecharwidth} +%D +%D \setuplayout +%D [width=\measure{textwidth}] +%D +%D \showframe +%D +%D \starttext +%D \input ward +%D \stoptext +%D \stoptyping + +\protect \endinput diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua index 97528097f..eaedcd69a 100644 --- a/tex/context/base/lang-ini.lua +++ b/tex/context/base/lang-ini.lua @@ -29,12 +29,14 @@ local trace_patterns = false trackers.register("languages.patterns", function(v local report_initialization = logs.reporter("languages","initialization") -local prehyphenchar = lang.prehyphenchar -- global per language +local prehyphenchar = lang.prehyphenchar -- global per language local posthyphenchar = lang.posthyphenchar -- global per language local lefthyphenmin = lang.lefthyphenmin local righthyphenmin = lang.righthyphenmin +local lang = lang lang.exceptions = lang.hyphenation +local new_langage = lang.new languages = languages or {} local languages = languages @@ -65,7 +67,7 @@ local function resolve(tag) if data then instance = data.instance if not instance then - instance = lang.new(data.number) + instance = new_langage(data.number) data.instance = instance end end @@ -78,7 +80,7 @@ local function tolang(what) -- returns lang object if data then local instance = data.lang if not instance then - instance = lang.new(data.number) + instance = new_langage(data.number) data.instance = instance end return instance @@ -100,34 +102,34 @@ local function loaddefinitions(tag,specification) local dataused, ok = data.used, false for i=1,#definitions do local definition = definitions[i] - if definition ~= "" then - if definition == "reset" then -- interfaces.variables.reset + if definition == "" then + -- error + elseif definition == "reset" then -- interfaces.variables.reset + if trace_patterns then + report_initialization("clearing patterns for language '%s'",tag) + end + instance:clear_patterns() + elseif not dataused[definition] then + dataused[definition] = definition + local filename = "lang-" .. definition .. ".lua" + local fullname = resolvers.findfile(filename) or "" + if fullname ~= "" then if trace_patterns then - report_initialization("clearing patterns for language '%s'",tag) + report_initialization("loading definition '%s' for language '%s' from '%s'",definition,tag,fullname) end - instance:clear_patterns() - elseif not dataused[definition] then - dataused[definition] = definition - local filename = "lang-" .. definition .. ".lua" - local fullname = resolvers.findfile(filename) or "" - if fullname ~= "" then - if trace_patterns then - report_initialization("loading definition '%s' for language '%s' from '%s'",definition,tag,fullname) - end - local defs = dofile(fullname) -- use regular loader instead - if defs then -- todo: version test - ok, nofloaded = true, nofloaded + 1 - instance:patterns (defs.patterns and defs.patterns.data or "") - instance:hyphenation(defs.exceptions and defs.exceptions.data or "") - else - report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename) - end - elseif trace_patterns then + local defs = dofile(fullname) -- use regular loader instead + if defs then -- todo: version test + ok, nofloaded = true, nofloaded + 1 + instance:patterns (defs.patterns and defs.patterns .data or "") + instance:hyphenation(defs.exceptions and defs.exceptions.data or "") + else report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename) end elseif trace_patterns then - report_initialization("definition '%s' for language '%s' already loaded",definition,tag) + report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename) end + elseif trace_patterns then + report_initialization("definition '%s' for language '%s' already loaded",definition,tag) end end return ok @@ -161,7 +163,7 @@ function languages.define(tag,parent) storage.shared.noflanguages = noflanguages end -function languages.synonym(synonym,tag) -- convenience function +function languages.setsynonym(synonym,tag) -- convenience function local l = registered[tag] if l then l.synonyms[synonym] = true -- maybe some day more info @@ -169,7 +171,7 @@ function languages.synonym(synonym,tag) -- convenience function end function languages.installed(separator) - context(concat(sortedkeys(registered),separator or ",")) + return concat(sortedkeys(registered),separator or ",") end function languages.current(n) @@ -187,8 +189,6 @@ function languages.association(tag) -- not yet used local lat = tag and associated[tag] if lat then return lat[1], lat[2] - else - return nil, nil end end @@ -204,7 +204,7 @@ 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.setdirty(tag) +function languages.unload(tag) local l = registered[tag] if l then l.dirty = true @@ -217,13 +217,9 @@ if environment.initex then return 0 end - function commands.languagenumber() - context(0) - end - else - local function getnumber(tag,default,patterns) + function languages.getnumber(tag,default,patterns) local l = registered[tag] if l then if l.dirty then @@ -264,12 +260,6 @@ else end end - languages.getnumber = getnumber - - function commands.languagenumber(tag,default,patterns) - context(getnumber(tag,default,patterns)) - end - end -- not that usefull, global values @@ -294,7 +284,7 @@ function languages.loadwords(tag,filename) end end -function languages.exceptions(tag,str) +function languages.setexceptions(tag,str) local data, instance = resolve(tag) if data then instance:hyphenation(string.strip(str)) -- we need to strip leading spaces @@ -404,3 +394,20 @@ end) --~ function hyphenation.loadexceptions(tag, exceptions) --~ return loadthem(tag, exceptions, filterexceptions, "exceptions") --~ end + +-- interface + +local getnumber = languages.getnumber + +function commands.languagenumber(tag,default,patterns) + context(getnumber(tag,default,patterns)) +end + +function commands.installedlanguages(separator) + context(languages.installed(separator)) +end + +commands.definelanguage = languages.define +commands.setlanguagesynonym = languages.setsynonym +commands.unloadlanguage = languages.unload +commands.setlanguageexceptions = languages.setexceptions diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv index 150b68f70..0b155cc74 100644 --- a/tex/context/base/lang-ini.mkiv +++ b/tex/context/base/lang-ini.mkiv @@ -174,7 +174,7 @@ \newtoks \everysetuplanguage -\def\installedlanguages{\ctxlua{languages.installed()}} +\def\installedlanguages{\ctxcommand{installedlanguages()}} \unexpanded\def\doiflanguageelse#1% {\ifcsname\??language#1\c!state\endcsname @@ -199,10 +199,10 @@ \lang_basics_install_indeed{#1}{#1}% \getparameters[\??language#1][\c!state=\v!start,#2]}% \edef\currentsetuplanguage{#1}% - \ctxlua{languages.define("#1","\specificlanguageparameter{#1}\s!default")}% + \ctxcommand{definelanguage("#1","\specificlanguageparameter{#1}\s!default")}% \the\everysetuplanguage} {\setvalue{\??languagelinked#1}{#2}% - \ctxlua{languages.synonym("#1","#2")}% + \ctxcommand{setlanguagesynonym("#1","#2")}% \lang_basics_install_indeed{#1}{#2}}} \def\lang_basics_install_indeed#1#2% @@ -254,7 +254,7 @@ \lang_basics_synchronize} \appendtoks - \ctxlua{languages.setdirty("\currentsetuplanguage")}% + \ctxcommand{unloadlanguage("\currentsetuplanguage")}% \to \everysetuplanguage \setuplanguage @@ -399,20 +399,27 @@ % we will also permit access by the other names -\unexpanded\def\lang_basics_set_current[#1]% - {\edef\askedlanguage{#1}% - \ifx\askedlanguage\empty \else +%D Fast switcher + +\def\lang_basics_switch_asked + {\ifx\askedlanguage\empty \else \ifcsname\??languagelinked\askedlanguage\endcsname \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}% \ifx\currentlanguage\askedlanguage \else \setcurrentlanguage\currentmainlanguage\askedlanguage \lang_basics_synchronize \fi - \else - \showmessage\m!languages6{#1}% \fi \fi} +\unexpanded\def\uselanguageparameter#1% + {\edef\askedlanguage{#1\c!language}% + \lang_basics_switch_asked} + +\unexpanded\def\lang_basics_set_current[#1]% + {\edef\askedlanguage{#1}% + \lang_basics_switch_asked} + \unexpanded\def\language {\doifnextoptionalelse\lang_basics_set_current\normallanguage} @@ -570,15 +577,15 @@ \let\stopexceptions\relax \unexpanded\def\startexceptions - {\dosingleempty\dostartexceptions} + {\dosingleempty\lang_basics_start_exceptions} -\def\dostartexceptions[#1]#2\stopexceptions % multilingual or not? +\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not? {\begingroup \edef\askedlanguage{\reallanguagetag{#1}}% \ifx\askedlanguage\empty \let\askedlanguage\currentlanguage \fi - \ctxlua{languages.exceptions("\askedlanguage",\!!bs#2\!!es)}% + \ctxcommand{setlanguageexceptions("\askedlanguage",\!!bs#2\!!es)}% \endgroup} %D For the moment here: diff --git a/tex/context/base/lang-lab.lua b/tex/context/base/lang-lab.lua index 360f2aa11..8d48a4988 100644 --- a/tex/context/base/lang-lab.lua +++ b/tex/context/base/lang-lab.lua @@ -61,15 +61,20 @@ if not modules then modules = { } end modules ['lang-lab'] = { local format, find = string.format, string.find local next, rawget, type = next, rawget, type -local prtcatcodes = tex.prtcatcodes local lpegmatch = lpeg.match -languages.labels = languages.labels or { } +local prtcatcodes = catcodes.numbers.prtcatcodes -- todo: use different method local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end) local report_labels = logs.reporter("languages","labels") -local variables = interfaces.variables +-- trace_labels = true + +languages.labels = languages.labels or { } +local labels = languages.labels + +local variables = interfaces.variables +local settings_to_array = utilities.parsers.settings_to_array local splitter = lpeg.splitat(":") @@ -77,19 +82,21 @@ local function split(tag) return lpegmatch(splitter,tag) end -languages.labels.split = split +labels.split = split + +local contextsprint = context.sprint -local function definelanguagelabels(data,command,tag,rawtag) +local function definelanguagelabels(data,class,tag,rawtag) for language, text in next, data.labels do if text == "" then -- skip elseif type(text) == "table" then - context("\\%s[%s][%s={{%s},{%s}}]",command,language,tag,text[1],text[2]) + contextsprint(prtcatcodes,"\\setlabeltextpair{",class,"}{",language,"}{",tag,"}{",text[1],"}{",text[2],"}") if trace_labels then report_labels("language '%s', defining label '%s' as '%s' and '%s'",language,rawtag,text[1],text[2]) end else - context("\\%s[%s][%s={{%s},}]",command,language,tag,text) + contextsprint(prtcatcodes,"\\setlabeltextpair{",class,"}{",language,"}{",tag,"}{",text,"}{}") if trace_labels then report_labels("language '%s', defining label '%s' as '%s'",language,rawtag,text) end @@ -97,11 +104,10 @@ local function definelanguagelabels(data,command,tag,rawtag) end end -function languages.labels.define(command,name,prefixed) +function labels.define(class,name,prefixed) local list = languages.data.labels[name] if list then report_labels("defining label set '%s'",name) - context.pushcatcodes(prtcatcodes) -- context.unprotect for tag, data in next, list do if data.hidden then -- skip @@ -110,31 +116,30 @@ function languages.labels.define(command,name,prefixed) if second then if rawget(variables,first) then if rawget(variables,second) then - definelanguagelabels(data,command,format("\\v!%s:\\v!%s",first,second),tag) + definelanguagelabels(data,class,format("\\v!%s:\\v!%s",first,second),tag) else - definelanguagelabels(data,command,format("\\v!%s:%s",first,second),tag) + definelanguagelabels(data,class,format("\\v!%s:%s",first,second),tag) end elseif rawget(variables,second) then - definelanguagelabels(data,command,format("%s:\\v!%s",first,second),tag) + definelanguagelabels(data,class,format("%s:\\v!%s",first,second),tag) else - definelanguagelabels(data,command,format("%s:%s",first,second),tag) + definelanguagelabels(data,class,format("%s:%s",first,second),tag) end elseif rawget(variables,rawtag) then - definelanguagelabels(data,command,format("\\v!%s",tag),tag) + definelanguagelabels(data,class,format("\\v!%s",tag),tag) else - definelanguagelabels(data,command,tag,tag) + definelanguagelabels(data,class,tag,tag) end else - definelanguagelabels(data,command,tag,tag) + definelanguagelabels(data,class,tag,tag) end end - context.popcatcodes() -- context.protect else report_labels("unknown label set '%s'",name) end end ---~ function languages.labels.check() +--~ function labels.check() --~ for category, list in next, languages.data.labels do --~ for tag, specification in next, list do --~ for language, text in next, specification.labels do @@ -147,8 +152,32 @@ end --~ end --~ end --~ ---~ languages.labels.check() +--~ labels.check() + + +-- interface + +commands.definelabels = labels.define -- function commands.setstrippedtextprefix(str) -- context(string.strip(str)) -- end + +function commands.concatcommalist(settings) -- it's too easy to forget that this one is there + local list = settings_to_array(settings.text or "") + local size = #list + if size > 1 then + local set = settings_to_array(settings.separators or "") + local one = set[1] or settings.first or " " + local two = set[2] or settings.second or " " + context(list[1]) + for i=2,size-1 do + context(one) + context(list[i]) + end + context(two) + end + if size > 0 then + context(list[size]) + end +end diff --git a/tex/context/base/lang-lab.mkiv b/tex/context/base/lang-lab.mkiv index a9744f699..c3c584beb 100644 --- a/tex/context/base/lang-lab.mkiv +++ b/tex/context/base/lang-lab.mkiv @@ -37,8 +37,6 @@ %D in front as well as after a part number. This is why the %D current implementation of labels supports two labels too. -\ifdefined\simplifiedcommands \else \newtoks\simplifiedcommands \fi - %D \macros %D {setupheadtext, setuplabeltext} %D @@ -135,8 +133,7 @@ \let#7\firstofoneargument % to be checked \let#8\firstofoneargument % to be checked \let#9\firstofoneargument % to be checked - \to \simplifiedcommands - } + \to \everysimplifycommands} \let\flushleftlabelclass \firstoftwoarguments \let\flushrightlabelclass\secondoftwoarguments @@ -234,17 +231,18 @@ \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 + {\expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right + \definelabelclass [head] [0] % titles \definelabelclass [label] [0] % texts \definelabelclass [mathlabel] [0] % functions \definelabelclass [taglabel] [2] % tags -\ctxlua{ - languages.labels.define("setupheadtext","titles",true)% - languages.labels.define("setuplabeltext","texts",true)% - languages.labels.define("setupmathlabeltext","functions",false)% - languages.labels.define("setuptaglabeltext","tags",false)% -} +\ctxcommand{definelabels("head", "titles", true )} +\ctxcommand{definelabels("label", "texts", true )} +\ctxcommand{definelabels("mathlabel", "functions",false)} +\ctxcommand{definelabels("taglabel", "tags", false)} %D \macros %D {translate} @@ -264,15 +262,17 @@ %D which expands to {\em something} or {\em iets}, depending on %D de current language. +\installcorenamespace{translation} + \unexpanded\def\translate {\dosingleempty\lang_translate} \def\lang_translate[#1]% - {\getparameters[\??lg][#1]% - \ifcsname\??lg\currentlanguage\endcsname - \csname\??lg\currentlanguage\endcsname - \else\ifcsname\??lg\s!en\endcsname - \csname\??lg\s!en\endcsname + {\getparameters[\??translation][#1]% + \ifcsname\??translation\currentlanguage\endcsname + \csname\??translation\currentlanguage\endcsname + \else\ifcsname\??translation\s!en\endcsname + \csname\??translation\s!en\endcsname \else [translation #1]% \fi\fi} @@ -295,7 +295,43 @@ %D \stoptyping \def\assigntranslation[#1]\to#2% - {\getparameters[\??lg][#1]% - \edef#2{\csname\??lg\currentlanguage\endcsname}} + {\getparameters[\??translation][#1]% + \edef#2{\csname\??translation\currentlanguage\endcsname}} + +%D \macros +%D {commalistsentence} +%D +%D Redone in \LUA: +%D +%D \startbuffer +%D \commalistsentence[aap,noot,mies] +%D \commalistsentence[aap,noot] +%D \commalistsentence[aap] +%D \commalistsentence[a,b,c] +%D \commalistsentence[a,b,c][{ \& },{ and }] +%D \commalistsentence[a,b,c][+,-] +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlines +%D \getbuffer +%D \stoplines + +\unexpanded\def\commalistsentence + {\dodoubleempty\typo_helpers_concat_comma_list} + +\def\typo_helpers_concat_comma_list[#1][#2]% + {\ctxcommand{concatcommalist{ + text = \!!bs#1\!!es, + separators = \!!bs#2\!!es, + first = \!!bs\labeltext{and-1}\!!es, + second = \!!bs\labeltext{and-2}\!!es + }}} + +\setuplabeltext [\s!nl] [and-1={{, }}, and-2={{ en }}] % 1, 2 en 3 +\setuplabeltext [\s!en] [and-1={{, }}, and-2={{, }}] % 1, 2, 3 +\setuplabeltext [\s!de] [and-1={{, }}, and-2={{ und }}] % 1, 2 und 3 +\setuplabeltext [\s!hr] [and-1={{, }}, and-2={{ i }}] % 1, 2 i 3 \protect \endinput diff --git a/tex/context/base/lang-mis.mkiv b/tex/context/base/lang-mis.mkiv index ce23c0f60..4d8b8e08a 100644 --- a/tex/context/base/lang-mis.mkiv +++ b/tex/context/base/lang-mis.mkiv @@ -664,4 +664,35 @@ \ifdefined\normalcompound \else \let\normalcompound=| \fi +%D \macros +%D {compound} +%D +%D We will overload the already active \type {|} so we have +%D to save its meaning in order to be able to use this handy +%D macro. +%D +%D \starttyping +%D so test\compound{}test can be used instead of test||test +%D \stoptyping + +\bgroup + + \catcode\barasciicode\activecatcode + + \unexpanded\gdef\compound#1{|#1|} + + \doglobal \appendtoks + \def|#1|{\ifx#1\empty\empty-\else#1\fi}% + \to \everysimplifycommands + +\egroup + +%D Here we hook some code into the clean up mechanism needed +%D for verbatim data. + +\appendtoks + \disablecompoundcharacters + \disablediscretionaries +\to \everycleanupfeatures + \protect \endinput diff --git a/tex/context/base/lang-txt.lua b/tex/context/base/lang-txt.lua index f28cb18f1..7b0e046fe 100644 --- a/tex/context/base/lang-txt.lua +++ b/tex/context/base/lang-txt.lua @@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['lang-txt'] = { comment = "companion to lang-lab.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } -- The content of this file is derived from the mkii lang-* files and @@ -65,229 +66,311 @@ data.labels={ functions={ Pr={ labels={ + cz="P", en="Pr", + sk="P", }, }, arccos={ labels={ + cz="arccos", en="arccos", hr="arc\\sixperemspace cos", pl="arc\\sixperemspace cos", + sk="arccos", }, }, arcctg={ labels={ + cz="arccotg", en="arccot", hr="arc\\sixperemspace ctg", pl="arc\\sixperemspace ctg", + sk="arccotg", }, }, arcsin={ labels={ + cz="arcsin", en="arcsin", hr="arc\\sixperemspace sin", pl="arc\\sixperemspace sin", + sk="arcsin", }, }, arctan={ labels={ + cz="arctg", en="arctan", hr="arc\\sixperemspace tg", pl="arc\\sixperemspace tg", + sk="arctg", }, }, arctg={ labels={ + cz="arctg", en="arctan", hr="arc\\sixperemspace tg", pl="arc\\sixperemspace tg", + sk="arctg", }, }, arg={ labels={ + cz="arg", en="arg", + sk="arg", }, }, cos={ labels={ + cz="cos", en="cos", + sk="cos", }, }, cosh={ labels={ + cz="cosh", en="cosh", + sk="cosh", }, }, cot={ labels={ + cz="cotg", en="cot", hr="ctg", pl="ctg", + sk="cotg", }, }, coth={ labels={ + cz="cotgh", en="coth", + sk="cotgh", }, }, csc={ labels={ + cz="cosec", en="csc", + sk="cosec", }, }, ctg={ labels={ + cz="cotg", en="cot", hr="ctg", pl="ctg", + sk="cotg", }, }, deg={ labels={ + cz="deg", en="deg", + sk="deg", }, }, det={ labels={ + cz="det", en="det", + sk="det", }, }, dim={ labels={ + cz="dim", en="dim", + sk="dim", }, }, exp={ labels={ + cz="exp", en="exp", + sk="exp", }, }, gcd={ labels={ + cz="NSD", en="gcd", hr="nzd", nl="ggd", + sk="NSD", }, }, hom={ labels={ + cz="Hom", en="hom", + sk="Hom", }, }, inf={ labels={ + cz="inf", en="inf", + sk="inf", }, }, injlim={ labels={ + cz="inj\\sixperemspace lim", en="inj\\sixperemspace lim", + sk="inj\\sixperemspace lim", }, }, ker={ labels={ + cz="ker", en="ker", + sk="ker", }, }, lcm={ labels={ + cz="NSN", en="lcm", hr="nzv", nl="kgv", + sk="NSN", }, }, lg={ labels={ + cz="log", en="lg", + sk="log", }, }, lim={ labels={ + cz="lim", en="lim", + sk="lim", }, }, liminf={ labels={ + cz="lim\\sixperemspace inf", en="lim\\sixperemspace inf", + sk="lim\\sixperemspace inf", }, }, limsup={ labels={ + cz="lim\\sixperemspace sup", en="lim\\sixperemspace sup", + sk="lim\\sixperemspace sup", }, }, ln={ labels={ + cz="ln", en="ln", + sk="ln", }, }, log={ labels={ + cz="log", en="log", + sk="log", }, }, max={ labels={ + cz="max", en="max", + sk="max", }, }, median={ labels={ + cz="\\tilde", en="median", + sk="\\tilde", }, }, min={ labels={ + cz="min", en="min", + sk="min", }, }, mod={ labels={ + cz="mod", en="mod", + sk="mod", }, }, projlim={ labels={ + cz="proj\\sixperemspace lim", en="proj\\sixperemspace lim", + sk="proj\\sixperemspace lim", }, }, sec={ labels={ + cz="sec", en="sec", + sk="sec", }, }, sin={ labels={ + cz="sin", en="sin", + sk="sin", }, }, sinh={ labels={ + cz="sinh", en="sinh", + sk="sinh", }, }, sup={ labels={ + cz="sup", en="sup", + sk="sup", }, }, tan={ labels={ + cz="tg", en="tan", hr="tg", pl="tg", + sk="tg", }, }, tanh={ labels={ + cz="tgh", en="tanh", + sk="tgh", }, }, tg={ labels={ + cz="tg", en="tan", hr="tg", pl="tg", + sk="tg", }, }, }, @@ -296,7 +379,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="a", da="", de="und", en="and", @@ -316,7 +399,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="a", sl="", sv="", tk="", @@ -403,10 +486,10 @@ data.labels={ }, }, ["april:mnem"]={ - labels={ + labels={ af="", ca="", - cs="", + cs="dub.", da="", de="", en="apr", @@ -426,7 +509,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="apr.", sl="", sv="", tk="", @@ -460,7 +543,7 @@ data.labels={ pt="", ro="", ru="на странице ", - sk="", + sk="na strane ", sl="na strani ", sv="på sida ", tk="", @@ -513,7 +596,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="srp.", da="", de="", en="aug", @@ -533,7 +616,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="aug.", sl="", sv="", tk="", @@ -584,7 +667,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs=" (pokračování)", da="", de="", en=" (continued)", @@ -604,7 +687,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk=" (pokračovanie)", sl="", sv="", tk="", @@ -656,7 +739,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="pros.", da="", de="", en="dec", @@ -676,7 +759,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="dec.", sl="", sv="", tk="", @@ -728,7 +811,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="ún.", da="", de="", en="feb", @@ -748,7 +831,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="feb.", sl="", sv="", tk="", @@ -822,7 +905,7 @@ data.labels={ pt="sexta-feira", ro="vineri", ru="пятница", - sk="", + sk="piatok", sl="petek", sv="fredag", tk="bäşinji gün", @@ -893,7 +976,7 @@ data.labels={ pt="", ro="", ru="см. выше", - sk="", + sk="pozri hore", sl="glej zgoraj", sv="se ovan", tk="", @@ -927,7 +1010,7 @@ data.labels={ pt="", ro="", ru="см. ниже", - sk="", + sk="pozri ďalej", sl="glej spodaj", sv="se nedan", tk="", @@ -1016,7 +1099,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="led.", da="", de="", en="jan", @@ -1036,7 +1119,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="jan.", sl="", sv="", tk="", @@ -1089,7 +1172,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="čce", da="", de="", en="jul", @@ -1109,7 +1192,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="júla", sl="", sv="", tk="", @@ -1161,7 +1244,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="čer.", da="", de="", en="jun", @@ -1181,7 +1264,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="júna", sl="", sv="", tk="", @@ -1306,7 +1389,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="břez.", da="", de="", en="mar", @@ -1326,7 +1409,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="mar.", sl="", sv="", tk="", @@ -1379,7 +1462,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="květ.", da="", de="", en="may", @@ -1399,7 +1482,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="mája", sl="", sv="", tk="", @@ -1436,7 +1519,7 @@ data.labels={ pt="segunda-feira", ro="luni", ru="понедельник", - sk="", + sk="pondelok", sl="ponedeljek", sv="måndag", tk="birinji gün", @@ -1488,7 +1571,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="list.", da="", de="", en="nov", @@ -1508,7 +1591,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="nov.", sl="", sv="", tk="", @@ -1559,7 +1642,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="říj.", da="", de="", en="oct", @@ -1579,7 +1662,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="okt.", sl="", sv="", tk="", @@ -1614,7 +1697,7 @@ data.labels={ pt="", ro="", ru="страница ", - sk="", + sk="strana ", sl="stran ", sv="Sida ", tk="", @@ -1647,7 +1730,7 @@ data.labels={ nb="Del", nl="Deel ", nn="Del", - pl="Część ", + pl="Część ", pt="Parte ", ro="Partea ", ru="Часть ", @@ -1688,7 +1771,7 @@ data.labels={ pt="sábado", ro="sâmbătă", ru="суббота", - sk="", + sk="sobota", sl="sobota", sv="lördag", tk="altynjy gün", @@ -1761,7 +1844,7 @@ data.labels={ pt="", ro="", ru="см. ", - sk="", + sk="pozri ", sl="glej ", sv="se ", tk="", @@ -1813,7 +1896,7 @@ data.labels={ labels={ af="", ca="", - cs="", + cs="září", da="", de="", en="sep", @@ -1833,7 +1916,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="sept.", sl="", sv="", tk="", @@ -1981,7 +2064,7 @@ data.labels={ pt="domingo", ro="duminică", ru="воскресенье", - sk="", + sk="nedeľa", sl="nedelja", sv="söndag", tk="dynç gün", @@ -2055,7 +2138,7 @@ data.labels={ pt="quinta-feira", ro="joi", ru="четверг", - sk="", + sk="štvrtok", sl="četrtek", sv="torsdag", tk="dördünji gün", @@ -2092,7 +2175,7 @@ data.labels={ pt="terça-feira", ro="marți", ru="вторник", - sk="", + sk="utorok", sl="torek", sv="tisdag", tk="ikinji gün", @@ -2129,7 +2212,7 @@ data.labels={ pt="quarta-feira", ro="miercuri", ru="среда", - sk="", + sk="streda", sl="sreda", sv="onsdag", tk="üçünji", @@ -2220,7 +2303,7 @@ data.labels={ ar="الأشكال", ca="Figures", cn="图形", - cs="Obrázky", + cs="Seznam obrázků", da="Figurer", de="Abbildungen", en="Figures", @@ -2242,7 +2325,7 @@ data.labels={ pt="Figuras", ro="Figuri", ru="Список иллюстраций", - sk="Obrázkov", + sk="Zoznam obrázkov", sl="Slike", sv="Figurer", tk="Suratlar", @@ -2257,7 +2340,7 @@ data.labels={ ar="الرسوم", ca="Gràfiques", cn="图", - cs="Grafy", + cs="Seznam grafů", da="Grafik", de="Graphiken", en="Graphics", @@ -2279,7 +2362,7 @@ data.labels={ pt="Gráficos", ro="Grafice", ru="Список графиков", - sk="Graf", + sk="Zoznam grafov", sl="Slike", sv="Grafik", tk="Grafikler", @@ -2423,7 +2506,7 @@ data.labels={ pt="", ro="", ru="", - sk="", + sk="Literatúra", sl="Literatura", sv="", tk="", @@ -2438,7 +2521,7 @@ data.labels={ ar="الجداول", ca="Taules", cn="表格", - cs="Tabulky", + cs="Seznam tabulek", da="Tabeller", de="Tabellen", en="Tables", @@ -2460,7 +2543,7 @@ data.labels={ pt="Tabelas", ro="Tabele", ru="Список таблиц", - sk="Tabuliek", + sk="Zoznam tabuliek", sl="Tabele", sv="Tabeller", tk="Tablisalar", diff --git a/tex/context/base/lang-url.lua b/tex/context/base/lang-url.lua index 09a4e5d90..3b354216a 100644 --- a/tex/context/base/lang-url.lua +++ b/tex/context/base/lang-url.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['lang-url'] = { local utf = unicode.utf8 local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues -local utfbyte, utfchar, utfgsub = utf.byte, utf.char, utf.gsub +local utfbyte, utfchar = utf.byte, utf.char context = context @@ -63,7 +63,7 @@ local characters = utilities.storage.allocate { } local mapping = utilities.storage.allocate { ---~ [utfchar(0xA0)] = "~", -- nbsp (catch) + -- [utfchar(0xA0)] = "~", -- nbsp (catch) } hyphenatedurl.characters = characters @@ -72,7 +72,8 @@ hyphenatedurl.lefthyphenmin = 2 hyphenatedurl.righthyphenmin = 3 hyphenatedurl.discretionary = nil --- more fun is to write nodes +-- more fun is to write nodes .. maybe it's nicer to do this +-- in an attribute handler anyway local function action(hyphenatedurl,str,left,right,disc) local n = 0 diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua index 3d3cb6aec..c5bc75ca2 100644 --- a/tex/context/base/lang-wrd.lua +++ b/tex/context/base/lang-wrd.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['lang-ini'] = { +if not modules then modules = { } end modules ['lang-wrd'] = { version = 1.001, comment = "companion to lang-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -90,76 +90,11 @@ function words.found(id, str) end end --- The following code is an adaption of experimental code for --- hyphenating and spell checking. +-- The following code is an adaption of experimental code for hyphenating and +-- spell checking. -- there is an n=1 problem somewhere in nested boxes ---~ local function mark_words(head,whenfound) -- can be optimized and shared ---~ local current, start, str, language, n, done = head, nil, "", nil, 0, false ---~ local function action() ---~ if #str > 0 then ---~ local f = whenfound(language,str) ---~ if f then ---~ done = true ---~ for i=1,n do ---~ f(start) ---~ start = start.next ---~ end ---~ end ---~ end ---~ str, start, n = "", nil, 0 ---~ end ---~ while current do ---~ local id = current.id ---~ if id == glyph_code then ---~ local a = current.lang ---~ if a then ---~ if a ~= language then ---~ if start then ---~ action() ---~ end ---~ language = a ---~ end ---~ elseif start then ---~ action() ---~ language = a ---~ end ---~ local components = current.components ---~ if components then ---~ start = start or current ---~ n = n + 1 ---~ for g in traverse_nodes(components) do ---~ str = str .. utfchar(g.char) ---~ end ---~ else ---~ local code = current.char ---~ local data = chardata[code] ---~ if is_letter[data.category] then ---~ start = start or current ---~ n = n + 1 ---~ str = str .. utfchar(code) -- slow, maybe str should be a table (and given max) ---~ elseif start then ---~ action() ---~ end ---~ end ---~ elseif id == disc_code then ---~ if n > 0 then ---~ n = n + 1 ---~ end ---~ elseif id == kern_code and current.subtype == kerning_code and start then ---~ -- ok ---~ elseif start then ---~ action() ---~ end ---~ current = current.next ---~ end ---~ if start then ---~ action() ---~ end ---~ return head, done ---~ end - local function mark_words(head,whenfound) -- can be optimized and shared local current, language, done = head, nil, nil, 0, false local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls @@ -263,21 +198,19 @@ end local cache = { } -- can also be done with method 1 -- frozen colors once used -setmetatable(cache, { - __index = function(t,k) -- k == language, numbers[k] == tag - local c - if type(k) == "string" then - c = colist[k] - elseif k < 0 then - c = colist["word:unset"] - else - c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"] - end - local v = c and function(n) set_attribute(n,a_color,c) end or false - t[k] = v - return v +table.setmetatableindex(cache, function(t,k) -- k == language, numbers[k] == tag + local c + if type(k) == "string" then + c = colist[k] + elseif k < 0 then + c = colist["word:unset"] + else + c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"] end -} ) + local v = c and function(n) set_attribute(n,a_color,c) end or false + t[k] = v + return v +end) -- method 1 diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua index 154296e9b..aee2c4edf 100644 --- a/tex/context/base/lpdf-ano.lua +++ b/tex/context/base/lpdf-ano.lua @@ -325,7 +325,7 @@ function nodeinjections.destination(width,height,depth,name,view) if trace_destinations then report_destination("w=%s, h=%s, d=%s, n=%s, v=%s",width,height,depth,name,view or "no view") end - return pdfdestination_node(width,height,depth,name,view) + return pdfdestination_node(width,height,depth,name,view) -- can be begin/end node end end @@ -607,8 +607,8 @@ function executers.submitform(arguments) local flag = flags[formmethod] or flags.post flag = (flag and (flag[formformat] or flag.xml)) or 32 -- default: post, xml return pdfdictionary { - S = pdfconstant("ResetForm"), - F = fieldset(arguments[1]), + S = pdfconstant("SubmitForm"), + F = arguments[1], Field = fieldset(arguments[2]), Flags = flag, -- \PDFsubmitfiller diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua index 0c2a49ebe..db9d3268b 100644 --- a/tex/context/base/lpdf-col.lua +++ b/tex/context/base/lpdf-col.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['lpdf-mis'] = { +if not modules then modules = { } end modules ['lpdf-col'] = { version = 1.001, comment = "companion to lpdf-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -13,6 +13,8 @@ local round = math.round local backends, lpdf, nodes = backends, lpdf, nodes +local allocate = utilities.storage.allocate + local nodeinjections = backends.pdf.nodeinjections local codeinjections = backends.pdf.codeinjections local registrations = backends.pdf.registrations @@ -44,7 +46,7 @@ local report_color = logs.reporter("colors","backend") -- page groups (might move to lpdf-ini.lua) -local colorspaceconstants = { -- v_none is ignored +local colorspaceconstants = allocate { -- v_none is ignored gray = pdfconstant("DeviceGray"), rgb = pdfconstant("DeviceRGB"), cmyk = pdfconstant("DeviceCMYK"), @@ -694,7 +696,7 @@ end -- this will move to lpdf-spe.lua -backends.pdf.tables.vfspecials = { -- todo: distinguish between glyph and rule color +backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color red = { "special", 'pdf: 1 0 0 rg 1 0 0 RG' }, green = { "special", 'pdf: 0 1 0 rg 0 1 0 RG' }, diff --git a/tex/context/base/lpdf-epa.lua b/tex/context/base/lpdf-epa.lua index c8d23a618..03a36f2dc 100644 --- a/tex/context/base/lpdf-epa.lua +++ b/tex/context/base/lpdf-epa.lua @@ -111,9 +111,9 @@ function codeinjections.mergereferences(specification) local size = specification.size or "crop" -- todo local pagedata = document.pages[pagenumber] local annotations = pagedata.Annots - local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname))) - local reference = namespace .. pagenumber - if annotations.n > 0 then + if annotations and annotations.n > 0 then + local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname))) + local reference = namespace .. pagenumber local mediabox = pagedata.MediaBox local llx, lly, urx, ury = mediabox[1], mediabox[2], mediabox[3], mediabox[4] local width, height = xscale * (urx - llx), yscale * (ury - lly) -- \\overlaywidth, \\overlayheight diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua index 76d258cef..1c4b4b5c5 100644 --- a/tex/context/base/lpdf-epd.lua +++ b/tex/context/base/lpdf-epd.lua @@ -179,14 +179,17 @@ checked_access = { ref = function(v) return v:getRef() end, + null = function() + return nil + end, } ---~ checked_access.real = epdf.real ---~ checked_access.integer = epdf.integer ---~ checked_access.string = epdf.string ---~ checked_access.boolean = epdf.boolean ---~ checked_access.name = epdf.name ---~ checked_access.ref = epdf.ref +-- checked_access.real = epdf.real +-- checked_access.integer = epdf.integer +-- checked_access.string = epdf.string +-- checked_access.boolean = epdf.boolean +-- checked_access.name = epdf.name +-- checked_access.ref = epdf.ref local function getnames(document,n,target) -- direct if n then @@ -323,6 +326,15 @@ function lpdf.epdf.load(filename) return document end +-- for k, v in next, expand(t) do + +function lpdf.epdf.expand(t) + if type(t) == "table" then + local dummy = t.dummy + end + return t +end + -- helpers -- function lpdf.epdf.getdestinationpage(document,name) diff --git a/tex/context/base/lpdf-fmt.lua b/tex/context/base/lpdf-fmt.lua index 8e118db12..859a489ef 100644 --- a/tex/context/base/lpdf-fmt.lua +++ b/tex/context/base/lpdf-fmt.lua @@ -36,6 +36,8 @@ local pdfstring = lpdf.string local pdfverbose = lpdf.verbose local pdfflushstreamfileobject = lpdf.flushstreamfileobject +local texset = tex.set -- we could make tex.setglobal + local addtoinfo = lpdf.addtoinfo local injectxmpinfo = lpdf.injectxmpinfo local insertxmpinfo = lpdf.insertxmpinfo @@ -360,7 +362,7 @@ local function loadprofile(name,filename) for i=1,#databases do local filename = locatefile(databases[i]) if filename and filename ~= "" then - local suffix = file.extname(filename) + local suffix = file.suffix(filename) local lname = lower(name) if suffix == "xml" then local xmldata = xml.load(filename) -- no need for caching it @@ -625,15 +627,17 @@ end lpdf.registerdocumentfinalizer(flushoutputintents,2,"output intents") function codeinjections.setformat(s) - local format, level, profile, intent, option, filename = - s.format or "", s.level or "", s.profile or "", s.intent or "", s.option or "", s.file or "" - if format == "" then - -- we ignore this as we hook it in \everysetupbackend - else + local format = s.format or "" + local level = tonumber(s.level) + local intent = s.intent or "" + local profile = s.profile or "" + local option = s.option or "" + local filename = s.file or "" + if format ~= "" then local spec = formats[lower(format)] if spec then - formatspecification, formatname = spec, spec.format_name - level = level and tonumber(level) + formatspecification = spec + formatname = spec.format_name report_backend("setting format to '%s'",formatname) local xmp_file = formatspecification.xmp_file or "" if xmp_file == "" then @@ -641,13 +645,20 @@ function codeinjections.setformat(s) else codeinjections.setxmpfile(xmp_file) end - local pdf_version, inject_metadata = spec.pdf_version * 10, spec.inject_metadata - local majorversion, minorversion = math.div(pdf_version,10), math.mod(pdf_version,10) + if not level then + level = 3 -- good compromise, default anyway + end + local pdf_version = spec.pdf_version * 10 + local inject_metadata = spec.inject_metadata + local majorversion = math.div(pdf_version,10) + local minorversion = math.mod(pdf_version,10) local objectcompression = spec.object_compression and pdf_version >= 15 local compresslevel = level or tex.pdfcompresslevel -- keep default local objectcompresslevel = (objectcompression and (level or tex.pdfobjcompresslevel)) or 0 - tex.pdfcompresslevel, tex.pdfobjcompresslevel = compresslevel, objectcompresslevel - tex.pdfmajorversion, tex.pdfminorversion = majorversion, minorversion + texset("global","pdfcompresslevel",compresslevel) + texset("global","pdfobjcompresslevel",objectcompresslevel) + texset("global","pdfmajorversion",majorversion) + texset("global","pdfminorversion",minorversion) if objectcompression then report_backend("forcing pdf version %s.%s, compression level %s, object compression level %s", majorversion,minorversion,compresslevel,objectcompresslevel) @@ -704,6 +715,11 @@ function codeinjections.setformat(s) else report_backend("error, format '%s' is not supported",format) end + elseif level then + texset("global","pdfcompresslevel",level) + texset("global","pdfobjcompresslevel",level) + else + -- we ignore this as we hook it in \everysetupbackend end end diff --git a/tex/context/base/lpdf-nod.lua b/tex/context/base/lpdf-nod.lua index fe0c975f7..0ce589c32 100644 --- a/tex/context/base/lpdf-nod.lua +++ b/tex/context/base/lpdf-nod.lua @@ -59,7 +59,7 @@ end function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) local t = copy_node(pdfsetmatrix) - t.data = format("%s %s %s %s",rs or 0,sx or 0,sy or 0,rx or 0) -- todo: tx ty + t.data = format("%s %s %s %s",rx or 0,sx or 0,sy or 0,ry or 0) -- todo: tx ty return t end @@ -69,21 +69,68 @@ nodeinjections.transform = nodepool.pdfsetmatrix function nodepool.pdfannotation(w,h,d,data,n) local t = copy_node(pdfannot) - if w and w ~= 0 then t.width = w end - if h and h ~= 0 then t.height = h end - if d and d ~= 0 then t.depth = d end - if n then t.objnum = n end - if data and data ~= "" then t.data = data end + if w and w ~= 0 then + t.width = w + end + if h and h ~= 0 then + t.height = h + end + if d and d ~= 0 then + t.depth = d + end + if n then + t.objnum = n + end + if data and data ~= "" then + t.data = data + end return t end +-- (!) The next code in pdfdest.w is wrong: +-- +-- case pdf_dest_xyz: +-- if (matrixused()) { +-- set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin) ; +-- } else { +-- pdf_ann_left(p) = pos.h ; +-- pdf_ann_top (p) = pos.v ; +-- } +-- break ; +-- +-- so we need to force a matrix. + function nodepool.pdfdestination(w,h,d,name,view,n) local t = copy_node(pdfdest) - if w and w ~= 0 then t.width = w end - if h and h ~= 0 then t.height = h end - if d and d ~= 0 then t.depth = d end - if n then t.objnum = n end + local hasdimensions = false + if w and w ~= 0 then + t.width = w + hasdimensions = true + end + if h and h ~= 0 then + t.height = h + hasdimensions = true + end + if d and d ~= 0 then + t.depth = d + hasdimensions = true + end + if n then + t.objnum = n + end + view = views[view] or view or 1 -- fit is default t.dest_id = name - t.dest_type = views[view] or view or 1 -- fit is default - return t + t.dest_type = view + if hasdimensions and view == 0 then -- xyz + -- see (!) s -> m -> t -> r + local s = copy_node(pdfsave) + local m = copy_node(pdfsetmatrix) + local r = copy_node(pdfrestore) + m.data = format("1 0 0 1") + s.next = m m.next = t t.next = r + m.prev = s t.prev = m r.prev = t + return s -- a list + else + return t + end end diff --git a/tex/context/base/lpdf-ren.lua b/tex/context/base/lpdf-ren.lua index e0c4b1973..6af65f9de 100644 --- a/tex/context/base/lpdf-ren.lua +++ b/tex/context/base/lpdf-ren.lua @@ -9,7 +9,8 @@ if not modules then modules = { } end modules ['lpdf-ren'] = { -- rendering local tostring, tonumber, next = tostring, tonumber, next -local format = string.format +local format, rep = string.format, string.rep +local concat = table.concat local settings_to_array = utilities.parsers.settings_to_array local backends, lpdf, nodes, node = backends, lpdf, nodes, node @@ -60,51 +61,12 @@ local lpdf_usage = pdfdictionary { Print = pdfdictionary { PrintState = pdf_off -- hide and vide actions. This is why we need to be able to force usage of layers -- at several moments. --- injection - -local cache = { } - -function codeinjections.startlayer(name) - codeinjections.useviewerlayer(name) - return format("/OC /%s BDC",name) -end - -function codeinjections.stoplayer(name) - return "EMC" -end - -function nodeinjections.startlayer(name) - local c = cache[name] - if not c then - codeinjections.useviewerlayer(name) - c = register(pdfliteral(format("/OC /%s BDC",name))) - cache[name] = c - end - return copy_node(c) -end - -local stop = register(pdfliteral("EMC")) - -function nodeinjections.stoplayer() - return copy_node(stop) -end - -local cache = { } - -function nodeinjections.switchlayer(name) -- not used, optimization - local c = cache[name] - if not c then - codeinjections.useviewerlayer(name) - c = register(pdfliteral(format("EMC /OC /%s BDC",name))) - end - return copy_node(c) -end - -- management local pdfln, pdfld = { }, { } local textlayers, hidelayers, videlayers = pdfarray(), pdfarray(), pdfarray() local pagelayers, pagelayersreference, cache = nil, nil, { } +local alphabetic = { } local specifications = { } local initialized = { } @@ -149,6 +111,7 @@ local function useviewerlayer(name) -- move up so that we can use it as local cache[#cache+1] = { dn, dd } pdfld[tag] = dr textlayers[#textlayers+1] = nr + alphabetic[tag] = nr if specification.visible == v_start then videlayers[#videlayers+1] = nr else @@ -185,11 +148,16 @@ local function flushtextlayers() pdfflushobject(ci[1],ci[2]) end if textlayers and #textlayers > 0 then -- we can group them if needed, like: layout + local sortedlayers = { } + for k, v in table.sortedhash(alphabetic) do + sortedlayers[#sortedlayers+1] = v -- maybe do a proper numeric sort as well + end local d = pdfdictionary { OCGs = textlayers, D = pdfdictionary { Name = "Document", - Order = (viewerlayers.hasorder and textlayers) or nil, + -- Order = (viewerlayers.hasorder and textlayers) or nil, + Order = (viewerlayers.hasorder and sortedlayers) or nil, ON = videlayers, OFF = hidelayers, BaseState = pdf_on, @@ -230,6 +198,74 @@ function executers.hidelayer (arguments) return setlayer(pdf_off, arguments) function executers.videlayer (arguments) return setlayer(pdf_on, arguments) end function executers.togglelayer(arguments) return setlayer(pdf_toggle,arguments) end +-- injection + +function codeinjections.startlayer(name) -- used in mp + if not name then + name = "unknown" + end + useviewerlayer(name) + return format("/OC /%s BDC",name) +end + +function codeinjections.stoplayer(name) -- used in mp + return "EMC" +end + +local cache = { } + +function nodeinjections.startlayer(name) + local c = cache[name] + if not c then + useviewerlayer(name) + c = register(pdfliteral(format("/OC /%s BDC",name))) + cache[name] = c + end + return copy_node(c) +end + +local stop = register(pdfliteral("EMC")) + +function nodeinjections.stoplayer() + return copy_node(stop) +end + +-- experimental stacker code (slow, can be optimized): !!!! TEST CODE !!!! + +local values = viewerlayers.values +local startlayer = codeinjections.startlayer +local stoplayer = codeinjections.stoplayer + +function nodeinjections.startstackedlayer(s,t,first,last) + local r = { } + for i=first,last do + r[#r+1] = startlayer(values[t[i]]) + end + r = concat(r," ") + return pdfliteral(r) +end + +function nodeinjections.stopstackedlayer(s,t,first,last) + local r = { } + for i=last,first,-1 do + r[#r+1] = stoplayer() + end + r = concat(r," ") + return pdfliteral(r) +end + +function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2) + local r = { } + for i=last1,first1,-1 do + r[#r+1] = stoplayer() + end + for i=first2,last2 do + r[#r+1] = startlayer(values[t2[i]]) + end + r = concat(r," ") + return pdfliteral(r) +end + -- transitions local pagetransitions = { diff --git a/tex/context/base/lpdf-u3d.lua b/tex/context/base/lpdf-u3d.lua index ac6038997..f5f66a487 100644 --- a/tex/context/base/lpdf-u3d.lua +++ b/tex/context/base/lpdf-u3d.lua @@ -370,7 +370,7 @@ local function insert3d(spec) -- width, height, factor, display, controls, label subtype = "PRC" elseif find(subdata,"^U3D") then subtype = "U3D" - elseif file.extname(foundname) == "prc" then + elseif file.suffix(foundname) == "prc" then subtype = "PRC" end diff --git a/tex/context/base/luat-bwc.lua b/tex/context/base/luat-bwc.lua index f893c7c5b..993de7bf3 100644 --- a/tex/context/base/luat-bwc.lua +++ b/tex/context/base/luat-bwc.lua @@ -27,6 +27,6 @@ if not tex.wd then __newindex = function(t,k,v) local bk = box[k] if bk then bk.depth = v end end, } ) ---~ tex.wd, tex.ht, tex.dp = wd, ht, dp + -- tex.wd, tex.ht, tex.dp = wd, ht, dp end diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua index 6622c64cd..c4f0aba02 100644 --- a/tex/context/base/luat-cbk.lua +++ b/tex/context/base/luat-cbk.lua @@ -34,10 +34,13 @@ functions.</p> local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end) local trace_calls = false -- only used when analyzing performance and initializations -local register_callback, find_callback, list_callbacks = callback.register, callback.find, callback.list +local register_callback = callback.register +local find_callback = callback.find +local list_callbacks = callback.list + local frozen, stack, list = { }, { }, callbacks.list -if not callbacks.list then -- otherwise counters get reset +if not list then -- otherwise counters get reset list = utilities.storage.allocate(list_callbacks()) @@ -113,15 +116,6 @@ function callbacks.report() end end -function callbacks.table() - local NC, NR, verbatim = context.NC, context.NR, context.type - context.starttabulate { "|l|l|p|" } - for name, _ in sortedhash(list) do - NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR() - end - context.stoptabulate() -end - function callbacks.freeze(name,freeze) freeze = type(freeze) == "string" and freeze if find(name,"%*") then @@ -311,3 +305,16 @@ function garbagecollector.check(size,criterium) end end end + +-- this will move + +commands = commands or { } + +function commands.showcallbacks() + local NC, NR, verbatim = context.NC, context.NR, context.type + context.starttabulate { "|l|l|p|" } + for name, _ in sortedhash(list) do + NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR() + end + context.stoptabulate() +end diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua index 609dc412b..07a5d51f2 100644 --- a/tex/context/base/luat-cnf.lua +++ b/tex/context/base/luat-cnf.lua @@ -123,19 +123,20 @@ function texconfig.init() local function init(start) local b = lua.bytecode local i = start + local t = os.clock() while b[i] do b[i]() ; b[i] = nil ; i = i + 1 -- collectgarbage('step') end - return i - start + return i - start, os.clock() - t end -- the stored tables and modules - storage.noftables = init(0) - storage.nofmodules = init(%s) + storage.noftables , storage.toftables = init(0) + storage.nofmodules, storage.tofmodules = init(%s) end diff --git a/tex/context/base/luat-cod.lua b/tex/context/base/luat-cod.lua index b022f31c3..87b2c0059 100644 --- a/tex/context/base/luat-cod.lua +++ b/tex/context/base/luat-cod.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['luat-cod'] = { license = "see context related readme files" } +local type, loadfile = type, loadfile local match, gsub, find, format = string.match, string.gsub, string.find, string.format local texconfig, lua = texconfig, lua @@ -19,11 +20,13 @@ texconfig.max_in_open = 127 -- registering bytecode chunks -lua.bytecode = lua.bytecode or { } -- built in anyway -lua.bytedata = lua.bytedata or { } -lua.bytedone = lua.bytedone or { } +local bytecode = lua.bytecode or { } +local bytedata = lua.bytedata or { } +local bytedone = lua.bytedone or { } -local bytecode, bytedata, bytedone = lua.bytecode, lua.bytedata, lua.bytedone +lua.bytecode = bytecode -- built in anyway +lua.bytedata = bytedata +lua.bytedone = bytedone lua.firstbytecode = 501 lua.lastbytecode = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier @@ -32,18 +35,19 @@ function lua.registeredcodes() return lua.lastbytecode - lua.firstbytecode + 1 end +-- no file.* functions yet + function lua.registercode(filename,version) local barename = gsub(filename,"%.[%a%d]+$","") if barename == filename then filename = filename .. ".lua" end local basename = match(barename,"^.+[/\\](.-)$") or barename - if not bytedone[barename] then + if not bytedone[basename] then local code = environment.luafilechunk(filename) if code then - assert(code)() - bytedone[barename] = true + bytedone[basename] = true if environment.initex then local n = lua.lastbytecode + 1 - bytedata[n] = { barename, version } + bytedata[n] = { barename, version or "0.000" } bytecode[n] = code lua.lastbytecode = n end @@ -54,10 +58,11 @@ end local finalizers = { } function lua.registerfinalizer(f,comment) + comment = comment or "unknown" if type(f) == "function" then finalizers[#finalizers+1] = { action = f, comment = comment } else - print(format("fatal error: invalid finalizer, action: %s",finalizer.comment or "unknown")) + texio.write_nl(format("fatal error: invalid finalizer, action: %s",comment)) os.exit() end end @@ -98,12 +103,15 @@ if not environment.luafilechunk then end local data = loadfile(filename) texio.write("<",data and "+ " or "- ",filename,">") + if data then + data() + end return data end end -if not environment.engineflags then +if not environment.engineflags then -- raw flags local engineflags = { } for i=-10,#arg do local a = arg[i] diff --git a/tex/context/base/luat-cod.mkiv b/tex/context/base/luat-cod.mkiv index 930532df9..034ab0613 100644 --- a/tex/context/base/luat-cod.mkiv +++ b/tex/context/base/luat-cod.mkiv @@ -15,12 +15,6 @@ \unprotect -%D We have this one for a rather long time now but nowadays \ETEX\ -%D provides a command with the same name and different meaning. That -%D one is available as \type {\normalexpanded}. - -\long\def\expanded#1{\long\xdef\lastexpanded{\noexpand#1}\lastexpanded} - %D We cannot use the following due to the fact that existing usage %D demanded duplicating hashes. %D diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua index 4f1b661c2..c8a391e76 100644 --- a/tex/context/base/luat-env.lua +++ b/tex/context/base/luat-env.lua @@ -20,7 +20,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find local unquoted, quoted = string.unquoted, string.quoted -local concat = table.concat +local concat, insert, remove = table.concat, table.insert, table.remove +local loadedluacode = utilities.lua.loadedluacode -- precautions @@ -38,8 +39,28 @@ if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaon for k=3,#arg do arg[k-2] = arg[k] end - arg[#arg] = nil -- last - arg[#arg] = nil -- pre-last + remove(arg) -- last + remove(arg) -- pre-last +end + +-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in: +-- +-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context +-- +-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base' +-- but it's unlikely that there will be more of this + +do + + local originalzero = file.basename(arg[0]) + local specialmapping = { luatools == "base" } + + if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then + arg[0] = specialmapping[originalzero] or originalzero + insert(arg,0,"--script") + insert(arg,0,"mtxrun") + end + end -- environment @@ -79,6 +100,8 @@ local mt = { setmetatable(environment,mt) +-- context specific arguments (in order not to confuse the engine) + function environment.initializearguments(arg) local arguments, files = { }, { } environment.arguments, environment.files, environment.sortedflags = arguments, files, nil @@ -87,10 +110,12 @@ function environment.initializearguments(arg) if index > 0 then local flag, value = match(argument,"^%-+(.-)=(.-)$") if flag then + flag = gsub(flag,"^c:","") arguments[flag] = unquoted(value or "") else flag = match(argument,"^%-+(.+)") if flag then + flag = gsub(flag,"^c:","") arguments[flag] = true else files[#files+1] = argument @@ -110,7 +135,7 @@ end -- tricky: too many hits when we support partials unless we add -- a registration of arguments so from now on we have 'partial' -function environment.argument(name,partial) +function environment.getargument(name,partial) local arguments, sortedflags = environment.arguments, environment.sortedflags if arguments[name] then return arguments[name] @@ -133,6 +158,8 @@ function environment.argument(name,partial) return nil end +environment.argument = environment.getargument + function environment.splitarguments(separator) -- rather special, cut-off before separator local done, before, after = false, { }, { } local originalarguments = environment.originalarguments @@ -234,7 +261,7 @@ function environment.texfile(filename) return resolvers.findfile(filename,'tex') end -function environment.luafile(filename) +function environment.luafile(filename) -- needs checking local resolved = resolvers.findfile(filename,'tex') or "" if resolved ~= "" then return resolved @@ -246,13 +273,16 @@ function environment.luafile(filename) return resolvers.findfile(filename,'luatexlibs') or "" end -environment.loadedluacode = loadfile -- can be overloaded +local function checkstrip(filename) + local modu = modules[file.nameonly(filename)] + return modu and modu.dataonly +end function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format filename = file.replacesuffix(filename, "lua") local fullname = environment.luafile(filename) if fullname and fullname ~= "" then - local data = environment.loadedluacode(fullname) + local data = loadedluacode(fullname,checkstrip,filename) if trace_locating then report_lua("loading file %s%s", fullname, not data and " failed" or "") elseif not silent then diff --git a/tex/context/base/luat-fmt.lua b/tex/context/base/luat-fmt.lua index cfb9a0bb7..37b0f5166 100644 --- a/tex/context/base/luat-fmt.lua +++ b/tex/context/base/luat-fmt.lua @@ -110,7 +110,6 @@ function environment.make_format(name) end function environment.run_format(name,data,more) - -- hm, rather old code here; we can now use the file.whatever functions if name and name ~= "" then local barename = file.removesuffix(name) local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats") diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua index 204cc7bd1..94c878eb1 100644 --- a/tex/context/base/luat-ini.lua +++ b/tex/context/base/luat-ini.lua @@ -8,12 +8,11 @@ if not modules then modules = { } end modules ['luat-ini'] = { -- rather experimental down here ... will change with lua 5.2 -- -local debug = require "debug" +local debug = require("debug") + local string, table, lpeg, math, io, system = string, table, lpeg, math, io, system local next, setfenv = next, setfenv or debug.setfenv -local mark = utilities.storage.mark - --[[ldx-- <p>We cannot load anything yet. However what we will do us reserve a fewtables. These can be used for runtime user data or third party modules and will not be @@ -26,15 +25,6 @@ moduledata = moduledata or { } -- only for development team documentdata = documentdata or { } -- for users (e.g. raw data) parametersets = parametersets or { } -- experimental for team -document = document or { } -- only for context itself - ---[[ldx-- -<p>These can be used/set by the caller program; <t>mtx-context.lua</t> does it.</p> ---ldx]]-- - -document.arguments = mark(document.arguments or { }) -document.files = mark(document.files or { }) - --[[ldx-- <p>Please create a namespace within these tables before using them!</p> @@ -157,33 +147,3 @@ end storage.register("lua/numbers", lua.numbers, "lua.numbers") storage.register("lua/messages", lua.messages, "lua.messages") - ---~ local arguments, files = document.arguments, document.files -- set later - -function document.setargument(key,value) - document.arguments[key] = value -end - -function document.setdefaultargument(key,default) - local v = document.arguments[key] - if v == nil or v == "" then - document.arguments[key] = default - end -end - -function document.getargument(key,default) - local v = document.arguments[key] - if type(v) == "boolean" then - v = (v and "yes") or "no" - document.arguments[key] = v - end - context(v or default or "") -end - -function document.setfilename(i,name) - document.files[tonumber(i)] = name -end - -function document.getfilename(i) - context(document.files[i] or "") -end diff --git a/tex/context/base/luat-ini.mkiv b/tex/context/base/luat-ini.mkiv index 46b2d1f7f..094c4ee53 100644 --- a/tex/context/base/luat-ini.mkiv +++ b/tex/context/base/luat-ini.mkiv @@ -108,16 +108,18 @@ %D Beware: because \type {\expanded} is een convert command, the error %D message will show \type{<inserted text>} as part of the message. +\installcorenamespace{luacode} + \def\luat_start_named_lua_code#1% {\begingroup \obeylualines \obeyluatokens - \csname\??lu:c:#1\endcsname} + \csname\??luacode#1\endcsname} \unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet - {\ifcsname\??lu:c:#1\endcsname \else + {\ifcsname\??luacode#1\endcsname \else \scratchcounter\ctxlua{lua.registername("#1","#3")}% - \normalexpanded{\edef\csname\??lu:c:#1\endcsname##1\csname\e!stop#1\v!code\endcsname}% + \normalexpanded{\edef\csname\??luacode#1\endcsname##1\csname\e!stop#1\v!code\endcsname}% {\endgroup\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}% \expandafter\def \csname\e!start#1\v!code\endcsname {\luat_start_named_lua_code{#1}}% \expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}% diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv index 5a53b7ea2..6ca0ac05a 100644 --- a/tex/context/base/luat-lib.mkiv +++ b/tex/context/base/luat-lib.mkiv @@ -30,6 +30,10 @@ \registerctxluafile{trac-log}{1.001} %registerctxluafile{trac-pro}{1.001} +\registerctxluafile{util-tpl}{1.001} % needs tracker + +\registerctxluafile{util-sta}{1.001} + \registerctxluafile{data-ini}{1.001} \registerctxluafile{data-exp}{1.001} \registerctxluafile{data-env}{1.001} @@ -65,6 +69,7 @@ \registerctxluafile{luat-exe}{1.001} \registerctxluafile{luat-iop}{1.001} \registerctxluafile{luat-bwc}{1.001} +\registerctxluafile{trac-lmx}{1.001} % might become l-lmx or luat-lmx \registerctxluafile{luat-mac}{1.001} \registerctxluafile{lxml-tab}{1.001} diff --git a/tex/context/base/luat-mac.lua b/tex/context/base/luat-mac.lua index f8f87a25a..199332bba 100644 --- a/tex/context/base/luat-mac.lua +++ b/tex/context/base/luat-mac.lua @@ -20,6 +20,8 @@ local lpegmatch, patterns = lpeg.match, lpeg.patterns local insert, remove = table.insert, table.remove local rep, sub = string.rep, string.sub local setmetatable = setmetatable +local filesuffix = file.suffix +local convertlmxstring = lmx.convertstring local pushtarget, poptarget = logs.pushtarget, logs.poptarget @@ -199,18 +201,91 @@ function macros.version(data) return lpegmatch(checker,data) end +-- function macros.processmkvi(str,filename) +-- if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then +-- local oldsize = #str +-- str = lpegmatch(parser,str,1,true) or str +-- pushtarget("log") +-- report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str) +-- poptarget("log") +-- end +-- return str +-- end +-- +-- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi") + +-- the document variables hack is temporary + +local processors = { } + +function processors.mkvi(str,filename) + local oldsize = #str + str = lpegmatch(parser,str,1,true) or str + pushtarget("log") + report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str) + poptarget("log") + return str +end + +function processors.mkix(str,filename) -- we could intercept earlier so that caching works better + if not document then -- because now we hash the string as well as the + document = { } + end + if not document.variables then + document.variables = { } + end + local oldsize = #str + str = convertlmxstring(str,document.variables,false) or str + pushtarget("log") + report_macros("processed mkix file %q, delta %s",filename,oldsize-#str) + poptarget("log") + return str +end + +function processors.mkxi(str,filename) + if not document then + document = { } + end + if not document.variables then + document.variables = { } + end + local oldsize = #str + str = convertlmxstring(str,document.variables,false) or str + str = lpegmatch(parser,str,1,true) or str + pushtarget("log") + report_macros("processed mkxi file %q, delta %s",filename,oldsize-#str) + poptarget("log") + return str +end + +function macros.processmk(str,filename) + if filename then + local suffix = filesuffix(filename) + local processor = processors[suffix] or processors[lpegmatch(checker,str)] + if processor then + str = processor(str,filename) + end + end + return str +end + +utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmk") + function macros.processmkvi(str,filename) - if (filename and file.suffix(filename) == "mkvi") or lpegmatch(checker,str) == "mkvi" then - local result = lpegmatch(parser,str,1,true) or str + if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then + local oldsize = #str + str = lpegmatch(parser,str,1,true) or str pushtarget("log") - report_macros("processed file '%s', delta %s",filename,#str-#result) + report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str) poptarget("log") - return result - else - return str end + return str end +utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi") + +-- bonus + if resolvers.schemes then local function handler(protocol,name,cachename) @@ -218,7 +293,7 @@ if resolvers.schemes then local path = hashed.path if path and path ~= "" then local str = resolvers.loadtexfile(path) - if file.suffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then + if filesuffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then -- already done automatically io.savedata(cachename,str) else @@ -234,9 +309,6 @@ if resolvers.schemes then resolvers.schemes.install('mkvi',handler,1) -- this will cache ! - utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi") - -- utilities.sequencers.disableaction(resolvers.openers.helpers.textfileactions,"resolvers.macros.processmkvi") - end -- print(macros.preprocessed( diff --git a/tex/context/base/luat-run.lua b/tex/context/base/luat-run.lua index ce25d1f55..bcd9e2bdc 100644 --- a/tex/context/base/luat-run.lua +++ b/tex/context/base/luat-run.lua @@ -67,11 +67,11 @@ end local function report_output_log() end ---~ local function show_open() ---~ end +-- local function show_open() +-- end ---~ local function show_close() ---~ end +-- local function show_close() +-- end local function pre_dump_actions() lua.finalize(trace_lua_dump and report_lua or nil) @@ -84,8 +84,8 @@ end callbacks.register('start_run', start_run, "actions performed at the beginning of a run") callbacks.register('stop_run', stop_run, "actions performed at the end of a run") ---~ callbacks.register('show_open', show_open, "actions performed when opening a file") ---~ callbacks.register('show_close', show_close, "actions performed when closing a file") +---------.register('show_open', show_open, "actions performed when opening a file") +---------.register('show_close', show_close, "actions performed when closing a file") callbacks.register('report_output_pages', report_output_pages, "actions performed when reporting pages") callbacks.register('report_output_log', report_output_log, "actions performed when reporting log file") diff --git a/tex/context/base/luat-soc.lua b/tex/context/base/luat-soc.lua index 1095ed087..9342a4b33 100644 --- a/tex/context/base/luat-soc.lua +++ b/tex/context/base/luat-soc.lua @@ -1,11 +1,11 @@ -- This is just a loader. The package handler knows about the TEX tree. ---~ require "luatex/lua/socket.lua" ---~ require "luatex/lua/ltn12.lua" ---~ require "luatex/lua/mime.lua" ---~ require "luatex/lua/socket/http.lua" ---~ require "luatex/lua/socket/url.lua" ---~ require "luatex/lua/socket/tp.lua" ---~ require "luatex/lua/socket/ftp.lua" +-- require "luatex/lua/socket.lua" +-- require "luatex/lua/ltn12.lua" +-- require "luatex/lua/mime.lua" +-- require "luatex/lua/socket/http.lua" +-- require "luatex/lua/socket/url.lua" +-- require "luatex/lua/socket/tp.lua" +-- require "luatex/lua/socket/ftp.lua" --- "luatex/lua/socket/smtp.lua" +-- "luatex/lua/socket/smtp.lua" diff --git a/tex/context/base/luat-sto.lua b/tex/context/base/luat-sto.lua index 30bb7d5bb..fddf262c2 100644 --- a/tex/context/base/luat-sto.lua +++ b/tex/context/base/luat-sto.lua @@ -12,7 +12,9 @@ local type, next, setmetatable, getmetatable, collectgarbage = type, next, setme local gmatch, format, write_nl = string.gmatch, string.format, texio.write_nl local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash local bytecode = lua.bytecode +local strippedloadstring = utilities.lua.strippedloadstring +local trace_storage = false local report_storage = logs.reporter("system","storage") storage = storage or { } @@ -62,11 +64,14 @@ local function dump() end max = max + 1 if trace_storage then - report_storage('saving %s in slot %s',message,max) - c = c + 1 ; code[c] = format("report_storage('restoring %s from slot %s')",message,max) + c = c + 1 ; code[c] = format("print('restoring %s from slot %s')",message,max) end c = c + 1 ; code[c] = serialize(original,name) - bytecode[max] = loadstring(concat(code,"\n")) + if trace_storage then + report_storage('saving %s in slot %s (%s bytes)',message,max,#code[c]) + end + -- we don't need tracing in such tables + bytecode[max] = strippedloadstring(concat(code,"\n"),true,format("slot %s",max)) collectgarbage("step") end storage.max = max @@ -103,9 +108,24 @@ end --~ end statistics.register("stored bytecode data", function() - local modules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - lua.firstbytecode - 1) - local dumps = (storage.noftables > 0 and storage.noftables) or storage.max-storage.min + 1 - return format("%s modules, %s tables, %s chunks",modules,dumps,modules+dumps) + local nofmodules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - lua.firstbytecode - 1) + local nofdumps = (storage.noftables > 0 and storage.noftables ) or storage.max-storage.min + 1 + local tofmodules = storage.tofmodules or 0 + local tofdumps = storage.toftables or 0 + if environment.initex then + return format("%s modules, %s tables, %s chunks, %s bytes stripped (%s chunks)", + nofmodules, + nofdumps, + nofmodules + nofdumps, + utilities.lua.nofstrippedbytes, utilities.lua.nofstrippedchunks + ) + else + return format("%s modules (%0.3f sec), %s tables (%0.3f sec), %s chunks (%0.3f sec)", + nofmodules, tofmodules, + nofdumps, tofdumps, + nofmodules + nofdumps, tofmodules + tofdumps + ) + end end) if lua.bytedata then diff --git a/tex/context/base/lxml-css.lua b/tex/context/base/lxml-css.lua index 112a5e75d..c5a85c2bd 100644 --- a/tex/context/base/lxml-css.lua +++ b/tex/context/base/lxml-css.lua @@ -24,22 +24,49 @@ local cmf = 1/dimenfactors.cm local mmf = 1/dimenfactors.mm local inf = 1/dimenfactors["in"] +local percentage, exheight, emwidth, pixels + +if tex then + + local exheights = fonts.hashes.exheights + local emwidths = fonts.hashes.emwidths + + percentage = function(s,pcf) return tonumber(s) * (pcf or tex.hsize) end + exheight = function(s,exf) return tonumber(s) * (exf or exheights[true]) end + emwidth = function(s,emf) return tonumber(s) * (emf or emwidths[true]) end + pixels = function(s,pxf) return tonumber(s) * (pxf or emwidths[true]/300) end + +else + + local function generic(s,unit) return tonumber(s) * unit end + + percentage = generic + exheight = generic + emwidth = generic + pixels = generic + +end + local validdimen = Cg(lpegpatterns.number,'a') * ( - Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end - + Cb('a') * P("cm") / function(s) return tonumber(s) * cmf end - + Cb('a') * P("mm") / function(s) return tonumber(s) * mmf end - + Cb('a') * P("in") / function(s) return tonumber(s) * inf end - + Cb('a') * P("px") * Carg(1) / function(s,pxf) return tonumber(s) * pxf end - + Cb('a') * P("%") * Carg(2) / function(s,pcf) return tonumber(s) * pcf end - + Cb('a') * P("ex") * Carg(3) / function(s,exf) return tonumber(s) * exf end - + Cb('a') * P("em") * Carg(4) / function(s,emf) return tonumber(s) * emf end - + Cb('a') * Carg(1) / function(s,pxf) return tonumber(s) * pxf end + Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end + + Cb('a') * P("cm") / function(s) return tonumber(s) * cmf end + + Cb('a') * P("mm") / function(s) return tonumber(s) * mmf end + + Cb('a') * P("in") / function(s) return tonumber(s) * inf end + + Cb('a') * P("px") * Carg(1) / pixels + + Cb('a') * P("%") * Carg(2) / percentage + + Cb('a') * P("ex") * Carg(3) / exheight + + Cb('a') * P("em") * Carg(4) / emwidth + + Cb('a') * Carg(1) / pixels ) local pattern = (validdimen * lpegpatterns.whitespace^0)^1 -- todo: default if "" +local function dimension(str,pixel,percent,exheight,emwidth) + return (lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth)) +end + local function padding(str,pixel,percent,exheight,emwidth) local top, bottom, left, right = lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth) if not bottom then @@ -52,7 +79,8 @@ local function padding(str,pixel,percent,exheight,emwidth) return top, bottom, left, right end -css.padding = padding +css.dimension = dimension +css.padding = padding -- local hsize = 655360*100 -- local exheight = 65536*4 diff --git a/tex/context/base/lxml-ctx.mkiv b/tex/context/base/lxml-ctx.mkiv index 530c29aa7..58807339d 100644 --- a/tex/context/base/lxml-ctx.mkiv +++ b/tex/context/base/lxml-ctx.mkiv @@ -20,9 +20,6 @@ \unprotect -% The \let|=letterbar is a messy hack and is needed for the tabulate. We now use -% \detokenize. - \settrue \xmllshowbuffer \setfalse\xmllshowtitle \settrue \xmllshowwarning diff --git a/tex/context/base/lxml-ini.mkiv b/tex/context/base/lxml-ini.mkiv index 84ebc5823..73cd4be7e 100644 --- a/tex/context/base/lxml-ini.mkiv +++ b/tex/context/base/lxml-ini.mkiv @@ -186,7 +186,7 @@ \unexpanded\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} \unexpanded\def\xmlprocessbuffer {\lxml_process\zerocount\xmlloadbuffer} \unexpanded\def\xmlprocessregistered{\lxml_process\zerocount\xmlloadregistered} -\let\xmlprocess \xmlprocessfile + \let\xmlprocess \xmlprocessfile \startxmlsetups xml:flush \xmlflush{#1} @@ -313,7 +313,7 @@ \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone \to \everysetupxml -\unexpanded\def\xmlinitialize +\unexpanded\def\initializexmlprocessing % is this still needed? {\the\everysetupxml} \let\p_lxml_entities\empty diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua index 44dd97155..0c10998a0 100644 --- a/tex/context/base/lxml-lpt.lua +++ b/tex/context/base/lxml-lpt.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['lxml-pth'] = { +if not modules then modules = { } end modules ['lxml-lpt'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -539,14 +539,23 @@ local lp_builtin = P ( -- for the moment we keep namespaces with attributes local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])") -local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end) -local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end) + +-- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end +-- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end + +lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0" +lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))" + local lp_fastpos = lp_fastpos_n + lp_fastpos_p + local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false") -local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling - return t .. "(" -end +-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling +-- return t .. "(" +-- end + +-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0(" +local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0" local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling if expressions[t] then @@ -1197,12 +1206,12 @@ xml.selection = selection -- new method, simple handle -- generic function finalizer (independant namespace) -local function dofunction(collected,fnc) +local function dofunction(collected,fnc,...) if collected then local f = functions[fnc] if f then for c=1,#collected do - f(collected[c]) + f(collected[c],...) end else report_lpath("unknown function '%s'",fnc) @@ -1357,3 +1366,29 @@ function xml.inspect(collection,pattern) report_lpath("pattern %q\n\n%s\n",pattern,xml.tostring(e)) end end + +-- texy (see xfdf): + +local function split(e) + local dt = e.dt + if dt then + for i=1,#dt do + local dti = dt[i] + if type(dti) == "string" then + dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1") + dti = gsub(dti,"[\n\r]+","\n\n") + dt[i] = dti + else + split(dti) + end + end + end + return e +end + +function xml.finalizers.paragraphs(c) + for i=1,#c do + split(c[i]) + end + return c +end diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua index b5c860787..6b23953cc 100644 --- a/tex/context/base/lxml-tab.lua +++ b/tex/context/base/lxml-tab.lua @@ -43,7 +43,7 @@ local utf = unicode.utf8 local concat, remove, insert = table.concat, table.remove, table.insert local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub -local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub +local utfchar = utf.char local lpegmatch = lpeg.match local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs @@ -365,15 +365,7 @@ local privates_n = { -- keeps track of defined ones } -local function escaped(s) - if s == "" then - return "" - else -- if utffind(s,privates_u) then - return (utfgsub(s,".",privates_u)) - -- else - -- return s - end -end +local escaped = utf.remapper(privates_u) local function unescaped(s) local p = privates_n[s] @@ -388,13 +380,7 @@ local function unescaped(s) return p end -local function unprivatized(s,resolve) - if s == "" then - return "" - else - return (utfgsub(s,".",privates_p)) - end -end +local unprivatized = utf.remapper(privates_p) xml.privatetoken = unescaped xml.unprivatized = unprivatized @@ -735,7 +721,12 @@ local function _xmlconvert_(data, settings) else errorhandler = errorhandler or xml.errorhandler if errorhandler then - xml.errorhandler(format("load error: %s",errorstr)) + local currentresource = settings.currentresource + if currentresource and currentresource ~= "" then + xml.errorhandler(format("load error in [%s]: %s",currentresource,errorstr)) + else + xml.errorhandler(format("load error: %s",errorstr)) + end end end else @@ -780,7 +771,7 @@ function xmlconvert(data,settings) if ok then return result else - return _xmlconvert_("") + return _xmlconvert_("",settings) end end @@ -841,7 +832,14 @@ function xml.load(filename,settings) elseif filename then -- filehandle data = filename:read("*all") end - return xmlconvert(data,settings) + if settings then + settings.currentresource = filename + local result = xmlconvert(data,settings) + settings.currentresource = nil + return result + else + return xmlconvert(data,{ currentresource = filename }) + end end --[[ldx-- @@ -907,7 +905,7 @@ function xml.checkbom(root) -- can be made faster return end end - insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } ) + insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } ) insert(dt, 2, "\n" ) end end @@ -1317,7 +1315,7 @@ function xml.tocdata(e,wrapper) -- a few more in the aux module if wrapper then whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper) end - local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e } + local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e } setmetatable(t,getmetatable(e)) e.dt = { t } end diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua index 0b21e0a9c..3f1ec8254 100644 --- a/tex/context/base/lxml-tex.lua +++ b/tex/context/base/lxml-tex.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['lxml-tst'] = { +if not modules then modules = { } end modules ['lxml-tex'] = { version = 1.001, comment = "companion to lxml-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -25,9 +25,10 @@ local lowerchars, upperchars, lettered = characters.lower, characters.upper, cha lxml = lxml or { } local lxml = lxml -local ctxcatcodes, notcatcodes = tex.ctxcatcodes, tex.notcatcodes - -local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing) +local catcodenumbers = catcodes.numbers +local ctxcatcodes = catcodenumbers.ctxcatcodes -- todo: use different method +local notcatcodes = catcodenumbers.notcatcodes -- todo: use different method +local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing) local xmlelements, xmlcollected, xmlsetproperty = xml.elements, xml.collected, xml.setproperty local xmlwithelements = xml.withelements @@ -381,7 +382,10 @@ function xml.load(filename,settings) noffiles, nofconverted = noffiles + 1, nofconverted + 1 starttiming(xml) local ok, data = resolvers.loadbinfile(filename) + settings = settings or { } + settings.currentresource = filename local xmltable = xml.convert((ok and data) or "",settings) + settings.currentresource = nil stoptiming(xml) return xmltable end @@ -390,12 +394,13 @@ local function entityconverter(id,str) return xmlentities[str] or xmlprivatetoken(str) or "" -- roundtrip handler end -function lxml.convert(id,data,entities,compress) +function lxml.convert(id,data,entities,compress,currentresource) local settings = { -- we're now roundtrip anyway unify_predefined_entities = true, utfize_entities = true, resolve_predefined_entities = true, resolve_entities = function(str) return entityconverter(id,str) end, -- needed for mathml + currentresource = tostring(currentresource or id), } if compress and compress == variables.yes then settings.strip_cm_and_dt = true @@ -410,13 +415,13 @@ end function lxml.load(id,filename,compress,entities) filename = commands.preparedfile(filename) -- not commands! if trace_loading then - report_lxml("loading file '%s' as '%s'",filename,id) + report_lxml("loading file %q as %q",filename,id) end noffiles, nofconverted = noffiles + 1, nofconverted + 1 -- local xmltable = xml.load(filename) starttiming(xml) local ok, data = resolvers.loadbinfile(filename) - local xmltable = lxml.convert(id,(ok and data) or "",compress,entities) + local xmltable = lxml.convert(id,(ok and data) or "",compress,entities,format("id: %s, file: %s",id,filename)) stoptiming(xml) lxml.store(id,xmltable,filename) return xmltable, filename @@ -457,14 +462,14 @@ function xml.getbuffer(name,compress,entities) -- we need to make sure that comm end nofconverted = nofconverted + 1 local data = buffers.getcontent(name) - xmltostring(lxml.convert(name,data,compress,entities)) -- one buffer + xmltostring(lxml.convert(name,data,compress,entities,format("buffer: %s",tostring(name or "?")))) -- one buffer end function lxml.loadbuffer(id,name,compress,entities) starttiming(xml) nofconverted = nofconverted + 1 local data = buffers.collectcontent(name or id) -- name can be list - local xmltable = lxml.convert(id,data,compress,entities) + local xmltable = lxml.convert(id,data,compress,entities,format("buffer: %s",tostring(name or id or "?"))) lxml.store(id,xmltable) stoptiming(xml) return xmltable, name or id @@ -473,7 +478,7 @@ end function lxml.loaddata(id,str,compress,entities) starttiming(xml) nofconverted = nofconverted + 1 - local xmltable = lxml.convert(id,str or "",compress,entities) + local xmltable = lxml.convert(id,str or "",compress,entities,format("id: %s",id)) lxml.store(id,xmltable) stoptiming(xml) return xmltable, id diff --git a/tex/context/base/m-barcodes.mkiv b/tex/context/base/m-barcodes.mkiv index 0282f706d..e4c43b376 100644 --- a/tex/context/base/m-barcodes.mkiv +++ b/tex/context/base/m-barcodes.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D You can best use m-zint instead of this one. +\writestatus{barcodes}{the 'zint' module is a better choice} % \startTEXpage % \startPSTRICKS @@ -106,15 +106,13 @@ end } \stopsetups -\def\barcode[#1]% +\unexpanded\def\barcode[#1]% {\bgroup \setvariables[barcode][type=isbn,#1]% \directsetup{barcode:\getvariable{barcode}{type}}% \egroup} -% \usemodule[barcodes] - -\doifnotmode{demo}{\endinput} +\continueifinputfile{m-barcodes.mkiv} \starttext \startTEXpage diff --git a/tex/context/base/m-chart.lua b/tex/context/base/m-chart.lua index 32de8a5ba..a00f246a9 100644 --- a/tex/context/base/m-chart.lua +++ b/tex/context/base/m-chart.lua @@ -15,11 +15,11 @@ moduledata.charts = moduledata.charts or { } local gsub, match, find, format, lower = string.gsub, string.match, string.find, string.format, string.lower local setmetatableindex = table.setmetatableindex +local P, S, C, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.match -local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc -local lpegmatch = lpeg.match +local report_chart = logs.reporter("chart") -local points = number.points +local points = number.points local variables = interfaces.variables @@ -27,7 +27,6 @@ local v_yes = variables.yes local v_no = variables.no local v_none = variables.none local v_standard = variables.standard -local v_start = variables.start local v_overlay = variables.overlay local v_round = variables.round local v_test = variables.test @@ -672,7 +671,7 @@ local function process_texts(chart,xoffset,yoffset) end end -local function getchart(settings) +local function getchart(settings,forced_x,forced_y,forced_nx,forced_ny) if not settings then print("no settings given") return @@ -688,7 +687,7 @@ local function getchart(settings) return end chart = expanded(chart,settings) - local cc_settings = chart.settings.chart + local chartsettings = chart.settings.chart local autofocus = chart.settings.chart.autofocus if autofocus then autofocus = utilities.parsers.settings_to_hash(autofocus) @@ -697,10 +696,10 @@ local function getchart(settings) end end -- check natural window - local x = tonumber(cc_settings.x) - local y = tonumber(cc_settings.y) - local nx = tonumber(cc_settings.nx) - local ny = tonumber(cc_settings.ny) + local x = forced_x or tonumber(chartsettings.x) + local y = forced_y or tonumber(chartsettings.y) + local nx = forced_nx or tonumber(chartsettings.nx) + local ny = forced_ny or tonumber(chartsettings.ny) -- local minx, miny, maxx, maxy = 0, 0, 0, 0 local data = chart.data @@ -715,8 +714,8 @@ local function getchart(settings) if miny == 0 or y > maxy then maxy = y end end end --- print("1>",x,y,nx,ny) --- print("2>",minx, miny, maxx, maxy) + -- print("1>",x,y,nx,ny) + -- print("2>",minx, miny, maxx, maxy) -- check of window should be larger (maybe autofocus + nx/ny?) if autofocus then -- x and y are ignored @@ -762,7 +761,9 @@ local function getchart(settings) end local function makechart(chart) - local settings = chart.settings + local settings = chart.settings + local chartsettings = settings.chart + -- context.begingroup() context.forgetall() -- @@ -770,27 +771,27 @@ local function makechart(chart) context("if unknown context_flow : input mp-char.mpiv ; fi ;") context("flow_begin_chart(0,%s,%s);",chart.nx,chart.ny) -- - if settings.chart.option == v_test or settings.chart.dot == v_yes then + if chartsettings.option == v_test or chartsettings.dot == v_yes then context("flow_show_con_points := true ;") context("flow_show_mid_points := true ;") context("flow_show_all_points := true ;") - elseif settings.chart.dot ~= "" then -- no checking done, private option - context("flow_show_%s_points := true ;",settings.chart.dot) + elseif chartsettings.dot ~= "" then -- no checking done, private option + context("flow_show_%s_points := true ;",chartsettings.dot) end -- - local backgroundcolor = settings.chart.backgroundcolor + local backgroundcolor = chartsettings.backgroundcolor if backgroundcolor and backgroundcolor ~= "" then context("flow_chart_background_color := \\MPcolor{%s} ;",backgroundcolor) end -- - local shapewidth = settings.chart.width - local gridwidth = shapewidth + 2*settings.chart.dx - local shapeheight = settings.chart.height - local gridheight = shapeheight + 2*settings.chart.dy - local chartoffset = settings.chart.offset - local labeloffset = settings.chart.labeloffset - local exitoffset = settings.chart.exitoffset - local commentoffset = settings.chart.commentoffset + local shapewidth = chartsettings.width + local gridwidth = shapewidth + 2*chartsettings.dx + local shapeheight = chartsettings.height + local gridheight = shapeheight + 2*chartsettings.dy + local chartoffset = chartsettings.offset + local labeloffset = chartsettings.labeloffset + local exitoffset = chartsettings.exitoffset + local commentoffset = chartsettings.commentoffset context("flow_grid_width := %s ;", points(gridwidth)) context("flow_grid_height := %s ;", points(gridheight)) context("flow_shape_width := %s ;", points(shapewidth)) @@ -802,8 +803,8 @@ local function makechart(chart) -- local radius = settings.line.radius local rulethickness = settings.line.rulethickness - local dx = settings.chart.dx - local dy = settings.chart.dy + local dx = chartsettings.dx + local dy = chartsettings.dy if radius < rulethickness then radius = 2.5*rulethickness if radius > dx then @@ -818,7 +819,7 @@ local function makechart(chart) context("flow_connection_arrow_size := %s ;", points(radius)) context("flow_connection_dash_size := %s ;", points(radius)) -- - local offset = settings.chart.offset -- todo: pass string + local offset = chartsettings.offset -- todo: pass string if offset == v_none or offset == v_overlay or offset == "" then offset = -2.5 * radius -- or rulethickness? elseif offset == v_standard then @@ -836,42 +837,80 @@ local function makechart(chart) context.endgroup() end +local function splitchart(chart) + local settings = chart.settings + local splitsettings = settings.split + local chartsettings = settings.chart + -- + local name = chartsettings.name + -- + local from_x = chart.from_x + local from_y = chart.from_y + local to_x = chart.to_x + local to_y = chart.to_y + -- + local step_x = splitsettings.nx or to_x + local step_y = splitsettings.ny or to_y + local delta_x = splitsettings.dx or 0 + local delta_y = splitsettings.dy or 0 + -- + report_chart("spliting %q: from (%s,%s) upto (%s,%s) into (%s,%s) with overlap (%s,%s)", + name,from_x,from_y,to_x,to_y,step_x,step_y,delta_x,delta_y) + -- + local part_x = 0 + local first_x = from_x + while true do + part_x = part_x + 1 + local last_x = first_x + step_x - 1 + local done = last_x >= to_x + if done then + last_x = to_x + end + local part_y = 0 + local first_y = from_y + while true do + part_y = part_y + 1 + local last_y = first_y + step_y - 1 + local done = last_y >= to_y + if done then + last_y = to_y + end + -- + report_chart("part (%s,%s) of %q: (%s,%s) -> (%s,%s)",part_x,part_y,name,first_x,first_y,last_x,last_y) + local x, y, nx, ny = first_x, first_y, last_x - first_x + 1,last_y - first_y + 1 + context.beforeFLOWsplit() + context.handleFLOWsplit(function() + makechart(getchart(settings,x,y,nx,ny)) -- we need to pass frozen settings ! + end) + context.afterFLOWsplit() + -- + if done then + break + else + first_y = last_y + 1 - delta_y + end + end + if done then + break + else + first_x = last_x + 1 - delta_x + end + end +end + function commands.flow_make_chart(settings) local chart = getchart(settings) if chart then local settings = chart.settings --- if settings.split.state == v_start then --- local nx = chart.settings.split.nx --- local ny = chart.settings.split.ny --- local x = 1 --- while true do --- local y = 1 --- while true do --- -- FLOTbefore --- -- doif @@FLOTmarking on -> cuthbox --- -- @@FLOTcommand --- chart.from_x = x --- chart.from_y = y --- chart.to_x = math.min(x + nx - 1,chart.nx) --- chart.to_y = math.min(x + ny - 1,chart.ny) --- makechart(chart) --- -- FLOTafter --- y = y + ny --- if y > chart.max_y then --- break --- else --- y = y - dy --- end --- end --- x = x + nx --- if x > chart.max_x then --- break --- else --- x = x - dx --- end --- end --- else + if settings then + local chartsettings = settings.chart + if chartsettings and chartsettings.split == v_yes then + splitchart(chart) + else + makechart(chart) + end + else makechart(chart) --- end + end end end diff --git a/tex/context/base/m-chart.mkii b/tex/context/base/m-chart.mkii index 13403966b..8a5f480ee 100644 --- a/tex/context/base/m-chart.mkii +++ b/tex/context/base/m-chart.mkii @@ -1094,7 +1094,7 @@ \def\FLOWsplitnx{1} \def\FLOWsplitny{1} -\def\FLOWcharts% +\def\FLOWcharts {\dodoubleempty\doFLOWcharts} %D While splitting, the following variables are available: diff --git a/tex/context/base/m-chart.mkvi b/tex/context/base/m-chart.mkvi index e94adeba2..cb6a1e8c8 100644 --- a/tex/context/base/m-chart.mkvi +++ b/tex/context/base/m-chart.mkvi @@ -30,19 +30,33 @@ % todo: figure out a nice way to define the lot: share current and % support current as name (nb: we need to set parent then) -\def\??flch{@@flch} % chart -\def\??flln{@@flln} % line -\def\??flsh{@@flsh} % shape -\def\??flfc{@@flfc} % focus -\def\??flst{@@flst} % sets -\def\??flsp{@@flsp} % split - -\installsimplecommandhandler \??flch {FLOWchart} \??flch -\installsimplecommandhandler \??flln {FLOWline} \??flln -\installsimplecommandhandler \??flsh {FLOWshape} \??flsh -\installsimplecommandhandler \??flfc {FLOWfocus} \??flfc -\installsimplecommandhandler \??flst {FLOWsets} \??flst -\installsimplecommandhandler \??flsp {FLOWsplit} \??flsp +% \def\??flch{@@flch} % chart +% \def\??flln{@@flln} % line +% \def\??flsh{@@flsh} % shape +% \def\??flfc{@@flfc} % focus +% \def\??flst{@@flst} % sets +% \def\??flsp{@@flsp} % split + +% \installsimplecommandhandler \??flch {FLOWchart} \??flch +% \installsimplecommandhandler \??flln {FLOWline} \??flln +% \installsimplecommandhandler \??flsh {FLOWshape} \??flsh +% \installsimplecommandhandler \??flfc {FLOWfocus} \??flfc +% \installsimplecommandhandler \??flst {FLOWsets} \??flst +% \installsimplecommandhandler \??flsp {FLOWsplit} \??flsp + +\installcorenamespace {flowchart} % \def\??flch{@@flch} % chart +\installcorenamespace {flowline} % \def\??flln{@@flln} % line +\installcorenamespace {flowshape} % \def\??flsh{@@flsh} % shape +\installcorenamespace {flowfocus} % \def\??flfc{@@flfc} % focus +\installcorenamespace {flowsets} % \def\??flst{@@flst} % sets +\installcorenamespace {flowsplit} % \def\??flsp{@@flsp} % split + +\installsimplecommandhandler \??flowchart {FLOWchart} \??flowchart % maybe just a setuphandler +\installsimplecommandhandler \??flowline {FLOWline} \??flowline % maybe just a setuphandler +\installsimplecommandhandler \??flowshape {FLOWshape} \??flowshape % maybe just a setuphandler +\installsimplecommandhandler \??flowfocus {FLOWfocus} \??flowfocus % maybe just a setuphandler +\installsimplecommandhandler \??flowsets {FLOWsets} \??flowsets % maybe just a setuphandler +\installsimplecommandhandler \??flowsplit {FLOWsplit} \??flowsplit % maybe just a setuphandler \let\setupFLOWcharts\setupFLOWchart \let\setupFLOWlines \setupFLOWline @@ -62,6 +76,7 @@ \c!labeloffset=.5\bodyfontsize, \c!commentoffset=.5\bodyfontsize, \c!exitoffset=\zeropoint, + % \c!split=\v!no, % \c!maxwidth=, % \c!maxheight=, % \c!option=, @@ -101,13 +116,17 @@ \c!offset=\FLOWshapeparameter\c!offset] \setupFLOWsplit - [\c!state=\v!stop, - \c!marking=\v!on, + [\c!dx=0, + \c!dy=0, % \c!command=, % \c!before=, % \c!after=, \c!nx=3, - \c!ny=3] + \c!ny=4] + +\unexpanded\def\beforeFLOWsplit{\FLOWsplitparameter\c!before} +\unexpanded\def\afterFLOWsplit {\FLOWsplitparameter\c!after} +\unexpanded\def\handleFLOWsplit{\FLOWsplitparameter\c!command} \definecolor [FLOWfocuscolor] [s=.2] \definecolor [FLOWlinecolor] [s=.5] @@ -184,7 +203,7 @@ {\dodoubleempty\module_charts_process} \def\module_charts_process[#name][#settings]% - {\vbox\bgroup + {\bgroup % \vbox removed \insidefloattrue \dontcomplain \setupFLOWchart[#settings]% @@ -212,6 +231,7 @@ labeloffset = \number\dimexpr\FLOWchartparameter\c!labeloffset, commentoffset = \number\dimexpr\FLOWchartparameter\c!commentoffset, exitoffset = \number\dimexpr\FLOWchartparameter\c!exitoffset, + split = "\FLOWchartparameter\c!split", }, shape = { rulethickness = \number\dimexpr\FLOWshapeparameter\c!rulethickness, @@ -236,9 +256,10 @@ set = { }, split = { - state = "\FLOWsplitparameter\c!state", nx = \number\FLOWsplitparameter\c!nx, ny = \number\FLOWsplitparameter\c!ny, + dx = \number\FLOWsplitparameter\c!dx, + dy = \number\FLOWsplitparameter\c!dy, command = "", marking = "\FLOWsplitparameter\c!marking", before = "", @@ -314,11 +335,14 @@ align=, set=\setups{flowcell:text:place}] +\def\FLOWx{\getvariable{flowcell:text}{x}} % compatibility (for Willi) +\def\FLOWy{\getvariable{flowcell:text}{y}} % compatibility (for Willi) + % \c!background={\@@FLOWbackground,\FLOWoverlay}, \defineoverlay - [flowcell:figure] - [\overlayfigure{\getvariable{flowcell:text}{figure}}] + [flowcell:figure] + [\overlayfigure{\getvariable{flowcell:text}{figure}}] \startsetups flowcell:text:place \begingroup @@ -387,35 +411,73 @@ \defineframed[flowcell:mb][flowcell:base][\c!bottom=,\c!align=\v!middle] \defineframed[flowcell:cb][flowcell:base][\c!bottom=,\c!align=\v!middle] -% todo: each cell its own setup +% \startsetups flowcell:text:user +% \setupframed +% [flowcell:base] +% [background=flowcell] +% \definelayer +% [flowcell] +% [width=\namedframedparameter{flowcell:base}{width}, +% height=\namedframedparameter{flowcell:base}{height}] +% \setlayerframed +% [flowcell] +% [preset=rightbottom,offset=-2.75ex] +% [frame=off] +% {\tx\FLOWx.\FLOWy} +% \stopsetups +% +% % or: % -% \startsetups flowcell -% \definelayer -% [flowcell] -% [width=\FLOWshapewidth, -% height=\FLOWshapeheight] -% \setlayerframed -% [flowcell] -% [preset=rightbottom,offset=1ex] -% [frame=off] -% {\tx(\FLOWx,\FLOWy)} +% \setupframed +% [flowcell:base] +% [background={flowcell-1,flowcell-2}] +% +% \defineoverlay +% [flowcell-1] +% [\directsetup{flowcell-1}] +% +% \definelayer +% [flowcell-2] +% [width=\overlaywidth, +% height=\overlayheight] +% +% \startsetups flowcell-1 +% \setlayerframed +% [flowcell-2] +% [preset=rightbottom,offset=-2.75ex] +% [frame=off] +% {\tx\FLOWx.\FLOWy} % \stopsetups -%D \starttyping -%D \setupFLOWsplit -%D [nx=5,ny=10, -%D dx=0,dy=0, -%D before=, -%D after=\page] -%D -%D \FLOWcharts[mybigflow] -%D \stoptyping -%D -%D \starttyping -%D \splitfloat -%D {\placefigure{What a big flowchart this is!}} -%D {\FLOWcharts[mybigflow]} -%D \stoptyping +% %D \starttyping +% %D \setupFLOWsplit +% %D [nx=5,ny=10, +% %D dx=0,dy=0, +% %D before=, +% %D after=\page] +% %D +% %D \FLOWcharts[mybigflow] +% %D \stoptyping +% %D +% %D \starttyping +% %D \splitfloat +% %D {\placefigure{What a big flowchart this is!}} +% %D {\FLOWcharts[mybigflow]} +% %D \stoptyping + +% \setupFLOWsplit +% [nx=5, +% ny=8, +% dx=1, +% dy=1, +% command=\framed, +% before=\page, +% after=\page] +% +% \FLOWchart[demo] \page +% \FLOWchart[demo][split=yes] \page +% \FLOWchart[demo][x=1,y=1,nx=5,ny=8] \page +% \FLOWchart[demo][x=1,y=9,nx=5,ny=10] \page \protect diff --git a/tex/context/base/m-database.mkiv b/tex/context/base/m-database.mkiv index cef0aa815..01f84482a 100644 --- a/tex/context/base/m-database.mkiv +++ b/tex/context/base/m-database.mkiv @@ -17,11 +17,6 @@ \unprotect -\def\c!first {first} -\def\c!last {last} -\def\c!quotechar {quotechar} -\def\c!commentchar {commentchar} - \definenamespace [db] [type=module, @@ -98,7 +93,7 @@ \protect -\doifnotmode{demo}{\endinput} +\continueifinputfile{m-database.mkiv} \starttext diff --git a/tex/context/base/m-graph.mkiv b/tex/context/base/m-graph.mkiv index db72927fb..8acbe1f8d 100644 --- a/tex/context/base/m-graph.mkiv +++ b/tex/context/base/m-graph.mkiv @@ -16,100 +16,76 @@ % the percent symbol. We also add a specifier when no one is given. \startluacode - local function strip(s) - return "\\times10^{"..(s:gsub("%+*0*","")).."}" + local format, gsub, find, match = string.format, string.gsub, string.find, string.match + + local simplify = true + + local function strip(n,e) + -- get rid of e(0) + -- get rid of e(+*) + e = gsub(e,"^+","") + -- remove leading zeros + e = gsub(e,"^([+-]*)0+(%d)","%1%2") + if not simplify then + -- take it as it is + elseif n == "1" then + return format("10^{%s}",e) + end + return format("%s\\times10^{%s}",n,e) end + function metapost.format_n(fmt,str) - fmt = fmt:gsub("@","%%") - local initial, format, final = fmt:match("^(.-)(%%.-[%a])(.-)$") - if format then - str = fmt:format(str) - str = str:gsub("e(.-)$",strip) - str = ("%s\\mathematics{%s}%s"):format(initial,str,final) - elseif not fmt:find("%%") then - str = ("%"..fmt):format(str) - str = str:gsub("e(.-)$",strip) - str = ("\\mathematics{%s}"):format(str) + fmt = gsub(fmt,"@","%%") + local initial, hasformat, final = match(fmt,"^(.-)(%%.-[%a])(.-)$") + if hasformat then + str = format(fmt,str) + str = gsub(str,"(.-)e(.-)$",strip) + str = format("%s\\mathematics{%s}%s",initial,str,final) + elseif not find(fmt,"%%") then + str = format("%"..fmt,str) + str = gsub(str,"(.-)e(.-)$",strip) + str = format("\\mathematics{%s}",str) end context(str) end \stopluacode -\unexpanded\long\def\MPgraphformat#1#2{\ctxlua{metapost.format_n("#1","#2")}} +\unexpanded\def\MPgraphformat#1#2{\ctxlua{metapost.format_n("#1","#2")}} % We could also delegate parsing using lower level plugins. -\startMPinclusions - % input string ; - % input marith ; - input graph.mp ; - - vardef roundd(expr x, d) = - if abs d > 4 : - if d > 0 : - x - else : - 0 - fi - elseif d > 0 : - save i ; i = floor x ; - i + round(Ten_to[d]*(x-i))/Ten_to[d] - else : - round(x/Ten_to[-d])*Ten_to[-d] - fi - enddef ; - - Ten_to0 = 1 ; - Ten_to1 = 10 ; - Ten_to2 = 100 ; - Ten_to3 = 1000 ; - Ten_to4 = 10000 ; - - def sFe_base = - enddef ; - - picture Fe_plus ; Fe_plus := btex + etex ; - - vardef format (expr f,x) = dofmt_.Feform_(f,x) enddef ; - vardef Mformat (expr f,x) = dofmt_.Meform (f,x) enddef ; - vardef formatstr (expr f,x) = dofmt_.Feform_(f,x) enddef ; - vardef Mformatstr(expr f,x) = dofmt_.Meform(f,x) enddef ; - - vardef escaped_format(expr s) = - "" for n=1 upto length(s) : & - if ASCII substring (n,n+1) of s = 37 : - "@" - else : - substring (n,n+1) of s - fi - endfor - enddef ; - - vardef dofmt_@\#(expr f, x) = - textext("\MPgraphformat{" & escaped_format(f) & "}{" & (if string x : x else: decimal x fi) & "}") - enddef ; - - % vardef format(expr f, x) = - % textext("\MPgraphformatN{"&escaped_format(f)&"}{"&(if string x : x else: decimal x fi)&"}") - % enddef; - % vardef Mformat(expr f, x) = - % format(f,x) - % enddef; - -\stopMPinclusions +\startMPextensions + if unknown Fe_plus : picture Fe_plus ; Fe_plus := textext("+") ; fi ; + if unknown context_grap: input "mp-grap.mpiv" ; fi ; +\stopMPextensions \continueifinputfile{m-graph.mkiv} \starttext \startMPpage -draw begingraph(3in,2in); - gdraw "t:/metapost/grphdata/agepop91.d"; -endgraph; + label(format("@g","1e-8"), (0, 0)) ; + label(format("@g","1e+8"), (2cm, 0)) ; + label(format("@g","1e-10"), (0, -0.5cm)) ; + label(format("@g","1e+10"), (2cm,-0.5cm)) ; + label(format("@g","1e-12"), (0, -1.0cm)) ; + label(format("@g","1e+12"), (2cm,-1.0cm)) ; + label(format("@g","1e-0"), (0, -1.5cm)) ; + label(format("@g","1e+0"), (2cm,-1.5cm)) ; + label(format("@g","1"), (0, -2.0cm)) ; + label(format("@g","1"), (2cm,-2.0cm)) ; + label(format("@g","1e-102"),(0, -2.5cm)) ; + label(format("@g","1e+102"),(2cm,-2.5cm)) ; \stopMPpage % \startMPpage % draw begingraph(3in,2in); +% gdraw "t:/metapost/grphdata/agepop91.d"; +% endgraph; +% \stopMPpage + +% \startMPpage +% draw begingraph(3in,2in); % gdraw "agepop91.d" plot btex $\bullet$ etex; % endgraph; % \stopMPpage diff --git a/tex/context/base/m-ipsum.mkiv b/tex/context/base/m-ipsum.mkiv new file mode 100644 index 000000000..1c5901d86 --- /dev/null +++ b/tex/context/base/m-ipsum.mkiv @@ -0,0 +1,198 @@ +%D \module +%D [ file=m-ipsum, +%D version=2012.07.19, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=Ipsum, +%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 After some discussing on the mailing list I made this example of +%D an implementation. Of course there can be alternatives as it's a +%D nice exercise in module writing. + +\startluacode + +local patterns = lpeg.patterns + +local variables = interfaces.variables +local v_random = variables.random + +local lowercase = characters.lower + +local ipsum = { } +moduledata.ipsum = ipsum + +local data = { } + +local function getfiledata(settings) + local filename = settings.filename or "" + local filedata = data[filename] + if not filedata then + local text = resolvers.loadtexfile(filename) or "" + local paragraphs = lpeg.match(patterns.paragraphs,text) or { } + local sentences = lpeg.match(patterns.sentences, text) or { } + local words = lpeg.match(patterns.words, text) or { } + for i=1,#words do + words[i] = lowercase(words[i]) + end + filedata = { + -- [variables.paragraphs] = paragraphs, + [variables.paragraph] = paragraphs, + [variables.lines] = sentences, + [variables.line] = sentences, + [variables.words] = words, + [variables.word] = words, + } + -- inspect(filedata) + data[filename] = filedata + end + local d = filedata[settings.alternative or v_paragraph] or filedata[v_paragraph] or { } + local nd = #d + local n = settings.n + if n ~= v_random then + n = tonumber(n) or 0 + if n == 0 then + n = nd + end + end + return d, n, nd +end + +function moduledata.ipsum.typeset(settings) + local d, n, nd = getfiledata(settings) + if nd > 0 then + context(settings.before) + if n == v_random then + context(settings.left) + context(d[math.random(1,nd)]) + context(settings.right) + else + for i=1,n do + context(settings.left) + context(d[i]) + context(settings.right) + if i < n then + context(settings.inbetween) + end + end + end + context(settings.after) + end +end + +function moduledata.ipsum.direct(settings) + local d, n, nd = getfiledata(settings) + if nd == 0 then + -- nothing + elseif n == v_random then + context(d[math.random(1,nd)]) + else + for i=1,n do + context(d[i]) + if i < n then + context(settings.separator) + end + end + end +end + +\stopluacode + +\unprotect + +\installnamespace {ipsum} + +\installcommandhandler \????ipsum {ipsum} \????ipsum + +\setupipsum + [\c!file=lorem, + \c!alternative=\v!paragraph, + %\c!language=, + %\c!styl=, + %\c!color=, + \c!n=0, + \c!left=, + \c!right=, + \c!before=, + \c!after=, + \c!separator=, + \c!inbetween=] + +\installactionhandler{ipsum} % grouped + +\startsetups[handler:action:ipsum] + \useipsumstyleandcolor\c!style\c!color + \uselanguageparameter\ipsumparameter + \ctxlua{moduledata.ipsum.typeset { + alternative = "\ipsumparameter\c!alternative", + filename = "\ipsumparameter\c!file", + n = "\ipsumparameter\c!n", + left = "\luaescapestring{\ipsumparameter\c!left}", + right = "\luaescapestring{\ipsumparameter\c!right}", + before = "\luaescapestring{\ipsumparameter\c!before}", + after = "\luaescapestring{\ipsumparameter\c!after}", + inbetween = "\luaescapestring{\ipsumparameter\c!inbetween}", + }} +\stopsetups + +\def\directipsum#1% only one argument, expanded + {\ctxlua{moduledata.ipsum.typeset { + alternative = "\namedipsumparameter{#1}\c!alternative", + filename = "\namedipsumparameter{#1}\c!file", + n = "\namedipsumparameter{#1}\c!n", + separator = "\luaescapestring{\ipsumparameter\c!separator}", + }} +} + +\protect + +\continueifinputfile{m-ipsum.mkiv} + +\setupbodyfont[dejavu,11pt] + +\starttext + + \ipsum[alternative=paragraph,before=\blank,after=\blank,language=la] + + \ipsum[alternative=lines,n=2,right=\par,before=\blank,after=\blank,language=la] + + \ipsum[alternative=lines,n=random,before=\blank,after=\blank,language=la] + + \ipsum[alternative=lines,before=\startitemize,after=\stopitemize,left=\startitem,right=\stopitem,language=la] + + \ipsum[alternative=words,left=(,right=),inbetween=\space,language=la] + + \page + + \defineipsum + [ward] + [file=ward, + before=\blank, + after=\blank] + + \defineipsum + [ward:itemize] + [ward] + [alternative=lines, + before={\startitemize[packed]}, + after=\stopitemize, + left=\startitem, + right=\stopitem] + + \defineipsum + [ward:title] + [ward] + [alternative=lines, + n=random] + + \subject{\directipsum{ward:title}} + + \ipsum[ward] + \ipsum[ward:itemize] + +\stoptext diff --git a/tex/context/base/m-json.mkiv b/tex/context/base/m-json.mkiv new file mode 100644 index 000000000..329aa0f31 --- /dev/null +++ b/tex/context/base/m-json.mkiv @@ -0,0 +1,30 @@ +%D \module +%D [ file=m-json, +%D version=2012.08.03, +%D title=\CONTEXT\ Modules, +%D subtitle=Json, +%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 side effect of looking into json. Currently there are +%D only a few helpers: +%D +%D \starttyping +%D moduledata.json.tolua (str) +%D moduledata.json.tostring(val) +%D \stoptyping +%D +%D Nothing spectacular but maybe handy to have around. + +\startmodule [json] + +% check for: utilities.json + +\registerctxluafile{util-jsn}{} + +\stopmodule diff --git a/tex/context/base/m-morse.mkvi b/tex/context/base/m-morse.mkvi index aba83bb2d..6082d588a 100644 --- a/tex/context/base/m-morse.mkvi +++ b/tex/context/base/m-morse.mkvi @@ -228,16 +228,16 @@ end \def\MorseSpace {\hskip7\dimexpr\MorseWidth\relax} \def\MorseUnknown #text{[\detokenize{#text}]} -\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}} -\def\MorseString #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}} -\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}} -\def\MorseTable {\ctxlua{moduledata.morse.showtable()}} +\unexpanded\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}} +\unexpanded\def\MorseString#text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}} +\unexpanded\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}} +\unexpanded\def\MorseTable {\ctxlua{moduledata.morse.showtable()}} -\let\Morse \MorseString +\let\Morse \MorseString \protect -\doifnotmode{demo}{\endinput} +\continueifinputfile{m-morse.mkiv} \starttext diff --git a/tex/context/base/supp-fun.mkiv b/tex/context/base/m-oldfun.mkiv index 33bee0306..1c5a1d29d 100644 --- a/tex/context/base/supp-fun.mkiv +++ b/tex/context/base/m-oldfun.mkiv @@ -1,5 +1,5 @@ %D \module -%D [ file=supp-fun, +%D [ file=m-oldfun, % was: supp-fun %D version=1995.10.10, %D title=\CONTEXT\ Support Macros, %D subtitle=Fun Stuff, @@ -119,7 +119,7 @@ \let\globaldropcaps\global % will be an option, but on by default -\def\localdropcaps{\let\globaldropcaps\relax} +\unexpanded\def\localdropcaps{\let\globaldropcaps\relax} \chardef\DroppedStatus = 0 % 0=done 1=starting 2=doing 3=error \chardef\DropMode = 0 % 1 == marginhang @@ -128,7 +128,7 @@ \let\keeplinestogether\gobbleoneargument \fi -\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars +\unexpanded\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars {\defconvertedargument\asciia{#7}% \defconvertedcommand \asciib{\DroppedString}% \doifinstringelse\asciia\asciib @@ -222,10 +222,10 @@ \newcount\lastprevgraf \newcount\droppedlines -\def\CheckDroppedCaps +\unexpanded\def\CheckDroppedCaps {\global\lastprevgraf\prevgraf} -\def\AutoDroppedCaps % will be proper core stuff since it +\unexpanded\def\AutoDroppedCaps % will be proper core stuff since it {\globaldropcaps\chardef\DroppedStatus\plusone \global\lastprevgraf\zerocount \global\droppedlines\zerocount @@ -234,10 +234,10 @@ \let\AutoDroppedNext\relax \ifx\AutoDroppedCapsCommand\undefined - \def\AutoDroppedCapsCommand{\NiceDroppedCaps{}{SerifBold}{.125em}{3}} + \unexpanded\def\AutoDroppedCapsCommand{\NiceDroppedCaps{}{SerifBold}{.125em}{3}} \fi -\def\doAutoDroppedCaps +\unexpanded\def\doAutoDroppedCaps {\ifcase\DroppedStatus % done \let\next\relax \or % starting @@ -287,7 +287,7 @@ %D the second command scales the font to a nice 2.5 times the %D line height, a value that gives a pleasant grayness. -\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines +\unexpanded\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines {\scratchcounter#5% \advance\scratchcounter \minusone \scratchdimen\scratchcounter\baselineskip @@ -296,10 +296,10 @@ \DroppedCaps{#2}{#3}\TheNormalizedFontSize{#4} {\scratchcounter\baselineskip}{#5}} -\def\LineDroppedCaps% command font offset lines +\unexpanded\def\LineDroppedCaps% command font offset lines {\DoLineDroppedCaps{\strutht}} -\def\NiceDroppedCaps% command font offset lines +\unexpanded\def\NiceDroppedCaps% command font offset lines {\DoLineDroppedCaps{.5\baselineskip}} %D \macros @@ -337,7 +337,7 @@ %D with that. A workaround is rather trivial but obscures the %D principles used. -\def\TreatFirstLine#1#2#3#4% before, after, first, next +\unexpanded\def\TreatFirstLine#1#2#3#4% before, after, first, next {\leavevmode \bgroup \forgetall @@ -428,7 +428,7 @@ %D \getbuffer complete we also offer a very simple one %D character alternative, that is not that hard to understand: -\def\TreatFirstCharacter#1#2% command, character +\unexpanded\def\TreatFirstCharacter#1#2% command, character {{#1{#2}}} %D A previous paragraph started with: @@ -440,7 +440,7 @@ %D %D The next hack deals with vertical stacking. -\def\StackCharacters#1#2#3#4% sequence vsize vskip command +\unexpanded\def\StackCharacters#1#2#3#4% sequence vsize vskip command {\vbox #2 {\forgetall \baselineskip\zeropoint @@ -531,10 +531,10 @@ %D %D These are implemented using an auxilliary macro: -\def\NormalizeFontHeight{\NormalizeFontSize\ht} -\def\NormalizeFontWidth {\NormalizeFontSize\wd} +\unexpanded\def\NormalizeFontHeight{\NormalizeFontSize\ht} +\unexpanded\def\NormalizeFontWidth {\NormalizeFontSize\wd} -\def\NormalizeFontSize#1#2#3#4#5% +\unexpanded\def\NormalizeFontSize#1#2#3#4#5% {\bgroup \dimen0=#4% #4 can be \ht0 or so \setbox0\hbox{\definedfont[#5 at 5pt]#3}% 10pt @@ -557,7 +557,7 @@ %D Extra: -\def\WidthSpanningText#1#2#3% text width font +\unexpanded\def\WidthSpanningText#1#2#3% text width font {\hbox{\NormalizeFontWidth\temp{#1}{#2}{#3}\temp\the\everydefinedfont#1}} %D Consider for instance: @@ -642,7 +642,7 @@ % #1 width #2 height #3 font #4 size #5 step #6 interlinie #7 text -\long\def\FittingText#1#2#3#4#5#6#7% +\unexpanded\def\FittingText#1#2#3#4#5#6#7% {\bgroup \forgetall \dontcomplain @@ -681,11 +681,9 @@ \unvbox\scratchbox \egroup} -%D New: - % \font width gap font spec text -\def\NormalizeFontWidthSpread#1#2#3#4#5#6% +\unexpanded\def\NormalizeFontWidthSpread#1#2#3#4#5#6% {\global\setfalse\NFSpread \scratchdimen#3% \scratchdimen-.5\scratchdimen @@ -704,10 +702,10 @@ \definefont[\strippedcsname#1][#4 #5]% \fi} -\def\SpreadGapText#1#2% +\unexpanded\def\SpreadGapText#1#2% {{\def\+{\kern#1}#2}} -\def\GapText#1#2#3#4#5% width distance font spec title +\unexpanded\def\GapText#1#2#3#4#5% width distance font spec title {\bgroup \NormalizeFontWidthSpread\DummyFont{#1}{#2}{#3}{#4}{#5}% \DummyFont\setupspacing\SpreadGapText{#2}{#5}\endgraf diff --git a/tex/context/base/supp-num.mkiv b/tex/context/base/m-oldnum.mkiv index be0df026d..efc0af472 100644 --- a/tex/context/base/supp-num.mkiv +++ b/tex/context/base/m-oldnum.mkiv @@ -1,5 +1,5 @@ %D \module -%D [ file=supp-num, +%D [ file=m-oldnum, % was: supp-num %D version=1998.05.15, %D title=\CONTEXT\ Support Macros, %D subtitle=Numbers, diff --git a/tex/context/base/m-pstricks.lua b/tex/context/base/m-pstricks.lua index 7f795feac..b151e313a 100644 --- a/tex/context/base/m-pstricks.lua +++ b/tex/context/base/m-pstricks.lua @@ -39,12 +39,12 @@ local template = [[ \stoptext ]] -local modules = { } +local loaded = { } local graphics = 0 function moduledata.pstricks.usemodule(names) for name in gmatch(names,"([^%s,]+)") do - modules[#modules+1] = format([[\readfile{%s}{}{}]],name) + loaded[#loaded+1] = format([[\readfile{%s}{}{}]],name) end end @@ -55,10 +55,10 @@ function moduledata.pstricks.process(n) local tmpfile = name .. ".tmp" local epsfile = name .. ".ps" local pdffile = name .. ".pdf" - local modules = concat(modules,"\n") + local loaded = concat(loaded,"\n") os.remove(epsfile) os.remove(pdffile) - io.savedata(tmpfile,format(template,modules,data)) + io.savedata(tmpfile,format(template,loaded,data)) os.execute(format("mtxrun --script texexec %s --once --dvips",tmpfile)) if lfs.isfile(epsfile) then os.execute(format("ps2pdf %s %s",epsfile,pdffile)) diff --git a/tex/context/base/m-spreadsheet.lua b/tex/context/base/m-spreadsheet.lua new file mode 100644 index 000000000..30980684f --- /dev/null +++ b/tex/context/base/m-spreadsheet.lua @@ -0,0 +1,331 @@ +if not modules then modules = { } end modules ['m-spreadsheet'] = { + version = 1.001, + comment = "companion to m-spreadsheet.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local byte, format, gsub, find = string.byte, string.format, string.gsub, string.find +local R, P, S, C, V, Cs, Cc, Ct, Cg, Cf, Carg = lpeg.R, lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Carg +local lpegmatch, patterns = lpeg.match, lpeg.patterns +local setmetatable, loadstring, next, tostring, tonumber,rawget = setmetatable, loadstring, next, tostring, tonumber, rawget + +local context = context + +local splitthousands = utilities.parsers.splitthousands +local variables = interfaces.variables + +local v_yes = variables.yes + +moduledata = moduledata or { } + +local spreadsheets = { } +moduledata.spreadsheets = spreadsheets + +local data = { + -- nothing yet +} + +local settings = { + period = ".", + comma = ",", +} + +spreadsheets.data = data +spreadsheets.settings = settings + +local defaultname = "default" +local stack = { } +local current = defaultname + +local d_mt ; d_mt = { + __index = function(t,k) + local v = { } + setmetatable(v,d_mt) + t[k] = v + return v + end, +} + +local s_mt ; s_mt = { + __index = function(t,k) + local v = settings[k] + t[k] = v + return v + end, +} + +function spreadsheets.setup(t) + for k, v in next, t do + settings[k] = v + end +end + +local function emptydata(name,settings) + local data = { } + local specifications = { } + local settings = settings or { } + setmetatable(data,d_mt) + setmetatable(specifications,d_mt) + setmetatable(settings,s_mt) + return { + name = name, + data = data, + maxcol = 0, + maxrow = 0, + settings = settings, + temp = { }, -- for local usage + specifications = specifications, + } +end + +function spreadsheets.reset(name) + if not name or name == "" then name = defaultname end + data[name] = emptydata(name,data[name] and data[name].settings) +end + +function spreadsheets.start(name,s) + if not name or name == "" then + name = defaultname + end + if not s then + s = { } + end + table.insert(stack,current) + current = name + if data[current] then + setmetatable(s,s_mt) + data[current].settings = s + else + data[current] = emptydata(name,s) + end +end + +function spreadsheets.stop() + current = table.remove(stack) +end + +spreadsheets.reset() + +local offset = byte("A") - 1 + +local function assign(s,n) + return format("moduledata.spreadsheets.data['%s'].data[%s]",n,byte(s)-offset) +end + +function datacell(a,b,...) + local n = 0 + if b then + local t = { a, b, ... } + for i=1,#t do + n = n * (i-1) * 26 + byte(t[i]) - offset + end + else + n = byte(a) - offset + end + return format("dat[%s]",n) +end + +local function checktemplate(s) + if find(s,"%%") then + -- normal template + return s + elseif find(s,"@") then + -- tex specific template + return gsub(s,"@","%%") + else + -- tex specific quick template + return "%" .. s + end +end + +local quoted = Cs(patterns.unquoted) +local spaces = patterns.whitespace^0 +local cell = C(R("AZ"))^1 / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1)) + +-- A nasty aspect of lpeg: Cf ( spaces * Cc("") * { "start" ... this will create a table that will +-- be reused, so we accumulate! + +local pattern = Cf ( spaces * Ct("") * { "start", + start = V("value") + V("set") + V("format") + V("string") + V("code"), + value = Cg(P([[=]]) * spaces * Cc("kind") * Cc("value")) * V("code"), + set = Cg(P([[!]]) * spaces * Cc("kind") * Cc("set")) * V("code"), + format = Cg(P([[@]]) * spaces * Cc("kind") * Cc("format")) * spaces * Cg(Cc("template") * Cs(quoted/checktemplate)) * V("code"), + string = Cg(#S([["']]) * Cc("kind") * Cc("string")) * Cg(Cc("content") * quoted), + code = spaces * Cg(Cc("code") * Cs((cell + P(1))^0)), +}, rawset) + +local functions = { } +spreadsheets.functions = functions + +function functions._s_(row,col,c,f,t) + local r = 0 + if f and t then -- f..t + -- ok + elseif f then -- 1..f + f, t = 1, f + else + f, t = 1, row - 1 + end + for i=f,t do + local ci = c[i] + if type(ci) == "number" then + r = r + c[i] + end + end + return r +end + +functions.fmt= string.tformat + +local template = [[ + local _m_ = moduledata.spreadsheets + local dat = _m_.data['%s'].data + local tmp = _m_.temp + local fnc = _m_.functions + local row = %s + local col = %s + function fnc.sum(...) return fnc._s_(row,col,...) end + local sum = fnc.sum + local fmt = fnc.fmt + return %s +]] + +-- to be considered: a weak cache + +local function propername(name) + if name ~= "" then + return name + elseif current ~= "" then + return current + else + return defaultname + end +end + +-- if name == "" then name = current if name == "" then name = defaultname end end + +local function execute(name,r,c,str) + if str ~= "" then + local d = data[name] + if c > d.maxcol then + d.maxcol = c + end + if r > d.maxrow then + d.maxrow = r + end + local specification = lpegmatch(pattern,str,1,name) + d.specifications[c][r] = specification + local kind = specification.kind + if kind == "string" then + return specification.content or "" + else + local code = specification.code + if code and code ~= "" then + code = format(template,name,r,c,code or "") + local result = loadstring(code) -- utilities.lua.strippedloadstring(code,true) -- when tracing + result = result and result() + if type(result) == "function" then + result = result() + end + if type(result) == "number" then + d.data[c][r] = result + end + if not result then + -- nothing + elseif kind == "set" then + -- no return + elseif kind == "format" then + return format(specification.template,result) + else + return result + end + end + end + end +end + +function spreadsheets.set(name,r,c,str) + name = propername(name) + execute(name,r,c,str) +end + +function spreadsheets.get(name,r,c,str) + name = propername(name) + local dname = data[name] + if not dname then + -- nothing + elseif not str or str == "" then + context(dname.data[c][r] or 0) + else + local result = execute(name,r,c,str) + if result then +-- if type(result) == "number" then +-- dname.data[c][r] = result +-- result = tostring(result) +-- end + local settings = dname.settings + local split = settings.split + local period = settings.period + local comma = settings.comma + if split == v_yes then + result = splitthousands(result) + end + if period == "" then period = nil end + if comma == "" then comma = nil end + result = gsub(result,".",{ ["."] = period, [","] = comma }) + context(result) + end + end +end + +function spreadsheets.doifelsecell(name,r,c) + name = propername(name) + local d = data[name] + local d = d and d.data + local r = d and rawget(d,r) + local c = r and rawget(r,c) + commands.doifelse(c) +end + +local function simplify(name) + name = propername(name) + local data = data[name] + if data then + data = data.data + local temp = { } + for k, v in next, data do + local t = { } + temp[k] = t + for kk, vv in next, v do + if type(vv) == "function" then + t[kk] = "<function>" + else + t[kk] = vv + end + end + end + return temp + end +end + +local function serialize(name) + local s = simplify(name) + if s then + return table.serialize(s,name) + else + return format("<unknown spreadsheet %q>",name) + end +end + +spreadsheets.simplify = simplify +spreadsheets.serialize = serialize + +function spreadsheets.inspect(name) + inspect(serialize(name)) +end + +function spreadsheets.tocontext(name) + context.tocontext(simplify(name)) +end diff --git a/tex/context/base/m-spreadsheet.mkiv b/tex/context/base/m-spreadsheet.mkiv index 839214096..ed9a92d05 100644 --- a/tex/context/base/m-spreadsheet.mkiv +++ b/tex/context/base/m-spreadsheet.mkiv @@ -13,192 +13,139 @@ %D This is an experimental follow up on discussion on the mailing list. -\startluacode -local byte, format = string.byte, string.format -local R, P, C, Cs, Cc, Carg, lpegmatch = lpeg.R, lpeg.P, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match - -local spreadsheets = { } -moduledata.spreadsheets = spreadsheets - -local data = { } -spreadsheets.data = data - -local stack, current = { }, "default" - -local mt ; mt = { - __index = function(t,k) - local v = { } - setmetatable(v,mt) - t[k] = v - return v - end, -} - -function spreadsheets.reset(name) - if not name or name == "" then name = "default" end - local d = { } - setmetatable(d,mt) - data[name] = d -end - -function spreadsheets.start(name) - if not name or name == "" then name = "default" end - table.insert(stack,current) - current = name - if not data[current] then - local d = { } - setmetatable(d,mt) - data[current] = d - end -end - -function spreadsheets.stop() - current = table.remove(stack) -end - -spreadsheets.reset() - -local offset = byte("A") - 1 - -local function assign(s,n) - return format("moduledata.spreadsheets.data['%s'][%s]",n,byte(s)-offset) -end - --------- datacell(name,a,b,...) -function datacell(a,b,...) - local n = 0 - if b then - local t = { a, b, ... } - for i=1,#t do - n = n * (i-1) * 26 + byte(t[i]) - offset - end - else - n = byte(a) - offset - end - -- return format("dat['%s'][%s]",name,n) - return format("dat[%s]",n) -end - ------ cell = (Carg(1) * C(R("AZ"))^1) / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1)) -local cell = C(R("AZ"))^1 / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1)) -local pattern = Cs(Cc("return ") * (cell + P(1))^0) - -local functions = { } -spreadsheets.functions = functions - -function functions.sum(c,f,t) - if f and t then - local r = 0 - for i=f,t do - r = r + c[i] - end - return r - else - return 0 - end -end - -function functions.fmt(pattern,n) - return format("%"..pattern,n) -end - -local template = [[ - local spr = moduledata.spreadsheets.functions - local dat = moduledata.spreadsheets.data['%s'] - local sum = spr.sum - local fmt = spr.fmt - %s -]] - -local function execute(name,r,c,str) - if name == "" then name = current if name == "" then name = "default" end end - str = lpegmatch(pattern,str,1,name) - str = format(template,name,str) - -- print(str) - local result = loadstring(str) - result = result and result() or 0 - data[name][c][r] = result - return result -end - -function spreadsheets.set(name,r,c,str) - if name == "" then name = current if name == "" then name = "default" end end - execute(name,r,c,str) -end - -function spreadsheets.get(name,r,c,str) - if name == "" then name = current if name == "" then name = "default" end end - if not str or str == "" then - context(data[name][c][r] or 0) - else - local result = execute(name,r,c,str) - if result then - if type(result) == "number" then - data[name][c][r] = result - end - context(result) - end - end -end - -function spreadsheets.doifelsecell(name,r,c) - if name == "" then name = current if name == "" then name = "default" end end - local d = data[name] - commands.testcase(d and d[c][r]) -end - -function spreadsheets.show(name) - if name == "" then name = current if name == "" then name = "default" end end - table.print(data[name],name) -end -\stopluacode +\registerctxluafile{m-spreadsheet}{1.001} \unprotect % todo: get(...) set(..) ctx(...) -\unexpanded\def\resetspreadsheet {\dosingleempty\doresetspreadsheet} -\unexpanded\def\doresetspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.reset("#1")}} -\unexpanded\def\startspreadsheet {\dosingleempty\dostartspreadsheet} -\unexpanded\def\dostartspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.start("#1")}} -\unexpanded\def\stopspreadsheet {\ctxlua{moduledata.spreadsheets.stop()}} -\unexpanded\def\showspreadsheet {\dosingleempty\doshowspreadsheet} -\unexpanded\def\doshowspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.show("#1")}} -\unexpanded\def\getspreadsheet {\dosingleempty\dogetspreadsheet} -\unexpanded\def\dosetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.set ("#1",\number#2,\number#3,"#4")}} -\unexpanded\def\setspreadsheet {\dosingleempty\dosetspreadsheet} -\unexpanded\def\dogetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.get ("#1",\number#2,\number#3,"#4")}} -\unexpanded\def\doifelsespreadsheetcell {\dosingleempty\dodoifelsespreadsheetcell} -\unexpanded\def\dodoifelsespreadsheetcell[#1]#2#3{\ctxlua{moduledata.spreadsheets.doifelsecell("#1","#2","#3")}} - -\def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}} -\def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}} +\installcorenamespace{spreadsheet} + +\installcommandhandler \??spreadsheet {spreadsheet} \??spreadsheet + +\appendtoks + \ctxlua{moduledata.spreadsheets.setup{ % global ! + period = "\spreadsheetparameter\c!period", + comma = "\spreadsheetparameter\c!comma", + split = "\spreadsheetparameter\c!split", + }}% +\to \everysetupspreadsheet + +\setupspreadsheet + [%\c!comma=, + %\c!period=, + \c!split=\v!no] + +\unexpanded\def\resetspreadsheet + {\dosingleempty\module_spreadsheet_reset} + +\unexpanded\def\module_spreadsheet_reset[#1]% + {\ctxlua{moduledata.spreadsheets.reset("#1")}} + +\unexpanded\def\startspreadsheet + {\dosingleempty\module_spreadsheet_start} + +\unexpanded\def\module_spreadsheet_start[#1]% + {\pushmacro\currentspreadsheet + \edef\currentspreadsheet{#1}% + \checkspreadsheetparent + \edef\m_spreadsheet_period{\spreadsheetparameter\c!period}% + \edef\m_spreadsheet_comma {\spreadsheetparameter\c!comma}% + \ctxlua{moduledata.spreadsheets.start("#1", { + period = \!!bs\detokenize\expandafter{\m_spreadsheet_period}\!!es, + comma = \!!bs\detokenize\expandafter{\m_spreadsheet_comma}\!!es, + split = "\spreadsheetparameter\c!split", + })}} + +\unexpanded\def\stopspreadsheet + {\ctxlua{moduledata.spreadsheets.stop()}% + \popmacro\currentspreadsheet} + +\unexpanded\def\showspreadsheet + {\dosingleempty\module_spreadsheet_show} + +\unexpanded\def\module_spreadsheet_show[#1]% + {\ctxlua{moduledata.spreadsheets.tocontext("#1")}} + +\unexpanded\def\inspectspreadsheet + {\dosingleempty\module_spreadsheet_inspect} + +\unexpanded\def\module_spreadsheet_inspect[#1]% + {\ctxlua{moduledata.spreadsheets.inspect("#1")}} + +\unexpanded\def\setspreadsheet + {\dosingleempty\module_spreadsheet_set} + +\unexpanded\def\module_spreadsheet_set[#1]#2#3#4% + {\ctxlua{moduledata.spreadsheets.set("#1",\number#2,\number#3,"#4")}} + +\unexpanded\def\getspreadsheet + {\dosingleempty\module_spreadsheet_get} + +\unexpanded\def\module_spreadsheet_get[#1]#2#3#4% + {\ctxlua{moduledata.spreadsheets.get("#1",\number#2,\number#3,"#4")}} + +\unexpanded\def\doifelsespreadsheetcell + {\dosingleempty\module_spreadsheet_doifelse_cell} + +\unexpanded\def\module_spreadsheet_doifelse_cell[#1]#2#3% + {\ctxlua{moduledata.spreadsheets.doifelsecell("#1",\number#2,\number#3)}} + +\ifdefined\tblrow + + \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}} + \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}} + +\else + + \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}} + \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}} + +\fi \appendtoks - \resetspreadsheet + \module_spreadsheet_reset[\currentspreadsheet]% \let\setspr\TABLEsetspreadsheet \let\getspr\TABLEgetspreadsheet \to \everyTABLEpass \unexpanded\def\startspreadsheettable % quick and dirty - {\dosingleempty\dostartspreadsheettable} + {\dodoubleempty\module_spreadsheet_start_table} -\unexpanded\def\dostartspreadsheettable[#1]% +\unexpanded\def\module_spreadsheet_start_table[#1][#2]% {\bgroup - \startspreadsheet[#1]%% - \def\startrow{\bTR}% - \def\stoprow {\eTR}% - \def\startcell##1\stopcell{\bTD\getspr{##1}\eTD}% - \bTABLE[\c!align=flushright]} + \let\startrow \module_spreadsheet_row_start + \let\stoprow \module_spreadsheet_row_stop + \let\startcell\module_spreadsheet_cell_start + \let\stopcell \module_spreadsheet_cell_stop + \doifassignmentelse{#1} + {\module_spreadsheet_start + \bTABLE[\c!align=\v!flushright,#1]} + {\module_spreadsheet_start[#1]% + \bTABLE[\c!align=\v!flushright,#2]}} \unexpanded\def\stopspreadsheettable {\eTABLE \stopspreadsheet \egroup} +\unexpanded\def\module_spreadsheet_row_start{\bTR} +\unexpanded\def\module_spreadsheet_row_stop {\eTR} + +\unexpanded\def\module_spreadsheet_cell_start + {\doifnextoptionalelse\module_spreadsheet_cell_start_yes\module_spreadsheet_cell_start_nop} + +\unexpanded\def\module_spreadsheet_cell_start_yes[#1]#2\stopcell + {\bTD[#1]\getspr{#2}\eTD} + +\unexpanded\def\module_spreadsheet_cell_start_nop#1\stopcell + {\bTD\getspr{#1}\eTD} + +\let\module_spreadsheet_cell_stop\relax + \protect -\doifnotmode{demo}{\endinput} +\continueifinputfile{m-spreadsheet.mkiv} \starttext @@ -220,10 +167,12 @@ end \bTD[nx=2] \bf \getspr{string.format("\letterpercent0.3f",(A[3] + B[3]) /100)} \eTD \eTR \bTR - \bTD[nx=2] \bf \getspr{fmt("0.3f",(sum(A,1,2)) / 10)} \eTD + \bTD[nx=2] \bf \getspr{fmt("@0.3f",(sum(A,1,2)) / 10)} \eTD \eTR \eTABLE +\setupspreadsheet[mysheet] + \startspreadsheet[mysheet] \bTABLE[align=middle] @@ -231,7 +180,7 @@ end \bTD \getspr{100} \eTD \bTD test \setspr{30} \eTD \eTR \bTR - \bTD \getspr{20} \eTD \bTD \getspr{4+3} \eTD + \bTD \getspr{20} \eTD \bTD \getspr{4+3.5} \eTD \eTR \bTR \bTD \getspr{A[1] + A[2]} \eTD @@ -244,17 +193,19 @@ end \stopspreadsheet -\startspreadsheettable +\blank + +\setupspreadsheet[test][period={{\bf\middlered .}},comma={{\bf\middlegreen ,}},split=yes] + +\startspreadsheettable[test] \startrow - \startcell 3 \stopcell - \startcell 9 \stopcell + \startcell 123456.78 \stopcell + \startcell 1234567.89 \stopcell \startcell A[1] + B[1] \stopcell \stoprow \stopspreadsheettable -bla bla \getspreadsheet[mysheet]{2}{2}{} - -bla bla \getspreadsheet[mysheet]{4}{1}{} +\blank % \showspreadsheet % \showspreadsheet[mysheet] diff --git a/tex/context/base/m-timing.mkiv b/tex/context/base/m-timing.mkiv index e5413ddb1..62d2ad91b 100644 --- a/tex/context/base/m-timing.mkiv +++ b/tex/context/base/m-timing.mkiv @@ -54,7 +54,7 @@ end \ctxlua{luatex.registerstopactions(function() moduledata.progress.save() end)} \stopnotmode -\def\ShowNamedUsage#1#2#3% +\unexpanded\def\ShowNamedUsage#1#2#3% {\setbox\scratchbox\vbox\bgroup\startMPcode begingroup ; save p, q, b, h, w ; path p, q, b ; numeric h, w ; @@ -92,9 +92,9 @@ end \stoplinecorrection \fi} -\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}} -\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",nil,nil,"elapsed_time")}} -\def\ShowMemoryUsage#1{\ctxlua{moduledata.progress.show("#1",nil,{}, "elapsed_time")}} -\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1",{},nil, "elapsed_time")}} +\unexpanded\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}} +\unexpanded\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",nil,nil,"elapsed_time")}} +\unexpanded\def\ShowMemoryUsage#1{\ctxlua{moduledata.progress.show("#1",nil,{}, "elapsed_time")}} +\unexpanded\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1",{},nil, "elapsed_time")}} \endinput diff --git a/tex/context/base/m-translate.mkiv b/tex/context/base/m-translate.mkiv index ae4f3899d..363f115cb 100644 --- a/tex/context/base/m-translate.mkiv +++ b/tex/context/base/m-translate.mkiv @@ -65,31 +65,40 @@ \unprotect -\def\translateinput{\dodoubleargument\dotranslateinput} +\unexpanded\def\translateinput + {\dodoubleargument\module_translate_input} -\def\dotranslateinput[#1][#2]{\ctxlua{moduledata.translators.register(\!!bs#1\!!es,\!!bs#2\!!es)}} +\def\module_translate_input[#1][#2]% + {\ctxlua{moduledata.translators.register(\!!bs#1\!!es,\!!bs#2\!!es)}} -\def\resetinputtranslation {\ctxlua{moduledata.translators.reset()}} -\def\enableinputtranslation {\ctxlua{moduledata.translators.enable()}} -\def\disableinputtranslation{\ctxlua{moduledata.translators.disable()}} +\unexpanded\def\resetinputtranslation + {\ctxlua{moduledata.translators.reset()}} -\def\readtranslatedfile#1% +\unexpanded\def\enableinputtranslation + {\ctxlua{moduledata.translators.enable()}} + +\unexpanded\def\disableinputtranslation + {\ctxlua{moduledata.translators.disable()}} + +\unexpanded\def\readtranslatedfile#1% {\enableinputtranslation \readfile{#1}\donothing\donothing \disableinputtranslation} \protect -\doifnotmode{demo}{\endinput} +\continueifinputfile{m-translate.mkiv} + \starttext \translateinput[Moica][Mojca] - \translateinput[Idris][Idris (aka ادريس)] + % \translateinput[Idris][Idris (aka ادريس)] + \translateinput[Idris][Idris (aka <something arabic here>)] \enableinputtranslation - Well, it's not that hard to satisfy Idris and Moica. + Well, it's not that hard to satisfy Idris' and Moicas \TEX\ needs. \readtranslatedfile{tufte} diff --git a/tex/context/base/m-visual.mkiv b/tex/context/base/m-visual.mkiv index 5d259f6ab..504c0d0c5 100644 --- a/tex/context/base/m-visual.mkiv +++ b/tex/context/base/m-visual.mkiv @@ -13,6 +13,9 @@ \unprotect +%D Much will probably be replaced by \LUA\ based solutions which is +%D rather trivial and fun doing. + %D This module collect a few more visual debugger features. I %D needed them for manuals and styles. The macros are documented %D in a my way document. @@ -28,11 +31,11 @@ \begingroup \directcolored[fakerulecolor]% \iffakebaseline - \vrule\!!height1.25ex\!!depth-.05ex\!!width#1% + \vrule\s!height1.25ex\s!depth-.05ex\s!width#1% \kern-#1% - \vrule\!!height-.05ex\!!depth .25ex\!!width#1% + \vrule\s!height-.05ex\s!depth .25ex\s!width#1% \else - \vrule\!!height1.25ex\!!depth .25ex\!!width#1% + \vrule\s!height1.25ex\s!depth .25ex\s!width#1% \fi \endgroup \allowbreak} @@ -116,9 +119,9 @@ \ifx\dofakedroppedcaps\relax {\fakeparindentcolor \vrule - \!!height \strutheight % not longer .5ex - \!!depth \strutdepth % not longer 0pt - \!!width \parindent}% + \s!height \strutheight % not longer .5ex + \s!depth \strutdepth % not longer 0pt + \s!width \parindent}% \else \dofakedroppedcaps \let\dofakedroppedcaps\relax \fi @@ -137,9 +140,9 @@ \advance\scratchdimen -\lineheight \advance\scratchdimen \dp\strutbox \vrule - \!!width#1\wd\scratchbox - \!!height\ht\scratchbox - \!!depth\scratchdimen}% + \s!width#1\wd\scratchbox + \s!height\ht\scratchbox + \s!depth\scratchdimen}% \ht\scratchbox\ht\strutbox \dp\scratchbox\dp\strutbox \hangindent\wd\scratchbox @@ -214,7 +217,7 @@ {\hss\lower.5\ht\scratchbox\box\scratchbox\hss}% \hbox to \zeropoint {\hss - \black\vrule\!!width6\linewidth\!!height3\linewidth\!!depth3\linewidth + \black\vrule\s!width6\linewidth\s!height3\linewidth\s!depth3\linewidth \hss}}} \unexpanded\def\bodyfontgrid @@ -243,10 +246,564 @@ \placefigure{\fakewords{8}{15}}{\fakeimage{5cm}{3cm}{10cm}{5cm}} \dorecurse{2}{\fakewords{100}{200}\endgraf}}}}} +%D Moved code: + +%D \module +%D [ file=trac-vis, % was core-vis, +%D version=1996.06.01, +%D title=\CONTEXT\ Tracking 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 This module adds some more visualization cues to the ones +%D supplied in the support module. +%D +%D %\everypar dual character, \the\everypar and \everypar= +%D %\hrule cannot be grabbed in advance, switches mode +%D %\vrule cannot be grabbed in advance, switches mode +%D % +%D %\indent only explicit ones +%D %\noindent only explicit ones +%D %\par only explicit ones +%D +%D %\leftskip only if explicit one +%D %\rightskip only if explicit one + +\writestatus{loading}{ConTeXt Tracking Macros / Visualization} + +\unprotect + +%D \macros +%D {indent, noindent, par} +%D +%D \TeX\ acts upon paragraphs. In mosts documents paragraphs +%D are separated by empty lines, which internally are handled as +%D \type{\par}. Paragraphs can be indented or not, depending on +%D the setting of \type{\parindent}, the first token of a +%D paragraph and/or user suppressed or forced indentation. +%D +%D Because the actual typesetting is based on both explicit +%D user and implicit system actions, visualization is only +%D possible for the user supplied \type{\indent}, +%D \type{\noindent}, and \type{\par}. Other +%D 'clever' tricks will quite certainly lead to more failures +%D than successes, so we only support these three explicit +%D primitives and one macro: + +\unexpanded\def\showparagraphcue#1#2#3#4#5% + {\bgroup + \scratchdimen#1\relax + \dontinterfere + \dontcomplain + %boxrulewidth5\testrulewidth + #3#4\relax + \setbox\scratchbox\normalhbox to \scratchdimen + {#2{\ruledhbox to \scratchdimen + {\vrule #5 20\testrulewidth \s!width \zeropoint + \normalhss}}}% + \smashbox\scratchbox + \normalpenalty\plustenthousand + \box\scratchbox + \egroup} + +\unexpanded\def\ruledhanging + {\ifdim\hangindent>\zeropoint + \ifnum\hangafter<\zerocount + \normalhbox + {%boxrulewidth5\testrulewidth + \setbox\scratchbox\ruledhbox to \hangindent + {\scratchdimen\strutht + \advance\scratchdimen \strutdp + \vrule + \s!width \zeropoint + \s!height \zeropoint + \s!depth -\hangafter\scratchdimen}% + \normalhskip-\hangindent + \smashbox\scratchbox + \raise\strutht\box\scratchbox}% + \fi + \fi} + +\unexpanded\def\ruledparagraphcues + {\bgroup + \dontcomplain + \normalhbox to \zeropoint + {\ifdim\leftskip>\zeropoint\relax + \showparagraphcue\leftskip\llap\relax\relax\!!depth + \normalhskip-\leftskip + \fi + \ruledhanging + \normalhskip\hsize + \ifdim\rightskip>\zeropoint\relax + \normalhskip-\rightskip + \showparagraphcue\rightskip\relax\relax\relax\!!depth + \fi}% + \egroup} + +\unexpanded\def\ruledpar + {\relax + \ifhmode + \showparagraphcue{40\testrulewidth}\relax\rightrulefalse\relax\s!height + \fi + \normalpar} + +\unexpanded\def\rulednoindent + {\relax + \normalnoindent + \ruledparagraphcues + \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\relax\s!height} + +\unexpanded\def\ruledindent + {\relax + \normalnoindent + \ruledparagraphcues + \ifdim\parindent>\zeropoint + \showparagraphcue\parindent\relax\relax\relax\s!height + \else + \showparagraphcue{40\testrulewidth}\llap\relax\relax\s!height + \fi + \normalhskip\parindent} + +\unexpanded\def\dontshowimplicits + {\let\noindent \normalnoindent + \let\indent \normalindent + \let\par \normalpar} + +\unexpanded\def\showimplicits + {\testrulewidth \defaulttestrulewidth + \let\noindent \rulednoindent + \let\indent \ruledindent + \let\par \ruledpar} + +%D The next few||line examples show the four cues. Keep in +%D mind that we only see them when we explicitly open or close +%D a paragraph. +%D +%D \bgroup +%D \def\voorbeeld#1% +%D {#1Visualizing some \TeX\ primitives and Plain \TeX\ +%D macros can be very instructive, at least it is to me. +%D Here we see {\tt\string#1} and {\tt\string\ruledpar} in +%D action, while {\tt\string\parindent} equals +%D {\tt\the\parindent}.\ruledpar} +%D +%D \showimplicits +%D +%D \voorbeeld \indent +%D \voorbeeld \noindent +%D +%D \parindent=60pt +%D +%D \voorbeeld \indent +%D \voorbeeld \noindent +%D +%D \startnarrower +%D \voorbeeld \indent +%D \voorbeeld \noindent +%D \stopnarrower +%D \egroup +%D +%D These examples also demonstrate the visualization of +%D \type {\leftskip} and \type {\rightskip}. The macro +%D \type {\nofruledbaselines} determines the number of lines +%D shown. + +\newcounter\ruledbaselines + +\def\nofruledbaselines{3} + +\unexpanded\def\ruledbaseline + {\vrule \s!width \zeropoint + \bgroup + \dontinterfere + \doglobal\increment\ruledbaselines + \scratchdimen\nofruledbaselines\baselineskip + \setbox\scratchbox\normalvbox to 2\scratchdimen + {\leaders + \normalhbox + {\strut + \vrule + \s!height \testrulewidth + \s!depth \testrulewidth + \s!width 120\points} + \normalvfill}% + \smashbox\scratchbox + \advance\scratchdimen \strutheightfactor\baselineskip + \setbox\scratchbox\normalhbox + {\normalhskip -48\points + \normalhbox to 24\points + {\normalhss + {\ttxx\ruledbaselines}% + \normalhskip6\points}% + \raise\scratchdimen\box\scratchbox}% + \smashbox\scratchbox + \box\scratchbox + \egroup} + +\unexpanded\def\showbaselines + {\testrulewidth\defaulttestrulewidth + \EveryPar{\ruledbaseline}} + +%D \macros +%D {showpagebuilder} +%D +%D The next tracing option probaly is only of use to me and a +%D few \CONTEXT\ hackers. + +\unexpanded\def\showpagebuilder + {\EveryPar{\doshowpagebuilder}} + +\unexpanded\def\doshowpagebuilder + {\strut\llap + {\startcolor[blue]\vl + \high{\infofont v:\the\vsize }\vl + \high{\infofont g:\the\pagegoal }\vl + \high{\infofont t:\the\pagetotal}\vl + \stopcolor}} + +%D \macros +%D {colormarkbox,rastermarkbox} +%D +%D This macro is used in the pagebody routine. No other use +%D is advocated here. +%D +%D \starttyping +%D \colormarkbox0 +%D \stoptyping + +\def\colormarkoffset{\cutmarkoffset} +\def\colormarklength{\cutmarklength} + +\def\dodocolorrangeA#1% + {\fastcolored[#1]{\hrule\s!width3em\s!height\scratchdimen\s!depth\zeropoint}} + +\def\docolorrangeA#1 #2 % + {\vbox + {\hsize3em % \scratchdimen + \ifcase#1\or + \dodocolorrangeA{c=#2}\or + \dodocolorrangeA{m=#2}\or + \dodocolorrangeA{y=#2}\or + \dodocolorrangeA{m=#2,y=#2}\or + \dodocolorrangeA{c=#2,y=#2}\or + \dodocolorrangeA{c=#2,m=#2}\fi + \ifdim\scratchdimen>1ex + \vskip-\scratchdimen + \vbox to \scratchdimen + {\vss\hbox to 3em{\hss#2\hss}\vss}% + \fi}} + +\def\colorrangeA#1% + {\vbox + {\startcolor[\s!white]% + \scratchdimen\dimexpr(-\colormarklength*4+\tractempheight+\tractempdepth)/21\relax + \offinterlineskip + \docolorrangeA #1 1.00 \docolorrangeA #1 0.95 + \docolorrangeA #1 0.75 + \docolorrangeA #1 0.50 + \docolorrangeA #1 0.25 \docolorrangeA #1 0.05 + \docolorrangeA #1 0.00 + \stopcolor}} + +\def\docolorrangeB #1 #2 #3 #4 #5 % + {\fastcolored + [\c!c=#2,\c!m=#3,\c!y=#4,\c!k=#5] + {\vrule\s!width\scratchdimen\s!height\colormarklength\s!depth\zeropoint}% + \ifdim\scratchdimen>2em + \hskip-\scratchdimen + \vbox to \colormarklength + {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}% + \fi} + +\def\colorrangeB + {\hbox + {\startcolor[\s!white]% + \scratchdimen\dimexpr(-\colormarklength*\plustwo+\tractempwidth)/11\relax + \docolorrangeB .5~C .5 0 0 0 + \docolorrangeB .5~M 0 .5 0 0 + \docolorrangeB .5~Y 0 0 .5 0 + \docolorrangeB .5~K 0 0 0 .5 + \docolorrangeB C 1 0 0 0 + \docolorrangeB G 1 0 1 0 + \docolorrangeB Y 0 0 1 0 + \docolorrangeB R 0 1 1 0 + \docolorrangeB M 0 1 0 0 + \docolorrangeB B 1 1 0 0 + \docolorrangeB K 0 0 0 1 + \stopcolor}} + +\def\docolorrangeC#1 % + {\fastcolored + [\c!s=#1]% + {\vrule\s!width\scratchdimen\s!height\colormarklength\s!depth\zeropoint}% + \ifdim\scratchdimen>2em + \hskip-\scratchdimen + \vbox to \colormarklength + {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}% + \fi} + +\def\colorrangeC + {\hbox + {\startcolor[\s!white]% + \scratchdimen\dimexpr(-\colormarklength*2+\tractempwidth)/14\relax + \docolorrangeC 1 \docolorrangeC .95 + \docolorrangeC .9 \docolorrangeC .85 + \docolorrangeC .8 \docolorrangeC .75 + \docolorrangeC .7 + \docolorrangeC .6 + \docolorrangeC .5 + \docolorrangeC .4 + \docolorrangeC .3 + \docolorrangeC .2 + \docolorrangeC .1 + \docolorrangeC 0 + \stopcolor}} + +\def\docolormarkbox#1#2% + {\tractempheight\ht#2% + \tractempdepth \dp#2% + \tractempwidth \wd#2% + \setbox#2\hbox + {\scratchdimen\dimexpr\colormarklength/2\relax + \forgetall + \ssxx + \setbox\scratchbox\vbox + {\offinterlineskip + \vskip\dimexpr-\colormarkoffset\scratchdimen-2\scratchdimen\relax + \ifcase#1\relax + \vskip\dimexpr\colormarklength+\scratchdimen+\tractempheight\relax + \else + \hbox to \tractempwidth{\hss\hbox{\colorrangeB}\hss}% + \vskip\colormarkoffset\scratchdimen + \vbox to \tractempheight + {\vss + \hbox to \tractempwidth + {\llap{\colorrangeA1\hskip\colormarkoffset\scratchdimen}\hfill + \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA4}}% + \vss + \hbox to \tractempwidth + {\llap{\colorrangeA2\hskip\colormarkoffset\scratchdimen}\hfill + \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA5}}% + \vss + \hbox to \tractempwidth + {\llap{\colorrangeA3\hskip\colormarkoffset\scratchdimen}\hfill + \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA6}}% + \vss}% + \fi + \vskip\colormarkoffset\scratchdimen + \hbox to \tractempwidth + {\hss\lower\tractempdepth\hbox{\colorrangeC}\hss}}% + \ht\scratchbox\tractempheight + \dp\scratchbox\tractempdepth + \wd\scratchbox\zeropoint + \box\scratchbox + \box#2}% + \wd#2\tractempwidth + \ht#2\tractempheight + \dp#2\tractempdepth} + +\unexpanded\def\colormarkbox {\docolormarkbox\plusone } % #1 +\unexpanded\def\rastermarkbox{\docolormarkbox\zerocount} % #1 + +%D \macros +%D {showwhatsits, dontshowwhatsits} +%D +%D \TEX\ has three so called whatsits: \type {\mark}, \type +%D {\write} and \type {\special}. The first one keeps track of +%D the current state at page boundaries, the last two are used +%D to communicate to the outside world. Due to fact that +%D especially \type {\write} is often used in conjunction with +%D \type {\edef}, we can only savely support that one in \ETEX. +%D +%D \bgroup \showwhatsits \setupcolors[state=start] +%D +%D Whatsits show up \color[blue]{in color} and are +%D characterized bij their first character.\footnote [some note] +%D {So we may encounter \type {w}, \type {m} and \type{s}.} +%D They are \writestatus{dummy}{demo}\color[yellow]{stacked}. +%D +%D \egroup + +\newif\ifimmediatewrite + +\let\supernormalmark \normalmark % mark may already been superseded +\let\supernormalmarks \normalmarks % mark may already been superseded + +\unexpanded\def\showwhatsits + {\protected\def\normalmark {\visualwhatsit100+m\supernormalmark }% + \protected\def\normalmarks{\visualwhatsit100+m\supernormalmarks}% + \protected\def\special {\visualwhatsit0100s\normalspecial }% + \protected\def\write {\visualwhatsit001-w\normalwrite }% + \let\immediate\immediatewhatsit + \appendtoks\dontshowwhatsits\to\everystoptext} + +\unexpanded\def\immediatewhatsit + {\bgroup\futurelet\next\doimmediatewhatsit} + +\unexpanded\def\doimmediatewhatsit + {\ifx\next\write + \egroup\immediatewritetrue + \else + \egroup\expandafter\normalimmediate + \fi} + +\unexpanded\def\dontshowwhatsits + {\let\immediate \normalimmediate + \let\normalmark\supernormalmark + \let\special \normalspecial + \let\write \normalwrite} + +\unexpanded\def\visualwhatsit#1#2#3#4#5% + {\bgroup + \pushwhatsit + \dontinterfere + \dontcomplain + \dontshowcomposition + \dontshowwhatsits + \ttx + \ifvmode\donetrue\else\donefalse\fi + \setbox\scratchbox\hbox + {\ifdone + \colored[r=#1,g=#2,b=#3]{#5}% temp hack + \else + \colored[s=0]{#5}% temp hack + \fi}% + \setbox\scratchbox\hbox + {\ifdone + \colored[r=#1,g=#2,b=#3]{\vrule\s!width\wd\scratchbox}% temp hack + \else + \colored[s=0]{\vrule\s!width\wd\scratchbox}% temp hack + \fi + \hskip-\wd\scratchbox\box\scratchbox}% + \scratchdimen1ex + \setbox\scratchbox\hbox + {\ifdone\hskip\else\raise#4\fi\scratchdimen\box\scratchbox}% + \smashbox\scratchbox + \ifdone\nointerlineskip\fi + \box\scratchbox + \ifvmode\nointerlineskip\fi + \popwhatsit + \egroup + \ifimmediatewrite + \immediatewritefalse + \expandafter\normalimmediate + \fi} + +\unexpanded\def\pushwhatsit + {\ifzeropt\lastskip + \ifcase\lastpenalty + \ifzeropt\lastkern + \ifhmode + \let\popwhatsit\relax + \else + \edef\popwhatsit{\prevdepth\the\prevdepth}% + \fi + \else + \ifhmode + \edef\popwhatsit{\kern\the\lastkern}\unkern + \else + \edef\popwhatsit{\kern\the\lastkern\prevdepth\the\prevdepth}% + \kern-\lastkern + \fi + \fi + \else + \ifhmode + \edef\popwhatsit{\the\lastpenalty}% + \unpenalty + \else + \edef\popwhatsit{\penalty\the\lastpenalty\prevdepth\the\prevdepth}% + %\nobreak + \fi + \fi + \else + \ifhmode + \edef\popwhatsit{\hskip\the\lastskip}\unskip + \else + \edef\popwhatsit{\vskip\the\lastskip\prevdepth\the\prevdepth}% + \vskip-\lastskip + \fi + \fi} + +%D The next macro can be used to keep track of classes of +%D boxes (handy for development cq.\ tracing). + +\def\dodotagbox#1#2#3% can be reimplemented + {\def\next##1##2##3##4% + {\vbox to \ht#2{##3\hbox to \wd#2{##1#3##2}##4}}% + \processaction + [#1] + [ l=>\next\relax\hfill\vfill\vfill, + r=>\next\hfill\relax\vfill\vfill, + t=>\next\hfill\hfill\relax\vfill, + b=>\next\hfill\hfill\vfill\relax, + lt=>\next\relax\hfill\relax\vfill, + lb=>\next\relax\hfill\vfill\relax, + rt=>\next\hfill\relax\relax\vfill, + rb=>\next\hfill\relax\vfill\relax, + tl=>\next\relax\hfill\relax\vfill, + bl=>\next\relax\hfill\vfill\relax, + tr=>\next\hfill\relax\relax\vfill, + br=>\next\hfill\relax\vfill\relax, + \s!default=>\next\hfill\hfill\vfill\vfill, + \s!unknown=>\next\hfill\hfill\vfill\vfill]} + +\def\dotagbox[#1]#2% + {\bgroup + \dowithnextbox + {\setbox\scratchbox\flushnextbox + \setbox\nextbox\ifhbox\nextbox\hbox\else\vbox\fi + \bgroup + \startoverlay + {\copy\scratchbox} + {\dodotagbox{#1}\scratchbox{\framed + [\c!background=\v!screen,\c!backgroundscreen=1]{#2}}} + \stopoverlay + \egroup + \nextboxwd\the\wd\scratchbox + \nextboxht\the\ht\scratchbox + \nextboxdp\the\dp\scratchbox + \flushnextbox + \egroup}} + +\unexpanded\def\tagbox + {\dosingleempty\dotagbox} + +%D \macros +%D {coloredhbox,coloredvbox,coloredvtop, +%D coloredstrut} +%D +%D The following visualizations are used in some of the manuals: + +\definecolor[boxcolor:ht][r=.5,g=.75,b=.5] +\definecolor[boxcolor:dp][r=.5,g=.5,b=.75] +\definecolor[boxcolor:wd][r=.75,g=.5,b=.5] +\definecolor[strutcolor] [r=.5,g=.25,b=.25] + +\unexpanded\def\coloredbox#1% + {\dowithnextbox{#1{\hbox + {\blackrule[\c!width=\nextboxwd,\c!height=\nextboxht,\c!depth=\zeropoint,\c!color=boxcolor:ht]% + \hskip-\nextboxwd + \blackrule[\c!width=\nextboxwd,\c!height=\zeropoint,\c!depth=\nextboxdp,\c!color=boxcolor:dp]% + \hskip-\nextboxwd + \box\nextbox}}}#1} + +\unexpanded\def\coloredhbox{\coloredbox\hbox} +\unexpanded\def\coloredvbox{\coloredbox\vbox} +\unexpanded\def\coloredvtop{\coloredbox\vtop} + +\unexpanded\def\coloredstrut + {\color[strutcolor]{\def\strutwidth{2\points}\setstrut\strut}} + +\protect + \continueifinputfile{m-visual.mkiv} \starttext \simplethesis \stoptext - -\protect \endinput diff --git a/tex/context/base/math-act.lua b/tex/context/base/math-act.lua index 278d323c6..9894fa172 100644 --- a/tex/context/base/math-act.lua +++ b/tex/context/base/math-act.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['math-act'] = { license = "see context related readme files" } +-- Here we tweak some font properties (if needed). + local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) local report_math = logs.reporter("mathematics","initializing") diff --git a/tex/context/base/math-ali.mkiv b/tex/context/base/math-ali.mkiv index 94800b3ba..9e6fda074 100644 --- a/tex/context/base/math-ali.mkiv +++ b/tex/context/base/math-ali.mkiv @@ -15,17 +15,6 @@ \unprotect -% helpers .. will move - -\def\doxxdoubleempty#1#2% - {\ifx#2[\expandafter\dodoxxdoubleempty\else\expandafter\noxxdoubleempty\fi#1#2} - -\def\dodoxxdoubleempty#1[#2]#3% - {\ifx#3[\else\expandafter\nonoxxdoubleempty\fi#1[#2]#3} - -\def\noxxdoubleempty #1{#1[][]} -\def\nonoxxdoubleempty#1[#2]{#1[#2][]} - %D The code here has been moved from other files. Beware: the \MKII\ and %D \MKIV\ code is not gathered in files with the same name. In the %D meantime this code has been adapted to \MKIV\ but mnore is possible. @@ -38,19 +27,25 @@ % n>1 #### needed, strange # interaction in recurse +\newtoks\c_math_align_a +\newtoks\c_math_align_b +\newtoks\c_math_align_c + \def\math_build_eqalign {\scratchtoks\emptytoks - \dorecurse{\mathalignmentparameter\c!m} - {\ifnum\recurselevel>\plusone - %\appendtoks - % \tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint - %\to\scratchtoks - \scratchtoks\expandafter{\the\scratchtoks\tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint}% - \fi - \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}% - \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax} - {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}}% - \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}} + \dorecurse{\mathalignmentparameter\c!m}\math_build_eqalign_step + \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}} + +\def\math_build_eqalign_step + {\ifnum\recurselevel>\plusone + %\appendtoks + % \tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint + %\to\scratchtoks + \scratchtoks\expandafter{\the\scratchtoks\tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint}% + \fi + \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}% + \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax} + {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}} \def\math_math_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks\displaystyle{{}#1{}}$} \def\math_text_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks#1$} @@ -73,14 +68,14 @@ % use zeroskipplusfill \def\math_prepare_r_eqalign_no - {\!!toksa{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% - \!!toksb{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% + {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% + \c_math_align_b{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% \ifnum\mathraggedstatus=\plusone - \!!toksc{\hfil&\span\math_text_in_eqalign{##}\tabskip\zeropoint}% + \c_math_align_c{\hfil&\span\math_text_in_eqalign{##}\tabskip\zeropoint}% \else\ifnum\mathraggedstatus=\plusthree - \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\span\math_text_in_eqalign{##}\tabskip\zeropoint}% + \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill&\span\math_text_in_eqalign{##}\tabskip\zeropoint}% \else - \!!toksc{\hfil\tabskip\centering&\llap{\span\math_text_in_eqalign{##}}\tabskip\zeropoint}% + \c_math_align_c{\hfil\tabskip\centering&\llap{\span\math_text_in_eqalign{##}}\tabskip\zeropoint}% \fi\fi \global\mathnumberstatus\zerocount \math_build_eqalign @@ -88,31 +83,31 @@ \tabskip\centering} \def\math_prepare_l_eqalign_no - {\!!toksa{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% - \!!toksb{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% + {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% + \c_math_align_b{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}% % problem: number is handled after rest and so ends up in the margin \ifnum\mathraggedstatus=\plusone - \!!toksc{\hfil&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% + \c_math_align_c{\hfil&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% \else\ifnum\mathraggedstatus=\plusthree - \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% + \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill&\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% \else - \!!toksc{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% + \c_math_align_c{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}% \fi\fi \global\mathnumberstatus\zerocount \math_build_eqalign \the\mathdisplayaligntweaks \tabskip\centering} -\def\math_both_eqalign_no#1#2% +\def\math_both_eqalign_no_normal#1#2% {\ifmmode - \the\mathdisplayaligntweaks % \let\doplaceformulanumber\relax % strange hack + \the\mathdisplayaligntweaks % \let\strc_formulas_place_number\relax % strange hack \vcenter\bgroup \let\math_finish_eqalign_no\egroup \else \let\math_finish_eqalign_no\relax \fi #1% - \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA {\the\scratchtoks\crcr#2\crcr}% + \halign \ifcase\eqalignmode \or to \displaywidth \fi \expandafter {\the\scratchtoks\crcr#2\crcr}% \math_finish_eqalign_no} \def\math_both_eqalign_no_aligned#1% @@ -128,7 +123,7 @@ \fi \fi #1% - \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr} + \halign \ifcase\eqalignmode \or to \displaywidth \fi \expandafter \bgroup\the\scratchtoks\crcr} \def\math_rlap#1% {\setbox\scratchbox\hbox{#1}% @@ -158,7 +153,7 @@ \newtoks \everymathalignment \def\math_alignment_NR_indeed[#1][#2]% - {\donestedformulanumber{#1}{#2}% to be tagged (better an attribute) + {\strc_formulas_place_number_nested{#1}{#2}% to be tagged (better an attribute) \crcr \dostoptagged % finish row \noalign{\glet\math_alignment_NC\math_alignment_NC_first}} % noalign used for change state, conditional does not work here @@ -221,7 +216,7 @@ \setupmathalignment [\c!n=2, \c!m=1, - \c!distance=1em] + \c!distance=\emwidth] \definemathalignment[align] % default case (this is what amstex users expect) \definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing) @@ -265,7 +260,7 @@ \letvalue{\??mathalignmentvariant\v!middle}\plusthree \def\math_align_NR_generic[#1][#2]% - {\donestedformulanumber{#1}{#2}\crcr} + {\strc_formulas_place_number_nested{#1}{#2}\crcr} %D \starttyping %D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0] @@ -408,8 +403,8 @@ \installcommandhandler \??mathcases {mathcases} \??mathcases \setupmathcases - [\c!distance=1em, - \c!numberdistance=2.5em, + [\c!distance=\emwidth, + \c!numberdistance=2.5\emwidth, \c!left={\left\{\mskip\thinmuskip}, \c!right={\right.}] @@ -434,7 +429,7 @@ \def\NC{\math_cases_NC}% \def\MC{\math_cases_NC\ifmmode\else$\def\endmath{$}\fi}% \global\let\math_cases_NC\math_cases_NC_indeed - \def\NR{\unskip\endmath&\global\let\math_cases_NC\math_cases_NC_indeed\doxxdoubleempty\math_cases_NR}% + \def\NR{\unskip\endmath&\global\let\math_cases_NC\math_cases_NC_indeed\dodirectdoubleempty\math_cases_NR}% \normalbaselines \mathsurround\zeropoint \everycr\emptytoks @@ -515,7 +510,7 @@ \installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix \setupmathmatrix - [\c!distance=1em, + [\c!distance=\emwidth, \c!left=, \c!right=, \c!align=\v!middle] @@ -570,20 +565,20 @@ \definemathmatrix[\v!mathmatrix] \def\math_matrix_prepare - {\!!toksa{\strut\math_first_in_eqalign\math_left_of_equalign\span + {\c_math_align_a{\strut\math_first_in_eqalign\math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}% - \!!toksb{&\hskip\mathmatrixparameter\c!distance + \c_math_align_b{&\hskip\mathmatrixparameter\c!distance \math_next_in_eqalign\math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}% - \!!toksc{&&\hskip\mathmatrixparameter\c!distance + \c_math_align_c{&&\hskip\mathmatrixparameter\c!distance \math_left_of_equalign\span \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}% \scratchtoks\emptytoks - \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}% + \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}% \dorecurse{\numexpr\scratchcounter-\plusone\relax} - {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}% - \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}% - \halign \@EA \bgroup\the\scratchtoks \crcr} + {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}% + \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}% + \halign \expandafter \bgroup\the\scratchtoks \crcr} \unexpanded\def\dodomatrixNC {\gdef\domatrixNC{\endmath&}} @@ -887,10 +882,10 @@ \expandafter\mathbin \else\ifdim\wd\scratchbox>\zeropoint \endgroup - \expandafter\expandafter\expandafter\mathrel + \doubleexpandafter\mathrel \else \endgroup - \expandafter\expandafter\expandafter\firstofoneargument + \doubleexpandafter\firstofoneargument \fi\fi} \unexpanded\def\overset#1#2% @@ -947,7 +942,7 @@ \let\normalleqno\leqno \let\normaleqno \eqno % added - \doplaceformulanumber + \strc_formulas_place_number \setbox\scratchbox\math_hbox to \displaywidth\bgroup \mathinnerstrut $% diff --git a/tex/context/base/math-arr.mkiv b/tex/context/base/math-arr.mkiv index f18d6be2b..5b50303d0 100644 --- a/tex/context/base/math-arr.mkiv +++ b/tex/context/base/math-arr.mkiv @@ -30,156 +30,112 @@ % \mathord\rightarrow % $} % -% \def\leftarrowfill % brrr no longer in luated +% \def\leftarrowfill % brrr no longer in luatex % {$% % \mathsurround\zeropoint % \mathord\leftarrow % \mkern-7mu% % \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill % \mkern-7mu -% \smash-$ +% \smash-% % $} -\def\exmthfont#1{\mr} % \symbolicsizedfont#1\plusone{MathExtension}} - -\def\domthfrac#1#2#3#4#5#6#7% +\def\math_stylebuilders_fract#1#2#3#4#5#6#7% {\begingroup \mathsurround\zeropoint \setbox0\hbox{$#1 #6$}% \setbox2\hbox{$#1 #7$}% - \dimen0\wd0 - \ifdim\wd2>\dimen0 \dimen0\wd2 \fi + \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% + \kern\ht4% \hbox to \dimen0{\hss\copy4\hss}% - \kern \ht4% + \kern\ht4% \hbox to \dimen0{\hss\box2\hss}}}}% \endgroup} -\def\domthsqrt#1#2#3#4#5% +\def\math_stylebuilders_sqrt#1#2#3#4#5% {\begingroup \mathsurround\zeropoint \setbox0\hbox{$#1 #5$}% - \dimen0=1.05\ht0 \advance\dimen0 1pt \ht0 \dimen0 - \dimen0=1.05\dp0 \advance\dimen0 1pt \dp0 \dimen0 - \dimen0\wd0 - \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}% - \delimitershortfall=0pt - \nulldelimiterspace=0pt - \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt - \right.$}% - \mathord{\vcenter{\hbox{\copy2 - \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}% + \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 - {\domthfrac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}% - {\domthfrac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}% - {\domthfrac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}% - {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}} + {\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 - {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}% - {\domthsqrt\textstyle \textface {#1}{#2}{#3}}% - {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}% - {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}} - -% temp here - -%D We next define extensible arrows. Extensible arrows are arrows that -%D change their length according to the width of the text to be placed -%D above and below the arrow. Since we need to define a lot of arrows, -%D we first define some helper macros. The basic idea is to measure -%D the width of the box to be placed above and below the arrow, and -%D make the \quotation{body} of the arrow as long as the bigger of the -%D two widths. - -\def\mtharrfactor{1} -\def\mtharrextra {0} - -% \def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel -% {\begingroup -% \def\mtharrfactor{1}% -% \def\mtharrextra {0}% -% \processaction[#1] % will be sped up -% [ \v!none=>\def\mtharrfactor{0}, -% \v!small=>\def\mtharrextra{10}, -% \v!medium=>\def\mtharrextra{15}, -% \v!big=>\def\mtharrextra{20}, -% \v!normal=>, -% \v!default=>, -% \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]% -% \mathsurround\zeropoint -% \muskip0=\thirdoffourarguments #2mu -% \muskip2=\fourthoffourarguments #2mu -% \muskip4=\firstoffourarguments #2mu -% \muskip6=\secondoffourarguments #2mu -% \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu -% \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu -% \setbox0\hbox{$\scriptstyle -% \mkern\muskip4\relax -% \mkern\muskip0\relax -% #5\relax -% \mkern\muskip2\relax -% \mkern\muskip6\relax -% $}% -% \setbox4\hbox{#3\displaystyle}% -% \dimen0\wd0 -% \ifdim\wd4>\dimen0 \dimen0\wd4 \fi -% \setbox2\hbox{$\scriptstyle -% \mkern\muskip4\relax -% \mkern\muskip0\relax -% #4\relax -% \mkern\muskip2\relax -% \mkern\muskip6\relax -% $}% -% \ifdim\wd2>\dimen0 \dimen0\wd2 \fi -% \setbox4\hbox to \dimen0{#3\displaystyle}% -% \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}% -% \endgroup} - -\def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel + {\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}}} + +%D We next define extensible arrows. Extensible arrows are arrows that change their +%D length according to the width of the text to be placed above and below the arrow. +%D Since we need to define a lot of arrows, we first define some helper macros. The +%D basic idea is to measure the width of the box to be placed above and below the +%D arrow, and make the \quote {body} of the arrow as long as the bigger of the two +%D widths. + +\installcorenamespace{matharrowsettings} + +\def\m_math_arrows_factor{1} +\def\m_math_arrows_extra {0} + +\setvalue{\??matharrowsettings\v!none }{\def\m_math_arrows_factor{0}} +\setvalue{\??matharrowsettings\v!small }{\def\m_math_arrows_extra{10}} +\setvalue{\??matharrowsettings\v!medium }{\def\m_math_arrows_extra{15}} +\setvalue{\??matharrowsettings\v!big }{\def\m_math_arrows_extra{20}} +\setvalue{\??matharrowsettings\v!normal }{} +\setvalue{\??matharrowsettings }{} +\setvalue{\??matharrowsettings\s!unknown}{\doifnumberelse\p_math_spacing{\let\m_math_arrows_extra\p_math_spacing}\donothing} + +\def\math_arrows_construct#1#2#3#4#5% hm, looks like we do a double mathrel (a bit cleaned up .. needs checking) {\begingroup - \def\mtharrfactor{1}% - \def\mtharrextra {0}% - \processaction[#1] % will be sped up - [ \v!none=>\def\mtharrfactor{0}, - \v!small=>\def\mtharrextra{10}, - \v!medium=>\def\mtharrextra{15}, - \v!big=>\def\mtharrextra{20}, - \v!normal=>, - \v!default=>, - \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]% + \def\m_math_arrows_factor{1}% + \def\m_math_arrows_extra {0}% + \edef\p_math_spacing{#1}% + \csname\??matharrowsettings + \ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi + \endcsname \mathsurround\zeropoint - \muskip0=\thirdoffourarguments #2mu - \muskip2=\fourthoffourarguments #2mu - \muskip0=\mtharrfactor\muskip0 - \muskip2=\mtharrfactor\muskip2 - \advance\muskip0 \mtharrextra mu - \advance\muskip2 \mtharrextra mu - \advance\muskip0 \firstoffourarguments #2mu - \advance\muskip2 \secondoffourarguments #2mu + \muskip0=\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax + \muskip2=\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax \setbox0\hbox{$\scriptstyle \mkern\muskip0\relax #5\relax \mkern\muskip2\relax $}% - \setbox4\hbox{#3\displaystyle}% - \dimen0\wd0 - \ifdim\wd4>\dimen0 \dimen0\wd4 \fi \setbox2\hbox{$\scriptstyle \mkern\muskip0\relax #4\relax \mkern\muskip2\relax $}% - \ifdim\wd2>\dimen0 \dimen0\wd2 \fi - \setbox4\hbox to \dimen0{#3\displaystyle}% + \setbox4\hbox{#3\displaystyle}% + \dimen0\wd0\relax + \ifdim\wd2>\dimen0 + \dimen0\wd2\relax + \fi + \ifdim\wd4>\dimen0 + \dimen0\wd4\relax + \fi + \ifdim\wd4=\dimen0\else + \setbox4\hbox to \dimen0{#3\displaystyle}% + \fi \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}% \endgroup} -\let\domthxarrsingle\domthxarr +\let\math_arrows_construct_single\math_arrows_construct %D There are some arrows which are created by stacking two arrows. The next %D macro helps in defining such \quotation{double arrows}. @@ -194,29 +150,27 @@ % \chemical{SO_2} % \stopchemicalformula -\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot +\def\math_arrows_construct_double#1#2#3#4#5#6#7% opt l r sp rs top bot {\mathrel - {\scratchdimen.32ex\relax % was .22, todo: make configurable - \setbox0\hbox{$\domthxarr{#1}{#2}{#4}{\phantom{#6}}{#7}$}% - \setbox2\hbox{$\domthxarr{#1}{#3}{#5}{#6}{\phantom{#7}}$}% + {\scratchdimen.32\exheight\relax % was .22, todo: make configurable + \setbox0\hbox{$\math_arrows_construct{#1}{#2}{#4}{\phantom{#6}}{#7}$}% + \setbox2\hbox{$\math_arrows_construct{#1}{#3}{#5}{#6}{\phantom{#7}}$}% \raise\scratchdimen\box0 \kern-\wd2 \lower\scratchdimen\box2}} %D \macros{definematharrow} %D -%D Macro for defining new arrows. We can define two types of -%D arrows|<|single arrows and double arrows. Single arrows are defined -%D as +%D Macro for defining new arrows. We can define two types of arrows|<|single arrows +%D and double arrows. Single arrows are defined as %D %D \starttyping %D \definematharrow [xrightarrow] [0359] [\rightarrowfill] %D \stoptyping %D -%D The first argument is the name of the arrow (\tex{xrightarrow} in -%D this case.) The second argument consists of a set of 4 numbers and -%D specify the spacing correction in math units~\type{mu}. These -%D numbers define: +%D The first argument is the name of the arrow (\tex {xrightarrow} in this case.) The +%D second argument consists of a set of 4 numbers and specify the spacing correction +%D in math units~\type {mu}. These numbers define: %D %D \startlines %D 1st number: arrow||tip correction @@ -225,9 +179,9 @@ %D 4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra}) %D \stoplines %D -%D The third argument is the name of the extensible fill. The third -%D argument is optional when the arrow is redefined later (this is -%D useful for font specific tweaking of the skips.) For example, +%D The third argument is the name of the extensible fill. The third argument is optional +%D when the arrow is redefined later (this is useful for font specific tweaking of the +%D skips.) For example, %D %D \startbuffer %D \math{\xrightarrow{above}} @@ -245,78 +199,80 @@ %D [\rightharpoonupfill,\leftharpoondownfill] %D \stoptyping %D -%D The second and the third set of arguments consist of comma -%D separated values. The first element of the second argument -%D (\type{3095}) corresponds to the spacing correction of top arrow -%D fill (\tex{rightarrowupfill}). Similarly, \type{0359} corresponds -%D to bottom arrow fill \tex{leftharpoondownfill}). Stacking them on -%D top of each other we get $\xrightleftharpoons[big]{above}{below}$. -%D The following math arrows are defined +%D The second and the third set of arguments consist of comma separated values. The +%D first element of the second argument (\type {3095}) corresponds to the spacing +%D correction of top arrow fill (\tex{rightarrowupfill}). Similarly, \type {0359} +%D corresponds to bottom arrow fill \tex {leftharpoondownfill}). Stacking them on +%D top of each other we get $\xrightleftharpoons [big] {above} {below}$. The +%D following math arrows are defined %D %D \placetable[none]{}{\starttable[|l|m|] -%D \NC \tex{xrightarrow } \NC \xrightarrow [big] \NC \NR -%D \NC \tex{xleftarrow } \NC \xleftarrow [big] \NC \NR -%D \NC \tex{xequal } \NC \xequal [big] \NC \NR -%D \NC \tex{xRightarrow } \NC \xRightarrow [big] \NC \NR -%D \NC \tex{xLeftarrow } \NC \xLeftarrow [big] \NC \NR -%D \NC \tex{xLeftrightarrow } \NC \xLeftrightarrow [big] \NC \NR -%D \NC \tex{xleftrightarrow } \NC \xleftrightarrow [big] \NC \NR -%D \NC \tex{xmapsto } \NC \xmapsto [big] \NC \NR -%D \NC \tex{xtwoheadrightarrow } \NC \xtwoheadrightarrow [big] \NC \NR -%D \NC \tex{xtwoheadleftarrow } \NC \xtwoheadleftarrow [big] \NC \NR -%D \NC \tex{xrightharpoondown } \NC \xrightharpoondown [big] \NC \NR -%D \NC \tex{xrightharpoonup } \NC \xrightharpoonup [big] \NC \NR -%D \NC \tex{xleftharpoondown } \NC \xleftharpoondown [big] \NC \NR -%D \NC \tex{xleftharpoonup } \NC \xleftharpoonup [big] \NC \NR -%D \NC \tex{xhookleftarrow } \NC \xhookleftarrow [big] \NC \NR -%D \NC \tex{xhookrightarrow } \NC \xhookrightarrow [big] \NC \NR -%D \NC \tex{xleftrightharpoons } \NC \xleftrightharpoons [big] \NC \NR -%D \NC \tex{xrightleftharpoons } \NC \xrightleftharpoons [big] \NC \NR +%D \NC \tex{xrightarrow} \NC \xrightarrow [big] \NC \NR +%D \NC \tex{xleftarrow} \NC \xleftarrow [big] \NC \NR +%D \NC \tex{xequal} \NC \xequal [big] \NC \NR +%D \NC \tex{xRightarrow} \NC \xRightarrow [big] \NC \NR +%D \NC \tex{xLeftarrow} \NC \xLeftarrow [big] \NC \NR +%D \NC \tex{xLeftrightarrow} \NC \xLeftrightarrow [big] \NC \NR +%D \NC \tex{xleftrightarrow} \NC \xleftrightarrow [big] \NC \NR +%D \NC \tex{xmapsto} \NC \xmapsto [big] \NC \NR +%D \NC \tex{xtwoheadrightarrow} \NC \xtwoheadrightarrow [big] \NC \NR +%D \NC \tex{xtwoheadleftarrow} \NC \xtwoheadleftarrow [big] \NC \NR +%D \NC \tex{xrightharpoondown} \NC \xrightharpoondown [big] \NC \NR +%D \NC \tex{xrightharpoonup} \NC \xrightharpoonup [big] \NC \NR +%D \NC \tex{xleftharpoondown} \NC \xleftharpoondown [big] \NC \NR +%D \NC \tex{xleftharpoonup} \NC \xleftharpoonup [big] \NC \NR +%D \NC \tex{xhookleftarrow} \NC \xhookleftarrow [big] \NC \NR +%D \NC \tex{xhookrightarrow} \NC \xhookrightarrow [big] \NC \NR +%D \NC \tex{xleftrightharpoons} \NC \xleftrightharpoons [big] \NC \NR +%D \NC \tex{xrightleftharpoons} \NC \xrightleftharpoons [big] \NC \NR %D \stoptable} +%D If needed this can be optimized (i.e. we can preexpand using \type +%D {\docheckedpair}). + \unexpanded\def\definematharrow - {\doquadrupleargument\dodefinematharrow} + {\doquadrupleargument\math_arrows_define} -\def\dodefinematharrow[#1][#2][#3][#4]% name type[none|both] template command +\def\math_arrows_define[#1][#2][#3][#4]% name type[none|both] template command {\iffourthargument - \executeifdefined{dodefine#2arrow}\gobblethreearguments{#1}{#3}{#4}% + \executeifdefined{math_arrows_define_#2}\gobblethreearguments{#1}{#3}{#4}% \else\ifthirdargument - \dodefinebotharrow{#1}{#2}{#3}% + \math_arrows_define_both{#1}{#2}{#3}% \else\ifsecondargument - \redefinebotharrow{#1}{#2}{#3}% + \math_arrows_define_both_again{#1}{#2}{#3}% \fi\fi\fi} -\def\redefinebotharrow#1#2#3% real dirty, this overload! - {\doifdefined{#1} - {\pushmacro\dohandlemtharrow - \def\dohandlemtharrow[##1][##2]{\setuvalue{#1}{\dohandlemtharrow[#2][##2]}}% - % == \def\dohandlemtharrow[##1][##2]{\dodefinebotharrow{#1}{#2}{##2}}% - \getvalue{#1}% - \popmacro\dohandlemtharrow}} +\def\math_arrows_define_both_again#1#2#3% real dirty, this overload! + {\ifcsname#1\endcsname + \pushmacro\math_arrows_do + \def\math_arrows_do[##1][##2]{\setuvalue{#1}{\math_arrows_do[#2][##2]}}% + \getvalue{#1}% + \popmacro\math_arrows_do + \fi} -\def\dodefinebotharrow#1#2#3% - {\setuvalue{#1}{\dohandlemtharrow[#2][#3]}} +\def\math_arrows_define_both#1#2#3% + {\setuvalue{#1}{\math_arrows_do[#2][#3]}} -\def\dohandlemtharrow - {\dotripleempty\doxmtharrow} +\unexpanded\def\math_arrows_do + {\dotripleempty\math_arrows_handle} -\def\doxmtharrow[#1][#2][#3]% #3 == optional arg - {\def\dodoxmtharrow{\dododoxmtharrow[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2} - \dodoublegroupempty\dodoxmtharrow} +\def\math_arrows_handle[#1][#2][#3]% #3 == optional arg .. \empty can be just 'empty' + {\def\math_arrows_handle_indeed{\math_arrows_handle_finalize[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2} + \dodoublegroupempty\math_arrows_handle_indeed} -\def\dododoxmtharrow[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg +\def\math_arrows_handle_finalize[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg {\edef\!!stringa{#2}% \ifx\!!stringa\empty \ifsecondargument - \mathrel{\domthxarrsingle{#7}{#1}{#4}{#8}{#9}}% + \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{#8}{#9}}% \else - \mathrel{\domthxarrsingle{#7}{#1}{#4}{}{#8}}% + \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{}{#8}}% \fi \else \ifsecondargument - \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{#8}{#9}}% + \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{#8}{#9}}% \else - \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{}{#8}}% + \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{}{#8}}% \fi \fi} @@ -324,40 +280,38 @@ %D \macros{mtharrowfill,defaultmtharrowfill} %D -%D To extend the arrows we need to define a \quotation{math arrow -%D fill}. This command takes 8 arguments: the first four correspond -%D the second argument of \tex{definematharrow} explained above. The -%D other three specify the tail, body and head of the arrow. The last -%D argument specifies the math-mode in which the arrow is drawn. -%D \tex{defaultmtharrowfill} has values tweaked to match Latin Modern -%D fonts. For fonts that are significantly different (e.g. cows) a +%D To extend the arrows we need to define a \quotation {math arrow fill}. This +%D command takes 8 arguments: the first four correspond the second argument of +%D \tex {definematharrow} explained above. The other three specify the tail, +%D body and head of the arrow. The last argument specifies the math-mode in which +%D the arrow is drawn. \tex {defaultmtharrowfill} has values tweaked to match +%D Latin Modern fonts. For fonts that are significantly different (e.g. cows) a %D different set of values need to be determined. \def\mtharrowfill#1#2#3#4#5#6#7#8% - {$\mathsurround 0pt - \thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip + {$\mathsurround\zeropoint + \thickmuskip\zeromuskip\medmuskip\thickmuskip\thinmuskip\thickmuskip \relax#8#5% - \mkern-#1mu - \cleaders\hbox{$#8\mkern -#2mu#6\mkern -#3mu$}\hfill - \mkern-#4mu#7$} + \mkern-#1\onemuskip + \cleaders\hbox{$#8\mkern-#2\onemuskip#6\mkern-#3\onemuskip$}\hfill + \mkern-#4\onemuskip#7$} \def\defaultmtharrowfill{\mtharrowfill 7227} -%D We now define some arrow fills that will be used for defining the -%D arrows. Plain \TEX\ already defines \tex{leftarrowfill} and -%D \tex{rightarrowfill}. The \tex{defaultmtharrowfill} command defines an -%D arrowfill that takes an argument (so that it can also be used -%D with over and under arrows). However the Plain \TEX\ definitions of -%D \tex{leftarrowfill} and \tex{rightarrowfill} do not take this extra -%D argument. To be backward compatible with Plain \TEX, we define two -%D arrowfills: \tex{specrightarrowfill} which takes an extra argument, and -%D \tex{rightarrowfill} which does not. +%D We now define some arrow fills that will be used for defining the arrows. Plain +%D \TEX\ already defines \tex {leftarrowfill} and \tex {rightarrowfill}. The \tex +%D {defaultmtharrowfill} command defines an arrowfill that takes an argument (so +%D that it can also be used with over and under arrows). However the Plain \TEX\ +%D definitions of \tex {leftarrowfill} and \tex {rightarrowfill} do not take this +%D extra argument. To be backward compatible with Plain \TEX, we define two +%D arrowfills: \tex {specrightarrowfill} which takes an extra argument, and \tex +%D {rightarrowfill} which does not. \unexpanded\def\specrightarrowfill {\defaultmtharrowfill \relbar \relbar \rightarrow} \unexpanded\def\specleftarrowfill {\defaultmtharrowfill \leftarrow \relbar \relbar} -\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle} -\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle} +\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle} +\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle} \unexpanded\def\equalfill {\defaultmtharrowfill \Relbar \Relbar \Relbar} \unexpanded\def\Rightarrowfill {\defaultmtharrowfill \Relbar \Relbar \Rightarrow} @@ -382,10 +336,27 @@ \unexpanded\def\doublebond{{\xequal}} \unexpanded\def\triplebond{{\xtriplerel}} -%D Now we define most commonly used arrows. These include arrows -%D defined in \filename{amsmath.sty}, \filename{extarrows.sty}, -%D \filename{extpfel.sty} and \filename{mathtools.sty} packages for -%D \LATEX\ (plus a few more). +%D A bit or arrow juggling: +%D +%D \startbuffer +%D \hbox to \hsize{\rightoverleftarrowfill} +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank + +\unexpanded\def\rightoverleftarrowfill + {\specrightoverleftarrowfill} + +\unexpanded\def\specrightoverleftarrowfill + {\defaultmtharrowfill + \ctxdoublearrowfillleftend + \ctxdoublearrowfillmiddlepart + \ctxdoublearrowfillrightend + \textstyle} + +%D Now we define most commonly used arrows. These include arrows defined in \filename +%D {amsmath.sty}, \filename {extarrows.sty}, \filename {extpfel.sty} and \filename +%D {mathtools.sty} packages for \LATEX\ (plus a few more). \definematharrow [xrightarrow] [0359] [\specrightarrowfill] \definematharrow [xleftarrow] [3095] [\specleftarrowfill] @@ -427,27 +398,27 @@ %D \macros{definemathoverarrow,defineunderarrow} %D -%D These macros for define math-overarrows are adapted from -%D \filename{amsmath.sty} +%D These macros for define math-overarrows are adapted from \filename +%D {amsmath.sty} \unexpanded\def\definemathoverarrow - {\dotripleargument\dodefinemathoverarrow} + {\dotripleargument\math_arrows_define_over} -\def\dodefinemathoverarrow[#1][#2][#3]% +\def\math_arrows_define_over[#1][#2][#3]% {\ifthirdargument - \setuvalue{#1}{\dohandlemathoverarrow[#2][#3]}% + \setuvalue{#1}{\math_arrows_over_handle[#2][#3]}% \else - \setuvalue{#1}{\dohandlemathoverarrow[\zeropoint][#2]}% + \setuvalue{#1}{\math_arrows_over_handle[\zeropoint][#2]}% \fi} -\def\dohandlemathoverarrow[#1][#2]% - {\mathpalette{\dodohandlemathoverarrow{#1}{#2}}} +\def\math_arrows_over_handle[#1][#2]% + {\mathpalette{\math_arrows_over_handle_indeed{#1}{#2}}} -%D Note: \filename{math-pln.tex} has \type{\kern-\onepoint} and -%D \filename{amsmath.sty} does not. We keep the kern amount -%D configurable. This is useful for harpoons. +%D Note: \filename {math-pln.tex} has \type {\kern-\onepoint} and \filename +%D {amsmath.sty} does not. We keep the kern amount configurable. This is useful +%D for harpoons. -\def\dodohandlemathoverarrow#1#2#3#4% +\def\math_arrows_over_handle_indeed#1#2#3#4% {\vbox{\ialign{##\crcr #2#3\crcr \noalign{\kern#1\nointerlineskip}% @@ -456,21 +427,21 @@ %D Now the under arrows \unexpanded\def\definemathunderarrow - {\dotripleargument\dodefinemathunderarrow} + {\dotripleargument\math_arrows_define_over} %D For underarrows the default kern is 0.3ex -\def\dodefinemathunderarrow[#1][#2][#3]% +\def\math_arrows_define_over[#1][#2][#3]% {\ifthirdargument - \setuvalue{#1}{\dohandlemathunderarrow[#2][#3]}% + \setuvalue{#1}{\math_arrows_under_handle[#2][#3]}% \else - \setuvalue{#1}{\dohandlemathunderarrow[0.3ex][#2]}% + \setuvalue{#1}{\math_arrows_under_handle[0.3ex][#2]}% \fi} -\def\dohandlemathunderarrow[#1][#2]% - {\mathpalette{\dodohandlemathunderarrow{#1}{#2}}} +\def\math_arrows_under_handle[#1][#2]% + {\mathpalette{\math_arrows_under_handle_indeed{#1}{#2}}} -\def\dodohandlemathunderarrow#1#2#3#4% +\def\math_arrows_under_handle_indeed#1#2#3#4% {\vtop{\ialign{##\crcr $\mathsurround\zeropoint\hfil#3#4\hfil$\crcr \noalign{\nointerlineskip\kern#1}% diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv index 1c602187f..61153cfdd 100644 --- a/tex/context/base/math-def.mkiv +++ b/tex/context/base/math-def.mkiv @@ -119,7 +119,7 @@ \dorightbigmath#2\relax \else \doleftbigmath#2\relax - \vbox\!!to\getvalue{\??mathbig\number#1}\bodyfontsize{}% + \vbox to\getvalue{\??mathbig\number#1}\bodyfontsize{}% \dorightbigmath#2\relax \fi \nulldelimiterspace\zeropoint\relax @@ -167,7 +167,8 @@ \unexpanded\def\implies {\mathrel{\;\Longrightarrow\;}} \unexpanded\def\impliedby{\mathrel{\;\Longleftarrow\;}} \unexpanded\def\And {\mathrel{\;\internalAnd\;}} -\unexpanded\def\iff {\;\Longleftrightarrow\;} +%unexpanded\def\iff {\;\Longleftrightarrow\;} +\setuvalue {iff}{\;\Longleftrightarrow\;} % nicer for if checker % todo: virtual in math-vfu @@ -222,8 +223,9 @@ \definemathcommand [mathstrut] {\vphantom{(}} \definemathcommand [joinrel] {\mathrel{\mkern-3mu}} -\unexpanded\def\{{\mathortext\lbrace\letterleftbrace } -\unexpanded\def\}{\mathortext\rbrace\letterrightbrace} +\unexpanded\def\{{\mathortext\lbrace\letterleftbrace } % or maybe a chardef +\unexpanded\def\}{\mathortext\rbrace\letterrightbrace} % or maybe a chardef +\unexpanded\def\|{\mathortext\vert \letterbar } % or maybe a chardef %D The following colon related definitions are provided by Aditya %D Mahajan who derived them from \type {mathtools.sty} and \type diff --git a/tex/context/base/math-dim.lua b/tex/context/base/math-dim.lua index a5d7c3963..f4fc7905e 100644 --- a/tex/context/base/math-dim.lua +++ b/tex/context/base/math-dim.lua @@ -128,9 +128,9 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled return table.fastcopy(dimens), { } elseif dimens.AxisHeight or dimens.axis_height then local t = { } - local math_x_height = dimens.x_height or 10*65526 - local math_quad = dimens.quad or 10*65526 - local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65526 + local math_x_height = dimens.x_height or 10*65536 + local math_quad = dimens.quad or 10*65536 + local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65536 dimens["0"] = 0 dimens["60"] = 60 dimens["0.25*default_rule_thickness"] = default_rule_thickness / 4 diff --git a/tex/context/base/math-ext.lua b/tex/context/base/math-ext.lua index da00c7a9e..047543970 100644 --- a/tex/context/base/math-ext.lua +++ b/tex/context/base/math-ext.lua @@ -20,8 +20,11 @@ characters.math = characters.math or { } local mathdata = characters.math local chardata = characters.data -function extras.add(unicode,t) +function extras.add(unicode,t) -- todo: if already stored ... local min, max = mathematics.extrabase, mathematics.privatebase - 1 + -- if mathdata[unicode] or chardata[unicode] then + -- report_math("extra U+%05X overloads existing character",unicode) + -- end if unicode >= min and unicode <= max then mathdata[unicode], chardata[unicode] = t, t else diff --git a/tex/context/base/math-fbk.lua b/tex/context/base/math-fbk.lua new file mode 100644 index 000000000..b2b7ed5f0 --- /dev/null +++ b/tex/context/base/math-fbk.lua @@ -0,0 +1,281 @@ +if not modules then modules = { } end modules ['math-fbk'] = { + 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" +} + +local trace_fallbacks = false trackers.register("math.fallbacks", function(v) trace_fallbacks = v end) + +local report_fallbacks = logs.reporter("math","fallbacks") + +local fallbacks = { } +mathematics.fallbacks = fallbacks + +local virtualcharacters = { } + +local identifiers = fonts.hashes.identifiers +local lastmathids = fonts.hashes.lastmathids + +-- we need a trick (todo): if we define scriptscript, script and text in +-- that order we could use their id's .. i.e. we could always add a font +-- table with those id's .. in fact, we could also add a whole lot more +-- as it doesn't hurt +-- +-- todo: use index 'true when luatex provides that feature (on the agenda) + +function fallbacks.apply(target,original) + local mathparameters = target.mathparameters -- why not hasmath + if mathparameters then + local characters = target.characters + local parameters = target.parameters + local mathsize = parameters.mathsize + local size = parameters.size + local usedfonts = target.fonts + if not usedfonts then + usedfonts = { } + target.fonts = usedfonts + end + -- This is not okay yet ... we have no proper way to refer to 'self' + -- otherwise I will make my own id allocator). +local self = #usedfonts == 0 and font.nextid() or nil -- will be true + local textid, scriptid, scriptscriptid + local textindex, scriptindex, scriptscriptindex + local textdata, scriptdata, scriptscriptdata + if mathsize == 3 then + -- scriptscriptsize + -- textid = nil -- self + -- scriptid = nil -- no smaller + -- scriptscriptid = nil -- no smaller +textid = self +scriptid = self +scriptscriptid = self + elseif mathsize == 2 then + -- scriptsize + -- textid = nil -- self +textid = self + scriptid = lastmathids[3] + scriptscriptid = lastmathids[3] + else + -- textsize + -- textid = nil -- self +textid = self + scriptid = lastmathids[2] + scriptscriptid = lastmathids[3] + end + if textid then + textindex = #usedfonts + 1 + usedfonts[textindex] = { id = textid } + textdata = identifiers[textid] + else + textdata = target + end + if scriptid then + scriptindex = #usedfonts + 1 + usedfonts[scriptindex] = { id = scriptid } + scriptdata = identifiers[scriptid] + else + scriptindex = textindex + scriptdata = textdata + end + if scriptscriptid then + scriptscriptindex = #usedfonts + 1 + usedfonts[scriptscriptindex] = { id = scriptscriptid } + scriptscriptdata = identifiers[scriptscriptid] + else + scriptscriptindex = scriptindex + scriptscriptdata = scriptdata + end +-- report_fallbacks("used textid: %s, used script id: %s, used scriptscript id: %s", +-- tostring(textid),tostring(scriptid),tostring(scriptscriptid)) + local data = { + textdata = textdata, + scriptdata = scriptdata, + scriptscriptdata = scriptscriptdata, + textindex = textindex, + scriptindex = scriptindex, + scriptscriptindex = scriptscriptindex, + characters = characters, + unicode = k, + target = target, + original = original, + size = size, + mathsize = mathsize, + } +-- inspect(usedfonts) + for k, v in next, virtualcharacters do + if not characters[k] then + local tv = type(v) + if tv == "table" then + characters[k] = v + elseif tv == "number" then + characters[k] = characters[v] + elseif tv == "function" then + characters[k] = v(data) + end + if trace_fallbacks then + if characters[k] then + report_fallbacks("extending font %q with U+%05X",target.properties.fullname,k) + end + end + end + end + end +end + +utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply") + +function fallbacks.install(unicode,value) + virtualcharacters[unicode] = value +end + +-- a few examples: + +local function reference(index,char) + if index then + return { "slot", index, char } + else + return { "char", char } + end +end + +local function raised(data,down) + local replacement = data.replacement + local character = data.scriptdata.characters[replacement] + if character then + return { + width = character.width, + height = character.height, + depth = character.depth, + commands = { + { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight + reference(data.scriptindex,replacement) + } + } + end +end + +-- virtualcharacters[0x207A] = 0x2212 +-- virtualcharacters[0x207B] = 0x002B +-- virtualcharacters[0x208A] = 0x2212 +-- virtualcharacters[0x208B] = 0x002B + +virtualcharacters[0x207A] = function(data) + data.replacement = 0x2212 + return raised(data) +end + +virtualcharacters[0x207B] = function(data) + data.replacement = 0x002B + return raised(data) +end + +virtualcharacters[0x208A] = function(data) + data.replacement = 0x2212 + return raised(data,true) +end + +virtualcharacters[0x208B] = function(data) + data.replacement = 0x002B + return raised(data,true) +end + +local addextra = mathematics.extras.add + +addextra(0xFE350, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW LEFT END", + mathclass="relation", + mathname="ctxdoublearrowfillleftend", + unicodeslot=0xFE350, +} ) + +addextra(0xFE351, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW MIDDLE PART", + mathclass="relation", + mathname="ctxdoublearrowfillmiddlepart", + unicodeslot=0xFE351, +} ) + +addextra(0xFE352, { + category="sm", + description="MATHEMATICAL DOUBLE ARROW RIGHT END", + mathclass="relation", + mathname="ctxdoublearrowfillrightend", + unicodeslot=0xFE352, +} ) + +local push = { "push" } +local pop = { "pop" } +local leftarrow = { "char", 0x2190 } +local relbar = { "char", 0x2212 } +local rightarrow = { "char", 0x2192 } + +virtualcharacters[0xFE350] = function(data) + -- return combined(data,0x2190,0x2212) -- leftarrow relbar + local charone = data.characters[0x2190] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + leftarrow, + pop, + { "down", -size/2 }, + relbar, + } + } + end +end + +virtualcharacters[0xFE351] = function(data) + -- return combined(data,0x2212,0x2212) -- relbar, relbar + local char = data.characters[0x2212] + if char then + local size = data.size/2 + return { + width = char.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + relbar, + pop, + { "down", -size/2 }, + relbar, + } + } + end +end + +virtualcharacters[0xFE352] = function(data) + -- return combined(data,0x2192,0x2212) -- rightarrow relbar + local charone = data.characters[0x2192] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + push, + { "down", size/2 }, + relbar, + pop, + { "right", chartwo.width - charone.width }, + { "down", -size/2 }, + rightarrow, + } + } + end +end + diff --git a/tex/context/base/math-for.mkiv b/tex/context/base/math-for.mkiv index aee640572..0c8bd05ae 100644 --- a/tex/context/base/math-for.mkiv +++ b/tex/context/base/math-for.mkiv @@ -30,19 +30,4 @@ \let\setupformulas \setupformula \let\setupsubformulas\setupsubformula -% D \macros -% D {setuptextformulas} -% D -% D This command sets up in||line math. Most features deals -% D with grid snapping and are experimental. - -% \newtoks \everysetuptextformulas -% -% \unexpanded\def\setuptextformulas -% {\dosingleempty\dosetuptextformulas} -% -% \def\dosetuptextformulas[#1]% -% {\getparameters[\??mt][#1]% -% \the\everysetuptextformulas} - \protect \endinput diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 54452282b..c84a92aee 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['math-ext'] = { +if not modules then modules = { } end modules ['math-ini'] = { version = 1.001, comment = "companion to math-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -33,6 +33,8 @@ local mathematics = mathematics mathematics.extrabase = 0xFE000 -- here we push some virtuals mathematics.privatebase = 0xFF000 -- here we push the ex +local chardata = characters.data + local families = allocate { mr = 0, mb = 1, @@ -63,6 +65,14 @@ local classes = allocate { nolop = 1, -- mathnolopcomm @@mathnolopcomm } +local accents = allocate { + topaccent = true, [11] = true, + botaccent = true, [12] = true, + under = true, [13] = true, + over = true, [14] = true, + unknown = false, +} + local codes = allocate { ordinary = 0, [0] = "ordinary", largeoperator = 1, [1] = "largeoperator", @@ -76,6 +86,7 @@ local codes = allocate { mathematics.classes = classes mathematics.codes = codes +-----------.accents = codes mathematics.families = families classes.alphabetic = classes.alpha @@ -99,33 +110,43 @@ classes.number = classes.alphabetic local function delcode(target,family,slot) return format('\\Udelcode%s="%X "%X ',target,family,slot) end + local function mathchar(class,family,slot) return format('\\Umathchar "%X "%X "%X ',class,family,slot) end + local function mathaccent(class,family,slot) return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class end + local function delimiter(class,family,slot) return format('\\Udelimiter "%X "%X "%X ',class,family,slot) end + local function radical(family,slot) return format('\\Uradical "%X "%X ',family,slot) end + local function mathchardef(name,class,family,slot) return format('\\Umathchardef\\%s "%X "%X "%X ',name,class,family,slot) end + local function mathcode(target,class,family,slot) return format('\\Umathcode%s="%X "%X "%X ',target,class,family,slot) end + local function mathtopaccent(class,family,slot) return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class end + local function mathbotaccent(class,family,slot) return format('\\Umathaccent bottom "%X "%X "%X ',0,family,slot) -- no class end + local function mathtopdelimiter(class,family,slot) return format('\\Udelimiterover "%X "%X ',family,slot) -- no class end + local function mathbotdelimiter(class,family,slot) return format('\\Udelimiterunder "%X "%X ',family,slot) -- no class end @@ -156,72 +177,75 @@ if setmathcode then setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing if class == classes.accent then - contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot)) elseif class == classes.topaccent then - contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot)) elseif class == classes.botaccent then - contextsprint(format([[\unexpanded\gdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot)) elseif class == classes.over then - contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterover "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Udelimiterover "%X "%X }]],name,family,slot)) elseif class == classes.under then - contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot)) elseif class == classes.open or class == classes.close then setdelcode(slot,{family,slot,0,0}) - contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot)) + contextsprint(format([[\ugdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot)) elseif class == classes.delimiter then setdelcode(slot,{family,slot,0,0}) - contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot)) elseif class == classes.radical then - contextsprint(format([[\unexpanded\gdef\%s{\Uradical "%X "%X }]],name,family,slot)) + contextsprint(format([[\ugdef\%s{\Uradical "%X "%X }]],name,family,slot)) else -- beware, open/close and other specials should not end up here --- contextsprint(format([[\unexpanded\gdef\%s{\Umathchar "%X "%X "%X }]],name,class,family,slot)) + -- contextsprint(format([[\ugdef\%s{\Umathchar "%X "%X "%X }]],name,class,family,slot)) contextsprint(format([[\Umathchardef\%s "%X "%X "%X ]],name,class,family,slot)) end end - else - setmathcharacter = function(class,family,slot,unicode) - if class <= 7 then - contextsprint(mathcode(slot,class,family,unicode or slot)) - end - end - - setmathsynonym = function(class,family,slot,unicode,setcode) - if setcode and class <= 7 then - contextsprint(mathcode(slot,class,family,unicode)) - end - if class == classes.open or class == classes.close then - contextsprint(delcode(slot,family,unicode)) - end - end - - setmathsymbol = function(name,class,family,slot) - if class == classes.accent then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathaccent(class,family,slot))) - elseif class == classes.topaccent then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopaccent(class,family,slot))) - elseif class == classes.botaccent then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotaccent(class,family,slot))) - elseif class == classes.over then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopdelimiter(class,family,slot))) - elseif class == classes.under then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotdelimiter(class,family,slot))) - elseif class == classes.open or class == classes.close then - contextsprint(delcode(slot,family,slot)) - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(class,family,slot))) - elseif class == classes.delimiter then - contextsprint(delcode(slot,family,slot)) - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(0,family,slot))) - elseif class == classes.radical then - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,radical(family,slot))) - else - -- beware, open/close and other specials should not end up here - contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathchar(class,family,slot))) - end - end + report_math("your version of luatex is to old") + + os.exit() + + -- setmathcharacter = function(class,family,slot,unicode) + -- if class <= 7 then + -- contextsprint(mathcode(slot,class,family,unicode or slot)) + -- end + -- end + -- + -- setmathsynonym = function(class,family,slot,unicode,setcode) + -- if setcode and class <= 7 then + -- contextsprint(mathcode(slot,class,family,unicode)) + -- end + -- if class == classes.open or class == classes.close then + -- contextsprint(delcode(slot,family,unicode)) + -- end + -- end + -- + -- setmathsymbol = function(name,class,family,slot) + -- if class == classes.accent then + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathaccent(class,family,slot))) + -- elseif class == classes.topaccent then + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathtopaccent(class,family,slot))) + -- elseif class == classes.botaccent then + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathbotaccent(class,family,slot))) + -- elseif class == classes.over then + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathtopdelimiter(class,family,slot))) + -- elseif class == classes.under then + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathbotdelimiter(class,family,slot))) + -- elseif class == classes.open or class == classes.close then + -- contextsprint(delcode(slot,family,slot)) + -- contextsprint(format([[\uxdef\%s{%s}]],name,delimiter(class,family,slot))) + -- elseif class == classes.delimiter then + -- contextsprint(delcode(slot,family,slot)) + -- contextsprint(format([[\uxdef\%s{%s}]],name,delimiter(0,family,slot))) + -- elseif class == classes.radical then + -- contextsprint(format([[\uxdef\%s{%s}]],name,radical(family,slot))) + -- else + -- -- beware, open/close and other specials should not end up here + -- contextsprint(format([[\uxdef\%s{%s}]],name,mathchar(class,family,slot))) + -- end + -- end end @@ -330,23 +354,29 @@ end -- needed for mathml analysis local function utfmathclass(chr, default) - local cd = characters.data[utfbyte(chr)] + local cd = chardata[utfbyte(chr)] return (cd and cd.mathclass) or default or "unknown" end +local function utfmathaccent(chr, default) + local cd = chardata[utfbyte(chr)] + local mc = cd and cd.mathclass or "unknown" + return mc and accents[mc] or false +end + local function utfmathstretch(chr, default) -- "h", "v", "b", "" - local cd = characters.data[utfbyte(chr)] + local cd = chardata[utfbyte(chr)] return (cd and cd.mathstretch) or default or "" end local function utfmathcommand(chr, default) - local cd = characters.data[utfbyte(chr)] + local cd = chardata[utfbyte(chr)] local cmd = cd and cd.mathname return cmd or default or "" end local function utfmathfiller(chr, default) - local cd = characters.data[utfbyte(chr)] + local cd = chardata[utfbyte(chr)] local cmd = cd and (cd.mathfiller or cd.mathname) return cmd or default or "" end @@ -363,6 +393,9 @@ function commands.utfmathstretch(chr) context(utfmathstretch(chr)) end function commands.utfmathcommand(chr) context(utfmathcommand(chr)) end function commands.utfmathfiller (chr) context(utfmathfiller (chr)) end +function commands.doifelseutfmathaccent(chr) + commands.doifelse(utfmathaccent(chr)) +end -- helpers diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv index 710a65f5b..77441e092 100644 --- a/tex/context/base/math-ini.mkiv +++ b/tex/context/base/math-ini.mkiv @@ -27,14 +27,6 @@ \unprotect -\ifdefined\v!autopunctuation \else \def\v!autopunctuation{autopunctuation} \fi -\ifdefined\v!integral \else \def\v!integral {integral} \fi - -\def\s!lcgreek {lcgreek} -\def\s!ucgreek {ucgreek} -\def\s!italics {italics} -\def\s!integral{integral} - %D We move these definitions into the format: % test [[\char948 \cldcontext{utf.char(948)}]] @@ -45,10 +37,12 @@ \registerctxluafile{math-act}{1.001} \registerctxluafile{math-ext}{1.001} \registerctxluafile{math-vfu}{1.001} +\registerctxluafile{math-ttv}{1.001} \registerctxluafile{math-map}{1.001} \registerctxluafile{math-ren}{1.001} \registerctxluafile{math-noa}{1.001} \registerctxluafile{math-tag}{1.001} +\registerctxluafile{math-fbk}{1.001} \definesystemattribute[mathalphabet] [public] \definesystemattribute[mathsize] [public] @@ -60,6 +54,8 @@ \definesystemattribute[mathmode] [public] \definesystemattribute[mathitalics] [public] +\definesystemattribute[displaymath] [public] + \appendtoks \attribute\mathmodeattribute\plusone \to \everydisplay @@ -68,6 +64,10 @@ \attribute\mathmodeattribute\plusone \to \everybeforedisplayformula +\appendtoksonce + \attribute\displaymathattribute\plusone +\to \everybeforedisplayformula + \setnewconstant\defaultmathfamily \zerocount % 255 %D Some measures (maybe spac-mth): @@ -82,18 +82,6 @@ %D Configuration for integrals. (If needed we can speed this up and make it %D installable; no processaction is needed then). -% \newtoks\everysetupmathematics -% -% \unexpanded\def\setupmathematics -% {\dosingleargument\dosetupmathematics} -% -% \def\dosetupmathematics[#1]% -% {\getparameters[\??mo][#1]% -% \the\everysetupmathematics} -% -% \def\mathematicsparameter#1% -% {\ifcsname\??mo#1\endcsname\csname\??mo#1\endcsname\fi} - \installcorenamespace{mathematics} \installswitchcommandhandler \??mathematics {mathematics} \??mathematics @@ -265,13 +253,15 @@ \def\utfmathcommand#1{\ctxcommand{utfmathcommand(\!!bs#1\!!es)}} \def\utfmathfiller #1{\ctxcommand{utfmathfiller (\!!bs#1\!!es)}} +\unexpanded\def\doifelseutfmathaccent#1{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es)}} + %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} +\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} \let\mathnothing\firstofoneunexpanded \let\mathalpha \firstofoneunexpanded @@ -857,15 +847,16 @@ \c_math_italics_attribute\csname\??mathitalics \ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi \endcsname\relax - \math_italics_initialize + % \math_italics_initialize \to \everyswitchmathematics % only in mathematics \appendtoks + \math_italics_initialize \attribute\mathitalicsattribute\c_math_italics_attribute \to \everymathematics \setupmathematics - [\s!italics=] + [\s!italics=4] % looks nicer but can generate bogus csnames % diff --git a/tex/context/base/math-int.mkiv b/tex/context/base/math-int.mkiv index 84c51cb24..8699cbc1c 100644 --- a/tex/context/base/math-int.mkiv +++ b/tex/context/base/math-int.mkiv @@ -38,7 +38,7 @@ \installcorenamespace{mathintegral} -\newconstant\mathintlimitmode % 0 nolimits 1 displaylimits 2 limits +\newconstant\mathintlimitmode \def\intlimits % also used elsewhere {\ifcase\mathintlimitmode @@ -47,18 +47,29 @@ \displaylimits \or \limits + \or + % auto + \ifcase\normalmathstyle\displaylimits\or\displaylimits\else\limits\fi + % \ifnum\attribute\mathmodeattribute=\plusone % we need a proper flag + % \displaylimits + % \else + % \limits + % \fi \fi} \letvalue{\??mathintegral nolimits}\zerocount \letvalue{\??mathintegral displaylimits}\plusone \letvalue{\??mathintegral limits}\plustwo +\letvalue{\??mathintegral autolimits}\plusthree +\letvalue{\??mathintegral none}\plusfour \appendtoks \mathintlimitmode\executeifdefined{\??mathintegral\mathematicsparameter\s!integral}\zerocount \to \everyswitchmathematics \setupmathematics - [\v!integral=nolimits] +% [\v!integral=nolimits] + [\v!integral=autolimits] %D The following code is used for fallbacks and might become obsolete once %D we have enough \OPENTYPE\ math fonts. diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua index 8caf21cc2..6643a8758 100644 --- a/tex/context/base/math-noa.lua +++ b/tex/context/base/math-noa.lua @@ -56,11 +56,14 @@ local has_attribute = node.has_attribute local mlist_to_hlist = node.mlist_to_hlist local font_of_family = node.family_font local insert_node_after = node.insert_after +local insert_node_before = node.insert_before local free_node = node.free local new_node = node.new -- todo: pool: math_noad math_sub local new_kern = nodes.pool.kern +local topoints = number.topoints + local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers local fontcharacters = fonthashes.characters @@ -103,6 +106,9 @@ local math_style = nodecodes.style -- attr style local math_choice = nodecodes.choice -- attr display text script scriptscript local math_fence = nodecodes.fence -- attr subtype +local hlist_code = nodecodes.hlist +local glyph_code = nodecodes.glyph + local left_fence_code = 1 local function process(start,what,n,parent) @@ -758,61 +764,104 @@ local a_mathitalics = attributes.private("mathitalics") local italics = { } local default_factor = 1/20 -italics[math_char] = function(pointer,what,n,parent) - local method = has_attribute(pointer,a_mathitalics) - if method and method > 0 then - local char = pointer.char - local font = font_of_family(pointer.fam) -- todo: table - local correction - if method == 1 then - -- only font data triggered by fontitalics - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - correction = character and character.italic_correction -- or character.italic (this one is for tex) - end - elseif method == 2 then - -- only font data triggered by fontdata + +local function getcorrection(method,font,char) + + local correction + + if method == 1 then + -- only font data triggered by fontitalics + local italics = fontitalics[font] + if italics then local character = fontcharacters[font][char] correction = character and character.italic_correction -- or character.italic (this one is for tex) - elseif method == 3 then - -- only quad based by selective + end + elseif method == 2 then + -- only font data triggered by fontdata + local character = fontcharacters[font][char] + correction = character and character.italic_correction -- or character.italic (this one is for tex) + elseif method == 3 then + -- only quad based by selective + local visual = chardata[char].visual + if not visual then + -- skip + elseif visual == "it" or visual == "bi" then + correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font] + end + elseif method == 4 then + -- combination of 1 and 3 + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + correction = character and character.italic_correction -- or character.italic (this one is for tex) + end + if not correction then local visual = chardata[char].visual if not visual then -- skip elseif visual == "it" or visual == "bi" then correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font] end - elseif method == 4 then - -- combination of 1 and 3 - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - correction = character and character.italic_correction -- or character.italic (this one is for tex) - end - if not correction then - local visual = chardata[char].visual - if not visual then - -- skip - elseif visual == "it" or visual == "bi" then - correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font] - end - end end - if correction and correction ~= 0 then - local next_noad = parent.next - if next_noad and next_noad.id == math_noad then - local next_subtype = next_noad.subtype - if next_subtype == noad_punct or next_subtype == noad_ord then - local next_nucleus = next_noad.nucleus - if next_nucleus.id == math_char then - local next_char = next_nucleus.char - if not chardata[next_char].italic then -- or category - if trace_italics then - report_italics("method %s: adding %s italic correction between %s (0x%05X) and %s (0x%05X)", - method,number.points(correction),utfchar(char),char,utfchar(next_char),next_char) + end + + if correction and correction ~= 0 then + return correction + end + +end + +local function insert_kern(current,kern) + local sub = new_node(math_sub) -- todo: pool + local noad = new_node(math_noad) -- todo: pool + sub.head = kern + kern.next = noad + noad.nucleus = current + return sub +end + +italics[math_char] = function(pointer,what,n,parent) + local method = has_attribute(pointer,a_mathitalics) + if method and method > 0 then + local char = pointer.char + local font = font_of_family(pointer.fam) -- todo: table + local correction = getcorrection(method,font,char) + + -- maybe also correction when next == nil + -- when sub/sup -> already done + + if correction then + if parent.id == math_noad and (parent.sub or parent.sup) then + if sub then + parent.sub = insert_kern(sub,new_kern(correction)) + end + local sup = parent.sup + if sup then + parent.sup = insert_kern(sup,new_kern(correction)) + end + else + local next_noad = parent.next + if not next_noad then + if true then -- this might become an option + if trace_italics then + report_italics("method %s: adding %s italic correction between %s (0x%05X) and end math", + method,number.points(correction),utfchar(char),char) + end + insert_node_after(parent,parent,new_kern(correction)) + end + elseif next_noad.id == math_noad then + local next_subtype = next_noad.subtype + if next_subtype == noad_punct or next_subtype == noad_ord then + local next_nucleus = next_noad.nucleus + if next_nucleus.id == math_char then + local next_char = next_nucleus.char + if not chardata[next_char].italic then -- or category + if trace_italics then + report_italics("method %s: adding %s italic correction between %s (0x%05X) and %s (0x%05X)", + method,number.points(correction),utfchar(char),char,utfchar(next_char),next_char) + end + insert_node_after(parent,parent,new_kern(correction)) end - insert_node_after(parent,parent,new_kern(correction)) end end end @@ -821,7 +870,27 @@ italics[math_char] = function(pointer,what,n,parent) end end +-- italics[math_noad] = function(pointer,what,n,parent) +-- local nucleus = pointer.nucleus +-- if nucleus.id == math_char then +-- local method = has_attribute(pointer,a_mathitalics) +-- if method and method > 0 then +-- local char = nucleus.char +-- local font = font_of_family(nucleus.fam) -- todo: table +-- local correction = getcorrection(method,font,char) +-- if correction then +-- if trace_italics then +-- report_italics("method %s: adding %s italic correction between %s (0x%05X) and script", +-- method,number.points(correction),utfchar(char),char) +-- end +-- insert_node_after(nucleus,nucleus,new_kern(correction)) +-- end +-- end +-- end +-- end + function handlers.italics(head,style,penalties) +-- nodes.showsimplelist(head) processnoads(head,italics,"italics") return true end @@ -836,6 +905,66 @@ enable = function() enable = false end +-- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- + +-- -- nice but not okay with multiple scripts (we need more clever hlist-shift checking then +-- +-- local function processitalics(head,previous,previousmethod) +-- local current = head +-- while current do +-- local id = current.id +-- if id == glyph_code then +-- local method = has_attribute(current,a_mathitalics) +-- if method and method > 0 then -- keep method of previous +-- if previous then +-- local previousfont = previous.font +-- local previouschar = previous.char +-- local currentchar = current.char +-- local correction = getcorrection(previousmethod,previousfont,previouschar) +-- if correction then +-- if trace_italics then +-- report_italics("correction %s between U+%05X and U+%05X using method",topoints(correction),previouschar,currentchar,previousmethod) +-- end +-- insert_node_after(previous,previous,new_kern(correction)) +-- else +-- if trace_italics then +-- report_italics("no correction between U+%05X and U+%05X",previouschar,currentchar) +-- end +-- end +-- end +-- previous, previousmethod = current, method +-- end +-- elseif id == hlist_code then +-- previous, previousmethod = processitalics(current.list,previous,previousmethod) +-- elseif id == vlist_code then +-- previous, previousmethod = processitalics(current.list,previous,previousmethod) +-- else +-- previous, previousmethod = nil +-- end +-- current = current.next +-- end +-- return previous, previousmethod +-- end +-- +-- function handlers.italics(head,style,penalties) +-- processitalics(head) +-- return true +-- end +-- +-- local enable +-- +-- enable = function() +-- tasks.enableaction("math", "noads.handlers.italics") +-- if trace_italics then +-- report_italics("enabling math italics") +-- end +-- enable = false +-- end + +-- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- + -- best do this only on math mode (less overhead) function mathematics.setitalics(n) diff --git a/tex/context/base/math-ttv.lua b/tex/context/base/math-ttv.lua new file mode 100644 index 000000000..be7d1949b --- /dev/null +++ b/tex/context/base/math-ttv.lua @@ -0,0 +1,799 @@ +if not modules then modules = { } end modules ['math-ttv'] = { + version = 1.001, + comment = "traditional tex vectors, companion to math-vfu.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", + dataonly = true, +} + +local vfmath = fonts.handlers.vf.math +local setletters = vfmath.setletters +local setdigits = vfmath.setdigits + +local mathencodings = fonts.encodings.math + +-- varphi is part of the alphabet, contrary to the other var*s' + +mathencodings["large-to-small"] = { + [0x00028] = 0x00, -- ( + [0x00029] = 0x01, -- ) + [0x0005B] = 0x02, -- [ + [0x0005D] = 0x03, -- ] + [0x0230A] = 0x04, -- lfloor + [0x0230B] = 0x05, -- rfloor + [0x02308] = 0x06, -- lceil + [0x02309] = 0x07, -- rceil + [0x0007B] = 0x08, -- { + [0x0007D] = 0x09, -- } + [0x027E8] = 0x0A, -- < + [0x027E9] = 0x0B, -- > + [0x0007C] = 0x0C, -- | +--~ [0x0] = 0x0D, -- lVert rVert Vert +-- [0x0002F] = 0x0E, -- / + [0x0005C] = 0x0F, -- \ +--~ [0x0] = 0x3A, -- lgroup +--~ [0x0] = 0x3B, -- rgroup +--~ [0x0] = 0x3C, -- arrowvert +--~ [0x0] = 0x3D, -- Arrowvert + [0x02195] = 0x3F, -- updownarrow +--~ [0x0] = 0x40, -- lmoustache +--~ [0x0] = 0x41, -- rmoustache + [0x0221A] = 0x70, -- sqrt + [0x021D5] = 0x77, -- Updownarrow + [0x02191] = 0x78, -- uparrow + [0x02193] = 0x79, -- downarrow + [0x021D1] = 0x7E, -- Uparrow + [0x021D3] = 0x7F, -- Downarrow + [0x0220F] = 0x59, -- prod + [0x02210] = 0x61, -- coprod + [0x02211] = 0x58, -- sum + [0x0222B] = 0x5A, -- intop + [0x0222E] = 0x49, -- ointop + [0xFE302] = 0x62, -- widehat + [0xFE303] = 0x65, -- widetilde + [0x022C0] = 0x5E, -- bigwedge + [0x022C1] = 0x5F, -- bigvee + [0x022C2] = 0x5C, -- bigcap + [0x022C3] = 0x5B, -- bigcup + [0x02044] = 0x0E, -- / +} + +-- Beware: these are (in cm/lm) below the baseline due to limitations +-- in the tfm format bu the engien (combined with the mathclass) takes +-- care of it. If we need them in textmode, we should make them virtual +-- and move them up but we're in no hurry with that. + +mathencodings["tex-ex"] = { + [0x0220F] = 0x51, -- prod + [0x02210] = 0x60, -- coprod + [0x02211] = 0x50, -- sum + [0x0222B] = 0x52, -- intop + [0x0222E] = 0x48, -- ointop + [0x022C0] = 0x56, -- bigwedge + [0x022C1] = 0x57, -- bigvee + [0x022C2] = 0x54, -- bigcap + [0x022C3] = 0x53, -- bigcup + [0x02A00] = 0x4A, -- bigodot -- fixed BJ + [0x02A01] = 0x4C, -- bigoplus + [0x02A02] = 0x4E, -- bigotimes + -- [0x02A03] = , -- bigudot -- + [0x02A04] = 0x55, -- biguplus + [0x02A06] = 0x46, -- bigsqcup +} + +-- only math stuff is needed, since we always use an lm or gyre +-- font as main font + +mathencodings["tex-mr"] = { + [0x00393] = 0x00, -- Gamma + [0x00394] = 0x01, -- Delta + [0x00398] = 0x02, -- Theta + [0x0039B] = 0x03, -- Lambda + [0x0039E] = 0x04, -- Xi + [0x003A0] = 0x05, -- Pi + [0x003A3] = 0x06, -- Sigma + [0x003A5] = 0x07, -- Upsilon + [0x003A6] = 0x08, -- Phi + [0x003A8] = 0x09, -- Psi + [0x003A9] = 0x0A, -- Omega +-- [0x00060] = 0x12, -- [math]grave +-- [0x000B4] = 0x13, -- [math]acute +-- [0x002C7] = 0x14, -- [math]check +-- [0x002D8] = 0x15, -- [math]breve +-- [0x000AF] = 0x16, -- [math]bar +-- [0x00021] = 0x21, -- ! +-- [0x00028] = 0x28, -- ( +-- [0x00029] = 0x29, -- ) +-- [0x0002B] = 0x2B, -- + +-- [0x0002F] = 0x2F, -- / +-- [0x0003A] = 0x3A, -- : +-- [0x02236] = 0x3A, -- colon +-- [0x0003B] = 0x3B, -- ; +-- [0x0003C] = 0x3C, -- < +-- [0x0003D] = 0x3D, -- = +-- [0x0003E] = 0x3E, -- > +-- [0x0003F] = 0x3F, -- ? + [0x00391] = 0x41, -- Alpha + [0x00392] = 0x42, -- Beta + [0x02145] = 0x44, + [0x00395] = 0x45, -- Epsilon + [0x00397] = 0x48, -- Eta + [0x00399] = 0x49, -- Iota + [0x0039A] = 0x4B, -- Kappa + [0x0039C] = 0x4D, -- Mu + [0x0039D] = 0x4E, -- Nu + [0x0039F] = 0x4F, -- Omicron + [0x003A1] = 0x52, -- Rho + [0x003A4] = 0x54, -- Tau + [0x003A7] = 0x58, -- Chi + [0x00396] = 0x5A, -- Zeta +-- [0x0005B] = 0x5B, -- [ +-- [0x0005D] = 0x5D, -- ] +-- [0x0005E] = 0x5E, -- [math]hat -- the text one + [0x00302] = 0x5E, -- [math]hat -- the real math one +-- [0x002D9] = 0x5F, -- [math]dot + [0x02146] = 0x64, + [0x02147] = 0x65, +-- [0x002DC] = 0x7E, -- [math]tilde -- the text one + [0x00303] = 0x7E, -- [math]tilde -- the real one +-- [0x000A8] = 0x7F, -- [math]ddot +} + +mathencodings["tex-mr-missing"] = { + [0x02236] = 0x3A, -- colon +} + +mathencodings["tex-mi"] = { + [0x1D6E4] = 0x00, -- Gamma + [0x1D6E5] = 0x01, -- Delta + [0x1D6E9] = 0x02, -- Theta + [0x1D6F3] = 0x02, -- varTheta (not present in TeX) + [0x1D6EC] = 0x03, -- Lambda + [0x1D6EF] = 0x04, -- Xi + [0x1D6F1] = 0x05, -- Pi + [0x1D6F4] = 0x06, -- Sigma + [0x1D6F6] = 0x07, -- Upsilon + [0x1D6F7] = 0x08, -- Phi + [0x1D6F9] = 0x09, -- Psi + [0x1D6FA] = 0x0A, -- Omega + [0x1D6FC] = 0x0B, -- alpha + [0x1D6FD] = 0x0C, -- beta + [0x1D6FE] = 0x0D, -- gamma + [0x1D6FF] = 0x0E, -- delta + [0x1D716] = 0x0F, -- epsilon TODO: 1D716 + [0x1D701] = 0x10, -- zeta + [0x1D702] = 0x11, -- eta + [0x1D703] = 0x12, -- theta TODO: 1D703 + [0x1D704] = 0x13, -- iota + [0x1D705] = 0x14, -- kappa + [0x1D718] = 0x14, -- varkappa, not in tex fonts + [0x1D706] = 0x15, -- lambda + [0x1D707] = 0x16, -- mu + [0x1D708] = 0x17, -- nu + [0x1D709] = 0x18, -- xi + [0x1D70B] = 0x19, -- pi + [0x1D70C] = 0x1A, -- rho + [0x1D70E] = 0x1B, -- sigma + [0x1D70F] = 0x1C, -- tau + [0x1D710] = 0x1D, -- upsilon + [0x1D719] = 0x1E, -- phi + [0x1D712] = 0x1F, -- chi + [0x1D713] = 0x20, -- psi + [0x1D714] = 0x21, -- omega + [0x1D700] = 0x22, -- varepsilon (the other way around) + [0x1D717] = 0x23, -- vartheta + [0x1D71B] = 0x24, -- varpi + [0x1D71A] = 0x25, -- varrho + [0x1D70D] = 0x26, -- varsigma + [0x1D711] = 0x27, -- varphi (the other way around) + [0x021BC] = 0x28, -- leftharpoonup + [0x021BD] = 0x29, -- leftharpoondown + [0x021C0] = 0x2A, -- rightharpoonup + [0x021C1] = 0x2B, -- rightharpoondown + [0xFE322] = 0x2C, -- lhook (hook for combining arrows) + [0xFE323] = 0x2D, -- rhook (hook for combining arrows) + [0x025B7] = 0x2E, -- triangleright : cf lmmath / BJ + [0x025C1] = 0x2F, -- triangleleft : cf lmmath / BJ + [0x022B3] = 0x2E, -- triangleright : cf lmmath this a cramped triangles / BJ / see * + [0x022B2] = 0x2F, -- triangleleft : cf lmmath this a cramped triangles / BJ / see * +-- [0x00041] = 0x30, -- 0 +-- [0x00041] = 0x31, -- 1 +-- [0x00041] = 0x32, -- 2 +-- [0x00041] = 0x33, -- 3 +-- [0x00041] = 0x34, -- 4 +-- [0x00041] = 0x35, -- 5 +-- [0x00041] = 0x36, -- 6 +-- [0x00041] = 0x37, -- 7 +-- [0x00041] = 0x38, -- 8 +-- [0x00041] = 0x39, -- 9 +--~ [0x0002E] = 0x3A, -- . + [0x0002C] = 0x3B, -- , + [0x0003C] = 0x3C, -- < +-- [0x0002F] = 0x3D, -- /, slash, solidus + [0x02044] = 0x3D, -- / AM: Not sure + [0x0003E] = 0x3E, -- > + [0x022C6] = 0x3F, -- star + [0x02202] = 0x40, -- partial +-- + [0x0266D] = 0x5B, -- flat + [0x0266E] = 0x5C, -- natural + [0x0266F] = 0x5D, -- sharp + [0x02323] = 0x5E, -- smile + [0x02322] = 0x5F, -- frown + [0x02113] = 0x60, -- ell +-- + [0x1D6A4] = 0x7B, -- imath (TODO: also 0131) + [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237) + [0x02118] = 0x7D, -- wp + [0x020D7] = 0x7E, -- vec (TODO: not sure) +-- 0x7F, -- (no idea what that could be) +} + +mathencodings["tex-it"] = { +-- [0x1D434] = 0x41, -- A + [0x1D6E2] = 0x41, -- Alpha +-- [0x1D435] = 0x42, -- B + [0x1D6E3] = 0x42, -- Beta +-- [0x1D436] = 0x43, -- C +-- [0x1D437] = 0x44, -- D +-- [0x1D438] = 0x45, -- E + [0x1D6E6] = 0x45, -- Epsilon +-- [0x1D439] = 0x46, -- F +-- [0x1D43A] = 0x47, -- G +-- [0x1D43B] = 0x48, -- H + [0x1D6E8] = 0x48, -- Eta +-- [0x1D43C] = 0x49, -- I + [0x1D6EA] = 0x49, -- Iota +-- [0x1D43D] = 0x4A, -- J +-- [0x1D43E] = 0x4B, -- K + [0x1D6EB] = 0x4B, -- Kappa +-- [0x1D43F] = 0x4C, -- L +-- [0x1D440] = 0x4D, -- M + [0x1D6ED] = 0x4D, -- Mu +-- [0x1D441] = 0x4E, -- N + [0x1D6EE] = 0x4E, -- Nu +-- [0x1D442] = 0x4F, -- O + [0x1D6F0] = 0x4F, -- Omicron +-- [0x1D443] = 0x50, -- P + [0x1D6F2] = 0x50, -- Rho +-- [0x1D444] = 0x51, -- Q +-- [0x1D445] = 0x52, -- R +-- [0x1D446] = 0x53, -- S +-- [0x1D447] = 0x54, -- T + [0x1D6F5] = 0x54, -- Tau +-- [0x1D448] = 0x55, -- U +-- [0x1D449] = 0x56, -- V +-- [0x1D44A] = 0x57, -- W +-- [0x1D44B] = 0x58, -- X + [0x1D6F8] = 0x58, -- Chi +-- [0x1D44C] = 0x59, -- Y +-- [0x1D44D] = 0x5A, -- Z +-- +-- [0x1D44E] = 0x61, -- a +-- [0x1D44F] = 0x62, -- b +-- [0x1D450] = 0x63, -- c +-- [0x1D451] = 0x64, -- d +-- [0x1D452] = 0x65, -- e +-- [0x1D453] = 0x66, -- f +-- [0x1D454] = 0x67, -- g +-- [0x1D455] = 0x68, -- h + [0x0210E] = 0x68, -- Planck constant (h) +-- [0x1D456] = 0x69, -- i +-- [0x1D457] = 0x6A, -- j +-- [0x1D458] = 0x6B, -- k +-- [0x1D459] = 0x6C, -- l +-- [0x1D45A] = 0x6D, -- m +-- [0x1D45B] = 0x6E, -- n +-- [0x1D45C] = 0x6F, -- o + [0x1D70A] = 0x6F, -- omicron +-- [0x1D45D] = 0x70, -- p +-- [0x1D45E] = 0x71, -- q +-- [0x1D45F] = 0x72, -- r +-- [0x1D460] = 0x73, -- s +-- [0x1D461] = 0x74, -- t +-- [0x1D462] = 0x75, -- u +-- [0x1D463] = 0x76, -- v +-- [0x1D464] = 0x77, -- w +-- [0x1D465] = 0x78, -- x +-- [0x1D466] = 0x79, -- y +-- [0x1D467] = 0x7A, -- z +} + +mathencodings["tex-ss"] = { } +mathencodings["tex-tt"] = { } +mathencodings["tex-bf"] = { } +mathencodings["tex-bi"] = { } +mathencodings["tex-fraktur"] = { } +mathencodings["tex-fraktur-bold"] = { } + +mathencodings["tex-sy"] = { + [0x0002D] = 0x00, -- - + [0x02212] = 0x00, -- - +-- [0x02201] = 0x00, -- complement +-- [0x02206] = 0x00, -- increment +-- [0x02204] = 0x00, -- not exists +-- [0x000B7] = 0x01, -- cdot + [0x022C5] = 0x01, -- cdot + [0x000D7] = 0x02, -- times + [0x0002A] = 0x03, -- * + [0x02217] = 0x03, -- * + [0x000F7] = 0x04, -- div + [0x022C4] = 0x05, -- diamond + [0x000B1] = 0x06, -- pm + [0x02213] = 0x07, -- mp + [0x02295] = 0x08, -- oplus + [0x02296] = 0x09, -- ominus + [0x02297] = 0x0A, -- otimes + [0x02298] = 0x0B, -- oslash + [0x02299] = 0x0C, -- odot + [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo + [0x02218] = 0x0E, -- circ + [0x02219] = 0x0F, -- bullet + [0x02022] = 0x0F, -- bullet + [0x0224D] = 0x10, -- asymp + [0x02261] = 0x11, -- equiv + [0x02286] = 0x12, -- subseteq + [0x02287] = 0x13, -- supseteq + [0x02264] = 0x14, -- leq + [0x02265] = 0x15, -- geq + [0x02AAF] = 0x16, -- preceq +-- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF + [0x02AB0] = 0x17, -- succeq +-- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0 + [0x0223C] = 0x18, -- sim + [0x02248] = 0x19, -- approx + [0x02282] = 0x1A, -- subset + [0x02283] = 0x1B, -- supset + [0x0226A] = 0x1C, -- ll + [0x0226B] = 0x1D, -- gg + [0x0227A] = 0x1E, -- prec + [0x0227B] = 0x1F, -- succ + [0x02190] = 0x20, -- leftarrow + [0x02192] = 0x21, -- rightarrow +--~ [0xFE190] = 0x20, -- leftarrow +--~ [0xFE192] = 0x21, -- rightarrow + [0x02191] = 0x22, -- uparrow + [0x02193] = 0x23, -- downarrow + [0x02194] = 0x24, -- leftrightarrow + [0x02197] = 0x25, -- nearrow + [0x02198] = 0x26, -- searrow + [0x02243] = 0x27, -- simeq + [0x021D0] = 0x28, -- Leftarrow + [0x021D2] = 0x29, -- Rightarrow + [0x021D1] = 0x2A, -- Uparrow + [0x021D3] = 0x2B, -- Downarrow + [0x021D4] = 0x2C, -- Leftrightarrow + [0x02196] = 0x2D, -- nwarrow + [0x02199] = 0x2E, -- swarrow + [0x0221D] = 0x2F, -- propto + [0x02032] = 0x30, -- prime + [0x0221E] = 0x31, -- infty + [0x02208] = 0x32, -- in + [0x0220B] = 0x33, -- ni + [0x025B3] = 0x34, -- triangle, bigtriangleup + [0x025BD] = 0x35, -- bigtriangledown + [0x00338] = 0x36, -- not +-- 0x37, -- (beginning of arrow) + [0x02200] = 0x38, -- forall + [0x02203] = 0x39, -- exists + [0x000AC] = 0x3A, -- neg, lnot + [0x02205] = 0x3B, -- empty set + [0x0211C] = 0x3C, -- Re + [0x02111] = 0x3D, -- Im + [0x022A4] = 0x3E, -- top + [0x022A5] = 0x3F, -- bot, perp + [0x02135] = 0x40, -- aleph + [0x1D49C] = 0x41, -- script A + [0x0212C] = 0x42, -- script B + [0x1D49E] = 0x43, -- script C + [0x1D49F] = 0x44, -- script D + [0x02130] = 0x45, -- script E + [0x02131] = 0x46, -- script F + [0x1D4A2] = 0x47, -- script G + [0x0210B] = 0x48, -- script H + [0x02110] = 0x49, -- script I + [0x1D4A5] = 0x4A, -- script J + [0x1D4A6] = 0x4B, -- script K + [0x02112] = 0x4C, -- script L + [0x02133] = 0x4D, -- script M + [0x1D4A9] = 0x4E, -- script N + [0x1D4AA] = 0x4F, -- script O + [0x1D4AB] = 0x50, -- script P + [0x1D4AC] = 0x51, -- script Q + [0x0211B] = 0x52, -- script R + [0x1D4AE] = 0x53, -- script S + [0x1D4AF] = 0x54, -- script T + [0x1D4B0] = 0x55, -- script U + [0x1D4B1] = 0x56, -- script V + [0x1D4B2] = 0x57, -- script W + [0x1D4B3] = 0x58, -- script X + [0x1D4B4] = 0x59, -- script Y + [0x1D4B5] = 0x5A, -- script Z + [0x0222A] = 0x5B, -- cup + [0x02229] = 0x5C, -- cap + [0x0228E] = 0x5D, -- uplus + [0x02227] = 0x5E, -- wedge, land + [0x02228] = 0x5F, -- vee, lor + [0x022A2] = 0x60, -- vdash + [0x022A3] = 0x61, -- dashv + [0x0230A] = 0x62, -- lfloor + [0x0230B] = 0x63, -- rfloor + [0x02308] = 0x64, -- lceil + [0x02309] = 0x65, -- rceil + [0x0007B] = 0x66, -- {, lbrace + [0x0007D] = 0x67, -- }, rbrace + [0x027E8] = 0x68, -- <, langle + [0x027E9] = 0x69, -- >, rangle + [0x0007C] = 0x6A, -- |, mid, lvert, rvert + [0x02225] = 0x6B, -- parallel + -- [0x02016] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert + [0x02195] = 0x6C, -- updownarrow + [0x021D5] = 0x6D, -- Updownarrow + [0x0005C] = 0x6E, -- \, backslash, setminus + [0x02216] = 0x6E, -- setminus + [0x02240] = 0x6F, -- wr + [0x0221A] = 0x70, -- sqrt. AM: Check surd?? + [0x02A3F] = 0x71, -- amalg + [0x1D6FB] = 0x72, -- nabla +-- [0x0222B] = 0x73, -- smallint (TODO: what about intop?) + [0x02294] = 0x74, -- sqcup + [0x02293] = 0x75, -- sqcap + [0x02291] = 0x76, -- sqsubseteq + [0x02292] = 0x77, -- sqsupseteq + [0x000A7] = 0x78, -- S + [0x02020] = 0x79, -- dagger, dag + [0x02021] = 0x7A, -- ddagger, ddag + [0x000B6] = 0x7B, -- P + [0x02663] = 0x7C, -- clubsuit + [0x02662] = 0x7D, -- diamondsuit + [0x02661] = 0x7E, -- heartsuit + [0x02660] = 0x7F, -- spadesuit + [0xFE321] = 0x37, -- mapstochar + + [0xFE325] = 0x30, -- prime 0x02032 +} + +-- The names in masm10.enc can be trusted best and are shown in the first +-- column, while in the second column we show the tex/ams names. As usual +-- it costs hours to figure out such a table. + +mathencodings["tex-ma"] = { + [0x022A1] = 0x00, -- squaredot \boxdot + [0x0229E] = 0x01, -- squareplus \boxplus + [0x022A0] = 0x02, -- squaremultiply \boxtimes + [0x025A1] = 0x03, -- square \square \Box + [0x025A0] = 0x04, -- squaresolid \blacksquare + [0x025AA] = 0x05, -- squaresmallsolid \centerdot + [0x022C4] = 0x06, -- diamond \Diamond \lozenge + [0x02666] = 0x07, -- diamondsolid \blacklozenge + [0x021BB] = 0x08, -- clockwise \circlearrowright + [0x021BA] = 0x09, -- anticlockwise \circlearrowleft + [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons + [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons + [0x0229F] = 0x0C, -- squareminus \boxminus + [0x022A9] = 0x0D, -- forces \Vdash + [0x022AA] = 0x0E, -- forcesbar \Vvdash + [0x022A8] = 0x0F, -- satisfies \vDash + [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow + [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow + [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows + [0x021C9] = 0x13, -- dblarrowright \rightrightarrows + [0x021C8] = 0x14, -- dblarrowup \upuparrows + [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows + [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction + [0x021C2] = 0x17, -- harpoondownright \downharpoonright + [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft + [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft + [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail + [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail + [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows +-- [0x021C5] = 0x00, -- \updownarrows (missing in lm) + [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows + [0x021B0] = 0x1E, -- shiftleft \Lsh + [0x021B1] = 0x1F, -- shiftright \Rsh + [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow + [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow + [0x021AB] = 0x22, -- curlyleft \looparrowleft + [0x021AC] = 0x23, -- curlyright \looparrowright + [0x02257] = 0x24, -- circleequal \circeq + [0x0227F] = 0x25, -- followsorequal \succsim + [0x02273] = 0x26, -- greaterorsimilar \gtrsim + [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox + [0x022B8] = 0x28, -- multimap \multimap + [0x02234] = 0x29, -- therefore \therefore + [0x02235] = 0x2A, -- because \because + [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot + [0x0225C] = 0x2C, -- defines \triangleq + [0x0227E] = 0x2D, -- precedesorequal \precsim + [0x02272] = 0x2E, -- lessorsimilar \lesssim + [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox + [0x02A95] = 0x30, -- equalorless \eqslantless + [0x02A96] = 0x31, -- equalorgreater \eqslantgtr + [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec + [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc + [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq + [0x02266] = 0x35, -- lessdblequal \leqq + [0x02A7D] = 0x36, -- lessorequalslant \leqslant + [0x02276] = 0x37, -- lessorgreater \lessgtr + [0x02035] = 0x38, -- primereverse \backprime + -- [0x0] = 0x39, -- axisshort \dabar + [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq + [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq + [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq + [0x02267] = 0x3D, -- greaterdblequal \geqq + [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant + [0x02277] = 0x3F, -- greaterorless \gtrless + [0x0228F] = 0x40, -- squareimage \sqsubset + [0x02290] = 0x41, -- squareoriginal \sqsupset + -- wrong: see ** + -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright + -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft + -- cf lm + [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq + [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq + -- + [0x02605] = 0x46, -- star \bigstar + [0x0226C] = 0x47, -- between \between + [0x025BC] = 0x48, -- triangledownsld \blacktriangledown + [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright + [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft + -- [0x0] = 0x4B, -- arrowaxisright + -- [0x0] = 0x4C, -- arrowaxisleft + [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle + [0x025B2] = 0x4E, -- trianglesolid \blacktriangle + [0x025BD] = 0x4F, -- triangleinv \triangledown + [0x02256] = 0x50, -- ringinequal \eqcirc + [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr + [0x022DB] = 0x52, -- greaterlessequal \gtreqless + [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr + [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless + [0x000A5] = 0x55, -- Yen \yen + [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow + [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow + [0x02713] = 0x58, -- check \checkmark + [0x022BB] = 0x59, -- orunderscore \veebar + [0x022BC] = 0x5A, -- nand \barwedge + [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge + [0x02220] = 0x5C, -- angle \angle + [0x02221] = 0x5D, -- measuredangle \measuredangle + [0x02222] = 0x5E, -- sphericalangle \sphericalangle + -- [0x0] = 0x5F, -- proportional \varpropto + -- [0x0] = 0x60, -- smile \smallsmile + -- [0x0] = 0x61, -- frown \smallfrown + [0x022D0] = 0x62, -- subsetdbl \Subset + [0x022D1] = 0x63, -- supersetdbl \Supset + [0x022D3] = 0x64, -- uniondbl \doublecup \Cup + [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap + [0x022CF] = 0x66, -- uprise \curlywedge + [0x022CE] = 0x67, -- downfall \curlyvee + [0x022CB] = 0x68, -- multiopenleft \leftthreetimes + [0x022CC] = 0x69, -- multiopenright \rightthreetimes + [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq + [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq + [0x0224F] = 0x6C, -- difference \bumpeq + [0x0224E] = 0x6D, -- geomequivalent \Bumpeq + [0x022D8] = 0x6E, -- muchless \lll \llless + [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr + [0x0231C] = 0x70, -- rightanglenw \ulcorner + [0x0231D] = 0x71, -- rightanglene \urcorner + [0x024C7] = 0x72, -- circleR \circledR + [0x024C8] = 0x73, -- circleS \circledS + [0x022D4] = 0x74, -- fork \pitchfork + [0x02214] = 0x75, -- dotplus \dotplus + [0x0223D] = 0x76, -- revsimilar \backsim + [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq. + [0x0231E] = 0x78, -- rightanglesw \llcorner + [0x0231F] = 0x79, -- rightanglese \lrcorner + [0x02720] = 0x7A, -- maltesecross \maltese + [0x02201] = 0x7B, -- complement \complement + [0x022BA] = 0x7C, -- intercal \intercal + [0x0229A] = 0x7D, -- circlering \circledcirc + [0x0229B] = 0x7E, -- circleasterisk \circledast + [0x0229D] = 0x7F, -- circleminus \circleddash +} + +mathencodings["tex-mb"] = { + -- [0x0] = 0x00, -- lessornotequal \lvertneqq + -- [0x0] = 0x01, -- greaterornotequal \gvertneqq + [0x02270] = 0x02, -- notlessequal \nleq + [0x02271] = 0x03, -- notgreaterequal \ngeq + [0x0226E] = 0x04, -- notless \nless + [0x0226F] = 0x05, -- notgreater \ngtr + [0x02280] = 0x06, -- notprecedes \nprec + [0x02281] = 0x07, -- notfollows \nsucc + [0x02268] = 0x08, -- lessornotdbleql \lneqq + [0x02269] = 0x09, -- greaterornotdbleql \gneqq + -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant + -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant + [0x02A87] = 0x0C, -- lessnotequal \lneq + [0x02A88] = 0x0D, -- greaternotequal \gneq + -- [0x0] = 0x0E, -- notprecedesoreql \npreceq + -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq + [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim + [0x022E9] = 0x11, -- followornoteqvlnt \succnsim + [0x022E6] = 0x12, -- lessornotsimilar \lnsim + [0x022E7] = 0x13, -- greaterornotsimilar \gnsim + -- [0x0] = 0x14, -- notlessdblequal \nleqq + -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq + [0x02AB5] = 0x16, -- precedenotslnteql \precneqq + [0x02AB6] = 0x17, -- follownotslnteql \succneqq + [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox + [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox + [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox + [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox + [0x02241] = 0x1C, -- notsimilar \nsim + [0x02247] = 0x1D, -- notapproxequal \ncong + -- [0x0] = 0x1E, -- upslope \diagup + -- [0x0] = 0x1F, -- downslope \diagdown + -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq + -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq + -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq + -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq + [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq + [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq + -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq + -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq + [0x0228A] = 0x28, -- subsetnoteql \subsetneq + [0x0228B] = 0x29, -- supersetnoteql \supsetneq + [0x02288] = 0x2A, -- notsubseteql \nsubseteq + [0x02289] = 0x2B, -- notsuperseteql \nsupseteq + [0x02226] = 0x2C, -- notparallel \nparallel + [0x02224] = 0x2D, -- notbar \nmid \ndivides + -- [0x0] = 0x2E, -- notshortbar \nshortmid + -- [0x0] = 0x2F, -- notshortparallel \nshortparallel + [0x022AC] = 0x30, -- notturnstile \nvdash + [0x022AE] = 0x31, -- notforces \nVdash + [0x022AD] = 0x32, -- notsatisfies \nvDash + [0x022AF] = 0x33, -- notforcesextra \nVDash + [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq + [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq + [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft + [0x022EB] = 0x37, -- nottriangleright \ntriangleright + [0x0219A] = 0x38, -- notarrowleft \nleftarrow + [0x0219B] = 0x39, -- notarrowright \nrightarrow + [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow + [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow + [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow + [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow + [0x022C7] = 0x3E, -- dividemultiply \divideontimes + [0x02300] = 0x3F, -- diametersign \varnothing + [0x02204] = 0x40, -- notexistential \nexists + [0x1D538] = 0x41, -- A (blackboard A) + [0x1D539] = 0x42, -- B + [0x02102] = 0x43, -- C + [0x1D53B] = 0x44, -- D + [0x1D53C] = 0x45, -- E + [0x1D53D] = 0x46, -- F + [0x1D53E] = 0x47, -- G + [0x0210D] = 0x48, -- H + [0x1D540] = 0x49, -- I + [0x1D541] = 0x4A, -- J + [0x1D542] = 0x4B, -- K + [0x1D543] = 0x4C, -- L + [0x1D544] = 0x4D, -- M + [0x02115] = 0x4E, -- N + [0x1D546] = 0x4F, -- O + [0x02119] = 0x50, -- P + [0x0211A] = 0x51, -- Q + [0x0211D] = 0x52, -- R + [0x1D54A] = 0x53, -- S + [0x1D54B] = 0x54, -- T + [0x1D54C] = 0x55, -- U + [0x1D54D] = 0x56, -- V + [0x1D54E] = 0x57, -- W + [0x1D54F] = 0x58, -- X + [0x1D550] = 0x59, -- Y + [0x02124] = 0x5A, -- Z (blackboard Z) + [0x02132] = 0x60, -- finv \Finv + [0x02141] = 0x61, -- fmir \Game + -- [0x0] = 0x62, tildewide + -- [0x0] = 0x63, tildewider + -- [0x0] = 0x64, Finv + -- [0x0] = 0x65, Gmir + [0x02127] = 0x66, -- Omegainv \mho + [0x000F0] = 0x67, -- eth \eth + [0x02242] = 0x68, -- equalorsimilar \eqsim + [0x02136] = 0x69, -- beth \beth + [0x02137] = 0x6A, -- gimel \gimel + [0x02138] = 0x6B, -- daleth \daleth + [0x022D6] = 0x6C, -- lessdot \lessdot + [0x022D7] = 0x6D, -- greaterdot \gtrdot + [0x022C9] = 0x6E, -- multicloseleft \ltimes + [0x022CA] = 0x6F, -- multicloseright \rtimes + -- [0x0] = 0x70, -- barshort \shortmid + -- [0x0] = 0x71, -- parallelshort \shortparallel + -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy + -- [0x0] = 0x73, -- similar \thicksim + -- [0x0] = 0x74, -- approxequal \thickapprox + [0x0224A] = 0x75, -- approxorequal \approxeq + [0x02AB8] = 0x76, -- followsorequal \succapprox + [0x02AB7] = 0x77, -- precedesorequal \precapprox + [0x021B6] = 0x78, -- archleftdown \curvearrowleft + [0x021B7] = 0x79, -- archrightdown \curvearrowright + [0x003DC] = 0x7A, -- Digamma \digamma + [0x003F0] = 0x7B, -- kappa \varkappa + [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k) + [0x0210F] = 0x7D, -- planckover2pi \hslash + [0x00127] = 0x7E, -- planckover2pi1 \hbar + [0x003F6] = 0x7F, -- epsiloninv \backepsilon +} + +mathencodings["tex-mc"] = { + -- this file has no tfm so it gets mapped in the private space + [0xFE324] = "mapsfromchar", +} + +mathencodings["tex-fraktur"] = { +-- [0x1D504] = 0x41, -- A (fraktur A) +-- [0x1D505] = 0x42, -- B + [0x0212D] = 0x43, -- C +-- [0x1D507] = 0x44, -- D +-- [0x1D508] = 0x45, -- E +-- [0x1D509] = 0x46, -- F +-- [0x1D50A] = 0x47, -- G + [0x0210C] = 0x48, -- H + [0x02111] = 0x49, -- I +-- [0x1D50D] = 0x4A, -- J +-- [0x1D50E] = 0x4B, -- K +-- [0x1D50F] = 0x4C, -- L +-- [0x1D510] = 0x4D, -- M +-- [0x1D511] = 0x4E, -- N +-- [0x1D512] = 0x4F, -- O +-- [0x1D513] = 0x50, -- P +-- [0x1D514] = 0x51, -- Q + [0x0211C] = 0x52, -- R +-- [0x1D516] = 0x53, -- S +-- [0x1D517] = 0x54, -- T +-- [0x1D518] = 0x55, -- U +-- [0x1D519] = 0x56, -- V +-- [0x1D51A] = 0x57, -- W +-- [0x1D51B] = 0x58, -- X +-- [0x1D51C] = 0x59, -- Y + [0x02128] = 0x5A, -- Z (fraktur Z) +-- [0x1D51E] = 0x61, -- a (fraktur a) +-- [0x1D51F] = 0x62, -- b +-- [0x1D520] = 0x63, -- c +-- [0x1D521] = 0x64, -- d +-- [0x1D522] = 0x65, -- e +-- [0x1D523] = 0x66, -- f +-- [0x1D524] = 0x67, -- g +-- [0x1D525] = 0x68, -- h +-- [0x1D526] = 0x69, -- i +-- [0x1D527] = 0x6A, -- j +-- [0x1D528] = 0x6B, -- k +-- [0x1D529] = 0x6C, -- l +-- [0x1D52A] = 0x6D, -- m +-- [0x1D52B] = 0x6E, -- n +-- [0x1D52C] = 0x6F, -- o +-- [0x1D52D] = 0x70, -- p +-- [0x1D52E] = 0x71, -- q +-- [0x1D52F] = 0x72, -- r +-- [0x1D530] = 0x73, -- s +-- [0x1D531] = 0x74, -- t +-- [0x1D532] = 0x75, -- u +-- [0x1D533] = 0x76, -- v +-- [0x1D534] = 0x77, -- w +-- [0x1D535] = 0x78, -- x +-- [0x1D536] = 0x79, -- y +-- [0x1D537] = 0x7A, -- z +} + +-- now that all other vectors are defined ... + +setletters(mathencodings, "tex-it", 0x1D434, 0x1D44E) +setletters(mathencodings, "tex-ss", 0x1D5A0, 0x1D5BA) +setletters(mathencodings, "tex-tt", 0x1D670, 0x1D68A) +setletters(mathencodings, "tex-bf", 0x1D400, 0x1D41A) +setletters(mathencodings, "tex-bi", 0x1D468, 0x1D482) +setletters(mathencodings, "tex-fraktur", 0x1D504, 0x1D51E) +setletters(mathencodings, "tex-fraktur-bold", 0x1D56C, 0x1D586) + +setdigits (mathencodings, "tex-ss", 0x1D7E2) +setdigits (mathencodings, "tex-tt", 0x1D7F6) +setdigits (mathencodings, "tex-bf", 0x1D7CE) + +-- setdigits (mathencodings, "tex-bi", 0x1D7CE) + +-- todo: add ss, tt, bf etc vectors +-- todo: we can make ss tt etc an option diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua index 21b101894..b46e06a01 100644 --- a/tex/context/base/math-vfu.lua +++ b/tex/context/base/math-vfu.lua @@ -814,299 +814,7 @@ function mathematics.makefont(name,set,goodies) end end --- varphi is part of the alphabet, contrary to the other var*s' - -mathencodings["large-to-small"] = { - [0x00028] = 0x00, -- ( - [0x00029] = 0x01, -- ) - [0x0005B] = 0x02, -- [ - [0x0005D] = 0x03, -- ] - [0x0230A] = 0x04, -- lfloor - [0x0230B] = 0x05, -- rfloor - [0x02308] = 0x06, -- lceil - [0x02309] = 0x07, -- rceil - [0x0007B] = 0x08, -- { - [0x0007D] = 0x09, -- } - [0x027E8] = 0x0A, -- < - [0x027E9] = 0x0B, -- > - [0x0007C] = 0x0C, -- | ---~ [0x0] = 0x0D, -- lVert rVert Vert --- [0x0002F] = 0x0E, -- / - [0x0005C] = 0x0F, -- \ ---~ [0x0] = 0x3A, -- lgroup ---~ [0x0] = 0x3B, -- rgroup ---~ [0x0] = 0x3C, -- arrowvert ---~ [0x0] = 0x3D, -- Arrowvert - [0x02195] = 0x3F, -- updownarrow ---~ [0x0] = 0x40, -- lmoustache ---~ [0x0] = 0x41, -- rmoustache - [0x0221A] = 0x70, -- sqrt - [0x021D5] = 0x77, -- Updownarrow - [0x02191] = 0x78, -- uparrow - [0x02193] = 0x79, -- downarrow - [0x021D1] = 0x7E, -- Uparrow - [0x021D3] = 0x7F, -- Downarrow - [0x0220F] = 0x59, -- prod - [0x02210] = 0x61, -- coprod - [0x02211] = 0x58, -- sum - [0x0222B] = 0x5A, -- intop - [0x0222E] = 0x49, -- ointop - [0xFE302] = 0x62, -- widehat - [0xFE303] = 0x65, -- widetilde - [0x022C0] = 0x5E, -- bigwedge - [0x022C1] = 0x5F, -- bigvee - [0x022C2] = 0x5C, -- bigcap - [0x022C3] = 0x5B, -- bigcup - [0x02044] = 0x0E, -- / -} - --- Beware: these are (in cm/lm) below the baseline due to limitations --- in the tfm format bu the engien (combined with the mathclass) takes --- care of it. If we need them in textmode, we should make them virtual --- and move them up but we're in no hurry with that. - -mathencodings["tex-ex"] = { - [0x0220F] = 0x51, -- prod - [0x02210] = 0x60, -- coprod - [0x02211] = 0x50, -- sum - [0x0222B] = 0x52, -- intop - [0x0222E] = 0x48, -- ointop - [0x022C0] = 0x56, -- bigwedge - [0x022C1] = 0x57, -- bigvee - [0x022C2] = 0x54, -- bigcap - [0x022C3] = 0x53, -- bigcup - [0x02A00] = 0x4A, -- bigodot -- fixed BJ - [0x02A01] = 0x4C, -- bigoplus - [0x02A02] = 0x4E, -- bigotimes - -- [0x02A03] = , -- bigudot -- - [0x02A04] = 0x55, -- biguplus - [0x02A06] = 0x46, -- bigsqcup -} - --- only math stuff is needed, since we always use an lm or gyre --- font as main font - -mathencodings["tex-mr"] = { - [0x00393] = 0x00, -- Gamma - [0x00394] = 0x01, -- Delta - [0x00398] = 0x02, -- Theta - [0x0039B] = 0x03, -- Lambda - [0x0039E] = 0x04, -- Xi - [0x003A0] = 0x05, -- Pi - [0x003A3] = 0x06, -- Sigma - [0x003A5] = 0x07, -- Upsilon - [0x003A6] = 0x08, -- Phi - [0x003A8] = 0x09, -- Psi - [0x003A9] = 0x0A, -- Omega --- [0x00060] = 0x12, -- [math]grave --- [0x000B4] = 0x13, -- [math]acute --- [0x002C7] = 0x14, -- [math]check --- [0x002D8] = 0x15, -- [math]breve --- [0x000AF] = 0x16, -- [math]bar --- [0x00021] = 0x21, -- ! --- [0x00028] = 0x28, -- ( --- [0x00029] = 0x29, -- ) --- [0x0002B] = 0x2B, -- + --- [0x0002F] = 0x2F, -- / --- [0x0003A] = 0x3A, -- : --- [0x02236] = 0x3A, -- colon --- [0x0003B] = 0x3B, -- ; --- [0x0003C] = 0x3C, -- < --- [0x0003D] = 0x3D, -- = --- [0x0003E] = 0x3E, -- > --- [0x0003F] = 0x3F, -- ? - [0x00391] = 0x41, -- Alpha - [0x00392] = 0x42, -- Beta - [0x02145] = 0x44, - [0x00395] = 0x45, -- Epsilon - [0x00397] = 0x48, -- Eta - [0x00399] = 0x49, -- Iota - [0x0039A] = 0x4B, -- Kappa - [0x0039C] = 0x4D, -- Mu - [0x0039D] = 0x4E, -- Nu - [0x0039F] = 0x4F, -- Omicron - [0x003A1] = 0x52, -- Rho - [0x003A4] = 0x54, -- Tau - [0x003A7] = 0x58, -- Chi - [0x00396] = 0x5A, -- Zeta --- [0x0005B] = 0x5B, -- [ --- [0x0005D] = 0x5D, -- ] --- [0x0005E] = 0x5E, -- [math]hat -- the text one - [0x00302] = 0x5E, -- [math]hat -- the real math one --- [0x002D9] = 0x5F, -- [math]dot - [0x02146] = 0x64, - [0x02147] = 0x65, --- [0x002DC] = 0x7E, -- [math]tilde -- the text one - [0x00303] = 0x7E, -- [math]tilde -- the real one --- [0x000A8] = 0x7F, -- [math]ddot -} - -mathencodings["tex-mr-missing"] = { - [0x02236] = 0x3A, -- colon -} - -mathencodings["tex-mi"] = { - [0x1D6E4] = 0x00, -- Gamma - [0x1D6E5] = 0x01, -- Delta - [0x1D6E9] = 0x02, -- Theta - [0x1D6F3] = 0x02, -- varTheta (not present in TeX) - [0x1D6EC] = 0x03, -- Lambda - [0x1D6EF] = 0x04, -- Xi - [0x1D6F1] = 0x05, -- Pi - [0x1D6F4] = 0x06, -- Sigma - [0x1D6F6] = 0x07, -- Upsilon - [0x1D6F7] = 0x08, -- Phi - [0x1D6F9] = 0x09, -- Psi - [0x1D6FA] = 0x0A, -- Omega - [0x1D6FC] = 0x0B, -- alpha - [0x1D6FD] = 0x0C, -- beta - [0x1D6FE] = 0x0D, -- gamma - [0x1D6FF] = 0x0E, -- delta - [0x1D716] = 0x0F, -- epsilon TODO: 1D716 - [0x1D701] = 0x10, -- zeta - [0x1D702] = 0x11, -- eta - [0x1D703] = 0x12, -- theta TODO: 1D703 - [0x1D704] = 0x13, -- iota - [0x1D705] = 0x14, -- kappa - [0x1D718] = 0x14, -- varkappa, not in tex fonts - [0x1D706] = 0x15, -- lambda - [0x1D707] = 0x16, -- mu - [0x1D708] = 0x17, -- nu - [0x1D709] = 0x18, -- xi - [0x1D70B] = 0x19, -- pi - [0x1D70C] = 0x1A, -- rho - [0x1D70E] = 0x1B, -- sigma - [0x1D70F] = 0x1C, -- tau - [0x1D710] = 0x1D, -- upsilon - [0x1D719] = 0x1E, -- phi - [0x1D712] = 0x1F, -- chi - [0x1D713] = 0x20, -- psi - [0x1D714] = 0x21, -- omega - [0x1D700] = 0x22, -- varepsilon (the other way around) - [0x1D717] = 0x23, -- vartheta - [0x1D71B] = 0x24, -- varpi - [0x1D71A] = 0x25, -- varrho - [0x1D70D] = 0x26, -- varsigma - [0x1D711] = 0x27, -- varphi (the other way around) - [0x021BC] = 0x28, -- leftharpoonup - [0x021BD] = 0x29, -- leftharpoondown - [0x021C0] = 0x2A, -- rightharpoonup - [0x021C1] = 0x2B, -- rightharpoondown - [0xFE322] = 0x2C, -- lhook (hook for combining arrows) - [0xFE323] = 0x2D, -- rhook (hook for combining arrows) - [0x025B7] = 0x2E, -- triangleright : cf lmmath / BJ - [0x025C1] = 0x2F, -- triangleleft : cf lmmath / BJ - [0x022B3] = 0x2E, -- triangleright : cf lmmath this a cramped triangles / BJ / see * - [0x022B2] = 0x2F, -- triangleleft : cf lmmath this a cramped triangles / BJ / see * --- [0x00041] = 0x30, -- 0 --- [0x00041] = 0x31, -- 1 --- [0x00041] = 0x32, -- 2 --- [0x00041] = 0x33, -- 3 --- [0x00041] = 0x34, -- 4 --- [0x00041] = 0x35, -- 5 --- [0x00041] = 0x36, -- 6 --- [0x00041] = 0x37, -- 7 --- [0x00041] = 0x38, -- 8 --- [0x00041] = 0x39, -- 9 ---~ [0x0002E] = 0x3A, -- . - [0x0002C] = 0x3B, -- , - [0x0003C] = 0x3C, -- < --- [0x0002F] = 0x3D, -- /, slash, solidus - [0x02044] = 0x3D, -- / AM: Not sure - [0x0003E] = 0x3E, -- > - [0x022C6] = 0x3F, -- star - [0x02202] = 0x40, -- partial --- - [0x0266D] = 0x5B, -- flat - [0x0266E] = 0x5C, -- natural - [0x0266F] = 0x5D, -- sharp - [0x02323] = 0x5E, -- smile - [0x02322] = 0x5F, -- frown - [0x02113] = 0x60, -- ell --- - [0x1D6A4] = 0x7B, -- imath (TODO: also 0131) - [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237) - [0x02118] = 0x7D, -- wp - [0x020D7] = 0x7E, -- vec (TODO: not sure) --- 0x7F, -- (no idea what that could be) -} - -mathencodings["tex-it"] = { --- [0x1D434] = 0x41, -- A - [0x1D6E2] = 0x41, -- Alpha --- [0x1D435] = 0x42, -- B - [0x1D6E3] = 0x42, -- Beta --- [0x1D436] = 0x43, -- C --- [0x1D437] = 0x44, -- D --- [0x1D438] = 0x45, -- E - [0x1D6E6] = 0x45, -- Epsilon --- [0x1D439] = 0x46, -- F --- [0x1D43A] = 0x47, -- G --- [0x1D43B] = 0x48, -- H - [0x1D6E8] = 0x48, -- Eta --- [0x1D43C] = 0x49, -- I - [0x1D6EA] = 0x49, -- Iota --- [0x1D43D] = 0x4A, -- J --- [0x1D43E] = 0x4B, -- K - [0x1D6EB] = 0x4B, -- Kappa --- [0x1D43F] = 0x4C, -- L --- [0x1D440] = 0x4D, -- M - [0x1D6ED] = 0x4D, -- Mu --- [0x1D441] = 0x4E, -- N - [0x1D6EE] = 0x4E, -- Nu --- [0x1D442] = 0x4F, -- O - [0x1D6F0] = 0x4F, -- Omicron --- [0x1D443] = 0x50, -- P - [0x1D6F2] = 0x50, -- Rho --- [0x1D444] = 0x51, -- Q --- [0x1D445] = 0x52, -- R --- [0x1D446] = 0x53, -- S --- [0x1D447] = 0x54, -- T - [0x1D6F5] = 0x54, -- Tau --- [0x1D448] = 0x55, -- U --- [0x1D449] = 0x56, -- V --- [0x1D44A] = 0x57, -- W --- [0x1D44B] = 0x58, -- X - [0x1D6F8] = 0x58, -- Chi --- [0x1D44C] = 0x59, -- Y --- [0x1D44D] = 0x5A, -- Z --- --- [0x1D44E] = 0x61, -- a --- [0x1D44F] = 0x62, -- b --- [0x1D450] = 0x63, -- c --- [0x1D451] = 0x64, -- d --- [0x1D452] = 0x65, -- e --- [0x1D453] = 0x66, -- f --- [0x1D454] = 0x67, -- g --- [0x1D455] = 0x68, -- h - [0x0210E] = 0x68, -- Planck constant (h) --- [0x1D456] = 0x69, -- i --- [0x1D457] = 0x6A, -- j --- [0x1D458] = 0x6B, -- k --- [0x1D459] = 0x6C, -- l --- [0x1D45A] = 0x6D, -- m --- [0x1D45B] = 0x6E, -- n --- [0x1D45C] = 0x6F, -- o - [0x1D70A] = 0x6F, -- omicron --- [0x1D45D] = 0x70, -- p --- [0x1D45E] = 0x71, -- q --- [0x1D45F] = 0x72, -- r --- [0x1D460] = 0x73, -- s --- [0x1D461] = 0x74, -- t --- [0x1D462] = 0x75, -- u --- [0x1D463] = 0x76, -- v --- [0x1D464] = 0x77, -- w --- [0x1D465] = 0x78, -- x --- [0x1D466] = 0x79, -- y --- [0x1D467] = 0x7A, -- z -} - -mathencodings["tex-ss"] = { } -mathencodings["tex-tt"] = { } -mathencodings["tex-bf"] = { } -mathencodings["tex-bi"] = { } -mathencodings["tex-fraktur"] = { } -mathencodings["tex-fraktur-bold"] = { } +-- helpers function vfmath.setletters(font_encoding, name, uppercase, lowercase) local enc = font_encoding[name] @@ -1122,494 +830,3 @@ function vfmath.setdigits(font_encoding, name, digits) enc[digits+i] = i + 0x30 end end - -mathencodings["tex-sy"] = { - [0x0002D] = 0x00, -- - - [0x02212] = 0x00, -- - --- [0x02201] = 0x00, -- complement --- [0x02206] = 0x00, -- increment --- [0x02204] = 0x00, -- not exists --- [0x000B7] = 0x01, -- cdot - [0x022C5] = 0x01, -- cdot - [0x000D7] = 0x02, -- times - [0x0002A] = 0x03, -- * - [0x02217] = 0x03, -- * - [0x000F7] = 0x04, -- div - [0x022C4] = 0x05, -- diamond - [0x000B1] = 0x06, -- pm - [0x02213] = 0x07, -- mp - [0x02295] = 0x08, -- oplus - [0x02296] = 0x09, -- ominus - [0x02297] = 0x0A, -- otimes - [0x02298] = 0x0B, -- oslash - [0x02299] = 0x0C, -- odot - [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo - [0x02218] = 0x0E, -- circ - [0x02219] = 0x0F, -- bullet - [0x02022] = 0x0F, -- bullet - [0x0224D] = 0x10, -- asymp - [0x02261] = 0x11, -- equiv - [0x02286] = 0x12, -- subseteq - [0x02287] = 0x13, -- supseteq - [0x02264] = 0x14, -- leq - [0x02265] = 0x15, -- geq - [0x02AAF] = 0x16, -- preceq --- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF - [0x02AB0] = 0x17, -- succeq --- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0 - [0x0223C] = 0x18, -- sim - [0x02248] = 0x19, -- approx - [0x02282] = 0x1A, -- subset - [0x02283] = 0x1B, -- supset - [0x0226A] = 0x1C, -- ll - [0x0226B] = 0x1D, -- gg - [0x0227A] = 0x1E, -- prec - [0x0227B] = 0x1F, -- succ - [0x02190] = 0x20, -- leftarrow - [0x02192] = 0x21, -- rightarrow ---~ [0xFE190] = 0x20, -- leftarrow ---~ [0xFE192] = 0x21, -- rightarrow - [0x02191] = 0x22, -- uparrow - [0x02193] = 0x23, -- downarrow - [0x02194] = 0x24, -- leftrightarrow - [0x02197] = 0x25, -- nearrow - [0x02198] = 0x26, -- searrow - [0x02243] = 0x27, -- simeq - [0x021D0] = 0x28, -- Leftarrow - [0x021D2] = 0x29, -- Rightarrow - [0x021D1] = 0x2A, -- Uparrow - [0x021D3] = 0x2B, -- Downarrow - [0x021D4] = 0x2C, -- Leftrightarrow - [0x02196] = 0x2D, -- nwarrow - [0x02199] = 0x2E, -- swarrow - [0x0221D] = 0x2F, -- propto - [0x02032] = 0x30, -- prime - [0x0221E] = 0x31, -- infty - [0x02208] = 0x32, -- in - [0x0220B] = 0x33, -- ni - [0x025B3] = 0x34, -- triangle, bigtriangleup - [0x025BD] = 0x35, -- bigtriangledown - [0x00338] = 0x36, -- not --- 0x37, -- (beginning of arrow) - [0x02200] = 0x38, -- forall - [0x02203] = 0x39, -- exists - [0x000AC] = 0x3A, -- neg, lnot - [0x02205] = 0x3B, -- empty set - [0x0211C] = 0x3C, -- Re - [0x02111] = 0x3D, -- Im - [0x022A4] = 0x3E, -- top - [0x022A5] = 0x3F, -- bot, perp - [0x02135] = 0x40, -- aleph - [0x1D49C] = 0x41, -- script A - [0x0212C] = 0x42, -- script B - [0x1D49E] = 0x43, -- script C - [0x1D49F] = 0x44, -- script D - [0x02130] = 0x45, -- script E - [0x02131] = 0x46, -- script F - [0x1D4A2] = 0x47, -- script G - [0x0210B] = 0x48, -- script H - [0x02110] = 0x49, -- script I - [0x1D4A5] = 0x4A, -- script J - [0x1D4A6] = 0x4B, -- script K - [0x02112] = 0x4C, -- script L - [0x02133] = 0x4D, -- script M - [0x1D4A9] = 0x4E, -- script N - [0x1D4AA] = 0x4F, -- script O - [0x1D4AB] = 0x50, -- script P - [0x1D4AC] = 0x51, -- script Q - [0x0211B] = 0x52, -- script R - [0x1D4AE] = 0x53, -- script S - [0x1D4AF] = 0x54, -- script T - [0x1D4B0] = 0x55, -- script U - [0x1D4B1] = 0x56, -- script V - [0x1D4B2] = 0x57, -- script W - [0x1D4B3] = 0x58, -- script X - [0x1D4B4] = 0x59, -- script Y - [0x1D4B5] = 0x5A, -- script Z - [0x0222A] = 0x5B, -- cup - [0x02229] = 0x5C, -- cap - [0x0228E] = 0x5D, -- uplus - [0x02227] = 0x5E, -- wedge, land - [0x02228] = 0x5F, -- vee, lor - [0x022A2] = 0x60, -- vdash - [0x022A3] = 0x61, -- dashv - [0x0230A] = 0x62, -- lfloor - [0x0230B] = 0x63, -- rfloor - [0x02308] = 0x64, -- lceil - [0x02309] = 0x65, -- rceil - [0x0007B] = 0x66, -- {, lbrace - [0x0007D] = 0x67, -- }, rbrace - [0x027E8] = 0x68, -- <, langle - [0x027E9] = 0x69, -- >, rangle - [0x0007C] = 0x6A, -- |, mid, lvert, rvert - [0x02225] = 0x6B, -- parallel - -- [0x02016] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert - [0x02195] = 0x6C, -- updownarrow - [0x021D5] = 0x6D, -- Updownarrow - [0x0005C] = 0x6E, -- \, backslash, setminus - [0x02216] = 0x6E, -- setminus - [0x02240] = 0x6F, -- wr - [0x0221A] = 0x70, -- sqrt. AM: Check surd?? - [0x02A3F] = 0x71, -- amalg - [0x1D6FB] = 0x72, -- nabla --- [0x0222B] = 0x73, -- smallint (TODO: what about intop?) - [0x02294] = 0x74, -- sqcup - [0x02293] = 0x75, -- sqcap - [0x02291] = 0x76, -- sqsubseteq - [0x02292] = 0x77, -- sqsupseteq - [0x000A7] = 0x78, -- S - [0x02020] = 0x79, -- dagger, dag - [0x02021] = 0x7A, -- ddagger, ddag - [0x000B6] = 0x7B, -- P - [0x02663] = 0x7C, -- clubsuit - [0x02662] = 0x7D, -- diamondsuit - [0x02661] = 0x7E, -- heartsuit - [0x02660] = 0x7F, -- spadesuit - [0xFE321] = 0x37, -- mapstochar - - [0xFE325] = 0x30, -- prime 0x02032 -} - --- The names in masm10.enc can be trusted best and are shown in the first --- column, while in the second column we show the tex/ams names. As usual --- it costs hours to figure out such a table. - -mathencodings["tex-ma"] = { - [0x022A1] = 0x00, -- squaredot \boxdot - [0x0229E] = 0x01, -- squareplus \boxplus - [0x022A0] = 0x02, -- squaremultiply \boxtimes - [0x025A1] = 0x03, -- square \square \Box - [0x025A0] = 0x04, -- squaresolid \blacksquare - [0x025AA] = 0x05, -- squaresmallsolid \centerdot - [0x022C4] = 0x06, -- diamond \Diamond \lozenge - [0x02666] = 0x07, -- diamondsolid \blacklozenge - [0x021BB] = 0x08, -- clockwise \circlearrowright - [0x021BA] = 0x09, -- anticlockwise \circlearrowleft - [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons - [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons - [0x0229F] = 0x0C, -- squareminus \boxminus - [0x022A9] = 0x0D, -- forces \Vdash - [0x022AA] = 0x0E, -- forcesbar \Vvdash - [0x022A8] = 0x0F, -- satisfies \vDash - [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow - [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow - [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows - [0x021C9] = 0x13, -- dblarrowright \rightrightarrows - [0x021C8] = 0x14, -- dblarrowup \upuparrows - [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows - [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction - [0x021C2] = 0x17, -- harpoondownright \downharpoonright - [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft - [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft - [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail - [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail - [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows --- [0x021C5] = 0x00, -- \updownarrows (missing in lm) - [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows - [0x021B0] = 0x1E, -- shiftleft \Lsh - [0x021B1] = 0x1F, -- shiftright \Rsh - [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow - [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow - [0x021AB] = 0x22, -- curlyleft \looparrowleft - [0x021AC] = 0x23, -- curlyright \looparrowright - [0x02257] = 0x24, -- circleequal \circeq - [0x0227F] = 0x25, -- followsorequal \succsim - [0x02273] = 0x26, -- greaterorsimilar \gtrsim - [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox - [0x022B8] = 0x28, -- multimap \multimap - [0x02234] = 0x29, -- therefore \therefore - [0x02235] = 0x2A, -- because \because - [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot - [0x0225C] = 0x2C, -- defines \triangleq - [0x0227E] = 0x2D, -- precedesorequal \precsim - [0x02272] = 0x2E, -- lessorsimilar \lesssim - [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox - [0x02A95] = 0x30, -- equalorless \eqslantless - [0x02A96] = 0x31, -- equalorgreater \eqslantgtr - [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec - [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc - [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq - [0x02266] = 0x35, -- lessdblequal \leqq - [0x02A7D] = 0x36, -- lessorequalslant \leqslant - [0x02276] = 0x37, -- lessorgreater \lessgtr - [0x02035] = 0x38, -- primereverse \backprime - -- [0x0] = 0x39, -- axisshort \dabar - [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq - [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq - [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq - [0x02267] = 0x3D, -- greaterdblequal \geqq - [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant - [0x02277] = 0x3F, -- greaterorless \gtrless - [0x0228F] = 0x40, -- squareimage \sqsubset - [0x02290] = 0x41, -- squareoriginal \sqsupset - -- wrong: see ** - -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright - -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft - -- cf lm - [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq - [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq - -- - [0x02605] = 0x46, -- star \bigstar - [0x0226C] = 0x47, -- between \between - [0x025BC] = 0x48, -- triangledownsld \blacktriangledown - [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright - [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft - -- [0x0] = 0x4B, -- arrowaxisright - -- [0x0] = 0x4C, -- arrowaxisleft - [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle - [0x025B2] = 0x4E, -- trianglesolid \blacktriangle - [0x025BC] = 0x4F, -- triangleinv \triangledown - [0x02256] = 0x50, -- ringinequal \eqcirc - [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr - [0x022DB] = 0x52, -- greaterlessequal \gtreqless - [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr - [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless - [0x000A5] = 0x55, -- Yen \yen - [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow - [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow - [0x02713] = 0x58, -- check \checkmark - [0x022BB] = 0x59, -- orunderscore \veebar - [0x022BC] = 0x5A, -- nand \barwedge - [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge - [0x02220] = 0x5C, -- angle \angle - [0x02221] = 0x5D, -- measuredangle \measuredangle - [0x02222] = 0x5E, -- sphericalangle \sphericalangle - -- [0x0] = 0x5F, -- proportional \varpropto - -- [0x0] = 0x60, -- smile \smallsmile - -- [0x0] = 0x61, -- frown \smallfrown - [0x022D0] = 0x62, -- subsetdbl \Subset - [0x022D1] = 0x63, -- supersetdbl \Supset - [0x022D3] = 0x64, -- uniondbl \doublecup \Cup - [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap - [0x022CF] = 0x66, -- uprise \curlywedge - [0x022CE] = 0x67, -- downfall \curlyvee - [0x022CB] = 0x68, -- multiopenleft \leftthreetimes - [0x022CC] = 0x69, -- multiopenright \rightthreetimes - [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq - [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq - [0x0224F] = 0x6C, -- difference \bumpeq - [0x0224E] = 0x6D, -- geomequivalent \Bumpeq - [0x022D8] = 0x6E, -- muchless \lll \llless - [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr - [0x0231C] = 0x70, -- rightanglenw \ulcorner - [0x0231D] = 0x71, -- rightanglene \urcorner - [0x024C7] = 0x72, -- circleR \circledR - [0x024C8] = 0x73, -- circleS \circledS - [0x022D4] = 0x74, -- fork \pitchfork - [0x02214] = 0x75, -- dotplus \dotplus - [0x0223D] = 0x76, -- revsimilar \backsim - [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq. - [0x0231E] = 0x78, -- rightanglesw \llcorner - [0x0231F] = 0x79, -- rightanglese \lrcorner - [0x02720] = 0x7A, -- maltesecross \maltese - [0x02201] = 0x7B, -- complement \complement - [0x022BA] = 0x7C, -- intercal \intercal - [0x0229A] = 0x7D, -- circlering \circledcirc - [0x0229B] = 0x7E, -- circleasterisk \circledast - [0x0229D] = 0x7F, -- circleminus \circleddash -} - -mathencodings["tex-mb"] = { - -- [0x0] = 0x00, -- lessornotequal \lvertneqq - -- [0x0] = 0x01, -- greaterornotequal \gvertneqq - [0x02270] = 0x02, -- notlessequal \nleq - [0x02271] = 0x03, -- notgreaterequal \ngeq - [0x0226E] = 0x04, -- notless \nless - [0x0226F] = 0x05, -- notgreater \ngtr - [0x02280] = 0x06, -- notprecedes \nprec - [0x02281] = 0x07, -- notfollows \nsucc - [0x02268] = 0x08, -- lessornotdbleql \lneqq - [0x02269] = 0x09, -- greaterornotdbleql \gneqq - -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant - -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant - [0x02A87] = 0x0C, -- lessnotequal \lneq - [0x02A88] = 0x0D, -- greaternotequal \gneq - -- [0x0] = 0x0E, -- notprecedesoreql \npreceq - -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq - [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim - [0x022E9] = 0x11, -- followornoteqvlnt \succnsim - [0x022E6] = 0x12, -- lessornotsimilar \lnsim - [0x022E7] = 0x13, -- greaterornotsimilar \gnsim - -- [0x0] = 0x14, -- notlessdblequal \nleqq - -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq - [0x02AB5] = 0x16, -- precedenotslnteql \precneqq - [0x02AB6] = 0x17, -- follownotslnteql \succneqq - [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox - [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox - [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox - [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox - [0x02241] = 0x1C, -- notsimilar \nsim - [0x02247] = 0x1D, -- notapproxequal \ncong - -- [0x0] = 0x1E, -- upslope \diagup - -- [0x0] = 0x1F, -- downslope \diagdown - -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq - -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq - -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq - -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq - [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq - [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq - -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq - -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq - [0x0228A] = 0x28, -- subsetnoteql \subsetneq - [0x0228B] = 0x29, -- supersetnoteql \supsetneq - [0x02288] = 0x2A, -- notsubseteql \nsubseteq - [0x02289] = 0x2B, -- notsuperseteql \nsupseteq - [0x02226] = 0x2C, -- notparallel \nparallel - [0x02224] = 0x2D, -- notbar \nmid \ndivides - -- [0x0] = 0x2E, -- notshortbar \nshortmid - -- [0x0] = 0x2F, -- notshortparallel \nshortparallel - [0x022AC] = 0x30, -- notturnstile \nvdash - [0x022AE] = 0x31, -- notforces \nVdash - [0x022AD] = 0x32, -- notsatisfies \nvDash - [0x022AF] = 0x33, -- notforcesextra \nVDash - [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq - [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq - [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft - [0x022EB] = 0x37, -- nottriangleright \ntriangleright - [0x0219A] = 0x38, -- notarrowleft \nleftarrow - [0x0219B] = 0x39, -- notarrowright \nrightarrow - [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow - [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow - [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow - [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow - [0x022C7] = 0x3E, -- dividemultiply \divideontimes - [0x02300] = 0x3F, -- diametersign \varnothing - [0x02204] = 0x40, -- notexistential \nexists - [0x1D538] = 0x41, -- A (blackboard A) - [0x1D539] = 0x42, -- B - [0x02102] = 0x43, -- C - [0x1D53B] = 0x44, -- D - [0x1D53C] = 0x45, -- E - [0x1D53D] = 0x46, -- F - [0x1D53E] = 0x47, -- G - [0x0210D] = 0x48, -- H - [0x1D540] = 0x49, -- I - [0x1D541] = 0x4A, -- J - [0x1D542] = 0x4B, -- K - [0x1D543] = 0x4C, -- L - [0x1D544] = 0x4D, -- M - [0x02115] = 0x4E, -- N - [0x1D546] = 0x4F, -- O - [0x02119] = 0x50, -- P - [0x0211A] = 0x51, -- Q - [0x0211D] = 0x52, -- R - [0x1D54A] = 0x53, -- S - [0x1D54B] = 0x54, -- T - [0x1D54C] = 0x55, -- U - [0x1D54D] = 0x56, -- V - [0x1D54E] = 0x57, -- W - [0x1D54F] = 0x58, -- X - [0x1D550] = 0x59, -- Y - [0x02124] = 0x5A, -- Z (blackboard Z) - [0x02132] = 0x60, -- finv \Finv - [0x02141] = 0x61, -- fmir \Game - -- [0x0] = 0x62, tildewide - -- [0x0] = 0x63, tildewider - -- [0x0] = 0x64, Finv - -- [0x0] = 0x65, Gmir - [0x02127] = 0x66, -- Omegainv \mho - [0x000F0] = 0x67, -- eth \eth - [0x02242] = 0x68, -- equalorsimilar \eqsim - [0x02136] = 0x69, -- beth \beth - [0x02137] = 0x6A, -- gimel \gimel - [0x02138] = 0x6B, -- daleth \daleth - [0x022D6] = 0x6C, -- lessdot \lessdot - [0x022D7] = 0x6D, -- greaterdot \gtrdot - [0x022C9] = 0x6E, -- multicloseleft \ltimes - [0x022CA] = 0x6F, -- multicloseright \rtimes - -- [0x0] = 0x70, -- barshort \shortmid - -- [0x0] = 0x71, -- parallelshort \shortparallel - -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy - -- [0x0] = 0x73, -- similar \thicksim - -- [0x0] = 0x74, -- approxequal \thickapprox - [0x0224A] = 0x75, -- approxorequal \approxeq - [0x02AB8] = 0x76, -- followsorequal \succapprox - [0x02AB7] = 0x77, -- precedesorequal \precapprox - [0x021B6] = 0x78, -- archleftdown \curvearrowleft - [0x021B7] = 0x79, -- archrightdown \curvearrowright - [0x003DC] = 0x7A, -- Digamma \digamma - [0x003F0] = 0x7B, -- kappa \varkappa - [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k) - [0x0210F] = 0x7D, -- planckover2pi \hslash - [0x00127] = 0x7E, -- planckover2pi1 \hbar - [0x003F6] = 0x7F, -- epsiloninv \backepsilon -} - -mathencodings["tex-mc"] = { - -- this file has no tfm so it gets mapped in the private space - [0xFE324] = "mapsfromchar", -} - -mathencodings["tex-fraktur"] = { --- [0x1D504] = 0x41, -- A (fraktur A) --- [0x1D505] = 0x42, -- B - [0x0212D] = 0x43, -- C --- [0x1D507] = 0x44, -- D --- [0x1D508] = 0x45, -- E --- [0x1D509] = 0x46, -- F --- [0x1D50A] = 0x47, -- G - [0x0210C] = 0x48, -- H - [0x02111] = 0x49, -- I --- [0x1D50D] = 0x4A, -- J --- [0x1D50E] = 0x4B, -- K --- [0x1D50F] = 0x4C, -- L --- [0x1D510] = 0x4D, -- M --- [0x1D511] = 0x4E, -- N --- [0x1D512] = 0x4F, -- O --- [0x1D513] = 0x50, -- P --- [0x1D514] = 0x51, -- Q - [0x0211C] = 0x52, -- R --- [0x1D516] = 0x53, -- S --- [0x1D517] = 0x54, -- T --- [0x1D518] = 0x55, -- U --- [0x1D519] = 0x56, -- V --- [0x1D51A] = 0x57, -- W --- [0x1D51B] = 0x58, -- X --- [0x1D51C] = 0x59, -- Y - [0x02128] = 0x5A, -- Z (fraktur Z) --- [0x1D51E] = 0x61, -- a (fraktur a) --- [0x1D51F] = 0x62, -- b --- [0x1D520] = 0x63, -- c --- [0x1D521] = 0x64, -- d --- [0x1D522] = 0x65, -- e --- [0x1D523] = 0x66, -- f --- [0x1D524] = 0x67, -- g --- [0x1D525] = 0x68, -- h --- [0x1D526] = 0x69, -- i --- [0x1D527] = 0x6A, -- j --- [0x1D528] = 0x6B, -- k --- [0x1D529] = 0x6C, -- l --- [0x1D52A] = 0x6D, -- m --- [0x1D52B] = 0x6E, -- n --- [0x1D52C] = 0x6F, -- o --- [0x1D52D] = 0x70, -- p --- [0x1D52E] = 0x71, -- q --- [0x1D52F] = 0x72, -- r --- [0x1D530] = 0x73, -- s --- [0x1D531] = 0x74, -- t --- [0x1D532] = 0x75, -- u --- [0x1D533] = 0x76, -- v --- [0x1D534] = 0x77, -- w --- [0x1D535] = 0x78, -- x --- [0x1D536] = 0x79, -- y --- [0x1D537] = 0x7A, -- z -} - --- now that all other vectors are defined ... - -vfmath.setletters(mathencodings, "tex-it", 0x1D434, 0x1D44E) -vfmath.setletters(mathencodings, "tex-ss", 0x1D5A0, 0x1D5BA) -vfmath.setletters(mathencodings, "tex-tt", 0x1D670, 0x1D68A) -vfmath.setletters(mathencodings, "tex-bf", 0x1D400, 0x1D41A) -vfmath.setletters(mathencodings, "tex-bi", 0x1D468, 0x1D482) -vfmath.setletters(mathencodings, "tex-fraktur", 0x1D504, 0x1D51E) -vfmath.setletters(mathencodings, "tex-fraktur-bold", 0x1D56C, 0x1D586) - -vfmath.setdigits (mathencodings, "tex-ss", 0x1D7E2) -vfmath.setdigits (mathencodings, "tex-tt", 0x1D7F6) -vfmath.setdigits (mathencodings, "tex-bf", 0x1D7CE) - --- vfmath.setdigits (mathencodings, "tex-bi", 0x1D7CE) - --- todo: add ss, tt, bf etc vectors --- todo: we can make ss tt etc an option diff --git a/tex/context/base/meta-grd.mkiv b/tex/context/base/meta-grd.mkiv new file mode 100644 index 000000000..da410ba68 --- /dev/null +++ b/tex/context/base/meta-grd.mkiv @@ -0,0 +1,116 @@ +%D \module +%D [ file=meta-grd, +%D version=2012.06.28, +%D title=\METAPOST\ Graphics, +%D subtitle=grids, +%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}{MetaPost Graphics / Grids} + +%D This used to be a \TEX\ method, and a rather old one too. We keep it around but +%D in a more modern way. +%D +%D \startbuffer +%D \basegrid +%D [nx=8,ny=5, +%D dx=.5,dy=.25, +%D unit=cm,scale=2,factor=1, +%D offset=1ex,xstep=2,ystep=1, +%D align=middle,style=\tt\tx] +%D \stopbuffer +%D +%D \typebuffer +%D +%D \placefigure +%D {An example of a grid.} +%D {\getbuffer} + +\startuseMPgraphic{grid}{nx,ny,dx,dy,factor,scale,xstep,ystep,xoffset,yoffset,align} + begingroup ; + + save nx, ny, dx, dy, wd, ht, xstep, ystep, xoffset, yoffset, align, xalign, yalign ; + + numeric nx ; nx := \MPvar{nx} ; + numeric ny ; ny := \MPvar{ny} ; + numeric dx ; dx := \MPvar{factor} * \MPvar{scale} * \MPvar{dx} ; + numeric dy ; dy := \MPvar{factor} * \MPvar{scale} * \MPvar{dy} ; + numeric wd ; wd := nx * dx ; + numeric ht ; ht := ny * dy ; + numeric xstep ; xstep := \MPvar{xstep} ; + numeric ystep ; ystep := \MPvar{ystep} ; + numeric xoffset ; xoffset := \MPvar{xoffset} ; + numeric yoffset ; yoffset := \MPvar{yoffset} ; + numeric align ; align := \MPvar{align} ; + numeric xalign ; xalign := 0 ; + numeric yalign ; yalign := 0 ; + + if align = 1 : + xalign := dx/2 ; + yalign := dy/2 ; + fi ; + + for i=0 step dx until wd : + draw (i,0) -- (i,ht) ; + endfor ; + for i=0 step dy until ht : + draw (0,i) -- (wd,i) ; + endfor ; + + if xstep > 0 : + for i=1 step xstep until nx : + draw thetextext.bot(decimal i,(i*dx-xalign,-xoffset)) ; + endfor ; + fi ; + if ystep > 0 : + for i=1 step ystep until ny : + draw thetextext.lft(decimal i,(-yoffset,i*dy-yalign)) ; + endfor ; + fi ; + + endgroup ; +\stopuseMPgraphic + +\unprotect + +\unexpanded\def\basegrid + {\dosingleempty\typo_grid_base} + +\def\typo_grid_base[#1]% + {\hbox\bgroup + \getdummyparameters + [\c!nx=10,\c!ny=10,\c!dx=.5,\c!dy=.5,\c!xstep=0,\c!ystep=0, + \c!unit=\s!cm,\c!scale=1,\c!factor=1, + \c!offset=.25ex,\c!xoffset=\directdummyparameter\c!offset,\c!yoffset=\directdummyparameter\c!offset, + \c!align=, + #1]% + \usedummystyleandcolor\c!style\c!color + \edef\p_align{\directdummyparameter\c!align}% + \ifx\p_align\v!middle + \let\p_align\!!plusone + \else + \let\p_align\!!zerocount + \fi + \useMPgraphic + {grid}% + {nx=\directdummyparameter\c!nx,% + ny=\directdummyparameter\c!ny,% + dx=\directdummyparameter\c!dx\directdummyparameter\c!unit,% + dy=\directdummyparameter\c!dy\directdummyparameter\c!unit,% + factor=\directdummyparameter\c!factor,% + scale=\directdummyparameter\c!scale,% + xstep=\directdummyparameter\c!xstep,% + ystep=\directdummyparameter\c!ystep,% + xoffset=\directdummyparameter\c!xoffset,% + yoffset=\directdummyparameter\c!yoffset,% + align=\p_align}% + \egroup} + +\let\grid\basegrid + +\protect \endinput diff --git a/tex/context/base/meta-imp-dum.mkiv b/tex/context/base/meta-imp-dum.mkiv index a622d94f4..83fe12f09 100644 --- a/tex/context/base/meta-imp-dum.mkiv +++ b/tex/context/base/meta-imp-dum.mkiv @@ -59,7 +59,7 @@ % clip currentpicture to p ; % \stopuseMPgraphic -\startuseMPgraphic{placeholder}{width,height,reduction,color} +\startuseMPgraphic{figure:placeholder}{width,height,reduction,color} numeric w, h, d, r ; path p ; if cmykcolor \MPvar{color} : cmykcolor c, b ; b := (0,0,0,0) @@ -82,66 +82,79 @@ clip currentpicture to p ; \stopuseMPgraphic +\defineoverlay + [figure:placeholder:graphic] + [\useMPgraphic + {figure:placeholder}% + {width=\figurewidth,% + height=\figureheight,% + reduction=\externalfigureparameter\c!reduction,% + color=placeholder:\the\c_grph_replacement_n}] + \definepalet [placeholder] [1=red,2=green,3=blue,4=cyan,5=magenta,6=yellow] -% \newcounter \figurereplacementcycle - -\let\figurereplacementcycle\relax +\newcount\c_grph_replacement_n \setupexternalfigures [\c!reduction=0, \c!text=\v!yes] -\let\normalexternalfigurereplacement\externalfigurereplacement +\let\grph_include_replacement_saved\grph_include_replacement -\unexpanded\def\externalfigurereplacement#1#2#3% - {\getpaletsize[placeholder]% - \ifx\figurereplacementcycle\relax - \getrandomnumber \figurereplacementcycle \!!plusone \paletsize - \globallet \figurereplacementcycle \figurereplacementcycle +\unexpanded\def\grph_include_replacement#1#2#3% + {\begingroup + \getpaletsize[placeholder]% + \ifnum\c_grph_replacement_n=\zerocount + \getrandomnumber \m_grph_replacement_n\plusone\paletsize + \global\c_grph_replacement_n \m_grph_replacement_n\relax \else - \doglobal\increment\figurereplacementcycle + \global\advance\c_grph_replacement_n\plusone \fi - \ifnum\figurereplacementcycle>\paletsize - \globallet\figurereplacementcycle\!!plusone + \ifnum\c_grph_replacement_n>\paletsize + \global\c_grph_replacement_n\plusone \fi - \defineoverlay - [\s!dummy] - [\useMPgraphic - {placeholder}% - {width=\figurewidth, - height=\figureheight, - reduction=\@@efreduction, - color=placeholder:\figurereplacementcycle}]% - \expanded{\localframed - [\??ef] + \setupcurrentexternalfigure [\c!width=\figurewidth, \c!height=\figureheight, \c!frame=\v!off, \c!strut=\v!no, - \c!background=\s!dummy, - \c!foregroundcolor=\s!white]}% - {\doif\@@eftext\v!yes - {\infofont \setupinterlinespace \dohyphens % \nohyphens - \edef\tempa{#1}\ifx\tempa\s!dummy\let\tempa\empty\fi - \edef\tempb{#2}\ifx\tempb\s!dummy\let\tempb\empty\fi - \edef\tempc{#3}\ifx\tempc\s!dummy\let\tempc\empty\fi - \ifx\tempa\empty\else - name: \expanded{\verbatimstring{#1}}\strut\endgraf - \fi - \ifx\tempb\empty\else - \ifx\tempa\empty\ifx\tempc\empty\else file: \fi\else file: \fi - \expanded{\verbatimstring{#2}}\strut\endgraf - \fi - \ifx\tempc\empty\else - state: \expanded{\verbatimstring{#3}}\strut\endgraf - \fi}}} + \c!background=figure:placeholder:graphic, + \c!foregroundcolor=\s!white]% + \doifelse{\externalfigureparameter\c!text}\v!yes + {\edef\m_graphics_text_a{#1}\edef\m_graphics_text_a{\ifx\m_graphics_text_a\s!dummy\else\detokenize\expandafter{\m_graphics_text_a}\fi}% + \edef\m_graphics_text_b{#2}\edef\m_graphics_text_b{\ifx\m_graphics_text_b\s!dummy\else\detokenize\expandafter{\m_graphics_text_b}\fi}% + \edef\m_graphics_text_c{#3}\edef\m_graphics_text_c{\ifx\m_graphics_text_c\s!dummy\else\detokenize\expandafter{\m_graphics_text_c}\fi}% + \infofont\setupinterlinespace\dohyphens + \inheritedexternalfigureframed{\directsetup{figure:placeholder:text}}}% + {\inheritedexternalfigureframed{}}% + \endgroup} \unexpanded\def\dummyfigure {\externalfigure[placeholder]} +\startsetups figure:placeholder:text + \ifx\m_graphics_text_a\empty\else + \strut name: \m_graphics_text_a\par + \fi + \ifx\m_graphics_text_b\empty\else + \strut + \ifx\m_graphics_text_a\empty + \ifx\m_graphics_text_c\empty + \else + file:\space + \fi + \else + file:\space + \fi + \m_graphics_text_b\par + \fi + \ifx\m_graphics_text_c\empty\else + \strut state: \m_graphics_text_c\par + \fi +\stopsetups + %D \starttyping %D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:comment] %D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:dummy] @@ -151,7 +164,7 @@ \defineframed [figurecomment] [\c!background=\v!color, - \c!backgroundcolor=\v!gray, + \c!backgroundcolor=\s!gray, \c!frame=\v!off, \c!foregroundstyle=\ttbf, \c!align={\v!middle,\v!lohi}, @@ -160,8 +173,8 @@ \defineframed [figuredummy] - [\c!background=figure:placeholder, - \c!foregroundcolor=white, + [\c!background=figure:dummy, + \c!foregroundcolor=\s!white, \c!backgroundcolor=\v!gray, \c!frame=\v!off, \c!foregroundstyle=\ttbf, @@ -170,18 +183,30 @@ \c!width=\figurewidth] \defineoverlay - [figure:placeholder] - [\externalfigurereplacement{}{}{}] + [figure:dummy] + [\grph_include_replacement\empty\empty\empty] \defineoverlay [figure:comment] - [\figurecomment{\@@efcomment}] + [\figurecomment{\externalfigureparameter\c!comment}] \defineoverlay [figure:dummy] - [\figuredummy{\@@efcomment}] + [\figuredummy{\externalfigureparameter\c!comment}] \setupexternalfigures - [comment=] + [\c!comment=] + +\protect + +\continueifinputfile{meta-imp-dum.mkiv} + +\starttext + + \externalfigure[whatever-missing] + + \blank + + \externalfigure[whatever-missing][width=2cm] -\protect \endinput +\stoptext diff --git a/tex/context/base/meta-ini.lua b/tex/context/base/meta-ini.lua index bac1429ae..8b6fd22a2 100644 --- a/tex/context/base/meta-ini.lua +++ b/tex/context/base/meta-ini.lua @@ -9,6 +9,8 @@ if not modules then modules = { } end modules ['meta-ini'] = { local tonumber = tonumber local format, gmatch, match, gsub = string.format, string.gmatch, string.match, string.gsub +local context = context + metapost = metapost or { } -- for the moment downward compatible diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv index a62b81ccf..cd4e03bd6 100644 --- a/tex/context/base/meta-ini.mkiv +++ b/tex/context/base/meta-ini.mkiv @@ -104,14 +104,6 @@ \c!textstyle=, \c!textcolor=] -% \unexpanded\def\defineMPinstance -% {\dodoubleargument\meta_define_instance} - -% \def\meta_define_instance[#1][#2]% -% {\ifcsname\??mpinstancetokens#1\endcsname\else\expandafter\newtoks\csname\??mpinstancetokens#1\endcsname\fi -% \t_meta_instance\emptytoks % in case we redefine -% \getparameters[\??mpinstance#1][\s!format=mpost,\s!extensions=\v!no,\s!initializations=\v!no,#2]} - \appendtoks \ifcsname\??mpinstancetokens\currentMPinstance\endcsname \else \expandafter\newtoks\csname\??mpinstancetokens\currentMPinstance\endcsname @@ -192,22 +184,43 @@ {\global\t_meta_instance\emptytoks \endgroup} +\def\meta_process_graphic_start + {\setbox\b_meta_graphic\hbox\bgroup} + +\def\meta_process_graphic_stop + {\egroup + \meta_place_graphic} + \unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig {\meta_start_current_graphic \forgetall - \setbox\b_meta_graphic\hbox\bgroup % ; added 20100901 (as in mkii) + \meta_process_graphic_start \normalexpanded{\noexpand\ctxlua{metapost.graphic( "\currentMPinstance", "\currentMPformat", \!!bs#1;\!!es, \!!bs\meta_flush_current_initializations;\!!es, \!!bs\meta_flush_current_preamble;\!!es, - \MPaskedfigure + "\MPaskedfigure" )}}% - \egroup - \placeMPgraphic + \meta_process_graphic_stop \meta_stop_current_graphic} +\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 + {\begingroup + \let\normal_meta_process_graphic_start\meta_process_graphic_start + \let\normal_meta_process_graphic_stop \meta_process_graphic_stop + \let\meta_process_graphic_start\relax + \let\meta_process_graphic_stop \relax + \def\meta_process_graphic_figure_start{\startTEXpage\normal_meta_process_graphic_start}% + \def\meta_process_graphic_figure_stop {\normal_meta_process_graphic_stop\stopTEXpage} + \def\MPaskedfigure{all}% + \meta_process_graphic{input "#1" ;}% + \endgroup} + \newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default \def\setMPrandomseed @@ -362,34 +375,36 @@ \let \m_meta_current_variable \empty \let \m_meta_current_variable_template\empty +\installcorenamespace{graphicvariable} + \def \meta_prepare_variable_default {\MPcolor{black}} % just to be sure we use a color but ... -\edef\meta_unknown_variable_template {\??gv:\s!unknown} +\edef\meta_unknown_variable_template {\??graphicvariable:\s!unknown} -\letvalue{\??gv:\s!unknown}\empty +\letvalue{\??graphicvariable:\s!unknown}\empty \unexpanded\def\setupMPvariables {\dodoubleempty\meta_setup_variables} \def\meta_setup_variables[#1][#2]% {\ifsecondargument - \getrawparameters[\??gv#1:][#2]% + \getrawparameters[\??graphicvariable#1:][#2]% \else - \getrawparameters[\??gv:][#1]% + \getrawparameters[\??graphicvariable:][#1]% \fi} \unexpanded\def\presetMPvariable {\dodoubleargument\meta_preset_variable} \def\meta_preset_variable[#1][#2=#3]% - {\ifcsname\??gv#1:#2\endcsname \else - \setvalue{\??gv#1:#2}{#3}% + {\ifcsname\??graphicvariable#1:#2\endcsname \else + \setvalue{\??graphicvariable#1:#2}{#3}% \fi} \def\MPrawvar#1#2% no checking - {\csname\??gv#1:#2\endcsname} + {\csname\??graphicvariable#1:#2\endcsname} \def\MPvariable#1% todo: could be a framed chain - {\csname\??gv\currentmpvariableclass:#1\endcsname} + {\csname\??graphicvariable\currentmpvariableclass:#1\endcsname} \unexpanded\def\useMPvariables {\dodoubleargument\meta_use_variables} @@ -403,7 +418,7 @@ \unexpanded\def\meta_prepare_variable#1% {\edef\m_meta_current_variable_template - {\??gv\currentmpvariableclass:#1}% + {\??graphicvariable\currentmpvariableclass:#1}% \edef\m_meta_current_variable {\csname\ifcsname\m_meta_current_variable_template\endcsname \m_meta_current_variable_template\else\meta_unknown_variable_template @@ -506,7 +521,7 @@ \let\meta_relocate_box\relax -\unexpanded\def\placeMPgraphic % the converter also displaces so in fact we revert +\unexpanded\def\meta_place_graphic % the converter also displaces so in fact we revert {\meta_relocate_box \box\b_meta_graphic} @@ -1172,11 +1187,9 @@ %D %D Here is a generic setup command: -\newtoks\everysetupMPgraphics +\installcorenamespace{MPgraphics} -\unexpanded\def\setupMPgraphics[#1]% - {\getparameters[\??mp][#1]% - \the\everysetupMPgraphics} +\installsetuponlycommandhandler \??MPgraphics {MPgraphics} %D Here we hook in the outer color. When \type {color} is set to \type %D {global} we get the outer color automatically. If you change this @@ -1184,7 +1197,7 @@ %D behave in unexpected ways. \appendtoks - \doifelse\@@mpcolor\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}% + \doifelse{\directMPgraphicsparameter\c!color}\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}% \to \everysetupMPgraphics \setupMPgraphics diff --git a/tex/context/base/meta-pag.mkiv b/tex/context/base/meta-pag.mkiv index 6cea270e3..ef53d4753 100644 --- a/tex/context/base/meta-pag.mkiv +++ b/tex/context/base/meta-pag.mkiv @@ -33,6 +33,12 @@ \stopMPinitializations \startMPinitializations + CurrentColumn:=\number\mofcolumns; + NOfColumns:=\number\nofcolumns; + % todo: ColumnDistance +\stopMPinitializations + +\startMPinitializations def LoadPageState = OnRightPage:=\MPonrightpage; OnOddPage:=\MPonoddpage; @@ -75,8 +81,8 @@ InnerEdgeWidth:=\the\inneredgewidth; OuterEdgeDistance:=\the\outeredgedistance; OuterEdgeWidth:=\the\outeredgewidth; - PageOffset:=\the\pageoffset; - PageDepth:=\the\pagedepth; + PageOffset:=\the\pagebackgroundoffset; + PageDepth:=\the\pagebackgrounddepth; LayoutColumns:=\the\layoutcolumns; LayoutColumnDistance:=\the\layoutcolumndistance; LayoutColumnWidth:=\the\layoutcolumnwidth; diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua index 13d39e445..c68350a96 100644 --- a/tex/context/base/meta-pdf.lua +++ b/tex/context/base/meta-pdf.lua @@ -9,6 +9,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = { -- Finally we used an optimized version. The test code can be found in -- meta-pdh.lua but since we no longer want to overload functione we use -- more locals now. This module keeps changing as it is also a testbed. +-- +-- We can make it even more efficient if needed, but as we don't use this +-- code often in \MKIV\ it makes no sense. local concat, format, gsub, find, byte, gmatch, match = table.concat, string.format, string.gsub, string.find, string.byte, string.gmatch, string.match local lpegmatch = lpeg.match @@ -50,8 +53,8 @@ end resetall() --- -- this does not work as expected (displacement of text) --- -- beware, needs another comment hack +-- -- this does not work as expected (displacement of text) beware, needs another +-- -- comment hack -- -- local function pdfcode(str) -- context(pdfliteral(str)) diff --git a/tex/context/base/meta-pdh.mkiv b/tex/context/base/meta-pdh.mkiv index 6d85a8dc1..b65fe6ac6 100644 --- a/tex/context/base/meta-pdh.mkiv +++ b/tex/context/base/meta-pdh.mkiv @@ -565,7 +565,7 @@ % {\ifcase\pdfoutput\or % will be hooked into the special driver % \doiffileelse{#7} % {\doifundefinedelse{mps:x:#7} -% {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}% +% {\immediate\pdfximage\s!width\onebasepoint\s!height\onebasepoint{#7}% % \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}% % {\message{[reusing figure #7]}}% % \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}% diff --git a/tex/context/base/meta-tex.lua b/tex/context/base/meta-tex.lua index 872e8154c..c29498ad1 100644 --- a/tex/context/base/meta-tex.lua +++ b/tex/context/base/meta-tex.lua @@ -31,7 +31,7 @@ if not modules then modules = { } end modules ['meta-tex'] = { local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match -local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0) +local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0) -- or \char function metapost.escaped(str) context(lpegmatch(pattern,str)) diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua index 493a45248..a8ef84b80 100644 --- a/tex/context/base/mlib-ctx.lua +++ b/tex/context/base/mlib-ctx.lua @@ -97,9 +97,11 @@ local environments = { } function metapost.tex.set(str) environments[#environments+1] = str end + function metapost.tex.reset() environments = { } end + function metapost.tex.get() return concat(environments,"\n") end diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua index 7a23ba947..88f26e755 100644 --- a/tex/context/base/mlib-pdf.lua +++ b/tex/context/base/mlib-pdf.lua @@ -11,26 +11,41 @@ local abs, sqrt, round = math.abs, math.sqrt, math.round local setmetatable = setmetatable local Cf, C, Cg, Ct, P, S, lpegmatch = lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.match -local allocate = utilities.storage.allocate - local report_metapost = logs.reporter("metapost") local mplib, context = mplib, context -local copy_node = node.copy -local write_node = node.write +local allocate = utilities.storage.allocate + +local copy_node = node.copy +local write_node = node.write + +metapost = metapost or { } +local metapost = metapost + +metapost.flushers = metapost.flushers or { } +local pdfflusher = { } +metapost.flushers.pdf = pdfflusher -metapost = metapost or { } -local metapost = metapost +metapost.multipass = false +metapost.n = 0 +metapost.optimize = true -- false -metapost.multipass = false -metapost.n = 0 -metapost.optimize = true -- false +local experiment = true -- uses context(node) that already does delayed nodes + +local savedliterals = nil -- needs checking +local mpsliteral = nodes.pool.register(node.new("whatsit",nodes.whatsitcodes.pdfliteral)) -- pdfliteral.mode = 1 + +local pdfliteral = function(s) + local literal = copy_node(mpsliteral) + literal.data = s + return literal +end ---~ Because in MKiV we always have two passes, we save the objects. When an extra ---~ mp run is done (due to for instance texts identifier in the parse pass), we ---~ get a new result table and the stored objects are forgotten. Otherwise they ---~ are reused. +-- Because in MKiV we always have two passes, we save the objects. When an extra +-- mp run is done (due to for instance texts identifier in the parse pass), we +-- get a new result table and the stored objects are forgotten. Otherwise they +-- are reused. local function getobjects(result,figure,f) if metapost.optimize then @@ -64,23 +79,6 @@ function metapost.convert(result, trialrun, flusher, multipass, askedfig) return true -- done end -metapost.flushers = { } -metapost.flushers.pdf = { } - --- \def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}} - -local savedliterals = nil -- needs checking - -local mpsliteral = nodes.pool.register(node.new("whatsit",8)) -- pdfliteral - -local pdfliteral = function(s) - local literal = copy_node(mpsliteral) - literal.data = s - return literal -end - -local experiment = true -- uses context(node) that already does delayed nodes - function metapost.flushliteral(d) if savedliterals then local literal = copy_node(mpsliteral) @@ -95,7 +93,7 @@ function metapost.flushreset() -- will become obsolete and internal savedliterals = nil end -function metapost.flushers.pdf.comment(message) +function pdfflusher.comment(message) if message then message = format("%% mps graphic %s: %s", metapost.n, message) if experiment then @@ -113,20 +111,20 @@ function metapost.flushers.pdf.comment(message) end end -function metapost.flushers.pdf.startfigure(n,llx,lly,urx,ury,message) +function pdfflusher.startfigure(n,llx,lly,urx,ury,message) savedliterals = nil metapost.n = metapost.n + 1 context.startMPLIBtoPDF(llx,lly,urx,ury) - if message then metapost.flushers.pdf.comment(message) end + if message then pdfflusher.comment(message) end end -function metapost.flushers.pdf.stopfigure(message) - if message then metapost.flushers.pdf.comment(message) end +function pdfflusher.stopfigure(message) + if message then pdfflusher.comment(message) end context.stopMPLIBtoPDF() context.MPLIBflushreset() -- maybe just at the beginning end -function metapost.flushers.pdf.flushfigure(pdfliterals) -- table +function pdfflusher.flushfigure(pdfliterals) -- table if #pdfliterals > 0 then pdfliterals = concat(pdfliterals,"\n") if experiment then @@ -144,7 +142,7 @@ function metapost.flushers.pdf.flushfigure(pdfliterals) -- table end end -function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor +function pdfflusher.textfigure(font,size,text,width,height,depth) -- we could save the factor text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib) context.MPtextext(font,size,text,0,-number.dimenfactors.bp*depth) end @@ -273,7 +271,7 @@ function metapost.flush(result,flusher,askedfig) if result then local figures = result.fig if figures then - flusher = flusher or metapost.flushers.pdf + flusher = flusher or pdfflusher local resetplugins = metapost.resetplugins or ignore -- before figure local processplugins = metapost.processplugins or ignore -- each object local synchronizeplugins = metapost.synchronizeplugins or ignore @@ -290,7 +288,7 @@ function metapost.flush(result,flusher,askedfig) local t = { } local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false local bbox = figure:boundingbox() - local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack + local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] metapost.llx = llx metapost.lly = lly metapost.urx = urx @@ -451,24 +449,17 @@ function metapost.parse(result,askedfig) local figures = result.fig if figures then local analyzeplugins = metapost.analyzeplugins -- each object - for f=1, #figures do + for f=1,#figures do local figure = figures[f] local fignum = figure:charcode() or 0 if askedfig == "direct" or askedfig == "all" or askedfig == fignum then local bbox = figure:boundingbox() - local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack - metapost.llx = llx - metapost.lly = lly - metapost.urx = urx - metapost.ury = ury + metapost.llx = bbox[1] + metapost.lly = bbox[2] + metapost.urx = bbox[3] + metapost.ury = bbox[4] local objects = getobjects(result,figure,f) if objects then - -- for o=1,#objects do - -- local object = objects[o] - -- local prescript = object.prescript - -- if prescript then - -- analyzeplugins(object) - -- end for o=1,#objects do analyzeplugins(objects[o]) end diff --git a/tex/context/base/mlib-pdf.mkiv b/tex/context/base/mlib-pdf.mkiv index b9871eead..68b4b922a 100644 --- a/tex/context/base/mlib-pdf.mkiv +++ b/tex/context/base/mlib-pdf.mkiv @@ -91,7 +91,8 @@ \def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}} \def\startMPLIBtoPDF#1#2#3#4% - {\dostarttagged\t!mpgraphic\empty + {\meta_process_graphic_figure_start + \dostarttagged\t!mpgraphic\empty \naturalhbox attr \imageattribute 1 \bgroup \dousecolorparameter\s!black\forcecolorhack \setMPboundingbox{#1}{#2}{#3}{#4}% @@ -104,7 +105,8 @@ \finalizeMPbox \box\MPbox \egroup - \dostoptagged} + \dostoptagged + \meta_process_graphic_figure_stop} \def\MPLIBflushreset % This can (will) move to the Lua end. {\ctxlua{metapost.flushreset()}} diff --git a/tex/context/base/mlib-pps.mkiv b/tex/context/base/mlib-pps.mkiv index cb6120066..704c9e635 100644 --- a/tex/context/base/mlib-pps.mkiv +++ b/tex/context/base/mlib-pps.mkiv @@ -64,13 +64,15 @@ \vbox to \zeropoint\bgroup \vss \hbox to \zeropoint \bgroup - \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}% - \forcecolorhack % needed ? already in the scale macro - % % This gives: LuaTeX warning: Misplaced \pdfrestore .. don't ask me why. - % - % \dostartscaling{#8}{#9}% - % \raise\dp\MPtextbox\box\MPtextbox - % \dostopscaling +% \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}% +% \scale[\c!sx=#8,\c!sy=#9,\c!depth=\v!no]{\box\MPtextbox}% + \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}% + % This gives: LuaTeX warning: Misplaced \pdfrestore .. don't ask me why. + % but I'll retry it some day soon. + % \dostartscaling{#8}{#9}% + % \raise\dp\MPtextbox\box\MPtextbox + % \dostopscaling + \forcecolorhack % needed ? already in the scale macro \hss \egroup \egroup diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua index 59dc88b90..08ed22e47 100644 --- a/tex/context/base/mlib-run.lua +++ b/tex/context/base/mlib-run.lua @@ -29,29 +29,29 @@ approach is way faster than an external <l n='metapost'/> and processing time nears zero.</p> --ldx]]-- +local format, gsub, match, find = string.format, string.gsub, string.match, string.find +local emptystring = string.is_empty +local lpegmatch, P = lpeg.match, lpeg.P + local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end) local report_metapost = logs.reporter("metapost") - local texerrormessage = logs.texerrormessage -local format, gsub, match, find = string.format, string.gsub, string.match, string.find -local emptystring = string.is_empty - -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming -local mplib = mplib +local mplib = mplib +metapost = metapost or { } +local metapost = metapost -metapost = metapost or { } -local metapost = metapost +local mplibone = tonumber(mplib.version()) <= 1.50 metapost.showlog = false metapost.lastlog = "" metapost.texerrors = false metapost.exectime = metapost.exectime or { } -- hack -local mplibone = tonumber(mplib.version()) <= 1.50 - directives.register("mplib.texerrors", function(v) metapost.texerrors = v end) function metapost.resetlastlog() @@ -68,19 +68,57 @@ end -- end -- end -local function i_finder(name, mode, ftype) -- fake message for mpost.map and metafun.mpvi - name = file.is_qualified_path(name) and name or resolvers.findfile(name,ftype) - if not (find(name,"/metapost/context/base/") or find(name,"/metapost/context/") or find(name,"/metapost/base/")) then +----- mpbasepath = lpeg.instringchecker(lpeg.append { "/metapost/context/", "/metapost/base/" }) +local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("base")) * P("/")) + +-- local function i_finder(askedname,mode,ftype) -- fake message for mpost.map and metafun.mpvi +-- local foundname = file.is_qualified_path(askedname) and askedname or resolvers.findfile(askedname,ftype) +-- if not mpbasepath(foundname) then +-- -- we could use the via file but we don't have a complete io interface yet +-- local data, found, forced = metapost.checktexts(io.loaddata(foundname) or "") +-- if found then +-- local tempname = luatex.registertempfile(foundname,true) +-- io.savedata(tempname,data) +-- foundname = tempname +-- end +-- end +-- return foundname +-- end + +-- mplib has no real io interface so we have a different mechanism than +-- tex (as soon as we have more control, we will use the normal code) + +local finders = { } +mplib.finders = finders + +-- for some reason mp sometimes calls this function twice which is inefficient +-- but we cannot catch this + +local function preprocessed(name) + if not mpbasepath(name) then + -- we could use the via file but we don't have a complete io interface yet local data, found, forced = metapost.checktexts(io.loaddata(name) or "") if found then local temp = luatex.registertempfile(name,true) io.savedata(temp,data) - name = temp + return temp end end return name end +mplib.preprocessed = preprocessed -- helper + +finders.file = function(specification,name,mode,ftype) + return preprocessed(resolvers.findfile(name,ftype)) +end + +local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi + local specification = url.hashed(name) + local finder = finders[specification.scheme] or finders.file + return finder(specification,name,mode,ftype) +end + local function o_finder(name, mode, ftype) return name end @@ -145,99 +183,103 @@ end if mplibone then - local preamble = [[ - boolean mplib ; mplib := true ; - string mp_parent_version ; mp_parent_version := "%s" ; - input "%s" ; dump ; - ]] - - metapost.parameters = { - hash_size = 100000, - main_memory = 4000000, - max_in_open = 50, - param_size = 100000, - } - - function metapost.make(name, target, version) - starttiming(mplib) - target = file.replacesuffix(target or name, "mem") -- redundant - local mpx = mplib.new ( table.merged ( - metapost.parameters, - { - ini_version = true, - find_file = finder, - job_name = file.removesuffix(target), - } - ) ) - if mpx then - starttiming(metapost.exectime) - local result = mpx:execute(format(preamble,version or "unknown",name)) - stoptiming(metapost.exectime) - mpx:finish() - end - stoptiming(mplib) - end - - function metapost.load(name) - starttiming(mplib) - local mpx = mplib.new ( table.merged ( - metapost.parameters, - { - ini_version = false, - mem_name = file.replacesuffix(name,"mem"), - find_file = finder, - -- job_name = "mplib", - } - ) ) - local result - if not mpx then - result = { status = 99, error = "out of memory"} - end - stoptiming(mplib) - return mpx, result - end - - function metapost.checkformat(mpsinput) - local mpsversion = environment.version or "unset version" - local mpsinput = file.addsuffix(mpsinput or "metafun", "mp") - local mpsformat = file.removesuffix(file.basename(texconfig.formatname or (tex and tex.formatname) or mpsinput)) - local mpsbase = file.removesuffix(file.basename(mpsinput)) - if mpsbase ~= mpsformat then - mpsformat = mpsformat .. "-" .. mpsbase - end - mpsformat = file.addsuffix(mpsformat, "mem") - local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or "" - if mpsformatfullname ~= "" then - report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname) - local mpx, result = metapost.load(mpsformatfullname) - if mpx then - local result = mpx:execute("show mp_parent_version ;") - if not result.log then - metapost.reporterror(result) - else - local version = match(result.log,">> *(.-)[\n\r]") or "unknown" - version = gsub(version,"[\'\"]","") - if version ~= mpsversion then - report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion) - else - return mpx - end - end - else - report_metapost("error in loading '%s' from '%s'", mpsinput, mpsformatfullname) - metapost.reporterror(result) - end - end - local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats") - report_metapost("making '%s' into '%s'", mpsinput, mpsformatfullname) - metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here - if lfs.isfile(mpsformatfullname) then - report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname) - return metapost.load(mpsformatfullname) - else - report_metapost("problems with '%s' from '%s'", mpsinput, mpsformatfullname) - end - end + report_metapost("fatal error: mplib is too old") + + os.exit() + + -- local preamble = [[ + -- boolean mplib ; mplib := true ; + -- string mp_parent_version ; mp_parent_version := "%s" ; + -- input "%s" ; dump ; + -- ]] + -- + -- metapost.parameters = { + -- hash_size = 100000, + -- main_memory = 4000000, + -- max_in_open = 50, + -- param_size = 100000, + -- } + -- + -- function metapost.make(name, target, version) + -- starttiming(mplib) + -- target = file.replacesuffix(target or name, "mem") -- redundant + -- local mpx = mplib.new ( table.merged ( + -- metapost.parameters, + -- { + -- ini_version = true, + -- find_file = finder, + -- job_name = file.removesuffix(target), + -- } + -- ) ) + -- if mpx then + -- starttiming(metapost.exectime) + -- local result = mpx:execute(format(preamble,version or "unknown",name)) + -- stoptiming(metapost.exectime) + -- mpx:finish() + -- end + -- stoptiming(mplib) + -- end + -- + -- function metapost.load(name) + -- starttiming(mplib) + -- local mpx = mplib.new ( table.merged ( + -- metapost.parameters, + -- { + -- ini_version = false, + -- mem_name = file.replacesuffix(name,"mem"), + -- find_file = finder, + -- -- job_name = "mplib", + -- } + -- ) ) + -- local result + -- if not mpx then + -- result = { status = 99, error = "out of memory"} + -- end + -- stoptiming(mplib) + -- return mpx, result + -- end + -- + -- function metapost.checkformat(mpsinput) + -- local mpsversion = environment.version or "unset version" + -- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp") + -- local mpsformat = file.removesuffix(file.basename(texconfig.formatname or (tex and tex.formatname) or mpsinput)) + -- local mpsbase = file.removesuffix(file.basename(mpsinput)) + -- if mpsbase ~= mpsformat then + -- mpsformat = mpsformat .. "-" .. mpsbase + -- end + -- mpsformat = file.addsuffix(mpsformat, "mem") + -- local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or "" + -- if mpsformatfullname ~= "" then + -- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname) + -- local mpx, result = metapost.load(mpsformatfullname) + -- if mpx then + -- local result = mpx:execute("show mp_parent_version ;") + -- if not result.log then + -- metapost.reporterror(result) + -- else + -- local version = match(result.log,">> *(.-)[\n\r]") or "unknown" + -- version = gsub(version,"[\'\"]","") + -- if version ~= mpsversion then + -- report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion) + -- else + -- return mpx + -- end + -- end + -- else + -- report_metapost("error in loading '%s' from '%s'", mpsinput, mpsformatfullname) + -- metapost.reporterror(result) + -- end + -- end + -- local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats") + -- report_metapost("making '%s' into '%s'", mpsinput, mpsformatfullname) + -- metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here + -- if lfs.isfile(mpsformatfullname) then + -- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname) + -- return metapost.load(mpsformatfullname) + -- else + -- report_metapost("problems with '%s' from '%s'", mpsinput, mpsformatfullname) + -- end + -- end else @@ -350,8 +392,9 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, if trace_graphics then if not mp_inp[mpx] then mp_tag = mp_tag + 1 - mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", tex.jobname,mp_tag),"w") - mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",tex.jobname,mp_tag),"w") + local jobname = tex.jobname + mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", jobname,mp_tag),"w") + mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",jobname,mp_tag),"w") end local banner = format("%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n", metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass)) mp_inp[mpx]:write(banner) diff --git a/tex/context/base/mult-aux.lua b/tex/context/base/mult-aux.lua index e0fd87a02..911888991 100644 --- a/tex/context/base/mult-aux.lua +++ b/tex/context/base/mult-aux.lua @@ -43,7 +43,7 @@ function namespaces.define(namespace,settings) local self = "\\" .. prefix .. namespace context.unprotect() -- context.installnamespace(namespace) - context("\\def\\%s%s{%s%s}",prefix,namespace,meaning,namespace) + context("\\def\\%s%s{%s%s}",prefix,namespace,meaning,namespace) -- or context.setvalue if trace_namespaces then report_namespaces("using namespace '%s' for '%s'",namespace,name) end diff --git a/tex/context/base/mult-aux.mkiv b/tex/context/base/mult-aux.mkiv index b4c6ad039..dc6aca920 100644 --- a/tex/context/base/mult-aux.mkiv +++ b/tex/context/base/mult-aux.mkiv @@ -2,7 +2,7 @@ %D [ file=mult-aux, %D version=2010.08.2, %D title=\CONTEXT\ Multilingual Macros, -%D subtitle=helpers, +%D subtitle=Helpers, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -14,6 +14,9 @@ % todo: setupxxx and setupxxxs (so a plural for the root setup and % we can consider blocking the root) +% todo (e.g for columnsets and registers): \definexxx[parent][1] +% + %D A generalization of \MKIV-like inheritance. Just something to play %D with (interface might change). The code here evolved in an email %D exchange between me and Wolgang Schuster. @@ -41,7 +44,7 @@ %D % \whateverparameter \c!test %D % \whateverparameterhash \c!test %D % \namedwhateverparameter \mycurrentwhatever \c!test -%D % \dosetwhateverstyleandcolor \c!style \c!color +%D % \usewhateverstyleandcolor \c!style \c!color %D % \everydefinewhatever (sets \currentwhatever) %D % \everypresetwhatever (can be used to reset parameters as we can redefine) %D % \everysetupwhatever (sets \currentwhatever) @@ -93,12 +96,8 @@ \expandafter\mult_interfaces_get_parameters_indeed \fi#2} -% \def\mult_interfaces_get_parameters#1% we can assume that the test already happened -% {\def\m_mult_interfaces_namespace{#1}% -% \mult_interfaces_get_parameters_indeed} - \def\mult_interfaces_get_parameters_indeed#1]% namespace already set - {\mult_interfaces_get_parameters_item#1,],\@relax@} + {\mult_interfaces_get_parameters_item#1,],\_e_o_p_} \def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before , {\if,#1,% dirty trick for testing #1=empty @@ -106,14 +105,14 @@ \else\if]#1% \doubleexpandafter\gobbleoneargument \else - \mult_interfaces_get_parameters_assign#1==\empty\@relax@ + \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_ \doubleexpandafter\mult_interfaces_get_parameters_item \fi\fi#2} \def\mult_interfaces_get_parameters_error#1#2#3% {\showassignerror{#2}{\the\inputlineno\space(#1)}} -\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\@relax@ +\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_ {\ifx\empty#1\empty \expandafter\mult_interfaces_get_parameters_error \else\ifx#3\empty @@ -125,21 +124,35 @@ \newif\ifassignment -\def\mult_check_for_assignment#1=#2#3\_end_ - {\expandafter\if\detokenize{#2}@\assignmentfalse\else\assignmenttrue\fi} +\def\mult_check_for_assignment_indeed#1=#2#3\_end_ + {\if#2@\assignmentfalse\else\assignmenttrue\fi} -% usage: \mult_check_for_assignment##1=@@_end_ +\def\mult_check_for_assignment#1% + {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_} % End of experimental code. +% the commented detokenized variant that backtracks ... needs testing usage first +% +% \let\whatever\relax +% +% \definetest[oeps][bagger=\whatever] +% +% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par +% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par + +\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter} + \unexpanded\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 + {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing %\def#3##1{\csname#4{#1#2}{##1}\endcsname}% \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\s!empty\else#4{##1}{##2}\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#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version + % \def#7##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#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}% \def#9##1{\csname#1#2:##1\endcsname}} @@ -251,30 +264,34 @@ \let\definehandlerparent\empty -\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% - {\ifx#4\relax\let#4\empty\fi +\unexpanded\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 \unexpanded\def#2{\dotripleempty#5}% \newtoks#6% \newtoks#7% - \def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] + \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] {\let#9#4% \edef#4{##1}% - \the#6% predefine \ifthirdargument + \the#6% predefine \edef#8{##2}% - \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2,##3]% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#4:}[##3]% \else\ifsecondargument - \mult_check_for_assignment##2=@@\_end_ + \the#6% predefine + \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_ \ifassignment \let#8\empty - \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3,##2]% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \mult_interfaces_get_parameters{#1#4:}[##2]% \else \edef#8{##2}% - \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2]% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% \fi \else + \the#6% predefine \let#8\empty - \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3]% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% \fi\fi \the#7% \let#4#9}} @@ -298,7 +315,7 @@ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it \newtoks#5% \newtoks#8% - \def#4[##1][##2]% maybe helper + \unexpanded\def#4[##1][##2]% maybe helper {\let#7#3% \ifsecondargument \def\mult_interfaces_with_comma_list_element####1% we will have a simple one as well @@ -342,7 +359,7 @@ \newtoks#8% \newtoks#9% \ifx#6\relax\let#6\empty\fi - \def#4[##1][##2]% maybe helper + \unexpanded\def#4[##1][##2]% maybe helper {\ifsecondargument % no commalist here % \setuplayout[whatever][key=value] \let#7#3% @@ -354,7 +371,8 @@ \ifx#3#6\the#8\fi % only switchsetups if previous == current \let#3#7% \else\iffirstargument - \mult_check_for_assignment##1=@@\_end_ % \docheckassignment{##1}% + % \mult_check_for_assignment{##1}% + \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ \ifassignment % \setuplayout[key=value] \let#7#3% @@ -413,7 +431,8 @@ \ifthirdargument \def\mult_interfaces_with_comma_list_element####1% {\edef#3{####1}% - \mult_interfaces_get_parameters{#1#3:}[\s!parent=#1##2,##3]% always sets parent + \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent \the#5}% \processcommalist[##1]\mult_interfaces_with_comma_list_element \else\ifsecondargument @@ -486,25 +505,26 @@ %D We don't need colons for such simple cases. -\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4% - {\def#2##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}% - \def#3##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% - \def#4##1{\csname#1##1\endcsname}} +\unexpanded\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#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{\csname#1##1\endcsname}} \unexpanded\def\installdirectparameterhandler#1#2% {\normalexpanded {\mult_interfaces_install_direct_parameter_handler {\noexpand#1}% + \expandafter\noexpand\csname current#2\endcsname \expandafter\noexpand\csname #2parameter\endcsname \expandafter\noexpand\csname detokenized#2parameter\endcsname \expandafter\noexpand\csname direct#2parameter\endcsname}} -\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4% +\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5% {\unexpanded\def#2{\dosingleempty#3}% - \newtoks#4% - \def#3[##1]% - {\mult_interfaces_get_parameters#1[##1]% - \the#4}} + \newtoks#5% + \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}% + \def#4{\mult_interfaces_get_parameters#1}} \unexpanded\def\installdirectsetuphandler#1#2% {\normalexpanded @@ -512,6 +532,7 @@ {\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}} \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% @@ -578,6 +599,34 @@ \unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} +%D Here is another experiment: + +\unexpanded\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}} + +\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4% + {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}% + \unexpanded\def#4[##1][##2]% + {\begingroup + \ifsecondargument + \edef#2{##1}% + #3[##2]% + \else\iffirstargument + \doifassignmentelse{##1} + {\let#2\empty + #3[##1]}% + {\edef#2{##1}}% + \else + \let#2\empty + \fi\fi + \directsetup{handler:action:#1}% + \endgroup}} + % First we had, in tune with the regular system variables: % % \starttyping @@ -606,9 +655,7 @@ \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{\number \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> @@ -635,6 +682,10 @@ \ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}% \fi} +\def\mult_interfaces_get_parameters_error#1#2#3% redefined + {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}% + \waitonfatalerror} + % We install two core namespaces here, as we want nice error messages. Maybe % we will reserve the first 9. @@ -642,6 +693,34 @@ \installcorenamespace{fontinstancebasic} \installcorenamespace{fontinstanceclass} +%D The next one is handy for local assignments. + +\installcorenamespace{dummy} + +\letvalue\??dummy\empty + + \def\dummyparameter #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname} + \def\directdummyparameter#1{\csname\??dummy#1\endcsname} +\unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname} +\unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname} + +% \unexpanded\def\getdummyparameters +% {\mult_interfaces_get_parameters\??dummy} + +\unexpanded\def\getdummyparameters[#1% + {\if\noexpand#1]% + \expandafter\gobbleoneargument + \else + \let\m_mult_interfaces_namespace\??dummy + \expandafter\mult_interfaces_get_parameters_indeed + \fi#1} + +\mult_interfaces_install_style_and_color_handler + \directdummyparameter + \usedummystyleandcolor + \usedummystyleparameter + \usedummycolorparameter + % Maybe a \definecorenamespace[name][directparameter,directsetup][parent] % but we don't gain much. Actually we might just inline all definitions. @@ -707,6 +786,31 @@ \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname \fi} +%D Another helper: + +\unexpanded\def\doifelsecommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\unexpanded\def\doifcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\unexpanded\def\doifnotcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\let\doifcommandhandlerelse\doifelsecommandhandler + %D Conventions: %D %D \starttyping diff --git a/tex/context/base/mult-chk.lua b/tex/context/base/mult-chk.lua index 43e7c5121..e3908ad40 100644 --- a/tex/context/base/mult-chk.lua +++ b/tex/context/base/mult-chk.lua @@ -9,9 +9,10 @@ if not modules then modules = { } end modules ['mult-chk'] = { local format = string.format local lpegmatch = lpeg.match local type = type -local make_settings_to_hash_pattern, settings_to_set = utilities.parsers.make_settings_to_hash_pattern, utilities.parsers.settings_to_set -local allocate = utilities.storage.allocate +local make_settings_to_hash_pattern = utilities.parsers.make_settings_to_hash_pattern +local settings_to_set = utilities.parsers.settings_to_set +local allocate = utilities.storage.allocate local report_interface = logs.reporter("interface","checking") diff --git a/tex/context/base/mult-chk.mkiv b/tex/context/base/mult-chk.mkiv index 9260d2040..1d02f166d 100644 --- a/tex/context/base/mult-chk.mkiv +++ b/tex/context/base/mult-chk.mkiv @@ -35,8 +35,8 @@ \registerctxluafile{mult-chk}{1.001} -\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys} -\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys} +\unexpanded\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys} +\unexpanded\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys} \def\mult_checkers_set_valid_parameter_keys[#1][#2]{\ctxlua{interfaces.setvalidkeys("#1",\!!bs#2\!!es)}} \def\mult_checkers_add_valid_parameter_keys[#1][#2]{\ctxlua{interfaces.addvalidkeys("#1",\!!bs#2\!!es)}} @@ -61,12 +61,12 @@ \expandafter\mult_checkers_get_checked_parameters_nop_indeed \fi{#3}#5} -\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]% - {\def\p!dogetparameter{\p!doassign#1}% - \xprocesscommaitem#2,],\@relax@} +\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]% needs checking with adapted syst-aux.mkiv + {\def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#1}% will change + \syst_helpers_process_comma_item#2,],\_e_o_p_} -\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop} -\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes} +\unexpanded\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop} +\unexpanded\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes} \disablecheckparameters diff --git a/tex/context/base/mult-de.mkii b/tex/context/base/mult-de.mkii index dee614e5e..ce34b6a5b 100644 --- a/tex/context/base/mult-de.mkii +++ b/tex/context/base/mult-de.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{nummerierung} \setinterfacevariable{environment}{umgebung} \setinterfacevariable{even}{gerade} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{extern} \setinterfacevariable{fact}{gegeben} \setinterfacevariable{february}{februar} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{untervorwaerts} \setinterfacevariable{subject}{thema} \setinterfacevariable{subpage}{unterseite} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{unterabsatz} \setinterfacevariable{subsubject}{unterthema} \setinterfacevariable{subsubsection}{unterunterabsatz} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{ersteseite} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusout} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{label} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{letzteseite} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{links} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{linkersubsatz} \setinterfaceconstant{lefttext}{linkertext} \setinterfaceconstant{leftwidth}{linkerbreite} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{niveau} \setinterfaceconstant{levels}{niveaus} \setinterfaceconstant{limittext}{limittext} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{minhoehe} \setinterfaceconstant{minwidth}{minbreite} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{name} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{seperator} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{setups} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{objektabstand} \setinterfaceconstant{sidealign}{sidealign} \setinterfaceconstant{sidemethod}{sidemethod} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{zeichen} \setinterfaceconstant{size}{groesse} \setinterfaceconstant{small}{klein} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sorttype} \setinterfaceconstant{source}{quelle} diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua index 1a4921a28..26b2b8529 100644 --- a/tex/context/base/mult-def.lua +++ b/tex/context/base/mult-def.lua @@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['mult-def'] = { comment = "companion to mult-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } return { @@ -6449,6 +6450,18 @@ return { }, }, ["constants"]={ + ["less"]={ + ["en"]="less", + ["nl"]="minder", + }, + ["more"]={ + ["en"]="more", + ["nl"]="meer", + }, + ["solution"]={ + ["en"]="solution", + ["nl"]="oplossing", + }, ["anchor"]={ ["en"]="anchor", ["nl"]="anker", @@ -7805,6 +7818,16 @@ return { ["pe"]="تمرکز", ["ro"]="focus", }, + ["firstpage"]={ + ["cs"]="prvnistranka", + ["de"]="ersteseite", + ["en"]="firstpage", + ["fr"]="premierepage", + ["it"]="primapagina", + ["nl"]="eerstepagina", + ["pe"]="صفحهاول", + ["ro"]="primapagina", + }, ["focusin"]={ ["cs"]="focusin", ["de"]="focusin", @@ -8362,6 +8385,16 @@ return { ["pe"]="برچسب", ["ro"]="eticheta", }, + ["lastpage"]={ + ["cs"]="poslednistrana", + ["de"]="letzteseite", + ["en"]="lastpage", + ["fr"]="dernierepage", + ["it"]="ultimapagina", + ["nl"]="laatstepagina", + ["pe"]="صفحهآخر", + ["ro"]="ultimapagina", + }, ["left"]={ ["cs"]="vlevo", ["de"]="links", @@ -10023,6 +10056,10 @@ return { ["pe"]="بارگذاریها", ["ro"]="setups", }, + ["shrink"]={ + ["en"]="shrink", + ["nl"]="krimp", + }, ["side"]={ ["cs"]="pocitat", ["de"]="objektabstand", @@ -11277,6 +11314,9 @@ return { ["en"]="end", ["nl"]="eind", }, + ["export"] = { + ["en"]="export", + }, ["begin"]={ ["en"]="begin", ["nl"]="begin", @@ -15721,6 +15761,9 @@ return { ["pe"]="زیرصفحه", ["ro"]="subpagina", }, + ["subs"]={ + ["en"]="subs", + }, ["subsection"]={ ["cs"]="podsekce", ["de"]="unterabsatz", diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv index f6f50ae72..0ee59d8c3 100644 --- a/tex/context/base/mult-def.mkiv +++ b/tex/context/base/mult-def.mkiv @@ -13,21 +13,75 @@ \unprotect -\setvalue{\??mi :czech}{cs} -\setvalue{\??mi :german}{de} -\setvalue{\??mi :english}{en} -\setvalue{\??mi :french}{fr} -\setvalue{\??mi :italian}{it} -\setvalue{\??mi :dutch}{nl} -\setvalue{\??mi :persian}{pe} -\setvalue{\??mi:romanian}{ro} - -\def\userinterfacetag{\ifcsname\??mi:\currentinterface\endcsname\csname\??mi:\currentinterface\endcsname\else en\fi} -\def\userresponsestag{\ifcsname\??mi:\currentresponses\endcsname\csname\??mi:\currentresponses\endcsname\else en\fi} +\installcorenamespace{multilingual} + +\setvalue{\??multilingual czech}{cs} +\setvalue{\??multilingual german}{de} +\setvalue{\??multilingual english}{en} +\setvalue{\??multilingual french}{fr} +\setvalue{\??multilingual italian}{it} +\setvalue{\??multilingual dutch}{nl} +\setvalue{\??multilingual persian}{pe} +\setvalue{\??multilingual romanian}{ro} + +\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\csname\??multilingual\currentinterface\endcsname\else en\fi} +\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\csname\??multilingual\currentresponses\endcsname\else en\fi} % \input mult-\userinterfacetag \relax % \input mult-m\userresponsestag \relax \ctxlua{interfaces.setuserinterface("\userinterfacetag","\userresponsestag")} +% start todo: + +\def\c!language {language} +\def\c!compressseparator{compressseparator} +\def\c!renderingsetup {renderingsetup} +\def\c!filler {filler} +\def\c!resources {resources} +\def\c!first {first} +\def\c!last {last} +\def\c!quotechar {quotechar} +\def\c!commentchar {commentchar} +\def\c!symbolcommand {symbolcommand} +\def\c!xmlsetup {xmlsetup} +\def\c!comma {comma} +\def\c!period {period} +\def\c!monthconversion {monthconversion} +\def\c!comment {comment} +\def\c!textalign {textalign} +\def\c!up {up} +\def\c!down {down} + +\def\v!compressseparator{compressseparator} +\def\v!notation {notation} +\def\v!endnote {endnote} +\def\v!interactive {interactive} +\def\v!autopunctuation {autopunctuation} +\def\v!integral {integral} +\def\v!shiftup {shiftup} +\def\v!shiftdown {shiftdown} +\def\v!construction {construction} +\def\v!unframed {unframed} +\def\v!chemical {chemical} +\def\v!chemicals {chemicals} + +\def\s!lcgreek {lcgreek} +\def\s!ucgreek {ucgreek} +\def\s!italics {italics} +\def\s!integral {integral} +\def\s!insert {insert} % maybe insertclass + +\def\c!HL {HL} +\def\c!VL {VL} +\def\c!NL {NL} + +\ifdefined\v!kerncharacters\else \def\v!kerncharacters{kerncharacters} \fi % no time now for translations should be a e! actually +\ifdefined\v!stretched \else \def\v!stretched {stretched} \fi +\ifdefined\v!vulgarfraction\else \def\v!vulgarfraction{vulgarfraction} \fi +\ifdefined\v!block \else \def\v!block {block} \fi +\ifdefined\v!rule \else \def\v!rule {rule} \fi + +% stop todo + \protect \endinput diff --git a/tex/context/base/mult-dim.mkvi b/tex/context/base/mult-dim.mkvi index 0889b411e..bad7af713 100644 --- a/tex/context/base/mult-dim.mkvi +++ b/tex/context/base/mult-dim.mkvi @@ -35,6 +35,7 @@ \installcorenamespace{dimensionnormal} \setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint} +\setvalue{\??dimensionnormal \empty }#value#dimension#small#medium#big{#dimension\zeropoint} \setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax} \setvalue{\??dimensionnormal \v!medium}#value#dimension#small#medium#big{#dimension=#medium\relax} \setvalue{\??dimensionnormal \v!big }#value#dimension#small#medium#big{#dimension=#big\relax} diff --git a/tex/context/base/mult-en.mkii b/tex/context/base/mult-en.mkii index b801ebc5f..860060247 100644 --- a/tex/context/base/mult-en.mkii +++ b/tex/context/base/mult-en.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{enumeration} \setinterfacevariable{environment}{environment} \setinterfacevariable{even}{even} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{external} \setinterfacevariable{fact}{fact} \setinterfacevariable{february}{february} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{subforward} \setinterfacevariable{subject}{subject} \setinterfacevariable{subpage}{subpage} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{subsection} \setinterfacevariable{subsubject}{subsubject} \setinterfacevariable{subsubsection}{subsubsection} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{firstpage} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusout} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{label} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{lastpage} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{left} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{leftsubsentence} \setinterfaceconstant{lefttext}{lefttext} \setinterfaceconstant{leftwidth}{leftwidth} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{level} \setinterfaceconstant{levels}{levels} \setinterfaceconstant{limittext}{limittext} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{minheight} \setinterfaceconstant{minwidth}{minwidth} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{name} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{separator} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{setups} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{side} \setinterfaceconstant{sidealign}{sidealign} \setinterfaceconstant{sidemethod}{sidemethod} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{sign} \setinterfaceconstant{size}{size} \setinterfaceconstant{small}{small} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sorttype} \setinterfaceconstant{source}{source} diff --git a/tex/context/base/mult-fr.mkii b/tex/context/base/mult-fr.mkii index 5717cf97b..f52a761d2 100644 --- a/tex/context/base/mult-fr.mkii +++ b/tex/context/base/mult-fr.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{enumeration} \setinterfacevariable{environment}{environement} \setinterfacevariable{even}{paire} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{external} \setinterfacevariable{fact}{fait} \setinterfacevariable{february}{fevrier} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{sousavance} \setinterfacevariable{subject}{sujet} \setinterfacevariable{subpage}{souspage} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{soussection} \setinterfacevariable{subsubject}{soussujet} \setinterfacevariable{subsubsection}{soussoussection} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{premierepage} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusout} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{etiquette} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{dernierepage} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{gauche} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{sousphrasegauche} \setinterfaceconstant{lefttext}{textegauche} \setinterfaceconstant{leftwidth}{largeurgauche} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{niveau} \setinterfaceconstant{levels}{niveaux} \setinterfaceconstant{limittext}{limittext} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{hauteurmin} \setinterfaceconstant{minwidth}{largeurmin} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{nom} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{separateur} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{reglages} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{cote} \setinterfaceconstant{sidealign}{sidealign} \setinterfaceconstant{sidemethod}{sidemethod} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{signe} \setinterfaceconstant{size}{dimension} \setinterfaceconstant{small}{petit} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sorttype} \setinterfaceconstant{source}{origine} diff --git a/tex/context/base/mult-fun.lua b/tex/context/base/mult-fun.lua new file mode 100644 index 000000000..ab9c5d434 --- /dev/null +++ b/tex/context/base/mult-fun.lua @@ -0,0 +1,95 @@ +return { + internals = { + -- + "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", + "shadefactor", + "textextoffset", + "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", + "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", + "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent", +-- "originlength", "tickstep ", "ticklength", +-- "autoarrows", "ahfactor", +-- "angleoffset", anglelength", anglemethod", + }, + commands = { + -- + "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", + "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", + "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", + "paired", "tripled", + "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", + -- "halfcircle", "quartercircle", + "llcircle", "lrcircle", "urcircle", "ulcircle", + "tcircle", "bcircle", "lcircle", "rcircle", + "lltriangle", "lrtriangle", "urtriangle", "ultriangle", + "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", + "punked", "curved", "unspiked", "simplified", "blownup", "stretched", + "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", + "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", + "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", + "llmoved", "lrmoved", "urmoved", "ulmoved", + "rightarrow", "leftarrow", "centerarrow", + "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", + "bottomboundary", "leftboundary", "topboundary", "rightboundary", + "xsized", "ysized", "xysized", "sized", "xyscaled", + "intersection_point", "intersection_found", "penpoint", + "bbwidth", "bbheight", + "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", + "withcircularshade", "withlinearshade", + "cmyk", "spotcolor", "multitonecolor", "namedcolor", + "drawfill", "undrawfill", + "inverted", "uncolored", "softened", "grayed", "greyed", + "onlayer", + "along", + "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", + "colordecimals", "ddecimal", "dddecimal", "ddddecimal", + "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "autoalign", + "transparent", "withtransparency", + "asgroup", + "infont", -- redefined usign textext + -- "property", "withproperties", "properties", -- not yet + "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", + "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", + "space", "CRLF", + "grayscale", "greyscale", "withgray", "withgrey", "colorpart", + "readfile", + "clearxy", "unitvector", "center", -- redefined + "epsed", "anchored", + "originpath", "infinite", + "break", + "xstretched", "ystretched", "snapped", + -- + "pathconnectors", "function", "constructedpath", "constructedpairs", + "punkedfunction", "curvedfunction", "tightfunction", + "punkedpath", "curvedpath", "tightpath", + "punkedpairs", "curvedpairs", "tightpairs", + -- + "evenly", "oddly", + -- + "condition", + -- + "pushcurrentpicture", "popcurrentpicture", + -- + "arrowpath", +-- "colorlike", "dowithpath", "rangepath", "straightpath", "addbackground", +-- "cleanstring", "asciistring", "setunstringed", "getunstringed", "unstringed", +-- "showgrid", +-- "phantom", +-- "xshifted", "yshifted", +-- "drawarrowpath", "midarrowhead", "arrowheadonpath", +-- "drawxticks", "drawyticks", "drawticks", +-- "pointarrow", +-- "thefreelabel", "freelabel", "freedotlabel", +-- "anglebetween", "colorcircle", +-- "remapcolors", "normalcolors", "resetcolormap", "remapcolor", "remappedcolor", +-- "recolor", "refill", "redraw", "retext", "untext", "restroke", "reprocess", "repathed", + "tensecircle", "roundedsquare", + "colortype", "whitecolor", "blackcolor", + -- +-- "swappointlabels", + "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", + "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", + "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", + "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", + }, +} diff --git a/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua index d14f38ad5..59eed7d83 100644 --- a/tex/context/base/mult-ini.lua +++ b/tex/context/base/mult-ini.lua @@ -6,16 +6,17 @@ if not modules then modules = { } end modules ['mult-ini'] = { license = "see context related readme files" } -local format, gmatch, gsub = string.format, string.gmatch, string.gsub +local format, gmatch, gsub, match = string.format, string.gmatch, string.gsub, string.match local lpegmatch = lpeg.match local serialize = table.serialize -local allocate = utilities.storage.allocate -local mark = utilities.storage.mark -local contextsprint = context.sprint -local setmetatableindex = table.setmetatableindex +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark +local prtcatcodes = catcodes.numbers.prtcatcodes +local contextsprint = context.sprint +local setmetatableindex = table.setmetatableindex -local report_interface = logs.reporter("interface","initialization") +local report_interface = logs.reporter("interface","initialization") interfaces = interfaces or { } interfaces.constants = mark(interfaces.constants or { }) @@ -25,27 +26,38 @@ interfaces.formats = mark(interfaces.formats or { }) interfaces.translations = mark(interfaces.translations or { }) interfaces.corenamespaces = mark(interfaces.corenamespaces or { }) -storage.register("interfaces/constants", interfaces.constants, "interfaces.constants") -storage.register("interfaces/variables", interfaces.variables, "interfaces.variables") -storage.register("interfaces/elements", interfaces.elements, "interfaces.elements") -storage.register("interfaces/formats", interfaces.formats, "interfaces.formats") -storage.register("interfaces/translations", interfaces.translations, "interfaces.translations") -storage.register("interfaces/corenamespaces", interfaces.corenamespaces, "interfaces.corenamespaces") +local registerstorage = storage.register +local sharedstorage = storage.shared + +local constants = interfaces.constants +local variables = interfaces.variables +local elements = interfaces.elements +local formats = interfaces.formats +local translations = interfaces.translations +local corenamespaces = interfaces.corenamespaces +local reporters = { } -- just an optimization + +registerstorage("interfaces/constants", constants, "interfaces.constants") +registerstorage("interfaces/variables", variables, "interfaces.variables") +registerstorage("interfaces/elements", elements, "interfaces.elements") +registerstorage("interfaces/formats", formats, "interfaces.formats") +registerstorage("interfaces/translations", translations, "interfaces.translations") +registerstorage("interfaces/corenamespaces", corenamespaces, "interfaces.corenamespaces") interfaces.interfaces = { "cs", "de", "en", "fr", "it", "nl", "ro", "pe", } -storage.shared.currentinterface = storage.shared.currentinterface or "en" -storage.shared.currentresponse = storage.shared.currentresponse or "en" +sharedstorage.currentinterface = sharedstorage.currentinterface or "en" +sharedstorage.currentresponse = sharedstorage.currentresponse or "en" -local currentinterface = storage.shared.currentinterface -local currentresponse = storage.shared.currentresponse +local currentinterface = sharedstorage.currentinterface +local currentresponse = sharedstorage.currentresponse local complete = allocate() interfaces.complete = complete -local function resolve(t,k) -- one access needed to get loaded +local function resolve(t,k) -- one access needed to get loaded (not stored!) report_interface("loading interface definitions from 'mult-def.lua'") complete = dofile(resolvers.findfile("mult-def.lua")) report_interface("loading interface messages from 'mult-mes.lua'") @@ -56,14 +68,6 @@ end setmetatableindex(complete, resolve) -local constants = interfaces.constants -local variables = interfaces.variables -local elements = interfaces.elements -local formats = interfaces.formats -local translations = interfaces.translations -local corenamespaces = interfaces.corenamespaces -local reporters = { } -- just an optimization - local function valueiskey(t,k) -- will be helper t[k] = k return k @@ -75,7 +79,7 @@ setmetatableindex(elements, valueiskey) setmetatableindex(formats, valueiskey) setmetatableindex(translations, valueiskey) -function commands.registernamespace(n,namespace) +function interfaces.registernamespace(n,namespace) corenamespaces[n] = namespace end @@ -85,7 +89,7 @@ local function resolve(t,k) return v end -setmetatableindex(reporters, resolve) +setmetatableindex(reporters,resolve) for category, _ in next, translations do -- We pre-create reporters for already defined messages @@ -146,7 +150,7 @@ function interfaces.getmessage(category,tag,default) end function interfaces.doifelsemessage(category,tag) - return commands.testcase(formats[fulltag(category,tag)]) + return formats[fulltag(category,tag)] end local splitter = lpeg.splitat(",") @@ -184,45 +188,38 @@ end logs.setmessenger(context.verbatim.ctxreport) --- status - -function commands.writestatus(category,message,...) - local r = reporters[category] - r(message,...) -end - -- initialization function interfaces.setuserinterface(interface,response) - storage.shared.currentinterface, currentinterface = interface, interface - storage.shared.currentresponse, currentresponse = response, response + sharedstorage.currentinterface, currentinterface = interface, interface + sharedstorage.currentresponse, currentresponse = response, response if environment.initex then local nofconstants = 0 for given, constant in next, complete.constants do constant = constant[interface] or constant.en or given constants[constant] = given -- breedte -> width - contextsprint("\\do@sicon{",given,"}{",constant,"}") + contextsprint(prtcatcodes,"\\ui_c{",given,"}{",constant,"}") -- user interface constant nofconstants = nofconstants + 1 end local nofvariables = 0 for given, variable in next, complete.variables do variable = variable[interface] or variable.en or given variables[given] = variable -- ja -> yes - contextsprint("\\do@sivar{",given,"}{",variable,"}") + contextsprint(prtcatcodes,"\\ui_v{",given,"}{",variable,"}") -- user interface variable nofvariables = nofvariables + 1 end local nofelements = 0 for given, element in next, complete.elements do element = element[interface] or element.en or given elements[element] = given - contextsprint("\\do@siele{",given,"}{",element,"}") + contextsprint(prtcatcodes,"\\ui_e{",given,"}{",element,"}") -- user interface element nofelements = nofelements + 1 end local nofcommands = 0 for given, command in next, complete.commands do command = command[interface] or command.en or given if command ~= given then - contextsprint("\\do@sicom{",given,"}{",command,"}") + contextsprint(prtcatcodes,"\\ui_m{",given,"}{",command,"}") -- user interface macro end nofcommands = nofcommands + 1 end @@ -244,12 +241,12 @@ end interfaces.cachedsetups = interfaces.cachedsetups or { } interfaces.hashedsetups = interfaces.hashedsetups or { } -storage.register("interfaces/cachedsetups", interfaces.cachedsetups, "interfaces.cachedsetups") -storage.register("interfaces/hashedsetups", interfaces.hashedsetups, "interfaces.hashedsetups") - local cachedsetups = interfaces.cachedsetups local hashedsetups = interfaces.hashedsetups +storage.register("interfaces/cachedsetups", cachedsetups, "interfaces.cachedsetups") +storage.register("interfaces/hashedsetups", hashedsetups, "interfaces.hashedsetups") + function interfaces.cachesetup(t) local hash = serialize(t) local done = hashedsetups[hash] @@ -271,3 +268,40 @@ function interfaces.interfacedcommand(name) local command = complete.commands[name] return command and command[currentinterface] or name end + +-- interface + +function commands.writestatus(category,message,...) + local r = reporters[category] + if r then + r(message,...) + end +end + +commands.registernamespace = interfaces.registernamespace +commands.setinterfaceconstant = interfaces.setconstant +commands.setinterfacevariable = interfaces.setvariable +commands.setinterfaceelement = interfaces.setelement +commands.setinterfacemessage = interfaces.setmessage +commands.setinterfacemessages = interfaces.setmessages +commands.showmessage = interfaces.showmessage + +function commands.doifelsemessage(category,tag) + commands.doifelse(interfaces.doifelsemessage(category,tag)) +end + +function commands.getmessage(category,tag,default) + context(interfaces.getmessage(category,tag,default)) +end + +function commands.showassignerror(namespace,key,value,line) + local ns, instance = match(namespace,"^(%d+)[^%a]+(%a+)") + if ns then + namespace = corenamespaces[tonumber(ns)] or ns + end + if instance then + context.writestatus("setup",format("error in line %s, namespace %q, instance %q, key %q",line,namespace,instance,key)) + else + context.writestatus("setup",format("error in line %s, namespace %q, key %q",line,namespace,key)) + end +end diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv index f0d47103d..eb5517277 100644 --- a/tex/context/base/mult-ini.mkiv +++ b/tex/context/base/mult-ini.mkiv @@ -101,24 +101,27 @@ %D %D \starttyping %D \hrule width 10pt height 2pt depth 1pt -%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{\!!height}, -%D \type{\!!width} and \type{\!!depth} as respectively -%D \type{height}, \type{width} and \type{depth}. Using this +%D One condition is that we have defined \type {\s!height}, +%D \type {\s!width} and \type {\s!depth} as respectively +%D \type {height}, \type {width} and \type {depth}. Using this %D scheme therefore only makes sense when a token sequence is %D used more than once. Savings like this should of course be %D implemented in english, just because \TEX\ is english. -\def\!!width {width} -\def\!!height{height} -\def\!!depth {depth} -\def\!!plus {plus} -\def\!!minus {minus} -\def\!!fill {fill} -\def\!!to {to} -\def\!!spread{spread} +\def\s!width {width} \let\!!width \s!width % obsolete +\def\s!height{height} \let\!!height\s!height % obsolete +\def\s!depth {depth} \let\!!depth \s!depth % obsolete +\def\s!spread{spread} \let\!!spread\s!spread % obsolete +\def\s!plus {plus} \let\!!plus \s!plus % obsolete +\def\s!minus {minus} \let\!!minus \s!minus % obsolete +\def\s!fil {fil} +\def\s!fill {fill} \let\!!fill \s!fill % obsolete +\def\s!filll {filll} +\def\s!to {to} \let\!!to \s!to % obsolete +\def\s!attr {attr} %D Kind of special: @@ -361,7 +364,7 @@ \doifinsetelse{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} \def\mult_messages_start_yes#1#2\stopmessages - {\ctxlua{interfaces.setmessages("#1",\!!bs#2\!!es)}% + {\ctxcommand{setinterfacemessages("#1",\!!bs#2\!!es)}% \egroup} \def\mult_messages_start_nop#1#2\stopmessages @@ -371,12 +374,12 @@ \unexpanded\def\setinterfacemessage#1#2#3% {\ifcsname\m!prefix!#1\endcsname\else\setgvalue{\m!prefix!#1}{#1}\fi - \ctxlua{interfaces.setmessage("#1","#2",\!!bs#3\!!es)}} + \ctxcommand{setinterfacemessage("#1","#2",\!!bs#3\!!es)}} -\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\cldcontext{interfaces.getmessage("#1","#2")}}} -\unexpanded\def\getmessage #1#2{\cldcontext{interfaces.getmessage("#1","#2")}} -\unexpanded\def\doifelsemessage #1#2{\ctxlua{interfaces.doifelsemessage("#1","#2")}} -\unexpanded\def\showmessage #1#2#3{\ctxlua{interfaces.showmessage("#1","#2",\!!bs#3\!!es)}} +\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\ctxcommand{getmessage("#1","#2")}}} +\unexpanded\def\getmessage #1#2{\ctxcommand{getmessage("#1","#2")}} +\unexpanded\def\doifelsemessage #1#2{\ctxcommand{doifelsemessage("#1","#2")}} +\unexpanded\def\showmessage #1#2#3{\ctxcommand{showmessage("#1","#2",\!!bs#3\!!es)}} \unexpanded\def\writestatus #1#2{\ctxcommand{writestatus("#1",\!!bs#2\!!es)}} %D \macros @@ -723,11 +726,11 @@ % temporary mkiv hack (we can best just store the whole table in memory) \unexpanded\def\setinterfaceconstant#1#2% - {\ctxlua{interfaces.setconstant("#1","#2")}% + {\ctxcommand{setinterfaceconstant("#1","#2")}% \expandafter\def\csname\c!prefix!#1\endcsname{#1}} \unexpanded\def\setinterfacevariable#1#2% - {\ctxlua{interfaces.setvariable("#1","#2")}% + {\ctxcommand{setinterfacevariable("#1","#2")}% \expandafter\def\csname\v!prefix!#1\endcsname{#2}} %D \macros @@ -756,7 +759,7 @@ %D part is needed, we use a \type{-}: \unexpanded\def\setinterfaceelement#1#2% - {\ctxlua{interfaces.setelement("#1","#2")}% + {\ctxcommand{setinterfaceelement("#1","#2")}% \ifcsname\e!prefix!#1\endcsname \doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}% \else @@ -776,15 +779,27 @@ %D For at the \LUA\ end (experiment): -\def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}% - \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english -\def\do@sivar#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}} -\def\do@siele#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}} -\def\do@sicom#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}} +% \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}% +% \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english +% \def\do@sivar#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}} +% \def\do@siele#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}} +% \def\do@sicom#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}} +% +% \startinterface english +% +% \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}} +% +% \stopinterface + +\def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}% + \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english +\def\ui_v#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}} +\def\ui_e#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}} +\def\ui_m#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}} \startinterface english - \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}} + \def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}} \stopinterface @@ -814,7 +829,8 @@ \def\contextversion {unknown} \def\contextversionnumber{0} \else - \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5} + %\def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5} + \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi\purenumber{#2}\ifnum#3<10 0\fi\purenumber{#3} #4:#5} \edef\contextversionnumber{\expandafter\contextversionnumber\contextversion\relax\space\contextmark} \fi diff --git a/tex/context/base/mult-it.mkii b/tex/context/base/mult-it.mkii index 88a371ac7..b91e3ee5b 100644 --- a/tex/context/base/mult-it.mkii +++ b/tex/context/base/mult-it.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{enumerazione} \setinterfacevariable{environment}{ambiente} \setinterfacevariable{even}{pari} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{esterno} \setinterfacevariable{fact}{fatto} \setinterfacevariable{february}{febbraio} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{sottoavanti} \setinterfacevariable{subject}{argomento} \setinterfacevariable{subpage}{sottopagina} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{sottocapoverso} \setinterfacevariable{subsubject}{sottoargomento} \setinterfacevariable{subsubsection}{sottosottocapoverso} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{primapagina} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusout} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{etichetta} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{ultimapagina} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{sinistra} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{sottofrasesinistra} \setinterfaceconstant{lefttext}{testosinistro} \setinterfaceconstant{leftwidth}{ampiezzasinistra} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{livello} \setinterfaceconstant{levels}{livelli} \setinterfaceconstant{limittext}{limittext} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{altezzamin} \setinterfaceconstant{minwidth}{ampiezzamin} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{nome} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{separatore} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{setups} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{lato} \setinterfaceconstant{sidealign}{sidealign} \setinterfaceconstant{sidemethod}{sidemethod} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{segno} \setinterfaceconstant{size}{dimensione} \setinterfaceconstant{small}{piccolo} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sorttype} \setinterfaceconstant{source}{origine} diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua index 7d61d0427..bffdd288f 100644 --- a/tex/context/base/mult-low.lua +++ b/tex/context/base/mult-low.lua @@ -17,6 +17,7 @@ return { "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", + "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", -- -- @@ -122,8 +123,10 @@ return { "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", + "startcontextcode", "stopcontextcode", -- "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", + "doifelsecommandhandler","doifnotcommandhandler","doifcommandhandler", -- "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", @@ -134,13 +137,22 @@ return { -- "then", -- - "donothing", "dontcomplain", + "firstargumentfalse", "firstargumenttrue", + "secondargumentfalse", "secondargumenttrue", + "thirdargumentfalse", "thirdargumenttrue", + "fourthargumentfalse", "fourthargumenttrue", + "fifthargumentfalse", "fifthsargumenttrue", + "sixthargumentfalse", "sixtsargumenttrue", + -- + "doglobal", "dodoglobal", "redoglobal", "resetglobal", + -- + "donothing", "dontcomplain", "forgetall", -- "donetrue", "donefalse", -- "htdp", "unvoidbox", - "vfilll", + "hfilll", "vfilll", -- "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", -- @@ -165,10 +177,15 @@ return { "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", -- + "availablehsize", "localhsize", "setlocalhsize", + -- "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", -- "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", + "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", + "scratchxposition", "scratchyposition", + "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", -- "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", @@ -176,6 +193,9 @@ return { "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", + "scratchnx", "scratchny", "scratchmx", "scratchmy", + -- + "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", -- "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", @@ -184,33 +204,38 @@ return { "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", - "doifdimensionelse", "doifnumberelse", + "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", - "doifassignmentelse", + "doifassignmentelse", "docheckassignment", -- "tracingall", "tracingnone", "loggingall", -- - "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", + "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", -- - "endgraf", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", + "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", -- "executeifdefined", -- "singleexpandafter", "doubleexpandafter", "tripleexpandafter", -- - "dontleavehmode", "removelastspace", "removeunwantedspaces", + "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", -- "wait", "writestatus", "define", "redefine", -- - "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "measure", + "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", -- "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", - "globallet", "glet", + -- + "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", + -- "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", -- + "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", + "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", + -- "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", -- @@ -232,9 +257,10 @@ return { -- "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", + "newsignal", -- "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", - "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", + "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", -- "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", @@ -245,6 +271,8 @@ return { -- "startnointerference", "stopnointerference", -- - "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "begstrut", "endstrut", + "twodigits","threedigits", + -- + "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", } } diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua index 473c86d35..68a392190 100644 --- a/tex/context/base/mult-mes.lua +++ b/tex/context/base/mult-mes.lua @@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['mult-mes'] = { comment = "companion to mult-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } -- floatsblocks -> floats diff --git a/tex/context/base/mult-nl.mkii b/tex/context/base/mult-nl.mkii index 01f7fa204..dbce41d85 100644 --- a/tex/context/base/mult-nl.mkii +++ b/tex/context/base/mult-nl.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{doornummering} \setinterfacevariable{environment}{omgeving} \setinterfacevariable{even}{even} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{extern} \setinterfacevariable{fact}{gegeven} \setinterfacevariable{february}{februari} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{subvooruit} \setinterfacevariable{subject}{onderwerp} \setinterfacevariable{subpage}{subpagina} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{subparagraaf} \setinterfacevariable{subsubject}{subonderwerp} \setinterfacevariable{subsubsection}{subsubparagraaf} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{eerstepagina} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusuit} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{label} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{laatstepagina} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{links} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{linkersubzin} \setinterfaceconstant{lefttext}{linkertekst} \setinterfaceconstant{leftwidth}{linkerbreedte} +\setinterfaceconstant{less}{minder} \setinterfaceconstant{level}{niveau} \setinterfaceconstant{levels}{niveaus} \setinterfaceconstant{limittext}{limiettekst} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{minhoogte} \setinterfaceconstant{minwidth}{minbreedte} \setinterfaceconstant{monthconversion}{maandconversie} +\setinterfaceconstant{more}{meer} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{naam} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{scheider} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{setups} +\setinterfaceconstant{shrink}{krimp} \setinterfaceconstant{side}{zij} \setinterfaceconstant{sidealign}{zijuitlijnen} \setinterfaceconstant{sidemethod}{zijmethode} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{teken} \setinterfaceconstant{size}{formaat} \setinterfaceconstant{small}{klein} +\setinterfaceconstant{solution}{oplossing} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sortering} \setinterfaceconstant{source}{bron} diff --git a/tex/context/base/mult-pe.mkii b/tex/context/base/mult-pe.mkii index 6dcd2fef6..58d3ff527 100644 --- a/tex/context/base/mult-pe.mkii +++ b/tex/context/base/mult-pe.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{شمارهبندی} \setinterfacevariable{environment}{محیط} \setinterfacevariable{even}{زوج} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{خارجی} \setinterfacevariable{fact}{fact} \setinterfacevariable{february}{فوریه} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{زیرجلوگرد} \setinterfacevariable{subject}{موضوع} \setinterfacevariable{subpage}{زیرصفحه} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{زیربخش} \setinterfacevariable{subsubject}{زیرموضوع} \setinterfacevariable{subsubsection}{زیرزیربخش} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{صفحهاول} \setinterfaceconstant{focus}{تمرکز} \setinterfaceconstant{focusin}{تمرکزدرون} \setinterfaceconstant{focusout}{تمرکزبیرون} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{برچسب} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{صفحهآخر} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{چپ} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{زیرجملهچپ} \setinterfaceconstant{lefttext}{متنچپ} \setinterfaceconstant{leftwidth}{عرضخط} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{مرحله} \setinterfaceconstant{levels}{مرحلهها} \setinterfaceconstant{limittext}{مرزمتن} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{کمترینارتفاع} \setinterfaceconstant{minwidth}{کمترینعرض} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{نام} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{جداکننده} \setinterfaceconstant{set}{قراربده} \setinterfaceconstant{setups}{بارگذاریها} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{کنار} \setinterfaceconstant{sidealign}{تنظیمکنار} \setinterfaceconstant{sidemethod}{روشکنار} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{علامت} \setinterfaceconstant{size}{اندازه} \setinterfaceconstant{small}{کوچک} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{ترتیبتایپ} \setinterfaceconstant{source}{منبع} diff --git a/tex/context/base/mult-prm.mkiv b/tex/context/base/mult-prm.mkiv index 7e5bc1edd..8c9179a16 100644 --- a/tex/context/base/mult-prm.mkiv +++ b/tex/context/base/mult-prm.mkiv @@ -1,3 +1,18 @@ +%D \module +%D [ file=mult-prm, +%D version=2011.09.18, % actually older +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=Primitives, +%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 therefore +%C copyrighted by \PRAGMA. See mreadme.pdf for details. + +%D This file is only a helper for generating files that can be used in an +%D editor for syntax highlighting. + \startluacode context.starttext() diff --git a/tex/context/base/mult-ro.mkii b/tex/context/base/mult-ro.mkii index 1eef26e0d..adc811188 100644 --- a/tex/context/base/mult-ro.mkii +++ b/tex/context/base/mult-ro.mkii @@ -157,6 +157,7 @@ \setinterfacevariable{enumeration}{enumerare} \setinterfacevariable{environment}{mediu} \setinterfacevariable{even}{par} +\setinterfacevariable{export}{export} \setinterfacevariable{external}{extern} \setinterfacevariable{fact}{fapt} \setinterfacevariable{february}{februarie} @@ -455,6 +456,7 @@ \setinterfacevariable{subforward}{subavans} \setinterfacevariable{subject}{subiect} \setinterfacevariable{subpage}{subpagina} +\setinterfacevariable{subs}{subs} \setinterfacevariable{subsection}{subsectiune} \setinterfacevariable{subsubject}{subsubiect} \setinterfacevariable{subsubsection}{subsubsectiune} @@ -684,6 +686,7 @@ \setinterfaceconstant{filtercommand}{filtercommand} \setinterfaceconstant{finalnamesep}{finalnamesep} \setinterfaceconstant{firstnamesep}{firstnamesep} +\setinterfaceconstant{firstpage}{primapagina} \setinterfaceconstant{focus}{focus} \setinterfaceconstant{focusin}{focusin} \setinterfaceconstant{focusout}{focusout} @@ -750,6 +753,7 @@ \setinterfaceconstant{label}{eticheta} \setinterfaceconstant{labeloffset}{labeloffset} \setinterfaceconstant{lastnamesep}{lastnamesep} +\setinterfaceconstant{lastpage}{ultimapagina} \setinterfaceconstant{lastpubsep}{lastpubsep} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{stanga} @@ -770,6 +774,7 @@ \setinterfaceconstant{leftsubsentence}{subpropozitiestanga} \setinterfaceconstant{lefttext}{textstanga} \setinterfaceconstant{leftwidth}{latimestanga} +\setinterfaceconstant{less}{less} \setinterfaceconstant{level}{nivel} \setinterfaceconstant{levels}{nivele} \setinterfaceconstant{limittext}{limittext} @@ -808,6 +813,7 @@ \setinterfaceconstant{minheight}{inaltimeminima} \setinterfaceconstant{minwidth}{latimeminima} \setinterfaceconstant{monthconversion}{monthconversion} +\setinterfaceconstant{more}{more} \setinterfaceconstant{n}{n} \setinterfaceconstant{name}{nume} \setinterfaceconstant{namesep}{namesep} @@ -962,6 +968,7 @@ \setinterfaceconstant{separator}{separator} \setinterfaceconstant{set}{set} \setinterfaceconstant{setups}{setups} +\setinterfaceconstant{shrink}{shrink} \setinterfaceconstant{side}{parte} \setinterfaceconstant{sidealign}{sidealign} \setinterfaceconstant{sidemethod}{sidemethod} @@ -970,6 +977,7 @@ \setinterfaceconstant{sign}{semn} \setinterfaceconstant{size}{dimensiune} \setinterfaceconstant{small}{mic} +\setinterfaceconstant{solution}{solution} \setinterfaceconstant{sort}{sort} \setinterfaceconstant{sorttype}{sorttype} \setinterfaceconstant{source}{sursa} diff --git a/tex/context/base/mult-sys.mkiv b/tex/context/base/mult-sys.mkiv index 9b67ab4ba..be653f643 100644 --- a/tex/context/base/mult-sys.mkiv +++ b/tex/context/base/mult-sys.mkiv @@ -11,20 +11,19 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D In boring module we define a lot of obscure but useful -%D system constants. By doing so we save lots of memory while -%D at the same time we prevent ourself from typing errors. +%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 -%D keep extending \MKIV, so it was bout time to have a dedicated -%D variant. +%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 -%D minimal change of conflicts. +%D The constants are grouped in such a way that there is a minimal change of +%D conflicts. %D %D \starttyping %D \definesystemconstants {word} @@ -36,8 +35,8 @@ \definesystemconstant {hans} \definesystemconstant {taco} -%D First we define some system constants used for both the -%D multi||lingual interface and multi||linguag typesetting. +%D First we define some system constants used for both the multi||lingual +%D interface and multi||linguag typesetting. \definesystemconstant {afrikaans} \definesystemconstant {af} \definesystemconstant {arabic} \definesystemconstant {ar} @@ -83,8 +82,7 @@ \definesystemconstant {japanese} \definesystemconstant {ja} \definesystemconstant {korean} \definesystemconstant {kr} -%D For proper \UNICODE\ support we need a few font related -%D constants. +%D For proper \UNICODE\ support we need a few font related constants. \definesystemconstant {BoldItalic} \definesystemconstant {BoldSlanted} @@ -115,7 +113,7 @@ \definesystemconstant {SerifSlanted} \definesystemconstant {SerifBoldSlanted} \definesystemconstant {SerifCaps} -% \definesystemconstant {SerifCapsSlanted} +%definesystemconstant {SerifCapsSlanted} \definesystemconstant {Sans} \definesystemconstant {SansBold} @@ -155,6 +153,9 @@ %definesystemconstant {mnem} % kind of generic short tag +\definesystemconstant {otr} +\definesystemconstant {box} + \definesystemconstant {file} \definesystemconstant {name} \definesystemconstant {spec} @@ -220,174 +221,176 @@ \definesystemconstant {second} \definesystemconstant {third} -%D Net come some \CONTEXT\ constants, used in the definition -%D of private commands: - -\definesystemconstant {tex} -\definesystemconstant {xml} -\definesystemconstant {lua} - -\definesystemconstant {next} -\definesystemconstant {pickup} -\definesystemconstant {ascii} -\definesystemconstant {default} -\definesystemconstant {unknown} -\definesystemconstant {action} -\definesystemconstant {compare} -\definesystemconstant {do} -\definesystemconstant {dodo} -\definesystemconstant {complex} -\definesystemconstant {simple} -\definesystemconstant {start} -\definesystemconstant {stop} -\definesystemconstant {dummy} -\definesystemconstant {local} -\definesystemconstant {global} -\definesystemconstant {done} -\definesystemconstant {font} -\definesystemconstant {link} -\definesystemconstant {parent} -\definesystemconstant {child} -\definesystemconstant {clone} -\definesystemconstant {section} -\definesystemconstant {handler} -\definesystemconstant {counter} -\definesystemconstant {single} -\definesystemconstant {multi} -\definesystemconstant {indeed} - -\definesystemconstant {hasnumber} -\definesystemconstant {hastitle} -\definesystemconstant {hascaption} -\definesystemconstant {haslevel} - -\definesystemconstant {mkiv} -\definesystemconstant {mkii} - -\definesystemconstant {normal} -\definesystemconstant {bold} -\definesystemconstant {italic} -\definesystemconstant {slanted} - -\definesystemconstant {default} -\definesystemconstant {smallcaps} - -\definesystemconstant {run} - -\definesystemconstant {mode} -\definesystemconstant {setup} -\definesystemconstant {environment} -\definesystemconstant {document} - -%definesystemconstant {fam} -\definesystemconstant {text} -\definesystemconstant {script} -\definesystemconstant {scriptscript} - -\definesystemconstant {lefthyphenmin} -\definesystemconstant {righthyphenmin} -\definesystemconstant {lefthyphenchar} -\definesystemconstant {righthyphenchar} - -%definesystemconstant {skewchar} -%definesystemconstant {hyphenchar} -\definesystemconstant {catcodes} -%definesystemconstant {encoding} -%definesystemconstant {entities} -%definesystemconstant {resource} -%definesystemconstant {mapping} -\definesystemconstant {language} -\definesystemconstant {patterns} -\definesystemconstant {rname} -\definesystemconstant {rscale} -%definesystemconstant {handling} -\definesystemconstant {features} -\definesystemconstant {direction} -\definesystemconstant {fallbacks} -\definesystemconstant {goodies} -\definesystemconstant {designsize} -%definesystemconstant {background} -%definesystemconstant {ucmap} - -%definesystemconstant {property} -%definesystemconstant {overprint} -%definesystemconstant {layer} -\definesystemconstant {effect} % todo s -%definesystemconstant {negative} -%definesystemconstant {color} -%definesystemconstant {transparency} - -\definesystemconstant {black} -\definesystemconstant {white} - -\definesystemconstant {system} % not yet interfaces messages -\definesystemconstant {user} -\definesystemconstant {check} -\definesystemconstant {reset} -\definesystemconstant {set} -\definesystemconstant {empty} - -\definesystemconstant {realpage} -\definesystemconstant {userpage} -\definesystemconstant {subpage} - -\definesystemconstant {page} -\definesystemconstant {subpage} -\definesystemconstant {leftpage} -\definesystemconstant {rightpage} -\definesystemconstant {somewhere} - -\definesystemconstant {userdata} -\definesystemconstant {command} -\definesystemconstant {simple} - -\definesystemconstant {full} -\definesystemconstant {text} -\definesystemconstant {paragraph} -\definesystemconstant {margintext} -\definesystemconstant {line} - -\definesystemconstant {number} -\definesystemconstant {symbol} -\definesystemconstant {format} -\definesystemconstant {data} -\definesystemconstant {float} -\definesystemconstant {extensions} -\definesystemconstant {initializations} - -\definesystemconstant {rgb} -\definesystemconstant {cmyk} -\definesystemconstant {gray} -\definesystemconstant {spot} -\definesystemconstant {all} -\definesystemconstant {dtp} -\definesystemconstant {none} - -\definesystemconstant {map} -\definesystemconstant {special} -\definesystemconstant {size} - -\definesystemconstant {depth} -\definesystemconstant {nodepth} +%D Next come some \CONTEXT\ constants, used in the definition of private commands: + +\definesystemconstant {tex} +\definesystemconstant {xml} +\definesystemconstant {lua} + +\definesystemconstant {next} +\definesystemconstant {pickup} +\definesystemconstant {ascii} +\definesystemconstant {default} +\definesystemconstant {unknown} +\definesystemconstant {action} +\definesystemconstant {compare} +\definesystemconstant {do} +\definesystemconstant {dodo} +\definesystemconstant {complex} +\definesystemconstant {simple} +\definesystemconstant {start} +\definesystemconstant {stop} +\definesystemconstant {dummy} +\definesystemconstant {local} +\definesystemconstant {global} +\definesystemconstant {done} +\definesystemconstant {font} +\definesystemconstant {link} +\definesystemconstant {parent} +\definesystemconstant {child} +\definesystemconstant {clone} +\definesystemconstant {section} +\definesystemconstant {handler} +\definesystemconstant {counter} +\definesystemconstant {single} +\definesystemconstant {multi} +\definesystemconstant {indeed} + +% \def\s!parent{->} % 1% faster / => does not work in assignments +% \def\s!child {<-} % 1% faster / <= does not work in assignments + +\definesystemconstant {hasnumber} +\definesystemconstant {hastitle} +\definesystemconstant {hascaption} +\definesystemconstant {haslevel} + +\definesystemconstant {mkiv} +\definesystemconstant {mkii} + +\definesystemconstant {normal} +\definesystemconstant {bold} +\definesystemconstant {italic} +\definesystemconstant {slanted} + +\definesystemconstant {default} +\definesystemconstant {smallcaps} + +\definesystemconstant {run} + +\definesystemconstant {mode} +\definesystemconstant {setup} +\definesystemconstant {environment} +\definesystemconstant {document} + +%definesystemconstant {fam} +\definesystemconstant {text} +\definesystemconstant {script} +\definesystemconstant {scriptscript} + +\definesystemconstant {lefthyphenmin} +\definesystemconstant {righthyphenmin} +\definesystemconstant {lefthyphenchar} +\definesystemconstant {righthyphenchar} + +%definesystemconstant {skewchar} +%definesystemconstant {hyphenchar} +\definesystemconstant {catcodes} +%definesystemconstant {encoding} +%definesystemconstant {entities} +%definesystemconstant {resource} +%definesystemconstant {mapping} +\definesystemconstant {language} +\definesystemconstant {patterns} +\definesystemconstant {rname} +\definesystemconstant {rscale} +%definesystemconstant {handling} +\definesystemconstant {features} +\definesystemconstant {direction} +\definesystemconstant {fallbacks} +\definesystemconstant {goodies} +\definesystemconstant {designsize} +%definesystemconstant {background} +%definesystemconstant {ucmap} + +%definesystemconstant {property} +%definesystemconstant {overprint} +%definesystemconstant {layer} +\definesystemconstant {effect} % todo s +%definesystemconstant {negative} +%definesystemconstant {color} +%definesystemconstant {transparency} + +\definesystemconstant {black} +\definesystemconstant {white} + +\definesystemconstant {system} % not yet interfaces messages +\definesystemconstant {user} +\definesystemconstant {check} +\definesystemconstant {reset} +\definesystemconstant {set} +\definesystemconstant {empty} + +\definesystemconstant {realpage} +\definesystemconstant {userpage} +\definesystemconstant {subpage} + +\definesystemconstant {page} +\definesystemconstant {subpage} +\definesystemconstant {leftpage} +\definesystemconstant {rightpage} +\definesystemconstant {somewhere} + +\definesystemconstant {userdata} +\definesystemconstant {command} +\definesystemconstant {simple} + +\definesystemconstant {full} +\definesystemconstant {text} +\definesystemconstant {paragraph} +\definesystemconstant {margintext} +\definesystemconstant {line} + +\definesystemconstant {number} +\definesystemconstant {symbol} +\definesystemconstant {format} +\definesystemconstant {data} +\definesystemconstant {float} +\definesystemconstant {extensions} +\definesystemconstant {initializations} + +\definesystemconstant {rgb} +\definesystemconstant {cmyk} +\definesystemconstant {gray} +\definesystemconstant {spot} +\definesystemconstant {all} +\definesystemconstant {dtp} +\definesystemconstant {none} + +\definesystemconstant {map} +\definesystemconstant {special} +\definesystemconstant {size} + +\definesystemconstant {depth} +\definesystemconstant {nodepth} %D Just to be complete we define the standard \TEX\ units. -\definesystemconstant {cm} -\definesystemconstant {em} -\definesystemconstant {ex} -\definesystemconstant {mm} -\definesystemconstant {pt} -\definesystemconstant {sp} -\definesystemconstant {bp} -\definesystemconstant {in} -\definesystemconstant {pc} -\definesystemconstant {dd} -\definesystemconstant {cc} -\definesystemconstant {nd} -\definesystemconstant {nc} - -%D As the name of their define command states, the next set of -%D constants is used in the message macro's. +\definesystemconstant {cm} +\definesystemconstant {em} +\definesystemconstant {ex} +\definesystemconstant {mm} +\definesystemconstant {pt} +\definesystemconstant {sp} +\definesystemconstant {bp} +\definesystemconstant {in} +\definesystemconstant {pc} +\definesystemconstant {dd} +\definesystemconstant {cc} +\definesystemconstant {nd} +\definesystemconstant {nc} + +%D As the name of their define command states, the next set of constants is used in +%D the message macro's. \definemessageconstant {check} \definemessageconstant {colors} @@ -415,9 +418,8 @@ \definemessageconstant {chemicals} \definemessageconstant {publications} -%D When we use numbers and dimensions the same applies as -%D with the keywords like \type{width} and \type{plus} -%D mentioned earlier. +%D When we use numbers and dimensions the same applies as with the keywords like +%D \type {width} and \type {plus} mentioned earlier. \def\!!ten {10} \def\!!twelve {12} @@ -447,138 +449,37 @@ \def\__unknown__ {\string\\//} % unlikely value -%D Variables are composed of a command specific tag and a user -%D supplied variable (system constant). The first tag \type{ag} -%D for instance is available as \type{\??ag} and expands to -%D \type{@@ag} in composed variables. - -\definesystemvariable {ab} % AlignedBoxes -\definesystemvariable {ac} % ACcent -\definesystemvariable {ae} % AttributEs -\definesystemvariable {al} % ALinea's -\definesystemvariable {an} % ANchor -\definesystemvariable {as} % AlignmentSwitch -\definesystemvariable {bg} % BleedinG -\definesystemvariable {bm} % BookMark -\definesystemvariable {bp} % BreakPoint -\definesystemvariable {bx} % BackendExport -\definesystemvariable {cb} % CollectBox -\definesystemvariable {cp} % CliP -\definesystemvariable {da} % DAte -\definesystemvariable {db} % Labels -\definesystemvariable {dd} % DoorDefinieren -\definesystemvariable {de} % DEel -\definesystemvariable {dl} % DunneLijnen -\definesystemvariable {dn} % DoorNummeren -\definesystemvariable {dm} % DefineMeasure -\definesystemvariable {du} % DUmmy -\definesystemvariable {ef} % ExternFiguur -\definesystemvariable {en} % ENvironments -%definesystemvariable {er} % external resources -\definesystemvariable {et} % EffecT -\definesystemvariable {ex} % ExterneFiguren -\definesystemvariable {fc} % FramedContent -\definesystemvariable {fi} % FIle Once -\definesystemvariable {fo} % xml FO (xtag) -\definesystemvariable {fu} % FontSolution +%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 -\definesystemvariable {fx} % FoXet -\definesystemvariable {gb} % Graphic Bitmaps -\definesystemvariable {gv} % Graphic Variable -\definesystemvariable {ha} % HAng -\definesystemvariable {id} % Index -\definesystemvariable {ih} % InHoudsopgave -\definesystemvariable {il} % stelInvulRegelsin -\definesystemvariable {ip} % InsertPages -\definesystemvariable {is} % Items -\definesystemvariable {it} % stelInTerliniein -\definesystemvariable {iv} % stelInvulLijnenin -\definesystemvariable {ka} % KAntlijn -\definesystemvariable {kl} % KoLommen -\definesystemvariable {km} % KenMerk -\definesystemvariable {kp} % KopPelteken -\definesystemvariable {ks} % KolomSpan + +% old pragma + \definesystemvariable {kt} % KonTakten \definesystemvariable {kw} % KontaktWaarde -\definesystemvariable {le} % LinetablE -\definesystemvariable {lf} % LocalFigures -\definesystemvariable {lg} % taal (LanGuage) -\definesystemvariable {lk} % LinK -\definesystemvariable {ll} % Layers -\definesystemvariable {lr} % LayeR -\definesystemvariable {lu} % LUacode -\definesystemvariable {lx} % LayerteXt -\definesystemvariable {ma} % MargeAchtergrond -\definesystemvariable {mc} % MultiColumn -\definesystemvariable {mi} % MultilingualInterface -\definesystemvariable {ml} % MultilingualLabel -\definesystemvariable {mm} % MultilingualMath -\definesystemvariable {mt} % inline MaTh -\definesystemvariable {mt} % multi column (!!! double usage) -\definesystemvariable {mo} % Math Options -\definesystemvariable {mp} % MetaPost -\definesystemvariable {nn} % structurenumbering -\definesystemvariable {nm} % Nummering -\definesystemvariable {np} % NaastPlaatsen -\definesystemvariable {nr} % Nummeren -\definesystemvariable {ob} % OBjects -\definesystemvariable {oi} % OmlijndInstellingen -\definesystemvariable {ol} % OmLijnd -\definesystemvariable {od} % Omlijnd Defaults (simple) -\definesystemvariable {ox} % OffsetBox -\definesystemvariable {pb} % PuBlication -\definesystemvariable {pc} % PageComment -\definesystemvariable {ph} % ParagrapH -\definesystemvariable {pn} % PaginaNummer -\definesystemvariable {pr} % PRogrammas -\definesystemvariable {ps} % PoSitioneren -\definesystemvariable {px} % Parallel -\definesystemvariable {py} % PropertYs -\definesystemvariable {pv} % PublicationVariable -\definesystemvariable {ql} % catcode table let % already defined -\definesystemvariable {qd} % catcode table def % already defined -\definesystemvariable {qu} % catcode table ued % already defined -\definesystemvariable {qm} % catcode table meaning % already defined -\definesystemvariable {rf} % ReFerencing -\definesystemvariable {rn} % RegelNummer -\definesystemvariable {rs} % RaSters -\definesystemvariable {rt} % RoosTers -\definesystemvariable {rw} % RenderingWindow -\definesystemvariable {sb} % SectieBlok -\definesystemvariable {sd} % SounD -\definesystemvariable {se} % SEctie -\definesystemvariable {sh} % ShapeText -\definesystemvariable {si} % SplIt -\definesystemvariable {sp} % SelecteerPapier \definesystemvariable {st} % STickers -\definesystemvariable {sx} % Selector -\definesystemvariable {ta} % TAb -\definesystemvariable {tb} % TekstBlokken -\definesystemvariable {te} % TEmplate -\definesystemvariable {ti} % TabelInstellingen -\definesystemvariable {tl} % TekstLijnen -\definesystemvariable {tt} % TabulaTe -\definesystemvariable {tx} % TeXtflow -\definesystemvariable {ur} % URl -\definesystemvariable {vn} % VoetNoten -\definesystemvariable {xf} % XML File (xtag) -\definesystemvariable {xp} % XML Processing (xtag, so still needed) -\definesystemvariable {za} % layout adapt % ZetspiegelAanpassing -\definesystemvariable {zc} % columns - -% still used but defined locally - -\definesystemvariable {cs} % CharacterSpacing -\definesystemvariable {ts} % TypeScript -\definesystemvariable {kk} % Kapitalen +\definesystemvariable {km} % KenMerk -% obsolete but kept for a while (core-obs) +% mkii -\definesystemvariable {fr} % Division +\definesystemvariable {xf} % XML File (xtag) +\definesystemvariable {xp} % XML Processing (xtag, so still needed) +\definesystemvariable {fo} % xml FO (xtag) +\definesystemvariable {fx} % FoXet -%D Next we define some language independant one letter -%D variables and keywords. We can actually make these -%D system variables. +%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} @@ -628,27 +529,25 @@ \def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi} -%D The names of files and their extensions are fixed. -%D \CONTEXT\ uses as less files as possible. Utility files can -%D be recognized by the first two characters of the extension: -%D \type{tu}. +%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 {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 -%D specific setups (or calls to other files), old macro's, to -%D garantee compatibility and new macro's noy yet present in -%D the format. +%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 {errfilename} {cont-err} \definefileconstant {sysfilename} {cont-sys} @@ -656,9 +555,8 @@ \definefileconstant {locfilename} {cont-loc} \definefileconstant {expfilename} {cont-exp} -%D The setup files for the language, font, color and special -%D subsystems have a common prefix. This means that we have at -%D most three characters for unique filenames. +%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 {colorprefix} {colo-} %definefileconstant {encodingprefix} {enco-} @@ -717,20 +615,32 @@ %defineinterfaceconstant {tmp} {tmp} %defineinterfaceconstant {cld} {cld} -%D A careful reader will have noticed that in the module -%D \type{mult-ini} we defined \type{\selectinterface}. We were -%D not yet able to actually select an interface, because we -%D still had to define the constants and variables. Now we've -%D done so, selection is permitted. +%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 ouselves some -%D extensions to \CONTEXT. +%D Ok, here are some more, because we've got ouselves some extensions to \CONTEXT. \definemessageconstant {addresses} \definemessageconstant {documents} -\protect +%D Nicer than being undefined: + +\let\p_align \empty +\let\p_aligntitle\empty +\let\p_continue \empty +\let\p_footer \empty +\let\p_label \empty +\let\p_number \empty +\let\p_page \empty +\let\p_state \empty +\let\p_strut \empty +\let\p_text \empty +\let\p_tolerance \empty + +% more will follow -\endinput +\protect \endinput diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index 43624adfd..03a8789f7 100644 --- a/tex/context/base/node-aux.lua +++ b/tex/context/base/node-aux.lua @@ -19,6 +19,7 @@ local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local attributelist_code = nodecodes.attributelist -- temporary local nodepool = nodes.pool @@ -35,14 +36,17 @@ local get_attribute = node.get_attribute local unset_attribute = node.unset_attribute local first_glyph = node.first_glyph or node.first_character local copy_node = node.copy +local copy_node_list = node.copy_list local slide_nodes = node.slide local insert_node_after = node.insert_after local isnode = node.is_node -local current_font = font.current() +local current_font = font.current local texbox = tex.box +local report_error = logs.reporter("node-aux:error") + function nodes.repackhlist(list,...) --~ nodes.showsimplelist(list) local temp, b = hpack_nodes(list,...) @@ -264,7 +268,7 @@ end nodes.tonodes = tonodes -local function link(head,tail,list,currentfont,currentattr) +local function link(list,currentfont,currentattr,head,tail) for i=1,#list do local n = list[i] if n then @@ -272,6 +276,9 @@ local function link(head,tail,list,currentfont,currentattr) if not tn then local tn = type(n) if tn == "number" then + if not currentfont then + currentfont = current_font() + end local h, t = tonodes(tostring(n),currentfont,currentattr) if not h then -- skip @@ -282,7 +289,10 @@ local function link(head,tail,list,currentfont,currentattr) end elseif tn == "string" then if #tn > 0 then - local h, t = tonodes(n,font.current(),currentattr) + if not currentfont then + currentfont = current_font() + end + local h, t = tonodes(n,currentfont,currentattr) if not h then -- skip elseif not head then @@ -293,7 +303,10 @@ local function link(head,tail,list,currentfont,currentattr) end elseif tn == "table" then if #tn > 0 then - head, tail = link(head,tail,n,currentfont,currentattr) + if not currentfont then + currentfont = current_font() + end + head, tail = link(n,currentfont,currentattr,head,tail) end end elseif not head then @@ -303,6 +316,18 @@ local function link(head,tail,list,currentfont,currentattr) else tail = n end + elseif n.id == attributelist_code then + -- weird case + report_error("weird node type in list at index %s:",i) + for i=1,#list do + local l = list[i] + if l.id == attributelist_code then + report_error("%3i: ! %s",i,tostring(l)) + else + report_error("%3i: > %s",i,tostring(l)) + end + end + os.exit() else tail.next = n n.prev = tail @@ -319,10 +344,7 @@ local function link(head,tail,list,currentfont,currentattr) return head, tail end -function nodes.link(...) - local currentfont = font.current - return link(nil,nil,{...},currentfont,currentattr) -end +nodes.link = link local function locate(start,wantedid,wantedsubtype) for n in traverse_nodes(start) do @@ -342,7 +364,7 @@ end nodes.locate = locate -function nodes.concat(list) -- no slide ! +function nodes.concat(list) local head, tail for i=1,#list do local li = list[i] @@ -351,10 +373,10 @@ function nodes.concat(list) -- no slide ! elseif head then tail.next = li li.prev = tail - tail = li + tail = li.next and slide_nodes(li) or li else head = li - tail = li + tail = li.next and slide_nodes(li) or li end end return head, tail diff --git a/tex/context/base/node-dir.lua b/tex/context/base/node-dir.lua index 970313d96..6ee5cd4b8 100644 --- a/tex/context/base/node-dir.lua +++ b/tex/context/base/node-dir.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['node-mir'] = { +if not modules then modules = { } end modules ['node-dir'] = { version = 1.001, comment = "companion to node-ini.mkiv", author = "Taco Hoekwater and Hans Hagen", diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 5c1cc9ad5..27793716d 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['node-fin'] = { } -- this module is being reconstructed +-- local functions, only slightly slower local next, type, format = next, type, string.format @@ -14,6 +15,7 @@ local attributes, nodes, node = attributes, nodes, node local has_attribute = node.has_attribute local copy_node = node.copy +local find_tail = node.slide local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -36,6 +38,8 @@ local triggering = false local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming +local unsetvalue = attributes.unsetvalue + -- these two will be like trackers function states.enabletriggering() @@ -176,6 +180,7 @@ local insert_node_after = node.insert_after local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! +local nsbegin, nsend function states.initialize(namespace,attribute,head) nsdata = namespace.data @@ -187,6 +192,13 @@ function states.initialize(namespace,attribute,head) current = 0 current_selector = 0 done = false -- todo: done cleanup + nsstep = namespace.resolve_step + if nsstep then + nsbegin = namespace.resolve_begin + nsend = namespace.resolve_end + nspush = namespace.push + nspop = namespace.pop + end end function states.finalize(namespace,attribute,head) -- is this one ok? @@ -205,81 +217,167 @@ function states.finalize(namespace,attribute,head) -- is this one ok? return head, false, false end +-- disc nodes can be ignored +-- we need to deal with literals too (reset as well as oval) +-- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then + +-- local function process(namespace,attribute,head,inheritance,default) -- one attribute +-- local stack, done = head, false +-- while stack do +-- local id = stack.id +-- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- local c = has_attribute(stack,attribute) +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- done = true +-- end +-- -- here ? compare selective +-- if id == glue_code then --leader +-- -- same as *list +-- local content = stack.leader +-- if content then +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- local ok = false +-- if nstrigger and has_attribute(stack,nstrigger) then +-- local outer = has_attribute(stack,attribute) +-- if outer ~= inheritance then +-- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.leader, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- current = savedcurrent +-- done = done or ok +-- end +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- done = true +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- local ok = false +-- if nstrigger and has_attribute(stack,nstrigger) then +-- local outer = has_attribute(stack,attribute) +-- if outer ~= inheritance then +-- stack.list, ok = process(namespace,attribute,content,inheritance,outer) +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.list, ok = process(namespace,attribute,content,inheritance,default) +-- end +-- done = done or ok +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + local function process(namespace,attribute,head,inheritance,default) -- one attribute local stack, done = head, false - while stack do - local id = stack.id - -- we need to deal with literals too (reset as well as oval) - -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - if id == glyph_code -- or id == disc_code - or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) - if c then - if default and c == inheritance then - if current ~= default then - head = insert_node_before(head,stack,copy_node(nsdata[default])) - current = default - done = true - end - elseif current ~= c then - head = insert_node_before(head,stack,copy_node(nsdata[c])) - current = c - done = true - end - -- here ? compare selective - if id == glue_code then --leader - -- same as *list - local content = stack.leader - if content then - local savedcurrent = current - local ci = content.id - if ci == hlist_code or ci == vlist_code then - -- else we reset inside a box unneeded, okay, the downside is - -- that we trigger color in each repeated box, so there is room - -- for improvement here - current = 0 - end - local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.leader, ok = process(namespace,attribute,content,inheritance,outer) - else - stack.leader, ok = process(namespace,attribute,content,inheritance,default) - end - else - stack.leader, ok = process(namespace,attribute,content,inheritance,default) - end - current = savedcurrent - done = done or ok - end - end - elseif default and inheritance then + + local function check() + local c = has_attribute(stack,attribute) + if c then + if default and c == inheritance then if current ~= default then head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default done = true end - elseif current > 0 then - head = insert_node_before(head,stack,copy_node(nsnone)) - current = 0 + elseif current ~= c then + head = insert_node_before(head,stack,copy_node(nsdata[c])) + current = c + done = true + end + elseif default and inheritance then + if current ~= default then + head = insert_node_before(head,stack,copy_node(nsdata[default])) + current = default done = true end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current = 0 + done = true + end + return c + end + + local function nested(content) + if nstrigger and has_attribute(stack,nstrigger) then + local outer = has_attribute(stack,attribute) + if outer ~= inheritance then + return process(namespace,attribute,content,inheritance,outer) + else + return process(namespace,attribute,content,inheritance,default) + end + else + return process(namespace,attribute,content,inheritance,default) + end + end + + while stack do + local id = stack.id + if id == glyph_code then + check() + elseif id == rule_code then + if stack.width ~= 0 then + check() + end + elseif id == glue_code then + local content = stack.leader + if content and check() then + local savedcurrent = current + local ci = content.id + if ci == hlist_code or ci == vlist_code then + -- else we reset inside a box unneeded, okay, the downside is + -- that we trigger color in each repeated box, so there is room + -- for improvement here + current = 0 + end + + local ok = false + stack.leader, ok = nested(content) + done = done or ok + + current = savedcurrent + end elseif id == hlist_code or id == vlist_code then local content = stack.list if content then + local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.list, ok = process(namespace,attribute,content,inheritance,outer) - else - stack.list, ok = process(namespace,attribute,content,inheritance,default) - end - else - stack.list, ok = process(namespace,attribute,content,inheritance,default) - end + stack.list, ok = nested(content) done = done or ok + end end stack = stack.next @@ -295,86 +393,185 @@ states.process = process -- state changes while the main state stays the same (like two glyphs following -- each other with the same color but different color spaces e.g. \showcolor) +-- local function selective(namespace,attribute,head,inheritance,default) -- two attributes +-- local stack, done = head, false +-- while stack do +-- local id = stack.id +-- -- we need to deal with literals too (reset as well as oval) +-- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- if id == glyph_code -- or id == disc_code +-- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code +-- local c = has_attribute(stack,attribute) +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- current = default +-- done = true +-- end +-- else +-- local s = has_attribute(stack,nsselector) +-- if current ~= c or current_selector ~= s then +-- local data = nsdata[c] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- current = c +-- current_selector = s +-- done = true +-- end +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- current = default +-- done = true +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current, current_selector, done = 0, 0, true +-- end +-- if id == glue_code then -- leader +-- -- same as *list +-- local content = stack.leader +-- if content then +-- local savedcurrent = current +-- local ci = content.id +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- local ok = false +-- if nstrigger and has_attribute(stack,nstrigger) then +-- local outer = has_attribute(stack,attribute) +-- if outer ~= inheritance then +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) +-- else +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- current = savedcurrent +-- done = done or ok +-- end +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = stack.list +-- if content then +-- local ok = false +-- if nstrigger and has_attribute(stack,nstrigger) then +-- local outer = has_attribute(stack,attribute) +-- if outer ~= inheritance then +-- stack.list, ok = selective(namespace,attribute,content,inheritance,outer) +-- else +-- stack.list, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- else +-- stack.list, ok = selective(namespace,attribute,content,inheritance,default) +-- end +-- done = done or ok +-- end +-- end +-- stack = stack.next +-- end +-- return head, done +-- end + local function selective(namespace,attribute,head,inheritance,default) -- two attributes local stack, done = head, false - while stack do - local id = stack.id - -- we need to deal with literals too (reset as well as oval) - -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - if id == glyph_code -- or id == disc_code - or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) - if c then - if default and c == inheritance then - if current ~= default then - local data = nsdata[default] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) - current = default - done = true - end - else - local s = has_attribute(stack,nsselector) - if current ~= c or current_selector ~= s then - local data = nsdata[c] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) - current = c - current_selector = s - done = true - end - end - elseif default and inheritance then + + local function check() + local c = has_attribute(stack,attribute) + if c then + if default and c == inheritance then if current ~= default then local data = nsdata[default] head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) current = default done = true end - elseif current > 0 then - head = insert_node_before(head,stack,copy_node(nsnone)) - current, current_selector, done = 0, 0, true + else + local s = has_attribute(stack,nsselector) + if current ~= c or current_selector ~= s then + local data = nsdata[c] + head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + current = c + current_selector = s + done = true + end end - if id == glue_code then -- leader - -- same as *list - local content = stack.leader - if content then - local savedcurrent = current - local ci = content.id - if ci == hlist_code or ci == vlist_code then - -- else we reset inside a box unneeded, okay, the downside is - -- that we trigger color in each repeated box, so there is room - -- for improvement here - current = 0 - end - local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) - else - stack.leader, ok = selective(namespace,attribute,content,inheritance,default) - end - else - stack.leader, ok = selective(namespace,attribute,content,inheritance,default) - end - current = savedcurrent - done = done or ok + elseif default and inheritance then + if current ~= default then + local data = nsdata[default] + head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + current = default + done = true + end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current, current_selector, done = 0, 0, true + end + return c + end + + local function nested(content) + if nstrigger and has_attribute(stack,nstrigger) then + local outer = has_attribute(stack,attribute) + if outer ~= inheritance then + return selective(namespace,attribute,content,inheritance,outer) + else + return selective(namespace,attribute,content,inheritance,default) + end + else + return selective(namespace,attribute,content,inheritance,default) + end + end + + while stack do + local id = stack.id + if id == glyph_code then + check() + elseif id == rule_code then + if stack.width ~= 0 then + check() + end + elseif id == glue_code then + local content = stack.leader + if content and check() then + local savedcurrent = current + local ci = content.id + if ci == hlist_code or ci == vlist_code then + -- else we reset inside a box unneeded, okay, the downside is + -- that we trigger color in each repeated box, so there is room + -- for improvement here + current = 0 end + + local ok = false + stack.leader, ok = nested(content) + done = done or ok + + current = savedcurrent end elseif id == hlist_code or id == vlist_code then local content = stack.list if content then + local ok = false - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) - if outer ~= inheritance then - stack.list, ok = selective(namespace,attribute,content,inheritance,outer) - else - stack.list, ok = selective(namespace,attribute,content,inheritance,default) - end - else - stack.list, ok = selective(namespace,attribute,content,inheritance,default) - end + stack.list, ok = nested(content) done = done or ok + + -- nicer: + -- + -- local content, ok = nested(content) + -- if ok then + -- stack.leader = content + -- done = true + -- end + end end stack = stack.next @@ -382,53 +579,65 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at return head, done end + states.selective = selective -- Ideally the next one should be merged with the previous but keeping it separate is -- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers -- (as used in the stepper). In the stepper we cannot use the box branch as it involves --- paragraph lines and then getsmixed up. A messy business (esp since we want to be +-- paragraph lines and then gets mixed up. A messy business (esp since we want to be -- efficient). +-- +-- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not +-- entirely trivial and a generic solution is nicer (compares to the exporter). local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise local stack, done = head, false local current, depth = default or 0, 0 + + local function check() + local a = has_attribute(stack,attribute) + if a then + if current ~= a then + head = insert_node_before(head,stack,copy_node(nsdata[a])) + depth = depth + 1 + current, done = a, true + end + elseif default > 0 then + -- + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + depth = depth - 1 + current, done = 0, true + end + return a + end + while stack do local id = stack.id - if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code - local c = has_attribute(stack,attribute) - if c then - if current ~= c then - head = insert_node_before(head,stack,copy_node(nsdata[c])) - depth = depth + 1 - current, done = c, true - end - if id == glue_code then - local content = stack.leader - if content then -- unchecked - local ok = false - stack.leader, ok = stacked(namespace,attribute,content,current) - done = done or ok - end - end ---~ elseif default then - elseif default > 0 then - -- - elseif current > 0 then - head = insert_node_before(head,stack,copy_node(nsnone)) - depth = depth - 1 - current, done = 0, true + if id == glyph_code then + check() + elseif id == rule_code then + if stack.width ~= 0 then + check() + end + elseif id == glue_code then + local content = stack.leader + if content and check() then + local ok = false + stack.leader, ok = stacked(namespace,attribute,content,current) + done = done or ok end elseif id == hlist_code or id == vlist_code then local content = stack.list if content then -- the problem is that broken lines gets the attribute which can be a later one if nslistwise then - local c = has_attribute(stack,attribute) - if c and current ~= c and nslistwise[c] then -- viewerlayer + local a = has_attribute(stack,attribute) + if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current - current, done = c, true - head = insert_node_before(head,stack,copy_node(nsdata[c])) + current, done = a, true + head = insert_node_before(head,stack,copy_node(nsdata[a])) stack.list = stacked(namespace,attribute,content,current) head, stack = insert_node_after(head,stack,copy_node(nsnone)) current = p @@ -448,13 +657,87 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in end while depth > 0 do head = insert_node_after(head,stack,copy_node(nsnone)) - depth = depth -1 + depth = depth - 1 end return head, done end states.stacked = stacked +-- experimental + +local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise + nsbegin() + local current, previous, done, okay = head, head, false, false + local attrib = default or unsetvalue + + local function check() + local a = has_attribute(current,attribute) or unsetvalue + if a ~= attrib then + local n = nsstep(a) + if n then + -- !!!! TEST CODE !!!! +-- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a + head = insert_node_before(head,current,n) -- a + end + attrib, done, okay = a, true, true + end + return a + end + + while current do + local id = current.id + if id == glyph_code then + check() + elseif id == glue_code then + local content = current.leader + if content and check() then + -- tricky as a leader has to be a list so we cannot inject before + local _, ok = stacker(namespace,attribute,content,attrib) + done = done or ok + end + elseif id == hlist_code or id == vlist_code then + local content = current.list + if not content then + -- skip + elseif nslistwise then + local a = has_attribute(current,attribute) + if a and attrib ~= a and nslistwise[a] then -- viewerlayer + done = true + head = insert_node_before(head,current,copy_node(nsdata[a])) + current.list = stacker(namespace,attribute,content,a) + head, current = insert_node_after(head,current,copy_node(nsnone)) + else + local ok = false + current.list, ok = stacker(namespace,attribute,content,attrib) + done = done or ok + end + else + local ok = false + current.list, ok = stacker(namespace,attribute,content,default) + done = done or ok + end + elseif id == rule_code then + if current.width ~= 0 then + check() + end + end + previous = current + current = current.next + end + if okay then + local n = nsend() + if n then + -- !!!! TEST CODE !!!! +-- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)])) + head = insert_node_after(head,previous,n) + end + end + return head, done +end + +states.stacker = stacker + -- -- -- statistics.register("attribute processing time", function() diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 0ed17a1b5..e654d9e0f 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -73,25 +73,29 @@ nodes.handlers = nodes.handlers or { } -- there will be more of this: local skipcodes = allocate { - [ 0] = "userskip", - [ 1] = "lineskip", - [ 2] = "baselineskip", - [ 3] = "parskip", - [ 4] = "abovedisplayskip", - [ 5] = "belowdisplayskip", - [ 6] = "abovedisplayshortskip", - [ 7] = "belowdisplayshortskip", - [ 8] = "leftskip", - [ 9] = "rightskip", - [10] = "topskip", - [11] = "splittopskip", - [12] = "tabskip", - [13] = "spaceskip", - [14] = "xspaceskip", - [15] = "parfillskip", - [16] = "thinmuskip", - [17] = "medmuskip", - [18] = "thickmuskip", + [ 0] = "userskip", + [ 1] = "lineskip", + [ 2] = "baselineskip", + [ 3] = "parskip", + [ 4] = "abovedisplayskip", + [ 5] = "belowdisplayskip", + [ 6] = "abovedisplayshortskip", + [ 7] = "belowdisplayshortskip", + [ 8] = "leftskip", + [ 9] = "rightskip", + [ 10] = "topskip", + [ 11] = "splittopskip", + [ 12] = "tabskip", + [ 13] = "spaceskip", + [ 14] = "xspaceskip", + [ 15] = "parfillskip", + [ 16] = "thinmuskip", + [ 17] = "medmuskip", + [ 18] = "thickmuskip", + [100] = "leaders", + [101] = "cleaders", + [102] = "xleaders", + [103] = "gleaders", } local penaltycodes = allocate { -- unfortunately not used diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua index 246aaade2..2cbcc8b88 100644 --- a/tex/context/base/node-inj.lua +++ b/tex/context/base/node-inj.lua @@ -34,7 +34,6 @@ local traverse_id = node.traverse_id local unset_attribute = node.unset_attribute local has_attribute = node.has_attribute local set_attribute = node.set_attribute -local copy_node = node.copy local insert_node_before = node.insert_before local insert_node_after = node.insert_after @@ -46,27 +45,16 @@ local curscurs = attributes.private('curscurs') local cursdone = attributes.private('cursdone') local kernpair = attributes.private('kernpair') local ligacomp = attributes.private('ligacomp') -local fontkern = attributes.private('fontkern') - -if context then - - local kern = nodes.pool.register(newkern()) - - set_attribute(kern,fontkern,1) -- we can have several, attributes are shared - - newkern = function(k) - local c = copy_node(kern) - c.kern = k - return c - end - -end -- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as -- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner -- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure -- that this code is not 100% okay but examples are needed to figure things out. +function injections.installnewkern(nk) + newkern = nk or newkern +end + local cursives = { } local marks = { } local kerns = { } @@ -352,16 +340,13 @@ function injections.handler(head,where,keep) -- new per 2010-10-06, width adapted per 2010-02-03 -- we used to negate the width of marks because in tfm -- that makes sense but we no longer do that so as a - -- consequence the sign of p.width was changed (we need - -- to keep an eye on it as we don't have that many fonts - -- that enter this branch .. I'm still not sure if this - -- one is right + -- consequence the sign of p.width was changed local k = wx[p] if k then - n.xoffset = p.xoffset + p.width + d[1] - k[2] + -- brill roman: A\char"0300 (but ugly anyway) + n.xoffset = p.xoffset - p.width + d[1] - k[2] -- was + p.width else - -- n.xoffset = p.xoffset + p.width + d[1] - -- lucida U\char"032F (default+mark) + -- lucida: U\char"032F (default+mark) n.xoffset = p.xoffset - p.width + d[1] -- 01-05-2011 end else diff --git a/tex/context/base/node-par.mkiv b/tex/context/base/node-par.mkiv deleted file mode 100644 index 685167e8a..000000000 --- a/tex/context/base/node-par.mkiv +++ /dev/null @@ -1,82 +0,0 @@ -%D \module -%D [ file=node-par, -%D version=2008.09.30, -%D title=\CONTEXT\ Node Macros, -%D subtitle=Paragraph Building, -%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 Node Macros / Paragraph Building} - -%D This is very experimental, undocumented, subjected to changes, etc. just as -%D the underlying interfaces. - -% \enableparbuilders -% -% \startparbuilder[default] -% \input tufte \par -% \startparbuilder[oneline] -% \input tufte \par -% \stopparbuilder -% \input tufte \par -% \stopparbuilder - -\unprotect - -\registerctxluafile{node-par}{1.001} - -\definesystemattribute[parbuilder][public] - -% todo auto-enable - -% management (enable/disable) is global and will move to lua - -\installcorenamespace {parbuilder} - -\newcount\c_node_paragraphs_n_of_builders - -\let\m_node_paragraphs_current_builder\empty - -\unexpanded\def\defineparbuilder[#1]% - {\global\advance\c_node_paragraphs_n_of_builders\plusone - \ctxlua{builders.paragraphs.constructors.register("#1",\number\c_node_paragraphs_n_of_builders)}% - \setxvalue{\??parbuilder#1}{\attribute\parbuilderattribute\number\c_node_paragraphs_n_of_builders}} - -\unexpanded\def\startparbuilder[#1]% - {\edef\m_node_paragraphs_current_builder{\number\attribute\parbuilderattribute}% - \globalpushmacro\m_node_paragraphs_current_builder - \getvalue{\??parbuilder#1}\relax - \node_paragraphs_builders_check} - -\unexpanded\def\stopparbuilder - {\ifhmode\par\fi - \globalpopmacro\m_node_paragraphs_current_builder - \attribute\parbuilderattribute\m_node_paragraphs_current_builder\relax - \node_paragraphs_builders_check} - -\unexpanded\def\setmainparbuilder[#1]% - {\ctxlua{builders.paragraphs.constructors.set("#1")}} - -% no high level interface, after all implementing a linebreaker is not something that -% the average user will do - -\defineparbuilder[default] % just for testing -\defineparbuilder[oneline] % just for testing -\defineparbuilder[basic] % just for testing - -\def\enableparbuilders {\ctxlua{builders.paragraphs.constructors.enable ()}} -\def\disableparbuilders{\ctxlua{builders.paragraphs.constructors.disable()}} - -\def\node_paragraphs_builders_check % can be made more efficient as we don't want to do this too often - {\ifcase\attribute\parbuilderattribute - \disableparbuilders - \else - \enableparbuilders - \fi} - -\protect \endinput diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index dc1410282..2896c0d67 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -1,6 +1,6 @@ -if not modules then modules = { } end modules ['node-bck'] = { +if not modules then modules = { } end modules ['node-ref'] = { version = 1.001, - comment = "companion to node-bck.mkiv", + comment = "companion to node-ref.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" @@ -493,12 +493,12 @@ local function makedestination(width,height,depth,reference) for n=1,#name do local annot = nodeinjections.destination(width,height,depth,name[n],view) if not result then - result, current = annot, annot + result = annot else current.next = annot annot.prev = current - current = annot end + current = find_node_tail(annot) end if result then -- some internal error @@ -544,6 +544,9 @@ function references.injectcurrentset(h,d) -- used inside doifelse end end +commands.injectreference = references.inject +commands.injectcurrentreference = references.injectcurrentset + -- local function checkboth(open,close) diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua index 4522bef98..2933fc86d 100644 --- a/tex/context/base/node-res.lua +++ b/tex/context/base/node-res.lua @@ -33,6 +33,8 @@ local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph +local allocate = utilities.storage.allocate + local reserved, nofreserved = { }, 0 local function register_node(n) @@ -83,7 +85,6 @@ local glue = register_node(new_node("glue")) -- glue.spec = nil local glue_spec = register_node(new_node("glue_spec")) local glyph = register_node(new_node("glyph",0)) local textdir = register_node(new_node("whatsit",whatsitcodes.dir)) -local rule = register_node(new_node("rule")) local latelua = register_node(new_node("whatsit",whatsitcodes.latelua)) local special = register_node(new_node("whatsit",whatsitcodes.special)) local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44 @@ -99,6 +100,12 @@ local rightskip = register_node(new_node("glue",skipcodes.rightskip)) local temp = register_node(new_node("temp",0)) local noad = register_node(new_node("noad")) +-- the dir field needs to be set otherwise crash: + +local rule = register_node(new_node("rule")) rule .dir = "TLT" +local hlist = register_node(new_node("hlist")) hlist.dir = "TLT" +local vlist = register_node(new_node("vlist")) vlist.dir = "TLT" + function pool.zeroglue(n) local s = n.spec return not writable or ( @@ -284,6 +291,14 @@ function pool.noad() return copy_node(noad) end +function pool.hlist() + return copy_node(hlist) +end + +function pool.vlist() + return copy_node(vlist) +end + --[[ <p>At some point we ran into a problem that the glue specification of the zeropoint dimension was overwritten when adapting a glue spec @@ -312,7 +327,7 @@ end -- local num = userids["my id"] -- local str = userids[num] -local userids = utilities.storage.allocate() pool.userids = userids +local userids = allocate() pool.userids = userids local lastid = 0 setmetatable(userids, { diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 7f49edffc..d81016af0 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -86,6 +86,7 @@ local hpack_nodes = node.hpack local fontdata = fonts.hashes.identifiers local variables = interfaces.variables local dimenfactor = fonts.helpers.dimenfactor +local splitdimen = number.splitdimen local nodecodes = nodes.nodecodes local skipcodes = nodes.skipcodes @@ -258,26 +259,43 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a return head end local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next) - local method, offset, continue, dy, rulethickness, unit, order, max, ma, ca, ta = - d.method, d.offset, d.continue, d.dy, d.rulethickness, d.unit, d.order, d.max, d.ma, d.ca, d.ta - local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node + local method, offset, continue, dy, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max + local rulethickness, unit = d.rulethickness, d.unit + local ma, ca, ta = d.ma, d.ca, d.ta local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1 local color = (ca > 0 and ca) or has_attribute(f,a_color) local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency) local foreground = order == variables.foreground - rulethickness= rulethickness/2 + + local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node + + local rt = tonumber(rulethickness) + if rt then + rulethickness = e * rulethickness / 2 + else + local n, u = splitdimen(rulethickness) + if n and u then -- we need to intercept ex and em and % and ... + rulethickness = n * dimenfactor(u,fontdata[f.font]) / 2 + else + rulethickness = 1/5 + end + end + if level > max then level = max end if method == 0 then -- center offset = 2*offset - m = (offset+(level-1)*dy+rulethickness)*e/2 +-- m = (offset+(level-1)*dy+rulethickness)*e/2 + m = (offset+(level-1)*dy)*e/2 + rulethickness/2 else m = 0 end for i=1,level do - local ht = (offset+(i-1)*dy+rulethickness)*e - m - local dp = -(offset+(i-1)*dy-rulethickness)*e + m +-- local ht = (offset+(i-1)*dy+rulethickness)*e - m +-- local dp = -(offset+(i-1)*dy-rulethickness)*e + m + local ht = (offset+(i-1)*dy)*e + rulethickness - m + local dp = -(offset+(i-1)*dy)*e + rulethickness + m local r = new_rule(w,ht,dp) local v = has_attribute(f,a_viewerlayer) -- quick hack diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv index 1f1ac20ec..54a43a006 100644 --- a/tex/context/base/node-rul.mkiv +++ b/tex/context/base/node-rul.mkiv @@ -21,15 +21,14 @@ %D overstrike,overstrikes, %D setupbar} %D -%D In the rare case that we need undelined words, for instance -%D because all font alternatives are already in use, one can -%D use \type{\underbar} and \type{\overstrike} and their plural -%D forms. +%D In the rare case that we need undelined words, for instance because all font +%D alternatives are already in use, one can use \type {\underbar} and \type +%D {\overstrike} and their plural forms. %D %D \startbuffer -%D \underbars{drawing \underbar{bars} under words is a typewriter leftover} -%D \overstrikes{striking words makes them \overstrike{unreadable} but -%D sometimes even \overbar{top lines} come into view.} +%D \underbars {drawing \underbar{bars} under words is a typewriter leftover} +%D \overstrikes {striking words makes them \overstrike {unreadable} but +%D sometimes even \overbar {top lines} come into view.} %D \stopbuffer %D %D \typebuffer @@ -38,9 +37,9 @@ %D \getbuffer %D \stoplines %D -%D The next macros are derived from the \PLAIN\ \TEX\ one, but -%D also supports nesting. The \type{$} keeps us in horizontal -%D mode and at the same time applies grouping. +%D The next macros are derived from the \PLAIN\ \TEX\ one, but also supports +%D nesting. The \type{$} keeps us in horizontal mode and at the same time +%D applies grouping. %D %D \showsetup{underbar} %D \showsetup{underbars} @@ -51,9 +50,19 @@ %D %D \showsetup{setupunderbar} %D -%D Nested bars can be configured by appending \type {:<index>} to the -%D category. - +%D Nested bars can be configured by appending \type {:<index>} to the category. +%D Normally units in combination with a unitless thickness specification but +%D there units can be used too. +%D +%D \startbuffer +%D \setupbars[unit=mm,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank +%D \setupbars[unit=ex,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank +%D \setupbars[unit=pt,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank +%D \setupbars[unit=pt,rulethickness=10pt] bar\startbar[underbar]foo\stopbar bar +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D %D As with many early usage of \LUA\ in \MKIV\ this mechanism explores a way %D to deal with local settings at the \TEX\ end and remembering parameters %D at the \LUA\ end. We might do things differently now, but as settings normally @@ -107,7 +116,7 @@ offset = \barparameter\c!offset, continue = "\barparameter\c!continue", dy = \barparameter\c!dy, - rulethickness = \barparameter\c!rulethickness, + rulethickness = "\barparameter\c!rulethickness", unit = "\barparameter\c!unit", order = "\barparameter\c!order", max = \barparameter\c!max, @@ -286,9 +295,6 @@ \c!style=, \c!color=] -\def\v!shiftup {shiftup} -\def\v!shiftdown{shiftdown} - \defineshift [\v!shiftup] [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=] \defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=] diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua index 63690d00a..8e999f520 100644 --- a/tex/context/base/node-ser.lua +++ b/tex/context/base/node-ser.lua @@ -19,6 +19,7 @@ local nodes, node = nodes, node local traverse = node.traverse local nodecodes = nodes.nodecodes +local noadcodes = nodes.noadcodes local nodefields = nodes.fields local hlist_code = nodecodes.hlist @@ -39,6 +40,7 @@ local expand = allocate ( tohash { "leader", -- leader_ptr "action", -- action_ptr "value", -- user_defined nodes with subtype 'a' en 'n' + "head", } ) -- page_insert: "height", "last_ins_ptr", "best_ins_ptr" @@ -94,9 +96,9 @@ end -- under construction: -local function totable(n,flat,verbose) -- todo: no attributes +local function totable(n,flat,verbose,noattributes) -- todo: no local function - local function to_table(n,flat,verbose) + local function to_table(n,flat,verbose,noattributes) -- no need to pass local f = nodefields(n) local tt = { } for k=1,#f do @@ -105,6 +107,8 @@ local function totable(n,flat,verbose) -- todo: no attributes if nv then if ignore[v] then -- skip + elseif noattributes and v == "attr" then + -- skip elseif expand[v] then if type(nv) == "number" or type(nv) == "string" then tt[v] = nv @@ -128,14 +132,14 @@ local function totable(n,flat,verbose) -- todo: no attributes local t, tn = { }, 0 while n do tn = tn + 1 - t[tn] = to_table(n,flat,verbose) + t[tn] = to_table(n,flat,verbose,noattributes) n = n.next end return t else local t = to_table(n) if n.next then - t.next = totable(n.next,flat,verbose) + t.next = totable(n.next,flat,verbose,noattributes) end return t end @@ -154,7 +158,7 @@ end -- todo: adapt to nodecodes etc -local function serialize(root,name,handle,depth,m) +local function serialize(root,name,handle,depth,m,noattributes) handle = handle or print if depth then depth = depth .. " " @@ -188,6 +192,11 @@ local function serialize(root,name,handle,depth,m) local k = fld[f] if k == "ref_count" then -- skip + elseif noattributes and k == "attr" then + -- skip + elseif k == "id" then + local v = root[k] + handle(format("%s id=%s,",depth,nodecodes[v] or noadcodes[v] or v)) elseif k then local v = root[k] local t = type(v) @@ -206,12 +215,12 @@ local function serialize(root,name,handle,depth,m) elseif t == "boolean" then handle(format("%s %s=%q,",depth,key(k),tostring(v))) elseif v then -- userdata or table - serialize(v,k,handle,depth,m+1) + serialize(v,k,handle,depth,m+1,noattributes) end end end if root['next'] then -- userdata or table - serialize(root['next'],'next',handle,depth,m+1) + serialize(root['next'],'next',handle,depth,m+1,noattributes) end end if m and m > 0 then @@ -221,13 +230,13 @@ local function serialize(root,name,handle,depth,m) end end -function nodes.serialize(root,name) +function nodes.serialize(root,name,noattributes) local t, n = { }, 0 local function flush(s) n = n + 1 t[n] = s end - serialize(root, name, flush, nil, 0) + serialize(root,name,flush,nil,0,noattributes) return concat(t,"\n") end diff --git a/tex/context/base/node-spl.lua b/tex/context/base/node-spl.lua deleted file mode 100644 index 3b208e0e7..000000000 --- a/tex/context/base/node-spl.lua +++ /dev/null @@ -1,619 +0,0 @@ -if not modules then modules = { } end modules ['node-spl'] = { - version = 1.001, - comment = "companion to node-spl.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This module is dedicated to the oriental tex project and for --- the moment is too experimental to be publicly supported. --- --- We could cache solutions: say that we store the featureset and --- all 'words' -> replacement ... so we create a large solution --- database (per font) --- --- This module can be optimized by using a dedicated dynamics handler --- but I'll only do that when the rest of the code is stable. --- --- Todo: bind setups to paragraph. - -local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove -local next, tostring, tonumber = next, tostring, tonumber -local utfchar = utf.char -local random = math.random - -local trace_split = false trackers.register("builders.paragraphs.solutions.splitters.splitter", function(v) trace_split = v end) -local trace_optimize = false trackers.register("builders.paragraphs.solutions.splitters.optimizer", function(v) trace_optimize = v end) -local trace_colors = false trackers.register("builders.paragraphs.solutions.splitters.colors", function(v) trace_colors = v end) -local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) - -local report_solutions = logs.reporter("fonts","solutions") -local report_splitters = logs.reporter("nodes","splitters") -local report_optimizers = logs.reporter("nodes","optimizers") - -local nodes, node = nodes, node - -local variables = interfaces.variables - -local settings_to_array = utilities.parsers.settings_to_array -local settings_to_hash = utilities.parsers.settings_to_hash - -local find_node_tail = node.tail or node.slide -local free_node = node.free -local free_nodelist = node.flush_list -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute -local new_node = node.new -local copy_node = node.copy -local copy_nodelist = node.copy_list -local traverse_nodes = node.traverse -local traverse_ids = node.traverse_id -local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs -local hpack_nodes = node.hpack -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after -local repack_hlist = nodes.repackhlist - -local setnodecolor = nodes.tracers.colors.set - -local nodecodes = nodes.nodecodes -local whatsitcodes = nodes.whatsitcodes - -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local hlist_code = nodecodes.hlist -local whatsit_code = nodecodes.whatsit - -local localpar_code = whatsitcodes.localpar -local dir_code = whatsitcodes.dir -local userdefined_code = whatsitcodes.userdefined - -local nodepool = nodes.pool -local tasks = nodes.tasks -local usernodeids = nodepool.userids - -local new_textdir = nodepool.textdir -local new_usernumber = nodepool.usernumber - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming -local process_characters = nodes.handlers.characters -local inject_kerns = nodes.injections.handler -local fontdata = fonts.hashes.identifiers -local setfontdynamics = fonts.hashes.setdynamics -local fontprocesses = fonts.hashes.processes - -local parbuilders = builders.paragraphs -parbuilders.solutions = parbuilders.solutions or { } -parbuilders.solutions.splitters = parbuilders.solutions.splitters or { } - -local splitters = parbuilders.solutions.splitters - -local preroll = true -local variant = "normal" -local split = attributes.private('splitter') -local cache = { } -local solutions = { } -- attribute sets -local variants = { } -local max_less = 0 -local max_more = 0 -local criterium = 0 -local randomseed = nil -local optimize = nil -- set later - -function splitters.setup(setups) - local method = settings_to_hash(setups.method or "") - if method[variables.preroll] then - preroll = true - else - preroll = false - end - for k, v in next, method do - if variants[k] then - optimize = variants[k] - end - end - randomseed = tonumber(setups.randomseed) - criterium = tonumber(setups.criterium) or criterium -end - -local contextsetups = fonts.specifiers.contextsetups - -local function convert(featuresets,name,set,what) - local list, numbers, nofnumbers = set[what], { }, 0 - if list then - for i=1,#list do - local feature = list[i] - local fs = featuresets[feature] - local fn = fs and fs.number - if not fn then - -- fall back on global features - fs = contextsetups[feature] - fn = fs and fs.number - end - if fn then - nofnumbers = nofnumbers + 1 - numbers[nofnumbers] = fn - if trace_goodies or trace_optimize then - report_solutions("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn) - end - else - report_solutions("solution %s has an invalid feature reference '%s'",i,name,tostring(feature)) - end - end - return nofnumbers > 0 and numbers - end -end - -local function initialize(goodies) - local solutions = goodies.solutions - if solutions then - local featuresets = goodies.featuresets - local goodiesname = goodies.name - if trace_goodies or trace_optimize then - report_solutions("checking solutions in '%s'",goodiesname) - end - for name, set in next, solutions do - set.less = convert(featuresets,name,set,"less") - set.more = convert(featuresets,name,set,"more") - end - end -end - -fonts.goodies.register("solutions",initialize) - -function splitters.define(name,parameters) - local settings = settings_to_hash(parameters) -- todo: interfacing - local goodies, solution, less, more = settings.goodies, settings.solution, settings.less, settings.more - local less_set, more_set - local l = less and settings_to_array(less) - local m = more and settings_to_array(more) - if goodies then - goodies = fonts.goodies.load(goodies) -- also in tfmdata - if goodies then - local featuresets = goodies.featuresets - local solution = solution and goodies.solutions[solution] - if l and #l > 0 then - less_set = convert(featuresets,name,settings,"less") -- take from settings - else - less_set = solution and solution.less -- take from goodies - end - if m and #m > 0 then - more_set = convert(featuresets,name,settings,"more") -- take from settings - else - more_set = solution and solution.more -- take from goodies - end - end - else - if l then - local n = #less_set - for i=1,#l do - local ss = contextsetups[l[i]] - if ss then - n = n + 1 - less_set[n] = ss.number - end - end - end - if m then - local n = #more_set - for i=1,#m do - local ss = contextsetups[m[i]] - if ss then - n = n + 1 - more_set[n] = ss.number - end - end - end - end - if trace_optimize then - report_solutions("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," ")) - end - local nofsolutions = #solutions + 1 - solutions[nofsolutions] = { - solution = solution, - less = less_set or { }, - more = more_set or { }, - settings = settings, -- for tracing - } - context(nofsolutions) -end - -local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0 - -local splitter_one = usernodeids["splitters.one"] -local splitter_two = usernodeids["splitters.two"] - -function splitters.split(head) - -- quite fast - local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 - cache, max_less, max_more = { }, 0, 0 - local function flush() -- we can move this - local font = start.font - local last = stop.next - local list = last and copy_nodelist(start,last) or copy_nodelist(start) - local n = #cache + 1 - local user_one = new_usernumber(splitter_one,n) - local user_two = new_usernumber(splitter_two,n) - head, start = insert_node_before(head,start,user_one) - insert_node_after(head,stop,user_two) - if rlmode == "TRT" or rlmode == "+TRT" then - local dirnode = new_textdir("+TRT") - list.prev = dirnode - dirnode.next = list - list = dirnode - end - local c = { - original = list, - attribute = attribute, - direction = rlmode, - font = font - } - if trace_split then - report_splitters("cached %4i: font: %s, attribute: %s, word: %s, direction: %s", n, - font, attribute, nodes.listtoutf(list,true), rlmode) - end - cache[n] = c - local solution = solutions[attribute] - local l, m = #solution.less, #solution.more - if l > max_less then max_less = l end - if m > max_more then max_more = m end - start, stop, done = nil, nil, true - end - while current do - local id = current.id - if id == glyph_code and current.subtype < 256 then - local a = has_attribute(current,split) - if not a then - start, stop = nil, nil - elseif not start then - start, stop, attribute = current, current, a - elseif a ~= attribute then - start, stop = nil, nil - else - stop = current - end - current = current.next - elseif id == disc_code then - start, stop, current = nil, nil, current.next - elseif id == whatsit_code then - if start then - flush() - end - local subtype = current.subtype - if subtype == dir_code or subtype == localpar_code then - rlmode = current.dir - end - current = current.next - else - if start then - flush() - end - current = current.next - end - end - if start then - flush() - end - nofparagraphs = nofparagraphs + 1 - nofwords = nofwords + #cache - return head, done -end - -local function collect_words(list) - local words, w, word = { }, 0, nil - for current in traverse_ids(whatsit_code,list) do - if current.subtype == userdefined_code then - local user_id = current.user_id - if user_id == splitter_one then - word = { current.value, current, current } - w = w + 1 - words[w] = word - elseif user_id == splitter_two then - word[3] = current - end - end - end - return words -- check for empty (elsewhere) -end - --- we could avoid a hpack but hpack is not that slow - -local function doit(word,list,best,width,badness,line,set,listdir) - local changed = 0 - local n = word[1] - local found = cache[n] - if found then - local original, attribute, direction = found.original, found.attribute, found.direction - local solution = solutions[attribute] - local features = solution and solution[set] - if features then - local featurenumber = features[best] -- not ok probably - if featurenumber then - noftries = noftries + 1 - local first = copy_nodelist(original) - if not trace_colors then - for n in traverse_nodes(first) do -- maybe fast force so no attr needed - set_attribute(n,0,featurenumber) -- this forces dynamics - end - elseif set == "less" then - for n in traverse_nodes(first) do - setnodecolor(n,"font:isol") - set_attribute(n,0,featurenumber) - end - else - for n in traverse_nodes(first) do - setnodecolor(n,"font:medi") - set_attribute(n,0,featurenumber) - end - end - local font = found.font - -- local dynamics = found.dynamics - -- local shared = fontdata[font].shared - -- if not dynamics then -- we cache this - -- dynamics = shared.dynamics - -- found.dynamics = dynamics - -- end - -- local processors = found[featurenumber] - -- if not processors then -- we cache this too - -- processors = fonts.handlers.otf.setdynamics(font,featurenumber) - -- found[featurenumber] = processors - -- end - local setdynamics = setfontdynamics[font] - if setdynamics then - local processes = setdynamics(font,featurenumber) - for i=1,#processes do -- often more than 1 - first = processes[i](first,font,featurenumber) - end - else - report_solutions("fatal error, no dynamics for font %s",font) - end - first = inject_kerns(first) - local h = word[2].next -- head of current word - local t = word[3].prev -- tail of current word - if first.id == whatsit_code then - local temp = first - first = first.next - free_node(temp) - end - local last = find_node_tail(first) - -- replace [u]h->t by [u]first->last - local next, prev = t.next, h.prev - prev.next, first.prev = first, prev - if next then - last.next, next.prev = next, last - end - -- check new pack - local temp, b = repack_hlist(list,width,'exactly',listdir) - if b > badness then - if trace_optimize then - report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> quit",line,badness,b,criterium) - end - -- remove last insert - prev.next, h.prev = h, prev - if next then - t.next, next.prev = next, t - else - t.next = nil - end - last.next = nil - free_nodelist(first) - else - if trace_optimize then - report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> continue",line,badness,b,criterium) - end - -- free old h->t - t.next = nil - free_nodelist(h) - changed, badness = changed + 1, b - end - if b <= criterium then - return true, changed - end - end - end - end - return false, changed -end - --- We repeat some code but adding yet another layer of indirectness is not --- making things better. - -variants[variables.normal] = function(words,list,best,width,badness,line,set,listdir) - local changed = 0 - for i=1,#words do - local done, c = doit(words[i],list,best,width,badness,line,set,listdir) - changed = changed + c - if done then - break - end - end - if changed > 0 then - nofadapted = nofadapted + 1 - -- todo: get rid of pack when ok because we already have packed and we only need the last b - local list, b = repack_hlist(list,width,'exactly',listdir) - return list, true, changed, b -- badness - else - nofkept = nofkept + 1 - return list, false, 0, badness - end -end - -variants[variables.reverse] = function(words,list,best,width,badness,line,set,listdir) - local changed = 0 - for i=#words,1,-1 do - local done, c = doit(words[i],list,best,width,badness,line,set,listdir) - changed = changed + c - if done then - break - end - end - if changed > 0 then - nofadapted = nofadapted + 1 - -- todo: get rid of pack when ok because we already have packed and we only need the last b - local list, b = repack_hlist(list,width,'exactly',listdir) - return list, true, changed, b -- badness - else - nofkept = nofkept + 1 - return list, false, 0, badness - end -end - -variants[variables.random] = function(words,list,best,width,badness,line,set,listdir) - local changed = 0 - while #words > 0 do - local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir) - changed = changed + c - if done then - break - end - end - if changed > 0 then - nofadapted = nofadapted + 1 - -- todo: get rid of pack when ok because we already have packed and we only need the last b - local list, b = repack_hlist(list,width,'exactly',listdir) - return list, true, changed, b -- badness - else - nofkept = nofkept + 1 - return list, false, 0, badness - end -end - -optimize = variants.normal -- the default - -local function show_quality(current,what,line) - local set = current.glue_set - local sign = current.glue_sign - local order = current.glue_order - local amount = set * ((sign == 2 and -1) or 1) - report_optimizers("line %s, %s, amount %s, set %s, sign %s (%s), order %s",line,what,amount,set,sign,how,order) -end - -function splitters.optimize(head) - local nc = #cache - if nc > 0 then - starttiming(splitters) - local listdir = nil -- todo ! ! ! - if randomseed then - math.setrandomseedi(randomseed) - randomseed = nil - end - local line = 0 - local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz - tex.hbadness, tex.hfuzz = 10000, number.maxdimen - if trace_optimize then - report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s", - tostring(preroll),variant,criterium,nc) - end - for current in traverse_ids(hlist_code,head) do - -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil)) - line = line + 1 - local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width - local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node - if badness > 0 then - if sign == 0 then - if trace_optimize then - report_optimizers("line %s, badness %s, okay",line,badness) - end - else - local set, max - if sign == 1 then - if trace_optimize then - report_optimizers("line %s, badness %s, underfull, trying more",line,badness) - end - set, max = "more", max_more - else - if trace_optimize then - report_optimizers("line %s, badness %s, overfull, trying less",line,badness) - end - set, max = "less", max_less - end - -- we can keep the best variants - local lastbest, lastbadness = nil, badness - if preroll then - local bb, base - for i=1,max do - if base then - free_nodelist(base) - end - base = copy_nodelist(list) - local words = collect_words(base) -- beware: words is adapted - for j=i,max do - local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir) - base = temp - if trace_optimize then - report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b) - end - bb = b - if b <= criterium then - break - end - -- if done then - -- break - -- end - end - if bb and bb > criterium then -- needs checking - if not lastbest then - lastbest, lastbadness = i, bb - elseif bb > lastbadness then - lastbest, lastbadness = i, bb - end - else - break - end - end - free_nodelist(base) - end - local words = collect_words(list) - for best=lastbest or 1,max do - local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir) - current.list = temp - if trace_optimize then - report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b) - end - if done then - if b <= criterium then -- was == 0 - protect_glyphs(list) - break - end - end - end - end - else - if trace_optimize then - report_optimizers("line %s, not bad enough",line) - end - end - -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus - current.list = hpack_nodes(current.list,width,'exactly',listdir) - -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil)) - end - for i=1,nc do - local ci = cache[i] - free_nodelist(ci.original) - end - cache = { } - tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz - stoptiming(splitters) - end -end - -statistics.register("optimizer statistics", function() - if nofwords > 0 then - local elapsed = statistics.elapsedtime(splitters) - local average = noftries/elapsed - return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second", - nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average) - end -end) - -function splitters.enable() - tasks.enableaction("processors", "builders.paragraphs.solutions.splitters.split") - tasks.enableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") -end - -function splitters.disable() - tasks.disableaction("processors", "builders.paragraphs.solutions.splitters.split") - tasks.disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") -end diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 70e4639b8..6b5f49964 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -46,6 +46,7 @@ local copy_node_list = node.copy_list local hpack_node_list = node.hpack local free_node_list = node.flush_list local traverse_nodes = node.traverse +local traverse_by_id = node.traverse_id local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -219,7 +220,7 @@ function step_tracers.nofsteps() return context(#collection) end -function step_tracers.glyphs(n,i) +function step_tracers.glyphs(n,i) -- no need for hpack local c = collection[i] if c then tex.box[n] = hpack_node_list(copy_node_list(c)) @@ -352,7 +353,7 @@ end function nodes.handlers.checkglyphs(head,message) local t = { } - for g in traverse_id(glyph_code,head) do + for g in traverse_by_id(glyph_code,head) do t[#t+1] = format("U+%04X:%s",g.char,g.subtype) end if #t > 0 then @@ -539,7 +540,7 @@ end nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end -local function listtoutf(h,joiner,textonly) +local function listtoutf(h,joiner,textonly,last) local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj local w = { } while h do @@ -557,13 +558,17 @@ local function listtoutf(h,joiner,textonly) mid and listtoutf(mid,joiner,textonly) or "" ) elseif textonly then - if id == glue_code and h.width > 0 then + if id == glue_code and h.spec and h.spec.width > 0 then w[#w+1] = " " end else w[#w+1] = "[-]" end - h = h.next + if h == last then + break + else + h = h.next + end end return concat(w) end @@ -710,22 +715,79 @@ local get_attribute = node.has_attribute local set_attribute = node.set_attribute local unset_attribute = node.unset_attribute -local attribute = attributes.private('color') -local colormodel = attributes.private('colormodel') -local mapping = attributes.list[attribute] or { } +local a_color = attributes.private('color') +local a_colormodel = attributes.private('colormodel') +local a_state = attributes.private('state') +local m_color = attributes.list[a_color] or { } function colors.set(n,c,s) - local mc = mapping[c] + local mc = m_color[c] if not mc then - unset_attribute(n,attribute) + unset_attribute(n,a_color) else - if not get_attribute(n,colormodel) then - set_attribute(n,colormodel,s or 1) + if not get_attribute(n,a_colormodel) then + set_attribute(n,a_colormodel,s or 1) + end + set_attribute(n,a_color,mc) + end +end + +function colors.setlist(n,c,s) + while n do + local mc = m_color[c] + if not mc then + unset_attribute(n,a_color) + else + if not get_attribute(n,a_colormodel) then + set_attribute(n,a_colormodel,s or 1) + end + set_attribute(n,a_color,mc) end - set_attribute(n,attribute,mc) + n = n.next end end function colors.reset(n) - unset_attribute(n,attribute) + unset_attribute(n,a_color) +end + +-- maybe + +local transparencies = { } +tracers.transparencies = transparencies + +local a_transparency = attributes.private('transparency') +local m_transparency = attributes.list[a_transparency] or { } + +function transparencies.set(n,t) + local mt = m_transparency[t] + if not mt then + unset_attribute(n,a_transparency) + else + set_attribute(n,a_transparency,mt) + end +end + +function transparencies.setlist(n,c,s) + while n do + local mt = m_transparency[c] + if not mt then + unset_attribute(n,a_transparency) + else + set_attribute(n,a_transparency,mt) + end + n = n.next + end +end + +function transparencies.reset(n) + unset_attribute(n,a_transparency) +end + +-- for the moment here + +nodes.visualizers = { } + +function nodes.visualizers.handler(head) + return head, false end diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua index efc51913c..ccaa6c6b4 100644 --- a/tex/context/base/node-tsk.lua +++ b/tex/context/base/node-tsk.lua @@ -14,9 +14,9 @@ local format = string.format local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end) -local report_tasks = logs.reporter("tasks") +local report_tasks = logs.reporter("tasks") -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate local nodes = nodes diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua index 5f8df2b44..754b398c4 100644 --- a/tex/context/base/node-typ.lua +++ b/tex/context/base/node-typ.lua @@ -13,6 +13,7 @@ local fontparameters = fonts.hashes.parameters local hpack = node.hpack local vpack = node.vpack +local fast_hpack = nodes.fasthpack local nodepool = nodes.pool @@ -45,7 +46,9 @@ local function tonodes(str,fontid,spacing) -- quick and dirty next = newglyph(fontid or 1,c) spacedone = false end - if not head then + if not next then + -- nothing + elseif not head then head = next else prev.next = next @@ -62,6 +65,10 @@ function typesetters.hpack(str,fontid,spacing) return hpack(tonodes(str,fontid,spacing),"exactly") end +function typesetters.fast_hpack(str,fontid,spacing) + return fast_hpack(tonodes(str,fontid,spacing),"exactly") +end + function typesetters.vpack(str,fontid,spacing) -- vpack is just a hack, and a proper implentation is on the agenda -- as it needs more info etc than currently available diff --git a/tex/context/base/norm-ctx.mkiv b/tex/context/base/norm-ctx.mkiv index ff1676743..4b0027332 100644 --- a/tex/context/base/norm-ctx.mkiv +++ b/tex/context/base/norm-ctx.mkiv @@ -1,8 +1,8 @@ %D \module %D [ file=norm-ctx, %D version=2009.03.19, -%D title=\CONTEXT\ Norm Macros, -%D subtitle=\ALEPH\ and \OMEGA, +%D title=\CONTEXT\ Normal Macros, +%D subtitle=\CONTEXT, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -11,8 +11,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +\unprotect + %D A few more might end up here (like the weird ones in syst-ini). \let\normalreqno\normaleqno -\endinput +\protect \endinput diff --git a/tex/context/base/pack-bar.mkiv b/tex/context/base/pack-bar.mkiv index 6967173e2..06eeebd14 100644 --- a/tex/context/base/pack-bar.mkiv +++ b/tex/context/base/pack-bar.mkiv @@ -13,55 +13,80 @@ \writestatus{loading}{ConTeXt Packaging Macros / Bars} -%D This code has been moved from scrn-int to here (was some old -%D experimental code). It could be in scrn-bar but it's static. \unprotect +%D This code has been moved from scrn-int to here (was some old +%D experimental code). It could be in scrn-bar but it's static. In +%D the meantime the interface has been adapted to a key|/|value one. +%D %D \startbuffer -%D \dorecurse{10} -%D {\horizontalpositionbar -%D \pos\recurselevel \min1 \max10 -%D \token\framed{\recurselevel}% -%D \\} +%D \dorecurse{10}{ +%D \ruledhbox{\horizontalpositionbar[n=#1,min=1,max=10,text=!,color=red]} +%D \par +%D } +%D \stopbuffer +%D +%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection %D -%D \hbox to 15em -%D {\hss -%D \dorecurse{10} -%D {\verticalpositionbar\pos\recurselevel\min1\max10\token\blackrule\\ -%D \hss}} +%D \startbuffer +%D \dorecurse{10}{ +%D \ruledhbox{\horizontalgrowingbar[n=#1,min=1,max=10,text=!,color=red]} +%D \par +%D } %D \stopbuffer +%D +%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection + +\installcorenamespace{positionbar} + +\installsimplecommandhandler \??positionbar {positionbar} + +\setuppositionbar + [\c!min=1, + \c!max=1, + \c!n=1, + \c!text=?, + \c!width=\emwidth, + \c!height=\strutheight, + \c!depth=\strutdepth] -\def\horizontalpositionbar\pos#1\min#2\max#3\token#4\\% +\unexpanded\def\horizontalpositionbar[#1]% {\hbox to \hsize - {\hskip\zeropoint\!!plus #1\!!fill - \hskip\zeropoint\!!plus-#2\!!fill - #4\relax - \hskip\zeropoint\!!plus #3\!!fill - \hskip\zeropoint\!!plus-#1\!!fill}} + {\setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \hskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill + \hskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill + \positionbarparameter\c!text\relax + \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} -\def\verticalpositionbar\pos#1\min#2\max#3\token#4\\% +\unexpanded\def\verticalpositionbar[#1]% {\vbox to \vsize - {\vskip\zeropoint\!!plus #1\!!fill - \vskip\zeropoint\!!plus-#2\!!fill - \hbox{#4}\relax - \vskip\zeropoint\!!plus #3\!!fill - \vskip\zeropoint\!!plus-#1\!!fill}} + {\setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \vskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill + \vskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill + \positionbarparameter\c!text\relax + \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} -\def\horizontalgrowingbar\pos#1\min#2\max#3\height#4\depth#5\\% +\unexpanded\def\horizontalgrowingbar[#1]% {\hbox to \hsize - {\scratchcounter\numexpr#1-#2+\plusone\relax - \leaders\vrule\hskip\zeropoint\!!plus \scratchcounter\!!fill - \vrule\!!width\zeropoint\!!height#4\!!depth#5% - \hskip\zeropoint\!!plus #3\!!fill - \hskip\zeropoint\!!plus-#1\!!fill}} + {\setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \leaders\vrule\hskip\zeropoint\s!plus \numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill + \vrule\s!width\zeropoint\s!height\positionbarparameter\c!height\s!depth\positionbarparameter\c!depth + \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} -\def\verticalgrowingbar\pos#1\min#2\max#3\width#4\\% +\unexpanded\def\verticalgrowingbar[#1]% {\vbox to \vsize - {\scratchcounter\numexpr#1-#2+\plusone\relax - \leaders\hrule\vskip\zeropoint\!!plus\scratchcounter\!!fill - \hrule\!!width#4\!!height\zeropoint\!!depth\zeropoint - \vskip\zeropoint\!!plus #3\!!fill - \vskip\zeropoint\!!plus-#1\!!fill}} + {\setuppositionbar[#1]% + \usepositionbarstyleandcolor\c!style\c!color + \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill + \hrule\s!width\positionbarparameter\c!width\s!height\zeropoint\s!depth\zeropoint + \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill + \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} \protect \endinput diff --git a/tex/context/base/pack-bck.mkvi b/tex/context/base/pack-bck.mkvi index fbe704fab..57d0ee456 100644 --- a/tex/context/base/pack-bck.mkvi +++ b/tex/context/base/pack-bck.mkvi @@ -209,7 +209,7 @@ % \c!color=, % \c!background=\v!screen, % \c!backgroundcolor=\backgroundparameter\c!color, -% \c!screen=\@@rsscreen, +% \c!screen=\defaultbackgroundscreen, % \c!background=\v!color, \c!backgroundcolor=lightgray, diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv index 41a17953b..bcdb93875 100644 --- a/tex/context/base/pack-box.mkiv +++ b/tex/context/base/pack-box.mkiv @@ -13,36 +13,24 @@ \writestatus{loading}{ConTeXt Packaging Macros / Boxes} -% to be cleaned up - -%D This module contains all kind of macros for moving content -%D around. Many macros here come from other modules, but -%D depencies made it more clear to isolate them. - -% \placeornament +%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 -% we need to set the size, else we get dimensions depending -% on the content, which in itself is ok, but can lead to loops -% due to rounding errors (happened in demo-obv) +%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=\overlaywidth,\c!height=\overlayheight] \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight] \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight] \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight] -% \unexpanded\def\positionregionlayer#1#2% -% {\composedlayer{#2}} -% -% \def\internaltextoverlay#1% will become more generic and installable -% {\startoverlay % i.e. probably an overlay by itself -% {\positionregionoverlay\textanchor{\v!text#1}}% see later -% {\positionregionlayer \textanchor{\v!text#1}}% -% \stopoverlay} - -\def\internaltextoverlay#1% will become more generic and installable - {\startoverlay % i.e. probably an overlay by itself +\unexpanded\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} @@ -52,75 +40,6 @@ \defineoverlay[\v!text+1][\internaltextoverlay{+1}] \defineoverlay[\v!text+2][\internaltextoverlay{+2}] -% to be documented - -% \definelayer[anchor] -% -% \unexpanded\def\defineanchor -% {\doquadrupleempty\dodefineanchor} -% -% \def\dodefineanchor[#1][#2][#3][#4]% -% {\setvalue{\??an#1}{\dodefinedanchor[#2][#3][#4]}} -% -% \def\dodefinedanchor[#1][#2][#3]% -% {\def\docommand[##1][##2]% -% {\ifsecondargument -% \def\next{\dodoanchorT[#1][#2,##1][#3,##2]}% -% \else\iffirstargument -% \def\next{\dodoanchorT[#1][#2,##1][#2,##1]}% -% \else -% \def\next{\dodoanchorT[#1][#2][#3]}% -% \fi\fi -% \next}% -% \dodoubleempty\docommand} -% -% \unexpanded\def\anchor -% {\dosingleargument\pack_anchor} -% -% \def\pack_anchor[#1]% -% {\ifcsname\??an#1\endcsname\@EA\nonoanchor\else\@EA\dodoanchor\fi[#1]} -% -% \def\nonoanchor[#1]% -% {\csname\??an#1\endcsname} -% -% \def\dodoanchor[#1]% -% {\dotripleempty\dododoanchor[#1]} -% -% \def\dododoanchor -% {\ifthirdargument -% \expandafter\dodoanchorT -% \else -% \expandafter\dodoanchorS -% \fi} -% -% \def\dodoanchorS[#1][#2][#3]% -% {\dodoanchorT[#1][#2][#2]} -% -% \def\dodoanchorT[#1][#2][#3]% brrr: we need to apply offset only once .. a bit messy -% {\dowithnextbox -% {\bgroup -% % \checktextbackgrounds -% \setbox\scratchbox\emptyhbox -% \wd\scratchbox\nextboxwd -% \ht\scratchbox\nextboxht -% \dp\scratchbox\nextboxdp -% \setlayer -% [anchor] -% [\c!width=\wd\scratchbox, -% \c!height=\ht\scratchbox, -% \c!offset=\!!zeropoint, -% #2,#3] -% {\setlayer[#1]{\flushnextbox}}% -% \framed -% [#2, -% \c!background=anchor, -% \c!offset=\v!overlay, -% \c!frame=\v!off, -% #3] -% {\box\scratchbox}% -% \egroup}% -% \vbox} - \installcorenamespace {anchor} \unexpanded\def\defineanchor @@ -194,7 +113,7 @@ \c!offset=\zeropoint, #2,#3] {\setlayer[#1]{\box\b_pack_anchors}}% % #1 uses ovelaywidth/height - \framed + \framed % could be a predefined framed [\c!background=anchor, \c!offset=\v!overlay, \c!frame=\v!off, @@ -204,157 +123,182 @@ % collectors -\def\@@collectorbox{@@collectorbox} +\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 -\unexpanded\def\definecollector - {\dodoubleargument\dodefinecollector} +\unexpanded\def\resetcollector[#1]% + {\ifcsname\??collectorbox#1\endcsname + \global\setbox\csname\??collectorbox#1\endcsname\emptybox + \fi} -\def\dodefinecollector[#1][#2]% - {\ifcsname\@@collectorbox#1\endcsname \else - \expandafter\newbox\csname\@@collectorbox#1\endcsname - \fi - \resetcollector[#1]% - \setupcollector - [#1] - [\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=,#2]} - -\unexpanded\def\setupcollector - {\dodoubleargument\dosetupcollector} - -\def\dosetupcollector[#1][#2]% - {\def\docommand##1{\getparameters[\??cb##1][#2]}% - \processcommalist[#1]\docommand} - -\def\setcollector - {\dodoubleargument\dosetcollector} - -\def\dosetcollector[#1][#2]% +\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\csname\??collectorbox\currentcollector\endcsname + \else + \setfalse\c_pack_boxes_collector_valid_box + \writestatus{collector}{unknown collector \currentcollector}% + \fi} + +\unexpanded\def\setcollector {\bgroup - \forgetall + \dodoubleargument\pack_boxes_collector} + +\def\pack_boxes_collector[#1][#2]% todo: keep reference point + {\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 - \dowithnextbox - {\ifcsname\@@collectorbox#1\endcsname - \dodosetcollector[#1][#2]% - \else - \writestatus{collector}{unknown layer #1}% - \fi - \egroup} - \hbox} + \dowithnextboxcs\pack_boxes_collector_finish\hbox} -\def\collectorparameter#1{\csname\??cb\currentcollector#1\endcsname} - -\def\dodosetcollector[#1][#2]% todo: keep reference point - {\def\currentcollector{#1}% - \chardef\collectorbox\csname\@@collectorbox#1\endcsname - \getparameters[\??cb#1][#2]% - \d_pack_layers_x_size\wd\collectorbox - \d_pack_layers_y_size\ht\collectorbox - \doifvaluesomething{\??cb#1\c!rotation} - {\setbox\nextbox\hbox - {\rotate - [\c!location=\v!high, - \c!rotation=\collectorparameter\c!rotation] - {\flushnextbox}}}% - \advance\d_pack_layers_y_size\dp\collectorbox - \d_pack_layers_x_position\collectorparameter\c!x - \advance\d_pack_layers_x_position\collectorparameter\c!hoffset - \d_pack_layers_y_position\collectorparameter\c!y - \advance\d_pack_layers_y_position\collectorparameter\c!voffset - \doifelse\v!middle{\collectorparameter\c!corner} - {\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}% - {\normalexpanded{\noexpand\doifinset{\v!bottom}{\collectorparameter\c!corner}} - {\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}% - \normalexpanded{\noexpand\doifinset{\v!right}{\collectorparameter\c!corner}} - {\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_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 + \csname\??collectorcorners#1\endcsname + \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\hbox + {\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\hbox - {\alignedbox[\collectorparameter\c!location]\vbox{\flushnextbox}}% + {\alignedbox[\collectorparameter\c!location]\vbox{\box\nextbox}}% \boxmaxdepth\zeropoint % really needed, nice example \global\advance\boxhdisplacement\d_pack_layers_x_position \ifdim\boxhdisplacement<\zeropoint - \global\setbox\collectorbox\hbox + \global\setbox\b_pack_boxes_collector\hbox {\hskip-\boxhdisplacement - \box\collectorbox}% + \box\b_pack_boxes_collector}% \fi \global\advance\boxvdisplacement\d_pack_layers_y_position \ifdim\boxvdisplacement<\zeropoint - \global\setbox\collectorbox\hbox + \global\setbox\b_pack_boxes_collector\hbox {\lower-\boxvdisplacement - \box\collectorbox}% + \box\b_pack_boxes_collector}% \fi - \d_pack_layers_x_size\wd\collectorbox - \d_pack_layers_y_size\ht\collectorbox - \advance\d_pack_layers_y_size\dp\collectorbox - \global\setbox\collectorbox\hbox - {\box\collectorbox - \hskip-\d_pack_layers_x_size - \hskip\d_pack_layers_x_position\relax - \ifdim\boxhdisplacement<\zeropoint - \hskip-\boxhdisplacement - \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\hbox + {\box\b_pack_boxes_collector + \hskip\dimexpr + -\d_pack_layers_x_size + +\d_pack_layers_x_position + \ifdim\boxhdisplacement<\zeropoint + -\boxhdisplacement + \fi + \relax \lower\d_pack_layers_y_position\hbox {\ifdim\boxvdisplacement<\zeropoint - \lower-\boxvdisplacement\flushnextbox - \else - \flushnextbox - \fi}}% + \lower-\boxvdisplacement + \fi + \box\nextbox}}% % combine height and depth into depth only (later flushed as height) - \global\setbox\collectorbox\hbox - {\lower\ht\collectorbox\box\collectorbox}% + \global\setbox\b_pack_boxes_collector\hbox + {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}% % just to be sure - \ifdim\wd\collectorbox<\d_pack_layers_x_size - \wd\collectorbox\d_pack_layers_x_size - \fi} + \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size + \wd\b_pack_boxes_collector\d_pack_layers_x_size + \fi + \egroup} -\def\flushcollector[#1]% - {\ifcsname\@@collectorbox#1\endcsname - \doifnotvalue{\??cb#1\c!state}\v!stop - {\vbox - {\hbox - {\doifelsevalue{\??cb#1\c!state}\v!repeat - {\let\next\copy}{\let\next\box}% - \raise\dp\csname\@@collectorbox#1\endcsname - \next\csname\@@collectorbox#1\endcsname}}}% - \else - \writestatus{collector}{unknown collector #1}% - \fi} +\unexpanded\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 + \vbox{\hbox{\raise + \dp\b_pack_boxes_collector + \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}% + \fi + \fi + \egroup} -\def\composedcollector#1{\flushcollector[#1]} +\unexpanded\def\composedcollector#1% no [], handy as argument + {\flushcollector[#1]} -\def\resetcollector[#1]% - {\ifcsname\@@collectorbox#1\endcsname - \global\setbox\csname\@@collectorbox#1\endcsname\emptybox - \fi} +\unexpanded\def\adaptcollector + {\dodoubleargument\pack_boxes_collector_adapt} -\def\adaptcollector - {\dodoubleargument\doadaptcollector} - -\def\doadaptcollector[#1][#2]% % a typical case where \global\wd looks better in the code - {\bgroup - \def\currentcollector{#1}% - \chardef\collectorbox\csname\@@collectorbox#1\endcsname - \getparameters[\??cb#1][\c!voffset=\zeropoint,\c!hoffset=\zeropoint,#2]% - \scratchdimen\wd\collectorbox - \advance\scratchdimen\collectorparameter\c!hoffset - \global\wd\collectorbox\scratchdimen - \scratchdimen\ht\collectorbox - \advance\scratchdimen\collectorparameter\c!voffset - \global\ht\collectorbox\scratchdimen - \egroup} +\def\pack_boxes_collector_adapt[#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 + \ifsecondargument + \setupcurrentcollector[#2]% + \fi + \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] @@ -368,23 +312,23 @@ \definecollector [caption] -\def\collectedtext - {\dodoubleempty\docollectedtext} - -\def\docollectedtext[#1][#2]#3% +\unexpanded\def\collectedtext % for captions {\bgroup - \dowithnextbox + \dodoubleempty\pack_boxes_collector_text} + +\def\pack_boxes_collector_text[#1][#2]#3% + {\dowithnextbox {\setcollector [caption] - {\flushnextbox}% + {\box\nextbox}% \setcollector [caption][#1] - {\getparameters[\??du][\c!style=,\c!color=,#2]% - \dousestyleparameter\@@dustyle + {\letdummyparameter\c!style\empty + \letdummyparameter\c!color\empty + \getdummyparameters[#2]% + \dousestyleparameter{\directdummyparameter\c!style}% \setupinterlinespace - \framed % watch the special setting of kader/overlay - [\c!frame=\v!overlay,\c!foregroundcolor=\@@ducolor,\c!foregroundstyle=\@@dustyle,#2] - {#3}}% + \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}% \composedcollector{caption}% \egroup}% \hbox} @@ -406,51 +350,6 @@ % [frame=on,offset=0pt] % {gans} % {\externalfigure[koe][width=3cm]} - -% lean and mean: -% -% \installcorenamespace {layeredtext} -% -% \newdimen\d_pack_layeredtexts_width -% \newdimen\d_pack_layeredtexts_height -% -% \definelayer -% [\??layeredtextlayer] -% -% \setuplayer -% [\??layeredtextlayer]% -% [\c!width=\d_pack_layeredtexts_width,\c!height=\d_pack_layeredtexts_height]% -% -% \unexpanded\def\layeredtext -% {\dodoubleempty\dolayeredtext} -% -% \def\dolayeredtext[#1][#2]#3% -% {\bgroup -% \dowithnextbox -% {\d_pack_layeredtexts_width \wd\nextbox -% \d_pack_layeredtexts_height\ht\nextbox -% \begingroup % preserve \nextbox -% \setlayer -% [\??layeredtextlayer]% -% [#1]% -% {\getparameters[\??du][\c!style=,\c!color=,#2]% -% \dousestyleparameter\@@dustyle -% \setupinterlinespace -% \framed -% [\c!frame=\v!overlay,\c!foregroundcolor=\@@ducolor,\c!foregroundstyle=\@@dustyle,#2]% -% {#3}}% -% \endgroup -% \framed -% [\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]% -% {\flushnextbox}% -% \egroup}% -% \hbox} -% -% maybe faster but more code: \installcorenamespace {layeredtext} \installcorenamespace {layeredtextlayer} @@ -531,15 +430,16 @@ % [frame=on,offset=0pt] % {gans} % {\externalfigure[koe][width=3cm]} - -\def\ornamenttext - {\dodoubleempty\doornamenttext} -\def\doornamenttext[#1][#2]% +\unexpanded\def\ornamenttext + {\dodoubleempty\pack_ornament_text} + +\def\pack_ornament_text[#1][#2]% {\bgroup \doifassignmentelse{#1} - {\getparameters[\s!dummy][\c!alternative=\v!a,#1]% - \doifelse\dummyalternative\v!a + {\letdummyparameter\c!alternative\v!a + \getdummyparameters[#1]% + \doifelse{\directdummyparameter\c!alternative}\v!a {\egroup\collectedtext}% {\egroup\layeredtext }% [#1][#2]}% @@ -549,7 +449,7 @@ {\dotripleempty\dodefineornament} \def\dodefineornament[#1][#2][#3]% - {\setvalue{#1}{\doornamenttext[#2][#3]}} + {\setuvalue{#1}{\pack_ornament_text[#2][#3]}} % \defineornament % [affiliation] @@ -582,13 +482,12 @@ % [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] % % \affiliation{drawing}{\externalfigure[hakker][width=3cm]} - -% pas op: aanpassen aan nieuwe layer hoek ankers en columnset -\newcount\nofbleeds % per pag +\newcount\c_pack_boxes_bleeds + +\installcorenamespace {bleeding} -\unexpanded\def\setupbleeding - {\dodoubleempty\getparameters[\??bg]} +\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding \setupbleeding [\c!location=l, @@ -597,92 +496,117 @@ \c!height=3cm, \c!offset=2mm, \c!page=\v!no, - \c!voffset=\@@bgoffset, - \c!hoffset=\@@bgoffset] + \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset + \c!hoffset=\scratchoffset] % which often saves one resolve -\unexpanded\def\bleed - {\dosingleempty\pack_boxes_bleed} +\def\bleedwidth {\the\hsize} % these are global ! +\def\bleedheight{\the\vsize} % these are global ! -\def\bleedwidth {\the\hsize}% -\def\bleedheight{\the\vsize}% +\newconditional\c_pack_boxes_l +\newconditional\c_pack_boxes_r +\newconditional\c_pack_boxes_t +\newconditional\c_pack_boxes_b -\def\pack_boxes_bleed[#1]#2% +\unexpanded\def\bleed {\hbox\bgroup + \dosingleempty\pack_boxes_bleed} + +\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} + +\def\pack_boxes_bleed[#1]% + {\global\advance\c_pack_boxes_bleeds\plusone + % \xdef\bleedwidth {\the\hsize}% \xdef\bleedheight{\the\vsize}% - \global\advance\nofbleeds\plusone - \getparameters[\??bg][#1]% - \!!doneafalse % left - \!!donebfalse % right - \!!donecfalse % top - \!!donedfalse % bottom - % replace this part ! todo: default location - \processaction - [\@@bglocation] - [ t=>\!!donectrue\let\@@bghoffset\!!zeropoint, - b=>\!!donedtrue\let\@@bghoffset\!!zeropoint, - l=>\!!doneatrue\let\@@bgvoffset\!!zeropoint, - r=>\!!donebtrue\let\@@bgvoffset\!!zeropoint, - bl=>\!!doneatrue\!!donedtrue, - lb=>\!!doneatrue\!!donedtrue, - br=>\!!donebtrue\!!donedtrue, - rb=>\!!donebtrue\!!donedtrue, - tl=>\!!doneatrue\!!donectrue, - lt=>\!!doneatrue\!!donectrue, - tr=>\!!donebtrue\!!donectrue, - rt=>\!!donebtrue\!!donectrue]% - \doifelse\@@bgstretch\v!yes\donetrue\donefalse - \scratchdimen\@@bgwidth - \edef\currentbgposition {\??bg:\number\nofbleeds}% + % + \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}% \edef\currentpageposition{page:0}% todo: per page - \ifdone - \if!!donea - \advance\scratchdimen\dimexpr \MPx\currentbgposition-\MPx\currentpageposition\relax - \else\if!!doneb - \scratchdimen\dimexpr\paperwidth-\MPx\currentbgposition+\MPx\currentpageposition\relax % not checked - \fi\fi - \fi - \advance\scratchdimen\@@bghoffset - \xdef\bleedwidth{\the\scratchdimen}% - \scratchdimen\@@bgheight - \ifdone - \if!!donec - \scratchdimen\dimexpr\paperheight-\MPy\currentbgposition+\MPy\currentpageposition\relax % not checked - \else\if!!doned - \advance\scratchdimen\dimexpr \MPy\currentbgposition-\MPy\currentpageposition\relax % not checked - \fi\fi - \fi - \advance\scratchdimen\@@bgvoffset - \xdef\bleedheight{\the\scratchdimen}% % - \bgroup - \hsize\bleedwidth - \vsize\bleedheight - \global\setbox\globalscratchbox\hbox{#2}% - \egroup - \setbox\scratchbox\box\globalscratchbox + \setupcurrentbleeding[#1]% % - \doif\@@bgpage\v!yes - {\setbox\scratchbox\topskippedbox{\box\scratchbox}}% - \setbox\scratchbox\hbox to \@@bgwidth - {\if!!donea\hss\fi\box\scratchbox\if!!doneb\hss\fi}% - \if!!doned - \setbox\scratchbox\hbox - {\lower\bleedheight\hbox{\raise\@@bgheight\box\scratchbox}}% + \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{\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}% + \xdef\bleedheight{\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 % not checked + \else + \scratchheight + \fi\fi + \else + \scratchheight + \fi+\scratchvoffset}% + \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\hbox 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\hbox + {\lower\bleedheight\hbox{\raise\scratchheight\box\nextbox}}% \fi - \wd\scratchbox\@@bgwidth - \ht\scratchbox\@@bgheight - \dp\scratchbox\zeropoint + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\zeropoint \ifdone - \hpos\currentbgposition{\box\scratchbox}% + \hpos\currentbgposition{\box\nextbox}% \else - \box\scratchbox + \box\nextbox \fi \egroup} -\setupbleeding[\c!stretch=\v!yes] - -\defineexternalfigure[bleed][\c!width=\bleedwidth,\c!height=\bleedheight] % should be \v!bleed +\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]}} @@ -717,7 +641,7 @@ % tricky: offsets apply to both the layer and the framed; it makes sense to % only apply the offset to ... -\def\setlayerframed +\unexpanded\def\setlayerframed {\dotripleempty\pack_layers_set_framed} \def\pack_layers_set_framed @@ -741,24 +665,22 @@ {\setlayer[#1][#2]% \normalframedwithsettings[#3]} -\def\setlayertext +\unexpanded\def\setlayertext {\dotripleempty\pack_layers_set_text} \def\pack_layers_set_text[#1][#2][#3]% {\bgroup - \getparameters - [\??lx] - [\c!align=, - \c!width=\hsize, - \c!color=, - \c!style=, - #3]% + \letdummyparameter\c!align\empty + \letdummyparameter\c!width\hsize + \letdummyparameter\c!color\empty + \letdummyparameter\c!style\empty + \getdummyparameters[#3]% \dowithnextboxcontent {\forgetall - \hsize\@@lxwidth - \normalexpanded{\setupalign[\@@lxalign]}% - \dousestyleparameter\@@lxstyle} - {\setlayer[#1][#2]{\strut\dousecolorparameter\@@lxcolor\flushnextbox}% + \hsize\directdummyparameter\c!width + \normalexpanded{\setupalign[\directdummyparameter\c!align]}% + \dousestyleparameter{\directdummyparameter\c!style}} + {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color \egroup}% \vtop} @@ -804,22 +726,6 @@ [\v!middle] [\c!corner=\v!middle,\c!location=\v!middle] -% \definelayerpreset -% [\v!middle\v!top] -% [\c!location=\v!bottom,\c!hoffset=.5\layerwidth] - -% \definelayerpreset -% [\v!middle\v!bottom] -% [\c!location=\v!top,\c!hoffset=.5\layerwidth,\c!voffset=\layerheight] - -% \definelayerpreset -% [\v!middle\v!left] -% [\c!location=\v!right,\c!voffset=.5\layerheight] - -% \definelayerpreset -% [\v!middle\v!right] -% [\c!location=\v!left,\c!hoffset=\layerwidth,\c!voffset=.5\layerheight] - \definelayerpreset [\v!middle\v!top] [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth] @@ -901,93 +807,133 @@ % 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=] + +\let\setupoffset\setupoffsetbox + \unexpanded\def\offsetbox{\dosingleempty\pack_boxes_offset_box} \unexpanded\def\offset {\dosingleempty\pack_boxes_offset} -\def\pack_boxes_offset_box[#1]{\bgroup\dowithnextbox{\pack_boxes_offsetfinish{#1}}} -\def\pack_boxes_offset [#1]{\bgroup\dowithnextbox{\pack_boxes_offsetfinish{#1}}\hbox} - -\def\pack_boxes_offsetfinish#1% - {\getparameters[\??ox] - [\c!x=\zeropoint, - \c!y=\zeropoint, - \c!width=\nextboxwd, - \c!height=\nextboxht, - \c!depth=\nextboxdp, - \c!location=, - \c!leftoffset=\zeropoint, - \c!rightoffset=\zeropoint, - \c!topoffset=\zeropoint, - \c!bottomoffset=\zeropoint, - \c!method=, - #1]% - \donefalse - \ifdim\@@oxleftoffset =\zeropoint\else\donetrue\fi - \ifdim\@@oxrightoffset =\zeropoint\else\donetrue\fi - \ifdim\@@oxtopoffset =\zeropoint\else\donetrue\fi - \ifdim\@@oxbottomoffset=\zeropoint\else\donetrue\fi +\def\pack_boxes_offset_box[#1]% + {\bgroup + \pack_boxes_offset_check[#1]% + \dowithnextboxcs\pack_boxes_offsetfinish} + +\def\pack_boxes_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 + \ifdim\scratchleftoffset =\zeropoint\else\donetrue\fi + \ifdim\scratchrightoffset =\zeropoint\else\donetrue\fi + \ifdim\scratchtopoffset =\zeropoint\else\donetrue\fi + \ifdim\scratchbottomoffset=\zeropoint\else\donetrue\fi \ifdone - \doif\@@oxmethod\v!fixed % new - {\ifdim\@@oxleftoffset=\zeropoint - \ifdim\@@oxrightoffset=\zeropoint \else - \edef\@@oxx{\the\dimexpr-\@@oxrightoffset}% - \let\@@oxrightoffset\zeropoint - \fi - \else - \let\@@oxx\@@oxleftoffset - \let\@@oxleftoffset\zeropoint - \fi - \ifdim\@@oxtopoffset=\zeropoint - \ifdim\@@oxbottomoffset=\zeropoint \else - \edef\@@oxy{\the\dimexpr-\@@oxbottomoffset}% - \let\@@oxbottomoffset\zeropoint - \fi - \else - \let\@@oxy\@@oxtopoffset - \let\@@oxtopoffset\zeropoint - \fi - \donefalse}% + \edef\p_method{\offsetboxparameter\c!method}% + \ifx\p_method\v!fixed % new + \ifdim\scratchleftoffset=\zeropoint + \ifdim\scratchrightoffset=\zeropoint \else + \scratchxposition-\scratchrightoffset + \scratchrightoffset\zeropoint + \fi + \else + \scratchxposition\scratchleftoffset + \scratchleftoffset\zeropoint + \fi + \ifdim\scratchtopoffset=\zeropoint + \ifdim\scratchbottomoffset=\zeropoint \else + \scratchyposition-\scratchbottomoffset + \scratchbottomoffset\zeropoint + \fi + \else + \scratchyposition\scratchtopoffset + \scratchtopoffset\zeropoint + \fi + \donefalse + \fi \fi \ifdone \setbox\nextbox\vbox {\forgetall % already done \offinterlineskip - \vskip\@@oxtopoffset + \vskip\scratchtopoffset \hbox - {\hskip\@@oxleftoffset + {\hskip\scratchleftoffset \box\nextbox - \hskip\@@oxrightoffset}% - \vskip\@@oxbottomoffset}% + \hskip\scratchrightoffset}% + \vskip\scratchbottomoffset}% \ht\nextbox\htdp\nextbox \dp\nextbox\zeropoint \fi - \freezedimenmacro\@@oxwidth - \freezedimenmacro\@@oxheight - \freezedimenmacro\@@oxdepth + \scratchwidth \offsetboxparameter\c!width + \scratchheight\offsetboxparameter\c!height + \scratchdepth \offsetboxparameter\c!depth + \edef\p_location{\offsetboxparameter\c!location}% \setbox\nextbox\hbox - {\hskip\@@oxx\lower\@@oxy\hbox - {\doifelsenothing\@@oxlocation - {\box\nextbox} - {\alignedbox[\@@oxlocation]\hbox{\box\nextbox}}}}% - \wd\nextbox\@@oxwidth - \ht\nextbox\@@oxheight - \dp\nextbox\@@oxdepth + {\hskip\scratchxposition + \lower\scratchyposition\hbox + {\ifx\p_location\empty + \box\nextbox + \else + \alignedbox[\p_location]\hbox{\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[koe][breedte=3cm]}} -% \input tufte -% \placefigure[left,none]{}{\offset[rightoffset=1cm]{\externalfigure[koe][breedte=3cm]}} -% \input tufte -% \placefigure[left,none]{}{\offset[topoffset=1cm]{\externalfigure[koe][breedte=3cm]}} -% \input tufte -% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}} -% \input tufte - -%\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c] -% {\framed[width=4cm,height=4cm]{x}}} +% \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: % @@ -1020,15 +966,14 @@ \unexpanded\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{} {\hbox\bgroup - \getparameters - [\??ol] % brrr - [\c!width=\zeropoint,% - \c!height=\zeropoint,% - \c!depth=\zeropoint,#1]% + \letdummyparameter\c!width \zeropoint + \letdummyparameter\c!height\zeropoint + \letdummyparameter\c!depth \zeropoint + \getdummyparameters[#1]% \setbox\scratchbox\emptyhbox - \wd\scratchbox\@@olwidth - \ht\scratchbox\@@olheight - \dp\scratchbox\@@oldepth + \wd\scratchbox\directdummyparameter\c!width + \ht\scratchbox\directdummyparameter\c!height + \dp\scratchbox\directdummyparameter\c!depth \box\scratchbox \egroup} @@ -1044,17 +989,17 @@ \ifcase#1\relax % just one \else - \scratchdimen#2\divide\scratchdimen\wd\nextbox\count0\scratchdimen\advance\count0\plusone - \scratchdimen#3\divide\scratchdimen\ht\nextbox\count2\scratchdimen\advance\count2\plusone + \scratchdimen#2\divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax + \scratchdimen#3\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax % to be considered: methods \ifcase#1% \or % x and y - \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}% - \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}% + \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}% + \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}% \or % x - \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}% + \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}% \or % y - \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}% + \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}% \fi \fi \ifdim\wd\nextbox>#2\relax diff --git a/tex/context/base/pack-com.mkiv b/tex/context/base/pack-com.mkiv index 4d50bf7c7..fbc2b2732 100644 --- a/tex/context/base/pack-com.mkiv +++ b/tex/context/base/pack-com.mkiv @@ -210,7 +210,7 @@ \alignmark\alignmark \m_pack_combinations_rightfiller \aligntab - \tabskip\zeropoint \!!plus 1fill + \tabskip\zeropoint \s!plus 1fill \alignmark\alignmark \cr \pack_combinations_pickup} @@ -663,8 +663,8 @@ \setvalue{\??pairedboxalign\v!middle}% 4 {\let\pack_pairedboxes_align_l\hss \let\pack_pairedboxes_align_r\hss - \let\pack_pairedboxes_align_t\hss - \let\pack_pairedboxes_align_b\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}} @@ -789,10 +789,10 @@ \unexpanded\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox} \unexpanded\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox} -\def\pack_topofeachother_one{\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_topofeach_two \hbox} -\def\pack_sidebyside_one {\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_sidebyside_two\hbox} +\def\pack_topofeachother_one{\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox} +\def\pack_sidebyside_one {\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox} -\def\pack_topofeachother_two{\setbox2\box\nextbox\halign{\hss####\hss\cr\box0\cr\box2\cr}\egroup\egroup} -\def\pack_sidebyside_two {\setbox2\box\nextbox\valign{\vss####\vss\cr\box0\cr\box2\cr}\egroup\egroup} +\def\pack_topofeachother_two{\setbox2\box\nextbox\halign{\hss##\hss\cr\box0\cr\box2\cr}\egroup\egroup} +\def\pack_sidebyside_two {\setbox2\box\nextbox\valign{\vss##\vss\cr\box0\cr\box2\cr}\egroup\egroup} \protect \endinput diff --git a/tex/context/base/pack-cut.mkiv b/tex/context/base/pack-cut.mkiv new file mode 100644 index 000000000..63f4524a8 --- /dev/null +++ b/tex/context/base/pack-cut.mkiv @@ -0,0 +1,163 @@ +%D \module +%D [ file=pack-cut, % comes from core-vis/trac-vis +%D version=1996.06.01, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Cut 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. + +\unprotect + +%D \macros +%D {makecutbox, cuthbox, cutvbox, cutvtop} +%D +%D Although mainly used for marking the page, these macros can +%D also serve local use. +%D +%D \startbuffer +%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0 +%D \stopbuffer +%D +%D \typebuffer +%D +%D This marked \type{\vbox} shows up as: +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D The alternative macros are used as: +%D +%D \startbuffer +%D \cuthbox{a made cut box} +%D \stopbuffer +%D +%D \typebuffer +%D +%D This is typeset as: +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D By setting the next macros one can influence the length of +%D the marks as well as the horizontal and vertical divisions. + +\newdimen\d_pack_cutmarks_width +\newdimen\d_pack_cutmarks_height +\newdimen\d_pack_cutmarks_depth + +\newcount\horizontalcutmarks \horizontalcutmarks \plustwo +\newcount\verticalcutmarks \verticalcutmarks \plustwo +\newcount\cutmarkoffset \cutmarkoffset \plusone + +\let\cutmarksymbol \relax +\let\cutmarktoptext \empty +\let\cutmarkbottomtext \empty +\let\cutmarkhoffset \empty +\let\cutmarkvoffset \empty +\def\cutmarklength {2\bodyfontsize} +\def\cutmarkrulethickness{\onepoint} + +\unexpanded\def\horizontalcuts + {\normalhbox to \d_pack_cutmarks_width + {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\normalhfill}% + \unskip}} + +\unexpanded\def\verticalcuts + {\normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + {\hsize\cutmarklength + \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\normalvfill}% + \unskip}} + +\unexpanded\def\baselinecuts + {\ifdim\d_pack_cutmarks_depth>\zeropoint + \normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + {\hsize\dimexpr\cutmarklength/2\relax + \normalvskip\zeropoint\s!plus\d_pack_cutmarks_height + \vrule\s!height\cutmarkrulethickness\s!width\hsize + \normalvskip\zeropoint\s!plus\d_pack_cutmarks_depth}% + \fi} + +\unexpanded\def\cutmarksymbols#1% + {\normalhbox to \d_pack_cutmarks_width + {\setbox\scratchbox\normalhbox to \cutmarklength + {\normalhss\infofont\cutmarksymbol\normalhss}% + \normalhss + \normalvbox to \cutmarklength + {\scratchdimen\dimexpr\cutmarklength/2\relax + \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi + \normalvss + \hbox to \d_pack_cutmarks_width + {\llap{\copy\scratchbox\normalhskip\scratchskip}% + \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen + \rlap{\normalhskip\scratchskip\copy\scratchbox}}% + \normalvss}% + \normalhss}} + +\unexpanded\def\makecutbox#1% + {\bgroup + \d_pack_cutmarks_height\ht#1% + \d_pack_cutmarks_depth \dp#1% + \d_pack_cutmarks_width \wd#1% + \setbox#1\normalhbox + {\dontcomplain + \forgetall + \boxmaxdepth\maxdimen + \offinterlineskip + \scratchdimen\dimexpr\cutmarklength/2\relax + \hsize\d_pack_cutmarks_width + \setbox\scratchbox\normalvbox + {\setbox\scratchbox\normalhbox{\horizontalcuts}% + \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi + \tlap{\copy\scratchbox\normalvskip\scratchskip}% + \hbox to \d_pack_cutmarks_width + {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi + \setbox\scratchbox\normalhbox{\verticalcuts}% + \llap{\copy\scratchbox\normalhskip\scratchskip}% + \ifdim\d_pack_cutmarks_depth=\zeropoint + \normalhfill + \else + \bgroup + \setbox\scratchbox\normalhbox{\baselinecuts}% + \llap{\copy\scratchbox\normalhskip\scratchskip}% + \normalhfill + \rlap{\normalhskip\scratchskip\copy\scratchbox}% + \egroup + \fi + \rlap{\normalhskip\scratchskip\copy\scratchbox}}% + \blap{\normalvskip\scratchskip\copy\scratchbox}}% + \ht\scratchbox\d_pack_cutmarks_height + \dp\scratchbox\d_pack_cutmarks_depth + \wd\scratchbox\zeropoint + \startcolor[\defaulttextcolor]% + \box\scratchbox + \ifx\cutmarksymbol\relax \else + \setbox\scratchbox\normalvbox + {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi + \vskip-\dimexpr\scratchskip+\cutmarklength\relax + \normalhbox{\cutmarksymbols\cutmarktoptext}% + \vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax + \normalhbox{\cutmarksymbols\cutmarkbottomtext}}% + \ht\scratchbox\d_pack_cutmarks_height + \dp\scratchbox\d_pack_cutmarks_depth + \wd\scratchbox\zeropoint + \box\scratchbox + \fi + \stopcolor + \box#1}% + \wd#1\d_pack_cutmarks_width + \ht#1\d_pack_cutmarks_height + \dp#1\d_pack_cutmarks_depth + \egroup} + +\unexpanded\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox} +\unexpanded\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox} +\unexpanded\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop} + +\protect \endinput diff --git a/tex/context/base/pack-mrl.mkiv b/tex/context/base/pack-mrl.mkiv index f3f3d11d9..ec214d4f3 100644 --- a/tex/context/base/pack-mrl.mkiv +++ b/tex/context/base/pack-mrl.mkiv @@ -13,26 +13,24 @@ \writestatus{loading}{ConTeXt Packaging Macros / More Rules} -%D This module needs an overhaul. +%D The (re)implementation of margin rules has been moved elsewhere. \unprotect %D \macros %D {setupblackrules,blackrule} %D -%D The graphic capabilities of \TEX\ do not go beyond simple -%D filled rules, except of course when using specials. Let's -%D start with a warning: using this commands is far more slower -%D than using the \TEX\ primitives \type{\hrule} and -%D \type{\vrule}, but they save us some tokens. The +%D The graphic capabilities of \TEX\ do not go beyond simple filled rules, except of +%D course when using specials or, in \MKIV, manipulate node lists. Let's start with +%D a warning: using this commands is far more slower than using the \TEX\ primitives +%D \type {\hrule} and \type {\vrule}, but they save us some tokens. The %D characteristics of these rule drawing command can be set by: %D %D \showsetup{setupblackrules} %D -%D The simple command draws only one rule. Its optional -%D argument can be used to specify the dimensions. By setting -%D the width, height or depth to \type {max}, one gets the -%D natural dimensions. +%D The simple command draws only one rule. Its optional argument can be used to +%D specify the dimensions. By setting the width, height or depth to \type {max}, one +%D gets the natural dimensions. %D %D \showsetup{blackrule} @@ -59,9 +57,9 @@ \fi\fi \useblackrulesstyleandcolor\c!style\c!color \vrule - \!!width \ifx\p_width \v!max\emwidth\else\p_width \fi - \!!height\ifx\p_height\v!max\strutht\else\p_height\fi - \!!depth \ifx\p_depth \v!max\strutdp\else\p_depth \fi + \s!width \ifx\p_width \v!max\emwidth\else\p_width \fi + \s!height\ifx\p_height\v!max\strutht\else\p_height\fi + \s!depth \ifx\p_depth \v!max\strutdp\else\p_depth \fi \egroup} \setupblackrules @@ -73,8 +71,8 @@ %D \macros %D {blackrules} %D -%D One can call for a sequence of black rules, if needed -%D equally spaced over the given width. +%D One can call for a sequence of black rules, if needed equally spaced over the +%D given width. %D %D \showsetup{blackrules} %D @@ -93,9 +91,8 @@ %D \getbuffer %D \stoplines %D -%D We could of course have implemented this macro using -%D \type{\leaders}, but this would probably have taken more -%D tokens. +%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 {\hbox\bgroup @@ -122,9 +119,9 @@ \useblackrulesstyleandcolor\c!style\c!color \dorecurse\scratchcounter % a typical case of where we can use a simple loop {\vrule - \!!width \scratchwidth - \!!height\scratchheight - \!!depth \scratchdepth + \s!width \scratchwidth + \s!height\scratchheight + \s!depth \scratchdepth \hskip\scratchdistance}% \unskip \egroup} @@ -135,169 +132,51 @@ \c!distance=.25\emwidth, \c!color=] -%D Marginrules will either become obsolete or be redone. - -%D The next commands can be used to draw margin rules. We -%D support two methods: \marginrule{one for in||line use} and -%D one that acts on a paragraph. Drawing a margin rule is -%D rather straightforward because we can use the commands that -%D put text in the margin. - -\def\dodrawmarginrule - {\setbox\scratchbox\hbox - {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}% - \smashbox\scratchbox % no \vsmash !!! - \box\scratchbox} - -\def\drawmarginrule - {\strut\inleft{\dodrawmarginrule}} - -%D \macros -%D {marginrule} -%D -%D The first method gobbles words and simply puts a bar in the -%D margin. This method is not entirely robust. -%D -%D \showsetup{marginrule} - -\definecomplexorsimple\marginrule - -\def\simplemarginrule - {\let\processword\drawmarginrule - \processwords} - -\def\complexmarginrule[#1]% - {\ifnum#1<\@@kalevel\relax \else - \def\@@kadefaultwidth{#1}% - \expandafter\simplemarginrule - \fi} - -%D We need an auxiliary variable - -\def\@@kadefaultwidth{1} - -%D \macros -%D {setupmarginrules} -%D -%D This macro definitions show us that we can pass an optional -%D level, which is matched against the previous set one. The -%D level can be set up with -%D -%D \showsetup{setupmarginrules} - -\unexpanded\def\setupmarginrules - {\dodoubleargument\getparameters[\??ka]} - -%D \macros -%D {startmarginrule} -%D -%D The second method collects text and reformats it afterwards, -%D using the shapebox macros. We prevent local margin rules. -%D -%D \showsetup{startmarginrule} - -\definecomplexorsimple\startmarginrule - -\def\simplestartmarginrule - {\bgroup - \let\drawmarginrule\relax - \let\stopmarginrule\dostopmarginrule - \beginofshapebox} - -\def\complexstartmarginrule[#1]% - {\bgroup - \let\drawmarginrule\relax - \ifnum#1<\@@kalevel\relax - \let\stopmarginrule\egroup - \else - \def\@@kadefaultwidth{#1}% - \let\stopmarginrule\dostopmarginrule - \expandafter\beginofshapebox - \fi} - -\def\dostopmarginrule - {\endofshapebox - \reshapebox - {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}% - \flushshapebox - \egroup} - -%D \startbuffer -%D \setupmarginrules[level=5] -%D -%D \startmarginrule[1] -%D First we set the level at~5. Next we typeset this first -%D paragraph as a level~1 one. As expected no rule show up. -%D \stopmarginrule -%D -%D \startmarginrule[5] -%D The second paragraph is a level~5 one. As we can see here, -%D the marginal rule gets a width according to its level. -%D \stopmarginrule -%D -%D \startmarginrule[8] -%D It will of course be no surprise that this third paragraph -%D has a even thicker margin rule. This behavior can be -%D overruled by specifying the width explictly. -%D \stopmarginrule -%D \stopbuffer -%D -%D In next example we show most features. Watch the rule -%D thickness adapting itself to the level. -%D -%D \startexample -%D \getbuffer -%D \stopexample -%D -%D We just said: -%D -%D \typebuffer - %D \macros %D {vl, hl} %D -%D The command \type{\vl} draws a vertical rule \vl\ with strut -%D dimensions, multiplied with the factor specified in the -%D optional argument. The height and depth are clipped \vl[3] -%D to the baselinedistance. Its horizontal counterpart -%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em, -%D multiplied with the optional factor. The horizontal rule is -%D drawn on top of the baseline. +%D The command \type {\vl} draws a vertical rule \vl\ with strut dimensions, +%D multiplied with the factor specified in the optional argument. The height and +%D depth are clipped \vl [3] to the baselinedistance. Its horizontal counterpart +%D \type {\hl} draws a horizontal rule \hl\ with a width of 1em, multiplied with the +%D optional factor. The horizontal rule is drawn on top of the baseline. %D %D \showsetup{vl} %D \showsetup{hl} -\unexpanded\def\dovlwdhtdp#1#2#3% used elsewhere +\unexpanded\def\pack_rule_vl_indeed#1#2#3% {\bgroup \setbox\scratchbox\hbox {\vrule - \!!width #1\linewidth - \!!height#2\strutht - \!!depth #3\strutdp}% + \s!width #1\linewidth + \s!height#2\strutht + \s!depth #3\strutdp}% \dp\scratchbox\strutdp \ht\scratchbox\strutht \box\scratchbox \egroup} -\def\complexvl[#1]% - {\dovlwdhtdp\plusone{#1}{#1}} +\def\pack_rule_vl[#1]% + {\pack_rule_vl_indeed{#1}{#1}{#1}} -\def\complexhl[#1]% +\def\pack_rule_hl[#1]% {\hbox {\vrule - \!!width #1\emwidth - \!!height\linewidth - \!!depth \zeropoint}} + \s!width #1\emwidth + \s!height\linewidth + \s!depth \zeropoint}} + +\unexpanded\def\vl{\dosingleempty\pack_rule_vl} +\unexpanded\def\hl{\dosingleempty\pack_rule_hl} -\definecomplexorsimple\vl \def\simplevl{\complexvl[\plusone]} -\definecomplexorsimple\hl \def\simplehl{\complexhl[\plusone]} +\let\dovlwdhtdp\pack_rule_vl_indeed % used elsewhere %D \macros %D {hairline, thinrule, thinrules, setupthinrules} %D -%D Drawing thin lines can of course easily be accomplished by -%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The -%D next few macros however free us from some specifications. +%D Drawing thin lines can of course easily be accomplished by the \TEX\ +%D primitives \type{\hrule} and \type{\vrule}. The next few macros however +%D free us from some specifications. %D %D \startbuffer %D some text @@ -338,112 +217,158 @@ %D %D which looks like: \thinrules[n=2] -\newconstant\ruletype +\installcorenamespace{thinrules} +\installcorenamespace{thinrulealternatives} + +\installdirectcommandhandler \??thinrules {thinrules} + +\setupthinrules + [\c!interlinespace=\v!small, + \c!n=3, + \c!before=, + \c!inbetween={\blank[\v!white]}, + \c!after=, + \c!color=, + \c!height=.5\linewidth, + \c!depth=.5\linewidth, + \c!frame=\v!on, % compatible with textbackgrounds + \c!alternative=\v!b, + \c!backgroundcolor=, + \c!background=, + \c!rulethickness=\linewidth] + +\letvalue{\??thinrulealternatives\v!a }\zerocount +\letvalue{\??thinrulealternatives\v!b }\plusone +\letvalue{\??thinrulealternatives\v!c }\plustwo +\letvalue{\??thinrulealternatives\v!none}\zerocount + +\newconstant\c_pack_thinrules_type \def\thinrule {\strut \bgroup - \ruletype\plusone - \processaction - [\@@dlalternative] - [ \v!a=>\ruletype\zerocount,% no line - %\v!b=>\ruletype\plusone ,% height/depth - \v!c=>\ruletype\plustwo ,% topheight/botdepth - % 11=>\ruletype\plusone ,% fallback for backgrounds - 0=>\ruletype\zerocount,% compatible with backgrounds - % 1=>\ruletype\plusone ,% compatible with backgrounds - 2=>\ruletype\plustwo ]% compatible with backgrounds - \doifsomething\@@dlrulethickness - {\linewidth\@@dlrulethickness}% + \edef\p_height {\directthinrulesparameter\c!height}% + \edef\p_depth {\directthinrulesparameter\c!depth}% + \edef\p_background{\directthinrulesparameter\c!background}% + \edef\p_frame {\directthinrulesparameter\c!frame}% + \linewidth\dimexpr\directthinrulesparameter\c!rulethickness/\plustwo\relax \ifdim\linewidth=\zeropoint - \ruletype\zerocount + \c_pack_thinrules_type\zerocount + \else\ifx\p_frame\v!on + \c_pack_thinrules_type\expandcheckedcsname\??thinrulealternatives{\directthinrulesparameter\c!alternative}\v!b\relax \else - \doifnot\@@dlframe\v!on{\ruletype\zerocount}% + \c_pack_thinrules_type\zerocount + \fi\fi + \ifnum\c_pack_thinrules_type=\plusone + \ifx\p_height\v!max + \scratchheight\strutht + \else + \setdimensionwithunit\scratchheight\p_height\strutht + \fi + \ifx\p_depth\v!max + \scratchdepth\strutdp + \else + \setdimensionwithunit\scratchdepth\p_depth\strutdp + \fi + \else + \scratchheight\strutht + \scratchdepth \strutdp \fi - \ifnum\ruletype=\plusone - \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}% - \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}% + \ifx\p_background\v!color + \startcolor[\directthinrulesparameter\c!backgroundcolor]% + \ifnum\c_pack_thinrules_type=\plustwo % prevent overshoot due to rounding + \leaders + \hrule + \s!height\dimexpr\scratchheight-\linewidth\relax + \s!depth \dimexpr\scratchdepth -\linewidth\relax + \hfill + \else + \leaders + \hrule + \s!height\scratchheight + \s!depth \scratchdepth + \hfill + \fi + \stopcolor + \ifcase\c_pack_thinrules_type + % no rule + \or + \startcolor[\directthinrulesparameter\c!color]% + \hfillneg + \leaders + \hrule + \s!height\linewidth + \s!depth \linewidth + \hfill + \stopcolor + \or + \startcolor[\directthinrulesparameter\c!color]% + \hfillneg + \leaders + \hrule + \s!height\dimexpr-\scratchdepth+\linewidth\relax + \s!depth \scratchdepth + \hfill + \hfillneg + \leaders + \hrule + \s!height\scratchheight + \s!depth \dimexpr-\scratchheight+\linewidth\relax + \hfill + \stopcolor + \fi \else - \let\@@dlheight\!!plusone - \let\@@dldepth\!!plusone + \ifcase\c_pack_thinrules_type + % no rule + \else + \startcolor[\directthinrulesparameter\c!color]% + \leaders + \hrule + \s!height\scratchheight + \s!depth \scratchdepth + \hfill + \stopcolor + \fi \fi - \freezedimensionwithunit\@@dlheight\strutht - \freezedimensionwithunit\@@dldepth\strutdp - \divide\linewidth \plustwo - \doifelse\@@dlbackground\v!color - {\startcolor[\@@dlbackgroundcolor]% - \ifnum\ruletype=\plustwo % prevent overshoot due to rounding - \leaders - \hrule - \!!height\dimexpr\@@dlheight-.5\linewidth\relax - \!!depth \dimexpr\@@dldepth -.5\linewidth\relax - \hfill - \else - \leaders - \hrule - \!!height\@@dlheight - \!!depth \@@dldepth - \hfill - \fi - \stopcolor - \ifcase\ruletype - % no rule - \or - \startcolor[\@@dlcolor]% - \hfillneg - \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill - \stopcolor - \or - \startcolor[\@@dlcolor]% - \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill - \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill - \stopcolor - \fi} - {\ifcase\ruletype \else - \startcolor[\@@dlcolor]% - \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill - \stopcolor - \fi}% \strut \carryoverpar\egroup} -\def\hairline +\unexpanded\def\hairline {\endgraf \thinrule \endgraf} -\def\dosetupthinrules[#1]% - {\getparameters[\??dl][#1]} +\unexpanded\def\thinrules + {\dosingleempty\pack_thinrules} -\unexpanded\def\setupthinrules - {\dosingleargument\dosetupthinrules} - -\def\dothinrules[#1]% +\def\pack_thinrules[#1]% {\bgroup - \dosetupthinrules[#1]% - \@@dlbefore - \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}% - \spacing\@@dlinterlinespace - \dorecurse\@@dln - {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else - \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi - \thinrule - \ifnum\recurselevel<\@@dln\relax + \setupcurrentthinrules[#1]% + \assignvalue{\directthinrulesparameter\c!interlinespace}\m_pack_thinrules_interlinespace{1.0}{1.5}{2.0}% + \spacing\m_pack_thinrules_interlinespace + \edef\p_after {\directthinrulesparameter\c!after}% + \edef\p_inbetween{\directthinrulesparameter\c!inbetween}% + \directthinrulesparameter\c!before + \scratchcounter\directthinrulesparameter\c!n\relax + \dorecurse\scratchcounter + {\ifnum\recurselevel=\scratchcounter \penalty500 \else + \ifnum\recurselevel=\plustwo \penalty500 \fi\fi + \thinrule + \ifnum\recurselevel<\scratchcounter\relax % test needed, else messed up whitespace - \ifx\@@dlinbetween\empty - \softbreak + \ifx\p_inbetween\empty + \softbreak % \ifhmode \hskip \parfillskip \break \fi \else \endgraf \nowhitespace - \@@dlinbetween + \p_inbetween \fi \fi}% - \doifelsenothing\@@dlafter - {\carryoverpar\egroup} - {\@@dlafter\egroup}} - -\def\thinrules - {\dosingleempty\dothinrules} + \ifx\p_after\empty + \carryoverpar\egroup + \else + \p_after\egroup + \fi{}} %D A couple of examples are given below. %D @@ -464,11 +389,10 @@ %D %D \typebuffer {\getbuffer} %D -%D There are a couple of alternative ways to visualize rules -%D using backgrounds. At first sight these may look strange, -%D but they make sense in educational settings. The -%D alternatives are more or less compatible with the more -%D advanced \METAPOST\ based implementation. +%D There are a couple of alternative ways to visualize rules using backgrounds. At +%D first sight these may look strange, but they make sense in educational settings. +%D The alternatives are more or less compatible with the more advanced \METAPOST\ +%D based implementation. %D %D \startbuffer[a] %D \setupthinrules @@ -507,22 +431,10 @@ %D \typebuffer[b] \getbuffer[a,b] %D \macros -%D {optimizethinrules} -%D -%D By saying \type {\thinrulestrue} or \type {-false}, we -%D can influence the way dangling lines are handled. - -\newif\ifoptimizethinrules \optimizethinrulestrue - -\def\dothinrulesnobreak - {\ifoptimizethinrules\penalty500\fi} - -%D \macros %D {textrule, starttextrule, setuptextrules} %D -%D Putting rules before and after a paragraph is very space -%D sensitive, but the next command handles that quite well. It -%D comes in two disguises: +%D Putting rules before and after a paragraph is very space sensitive, but the +%D next command handles that quite well. It comes in two disguises: %D %D \startbuffer %D \textrule[top]{fragments} @@ -562,132 +474,176 @@ %D \showsetup{starttextrule} %D \showsetup{setuptextrules} %D -%D The implementation looks a bit complicated due to the -%D optional arguments. +%D The implementation looks a bit complicated due to the optional arguments. -\unexpanded\def\setuptextrules - {\dodoubleargument\getparameters[\??tl]} +\installcorenamespace{textrules} +\installcorenamespace{textrulealternatives} -\def\complextextrule[#1]% if needed we can make it installable - {\let\next\dobottomtextrule - \processaction - [#1] - [ \v!top=>\let\next\dotoptextrule, - \v!middle=>\let\next\domiddletextrule, - \v!bottom=>\let\next\dobottomtextrule]% - \dosinglegroupempty\next} +\installdirectcommandhandler \??textrules {textrules} -\definecomplexorsimple\textrule +\setuptextrules + [\c!location=\v!left, + \c!before=\blank, + \c!after=\blank, + \c!inbetween=, + \c!width=2\emwidth, + \c!style=\v!bold, + \c!color=, + \c!rulecolor=, + \c!bodyfont=, + \c!depthcorrection=\v!on, + \c!rulethickness=\linewidth, + \c!distance=.5\emwidth] -\def\simpletextrule - {\dosinglegroupempty\dounknowntextrule} +\unexpanded\def\textrule + {\dosingleempty\pack_textrule} -\def\docomplextextrule#1% +\def\pack_textrule + {\iffirstargument + \expandafter\pack_textrule_yes + \else + \expandafter\pack_textrule_nop + \fi} + +\def\pack_textrule_yes[#1]% + {\expandcheckedcsname\??textrulealternatives{#1}\v!bottom} + +\def\pack_textrule_nop[#1]% + {\dosinglegroupempty\pack_textrule_nop_indeed} + +\def\pack_textrule_nop_indeed + {\iffirstargument + \expandafter\pack_textrule_nop_indeed_yes + \else + \expandafter\pack_textrule_nop_indeed_nop + \fi} + +\def\pack_textrule_nop_indeed_yes + {\csname\??textrulealternatives\v!top\endcsname} + +\def\pack_textrule_nop_indeed_nop + {\csname\??textrulealternatives\v!bottom\endcsname\empty} + +%D\startbuffer +%D\showstruts +%D +%D\setupwhitespace[none] +%D +%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test} +%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test} +%D +%D\setupwhitespace[big] +%D +%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test} +%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test} +%D\stoptyping +%D +%D \typebuffer \start \getbuffer \stop + +\setvalue{\??textrulealternatives\v!top}#1% + {\page[\v!preference] % interferes + \directtextrulesparameter\c!before\relax + \blank[\v!samepage,\v!nowhite]% + \pack_textrule_with_text{#1}% + \blank[\v!samepage,\v!nowhite]% + \directtextrulesparameter\c!inbetween\relax + \endgraf} + +\setvalue{\??textrulealternatives\v!bottom}#1% + {\blank[\v!samepage,\v!nowhite]% + \pack_textrule_following{#1}% + \blank[\v!samepage,\v!nowhite]% + \directtextrulesparameter\c!after\relax + \page[\v!preference]} + +\setvalue{\??textrulealternatives\v!middle}#1% + {\blank[\v!samepage,\v!nowhite]% + \directtextrulesparameter\c!inbetween\relax + \pack_textrule_following{#1}% + \blank[\v!samepage,\v!nowhite]% + \directtextrulesparameter\c!inbetween\relax + \page[\v!preference]} + +\def\pack_textrule_with_text#1% {\bgroup - \advance\hsize\dimexpr-\rightskip-\leftskip\relax - \setbox\scratchbox\hbox to \hsize - {\dimen4\dimexpr .5ex+.5\linewidth\relax - \dimen6\dimexpr-.5ex+.5\linewidth\relax + \setbox\scratchbox\hbox to \availablehsize + {\scratchwidth \directtextrulesparameter\c!rulethickness\relax + \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax + \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax \doifsomething{#1} - {\doifelse\@@tllocation\v!inmargin + {\doifelse{\directtextrulesparameter\c!location}\v!inmargin {\llap - {\dousestyleparameter\@@tlstyle - \dousecolorparameter\@@tlcolor + {\usetextrulesstyleandcolor\c!style\c!color #1% \hskip\leftmargindistance}} - {\color[\@@tlrulecolor] - {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}% - \hbox spread 2\dimexpr\@@tldistance\relax + {\color[\directtextrulesparameter\c!rulecolor] + {\vrule\s!height\scratchheight\s!depth\scratchdepth\s!width\directtextrulesparameter\c!width}% + \hbox spread 2\dimexpr\directtextrulesparameter\c!distance\relax {\hss - \dousestyleparameter\@@tlstyle - \dousecolorparameter\@@tlcolor + \usetextrulesstyleandcolor\c!style\c!color \strut#1% \hss}}}% - \color[\@@tlrulecolor] - {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}% + \color[\directtextrulesparameter\c!rulecolor] + {\leaders\hrule\s!height\scratchheight\s!depth\scratchdepth\hfill}}% \ht\scratchbox\strutht \dp\scratchbox\strutdp \noindent\box\scratchbox -%\nobreak\verticalstrut\kern-\struttotal -% evt \witruimte \egroup} -\def\dotoptextrule#1% - {\page[\v!preference] % interferes - %\whitespace % no - \@@tlbefore - \docomplextextrule{#1}% -% todo, option: \doifnothing{#1}{\ruledvskip-.5ex} - \nowhitespace - \@@tlinbetween - \endgraf} - -\def\dodobottomtextrule#1#2% - {\ifhmode - \endgraf - \fi - \dimen0\strutdp - \ifdim\prevdepth>\strutdp\else % was <\strutdp - \ifdim\prevdepth>\zeropoint - \advance\dimen0 -\prevdepth +\def\pack_textrule_correct_depth_yes + {\vskip\dimexpr + \strutdp +.5\exheight + \ifdim\prevdepth>\strutdp\else + \ifdim\prevdepth>\zeropoint + -\prevdepth + \fi \fi - \fi - \advance\dimen0 .5ex - \vskip\dimen0 -% == -% \vskip\dimexpr \strutdp + .5ex -% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax -% - \@@tlinbetween - \doifelsenothing{#2} - {\bgroup - \advance\hsize\dimexpr-\rightskip-\leftskip\relax + \relax + \relax} + +\def\pack_textrule_correct_depth_nop + {\vskip\dimexpr + \strutdp +.5\exheight + \relax + \relax} + +\def\pack_textrule_following#1% + {\doifelsenothing{#1} + {\ifhmode + \endgraf + \fi + \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on\pack_textrule_correct_depth_yes\pack_textrule_correct_depth_nop \nointerlineskip - \moveleft-\leftskip\vbox - {\color[\@@tlrulecolor] - {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}% - \egroup} - {\docomplextextrule{#2}}% - \ifvmode\prevdepth\zeropoint\fi - #1% - \page[\v!preference]} - -\def\dobottomtextrule - {\dodobottomtextrule\@@tlafter} - -\def\domiddletextrule - {\dodobottomtextrule\@@tlinbetween} - -\def\dounknowntextrule - {\iffirstargument - \@EA\dotoptextrule - \else - \@EA\dobottomtextrule\@EA\empty + \dontleavehmode\vbox + {\color[\directtextrulesparameter\c!rulecolor] + {\hrule\s!depth\directtextrulesparameter\c!rulethickness\s!height\zeropoint\s!width\availablehsize}}} + {\pack_textrule_with_text{#1}}% + \ifvmode + \prevdepth\zeropoint \fi} %D The grouped commands also supports bodyfont switching: \unexpanded\def\starttextrule#1% {\bgroup - \def\dounknowntextrule{\domiddletextrule} - \dotoptextrule{#1} + \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}% + \csname\??textrulealternatives\v!top\endcsname{#1}% \bgroup - \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}} + \doifsomething{\directtextrulesparameter\c!bodyfont}{\switchtobodyfont[\directtextrulesparameter\c!bodyfont]}} \unexpanded\def\stoptextrule {\par \egroup - \dobottomtextrule\empty + \csname\??textrulealternatives\v!bottom\endcsname\empty \egroup} %D \macros %D {fillinrules, setupfillinrules} %D -%D The next few commands do not really deserve a place in a -%D core module, because they deal with specific typography. -%D Nevertheless I decided to make them part of the core, -%D because they permit us to make questionaires. Let's start -%D with some examples. +%D The next few commands do not really deserve a place in a core module, because +%D they deal with specific typography. Nevertheless I decided to make them part of +%D the core, because they permit us to make questionaires. Let's start with some +%D examples. %D %D \fillinrules[n=2,width=fit]{first} %D \fillinrules[n=2,width=broad]{first} @@ -696,85 +652,112 @@ %D \fillinrules[n=2]{first}{last} %D \fillintext{first}{last} \input reich \par %D -%D The main command is \type{\fillinrules}. This command takes -%D one and an optional second argument and sets a paragraph with -%D empty visualized lines. +%D The main command is \type{\fillinrules}. This command takes one and an optional +%D second argument and sets a paragraph with empty visualized lines. %D %D \showsetup{fillinrules} %D \showsetup{setupfillinrules} -\unexpanded\def\setupfillinrules - {\dodoubleargument\getparameters[\??il]} -\definecomplexorsimpleempty\fillinrules +\installcorenamespace{fillinrules} -\def\complexfillinrules[#1]% - {\def\docomplexfillinrules##1##2% - {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules - [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}% - \dodoublegroupempty\docomplexfillinrules} +\installdirectcommandhandler \??fillinrules {fillinrules} -\def\dodocomplexfillinrules[#1]#2#3#4% +\setupfillinrules + [\c!width=\v!broad, + \c!distance=\emwidth, + \c!before=\blank, + \c!after=\blank, + \c!n=\plusone, + \c!interlinespace=\v!small, + \c!separator=, + \c!style=, + \c!color=] + +\unexpanded\def\fillinrules + {\dosingleempty\pack_fillinrules} + +\def\pack_fillinrules[#1]% {\endgraf - \@@ilbefore \begingroup - \setupfillinrules[#1]% + \setupcurrentfillinrules[#1]% + \let\pack_fillinrules_rule\thinrules + \dodoublegroupempty\pack_fillinrules_indeed} + +\def\pack_fillinrules_indeed#1#2% + {\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 - \doifsomething{#2} - {\doifelse\@@ilwidth\v!fit - {\let\@@ildistance\!!zeropoint - \hbox} - {\doifelse\@@ilwidth\v!broad - {\hbox} - {\hbox to \@@ilwidth}}% - \bgroup - \dousestyleparameter\@@ilstyle - \dousecolorparameter\@@ilcolor - \strut#2\hfill\@@ilseparator\hskip\@@ildistance - \egroup}% - %\hangindent=\wd0\relax % tzt hang=yes,n - %\parindent=\hangindent - %\box0\relax + \ifx\m_fillinrules_one\empty \else + \edef\p_width{\directfillinrulesparameter\c!width}% + \ifx\p_width\v!fit + \scratchdistance\zeropoint + \hbox + \else\ifx\p_width\v!broad + \hbox + \else + \hbox to \directfillinrulesparameter\c!width + \fi\fi + \bgroup + \usefillinrulesstyleandcolor\c!style\c!color + \strut + \m_fillinrules_one + \hfill\directfillinrulesparameter\c!separator + \hskip\scratchdistance + \egroup + \fi \setupwhitespace[\v!big]% \ignorespaces - #4% - \doifsomething{#3} - {\kern\@@ildistance - \dousestyleparameter\@@ilstyle - \dousecolorparameter\@@ilcolor - #3\strut}% - \endgroup + \pack_fillinrules_rule + \ifx\m_fillinrules_two\empty \else + \kern\scratchdistance + \usefillinrulesstyleandcolor\c!style\c!color + \m_fillinrules_two + \strut + \fi \endgraf - \@@ilafter} + \directfillinrulesparameter\c!after + \endgroup} %D \macros %D {fillintext} %D -%D To provide compatible layouts when texts and lines are -%D mixed, one can typeset a paragraph by using the command -%D \type{\fillintext}. +%D To provide compatible layouts when texts and lines are mixed, one can typeset +%D a paragraph by using the command \type {\fillintext}. %D %D \showsetup{fillintext} -\definecomplexorsimpleempty\fillintext +\unexpanded\def\fillintext + {\dosingleempty\pack_fillintext} + +\def\pack_fillintext[#1]% ugly + {\endgraf + \begingroup + \setupcurrentfillinrules[#1]% + \dodoublegroupempty\pack_fillintext_indeed} -\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal - {\def\docomplexfillintext##1##2% - {\dowithnextbox - {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}% - \hbox\bgroup\let\par\egroup\ignorespaces}% - \dodoublegroupempty\docomplexfillintext} +\def\pack_fillintext_indeed#1#2% + {\def\pack_fillinrules_rule{\unhbox\nextbox\unskip}% + \dowithnextbox{\pack_fillinrules_indeed{#1}{\hfill#2}}% + \hbox\bgroup\let\par\egroup\ignorespaces} %D \macros %D {fillinline, setupfillinlines} %D -%D Another member of the family takes care of putting a (often -%D small) rule after a piece of text, like +%D Another member of the family takes care of putting a (often small) rule after +%D a piece of text, like %D %D \startbuffer -%D \fillinline \input reich \par +%D +%D \stopbuffer\fillinline \input reich \par %D \fillinline[margin=0cm] \input reich \par -%D \stopbuffer %D %D \startexample %D \getbuffer @@ -789,82 +772,71 @@ %D \showsetup{fillinline} %D \showsetup{setupfillinlines} -\unexpanded\def\setupfillinlines - {\dodoubleargument\getparameters[\??iv]} - -\definecomplexorsimpleempty\fillinline +\installcorenamespace{fillinlines} -\def\complexfillinline[#1]% - {%\endgraf % interferes with \definedescription cum suis - \@@ivbefore - \begingroup - \setupfillinlines[#1]% - \advance\rightskip \@@ivmargin - \parfillskip\zeropoint - \def\par % very dangerous - {\let\par\endgraf % -) - \ifhmode\unskip\hfill\fi - \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax - \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi - {\kern\@@ivdistance - \vrule - \!!width \scratchdimen - \!!height.5\linewidth - \!!depth .5\linewidth}% - \endgraf % ! - \endgroup - \endgraf % ! - \@@ilafter}} - -%D Will move up: - -\setupmarginrules - [\c!level=0, - \c!rulethickness=\@@kadefaultwidth\linewidth] +\installdirectcommandhandler \??fillinlines {fillinlines} -\setupthinrules - [\c!interlinespace=\v!small, - \c!n=3, - \c!before=, - \c!inbetween={\blank[\v!white]}, - \c!after=, +\setupfillinlines + [\c!width=8\emwidth, % was 3cm + \c!margin=\directfillinlinesparameter\c!width, + \c!rulethickness=\linewidth, \c!color=, - \c!height=.5\linewidth, - \c!depth=.5\linewidth, - \c!frame=\v!on, % compatible with textbackgrounds - \c!alternative=\v!b, - \c!backgroundcolor=, - \c!background=, - \c!rulethickness=] - -\setuptextrules - [\c!location=\v!left, + \c!distance=\emwidth, \c!before=\blank, - \c!after=\blank, - \c!inbetween=, - \c!width=2em, - \c!style=\v!bold, - \c!color=, - \c!rulecolor=, - \c!bodyfont=, - \c!distance=.5em] + \c!after=\blank] -\setupfillinrules - [\c!width=\v!broad, - \c!distance=1em, - \c!before=\blank, - \c!after=\blank, - \c!n=1, - \c!interlinespace=\v!small, - \c!separator=, - \c!style=\v!normal, - \c!color=] +\unexpanded\def\fillinline + {\dosingleempty\pack_fillinline} + +\ifdefined\endpar % experiment with \endpar + + \def\pack_fillinline[#1]% + {% \endpar % no, as it interferes with \definedescription cum suis + \begingroup + \setupcurrentfillinlines[#1]% + \directfillinlinesparameter\c!before + \begingroup + \advance\rightskip \directfillinlinesparameter\c!margin\relax + \parfillskip\zeropoint + \pushmacro\endpar + \def\endpar + {\popmacro\endpar + \ifhmode\unskip\hfill\fi + \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax + \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi + {\kern\directfillinlinesparameter\c!distance + \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax + \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}% + \endpar + \endgroup + \endpar + \directfillinlinesparameter\c!after + \endgroup}} % carryover ? + +\else + + \def\pack_fillinline[#1]% + {%\endgraf % no, as it interferes with \definedescription cum suis + \begingroup + \setupcurrentfillinlines[#1]% + \directfillinlinesparameter\c!before + \begingroup + \advance\rightskip \directfillinlinesparameter\c!margin\relax + \parfillskip\zeropoint + \def\par + {\let\par\endgraf + \ifhmode\unskip\hfill\fi + \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax + \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi + {\kern\directfillinlinesparameter\c!distance + \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax + \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}% + \endgraf + \endgroup + \endgraf + \directfillinlinesparameter\c!after + \endgroup}} % carryover ? -\setupfillinlines - [\c!width=3cm, - \c!margin=\@@ivwidth, - \c!distance=1em, - \c!before=\blank, - \c!after=\blank] +\fi \protect \endinput diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua index c580aaa62..1e4e0f59e 100644 --- a/tex/context/base/pack-obj.lua +++ b/tex/context/base/pack-obj.lua @@ -11,6 +11,8 @@ if not modules then modules = { } end modules ['pack-obj'] = { reusable components.</p> --ldx]]-- +local commands, context = commands, context + local texcount = tex.count local allocate = utilities.storage.allocate @@ -46,15 +48,30 @@ end function jobobjects.number(tag,default) local o = collected[tag] or tobesaved[tag] - context((o and o[1]) or default) + return o and o[1] or default end function jobobjects.page(tag,default) local o = collected[tag] or tobesaved[tag] - context((o and o[2]) or default) + return o and o[2] or default +end + +-- interface + +commands.saveobject = jobobjects.save +commands.setobject = jobobjects.set + +function commands.objectnumber(tag,default) + local o = collected[tag] or tobesaved[tag] + context(o and o[1] or default) +end + +function commands.objectpage(tag,default) + local o = collected[tag] or tobesaved[tag] + context(o and o[2] or default) end -function jobobjects.doifelse(tag) - commands.testcase(collected[tag] or tobesaved[tag]) +function commands.doifobjectreferencefoundelse(tag) + commands.doifelse(collected[tag] or tobesaved[tag]) end diff --git a/tex/context/base/pack-obj.mkiv b/tex/context/base/pack-obj.mkiv index 6c9848a01..356a0b7eb 100644 --- a/tex/context/base/pack-obj.mkiv +++ b/tex/context/base/pack-obj.mkiv @@ -105,29 +105,27 @@ % % \everyobject{\the\pdfbackendeveryxform} % -% \let\doresetobjects\relax -% -% \def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}} -% \def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}} +% \unexpanded\def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\pack_objects_set{#1}{#2}}} +% \unexpanded\def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\pack_objects_set{#1}{#2}}} % % \let\objectsetvbox\vbox %\def\objectsetvbox{\ruledvbox} % \let\objectgetvbox\vbox %\def\objectgetvbox{\ruledvbox} % \let\objectsethbox\hbox %\def\objectsethbox{\ruledhbox} % \let\objectgethbox\hbox %\def\objectgethbox{\ruledhbox} % -% \def\dosetobject#1#2% +% \unexpanded\def\pack_objects_set#1#2% % {\objectwd\wd\nextbox % \objectht\ht\nextbox % \objectdp\dp\nextbox % \ifdim\objectoff=\zeropoint\relax % \setbox\objectbox\box\nextbox % \else -% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\flushnextbox\hss}\vss}% +% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\box\nextbox\hss}\vss}% % \fi % \ctxlua{objects.register("#1::#2")}% % \endgroup} % -% \def\getobject#1#2% +% \unexpanded\def\getobject#1#2% % {\begingroup % \ctxlua{objects.restore("#1::#2")}% % \ifdim\objectoff=\zeropoint\relax \else @@ -140,7 +138,7 @@ % \box\objectbox % \endgroup} % -% \def\getpageobject#1#2% +% \unexpanded\def\getpageobject#1#2% % {\begingroup % \ctxlua{objects.restore("#1::#2")}% % \ifdim\objectoff=\zeropoint\relax @@ -155,25 +153,25 @@ % \box\objectbox % \endgroup} % -% \def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}} -% \def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}} -% \def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}} -% \def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}} -% \def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}} +% \unexpanded\def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}} +% \unexpanded\def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}} +% \unexpanded\def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}} +% \unexpanded\def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}} +% \unexpanded\def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}} % % \let\objectreferenced\relax % \let\driverreferenced\relax % -% \def\doregisterobjectreference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments} -% \def\dooverloadobjectreference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments} -% \def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments} -% \def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments} +% \unexpanded\def\pack_objects_register_reference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments} +% \unexpanded\def\pack_objects_overload_reference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments} +% \unexpanded\def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments} +% \unexpanded\def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments} % % \def\defaultobjectreference{0} % \def\defaultobjectpage {\realfolio} % -% \def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}} -% \def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}} +% \unexpanded\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}} +% \unexpanded\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}} % % \protect % @@ -219,26 +217,27 @@ %D housekeeping to the driver. The current approach permits %D us to keep the box characteristic too. -\newif\ifinobject +\installcorenamespace {objects} + +\newif\ifinobject % public (might become a conditional) -\def\objectplaceholder{NOT YET FLUSHED}% +\def\objectplaceholder{NOT YET FLUSHED} -\def\presetobject#1#2% \global added - {\ifcsname\??ob:#1::#2\endcsname\else - \global\@EA\let\csname\??ob:#1::#2\endcsname\objectplaceholder +\unexpanded\def\presetobject#1#2% \global added + {\ifcsname\??objects#1::#2\endcsname\else + \global\expandafter\let\csname\??objects#1::#2\endcsname\objectplaceholder \fi} -\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout - {% \initializepaper - \ifcsname\??ob:#2::#3\endcsname +\unexpanded\def\pack_objects_set#1#2#3% + {\ifcsname\??objects#2::#3\endcsname \expandafter\gobblefivearguments \else % tzt, overload internal referenced objects to save entries - \expandafter\dodosetobject + \expandafter\pack_objects_set_indeed \fi {#1}{#2}{#3}} -\def\resetobject#1#2% - {\letbeundefined{\??ob:#1::#2}} +\unexpanded\def\resetobject#1#2% + {\letbeundefined{\??objects#1::#2}} %D \macros %D {finalizeobjectbox} @@ -246,7 +245,7 @@ %D This one provides a hook for last minute object box processing %D we need this in \MKIV. -\ifx\finalizeobjectbox\undefined +\ifdefined\finalizeobjectbox \else \let\finalizeobjectbox\gobbleoneargument \fi @@ -257,47 +256,54 @@ \def\objectoffset{1cm} -\def\dodosetobject#1#2#3% +\unexpanded\def\pack_objects_set_indeed#1#2#3% {\bgroup - \globalpushmacro\crossreferenceobject \objectreferenced + \globalpushmacro\crossreferenceobject + \objectreferenced \inobjecttrue \dowithnextbox {\globalpopmacro\crossreferenceobject - \dododosetobject{#1}{#2}{#3}\egroup}} + \pack_objects_set_indeed_indeed{#1}{#2}{#3}% + \egroup}} % in luatex version < 66 we had a 1bp compensation (hardcoded in luatex) -\def\dododosetobject#1#2#3% +\let\pack_objects_handle\relax + +\unexpanded\def\pack_objects_set_indeed_indeed#1#2#3% {\begingroup \scratchdimen\objectoffset - \@EA\xdef\csname\??ob:#2::#3\endcsname - {\noexpand\dohandleobject{#2}{#3}% + \expandafter\xdef\csname\??objects#2::#3\endcsname + {\pack_objects_handle + {#2}% + {#3}% {\ifhbox\nextbox\hbox\else\vbox\fi}% - {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}% + {\number\wd\nextbox}% + {\number\ht\nextbox}% + {\number\dp\nextbox}% {\number\scratchdimen}}% \expanded % freeze the dimensions since \dostartobject may use \nextbox - {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}% + {\dostartobject{#2}{#3}{\the\wd\nextbox}{\the\ht\nextbox}{\the\dp\nextbox}}% \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint - \setbox\nextbox\vbox spread 2\scratchdimen + \setbox\nextbox\vbox \s!spread 2\scratchdimen {\forgetall \offinterlineskip - \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}% + \vss\hbox \s!spread 2\scratchdimen{\hss\box\nextbox\hss}\vss}% \fi \fi - \flushnextbox + \box\nextbox \dostopobject \endgroup} -\def\getobject#1#2% - {\ifcsname\??ob:#1::#2\endcsname +\unexpanded\def\getobject#1#2% + {\ifcsname\??objects#1::#2\endcsname \begingroup - \let\dohandleobject\dogetobject - \csname\??ob:#1::#2\expandafter\endcsname + \let\pack_objects_handle\pack_objects_get + \csname\??objects#1::#2\expandafter\endcsname \else {\infofont[object #1::#2]}% \fi} -\def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf - {% \initializepaper - \forgetall +\unexpanded\def\pack_objects_get#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf + {\forgetall % todo: if no attr then faster \setbox\scratchbox\vbox attr \viewerlayerattribute \attribute\viewerlayerattribute {\doinsertobject{#1}{#2}}% @@ -323,18 +329,18 @@ %D The results are reported in \type {\objectwidth}, \type %D {\objectheight} and \type {\objectdepth}. -\def\dogetobjectdimensions#1#2#3#4#5#6#7% +\unexpanded\def\pack_objects_get_dimensions#1#2#3#4#5#6#7% {\def\objectwidth {#4\s!sp}% \def\objectheight{#5\s!sp}% \def\objectdepth {#6\s!sp}% \def\objectmargin{#7\s!sp}} -\def\getobjectdimensions#1#2% - {\let\dohandleobject\dogetobjectdimensions +\unexpanded\def\getobjectdimensions#1#2% + {\let\pack_objects_handle\pack_objects_get_dimensions \let\objectwidth \!!zeropoint \let\objectheight\!!zeropoint \let\objectdepth \!!zeropoint - \csname\??ob:#1::#2\endcsname} + \csname\??objects#1::#2\endcsname} %D Apart from this kind of objects, that have typeset content, %D we can have low level driver specific objects. Both types @@ -352,35 +358,35 @@ %D These commands are to be called by the \type{\startobject}, %D \type{\stopobject} and \type{\insertobject} specials. -\def\objectreferenced{\global\chardef\crossreferenceobject\plusone} -\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount} +\unexpanded\def\objectreferenced{\global\chardef\crossreferenceobject\plusone} +\unexpanded\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount} \objectreferenced % no undefined test ! ! ! ! (pdftex fails on undefined objects) -\def\doregisterobjectreference#1#2#3{\normalexpanded{\noexpand\ctxlatelua{job.objects.save("#1::#2",#3,\noexpand\the\realpageno)}}} -\def\dooverloadobjectreference#1#2#3{\ctxlua{job.objects.set("#1::#2",#3,\the\realpageno)}} +\unexpanded\def\pack_objects_register_reference#1#2#3{\normalexpanded{\noexpand\ctxlatecommand{saveobject("#1::#2",#3,\noexpand\the\realpageno)}}} +\unexpanded\def\pack_objects_overload_reference#1#2#3{\ctxcommand{setobject("#1::#2",#3,\the\realpageno)}} -\def\dosetobjectreference +\unexpanded\def\dosetobjectreference {\ifcase\crossreferenceobject \objectreferenced - \expandafter\dooverloadobjectreference + \expandafter\pack_objects_overload_reference \else - \expandafter\doregisterobjectreference + \expandafter\pack_objects_register_reference \fi} -\def\dosetdriverreference +\unexpanded\def\dosetdriverreference {\driverreferenced\dosetobjectreference} \def\defaultobjectreference#1#2{0} % driver dependent \def\defaultobjectpage #1#2{\realfolio} -\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{job.objects.number("#1::#2","\defaultobjectreference{#1}{#2}")}}} -\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{job.objects.page("#1::#2","\defaultobjectpage{#1}{#2}")}}} +\unexpanded\def\dogetobjectreference #1#2#3{\xdef#3{\ctxcommand{objectnumber("#1::#2","\defaultobjectreference{#1}{#2}")}}} +\unexpanded\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxcommand{objectpage("#1::#2","\defaultobjectpage{#1}{#2}")}}} -\def\setobject {\driverreferenced\dosetobject1} -\def\settightobject{\driverreferenced\dosetobject0} +\unexpanded\def\setobject {\driverreferenced\pack_objects_set1} +\unexpanded\def\settightobject{\driverreferenced\pack_objects_set0} %D \macros %D {doifobjectfoundelse,doifobjectreferencefoundelse} @@ -393,13 +399,14 @@ %D \doifobjectreferencefoundelse{class}{object}{do then}{do else} %D \stoptyping -\def\doifobjectfoundelse#1#2% - {\ifcsname\??ob:#1::#2\endcsname +\unexpanded\def\doifobjectfoundelse#1#2% + {\ifcsname\??objects#1::#2\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\def\doifobjectreferencefoundelse#1#2{\ctxlua{job.objects.doifelse("#1::#2")}} +\unexpanded\def\doifobjectreferencefoundelse#1#2% + {\ctxcommand{doifobjectreferencefoundelse("#1::#2")}} \protect \endinput diff --git a/tex/context/base/pack-pos.mkiv b/tex/context/base/pack-pos.mkiv index fab73bc4a..ff8244f0a 100644 --- a/tex/context/base/pack-pos.mkiv +++ b/tex/context/base/pack-pos.mkiv @@ -23,114 +23,141 @@ % \position[ystep=relative](3,-1){test} % \position(10,10){test} % \stoppositioning} +% +% watch out: rather global -\newdimen\positioningxposition \newdimen\positioningyposition -\newdimen\positioningxdimension \newdimen\positioningydimension -\newdimen\positioningxoffset \newdimen\positioningyoffset +\installcorenamespace {positioning} -\newbox\positioningbox +\installcommandhandler \??positioning {positioning} \??positioning -\unexpanded\def\startpositioning - {\dosingleempty\dostartpositioning} +\setuppositioning + [\c!state=\v!start, + \c!unit=\s!cm, + \c!factor=\plusone, + \c!scale =\plusone, + \c!xfactor=\positioningparameter\c!factor, + \c!yfactor=\positioningparameter\c!factor, + \c!xscale=\positioningparameter\c!scale, + \c!yscale=\positioningparameter\c!scale, + \c!xstep=\v!absolute, + \c!ystep=\v!absolute, + \c!xoffset=\zeropoint, + \c!yoffset=\zeropoint] + +\newdimen\d_pack_positioning_x_position +\newdimen\d_pack_positioning_y_position +\newdimen\d_pack_positioning_x_dimension +\newdimen\d_pack_positioning_y_dimension +\newdimen\d_pack_positioning_x_offset +\newdimen\d_pack_positioning_y_offset -\def\dostartpositioning[#1]% +\newbox\b_pack_positioning + +\unexpanded\def\startpositioning {\bgroup - \getparameters[\??ps][#1]% - \positioningxposition \zeropoint \positioningyposition \zeropoint - \positioningxdimension\zeropoint \positioningydimension\zeropoint - \positioningxoffset \zeropoint \positioningyoffset \zeropoint - \hfuzz \paperwidth \vfuzz \paperheight - \setbox\positioningbox\hbox\bgroup + \dodoubleempty\pack_positioning_start} + +\def\pack_positioning_start[#1][#2]% + {\ifsecondargument + \edef\currentpositioning{#1}% + \setupcurrentpositioning[#2]% + \else\iffirstargument + \doifassignmentelse{#1} + {\let\currentpositioning\empty + \setupcurrentpositioning[#1]}% + {\edef\currentpositioning{#1}}% + \else + \let\currentpositioning\empty + \fi\fi + \d_pack_positioning_x_position \zeropoint + \d_pack_positioning_y_position \zeropoint + \d_pack_positioning_x_dimension\zeropoint + \d_pack_positioning_y_dimension\zeropoint + \d_pack_positioning_x_offset \zeropoint + \d_pack_positioning_y_offset \zeropoint + \hfuzz\paperwidth + \vfuzz\paperheight + \setbox\b_pack_positioning\hbox\bgroup \ignorespaces} \unexpanded\def\stoppositioning {\removeunwantedspaces - \doifnot\@@psoffset\v!yes - {\global\positioningxoffset\zeropoint - \global\positioningyoffset\zeropoint}% - \global\advance\positioningxdimension \positioningxoffset - \global\advance\positioningydimension \positioningyoffset + \doifnot{\positioningparameter\c!offset}\v!yes + {\global\d_pack_positioning_x_offset\zeropoint + \global\d_pack_positioning_y_offset\zeropoint}% + \global\advance\d_pack_positioning_x_dimension\d_pack_positioning_x_offset + \global\advance\d_pack_positioning_y_dimension\d_pack_positioning_y_offset \egroup - \vbox to \positioningydimension - {\vskip\positioningyoffset - \hbox to \positioningxdimension - {\hskip\positioningxoffset - \box\positioningbox + \vbox to \d_pack_positioning_y_dimension + {\vskip\d_pack_positioning_y_offset + \hbox to \d_pack_positioning_x_dimension + {\hskip\d_pack_positioning_x_offset + \box\b_pack_positioning \hfill} \vfill}% \egroup} -\def\resetpositioning - {\let\@@psstate \v!start - \let\@@psunit \s!cm - \let\@@psfactor \plusone - \let\@@psscale \plusone - \def\@@psxfactor{\@@psfactor}% - \def\@@psyfactor{\@@psfactor}% - \def\@@psxscale {\@@psscale}% - \def\@@psyscale {\@@psscale}% - \let\@@psxstep \v!absolute - \let\@@psystep \v!absolute - \let\@@psxoffset \zeropoint - \let\@@psyoffset \zeropoint} - -\resetpositioning - -\unexpanded\def\setuppositioning - {\resetpositioning - \dodoubleargument\getparameters[\??ps]} - -\def\calculateposition#1#2#3#4#5#6#7#8#9% - {\setdimensionwithunit\scratchdimen{#1}\@@psunit - \scratchdimen#8\scratchdimen - \scratchdimen#9\scratchdimen - \advance\scratchdimen #4\relax +\unexpanded\def\pack_positioning_calculate#1#2#3#4#5#6#7#8#9% + {\setdimensionwithunit\scratchdimen{#1}{\positioningparameter\c!unit}% + \scratchdimen\positioningparameter#8\scratchdimen + \scratchdimen\positioningparameter#9\scratchdimen + \advance\scratchdimen\positioningparameter#4\relax % == \scratchdimen\dimexpr#8\dimexpr#9\scratchdimen\relax+#4\relax - \doif{#2}\v!relative + \doif{\positioningparameter#2}\v!relative {\advance\scratchdimen#3% - \let#4\zeropoint}% + \letpositioningparameter#4\zeropoint}% #3\scratchdimen - \doifnot\@@psstate\v!overlay - {\scratchdimen\dimexpr#5+#3\relax + \doifnot{\positioningparameter\c!state}\v!overlay + {\scratchdimen\dimexpr#5\nextbox+#3\relax \ifdim #3<-#7\relax \global#7-#3\relax \fi \ifdim\scratchdimen> #6\relax \global#6\scratchdimen\fi}} -\def\position - {\dosingleempty\doposition} - -\def\doposition[#1]#2(#3,#4)% - {\removeunwantedspaces - \dowithnextbox{\dodoposition{#1}{#2}{#3}{#4}}\hbox} - -\def\dodoposition#1#2#3#4% +\unexpanded\def\position {\bgroup - \dontcomplain - \getparameters[\??ps][#1]% - \calculateposition{#3}\@@psxstep\positioningxposition\@@psxoffset\nextboxwd \positioningxdimension\positioningxoffset\@@psxscale\@@psxfactor - \calculateposition{#4}\@@psystep\positioningyposition\@@psyoffset\nextboxhtdp\positioningydimension\positioningyoffset\@@psyscale\@@psyfactor + \dosingleempty\pack_positioning_position} + +\def\pack_positioning_position[#1]#2(#3,#4)% + {\iffirstargument + \setupcurrentpositioning[#1]% + \fi + \removeunwantedspaces + \dowithnextbox{\pack_positioning_position_indeed{#3}{#4}}\hbox} + +\def\pack_positioning_position_indeed#1#2% + {\dontcomplain + \pack_positioning_calculate + {#1}% + \c!xstep + \d_pack_positioning_x_position + \c!xoffset + \wd + \d_pack_positioning_x_dimension + \d_pack_positioning_x_offset + \c!xscale + \c!xfactor + \pack_positioning_calculate + {#2}% + \c!ystep + \d_pack_positioning_y_position + \c!yoffset + \htdp + \d_pack_positioning_y_dimension + \d_pack_positioning_y_offset + \c!yscale + \c!yfactor \vbox to \zeropoint - {\vskip\positioningyposition + {\vskip\d_pack_positioning_y_position \hbox to \zeropoint - {\hskip\positioningxposition - \flushnextbox + {\hskip\d_pack_positioning_x_position + \box\nextbox \hss} \vss}% \normalexpanded {\egroup - \positioningxposition\the\positioningxposition - \positioningyposition\the\positioningyposition - \def\noexpand\@@psxoffset{\the\dimexpr\@@psxoffset}% - \def\noexpand\@@psyoffset{\the\dimexpr\@@psyoffset}}% + \d_pack_positioning_x_position\the\d_pack_positioning_x_position + \d_pack_positioning_y_position\the\d_pack_positioning_y_position + \setexpandedpositioningparameter\c!xoffset{\the\dimexpr\positioningparameter\c!xoffset}% + \setexpandedpositioningparameter\c!yoffset{\the\dimexpr\positioningparameter\c!yoffset}}% \ignorespaces} -\setuppositioning - [\c!unit=\s!cm, - \c!factor=\plusone, - \c!scale=\plusone, - \c!xstep=\v!absolute, - \c!ystep=\v!absolute, - \c!offset=\v!yes, - \c!xoffset=\zeropoint, - \c!yoffset=\zeropoint] - \protect \endinput diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv index 480997919..9eb44b747 100644 --- a/tex/context/base/pack-rul.mkiv +++ b/tex/context/base/pack-rul.mkiv @@ -13,31 +13,27 @@ \writestatus{loading}{ConTeXt Packaging Macros / Ruled Content} -%D The code here is expanded lots of time as framed is used in -%D many places. This is why the code here is (and gets) optimized -%D as much as possible. Also, by avoiding packaging and expansion -%D we also keep tracing reasonable. For instance, multiple stacked -%D backgrounds can slow down a run if not optimized this way. - -% eventually this will use the commandhandler code (same trick as -% with itemize) +%D The code here is expanded lots of time as framed is used in many places. This is +%D why the code here is (and gets) optimized as much as possible. Also, by avoiding +%D packaging and expansion we also keep tracing reasonable. For instance, multiple +%D stacked backgrounds can slow down a run if not optimized this way. \registerctxluafile{pack-rul}{1.001} \unprotect +\definesystemvariable {ol} % OmLijnd -> check scrn-fld too + %D \macros %D {linewidth, setuplinewidth} %D -%D This module deals with rules (lines) in several ways. First -%D we introduce two macros that can be used to set some common -%D characteristics. +%D This module deals with rules (lines) in several ways. First we introduce two +%D macros that can be used to set some common characteristics. %D %D \showsetup{setuplinewidth} %D -%D The linewidth is available in \type{\linewidth}. The -%D preset value of .4pt equals the default hard coded \TEX\ -%D rule width. +%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals +%D the default hard coded \TEX\ rule width. \newdimen\linewidth @@ -54,8 +50,16 @@ %D %D \showsetup{setupscreens} -\unexpanded\def\setupscreens - {\dodoubleargument\getparameters[\??rs]} +\installcorenamespace{screens} + +\installsetuponlycommandhandler \??screens {screens} + +\appendtoks + \edef\defaultbackgroundscreen{\directscreensparameter\c!screen} +\to \everysetupscreens + +\setupscreens + [\c!screen=.90] % was .95 but that's hardly visible %D The parameter handler: @@ -65,41 +69,26 @@ \installcorenamespace{framedleft} \installcorenamespace{framedright} -\let\currentframed\s!unknown % brrr must have a value - -% \def\framedparameter #1{\csname\doframedparameter\currentframed{#1}\endcsname} -% \def\framedparameterhash#1{\doframedparameterhash \currentframed#1} - -\def\framedparameter #1{\csname\ifcsname\currentframed#1\endcsname\currentframed#1\else\expandafter\doframedparentparameter\csname\currentframed\s!parent\endcsname{#1}\fi\endcsname} -\def\framedparameterhash#1{\ifcsname\currentframed#1\endcsname\currentframed\else\expandafter\doframedparentparameterhash\csname\currentframed\s!parent\endcsname#1\fi} +\installcorenamespace{regularframed} +\installcorenamespace{simplifiedframed} -\def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname{#2}\fi} -\def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi} +\installcommandhandler \??framed {framed} \??framed -\def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1{#2}\fi} -\def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi} +\let\pack_framed_framedparameter \framedparameter +\let\pack_framed_framedparameterhash\framedparameterhash +\let\pack_framed_setupcurrentframed \setupcurrentframed -\def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1{#2}\fi} -\def\doframedrootparameter #1{\ifcsname\??framed#1\endcsname\??framed#1\else\s!empty\fi} +\def\pack_framed_initialize + {\let\framedparameter \pack_framed_framedparameter + \let\framedparameterhash\pack_framed_framedparameterhash + \let\setupcurrentframed \pack_framed_setupcurrentframed + \inframedtrue} -\def\useframedstyleandcolor#1#2% style color - {\edef\currentstyleparameter{\framedparameter#1}% - \edef\currentcolorparameter{\framedparameter#2}% - \ifx\currentstyleparameter\empty\else\dousestyleparameter\currentstyleparameter\fi - \ifx\currentcolorparameter\empty\else\dousecolorparameter\currentcolorparameter\fi} +%D A helper: \def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax} -% \unexpanded\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]} - -\let\normalframedparameter \framedparameter -\let\normalframedparameterhash\framedparameterhash - -\def\pack_framed_initialize#1% will be inlined - {\inframedtrue - \edef\currentframed{#1}% - \let\framedparameter \normalframedparameter - \let\framedparameterhash\normalframedparameterhash} +%D Inheritance: \def\installinheritedframed#1% {\normalexpanded{\doinstallinheritedframed @@ -109,19 +98,21 @@ \expandafter\noexpand\csname do#1parameter\endcsname \expandafter\noexpand\csname do#1parentparameter\endcsname \expandafter\noexpand\csname do#1rootparameter\endcsname + \expandafter\noexpand\csname setupcurrent#1\endcsname \expandafter\noexpand\csname inherited#1framed\endcsname \noexpand\??framed}} % if needed we can have a variant -\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8% - {\def#5##1##2{\ifx##1\relax#6{##2}\else#4##1{##2}\fi}% - \def#6##1{\ifcsname#8##1\endcsname#8##1\else\s!empty\fi}% - \unexpanded\def#7% +\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#9:##1\endcsname#9:##1\else\s!empty\fi}% root + \unexpanded\def#8% {\bgroup \bgroup \inframedtrue - \let\currentframed #1% not used (more for tracing) + \let\currentframed #1% \let\framedparameter #2% \let\framedparameterhash#3% + \let\setupcurrentframed #7% \pack_framed_process_indeed}} \unexpanded\def\installframedcommandhandler#1#2#3% @@ -138,12 +129,11 @@ % for regular framed -\getparameters - [\??framed] +\setupframed [\c!width=\v!fit, \c!height=\v!broad, %\c!lines=, - \c!offset=0.25ex, % \defaultframeoffset + \c!offset=.25ex, % \defaultframeoffset \c!empty=\v!no, \c!frame=\v!on, %\c!topframe=, @@ -158,11 +148,12 @@ %\c!foregroundstyle=, %\c!background=, %\c!backgroundscreen=, + \c!backgroundscreen=\defaultbackgroundscreen, %\c!backgroundcolor=, \c!backgroundoffset=\zeropoint, %\c!framecolor=, \c!frameoffset=\zeropoint, - \c!backgroundcorner=\framedparameter\c!corner, + \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here \c!backgroundradius=\framedparameter\c!radius, \c!backgrounddepth=\framedparameter\c!depth, \c!framecorner=\framedparameter\c!corner, @@ -184,21 +175,21 @@ \c!toffset=\zeropoint, \c!boffset=\zeropoint] -% for backgrounds +%D For backgrounds and such: -\getparameters - [\??od] % for fast version +\defineframed + [\??simplifiedframed] [\c!frame=\v!off, \c!depth=\zeropoint, \c!offset=\v!overlay, - %\c!component=, - %\c!region=, + \c!component=, + \c!region=, \c!radius=.5\bodyfontsize, \c!rulethickness=\linewidth, \c!corner=\v!rectangular, \c!backgroundoffset=\zeropoint, \c!frameoffset=\zeropoint, - \c!backgroundcorner=\framedparameter\c!corner, + \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here \c!backgroundradius=\framedparameter\c!radius, \c!backgrounddepth=\framedparameter\c!depth, \c!framecorner=\framedparameter\c!corner, @@ -210,13 +201,19 @@ \c!toffset=\zeropoint, \c!boffset=\zeropoint] -%D We will communicate through module specific variables, current -%D framed parameters and some reserved dimension registers. +\unexpanded\def\definesimplifiedframed[#1]% no settings + {\defineframed[#1][\??simplifiedframed]% + \expandafter\let\csname#1\endcsname\undefined} + +\expandafter\let\csname\??simplifiedframed\endcsname\undefined + +%D We will communicate through module specific variables, current framed +%D parameters and some reserved dimension registers. \newdimen\d_framed_target_wd \newdimen\d_framed_target_ht \newdimen\d_framed_target_dp -\newdimen\d_framed_linewidth +\newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end \let\p_framed_frame \empty % \framedparameter\c!frame \let\p_framed_backgroundoffset\empty @@ -255,9 +252,9 @@ \def\pack_framed_filled_box_normal {\vrule - \!!width \d_framed_target_wd - \!!height\d_framed_target_ht - \!!depth \d_framed_target_dp + \s!width \d_framed_target_wd + \s!height\d_framed_target_ht + \s!depth \d_framed_target_dp \relax} \def\pack_framed_filled_box_radius @@ -269,16 +266,10 @@ \fi} \def\pack_framed_filled_box_round - {\normalexpanded{\doovalbox - {\the\d_framed_target_wd}% - {\the\d_framed_target_ht}% - {\the\d_framed_target_dp}% - {\the\dimexpr\d_framed_linewidth\relax}% - {\the\dimexpr\p_framed_backgroundradius\relax}% - {0}% - {1}% - {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}% - }} + {\back_ovalbox + \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp + \d_framed_linewidth \p_framed_backgroundradius + \zerocount \plusone {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}} \def\pack_framed_stroked_box {\edef\p_framed_framecorner{\framedparameter\c!framecorner}% @@ -292,25 +283,17 @@ {\edef\p_framed_frameradius{\framedparameter\c!frameradius}% \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize \pack_framed_stroked_box_normal - \else - \ifx\p_framed_frame\v!on - \pack_framed_stroked_box_round - \fi - \fi} + \else\ifx\p_framed_frame\v!on + \pack_framed_stroked_box_round + \fi\fi} % \pack_framed_stroked_box_normal % later \def\pack_framed_stroked_box_round - {\normalexpanded{\doovalbox - {\the\d_framed_target_wd}% - {\the\d_framed_target_ht}% - {\the\d_framed_target_dp}% - {\the\dimexpr\d_framed_linewidth\relax}% - {\the\dimexpr\p_framed_frameradius\relax}% - {1}% - {0}% - {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}% - }} + {\back_ovalbox + \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp + \d_framed_linewidth \p_framed_frameradius + \plusone \zerocount {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}} % a lot of weird corners % @@ -370,8 +353,8 @@ \def\pack_framed_background_box_gray_indeed % can be more direct but who cares, just compatibility {\colored[s=\p_framed_backgroundscreen]{\pack_framed_filled_box}} -%D It won't be a surprise that we not only provide gray boxes, -%D but also colored ones. Here it is: +%D It won't be a surprise that we not only provide gray boxes, but also colored +%D ones. Here it is: \def\pack_framed_background_box_color {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}% @@ -387,10 +370,9 @@ %D overlaywidth, overlayheight, overlaydepth, %D overlaycolor, overlaylinecolor, overlaylinewidth} %D -%D Before we define the macro that actually takes card of the -%D backgrounds, we introduce overlays. An overlay is something -%D that contrary to its name lays {\em under} the text. An -%D example of an overlay definition is: +%D Before we define the macro that actually takes card of the backgrounds, we +%D introduce overlays. An overlay is something that contrary to its name lays {\em +%D under} the text. An example of an overlay definition is: %D %D \startbuffer[tmp-1] %D \defineoverlay @@ -420,17 +402,16 @@ %D %D \showsetup{defineoverlay} %D -%D This macro's definition is a bit obscure, due the many -%D non||used arguments and the two step call that enable the -%D setting of the width, height and depth variables. -%D Multiple backgrounds are possible and are specified as: +%D This macro's definition is a bit obscure, due the many non||used arguments and +%D the two step call that enable the setting of the width, height and depth +%D variables. Multiple backgrounds are possible and are specified as: %D %D \starttyping %D \framed[background={one,two,three}]{Three backgrounds!} %D \stoptyping %D -%D Most drawing packages only know width and height. Therefore -%D the dimensions have a slightly different meaning here: +%D Most drawing packages only know width and height. Therefore the dimensions have a +%D slightly different meaning here: %D %D \startitemize[packed] %D \item \type{\overlaywidth }: width of the overlay @@ -452,9 +433,8 @@ \newtoks\everyoverlay -%D An example of an initialization is the following (overlays -%D can contain text and be executed under an regime where -%D interlineskip is off). +%D An example of an initialization is the following (overlays can contain text +%D and be executed under an regime where interlineskip is off). \installcorenamespace{overlay} \installcorenamespace{overlaybuiltin} @@ -515,8 +495,8 @@ \expandafter\secondoftwoarguments \fi} -%D The content of the box will be (temporary) saved in a box. We -%D also have an extra box for backgrounds. +%D The content of the box will be (temporary) saved in a box. We also have an +%D extra box for backgrounds. \newbox\b_framed_normal \newbox\b_framed_extra @@ -572,8 +552,8 @@ \expandafter\pack_framed_process_backgrounds \fi#2} -% beware, a backgroundbox can be empty which is another reason -% why we set the width to zero instead of back-skipping +%D Beware, a backgroundbox can be empty which is another reason why we set the +%D width to zero instead of back-skipping. \newdimen\framedbackgroundwidth \newdimen\framedbackgroundheight @@ -612,8 +592,7 @@ \egroup}} \def\pack_framed_overlay_initialize_indeed - {%\writestatus{!!!!}{<<<<<}% - \edef\overlaywidth {\the\d_framed_target_wd\space}% + {\edef\overlaywidth {\the\d_framed_target_wd\space}% \edef\overlayheight {\the\dimexpr\d_framed_target_ht+\d_framed_target_dp\relax\space}% \edef\overlaydepth {\the\d_framed_target_dp\space}% \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ? @@ -624,8 +603,8 @@ \edef\overlayoffset {\the\framedbackgroundoffset\space}% \backgroundoffset % we steal this one \let\pack_framed_overlay_initialize\relax} -%D One can explictly insert the foreground box. For that -%D purpose we introduce the overlay \type {foreground}. +%D One can explictly insert the foreground box. For that purpose we introduce the +%D overlay \type {foreground}. %D %D We predefine two already familiar backgrounds: @@ -633,14 +612,13 @@ \letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color \letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox] -%D We can specify overlays as a comma separated list of -%D overlays, a sometimes handy feature. - -%D Besides backgrounds (overlays) we also need some macros to -%D draw outlines (ruled borders). Again we have to deal with -%D square and round corners. The first category can be handled -%D by \TEX\ itself, the latter one depends on the driver. This -%D macro also support a negative offset. +%D We can specify overlays as a comma separated list of overlays, a sometimes +%D handy feature. +%D +%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled +%D borders). Again we have to deal with square and round corners. The first category +%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro +%D also support a negative offset. \def\pack_framed_add_outline {\setbox\b_framed_normal\hbox % rules on top of box @@ -687,10 +665,10 @@ \dp\scratchbox\d_framed_target_dp \box\scratchbox} -\def\pack_framed_t_rule{\hrule\!!height\d_framed_linewidth\kern-\d_framed_linewidth} -\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\!!height\d_framed_linewidth} -\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\!!width\d_framed_linewidth} -\def\pack_framed_l_rule{\vrule\!!width\d_framed_linewidth\kern-\d_framed_linewidth} +\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} +\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} +\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} +\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth} \letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule \letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule @@ -710,10 +688,10 @@ % no overlapping rules -\def\pack_framed_t_rules{\hbox{\kern\d_framed_linewidth\vrule\!!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\!!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} -\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hbox{\kern\d_framed_linewidth\vrule\!!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\!!height\d_framed_linewidth}} -\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\!!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\!!depth-\d_framed_linewidth\!!width\d_framed_linewidth} -\def\pack_framed_l_rules{\vrule\!!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\!!depth-\d_framed_linewidth\!!width\d_framed_linewidth\kern-\d_framed_linewidth} +\def\pack_framed_t_rules{\hbox{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} +\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hbox{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} +\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} +\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} \letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules \letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules @@ -744,11 +722,10 @@ % frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on] % {} -%D The next few macros are probably the most misused ones in -%D \CONTEXT. They deal with putting rules around boxes, provide -%D backgrounds, offer alignment features, and some more. We -%D start with defining some booleans. These give an impression -%D of what we are going to take into account. +%D The next few macros are probably the most misused ones in \CONTEXT. They deal +%D with putting rules around boxes, provide backgrounds, offer alignment features, +%D and some more. We start with defining some booleans. These give an impression of +%D what we are going to take into account. % todo : \c_framed_hasoffset % faster : \let\c_framed_hasoffset\falseconditional @@ -766,67 +743,72 @@ %D \macros %D {framed, setupframed} %D -%D Ruled boxes are typeset using \type{\framed}. This command -%D is quite versatile and, although some users will probably -%D seldom use it, one cannot overlook its features. +%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile +%D and, although some users will probably seldom use it, one cannot overlook its +%D features. %D -%D \showsetup{setupframed} -%D \showsetup{framed} +%D \showsetup{setupframed} +%D \showsetup{framed} %D -%D This general macro is a special version of an even more -%D general case, that can easily be linked into other macros -%D that need some kind of framing. The local version is called -%D with an extra parameter: the variable identifier. The reason -%D for passing this identifier between brackets lays in the -%D mere fact that this way we can use the optional argument -%D grabbers. +%D This general macro is a special version of an even more general case, that can +%D easily be linked into other macros that need some kind of framing. The local +%D version is called with an extra parameter: the variable identifier. The reason +%D for passing this identifier between brackets lays in the mere fact that this way +%D we can use the optional argument grabbers. \def\defaultframeoffset{.25ex} -\def\presetlocalframed [#1]{\letvalue {#1\s!parent}\??framed} -\def\inheritlocalframed[#1]#2[#3]{\setevalue{#1\s!parent}{#3}} +\installcorenamespace{regularframedlevel} + +\unexpanded\def\installregularframed#1% + {\defineframed[#1]} + +\unexpanded\def\presetlocalframed[#1]% + {\defineframed[#1]} -\presetlocalframed[\??ol] +% \presetlocalframed[\??framed] -\newcount\framednesting +\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 {\bgroup - \advance\framednesting\plusone - \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol - \dodoubleempty\pack_framed_process[\??ol:\the\framednesting]} + \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 - \advance\framednesting\plusone - \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol + \advance\c_pack_framed_nesting\plusone + \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed \iffirstargument\secondargumenttrue\fi % dirty trick - \pack_framed_process[\??ol:\the\framednesting][#1]% + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \pack_framed_process_framed[#1]% can be inlined \bgroup} \let\stopframed\egroup -\unexpanded\def\setupframed - {\dodoubleempty\dosetupframed} - -\unexpanded\def\normalframedwithsettings +\unexpanded\def\normalframedwithsettings[#1]% {\bgroup - \advance\framednesting\plusone - \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol - \pack_framed_process[\??ol:\the\framednesting]} - -% we can consider setting the parent of the regular framed to -% something else in the otr so that we isolate it there - -\def\dosetupframed[#1][#2]% - {\ifsecondargument - \getparameters[\??ol#1][#2]% - \else - \getparameters[\??ol][#1]% - \fi} + \advance\c_pack_framed_nesting\plusone + \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \bgroup + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \setupcurrentframed[#1]% + \pack_framed_process_indeed} %D \startbuffer %D \setupframed [framecolor=yellow] \framed{A} @@ -846,13 +828,11 @@ %D \macros %D {ifinframed} %D -%D The normal case first presets all parameters and next starts -%D looking for the user supplied ones. The first step is -%D omitted in the local case, because these are preset at -%D declaration time and keep their values unless explictly -%D changed. By presetting the variables everytime the normal -%D command is called, we can use this command nested, without -%D the unwanted side effect of inheritance. The boolean is +%D The normal case first presets all parameters and next starts looking for the user +%D supplied ones. The first step is omitted in the local case, because these are +%D preset at declaration time and keep their values unless explictly changed. By +%D presetting the variables everytime the normal command is called, we can use this +%D command nested, without the unwanted side effect of inheritance. The boolean is %D used to speed up the color stack. \newif\ifinframed @@ -862,7 +842,8 @@ \unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4 {\bgroup - \pack_framed_initialize{#1}% + \edef\currentframed{#1}% + \pack_framed_initialize \setbox\b_framed_normal\hbox{#4}% \edef\p_framed_region{\framedparameter\c!region}% \ifx\p_framed_region\v!yes % maybe later named @@ -880,8 +861,7 @@ \d_framed_linewidth\p_framed_rulethickness\relax \fi \pack_framed_add_outline % real or invisible frame - \fi \fi - \fi + \fi\fi \ifx\p_framed_background\empty \else \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% \d_framed_backgroundoffset @@ -897,12 +877,13 @@ \box\b_framed_normal \egroup} -%D The next macro uses a box and takes its natural width and -%D height so these can better be correct. +%D The next macro uses a box and takes its natural width and height so these +%D can better be correct. -\def\localbackgroundframed#1#2#3% namespace component box +\unexpanded\def\localbackgroundframed#1#2#3% namespace component box {\bgroup - \pack_framed_initialize{#1}% + \edef\currentframed{#1}% + \pack_framed_initialize \setbox\b_framed_normal\box#3% \edef\p_framed_region{\framedparameter\c!region}% \ifx\p_framed_region\v!yes % maybe later named @@ -917,7 +898,7 @@ \d_framed_linewidth\p_framed_rulethickness\relax \fi \pack_framed_add_outline % real or invisible frame - \fi \fi + \fi\fi \ifx\p_framed_background\empty \else \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% \d_framed_backgroundoffset @@ -955,35 +936,36 @@ \unexpanded\def\localframed {\bgroup - \dodoubleempty\pack_framed_process} + \dodoubleempty\pack_framed_local} -\unexpanded\def\pack_framed_process[#1][#2]% assumes a \dodoubleempty (slows down), also should have leading \bgroup +\unexpanded\def\pack_framed_local[#1][#2]% {\bgroup - \pack_framed_initialize{#1}% + \edef\currentframed{#1}% + \pack_framed_initialize \ifsecondargument % faster - \getparameters[\currentframed][#2]% here ! + \setupcurrentframed[#2]% here ! \fi \pack_framed_process_indeed} \unexpanded\def\directlocalframed[#1]% no optional {\bgroup \bgroup - \pack_framed_initialize{#1}% + \edef\currentframed{#1}% + \pack_framed_initialize \pack_framed_process_indeed} \unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between) {\bgroup \bgroup - \pack_framed_initialize{#1}% - \getparameters[\currentframed][#2]% here ! + \edef\currentframed{#1}% + \pack_framed_initialize + \setupcurrentframed[#2]% here ! \pack_framed_process_indeed} % done \def\c!fr!analyze{fr:analyze} % private option -% we can make macros for the offset, width, and height branches or do an \csname - \unexpanded\def\pack_framed_process_indeed {\d_framed_frameoffset\framedparameter\c!frameoffset \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% @@ -1038,78 +1020,28 @@ \settrue\c_framed_has_format \dosetraggedcommand\localformat % not that fast \fi - \ifx\localoffset\v!none - \setfalse\c_framed_has_offset - \setfalse\c_framed_has_strut - \setfalse\c_framed_is_overlaid - \d_framed_local_offset\d_framed_linewidth - \else\ifx\localoffset\v!overlay - % \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first - \setfalse\c_framed_has_offset - \setfalse\c_framed_has_strut - \settrue \c_framed_is_overlaid - \d_framed_local_offset\zeropoint -% \else\ifx\localoffset\v!strut -% \setfalse\c_framed_has_offset -% \settrue \c_framed_has_strut -% \settrue \c_framed_is_overlaid -% \d_framed_local_offset\zeropoint - \else - \settrue \c_framed_has_offset - \settrue \c_framed_has_strut - \setfalse\c_framed_is_overlaid - \ifx\localoffset\v!default % new per 2-6-2000 - \let\localoffset\defaultframeoffset - \letframedparameter\c!offset\defaultframeoffset % brrr + \csname\??framedoffsetalternative + \ifcsname\??framedoffsetalternative\localoffset\endcsname + \localoffset \else - \let\defaultframeoffset\localoffset + \s!unknown \fi - \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax - \fi\fi % \fi - \d_framed_height\zeropoint - \d_framed_width \zeropoint - \ifx\localwidth\empty % fallback to fit - \ifconditional\c_framed_has_format - \settrue\c_framed_has_width - \d_framed_width\hsize + \endcsname + \csname\??framedwidthalternative + \ifcsname\??framedwidthalternative\localwidth\endcsname + \localwidth \else - \setfalse\c_framed_has_width + \s!unknown \fi - \else\ifx\localwidth\v!fit - \ifconditional\c_framed_has_format - \settrue\c_framed_has_width - \d_framed_width\hsize + \endcsname + \csname\??framedheightalternative + \ifcsname\??framedheightalternative\localheight\endcsname + \localheight \else - \setfalse\c_framed_has_width + \s!unknown \fi - \else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox - \ifconditional\c_framed_has_format - \settrue\c_framed_has_width - \d_framed_width\hsize - \else - \setfalse\c_framed_has_width - \fi - \else\ifx\localwidth\v!broad - \settrue\c_framed_has_width - \d_framed_width\hsize - \else\ifx\localwidth\v!local - \settrue\c_framed_has_width - \setlocalhsize - \d_framed_width\localhsize - \else - \settrue\c_framed_has_width - \d_framed_width\localwidth - \fi\fi\fi\fi\fi - \ifx\localheight\empty % fallback to fit - \setfalse\c_framed_has_height - \else\ifx\localheight\v!fit - \setfalse\c_framed_has_height - \else\ifx\localheight\v!broad - \setfalse\c_framed_has_height - \else - \settrue\c_framed_has_height - \d_framed_height\localheight - \fi\fi\fi + \endcsname + % the next check could move to heightalternative \ifconditional\c_framed_has_height % obey user set height, also downward compatible \else @@ -1132,15 +1064,14 @@ % i.e. disable (colsetbackgroundproblemintechniek) \advance\d_framed_width -2\d_framed_local_offset \advance\d_framed_height -2\d_framed_local_offset - \ifx\localstrut\v!no - \setfalse\c_framed_has_strut - \else\ifx\localstrut\v!global - \setstrut - \else\ifx\localstrut\v!local - \setfontstrut - \else - \setstrut - \fi\fi\fi + \csname\??framedstrutalternative + \ifcsname\??framedstrutalternative\localstrut\endcsname + \localstrut + \else + \s!unknown + \fi + \endcsname + % the next check could move to strutalternative \ifconditional\c_framed_has_strut \let\localbegstrut\begstrut \let\localendstrut\endstrut @@ -1219,6 +1150,136 @@ \afterassignment\pack_framed_restart \setbox\b_framed_normal\next} +% alternatives for width, height, strut and offset + +\installcorenamespace{framedwidthalternative} +\installcorenamespace{framedheightalternative} +\installcorenamespace{framedstrutalternative} +\installcorenamespace{framedoffsetalternative} + +% widths + +\setvalue{\??framedwidthalternative\empty}% + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!fit}% + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox + {\ifconditional\c_framed_has_format + \settrue\c_framed_has_width + \d_framed_width\hsize + \else + \setfalse\c_framed_has_width + \d_framed_width\zeropoint + \fi} + +\setvalue{\??framedwidthalternative\v!broad}% + {\settrue\c_framed_has_width + \d_framed_width\hsize} + +\setvalue{\??framedwidthalternative\v!max}% idem broad + {\settrue\c_framed_has_width + \d_framed_width\hsize} + +\setvalue{\??framedwidthalternative\v!local}% + {\settrue\c_framed_has_width + \setlocalhsize + \d_framed_width\localhsize} + +\setvalue{\??framedwidthalternative\s!unknown}% + {\settrue\c_framed_has_width + \d_framed_width\localwidth} + +% heights + +\setvalue{\??framedheightalternative\empty}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!fit}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!broad}% + {\setfalse\c_framed_has_height + \d_framed_height\zeropoint} + +\setvalue{\??framedheightalternative\v!max}% + {\settrue\c_framed_has_height + \d_framed_height\vsize} + +\setvalue{\??framedheightalternative\s!unknown}% + {\settrue\c_framed_has_height + \d_framed_height\localheight} + +% struts + +\setvalue{\??framedstrutalternative\v!no}% + {\setfalse\c_framed_has_strut} + +\setvalue{\??framedstrutalternative\v!global}% + {\setstrut} + +\setvalue{\??framedstrutalternative\v!local}% + {\setfontstrut} + +\setvalue{\??framedstrutalternative\v!yes}% + {\setstrut} + +\setvalue{\??framedstrutalternative\s!unknown}% + {\setstrut} + +% offsets + +\setvalue{\??framedoffsetalternative\v!none}% + {\setfalse\c_framed_has_offset + \setfalse\c_framed_has_strut + \setfalse\c_framed_is_overlaid + \d_framed_local_offset\d_framed_linewidth} + +\setvalue{\??framedoffsetalternative\v!overlay}% + {% \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first + \setfalse\c_framed_has_offset + \setfalse\c_framed_has_strut + \settrue \c_framed_is_overlaid + \d_framed_local_offset\zeropoint} + +% \setvalue{\??framedoffsetalternative\v!strut}% +% {\setfalse\c_framed_has_offset +% \settrue \c_framed_has_strut +% \settrue \c_framed_is_overlaid +% \d_framed_local_offset\zeropoint} + +\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000 + {\settrue \c_framed_has_offset + \settrue \c_framed_has_strut + \setfalse\c_framed_is_overlaid + \let\localoffset\defaultframeoffset + \letframedparameter\c!offset\defaultframeoffset % brrr + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +\setvalue{\??framedoffsetalternative\s!unknown}% + {\settrue \c_framed_has_offset + \settrue \c_framed_has_strut + \setfalse\c_framed_is_overlaid + \let\defaultframeoffset\localoffset + \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax} + +% so far for alternatives + \let\pack_framed_stop_orientation\relax \def\pack_framed_restart @@ -1227,18 +1288,17 @@ \def\pack_framed_do_top {\raggedtopcommand\framedparameter\c!top} \def\pack_framed_do_bottom{\framedparameter\c!bottom\raggedbottomcommand} -%D Carefull analysis of this macro will learn us that not all -%D branches in the last conditionals can be encountered, that -%D is, some assignments to \type{\next} will never occur. -%D Nevertheless we implement the whole scheme, if not for -%D future extensions. +%D Carefull analysis of this macro will learn us that not all branches in the last +%D conditionals can be encountered, that is, some assignments to \type{\next} will +%D never occur. Nevertheless we implement the whole scheme, if not for future +%D extensions. %D \macros %D {doassigncheckedframeoffset} %D %D Offset helper (see menus): -\def\doassigncheckedframeoffset#1#2% +\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname {\edef\checkedframeoffset{#2}% #1% \ifx\checkedframeoffset\empty \zeropoint\else @@ -1253,11 +1313,10 @@ %D \macros %D {ifreshapeframebox} %D -%D The last few lines tell what to do after the content of the -%D box is collected and passed to the next macro. In the case -%D of a fixed width and centered alignment, the content is -%D evaluated and used to determine the most natural width. The -%D rest of the code deals with backgrounds and frames. +%D The last few lines tell what to do after the content of the box is collected and +%D passed to the next macro. In the case of a fixed width and centered alignment, +%D the content is evaluated and used to determine the most natural width. The rest +%D of the code deals with backgrounds and frames. \newif\ifreshapeframebox \reshapeframeboxtrue @@ -1323,8 +1382,8 @@ \else \pack_framed_finish_c \fi\fi\fi - \ifconditional\boxcontentneedsprocessing - \mkdoprocessboxcontents\b_framed_normal + \ifconditional\page_postprocessors_needed_box + \page_postprocessors_linenumbers_box\b_framed_normal \fi \else \pack_framed_finish_c @@ -1570,9 +1629,9 @@ \def\pack_framed_stop_orientation_even {\setbox\b_framed_normal\hbox{\dorotatebox\p_framed_orientation\hbox{\box\b_framed_normal}}} -%D The last conditional takes care of the special situation of -%D in||line \inframed[height=3cm]{framed} boxes. Such boxes have -%D to be \inframed{aligned} with the running text. +%D The last conditional takes care of the special situation of in||line \inframed +%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the +%D running text. \unexpanded\def\inframed {\dosingleempty\pack_framed_inline} @@ -1585,15 +1644,14 @@ \def\pack_framed_inline[% {\framed[\c!location=\v!low,} -%D When we set \type{empty} to \type{yes}, we get -%D ourselves a frame and/or background, but no content, so -%D actually we have a sort of phantom framed box. +%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. %D \macros %D {mframed, minframed} %D -%D When Tobias asked how to frame mathematical elements in -%D formulas, Taco's posted the next macro: +%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the +%D next macro: %D %D \starttyping %D \def\mframed#1% @@ -1605,9 +1663,8 @@ %D \fi} %D \stoptyping %D -%D Because \type {\ifinner} does not (always) reports what -%D one would expect, we move the test to the outer level. We -%D also want to pass arguments, +%D Because \type {\ifinner} does not (always) reports what one would expect, we move the +%D test to the outer level. We also want to pass arguments, %D %D \starttyping %D \def\mframed% @@ -1626,8 +1683,8 @@ %D \fi} %D \stoptyping %D -%D Still better is the next alternative, if only because it -%D takes care of setting the super- and subscripts styles +%D Still better is the next alternative, if only because it takes care of setting the super- +%D and subscripts styles \newcount\c_framed_mstyle @@ -1637,22 +1694,6 @@ \vphantom{(}% \Ustopmath} -% \unexpanded\def\mframed {\dosingleempty\pack_framed_math_display} -% \unexpanded\def\inmframed{\dosingleempty\pack_framed_math_inline } -% -% \def\pack_framed_math_inline[#1]#2% -% {\begingroup -% \c_framed_mstyle\mathstyle -% \inframed[#1]{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}% -% \endgroup} -% -% \def\pack_framed_math_display[#1]#2% -% {\begingroup -% \c_framed_mstyle\mathstyle -% \let\normalstrut\pack_framed_math_strut -% \framed[#1]{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}% -% \endgroup} - \installcorenamespace{mathframed} \installframedcommandhandler \??mathframed {mathframed} \??mathframed @@ -1678,8 +1719,7 @@ \definemathframed[mframed] \definemathframed[inmframed][\c!location=\v!low] -%D So instead of the rather versatile \type {\framed}, we ue -%D the \type {\mframed}. +%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}: %D %D \startbuffer %D \startformula @@ -1700,11 +1740,9 @@ %D %D \typebuffer \getbuffer %D -%D As usual, one can specify in what way the text should be -%D framed. One should be aware of the fact that, inorder to -%D preserve the proper spacing, the \type {offset} is set to -%D \type {overlay} and \type {frameoffset} is used used -%D instead. +%D As usual, one can specify in what way the text should be framed. One should be +%D aware of the fact that, inorder to preserve the proper spacing, the \type +%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead. %D %D \startbuffer %D \startformula @@ -1714,13 +1752,11 @@ %D %D \typebuffer \getbuffer %D -%D For inline use, we also provide the \type {\inmframed} -%D alternative: we want $x \times \inmframed{y}$ in inline -%D math, right? +%D For inline use, we also provide the \type {\inmframed} alternative: we want $x +%D \times \inmframed{y}$ in inline math, right? -%D This previous framing macros needs a lot of alternatives for -%D putting rules around boxes, inserting offsets and aligning -%D text. Each step is handled by separate macros. +%D This previous framing macros needs a lot of alternatives for putting rules around +%D boxes, inserting offsets and aligning text. Each step is handled by separate macros. \newdimen\d_framed_applied_offset \newdimen\d_framed_loffset @@ -1760,8 +1796,8 @@ \hbox{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}% \kern\d_framed_applied_offset}} -%D Let's hope that the next few examples show us enough of -%D what needs to be done by the auxiliary macros. +%D Let's hope that the next few examples show us enough of what needs to be +%D done by the auxiliary macros. %D %D \startbuffer %D \framed[height=1cm,offset=.5cm] {rule based learning} @@ -1815,25 +1851,21 @@ %D \hbox{\dontcomplain\getbuffer} %D \stoplinecorrection %D -%D So now we're ready for the complicated stuff. We distinguish -%D between borders with straight lines and those with round -%D corners. When using the first alternative it is possible to -%D turn off one or more lines. More fancy shapes are also -%D possible by specifying dedicated backgrounds. Turning lines -%D on and off is implemented as efficient as possible and as a -%D result is interface language dependant. This next -%D implementation evolved from simpler ones. It puts for -%D instance the rules on top of the content and provides -%D additional offset capabilities. The lot of calls to other -%D macros makes this mechanism not that easy to comprehend. - -%D We handle left, right or middle alignment as well as fixed -%D or free widths and heights. Each combination gets its own -%D macro. - -%D The following code handles one-liners: \type{align={line,flushright}}. -%D Beware, since we entered a group and either or not grab the next -%D bgroup token, we need to finish the group in the oneliner mode. +%D So now we're ready for the complicated stuff. We distinguish between borders with +%D straight lines and those with round corners. When using the first alternative it +%D is possible to turn off one or more lines. More fancy shapes are also possible by +%D specifying dedicated backgrounds. Turning lines on and off is implemented as +%D efficient as possible and as a result is interface language dependant. This next +%D implementation evolved from simpler ones. It puts for instance the rules on top +%D of the content and provides additional offset capabilities. The lot of calls to +%D other macros makes this mechanism not that easy to comprehend. +%D +%D We handle left, right or middle alignment as well as fixed or free widths and +%D heights. Each combination gets its own macro. +%D +%D The following code handles one-liners: \type {align={line,flushright}}. Beware, +%D since we entered a group and either or not grab the next bgroup token, we need to +%D finish the group in the oneliner mode. \ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi @@ -2013,11 +2045,10 @@ \localstrut \doformatonelinerbox} -%D On the next page we show some examples of how these macros -%D come into action. The examples show us how -%D \type {fit}, \type {broad} dimensions influence the -%D formatting. Watch the visualized struts. \footnote {Here we -%D used \type {\showstruts}.} +%D On the next page we show some examples of how these macros come into action. The +%D examples show us how \type {fit}, \type {broad} dimensions influence the +%D formatting. Watch the visualized struts. \footnote {Here we used \type +%D {\showstruts}.} %D %D \startpostponing %D \bgroup @@ -2072,9 +2103,8 @@ %D \macros %D {framednoflines, framedlastlength} %D -%D It is possible to let the frame macro calculate the width -%D of a centered box automatically (\type {fit}). When -%D doing so, we need to reshape the box: +%D It is possible to let the frame macro calculate the width of a centered box +%D automatically (\type {fit}). When doing so, we need to reshape the box: \newcount\framednoflines \newdimen\framedfirstheight @@ -2106,13 +2136,12 @@ % \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula % \stopTEXpage -%D The examples on the next page show how one can give the -%D frame as well as the background an additional offset and -%D even a bit more depth. The blue outline is the frame, the -%D red box is the background and the small black outline is the -%D visualization of the resulting box, that is, we applied -%D \type{\ruledhbox} to the result. - +%D The examples on the next page show how one can give the frame as well as the +%D background an additional offset and even a bit more depth. The blue outline is +%D the frame, the red box is the background and the small black outline is the +%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to +%D the result. +%D %D \startpostponing %D \bgroup %D \unprotect @@ -2162,9 +2191,8 @@ %D \egroup %D \stoppostponing -%D We can draw lines from left to right and top to bottom by -%D using the normal \type{\hairline} command. Both directions -%D need a different treatment. +%D We can draw lines from left to right and top to bottom by using the normal \type +%D {\hairline} command. Both directions need a different treatment. %D %D \startbuffer %D \framed[width=4cm] {alfa\hairline beta\hairline gamma} @@ -2178,26 +2206,8 @@ %D \hbox{\getbuffer} %D \stoplinecorrection %D -%D These macros try to adapt their behaviour as good as -%D possible to the circumstances and act as natural as -%D possible. - -% \unexpanded\def\pack_framed_vboxed_hairline -% {\bgroup -% \dimen2=\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi -% \dimen4=\dimexpr\dimen2+\d_framed_linewidth\relax -% \setbox0\vbox -% {\advance\hsize 2\dimen4 -% \vskip\dimen2 -% \hrule -% \!!height\d_framed_linewidth -% \!!depth\zeropoint -% \!!width\hsize -% \vskip\dimen2}% -% \endgraf\obeydepth\nointerlineskip -% \moveleft\dimen4\box0 -% \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight -% \egroup} % so this must not be changed +%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 {\begingroup @@ -2207,13 +2217,13 @@ \nointerlineskip \kern\scratchoffset \dontleavehmode - \hrule\!!height\d_framed_linewidth\!!depth\zeropoint + \hrule\s!height\d_framed_linewidth\s!depth\zeropoint \par \kern-\d_framed_linewidth \dontleavehmode - \hbox to \zeropoint{\normalhss\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth}% + \hbox to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% \hfill - \hbox to \zeropoint{\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth\normalhss}% + \hbox to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}% \par \nointerlineskip \kern\scratchoffset @@ -2223,32 +2233,29 @@ \localbegstrut \endgroup} -% todo: - \unexpanded\def\pack_framed_hboxed_hairline % use framed dimen {\bgroup - \dimen2=\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi + \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi \ifconditional\c_framed_has_height - \dimen4\dimexpr\localheight/2+\strutdp-2\d_framed_linewidth\relax - \dimen6\dimexpr\localheight/2-\strutdp+2\d_framed_linewidth\relax + \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax + \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax \else - \dimen4\dimexpr\strutht+\dimen2\relax - \dimen6\dimexpr\strutdp+\dimen2\relax + \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax + \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax \fi \unskip \setbox\scratchbox\hbox - {\hskip\dimen2 - \vrule\!!height\dimen4\!!depth\dimen6\!!width\d_framed_linewidth - \hskip\dimen2}% + {\hskip\scratchoffset + \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth + \hskip\scratchoffset}% \ht\scratchbox\strutht \dp\scratchbox\strutdp \box\scratchbox \ignorespaces \egroup} -%D The argument of the frame command accepts \type{\\} as a -%D sort of newline signal. In horizontal boxes it expands to a -%D space. +%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 {\endgraf\ignorespaces} @@ -2256,10 +2263,9 @@ \unexpanded\def\pack_framed_hboxed_newline {\unskip\normalspace\ignorespaces} -%D We can set each rule on or off. The default setting is -%D inherited from \type{frame}. An earlier implementation -%D use a bit different approach, but the new one seems more -%D natural: +%D We can set each rule on or off. The default setting is inherited from +%D \type {frame}. An earlier implementation use a bit different approach, but the new +%D one seems more natural: %D %D \bgroup %D \setuptyping[margin=0pt] @@ -2299,10 +2305,9 @@ %D \macros %D {startframedtext, setupframedtexts, defineframedtext} %D -%D The general framing command we discussed previously, is not -%D entirely suited for what we call framed texts, as for -%D instance used in intermezzo's. The next examples show what -%D we have in mind. +%D The general framing command we discussed previously, is not entirely suited for +%D what we call framed texts, as for instance used in intermezzo's. The next +%D examples show what we have in mind. %D %D \startbuffer[framed-0] %D \setupframedtexts @@ -2364,8 +2369,8 @@ %D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup %D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup %D -%D Here we can see that we have a predefined framed text class -%D as well as the tools for defining our own. So we have: +%D Here we can see that we have a predefined framed text class as well as the +%D tools for defining our own. So we have: %D %D \showsetup{setupframedtexts} %D @@ -2388,7 +2393,7 @@ \let\setupframedtexts\setupframedtext \setupframedtext - [\c!width=0.75\hsize, + [\c!width=.75\hsize, \c!height=\v!fit, \c!align=\v!yes, %\c!top=, @@ -2415,7 +2420,7 @@ %\c!foregroundstyle=, %\c!background=, %\c!backgroundcolor=, - \c!backgroundscreen=\@@rsscreen, + \c!backgroundscreen=\defaultbackgroundscreen, \c!linecorrection=\v!on, \c!depthcorrection=\v!on, \c!margin=\v!standard] @@ -2461,7 +2466,6 @@ \hsize\localhsize % \insidefloattrue % ? better \normalexpanded{\switchtobodyfont[\framedtextparameter\c!bodyfont]}% -% \startcolor[\framedtextparameter\c!color]% \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup \let\\=\endgraf @@ -2471,9 +2475,8 @@ \setupindenting[\framedtextparameter\c!indenting]% \useframedtextstyleandcolor\c!style\c!color} -%D The \type {none} option is handy for nested usage, as -%D in the presentation styles, where we don't want -%D interference. +%D The \type {none} option is handy for nested usage, as in the presentation +%D styles, where we don't want interference. \defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext] @@ -2482,7 +2485,6 @@ \removelastskip \doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_stop_depth_correction \stopboxedcontent -% \stopcolor \ifconditional\c_framed_text_location_none \egroup \box\b_framed_normal @@ -2551,8 +2553,8 @@ %D \egroup %D \stoptyping -%D The simple brace (or group) delimited case is typeset -%D slightly different and is not aligned. +%D The simple brace (or group) delimited case is typeset slightly different +%D and is not aligned. \unexpanded\def\pack_framed_text_direct#1% {\bgroup @@ -2579,7 +2581,8 @@ \egroup \egroup} -\defineframedtext[\v!framedtext] +\defineframedtext + [\v!framedtext] %D \macros %D {defineframed} @@ -2588,47 +2591,44 @@ %D %D \showsetup{defineframed} %D -%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance -%D model instead of passing a combination of arguments. This also -%D also simplified the \type {\setupframed} command. There are -%D certainly more places where such improvements can be made. - -% actually, this can be another command handler .. todo +%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead +%D of passing a combination of arguments. This also also simplified the \type +%D {\setupframed} command. There are certainly more places where such improvements +%D can be made. -\unexpanded\def\defineframed - {\dotripleempty\pack_framed_define} +\appendtoks + \ifcsname\??regularframedlevel\currentframed\endcsname + % already defined, keeps settings + \else + \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname + \fi +\to \everypresetframed -\def\pack_framed_define[#1][#2][#3]% - {\ifcsname\??ol:#1\endcsname - % already defined, keeps settings - \else - \expandafter\newcount\csname\??ol:#1\endcsname % \the\everypresetframed - \fi - \ifsecondargument - \doifassignmentelse{#2} - {\getparameters[\??ol#1][\s!parent=\??ol,#2]}% - {\ifcsname#2\endcsname - \getparameters[\??ol#1][\s!parent=\??ol#2,#3]% - \else - \getparameters[\??ol#1][\s!parent=\??ol,#3]% - \fi}% - \else - \getparameters[\??ol#1][\s!parent=\??ol,#2]% - \fi - \setuvalue{#1}{\pack_framed_defined_process[#1]}}% % \the\everydefineframed +\appendtoks + \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}% +\to \everydefineframed -\newcount\c_framed_crap +\newcount\c_temp_framed_crap \unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent) {\bgroup - \ifcsname\??ol:#1\endcsname - \expandafter\let\expandafter\c_framed_temp\csname\??ol:#1\endcsname + \ifcsname\??regularframedlevel#1\endcsname + \expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname \else - \let\c_framed_temp\c_framed_crap + \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 + \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 - \advance\c_framed_temp\plusone - \expandafter\def\csname\??ol#1:\the\c_framed_temp\s!parent\endcsname{\??ol#1}% \inheritlocalframed - \dodoubleempty\pack_framed_process[\??ol#1:\the\c_framed_temp]} + \pack_framed_process_indeed} \let\placeframed\pack_framed_defined_process % new per 2012/04/23 @@ -2640,8 +2640,8 @@ %D %D but the existing one is ok as well (less csname messy too). -%D New, for the moment private; let's see when GB finds out -%D about this one and its obscure usage. It's used in: +%D New, for the moment private; let's see when GB finds out about this one and its +%D obscure usage. It's used in: %D %D \startbuffer %D \defineframedtext @@ -2675,21 +2675,17 @@ %D %D \typebuffer -% to be redone +\installcorenamespace{framedcontent} -\def\framedcontentparameter #1{\csname\doframedcontentparameter{\??fc\currentframedcontent}#1\endcsname} -\def\doframedcontentparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedcontentparentparameter\csname#1\s!parent\endcsname#2\fi} -\def\doframedcontentparentparameter#1#2{\ifx#1\relax\s!empty\else\doframedcontentparameter#1#2\fi} -\def\letframedcontentparameter #1{\expandafter\let\csname\??fc\currentframedcontent#1\endcsname} +\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent -\presetlocalframed[\??fc] - -\getparameters - [\??fc] +\setupframedcontent [\c!leftoffset=\zeropoint, - \c!rightoffset=\framedcontentparameter\c!leftoffset, + %\c!rightoffset=\framedcontentparameter\c!leftoffset, + \c!rightoffset=\scratchleftoffset, \c!topoffset=\zeropoint, - \c!bottomoffset=\framedcontentparameter\c!topoffset, + %\c!bottomoffset=\framedcontentparameter\c!topoffset, + \c!bottomoffset=\scratchtopoffset, \c!strut=\v!no, %\c!linecorrection=\v!no, %\c!left=, @@ -2697,19 +2693,6 @@ %\c!width=\v!fit, \c!offset=\v!overlay] -\unexpanded\def\defineframedcontent - {\dodoubleempty\dodefineframedcontent} - -\def\dodefineframedcontent[#1][#2]% - {\getparameters[\??fc#1][\s!parent=\??fc,#2]} - -\unexpanded\def\setupframedcontent - {\dodoubleempty\dosetupframedcontent} - -\def\dosetupframedcontent[#1][#2]% - {\def\docommand##1{\getparameters[\??fc##1][#2]}% - \processcommacommand[#1]\docommand} - \unexpanded\def\startframedcontent {\dosingleempty\pack_framed_start_content} @@ -2727,11 +2710,15 @@ {\setbox\b_framed_normal\hbox\bgroup \setlocalhsize \hsize\localhsize - \advance\hsize\dimexpr-\framedcontentparameter\c!leftoffset-\framedcontentparameter\c!rightoffset \relax - \advance\vsize\dimexpr-\framedcontentparameter\c!topoffset -\framedcontentparameter\c!bottomoffset\relax - \hskip\framedcontentparameter\c!leftoffset + \scratchleftoffset \framedcontentparameter\c!leftoffset \relax + \scratchrightoffset \framedcontentparameter\c!rightoffset \relax + \scratchtopoffset \framedcontentparameter\c!topoffset \relax + \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax + \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax + \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax + \hskip\scratchleftoffset \vbox\bgroup - \vskip\framedcontentparameter\c!topoffset + \vskip\scratchtopoffset \vbox\bgroup \forgetall \blank[\v!disable]} @@ -2739,9 +2726,9 @@ \def\pack_framed_stop_content_indeed {\removelastskip \egroup - \vskip\framedcontentparameter\c!bottomoffset + \vskip\scratchbottomoffset \egroup - \hskip\framedcontentparameter\c!rightoffset + \hskip\scratchrightoffset \egroup \doif{\framedcontentparameter\c!width}\v!fit {\letframedcontentparameter\c!width\v!fixed}% no shapebox @@ -2753,7 +2740,7 @@ % plaats ? \ifdone\startlinecorrection\fi \framedcontentparameter\c!left % new - \localframed[\??fc\currentframedcontent]{\box\b_framed_normal}% hm + \inheritedframedcontentframed{\box\b_framed_normal}% hm \framedcontentparameter\c!right % new \ifdone\stoplinecorrection\fi \egroup} @@ -2763,57 +2750,15 @@ \setuplinewidth [\v!medium] -% We could omit the empty setings but that is some 10% slower due to -% extra testing in the chain. +%D A Goodie: -\setupframed - [\c!width=\v!fit, - \c!height=\v!broad, - %\c!lines=, - \c!offset=0.25ex, % \defaultframeoffset - \c!empty=\v!no, - \c!frame=\v!on, - %\c!topframe=, - %\c!bottomframe=, - %\c!leftframe=, - %\c!rightframe=, - \c!radius=.5\bodyfontsize, - \c!rulethickness=\linewidth, - \c!corner=\v!rectangular, - \c!depth=\zeropoint, - %\c!foregroundcolor=, - %\c!foregroundstyle=, - %\c!background=, - \c!backgroundscreen=\@@rsscreen, - %\c!backgroundcolor=, - \c!backgroundoffset=\zeropoint, - %\c!framecolor=, - \c!frameoffset=\zeropoint, - % somewhat messy - \c!backgroundcorner=\framedparameter\c!corner, - \c!backgroundradius=\framedparameter\c!radius, - \c!backgrounddepth=\framedparameter\c!depth, - \c!framecorner=\framedparameter\c!corner, - \c!frameradius=\framedparameter\c!radius, - \c!framedepth=\framedparameter\c!depth, - % - %\c!component=, - %\c!region=, - %\c!align=, - \c!bottom=\vss, - %\c!top=, - \c!autostrut=\v!yes, - \c!location=\v!normal, - %\c!orientation=, - \c!autowidth=\v!yes, - %\c!setups=, - \c!strut=\v!yes, - %\c!loffset=\zeropoint, - %\c!roffset=\zeropoint, - %\c!toffset=\zeropoint, - ]%\c!boffset=\zeropoint] +\def\v!unframed{unframed} -\setupscreens - [\c!screen=0.95] +\defineframed + [\v!unframed] + [\c!frame=\v!off, + \c!rulethickness=\zeropoint, + \c!foregroundstyle=\framedparameter\c!style, + \c!foregroundcolor=\framedparameter\c!color] \protect \endinput diff --git a/tex/context/base/page-app.mkiv b/tex/context/base/page-app.mkiv index df9607daa..0cf83592d 100644 --- a/tex/context/base/page-app.mkiv +++ b/tex/context/base/page-app.mkiv @@ -34,6 +34,7 @@ [fittingpage] [\c!textstate=\v!empty, \c!doublesided=\v!no, + \c!location=\v!top, % no topskip \c!pagestate=\fittingpageparameter\c!pagestate]% \definelayout @@ -180,14 +181,16 @@ %D \starttext \pagefigure[two.1] \stoptext %D \stoptyping +\defineexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay] % we force a parent + \unexpanded\def\startpagefigure {\dodoubleempty\page_figures_start} \def\page_figures_start[#1][#2]% {\bgroup - \getparameters[\??ex][\c!offset=\v!overlay,#2]% - \startTEXpage[\c!offset=\@@exoffset]% - \externalfigure[#1][#2]\ignorespaces} % so we can put some text below the graphic + \setupexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay,#2]% + \startTEXpage[\c!offset=\externalfigureparameter\c!offset]% + \externalfigure[#1][\v!page:\v!figure]\ignorespaces} % so we can put some text below the graphic \unexpanded\def\stoppagefigure {\stopTEXpage diff --git a/tex/context/base/page-bck.mkiv b/tex/context/base/page-bck.mkiv index 100c186dd..cc4db92fb 100644 --- a/tex/context/base/page-bck.mkiv +++ b/tex/context/base/page-bck.mkiv @@ -11,19 +11,18 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% todo: ma:r:c -% -% 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 ares do support foreground order change. +% 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 -%D For special purposes, users can question the \type -%D {*background} mode. This mode is only available when -%D typesetting the pagebody. +% 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] ... @@ -42,17 +41,23 @@ \fi \to \everybeforepagebody -%D We keep calculations and checks to a minimum and also -%D try to minimize the amount of tracing due to expansion. +\unexpanded\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 -\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax } -\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined} +%D This is the only spot where we hav ea low level dependency on the way +%D parent chains are defined but we want the speed. \def\page_backgrounds_check_background - {\ifcsname\currentotrbackground\c!background\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!background\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!background\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}% \ifx\page_background_temp\empty \expandafter\expandafter\expandafter\page_backgrounds_check_frame \else @@ -63,8 +68,8 @@ \fi} \def\page_backgrounds_check_frame - {\ifcsname\currentotrbackground\c!frame\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!frame\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}% \ifx\page_background_temp\v!on \page_backgrounds_set_yes \else @@ -75,8 +80,8 @@ \fi} \def\page_backgrounds_check_leftframe - {\ifcsname\currentotrbackground\c!leftframe\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!leftframe\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}% \ifx\page_background_temp\v!on \page_backgrounds_set_yes \else @@ -87,8 +92,8 @@ \fi} \def\page_backgrounds_check_rightframe - {\ifcsname\currentotrbackground\c!rightframe\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!rightframe\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}% \ifx\page_background_temp\v!on \page_backgrounds_set_yes \else @@ -99,8 +104,8 @@ \fi} \def\page_backgrounds_check_topframe - {\ifcsname\currentotrbackground\c!topframe\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!topframe\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}% \ifx\page_background_temp\v!on \page_backgrounds_set_yes \else @@ -111,8 +116,8 @@ \fi} \def\page_backgrounds_check_bottomframe - {\ifcsname\currentotrbackground\c!bottomframe\endcsname - \edef\page_background_temp{\csname\currentotrbackground\c!bottomframe\endcsname}% + {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname + \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}% \ifx\page_background_temp\v!on \page_backgrounds_set_yes \else @@ -122,58 +127,66 @@ \page_backgrounds_set_nop \fi} -\def\page_backgrounds_check#1% - {\edef\currentotrbackground{\??ma#1}% - \page_backgrounds_check_background} +%D We don't use the commandhandler code as we want these multitude of backgrounds to be +%D as fast as possible. -\def\ifsomebackgroundfound#1% - {\ifcsname\??ma#1\endcsname} +\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} + +\unexpanded\def\page_backgrounds_check#1% + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \page_backgrounds_check_background} \def\doifsomebackgroundelse#1% - {\ifcsname\??ma#1\endcsname + {\ifcsname\??layoutbackgrounds#1\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \def\doifsomebackground#1% - {\ifcsname\??ma#1\endcsname + {\ifcsname\??layoutbackgrounds#1\endcsname \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} -%D The background mechanism falls back on the \type {\framed} -%D macro. This means that all normal frame and overlay -%D features can be used. +%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\??ma#1\endcsname + {\ifcsname\??layoutbackgrounds#1\endcsname \expandafter\page_backgrounds_add_to_box_indeed \else \expandafter\gobblefourarguments \fi#1} -% we don't need the dimensions here as this is a real framed but the question is: do we indeed -% need a real framed or can we use a fake (i.e. no foreground, only for hidden) +%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 - {\ifcsname\??ma#1\c!setups\endcsname % to be done - \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces ! + {\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\hbox{\localbackgroundframed{\??ma#1}#1#2}}% a real framed (including foreground) + \setbox#2\hbox{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground) + -%D There are quite some backgrounds. At the bottom layer, -%D there is the {\em paper} background. This one is only -%D used for special purposes, like annotations to documents. +%D There are quite some backgrounds. At the bottom layer, there is the {\em +%D paper} background. This one is only used for special purposes, like +%D annotations to 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 -%D page}, the {\em right page} or {\em each page}. As with -%D the paper background, these are calculated on each page. +%D The page backgrounds can be put behind the {\em left page}, the {\em +%D right page} or {\em each page}. As with the paper background, these are +%D calculated on each page. \def\page_backgrounds_add_to_paper#1% {\doifbothsidesoverruled @@ -182,18 +195,17 @@ {\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 -%D top, header, text, footer, bottom} times {\em left edge, -%D left margin, text, right margin, right edge}. These are -%D only recalculated when they change or when the \type -%D {status} is set to \type {repeat}. +%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 -%D useful for special purposes only. This one is calculated -%D each time. The hidden backgrounds are not meant for users! +%D Finaly there is an aditional {\em text} background, again useful for +%D special purposes only. This one is calculated each time. The hidden +%D backgrounds are not meant for users! \newconditional\c_page_backgrounds_hidden_enabled @@ -203,21 +215,19 @@ \fi \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight} -%D The next couple of macros implement the area backgrounds. -%D As said, these are cached in dedicated boxes. The offsets -%D and depth of the page are used for alignment purposes. +%D The next couple of macros implement the area backgrounds. As said, these +%D are cached in dedicated boxes. The offsets and depth of the page are used +%D for alignment purposes. -\newdimen\pageoffset % bleed -\newdimen\pagedepth +%newdimen\pageoffset % bleed +%newdimen\pagedepth % built-in -%D We need a bit more clever mechanism in order to handle -%D layers well. This means that we cannot calculate both -%D background at the same time since something may have -%D changed halfway a page. +%D We need a bit more clever mechanism in order to handle layers well. +%D This means that we cannot calculate both background at the same time +%D since something may have changed halfway a page. -%D Margin swapping has been simplified: see mkii code in case of -%D regression. Calculation is delayed till the page anyway so the -%D state is known. +%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} @@ -230,7 +240,7 @@ \page_backgrounds_set_boxes_a \page_backgrounds_set_boxes_b \page_backgrounds_set_boxes_c - \ifx\@@mastate\v!repeat\else + \ifx\p_page_backgrounds_state\v!repeat\else \global\setfalse\c_page_backgrounds_new \fi} @@ -273,20 +283,19 @@ \newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE \newdimen\pagebackgroundvoffset +\newdimen\pagebackgroundoffset % used elsewhere \newdimen\pagebackgrounddepth \newdimen\pagebackgroundcompensation -\newdimen\pagebackgroundoffset % used elsewhere - \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\??ma\v!text\v!text\endcsname + {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname \page_backgrounds_set_offsets_yes - \else\ifcsname\??ma\v!text\endcsname + \else\ifcsname\??layoutbackgrounds\v!text\endcsname \page_backgrounds_set_offsets_yes \else \page_backgrounds_set_offsets_nop @@ -299,26 +308,27 @@ \global\pagebackgroundcompensation\zeropoint} \def\page_backgrounds_set_offsets_yes - {\global\pagebackgroundcompensation\csname\??ma\v!page\c!offset\endcsname\relax + {\global\pagebackgroundoffset \d_page_backgrounds_depth + \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax \ifzeropt\pagebackgroundcompensation \page_backgrounds_set_offsets_nop \else - \ifcsname\??ma\v!top\v!text\endcsname + \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname \global\pagebackgroundhoffset\zeropoint - \else\ifcsname\??ma\v!bottom\v!text\endcsname + \else\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname \global\pagebackgroundhoffset\zeropoint \else \global\pagebackgroundhoffset\pagebackgroundcompensation \fi\fi - \ifcsname\??ma\v!text\v!rightedge\endcsname + \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname \global\pagebackgroundvoffset\zeropoint \global\pagebackgrounddepth \zeropoint - \else\ifcsname\??ma\v!text\v!leftedge\endcsname + \else\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname \global\pagebackgroundvoffset\zeropoint \global\pagebackgrounddepth \zeropoint \else \global\pagebackgroundvoffset\pagebackgroundcompensation - \global\pagebackgrounddepth \csname\??ma\v!page\c!depth\endcsname\relax + \global\pagebackgrounddepth \d_page_backgrounds_depth \fi\fi \fi} @@ -370,7 +380,7 @@ \bgroup\hbox\bgroup \goleftonpage \ifdim\leftedgewidth>\zeropoint - \ifcsname\??ma#1\v!leftedge\endcsname + \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2% \else \kern\leftedgewidth @@ -378,21 +388,21 @@ \kern\leftedgedistance \fi \ifdim\leftmarginwidth>\zeropoint - \ifcsname\??ma#1\v!leftmargin\endcsname + \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2% \else \kern\leftmarginwidth \fi \kern\leftmargindistance \fi - \ifcsname\??ma#1\v!text\endcsname + \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\??ma#1\v!rightmargin\endcsname + \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2% \else \kern\rightmarginwidth @@ -400,7 +410,7 @@ \fi \ifdim\rightedgewidth>\zeropoint \kern\rightedgedistance - \ifcsname\??ma#1\v!rightedge\endcsname + \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2% \else \kern\rightedgewidth @@ -415,30 +425,31 @@ \def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height {\begingroup - \ifcsname\??ma#1#2\c!setups\endcsname - \doprocesslocalsetups{\csname\??ma#1#2\c!setups\endcsname}% should not produce funny spaces ! + \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 - \ifcsname\??ma#1#2\c!command\endcsname + \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#1#2#3#4% - \localbackgroundframed{\??ma#1#2}{#1:#2}\scratchbox + \fi#3#4% + \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox \endgroup} -\def\page_backgrounds_set_box_cell_nop#1#2#3#4% +\def\page_backgrounds_set_box_cell_nop#1#2% {\setbox\scratchbox\emptyvbox - \wd\scratchbox#3% - \ht\scratchbox#4} + \wd\scratchbox#1% + \ht\scratchbox#2} -\def\page_backgrounds_set_box_cell_yes#1#2#3#4% - {\setbox\scratchbox\vbox to #4{\vss\hbox to#3{\hss\csname\??ma#1#2\c!command\endcsname\hss}\vss}% +\def\page_backgrounds_set_box_cell_yes#1#2% + {\setbox\scratchbox\vbox to #2{\vss\hbox to#1{\hss\p_page_backgrounds_command\hss}\vss}% \dp\scratchbox\zeropoint} -%D The background mechanism is quite demanding in terms or -%D resources. We used to delay these definitions till runtime -%D usage, but since today's \TEX's are large, we now do the -%D work on forehand. +%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] @@ -448,110 +459,115 @@ %D %D \showsetup{setupbackgrounds} %D -%D Because the number of arguments runs from one to three, -%D we need to check for it. +%D Because the number of arguments runs from one to three, we need to check +%D for it. \newtoks\everybackgroundssetup \unexpanded\def\setupbackgrounds {\dotripleempty\page_backgrounds_setup} -\def\page_backgrounds_setup[#1][#2][#3]% +\def\page_backgrounds_setup {\ifthirdargument - \page_backgrounds_setup_double{#1}{#2}{#3}% + \expandafter\page_backgrounds_setup_double \else\ifsecondargument - \page_backgrounds_setup_single{#1}{#2}% + \doubleexpandafter\page_backgrounds_setup_single \else\iffirstargument - \page_backgrounds_setup_basics{#1}% - \fi\fi\fi - \the\everybackgroundssetup} + \tripleexpandafter\page_backgrounds_setup_basics + \fi\fi\fi} + +\newdimen\d_page_backgrounds_offset +\newdimen\d_page_backgrounds_depth \appendtoks - \doifelsevalue{\??ma\v!page\c!offset}\v!overlay - {\global\pageoffset\zeropoint} - {\global\pageoffset\csname\??ma\v!page\c!offset\endcsname}% - \global\pagedepth\csname\??ma\v!page\c!depth\endcsname - \global\pagebackgroundoffset\pageoffset - \global\pagebackgrounddepth\pagedepth - \doifelse\@@mastate\v!stop - {\global\setfalse\c_page_backgrounds_new} - {\global\settrue \c_page_backgrounds_new}% + \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} -\def\page_backgrounds_setup_double#1#2#3% +\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up {\global\settrue\c_page_backgrounds_some - \def\docommand##1% + \def\page_backgrounds_setup_step##1% {\doifinsetelse{##1}\v_page_backgrounds_double_set {\page_backgrounds_setup_and_check{##1}{#3}} - {\def\dodocommand####1{\page_backgrounds_setup_and_check{##1####1}{#3}}% - \processcommalist[#2]\dodocommand}}% - \processcommalist[#1]\docommand} + {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}% + \processcommalist[#2]\page_backgrounds_setup_step_nested}}% + \processcommalist[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup} -\def\page_backgrounds_setup_single#1#2% +\def\page_backgrounds_setup_single[#1][#2][#3]% {\global\settrue\c_page_backgrounds_some \doifcommonelse{#1}\v_page_backgrounds_single_set - {\def\docommand##1{\page_backgrounds_setup_and_check{##1}{#2}}% - \processcommalist[#1]\docommand}% - {\page_backgrounds_setup_double{#1}\v_page_backgrounds_common_set{#2}}} + {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}% + \processcommalist[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup}% + {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}} -\def\page_backgrounds_setup_basics#1% - {\getparameters[\??ma][#1]} +\def\page_backgrounds_setup_basics[#1][#2][#3]% + {\setupframed[\??layoutbackgrounds][#1]% + \the\everybackgroundssetup} \def\page_backgrounds_setup_and_check#1#2% tag settings - {\edef\currentotrbackground{\??ma#1}% - \getparameters[\currentotrbackground][#2]% + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \setupframed[\currentotrbackground][#2]% \page_backgrounds_check_background} -%D Each areas (currently there are $1+3+25+1=30$ of them) -%D has its own low level framed object associated. - -% hm, we can delay them +%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] -\unexpanded\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]} - -\installsomebackground \v!paper \empty -\installsomebackground \v!page \empty -\installsomebackground \v!leftpage \empty -\installsomebackground \v!rightpage \empty - -%D The stand alone text area inherits from the page too. - -\installsomebackground \v!text \empty -\installsomebackground \v!hidden \empty - -%D We save some keying by defining the areas using a helper: - -\def\docommand#1% - {\installsomebackground#1\v!leftedge - \installsomebackground#1\v!leftmargin - \installsomebackground#1\v!text - \installsomebackground#1\v!rightmargin - \installsomebackground#1\v!rightedge} - -\docommand \v!top -\docommand \v!header -\docommand \v!text -\docommand \v!footer -\docommand \v!bottom - -%D We need some cleanup now. - -\let\docommand\relax - -%D We now set up the individual areas to use reasonable -%D defaults. - -\installsomebackground \v!paper \empty -\installsomebackground \v!page \empty -\installsomebackground \v!leftpage \empty -\installsomebackground \v!rightpage \empty - -\getparameters - [\??ma\v!page] +\setupbackgrounds + [\v!page] [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere \c!depth=\zeropoint] @@ -560,29 +576,23 @@ \setupbackgrounds [\c!state=\c!start] -%D The hidden layer can be populated by extending the -%D following comma separated list. This only happens in core -%D modules. +%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) -\def\enablehiddenbackground +\unexpanded\def\enablehiddenbackground {\global\settrue\c_page_backgrounds_hidden_enabled \global\settrue\c_page_backgrounds_some \page_backgrounds_recalculate} -\def\disablehiddenbackground +\unexpanded\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][\positionoverlay{\v!text-2}] -% \defineoverlay[\v!text-1][\positionoverlay{\v!text-1}] -% \defineoverlay[\v!text+1][\positionoverlay{\v!text+1}] -% \defineoverlay[\v!text+2][\positionoverlay{\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}] @@ -592,13 +602,19 @@ [\v!hidden] [\c!background=\hiddenbackgroundlist] -% The next series is used in local (for instance floating) -% backgrounds. +%D Because we haven't really set up backgrounds yet, we set the main efficiency +%D switch to false. + +\setfalse\c_page_backgrounds_some + +\protect \endinput -% \installsomebackground \v!local \empty % not really a background, invisible for users +% %D The next series is used in local (for instance floating) backgrounds. +% +% \installsimplifiedframed{\??layoutbackgrounds\v!local} % % \getparameters -% [\??ma\v!local] +% [\??layoutbackgrounds\v!local] % [\c!component=local, % \c!background=\localbackgroundlist] % @@ -618,7 +634,7 @@ % \fi} % % \def\page_backgrounds_add_local_to_box_indeed#1% -% {\setbox#1\hbox{\localbackgroundframed{\??ma\v!local}\v!local#1}% +% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}% % \global\advance\localpositionnumber\plusone} % afterwards ! % % \let\page_backgrounds_add_local_to_box\gobbleoneargument @@ -633,9 +649,3 @@ % \input tufte % \stopcolumnset -%D Because we haven't really set up backgrounds yet, we set -%D the main efficiency switch to false. - -\setfalse\c_page_backgrounds_some - -\protect \endinput diff --git a/tex/context/base/page-brk.mkiv b/tex/context/base/page-brk.mkiv index 722556760..ac1fffd6b 100644 --- a/tex/context/base/page-brk.mkiv +++ b/tex/context/base/page-brk.mkiv @@ -53,9 +53,9 @@ \def\page_breaks_handle#1% {\edef\page_breaks_current_options{#1}% handy for tracing - \processcommacommand[\page_breaks_current_options]\page_breaks_handle_indeed} + \processcommacommand[\page_breaks_current_options]\page_breaks_handle_step} -\def\page_breaks_handle_indeed#1% +\def\page_breaks_handle_step#1% {\edef\page_breaks_current_option{#1}% can be used in handler \ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname \csname\??pagebreakmethod\page_breaks_current_option\endcsname @@ -80,7 +80,8 @@ {\setvalue{\??pagebreaks#1}{#2}} \unexpanded\def\pagebreak - {\dosingleempty\page_breaks_process} + {\par % else no vertical penalties + \dosingleempty\page_breaks_process} \let\page\pagebreak @@ -269,9 +270,9 @@ \def\page_breaks_columns_handle#1% {\edef\page_breaks_columns_current_options{#1}% - \processcommacommand[#1]\page_breaks_columns_handle_indeed} + \processcommacommand[#1]\page_breaks_columns_handle_step} -\def\page_breaks_columns_handle_indeed#1% +\def\page_breaks_columns_handle_step#1% {\edef\page_breaks_columns_current_option{#1}% \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname \csname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname @@ -296,7 +297,8 @@ {\setvalue{\??columnbreaks#1}{#2}} \unexpanded\def\columnbreak - {\dosingleempty\page_breaks_columns_process} + {\par % else no vertical penalties + \dosingleempty\page_breaks_columns_process} \let\column\columnbreak diff --git a/tex/context/base/page-col.mkiv b/tex/context/base/page-col.mkiv index 50a05d351..14b512421 100644 --- a/tex/context/base/page-col.mkiv +++ b/tex/context/base/page-col.mkiv @@ -13,74 +13,36 @@ \writestatus{loading}{ConTeXt Page Macros / Column Helpers} -%D Here we implement a coouple of helpers for dealing with -%D columns. For the moment we keep the names. +%D Here we implement a couple of helpers for dealing with columns. For +%D the moment we keep the names. When the mul and set modules are redone +%D these can be adapted or disappear. \unprotect -%D The next two registers can be used to store pre column -%D material as well as footnotes or so. +%D We reserve a counter for the number of columns as well as the current +%D column. Both are not to be changed by users! -\newbox\precolumnbox \newdimen\precolumnboxheight -\newbox\postcolumnbox \newdimen\postcolumnboxheight +\newcount\nofcolumns \nofcolumns\plusone +\newcount\mofcolumns \mofcolumns\plusone -%D We reserve a counter for the number of columns as well as -%D the current column. Both are not to be changed by users! - -\newcount\nofcolumns \nofcolumns = 1 -\newcount\mofcolumns \mofcolumns = 1 +\newconstant\columndirection % 0:lr 1:rl \setnewconstant\maxnofcolumns 50 \setnewconstant\allocatednofcolumns 0 -%D The next dimensions reports the final column height - -\newdimen\finalcolumnheights -\newcount\finalcolumnlines - -%D This register can be used as a temporary storage for page -%D content. - -\newbox\restofpage - -%D A few more (some might go away): - -\newif\ifintermediatefootnotes -\newif\ifcarryoverfootnotes %\carryoverfootnotestrue -\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue -\newif\ifbalancecolumns %\balancecolumnstrue -\newif\ifbalancetoheight %\balancetoheighttrue -\newif\ifforcecolumngrid \forcecolumngridtrue -\newif\ifstretchcolumns \stretchcolumnsfalse -\newif\ifinheritcolumns \inheritcolumnsfalse -\newif\ifheightencolumns \heightencolumnsfalse - -\newif\ifbalancingcolumns -\newif\ifcollectingcontent -\newif\ifcolumnoverflow - -\newdimen\intercolumnwidth -\newdimen\localcolumnwidth -\newdimen\savedpagetotal - -\newconstant\columndirection % 0:lr 1:rl - -\def\minbalancetoplines {1} -\def\minfreecolumnlines {2} - -\newif\ifrecentercolumnbox \recentercolumnboxtrue -\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue -\newif\ifpackcolumnfloats \packcolumnfloatstrue - -%D During initialization the temporary boxes are allocated. -%D This enables us to use as much columns as we want, without -%D exhausting the pool of boxes too fast. We could have packed -%D them in one box, but we've got enough boxes. +%D During initialization the temporary boxes are allocated. This enables us to +%D use as much columns as we want, without exhausting the pool of boxes too +%D fast. We could have packed them in one box, but we've got enough boxes. %D -%D Two sets of boxes are declared, the txtboxes are used for -%D the text, the topboxes are for moved column floats. +%D Two sets of boxes are declared, the txtboxes are used for the text, the +%D topboxes are for moved column floats. + +\installcorenamespace{columntext} +\installcorenamespace{columnfooter} +\installcorenamespace{columntop} +\installcorenamespace{columnbottom} -\def\initializecolumns#1% +\unexpanded\def\initializecolumns#1% {\ifnum#1>\maxnofcolumns \showmessage\m!columns1\maxnofcolumns \nofcolumns\maxnofcolumns @@ -88,17 +50,23 @@ \nofcolumns#1\relax \fi \ifnum\nofcolumns>\allocatednofcolumns - \dorecurse\nofcolumns - {\ifnum\recurselevel>\allocatednofcolumns\relax - % \newbox\next \letgvalue{\??zc-\recurselevel-t}=\next - \expandafter\newbox\csname\??zc-\recurselevel-t\endcsname % text - \expandafter\newbox\csname\??zc-\recurselevel-f\endcsname % foot - \expandafter\newbox\csname\??zc-\recurselevel-h\endcsname % top insert - \expandafter\newbox\csname\??zc-\recurselevel-l\endcsname % top insert - \fi}% - \global\allocatednofcolumns\nofcolumns + \page_columns_allocate \fi} +\def\page_columns_allocate + {\dorecurse\nofcolumns + {\ifnum\recurselevel>\allocatednofcolumns\relax + \ifcsname\??columntext\recurselevel\endcsname \else + \expandafter\newbox\csname\??columntext \recurselevel\endcsname % text + \expandafter\newbox\csname\??columnfooter\recurselevel\endcsname % footer + \expandafter\newbox\csname\??columntop \recurselevel\endcsname % top insert + \expandafter\newbox\csname\??columnbottom\recurselevel\endcsname % bottom insert + \fi + \fi}% + \global\allocatednofcolumns\nofcolumns} + +\def\currentcolumn {1} + \def\firstcolumnbox {\columntextbox\plusone} \def\currentcolumnbox {\columntextbox\mofcolumns} \def\lastcolumnbox {\columntextbox\nofcolumns} @@ -107,50 +75,105 @@ \def\currenttopcolumnbox {\columntopbox \mofcolumns} \def\lasttopcolumnbox {\columntopbox \nofcolumns} -\def\columntextbox #1{\csname\??zc-\number#1-t\endcsname} -\def\columnfootbox #1{\csname\??zc-\number#1-f\endcsname} -\def\columntopbox #1{\csname\??zc-\number#1-h\endcsname} -\def\columnbotbox #1{\csname\??zc-\number#1-l\endcsname} - -\def\columnsettextbox {\global\setbox\columntextbox} -\def\columnsetfootbox {\global\setbox\columnfootbox} -\def\columnsettopbox {\global\setbox\columntopbox} -\def\columnsetbotbox {\global\setbox\columnbotbox} - -\def\columngettextbox {\copy\columntextbox} -\def\columngetfootbox {\copy\columnfootbox} -\def\columngettopbox {\copy\columntopbox} -\def\columngetbotbox {\copy\columnbotbox} - -\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}} -\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}} -\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}} -\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}} - -%D Without going in details we present two macro's which handle -%D the columns. The action which is transfered by the the first -%D and only parameter can do something with \type -%D {\currentcolumnbox}. In case of the mid columns, \type -%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled -%D outside these macro's. - -\def\dohandlecolumn#1% - {\mofcolumns\recurselevel - \let\currentcolumn\recurselevel - #1\relax} - -\def\dohandleallcolumns#1% - {\dorecurse\nofcolumns{\dohandlecolumn{#1}}} - -\def\dohandlerevcolumns#1% - {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}} - -\def\dohandlemidcolumns#1% - {\dohandleallcolumns - {\ifnum\recurselevel>\plusone - \ifnum\recurselevel<\nofcolumns - \dohandlecolumn{#1}% - \fi - \fi}} +\def\columntextbox #1{\csname\??columntext \number#1\endcsname} +\def\columnfootbox #1{\csname\??columnfooter\number#1\endcsname} +\def\columntopbox #1{\csname\??columntop \number#1\endcsname} +\def\columnbotbox #1{\csname\??columnbottom\number#1\endcsname} + +\unexpanded\def\columnsettextbox {\global\setbox\columntextbox} +\unexpanded\def\columnsetfootbox {\global\setbox\columnfootbox} +\unexpanded\def\columnsettopbox {\global\setbox\columntopbox} +\unexpanded\def\columnsetbotbox {\global\setbox\columnbotbox} + +\unexpanded\def\columngettextbox {\copy\columntextbox} +\unexpanded\def\columngetfootbox {\copy\columnfootbox} +\unexpanded\def\columngettopbox {\copy\columntopbox} +\unexpanded\def\columngetbotbox {\copy\columnbotbox} + +\unexpanded\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}} +\unexpanded\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}} +\unexpanded\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}} +\unexpanded\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}} + +%D Without going in details we present two macro's which handle the columns. The +%D action which is transfered by the the first and only parameter can do something +%D with \type {\currentcolumnbox}. In case of the mid columns, \type +%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled outside these macro's. + +% \unexpanded\def\dohandlecolumn#1% +% {\mofcolumns\recurselevel +% \let\currentcolumn\recurselevel +% #1\relax} +% +% \unexpanded\def\dohandleallcolumns#1% +% {\dorecurse\nofcolumns{\dohandlecolumn{#1}}} +% +% \unexpanded\def\dohandlerevcolumns#1% +% {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}} +% +% \unexpanded\def\dohandlemidcolumns#1% +% {\dohandleallcolumns +% {\ifnum\recurselevel>\plusone +% \ifnum\recurselevel<\nofcolumns +% \dohandlecolumn{#1}% +% \fi +% \fi}} +% +% As we don't nest we can use a fast variant: + +\unexpanded\def\dohandleallcolumnscs#1{\let\page_columns_action #1\page_columns_all_indeed} +\unexpanded\def\dohandleallcolumns #1{\def\page_columns_action{#1}\page_columns_all_indeed} + +\unexpanded\def\dohandlerevcolumnscs#1{\let\page_columns_action #1\page_columns_rev_indeed} +\unexpanded\def\dohandlerevcolumns #1{\def\page_columns_action{#1}\page_columns_rev_indeed} + +\unexpanded\def\dohandlemidcolumnscs#1{\let\page_columns_action #1\page_columns_mid_indeed} +\unexpanded\def\dohandlemidcolumns #1{\def\page_columns_action{#1}\page_columns_mid_indeed} + +\unexpanded\def\page_columns_all_indeed + {\mofcolumns\plusone + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_all_next + \fi} + +\unexpanded\def\page_columns_all_next + {\advance\mofcolumns\plusone + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_all_next + \fi} + +\unexpanded\def\page_columns_rev_indeed + {\mofcolumns\nofcolumns + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns>\plusone + \expandafter\page_columns_rev_prev + \fi} + +\unexpanded\def\page_columns_rev_prev + {\advance\mofcolumns\minusone + \edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \ifnum\mofcolumns>\plusone + \expandafter\page_columns_rev_prev + \fi} + +\unexpanded\def\page_columns_mid_indeed + {\mofcolumns\plustwo + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_mid_next + \fi} + +\unexpanded\def\page_columns_mid_next + {\edef\currentcolumn{\the\mofcolumns}% + \page_columns_action\relax + \advance\mofcolumns\plusone + \ifnum\mofcolumns<\nofcolumns + \expandafter\page_columns_mid_next + \fi} \protect \endinput diff --git a/tex/context/base/page-com.mkiv b/tex/context/base/page-com.mkiv index 80012dd14..61cb49e89 100644 --- a/tex/context/base/page-com.mkiv +++ b/tex/context/base/page-com.mkiv @@ -30,79 +30,141 @@ %D \stoppagecomment %D \stoptyping -\unexpanded\def\setuppagecomment - {\dosingleempty\dosetuppagecomment} - -\def\dosetuppagecomment[#1]% - {\getparameters[\??pc][#1]% - \doifelse\@@pcstate\v!start - {\doifinsetelse\@@pclocation{\v!bottom,\v!top} - {\setuppapersize[\c!left=\hskip\@@pcoffset]% - \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcheight}% - \edef\@@pcpaperwidth {\the\dimexpr\paperwidth +\@@pcoffset+\@@pcoffset}% - \defineoverlay[\v!pagecomment][\placepagecommentTB]} - {\setuppapersize[\c!top=\vskip\@@pcoffset]% - \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset}% - \edef\@@pcpaperwidth {\the\dimexpr\paperwidth +\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcwidth}% - \defineoverlay[\v!pagecomment][\placepagecommentLR]}% - \processaction - [\@@pclocation] - [ \v!bottom=>{\setuplayout[\c!location=]\setuppapersize[\c!bottom=\vss,\c!top =\vskip\@@pcoffset]}, - \v!top=>{\setuplayout[\c!location=]\setuppapersize[\c!top =\vss,\c!bottom=\vskip\@@pcoffset]}, - \v!left=>{\setuplayout[\c!location=]\setuppapersize[\c!left =\hss,\c!right =\hskip\@@pcoffset]}, - \v!right=>{\setuplayout[\c!location=]\setuppapersize[\c!right =\hss,\c!left =\hskip\@@pcoffset]}]% - \definepapersize - [\v!pagecomment] - [\c!height=\@@pcpaperheight, - \c!width=\@@pcpaperwidth]% - \let\@@pcprintpapersize\printpapersize - \setuppapersize[\papersize][\v!pagecomment]% - \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]}% todo append if already set - {\doif\@@pcstate\v!stop % else initialization invokes backgrounds - {% this should be tested first - % \normalexpanded{\noexpand\setuppapersize[\papersize][\@@pcprintpapersize]}% - \setupbackgrounds[\v!paper][\c!background=]}}} - -\def\@@pcprintpapersize{\printpapersize} - -\unexpanded\def\placepagecommentTB +\installcorenamespace{pagecomment} +\installcorenamespace{pagecommentlocations} +\installcorenamespace{pagecommentstates} + +\newdimen\d_page_comments_offset +\newdimen\d_page_comments_page_width +\newdimen\d_page_comments_page_height +\newdimen\d_page_comments_width +\newdimen\d_page_comments_height +\newdimen\d_page_comments_distance + +\newconditional\c_page_comment_enabled + +\let\p_page_commands_location\v!none +\let\p_page_commands_state \v!stop + +\installsetuponlycommandhandler \??pagecomment {pagecomment} + +\appendtoks + \edef\p_page_commands_location{\directpagecommentparameter\c!location}% + \edef\p_page_commands_state {\directpagecommentparameter\c!state}% + \expandcheckedcsname\??pagecommentstates\p_page_commands_state\v!none +\to \everysetuppagecomment + +\ifdefined\scrn_canvas_synchronize_simple + + \appendtoks + \ifx\p_page_commands_state\v!start + \scrn_canvas_synchronize_simple + \else + \scrn_canvas_synchronize_complex + \fi + \to \everyshipout + +\fi + +\setvalue{\??pagecommentstates\v!start}% + {\d_page_comments_offset \directpagecommentparameter\c!offset \relax + \d_page_comments_distance\directpagecommentparameter\c!distance\relax + \d_page_comments_width \directpagecommentparameter\c!width \relax + \d_page_comments_height \directpagecommentparameter\c!height \relax + \expandcheckedcsname\??pagecommentlocations\p_page_commands_location\v!none + \definepapersize[\v!pagecomment][\c!height=\d_page_comments_page_height,\c!width=\d_page_comments_page_width]% + \setuppapersize[\papersize][\v!pagecomment]% + \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]} % maybe append if already set + +\setvalue{\??pagecommentstates\v!stop}% + {\setupbackgrounds[\v!paper][\c!background=]} + +\setvalue{\??pagecommentstates\v!none}% + {} + +\setvalue{\??pagecommentlocations\v!bottom}% + {\setuplayout[\c!location=]% + \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=\vss,\c!left=\hskip\d_page_comments_offset,\c!right=]% + \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax + \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax + \defineoverlay[\v!pagecomment][\page_comments_top_bottom]} + +\setvalue{\??pagecommentlocations\v!top}% + {\setuplayout[\c!location=]% + \setuppapersize[\c!top=\vss,\c!bottom=\vskip\d_page_comments_offset,\c!left=\hskip\d_page_comments_offset,\c!right=]% + \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax + \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax + \defineoverlay[\v!pagecomment][\page_comments_top_bottom]} + +\setvalue{\??pagecommentlocations\v!left}% + {\setuplayout[\c!location=]% + \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hss,\c!right=\hskip\d_page_comments_offset]% + \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax + \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax + \defineoverlay[\v!pagecomment][\page_comments_left_right]} + +\setvalue{\??pagecommentlocations\v!right}% + {\setuplayout[\c!location=]% + \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hskip\d_page_comments_offset,\c!right =\hss]% + \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax + \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax + \defineoverlay[\v!pagecomment][\page_comments_left_right]} + +\setvalue{\??pagecommentlocations\v!none}% + {}% \setuppapersize[\c!bottom=,\c!top=,\c!left=,\c!right=]} + +\unexpanded\def\page_comments_top_bottom {\vbox to \printpaperheight {%\forgetall - \hsize\printpaperwidth - \vskip\@@pcoffset - \doifelse\@@pclocation\v!bottom{\vskip\dimexpr\paperheight+\@@pcdistance\relax}\vss - \hskip\@@pcoffset - \vbox to \@@pcheight + \hsize\printpaperwidth\relax + \ifx\p_page_commands_location\v!bottom + \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax + \else + \vskip\d_page_comments_offset + \vss + \fi + \hskip\d_page_comments_offset + \vbox to \d_page_comments_height {%\forgetall \hsize\paperwidth - \ifpagecomment + \ifconditional\c_page_comment_enabled \getbuffer[\v!pagecomment]% - \global\pagecommentfalse + \global\setfalse\c_page_comment_enabled \fi}% \hfill - \doifelse\@@pclocation\v!bottom\vss{\vskip\dimexpr\paperheight+\@@pcdistance\relax}% - \vskip\@@pcoffset}} + \ifx\p_page_commands_location\v!bottom + \vss + \vskip\d_page_comments_offset + \else + \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax + \fi}} -\unexpanded\def\placepagecommentLR +\unexpanded\def\page_comments_left_right {\hbox to \printpaperwidth - {\hskip\@@pcoffset - \doifelse\@@pclocation\v!right{\hskip\paperwidth\hskip\@@pcdistance}\hss + {\ifx\p_page_commands_location\v!right + \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax + \else + \hskip\d_page_comments_offset + \hss + \fi \vbox to \printpaperheight {%\forgetall - \vskip\@@pcoffset - \hsize\@@pcwidth - \ifpagecomment + \vskip\d_page_comments_offset + \hsize\d_page_comments_width + \ifconditional\c_page_comment_enabled \getbuffer[\v!pagecomment]% - \global\pagecommentfalse + \global\setfalse\c_page_comment_enabled \fi \vss}% - \doifelse\@@pclocation\v!right\hss{\hskip\paperwidth\hskip\@@pcdistance}% - \hskip\@@pcoffset}} - -\newif\ifpagecomment + \ifx\p_page_commands_location\v!right + \hss + \hskip\d_page_comments_offset + \else + \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax + \fi}} \setvalue{\e!start\v!pagecomment}% - {\global\pagecommenttrue + {\global\settrue\c_page_comment_enabled \grabbufferdatadirect\v!pagecomment{\e!start\v!pagecomment}{\e!stop\v!pagecomment}} \setuppagecomment diff --git a/tex/context/base/page-fac.mkiv b/tex/context/base/page-fac.mkiv index fef1cd5ac..88789abe9 100644 --- a/tex/context/base/page-fac.mkiv +++ b/tex/context/base/page-fac.mkiv @@ -25,19 +25,21 @@ %D \stoptext %D \stoptyping -\newbox\b_page_facings_content +\newbox \b_page_facings_content +\newconditional\c_page_facings_busy -\unexpanded\def\setupoppositeplacing - {\dodoubleargument\getparameters[\??np]} +\installcorenamespace{oppositeplacing} + +\installsetuponlycommandhandler \??oppositeplacing {oppositeplacing} \unexpanded\def\startopposite {\dowithnextboxcontent {\hsize\makeupwidth}% {\global\setbox\b_page_facings_content\vbox {\ifvoid\b_page_facings_content - \@@npbefore + \directoppositeplacingparameter\c!before \else - \@@npinbetween + \directoppositeplacingparameter\c!inbetween \unvbox\b_page_facings_content \fi \box\nextbox}}% @@ -47,26 +49,34 @@ {\egroup} \def\page_facings_finish - {\ifvoid\b_page_facings_content\else + {\ifvoid\b_page_facings_content \else \global\setbox\b_page_facings_content\vbox to \makeupheight {\unvbox\b_page_facings_content - \@@npafter + \directoppositeplacingparameter\c!after \vss}% \fi} \def\page_facings_flush - {\doif\@@npstate\v!start - {\ifvoid\b_page_facings_content\else - \ifnum\realpageno>\plusone - \begingroup - \pageornamentstate\plusone % tricky - \page_facings_finish - \page_boxes_shipout{\page_boxes_constructed_page\box\b_page_facings_content}% - \endgroup - \else - \global\setbox\b_page_facings_content\emptybox - \fi - \fi}} + {\ifconditional\c_page_facings_busy + \ifvoid\b_page_facings_content \else + \page_facings_flush_indeed + \fi + \fi} + +\def\page_facings_flush_indeed + {\ifnum\realpageno>\plusone + \begingroup + \pageornamentstate\plusone % tricky + \page_facings_finish + \page_boxes_shipout{\page_boxes_constructed_page\box\b_page_facings_content}% + \endgroup + \else + \global\setbox\b_page_facings_content\emptybox + \fi} + +\appendtoks + \doifelse{\directoppositeplacingparameter\c!state}\v!start\settrue\setfalse\c_page_facings_busy +\to \everysetupoppositeplacing \setupoppositeplacing [\c!state=\v!start, diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua index ecd7004ae..c383380fb 100644 --- a/tex/context/base/page-flt.lua +++ b/tex/context/base/page-flt.lua @@ -243,11 +243,10 @@ local label = P(":") * C((1-S(",*: "))^0) local pattern = method * ( label * position + C("") * position - + label + + label * C("") * C("") + C("") * C("") * C("") ) + C("") * C("") * C("") * C("") - -- inspect { lpegmatch(pattern,"somewhere:blabla,crap") } -- inspect { lpegmatch(pattern,"somewhere:1*2") } -- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") } @@ -262,6 +261,9 @@ end -- interface +local context = context +local setvalue = context.setvalue + commands.flushfloat = floats.flush commands.savefloat = floats.save commands.resavefloat = floats.resave @@ -278,8 +280,8 @@ function commands.doifelsesavedfloat(...) commands.doifelse(floats.nofstacked(.. function commands.analysefloatmethod(str) local method, label, row, column = floats.analysemethod(str) - context.setvalue("floatmethod",method) - context.setvalue("floatlabel", label ) - context.setvalue("floatrow", row ) - context.setvalue("floatcolumn",column) + setvalue("floatmethod",method) + setvalue("floatlabel", label ) + setvalue("floatrow", row ) + setvalue("floatcolumn",column) end diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv index 18c0ad263..65abc844c 100644 --- a/tex/context/base/page-flt.mkiv +++ b/tex/context/base/page-flt.mkiv @@ -20,31 +20,42 @@ \unprotect -%D To be checked and removed +\ifdefined\s!topfloat \else \def\s!topfloat {topfloat} \fi +\ifdefined\s!bottomfloat \else \def\s!bottomfloat{bottomfloat} \fi -%def\dosavefloatinfo {\showmessage\m!floatblocks2{\the\totalnoffloats}} -\def\doinsertfloatinfo {\showmessage\m!floatblocks4{\the\totalnoffloats}} -\def\dofloatflushedinfo{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}} +\defineinsertion[\s!topfloat] +\defineinsertion[\s!bottomfloat] + +\newdimen \d_page_floats_inserted_bottom +\newdimen \d_page_floats_inserted_top +\newcount \c_page_floats_n_of_top \c_page_floats_n_of_top \plustwo +\newcount \c_page_floats_n_of_bottom \c_page_floats_n_of_bottom\zerocount + +\newconstant\c_page_floats_insertions_topskip_mode % 1 = no topskip + +%def\page_floats_report_saved {\showmessage\m!floatblocks2{\the\totalnoffloats}} +\def\page_floats_report_total {\showmessage\m!floatblocks4{\the\totalnoffloats}} +\def\page_floats_report_flushed{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}} %D Extra float registers. -\newif\ifsomefloatwaiting \somefloatwaitingfalse -\newif\ifroomforfloat \roomforfloattrue -\newif\ifnofloatpermitted \nofloatpermittedfalse -\newif\ifcenterfloatbox \centerfloatboxtrue -\newif\iflocalcenterfloatbox \localcenterfloatboxfalse -\newif\ifglobalcenterfloatbox \globalcenterfloatboxfalse -\newif\ifflushingfloats \flushingfloatsfalse -\newif\ifpackflushedfloats \packflushedfloatstrue % for the moment -\newif\ifpackcolumnfloats \packcolumnfloatstrue - -\newcount\totalnoffloats -\newcount\savednoffloats -\newcount\noffloatinserts +\newconditional\c_page_floats_room +\newconditional\c_page_floats_some_waiting +\newconditional\c_page_floats_not_permitted +\newconditional\c_page_floats_flushing +\newconditional\c_page_floats_center_box \settrue\c_page_floats_center_box +\newconditional\c_page_floats_center_box_local +\newconditional\c_page_floats_center_box_global +\newconditional\c_page_floats_pack_flushed \settrue\c_page_floats_pack_flushed + +%D For the moment we keep this but they will become private too. + +\newcount\totalnoffloats % these will be redone ... handled at the lua end anyway +\newcount\savednoffloats % these will be redone ... handled at the lua end anyway \newcount\nofcollectedfloats % communication channel -\newbox \floatlist -\newbox \savedfloatlist +\newcount\noffloatinserts % these will be redone ... handled at the lua end anyway + \newbox \floattext \newdimen\floatwidth @@ -65,55 +76,55 @@ \appendtoks \ifcase\savednoffloats - \global\somefloatwaitingfalse + \global\setfalse\c_page_floats_some_waiting \else - \global\somefloatwaitingtrue + \global\settrue\c_page_floats_some_waiting \fi \to \everyfloatscheck -\def\dofloatsflush#1#2% +\unexpanded\def\page_floats_flush#1#2% {\ctxcommand{flushfloat("#1",\number#2)}% \the\everyfloatscheck} -\def\dofloatsflushbylabel#1#2% +\unexpanded\def\page_floats_flush_by_label#1#2% {\ctxcommand{flushfloat("#1","#2",true)}% \the\everyfloatscheck} -\def\dofloatssave#1% +\unexpanded\def\page_floats_save#1% {\ctxcommand{savefloat("#1")}% \the\everyfloatscheck} -\def\dofloatsresave#1% +\unexpanded\def\page_floats_resave#1% {\ctxcommand{resavefloat("#1")}% \the\everyfloatscheck} -\def\dopushsavedfloats +\unexpanded\def\page_floats_push_saved {\ctxcommand{pushfloat()}% \the\everyfloatscheck} -\def\dopopsavedfloats +\unexpanded\def\page_floats_pop_saved {\ctxcommand{popfloat()}% \the\everyfloatscheck} -\def\dofloatsgetinfo#1% +\unexpanded\def\page_floats_get_info#1% {\ctxcommand{consultfloat("#1")}} -\def\doifelsesavedfloat#1% +\unexpanded\def\page_floats_if_else#1% {\ctxcommand{doifelsesavedfloat("#1")}} -\def\dofloatscollect#1#2#3% +\unexpanded\def\page_floats_collect#1#2#3% {\ctxcommand{collectfloat("#1",\number\dimexpr#2,\number\dimexpr#3)}} -\def\nofstackedfloatincategory#1% +\unexpanded\def\nofstackedfloatincategory#1% {\ctxcommand{nofstackedfloats("#1")}} -\let\dopushcolumnfloats\dopushsavedfloats -\let\dopopcolumnfloats \dopopsavedfloats +\let\page_floats_column_push_saved\page_floats_push_saved % overloaded in page-mul +\let\page_floats_column_pop_saved \page_floats_pop_saved % overloaded in page-mul -\def\dofloatssavepagefloat#1#2% +\unexpanded\def\page_floats_save_page_float#1#2% {\ctxcommand{savefloat("#1", { specification = "#2" })}} -\def\dofloatssavesomewherefloat#1#2% #1=method +\unexpanded\def\page_floats_save_somewhere_float#1#2% #1=method {\ctxcommand{savefloat("#1", { specification = "#2", label = "\floatlabel" })}} %D This is an experimental new feature (for Alan Braslau), a prelude to more: @@ -133,19 +144,19 @@ %D \placenamedfloat[figure][beta] %D \stoptyping -\def\placenamedfloat - {\dodoubleargument\doplacenamedfloat} +\unexpanded\def\placenamedfloat + {\dodoubleargument\page_floats_place_named} -\def\doplacenamedfloat[#1][#2]% +\def\page_floats_place_named[#1][#2]% {\doloop - {\dofloatsflushbylabel\s!somewhere{#2}% + {\page_floats_flush_by_label\s!somewhere{#2}% \ifvoid\floatbox \exitloop \else - \def\currentfloat{#1}% + \def {#1}% \blank[\rootfloatparameter\c!spacebefore]% \box\floatbox - \blank[\rootfloatparameter\c!spaceafter] + \blank[\rootfloatparameter\c!spaceafter]% \fi}} % \setupcaption [figure] [align=flushleft] @@ -162,10 +173,10 @@ % % \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]} -\def\placefloatwithsetups - {\dotripleempty\doplacefloatwithsetups} +\unexpanded\def\placefloatwithsetups + {\dotripleempty\page_floats_place_with_setups} -\long\def\doplacefloatwithsetups[#1][#2][#3]#4% +\def\page_floats_place_with_setups[#1][#2][#3]#4% {\def\floatsetupcaption {#4}% \def\floatsetupcontent {\copy\nextbox}% \def\floatsetupwidth {\wd\nextbox}% @@ -178,10 +189,10 @@ %D %D First we reimplement some helpers. -\def\dogetfloat - {\ifsomefloatwaiting - \dofloatsflush\s!text{1}% - \ifcenterfloatbox +\unexpanded\def\page_floats_get + {\ifconditional\c_page_floats_some_waiting + \page_floats_flush\s!text\plusone + \ifconditional\c_page_floats_center_box \ifdim\wd\globalscratchbox<\hsize \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}% \else @@ -198,40 +209,53 @@ \global\setbox\floatbox\emptybox \fi} -\def\dosavefloat - {\dofloatssave\s!text - \nonoindentation} % brrr nonoindentation here - -\def\doresavefloat - {\dofloatsresave\s!text} - -\def\doreversesavefloat - {\dofloatsresave\s!text} - -\def\doflushsavedfloats +\unexpanded\def\page_floats_flush_saved {\doloop - {\ifsomefloatwaiting + {\ifconditional\c_page_floats_some_waiting \page_otr_command_check_if_float_fits - \ifroomforfloat - \dogetfloat + \ifconditional\c_page_floats_room + \page_floats_get \doplacefloatbox \else \exitloop \fi \else -% \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit -% \page_otr_command_flush_margin_blocks -% \else + % \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit + % \page_otr_command_flush_margin_blocks + % \else \exitloop -% \fi + % \fi \fi}} +%D This is a future mechamism that will be integrated once we're sure about it: +%D +%D \starttyping +%D \dorecurse{10} +%D {\input thuan +%D \placefigure{}{\framed[height=1.5cm]{test}} +%D \placefloatplaceholder} +%D \stoptyping + +\unexpanded\def\placefloatplaceholder + {\ifconditional\c_page_floats_room \else + \ifdim\dimexpr\pagegoal-\pagetotal-3\lineheight\relax>\zeropoint + \startlinecorrection[blank] + \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}% + \stoplinecorrection + \else + \allowbreak + \fi + \fi} + +\setuplabeltext + [placeholder={\Word{\lastplacedfloat}~, moved}] + %D Page floats use different stacks. -\newtoks \everybeforeflushedpagefloat +\newtoks\everybeforeflushedpagefloat -\def\doflushsomepagefloat#1% future releases can do more clever things - {\dofloatsflush{#1}{1}% +\def\page_floats_flush_page_floats_indeed#1% future releases can do more clever things + {\page_floats_flush{#1}\plusone \edef\floatspecification{\ctxcommand{getfloatvariable("specification")}}% Is this okay? \the\everybeforeflushedpagefloat \vbox to \textheight @@ -240,38 +264,15 @@ \doifnotinset\v!low\floatspecification\vfill}% \page_otr_fill_and_eject_page} -\def\doflushpagefloats +\unexpanded\def\page_floats_flush_page_floats % used in postpone {\edef\m_page_otf_checked_page_float{\ctxcommand{checkedpagefloat()}}% (true) for packed \ifx\m_page_otf_checked_page_float\empty % nothing \else\ifx\m_page_otf_checked_page_float\v!empty \emptyhbox \page_otr_fill_and_eject_page % why not dummy_page \else - \doflushsomepagefloat\m_page_otf_checked_page_float + \page_floats_flush_page_floats_indeed\m_page_otf_checked_page_float \fi\fi} - -\def\uncenteredfloatbox % hm, where is this one used (was in save/restore, see old implementation) - {\ifcenterfloatbox - \ifhbox\floatbox\relax % remove centering - \ifdim\wd\floatbox=\hsize - \ifhbox\floatbox - \setbox\scratchbox\hbox - {\unhbox\floatbox - \unskip\unskip - \global\setbox\globalscratchbox\lastbox}% - \box\globalscratchbox - \else - \box\floatbox - \fi - \else - \box\floatbox - \fi - \else - \box\floatbox - \fi - \else - \box\floatbox - \fi} % temp hack, needed to prevent floatbox being forgotten during % output, this will change to using another box for flushing @@ -291,3 +292,28 @@ \to \everyafteroutput \protect \endinput + +% hm, where is this one used (was in save/restore, see old implementation) +% +% \unexpanded\def\uncenteredfloatbox +% {\ifconditional\c_page_floats_center_box +% \ifhbox\floatbox\relax % remove centering +% \ifdim\wd\floatbox=\hsize +% \ifhbox\floatbox +% \setbox\scratchbox\hbox +% {\unhbox\floatbox +% \unskip\unskip +% \global\setbox\globalscratchbox\lastbox}% +% \box\globalscratchbox +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi +% \else +% \box\floatbox +% \fi} diff --git a/tex/context/base/page-flw.mkiv b/tex/context/base/page-flw.mkiv index 9afacf584..ec1fa636d 100644 --- a/tex/context/base/page-flw.mkiv +++ b/tex/context/base/page-flw.mkiv @@ -14,93 +14,127 @@ \writestatus{loading}{ConTeXt Page Macros / Text Flows} %D This is high experimental and especially flushing may change (proper -%D spacing is the driving force here). +%D spacing is the driving force here). It's an old mechanism used for +%D playing with stepping through document threads. As it's a simple and +%D effective mechanism we keep it around. It's not to be confused with +%D upcoming stream support. +%D +%D \starttyping +%D \setuppapersize [S6] +%D \setuptolerance [verytolerant,stretch] +%D \setupfooter [strut=no] +%D \setupwhitespace[big] +%D +%D \setuplayout +%D [rightedge=5cm,width=fit,margin=0pt,edgedistance=1cm, +%D footer=4cm,footerdistance=1cm,header=0cm] +%D +%D \setuptexttexts [edge][][\vbox{\flushtextflow{alpha}}] +%D \setupfootertexts[edge][][\vbox{\flushtextflow{beta}}] +%D \setupfootertexts [\vbox{\flushtextflow{gamma}}][] +%D +%D \definetextflow [alfa] [width=\rightedgewidth] +%D \definetextflow [beta] [width=\rightedgewidth] +%D \definetextflow [gamma] [width=\footerheight] +%D +%D \starttext +%D +%D \dorecurse{50} +%D {\getrandomnumber{\funny}{0}{8} +%D \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow +%D \or \starttextflow[beta] \input knuth.tex \stoptextflow +%D \or \starttextflow[gamma] \input materie.tex \stoptextflow +%D \or {\bf TUFTE}\quad \input tufte \par +%D \or {\bf TUFTE}\quad \input tufte \par +%D \or {\bf KNUTH}\quad \input knuth \par +%D \or {\bf KNUTH}\quad \input knuth \par +%D \or {\bf MATERIE}\quad \input materie \par +%D \else {\bf MATERIE}\quad \input materie \par +%D \fi} +%D +%D \stoptext +%D \stoptyping \unprotect -\unexpanded\def\definetextflow - {\dodoubleempty\dodefinetextflow} +\installcorenamespace{textflow} +\installcorenamespace{textflowbox} -\def\dodefinetextflow[#1][#2]% flow settings - {\iffirstargument - \doiftextflowcollectorelse{#1} - {\setbox\textflowcollector{#1}\emptybox} - {\@EA\newbox\csname\??tx:c:#1\endcsname}% - \getparameters[\??tx:p:#1] - [\c!width=\hsize,\c!style=,#2]% - \fi} +\installcommandhandler \??textflow {textflow} \??textflow -\def\textflowparameter#1#2{\csname\??tx:p:#1#2\endcsname} -\def\textflowcollector #1{\csname\??tx:c:#1\endcsname} +\setuptextflow + [%c!style=, + %c!color=, + \c!width=\availablehsize] -\def\doiftextflowcollectorelse#1{\doifdefinedelse{\??tx:c:#1}} +\appendtoks + \ifcsname\??textflowbox\currenttextflow\endcsname + \setbox\csname\??textflowbox\currenttextflow\endcsname\emptybox + \else + \expandafter\newbox\csname\??textflowbox\currenttextflow\endcsname + \fi +\to \everydefinetextflow -\def\doiftextflowelse#1% - {\doiftextflowcollectorelse{#1} - {\ifvoid\textflowcollector{#1}% - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - {\secondoftwoarguments}} +\let\b_page_textflow_box\zerocount -\def\doiftextflow#1% - {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument} +\def\textflowcollector#1% + {\csname\??textflowbox#1\endcsname} + +\unexpanded\def\doiftextflowcollectorelse#1% + {\ifcsname\??textflowbox#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\unexpanded\def\doiftextflowelse#1% + {\ifcsname\??textflowbox#1\endcsname + \ifvoid\csname\??textflowbox#1\endcsname + \doubleexpandafter\secondoftwoarguments + \else + \doubleexpandafter\firstoftwoarguments + \fi + \else + \expandafter\secondoftwoarguments + \fi} + +% \unexpanded\def\doiftextflow#1% +% {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument} \unexpanded\def\starttextflow[#1]% - {\doiftextflowcollectorelse{#1} - {\global\setbox\textflowcollector{#1}\vbox - \bgroup - \unvbox\textflowcollector{#1}% - \hsize\textflowparameter{#1}\c!width - \dousestyleparameter{\textflowparameter{#1}\c!style}% - \unexpanded\def\stoptextflow{\endgraf\egroup}} - {\let\stoptextflow\relax}} + {\begingroup + \edef\currenttextflow{#1}% + \ifcsname\??textflowbox\currenttextflow\endcsname + \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname + \global\setbox\b_page_textflow_box\vbox + \bgroup + \dontcomplain + \ifvoid\b_page_textflow_box\else + \unvbox\b_page_textflow_box + \fi + \hsize\textflowparameter\c!width\relax + \usetextflowstyleandcolor\c!style\c!color + \unexpanded\def\stoptextflow{\endgraf\egroup\endgroup}% + \else + \let\stoptextflow\endgroup + \fi} -\def\flushtextflow#1% - {\doiftextflow{#1} - {\ifdim\ht\textflowcollector{#1}>\vsize - \setbox\scratchbox\vsplit\textflowcollector{#1} to \vsize - \unvbox\scratchbox +\unexpanded\def\flushtextflow#1% + {\begingroup + \edef\currenttextflow{#1}% + \ifcsname\??textflowbox\currenttextflow\endcsname + \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname + \ifvoid\b_page_textflow_box + % sorry + \else\ifdim\ht\b_page_textflow_box>\vsize + \setbox\scratchbox\vsplit\b_page_textflow_box to \vsize + \ifvoid\scratchbox\else + \unvbox\scratchbox + \fi \else - \unvbox\textflowcollector{#1}% - \fi}} + \unvbox\b_page_textflow_box + \fi\fi + \fi + \endgroup} \protect \endinput - -% Example (dutch) -% -% \stelpapierformaatin [S6] -% \steltolerantiein [soepel,rek] -% \stelkleurenin [status=start] -% \stelvoetin [strut=nee] -% \stelwitruimtein [groot] -% -% \stellayoutin -% [rechterrand=5cm,breedte=passend,marge=0pt,randafstand=1cm, -% voet=4cm,voetafstand=1cm,hoofd=0cm] -% -% \stelteksttekstenin[rand][][\vbox{\flushtextflow{alpha}}] -% \stelvoettekstenin [rand][][\vbox{\flushtextflow{beta}}] -% \stelvoettekstenin [\vbox{\flushtextflow{gamma}}][] -% -% \definetextflow [alfa] [breedte=\rechterrandbreedte] -% \definetextflow [beta] [breedte=\rechterrandbreedte] -% \definetextflow [gamma] [breedte=\voethoogte] -% -% \starttekst -% -% \dorecurse{50} -% {\getrandomnumber{\funny}{0}{8} -% \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow -% \or \starttextflow[beta] \input knuth.tex \stoptextflow -% \or \starttextflow[gamma] \input materie.tex \stoptextflow -% \or {\bf TUFTE}\quad \input tufte \par -% \or {\bf TUFTE}\quad \input tufte \par -% \or {\bf KNUTH}\quad \input knuth \par -% \or {\bf KNUTH}\quad \input knuth \par -% \or {\bf MATERIE}\quad \input materie \par -% \else {\bf MATERIE}\quad \input materie \par -% \fi} -% -% \stoptekst diff --git a/tex/context/base/page-grd.mkiv b/tex/context/base/page-grd.mkiv index e882978ca..281d0bfbe 100644 --- a/tex/context/base/page-grd.mkiv +++ b/tex/context/base/page-grd.mkiv @@ -70,9 +70,9 @@ {\hskip\layoutcolumnwidth \ifnum\recurselevel<\layoutcolumns \vrule - \!!height\ht\scratchbox - \!!depth\dp\scratchbox - \!!width\layoutcolumndistance + \s!height\ht\scratchbox + \s!depth \dp\scratchbox + \s!width \layoutcolumndistance \fi}}% \hskip-\makeupwidth \fi diff --git a/tex/context/base/page-imp.mkiv b/tex/context/base/page-imp.mkiv index 9d0f722fe..5eb587b7b 100644 --- a/tex/context/base/page-imp.mkiv +++ b/tex/context/base/page-imp.mkiv @@ -148,8 +148,7 @@ \donetrue \fi \else % testen, aangepast / expanded nodig ? - \normalexpanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}% - \donetrue\donefalse + \normalexpanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse \fi \ifdone \setbox\shipoutscratchbox\hbox{#1}% diff --git a/tex/context/base/page-inf.mkiv b/tex/context/base/page-inf.mkiv index 6c220fb31..acfbf26f6 100644 --- a/tex/context/base/page-inf.mkiv +++ b/tex/context/base/page-inf.mkiv @@ -24,7 +24,7 @@ \let\currentversioninfo\empty -\def\setupversion +\unexpanded\def\setupversion {\dosingleargument\page_info_setup} \let\version\setupversion @@ -52,7 +52,7 @@ {\csname\??layoutinfo#1\endcsname} \installversioninfo\v!concept - {\vskip\!!sixpoint + {\vskip6\points \hbox to \makeupwidth {\infofont \v!concept:\space\currentdate @@ -60,7 +60,7 @@ \page_adapts_status_info}} \installversioninfo\v!file - {\vskip\!!sixpoint + {\vskip6\points \hbox to \makeupwidth {\infofont \getmessage\m!system{27}:\space\currentdate\space diff --git a/tex/context/base/page-ini.mkiv b/tex/context/base/page-ini.mkiv index aad08ef3e..fdffa552d 100644 --- a/tex/context/base/page-ini.mkiv +++ b/tex/context/base/page-ini.mkiv @@ -56,18 +56,18 @@ \newbox\pagebox -\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi -\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi -\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi +\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 %D Floats. \def\page_otr_flush_all_floats {%\flushnotes already done - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \begingroup - \noftopfloats\plusthousand - \nofbotfloats\zerocount + \c_page_floats_n_of_top\plusthousand + \c_page_floats_n_of_bottom\zerocount % this is needed in case a float that has been stored % ends up at the current page; this border case occurs when % the calculated room is 'eps' smaller that the room available @@ -104,10 +104,11 @@ \inpagebodytrue % needed for enabling \blank ! brrr \page_otr_command_flush_saved_floats \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns - \doincrementpageboundcounters % should hook into an every + \strc_pagenumbers_increment_counters % should hook into an every \page_adapts_synchronize \page_otr_check_for_pending_inserts - \doflushspread + \page_floats_flush_page_floats % before postponed blocks + \page_spread_flush % defined later \page_postponed_blocks_flush} % Can't we get rid of this hackery? It's used in some widgets @@ -215,7 +216,6 @@ {\vbox\bgroup % intercept spurious spaces \the\everybeforepagebody \starttextproperties - \dontshowboxes \checkmarginblocks \the\beforeeverypage \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% @@ -229,4 +229,32 @@ \the\everyafterpagebody \egroup} +\def\doiftopofpageelse + {\ifdim\pagegoal=\maxdimen + \expandafter\firstoftwoarguments + \else\ifdim\pagegoal=\vsize + \doubleexpandafter\firstoftwoarguments + \else + \doubleexpandafter\secondoftwoarguments + \fi\fi} + +% %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 +% +% %D Idea: +% +% \definemarkedpage[nobackgrounds] +% \markpage[nobackgrounds] +% \doifmarkedpageelse{nobackgrounds} + \protect \endinput diff --git a/tex/context/base/page-ins.lua b/tex/context/base/page-ins.lua new file mode 100644 index 000000000..7f870735d --- /dev/null +++ b/tex/context/base/page-ins.lua @@ -0,0 +1,97 @@ +if not modules then modules = { } end modules ['page-ins'] = { + version = 1.001, + comment = "companion to page-mix.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", + -- public = { + -- functions = { + -- "inserts.define", + -- "inserts.getdata", + -- }, + -- commands = { + -- "defineinsertion", + -- "inserttionnumber", + -- } + -- } +} + +-- Maybe we should only register in lua and forget about the tex end. + +structures = structures or { } +structures.inserts = structures.inserts or { } +local inserts = structures.inserts + +local report_inserts = logs.reporter("inserts") + +local allocate = utilities.storage.allocate + +inserts.stored = inserts.stored or allocate { } -- combining them in one is inefficient in the +inserts.data = inserts.data or allocate { } -- bytecode storage pool + +local variables = interfaces.variables +local v_page = variables.page +local v_columns = variables.columns +local v_firstcolumn = variables.firstcolumn +local v_lastcolumn = variables.lastcolumn +local v_text = variables.text + +storage.register("structures/inserts/stored", inserts.stored, "structures.inserts.stored") + +local data = inserts.data +local stored = inserts.stored + +for name, specification in next, stored do + data[specification.number] = specification + data[name] = specification +end + +function inserts.define(name,specification) + specification.name= name + local number = specification.number or 0 + data[name] = specification + data[number] = specification + -- only needed at runtime as this get stored in a bytecode register + stored[name] = specification + if not specification.location then + specification.location = v_page + end + return specification +end + +function inserts.setup(name,settings) + local specification = data[name] + for k, v in next, settings do + -- maybe trace change + specification[k] = v + end + return specification +end + +function inserts.setlocation(name,location) -- a practical fast one + data[name].location = location +end + +function inserts.getlocation(name,location) + return data[name].location or v_page +end + +function inserts.getdata(name) -- or number + return data[name] +end + +function inserts.getname(number) + return data[name].name +end + +function inserts.getnumber(name) + return data[name].number +end + +-- interface + +commands.defineinsertion = inserts.define +commands.setupinsertion = inserts.setup +commands.setinsertionlocation = inserts.setlocation +commands.insertionnumber = function(name) context(data[name].number or 0) end + diff --git a/tex/context/base/page-ins.mkiv b/tex/context/base/page-ins.mkiv index 793e28d4c..a63de0b26 100644 --- a/tex/context/base/page-ins.mkiv +++ b/tex/context/base/page-ins.mkiv @@ -13,81 +13,164 @@ \writestatus{loading}{ConTeXt Core Macros / Insertions} -%D Insertions are special data collections that are associated -%D to \TEX's internal page builder. When multiple footnote -%D classes were introduced, I decided to isolate some of the -%D functionality in a module. +%D Insertions are special data collections that are associated to \TEX's internal +%D page builder. When multiple footnote classes were introduced, I decided to +%D isolate some of the functionality in a module. + +\registerctxluafile{page-ins}{1.001} \unprotect -\newtoks\@@insertionlist +%D Because we need to deal with inserts at the \LUA\ end as well, +%D we provide a proper installer. -\def\processinsertions{\the\@@insertionlist} +% Not yet used as we need to adapt some code to this. -\let\doprocessinsert\gobbleoneargument +\installcorenamespace{insertion} +\installcorenamespace{insertionnumber} -\def\installinsertion#1% - {\ifdefined#1\else - \let#1\relax - \fi - \ifx#1\relax % permits \csname...\endcsname - \newinsert#1% - \count#1\plusthousand - \skip #1\zeropoint - \dimen#1\maxdimen - \appendtoks\doprocessinsert#1\to\@@insertionlist - \fi} +\installcommandhandler \??insertion {insertion} \??insertion -\def\synchronizeinsertions - {\def\doprocessinsert##1{\ifvoid##1\else\insert##1{\unvbox##1}\fi}% - \processinsertions} +\setupinsertion + [%c!n=\plusone, + %c!distance=\zeropoint, + %c!maxheight=\maxdimen, + %c!factor=\plusthousand, + \c!location=\v!page] -%D For instance, when we postpone footnotes, we need to save -%D some data related to the inserts. The next methods are -%D far from ideal, but better than nothing. We save and -%D restore box content and associated data independently. -%D The box content is only restores when non||void. +\newcount\currentinsertionnumber % This is a count and not a macro ! -\def\backupinsertion#1% - {\csname\string#1\endcsname} +\newtoks\t_page_inserts_list -\def\installbackupinsertion#1% - {\expandafter\newinsert\csname\string#1\endcsname - \count\backupinsertion#1\zerocount - \skip \backupinsertion#1\zeropoint - \dimen\backupinsertion#1\maxdimen} +\let\doprocessinsert\relax -\def\saveinsertionbox#1% - {\ifdim\ht#1>\zeropoint % hm, actually unknown - \global\setbox\backupinsertion#1\box#1% - \else - \global\setbox\backupinsertion#1\emptybox - \fi} +%D Maybe some day we will move settings here. -\def\restoreinsertionbox#1% - {\ifvoid\backupinsertion#1\else % if void, we keep the content - \global\setbox#1\box\backupinsertion#1% - \fi} +\unexpanded\def\setcurrentinsertion#1% + {\edef\currentinsertion{#1}% + \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname} -\def\eraseinsertionbackup#1% - {\global\setbox\backupinsertion#1\emptybox} +\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname} -\def\saveinsertiondata#1% - {\global\skip \backupinsertion#1\skip #1% - \global\count\backupinsertion#1\count#1% - \global\dimen\backupinsertion#1\dimen#1} +\unexpanded\def\page_inserts_synchronize_registers + {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname} -\def\restoreinsertiondata#1% - {\global\skip #1\skip \backupinsertion#1% - \global\count#1\count\backupinsertion#1% - \global\dimen#1\dimen\backupinsertion#1} +% for practical reasone we still set these elsewhere but that might chaneg in the future +% +% \global\count\currentinsertionnumber\numexpr\insertionparameter\c!factor/\insertionparameter\c!n\relax +% \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax +% \global\dimen\currentinsertionnumber\insertionparameter\c!maxheight\relax} -%D Auxiliary macros: +\appendtoks + \page_inserts_synchronize_registers +\to \everysetupinsertion + +\unexpanded\def\page_inserts_process#1% beware, this addapts currentinsertion ! + {\edef\currentinsertion{#1}% + \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname + \doprocessinsert\currentinsertionnumber} % old method + +\unexpanded\def\processinsertions + {\the\t_page_inserts_list} -\def\addinsertionheight#1\to#2% +\unexpanded\def\synchronizeinsertions + {\let\doprocessinsert\page_inserts_synchronize + \processinsertions} + +\unexpanded\def\page_inserts_synchronize#1% yes or no {\ifvoid#1\else - \advance#2 1\skip#1\relax - \advance#2 \ht #1\relax + \insert#1{\unvbox#1}% + \fi} + +\unexpanded\def\doifinsertionelse#1% + {\ifcsname\??insertionnumber#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments \fi} +% \unexpanded\def\startinsertion[#1]% +% {\insert\csname\??insertionnumber#1\endcsname\bgroup} +% +% \unexpanded\def\stopinsertion +% {\egroup} + +% For the moment we use the regular insertion allocator so that users can +% still define their own insertions (not that they will play nicely with +% all context mechanisms then). We can use the dimensions at the \LUA\ end +% so we don't need to pass pass them explicitly. Actually, when we see an +% insertion node at that end, we already know the number. + +\appendtoks + \ifx\currentinsertionparent\empty + \ifcsname\??insertionnumber\currentinsertion\endcsname + % bad news + \else + \expandafter\newinsert\csname\??insertionnumber\currentinsertion\endcsname + \page_inserts_synchronize_registers + \ctxcommand{defineinsertion("\currentinsertion",{ number = \number\currentinsertionnumber })}% + \t_page_inserts_list\expandafter\expandafter\expandafter + {\expandafter\the\expandafter\t_page_inserts_list + \expandafter\page_inserts_process\csname\??insertionnumber\currentinsertion\endcsname}% + \count\currentinsertionnumber\plusthousand + \skip \currentinsertionnumber\zeropoint + \dimen\currentinsertionnumber\maxdimen + \fi + \else + \expandafter\let\csname\??insertionnumber\currentinsertion\expandafter\endcsname + \csname\??insertionnumber\currentinsertionparent\endcsname + \fi +\to \everydefineinsertion + +\appendtoks + \ctxcommand{setupinsertion("\currentinsertion",{ + location = "\insertionparameter\c!location", + })}% +\to \everysetupinsertion + +\unexpanded\def\page_inserts_set_location#1#2% fast one + {\ctxcommand{setinsertionlocation("#1","#2")}} + +%D Auxiliary macros: + +\def\page_insert_insertion_height#1% + {\dimexpr\expandafter\page_insert_insertion_height_indeed\csname\??insertionnumber#1\endcsname\relax} + +\def\page_insert_insertion_height_indeed#1% + {\ifvoid#1\zeropoint\else1\skip#1+\ht#1\fi} + +%D Obsolete: + +% \installcorenamespace{insertionbackup} +% +% \unexpanded\def\installbackupinsertion#1% +% {\ifcsname\??insertionbackup\string#1\endcsname \else +% \expandafter\newinsert\csname\??insertionbackup\string#1\endcsname +% \count\csname\??insertionbackup\string#1\endcsname\zerocount +% \skip \csname\??insertionbackup\string#1\endcsname\zeropoint +% \dimen\csname\??insertionbackup\string#1\endcsname\maxdimen +% \fi} +% +% \unexpanded\def\saveinsertionbox#1% hm, actually unknown +% {\global\setbox\csname\??insertionbackup\string#1\endcsname +% \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi} +% +% \unexpanded\def\restoreinsertionbox#1% +% {\ifvoid\backupinsertion#1\else % if void, we keep the content +% \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname +% \fi} +% +% \unexpanded\def\eraseinsertionbackup#1% +% {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox} +% +% \unexpanded\def\saveinsertiondata#1% +% {\global\skip \csname\??insertionbackup\string#1\endcsname\skip #1% +% \global\count\csname\??insertionbackup\string#1\endcsname\count#1% +% \global\dimen\csname\??insertionbackup\string#1\endcsname\dimen#1} +% +% \unexpanded\def\restoreinsertiondata#1% +% {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname +% \global\count#1\count\csname\??insertionbackup\string#1\endcsname +% \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname} + \protect \endinput diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv index 78839ea70..febabdac4 100644 --- a/tex/context/base/page-lay.mkiv +++ b/tex/context/base/page-lay.mkiv @@ -576,7 +576,7 @@ %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}% \page_layouts_synchronize} -\ifx\page_paper_set_offsets\undefined +\ifdefined\page_paper_set_offsets \else \def\page_paper_set_offsets % will move {\global\paperoffset\v_page_target_offset @@ -585,8 +585,13 @@ \fi -\ifdefined\setups \else \unexpanded\def\setups[#1]{\setdefaultpenalties} \fi % still needed? -\ifdefined\synchronizegridsnapping \else \let\synchronizegridsnapping\relax \fi +\ifdefined\setups \else + \unexpanded\def\setups[#1]{\setdefaultpenalties} % still needed? +\fi + +\ifdefined\synchronizegridsnapping \else + \let\synchronizegridsnapping\relax +\fi \let\p_page_layouts_width \empty \let\p_page_layouts_height\empty @@ -806,7 +811,7 @@ \page_layouts_check_revert \fi\fi\fi\fi\fi\fi} -\def\installlayoutmethod#1#2% +\unexpanded\def\installlayoutmethod#1#2% {\setgvalue{\??layoutmethod#1}{#2}} \installlayoutmethod\v!default{\page_layouts_check_default} @@ -926,8 +931,11 @@ %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 @@ -946,27 +954,33 @@ \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% - {\getparameters[\??za][\c!height=\zeropoint,\c!lines=0,#1]% + {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]% \page_adepts_push - \doifelse\@@zaheight\v!max - {\global\d_page_adepts_height\footerheight} - {\global\d_page_adepts_height\dimexpr - \ifnum\@@zalines=\zerocount - \@@zaheight + \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 - \@@zalines\openlineheight + \p_adapts_lines\openlineheight \fi \relax \ifdim\d_page_adepts_height>\footerheight \global\d_page_adepts_height\footerheight - \fi} + \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 - \global\pagegoal\vsize % \page_backgrounds_recalculate \global\let\page_adepts_push\relax @@ -1105,33 +1119,50 @@ % #single #left #right -\def\doifoddpageelse {\ifodd\pagenoshift\expandafter\doifoddpageelseyes \else\expandafter\doifoddpageelsenop \fi} -\def\doifoddpageelseyes{\ifodd\realpageno \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments \fi} -\def\doifoddpageelsenop{\ifodd\realpageno \expandafter\firstoftwoarguments \else\expandafter\secondoftwoarguments\fi} +\def\doifoddpageelse + {\ifodd\pagenoshift + \expandafter\page_layouts_if_odd_else_yes + \else + \expandafter\page_layouts_if_odd_else_nop + \fi} + +\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} \let\doifonevenpaginaelse\doifoddpageelse -\def\redoifoddpageelse#1{\doifoddpageelse} +\def\page_layouts_if_odd_else_again#1{\doifoddpageelse} \def\doifbothsidesoverruled {\ifdoublesided - \expandafter\redoifoddpageelse + \expandafter\page_layouts_if_odd_else_again \else \expandafter\firstofthreearguments \fi} \def\doifbothsides% #1 #2 #3 {\ifdoublesided - \expandafter\doifbothsidesindeed + \expandafter\page_layouts_if_both_sides \else \expandafter\firstofthreearguments \fi} -\def\doifbothsidesindeed +\def\page_layouts_if_both_sides {\ifsinglesided \expandafter\firstofthreearguments \else - \expandafter\redoifoddpageelse + \expandafter\page_layouts_if_odd_else_again \fi} \newdimen\texthoffset @@ -1179,12 +1210,12 @@ \def\rightorleftpageaction {\ifdoublesided - \expandafter\rightorleftpageactionindeed + \expandafter\page_layouts_right_or_left_page_action \else \expandafter\firstoftwoarguments \fi} -\def\rightorleftpageactionindeed +\def\page_layouts_right_or_left_page_action {\ifsinglesided \expandafter\firstoftwoarguments \else diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index b830dbbb9..4dec0deec 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -134,6 +134,10 @@ function boxed.register(configuration) return last end +function commands.registerlinenumbering(configuration) + context(boxed.register(configuration)) +end + function boxed.setup(n,configuration) local d = data[n] if d then @@ -152,6 +156,8 @@ function boxed.setup(n,configuration) return n end +commands.setuplinenumbering = boxed.setup + local function check_number(n,a,skip,sameline) local d = data[a] if d then @@ -280,3 +286,6 @@ function boxed.stage_two(n,m) end end end + +commands.linenumbersstageone = boxed.stage_one +commands.linenumbersstagetwo = boxed.stage_two diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv index 7b1cbcd94..dd13fb87d 100644 --- a/tex/context/base/page-lin.mkiv +++ b/tex/context/base/page-lin.mkiv @@ -26,20 +26,6 @@ % % we should use normal counters but then we need to sync settings -% not yet ok, we need to give the top line a proper height -% -% \newbox\locallinenumberbox -% -% \unexpanded\def\startlocallinenumbering -% {\setbox\locallinenumberbox\vbox\bgroup -% \startlinenumbering} -% -% \unexpanded\def\stoplocallinenumbering -% {\stoplinenumbering -% \egroup -% \mkdoprocessdeepboxcontents\locallinenumberbox -% \unvbox\locallinenumberbox} - % some line % % \startlocallinenumbering @@ -55,137 +41,96 @@ \definesystemattribute[linenumber] [public] \definesystemattribute[linereference][public] -\appendtoksonce \attribute\linenumberattribute \attributeunsetvalue \to \everyforgetall -\appendtoksonce \attribute\displaymathattribute\plusone \to \everybeforedisplayformula +\appendtoksonce + \attribute\linenumberattribute\attributeunsetvalue +\to \everyforgetall \newcount \linenumber % not used -\newbox \linenumberscratchbox -\newcount \linenumberchunk -\newcount \linerefcounter -\newconstant\linenumbernesting +\newbox \b_page_lines_scratch +\newcount \c_page_lines_reference +\newconstant\c_page_lines_nesting \newconditional\tracelinenumbering -\def\mkprocesstextlinenumbers#1#2% - {\setbox\linenumberscratchbox\vbox - {\forgetall - \offinterlineskip - \ctxlua{nodes.lines.boxed.stage_one(\number#1,\ifcase\linenumbernesting false\else true\fi)}}% #2 - \ctxlua{nodes.lines.boxed.stage_two(\number#1,\number\linenumberscratchbox)}}% can move to lua code - % id nr shift width leftskip dir -\let\makelinenumber\gobblesevenarguments +\installcorenamespace{linenumberinginstance} -\newconditional\boxcontentneedsprocessing +\let\makelinenumber\gobblesevenarguments % used at lua end -\def\mkdoprocesspagecontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone \zerocount} -\def\mkdoprocessboxcontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone \zerocount} -\def\mkdoprocessdeepboxcontents#1{\mkaddtextlinenumbers{#1}\plusone \plusone \plusone } -\def\mkdoprocesscolumncontents #1{\mkaddtextlinenumbers{#1}\currentcolumn\nofcolumns\zerocount} +\newconditional\page_postprocessors_needed_box -\def\mklinenumberparameters - {continue = "\linenumberparameter\c!continue", - start = \linenumberparameter\c!start, - step = \linenumberparameter\c!step, - method = "\linenumberparameter\c!method", - tag = "\currentlinenumbering"} +\unexpanded\def\page_postprocessors_linenumbers_page #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount} +\unexpanded\def\page_postprocessors_linenumbers_box #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount} +\unexpanded\def\page_postprocessors_linenumbers_deepbox#1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \plusone } +\unexpanded\def\page_postprocessors_linenumbers_column #1{\page_lines_add_numbers_to_box{#1}\currentcolumn\nofcolumns\zerocount} -\def\mklinenumberupdateparameters - {continue = "\linenumberparameter\c!continue"} +\def\page_lines_parameters_regular + {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi", + start = \number\linenumberingparameter\c!start, + step = \number\linenumberingparameter\c!step, + method = "\linenumberingparameter\c!method", + tag = "\currentlinenumbering"} -\def\mkdefinetextlinenumbering - {\setxvalue{ln:c:\currentlinenumbering}{\number\cldcontext{nodes.lines.boxed.register({\mklinenumberparameters})}}} +\def\page_lines_parameters_update + {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi"} -\def\mkupdatetextlinenumbering - {\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberupdateparameters})}} +\def\page_lines_start_define + {\setxvalue{\??linenumberinginstance\currentlinenumbering}{\ctxcommand{registerlinenumbering({\page_lines_parameters_regular})}}} -\def\mkstarttextlinenumbering#1#2% always when assignment - {\globallet\mkprocesspagecontents \mkdoprocesspagecontents - \globallet\mkprocesscolumncontents\mkdoprocesscolumncontents - \global\settrue\boxcontentneedsprocessing % see core-rul.mkiv - \edef\currentlinenumbering{#1}% - \ifcase#2\relax - \mkupdatetextlinenumbering % continue - \or - \mkdefinetextlinenumbering % only when assignment - \fi - \attribute\linenumberattribute\getvalue{ln:c:\currentlinenumbering}\relax} +\def\page_lines_start_update + {\ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_update})}} -\def\mksetuptextlinenumbering - {\ifcsname ln:c:\currentlinenumbering\endcsname - \ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberparameters})}% +\def\page_lines_setup + {\ifcsname \??linenumberinginstance\currentlinenumbering\endcsname + \ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_regular})}% \fi} -\def\mkstoptextlinenumbering - {\attribute\linenumberattribute\attributeunsetvalue} - % we could make this a bit more efficient by putting the end reference % in the same table as the start one but why make things complex ... -\let\dofinishlinereference\dofinishfullreference +\let\dofinishlinereference\dofinishfullreference % at lua end -\def\mksomelinereference#1#2#3% +\unexpanded\def\page_lines_some_reference#1#2#3% {\dontleavehmode\begingroup - \global\advance\linerefcounter\plusone - \attribute\linereferenceattribute\linerefcounter + \global\advance\c_page_lines_reference\plusone + \attribute\linereferenceattribute\c_page_lines_reference #3% % for the moment we use a simple system i.e. no prefixes etc .. todo: store as number - \expanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberparameter\c!conversion}{\the\linerefcounter}}% kind labels userdata text + \normalexpanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberingparameter\c!conversion}{\the\c_page_lines_reference}}% kind labels userdata text \endgroup} -\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{}\ignorespaces} -\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{}} +\def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{}\ignorespaces} +\def\page_lines_reference_stop #1{\removeunwantedspaces\page_lines_some_reference{#1}{lr:e:#1}{}} + +% \def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced/ not used +% \def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced/ not used -\def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced -\def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced +\newif\ifnumberinglines % will change +\newif\iftypesettinglines % will change -% high level interface +\installcorenamespace{linenumbering} -\newif\ifnumberinglines -\newif\iftypesettinglines +\installcommandhandler \??linenumbering {linenumbering} \??linenumbering -\let\currentlinenumbering\empty +\setnewconstant\c_page_lines_mode \plusone % 0=continue, 1=restart +\setnewconstant\c_page_lines_location \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end +\setnewconstant\c_page_lines_alignment\plusfive % 0=middle, 1=left, 2=right, 5=auto -\setnewconstant\linenumbermode \plusone % 0=continue, 1=restart -\setnewconstant\linenumberlocation \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end -\setnewconstant\linenumberalignment\plusfive % 0=middle, 1=left, 2=right, 5=auto +\newdimen\d_page_lines_width +\newdimen\d_page_lines_distance \newevery \beforeeverylinenumbering \relax \newevery \aftereverylinenumbering \relax \newevery \everylinenumber \relax -\newdimen\linenumberwidth -\newdimen\linenumberdistance - -\unexpanded\def\definelinenumbering - {\dosingleempty\dodefinelinenumbering} +\appendtoks + \page_lines_setup +\to \everysetuplinenumbering -\def\dodefinelinenumbering[#1]% - {\edef\currentlinenumbering{#1}% - \mkdefinetextlinenumbering} - -\unexpanded\def\setuplinenumbering - {\dodoubleempty\dosetuplinenumbering} - -\def\dosetuplinenumbering[#1][#2]% - {\ifsecondargument - \def\currentlinenumbering{#1}% - \getparameters[\??rn#1][#2]% - \else - \let\currentlinenumbering\empty - \getparameters[\??rn][#1]% - \fi - \mksetuptextlinenumbering} - -% some day commandhandler - -\def\linenumberparameter#1% - {\csname\??rn\ifcsname\??rn\currentlinenumbering#1\endcsname\currentlinenumbering\fi#1\endcsname} - -\unexpanded\def\dolinenumberattributes#1#2% - {\dousestyleparameter{\linenumberparameter#1}% - \dousecolorparameter{\linenumberparameter#2}} +\appendtoks + \page_lines_start_define +\to \everydefinelinenumbering \setuplinenumbering [\c!conversion=\v!numbers, @@ -196,7 +141,7 @@ \c!location=\v!left, \c!style=, \c!color=, - \c!width=2em, + \c!width=2\emwidth, \c!left=, \c!right=, \c!command=, @@ -204,253 +149,314 @@ \c!align=\v!auto] \definelinenumbering - -\unexpanded\def\startlinenumbering - {\dodoubleempty\dostartlinenumbering} + [] % no intermediate changes in values, define a class, otherwise each range % would need a number % todo: text -\expandafter\let\csname\??rn:l:\v!middle \endcsname \zerocount -\expandafter\let\csname\??rn:l:\v!left \endcsname \plusone -\expandafter\let\csname\??rn:l:\v!margin \endcsname \plusone -\expandafter\let\csname\??rn:l:\v!inmargin \endcsname \plusone -\expandafter\let\csname\??rn:l:\v!inleft \endcsname \plusone -\expandafter\let\csname\??rn:l:\v!right \endcsname \plustwo -\expandafter\let\csname\??rn:l:\v!inright \endcsname \plustwo -\expandafter\let\csname\??rn:l:\v!inner \endcsname \plusthree -\expandafter\let\csname\??rn:l:\v!outer \endcsname \plusfour -\expandafter\let\csname\??rn:l:\v!text \endcsname \plusfive -\expandafter\let\csname\??rn:l:\v!begin \endcsname \plussix -\expandafter\let\csname\??rn:l:\v!end \endcsname \plusseven - -\expandafter\let\csname\??rn:a:\v!middle \endcsname \zerocount -\expandafter\let\csname\??rn:a:\v!right \endcsname \plusone -\expandafter\let\csname\??rn:a:\v!flushleft \endcsname \plusone -\expandafter\let\csname\??rn:a:\v!left \endcsname \plustwo -\expandafter\let\csname\??rn:a:\v!flushright\endcsname \plustwo -\expandafter\let\csname\??rn:a:\v!auto \endcsname \plusfive - -\def\dostartlinenumbering[#1][#2]% todo: c!continue +\installcorenamespace{linennumberinglocation} +\installcorenamespace{linennumberingalternative} + +\expandafter\let\csname\??linennumberinglocation\v!middle \endcsname \zerocount +\expandafter\let\csname\??linennumberinglocation\v!left \endcsname \plusone +\expandafter\let\csname\??linennumberinglocation\v!margin \endcsname \plusone +\expandafter\let\csname\??linennumberinglocation\v!inmargin \endcsname \plusone +\expandafter\let\csname\??linennumberinglocation\v!inleft \endcsname \plusone +\expandafter\let\csname\??linennumberinglocation\v!right \endcsname \plustwo +\expandafter\let\csname\??linennumberinglocation\v!inright \endcsname \plustwo +\expandafter\let\csname\??linennumberinglocation\v!inner \endcsname \plusthree +\expandafter\let\csname\??linennumberinglocation\v!outer \endcsname \plusfour +\expandafter\let\csname\??linennumberinglocation\v!text \endcsname \plusfive +\expandafter\let\csname\??linennumberinglocation\v!begin \endcsname \plussix +\expandafter\let\csname\??linennumberinglocation\v!end \endcsname \plusseven + +\expandafter\let\csname\??linennumberingalternative\v!middle \endcsname \zerocount +\expandafter\let\csname\??linennumberingalternative\v!right \endcsname \plusone +\expandafter\let\csname\??linennumberingalternative\v!flushleft \endcsname \plusone +\expandafter\let\csname\??linennumberingalternative\v!left \endcsname \plustwo +\expandafter\let\csname\??linennumberingalternative\v!flushright\endcsname \plustwo +\expandafter\let\csname\??linennumberingalternative\v!auto \endcsname \plusfive + +% \startlinenumbering[<startvalue>|continue|settings|name] +% \startlinenumbering[name][<startvalue>|continue|settings] + +\unexpanded\def\startlinenumbering + {\dodoubleempty\page_lines_start} + +\def\page_lines_start % we stay downward compatible {\begingroup - \linenumbermode\plusone \ifsecondargument - \def\currentlinenumbering{#1}% - \doifassignmentelse{#2} - {\getparameters[\??rn\currentlinenumbering][#2]} - {\doifnumberelse{#2}% downward compatible - {\setvalue{\??rn#1\c!start}{#2}}% - {\doif{#2}\v!continue - {\getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]% - \linenumbermode\zerocount}}}% + \expandafter\page_lines_start_two \else\iffirstargument - \doifnumberelse{#1}% downward compatible - {\let\currentlinenumbering\empty - \setvalue{\??rn\c!start}{#1}}% - {\doifelse{#1}\v!continue - {\let\currentlinenumbering\empty - \getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]% - \linenumbermode\zerocount} - {\def\currentlinenumbering{#1}}}% - \fi\fi - \doif{\linenumberparameter\c!continue}\v!yes - {\linenumbermode\zerocount}% - \numberinglinestrue + \doubleexpandafter\page_lines_start_one + \else + \doubleexpandafter\page_lines_start_zero + \fi\fi} + +\def\page_lines_start_zero[#1][#2]% + {\edef\m_argument{\linenumberingparameter\c!continue}% + \ifx\m_argument\v!continue + \c_page_lines_mode\zerocount + \else + \c_page_lines_mode\plusone + \fi + \page_lines_start_followup} + +\def\page_lines_start_one[#1][#2]% [continue|<number>|settings] % historic + {\edef\m_argument{#1}% + \ifx\m_argument\v!continue + \c_page_lines_mode\zerocount + \let\currentlinenumbering\empty + \else + \c_page_lines_mode\plusone + \ifx\m_argument\v!empty + \let\currentlinenumbering\empty + \else + \doifassignmentelse{#1} + {\let\currentlinenumbering\empty + \setupcurrentlinenumbering[#1]} + {\doifnumberelse\m_argument + {\let\currentlinenumbering\empty + \letlinenumberingparameter\c!start\m_argument} + {\let\currentlinenumbering\m_argument}}% + \fi + \edef\m_argument{\linenumberingparameter\c!continue}% + \ifx\m_argument\v!continue + \c_page_lines_mode\zerocount + \fi + \fi + \page_lines_start_followup} + +\def\page_lines_start_two[#1][#2]% [tag][continue|<number>|settings] + {\edef\currentlinenumbering{#1}% + \edef\m_argument{#2}% + \ifx\m_argument\v!continue + \c_page_lines_mode\zerocount + \else + \c_page_lines_mode\plusone + \ifx\m_argument\v!empty \else + \doifassignmentelse{#2} + {\setupcurrentlinenumbering[#2]} + {\doifnumber\m_argument + {\letlinenumberingparameter\c!start\m_argument}}% + \fi + \edef\m_argument{\linenumberingparameter\c!continue}% + \ifx\m_argument\v!continue + \c_page_lines_mode\zerocount + \fi + \fi + \page_lines_start_followup} + +\def\page_lines_start_followup + {\numberinglinestrue \the\beforeeverylinenumbering - \mkstarttextlinenumbering\currentlinenumbering\linenumbermode} + \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page + \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column + \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv + \ifcase\c_page_lines_mode\relax + \page_lines_start_update % continue + \or + \page_lines_start_define % only when assignment + \fi + \attribute\linenumberattribute\getvalue{\??linenumberinginstance\currentlinenumbering}\relax} \unexpanded\def\stoplinenumbering - {\mkstoptextlinenumbering + {\attribute\linenumberattribute\attributeunsetvalue \the\aftereverylinenumbering \endgroup} % number placement .. will change into (the new) margin code -\def\mkdoinnerlinenumber{\doifoddpageelse\mkdoleftlinenumber\mkdorightlinenumber} -\def\mkdoouterlinenumber{\doifoddpageelse\mkdorightlinenumber\mkdoleftlinenumber} +\def\page_lines_number_inner_indeed{\doifoddpageelse\page_lines_number_left_indeed\page_lines_number_right_indeed} +\def\page_lines_number_outer_indeed{\doifoddpageelse\page_lines_number_right_indeed\page_lines_number_left_indeed} -\def\mkleftlinenumber - {\ifcase\linenumberlocation - \expandafter\mkdoleftlinenumber +\def\page_lines_number_left + {\ifcase\c_page_lines_location + \expandafter\page_lines_number_left_indeed \or - \expandafter\mkdoleftlinenumber + \expandafter\page_lines_number_left_indeed \or - \expandafter\mkdoleftlinenumber + \expandafter\page_lines_number_left_indeed \or - \expandafter\mkdoinnerlinenumber + \expandafter\page_lines_number_inner_indeed \or - \expandafter\mkdoouterlinenumber + \expandafter\page_lines_number_outer_indeed \or - \expandafter\mkdotextlinenumber + \expandafter\page_lines_number_text_indeed \or - \expandafter\mkdobeginlinenumber + \expandafter\page_lines_number_begin_indeed \or - \expandafter\mkdoendlinenumber + \expandafter\page_lines_number_end_indeed \fi} -\def\mkrightlinenumber - {\ifcase\linenumberlocation - \expandafter\mkdorightlinenumber +\def\page_lines_number_right + {\ifcase\c_page_lines_location + \expandafter\page_lines_number_right_indeed \or - \expandafter\mkdorightlinenumber + \expandafter\page_lines_number_right_indeed \or - \expandafter\mkdorightlinenumber + \expandafter\page_lines_number_right_indeed \or - \expandafter\mkdoouterlinenumber + \expandafter\page_lines_number_outer_indeed \or - \expandafter\mkdoinnerlinenumber + \expandafter\page_lines_number_inner_indeed \or - \expandafter\mkdotextlinenumber + \expandafter\page_lines_number_text_indeed \or - \expandafter\mkdoendlinenumber + \expandafter\page_lines_number_end_indeed \or - \expandafter\mkdobeginlinenumber + \expandafter\page_lines_number_begin_indeed \fi} -\newconditional\faketextlinenumber -\newconstant \linenumberbox -\newconstant \linenumbercolumn -\newconstant \linenumberlastcolumn +\newconditional\c_page_lines_fake_number +\newconstant \b_page_lines_number +\newconstant \c_page_lines_column +\newconstant \c_page_lines_last_column -\def\mkaddtextlinenumbers#1#2#3#4% box col max nesting +\def\page_lines_add_numbers_to_box#1#2#3#4% box col max nesting {\bgroup - \linenumberbox #1\relax - \linenumbercolumn #2\relax - \linenumberlastcolumn#3\relax - \linenumbernesting #4\relax + \b_page_lines_number #1\relax + \c_page_lines_column #2\relax + \c_page_lines_last_column#3\relax + \c_page_lines_nesting #4\relax \fullrestoreglobalbodyfont - \let\makelinenumber\maketextlinenumber - \mkprocesstextlinenumbers\linenumberbox\linenumbernesting + \let\makelinenumber\page_lines_make_number % used at lua end + \setbox\b_page_lines_scratch\vbox + {\forgetall + \offinterlineskip + \ctxcommand{linenumbersstageone(\number\b_page_lines_number,\ifcase\c_page_lines_nesting false\else true\fi)}}% + \ctxcommand{linenumbersstagetwo(\number\b_page_lines_number,\number\b_page_lines_scratch)}% can move to lua code \egroup} -\def\maketextlinenumber#1#2% +\let\page_lines_make_number_indeed\relax + +\def\page_lines_make_number#1#2% {\edef\currentlinenumbering{#1}% \ifcase#2\relax - \settrue \faketextlinenumber + \settrue \c_page_lines_fake_number \else - \setfalse\faketextlinenumber + \setfalse\c_page_lines_fake_number \fi - \linenumberlocation \executeifdefined{\??rn:l:\linenumberparameter\c!location}\plusone % left - \linenumberalignment\executeifdefined{\??rn:a:\linenumberparameter\c!align }\plusfive % auto - \ifcase\linenumberlastcolumn\relax - \settrue \faketextlinenumber + \c_page_lines_location \executeifdefined{\??linennumberinglocation \linenumberingparameter\c!location}\plusone \relax % left + \c_page_lines_alignment\executeifdefined{\??linennumberingalternative\linenumberingparameter\c!align }\plusfive\relax % auto + \ifcase\c_page_lines_last_column\relax + \settrue \c_page_lines_fake_number \or % one column - \ifcase\linenumberlocation - \settrue \faketextlinenumber - % hm + \ifcase\c_page_lines_location + \settrue \c_page_lines_fake_number + \let\page_lines_make_number_indeed\page_lines_number_fake_indeed \or - \let\domakelinenumber\mkleftlinenumber + \let\page_lines_make_number_indeed\page_lines_number_left \or - \let\domakelinenumber\mkrightlinenumber + \let\page_lines_make_number_indeed\page_lines_number_right \or % inner - \let\domakelinenumber\mkdoinnerlinenumber + \let\page_lines_make_number_indeed\page_lines_number_inner_indeed \or % outer - \let\domakelinenumber\mkdoouterlinenumber + \let\page_lines_make_number_indeed\page_lines_number_outer_indeed \or % text - \let\domakelinenumber\mkdotextlinenumber + \let\page_lines_make_number_indeed\page_lines_number_text_indeed \or - \let\domakelinenumber\mkdobeginlinenumber + \let\page_lines_make_number_indeed\page_lines_number_begin_indeed \or - \let\domakelinenumber\mkdoendlinenumber + \let\page_lines_make_number_indeed\page_lines_number_end_indeed \fi - \else\ifcase\linenumbercolumn\relax - \settrue \faketextlinenumber + \else\ifcase\c_page_lines_column\relax + \settrue \c_page_lines_fake_number \or - \let\domakelinenumber\mkleftlinenumber - \ifcase\linenumberlocation\or - \linenumberlocation\plusone + \let\page_lines_make_number_indeed\page_lines_number_left + \ifcase\c_page_lines_location\or + \c_page_lines_location\plusone \or - \linenumberlocation\plustwo + \c_page_lines_location\plustwo \else - \linenumberlocation\plusone + \c_page_lines_location\plusone \or - \linenumberlocation\plusone + \c_page_lines_location\plusone \or - \linenumberlocation\plusone + \c_page_lines_location\plusone \or - \linenumberlocation\plusone % todo + \c_page_lines_location\plusone % todo \or - \linenumberlocation\plusone % todo + \c_page_lines_location\plusone % todo \fi \else - \let\domakelinenumber\mkrightlinenumber - \ifcase\linenumberlocation\or - \linenumberlocation\plustwo + \let\page_lines_make_number_indeed\page_lines_number_right + \ifcase\c_page_lines_location\or + \c_page_lines_location\plustwo \or - \linenumberlocation\plusone + \c_page_lines_location\plusone \or - \linenumberlocation\plustwo + \c_page_lines_location\plustwo \or - \linenumberlocation\plustwo + \c_page_lines_location\plustwo \or - \linenumberlocation\plustwo % todo + \c_page_lines_location\plustwo % todo \or - \linenumberlocation\plustwo % todo + \c_page_lines_location\plustwo % todo \fi \fi\fi - \domakelinenumber{#1}} + \page_lines_make_number_indeed{#1}} -\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width ! - {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}} +\let\page_lines_number_fake_indeed\gobblesixarguments % needs checking -\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width ! - {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}} +\def\page_lines_number_text_indeed#1#2#3#4#5#6% beware, one needs so compensate for this in the \hsize + {\hbox{\page_lines_number_construct{#1}{2}{#2}{#5}\hskip#3\scaledpoint}} -\def\mkdoleftlinenumber #1#2#3#4#5#6% +\def\page_lines_number_left_indeed#1#2#3#4#5#6% {\naturalhbox to \zeropoint {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi - \llap{\dosomelinenumber{#1}{2}{#2}{#5}\kern#3\scaledpoint}}} + \llap{\page_lines_number_construct{#1}{2}{#2}{#5}\kern#3\scaledpoint}}} -\def\mkdorightlinenumber#1#2#3#4#5#6% +\def\page_lines_number_right_indeed#1#2#3#4#5#6% {\naturalhbox to \zeropoint {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi - \rlap{\hskip#4\scaledpoint\hskip#3\scaledpoint\dosomelinenumber{#1}{1}{#2}{#5}}}} + \rlap{\hskip\dimexpr#4\scaledpoint+#3\scaledpoint\relax\page_lines_number_construct{#1}{1}{#2}{#5}}}} -\def\mkdobeginlinenumber #1#2#3#4#5#6% +\def\page_lines_number_begin_indeed#1#2#3#4#5#6% {\ifcase\istltdir#6\relax - \linenumberlocation\plusone - \expandafter\mkdoleftlinenumber + \c_page_lines_location\plusone + \expandafter\page_lines_number_left_indeed \else - \linenumberlocation\plustwo - \expandafter\mkdorightlinenumber + \c_page_lines_location\plustwo + \expandafter\page_lines_number_left_indeed \fi{#1}{#2}{#3}{#4}{#5}{#6}} -\def\mkdoendlinenumber#1#2#3#4#5#6% +\def\page_lines_number_end_indeed#1#2#3#4#5#6% {\ifcase\istltdir#6\relax - \linenumberlocation\plustwo - \expandafter\mkdorightlinenumber + \c_page_lines_location\plustwo + \expandafter\page_lines_number_left_indeed \else - \linenumberlocation\plusone - \expandafter\mkdoleftlinenumber + \c_page_lines_location\plusone + \expandafter\page_lines_number_left_indeed \fi{#1}{#2}{#3}{#4}{#5}{#6}} -\def\dosomelinenumber#1#2#3#4% tag 1=left|2=right linenumber leftskip +\def\page_lines_number_construct#1#2#3#4% tag 1=left|2=right linenumber leftskip {\begingroup \def\currentlinenumbering{#1}% \def\linenumber{#3}% unsafe - \doifelse{\linenumberparameter\c!width}\v!margin - {\linenumberwidth\leftmarginwidth} - {\linenumberwidth\linenumberparameter\c!width}% - \linenumberdistance\linenumberparameter\c!distance\relax - \ifcase#2\relax\or\hskip\linenumberdistance\fi\relax - \ifnum\linenumberlocation=\plusfive - \scratchdimen\dimexpr#4\scaledpoint-\linenumberdistance\relax - \linenumberlocation\plusone + \doifelse{\linenumberingparameter\c!width}\v!margin + {\d_page_lines_width\leftmarginwidth} + {\d_page_lines_width\linenumberingparameter\c!width}% + \d_page_lines_distance\linenumberingparameter\c!distance\relax + \ifcase#2\relax\or\hskip\d_page_lines_distance\fi\relax + \ifnum\c_page_lines_location=\plusfive + \scratchdimen\dimexpr#4\scaledpoint-\d_page_lines_distance\relax + \c_page_lines_location\plusone \else \scratchdimen\zeropoint \fi - \ifcase\linenumberalignment - \linenumberlocation\zerocount % middle + \ifcase\c_page_lines_alignment + \c_page_lines_location\zerocount % middle \or - \linenumberlocation\plusone % left + \c_page_lines_location\plusone % left \or - \linenumberlocation\plustwo % right + \c_page_lines_location\plustwo % right \fi - \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \linenumberwidth - {\ifcase\linenumberlocation + \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \d_page_lines_width + {\ifcase\c_page_lines_location \hss % middle \or % left @@ -461,16 +467,16 @@ \or \doifoddpageelse\hss\relax % outer \fi - \ifconditional\faketextlinenumber + \ifconditional\c_page_lines_fake_number % we need to reserve space \else - \dolinenumberattributes\c!style\c!color - \linenumberparameter\c!command - {\linenumberparameter\c!left - \convertnumber{\linenumberparameter\c!conversion}{#3}% - \linenumberparameter\c!right}% + \uselinenumberingstyleandcolor\c!style\c!color + \linenumberingparameter\c!command + {\linenumberingparameter\c!left + \convertnumber{\linenumberingparameter\c!conversion}{#3}% + \linenumberingparameter\c!right}% \fi - \ifcase\linenumberlocation + \ifcase\c_page_lines_location \hss % middle \or \hss % left @@ -481,53 +487,60 @@ \or \doifoddpageelse\relax\hss % outer \fi}% - \ifcase#2\relax\or\or\hskip\linenumberdistance\fi\relax - \hskip-\scratchdimen + \ifcase#2\relax + \hskip-\scratchdimen + \or + \hskip-\scratchdimen + \or + \hskip\dimexpr\d_page_lines_distance-\scratchdimen\relax + \fi + \relax \the\everylinenumber \endgroup} -% left right inner outer - -% align: \alignedline\@@rnalign\v!right{\box0\hskip\@@rndistance} - % referencing -\unexpanded\def\someline [#1]{\mkstartlinereference{#1}\mkstoplinereference{#1}} % was just a def -\unexpanded\def\startline[#1]{\mkstartlinereference{#1}} -\unexpanded\def\stopline [#1]{\mkstoplinereference {#1}} +\unexpanded\def\someline [#1]{\page_lines_reference_start{#1}\page_lines_reference_stop{#1}} % was just a def +\unexpanded\def\startline[#1]{\page_lines_reference_start{#1}} +\unexpanded\def\stopline [#1]{\page_lines_reference_stop {#1}} -\def\mkshowstartlinereference#1% +\def\page_lines_reference_show_start#1% {\ifconditional\tracelinenumbering \setbox\scratchbox\hbox{\llap - {\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}% - \smashbox\scratchbox\box\scratchbox + {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}% + \smashbox\scratchbox + \box\scratchbox \fi} -\def\mkshowstoplinereference#1% +\def\page_lines_reference_show_stop#1% {\ifconditional\tracelinenumbering \setbox\scratchbox\hbox{\rlap - {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht}}% - \smashbox\scratchbox\box\scratchbox + {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}% + \smashbox\scratchbox + \box\scratchbox \fi} -\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{\mkshowstartlinereference{#1}}\ignorespaces} -\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{\mkshowstoplinereference{#1}}} +\def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{\page_lines_reference_show_start{#1}}\ignorespaces} +\def\page_lines_reference_stop #1{\removeunwantedspaces\page_lines_some_reference{#1}{lr:e:#1}{\page_lines_reference_show_stop{#1}}} % eventually we will do this in lua -\def\currentreferencelinenumber{\ctxlua{structures.references.filter("linenumber")}} +\def\currentreferencelinenumber{\ctxcommand{filterreference("linenumber")}} + +\let\m_page_lines_from\empty +\let\m_page_lines_to \empty -\def\doifelsesamelinereference#1#2#3% +\unexpanded\def\doifelsesamelinereference#1#2#3% {\doifreferencefoundelse{lr:b:#1} - {\edef\fline{\currentreferencelinenumber}% + {\edef\m_page_lines_from{\currentreferencelinenumber}% \doifreferencefoundelse{lr:e:#1} - {\edef\tline{\currentreferencelinenumber}% - %[\fline,\tline] - \ifx\fline\tline#2\else#3\fi} + {\edef\m_page_lines_to{\currentreferencelinenumber}% + %[\m_page_lines_from,\m_page_lines_to] + \ifx\m_page_lines_from\m_page_lines_to#2\else#3\fi} {#2}} {#2}} -\def\inline#1[#2]% +\unexpanded\def\inline#1[#2]% {\doifelsenothing{#1} {\doifelsesamelinereference{#2} {\in{\leftlabeltext\v!line}{\rightlabeltext\v!line}[lr:b:#2]} @@ -536,9 +549,9 @@ {\in{#1}[lr:b:#2]} {\in{#1}[lr:b:#2]--\in[lr:e:#2]}}} -\def\inlinerange[#1]% +\unexpanded\def\inlinerange[#1]% {\doifelsesamelinereference{#1} {\in[lr:b:#1]} - {\in[lr:b:#1]--\in[lr:e:#1]}} + {\in[lr:b:#1]\endash\in[lr:e:#1]}} \protect \endinput diff --git a/tex/context/base/page-mak.mkvi b/tex/context/base/page-mak.mkvi index f37c4f613..6120f56bb 100644 --- a/tex/context/base/page-mak.mkvi +++ b/tex/context/base/page-mak.mkvi @@ -88,7 +88,10 @@ \newbox \b_page_makeup \newtoks\t_page_makeup_every_setup -\def\page_makeup_start_yes[#name][#settings]% +\def\page_makeup_start_yes[#name]% [#settings]% + {\doifelsecommandhandler\??makeup{#name}\page_makeup_start_indeed\page_makeup_start_nop[#name]}% + +\def\page_makeup_start_indeed[#name][#settings]% {\doifelsenothing{\namedmakeupparameter{#name}\c!page} {\page}% new, so best not have dangling mess here like references (we could capture then and flush embedded) {\page[\namedmakeupparameter{#name}\c!page]}% @@ -113,22 +116,23 @@ {\endgraf \makeupparameter\c!bottom \egroup - \pushpagestate % new - \makeupparameter\c!before - \relax % to be sure we don't enter the \if - \ifdim\ht\b_page_makeup>\vsize - \ht\b_page_makeup\vsize % is already set to \textheight (maybe set dp to 0) - \fi - \setuppagenumber[\c!state=\makeupparameter\c!pagestate]% - \box\b_page_makeup - \the\t_page_makeup_every_setup - \page - \makeupparameter\c!after - \relax % to be sure we don't enter the \if + \strc_pagenumbers_page_state_push % new + \makeupparameter\c!before\relax + \begingroup + \ifdim\ht\b_page_makeup>\vsize + \ht\b_page_makeup\vsize % is already set to \textheight (maybe set dp to 0) + \fi + \setuppagenumber[\c!state=\makeupparameter\c!pagestate]% + \doif{\makeupparameter\c!location}\v!top{\topskip\zeropoint}% + \box\b_page_makeup + \the\t_page_makeup_every_setup + \page + \endgroup + \makeupparameter\c!after\relax \ifdoublesided \ifodd\realpageno \else \getvalue{\??makeupdoublesided\makeupparameter\c!doublesided}% \fi \fi - \poppagestate % new + \strc_pagenumbers_page_state_pop % new \egroup \stoplayout} % includes \page @@ -166,6 +170,7 @@ %\c!align=, %\c!before=, %\c!after=, + %\c!location=, \c!page=\v!right, \c!doublesided=\v!empty, \c!top=\vss, diff --git a/tex/context/base/page-mbk.mkvi b/tex/context/base/page-mbk.mkvi index eb8061bf3..9e3e57193 100644 --- a/tex/context/base/page-mbk.mkvi +++ b/tex/context/base/page-mbk.mkvi @@ -220,9 +220,9 @@ \box\floatbox \filbreak}% \ifdim\ht\b_page_margin_blocks>\textheight - % \dosavefloatinfo % no saving done anyway + % page_floats_report_saved % no saving done anyway \else - \doinsertfloatinfo + \page_floats_report_total \fi} \def\page_margin_blocks_process_float_nop diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua new file mode 100644 index 000000000..be87b79a7 --- /dev/null +++ b/tex/context/base/page-mix.lua @@ -0,0 +1,642 @@ +if not modules then modules = { } end modules ['page-mix'] = { + version = 1.001, + comment = "companion to page-mix.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- inserts.getname(name) + +-- local node, tex = node, tex +-- local nodes, interfaces, utilities = nodes, interfaces, utilities +-- local trackers, logs, storage = trackers, logs, storage +-- local number, table = number, table + +local concat = table.concat + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local nodepool = nodes.pool + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local insert_code = nodecodes.ins +local mark_code = nodecodes.mark + +local new_hlist = nodepool.hlist +local new_vlist = nodepool.vlist +local new_glue = nodepool.glue + +local hpack = node.hpack +local vpack = node.vpack +local freenode = node.free + +local texbox = tex.box +local texskip = tex.skip +local texdimen = tex.dimen +local points = number.points +local settings_to_hash = utilities.parsers.settings_to_hash + +local variables = interfaces.variables +local v_yes = variables.yes +local v_global = variables["global"] +local v_local = variables["local"] +local v_columns = variables.columns + +local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end) +local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end) + +local report_state = logs.reporter("mixed columns") + +pagebuilders = pagebuilders or { } +pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { } +local mixedcolumns = pagebuilders.mixedcolumns + +local forcedbreak = -123 + +-- initializesplitter(specification) +-- cleanupsplitter() + +-- Inserts complicate matters a lot. In order to deal with them well, we need to +-- distinguish several cases. +-- +-- (1) full page columns: firstcolumn, columns, lastcolumn, page +-- (2) mid page columns : firstcolumn, columns, lastcolumn, page +-- +-- We need to collect them accordingly. + +local function collectinserts(result,nxt,nxtid) + local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0 + while nxt do + if nxtid == insert_code then + inserttotal = inserttotal + nxt.height + nxt.depth + local s = nxt.subtype +-- print(">>>",structures.inserts.getlocation(s)) + local c = inserts[s] + if not c then + c = { } + inserts[s] = c + local width = texskip[s].width + if not result.inserts[s] then + currentskips = currentskips + width + end + nextskips = nextskips + width + end + c[#c+1] = nxt + if trace_detail then + report_state("insert of class %s found",s) + end + elseif nxtid == mark_code then + if trace_detail then + report_state("mark found") + end + else + break + end + nxt = nxt.next + if nxt then + nxtid = nxt.id + else + break + end + end + return nxt, inserts, currentskips, nextskips, inserttotal +end + +local function appendinserts(ri,inserts) + for class, collected in next, inserts do + local ric = ri[class] + if not ric then + -- assign to collected + ri[class] = collected + else + -- append to collected + for j=1,#collected do + ric[#ric+1] = collected[j] + end + end + end +end + +local function discardtopglue(current,discarded) + while current do + local id = current.id + if id == glue_code or (id == penalty_code and current.penalty ~= forcedbreak) then + discarded[#discarded+1] = current + current = current.next + else + break + end + end + return current +end + +local function stripbottomglue(results,discarded) + local height = 0 + for i=1,#results do + local r = results[i] + local t = r.tail + while t and t ~= r.head do + local prev = t.prev + if not prev then + break + elseif t.id == penalty_code then + if t.penalty == forcedbreak then + break + else + discarded[#discarded+1] = t + r.tail = prev + t = prev + end + elseif t.id == glue_code then + discarded[#discarded+1] = t + r.height = r.height - t.spec.width + r.tail = prev + t = prev + else + break + end + end + if r.height > height then + height = r.height + end + end + return height +end + +local function setsplit(specification) -- a rather large function + local box = specification.box + if not box then + report_state("fatal error, no box") + return + end + local list = texbox[box] + if not list then + report_state("fatal error, no list") + return + end + local head = list.head or specification.originalhead + if not head then + report_state("fatal error, no head") + return + end + local discarded = { } + local originalhead = head + local originalwidth = specification.originalwidth or list.width + local originalheight = specification.originalheight or list.height + local current = head + local height = 0 + local depth = 0 + local skip = 0 + local options = settings_to_hash(specification.option or "") + local stripbottom = specification.alternative == v_local + local cycle = specification.cycle or 1 + local nofcolumns = specification.nofcolumns or 1 + if nofcolumns == 0 then + nofcolumns = 1 + end + local preheight = specification.preheight or 0 + local extra = specification.extra or 0 + local maxheight = specification.maxheight + local optimal = originalheight/nofcolumns + if specification.balance ~= v_yes then + optimal = maxheight + end + local target = optimal + extra + local overflow = target > maxheight - preheight + local threshold = specification.threshold or 0 + if overflow then + target = maxheight - preheight + end + if trace_state then + report_state("cycle: %s, maxheight: %s, preheight: %s, target: %s, overflow: %s, extra: %s", + cycle, points(maxheight),points(preheight),points(target),tostring(overflow),points(extra)) + end + local results = { } + for i=1,nofcolumns do + results[i] = { + head = false, + tail = false, + height = 0, + depth = 0, + inserts = { }, + delta = 0, + } + end + local column = 1 + local result = results[column] + local lasthead = nil + local rest = nil + local function gotonext() + if head == lasthead then + if trace_state then + report_state("empty column %s, needs more work",column) + end +rest = current +return false + else + lasthead = head + result.head = head + if current == head then + result.tail = head + else + result.tail = current.prev + end + result.height = height + result.depth = depth + end + head = current + height = 0 + depth = 0 + skip = 0 + if column == nofcolumns then + column = 0 -- nicer in trace + rest = head +-- lasthead = head + return false + else + column = column + 1 + result = results[column] + current = discardtopglue(current,discarded) + head = current +-- lasthead = head + return true + end + end + local function checked(advance) + local total = skip + height + depth + advance + local delta = total - target + if trace_detail then + local currentcolumn = column + local state + if delta > threshold then + result.delta = delta + if gotonext() then + state = "next" + else + state = "quit" + end + else + state = "same" + end + if trace_detail then + report_state("check > column %s, advance: %s, total: %s, target: %s => %s (height: %s, depth: %s, skip: %s)", + currentcolumn,points(advance),points(total),points(target),state,points(height),points(depth),points(skip)) + end + return state + else + if delta > threshold then + result.delta = delta + if gotonext() then + return "next" + else + return "quit" + end + else + return "same" + end + end + end + current = discardtopglue(current,discarded) + head = current + while current do + local id = current.id + local nxt = current.next + if id == hlist_code or id == vlist_code then + local nxtid = nxt and nxt.id + local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0 + local advance = current.height -- + current.depth + if nxt and (nxtid == insert_code or nxtid == mark_code) then + nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid) + end + local state = checked(advance+inserttotal+currentskips) + if trace_state then + report_state('line > column %s, advance: %s, insert: %s, height: %s, state: %s', + column,points(advance),points(inserttotal),points(height),state) + end + if state == "quit" then + break + else + height = height + depth + skip + advance + inserttotal + if state == "next" then + height = height + nextskips + else + height = height + currentskips + end + end + depth = current.depth + skip = 0 + if inserts then + appendinserts(result.inserts,inserts) + end + elseif id == glue_code then + local advance = current.spec.width + if advance ~= 0 then + local state = checked(advance) + if trace_state then + report_state('glue > column %s, advance: %s, height: %s, state: %s', + column,points(advance),points(height),state) + end + if state == "quit" then + break + end + height = height + depth + skip + depth = 0 + skip = height > 0 and advance or 0 + end + elseif id == kern_code then + local advance = current.kern + if advance ~= 0 then + local state = checked(advance) + if trace_state then + report_state('kern > column %s, advance: %s, height: %s, state: %s', + column,points(advance),points(height),state) + end + if state == "quit" then + break + end + height = height + depth + skip + advance + depth = 0 + skip = 0 + end + elseif id == penalty_code then + local penalty = current.penalty + if penalty == 0 then + -- don't bother + elseif penalty == forcedbreak then + if gotonext() then + if trace_state then + report_state("cycle: %s, forced column break (same page)",cycle) + end + else + if trace_state then + report_state("cycle: %s, forced column break (next page)",cycle) + end + break + end + else + -- todo: nobreak etc ... we might need to backtrack so we need to remember + -- the last acceptable break + -- club and widow and such i.e. resulting penalties (if we care) + end + end + if nxt then + current = nxt + elseif head == lasthead then + -- to be checked but break needed as otherwise we have a loop + if trace_state then + report_state("quit as head is lasthead") + end + break + else + local r = results[column] + r.head = head + r.tail = current + r.height = height + r.depth = depth + break + end + end + if not current then + if trace_state then + report_state("nilling rest") + end + rest = nil + elseif rest == lasthead then + if trace_state then + report_state("nilling rest as rest is lasthead") + end + rest = nil + end + + if stripbottom then + local height = stripbottomglue(results,discarded) + if height > 0 then + target = height + end + end + + specification.results = results + specification.height = target + specification.originalheight = originalheight + specification.originalwidth = originalwidth + specification.originalhead = originalhead + specification.targetheight = target or 0 + specification.rest = rest + specification.overflow = overflow + specification.discarded = discarded + + texbox[specification.box].head = nil + + return specification +end + +function mixedcolumns.finalize(result) + if result then + local results = result.results + for i=1,result.nofcolumns do + local r = results[i] + local h = r.head + if h then + h.prev = nil + local t = r.tail + if t then + t.next = nil + else + h.next = nil + r.tail = h + end + for c, list in next, r.inserts do + local t = { } + for i=1,#list do + local l = list[i] + local h = new_hlist() + t[i] = h + h.head = l.head + h.height = l.height + h.depth = l.depth + l.head = nil + end + t[1].prev = nil -- needs checking + t[#t].next = nil -- needs checking + r.inserts[c] = t + end + end + end + end +end + +local splitruns = 0 + +local function report_deltas(result,str) + local t = { } + for i=1,result.nofcolumns do + t[#t+1] = points(result.results[i].delta or 0) + end + report_state("%s, cycles: %s, deltas: %s",str,result.cycle or 1,concat(t," | ")) +end + +function mixedcolumns.setsplit(specification) + splitruns = splitruns + 1 + if trace_state then + report_state("split run %s",splitruns) + end + local result = setsplit(specification) + if result then + if result.overflow then + if trace_state then + report_deltas(result,"overflow") + end + -- we might have some rest + elseif result.rest and specification.balance == v_yes then + local step = specification.step or 65536*2 + local cycle = 1 + local cycles = specification.cycles or 100 + while result.rest and cycle <= cycles do + specification.extra = cycle * step + result = setsplit(specification) or result + if trace_state then + report_state("cycle: %s.%s, original height: %s, total height: %s", + splitruns,cycle,points(result.originalheight),points(result.nofcolumns*result.targetheight)) + end + cycle = cycle + 1 + specification.cycle = cycle + end + if cycle > cycles then + report_deltas(result,"too many balancing cycles") + elseif trace_state then + report_deltas(result,"balanced") + end + elseif trace_state then + report_deltas(result,"done") + end + return result + elseif trace_state then + report_state("no result") + end +end + +local topskip_code = gluecodes.topskip +local baselineskip_code = gluecodes.baselineskip + +function mixedcolumns.getsplit(result,n) + if not result then + report_state("flush, column: %s, no result",n) + return + end + local r = result.results[n] + if not r then + report_state("flush, column: %s, empty",n) + end + local h = r.head + if not h then + return new_glue(result.originalwidth) + end + + if trace_state then + local id = h.id + if id == hlist_code then + report_state("flush, column: %s, top line: %s",n,nodes.toutf(h.list)) + else + report_state("flush, column: %s, head node: %s",n,nodecodes[id]) + end + end + + h.prev = nil -- move up + local strutht = result.strutht + local strutdp = result.strutdp + local lineheight = strutht + strutdp + + local v = new_vlist() + v.head = h + + -- local v = vpack(h,"exactly",height) + + v.width = result.originalwidth + if result.alternative == v_global then -- option + result.height = result.maxheight + end + v.height = lineheight * math.ceil(result.height/lineheight) - strutdp + v.depth = strutdp + + for c, list in next, r.inserts do + -- tex.setbox("global",c,vpack(nodes.concat(list))) + -- tex.setbox(c,vpack(nodes.concat(list))) + texbox[c] = vpack(nodes.concat(list)) + r.inserts[c] = nil + end + return v +end + +function mixedcolumns.getrest(result) + local rest = result and result.rest + result.rest = nil -- to be sure + return rest +end + +function mixedcolumns.getlist(result) + local originalhead = result and result.originalhead + result.originalhead = nil -- to be sure + return originalhead +end + +function mixedcolumns.cleanup(result) + local discarded = result.discarded + for i=1,#discarded do + freenode(discarded[i]) + end +end + +-- interface -- + +local result + +function commands.mixsetsplit(specification) + if result then + for k, v in next, specification do + result[k] = v + end + result = mixedcolumns.setsplit(result) + else + result = mixedcolumns.setsplit(specification) + end +end + +function commands.mixgetsplit(n) + if result then + context(mixedcolumns.getsplit(result,n)) + end +end + +function commands.mixfinalize() + if result then + mixedcolumns.finalize(result) + end +end + +function commands.mixflushrest() + if result then + context(mixedcolumns.getrest(result)) + end +end + +function commands.mixflushlist() + if result then + context(mixedcolumns.getlist(result)) + end +end + +function commands.mixstate() + context(result and result.rest and 1 or 0) +end + +function commands.mixcleanup() + if result then + mixedcolumns.cleanup(result) + result = nil + end +end diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv new file mode 100644 index 000000000..a4ef619bb --- /dev/null +++ b/tex/context/base/page-mix.mkiv @@ -0,0 +1,771 @@ +%D \module +%D [ file=page-mix, +%D version=2012.07.12, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Mixed Columns, +%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 / Mixed Columns} + +%D This is a very experimental module. Eventually it will replace the current +%D multi column mechanism (that then will be an instance). The \LUA\ part of +%D the interface will quite probably change so don't use that one directly +%D (yet). + +% todo: +% +% consult note class +% notes per page +% notes in each column +% notes in last column +% notes local/global +% top and bottom inserts +% wide floats +% move floats + +% luatex buglet: +% +% \ctxlua{tex.setbox("global",0,node.hpack(nodes.pool.glyph("a",font.current())))}\box0 + +\registerctxluafile{page-mix}{1.001} + +\unprotect + +%D The mixed output routine replaces the traditional multi column handler that +%D started out in \MKII. One of the complications of a routine is that it needs +%D to align nicely when mixed in a single column layout. Instead of using all +%D kind of shift juggling in this mechanism we simply switch to grid mode +%D locally. After all, columns don't look nice when not on a grid. As the grid +%D snapper in \MKIV\ is more advanced not that much extra code is needed. + +%D We use the command handler but the parent settings are not to be changed. +%D Instead we could have used a dedicated root setup, but it's not worth the +%D trouble. + +\installcorenamespace{mixedcolumns} + +\def\s!mixedcolumn{mixedcolumn} + +\installframedcommandhandler \??mixedcolumns {mixedcolumns} \??mixedcolumns + +\setupmixedcolumns + [\c!distance=1.5\bodyfontsize, + \c!n=\plustwo, + %\c!rule=\v!none, + \c!frame=\v!off, + \c!strut=\v!no, + \c!offset=\v!overlay, + \c!alternative=\v!local, + \c!maxheight=\textheight, + \c!maxwidth=\makeupwidth, + \c!step=.25\lineheight, % needs some experimenting + \c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS + +\let\startmixedcolumns\relax % defined later +\let\stopmixedcolumns \relax % defined later + +\appendtoks + \setuevalue{\e!start\currentmixedcolumns}{\startmixedcolumns[\currentmixedcolumns]}% + \setuevalue{\e!stop \currentmixedcolumns}{\stopmixedcolumns}% +\to \everydefinemixedcolumns + +%D In order to avoid a mixup we use quite some local registers. + +\newdimen \d_page_mix_column_width +\newdimen \d_page_mix_max_height +\newdimen \d_page_mix_max_width +\newdimen \d_page_mix_distance +\newcount \c_page_mix_n_of_columns +\newdimen \d_page_mix_threshold +\newdimen \d_page_mix_leftskip +\newdimen \d_page_mix_rightskip + +\newdimen \d_page_mix_balance_step +\setnewconstant\c_page_mix_balance_cycles 500 + +\setnewconstant\c_page_mix_break_forced -123 + +\newbox \b_page_mix_preceding +\newdimen \d_page_mix_preceding_height + +\newbox \b_page_mix_collected + +\newconstant \c_page_mix_routine + +\setnewconstant\c_page_mix_routine_regular \zerocount +\setnewconstant\c_page_mix_routine_intercept\plusone +\setnewconstant\c_page_mix_routine_continue \plustwo +\setnewconstant\c_page_mix_routine_balance \plusthree +\setnewconstant\c_page_mix_routine_error \plusfour + +%D The main environment is called as follows: +%D +%D \starttyping +%D \startmixedcolumns[instance][settings] +%D \startmixedcolumns[instance] +%D \startmixedcolumns[settings] +%D \stoptyping +%D +%D However, best is not to use this one directly but define an instance and +%D use that one. + +% % For the moment only on my machine: +% +% \definemixedcolumns +% [\v!columns] +% +% \unexpanded\def\setupcolumns +% {\setupmixedcolumns[\v!columns]} + +%D In itemizations we also need columns, so let's define a apecial instance +%D for them. These need to work well in situations like this: +%D +%D \starttyping +%D \input zapf +%D +%D \startnarrower +%D \startitemize[columns,two,packed][before=,after=] +%D \dorecurse{10}{\startitem item #1 \stopitem} +%D \stopitemize +%D \stopnarrower +%D +%D \input zapf +%D +%D \startnarrower +%D \startitemize[columns,two][before=,after=] +%D \dorecurse{10}{\startitem item #1 \stopitem} +%D \stopitemize +%D \stopnarrower +%D +%D \input zapf +%D +%D \startnarrower +%D \startitemize[columns,two] +%D \dorecurse{10}{\startitem item #1 \stopitem} +%D \stopitemize +%D \stopnarrower +%D +%D \input zapf +%D \stoptyping + +\ifdefined\s!itemgroupcolumns \else \def\s!itemgroupcolumns{itemgroupcolumns} \fi + +\definemixedcolumns + [\s!itemgroupcolumns] + [\c!n=\itemgroupparameter\c!n, + \c!rule=\v!off, + \c!balance=\v!yes] + +\unexpanded\def\strc_itemgroups_start_columns + {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one + +\unexpanded\def\strc_itemgroups_stop_columns + {\stopmixedcolumns} + +%D The mixed output routine can be in different states. First we need to intercept +%D the already present content. This permits mixed single and multi column usage. +%D Then we have the continuous routine, one that intercepts pages in sequence. +%D Finally, when we finish the mixed columns mode, we can (optionally) balance the +%D last page. + +\unexpanded\def\page_mix_command_routine + {\ifcase\c_page_mix_routine + \page_one_command_routine + \or + \page_mix_routine_intercept + \or + \page_mix_routine_continue + \or + \page_mix_routine_balance + \or + \page_mix_routine_error + \fi} + +%D The interceptor is quite simple, at least for the moment. + +\def\page_mix_routine_intercept + {\global\setbox\b_page_mix_preceding\vbox + {\page_otr_command_flush_top_insertions + \unvbox\normalpagebox}} + +%D The error routine is there but unlikely to be called. It is a left-over from +%D the traditional routine that might come in handy some day. + +\def\page_mix_routine_error + {\showmessage\m!columns3\empty + \page_otr_construct_and_shipout\unvbox\normalpagebox} + +%D Some settings (and actions) depend on the current output routine and setting the +%D hsize and vsize is among them. The calculation of the hsize is done elsewhere. + +\unexpanded\def\page_mix_command_set_hsize + {\hsize\d_page_mix_column_width} + +%D When setting the vsize we make sure that we collect a few more lines than needed +%D so that we have enough to split over the columns. Collecting too much is somewhat +%D tricky as they will spill over to the next page. + +\unexpanded\def\page_mix_command_set_vsize + {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax + \pagegoal\vsize} + +%D As we use \LUA\ there is the usual amount of tracing at that end. At the tex end +%D we only visualize boxes. + +\let\page_mix_hbox\hbox +\let\page_mix_vbox\vbox + +\installtextracker + {mixedcolumns.boxes} + {\let\page_mix_hbox\ruledhbox + \let\page_mix_vbox\ruledvbox} + {\let\page_mix_hbox\hbox + \let\page_mix_vbox\vbox} + +%D We provide a few column break options. Interesting is that while forcing a new +%D column in the traditional mechanism was a pain, here it works quite well. + +\installcolumnbreakmethod \s!mixedcolumn \v!preference + {\goodbreak} + +\installcolumnbreakmethod \s!mixedcolumn \v!yes + {\penalty\c_page_mix_break_forced\relax} + +%D As we operate in grid snapping mode, we use a dedicated macro to enable this +%D mechamism. + +\def\page_mix_enable_grid_snapping + {\gridsnappingtrue + \setsystemmode\v!grid + \spac_grids_snap_value_set\v!yes} + +%D Between columns there is normally just spacing unless one enforces a rule. +%D +%D \starttyping +%D \input zapf +%D +%D \startnarrower +%D \startmixedcolumns[n=2,background=color,backgroundcolor=red,rulethickness=1mm,rulecolor=green,separator=rule] +%D \input zapf +%D \stopmixedcolumns +%D \stopnarrower +%D +%D \input zapf +%D \stoptyping + +\installcorenamespace{mixedcolumnsseparator} + +\setvalue{\??mixedcolumnsseparator\v!rule}% + {\starttextproperties + \usemixedcolumnscolorparameter\c!rulecolor + \vrule\s!width\mixedcolumnsparameter\c!rulethickness + \stoptextproperties} + +\unexpanded\def\page_mix_command_inject_separator + {\bgroup + \hss + \csname\??mixedcolumnsseparator\mixedcolumnsparameter\c!separator\endcsname + \hss + \egroup} + +%D We've now arrived at the real code. The start command mostly sets up the +%D environment and variables that are used in the splitter. One of the last +%D things happening at the start is switching over to the mixed continuous +%D routine. + +\installcorenamespace{mixedcolumnsbefore} +\installcorenamespace{mixedcolumnsstart} +\installcorenamespace{mixedcolumnsstop} +\installcorenamespace{mixedcolumnsafter} + +%D For practical reasons there is always a first argument needed that +%D indicates the class. +%D +%D \starttyping +%D \startmixedcolumns[n=3,alternative=global] +%D \dorecurse{200}{Zomaar wat #1 met een footnote\footnote{note #1}. } +%D \stopmixedcolumns +%D \stoptyping + +\unexpanded\def\startmixedcolumns + {\dodoubleempty\page_mix_start_columns} + +\unexpanded\def\page_mix_start_columns + {\pushmacro\currentmixedcolumns + \pushmacro\currentmixedcolumnsmethod + \ifsecondargument + \singleexpandafter\page_mix_start_columns_a + \else\iffirstargument + \doubleexpandafter\page_mix_start_columns_b + \else + \doubleexpandafter\page_mix_start_columns_c + \fi\fi} + +\def\page_mix_start_columns_a[#1][#2]% + {\edef\currentmixedcolumns{#1}% + \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \mixedcolumnsparameter\c!before\relax + \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \setupcurrentmixedcolumns[#2]% + \page_mix_initialize_columns + \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} + +\def\page_mix_start_columns_b[#1][#2]% + {\doifassignmentelse{#1}% + {\let\currentmixedcolumns\empty + \page_mix_error_b} + {\edef\currentmixedcolumns{#1}% + \firstargumentfalse}% + \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings ! + \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \iffirstargument + \setupcurrentmixedcolumns[#1]% + \fi + \page_mix_initialize_columns + \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax + +\def\page_mix_error_b + {\writestatus\m!columns{best use an instance of mixed columns}} + +\def\page_mix_start_columns_c[#1][#2]% + {\let\currentmixedcolumns\empty + \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \mixedcolumnsparameter\c!before\relax + \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \page_mix_initialize_columns + \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} + +\unexpanded\def\page_mix_fast_columns_start#1% + {\pushmacro\currentmixedcolumns + \pushmacro\currentmixedcolumnsmethod + \edef\currentmixedcolumns{#1}% + \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% + \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings ! + \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax + \begingroup + \page_mix_initialize_columns + \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax + +%D When we stop, we switch over to the balancing routine. After we're done we +%D make sure to set the sizes are set, a somewhat redundant action when we +%D already have flushed but better be safe. + +\unexpanded\def\stopmixedcolumns + {\csname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax + \endgroup + \csname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax + \mixedcolumnsparameter\c!after\relax + \popmacro\currentmixedcolumnsmethod + \popmacro\currentmixedcolumns} + +% \unexpanded\def\stopmixedcolumns +% {\csname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax +% \endgroup +% \csname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax +% \mixedcolumnsparameter\c!after\relax +% \ifx\currentmixedcolumnsmethod\s!otr +% \popmacro\currentmixedcolumnsmethod +% \popmacro\currentmixedcolumns +% \synchronizeoutput % brrr, otherwise sometimes issues in itemize +% \else +% \popmacro\currentmixedcolumnsmethod +% \popmacro\currentmixedcolumns +% \fi +% } + +\let\page_mix_fast_columns_stop\stopmixedcolumns + +%D This is how the fast one is used: + +\unexpanded\def\strc_itemgroups_start_columns + {\page_mix_fast_columns_start\s!itemgroupcolumns} + +\let\strc_itemgroups_stop_columns\page_mix_fast_columns_stop + +%D The common initialization: + +\def\page_mix_initialize_columns + {\page_mix_enable_grid_snapping + % + \d_page_mix_distance \mixedcolumnsparameter\c!distance + \c_page_mix_n_of_columns\mixedcolumnsparameter\c!n + \d_page_mix_max_height \mixedcolumnsparameter\c!maxheight + \d_page_mix_max_width \mixedcolumnsparameter\c!maxwidth + \d_page_mix_balance_step\mixedcolumnsparameter\c!step + % + \d_page_mix_max_width\dimexpr\d_page_mix_max_width-\leftskip-\rightskip\relax + \d_page_mix_leftskip \leftskip + \d_page_mix_rightskip\rightskip + \leftskip \zeropoint + \rightskip\zeropoint + % + \d_page_mix_threshold\zeropoint + % + \d_page_mix_column_width\dimexpr(\d_page_mix_max_width-\d_page_mix_distance*\numexpr(\c_page_mix_n_of_columns-\plusone)\relax)/\c_page_mix_n_of_columns\relax + % + \usemixedcolumnscolorparameter\c!color + % + \nofcolumns\c_page_mix_n_of_columns} % public + +%D The otr method related hooks are defined next: + +% \setvalue{\??mixedcolumnsbefore\s!otr}% +% {\par +% \ifdim\pagetotal=\zeropoint \else +% \verticalstrut % probably no longer needed +% \vskip-\struttotal % probably no longer needed +% \fi} + +\newcount\c_page_mix_otr_nesting + +\setvalue{\??mixedcolumnsbefore\s!otr}% + {\par + \global\advance\c_page_mix_otr_nesting\plusone + \ifcase\c_page_mix_otr_nesting\or + \ifdim\pagetotal=\zeropoint \else + \obeydepth % we could handle this in pre material + \fi + \fi} + +\setvalue{\??mixedcolumnsstart\s!otr}% + {\ifcase\c_page_mix_otr_nesting\or + \setupoutputroutine[\s!mixedcolumn]% + \c_page_mix_routine\c_page_mix_routine_intercept + \page_otr_trigger_output_routine + % + \holdinginserts\maxdimen + % + \global\d_page_mix_preceding_height\ht\b_page_mix_preceding + \c_page_mix_routine\c_page_mix_routine_continue + % + \page_mix_command_set_vsize + \page_mix_command_set_hsize + \fi} + +\setvalue{\??mixedcolumnsstop\s!otr}% + {\par + \ifcase\c_page_mix_otr_nesting\or + \c_page_mix_routine\c_page_mix_routine_balance + \page_otr_trigger_output_routine + \fi} + +\setvalue{\??mixedcolumnsafter\s!otr}% + {\ifcase\c_page_mix_otr_nesting\or + \prevdepth\strutdp + \page_otr_command_set_vsize + \page_otr_command_set_hsize + \fi + \global\advance\c_page_mix_otr_nesting\minusone} + +%D The splitting and therefore balancing is done at the \LUA\ end. This gives +%D more readable code and also makes it easier to deal with insertions like +%D footnotes. Eventually we will have multiple strategies available. + +\unexpanded\def\page_mix_routine_construct#1% + {\ctxcommand{mixsetsplit { + box = \number\b_page_mix_collected, + nofcolumns = \number\c_page_mix_n_of_columns, + maxheight = \number\d_page_mix_max_height, + step = \number\d_page_mix_balance_step, + cycles = \number\c_page_mix_balance_cycles, + preheight = \number\d_page_mix_preceding_height, + prebox = \number\b_page_mix_preceding, + strutht = \number\strutht, + strutdp = \number\strutdp, + threshold = \number\d_page_mix_threshold, + balance = "#1", + alternative = "\mixedcolumnsparameter\c!alternative", + }}% + \deadcycles\zerocount} + +\unexpanded\def\page_mix_routine_package + {\ctxcommand{mixfinalize()}% + \setbox\b_page_mix_collected\vbox \bgroup + \ifvoid\b_page_mix_preceding \else + \box\b_page_mix_preceding + \global\d_page_mix_preceding_height\zeropoint + \nointerlineskip + \fi + \hskip\d_page_mix_leftskip + \page_mix_hbox to \d_page_mix_max_width \bgroup + \letmixedcolumnsparameter\c!strut\v!no + % maybe use \c_page_mix_used_of_columns + \dorecurse\c_page_mix_n_of_columns {% + \inheritedmixedcolumnsframed{\page_mix_command_package_column}% + \ifnum\recurselevel<\c_page_mix_n_of_columns + \page_mix_command_inject_separator + \fi + }% + \egroup + \egroup} + +\unexpanded\def\page_mix_command_package_column + {\page_mix_hbox to \d_page_mix_column_width \bgroup + % maybe intercept empty + \ctxcommand{mixgetsplit(\recurselevel)}% + \hskip-\d_page_mix_column_width + \page_mix_hbox to \d_page_mix_column_width \bgroup + \placenoteinserts + \hss + \egroup + \egroup} + +\unexpanded\def\page_mix_routine_continue + {\bgroup + \forgetall + \dontcomplain + \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua) + \page_mix_routine_construct\v!no + \page_mix_routine_package + \page_otr_construct_and_shipout\box\b_page_mix_collected + \ctxcommand{mixflushrest()}% + \ctxcommand{mixcleanup()}% + \egroup} + +\unexpanded\def\page_mix_routine_balance + {\bgroup + \forgetall + \dontcomplain + \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua) + \doloop + {%writestatus\m!columns{construct continue (\the\htdp\b_page_mix_collected)}% + \page_mix_routine_construct\v!no + \ifcase\ctxcommand{mixstate()}\relax + % 0 = okay, we can balance + \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushlist()}}% we could avoid this + %writestatus\m!columns{construct balance}% + \page_mix_routine_construct\v!yes + \page_mix_routine_package + \c_page_mix_routine\c_page_mix_routine_regular + % \setupoutputroutine[\s!singlecolumn]% + \page_otr_command_set_vsize + \page_otr_command_set_hsize + \par + %writestatus\m!columns{flush balance}% + \box\b_page_mix_collected + \vskip\zeropoint % triggers recalculation of page stuff (weird that this is needed but it *is* needed, see mixed-001.tex) + \par + \nointerlineskip + \prevdepth\strutdp + \ctxcommand{mixflushrest()}% rubish + \ctxcommand{mixcleanup()}% rubish + \exitloop + \or + % 1 = we have stuff left, so flush and rebalance + %writestatus\m!columns{flush continue}% + \page_mix_routine_package + \page_otr_construct_and_shipout\box\b_page_mix_collected + \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushrest()}}% we could avoid this + \ctxcommand{mixcleanup()}% + \ifdim\ht\b_page_mix_collected=\zeropoint + \exitloop + \fi + \fi}% + \egroup} + +%D We also implement a variant compatible with the so called simple columns +%D mechanism: +%D +%D \starttyping +%D \startboxedcolumns +%D \input zapf +%D \stopboxedcolumns +%D \stoptyping +%D +%D This is a rather mininimalistic variant. + +% Maybe we also need a variant with obeydepth before and prevdepth after so +% that we get a nice spacing. + +\definemixedcolumns + [boxedcolumns] + [\c!balance=\v!yes, + \c!n=2, + \c!method=\s!box, + \c!strut=\v!yes, + \c!maxwidth=\availablehsize] + +%D Boxed columns can be used nested: +%D +%D \starttyping +%D \setupmixedcolumns +%D [boxedcolumns] +%D [n=2, +%D background=color, +%D backgroundcolor=darkred, +%D color=white, +%D backgroundoffset=1mm] +%D +%D \definemixedcolumns +%D [nestedboxedcolumns] +%D [boxedcolumns] +%D [n=2, +%D background=color, +%D backgroundcolor=white, +%D color=darkred, +%D strut=yes, +%D backgroundoffset=0mm] +%D +%D \startboxedcolumns +%D \input zapf \par \input ward \par \obeydepth +%D \startnestedboxedcolumns +%D \input zapf +%D \stopnestedboxedcolumns +%D \par \input zapf \par \obeydepth +%D \startnestedboxedcolumns +%D \input zapf +%D \stopnestedboxedcolumns +%D \par \input zapf +%D \stopboxedcolumns +%D \stoptyping + +%D Next we define the hooks: + +\letvalue{\??mixedcolumnsbefore\s!box}\donothing +\letvalue{\??mixedcolumnsafter \s!box}\donothing + +\setvalue{\??mixedcolumnsstart\s!box}% + {\edef\p_page_mix_strut{\mixedcolumnsparameter\c!strut}% + \setbox\b_page_mix_collected\vbox\bgroup + \let\currentoutputroutine\s!mixedcolumn % makes \column work + \forgetall + \page_mix_command_set_hsize + \ifx\p_page_mix_strut\v!yes + \begstrut + \ignorespaces + \fi} + +\setvalue{\??mixedcolumnsstop\s!box}% + {\ifx\p_page_mix_strut\v!yes + \removeunwantedspaces + \endstrut + \fi + \egroup + \page_mix_box_balance} + +%D The related balancer is only a few lines: + +\unexpanded\def\page_mix_box_balance + {\bgroup + \dontcomplain + \page_mix_routine_construct\v!yes + \page_mix_routine_package + \dontleavehmode\box\b_page_mix_collected + \ctxcommand{mixflushrest()}% + \ctxcommand{mixcleanup()}% + \egroup} + +%D As usual, floats complicates matters and this is where experimental code +%D starts. + +\let\page_mix_command_package_contents\page_one_command_package_contents +\let\page_mix_command_flush_float_box \page_one_command_flush_float_box + +\unexpanded\def\page_mix_command_check_if_float_fits + {\ifpostponecolumnfloats + \global\setfalse\c_page_floats_room + \else\ifconditional\c_page_floats_not_permitted + \global\setfalse\c_page_floats_room + \else +% \bgroup +% \getcolumnstatus{\count255}{\dimen0}{\dimen2}% +% \page_floats_get_info\s!text +% \setbox\scratchbox\vbox % tricky met objecten ? +% {\blank[\rootfloatparameter\c!spacebefore] +% \snaptogrid\vbox{\vskip\floatheight}}% copy? +% \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher +% \ifdim\dimen0>\dimen2 +% \global\setfalse\c_page_floats_room +% \else + \global\settrue\c_page_floats_room + \fi + \ifdim\floatwidth>\hsize + \showmessage\m!columns{11}\empty + \global\setfalse\c_page_floats_room + \fi} + +\unexpanded\def\page_mix_command_flush_floats + {\page_one_command_flush_floats} + +\unexpanded\def\page_mix_command_flush_saved_floats + {\page_one_command_flush_saved_floats} + +% \unexpanded\def\page_mix_command_flush_top_insertions +% {\page_one_command_flush_top_insertions} + +% \unexpanded\def\page_mix_place_float_top +% {\showmessage\m!columns4\empty\page_one_place_float_here} + +% \unexpanded\def\page_mix_place_float_bottom +% {\showmessage\m!columns5\empty\page_one_place_float_here} + +\unexpanded\def\page_mix_place_float_here + {\page_one_place_float_here} + +\unexpanded\def\page_mix_place_float_force + {\page_one_place_float_force} + +\unexpanded\def\page_mix_command_side_float_output % hm + {\page_otr_construct_and_shipout\unvbox\normalpagebox} + +\unexpanded\def\page_mix_command_synchronize_side_floats % hm + {\page_sides_forget_floats} + +\unexpanded\def\page_mix_command_flush_side_floats + {\page_sides_forget_floats} + +\unexpanded\def\page_mix_command_next_page + {\page_otr_eject_page} + +\unexpanded\def\page_mix_command_next_page_and_inserts + {\page_otr_eject_page_and_flush_inserts} + +%D We need to hook some handlers into the output routine and we define +%D a dedicated one: + +\defineoutputroutine + [\s!mixedcolumn] + [\s!page_otr_command_routine =\page_mix_command_routine, + \s!page_otr_command_package_contents =\page_mix_command_package_contents, + \s!page_otr_command_set_vsize =\page_mix_command_set_vsize, + \s!page_otr_command_set_hsize =\page_mix_command_set_hsize, + \s!page_otr_command_next_page =\page_mix_command_next_page, + \s!page_otr_command_next_page_and_inserts =\page_mix_command_next_page_and_inserts, + % \s!page_otr_command_synchronize_hsize =\page_mix_command_synchronize_hsize, + % \s!page_otr_command_set_top_insertions =\page_mix_command_set_top_insertions, + % \s!page_otr_command_set_bottom_insertions =\page_mix_command_set_bottom_insertions, + % \s!page_otr_command_flush_top_insertions =\page_mix_command_flush_top_insertions, + % \s!page_otr_command_flush_bottom_insertions=\page_mix_command_flush_bottom_insertions, + % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize, + \s!page_otr_command_check_if_float_fits =\page_mix_command_check_if_float_fits, + \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box, + \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats, + \s!page_otr_command_side_float_output =\page_mix_command_side_float_output, + \s!page_otr_command_flush_floats =\page_mix_command_flush_floats, + \s!page_otr_command_flush_side_floats =\page_mix_command_flush_side_floats, + \s!page_otr_command_flush_saved_floats =\page_mix_command_flush_saved_floats + % \s!page_otr_command_flush_margin_blocks =\page_mix_command_flush_margin_blocks, % not used + ] + +%D Only a few float placement options are supported: + +\installfloatmethod \s!mixedcolumn \v!here \page_mix_place_float_here +\installfloatmethod \s!mixedcolumn \v!force \page_mix_place_float_force +\installfloatmethod \s!mixedcolumn \v!top \page_mix_place_float_top +\installfloatmethod \s!mixedcolumn \v!bottom \page_mix_place_float_bottom + +\installfloatmethod \s!mixedcolumn \v!local \somelocalfloat + +%D It ends here. + +\protect \endinput diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv index 3792f06ee..1d1698764 100644 --- a/tex/context/base/page-mul.mkiv +++ b/tex/context/base/page-mul.mkiv @@ -11,35 +11,21 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% SEE PAGE-MUL-NEW.MKIV +% todo: basecolumns as parent for columns and itemize -% BEWARE: TEMPORARY ISSUES WITH VSIZE AND HSIZE BUT WILL BE REDONE +% !!! there are some issues with hsize an vsize as well as flushing +% !!! floats but this module will be redone anyway \writestatus{loading}{ConTeXt Page Macros / Simple Multi Column} -%D This module is mostly a copy from the original multi column -%D routine as implemented in \type {core-mul}. When the main -%D OTR macro's were isolated in modules and column sets were -%D introduced, this module became part of the OTR modules. As -%D a result this module is no longer generic. It also needs -%D an overhaul. +%D This module is mostly a copy from the original multi column routine as +%D implemented in \type {core-mul}. When the main OTR macro's were +%D isolated in modules and column sets were introduced, this module became +%D part of the OTR modules. As a result this module is no longer generic. \unprotect -\unexpanded\def\page_mul_command_side_float_output - {\page_otr_construct_and_shipout\unvbox\normalpagebox} - -\unexpanded\def\page_mul_command_flush_side_floats - {\page_sides_forget_floats} - -\unexpanded\def\page_mul_command_synchronize_side_floats - {\page_sides_forget_floats} - -\unexpanded\def\page_mul_command_next_page - {\page_otr_eject_page} - -\unexpanded\def\page_mul_command_next_page_and_inserts - {\page_otr_eject_page_and_flush_inserts} +\definesystemvariable {ks} % KolomSpan % check \count<insert> multiplications @@ -47,7 +33,7 @@ %D implementation was based on Donald Knuth's implementation, which was adapted by %D Craig Platt to support balancing of the last page. I gradually adapted Platt's %D version to our needs but under certain circumstances things still went wrong. I -%D considered all calls to Platt's \type{\balancingerror} as undesirable. +%D considered all calls to Platt's \type{\page_mul_routine_error} as undesirable. %D %D This completely new implementation can handle enough situations for everyday %D documents, but is still far from perfect. While at the moment the routine doesn't @@ -56,7 +42,7 @@ %D \startitemize[packed] %D \item an unlimitted number of columns %D \item ragged or not ragged bottoms -%D \item optional balancing without \type{\balancingerrors} +%D \item optional balancing without \type{\page_mul_routine_errors} %D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and %D \type {\maxdepth} %D \item left- and right indentation, e.g. within lists @@ -70,83 +56,147 @@ %D special case of multi||columns is posible but at the cost of worse float %D handling, worse page breaking, worse etc. Complicated multi||column page handling %D should be done in \cap{DTP}||systems anyway. -%D -%D There are three commands provided for entering and leaving multi||column mode and -%D for going to the next column: -%D -%D \interface \type{\beginmulticolumns} \\ \\ -%D \interface \type{\endmulticolumns} \\ \\ -%D \interface \type{\ejectcolumn} \\ \\ -\def\finalcolumntextwidth {\makeupwidth} -\def\finalcolumntextheight {\textheight} -\def\columntextwidth {\makeupwidth} -\def\columntextheight {\textheight} -\def\usercolumnwidth {\textwidth} -\def\columntextoffset {\!!zeropoint} +\installcorenamespace {columns} + +\installcommandhandler \??columns {columns} \??columns + +%D Going to a new columns is done by means of a \type {\ejectcolumn}. The +%D following definition does not always work. + + \unexpanded\def\ejectcolumn % not good enough + {\goodbreak + \showmessage\m!columns2\empty} -\def\fixedcolumnheight {\textheight} -\def\betweencolumns {\hskip\bodyfontsize} +%D The output routines plug into a more generic mechanism as can be seen at the +%D end of this file. So, occasionally we need to define some plugin code. -\let\setcolumnfloats \relax % in CONTEXT used for floats -\let\flushcolumnfloats \relax % in CONTEXT used for floats -\let\flushcolumnfloat \relax % in CONTEXT used for floats -\let\finishcolumnbox \relax % in CONTEXT used for backgrounds +\unexpanded\def\page_mul_place_float_top + {\showmessage\m!columns4\empty\page_one_place_float_here} -%D Both macros are redefined in \CONTEXT\ when backgrounds are applied to -%D columns. The final values are used when flushing the columns. +\unexpanded\def\page_mul_place_float_bottom + {\showmessage\m!columns5\empty\page_one_place_float_here} -%D It's more convenient to use \type {\columnwidth} instead of messing around -%D with boxes each time. +\unexpanded\def\page_mul_place_float_here + {\page_one_place_float_here} -\newdimen\columnwidth -\newdimen\gutterwidth +\unexpanded\def\page_mul_place_float_force + {\page_one_place_float_force} -\def\determinecolumnwidth +\unexpanded\def\page_mul_command_side_float_output + {\page_otr_construct_and_shipout\unvbox\normalpagebox} + +\unexpanded\def\page_mul_command_flush_side_floats + {\page_sides_forget_floats} + +\unexpanded\def\page_mul_command_synchronize_side_floats + {\page_sides_forget_floats} + +\unexpanded\def\page_mul_command_next_page + {\page_otr_eject_page} + +\unexpanded\def\page_mul_command_next_page_and_inserts + {\page_otr_eject_page_and_flush_inserts} + +\let\page_mul_initialize_floats\relax +\let\page_mul_flush_floats \relax +\let\page_mul_flush_float \relax + +%D A hook: + + \let\finishcolumnbox\relax + +%D This will change to a local one: + +\ifdefined\nofcolumns \else \newcount\nofcolumn \fi +\ifdefined\mofcolumns \else \newcount\mofcolumn \fi + +\appendtoks + \nofcolumns\columnsparameter\c!n\relax +\to \everysetupcolumns + +%D Columns are separated by spacing or rules or whatever suits. + +\installcorenamespace{columnseparators} + +\setvalue{\??columnseparators\v!on }{\let\page_mul_between_columns\page_mul_between_columns_rule} +\setvalue{\??columnseparators\v!off }{\let\page_mul_between_columns\page_mul_between_columns_space} +\setvalue{\??columnseparators }{\let\page_mul_between_columns\page_mul_between_columns_space} +\setvalue{\??columnseparators\s!unknown}{\let\page_mul_between_columns\p_page_mul_rule} + +\def\page_mul_between_columns_rule {\bgroup - \setbox\scratchbox\hbox - {\page_mul_command_set_hsize - \global\columnwidth\usercolumnwidth - \global\gutterwidth\intercolumnwidth}% + \starttextproperties + \scratchdistance\dimexpr\columnsparameter\c!distance/2\relax + \hskip\scratchdistance\relax + \vrule + \s!width\linewidth + \ifnum\bottomraggednessmode=\plustwo % baselinebottom + \s!depth\strutdepth + \fi + \hskip\scratchdistance\relax + \stoptextproperties \egroup} -%D Going to a new columns is done by means of a \type {\ejectcolumn}. The -%D following definition does not always work. +\def\page_mul_between_columns_space + {\hskip\columnsparameter\c!distance\relax} -\def\ejectcolumn - {\goodbreak - \showmessage\m!columns2\empty} +\let\page_mul_between_columns\page_mul_between_columns_space -\def\balancingerror - {\showmessage\m!columns3\empty - \page_otr_construct_and_shipout\unvbox\normalpagebox} +%D We declare some registers: + +\newdimen \d_page_mul_available_width +\newdimen \d_page_mul_distance +\newdimen \d_page_mul_leftskip +\newdimen \d_page_mul_rightskip +\newdimen \d_page_mul_offset +\newdimen \d_page_mul_forced_height +\newdimen \d_page_mul_used_width +\newdimen \d_page_mul_temp -\def\page_mul_place_float_top {\showmessage\m!columns4\empty\page_one_place_float_here} -\def\page_mul_place_float_bottom{\showmessage\m!columns5\empty\page_one_place_float_here} -\def\page_mul_place_float_here {\page_one_place_float_here} -\def\page_mul_place_float_force {\page_one_place_float_force} +\newcount \c_page_mul_balance_minimum +\newcount \c_page_mul_n_of_lines -%D The local column width is available in the dimension register \type -%D {\localcolumnwidth}, which is calculated as: +\newbox \b_page_mul_preceding +\newdimen \d_page_mul_preceding_height +\newdimen \d_page_mul_preceding_depth +\newconditional\c_page_mul_preceding_present + +\newbox \b_page_mul_preceding_rest_of_page + +\newconditional\c_page_mul_reverse + +\newconditional\c_page_mul_trace + +%D The next dimensions reports the final column height .. todo + + \newdimen\finalcolumnheights + \newcount\finalcolumnlines + + \newdimen\savedpagetotal % brrr + + \newif\ifstretchcolumns \stretchcolumnsfalse + \newif\ifheightencolumns \heightencolumnsfalse + \newif\ifinheritcolumns \inheritcolumnsfalse + \newif\ifbalancecolumns %\balancecolumnstrue + +%D An important one: \unexpanded\def\page_mul_command_set_hsize % beware, this one is available for use in macros - {\setbox\scratchbox\hbox{\parindent\zeropoint\betweencolumns}% - \intercolumnwidth\wd\scratchbox - \localcolumnwidth\columntextwidth - \advance\localcolumnwidth -\leftskip - \advance\localcolumnwidth -\rightskip - % new - \advance\localcolumnwidth -\colleftskip - \advance\localcolumnwidth -\colrightskip - % - \advance\localcolumnwidth -\nofcolumns\intercolumnwidth - \advance\localcolumnwidth \intercolumnwidth - \divide \localcolumnwidth \nofcolumns - \scratchdimen\columntextoffset - \multiply\scratchdimen \plustwo - \advance\localcolumnwidth -\scratchdimen - \usercolumnwidth\localcolumnwidth - \hsize\localcolumnwidth} % we don't do it \global + {\setbox\scratchbox\hbox{\page_mul_between_columns}% + \d_page_mul_distance\wd\scratchbox + \d_page_mul_available_width\dimexpr + \makeupwidth + -\d_page_mul_leftskip + -\d_page_mul_rightskip + -\nofcolumns\d_page_mul_distance + +\d_page_mul_distance + \relax + \d_page_mul_used_width\dimexpr + \d_page_mul_available_width/\nofcolumns + -\d_page_mul_offset*\plustwo + \relax + \hsize\d_page_mul_used_width} %D Torture test: %D @@ -217,122 +267,79 @@ %D in||between material, these dimensions are influenced by bodyfont switches inside %D multi||column mode. -\newdimen\mcscratchdimen -\newcount\nofcolumnlines +\setnewconstant\multicolumnlinemethod\zerocount % 0=normal 1=raw -\setnewconstant\multicolumnlinemethod\plusone % 0: overshoot (old default), 1: tight +\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi} -\def\getmulticolumnlines - {\mcscratchdimen-\columntextoffset - \multiply\mcscratchdimen \plustwo - \advance\mcscratchdimen \columntextheight - \ifdim\precolumnboxheight>\zeropoint - \advance\mcscratchdimen -\precolumnboxheight - \fi - \settotalinsertionheight - \advance\mcscratchdimen -\totalinsertionheight - \ifcase\multicolumnlinemethod \getnoflines\mcscratchdimen - \or \getrawnoflines\mcscratchdimen - \else \getrawnoflines\mcscratchdimen +\unexpanded\def\page_mul_set_n_of_lines + {\settotalinsertionheight + \d_page_mul_temp\dimexpr + -\d_page_mul_offset*\plustwo + +\textheight + \ifdim\d_page_mul_preceding_height>\zeropoint -\d_page_mul_preceding_height \fi + -\totalinsertionheight + \relax + \ifcase\multicolumnlinemethod + \getnoflines \d_page_mul_temp \or + \getrawnoflines\d_page_mul_temp \else + \getrawnoflines\d_page_mul_temp \fi % added 30/7/2004 \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines \noflines\layoutlines \fi \fi - \nofcolumnlines\noflines} - -\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi} + \c_page_mul_n_of_lines\noflines} \unexpanded\def\page_mul_command_set_vsize {\page_one_command_set_vsize % indeed? - \getmulticolumnlines - \mcscratchdimen\nofcolumnlines\openlineheight - \advance\mcscratchdimen \multicolumnovershootratio\openlineheight % collect enough data - \global\vsize\nofcolumns\mcscratchdimen - \global\pagegoal\vsize} % let's do it only here + \page_mul_set_n_of_lines + \d_page_mul_temp\nofcolumns\dimexpr + \c_page_mul_n_of_lines\openlineheight + +\multicolumnovershootratio\openlineheight % collect enough data + \relax + \global\vsize\d_page_mul_temp + \pagegoal \d_page_mul_temp} % let's do it only here %D It really starts here. After some checks and initializations we change the output %D routine to continous multi||column mode. This mode handles columns that fill the %D current and next full pages. The method used is (more or less) multiplying \type %D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be %D found in the \TeX book. We save the top of the current page in box -%D \type{\precolumnbox}. +%D \type {\b_page_mul_preceding}. %D %D We manipulate \type {\topskip} a bit, just to be shure that is has no %D flexibility. This has te be done every time a font switch takles place, because -%D \type{\topskip} can depend on this. +%D \type {\topskip} can depend on this. \newconstant\c_page_mul_routine -\setnewconstant\c_page_mul_routine_regular \zerocount -\setnewconstant\c_page_mul_routine_intercept \plusone -\setnewconstant\c_page_mul_routine_continuous \plustwo -\setnewconstant\c_page_mul_routine_balanced \plusthree -\setnewconstant\c_page_mul_routine_error \plusfour +\setnewconstant\c_page_mul_routine_regular \zerocount +\setnewconstant\c_page_mul_routine_intercept \plusone +\setnewconstant\c_page_mul_routine_continue \plustwo +\setnewconstant\c_page_mul_routine_balance \plusthree +\setnewconstant\c_page_mul_routine_error \plusfour \unexpanded\def\page_mul_command_routine {\ifcase\c_page_mul_routine \page_one_command_routine \or - \interceptmulticolumnsout + \page_mul_routine_intercept \or - \continuousmulticolumnsout + \page_mul_routine_continue \or - \balancedmulticolumnsout + \page_mul_routine_balance \or - \balancingerror + \page_mul_routine_error \fi} -\def\interceptmulticolumnsout - {\global\setbox\precolumnbox\vbox - {\page_otr_command_flush_top_insertions\unvbox\normalpagebox}} +\def\page_mul_routine_intercept + {\global\setbox\b_page_mul_preceding\vbox + {\page_otr_command_flush_top_insertions + \unvbox\normalpagebox}} -\def\beginmulticolumns - {\par - \flushnotes - \xdef\precolumndepth{\the\prevdepth}% - \begingroup - % new - \leftskip1\leftskip - \rightskip1\rightskip - \edef\colleftskip {\the\leftskip}% - \edef\colrightskip{\the\rightskip}% - \leftskip\zeropoint - \rightskip\zeropoint - % - %\setcolumntextwidth\relax - %\setcolumntextheight\relax - \widowpenalty\zerocount % is gewoon beter - \clubpenalty \zerocount % zeker bij grids - \dopushcolumnfloats - \dimen0\dimexpr\pagetotal+\parskip+\openlineheight\relax - \ifdim\dimen0<\pagegoal - \allowbreak - \else - \break % Sometimes fails - \fi - \appendtoks\topskip1\topskip\to\everybodyfont - \the\everybodyfont % ugly here - \saveinterlinespace % ugly here - \initializecolumns\nofcolumns - \hangafter\zerocount - \hangindent\zeropoint - \everypar\emptytoks - \ifdim\pagetotal=\zeropoint \else - \verticalstrut - \vskip-\struttotal - \fi - \global\savedpagetotal\pagetotal - \setupoutputroutine[\s!multicolumn]% - \c_page_mul_routine\c_page_mul_routine_intercept - \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear ! - \global\precolumnboxheight\ht\precolumnbox - \c_page_mul_routine\c_page_mul_routine_continuous - \setcolumnfloats - \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}% - \checkbegincolumnfootnotes - \page_otr_command_set_hsize - \page_otr_command_set_vsize} +\def\page_mul_routine_error + {\showmessage\m!columns3\empty + \page_otr_construct_and_shipout\unvbox\normalpagebox} %D When we leave the multi||column mode, we have to process the not yet shipped out %D part of the columns. When we don't balance, we simply force a continuous output, @@ -343,160 +350,150 @@ %D macro's. It takes some reasoning to find out what happens and maybe I'm making %D some mistake, but it works. %D -%D Voiding box \type {\precolumnbox} is sometimes necessary, e.g. when there is no +%D Voiding box \type {\b_page_mul_preceding} is sometimes necessary, e.g. when there is no %D text given between \type {\begin..} and \type {\end..}. The \type {\par} is %D needed! -\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! ! - -\def\endmulticolumns - {%\par - \ifnum\multicolumnendsyncmethod=\plustwo - \synchronizeoutput - \else - % don't combine these - \vskip\lineheight - \vskip-\lineheight % take footnotes into account - \fi - \doflushcolumnfloat % added recently - %\doflushcolumnfloats % no, since it results in wrong top floats - \flushnotes % before start of columns - \par - \ifbalancecolumns - \ifnum\multicolumnendsyncmethod=\plusone - \c_page_mul_routine\c_page_mul_routine_continuous - \goodbreak - \fi - \c_page_mul_routine\c_page_mul_routine_balanced - \else - \goodbreak - \fi - % still the multi column routine - \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in - \prevdepth\zeropoint % columns before some noncolumned text text - % - \c_page_mul_routine\c_page_mul_routine_regular -% \page_otf_set_engine_output_routine{\singlecolumnout}% -% \page_otf_set_engine_output_routine{\page_otr_triggered_output_routine}% - % - \ifvoid\precolumnbox\else - \unvbox\precolumnbox - \fi - \global\precolumnboxheight\zeropoint - \endgroup % here - \nofcolumns\plusone - \page_otr_command_set_vsize % the outer vsize (NEEDS CHECKING) - \synchronizeoutput % new may 2004 / we need to: \pagegoal\vsize - \checkendcolumnfootnotes - \dosomebreak\allowbreak - \dopopcolumnfloats} - %D Because some initializations happen three times, we defined a macro for %D them. Erasing \type{\everypar} is needed because we don't want anything %D to interfere. -\def\setmulticolumnsout - {\everypar\emptytoks +\unexpanded\def\page_mul_initialize_variables + {\reseteverypar \dontcomplain \settopskip \setmaxdepth - \topskip1\topskip - \splittopskip\topskip - \splitmaxdepth\maxdepth - \boxmaxdepth\maxdepth % dangerous - \emergencystretch\zeropoint\relax} % sometimes needed ! + \topskip 1\topskip + \splittopskip \topskip + \splitmaxdepth \maxdepth + \boxmaxdepth \maxdepth % dangerous + \emergencystretch\zeropoint + \relax} % sometimes needed ! %D Flushing the page comes to pasting the columns together and appending the result -%D to box \type {\precolumnbox}, if not void. I've seen a lot of implementations in +%D to box \type {\b_page_mul_preceding}, if not void. I've seen a lot of implementations in %D which some skip was put between normal text and multi||column text. When we don't %D want this, the baselines can be messed up. I hope the seemingly complicated %D calculation of a correction \type {\kern} is adequate to overcome this. Although %D not watertight, spacing is taken into account and even multiple mode changes on %D one page go well. But cross your fingers and don't blame me. %D -%D One of the complications of flushing out the boxes is that \type {\precolumnbox} +%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding} %D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the %D page when using \type {\raggedbottom}. It took a lot of time before these kind of %D problems were overcome. Using \type {\unvbox} at the wrong moment can generate -%D \type {\balancingerror}'s. +%D \type {\page_mul_routine_error}'s. %D %D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when %D generating material between columns as well as postprocessing column lines. -\let\maxcolumnheight=\zeropoint -\let\maxcolumndepth =\zeropoint +\newdimen\maxcolumnheight +\newdimen\maxcolumndepth \newbox\columnpagebox -\def\setmaxcolumndimensions - {\let\maxcolumnheight\!!zeropoint - \let\maxcolumndepth \!!zeropoint - \dohandleallcolumns - {\ifdim\ht\currentcolumnbox>\maxcolumnheight - \edef\maxcolumnheight{\the\ht\currentcolumnbox}% - \fi - \ifdim\dp\currentcolumnbox>\maxcolumndepth - \edef\maxcolumndepth{\the\dp\currentcolumnbox}% - \fi}} +\def\page_mul_calculate_column_result_dimensions + {\maxcolumnheight\zeropoint + \maxcolumndepth \zeropoint + \dohandleallcolumnscs\page_mul_calculate_column_result_dimensions_step} + +\def\page_mul_calculate_column_result_dimensions_step + {\ifdim\ht\currentcolumnbox>\maxcolumnheight + \maxcolumnheight\ht\currentcolumnbox + \fi + \ifdim\dp\currentcolumnbox>\maxcolumndepth + \maxcolumndepth\dp\currentcolumnbox + \fi} \setnewconstant\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++ \setnewconstant\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid -\def\flushprecolumnboxnogrid - {\unvbox\precolumnbox} - -\def\flushprecolumnboxongrid - {\scratchdimen\savedpagetotal - \advance\scratchdimen -\ht\precolumnbox - \advance\scratchdimen -\dp\precolumnbox - \advance\scratchdimen -\topskip - \box\precolumnbox +\def\page_mul_flush_preceding_normal + {\unvbox\b_page_mul_preceding} + +\def\page_mul_flush_preceding_ongrid + {\scratchdimen\dimexpr + \savedpagetotal + -\d_page_mul_preceding_height + -\d_page_mul_preceding_depth + -\topskip + \relax + \box\b_page_mul_preceding \kern\scratchdimen} -\newconditional\someprecolumncontent +\def\page_mul_flush_packaged_columns_continued + {\bgroup + \page_mul_flush_packaged_columns_indeed + \box\columnpagebox + \egroup} -\def\flushcolumnedpage#1% +\def\page_mul_flush_packaged_columns_balanced {\bgroup - \ifvoid\precolumnbox - \setfalse\someprecolumncontent % will be set elsewhere + \page_mul_flush_packaged_columns_indeed + % messy correction, we need to rewrite this module (newcolumns) + \setbox\columnpagebox\vbox + {\offinterlineskip + \scratchdimen\ht\columnpagebox + \advance\scratchdimen\dp\columnpagebox % we probably lost that one already + \box\columnpagebox + \vskip-\scratchdimen}% + \scratchdimen\noflines\openlineheight + \advance\scratchdimen-\openstrutdepth + \ifgridsnapping + % quick hack (at least it works with itemize) \else - \settrue\someprecolumncontent - \mkprocessboxcontents\precolumnbox + \advance\scratchdimen-\openlineheight + \advance\scratchdimen\topskip + \fi + \ht\columnpagebox\scratchdimen + \dp\columnpagebox\openstrutdepth + % end of mess + \box\columnpagebox + \egroup} + +\def\page_mul_flush_packaged_columns_indeed + {\ifvoid\b_page_mul_preceding + \setfalse\c_page_mul_preceding_present % will be set elsewhere + \else + \settrue\c_page_mul_preceding_present + \page_postprocessors_box\b_page_mul_preceding \fi \forgetall - \setmulticolumnsout - \setmaxcolumndimensions + \page_mul_initialize_variables + \page_mul_calculate_column_result_dimensions + \page_mul_postprocess_linenumbers \dohandleallcolumns - {\mkprocesscolumncontents\currentcolumnbox}% + {\page_postprocessors_column\currentcolumnbox}% \dohandleallcolumns {\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}% - \postprocesscolumns + \page_mul_postprocess_lines + \page_mul_postprocess_columns \dohandleallcolumns - {\global\setbox\currentcolumnbox\hbox to \localcolumnwidth + {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width {\box\currentcolumnbox}% - \wd\currentcolumnbox\localcolumnwidth + \wd\currentcolumnbox\d_page_mul_used_width \ifheightencolumns - \ht\currentcolumnbox\fixedcolumnheight + \ht\currentcolumnbox\d_page_mul_forced_height \fi}% - \setmaxcolumndimensions + \page_mul_calculate_column_result_dimensions \overlaycolumnfootnotes \setbox\columnpagebox\vbox - {\hbox to \finalcolumntextwidth - {\hskip\colleftskip\relax % new, \relax needed - \ifreversecolumns - \@EA\dohandlerevcolumns + {\hbox to \makeupwidth + {\hskip\d_page_mul_leftskip\relax % new, \relax needed + \ifconditional\c_page_mul_reverse + \expandafter\dohandlerevcolumns \else - \@EA\dohandleallcolumns + \expandafter\dohandleallcolumns \fi {\finishcolumnbox {\setbox\scratchbox\hbox {\ifx\finishcolumnbox\relax\else\strut\fi - \strut\box\currentcolumnbox}% + \box\currentcolumnbox}% hm, why strut \anch_mark_column_box\scratchbox \box\scratchbox}% \hfil}% \unskip - \hskip\colrightskip}}% new + \hskip\d_page_mul_rightskip}}% new \scratchdimen\zeropoint \dohandleallcolumns {\ifdim-\ht\currenttopcolumnbox<\scratchdimen @@ -504,31 +501,31 @@ \fi \global\setbox\currenttopcolumnbox\emptybox}% \advance\scratchdimen \ht\columnpagebox - \setbox\scratchbox\hbox to \columntextwidth + \setbox\scratchbox\hbox to \makeupwidth {\vrule - \!!width\zeropoint - \!!height\scratchdimen - \!!depth\dp\columnpagebox - \dostepwiserecurse2\nofcolumns1{\hfil\betweencolumns}\hfil}% + \s!width\zeropoint + \s!height\scratchdimen + \s!depth\dp\columnpagebox + \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}% \setbox\columnpagebox\hbox {\box\columnpagebox - \hskip-\columntextwidth + \hskip-\makeupwidth \box\scratchbox}% - \postprocesscolumnpagebox % new, acts upon \box\columnpagebox - \ifconditional\someprecolumncontent - \settrue\someprecolumncontent + \page_mul_postprocess_page + \ifconditional\c_page_mul_preceding_present + \settrue\c_page_mul_preceding_present % next some incredible crappy code \ifcase\multicolumntopalignmethod - \flushprecolumnboxnogrid % not on grid + \page_mul_flush_preceding_normal % not on grid \or - \flushprecolumnboxongrid % force on grid - \else\ifgridsnapping % somehow this junk fails in pascal - \flushprecolumnboxongrid % obey grid settings, force on grid + \page_mul_flush_preceding_ongrid % force on grid + \else\ifgridsnapping + \page_mul_flush_preceding_ongrid % obey grid settings, force on grid \else - \flushprecolumnboxnogrid % ignore grid settings, not on grid + \page_mul_flush_preceding_normal % ignore grid settings, not on grid \fi \fi \fi - \global\precolumnboxheight\zeropoint + \global\d_page_mul_preceding_height\zeropoint \page_otr_command_set_vsize \dosomebreak\nobreak % hm, only needed when topstuff \ifgridsnapping @@ -538,7 +535,7 @@ % when we run into it again \or % \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte - \ifconditional\someprecolumncontent + \ifconditional\c_page_mul_preceding_present % \scratchdimen\topskip % \advance\scratchdimen -\openstrutheight % \nointerlineskip @@ -571,29 +568,7 @@ \dp\columnpagebox\zeropoint \global\finalcolumnheights\ht\columnpagebox \getnoflines\finalcolumnheights - \global\finalcolumnlines\noflines - \ifcase#1\else - % messy correction, we need to rewrite this module (newcolumns) - \setbox\columnpagebox\vbox - {\offinterlineskip - \scratchdimen\ht\columnpagebox - \advance\scratchdimen\dp\columnpagebox % we probably lost that one already - \box\columnpagebox - \vskip-\scratchdimen}% - \scratchdimen\noflines\openlineheight - \advance\scratchdimen-\openstrutdepth - \ifgridsnapping - % quick hack (at least it works with itemize) - \else - \advance\scratchdimen-\openlineheight - \advance\scratchdimen\topskip - \fi - \ht\columnpagebox\scratchdimen - \dp\columnpagebox\openstrutdepth - % end of mess - \fi - \box\columnpagebox - \egroup} + \global\finalcolumnlines\noflines} %D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to %D all boxes. One can use these hooks for special purposes. @@ -637,51 +612,55 @@ %D %D {\getbuffer} %D -%D This feature is implemented using the reshape macros -%D presented in \type{supp-box}. - -\def\postprocesscolumns - {\ifx\postprocesscolumnline\undefined \else - \dohandleallcolumns - {\global\setbox\currentcolumnbox\vtop - {\beginofshapebox - \unvbox\currentcolumnbox - \unskip\unskip - \endofshapebox - \reshapebox - {\dimen0\ht\shapebox - \dimen2\dp\shapebox - \setbox\shapebox\hbox to \hsize - {\postprocesscolumnline\shapebox}% - \ht\shapebox\dimen0 - \dp\shapebox\dimen2 - \box\shapebox}% - \flushshapebox - \everypar\emptytoks - \parskip\zeropoint % = \forgetall - \verticalstrut - \vskip-\struttotal - \vfil}}% - \fi - \ifx\postprocesscolumnbox\undefined \else - \dohandleallcolumns - {\global\setbox\currentcolumnbox\hbox - {\postprocesscolumnbox\currentcolumnbox}} - \fi} - -%D We default to doing nothing! - -\let\postprocesscolumnline =\undefined -\let\postprocesscolumnbox =\undefined -\let\postprocesscolumnpagebox=\relax - -%D \macros -%D {reversecolumnstrue} -%D -%D We can force the macro that takes care of combining the columns, to -%D flush them in the revere order. Of course, by default we don't reverse. - -\newif\ifreversecolumns +%D This feature is implemented using the reshape macros presented +%D in \type{supp-box}. + +\ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box +\ifdefined\postprocesscolumnline \else\let\postprocesscolumnline \relax\fi % operates on passed box +\ifdefined\postprocesscolumnbox \else\let\postprocesscolumnbox \relax\fi % operates on passed box +\ifdefined\postprocesscolumnpagebox \else\let\postprocesscolumnpagebox \relax\fi % operates on passed box + +\def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi} +\def\page_mul_postprocess_lines {\ifx\postprocesscolumnline \relax\else\page_mul_postprocess_lines_indeed \fi} +\def\page_mul_postprocess_columns {\ifx\postprocesscolumnbox \relax\else\page_mul_postprocess_columns_indeed \fi} +\def\page_mul_postprocess_page {\ifx\postprocesscolumnpagebox \relax\else\page_mul_postprocess_page_indeed \fi} + +\def\page_mul_postprocess_linenumbers_indeed + {\dohandleallcolumns{\page_postprocessors_column\currentcolumnbox}} + +\def\page_mul_postprocess_lines_indeed + {\dohandleallcolumnscs\page_mul_postprocess_lines_step} + +\def\page_mul_postprocess_lines_step % TODO: use lua solution instead + {\global\setbox\currentcolumnbox\vtop + {\beginofshapebox + \unvbox\currentcolumnbox + \unskip\unskip + \endofshapebox + \reshapebox + {\scratchheight\ht\shapebox + \scratchdepth \dp\shapebox + \setbox\shapebox\hbox to \hsize + {\postprocesscolumnline\shapebox}% + \ht\shapebox\scratchheight + \dp\shapebox\scratchdepth + \box\shapebox}% + \flushshapebox + \reseteverypar + \parskip\zeropoint % = \forgetall + \verticalstrut + \vskip-\struttotal + \vfil}} + +\def\page_mul_postprocess_columns_indeed + {\dohandleallcolumnscs\page_mul_postprocess_columns_step} + +\def\page_mul_postprocess_columns_step + {\global\setbox\currentcolumnbox\hbox + {\postprocesscolumnbox\currentcolumnbox}} + +\def\page_mul_postprocess_page_indeed + {\postprocesscolumnpagebox\columnpagebox} %D Here comes the simple splitting routine. It's a bit longer than expected because %D of ragging bottoms or not. This part can be a bit shorter but I suppose that I @@ -691,46 +670,48 @@ %D First we present some auxiliary routines. Any material, like for instance floats, %D that is already present in the boxes is preserved. -\def\splitcolumn#1from \box#2to \dimen#3 top \box#4% +\newdimen\d_page_mul_split_height_used +\newdimen\d_page_mul_split_height_max + +\def\page_mul_split_column#1#2#3#4% copy or box {\bgroup \ifdim\ht#4>\zeropoint - \dimen0\dimen#3\relax - \dimen2\dimen0 - \advance\dimen0 -\ht#4% - \columnfootnotecorrection{#1}{\dimen0}% - \setbox0\vsplit#2 to \dimen0 - \global\setbox#1\vbox to \dimen2 + \d_page_mul_split_height_used#3\relax + \d_page_mul_split_height_max\d_page_mul_split_height_used + \advance\d_page_mul_split_height_used -\ht#4% + \columnfootnotecorrection{#1}\d_page_mul_split_height_used + \setbox\scratchbox\vsplit#2 to \d_page_mul_split_height_used + \global\setbox#1\vbox to \d_page_mul_split_height_max {\ifgridsnapping - \dimen0-\openstrutheight - \advance\dimen0 \topskip - \vskip\dimen0\copy#4\vskip-\dimen0 + \scratchdimen\dimexpr\topskip-\openstrutheight\relax + \vskip\scratchdimen + \copy#4% + \vskip-\scratchdimen \else \unvcopy#4% \fi - \fuzzysnappedbox\unvbox0 + \fuzzysnappedbox\unvbox\scratchbox \fakecolumnfootnotes{#1}}% + \else\ifcase\c_strc_notes_page_location + \global\setbox#1\vsplit#2 to #3% + \global\setbox#1\vbox + {\fuzzysnappedbox\unvbox{#1}}% % or \box ? \else - \ifcase\c_strc_notes_page_location - \global\setbox#1\vsplit#2 to \dimen#3% - \global\setbox#1\vbox - {\fuzzysnappedbox\unvbox{#1}}% % or \box ? - \else - \columnfootnotecorrection{#1}{\dimen#3}% - \setbox0\vsplit#2 to \dimen#3% - \global\setbox#1\vbox to \dimen#3% - {\fuzzysnappedbox\unvbox0 - \fakecolumnfootnotes{#1}}% - \fi - \fi + \columnfootnotecorrection{#1}{#3}% + \setbox\scratchbox\vsplit#2 to #3% + \global\setbox#1\vbox to #3% + {\fuzzysnappedbox\unvbox\scratchbox + \fakecolumnfootnotes{#1}}% + \fi \fi \egroup} -\def\splitcurrentcolumn from \box#1to \dimen#2% - {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox} +\def\page_mul_split_current_column#1#2% + {\page_mul_split_column\currentcolumnbox{#1}{#2}\currenttopcolumnbox} -\def\splitfirstcolumn from \box#1to \dimen#2% - {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox} +\def\page_mul_split_first_column#1#2% + {\page_mul_split_column\firstcolumnbox{#1}{#2}\firsttopcolumnbox} -\def\splitlastcolumn from \box#1to \dimen#2% +\def\page_mul_split_last_column#1#2% {\global\setbox\lastcolumnbox\vbox {\unvcopy\lasttopcolumnbox \fuzzysnappedbox\unvbox{#1}% @@ -738,128 +719,130 @@ %D NEW: still to be documented. -\def\fakecolumnfootnotes#1% - {\relax - \ifcase\c_strc_notes_page_location\else - \ifnum#1=\lastcolumnbox - \fakenotes - \fi - \fi} - -\def\columnfootnotecorrection#1#2% - {\relax - \ifcase\c_strc_notes_page_location - % page notes - \or - \ifnum#1=\firstcolumnbox\relax - \calculatetotalclevernoteheight - \advance#2 -\totalnoteheight - \fi - \else - \ifnum#1=\lastcolumnbox\relax - \calculatetotalclevernoteheight - \advance#2 -\totalnoteheight - \fi - \fi} - -\def\overlaycolumnfootnotes - {\relax - \ifcase\c_strc_notes_page_location - % page - \or - \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi - \or - \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi - \fi} - -\newbox\b_page_mul_notes - -\def\page_mul_notes_flush_first_column - {\begingroup - \setbox\b_page_mul_notes\vbox{\placenoteinserts}% - \ifzeropt\ht\b_page_mul_notes - % can't happen as we already checked - \else - \getmulticolumnlines - \advance\nofcolumnlines \minustwo - \scratchdimen\dimexpr\nofcolumnlines\lineheight+\topskip\relax - \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% - \ht\b_page_mul_notes\openstrutheight - \dp\b_page_mul_notes\openstrutdepth - \wd\b_page_mul_notes\zeropoint - \scratchdimen\ht\firstcolumnbox - \global\setbox\firstcolumnbox\vbox to \scratchdimen - {\box\firstcolumnbox - \vskip-\scratchdimen - \box\b_page_mul_notes}% - \fi - \endgroup} + \def\fakecolumnfootnotes#1% + {\relax + \ifcase\c_strc_notes_page_location\else + \ifnum#1=\lastcolumnbox + \fakenotes + \fi + \fi} + + \def\columnfootnotecorrection#1#2% + {\relax + \ifcase\c_strc_notes_page_location + % page notes + \or + \ifnum#1=\firstcolumnbox\relax + \calculatetotalclevernoteheight + \advance#2 -\totalnoteheight + \fi + \else + \ifnum#1=\lastcolumnbox\relax + \calculatetotalclevernoteheight + \advance#2 -\totalnoteheight + \fi + \fi} + + \def\overlaycolumnfootnotes + {\relax + \ifcase\c_strc_notes_page_location + % page + \or + \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi + \or + \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi + \fi} + + \newbox\b_page_mul_notes + + \def\page_mul_notes_flush_first_column + {\begingroup + \setbox\b_page_mul_notes\vbox{\placenoteinserts}% + \ifzeropt\ht\b_page_mul_notes + % can't happen as we already checked + \else + \page_mul_set_n_of_lines + \advance\c_page_mul_n_of_lines \minustwo + \scratchdimen\dimexpr\c_page_mul_n_of_lines\lineheight+\topskip\relax + \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% + \ht\b_page_mul_notes\openstrutheight + \dp\b_page_mul_notes\openstrutdepth + \wd\b_page_mul_notes\zeropoint + \scratchdimen\ht\firstcolumnbox + \global\setbox\firstcolumnbox\vbox to \scratchdimen + {\box\firstcolumnbox + \vskip-\scratchdimen + \box\b_page_mul_notes}% + \fi + \endgroup} -\def\page_mul_notes_flush_last_column - {\begingroup - \setbox\b_page_mul_notes\vbox{\placenoteinserts}% - \ifzeropt\ht\b_page_mul_notes - % can't happen as we already checked - \else - % maybe here also \getmulticolumnlines - \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp - \getnoflines\scratchdimen - \advance\noflines \minustwo - \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax - \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% - \ht\b_page_mul_notes\openstrutheight - \dp\b_page_mul_notes\openstrutdepth - \wd\b_page_mul_notes\zeropoint - \scratchdimen\ht\lastcolumnbox - \global\setbox\lastcolumnbox\vbox to \scratchdimen - {\box\lastcolumnbox - \vskip-\scratchdimen - \box\b_page_mul_notes}% - \fi - \endgroup} + \def\page_mul_notes_flush_last_column + {\begingroup + \setbox\b_page_mul_notes\vbox{\placenoteinserts}% + \ifzeropt\ht\b_page_mul_notes + % can't happen as we already checked + \else + % maybe here also \page_mul_set_n_of_lines + \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp + \getnoflines\scratchdimen + \advance\noflines \minustwo + \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax + \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% + \ht\b_page_mul_notes\openstrutheight + \dp\b_page_mul_notes\openstrutdepth + \wd\b_page_mul_notes\zeropoint + \scratchdimen\ht\lastcolumnbox + \global\setbox\lastcolumnbox\vbox to \scratchdimen + {\box\lastcolumnbox + \vskip-\scratchdimen + \box\b_page_mul_notes}% + \fi + \endgroup} %D Here comes the routine that splits the long box in columns. The macro \type -%D {\flushcolumnfloats} can be used to flush either floats that were present before +%D {\page_mul_flush_floats} can be used to flush either floats that were present before %D the multi||column mode was entered, or floats that migrate to next columns. %D Flushing floats is a delicate process. -\def\continuousmulticolumnsout +\def\page_mul_routine_continue {\bgroup \forgetall - \setmulticolumnsout -% \dimen0=\columntextheight -% \advance\dimen0 -\precolumnboxheight -% \settotalinsertionheight -% \advance\dimen0 -\totalinsertionheight -% \ifgridsnapping % evt altijd, nog testen -% \getnoflines{\dimen0} -% \dimen0=\noflines\openlineheight -% \fi - \getmulticolumnlines - \dimen0=\nofcolumnlines\openlineheight + \page_mul_initialize_variables + % \dimen0=\makeupheight + % \advance\dimen0 -\d_page_mul_preceding_height + % \settotalinsertionheight + % \advance\dimen0 -\totalinsertionheight + % \ifgridsnapping % evt altijd, nog testen + % \getnoflines{\dimen0} + % \dimen0=\noflines\openlineheight + % \fi + \page_mul_set_n_of_lines + \d_page_mul_balance_target\c_page_mul_n_of_lines\openlineheight + \ifconditional\c_page_mul_trace + \writestatus\m!columns{continue: lines=\the\c_page_mul_n_of_lines, target=\the\d_page_mul_balance_target, textheight=\the\textheight}% + \fi \dohandleallcolumns - {\splitcurrentcolumn from \box\normalpagebox to \dimen0}% - \setbox\restofpage\vbox{\unvbox\normalpagebox}% + {\page_mul_split_current_column\normalpagebox\d_page_mul_balance_target}% + \setbox\b_page_mul_preceding_rest_of_page\vbox{\unvbox\normalpagebox}% \ifinheritcolumns \ifcase\bottomraggednessmode % 0 = ragged \dohandleallcolumns {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox - {\dimen0\dp\currentcolumnbox + {\scratchdepth\dp\currentcolumnbox \unvbox\currentcolumnbox - \vskip-\dimen0 - \vskip\openstrutdepth % \strutdp + \vskip\dimexpr\openstrutdepth-\scratchdepth\relax \prevdepth\openstrutdepth % \strutdp \vfill}}% \strc_notes_check_if_bottom_present - \ifconditional\c_notes_bottom_present \else - \dimen0\ht\firstcolumnbox - \fi + %\ifconditional\c_notes_bottom_present \else + % \dimen0\ht\firstcolumnbox % ?? + %\fi \or % 1 = normal - \advance\dimen0 \maxdepth + \advance\d_page_mul_balance_target\maxdepth \dohandleallcolumns - {\global\setbox\currentcolumnbox\vbox to \dimen0 + {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target {\unvbox\currentcolumnbox}}% \or % 2 = baseline @@ -867,7 +850,7 @@ \fi \else \dohandleallcolumns - {\global\setbox\currentcolumnbox\vbox to \dimen0 + {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target {\ifstretchcolumns \unvbox\currentcolumnbox \else @@ -875,14 +858,14 @@ \vfill \fi}}% \dohandleallcolumns - {\ht\currentcolumnbox\dimen0}% redundant + {\ht\currentcolumnbox\d_page_mul_balance_target}% redundant \fi - \setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}% - \page_otr_construct_and_shipout\box\precolumnbox + \setbox\b_page_mul_preceding\vbox{\page_mul_flush_packaged_columns_continued}% + \page_otr_construct_and_shipout\box\b_page_mul_preceding \page_otr_command_set_hsize \page_otr_command_set_vsize - \flushcolumnfloats - \unvbox\restofpage + \page_mul_flush_floats + \unvbox\b_page_mul_preceding_rest_of_page % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen \egroup} @@ -892,161 +875,184 @@ %D balance columns with few lines. The use of \type {\box2} and \type {\box4} %D garantees a more robust check when skips are used. -\def\multicolumnsbalancemax{250} % 100 is too small when floats are involved - -\def\balancedmulticolumnsout +\newbox \b_page_mul_balance_content +\newbox \b_page_mul_balance_first_column +\newbox \b_page_mul_balance_column +\newconstant \c_page_mul_balance_tries_max +\newcount \c_page_mul_balance_tries +\newdimen \d_page_mul_balance_target +\newdimen \d_page_mul_balance_target_less +\newdimen \d_page_mul_balance_natural_height +\newdimen \d_page_mul_balance_regular_height +\newdimen \d_page_mul_balance_step +\newdimen \d_page_mul_balance_fuzzyness +\newdimen \d_page_mul_balance_threshold +\newconditional\c_page_mul_balance_possible + +\c_page_mul_balance_tries_max 250 % 100 is too small when floats are involved + +\def\page_mul_routine_balance {\bgroup - \setmulticolumnsout + \page_mul_initialize_variables \widowpenalty\zerocount - \setbox0\vbox{\unvbox\normalpagebox}% - \ifdim\ht0>\openlineheight % at least one line - \ifnum\minbalancetoplines<2 % balance anyway - \donetrue + \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}% + \ifdim\ht\b_page_mul_balance_content>\openlineheight % at least one line + \ifnum\c_page_mul_balance_minimum<\plustwo % balance anyway + \settrue\c_page_mul_balance_possible \else % check criterium to available lines - \getnoflines{\ht0}% + \getnoflines{\ht\b_page_mul_balance_content}% \divide\noflines \nofcolumns \relax - \ifnum\noflines<\minbalancetoplines \relax - % let's play safe - \ifdim\dimexpr\ht0+\ht\firsttopcolumnbox+\openlineheight\relax>\columntextheight - \donetrue % column exceeding text height + \ifnum\noflines<\c_page_mul_balance_minimum \relax + \ifdim\dimexpr\ht\b_page_mul_balance_content+\ht\firsttopcolumnbox+\openlineheight\relax>\makeupheight + \settrue\c_page_mul_balance_possible % column exceeding text height \else - \donefalse % it seems to fit + \setfalse\c_page_mul_balance_possible % it seems to fit \fi - \else % balance indeed - \donetrue + \else + \settrue\c_page_mul_balance_possible % balance indeed \fi \fi - \else % balancing does not make sense - \donefalse + \else + \setfalse\c_page_mul_balance_possible % balancing does not make sense \fi - \ifdone % start balancing, was: \ifdim\ht0>\openlineheight - \dimen0\ht0 - \advance\dimen0 \topskip - \advance\dimen0 -\baselineskip - \dohandleallcolumns - {\advance\dimen0 \ht\currenttopcolumnbox}% - \divide\dimen0 \nofcolumns - \vbadness\plustenthousand - \count255=\zerocount - \bgroup - \ifgridsnapping - \dimen2\lineheight - \else - \dimen2=\onepoint % RUBISH - \dimen2=\spacingfactor\dimen2 - \fi - \doloop - {\advance\count255 \plusone - \global\setbox\restofpage\copy0\relax - \splitfirstcolumn from \box\restofpage to \dimen0 - \dohandlemidcolumns - {\splitcurrentcolumn from \box\restofpage to \dimen0}% - \splitlastcolumn from \box\restofpage to \dimen0 - \setbox2\vbox{\unvcopy\firstcolumnbox}% - \dimen4\zeropoint - \dohandleallcolumns - {\setbox4\vbox - {\unvcopy\currentcolumnbox - %rather new, test this on pdftex-z.tex - \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter - %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}% -% \dimen6\ht4 \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}% - \ifdim\ht4>\dimen4 \dimen4=\ht4 \fi}% - \advance\dimen4 -.0005pt % get rid of accurracy problem, pretty new - \ifnum\count255>\multicolumnsbalancemax\relax - \exitloop - \else\ifdim\dimen4>\ht2 - \advance\dimen0 \dimen2\relax - \else - \exitloop - \fi\fi}% - \dohandleallcolumns - {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% NIEUW - \ifnum\count255>\multicolumnsbalancemax\relax - \showmessage\m!columns7\empty - \else - \showmessage\m!columns8{\the\count255\space}% - \fi - \egroup + \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight + \page_mul_balance_try_one \ifinheritcolumns - % We cannot assume that the first column is the tallest, if - % only because we may have an aborted balance (one line in the - % first column and a graphic in the second one). - % - % \dimen0\ht\firstcolumnbox - % \dimen2\ht\firstcolumnbox - % - \dimen0=\zeropoint - \dohandleallcolumns - {\ifdim\ht\currentcolumnbox>\dimen0 - \dimen0=\ht\currentcolumnbox - \fi}% - \dimen2\dimen0 - % so far - \advance\dimen2 -\openlineheight - \dohandleallcolumns - {\dimen4\ht\currentcolumnbox - \dimen6=10\openlineheight % funny value - \global\setbox\currentcolumnbox\vbox to \dimen0 - {\unvbox\currentcolumnbox - \ifdim\dimen4>\dimen6 - \ifdim\dimen4<\dimen0 - \ifdim\dimen4>\dimen2 - \vskip\zeropoint % !! - \else - \vskip\openlineheight - \vfill - \fi - \else - \vskip\zeropoint - \fi - \else - \vskip\openlineheight - \vfill - \fi}}% + \page_mul_balance_try_two \else - \bgroup - \ifstretchcolumns - \dimen0\ht\firstcolumnbox - \dimen2=\bottomtolerance\ht\firstcolumnbox - \setbox0\vbox{\unvcopy\lastcolumnbox}% - \advance\dimen0 -\ht0\relax - \advance\dimen0 -\dp0\relax - \ifdim\dimen0>\openlineheight\relax - \ifdim\dimen0>\dimen2\relax - % \stretchcolumnsfalse % beter goed slecht dan slecht goed - \showmessage\m!columns9\empty - \fi - \fi - \fi - \dohandleallcolumns - {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox - {\ifstretchcolumns - \unvbox\currentcolumnbox - \else - \box\currentcolumnbox - \vfill - \fi}}% - \egroup + \page_mul_balance_try_three \fi \else % a one liner is not properly handled here, so best rewrite the text then \showmessage\m!columns{10}\empty - \global\setbox\firstcolumnbox\vbox{\unvbox0}% + \global\setbox\firstcolumnbox\vbox{\unvbox\b_page_mul_balance_content}% \fi \c_page_mul_routine\c_page_mul_routine_error \baselinebottom % forces depth in separation rule - \flushcolumnedpage\plusone - \multicolumnseject + \page_mul_flush_packaged_columns_balanced + \page_mul_eject_page \egroup} -\def\multicolumnseject +\def\page_mul_eject_page {%\ifdim\pagetotal>\textheight % \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point) %\else \allowbreak }%\fi} +\def\page_mul_balance_try_one + {\d_page_mul_balance_target\dimexpr\ht\b_page_mul_balance_content+\topskip-\baselineskip\relax + \dohandleallcolumns + {\advance\d_page_mul_balance_target \ht\currenttopcolumnbox}% + \divide\d_page_mul_balance_target \nofcolumns + \vbadness\plustenthousand + \c_page_mul_balance_tries\zerocount + \bgroup + \ifgridsnapping + \d_page_mul_balance_step\lineheight + \else + \d_page_mul_balance_step\spacingfactor\onepoint % rubish + \fi + \doloop\page_mul_balance_try_one_attempt + \dohandleallcolumns + {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% + \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax + \showmessage\m!columns7\empty + \else + \showmessage\m!columns8{\the\c_page_mul_balance_tries\space}% + \fi + \egroup} + +\def\page_mul_balance_try_one_attempt + {\advance\c_page_mul_balance_tries \plusone + \global\setbox\b_page_mul_preceding_rest_of_page\copy\b_page_mul_balance_content\relax + \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target + \dohandlemidcolumns + {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}% + \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target + \setbox\b_page_mul_balance_first_column\vbox{\unvcopy\firstcolumnbox}% + \d_page_mul_balance_natural_height\zeropoint + \dohandleallcolumns\page_mul_balance_try_one_attempt_step + \advance\d_page_mul_balance_natural_height -.0005pt % (33sp) get rid of accurracy problem, pretty new + \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax + \exitloop + \else\ifdim\d_page_mul_balance_natural_height>\ht\b_page_mul_balance_first_column + \advance\d_page_mul_balance_target \d_page_mul_balance_step\relax + \else + \exitloop + \fi\fi} + +\def\page_mul_balance_try_one_attempt_step + {\setbox\b_page_mul_balance_column\vbox + {\unvcopy\currentcolumnbox + \unpenalty + \unskip + \unpenalty + \unskip}% maybe better in main splitter + \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height + \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column + \fi} + +% We cannot assume that the first column is the tallest, if only because we may +% have an aborted balance (one line in the first column and a graphic in the +% second one). + +\def\page_mul_balance_try_two + {\d_page_mul_balance_target\zeropoint + \dohandleallcolumns + {\ifdim\ht\currentcolumnbox>\d_page_mul_balance_target + \d_page_mul_balance_target\ht\currentcolumnbox + \fi}% + \d_page_mul_balance_target_less\dimexpr\d_page_mul_balance_target-\openlineheight\relax + \dohandleallcolumnscs\page_mul_balance_try_two_step} + +\def\page_mul_balance_try_two_step + {\d_page_mul_balance_regular_height\ht\currentcolumnbox + \d_page_mul_balance_threshold\plusten\openlineheight % funny value + \global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target + {\unvbox\currentcolumnbox + \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_threshold + \ifdim\d_page_mul_balance_regular_height<\d_page_mul_balance_target + \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_target_less + \vskip\zeropoint % !! + \else + \vskip\openlineheight + \vfill + \fi + \else + \vskip\zeropoint + \fi + \else + \vskip\openlineheight + \vfill + \fi}} + +\def\page_mul_balance_try_three + {\bgroup + \ifstretchcolumns + \d_page_mul_balance_target\ht\firstcolumnbox + \d_page_mul_balance_fuzzyness\bottomtolerance\ht\firstcolumnbox + \setbox\b_page_mul_balance_content\vbox{\unvcopy\lastcolumnbox}% + \advance\d_page_mul_balance_target-\htdp\b_page_mul_balance_content\relax + \ifdim\d_page_mul_balance_target>\openlineheight\relax + \ifdim\d_page_mul_balance_target>\d_page_mul_balance_fuzzyness\relax + % \stretchcolumnsfalse % beter good bad than bad good + \showmessage\m!columns9\empty + \fi + \fi + \fi + \dohandleallcolumnscs\page_mul_balance_try_three_step + \egroup} + +\def\page_mul_balance_try_three_step + {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox + {\ifstretchcolumns + \unvbox\currentcolumnbox + \else + \box\currentcolumnbox + \vfill + \fi}} + %D The multicolumn mechanism is incorporated in a \CONTEXT\ interface, %D which acts like: %D @@ -1084,23 +1090,26 @@ %D %D When all those floats are flushed, we switch to the local flushing routine. -\def\dopushcolumnfloats - {\ifsomefloatwaiting - \showmessage\m!columns6{\the\savednoffloats}% - \global\setbox\savedfloatlist\box\floatlist - \xdef\dopopcolumnfloats - {\global\savednoffloats\the\savednoffloats - \global\setbox\floatlist\box\savedfloatlist - \global\noexpand\somefloatwaitingtrue}% - \global\savednoffloats\zerocount - \global\somefloatwaitingfalse - \else - \global\let\dopopcolumnfloats\relax - \fi} - -\let\dopopcolumnfloats\relax +% \newbox \floatlist +% \newbox \savedfloatlist +% +% \def\page_floats_column_push_saved +% {\ifconditional\c_page_floats_some_waiting +% \showmessage\m!columns6{\the\savednoffloats}% +% \global\setbox\savedfloatlist\box\floatlist +% \xdef\page_floats_column_pop_saved +% {\global\savednoffloats\the\savednoffloats +% \global\setbox\floatlist\box\savedfloatlist +% \global\noexpand\settrue\c_page_floats_some_waiting}% +% \global\savednoffloats\zerocount +% \global\setfalse\c_page_floats_some_waiting +% \else +% \global\let\page_floats_column_pop_saved\relax +% \fi} +% +% \let\page_floats_column_pop_saved\relax -% \def\setcolumnfloats % messy as it adapts everypar +% \def\page_mul_initialize_floats % messy as it adapts everypar % {\xdef\globalsavednoffloats{\the\savednoffloats}% % \ifnum\globalsavednoffloats>\zerocount % \setglobalcolumnfloats % hm, we always push so this never happens @@ -1108,66 +1117,66 @@ % \setlocalcolumnfloats % \fi} -\def\setcolumnfloats % messy as it adapts everypar, we need to adapt this - {\setlocalcolumnfloats} - -\newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now) + \def\page_mul_initialize_floats % messy as it adapts everypar, we need to adapt this + {\setlocalcolumnfloats} -\unexpanded\def\page_mul_command_flush_floats - {\ifconditional\onlylocalcolumnfloats - \doflushcolumnfloats - \else - \page_one_command_flush_floats - \fi} + \newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now) + \newtoks \everylocalcolumnfloatspar -\unexpanded\def\page_mul_command_check_if_float_fits - {\ifconditional\onlylocalcolumnfloats - \docolumnroomfloat - \fi} - -\unexpanded\def\page_mul_command_flush_saved_floats - {\ifconditional\onlylocalcolumnfloats\relax - \else - \page_one_command_flush_saved_floats - \fi} - -\unexpanded\def\page_mul_command_flush_top_insertions - {\ifconditional\onlylocalcolumnfloats\relax - \else - \page_one_command_flush_top_insertions - \fi} - -\newtoks\everylocalcolumnfloatspar - -\everylocalcolumnfloatspar - {\flushnotes - \flushcolumnfloat - % \flushmargincontents - \checkindentation} + \unexpanded\def\page_mul_command_flush_floats + {\ifconditional\onlylocalcolumnfloats + \doflushcolumnfloats + \else + \page_one_command_flush_floats + \fi} -\def\setlocalcolumnfloats - {\settrue\onlylocalcolumnfloats - \everypar\everylocalcolumnfloatspar - \let\flushcolumnfloat\doflushcolumnfloat - \let\flushcolumnfloats\doflushcolumnfloats} + \unexpanded\def\page_mul_command_check_if_float_fits + {\ifconditional\onlylocalcolumnfloats + \docolumnroomfloat + \fi} -\def\setglobalcolumnfloats - {\setfalse\onlylocalcolumnfloats - \everypar\emptytoks - \let\flushcolumnfloat\relax - \let\flushcolumnfloats\noflushcolumnfloats} + \unexpanded\def\page_mul_command_flush_saved_floats + {\ifconditional\onlylocalcolumnfloats\relax + \else + \page_one_command_flush_saved_floats + \fi} -\def\noflushcolumnfloats - {\bgroup - \xdef\localsavednoffloats{\the\savednoffloats}% - \global\savednoffloats\globalsavednoffloats - \page_otr_command_flush_top_insertions - \xdef\globalsavenoffloats{\the\savednoffloats}% - \ifnum\globalsavednoffloats=\zerocount - \setlocalcolumnfloats - \fi - \global\savednoffloats\localsavednoffloats - \egroup} + \unexpanded\def\page_mul_command_flush_top_insertions + {\ifconditional\onlylocalcolumnfloats\relax + \else + \page_one_command_flush_top_insertions + \fi} + + \appendtoks + \flushnotes + \page_mul_flush_float + %\flushmargincontents + \checkindentation + \to \everylocalcolumnfloatspar + + \def\setlocalcolumnfloats + {\settrue\onlylocalcolumnfloats + \everypar\everylocalcolumnfloatspar + \let\page_mul_flush_float\doflushcolumnfloat + \let\page_mul_flush_floats\doflushcolumnfloats} + + \def\setglobalcolumnfloats + {\setfalse\onlylocalcolumnfloats + \reseteverypar + \let\page_mul_flush_float\relax + \let\page_mul_flush_floats\noflushcolumnfloats} + + \def\noflushcolumnfloats + {\bgroup + \xdef\localsavednoffloats{\the\savednoffloats}% + \global\savednoffloats\globalsavednoffloats + \page_otr_command_flush_top_insertions + \xdef\globalsavenoffloats{\the\savednoffloats}% + \ifnum\globalsavednoffloats=\zerocount + \setlocalcolumnfloats + \fi + \global\savednoffloats\localsavednoffloats + \egroup} %D We need to calculate the amount of free space in a columns. When there is not %D enough room, we migrate the float to the next column. These macro's are @@ -1176,124 +1185,124 @@ %D floats have to be taken into account when we calculate the available space. It's %D a pitty that such things are no integral part of \TEX. -\def\getcolumnstatus\column#1\total#2\goal#3\\% - {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi - \dimen2=\zeropoint - \count255=\zerocount - \dimen8=\columntextheight - \advance\dimen8 -\precolumnboxheight - \def\dogetcolumnstatus - {\advance\count255 \plusone - \advance\dimen2 \ht\currenttopcolumnbox - \advance\dimen2 \dp\currenttopcolumnbox - \dimen4\dimen2 - \advance\dimen4 \dimen0 - \dimen6=\count255\dimen8 - \ifdim\dimen4>\dimen6 - \else - \let\dogetcolumnstatus\relax - \fi}% - \dohandleallcolumns{\dogetcolumnstatus}% - \ifnum\count255=0 \count255=1 \fi - #1=\count255 - #2=\dimen4 - #3=\dimen6 } - -\def\getinsertionheight - {\ifdim\pagegoal<\maxdimen - \bgroup - \dimen0=\columntextheight - \advance\dimen0 -\pagegoal - \xdef\insertionheight{\the\dimen0}% - \egroup - \else - \global\let\insertionheight\zeropoint - \fi} - -\def\docolumnroomfloat - {\ifpostponecolumnfloats - \global\roomforfloatfalse - \else\ifnofloatpermitted - \global\roomforfloatfalse - \else - \bgroup - \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\% - \dofloatsgetinfo\s!text - \setbox\scratchbox\vbox % tricky met objecten ? - {\blank[\rootfloatparameter\c!spacebefore] - \snaptogrid\vbox{\vskip\floatheight}}% copy? - \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher - \ifdim\dimen0>\dimen2 - \global\roomforfloatfalse - \else - \global\roomforfloattrue - \fi - \ifdim\floatwidth>\hsize - \showmessage\m!columns{11}\empty - \global\roomforfloatfalse - \fi - \egroup - \fi\fi} + \def\getcolumnstatus#1#2#3% + {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi + \dimen2=\zeropoint + \count255=\zerocount + \dimen8=\makeupheight + \advance\dimen8 -\d_page_mul_preceding_height + \def\dogetcolumnstatus + {\advance\count255 \plusone + \advance\dimen2 \ht\currenttopcolumnbox + \advance\dimen2 \dp\currenttopcolumnbox + \dimen4\dimen2 + \advance\dimen4 \dimen0 + \dimen6=\count255\dimen8 + \ifdim\dimen4>\dimen6 + \else + \let\dogetcolumnstatus\relax + \fi}% + \dohandleallcolumns{\dogetcolumnstatus}% + \ifnum\count255=0 \count255=1 \fi + #1=\count255 + #2=\dimen4 + #3=\dimen6 } + + \def\getinsertionheight + {\ifdim\pagegoal<\maxdimen + \bgroup + \dimen0=\makeupheight + \advance\dimen0 -\pagegoal + \xdef\insertionheight{\the\dimen0}% + \egroup + \else + \global\let\insertionheight\zeropoint + \fi} + + \def\docolumnroomfloat + {\ifpostponecolumnfloats + \global\setfalse\c_page_floats_room + \else\ifconditional\c_page_floats_not_permitted + \global\setfalse\c_page_floats_room + \else + \bgroup + \getcolumnstatus{\count255}{\dimen0}{\dimen2}% + \page_floats_get_info\s!text + \setbox\scratchbox\vbox % tricky met objecten ? + {\blank[\rootfloatparameter\c!spacebefore] + \snaptogrid\vbox{\vskip\floatheight}}% copy? + \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher + \ifdim\dimen0>\dimen2 + \global\setfalse\c_page_floats_room + \else + \global\settrue\c_page_floats_room + \fi + \ifdim\floatwidth>\hsize + \showmessage\m!columns{11}\empty + \global\setfalse\c_page_floats_room + \fi + \egroup + \fi\fi} %D Flushing one float is done as soon as possible, i.e. \type {\everypar}. %D This means that (at the moment) sidefloats are not supported (overulled)! -\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue - -\def\doflushcolumnfloat - {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifsomefloatwaiting - \doflushcolumnfloatindeed - \fi\fi\fi} - -\def\doflushcolumnfloatindeed - {\bgroup - \forgetall - \let\doflushcolumnfloat\relax - \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\% - \ifdim\dimen0>\zeropoint - \dofloatsgetinfo\s!text - \ifdim\floatwidth>\hsize - % dropped ? - \else - \setbox2\vbox - {\blank[\rootfloatparameter\c!spacebefore] - \snaptogrid\vbox{\vskip\floatheight}}% - \advance\dimen0 \ht2 - \ifdim\dimen0>\dimen2 - \ifnum\mofcolumns<\nofcolumns - \advance\mofcolumns \plusone - \ifdim\ht\currenttopcolumnbox=\zeropoint - \dofloatsflush\s!text{1}% - \global\setbox\currenttopcolumnbox\vbox - {\snaptogrid\vbox{\box\floatbox} - \whitespace % nodig ? - \blank[\rootfloatparameter\c!spaceafter]}% - \dimen4=\htdp\currenttopcolumnbox - \global\advance\vsize -\dimen4 - \advance\dimen4 -\pagegoal - \global\pagegoal-\dimen4 - \showmessage\m!columns{12}a% + \newif\ifflushingcolumnfloats \flushingcolumnfloatstrue + + \def\doflushcolumnfloat + {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting + \doflushcolumnfloatindeed + \fi\fi\fi} + + \def\doflushcolumnfloatindeed + {\bgroup + \forgetall + \let\doflushcolumnfloat\relax + \getcolumnstatus{\mofcolumns}{\dimen0}{\dimen2}% + \ifdim\dimen0>\zeropoint + \page_floats_get_info\s!text + \ifdim\floatwidth>\hsize + % dropped ? + \else + \setbox2\vbox + {\blank[\rootfloatparameter\c!spacebefore] + \snaptogrid\vbox{\vskip\floatheight}}% + \advance\dimen0 \ht2 + \ifdim\dimen0>\dimen2 + \ifnum\mofcolumns<\nofcolumns + \advance\mofcolumns \plusone + \ifdim\ht\currenttopcolumnbox=\zeropoint + \page_floats_flush\s!text\plusone + \global\setbox\currenttopcolumnbox\vbox + {\snaptogrid\vbox{\box\floatbox} + \whitespace % nodig ? + \blank[\rootfloatparameter\c!spaceafter]}% + \dimen4=\htdp\currenttopcolumnbox + \global\advance\vsize -\dimen4 + \advance\dimen4 -\pagegoal + \pagegoal-\dimen4 + \showmessage\m!columns{12}a% + \else + \showmessage\m!columns{12}b% + \fi + \else + \showmessage\m!columns{12}c% + \fi \else - \showmessage\m!columns{12}b% + \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen + \par + \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte + \nobreak + \blank[\rootfloatparameter\c!spacebefore] + \nobreak + \fi + \page_floats_flush\s!text\plusone + \page_otr_command_flush_float_box + \blank[\rootfloatparameter\c!spaceafter] \fi - \else - \showmessage\m!columns{12}c% \fi - \else - \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen - \par - \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte - \nobreak - \blank[\rootfloatparameter\c!spacebefore] - \nobreak - \fi - \dofloatsflush\s!text{1}% - \page_otr_command_flush_float_box - \blank[\rootfloatparameter\c!spaceafter] \fi - \fi - \fi - \egroup} + \egroup} %D This one looks complicated. Upto \type{\nofcolumns} floats are placed, %D taking the width of a float into account. This routine can be improved @@ -1308,96 +1317,96 @@ %D When handling lots of (small) floats spacing can get worse because of %D lining out the columns. -\def\doflushcolumnfloats - {\ifpostponecolumnfloats\else - \bgroup - \forgetall - \ifsomefloatwaiting - \dimen8\zeropoint - \dimen4\zeropoint - \count0\zerocount % count0 can be used local - \count2\nofcolumns % count2 can be used local - \dohandleallcolumns - {\ifnum\count0>\zerocount % the wide one's reserved space - \global\setbox\currenttopcolumnbox\vbox - {\snaptogrid\vbox - {\copy\currenttopcolumnbox - \hbox{\vphantom{\vskip\floatheight}}}% known from previous - \whitespace % nodig ? - \blank[\rootfloatparameter\c!spaceafter]}% - \else - \dofloatsgetinfo\s!text - \ifdim\floatwidth>\hsize - \dimen0\dimexpr\floatwidth+\intercolumnwidth+.5pt\relax - \dimen2\dimexpr\hsize +\intercolumnwidth+.5pt\relax - \divide\dimen0 \dimen2 - \count0\dimen0 - \advance\count0 \plusone - \ifnum\count0>\count2 - \count0\zerocount + \def\doflushcolumnfloats + {\ifpostponecolumnfloats\else + \bgroup + \forgetall + \ifconditional\c_page_floats_some_waiting + \dimen8\zeropoint + \dimen4\zeropoint + \count0\zerocount % count0 can be used local + \count2\nofcolumns % count2 can be used local + \dohandleallcolumns + {\ifnum\count0>\zerocount % the wide one's reserved space + \global\setbox\currenttopcolumnbox\vbox + {\snaptogrid\vbox + {\copy\currenttopcolumnbox + \hbox{\vphantom{\vskip\floatheight}}}% known from previous + \whitespace % nodig ? + \blank[\rootfloatparameter\c!spaceafter]}% \else - \dimen0\dimexpr\count0\hsize+\count0\intercolumnwidth-\intercolumnwidth\relax - \dofloatsflush\s!text{1}% - \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too - \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}% - \fi % otherwise the graphic may disappear - \global\setbox\floatbox\hbox to \dimen0 - {\processaction[\rootfloatparameter\c!location] % how easy to forget - [ \v!left=>\box\floatbox\hss, - \v!right=>\hss\box\floatbox, - \s!default=>\hss\box\floatbox\hss, - \s!unknown=>\hss\box\floatbox\hss]}% + \page_floats_get_info\s!text + \ifdim\floatwidth>\hsize + \dimen0\dimexpr\floatwidth+\d_page_mul_distance+.5pt\relax + \dimen2\dimexpr\hsize +\d_page_mul_distance+.5pt\relax + \divide\dimen0 \dimen2 + \count0\dimen0 + \advance\count0 \plusone + \ifnum\count0>\count2 + \count0\zerocount + \else + \dimen0\dimexpr\count0\hsize+\count0\d_page_mul_distance-\d_page_mul_distance\relax + \page_floats_flush\s!text\plusone + \ifdim\floatwidth>\makeupwidth % better somewhere else too + \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}% + \fi % otherwise the graphic may disappear + \global\setbox\floatbox\hbox to \dimen0 + {\processaction[\rootfloatparameter\c!location] % how easy to forget + [ \v!left=>\box\floatbox\hss, + \v!right=>\hss\box\floatbox, + \s!default=>\hss\box\floatbox\hss, + \s!unknown=>\hss\box\floatbox\hss]}% + \fi + \showmessage\m!columns{13}\empty + \else + \page_floats_flush\s!text\plusone + \ifdim\floatwidth>\makeupwidth % better somewhere else too + \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}% + \fi % otherwise the graphic may disappear + % \showmessage\m!columns{13}\empty + \fi + \ifdim\ht\floatbox>\zeropoint\relax + \global\setbox\currenttopcolumnbox\vbox + {\snaptogrid\vbox + {\box\currenttopcolumnbox % was copy + \box\floatbox} + \whitespace % nodig ? + \blank[\rootfloatparameter\c!spaceafter]}% + \fi + \dimen6\htdp\currenttopcolumnbox \fi - \showmessage\m!columns{13}\empty - \else - \dofloatsflush\s!text{1}% - \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too - \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}% - \fi % otherwise the graphic may disappear - % \showmessage\m!columns{13}\empty - \fi - \ifdim\ht\floatbox>\zeropoint\relax - \global\setbox\currenttopcolumnbox\vbox - {\snaptogrid\vbox - {\box\currenttopcolumnbox % was copy - \box\floatbox} - \whitespace % nodig ? - \blank[\rootfloatparameter\c!spaceafter]}% - \fi - \dimen6\htdp\currenttopcolumnbox - \fi - \ifdim\dimen4<\ht\currenttopcolumnbox - \dimen4\ht\currenttopcolumnbox - \fi - \advance\dimen8 \dimen6 - \advance\count2 \minusone - \advance\count0 \minusone }% - \page_otr_command_set_vsize - \global\advance\vsize -\dimen8 - \global\pagegoal\vsize - \else - % \page_mul_command_flush_floats % does not snap! - \fi - \egroup - \fi} + \ifdim\dimen4<\ht\currenttopcolumnbox + \dimen4\ht\currenttopcolumnbox + \fi + \advance\dimen8 \dimen6 + \advance\count2 \minusone + \advance\count0 \minusone }% + \page_otr_command_set_vsize + \global\advance\vsize -\dimen8 + \pagegoal\vsize + \else + % \page_mul_command_flush_floats % does not snap! + \fi + \egroup + \fi} %D The next macro can be used to flush floats in the current stream. No %D width checking is (yet) done. -\def\insertcolumnfloats - {\doloop - {\ifsomefloatwaiting - \bgroup - \forgetall - % no check for width - \dogetfloat - \blank[\rootfloatparameter\c!spacebefore] - \snaptogrid\vbox{\copy\floatbox} - \blank[\rootfloatparameter\c!spaceafter] - \egroup - \else - \exitloop - \fi}} + \def\insertcolumnfloats + {\doloop + {\ifconditional\c_page_floats_some_waiting + \bgroup + \forgetall + % no check for width + \page_floats_get + \blank[\rootfloatparameter\c!spacebefore] + \snaptogrid\vbox{\copy\floatbox} + \blank[\rootfloatparameter\c!spaceafter] + \egroup + \else + \exitloop + \fi}} %D This were the multi||column routines. They can and need to be improved %D but at the moment their behaviour is acceptable. @@ -1417,57 +1426,21 @@ % 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}} % \stopcolumns -\unexpanded\def\setupcolumns - {\dosingleempty\dosetupcolumns} - -\def\dosetupcolumns[#1]% - {\getparameters[\??kl][#1]% - \nofcolumns\@@kln\relax - \processaction - [\@@klrule] - [ \v!on=>\let\betweencolumns\linebetweencolumns, - \v!off=>\let\betweencolumns\spacebetweencolumns, - \s!default=>\let\betweencolumns\spacebetweencolumns, - \s!unknown=>\let\betweencolumns\@@klrule]} - -\def\linebetweencolumns - {\bgroup - \starttextproperties - \ifdim\@@kldistance>\zeropoint - \dimen0=\@@kldistance - \else - \dimen0=\linewidth - \fi - \advance\dimen0 -\linewidth - \hskip.5\dimen0 - \vrule - \!!width\linewidth - \ifnum\bottomraggednessmode=\plustwo % baselinebottom - \!!depth\strutdepth - \fi - \hskip.5\dimen0\relax - \stoptextproperties - \egroup} - -\def\spacebetweencolumns - {\hskip\@@kldistance} - -\presetlocalframed[\??kl] - -\def\backgroundfinishcolumnbox - {\doifinsetelse\@@kloffset{\v!none,\v!overlay} - {\let\@@kloffset\!!zeropoint} - {\scratchdimen\@@kloffset - \advance\scratchdimen -\@@klrulethickness - \edef\@@kloffset{\the\scratchdimen}}% - \localframed - [\??kl] - [\c!strut=\v!no, - \c!width=\v!fit, - \c!height=\v!fit, - \c!align=]} - -\definecomplexorsimpleempty\startcolumns + % \def\backgroundfinishcolumnbox + % {\doifinsetelse\@@kloffset{\v!none,\v!overlay} + % {\let\@@kloffset\!!zeropoint} + % {\scratchdimen\@@kloffset + % \advance\scratchdimen -\@@klrulethickness + % \edef\@@kloffset{\the\scratchdimen}}% + % \localframed + % [\??kl] + % [\c!strut=\v!no, + % \c!width=\v!fit, + % \c!height=\v!fit, + % \c!align=]} + + \def\backgroundfinishcolumnbox + {} % to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30) @@ -1475,133 +1448,196 @@ \unexpanded\def\page_columns_align_option_no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key \unexpanded\def\page_columns_align_option_text{\stretchcolumnsfalse\inheritcolumnstrue }% -\def\complexstartcolumns[#1]% %% \startcolumns +\newtoks\t_page_mul_initialize + +\unexpanded\def\startcolumns + {\dosingleempty\page_mul_start} + +\def\page_mul_start[#1]% %% \startcolumns {\bgroup - \let\stopcolumns\egroup \ifinsidecolumns + \page_mul_start_nop \else - \setupcolumns[#1]% - \ifnum\@@kln>1\relax - \whitespace - \begingroup - \doif\@@kloption\v!background - {\let\finishcolumnbox\backgroundfinishcolumnbox - \let\columntextoffset\@@kloffset}% - \ifx\@@klcommand\empty\else - \let\postprocesscolumnline\@@klcommand - \fi - \doifelsenothing\@@klheight - \heightencolumnsfalse - \heightencolumnstrue - \doifelse\@@kldirection\v!right - \reversecolumnsfalse - \reversecolumnstrue - \doifelse\@@klbalance\v!yes - \balancecolumnstrue - \balancecolumnsfalse - \installalign\v!yes {\page_columns_align_option_yes }% - \installalign\v!no {\page_columns_align_option_no }% - \installalign\v!text{\page_columns_align_option_text}% - \stretchcolumnsfalse - \inheritcolumnstrue - \doifsomething\@@klalign{\expanded{\setupalign[\@@klalign]}}% - \nofcolumns\@@kln - \edef\fixedcolumnheight{\@@klheight}% - \edef\minbalancetoplines{\@@klntop}% - \setuptolerance[\@@kltolerance]% %% \startcolumns - \setupblank[\@@klblank]% - \ifdim\s_spac_whitespace_parskip>\zeropoint\relax - \setupwhitespace[\@@klblank]% - \fi - \unexpanded\def\stopcolumns - {\endmulticolumns - \global\insidecolumnsfalse - \endgroup - \egroup}% - \global\insidecolumnstrue - \beginmulticolumns + \iffirstargument + \setupcolumns[#1]% + \fi + \nofcolumns\columnsparameter\c!n\relax + \ifnum\nofcolumns>\plusone + \page_mul_start_yes + \else + \page_mul_start_nop \fi \fi} -\installcolumnbreakmethod \s!multicolumn \v!preference - {\goodbreak} +\unexpanded\def\page_mul_start_nop + {\let\stopcolumns\page_mul_stop_nop} -\installcolumnbreakmethod \s!multicolumn \v!yes - {\par % todo: since - {\testrulewidth\zeropoint\ruledvskip\textheight} % we misuse a - \penalty-200 % side effect - \vskip-\textheight - }% bugged : \prevdepth-\thousandpoint} % signals top of column to \blank - -%D New: only at start of columns; may change ! Rather interwoven and therefore -%D to be integrated when the multi column modules are merged. - -\unexpanded\def\setupcolumnspan[#1]% - {\getparameters[\??ks][#1]} - -\presetlocalframed - [\??ks] +\unexpanded\def\page_mul_stop_nop + {\egroup} -\setupcolumnspan - [\c!n=2, - \c!offset=\v!overlay, - \c!frame=\v!off] +\unexpanded\def\page_mul_start_yes + {\whitespace + \begingroup + \let\stopcolumns\page_mul_stop_indeed + \global\insidecolumnstrue + \the\t_page_mul_initialize + % + \flushnotes + \begingroup + % + \d_page_mul_leftskip\leftskip + \d_page_mul_rightskip\rightskip + \leftskip\zeropoint + \rightskip\zeropoint + % + \widowpenalty\zerocount % will become option + \clubpenalty \zerocount % will become option + % + \page_floats_column_push_saved + % + \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal + \allowbreak + \else + \break % sometimes fails + \fi + \appendtoks + \topskip1\topskip % best a switch + \to \everybodyfont + \the\everybodyfont % ugly here + \saveinterlinespace % ugly here + % + \initializecolumns\nofcolumns + % + \hangafter\zerocount + \hangindent\zeropoint + \reseteverypar + \ifdim\pagetotal=\zeropoint \else + \verticalstrut + \vskip-\struttotal + \fi + \global\savedpagetotal\pagetotal + \setupoutputroutine[\s!multicolumn]% + \c_page_mul_routine\c_page_mul_routine_intercept + \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear ! + \global\d_page_mul_preceding_height\ht\b_page_mul_preceding + \c_page_mul_routine\c_page_mul_routine_continue + \page_mul_initialize_floats + \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}% + \checkbegincolumnfootnotes + \page_otr_command_set_hsize + \page_otr_command_set_vsize} -\newbox\b_page_columns_span \let\postprocesscolumnspanbox\gobbleoneargument +\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! ! -\def\dostartcolumnspan[#1]% - {\bgroup - \setupcolumnspan[#1]% - \forgetall - \ifinsidecolumns - \advance\hsize \intercolumnwidth - \hsize\@@ksn\hsize - \advance\hsize -\intercolumnwidth +\unexpanded\def\page_mul_stop_indeed + {\relax + \ifnum\multicolumnendsyncmethod=\plustwo + \synchronizeoutput + \else + % don't collapse these + \vskip \lineheight + \vskip-\lineheight % take footnotes into account \fi - \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup - %\topskipcorrection % becomes an option ! - \EveryPar{\begstrut\EveryPar{}}} % also ! - -\def\dofinishcolumnsetspan - {\setbox\b_page_columns_span\flushnextbox - \ifinsidecolumns\wd\b_page_columns_span\hsize\fi - \postprocesscolumnspanbox\b_page_columns_span - \scratchdimen\ht\b_page_columns_span - \setbox\b_page_columns_span\hbox % depth to be checked, probably option! - {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}% - \ht\b_page_columns_span\scratchdimen - \dp\b_page_columns_span\strutdp - \wd\b_page_columns_span\hsize - \ifinsidecolumns - \ifnum\@@ksn>1 - \page_otr_command_set_vsize - \dohandleallcolumns - {\ifnum\currentcolumn>\@@ksn\else - \global\setbox\currenttopcolumnbox=\vbox - {\ifnum\currentcolumn=1 - \snaptogrid\vbox{\copy\b_page_columns_span} - \else - \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}} - \fi}% - \wd\currenttopcolumnbox\hsize - \global\advance\vsize -\ht\currenttopcolumnbox - \fi} - \global\pagegoal\vsize - \else - \snaptogrid\vbox{\box\b_page_columns_span} + \doflushcolumnfloat % added recently + %\doflushcolumnfloats % no, since it results in wrong top floats + \flushnotes % before start of columns + \par + \ifbalancecolumns + \ifnum\multicolumnendsyncmethod=\plusone + \c_page_mul_routine\c_page_mul_routine_continue + \goodbreak \fi + \c_page_mul_routine\c_page_mul_routine_balance \else - \snaptogrid\vbox{\box\b_page_columns_span} + \goodbreak \fi - \endgraf - \ifvmode\prevdepth\strutdp\fi - \egroup} + % still the multi column routine + \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in + \prevdepth\zeropoint % columns before some noncolumned text text + % + \c_page_mul_routine\c_page_mul_routine_regular + % + \ifvoid\b_page_mul_preceding\else + \unvbox\b_page_mul_preceding + \fi + \global\d_page_mul_preceding_height\zeropoint + \endgroup % here + \nofcolumns\plusone + \page_otr_command_set_vsize + \checkendcolumnfootnotes + \dosomebreak\allowbreak + \page_floats_column_pop_saved + % + \global\insidecolumnsfalse + \endgroup + \egroup}% + +\appendtoks + \edef\p_option{\columnsparameter\c!option}% + \ifx\p_option\v!background + \let\finishcolumnbox\backgroundfinishcolumnbox + \fi + \d_page_mul_offset\columnsparameter\c!offset\relax + \edef\p_command{\columnsparameter\c!command}% + \ifx\p_command\empty \else + \let\postprocesscolumnline\p_command + \fi + \edef\p_height{\columnsparameter\c!height}% + \ifx\p_height\empty + \d_page_mul_forced_height\textheight + \heightencolumnsfalse + \else + \d_page_mul_forced_height\p_height\relax + \heightencolumnstrue + \fi + \edef\p_direction{\columnsparameter\c!direction}% + \ifx\p_direction\v!right + \setfalse\c_page_mul_reverse + \else + \settrue\c_page_mul_reverse + \fi + \edef\p_balance{\columnsparameter\c!balance}% + \ifx\p_balance\v!yes + \balancecolumnstrue + \else + \balancecolumnsfalse + \fi + \installalign\v!yes {\page_columns_align_option_yes }% + \installalign\v!no {\page_columns_align_option_no }% + \installalign\v!text{\page_columns_align_option_text}% + \stretchcolumnsfalse + \inheritcolumnstrue + \edef\p_align{\columnsparameter\c!align}% + \ifx\p_align\empty \else + \setupalign[\p_align]% + \fi + \edef\p_tolerance{\columnsparameter\c!tolerance}% + \ifx\p_tolerance\empty \else + \setuptolerance[\p_tolerance]% + \fi + \edef\p_blank{\columnsparameter\c!blank}% + \ifx\p_blank\empty \else + \setupblank[\p_blank]% + \fi + \ifdim\s_spac_whitespace_parskip>\zeropoint\relax + \setupwhitespace[\p_blank]% + \fi + \c_page_mul_balance_minimum\columnsparameter\c!ntop\relax + \edef\p_page_mul_rule{\columnsparameter\c!rule}% + \expandcheckedcsname\??columnseparators\p_page_mul_rule\s!unknown +\to \t_page_mul_initialize + +%D Columns breaks -\unexpanded\def\startcolumnspan - {\dosingleempty\dostartcolumnspan} +\installcolumnbreakmethod \s!multicolumn \v!preference + {\goodbreak} -\unexpanded\def\stopcolumnspan - {\egroup} +\installcolumnbreakmethod \s!multicolumn \v!yes + {\vskip\textheight + \penalty-200 % we can mark and intercept this + \vskip-\textheight} + +%D Next we initialize the lot: \setupcolumns [\c!n=2, @@ -1619,19 +1655,85 @@ \c!rulethickness=\linewidth, \c!offset=.5\bodyfontsize] -%D Undocumented and still under development. +%D New: only at start of columns; may change ! Rather interwoven and therefore +%D to be integrated when the multi column modules are merged. + + \unexpanded\def\setupcolumnspan[#1]% + {\getparameters[\??ks][#1]} + + \presetlocalframed + [\??ks] + + \setupcolumnspan + [\c!n=2, + \c!offset=\v!overlay, + \c!frame=\v!off] + + \newbox\b_page_columns_span \let\page_mul_postprocess_spanbox\gobbleoneargument + + \unexpanded\def\startcolumnspan + {\dosingleempty\dostartcolumnspan} + + \unexpanded\def\stopcolumnspan + {\egroup} + + \def\dostartcolumnspan[#1]% + {\bgroup + \setupcolumnspan[#1]% + \forgetall + \ifinsidecolumns + \advance\hsize \d_page_mul_distance + \hsize\@@ksn\hsize + \advance\hsize -\d_page_mul_distance + \fi + \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup + %\topskipcorrection % becomes an option ! + \EveryPar{\begstrut\EveryPar{}}} % also ! + + \def\dofinishcolumnsetspan + {\setbox\b_page_columns_span\flushnextbox + \ifinsidecolumns\wd\b_page_columns_span\hsize\fi + \page_mul_postprocess_spanbox\b_page_columns_span + \scratchdimen\ht\b_page_columns_span + \setbox\b_page_columns_span\hbox % depth to be checked, probably option! + {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}% + \ht\b_page_columns_span\scratchdimen + \dp\b_page_columns_span\strutdp + \wd\b_page_columns_span\hsize + \ifinsidecolumns + \ifnum\@@ksn>1 + \page_otr_command_set_vsize + \dohandleallcolumns + {\ifnum\currentcolumn>\@@ksn\else + \global\setbox\currenttopcolumnbox=\vbox + {\ifnum\currentcolumn=1 + \snaptogrid\vbox{\copy\b_page_columns_span} + \else + \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}} + \fi}% + \wd\currenttopcolumnbox\hsize + \global\advance\vsize -\ht\currenttopcolumnbox + \fi} + \pagegoal\vsize + \else + \snaptogrid\vbox{\box\b_page_columns_span} + \fi + \else + \snaptogrid\vbox{\box\b_page_columns_span} + \fi + \endgraf + \ifvmode\prevdepth\strutdp\fi + \egroup} + +%D Undocumented and still under development.\ifdefined\startsimplecolumns \else \unexpanded\def\startsimplecolumns - {\dosingleempty\dostartsimplecolumns} + {\dosingleempty\page_mul_simple_start} -\def\dostartsimplecolumns[#1]% +\def\page_mul_simple_start[#1]% {\bgroup + \setsimplecolumnshsize[#1]% \nopenalties - \getparameters[\??kl] - [\c!width=\hsize,\c!distance=1.5\bodyfontsize,% - \c!n=2,\c!lines=0,#1]% - \let\rigidcolumnlines\@@kllines - \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln \setbox\scratchbox\vbox\bgroup \forgetall} % \blank[\v!disable] @@ -1642,35 +1744,44 @@ \egroup} \unexpanded\def\setsimplecolumnshsize[#1]% - {\getparameters[\??kl][\c!width=\hsize,\c!distance=1.5\bodyfontsize,\c!n=2,\c!lines=0,#1]% - \let\rigidcolumnlines\@@kllines - \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln} + {\getdummyparameters + [\c!width=\hsize, + \c!distance=1.5\bodyfontsize, + \c!n=2, + \c!lines=0, + #1]% + \edef\rigidcolumnlines + {\directdummyparameter\c!lines}% + \setrigidcolumnhsize + {\directdummyparameter\c!width}% + {\directdummyparameter\c!distance}% + {\directdummyparameter\c!n}} \let\page_mul_command_package_contents\page_one_command_package_contents \let\page_mul_command_flush_float_box \page_one_command_flush_float_box \defineoutputroutine [\s!multicolumn] - [\s!page_otr_command_routine =\page_mul_command_routine, - \s!page_otr_command_package_contents =\page_mul_command_package_contents, - \s!page_otr_command_set_vsize =\page_mul_command_set_vsize, - \s!page_otr_command_set_hsize =\page_mul_command_set_hsize, - \s!page_otr_command_next_page =\page_mul_command_next_page, - \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts, - % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize, - % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions, - % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions, - \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions, - % \s!page_otr_command_flush_bottom_insertions =\page_mul_command_flush_bottom_insertions, - % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize, - \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits, - \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box, - \s!page_otr_command_synchronize_side_floats =\page_mul_command_synchronize_side_floats, - \s!page_otr_command_side_float_output =\page_mul_command_side_float_output, - \s!page_otr_command_flush_floats =\page_mul_command_flush_floats, - \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats, - \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats - % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used + [\s!page_otr_command_routine =\page_mul_command_routine, + \s!page_otr_command_package_contents =\page_mul_command_package_contents, + \s!page_otr_command_set_vsize =\page_mul_command_set_vsize, + \s!page_otr_command_set_hsize =\page_mul_command_set_hsize, + \s!page_otr_command_next_page =\page_mul_command_next_page, + \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts, + % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize, + % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions, + % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions, + \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions, + % \s!page_otr_command_flush_bottom_insertions=\page_mul_command_flush_bottom_insertions, + % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize, + \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits, + \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box, + \s!page_otr_command_synchronize_side_floats=\page_mul_command_synchronize_side_floats, + \s!page_otr_command_side_float_output =\page_mul_command_side_float_output, + \s!page_otr_command_flush_floats =\page_mul_command_flush_floats, + \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats, + \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats + % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used ] \protect \endinput diff --git a/tex/context/base/page-not.mkiv b/tex/context/base/page-not.mkiv index 06e2f3875..d7602bd26 100644 --- a/tex/context/base/page-not.mkiv +++ b/tex/context/base/page-not.mkiv @@ -13,12 +13,12 @@ \writestatus{loading}{ConTeXt Page Macros / Footnotes} -%D Terrible hacks: we need to share save/restore +%D This is an old mechanism that will be replaced as soon as the multicolumn +%D code is redone. -%D We've moved some footnote handling to a separate page -%D module. The macros below are used in the single and multi -%D column page handlers and permit mixed usage of column and -%D page notes. +%D We've moved some footnote handling to a separate page module. The macros below +%D are used in the single and multi column page handlers and permit mixed usage of +%D column and page notes. \unprotect @@ -41,11 +41,13 @@ \newdimen\totalinsertionheight -\def\settotalinsertionheight +\unexpanded\def\settotalinsertionheight {\calculatetotalnoteheight - \totalinsertionheight\totalnoteheight - \addinsertionheight\topins\to\totalinsertionheight - \addinsertionheight\botins\to\totalinsertionheight} + \totalinsertionheight\dimexpr + \totalnoteheight + +\page_insert_insertion_height\s!topfloat + +\page_insert_insertion_height\s!bottomfloat + \relax} % hm diff --git a/tex/context/base/page-one.mkiv b/tex/context/base/page-one.mkiv index 89fd7d4a8..6261938b6 100644 --- a/tex/context/base/page-one.mkiv +++ b/tex/context/base/page-one.mkiv @@ -20,7 +20,7 @@ % OTRONE: basic single column -\newdimen\d_page_one_saved_vsize +\newconstant \c_page_one_float_method \unexpanded\def\page_one_command_next_page {\page_otr_eject_page} @@ -34,6 +34,34 @@ \unexpanded\def\page_one_command_set_float_hsize {\global\hsize\textwidth} +% \newdimen\d_page_one_saved_vsize +% +% \unexpanded\def\page_one_command_set_vsize +% {\ifgridsnapping +% \ifcase\layoutlines +% \getrawnoflines\textheight +% \else +% \noflines\layoutlines +% \fi +% \global\vsize\noflines\openlineheight +% \else +% \global\vsize\textheight +% \fi +% \ifdim\pagegoal<\maxdimen +% \ifdim\d_page_one_saved_vsize=\vsize +% % let's assume that the layout didn't change +% \else +% \global\d_page_one_saved_vsize\vsize +% \pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax +% % \bgroup +% % \global\d_page_one_saved_vsize\vsize +% % \advance\vsize-\d_page_floats_inserted_top +% % \advance\vsize-\d_page_floats_inserted_bottom +% % \pagegoal\vsize +% % \egroup +% \fi +% \fi} + \unexpanded\def\page_one_command_set_vsize {\ifgridsnapping \ifcase\layoutlines @@ -45,20 +73,10 @@ \else \global\vsize\textheight \fi - \ifdim\pagegoal<\maxdimen - \ifdim\d_page_one_saved_vsize=\vsize - % let's assume that the layout didn't change - \else - \global\d_page_one_saved_vsize\vsize - \global\pagegoal\dimexpr\vsize-\topinserted-\botinserted\relax -% \bgroup -% \global\d_page_one_saved_vsize\vsize -% \advance\vsize-\topinserted -% \advance\vsize-\botinserted -% \global\pagegoal\vsize -% \egroup - \fi - \fi} + % alternatively we could set it in builders.buildpage_filter + % \ifdim\pagegoal<\maxdimen .. \fi + \global\pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax} + % 1 = partial page, 2 = whole page, 3 = partial page @@ -186,31 +204,32 @@ \newskip \s_page_one_between_top_insert \def\page_one_prepare_top_float - {\ifdim\topinserted=\zeropoint + {\ifdim\d_page_floats_inserted_top=\zeropoint \settrue\c_page_one_top_of_insert \else \setfalse\c_page_one_top_of_insert \fi - \s_page_one_between_top_insert\ifdim\floattopskip>\floatbottomskip\floattopskip\else\floatbottomskip\fi\relax - \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax} + \s_page_one_between_top_insert\ifdim\d_strc_floats_top>\d_strc_floats_bottom\d_strc_floats_top\else\d_strc_floats_bottom\fi\relax + \global\advance\d_page_floats_inserted_top\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax} \def\page_one_insert_top_float % maybe remember last beforeskip - {\insert\topins - {\forgetall - \ifconditional\c_page_one_top_of_insert - \ifconditional\c_page_one_correct_top_insert - \topskipcorrection % [xx] new: see icare topbleed - \kern-\lineskip - \par - \prevdepth\maxdimen - \fi - \fi - \page_otr_command_flush_float_box - \vskip\s_page_one_between_top_insert}} + {\insert\namedinsertionnumber\s!topfloat\bgroup + \forgetall + \ifconditional\c_page_one_top_of_insert + \ifconditional\c_page_one_correct_top_insert + \topskipcorrection % [xx] new: see icare topbleed + \kern-\lineskip + \par + \prevdepth\maxdimen + \fi + \fi + \page_otr_command_flush_float_box + \vskip\s_page_one_between_top_insert + \egroup} \unexpanded\def\page_one_command_set_top_insertions {\bgroup - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \let\totaltopinserted\!!zeropoint \page_one_command_set_top_insertions_indeed @@ -228,25 +247,25 @@ \egroup} \def\page_one_command_set_top_insertions_indeed - {\ifnum\noffloatinserts<\noftopfloats - \dogetfloat + {\ifnum\noffloatinserts<\c_page_floats_n_of_top + \page_floats_get \page_one_prepare_top_float - \ifdim\topinserted<\textheight\relax - \xdef\totaltopinserted{\the\topinserted}% + \ifdim\d_page_floats_inserted_top<\textheight\relax + \xdef\totaltopinserted{\the\d_page_floats_inserted_top}% \page_one_insert_top_float - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \advance\noffloatinserts \plusone \else - \noffloatinserts\noftopfloats\relax + \noffloatinserts\c_page_floats_n_of_top\relax \fi - \dofloatflushedinfo + \page_floats_report_flushed \else - \doresavefloat - \noffloatinserts\noftopfloats\relax + \page_floats_resave\s!text + \noffloatinserts\c_page_floats_n_of_top\relax \fi \else - \ifsomefloatwaiting - \showmessage\m!floatblocks6{\the\noftopfloats}% + \ifconditional\c_page_floats_some_waiting + \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}% \fi \let\page_one_command_set_top_insertions_indeed\relax \fi @@ -254,101 +273,98 @@ \unexpanded\def\page_one_command_set_bottom_insertions {\bgroup - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \page_one_command_set_bottom_insertions_indeed \fi \egroup} \def\page_one_command_set_bottom_insertions_indeed - {\ifnum\noffloatinserts<\nofbotfloats\relax - \dogetfloat - \global\advance\botinserted \ht\floatbox\relax - \global\advance\botinserted \dp\floatbox\relax - \global\advance\botinserted \floattopskip\relax - \ifdim\botinserted<\pagegoal\relax - \insert\botins - {\forgetall - \blank[\rootfloatparameter\c!spacebefore]% - \page_otr_command_flush_float_box}% - \ifsomefloatwaiting + {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax + \page_floats_get + \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax + \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax + \insert\namedinsertionnumber\s!bottomfloat\bgroup + \forgetall + \blank[\rootfloatparameter\c!spacebefore]% + \page_otr_command_flush_float_box + \egroup + \ifconditional\c_page_floats_some_waiting \advance\noffloatinserts \plusone \else - \noffloatinserts\nofbotfloats + \noffloatinserts\c_page_floats_n_of_bottom \fi - \dofloatflushedinfo + \page_floats_report_flushed \else - \doresavefloat - \noffloatinserts\nofbotfloats\relax + \page_floats_resave\s!text + \noffloatinserts\c_page_floats_n_of_bottom\relax \fi - \global\nofloatpermittedtrue % vgl topfloats s! + \global\settrue\c_page_floats_not_permitted % vgl topfloats s! \else - \ifsomefloatwaiting - \showmessage\m!floatblocks7{\the\nofbotfloats}% + \ifconditional\c_page_floats_some_waiting + \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}% \fi \let\page_one_command_set_bottom_insertions_indeed\relax \fi \page_one_command_set_bottom_insertions_indeed} -\newconstant\topinserttopskipmode % 1 = no topskip - \unexpanded\def\page_one_command_flush_top_insertions - {\ifvoid\topins\else + {\ifvoid\namedinsertionnumber\s!topfloat\else \ifgridsnapping - \box\topins + \box\namedinsertionnumber\s!topfloat \vskip-\topskip \vskip\strutheight % [xx] new: see icare topbleed \else - \ifcase\topinserttopskipmode + \ifcase\c_page_floats_insertions_topskip_mode % 0: default, do nothing \or % 1: no topskip (crossed fingers) \vskip-\topskip \vskip\strutheight \fi - \unvbox\topins + \unvbox\namedinsertionnumber\s!topfloat \fi \fi - \global\topinserted\zeropoint} + \global\d_page_floats_inserted_top\zeropoint} \unexpanded\def\page_one_command_flush_bottom_insertions - {\ifvoid\botins\else + {\ifvoid\namedinsertionnumber\s!bottomfloat\else \ifgridsnapping % \floatparameter\c!bottombefore - \snaptogrid\hbox{\box\botins}% + \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% % \floatparameter\c!bottomafter \else \floatparameter\c!bottombefore - \unvbox\botins + \unvbox\namedinsertionnumber\s!bottomfloat \floatparameter\c!bottomafter \fi \fi - \global\botinserted\zeropoint - \global\nofloatpermittedfalse} + \global\d_page_floats_inserted_bottom\zeropoint + \global\setfalse\c_page_floats_not_permitted} \unexpanded\def\page_one_command_flush_floats - {\global\flushingfloatstrue - \ifsomefloatwaiting + {\global\settrue\c_page_floats_flushing + \ifconditional\c_page_floats_some_waiting \par % if kept, then option and definitely off in gridmode ! ! ! ! % \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests \page_one_command_flush_floats_indeed \fi \global\savednoffloats\zerocount - \global\somefloatwaitingfalse - \global\flushingfloatsfalse} + \global\setfalse\c_page_floats_some_waiting + \global\setfalse\c_page_floats_flushing} \unexpanded\def\page_one_command_flush_float_box - {\ifcenterfloatbox \ifdim\wd\floatbox<\hsize + {\ifconditional\c_page_floats_center_box \ifdim\wd\floatbox<\hsize \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}% \fi \fi - \snaptogrid\hbox{\iftestfloatbox\ruledhbox\fi{\box\floatbox}}} % was copy + \snaptogrid\hbox{\box\floatbox}} % was copy \def\page_one_command_flush_floats_indeed % much in common with OTRSET - {\ifsomefloatwaiting - \ifpackflushedfloats - \centerfloatboxfalse % not needed as we do call directly - \dofloatscollect\s!text{\hsize}{1em}% + {\ifconditional\c_page_floats_some_waiting + \ifconditional\c_page_floats_pack_flushed + \setfalse\c_page_floats_center_box % not needed as we do call directly + \page_floats_collect\s!text\hsize\emwidth %% no longer (interferes with footnotes): %% %% \page_one_command_set_vsize % test 2011.06.24.001 @@ -357,9 +373,9 @@ {\hfil \dorecurse\nofcollectedfloats {\ifcase\columndirection % nog document wide - \dofloatsflush\s!text{1}% + \page_floats_flush\s!text\plusone \else - \dofloatsflush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}% + \page_floats_flush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}% \fi \ifdim\wd\floatbox>\makeupwidth % \hsize \hbox to \makeupwidth{\hss\box\floatbox\hss}% @@ -371,7 +387,7 @@ \fi}% \hfil}% \else - \dogetfloat + \page_floats_get \fi % there is a chance that due to rounding errors, the float % fits on a page where it was first rejected, in which case @@ -394,8 +410,8 @@ \fi} \unexpanded\def\page_one_command_check_if_float_fits - {\ifnofloatpermitted - \global\roomforfloatfalse + {\ifconditional\c_page_floats_not_permitted + \global\setfalse\c_page_floats_room \else % new per 31/5/2004, should be an option, only one column mode \begingroup @@ -405,10 +421,10 @@ \fi % should be an option \endgroup - \dimen0\dimexpr\pagetotal+\floatheight+\floattopskip-\pageshrink\relax + \dimen0\dimexpr\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink\relax \dimen2\pagegoal \relax % needed - \ifcase\textfloatmethod + \ifcase\c_page_one_float_method % method 0 : raw \or % method 1 : safe @@ -419,19 +435,19 @@ \fi \relax % really needed ! ! ! ! \ifdim\dimen0>\dimen2 - \global\roomforfloatfalse + \global\setfalse\c_page_floats_room \else - \global\roomforfloattrue + \global\settrue\c_page_floats_room \fi \fi} \unexpanded\def\page_one_command_flush_saved_floats - {\global\topinserted\zeropoint - \global\botinserted\zeropoint - \ifflushingfloats \else + {\global\d_page_floats_inserted_top\zeropoint + \global\d_page_floats_inserted_bottom\zeropoint + \ifconditional\c_page_floats_flushing \else \page_one_command_set_top_insertions \page_one_command_set_bottom_insertions - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \doif{\rootfloatparameter\c!cache}\v!no\page_one_command_flush_floats % could be _otr_ \else\ifconditional\c_page_margin_blocks_present \page_one_command_flush_floats @@ -443,7 +459,7 @@ \baselinecorrection %\fi \doplacefloatbox - \doinsertfloatinfo + \page_floats_report_total \dohandlenextfloatindent} \def\page_one_place_float_force @@ -469,10 +485,10 @@ %def\page_one_place_float_margin {\page_one_place_float_side_indeed\page_sides_process_float_margin\nonoindentation} % wil be overloaded \def\page_one_place_float_margin {\page_margin_blocks_process_float} -\def\page_one_place_float_page {\dofloatssavepagefloat \s!page \floatlocationmethod} -\def\page_one_place_float_leftpage {\dofloatssavepagefloat \s!leftpage \floatlocationmethod} -\def\page_one_place_float_rightpage {\dofloatssavepagefloat \s!rightpage\floatlocationmethod} -\def\page_one_place_float_somewhere {\dofloatssavesomewherefloat\s!somewhere\floatlocationmethod} +\def\page_one_place_float_page {\page_floats_save_page_float \s!page \floatlocationmethod} +\def\page_one_place_float_leftpage {\page_floats_save_page_float \s!leftpage \floatlocationmethod} +\def\page_one_place_float_rightpage {\page_floats_save_page_float \s!rightpage\floatlocationmethod} +\def\page_one_place_float_somewhere {\page_floats_save_somewhere_float\s!somewhere\floatlocationmethod} \def\page_one_place_float_here {\page_one_place_float_otherwise_here} \def\page_one_place_float_auto {\page_one_place_float_otherwise} @@ -488,38 +504,41 @@ {\doifinsetelse\v!always\floatlocationmethod {\page[\v!preference]% \page_otr_command_check_if_float_fits - \ifroomforfloat + \ifconditional\c_page_floats_room \page_one_place_float_here_indeed \else \showmessage\m!floatblocks9\empty - \doreversesavefloat + \page_floats_resave\s!text \fi} - {\ifsomefloatwaiting - \dosavefloat + {\ifconditional\c_page_floats_some_waiting + \page_floats_save\s!text + \nonoindentation \else \page[\v!preference]% \page_otr_command_check_if_float_fits - \ifroomforfloat + \ifconditional\c_page_floats_room \page_one_place_float_here_indeed \else - \dosavefloat + \page_floats_save\s!text + \nonoindentation \fi \fi}} \def\page_one_place_float_otherwise_else {\doifinsetelse\v!always\floatlocationmethod {\page_otr_command_check_if_float_fits - \ifroomforfloat + \ifconditional\c_page_floats_room \page_one_place_float_auto_top_bottom \else \showmessage\m!floatblocks9\empty - \doreversesavefloat + \page_floats_resave\s!text \fi} {\page_otr_command_check_if_float_fits - \ifroomforfloat + \ifconditional\c_page_floats_room \page_one_place_float_auto_top_bottom \else - \dosavefloat + \page_floats_save\s!text + \nonoindentation \fi}} \def\floatautofactor{.5} @@ -544,23 +563,23 @@ \def\page_one_place_float_top_indeed % maybe remember last beforeskip {\page_one_prepare_top_float \page_one_insert_top_float - \doinsertfloatinfo} + \page_floats_report_total} \def\page_one_place_float_bottom_indeed - {\global\advance\botinserted\dimexpr\ht\floatbox+\dp\floatbox+\floattopskip\relax - \insert\botins - {\forgetall - \blank[\rootfloatparameter\c!spacebefore]% - \page_otr_command_flush_float_box}% - %\global\nofloatpermittedtrue - \doinsertfloatinfo} + {\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax + \insert\namedinsertionnumber\s!bottomfloat\bgroup + \forgetall + \blank[\rootfloatparameter\c!spacebefore]% + \page_otr_command_flush_float_box + \egroup + \page_floats_report_total} \def\page_one_place_float_face % links, rechts, midden, hoog, midden, laag {%\checkwaitingfloats{#1}% \startopposite \page_otr_command_flush_float_box \stopopposite - }%\doinsertfloatinfo} + }%\page_floats_report_total} \unexpanded\def\page_one_command_flush_side_floats {\page_sides_flush_floats} diff --git a/tex/context/base/page-otr.mkvi b/tex/context/base/page-otr.mkvi index 19c308c32..e5433c866 100644 --- a/tex/context/base/page-otr.mkvi +++ b/tex/context/base/page-otr.mkvi @@ -258,8 +258,8 @@ \definesystemconstant{page_otr_command_flush_margin_blocks} \definesystemconstant{singlecolumn} -\definesystemconstant{multicolumn} -\definesystemconstant{columnset} +\definesystemconstant{multicolumn} % will move +\definesystemconstant{columnset} % will move \defineoutputroutinecommand [\s!page_otr_command_routine, diff --git a/tex/context/base/page-par.mkiv b/tex/context/base/page-par.mkiv index 26e306ef5..588065d65 100644 --- a/tex/context/base/page-par.mkiv +++ b/tex/context/base/page-par.mkiv @@ -15,49 +15,59 @@ \unprotect -\newcount\internalparagraphnumber - -\unexpanded\def\setupparagraphnumbering - {\dosingleempty\dosetupparagraphnumbering} - -\def\dosetupparagraphnumbering[#1]% - {\getparameters - [\??ph][#1]% - \processaction - [\@@phstate] - [\v!start=>\let\showparagraphnumber\doshowparagraphnumberA, - \v!stop=>\let\showparagraphnumber\relax, - \v!line=>\let\showparagraphnumber\doshowparagraphnumberB, - \v!reset=>\global\internalparagraphnumber\zerocount - \let\showparagraphnumber\doshowparagraphnumberA]} - -\def\dodoshowparagraphnumber - {\global\advance\internalparagraphnumber \plusone - \inleftmargin % \tf normalizes em - {\tf - \dousestyleparameter\@phstyle - \dousecolorparameter\@phcolor - \the\internalparagraphnumber - \kern\@@phdistance}} - -\def\doshowparagraphnumberA - {%\ifprocessingverbatim - % \iflinepar - % % obsolete: \dodoshowparagraphnumber - % \fi - %\else - \dodoshowparagraphnumber - }%\fi} - -\def\doshowparagraphnumberB +\installcorenamespace {paragraphnumbering} +\installcorenamespace {paragraphnumberingvariants} + +\installsimplecommandhandler \??paragraphnumbering {paragraphnumbering} \??paragraphnumbering + +\definecounter[\v!paragraph] + +\let\showparagraphnumber\relax + +\appendtoks + \page_par_check_state +\to \everysetupparagraphnumbering + +\unexpanded\def\page_par_check_state + {\rawprocesscommacommand[\paragraphnumberingparameter\c!state]\page_par_check_state_step} + +\def\page_par_check_state_step#1% + {\ifcsname\??paragraphnumberingvariants#1\endcsname + \csname\??paragraphnumberingvariants#1\endcsname + \fi} + +\setvalue{\??paragraphnumberingvariants\v!start}% + {\let\showparagraphnumber\page_par_show_number_normal} + +\setvalue{\??paragraphnumberingvariants\v!stop}% + {\let\showparagraphnumber\relax} + +\setvalue{\??paragraphnumberingvariants\v!line}% + {\let\showparagraphnumber\page_par_show_number_lines} + +\setvalue{\??paragraphnumberingvariants\v!reset}% + {\strc_counters_reset\v!paragraph + \let\showparagraphnumber\page_par_show_number_normal} + +\unexpanded\def\page_par_show_number_normal + {\strc_counters_increment\v!paragraph + \inleftmargin % todo: \c!location, only a few make sense + {\hfill % no complaints + \tf % \tf normalizes em + \useparagraphnumberingstyleandcolor\c!style\c!color + \convertedcounter[\v!paragraph]% + \kern\paragraphnumberingparameter\c!distance}} + +\unexpanded\def\page_par_show_number_lines {\ifnumberinglines - \doshowparagraphnumberA + \page_par_show_number_normal \fi} \setupparagraphnumbering [\c!state=\v!stop, - \c!style=, - \c!color=, - \c!distance=\ifcase\linenumberlocation2em\else\!!zeropoint\fi] % will change + %\c!location, + %\c!style=, + %\c!color=, + \c!distance=\ifcase\c_page_lines_location2\emwidth\else\zeropoint\fi] % will change \protect \endinput diff --git a/tex/context/base/page-plg.mkiv b/tex/context/base/page-plg.mkiv index 004b9204d..b59a05a94 100644 --- a/tex/context/base/page-plg.mkiv +++ b/tex/context/base/page-plg.mkiv @@ -11,10 +11,11 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% \ifx\pageareabox\undefined \else \endinput \fi - \writestatus{loading}{ConTeXt Page Macros / Extra Page Building} +%D This still needs some work, especially the dimensions need to be +%D checked cq.\ optimized. Beware: method has become alternative! + %D This feature has been present for a while but has never been %D exploited: pluggable pagebuilders. The next example code %D demonstrates the application of one such a plug-in. This variant @@ -31,6 +32,8 @@ %D \startpagelayout[leftpage] %D \setupTABLE[offset=overlay] %D \setupTABLE[c][1][width=\leftmarginwidth] +%D \setupTABLE[c][2][width=\textwidth] +%D \setupTABLE[c][3][width=\rightmarginwidth] %D \bTABLE %D \bTR %D \bTD[nx=3,background=color,backgroundcolor=green] @@ -43,7 +46,7 @@ %D \eTR %D \bTR %D \bTD[nx=3,offset=overlay] -%D {\bTABLE[width=.5\hsize] +%D {\bTABLE %D \bTR %D \bTD \pagearea[footer][text][left] \eTD %D \bTD \pagearea[bottom][text][left] \eTD @@ -56,7 +59,9 @@ %D %D \startpagelayout[rightpage] %D \setupTABLE[offset=overlay] -%D \setupTABLE[c][1][width=\rightmarginwidth] +%D \setupTABLE[c][1][width=\leftmarginwidth] +%D \setupTABLE[c][2][width=\textwidth] +%D \setupTABLE[c][3][width=\rightmarginwidth] %D \bTABLE %D \bTR %D \bTD[nx=3] \pagearea[header][text][middle] \eTD @@ -67,7 +72,7 @@ %D \eTR %D \bTR %D \bTD[nx=3,offset=overlay] -%D {\bTABLE[width=.5\hsize] +%D {\bTABLE %D \bTR %D \bTD \pagearea[bottom][text][right] \eTD %D \bTD \pagearea[footer][text][right] \eTD @@ -80,12 +85,9 @@ %D %D \setupcolors[state=start] %D -%D \setupbackgrounds[text][background=color,backgroundcolor=blue] -%D \setupbackgrounds[header][text][background=color,backgroundcolor=red] -%D %D \setuppagenumbering[alternative=doublesided,location=] %D -%D \setuplayout[method=makeup] +%D \setuplayout[alternative=makeup] %D %D \definetextbackground %D [test] @@ -110,6 +112,8 @@ \unprotect +\installcorenamespace{layoutmakeupalternative} + \def\page_boxes_construct_content_makeup#1#2#3% targetbox flusher box {\setbox#1\hbox {\vbox to \textheight @@ -125,65 +129,77 @@ \dp#1\zeropoint \hsize\paperwidth \vsize\paperheight - \setbox#1\vbox{\csname\??layoutmethod\doifbothsidesoverruled\v!page\v!rightpage\v!leftpage\endcsname}% + \setbox#1\vbox{\csname\??layoutmakeupalternative\doifbothsidesoverruled\v!page\v!rightpage\v!leftpage\endcsname}% \wd#1\paperwidth \ht#1\paperheight \dp#1\zeropoint} \installlayoutalternative\v!makeup{\page_boxes_construct_content_makeup} -\newbox\pageareabox +\newbox\b_page_area \unexpanded\def\pagearea {\dotripleempty\page_area} -\def\page_area[#1][#2][#3]% +\def\page_area {\ifthirdargument - \doifelse{#3}\v!left - {\page_area_indeed{#1}{#2}\c!lefttext} - {\doifelse{#3}\v!right - {\page_area_indeed{#1}{#2}\c!righttext} - {\page_area_indeed{#1}{#2}\c!middletext}}% + \expandafter\page_area_three \else\ifsecondargument - \doifbothsidesoverruled - {\page_area_indeed{#1}{#2}\c!righttext} - {\page_area_indeed{#1}{#2}\c!righttext} - {\page_area_indeed{#1}{#2}\c!lefttext }% + \doubleexpandafter\page_area_two \else - \doif{#1}\v!text % copy due to trial runs in TABLE - {\iftrialtypesetting -% \copy\pagebox - \fakebox\pagebox - \else -% \localpositioningfalse - \page_backgrounds_add_to_text\pagebox - \page_grids_add_to_box\pagebox - \box\pagebox - \fi}% + \doubleexpandafter\page_area_one \fi\fi} -\def\page_area_indeed#1#2#3% - {\setbox\pageareabox\vbox{\getspecificlayouttext{#1}{#2}{#3}}% - \ifsomebackgroundfound{#1#2}% +\def\page_area_three[#1][#2][#3]% + {\edef\m_page_area_three{#3}% + \ifx\m_page_area_three\v!left + \let\m_page_area_three\c!lefttext + \else\ifx\m_page_area_three\v!right + \let\m_page_area_three\c!righttext + \else + \let\m_page_area_three\c!middletext + \fi\fi + \page_area_indeed{#1}{#2}\m_page_area_three} + +\def\page_area_two[#1][#2][#3]% + {\edef\m_page_area_three{\doifbothsidesoverruled\c!righttext\c!righttext\c!lefttext}% + \page_area_indeed{#1}{#2}\m_page_area_three} + +\def\page_area_one[#1][#2][#3]% + {\edef\m_page_area_one{#1} + \ifx\m_page_area_one\v!text % copy due to trial runs in TABLE \iftrialtypesetting -% \box\pageareabox - \fakebox\pageareabox + \fakebox\pagebox \else - \localframed - [\??ma#1#2] - [\c!width=\wd\pageareabox, - \c!height=\ht\pageareabox, - \c!offset=\v!overlay] - {\box\pageareabox}% + \page_backgrounds_add_to_text\pagebox + \page_grids_add_to_box\pagebox + \box\pagebox \fi - \else - \box\pageareabox \fi} +\def\page_area_indeed#1#2#3% + {\setbox\b_page_area\vbox{\getspecificlayouttext{#1}{#2}{#3}}% + \iftrialtypesetting + \fakebox\b_page_area + \else\ifcsname\??layoutbackgrounds#1#2\endcsname + \page_area_indeed_yes{#1}{#2}% + \else + \box\b_page_area + \fi\fi} + +\def\page_area_indeed_yes#1#2% + {% todo: \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2} + \localframed % todo: + [\??layoutbackgrounds#1#2] + [\c!width=\wd\b_page_area, + \c!height=\ht\b_page_area, + \c!offset=\v!overlay] + {\box\b_page_area}} + % to be done nicely (proper namespacing) -\setvalue{\??layoutmethod\v!leftpage }{\csname\??layoutmethod\v!page\endcsname} -\setvalue{\??layoutmethod\v!rightpage}{\csname\??layoutmethod\v!page\endcsname} +\setvalue{\??layoutmakeupalternative\v!leftpage }{\csname\??layoutmakeupalternative\v!page\endcsname} +\setvalue{\??layoutmakeupalternative\v!rightpage}{\csname\??layoutmakeupalternative\v!page\endcsname} \unexpanded\def\startpagelayout {\bgroup @@ -194,6 +210,6 @@ \def\page_layouts_start_layout[#1]#2\stoppagelayout {\egroup - \setvalue{\??layoutmethod#1}{#2}} + \setvalue{\??layoutmakeupalternative#1}{#2}} \protect \endinput diff --git a/tex/context/base/page-mis.lua b/tex/context/base/page-pst.lua index 4f9d3c3e2..8586830cf 100644 --- a/tex/context/base/page-mis.lua +++ b/tex/context/base/page-pst.lua @@ -1,6 +1,6 @@ -if not modules then modules = { } end modules ['page-mis'] = { +if not modules then modules = { } end modules ['page-pst'] = { version = 1.001, - comment = "companion to page-mis.mkiv", + comment = "companion to page-pst.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" @@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['page-mis'] = { -- todo: adapt message +local format, validstring = string.format, string.valid local sortedkeys = table.sortedkeys local cache = { } @@ -16,7 +17,7 @@ local function flush(page) local c = cache[page] if c then for i=1,#c do - context.viafile(c[i]) + context.viafile(c[i],format("page.%s",validstring(page,"nopage"))) end cache[page] = nil end diff --git a/tex/context/base/page-mis.mkiv b/tex/context/base/page-pst.mkiv index 6137bb462..7f8a39ca6 100644 --- a/tex/context/base/page-mis.mkiv +++ b/tex/context/base/page-pst.mkiv @@ -2,7 +2,7 @@ %D [ file=page-mis, %D version=2008.11.17, % was part of page-flt.tex / 2000.10.20 %D title=\CONTEXT\ Page Macros, -%D subtitle=Misc Float Things, +%D subtitle=Postponing, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -11,9 +11,9 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\writestatus{loading}{ConTeXt Page Macros / Misc Float Things} +\writestatus{loading}{ConTeXt Page Macros / Postponing} -\registerctxluafile{page-mis}{1.001} +\registerctxluafile{page-pst}{1.001} \unprotect @@ -21,8 +21,13 @@ \newevery\everytopofpage\relax -\appendtoks \the\everytopofpage \to\everystarttext -\appendtoks\global\everytopofpage\emptytoks\to\everystoptext +\appendtoks + \the\everytopofpage +\to \everystarttext + +\appendtoks + \global\everytopofpage\emptytoks +\to \everystoptext % \startpostponing [pagenumber] [+pageoffset] % @@ -44,8 +49,10 @@ %D is somewhat easier and we also can erase buffers easier when %D we keep a local cache, especially as we can flush per page. -\newif \ifinpostponing % prevents nesting -\newcount\c_page_postponed_blocks_next_page % set at the lua end +%newif \ifinpostponing % prevents nesting + +\newcount \c_page_postponed_blocks_next_page % set at the lua end +\newconditional\c_page_postponed_busy \unexpanded\setvalue{\e!start\v!postponing}% {\bgroup @@ -65,11 +72,11 @@ \unexpanded\def\page_postponed_blocks_flush_indeed {\begingroup \setsystemmode\v!postponing - \inpostponingtrue % for old times sake - \global\pagetotal\zeropoint % here? still needed? (was after flush pagefloats) + \settrue\c_page_postponed_busy + \pagetotal\zeropoint % here? still needed? (was after flush pagefloats) \the\everytopofpage\relax %\flushrestfloats - \doflushpagefloats + \page_floats_flush_page_floats \setnormalcatcodes % postponing in verbatim \restoreglobalbodyfont % otherwise problems inside split verbatim \ctxcommand{flushpostponedblocks()}% @@ -77,8 +84,8 @@ \page_otr_command_flush_floats % new but potential dangerous, maybe we need a classification \endgroup} % of blocks: with and without flush -\def\page_postponed_blocks_flush - {\ifinpostponing +\unexpanded\def\page_postponed_blocks_flush + {\ifconditional\c_page_postponed_busy % probably a nested flush \else\ifnum\c_page_postponed_blocks_next_page=\zerocount % nothing in cache diff --git a/tex/context/base/page-run.mkiv b/tex/context/base/page-run.mkiv index 62b1030ee..dabf37252 100644 --- a/tex/context/base/page-run.mkiv +++ b/tex/context/base/page-run.mkiv @@ -242,16 +242,16 @@ end [\v!page] [\c!frame=\v!on, \c!corner=\v!rectangular, - \c!frameoffset=\!!zeropoint, - \c!framedepth=\!!zeropoint, + \c!frameoffset=\zeropoint, + \c!framedepth=\zeropoint, \c!framecolor=layout:page] \setupbackgrounds [#1][#2] [\c!background=, \c!frame=\v!on, \c!corner=\v!rectangular, - \c!frameoffset=\!!zeropoint, - \c!framedepth=\!!zeropoint, + \c!frameoffset=\zeropoint, + \c!framedepth=\zeropoint, \c!framecolor=] \else\iffirstargument \showframe diff --git a/tex/context/base/page-sel.mkiv b/tex/context/base/page-sel.mkiv deleted file mode 100644 index 1e706aa22..000000000 --- a/tex/context/base/page-sel.mkiv +++ /dev/null @@ -1,347 +0,0 @@ -%D \module -%D [ file=page-sel, % moved from page-imp -%D version=1998.01.15, -%D title=\CONTEXT\ Page Macros, -%D subtitle=Page Selection, -%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 will become runtime loaded code. - -\writestatus{loading}{ConTeXt Page Macros / Page Selection} - -\unprotect - -%D One can (mis)use this mechanism, in close cooperation -%D with \PDFTEX\ to arrange pages of already produced files. -%D -%D \starttyping -%D \insertpages[file.pdf][1,3][n=30,width=18cm] -%D \stoptyping -%D -%D The pages are inserted in the text area, and even pages -%D are repositioned according to the width. In this example -%D empty pages are added after page 1 and 3. -%D -%D Selecting pages can be accomplished by: -%D -%D \starttyping -%D \filterpages[file.pdf][1,3,5][n=30,width=18cm] -%D \stoptyping -%D -%D One may pass \type {odd} or \type {even} instead of a -%D comma separated list. A third alternative is: -%D -%D \starttyping -%D \copypages[file.pdf][n=30,scale=950] -%D \stoptyping -%D -%D This macros inserts the page, according to the settings -%D provided. - -\def\insertpages - {\dotripleempty\doinsertpages} - -\def\doinsertpages[#1][#2][#3]% - {\doifassignmentelse{#2} - {\dodoinsertpages[#1][][#2]} - {\dodoinsertpages[#1][#2][#3]}} - -\def\dodoinsertpages[#1][#2][#3]% - {\bgroup - \dontcomplain - \getfiguredimensions[#1]% - \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]% - \doifinset0{#2}{\emptyhbox\page}% - \dorecurse\@@ipn - {\dofilterpage{#1}\recurselevel - \doifinset\recurselevel{#2}{\emptyhbox\page}}% - \egroup} - -\def\filterpages - {\dotripleempty\dofilterpages} - -\def\dofilterpages[#1][#2][#3]% % \noffigurepages not yet supported - {\bgroup - \dontcomplain - \getfiguredimensions[#1]% - \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]% - \doifelse{#2}\v!even - {\dorecurse\@@ipn - {\ifodd\recurselevel\relax\else\dofilterpage{#1}\recurselevel\fi}} - {\doifelse{#2}\v!odd - {\dorecurse\@@ipn - {\ifodd\recurselevel\relax\dofilterpage{#1}\recurselevel\fi}} - {\def\dodocommand##1{\ifnum##1>\@@ipn\else\dofilterpage{#1}{##1}\fi}% - \def\docommand ##1{\dowithrange{##1}\dodocommand}% - \processcommalist[#2]\docommand}}% - \egroup} - -\def\dofilterpage#1#2% - {\hbox to \textwidth - {\ifdoublesided\ifdim\@@ipwidth>\zeropoint\relax\ifodd\realpageno\else - \hfill - \def\dowithfigure{\hskip-\@@ipwidth}% - \fi\fi\fi - \setbox0\hbox - {\externalfigure[#1][\c!page=#2,\c!height=\textheight]}% - \wd0\zeropoint - \box0} - \page} - -\def\copypages - {\dodoubleempty\docopypages} - -\def\docopypages[#1][#2]% - {\bgroup - \getfiguredimensions[#1]% - \getparameters[\??ip] - [\c!n=\noffigurepages, - \c!marking=\v!off, - \c!scale=\!!thousand, - \c!offset=\!!zeropoint, - #2]% - \dorecurse\@@ipn - {\vbox to \textheight - {\hsize\textwidth - \scratchdimen\@@ipoffset - \centeredbox - {\doifelse\@@ipmarking\v!on\cuthbox\hbox - {\ifdim\scratchdimen>\zeropoint\relax - \advance\vsize -2\scratchdimen - \advance\hsize -2\scratchdimen - \externalfigure[#1][\c!page=\recurselevel,#2,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]% - \else - \externalfigure[#1][\c!page=\recurselevel,#2,\c!offset=\v!overlay]% - \fi}}} - \page} - \egroup} - -%D \macros -%D {combinepages} -%D -%D Yet another way of postprocessing is handles by \type -%D {\combinepages}. This macro builds a matrix of pages from a -%D file, for example: -%D -%D \starttyping -%D \setuppapersize -%D [A4][A4] % or [A4,landscape][A4,landscape] -%D -%D \setuplayout -%D [header=0pt,footer=1cm, -%D backspace=1cm,topspace=1cm, -%D width=middle,height=middle] -%D -%D \setupfootertexts -%D [presentation---\currentdate\space---\space\pagenumber] -%D -%D \starttext -%D \combinepages[slides][nx=2,ny=3,frame=on] -%D \stoptext -%D \stoptyping -%D -%D One can influence the way the pages are combined. (This -%D will be explained some time.) - -\def\combinepages - {\dodoubleempty\docombinepages} - -\def\docombinepages[#1][#2]% a=perpag b=free - {\bgroup - \dontcomplain - \getfiguredimensions[#1]% - \getparameters - [\??ip] - [\c!alternative=\v!a, - \c!n=\noffigurepages,\c!nx=2,\c!ny=2,\c!start=1,\c!stop=\!!maxcard, - \c!distance=\bodyfontsize, - \c!bottom=\vfill,\c!top=\vss, - \c!left=\hss,\c!right=\hss, - \c!before=\page,\c!after=\page,\c!inbetween=\blank, - \c!frame=,\c!background=,\c!backgroundcolor=, - #2]% - \def\@@ipname{#1}% - \@@ipbefore - \expandcheckedcsname{\??ip::\c!alternative:}\@@ipalternative\v!b - \@@ipafter - \egroup} - -\setvalue{\??ip::\c!alternative:\v!a}% - {\global\combinedpagescounter\@@ipstart - \doloop - {\vbox to \textheight - {\hsize\textwidth % ? ? - \scratchdimen\@@ipdistance - \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax - \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax - \dorecurse\@@ipny - {\hbox to \hsize - {\dorecurse\@@ipnx - {\vbox to \!!heighta - {\hsize\!!widtha - \vsize\!!heighta - \@@iptop - \hbox to \hsize - {\@@ipleft - \ifnum\combinedpagescounter>\@@ipstop\relax - \globallet\@@ipn\!!zerocount - \else\ifnum\combinedpagescounter>\@@ipn \else - \externalfigure[\@@ipname] - [\c!object=\v!no, - \c!page=\number\combinedpagescounter, - \c!factor=\v!max, - \c!background=\@@ipbackground, - \c!backgroundcolor=\@@ipbackgroundcolor, - \c!frame=\@@ipframe]% - \fi\fi - \@@ipright} - \@@ipbottom}% - \global\advance\combinedpagescounter\plusone - \hfil}% - \hfilneg} - \vfil}% - \vfilneg}% - \page - \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}} - -\setvalue{\??ip::\c!alternative:\v!c}% - {\global\combinedpagescounter\@@ipstart - \doloop - {\vbox to \textheight - {\hsize\textwidth % ? ? - \scratchdimen\@@ipdistance - \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax - \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax - \hbox to \hsize - {\dorecurse\@@ipnx - {\@@ipleft - \vbox to \textheight - {\hsize\!!widtha - {\dorecurse\@@ipny - {\@@iptop - \hbox to \hsize - {\vbox to \!!heighta - {\hsize\!!widtha - \vsize\!!heighta - \ifnum\combinedpagescounter>\@@ipstop\relax - \globallet\@@ipn\!!zerocount - \else\ifnum\combinedpagescounter>\@@ipn \else - \externalfigure[\@@ipname] - [\c!object=\v!no, - \c!page=\number\combinedpagescounter, - \c!factor=\v!max, - \c!background=\@@ipbackground, - \c!backgroundcolor=\@@ipbackgroundcolor, - \c!frame=\@@ipframe]% - \fi\fi}} - \global\advance\combinedpagescounter\plusone - \@@ipbottom}% - \vfil}% - \vfilneg} - \hfil}% - \hfilneg}} - \page - \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}} - -\setvalue{\??ip::\c!alternative:\v!horizontal}{\getvalue{\??ip::\c!alternative:\v!a}} -\setvalue{\??ip::\c!alternative:\v!vertical }{\getvalue{\??ip::\c!alternative:\v!c}} - -\setvalue{\??ip::\c!alternative:\v!b}% - {\global\combinedpagescounter\@@ipstart - \doloop - {\startbaselinecorrection - \scratchdimen\@@ipdistance - \!!widtha\dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax - \hbox to \hsize - {\dorecurse\@@ipnx - {\global\advance\combinedpagescounter\plusone - \ifnum\combinedpagescounter>\@@ipn \else - \normalexpanded{\noexpand\externalfigure[\@@ipname] - [\c!page=\number\combinedpagescounter, - \c!width=\the\!!widtha,% todo \freezedimenmacro - \c!background=\@@ipbackground, - \c!backgroundcolor=\@@ipbackgroundcolor, - \c!frame=\@@ipframe]}% - \hfill - \fi}\hfillneg}% - \stopbaselinecorrection - \ifnum\combinedpagescounter<\@@ipn\relax - \@@ipinbetween - \else - \exitloop - \fi}} - -% This macro cuts a page into n parts that can be pasted -% together. - -\def\slicepages - {\dotripleempty\doslicepages} - -\def\doslicepages[#1][#2][#3]% - {\ifthirdargument - \dodoslicepages[#1][#2][#3]% - \else - \dodoslicepages[#1][#2][#2]% - \fi} - -\newcounter\slicedpagenumber - -\def\dodoslicepages[#1][#2][#3]% - {\bgroup - \dontcomplain - \globallet\slicedpagenumber\!!zerocount - \getfiguredimensions[#1] - \getparameters - [\??ip] - [\c!n=1, - \c!offset=\!!zeropoint, - \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint, - \c!width=\figurewidth,\c!height=\figureheight,#2] - \ifnum\@@ipn>\zerocount - \definepapersize - [\s!dummy][\c!height=\@@ipheight,\c!width=\@@ipwidth] - \setuppapersize - [\s!dummy][\s!dummy] - \setuplayout - [\c!backspace=\!!zeropoint,\c!topspace=\!!zeropoint, - \c!height=\v!middle,\c!width=\v!middle, - \c!textdistance=\!!zeropoint, - \c!header=\!!zeropoint,\c!footer=\!!zeropoint] - \fi - \dorecurse\noffigurepages - {\global\let\slicedpagenumber\recurselevel - \ifnum\@@ipn>\plusone - \dorecurse\@@ipn - {\let\xslice\recurselevel - \dorecurse\@@ipn - {\let\yslice\recurselevel - \clip - [\c!nx=\@@ipn,\c!ny=\@@ipn,\c!x=\xslice,\c!y=\yslice] - {\scale - [\c!scale=\@@ipn000] - {\externalfigure[#1][\c!page=\slicedpagenumber]}} - \page}} - \else - \ifodd\slicedpagenumber\relax - \getparameters[\??ip][#2] - \else - \getparameters[\??ip][#3] - \fi - \hskip\@@ipoffset - \clip - [\c!hoffset=\@@iphoffset,\c!voffset=\@@ipvoffset, - \c!height=\@@ipheight,\c!width=\@@ipwidth] - {\externalfigure[#1][\c!page=\slicedpagenumber]} - \page - \fi} - \egroup} - -% \starttext \slicepages[slice1.pdf][n=3] \stoptext - -\protect \endinput diff --git a/tex/context/base/page-sel.mkvi b/tex/context/base/page-sel.mkvi new file mode 100644 index 000000000..1fe3f2f38 --- /dev/null +++ b/tex/context/base/page-sel.mkvi @@ -0,0 +1,368 @@ +%D \module +%D [ file=page-sel, % moved from page-imp +%D version=1998.01.15, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Page Selection, +%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 code relates to old texexec features and one can wonder if it needs +%D to be in the core. So, this could become runtime loaded code. Some of +%D the alternatives need checking. + +\writestatus{loading}{ConTeXt Page Macros / Page Selection} + +\unprotect + +%D One can (mis)use this mechanism to (re)arrange pages of already produced +%D files. +%D +%D \starttyping +%D \insertpages[file.pdf][1,3][n=30,width=18cm] +%D \stoptyping +%D +%D The pages are inserted in the text area, and even pages are repositioned +%D according to the width. In this example empty pages are added after page +%D 1 and 3. +%D +%D Selecting pages can be accomplished by: +%D +%D \starttyping +%D \filterpages[file.pdf][1,3,5][n=30,width=18cm] +%D \stoptyping +%D +%D One may pass \type {odd} or \type {even} instead of a comma separated list. A +%D third alternative is: +%D +%D \starttyping +%D \copypages[file.pdf][n=30,scale=950] +%D \stoptyping +%D +%D This macros inserts the page, according to the settings provided. + +\installcorenamespace{withpages} + +\installsetuponlycommandhandler \??withpages {withpages} +% \installdirectcommandhandler \??withpages {withpages} + +\newcount\c_page_selectors_n + +\unexpanded\def\insertpages + {\dotripleempty\page_selectors_insert} + +\def\page_selectors_insert[#filename][#emptylist][#settings]% + {\doifassignmentelse{#emptylist} + {\page_selectors_insert_indeed[#filename][][#emptylist]} + {\page_selectors_insert_indeed[#filename][#emptylist][#settings]}} + +\def\page_selectors_insert_indeed[#filename][#emptylist][#settings]% + {\bgroup + \dontcomplain + \getfiguredimensions[#filename]% + \global\c_page_selectors_n\noffigurepages\relax + \setupcurrentwithpages[\c!width=\zeropoint,#settings]% + \scratchwidth\directwithpagesparameter\c!width\relax + \doifinset0{#emptylist} + {\emptyhbox\page}% + \dorecurse\c_page_selectors_n + {\page_selectors_filter_a_page{#filename}\recurselevel + \doifinset\recurselevel{#emptylist} + {\emptyhbox\page}}% + \egroup} + +\unexpanded\def\filterpages + {\dotripleempty\page_selectors_filter} + +\def\page_selectors_filter[#filename][#selection][#settings]% % \noffigurepages not yet supported + {\bgroup + \dontcomplain + \getfiguredimensions[#filename]% + \global\c_page_selectors_n\noffigurepages\relax + \setupcurrentwithpages[\c!width=\zeropoint,#settings]% + \scratchwidth\directwithpagesparameter\c!width\relax + \edef\p_selection{#selection}% + \ifx\p_selection\v!even + \dorecurse\c_page_selectors_n + {\ifodd\recurselevel\else + \page_selectors_filter_a_page{#filename}\recurselevel + \fi}% + \else\ifx\p_selection\v!odd + \dorecurse\c_page_selectors_n + {\ifodd\recurselevel\relax + \page_selectors_filter_a_page{#filename}\recurselevel + \fi}% + \else + \def\page_selectors_filter_step_indeed#page% + {\ifnum#page>\c_page_selectors_n\else + \page_selectors_filter_a_page{#filename}{#page}% + \fi}% + \def\page_selectors_filter_step#step% + {\dowithrange{#step}\page_selectors_filter_step_indeed}% + \processcommacommand[\p_selection]\page_selectors_filter_step + \fi\fi + \egroup} + +\def\page_selectors_filter_a_page#filename#page% + {\hbox to \textwidth + {\ifdim\scratchwidth>\zeropoint + \rightorleftpageaction{\scratchwidth\zeropoint}{\hfill}% + \fi + \setbox\scratchbox\hbox + {\hskip-\scratchwidth + \externalfigure[#filename][\c!page=#page,\c!height=\textheight]\hss}% + \wd\scratchbox\zeropoint + \box\scratchbox} + \page} + +\unexpanded\def\copypages + {\dotripleempty\page_selectors_copy} + +\def\page_selectors_copy[#filename][#settings][#figuresettings]% + {\bgroup + \getfiguredimensions[#filename]% + \global\c_page_selectors_n\noffigurepages\relax + \setupcurrentwithpages[\c!marking=\v!off,\c!offset=\zeropoint,#settings]% + \scratchoffset\directwithpagesparameter\c!offset\relax + \dorecurse\c_page_selectors_n + {\vbox to \textheight + {\hsize\textwidth + \centeredbox + {\doifelse{\directwithpagesparameter\c!marking}\v!on\cuthbox\hbox % only place where cuthbox is used + {\ifdim\scratchoffset>\zeropoint\relax + \advance\vsize -2\scratchoffset + \advance\hsize -2\scratchoffset + \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]% + \else + \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!offset=\v!overlay]% + \fi}}} + \page} + \egroup} + +%D \macros +%D {combinepages} +%D +%D Yet another way of postprocessing is handles by \type {\combinepages}. This macro +%D builds a matrix of pages from a file, for example: +%D +%D \starttyping +%D \setuppapersize +%D [A4][A4] % or [A4,landscape][A4,landscape] +%D +%D \setuplayout +%D [header=0pt,footer=1cm, +%D backspace=1cm,topspace=1cm, +%D width=middle,height=middle] +%D +%D \setupfootertexts +%D [presentation---\currentdate\space---\space\pagenumber] +%D +%D \starttext +%D \combinepages[slides][nx=2,ny=3,frame=on] +%D \stoptext +%D \stoptyping +%D +%D One can influence the way the pages are combined. (This will be explained some +%D time.) + +\installcorenamespace{combinepagesalternative} + +\unexpanded\def\combinepages + {\dodoubleempty\page_selectors_combine} + +\def\page_selectors_combine[#filename][#settings]% a=perpag b=free + {\bgroup + \dontcomplain + \getfiguredimensions[#filename]% + \global\c_page_selectors_n\noffigurepages\relax + \setupcurrentwithpages + [\c!alternative=\v!a, + \c!nx=\plustwo,\c!ny=\plustwo,\c!start=\plusone,\c!stop=\maxcard, + \c!distance=\bodyfontsize, + \c!bottom=\vfill,\c!top=\vss,\c!left=\hss,\c!right=\hss, + \c!before=\page,\c!after=\page,\c!inbetween=\blank, + \c!frame=,\c!background=,\c!backgroundcolor=, + \c!name={#filename}, + #settings]% + \directwithpagesparameter\c!before + \scratchnx\directwithpagesparameter\c!nx + \scratchny\directwithpagesparameter\c!ny + \scratchdistance\directwithpagesparameter\c!distance\relax + \scratchwidth\dimexpr(\textwidth-\scratchnx\scratchdistance+\scratchdistance)/\scratchnx\relax + \scratchheight\dimexpr(\textheight-\scratchny\scratchdistance+\scratchdistance)/\scratchny\relax + \expandcheckedcsname{\??combinepagesalternative}{\directwithpagesparameter\c!alternative}\v!b + \directwithpagesparameter\c!after + \egroup} + +\setvalue{\??combinepagesalternative\v!a}% + {\global\combinedpagescounter\directwithpagesparameter\c!start\relax + \doloop + {\vbox to \textheight + {\dorecurse\scratchny + {\hbox to \textwidth + {\dorecurse\scratchnx + {\vbox to \scratchheight + {\hsize\scratchwidth + \vsize\scratchheight + \directwithpagesparameter\c!top + \hbox to \hsize + {\directwithpagesparameter\c!left + \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax + \global\c_page_selectors_n\zerocount + \else\ifnum\combinedpagescounter>\c_page_selectors_n \else + \externalfigure + [\directwithpagesparameter\c!name] + [\c!object=\v!no, + \c!page=\number\combinedpagescounter, + \c!factor=\v!max, + \c!background=\directwithpagesparameter\c!background, + \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor, + \c!frame=\directwithpagesparameter\c!frame]% + \fi\fi + \directwithpagesparameter\c!right} + \directwithpagesparameter\c!bottom}% + \global\advance\combinedpagescounter\plusone + \hfil}% + \hfilneg} + \vfil}% + \vfilneg}% + \page + \ifnum\combinedpagescounter>\c_page_selectors_n + \exitloop + \fi}} + +\setvalue{\??combinepagesalternative\v!c}% + {\global\combinedpagescounter\directwithpagesparameter\c!start\relax + \doloop + {\vbox to \textheight + {\hbox to \textwidth + {\dorecurse\scratchnx + {\directwithpagesparameter\c!left + \vbox to \textheight + {\hsize\scratchwidth + \dorecurse\scratchny + {\directwithpagesparameter\c!top + \hbox to \hsize + {\vbox to \scratchheight + {\hsize\scratchwidth + \vsize\scratchheight + \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax + \global\c_page_selectors_n\zerocount + \else\ifnum\combinedpagescounter>\c_page_selectors_n \else + \externalfigure + [\directwithpagesparameter\c!name] + [\c!object=\v!no, + \c!page=\number\combinedpagescounter, + \c!factor=\v!max, + \c!background=\directwithpagesparameter\c!background, + \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor, + \c!frame=\directwithpagesparameter\c!frame]% + \fi\fi}} + \global\advance\combinedpagescounter\plusone + \directwithpagesparameter\c!bottom}}% + \hfil}% + \hfilneg}}% + \page + \ifnum\combinedpagescounter>\c_page_selectors_n + \exitloop + \fi}} + +\setvalue{\??combinepagesalternative\v!horizontal}{\getvalue{\??combinepagesalternative\v!a}} +\setvalue{\??combinepagesalternative\v!vertical }{\getvalue{\??combinepagesalternative\v!c}} + +\setvalue{\??combinepagesalternative\v!b}% + {\global\combinedpagescounter\directwithpagesparameter\c!start\relax + \doloop + {\startbaselinecorrection + \hbox to \textwidth + {\dorecurse\scratchnx + {\global\advance\combinedpagescounter\plusone + \ifnum\combinedpagescounter>\c_page_selectors_n \else + \normalexpanded{\externalfigure + [\directwithpagesparameter\c!name] + [\c!page=\number\combinedpagescounter, + \c!width=\the\scratchwidth, + \c!background=\directwithpagesparameter\c!background, + \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor, + \c!frame=\directwithpagesparameter\c!frame]}% + \hfill + \fi}% + \hfillneg}% + \stopbaselinecorrection + \ifnum\combinedpagescounter<\c_page_selectors_n\relax + \directwithpagesparameter\c!inbetween + \else + \exitloop + \fi}} + +% This macro cuts a page into n parts that can be pasted together. + +\unexpanded\def\slicepages + {\dotripleempty\page_selectors_slice} + +\def\page_selectors_slice[#filename][#oddsettings][#evensettings]% + {\ifthirdargument + \page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]% + \else + \page_selectors_slice_indeed[#filename][#oddsettings][#oddsettings]% + \fi} + +\let\slicedpagenumber\!!zerocount +\let\slicedpagestepx \!!zerocount +\let\slicedpagestepy \!!zerocount + +\def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]% + {\bgroup + \dontcomplain + \global\let\slicedpagenumber\!!zerocount + \getfiguredimensions[#filename]% + \global\c_page_selectors_n\noffigurepages\relax + \setupcurrentwithpages + [\c!offset=\zeropoint,\c!hoffset=\zeropoint,\c!voffset=\zeropoint, + \c!width=\figurewidth,\c!height=\figureheight,#oddsettings]% + \ifnum\c_page_selectors_n>\zerocount + \definepapersize + [\s!dummy][\c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width]% + \setuppapersize + [\s!dummy][\s!dummy]% + \setuplayout + [\c!backspace=\zeropoint,\c!topspace=\zeropoint, + \c!height=\v!middle,\c!width=\v!middle, + \c!textdistance=\zeropoint, + \c!header=\zeropoint,\c!footer=\zeropoint]% + \fi + \dorecurse\noffigurepages + {\global\let\slicedpagenumber\recurselevel + \ifnum\c_page_selectors_n>\plusone + \dorecurse\c_page_selectors_n + {\let\slicedpagestepx\recurselevel + \dorecurse\c_page_selectors_n + {\let\slicedpagestepy\recurselevel + \clip + [\c!nx=\c_page_selectors_n,\c!ny=\c_page_selectors_n,\c!x=\slicedpagestepx,\c!y=\slicedpagestepy] + {\scale + [\c!scale=\number\c_page_selectors_n000] + {\externalfigure[#filename][\c!page=\slicedpagenumber]}}% + \page}}% + \else + \ifodd\slicedpagenumber\relax + \setupcurrentwithpages[#oddsettings]% + \else + \setupcurrentwithpages[#evensettings]% + \fi + \hskip\directwithpagesparameter\c!offset\relax + \clip + [\c!hoffset=\directwithpagesparameter\c!hoffset,\c!voffset=\directwithpagesparameter\c!voffset, + \c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width] + {\externalfigure[#filename][\c!page=\slicedpagenumber]}% + \page + \fi} + \egroup} + +% \starttext \slicepages[slice1.pdf][n=3] \stoptext + +\protect \endinput diff --git a/tex/context/base/page-set.mkiv b/tex/context/base/page-set.mkiv index 467f22493..45755436e 100644 --- a/tex/context/base/page-set.mkiv +++ b/tex/context/base/page-set.mkiv @@ -13,7 +13,9 @@ % getnoflines vs getrawnoflines -% some day: cleanup and go etex +% This is a rather old mechanism and we can best keep it as it is. If it gets +% replaced by a more modern solution, it will be an extra mechanism. So, we +% only do some basic cleanup. \writestatus{loading}{ConTeXt Page Macros / Column Sets} @@ -44,13 +46,95 @@ \newif\ifenoughcolumncells \newif\ifsomefreecolumncells \newif\ifcolumnspread -\newif\iftracecolumnset % \tracecolumnsettrue +\newif\iftracecolumnset + +\newif\ifforcecolumnsetgrid \forcecolumnsetgridtrue +\newif\ifcollectingsetcontent % never set +\newif\ifcarryoverfootnotes %\carryoverfootnotestrue +\newif\iflastcolumnfootnotes % never set \lastcolumnfootnotestrue +\newif\ifintermediatefootnotes + +\newbox \b_page_set_preceding +\newbox \b_page_set_trailing + +\newdimen \d_page_set_local_hsize +\newconditional\c_page_set_width_set + +\installcorenamespace{columnsetgrid} \def\columnmaxcells {75} % runtime \def\columnmaxfreecells {0} % runtime \def\columngaplimit {0} % {5} -\def\@otr@{otr} +\def\page_set_cell #1#2{\csname \??columnsetgrid:\number#1:\number#2\endcsname} +\def\page_set_cell_get#1#2{\box\csname \??columnsetgrid:\number#1:\number#2\endcsname} +\def\page_set_cell_set#1#2{\global\setbox\csname\??columnsetgrid:\number#1:\number#2\endcsname} + +\def\page_set_cell_doifelse#1#2% + {\relax + \ifvoid\csname\??columnsetgrid:\number#1:\number#2\endcsname + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\def\page_set_cell_erase_grid % maybe dedicated loops ... make another loop when max's have changed + {\bgroup + \increment\columnmaxcells\relax + \ifodd\realpageno \else + \columnspreadfalse + \fi + \ifcolumnspread + \page_set_cell_erase_grid_spread + \else + \page_set_cell_erase_grid_page + \fi + \page_set_cell_erase_grid_top + \global\columnfirstcell\zerocount + \global\columnlastcell \columnfirstcell + \global\columnfreecells\columnfirstcell + \egroup} + +\let\m_page_column_l\relax +\let\m_page_column_r\relax + +\def\page_set_cell_erase_grid_spread + {\dorecurse\nofcolumns + {\let \m_page_column_l\recurselevel + \edef\m_page_column_r{\the\numexpr\recurselevel+\lofcolumns}% + \dostepwiserecurse \zerocount \columnmaxcells \plusone + {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname + \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname + \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \else + \emptyhbox + \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \fi + \else + \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname + \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \else + \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname + \fi + \fi}}} + +\def\page_set_cell_erase_grid_page + {\dorecurse \tofcolumns + {\let\m_page_column_l\recurselevel + \dostepwiserecurse \zerocount \columnmaxcells \plusone + {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname + \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\emptybox + \else + \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname + \fi}}} + +\def\page_set_cell_erase_grid_top + {\dorecurse\tofcolumns + {\global\setbox\csname\??columnsetgrid:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}} + +% % % % \def\OTRSETmakeupwidth{\innermakeupwidth} @@ -60,15 +144,6 @@ \unexpanded\def\page_set_command_synchronize_side_floats {\page_sides_forget_floats} -\def\OTRSETgridcell #1#2{\csname \@otr@:\number#1:\number#2\endcsname} -\def\OTRSETgetgridcell#1#2{\box\csname \@otr@:\number#1:\number#2\endcsname} -\def\OTRSETsetgridcell#1#2{\global\setbox\csname\@otr@:\number#1:\number#2\endcsname} - -\long\def\OTRSETdoifcellelse#1#2% - {\relax\ifvoid\csname\@otr@:\number#1:\number#2\endcsname - \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments - \fi} - % The following two macros are used to compensate for a switch in body fonts % as in: % @@ -184,64 +259,16 @@ \relax % needed ! ! ! ! else lookahead over \fi and \@EA \@EA\egroup\@EA\scratchdimen\the\!!dimena\relax} -\def\columnerasegridboxes % maybe dedicated loops - {\bgroup - \increment\columnmaxcells\relax - \ifodd\realpageno - \else % we are on the other page - \columnspreadfalse - \fi - \ifcolumnspread - \dorecurse\nofcolumns - {\let\!!stringa\recurselevel - \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns - \edef\!!stringb{\the\scratchcounter}% - \dostepwiserecurse \zerocount \columnmaxcells \plusone - {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname - \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname - \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname - \box\csname\@otr@:\!!stringb:\recurselevel\endcsname - %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname - \else - \emptyhbox - %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox - \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname - \fi - \else - \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname - \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname - \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname - \else - \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname - \fi - \fi}}% - \else - \dorecurse \tofcolumns - {\let\!!stringa\recurselevel - \dostepwiserecurse \zerocount \columnmaxcells \plusone - {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname - \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox - \else - \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname - \fi}}% - \fi - \dorecurse\tofcolumns - {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}% - \global\columnfirstcell\zerocount - \global\columnlastcell\columnfirstcell - \global\columnfreecells\columnfirstcell - \egroup} - \def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data} {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone \!!counte#3\advance\!!counte#5\advance\!!counte\minusone \dostepwiserecurse{#2}\!!countd\plusone {\!!countf\recurselevel \dostepwiserecurse{#3}\!!counte\plusone - {\OTRSETsetgridcell\!!countf\recurselevel#1}}% + {\page_set_cell_set\!!countf\recurselevel#1}}% \dostepwiserecurse{#3}\!!counte\plusone - {\wd\OTRSETgridcell{#2}\recurselevel\hsize}% - \OTRSETsetgridcell{#2}\!!counte#6} + {\wd\page_set_cell{#2}\recurselevel\hsize}% + \page_set_cell_set{#2}\!!counte#6} \def\OTRSETsetgridcells {\doOTRSETsetgridcells{\copy\placeholderboxb}} @@ -252,19 +279,17 @@ \unexpanded\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]} \unexpanded\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]} +\installcorenamespace{columnsettag} % temp hack + \def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value - {% not needed, is already relative - % \doifinstringelse{+}{#3}{\scratchcounter\realpageno}{\scratchcounter\zerocount}% - % \advance\scratchcounter#3\relax % \relax needed - % \setevalue{\??mc:#1:#2:\the\scratchcounter:\number#4}{\number#5}} - \iffifthargument - \setevalue{\??mc:#1:#2:\number#3:\number#4}{\number#5}% + {\iffifthargument + \setevalue{\??columnsettag:#1:#2:\number#3:\number#4}{\number#5}% \else - \setevalue{\??mc:#1:#2:\number#3:0}{\number#4}% + \setevalue{\??columnsettag:#1:#2:\number#3:0}{\number#4}% \fi} -\def\currentcolumnmaxcellstag #1{\??mc:l:\OTRSETidentifier:\columnsetpage:\number#1} -\def\currentcolumnstartcelltag#1{\??mc:s:\OTRSETidentifier:\columnsetpage:\number#1} +\def\currentcolumnmaxcellstag #1{\??columnsettag:l:\OTRSETidentifier:\columnsetpage:\number#1} +\def\currentcolumnstartcelltag#1{\??columnsettag:s:\OTRSETidentifier:\columnsetpage:\number#1} \def\doresetcolumnsetlines#1% {\ifcsname\currentcolumnmaxcellstag{#1}\endcsname @@ -312,7 +337,7 @@ {\ifnum\columnfirstcell>\columnmaxcells\relax \exitloop \else - \OTRSETdoifcellelse{#1}\columnfirstcell + \page_set_cell_doifelse{#1}\columnfirstcell {\global\advance\columnfirstcell\plusone}\exitloop \fi}% \global\columnlastcell\columnfirstcell @@ -320,7 +345,7 @@ {\ifnum\columnlastcell>\columnmaxcells\relax \exitloop \else - \OTRSETdoifcellelse{#1}\columnlastcell + \page_set_cell_doifelse{#1}\columnlastcell {\global\advance\columnlastcell \minusone \exitloop} {\global\advance\columnlastcell \plusone }% \fi}% @@ -351,7 +376,7 @@ \edef\columnmaxcells{\the\scratchcounter}% \scratchcounter\zerocount \dostepwiserecurse{#2}\columnmaxcells\plusone - {\OTRSETdoifcellelse{#1}\recurselevel + {\page_set_cell_doifelse{#1}\recurselevel {\ifnum\columnmaxfreecells<\scratchcounter \edef\columnmaxfreecells{\the\scratchcounter}% \let\columnfrmfreecells\recurselevel @@ -362,7 +387,7 @@ \long\def\OTRSETrecurseRL#1% {\dostepwiserecurse\nofcolumns\plusone\minusone - {#1\hskip\OTRSETgetparameter\c!distance\recurselevel}} + {#1\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}} \def\OTRSETmakegridbox {\ifcase\columndirection @@ -373,6 +398,28 @@ \def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness +\def\page_set_make_background_box + {\begingroup + \mofcolumns\recurselevel % used to signal mp + \d_page_set_local_hsize\OTRSETlocalwidth\recurselevel + \scratchdistance\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\relax + \edef\currentcolumnset{\currentcolumnset:\recurselevel}% + \letcolumnsetparameter\c!width \d_page_set_local_hsize + \letcolumnsetparameter\c!height\!!heighta + \letcolumnsetparameter\c!lines \empty + \letcolumnsetparameter\c!region\currentcolumnset + \setbox\scratchbox\hbox\inheritedcolumnsetframed{}% maybe \fastlocalframed + \wd\scratchbox\d_page_set_local_hsize + \ht\scratchbox\!!heighta + \ifcase\columndirection + \hskip\scratchdistance + \box\scratchbox + \else + \box\scratchbox + \hskip\scratchdistance + \fi + \endgroup} + \def\OTRSETdomakegridbox#1#2#3% {\hbox\bgroup \dontcomplain @@ -380,28 +427,13 @@ \!!heighta \textheight % test first ! \hbox to \OTRSETmakeupwidth - {\dostepwiserecurse{#1}{#2}{#3} - {\mofcolumns\recurselevel - \localcolumnwidth\OTRSETlocalwidth\mofcolumns - \setbox\scratchbox\hbox\localframed - [\??mc\OTRSETidentifier\number\mofcolumns]% - [\c!width=\localcolumnwidth,\c!height=\!!heighta,\c!lines=]% - {}% - \wd\scratchbox\localcolumnwidth - \ht\scratchbox\!!heighta - \ifcase\columndirection - \hskip\OTRSETgetparameter\c!distance\recurselevel - \box\scratchbox - \else - \box\scratchbox - \hskip\OTRSETgetparameter\c!distance\recurselevel - \fi}}% + {\dostepwiserecurse{#1}{#2}{#3}\page_set_make_background_box}% \hskip-\OTRSETmakeupwidth % main text \hbox to \OTRSETmakeupwidth {\dostepwiserecurse{#1}{#2}{#3} {\mofcolumns\recurselevel - \localcolumnwidth\OTRSETlocalwidth\mofcolumns + \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns \offinterlineskip \setbox\scratchbox\vbox to \!!heighta {%\topskipcorrection % not needed @@ -417,14 +449,14 @@ \vfill \fi \dorecurse\columnmaxcells - {\setbox\scratchbox\hbox{\OTRSETgetgridcell\mofcolumns\recurselevel}% + {\setbox\scratchbox\hbox{\page_set_cell_get\mofcolumns\recurselevel}% \ht\scratchbox\strutht \dp\scratchbox\strutdp \ifcase\columndirection \box\scratchbox \else - \hbox to \localcolumnwidth - {\hskip\localcolumnwidth\llap{\box\scratchbox}}% + \hbox to \d_page_set_local_hsize + {\hskip\d_page_set_local_hsize\llap{\box\scratchbox}}% \fi \par}% \ifcase\OTRSETbalancemethod @@ -439,12 +471,12 @@ \kern\zeropoint \vss \fi}% - \wd\scratchbox\localcolumnwidth % \textwidth + \wd\scratchbox\d_page_set_local_hsize % \textwidth \page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox \ifcase\columndirection - \hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox + \hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\box\scratchbox \else - \box\scratchbox\hskip\OTRSETgetparameter\c!distance\recurselevel + \box\scratchbox\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance \fi}}% \egroup} @@ -459,7 +491,7 @@ \!!counta\columnmaxcells \donetrue \doloop - {\dorecurse\nofcolumns{\OTRSETdoifcellelse\recurselevel\!!counta\donefalse\donothing}% + {\dorecurse\nofcolumns{\page_set_cell_doifelse\recurselevel\!!counta\donefalse\donothing}% \ifdone \ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi \else @@ -483,22 +515,22 @@ {\placebottomnotes}% \ifdim\ht\scratchbox>\zeropoint \setbox\scratchbox\hbox - {\hbox to \zeropoint{\OTRSETgetgridcell\nofcolumns\lastcolumnlastcell}% + {\hbox to \zeropoint{\page_set_cell_get\nofcolumns\lastcolumnlastcell}% \box\scratchbox}% \ht\scratchbox\strutht \dp\scratchbox\strutdp - \OTRSETsetgridcell\nofcolumns\lastcolumnlastcell\box\scratchbox + \page_set_cell_set\nofcolumns\lastcolumnlastcell\box\scratchbox \fi \global\lastcolumnlastcell\zerocount \fi} \def\OTRSETdoflush - {\ifcollectingcontent + {\ifcollectingsetcontent \global\mofcolumns\plusone \else \OTRSETdofinalflush \OTRSETdofinaloutput - \ifnum\columnsetpage>0 + \ifnum\columnsetpage>\zerocount \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}% \fi \doglobal\increment\columnsetpage @@ -554,11 +586,10 @@ \newdimen \OTRSETtextsheight \let \OTRSETidentifier=\empty -\def\OTRSETgetparameter#1#2{\csname\??mc\OTRSETidentifier\number#2#1\endcsname} -\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}} - \def\OTRSETskipstart - {\scratchcounter\executeifdefined{\??mc\OTRSETidentifier\c!start}\zerocount + {\doifelsenothing{\columnsetparameter\c!start} + {\scratchcounter\zerocount}% + {\scratchcounter\columnsetparameter\c!start}% \relax % needed ! \ifcase\scratchcounter\else \advance\scratchcounter\plusone @@ -569,7 +600,7 @@ \fi} \unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?) - {\ifcollectingcontent \else % can be assigndimen + {\ifcollectingsetcontent \else % can be assigndimen \OTRSETsetcolumnmaxcells % layout can be changed \OTRSETskipstart % not that well tested \OTRSETcheckinsert % added @@ -577,7 +608,7 @@ \ifsomefreecolumncells \global\vsize\columnfreecells\lineheight \ifinotr % else problems with floats, see extreme - \global\pagegoal\vsize % niet nodig, tenzij binnen otr + \pagegoal\vsize % niet nodig, tenzij binnen otr \fi \synchronizeoutput % fails on example % \allowbreak % hm @@ -586,12 +617,12 @@ \fi} \def\page_set_command_set_hsize % of course this does not migrate outside the otr - {\localcolumnwidth\OTRSETlocalwidth\mofcolumns - \textwidth\localcolumnwidth - \hsize\localcolumnwidth} + {\d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns + \textwidth\d_page_set_local_hsize + \hsize\d_page_set_local_hsize} \unexpanded\def\page_set_command_synchronize_hsize - {\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set + {\ifconditional\c_page_set_width_set \bgroup \scratchdimen\OTRSETlocalwidth\mofcolumns \ifdim\scratchdimen=\textwidth @@ -829,7 +860,7 @@ {\ifnum\columngaplimit>\zerocount \donefalse \dostepwiserecurse{#2}\columnmaxcells\plusone - {\OTRSETdoifcellelse{#1}\recurselevel + {\page_set_cell_doifelse{#1}\recurselevel {\ifdone \!!countb\recurselevel \advance\!!countb -\!!counta\relax \ifnum\!!countb>\plusone @@ -837,7 +868,7 @@ \ifnum\!!countb<\columngaplimit\relax \!!countb\recurselevel \advance\!!countb \minusone \dostepwiserecurse\!!counta\!!countb\plusone - {\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}% + {\page_set_cell_set{#1}\recurselevel\copy\placeholderboxc}% %\message{[gap]}% \fi \fi @@ -951,7 +982,7 @@ \else \advance\columnhcells \plusone \advance\scratchcounter \plusone - \advance\totalcolumnspace \OTRSETgetparameter\c!distance\scratchcounter + \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\number\scratchcounter}\c!distance \fi \else \exitloop @@ -973,9 +1004,9 @@ %\scratchcounter#2\advance\scratchcounter\minusone %\ifnum\scratchcounter>0 % \dostepwiserecurse{#1}\!!countd\plusone -% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint +% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint % \let\columnspacetopoffset\plusone -% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint +% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint % \let\columnspacetopoffset\plusone % \fi\fi}% % \advance\!!counte \columnspacetopoffset \relax @@ -986,9 +1017,9 @@ %\advance\scratchcounter \columnvcells \relax %\ifnum\scratchcounter>\columnmaxcells\else % \dostepwiserecurse{#1}\!!countd\plusone -% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint +% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint % \let\columnspacebotoffset\plusone -% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint +% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint % \let\columnspacebotoffset\plusone % \fi\fi}% % \advance\!!counte \columnspacebotoffset \relax @@ -999,12 +1030,15 @@ \!!countf\recurselevel\relax \dostepwiserecurse{#2}\!!counte\plusone % rows {\ifenoughcolumncells - \OTRSETdoifcellelse\!!countf\recurselevel + \page_set_cell_doifelse\!!countf\recurselevel {\enoughcolumncellsfalse}{}% \fi}% \fi}% \fi} +\let\preferedcolumn\empty +\let\preferedrow \empty + \def\OTRSETsetpreferedcolumnslot#1#2% {\doifsomething{#1}{\edef\preferedcolumn{#1}}% \doifsomething{#2}{\edef\preferedrow {#2}}} @@ -1078,7 +1112,7 @@ \def\OTRSETstoreincolumnslotFXTB#1% fixed column {\OTRSETcheckprefered - \OTRSETdoifcellelse\pofcolumns\plusone + \page_set_cell_doifelse\pofcolumns\plusone {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo \OTRSETflushtextsofar \OTRSETstoreincolumnslotindeed @@ -1087,7 +1121,7 @@ \def\OTRSETstoreincolumnslotFXBT#1% fixed column {\OTRSETcheckprefered - \OTRSETdoifcellelse\pofcolumns\columnmaxcells + \page_set_cell_doifelse\pofcolumns\columnmaxcells {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo \OTRSETflushtextsofar \OTRSETstoreincolumnslotindeed @@ -1264,7 +1298,7 @@ \fi} \unexpanded\def\page_set_command_check_if_float_fits - {\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi} + {\global\ifconditional\c_page_floats_not_permitted\setfalse\c_page_floats_room\else\settrue\c_page_floats_room\fi} \def\OTRSETunpreparebox#1% {\ifhbox#1% spans and so @@ -1279,25 +1313,25 @@ \def\OTRSETsavebox#1% clean up the skips {\OTRSETunpreparebox{#1}% - \dofloatssave\s!text} + \page_floats_save\s!text} \def\OTRSETresavebox#1% clean up the skips {\OTRSETunpreparebox{#1}% - \dofloatsresave\s!text} + \page_floats_resave\s!text} \unexpanded\def\page_set_command_flush_float_box - {\iftestfloatbox\ruledhbox\fi{\box\floatbox}} + {\box\floatbox} \unexpanded\def\page_set_command_flush_floats {\bgroup \def\OTRSETsavebox##1{\!!doneafalse}% \doloop - {\ifsomefloatwaiting + {\ifconditional\c_page_floats_some_waiting \OTRSETskipstart - \dofloatsgetinfo\s!text + \page_floats_get_info\s!text \ifdim\floatwidth>\zeropoint \!!doneatrue - \dofloatsflush\s!text{1}% + \page_floats_flush\s!text\plusone \dp\floatbox\zeropoint \OTRSETstoreincolumnslot{TBLR}\floatbox \if!!donea @@ -1333,9 +1367,9 @@ \else % only span if there is a next column with content \dorecurse\columnmaxcells - {\ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint + {\ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint \centergridcellonlyfalse - \else\ifdim\dp\OTRSETgridcell\currenthcell\currentvcell>\zeropoint + \else\ifdim\dp\page_set_cell\currenthcell\currentvcell>\zeropoint \centergridcellonlyfalse \fi\fi}% \fi @@ -1343,10 +1377,10 @@ \currenthcell\recurselevel \dorecurse\columnmaxcells {\currentvcell\recurselevel\relax - \ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint - \ifdim\dp\OTRSETgridcell\currenthcell\currentvcell=\zeropoint + \ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint + \ifdim\dp\page_set_cell\currenthcell\currentvcell=\zeropoint \bgroup - \setbox\scratchbox\OTRSETgetgridcell\currenthcell\currentvcell + \setbox\scratchbox\page_set_cell_get\currenthcell\currentvcell \getnoflines{\ht\scratchbox}% \!!counta\currentvcell \advance\!!counta -\noflines @@ -1363,9 +1397,9 @@ {\if!!doneb \let\xrecurselevel\recurselevel \dostepwiserecurse\!!counta\currentvcell\plusone - {\ifdim\ht\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint + {\ifdim\ht\page_set_cell\xrecurselevel\recurselevel>\zeropoint \!!donebfalse - \else\ifdim\wd\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint + \else\ifdim\wd\page_set_cell\xrecurselevel\recurselevel>\zeropoint \!!donebfalse \fi\fi}% \if!!doneb @@ -1375,11 +1409,11 @@ \totalcolumnspace\OTRSETlocalwidth\currenthcell \dostepwiserecurse\!!countc\!!countb\plusone {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel - \advance\totalcolumnspace \OTRSETgetparameter\c!distance\recurselevel}% + \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}% \ifdim\totalcolumnspace>\wd\scratchbox \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}% \fi - \OTRSETsetgridcell\currenthcell\currentvcell\box\scratchbox + \page_set_cell_set\currenthcell\currentvcell\box\scratchbox \egroup \fi \fi}}% @@ -1388,8 +1422,8 @@ \def\OTRSETinitializecolumns% once per page {\columnspreadtrue % todo \ifcolumnspread - \global\rofcolumns\getvalue{\??mc\OTRSETidentifier\c!nright}% - \global\lofcolumns\getvalue{\??mc\OTRSETidentifier\c!nleft}% + \global\rofcolumns\columnsetparameter\c!nright + \global\lofcolumns\columnsetparameter\c!nleft \global\tofcolumns\rofcolumns \relax \ifodd\realpageno\relax \global\nofcolumns\rofcolumns @@ -1398,67 +1432,70 @@ \global\nofcolumns\lofcolumns \fi \else - \global\nofcolumns\getvalue{\??mc\OTRSETidentifier\c!n}% + \global\nofcolumns\columnsetparameter\c!n \global\rofcolumns\nofcolumns \global\lofcolumns\nofcolumns \global\tofcolumns\nofcolumns \fi \OTRSETassignwidths \global\mofcolumns\plusone - \columnerasegridboxes} + \page_set_cell_erase_grid} -% vanaf hier: - -\unexpanded\def\definecolumnset - {\dodoubleargument\dodefinecolumnset} - -\def\dodefinecolumnset[#1][#2]% - {\getparameters[\??mc#1] - [\c!direction=\v!right, - \c!balance=\v!no, - \c!distance=1.5\bodyfontsize, % controleren - \c!n=2, - \c!nleft=\getvalue{\??mc#1\c!n}, - \c!nright=\getvalue{\??mc#1\c!n}, - \c!width=\v!fit, - \c!lines=0, - \c!start=0, - #2]% - \dorecurse{\getvalue{\??mc#1\c!nleft}} % todo - {\dododefinecolumnset[#1][\recurselevel]}% - \dorecurse{\getvalue{\??mc#1\c!nright}} % todo - {\dododefinecolumnset[#1][\recurselevel]}% - % redo framed settings - \setupcolumnset[#1][1][\c!distance=\!!zeropoint]} - -\def\dododefinecolumnset[#1][#2]% - {\presetlocalframed - [\??mc#1#2]% - \setupcolumnset - [#1][#2] - [\c!offset=\v!overlay, - \c!frame=\v!off, - \c!align=, - \c!lines=0,% really needed since c!regels is now part of framed - \c!width=\getvalue{\??mc#1\c!width}, - \c!distance=\getvalue{\??mc#1\c!distance}]} +% this is a first step in upgrading + +\installcorenamespace{columnset} + +\installframedcommandhandler \??columnset {columnset} \??columnset + +\setupcolumnset % todo, use the rather basic backgroundframed + [\c!direction=\v!right, + \c!balance=\v!no, + \c!distance=1.5\bodyfontsize, + \c!n=2, + \c!nleft=\columnsetparameter\c!n, + \c!nright=\columnsetparameter\c!n, + \c!width=\v!fit, + \c!lines=0, + \c!start=0, + \c!frame=\v!off, + \c!offset=\v!overlay, + \c!frame=\v!off, + \c!align=, + \c!lines=0] + +\let\page_set_setup_saved\setupcolumnset + +\newconditional\c_page_set_defining + +\appendtoks + \ifconditional\c_page_set_defining \else + \settrue\c_page_set_defining + \dorecurse{\columnsetparameter\c!nleft} + {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}% + \dorecurse{\columnsetparameter\c!nright} + {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}% + \normalexpanded{\page_set_setup_saved[\currentcolumnset:1][\c!distance=\zeropoint]}% + \setfalse\c_page_set_defining + \fi +\to \everydefinecolumnset \unexpanded\def\setupcolumnset - {\dotripleargument\dosetupcolumnset} + {\dotripleargument\page_set_setup} -\def\dosetupcolumnset[#1][#2][#3]% +\def\page_set_setup[#1][#2][#3]% {\ifthirdargument - \def\docommand##1% + \unexpanded\def\page_set_setup_step##1% {\doifelse{##1}\v!each - {\dorecurse{\getvalue{\??mc#1\c!n}}{\docommand\recurselevel}} - {\getparameters[\??mc#1##1][#3]}}% - \processcommalist[#2]\docommand + {\dorecurse{\namedcolumnsetparameter{#1}\c!n}{\page_set_setup_step\recurselevel}} + {\normalexpanded{\page_set_setup_saved[#1:\recurselevel]}[#3]}}% + \processcommalist[#2]\page_set_setup_step \else - \getparameters[\??mc#1][#2]% + \page_set_setup_saved[#1][#2]% \fi} - -\definecolumnset[\s!default][\c!n=2] % fallback - + +\definecolumnset + [\s!default] + \unexpanded\def\page_set_command_next_page {\page_otr_fill_and_eject_page \relax\ifnum\mofcolumns>\plusone @@ -1470,7 +1507,6 @@ \let\page_set_command_next_page_and_inserts\page_set_command_next_page - \def\OTRSETgotocolumn {\dosingleempty\doOTRSETgotocolumn} @@ -1500,7 +1536,7 @@ \currenthcell\mofcolumns \currentvcell#1\advance\currentvcell \minusone \dorecurse\currentvcell - {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing + {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing {\advance\scratchcounter\plusone}} \getnoflines\pagetotal \advance\scratchcounter-\noflines @@ -1547,7 +1583,7 @@ % \currenthcell\mofcolumns % \currentvcell#2\advance\currentvcell \minusone % \dorecurse\currentvcell -% {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing +% {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing % {\advance\scratchcounter\plusone}} % \getnoflines\pagetotal % \advance\scratchcounter-\noflines @@ -1610,7 +1646,7 @@ % \stoptext \def\OTRSETflushleftovers % new per 13/4/2006 - {\OTRSETdoifcellelse{1}{1} + {\page_set_cell_doifelse\plusone\plusone {\bgroup \OTRSETcentergridcells \OTRSETbalancemethod\plusone @@ -1643,7 +1679,7 @@ \fi \fi \global\setfalse\OTRSETfinish - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \page_otr_command_set_vsize \pagebreak \page_otr_command_set_vsize @@ -1725,8 +1761,8 @@ {\doifsomething\OTRSETlist {\getfromcommacommand[\OTRSETlist][1]% \global\let\OTRSETidentifier\commalistelement - \doifundefined{\??mc\OTRSETidentifier\c!n} - {\globallet\OTRSETidentifier\s!default}% + \xdef\currentcolumnset{\commalistelement}% + \checkcolumnsetparent \let\newcommalistelement\empty \doglobal\replaceincommalist\OTRSETlist1% \OTRSETrestart}} @@ -1752,8 +1788,8 @@ \OTRSETsetcorrectnofcells\currentcolumnstartcell \advance\scratchcounter \minusone \dorecurse\scratchcounter - {\OTRSETdoifcellelse\mofcolumns\recurselevel - \donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}% + {\page_set_cell_doifelse\mofcolumns\recurselevel + \donothing{\page_set_cell_set\mofcolumns\recurselevel\copy\placeholderboxe}}% \egroup}} \unexpanded\def\page_set_command_routine @@ -1778,13 +1814,13 @@ % new: raw \OTRSETsetcolumnmaxcells % direction - \doifelsevalue{\??mc\OTRSETidentifier\c!direction}\v!right + \doifelse{\columnsetparameter\c!direction}\v!right {\columndirection\zerocount} {\columndirection\plusone}% % balancing \OTRSETbalancemethod\zerocount \processaction - [\getvalue{\??mc\OTRSETidentifier\c!balance}] + [\columnsetparameter\c!balance] [ \v!yes=>\OTRSETbalancemethod\plusone, \v!top=>\OTRSETbalancemethod\plustwo, \v!bottom=>\OTRSETbalancemethod\plusthree]} @@ -1803,46 +1839,46 @@ \ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi \installoutputroutine\OTRSETflushpreposttext - {\global\setbox\precolumnbox\vbox + {\global\setbox\b_page_set_preceding\vbox {\unvbox\normalpagebox \global\lastskipinotr\lastskip}% \ifdim\lastskipinotr>\zeropoint - \global\setbox\precolumnbox\hbox - {\lower\strutdepth\box\precolumnbox}% + \global\setbox\b_page_set_preceding\hbox + {\lower\strutdepth\box\b_page_set_preceding}% \fi - \dp\precolumnbox\strutdepth + \dp\b_page_set_preceding\strutdepth \ifcarryoverfootnotes \else - \global\setbox\postcolumnbox\vbox{\placebottomnotes}% + \global\setbox\b_page_set_trailing\vbox{\placebottomnotes}% \fi} \let\precolumnlines \!!zerocount \let\postcolumnlines\!!zerocount \def\OTRSEThandlepreposttext - {\ifdim\ht\precolumnbox>\zeropoint % new - \getnoflines{\ht\precolumnbox}% + {\ifdim\ht\b_page_set_preceding>\zeropoint % new + \getnoflines{\ht\b_page_set_preceding}% \edef\precolumnlines{\the\noflines}% \doOTRSETsetgridcells {\copy\placeholderboxe} \plusone\plusone\nofcolumns\noflines % normal version (single column set) - % {\box\precolumnbox}% + % {\box\b_page_set_preceding}% % compensated for bodyfont change {\hbox {\OTRSETsetcorrectcellht - \raise\scratchdimen\box\precolumnbox}}% + \raise\scratchdimen\box\b_page_set_preceding}}% \else \let\precolumnlines\!!zerocount \fi - \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line - \getnoflines{\ht\postcolumnbox}% + \ifdim\ht\b_page_set_trailing>\zeropoint % new, otherwise empty bottom line + \getnoflines{\ht\b_page_set_trailing}% \edef\postcolumnlines{\the\noflines}% \advance\columnfreecells -\noflines \advance\columnfreecells \plusone \doOTRSETsetgridcells {\copy\placeholderboxe} \plusone\columnfreecells\nofcolumns\noflines - {\box\postcolumnbox}% + {\box\b_page_set_trailing}% \else \let\postcolumnlines\!!zerocount \fi} @@ -1855,7 +1891,7 @@ \def\OTRSETcheckgrid {\topskip1\topskip - \ifforcecolumngrid + \ifforcecolumnsetgrid \widowpenalty\zerocount \clubpenalty\zerocount \brokenpenalty\zerocount @@ -1894,29 +1930,31 @@ % interface to footnotes +\installcorenamespace{columnsetwidth} + \def\OTRSETassignwidths {%\scratchdimen\makeupwidth \freezetextwidth \scratchdimen\textwidth % \scratchcounter\zerocount \dorecurse\nofcolumns - {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit - {\advance\scratchcounter \plusone } - {\advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}% - \advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!distance}}% + {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit + {\advance\scratchcounter \plusone} + {\advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}% + \advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}% \ifcase\scratchcounter\else \divide\scratchdimen \scratchcounter \fi - \setgvalue{\??mc\??mc\c!width}{0}% + \global\setfalse\c_page_set_width_set \dorecurse\nofcolumns - {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit + {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit {\dimen0=\scratchdimen} - {\setgvalue{\??mc\??mc\c!width}{1}% - \dimen0=\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}% - \setxvalue{\??mc\recurselevel\??mc\c!width}{\the\dimen0}}} + {\global\settrue\c_page_set_width_set + \dimen0=\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}% + \setxvalue{\??columnsetwidth\recurselevel}{\the\dimen0}}} \def\OTRSETlocalwidth#1% - {\getvalue{\??mc\number#1\??mc\c!width}} + {\getvalue{\??columnsetwidth\number#1}} \newbox\placeholderboxa \newbox\placeholderboxb @@ -1930,7 +1968,7 @@ {\setbox\scratchbox\hbox to \hsize {\iftracecolumnset \hskip-.5ex% - \startcolor[columnset:#2]\vrule\!!width1ex\!!height.5ex\!!depth.5ex\stopcolor + \startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor \fi \hss}% \ifcase#1\relax @@ -1984,14 +2022,14 @@ \def\page_set_place_float_bottom{\def\floatmethod{BOTS}\page_set_place_float_slot} % check \def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge - {\iftestfloatbox\ruledhbox\fi{\box\floatbox}} + {\box\floatbox} \def\page_set_place_float_slot {\setbox\floatbox\vbox{\page_otr_command_flush_float_box}% \dp\floatbox\strutdp \@EA\uppercasestring\floatmethod\to\floatmethod \OTRSETstoreincolumnslot\floatmethod\floatbox - \doinsertfloatinfo} + \page_floats_report_total} % kind of new, looks much like OTRONE, but not entirely @@ -1999,7 +2037,7 @@ \unexpanded\def\page_set_command_set_top_insertions {\bgroup - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \let\totaltopinserted\!!zeropoint \OTRSETdodosettopinserts @@ -2020,9 +2058,9 @@ \egroup} \def\OTRSETdodosettopinserts - {\ifnum\noffloatinserts<\noftopfloats - \dogetfloat - \ifdim\topinserted=\zeropoint\relax + {\ifnum\noffloatinserts<\c_page_floats_n_of_top + \page_floats_get + \ifdim\d_page_floats_inserted_top=\zeropoint\relax \settrue\c_page_set_top_of_insert \else \setfalse\c_page_set_top_of_insert @@ -2038,25 +2076,28 @@ \fi \page_otr_command_flush_float_box \blank[\rootfloatparameter\c!spaceafter]}% - \global\advance\topinserted \ht\scratchbox\relax - \ifdim\topinserted>\vsize % was \textheight\relax + \global\advance\d_page_floats_inserted_top \ht\scratchbox\relax + \ifdim\d_page_floats_inserted_top>\vsize % was \textheight\relax \OTRSETresavebox\floatbox - \noffloatinserts\noftopfloats\relax - \global\advance\topinserted -\ht\scratchbox + \noffloatinserts\c_page_floats_n_of_top\relax + \global\advance\d_page_floats_inserted_top -\ht\scratchbox \let\OTRSETdodosettopinserts\relax % to be tested \else - \xdef\totaltopinserted{\the\topinserted}% - \insert\topins{\forgetall\box\scratchbox}% interlineskip ? - \ifsomefloatwaiting + \xdef\totaltopinserted{\the\d_page_floats_inserted_top}% + \insert\namedinsertionnumber\s!topfloat\bgroup + \forgetall + \box\scratchbox + \egroup + \ifconditional\c_page_floats_some_waiting \advance\noffloatinserts \plusone \else - \noffloatinserts\noftopfloats\relax + \noffloatinserts\c_page_floats_n_of_top\relax \fi - \dofloatflushedinfo + \page_floats_report_flushed \fi \else - \ifsomefloatwaiting - \showmessage\m!floatblocks6{\the\noftopfloats}% + \ifconditional\c_page_floats_some_waiting + \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}% \fi \let\OTRSETdodosettopinserts\relax \fi @@ -2064,67 +2105,66 @@ \unexpanded\def\page_set_command_set_bottom_insertions {\bgroup - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \OTRSETdodosetbotinserts \fi \egroup} \def\OTRSETdodosetbotinserts - {\ifnum\noffloatinserts<\nofbotfloats\relax - \dogetfloat - \global\advance\botinserted \ht\floatbox\relax - \global\advance\botinserted \dp\floatbox\relax - \global\advance\botinserted \floattopskip\relax - \ifdim\botinserted<\pagegoal\relax - \insert\botins - {\forgetall - \blank[\rootfloatparameter\c!spacebefore]% - \page_otr_command_flush_float_box}% - \ifsomefloatwaiting + {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax + \page_floats_get + \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax + \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax + \insert\namedinsertionnumber\s!bottomfloat\bgroup + \forgetall + \blank[\rootfloatparameter\c!spacebefore]% + \page_otr_command_flush_float_box + \egroup + \ifconditional\c_page_floats_some_waiting \advance\noffloatinserts \plusone \else - \noffloatinserts\nofbotfloats + \noffloatinserts\c_page_floats_n_of_bottom \fi - \dofloatflushedinfo + \page_floats_report_flushed \else \OTRSETresavebox\floatbox - \noffloatinserts\nofbotfloats\relax + \noffloatinserts\c_page_floats_n_of_bottom\relax \fi - \global\nofloatpermittedtrue % vgl topfloats s! + \global\settrue\c_page_floats_not_permitted % vgl topfloats s! \else - \ifsomefloatwaiting - \showmessage\m!floatblocks7{\the\nofbotfloats}% + \ifconditional\c_page_floats_some_waiting + \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}% \fi \let\OTRSETdodosetbotinserts\relax \fi \OTRSETdodosetbotinserts} \unexpanded\def\page_set_command_flush_top_insertions - {\ifvoid\topins\else + {\ifvoid\namedinsertionnumber\s!topfloat\else \ifvoid\columntopbox\mofcolumns - \columnsettopbox\mofcolumns\box\topins + \columnsettopbox\mofcolumns\box\namedinsertionnumber\s!topfloat \else \columnsettopbox\mofcolumns\vbox % temp, must be better {\forgetall \offinterlineskip \box\columntopbox\mofcolumns - \box\topins} + \box\namedinsertionnumber\s!topfloat} \fi \fi - \global\topinserted\zeropoint\relax} % goes away + \global\d_page_floats_inserted_top\zeropoint\relax} % goes away \unexpanded\def\page_set_command_flush_bottom_insertions - {\ifvoid\botins \else - \columnsetbotbox\mofcolumns\box\botins + {\ifvoid\namedinsertionnumber\s!bottomfloat \else + \columnsetbotbox\mofcolumns\box\namedinsertionnumber\s!bottomfloat % \else % \columnsetbotbox\mofcolumns\vbox % temp, must be better % {\forgetall % \offinterlineskip -% \box\botins +% \box\namedinsertionnumber\s!bottomfloat % \box\columnbotbox\mofcolumns} \fi - \global\botinserted\zeropoint\relax} % goes away + \global\d_page_floats_inserted_bottom\zeropoint\relax} % goes away % set ipv text @@ -2135,6 +2175,8 @@ % links rechts => odd, even, n, named +\definesystemvariable {mt} % MulTicolumn + \unexpanded\def\definecolumntextarea {\dotripleempty\dodefinecolumntextarea} @@ -2311,7 +2353,7 @@ \c!height=\!!heighta]% {\copy\scratchbox}% \fi}% - \OTRSETsetgridcell\!!counta\!!countb\box0 + \page_set_cell_set\!!counta\!!countb\box0 \ifcase\!!countc\else \advance\!!counta \columntextareaparameter\c!nx \advance\!!counta -\!!countc @@ -2328,7 +2370,7 @@ \c!height=\!!heighta,% \c!hoffset=\!!widthb]% {\copy\scratchbox}}% - \OTRSETsetgridcell\!!counta\!!countb\box0% + \page_set_cell_set\!!counta\!!countb\box0% \fi} \unexpanded\def\setupcolumntextareatext @@ -2366,7 +2408,7 @@ \fi \advance\!!counta \plusone \dostepwiserecurse\!!counta\!!countb\plusone - {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}% + {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}% \!!widthb\!!widtha \advance\!!widthb -\!!countc\textwidth \ifodd\realpageno \else % tricky, assumes that we keep there @@ -2376,7 +2418,7 @@ \advance\!!widtha \namedlayoutparameter\v!odd \c!backspace \advance\!!widthb \namedlayoutparameter\v!even\c!backspace \dorecurse\!!countc - {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}% + {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}% \fi \fi} @@ -2386,12 +2428,12 @@ {\!!counta#1\!!countb#2\docalculatecolumnsetspan \edef\columnsetspanhsize{\the\!!widtha}} -\unexpanded\def\page_set_command_set_float_hsize +\unexpanded\def\page_set_command_set_float_hsize % this helper has to be moved to strc-flt {\hsize % maybe checking optional - \ifdim\tempfloatwidth>\makeupwidth + \ifdim\d_strc_float_temp_width>\makeupwidth \makeupwidth \else - \tempfloatwidth + \d_strc_float_temp_width \fi} \unexpanded\def\definecolumnsetspan @@ -2538,12 +2580,12 @@ % \stopcolumnset \unexpanded\def\page_set_command_flush_saved_floats % rather similar to _one_ ut this might change - {\global\topinserted\zeropoint - \global\botinserted\zeropoint - \ifflushingfloats \else + {\global\d_page_floats_inserted_top\zeropoint + \global\d_page_floats_inserted_bottom\zeropoint + \ifconditional\c_page_floats_flushing \else \page_set_command_set_top_insertions \page_set_command_set_bottom_insertions - \ifsomefloatwaiting + \ifconditional\c_page_floats_some_waiting \doif{\rootfloatparameter\c!cache}\v!no\page_set_command_flush_floats % could be _otr_ \fi \fi} diff --git a/tex/context/base/page-sid.mkiv b/tex/context/base/page-sid.mkiv index f4d42a41c..f7a2357bf 100644 --- a/tex/context/base/page-sid.mkiv +++ b/tex/context/base/page-sid.mkiv @@ -68,29 +68,8 @@ \newdimen \d_page_sides_bottomskip \newdimen \d_page_sides_downshift -\setnewconstant \c_page_sides_align \zerocount \setnewconstant \c_page_sides_method \plusone % 0=raw 1=safe (.99) 2=tight (-1pt) - -% begin of public variables, this will change -% -% we need a setter and resetter .. or maybe a \placesidefloat[settings] to -% keep variables separated - -\let\sidefloatshift \d_page_sides_shift -\let\sidefloatextrashift\d_page_sides_extrashift -\let\sidefloatleftshift \d_page_sided_leftshift -\let\sidefloatrightshift\d_page_sided_rightshift -\let\sidefloatleftskip \d_page_sides_leftskip -\let\sidefloatrightskip \d_page_sides_rightskip -\let\sidefloatmaximum \d_page_sides_maximum -\let\sidefloattopskip \d_page_sides_topskip -\let\sidefloatbottomskip\d_page_sides_bottomskip -\let\sidefloatdownshift \d_page_sides_downshift - -\let\sidefloatsidelines \c_page_sides_n_of_lines - -\let\sidefloatalign \c_page_sides_align -\let\sidefloatmethod \c_page_sides_method +\setnewconstant \c_page_sides_align \zerocount \def\page_sides_process_float_backspace {\global\c_page_sides_float_type\plusone \page_sides_handle_float} \def\page_sides_process_float_leftedge {\global\c_page_sides_float_type\plustwo \page_sides_handle_float} @@ -104,13 +83,12 @@ \let\logsidefloat \relax -\newif\ifroomforfloat % shared (will change) \newif\iftracesidefloats % public (might change) % end of public variables \def\page_sides_insert_info - {\doinsertfloatinfo} + {\page_floats_report_total} \def\page_sides_apply_horizontal_shift {\ifdim\d_page_sides_maximum>\zeropoint @@ -211,8 +189,8 @@ +\compensatedinnermakeupmargin \relax \fi - \ifdim\d_page_sides_rightskip>\zeropoint \doglobal\advance\d_page_sides_rightskip\rightskip \fi - \ifdim\d_page_sides_leftskip >\zeropoint \doglobal\advance\d_page_sides_leftskip \leftskip \fi} + \ifdim\d_page_sides_rightskip>\zeropoint \global\advance\d_page_sides_rightskip\rightskip \fi + \ifdim\d_page_sides_leftskip >\zeropoint \global\advance\d_page_sides_leftskip \leftskip \fi} \def\page_sides_flush_floats {\par @@ -232,10 +210,7 @@ \doloop {\strut \iftracesidefloats - \color[darkgray]% - {\baselinerulefalse - \boxrulewidth.5\points - \ruledhbox{\strut\kern\d_page_sides_width}}% + \color[darkgray]{\ruledhbox{\strut\kern\d_page_sides_width}}% \fi \par \ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint @@ -330,7 +305,9 @@ \ifdim\wd\b_page_sides_bottom<\d_page_sides_hsize \parskip\zeropoint %\noindent - \ifinner\else\vadjust{\penalty\minusone}\fi + \ifinner\else + \vadjust{\penalty\minusone}% + \fi \ifconditional\c_page_sides_l_eq \global\setfalse\c_page_sides_l_eq \else @@ -421,7 +398,7 @@ \else \kern\d_page_sides_shift \fi - \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth\fi}% + \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth \fi}% \ifnum\c_page_sides_float_type>\plusfour \kern\d_page_sides_shift \else @@ -535,7 +512,7 @@ \def\page_sides_push_float_inline#1% {\begingroup - \everypar\emptytoks % needed ! + \reseteverypar % needed ! \parskip\zeropoint % needed ! \page_sides_set_skips \page_sides_insert_info @@ -579,7 +556,7 @@ \else\ifnum\c_page_sides_float_type>\plusfive \global\d_page_sides_width\zeropoint \else - \global\d_page_sides_width\dimexpr\wd\floatbox+\floatsideskip\relax + \global\d_page_sides_width\dimexpr\wd\floatbox+\d_strc_floats_margin\relax \fi\fi \ifdim\d_page_sides_width<\zeropoint \global\d_page_sides_width\zeropoint @@ -601,7 +578,7 @@ \fi \relax % really needed ! ! ! ! \ifdim\dimen0>\dimen2 - \global\roomforfloatfalse + \global\setfalse\c_page_floats_room \else \ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomskip \global\advance\d_page_sides_vsize \dimen0 @@ -612,15 +589,15 @@ \global\advance\d_page_sides_vsize \d_page_sides_bottomskip \global\setfalse\c_page_sides_short \fi - \global\roomforfloattrue + \global\settrue\c_page_floats_room \fi} \def\page_sides_prepare_space {\par \whitespace \begingroup - \everypar\emptytoks \forgetall + \reseteverypar \verticalstrut \vskip-\struttotal \endgroup} @@ -633,7 +610,7 @@ \page_sides_relocate_float{#1}% \page_sides_apply_vertical_shift \page_sides_analyse_space - \ifroomforfloat \else + \ifconditional\c_page_floats_room \else \page_otr_fill_and_eject_page \page_sides_analyse_space \page_sides_inject_dummy_lines @@ -653,9 +630,6 @@ \let\page_sides_check_floats\page_sides_check_floats_indeed -\def\iffirstsidefloatparagraph - {\ifcase\c_page_sides_checks_done\or} - \unexpanded\def\page_sides_check_floats_set {\scratchdimen\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax \c_page_sides_n_of_hang\scratchdimen @@ -704,7 +678,7 @@ \iftracesidefloats \hskip-\d_page_sides_width % kern \color[darkgray]% - {\vrule\!!height.5\points\!!depth.5\points\!!width\d_page_sides_width + {\vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width \llap{\showstruts\strut\kern.25\bodyfontsize}}% \fi} @@ -788,7 +762,7 @@ % some will become obsolete \def\checksidefloat {\page_sides_check_floats} -%def\flushsidefloats {\page_sides_flush_floats} +\def\flushsidefloats {\page_sides_flush_floats} \def\flushsidefloatsafterpar{\page_sides_flush_floats_after_par} %def\forgetsidefloats {\page_sides_forget_floats} %def\synchronizesidefloats {\page_sides_synchronize_floats} diff --git a/tex/context/base/page-spr.mkiv b/tex/context/base/page-spr.mkiv index f4768d4e9..dc1e013d5 100644 --- a/tex/context/base/page-spr.mkiv +++ b/tex/context/base/page-spr.mkiv @@ -17,10 +17,9 @@ \unprotect -\newbox\spreadbox -\newif \ifinspread - -\setnewconstant\showspreadmode\plusone +\newbox \b_page_spread_content +\newconditional\c_page_spread_busy +\newconditional\c_page_spread_once % when true only one flush (writes etc) % beware, ugly overload, to be redone @@ -35,52 +34,81 @@ \noindent % content can be < \hsize \page_otr_command_package_contents#2#3}}% \dp#1\zeropoint - \setbox#1\hbox to \makeupwidth - {\ifinspread - \ifvoid\spreadbox - \global\setbox\spreadbox\box#1% - \copy\spreadbox\hss % left page + \ifconditional\c_page_spread_busy + \normalsettextpagecontent_spread{#1}% + \else + \normalsettextpagecontent_normal{#1}% + \fi} + +\def\normalsettextpagecontent_normal#1% + {\setbox#1\hbox to \makeupwidth + {\hss\box#1\hss}} % never change the \hss's + +\def\normalsettextpagecontent_spread#1% + {\setbox#1\hbox to \makeupwidth + {\ifvoid\b_page_spread_content + \ifconditional\c_page_spread_once + \box#1% \else - % prevent duplicate writes in normal run - \ifarrangingpages \else \ifcase\showspreadmode - \global\setbox\spreadbox\emptyhbox - \wd\spreadbox\makeupwidth - \ht\spreadbox\textheight - \fi \fi - \hss\box\spreadbox % right page + \global\setbox\b_page_spread_content\box#1% + \copy\b_page_spread_content \fi + \hss % left page \else - \hss\box#1\hss % never change the \hss's + \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}} -\def\doflushspread - {\ifinspread \ifvoid\spreadbox\else +\unexpanded\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 } \unexpanded\def\startspread - {\bgroup - \ifdoublesided - \page[\v!left]% - %\setsystemmode{spread}% - \inspreadtrue - \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}% - \unexpanded\def\startspread{\bgroup\let\stopspread\egroup}% - \let\stopspread\dostopspread + {\ifdoublesided + \ifconditional\c_page_spread_busy + \doubleexpandafter\page_spread_start_nop + \else + \doubleexpandafter\page_spread_start_yes + \fi \else - \let\stopspread\egroup + \expandafter\page_spread_start_nop \fi} \let\stopspread\relax -\def\dostopspread - {\kern\zeropoint\page - \inspreadfalse +\unexpanded\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} + +\unexpanded\def\page_spread_stop_yes + {\kern\zeropoint + \page \setuplayout[\c!textwidth=\textwidth] \page[\v!left] \egroup} +\unexpanded\def\page_spread_start_nop + {\bgroup + \let\stopspread\page_spread_stop_nop} + +\unexpanded\def\page_spread_stop_nop + {\egroup} + \protect \endinput % texexec --arr --pdf test diff --git a/tex/context/base/page-str.mkiv b/tex/context/base/page-str.mkiv index f14f2f716..200a71377 100644 --- a/tex/context/base/page-str.mkiv +++ b/tex/context/base/page-str.mkiv @@ -36,25 +36,25 @@ \unprotect \let \currentoutputstream \empty -\newif \ifinoutputstream +\newif \ifinoutputstream % will becoem a conditional or mode \newtoks \everyenableoutputstream \appendtoks \page_otr_command_flush_side_floats \to \everyenableoutputstream -\def\initializeoutputstreams +\unexpanded\def\initializeoutputstreams {\ctxlua{streams.initialize()}% \glet\initializeoutputstreams\relax} -\def\enableoutputstream[#1]% could be \startoutputsubstream +\unexpanded\def\enableoutputstream[#1]% could be \startoutputsubstream {\initializeoutputstreams \the\everyenableoutputstream \inoutputstreamtrue \xdef\currentoutputstream{#1}% \ctxlua{streams.enable("#1")}} -\def\disableoutputstream +\unexpanded\def\disableoutputstream {\inoutputstreamfalse \global\let\currentoutputstream\s!default \ctxlua{streams.disable()}} @@ -71,15 +71,13 @@ {\ctxlua{streams.stop()}% \endgroup} -\let\currentoutputsubstream\empty - -\def\startoutputsubstream[#1]% - {\glet\savedcurrentoutputstream\currentoutputstream +\unexpanded\def\startoutputsubstream[#1]% just push/pop instead + {\globalpushmacro\currentoutputstream \enableoutputstream[#1]} -\def\stopoutputsubstream - {\glet\currentoutputstream\savedcurrentoutputstream - \enableoutputstream[\savedcurrentoutputstream]} +\unexpanded\def\stopoutputsubstream + {\globalpopmacro\currentoutputstream + \enableoutputstream[\currentoutputstream]} \def\flushoutputstream [#1]{\ctxlua{streams.flush("#1")}} \def\outputstreamcopy [#1]{\vbox{\ctxlua{streams.flush("#1",true)}}} @@ -89,7 +87,8 @@ \def\synchronizestreams [#1]{\ctxlua{streams.synchronize("#1")}} \def\dopushoutputstream [#1]{\ctxlua{streams.push("#1")}} -\def\pushoutputstream {\dosingleempty\dopushoutputstream} +\unexpanded\def\pushoutputstream + {\dosingleempty\dopushoutputstream} % \unexpanded\def\defineoutputstream[#1]% % {\doifundefined{otrs:#1}{\expandafter\newbox\csname otrs:#1\endcsname}} @@ -103,13 +102,15 @@ % \directsetup{stream:\firstoutputstream:bottom} % \directsetup{stream:\firstoutputstream:reset} -%D Obsolete in \MKIV: - -\unexpanded\def\definemarknote {\dodoubleempty\dodefinemarknote} -\def\dodefinemarknote[#1][#2]{} -\def\setmarknote [#1]{\gobbleoneargument} -\def\flushmarknotes [#1]{} -\def\erasemarknotes [#1]{} +% Obsolete in \MKIV: +% +% \unexpanded\def\definemarknote +% {\dodoubleempty\dodefinemarknote} +% +% \def\dodefinemarknote[#1][#2]{} +% \def\setmarknote [#1]{\gobbleoneargument} +% \def\flushmarknotes [#1]{} +% \def\erasemarknotes [#1]{} \protect \endinput diff --git a/tex/context/base/page-txt.mkvi b/tex/context/base/page-txt.mkvi index c86597338..dc445e0e1 100644 --- a/tex/context/base/page-txt.mkvi +++ b/tex/context/base/page-txt.mkvi @@ -430,6 +430,9 @@ \global\setfalse\resyncaftertextline \fi} +\def\getspecificlayouttext#vertical#horizontal#what% + {\csname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname} + % \settext[header][text][middle][xxx][yyy] \def\settextcontent @@ -474,8 +477,6 @@ %D macros. These are hooked into the general purpose token %D list registers mentioned before. -\def\ignoredlinebreak{\unskip\space\ignorespaces} - \def\page_layouts_place_text_line_indeed#vertical#height% {\let\currentlayouttextline#vertical% \ifdim#height>\zeropoint\relax % prevents pagenumbers when zero height @@ -693,26 +694,26 @@ % associated. This is a rather messy test but better than the MkII % way where we use states and keep settings. -\let\m_page_layouts_page_number_location_ \relax -\let\m_page_layouts_page_number_location__v\relax -\let\m_page_layouts_page_number_location__h\relax -\let\m_page_layouts_page_number_location__x\relax +\let\m_page_layouts_page_number_location \relax +\let\m_page_layouts_page_number_location_v\relax +\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 - {\placelocationpagenumber} % test below fails +\def\page_layouts_place_page_number % also elsewhere .. beware, not \unexpanded else + {\strc_pagenumbers_place_location} % test below fails \def\page_layouts_reset_page_number_location - {\ifx\m_page_layouts_page_number_location__v\relax\else - \edef\currentlayoutelement{\m_page_layouts_page_number_location__v:\m_page_layouts_page_number_location__h}% - \edef\page_layouts_previous_page_number_locator{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location__x}% + {\ifx\m_page_layouts_page_number_location_v\relax\else + \edef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}% + \edef\page_layouts_previous_page_number_locator{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location_x}% \doif{\meaning\page_layouts_previous_page_number_locator}{\meaning\page_layouts_place_page_number} - {\resetlayoutelementparameter\m_page_layouts_page_number_location__x}% + {\resetlayoutelementparameter\m_page_layouts_page_number_location_x}% \fi} \def\page_layouts_set_page_number_location - {\edef\currentlayoutelement{\m_page_layouts_page_number_location__v:\m_page_layouts_page_number_location__h}% - \letlayoutelementparameter\m_page_layouts_page_number_location__x\page_layouts_place_page_number - \ifx\m_page_layouts_page_number_location__x\c!marginedgetext + {\edef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}% + \letlayoutelementparameter\m_page_layouts_page_number_location_x\page_layouts_place_page_number + \ifx\m_page_layouts_page_number_location_x\c!marginedgetext \let\page_layouts_place_extra_text_left \page_layouts_place_page_number_left \let\page_layouts_place_extra_text_right\page_layouts_place_page_number_right \else @@ -721,38 +722,39 @@ \fi} \def\page_layouts_identify_page_number_location - {\let\m_page_layouts_page_number_location__v\v!footer - \let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!middletext - \processallactionsinset[\@@nmlocation] - [ \v!header=>\let\m_page_layouts_page_number_location__v\v!header, - \v!footer=>\let\m_page_layouts_page_number_location__v\v!footer, - \v!middle=>\let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!middletext, - \v!left=>\let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!lefttext, - \v!right=>\let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!righttext, - \v!inleft=>\let\m_page_layouts_page_number_location__h\v!margin - \let\m_page_layouts_page_number_location__x\c!lefttext, - \v!inright=>\let\m_page_layouts_page_number_location__h\v!margin - \let\m_page_layouts_page_number_location__x\c!righttext, - \v!inmargin=>\let\m_page_layouts_page_number_location__h\v!margin - \def\m_page_layouts_page_number_location__x{\ifdoublesided\c!margintext\else\c!righttext\fi}, - \v!margin=>\let\m_page_layouts_page_number_location__h\v!margin - \def\m_page_layouts_page_number_location__x{\ifdoublesided\c!margintext\else\c!righttext\fi}, - \v!atmargin=>\let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!marginedgetext, - \v!marginedge=>\let\m_page_layouts_page_number_location__h\v!text - \let\m_page_layouts_page_number_location__x\c!marginedgetext]} - -\unexpanded\def\dosetpagenumberlocation - {\ifx\@@nmlocation\m_page_layouts_page_number_location_ + {\let\m_page_layouts_page_number_location_v\v!footer + \let\m_page_layouts_page_number_location_h\v!text + \let\m_page_layouts_page_number_location_x\c!middletext + \processallactionsinset[\directpagenumberingparameter\c!location] + [ \v!header=>\let\m_page_layouts_page_number_location_v\v!header, + \v!footer=>\let\m_page_layouts_page_number_location_v\v!footer, + \v!middle=>\let\m_page_layouts_page_number_location_h\v!text + \let\m_page_layouts_page_number_location_x\c!middletext, + \v!left=>\let\m_page_layouts_page_number_location_h\v!text + \let\m_page_layouts_page_number_location_x\c!lefttext, + \v!right=>\let\m_page_layouts_page_number_location_h\v!text + \let\m_page_layouts_page_number_location_x\c!righttext, + \v!inleft=>\let\m_page_layouts_page_number_location_h\v!margin + \let\m_page_layouts_page_number_location_x\c!lefttext, + \v!inright=>\let\m_page_layouts_page_number_location_h\v!margin + \let\m_page_layouts_page_number_location_x\c!righttext, + \v!inmargin=>\let\m_page_layouts_page_number_location_h\v!margin + \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi}, + \v!margin=>\let\m_page_layouts_page_number_location_h\v!margin + \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi}, + \v!atmargin=>\let\m_page_layouts_page_number_location_h\v!text + \let\m_page_layouts_page_number_location_x\c!marginedgetext, + \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 + {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}% + \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location % unchanged \else - \let\m_page_layouts_page_number_location_\@@nmlocation + \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location \page_layouts_reset_page_number_location - \ifx\@@nmlocation\empty + \ifx\p_strc_pagenumbers_location\empty % set otherwise \else \page_layouts_identify_page_number_location @@ -764,9 +766,12 @@ {\begingroup \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}% \ifzeropt\wd\scratchbox\else - \doifelsenothing\@@nmwidth - {\box\scratchbox\tfskip} - {\hbox to \@@nmwidth{\box\scratchbox\hss}}% + \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}% + \ifx\p_strc_pagenumbers_width\empty + \box\scratchbox\tfskip + \else + \hbox to \p_strc_pagenumbers_width{\box\scratchbox\hss}% + \fi \fi \endgroup} @@ -774,13 +779,16 @@ {\begingroup \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}% \ifzeropt\wd\scratchbox\else - \doifelsenothing\@@nmwidth - {\tfskip\box\scratchbox} - {\hbox to \@@nmwidth{\hss\box\scratchbox}}% + \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}% + \ifx\p_strc_pagenumbers_width\empty + \tfskip\box\scratchbox + \else + \hbox to \p_strc_pagenumbers_width{\hss\box\scratchbox}% + \fi \fi \endgroup} -\dosetpagenumberlocation +\strc_pagenumbers_set_location % initializes % will go to page-box.mkiv @@ -839,7 +847,7 @@ \kern\dimexpr\leftmarginwidth+\leftmargindistance\relax \fi \endgroup - \mkprocesspagecontents{#2}% + \page_postprocessors_page{#2}% \settextpagecontent\b_page_layouts_element{#1}{#2}% \page_backgrounds_add_to_text\b_page_layouts_element \page_grids_add_to_box\b_page_layouts_element diff --git a/tex/context/base/phys-dim.lua b/tex/context/base/phys-dim.lua index c47821b1c..5b883ac88 100644 --- a/tex/context/base/phys-dim.lua +++ b/tex/context/base/phys-dim.lua @@ -116,27 +116,51 @@ local dnumber = (ddigitspace + ddigit)^1 -- : ; for the moment not used, maybe for invisible fraction . , when no leading number -local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___, - * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000, - * ddigitspace^0 * ddigit^0 -- _00 000 +-- local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___, +-- * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000, +-- * ddigitspace^0 * ddigit^0 -- _00 000 +-- * ( +-- dfinalperiod * ddigit -- .00 +-- + dskipperiod * dpadding^1 -- .== +-- + dsemiperiod * ddigit -- :00 +-- + dsemiperiod * dpadding^1 -- :== +-- )^0 +-- + ddigit -- 00 +-- +-- local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___. +-- * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000. +-- * ddigitspace^0 * ddigit^0 -- _00 000 +-- * ( +-- dfinalcomma * ddigit -- ,00 +-- + dskipcomma * dpadding^1 -- ,== +-- + dsemicomma * ddigit -- :00 +-- + dsemicomma * dpadding^1 -- :== +-- )^0 +-- + ddigit -- 00 +-- +-- fix by WS/SB (needs further testing) + +local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___, + * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000, + * ddigitspace^0 * ddigit^0 -- _00 000 * ( - dfinalperiod * ddigit -- .00 - + dskipperiod * dpadding^1 -- .== - + dsemiperiod * ddigit -- :00 - + dsemiperiod * dpadding^1 -- :== + dfinalperiod * ddigit * (dintercomma * ddigit)^0 -- .00 + + dskipperiod * dpadding^1 -- .== + + dsemiperiod * ddigit * (dintercomma * ddigit)^0 -- :00 + + dsemiperiod * dpadding^1 -- :== )^0 - + ddigit -- 00 + + ddigit -- 00 -local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___. - * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000. - * ddigitspace^0 * ddigit^0 -- _00 000 +local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___. + * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000. + * ddigitspace^0 * ddigit^0 -- _00 000 * ( - dfinalcomma * ddigit -- ,00 - + dskipcomma * dpadding^1 -- ,== - + dsemicomma * ddigit -- :00 - + dsemicomma * dpadding^1 -- :== + dfinalcomma * ddigit * (dinterperiod * ddigit)^0 -- 00 + + dskipcomma * dpadding^1 -- ,== + + dsemicomma * ddigit * (dinterperiod * ddigit)^0 -- :00 + + dsemicomma * dpadding^1 -- :== )^0 - + ddigit -- 00 + + ddigit -- 00 local p_c_dparser = math_one + math_two + dleader * p_c * dtrailer * dfinal local c_p_dparser = math_one + math_two + dleader * c_p * dtrailer * dfinal @@ -482,7 +506,7 @@ local unitsNspace = context.unitsNspace local labels = languages.data.labels -labels.prefixes = { +labels.prefixes = allocate { yocto = { labels = { en = [[y]] } }, -- 10^{-24} zepto = { labels = { en = [[z]] } }, -- 10^{-21} atto = { labels = { en = [[a]] } }, -- 10^{-18} @@ -515,7 +539,7 @@ labels.prefixes = { root = { labels = { en = [[√]] } }, -- 0x221A } -labels.units = { +labels.units = allocate { meter = { labels = { en = [[m]] } }, gram = { labels = { en = [[g]] } }, -- strictly kg is the base unit second = { labels = { en = [[s]] } }, @@ -597,14 +621,14 @@ labels.units = { micron = { labels = { en = [[\textmu m]] } }, } -labels.operators = { +labels.operators = allocate { times = { labels = { en = [[\unitsTIMES]] } }, solidus = { labels = { en = [[\unitsSOLIDUS]] } }, per = { labels = { en = [[\unitsSOLIDUS]] } }, outof = { labels = { en = [[\unitsOUTOF]] } }, } -labels.suffixes = { +labels.suffixes = allocate { linear = { labels = { en = [[1]] } }, square = { labels = { en = [[2]] } }, cubic = { labels = { en = [[3]] } }, @@ -849,7 +873,7 @@ local t_shortcuts = { suffixes = setmetatablenewindex(short_suffixes,trigger), } -physics.units.tables = { +physics.units.tables = allocate { units = t_units, shortcuts = t_shortcuts, } diff --git a/tex/context/base/phys-dim.mkiv b/tex/context/base/phys-dim.mkiv index 84c3c7a2a..934985399 100644 --- a/tex/context/base/phys-dim.mkiv +++ b/tex/context/base/phys-dim.mkiv @@ -216,10 +216,15 @@ \unexpanded\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname} \unexpanded\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname} -\unexpanded\def\digitsfinalcomma {\digitscommasymbol } % more for tracing +% \unexpanded\def\digitsfinalcomma {\digitscommasymbol } % more for tracing +% \unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing +% \unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing +% \unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing + +\unexpanded\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing \unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing \unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing -\unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing +\unexpanded\def\digitsintermediateperiod {\digitscommasymbol } % more for tracing %D The user macro: @@ -639,12 +644,10 @@ \definelabelclass [prefix] [2] \definelabelclass [suffix] [2] % This is only a label because we want to show them in a table. -\ctxlua{ - languages.labels.define("setupprefixtext","prefixes")% - languages.labels.define("setupunittext","units")% - languages.labels.define("setupoperatortext","operators")% - languages.labels.define("setupsuffixtext","suffixes")% -} +\ctxcommand{definelabels("prefix", "prefixes" )} +\ctxcommand{definelabels("unit", "units" )} +\ctxcommand{definelabels("operator","operators")} +\ctxcommand{definelabels("suffix", "suffixes" )} %D You can define additional units: %D diff --git a/tex/context/base/ppchtex.mkiv b/tex/context/base/ppchtex.mkiv index a14578ceb..0f42f91ce 100644 --- a/tex/context/base/ppchtex.mkiv +++ b/tex/context/base/ppchtex.mkiv @@ -474,9 +474,9 @@ \or \resetchemicalcoordinates \setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}% - \wd2=\!!zeropoint - \ht2=\!!zeropoint - \dp2=\!!zeropoint + \wd2\zeropoint + \ht2\zeropoint + \dp2\zeropoint \put {\box2} at 0 0 \endpicture \popMPdrawing @@ -515,9 +515,9 @@ \ifMPdrawingdone \resetchemicalcoordinates \setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}% - \wd2=\!!zeropoint - \ht2=\!!zeropoint - \dp2=\!!zeropoint + \wd2\zeropoint + \ht2\zeropoint + \dp2\zeropoint \put {\box2} at 0 0 % \fi \endpicture @@ -576,7 +576,7 @@ \!!widtha=50.8mm \divide\!!widtha by \@@chemicalresolution\relax \plotsymbolspacing=\!!widtha - \setplotsymbol({\vrule\!!height\!!widtha\!!width\!!widtha})% + \setplotsymbol({\vrule\s!height\!!widtha\s!width\!!widtha})% \fi} % Something for Dirk: @@ -2149,8 +2149,8 @@ \ifdim\wd4>\dimen2 \dimen0=\wd4 \fi \chemicaloutermolecule {#1} - {\ifdim\ht2>\!!zeropoint\box2\fi} % expands to \empty in test - {\ifdim\ht4>\!!zeropoint\box4\fi}% % expands to \empty in test + {\ifdim\ht2>\zeropoint\box2\fi} % expands to \empty in test + {\ifdim\ht4>\zeropoint\box4\fi}% % expands to \empty in test \egroup} \def\chemicalsingleouterarrow diff --git a/tex/context/base/prop-ini.mkiv b/tex/context/base/prop-ini.mkiv index d8d2ea2f4..3b1c59b24 100644 --- a/tex/context/base/prop-ini.mkiv +++ b/tex/context/base/prop-ini.mkiv @@ -37,7 +37,7 @@ \def\properties_define[#1][#2][#3]% {\properties_obsolete_message - \setevalue{\??propertytypes#1e}{#2}% + \setevalue{\??propertytypes#1}{#2}% \getvalue{\??propertydefiners#2}[#1][#2][#3]} \setvalue{\??propertystarters\v!layer }#1{\let\properties_stop\stopviewerlayer\startviewerlayer[#1]} diff --git a/tex/context/base/regi-ini.lua b/tex/context/base/regi-ini.lua index ec6f812cc..f9507bd0b 100644 --- a/tex/context/base/regi-ini.lua +++ b/tex/context/base/regi-ini.lua @@ -12,11 +12,13 @@ if not modules then modules = { } end modules ['regi-ini'] = { runtime.</p> --ldx]]-- -local utfchar, utfgsub = utf.char, utf.gsub +local commands, context = commands, context + +local utfchar = utf.char +local lpegmatch = lpeg.match local char, gsub, format = string.char, string.gsub, string.format local next = next -local insert, remove = table.insert, table.remove - +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy local allocate = utilities.storage.allocate local sequencers = utilities.sequencers @@ -138,17 +140,51 @@ local function translate(line,regime) return line end +-- local remappers = { } +-- +-- local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?") +-- local t = backmapping[vector] +-- local remapper = remappers[vector] +-- if not remapper then +-- remapper = utf.remapper(t) +-- remappers[t] = remapper +-- end +-- local m = getmetatable(t) +-- setmetatableindex(t, function(t,k) +-- local v = default or "?" +-- t[k] = v +-- return v +-- end) +-- str = remapper(str) +-- setmetatable(t,m) +-- return str +-- end +-- +-- -- much faster (but only matters when we have > 10K calls + +local cache = { } -- if really needed we can copy vectors and hash defaults + +setmetatableindex(cache, function(t,k) + local v = { remappers = { } } + t[k] = v + return v +end) + local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?") - local t = backmapping[vector] - local m = getmetatable(t) - setmetatableindex(t, function(t,k) - local v = default or "?" - t[k] = v - return v - end) - str = utfgsub(str,".",t) - setmetatable(t,m) - return str + local d = default or "?" + local c = cache[vector].remappers + local r = c[d] + if not r then + local t = fastcopy(backmapping[vector]) + setmetatableindex(t, function(t,k) + local v = d + t[k] = v + return v + end) + r = utf.remapper(t) + c[d] = r + end + return r(str) end local function disable() @@ -186,14 +222,14 @@ function regimes.process(str,filename,currentline,noflines,coding) return str end -function regimes.push() +local function push() level = level + 1 if trace_translating then report_translating("pushing level: %s",level) end end -function regimes.pop() +local function pop() if level > 0 then if trace_translating then report_translating("popping level: %s",level) @@ -202,6 +238,9 @@ function regimes.pop() end end +regimes.push = push +regimes.pop = pop + sequencers.prependaction(textlineactions,"system","regimes.process") sequencers.disableaction(textlineactions,"regimes.process") @@ -210,6 +249,9 @@ sequencers.disableaction(textlineactions,"regimes.process") commands.enableregime = enable commands.disableregime = disable +commands.pushregime = push +commands.popregime = pop + function commands.currentregime() context(currentregime) end diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex index d6685bd71..87fb72863 100644 --- a/tex/context/base/s-abr-01.tex +++ b/tex/context/base/s-abr-01.tex @@ -19,279 +19,291 @@ \protect -\logo [MKI] {MkI} % joke -\logo [MKII] {MkII} -\logo [MKIII] {MkIII} % joke -\logo [MKIV] {MkIV} -\logo [MKVI] {MkVI} -\logo [MPII] {MpII} -\logo [MPIV] {MpIV} +\logo [MKI] {MkI} % joke +\logo [MKII] {MkII} +\logo [MKIII] {MkIII} % joke +\logo [MKIV] {MkIV} +\logo [MKVI] {MkVI} +\logo [MKIX] {MkIX} +\logo [MKXI] {MkXI} +\logo [MKIC] {MkIC} +\logo [MKCI] {MkCI} +\logo [MPII] {MpII} +\logo [MPIV] {MpIV} -%logo [FGA] {fga} -%logo [FGBBS] {fgbbs} -\logo [ACROBAT] {Acro\-bat} -\logo [AFM] {afm} -\logo [API] {api} -\logo [ALEPH] {Aleph} % {\mathematics{\aleph}} -\logo [ALGOL] {ALGOL} -\logo [AMS] {ams} -\logo [AMSLATEX] {\AmSLaTeX} -\logo [AMSTEX] {\AmSTeX} -\logo [ANSI] {ansi} -\logo [ARABTEX] {Arab\TeX} -\logo [ASCII] {ascii} -\logo [ASCIITEX] {ascii\TeX} -\logo [BACHOTEX] {Bacho\TeX} -\logo [BIBTEX] {bib\TeX} -\logo [BLUESKY] {BlueSky} -\logo [BMP] {bmp} -\logo [BSD] {bsd} -\logo [CCODE] {C} -\logo [CPLUSPLUS] {C\high{++}} -\logo [CALCMATH] {CalcMath} -\logo [CD] {cd} -\logo [CPU] {cpu} -\logo [CDROM] {cdrom} -\logo [CID] {cid} -\logo [CJK] {cjk} -\logo [CMR] {cmr} -\logo [CLD] {cld} -\logo [CMYK] {cmyk} -\logo [CODHOST] {CodHost} -\logo [CONTEXT] {\ConTeXt} -\logo [CSS] {css} -\logo [CTAN] {ctan} -\logo [CTXTOOLS] {ctxtools} -\logo [CWEB] {cweb} -\logo [DANTE] {Dante} -\logo [DISTILLER] {distiller} -\logo [DRATEX] {Dra\TeX} -\logo [DSC] {dsc} -\logo [DTD] {dtd} -\logo [DTK] {dtk} -\logo [DTP] {dtp} -\logo [DVD] {dvd} -\logo [DVI] {dvi} -\logo [DVIPDFM] {dvipdfm} -\logo [DVIPDFMX] {dvipdfmx} -\logo [DVIPOS] {dvipos} -\logo [DVIPS] {dvips} -\logo [DVIPSONE] {dvipsone} -\logo [DVISCR] {dviscr} -\logo [DVIWINDO] {dviwindo} -\logo [EBCDIC] {ebcdic} -\logo [EC] {ec} -\logo [EIFFEL] {Eiffel} -\logo [EMACS] {emacs} -\logo [EMTEX] {em\TeX} -\logo [ENCODING] {enc} -\logo [ENCTEX] {enc\TeX} -\logo [EPS] {eps} -\logo [ETEX] {\eTeX} +%logo [FGA] {fga} +%logo [FGBBS] {fgbbs} +\logo [ACROBAT] {Acro\-bat} +\logo [AFM] {afm} +\logo [API] {api} +\logo [ALEPH] {Aleph} % {\mathematics{\aleph}} +\logo [ALGOL] {ALGOL} +\logo [AMS] {ams} +\logo [AMSLATEX] {\AmSLaTeX} +\logo [AMSTEX] {\AmSTeX} +\logo [ANSI] {ansi} +\logo [ARABTEX] {Arab\TeX} +\logo [ASCII] {ascii} +\logo [ASCIITEX] {ascii\TeX} +\logo [BACHOTEX] {Bacho\TeX} +\logo [BIBTEX] {bib\TeX} +\logo [BLUESKY] {BlueSky} +\logo [BMP] {bmp} +\logo [BSD] {bsd} +\logo [CCODE] {C} +\logo [CPLUSPLUS] {C\high{++}} +\logo [CALCMATH] {CalcMath} +\logo [CD] {cd} +\logo [CPU] {cpu} +\logo [CDROM] {cdrom} +\logo [CID] {cid} +\logo [CJK] {cjk} +\logo [CMR] {cmr} +\logo [CLD] {cld} +\logo [CMYK] {cmyk} +\logo [CODHOST] {CodHost} +\logo [CONTEXT] {\ConTeXt} +\logo [CSS] {css} +\logo [CTAN] {ctan} +\logo [CTXTOOLS] {ctxtools} +\logo [CWEB] {cweb} +\logo [CSTUG] {cstug} +\logo [DANTE] {Dante} +\logo [DISTILLER] {distiller} +\logo [DRATEX] {Dra\TeX} +\logo [DSC] {dsc} +\logo [DTD] {dtd} +\logo [DTK] {dtk} +\logo [DTP] {dtp} +\logo [DVD] {dvd} +\logo [DVI] {dvi} +\logo [DVIPDFM] {dvipdfm} +\logo [DVIPDFMX] {dvipdfmx} +\logo [DVIPOS] {dvipos} +\logo [DVIPS] {dvips} +\logo [DVIPSONE] {dvipsone} +\logo [DVISCR] {dviscr} +\logo [DVIWINDO] {dviwindo} +\logo [EBCDIC] {ebcdic} +\logo [EC] {ec} +\logo [EIFFEL] {Eiffel} +\logo [EMACS] {emacs} +\logo [EMTEX] {em\TeX} +\logo [ENCODING] {enc} +\logo [ENCTEX] {enc\TeX} +\logo [EPS] {eps} +\logo [ETEX] {\eTeX} \logo [EUROBACHOTEX] {EuroBacho\TeX} -\logo [EUROMATH] {EuroMath} -\logo [EUROTEX] {Euro\TeX} -\logo [EXAMPLE] {eXaMpLe} -\logo [EXAMPLED] {exampled} -\logo [EXAMPLEQ] {exampleq} -\logo [EXAMPLER] {exampler} -\logo [EXAMPLET] {examplet} -\logo [EXAMPLEX] {examplex} -\logo [EXIMPLE] {eXiMpLe} -\logo [FLAC] {flac} -\logo [FAQ] {faq} -\logo [FDF] {fdf} -\logo [FONTFORGE] {FontForge} -\logo [FOXET] {foXet} -\logo [FPTEX] {fp\TeX} -\logo [FREEBSD] {FreeBSD} -\logo [FTP] {ftp} -\logo [GHOSTSCRIPT]{Ghost\-script} -\logo [GHOSTVIEW] {Ghost\-view} -\logo [GIF] {gif} -\logo [GNU] {gnu} -\logo [GNUPLOT] {gnuplot} -\logo [GS] {Ghost\-Script} -\logo [GUST] {Gust} -\logo [GWTEX] {gw\TeX} -\logo [HSB] {hsb} -\logo [HTML] {html} -\logo [HTTP] {http} -\logo [HZ] {hz} -\logo [IBM] {ibm} -\logo [IMAGEMAGICK]{ImageMagick} -\logo [INITEX] {ini\TeX} -\logo [INRSTEX] {inrs\TeX} -\logo [IO] {io} -\logo [IRCNET] {IRCnet} -\logo [ISO] {iso} -\logo [JAVA] {Java} -\logo [JAVASCRIPT] {Java\-Script} -\logo [JPEG] {jpeg} -\logo [JPG] {jpg} -\logo [KPATHSEA] {kpathsea} -\logo [KPSE] {kpse} -\logo [KPSEWHICH] {kpsewhich} -\logo [MKTEXLSR] {mktexlsr} -\logo [LAMSTEX] {\LamSTeX} -\logo [LATEX] {\LaTeX} -\logo [LATEXTE] {\LaTeX2e} -\logo [LATEXTN] {\LaTeX2.09} -\logo [LCD] {lcd} -\logo [LINUX] {linux} -\logo [LISP] {Lisp} -\logo [LPEG] {lpeg} -\logo [LUA] {Lua} -\logo [LUAJIT] {LuaJIT} -\logo [LUATEX] {Lua\TeX} -\logo [LUATOOLS] {luatools} -\logo [MACOSX] {MacOSX} -\logo [MACROTEX] {Macro\TeX} -\logo [MAKEMPY] {MakeMPY} -\logo [MAPPING] {map} -\logo [MAPS] {Maps} -\logo [MATHML] {MathML} -\logo [METAFONT] {\MetaFont} -\logo [METAPOST] {\MetaPost} -\logo [METATEX] {Meta\TeX} -\logo [MIKTEX] {Mik\TeX} -\logo [MLTEX] {ml\TeX} -\logo [METATYPE] {MetaType1} -\logo [MODULA] {Modula} -\logo [MOV] {mov} -\logo [MPS] {mps} -\logo [MPTOPDF] {mptopdf} -\logo [MPLIB] {mplib} -\logo [MSDOS] {msdos} -\logo [MICROSOFT] {Microsoft} -\logo [MSWINDOWS] {MS~Windows} -\logo [MTXRUN] {mtxrun} -\logo [MTXTOOLS] {mtxtools} -\logo [NETPBM] {NetPBM} -\logo [NTG] {ntg} -\logo [NTS] {nts} -\logo [OFM] {ofm} -\logo [OMEGA] {Omega} -\logo [OPENMATH] {OpenMath} -\logo [OPENTYPE] {OpenType} -\logo [OPI] {opi} -\logo [OTF] {otf} -\logo [OTP] {otp} -\logo [OVF] {ovf} -\logo [PASCAL] {Pascal} -\logo [PCTEX] {pc\TeX} -\logo [PFA] {pfa} -\logo [PFB] {pfb} -\logo [PDF] {pdf} -\logo [PDFETEX] {pdfe\TeX} -\logo [PDFTEX] {pdf\TeX} -\logo [PDFTOOLS] {pdftools} -\logo [PDFTOPS] {pdftops} -\logo [PERL] {Perl} -\logo [PERLTK] {Perl/Tk} -\logo [PICTEX] {\PiCTeX} -\logo [PK] {pk} -\logo [PLAIN] {Plain} -\logo [PNG] {png} -\logo [POSIX] {posix} -\logo [POSTSCRIPT] {Post\-Script} -\logo [PPCHTEX] {\PPCHTeX} -\logo [PRAGMA] {Pragma ADE} -\logo [PRESS] {press} -\logo [PRIFIL] {prifil} -\logo [PS] {Post\-Script} -\logo [PSCHECK] {pscheck} -\logo [PSTOEDIT] {pstoedit} -\logo [PSTOPAGE] {pstopage} -\logo [PSTOPDF] {pstopdf} -\logo [PSTRICKS] {pstricks} -\logo [RAM] {ram} -\logo [READER] {Acro\-bat Reader} -\logo [RELAXNG] {Relax\kern.125emNG} -\logo [RGB] {rgb} -\logo [RLXTOOLS] {rlxtools} -\logo [RUBY] {Ruby} -\logo [SCITE] {SciTE} -\logo [SGML] {sgml} -\logo [SI] {si} -\logo [SQL] {sql} -\logo [SVG] {svg} -\logo [TABLE] {\TaBlE} -\logo [TCPIP] {tcp/ip} -\logo [TDS] {tds} % no sc te -\logo [TETEX] {te\TeX} % no sc te -\logo [TEX] {\TeX} -\logo [TEXADRES] {\TeX adress} -\logo [TEXBASE] {\TeX base} -\logo [TEXEDIT] {\TeX edit} -\logo [TEXEXEC] {\TeX exec} -\logo [TEXFONT] {\TeX font} -\logo [TEXFORM] {\TeX form} -\logo [TEXLIVE] {\TeX Live} -\logo [TEXLUA] {\TeX Lua} -\logo [TEXMF] {texmf} -\logo [TEXMFSTART] {texmfstart} -\logo [TEXNL] {tex-nl} -\logo [TEXSHOW] {\TeX show} -\logo [TEXSPELL] {\TeX spell} -\logo [TEXGYRE] {\TeX\ Gyre} -\logo [TEXSYNC] {texsync} -\logo [TEXTMATE] {TextMate} -\logo [TEXTOOLS] {\TeX tools} -\logo [TEXUTIL] {\TeX util} -\logo [TEXWORK] {\TeX work} -\logo [TEXXET] {\TeX\XeT} \def\XeT{XeT} -\logo [TFM] {tfm} -\logo [TIF] {tif} -\logo [TIFF] {tiff} -\logo [TIFFINFO] {tiffinfo} -\logo [TIFFTAGS] {tifftags} -\logo [TMFTOOLS] {tmftools} -\logo [TPIC] {tpic} -\logo [TPM] {tpm} -\logo [TRUETYPE] {TrueType} -\logo [TTC] {ttc} -\logo [TTF] {ttf} -\logo [TUG] {tug} -\logo [TUGBOAT] {Tug\-Boat} -\logo [TUGNEWS] {Tug\-News} -\logo [TYPEONE] {Type1} -\logo [UCS] {ucs} -\logo [UNICODE] {Uni\-code} -\logo [UNIX] {Unix} -\logo [URI] {uri} -\logo [URL] {url} -\logo [USA] {usa} -\logo [USENET] {usenet} -\logo [UTF] {utf} -\logo [USB] {usb} -\logo [VF] {vf} -\logo [WDT] {wdt} -\logo [WEB] {web} -\logo [WEBC] {web2c} -\logo [WIKI] {Wiki} -\logo [WINDOWS] {Windows} -\logo [WINNT] {WinNT} -\logo [WINNX] {Win9x} -\logo [WWW] {www} -\logo [WTHREEC] {W3C} -\logo [WYSIWYG] {wysiwyg} -\logo [XDVI] {Xdvi} -\logo [XETEX] {\XeTeX} -\logo [XFDF] {xfdf} -\logo [XHTML] {xhtml} -\logo [XINDY] {Xindy} -\logo [XML] {xml} -\logo [XPATH] {xpath} -\logo [XMLTOOLS] {xmltools} -\logo [XPDFETEX] {xpdfe\TeX} -\logo [XSL] {xsl} -\logo [XSLFO] {xsl-fo} -\logo [XSLT] {xslt} -\logo [XSLTPROC] {xsltproc} -\logo [XYPIC] {XYPIC} % wrong logo -\logo [YandY] {y\&y} -\logo [ZIP] {zip} +\logo [EUROMATH] {EuroMath} +\logo [EUROTEX] {Euro\TeX} +\logo [EXAMPLE] {eXaMpLe} +\logo [EXAMPLED] {exampled} +\logo [EXAMPLEQ] {exampleq} +\logo [EXAMPLER] {exampler} +\logo [EXAMPLET] {examplet} +\logo [EXAMPLEX] {examplex} +\logo [EXIMPLE] {eXiMpLe} +\logo [FLAC] {flac} +\logo [FAQ] {faq} +\logo [FDF] {fdf} +\logo [FONTFORGE] {FontForge} +\logo [FOXET] {foXet} +\logo [FPTEX] {fp\TeX} +\logo [FREEBSD] {FreeBSD} +\logo [FTP] {ftp} +\logo [GHOSTSCRIPT] {Ghost\-script} +\logo [GHOSTVIEW] {Ghost\-view} +\logo [GIF] {gif} +\logo [GNU] {gnu} +\logo [GNUPLOT] {gnuplot} +\logo [GS] {Ghost\-Script} +\logo [GUST] {Gust} +\logo [GCC] {gcc} +\logo [GWTEX] {gw\TeX} +\logo [HSB] {hsb} +\logo [HTML] {html} +\logo [HTTP] {http} +\logo [HZ] {hz} +\logo [IBM] {ibm} +\logo [IMAGEMAGICK] {ImageMagick} +\logo [INITEX] {ini\TeX} +\logo [INRSTEX] {inrs\TeX} +\logo [IO] {io} +\logo [IRCNET] {IRCnet} +\logo [ISO] {iso} +\logo [JAVA] {Java} +\logo [JAVASCRIPT] {Java\-Script} +\logo [JPEG] {jpeg} +\logo [JPG] {jpg} +\logo [KPATHSEA] {kpathsea} +\logo [KPSE] {kpse} +\logo [KPSEWHICH] {kpsewhich} +\logo [MKTEXLSR] {mktexlsr} +\logo [MYSQL] {MySQL} +\logo [LAMSTEX] {\LamSTeX} +\logo [LATEX] {\LaTeX} +\logo [LATEXTE] {\LaTeX2e} +\logo [LATEXTN] {\LaTeX2.09} +\logo [LCD] {lcd} +\logo [LINUX] {linux} +\logo [LISP] {Lisp} +\logo [LPEG] {lpeg} +\logo [LUA] {Lua} +\logo [LUAJIT] {LuaJIT} +\logo [LUATEX] {Lua\TeX} +\logo [LUATOOLS] {luatools} +\logo [LMX] {lmx} +\logo [MACOSX] {MacOSX} +\logo [MACROTEX] {Macro\TeX} +\logo [MAKEMPY] {MakeMPY} +\logo [MAPPING] {map} +\logo [MAPS] {Maps} +\logo [MATHML] {MathML} +\logo [METAFONT] {\MetaFont} +\logo [METAPOST] {\MetaPost} +\logo [METATEX] {Meta\TeX} +\logo [MIKTEX] {Mik\TeX} +\logo [MINGW] {MingW} +\logo [MLTEX] {ml\TeX} +\logo [METATYPE] {MetaType1} +\logo [MODULA] {Modula} +\logo [MOV] {mov} +\logo [MPS] {mps} +\logo [MPTOPDF] {mptopdf} +\logo [MPLIB] {mplib} +\logo [MSDOS] {msdos} +\logo [MICROSOFT] {Microsoft} +\logo [MSWINDOWS] {MS~Windows} +\logo [MSWORD] {MS~Word} +\logo [MTXRUN] {mtxrun} +\logo [MTXTOOLS] {mtxtools} +\logo [NETPBM] {NetPBM} +\logo [NTG] {ntg} +\logo [NTS] {nts} +\logo [OFM] {ofm} +\logo [OMEGA] {Omega} +\logo [OPENMATH] {OpenMath} +\logo [OPENTYPE] {OpenType} +\logo [OPI] {opi} +\logo [OTEX] {Oriental \TeX} +\logo [OTF] {otf} +\logo [OTP] {otp} +\logo [OVF] {ovf} +\logo [PASCAL] {Pascal} +\logo [PCTEX] {pc\TeX} +\logo [PFA] {pfa} +\logo [PFB] {pfb} +\logo [PDF] {pdf} +\logo [PDFETEX] {pdfe\TeX} +\logo [PDFTEX] {pdf\TeX} +\logo [PDFTOOLS] {pdftools} +\logo [PDFTOPS] {pdftops} +\logo [PERL] {Perl} +\logo [PERLTK] {Perl/Tk} +\logo [PICTEX] {\PiCTeX} +\logo [PK] {pk} +\logo [PLAIN] {Plain} +\logo [PNG] {png} +\logo [POSIX] {posix} +\logo [POSTSCRIPT] {Post\-Script} +\logo [PPCHTEX] {\PPCHTeX} +\logo [PRAGMA] {Pragma ADE} +\logo [PRESS] {press} +\logo [PRIFIL] {prifil} +\logo [PS] {Post\-Script} +\logo [PSCHECK] {pscheck} +\logo [PSTOEDIT] {pstoedit} +\logo [PSTOPAGE] {pstopage} +\logo [PSTOPDF] {pstopdf} +\logo [PSTRICKS] {pstricks} +\logo [RAM] {ram} +\logo [READER] {Acro\-bat Reader} +\logo [RELAXNG] {Relax\kern.125emNG} +\logo [RGB] {rgb} +\logo [RLXTOOLS] {rlxtools} +\logo [RUBY] {Ruby} +\logo [SCITE] {SciTE} +\logo [SGML] {sgml} +\logo [SI] {si} +\logo [SQL] {sql} +\logo [SVG] {svg} +\logo [SWIG] {swig} +\logo [TABLE] {\TaBlE} +\logo [TCPIP] {tcp/ip} +\logo [TDS] {tds} % no sc te +\logo [TETEX] {te\TeX} % no sc te +\logo [TEX] {\TeX} +\logo [TEXADRES] {\TeX adress} +\logo [TEXBASE] {\TeX base} +\logo [TEXEDIT] {\TeX edit} +\logo [TEXEXEC] {\TeX exec} +\logo [TEXFONT] {\TeX font} +\logo [TEXFORM] {\TeX form} +\logo [TEXLIVE] {\TeX Live} +\logo [TEXLUA] {\TeX Lua} +\logo [TEXMF] {texmf} +\logo [TEXMFSTART] {texmfstart} +\logo [TEXNL] {tex-nl} +\logo [TEXSHOW] {\TeX show} +\logo [TEXSPELL] {\TeX spell} +\logo [TEXGYRE] {\TeX\ Gyre} +\logo [TEXSYNC] {texsync} +\logo [TEXTMATE] {TextMate} +\logo [TEXTOOLS] {\TeX tools} +\logo [TEXUTIL] {\TeX util} +\logo [TEXWORK] {\TeX work} +\logo [TEXXET] {\TeX\XeT} \def\XeT{XeT} +\logo [TFM] {tfm} +\logo [TIF] {tif} +\logo [TIFF] {tiff} +\logo [TIFFINFO] {tiffinfo} +\logo [TIFFTAGS] {tifftags} +\logo [TMFTOOLS] {tmftools} +\logo [TPIC] {tpic} +\logo [TPM] {tpm} +\logo [TRUETYPE] {TrueType} +\logo [TTC] {ttc} +\logo [TTF] {ttf} +\logo [TUG] {tug} +\logo [TUGBOAT] {Tug\-Boat} +\logo [TUGNEWS] {Tug\-News} +\logo [TYPEONE] {Type1} +\logo [UCS] {ucs} +\logo [UNICODE] {Uni\-code} +\logo [UNIX] {Unix} +\logo [URI] {uri} +\logo [URL] {url} +\logo [USA] {usa} +\logo [USENET] {usenet} +\logo [UTF] {utf} +\logo [USB] {usb} +\logo [VF] {vf} +\logo [WDT] {wdt} +\logo [WEB] {web} +\logo [WEBC] {web2c} +\logo [WIKI] {Wiki} +\logo [WINDOWS] {Windows} +\logo [WINNT] {WinNT} +\logo [WINNX] {Win9x} +\logo [WWW] {www} +\logo [WTHREEC] {W3C} +\logo [WYSIWYG] {wysiwyg} +\logo [XDVI] {Xdvi} +\logo [XETEX] {\XeTeX} +\logo [XFDF] {xfdf} +\logo [XHTML] {xhtml} +\logo [XINDY] {Xindy} +\logo [XML] {xml} +\logo [XPATH] {xpath} +\logo [XMLTOOLS] {xmltools} +\logo [XPDFETEX] {xpdfe\TeX} +\logo [XSL] {xsl} +\logo [XSLFO] {xsl-fo} +\logo [XSLT] {xslt} +\logo [XSLTPROC] {xsltproc} +\logo [XYPIC] {XYPIC} % wrong logo +\logo [YandY] {y\&y} +\logo [ZIP] {zip} \def\METAFUN {\MetaFun} diff --git a/tex/context/base/s-art-01.mkiv b/tex/context/base/s-art-01.mkiv index 10b4de9ab..c8d849d8c 100644 --- a/tex/context/base/s-art-01.mkiv +++ b/tex/context/base/s-art-01.mkiv @@ -2,6 +2,8 @@ % \showframe +\unprotect + \setuplayout [\c!topspace=2cm, \c!bottomspace=2.5cm, @@ -33,4 +35,6 @@ [\c!style=\bf, \c!after=] +\protect + \stopmodule diff --git a/tex/context/base/s-def-01.mkiv b/tex/context/base/s-def-01.mkiv index 1c8ee9469..49e585bd0 100644 --- a/tex/context/base/s-def-01.mkiv +++ b/tex/context/base/s-def-01.mkiv @@ -4,7 +4,7 @@ \startsetups defaults:frontpart:pagenumbers:roman \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals] - \setupuserpagenumber[\c!way=\v!byblock] + \setupuserpagenumber[\c!way=\v!by\v!block] \stopsetups \protect diff --git a/tex/context/base/s-fnt-10.mkiv b/tex/context/base/s-fnt-10.mkiv index 0d4a608a4..0edb19120 100644 --- a/tex/context/base/s-fnt-10.mkiv +++ b/tex/context/base/s-fnt-10.mkiv @@ -135,7 +135,7 @@ end \page \egroup} -\doifnotmode{demo} {\endinput} +\continueifinputfile{s-fnt-10.mkiv} \starttext diff --git a/tex/context/base/s-fnt-20.mkiv b/tex/context/base/s-fnt-20.mkiv index a78f62555..54ed419c0 100644 --- a/tex/context/base/s-fnt-20.mkiv +++ b/tex/context/base/s-fnt-20.mkiv @@ -85,10 +85,10 @@ rlig=yes,liga=yes,dlig=yes, mark=yes,mkmk=yes,kern=yes,curs=yes] -\setvalue{otftracker-direction-arabtype}{-1} -\setvalue{otftracker-direction-husayni}{-1} -\setvalue{otftracker-direction-simplenaskhi}{-1} -\setvalue{otftracker-direction-default}{0} +\setvalue{otftracker-direction-arabtype}{r2l} +\setvalue{otftracker-direction-husayni}{r2l} +\setvalue{otftracker-direction-simplenaskhi}{r2l} +\setvalue{otftracker-direction-default}{} \setvariables [otftracker] @@ -129,7 +129,7 @@ \chapter{\getvariable{otftracker}{title}} \doifsomething {\getvariable{otftracker}{figure}} { \startlinecorrection - \externalfigure[\getvariable{otftracker}{figure}] + \externalfigure[\getvariable{otftracker}{figure}][maxwidth=\hsize,frame=on] \stoplinecorrection } \showotfcomposition diff --git a/tex/context/base/s-fnt-28.mkiv b/tex/context/base/s-fnt-28.mkiv index 039cc6ca8..778a4c390 100644 --- a/tex/context/base/s-fnt-28.mkiv +++ b/tex/context/base/s-fnt-28.mkiv @@ -35,7 +35,7 @@ end \stopluacode -\doifnotmode{demo}{\endinput} +\continueifinputfile{s-fnt-28.mkiv} \starttext diff --git a/tex/context/base/s-fnt-29.mkiv b/tex/context/base/s-fnt-29.mkiv index 0378550e8..f9e0a1658 100644 --- a/tex/context/base/s-fnt-29.mkiv +++ b/tex/context/base/s-fnt-29.mkiv @@ -48,7 +48,7 @@ \stopluacode -\doifnotmode{demo}{\endinput} +\continueifinputfile{s-fnt-29.mkiv} \setupbodyfont[dejavu,tt,9pt] diff --git a/tex/context/base/s-fnt-32.mkiv b/tex/context/base/s-fnt-32.mkiv index 5ffbb2ac5..20a939a97 100644 --- a/tex/context/base/s-fnt-32.mkiv +++ b/tex/context/base/s-fnt-32.mkiv @@ -30,7 +30,7 @@ end \stopluacode -\doifnotmode{demo}{\endinput} +\continueifinputfile{s-fnt-32.mkiv} \setupbodyfont[dejavu,10pt] diff --git a/tex/context/base/s-inf-01.mkvi b/tex/context/base/s-inf-01.mkvi index 51d3cbac8..b3f44e908 100644 --- a/tex/context/base/s-inf-01.mkvi +++ b/tex/context/base/s-inf-01.mkvi @@ -226,7 +226,7 @@ \stopTEXpage \stoptexdefinition -% \doifnotmode{demo}{\endinput} +% \continueifinputfile{s-inf-01.mkvi} \starttext \Show diff --git a/tex/context/base/s-inf-03.mkiv b/tex/context/base/s-inf-03.mkiv index 1ff4cd0d0..e2428ce5e 100644 --- a/tex/context/base/s-inf-03.mkiv +++ b/tex/context/base/s-inf-03.mkiv @@ -1,6 +1,12 @@ % \nopdfcompression -\enablemode[ipad] +% \starttext +% There is a loop somewhere ... todo. +% \stoptext + +\enablemode[ipad] % whatever that means + +\setupbodyfont[dejavu] \doifmodeelse {ipad} { @@ -10,16 +16,16 @@ \definefont [TitlePageFont] - [MonoBold at 18pt] + [MonoBold at 16pt] \setupbodyfont - [tt,10pt] + [tt,8pt] } { \definefont [TitlePageFont] - [MonoBold at 24pt] + [MonoBold at 20pt] \setupbodyfont [tt] @@ -231,7 +237,6 @@ end local function handler(k,t,depth) k = gsub(k,"([~#$%%^&{}\\\|])",cleanup) --- NC() rlap("\\quad\\tx " .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR() NC() rlap("\\quad\\tx\\kern" .. (depth or 0).. "em" .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR() end @@ -260,67 +265,65 @@ local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mar for i=1,#keys do local k = keys[i] local v = t[k] - if k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then + if k and k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then local inlib = lib and lib[k] local inglo = glo and glo[k] - if k then - local t = type(v) - local kstr, tstr = k, t - local obs = t_obsolete and t_obsolete[k] - if obs then - tstr = function() overstrike(t) end - kstr = function() overstrike(k) end - end - local marked = marked(v) - if marked then - tstr = "data table" - end - if t == "table" then - local m = getmetatable(v) - if m and m.__call then - tstr = "function" - end - end - if not mark then - -- - elseif inlib and tostring(inlib) ~= tostring(v) then - tstr = "overloaded ".. tstr - elseif inglo and tostring(inglo) ~= tostring(v) then - tstr = "overloaded ".. tstr + local t = type(v) + local kstr, tstr = k, t + local obs = t_obsolete and t_obsolete[k] + if obs then + tstr = function() overstrike(t) end + kstr = function() overstrike(k) end + end + local marked = marked(v) + if marked then + tstr = "data table" + end + if t == "table" then + local m = getmetatable(v) + if m and m.__call then + tstr = "function" end - NC() bf() - if inlib then - if not mark and t == "table" then - goto(function() color( { libcolor }, kstr) end, { k } ) - else - color( { libcolor }, kstr) - end - elseif inglo then - if not mark and t == "table" then - goto(function() color( { glocolor }, kstr) end, { k } ) - else - color( { glocolor }, kstr) - end + end + if not mark then + -- + elseif inlib and tostring(inlib) ~= tostring(v) then + tstr = "overloaded ".. tstr + elseif inglo and tostring(inglo) ~= tostring(v) then + tstr = "overloaded ".. tstr + end + NC() bf() + if inlib then + if not mark and t == "table" then + goto(function() color( { libcolor }, kstr) end, { k } ) else - if not mark and t == "table" then - goto(k, { kstr } ) - else - context(kstr) - end + color( { libcolor }, kstr) end - NC() - if inlib then - color( { libcolor }, tstr) - elseif inglo then - color( { glocolor }, tstr) + elseif inglo then + if not mark and t == "table" then + goto(function() color( { glocolor }, kstr) end, { k } ) else - context(tstr) + color( { glocolor }, kstr) end - NC() NR() - if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then - childtables(false,v,handler) -- (k,v,handler) + else + if not mark and t == "table" then + goto(k, { kstr } ) + else + context(kstr) end end + NC() + if inlib then + color( { libcolor }, tstr) + elseif inglo then + color( { glocolor }, tstr) + else + context(tstr) + end + NC() NR() + if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then + childtables(false,v,handler) -- (k,v,handler) + end end end context.stoptabulate() diff --git a/tex/context/base/s-lan-04.mkiv b/tex/context/base/s-lan-04.mkiv index 80283bfd4..c04be9466 100644 --- a/tex/context/base/s-lan-04.mkiv +++ b/tex/context/base/s-lan-04.mkiv @@ -138,7 +138,7 @@ \definecolor[hyphenation:de] [g=.8] \definecolor[hyphenation:nl] [b=.8] -\doifnotmode{demo}{\endinput} +\continueifinputfile{s-lan-04.mkiv} \starttext diff --git a/tex/context/base/s-mod.ctx b/tex/context/base/s-mod.ctx index 5059c77d4..09ecf714c 100644 --- a/tex/context/base/s-mod.ctx +++ b/tex/context/base/s-mod.ctx @@ -11,7 +11,6 @@ </ctx:files> </ctx:preprocess> <ctx:flags> - <!-- ctx:flag>purge</ctx:flag --> <ctx:flag>global</ctx:flag> <ctx:flag>prep</ctx:flag> <ctx:flag>purge</ctx:flag> diff --git a/tex/context/base/s-pre-60.mkiv b/tex/context/base/s-pre-60.mkiv index b39a06311..70f8978b0 100644 --- a/tex/context/base/s-pre-60.mkiv +++ b/tex/context/base/s-pre-60.mkiv @@ -13,6 +13,8 @@ % use lua instead of global mess +\unprotect + \startmode[paper,print] \let\StartSteps\relax \let\StopSteps \relax @@ -23,22 +25,31 @@ \endinput \stopmode -\newcounter\StepCounter -\newcounter\StepMaximum +\newcount\c_module_pre_steps_current +\newcount\c_module_pre_steps_maximum +\newcount\c_module_pre_steps_nesting_step +\newcount\c_module_pre_steps_nesting_steps +\newcount\c_module_pre_steps_nesting_busy + +\def\StepCounter {\the\c_module_pre_steps_current} +\def\StepMaximum {\the\c_module_pre_steps_maximum} +\def\StepLayer {step:\the\c_module_pre_steps_current} +\def\NextStepLayer {step:\the\numexpr\c_module_pre_steps_current+\plusone\relax} +\def\FirstStepLayer{step:1} \useJSscripts[stp] \startsetups[set-stepper] - \ifnum\getvariable{stepper}{nofsteps}>\StepMaximum + \ifnum\getvariable{stepper}{nofsteps}>\c_module_pre_steps_maximum - \dostepwiserecurse {\numexpr\StepMaximum+1\relax} {\getvariable{stepper}{nofsteps}} {1} { + \dostepwiserecurse {\numexpr\c_module_pre_steps_maximum+\plusone\relax} {\getvariable{stepper}{nofsteps}} {1} { \doifnotmode{nosteps,nostep} { \expanded{\defineviewerlayer[step:\recurselevel][state=stop,scope=global]} } } - \xdef\StepMaximum{\getvariable{stepper}{nofsteps}} + \global\c_module_pre_steps_maximum\getvariable{stepper}{nofsteps}\relax \fi @@ -58,25 +69,100 @@ % todo: roll back blank -\def\ResetStep {\doglobal\newcounter\StepCounter} -\def\NextStep {\doglobal\increment \StepCounter} -\def\PrevStep {\doglobal\decrement \StepCounter} +\unexpanded\def\ResetStep + {\iftrialtypesetting\else + \global\c_module_pre_steps_current\zerocount + \fi} + +\unexpanded\def\NextStep + {\iftrialtypesetting\else + \global\advance\c_module_pre_steps_current\plusone + \fi} + +\unexpanded\def\PrevStep + {\iftrialtypesetting\else + \global\advance\c_module_pre_steps_current\minusone + \fi} + +\unexpanded\def\FlushStep + {\iftrialtypesetting\else + \StopStep + \NextStep + \StartStep + \fi} + +\unexpanded\def\StartStep + {\iftrialtypesetting\else + \global\advance\c_module_pre_steps_nesting_step\plusone + \ifcase\c_module_pre_steps_nesting_step\or + \startviewerlayer[\StepLayer]% + \fi + \fi + \ignorespaces} + +\unexpanded\def\StopStep + {\removeunwantedspaces + \iftrialtypesetting\else + \ifcase\c_module_pre_steps_nesting_step\or + \stopviewerlayer + \fi + \global\advance\c_module_pre_steps_nesting_step\minusone + \fi} + +\unexpanded\def\StartSteps + {\iftrialtypesetting\else + \global\advance\c_module_pre_steps_nesting_steps\plusone + \ifcase\c_module_pre_steps_nesting_steps\or + \ResetStep + \NextStep + \StartStep + \fi + \fi} + +\unexpanded\def\StopSteps + {\iftrialtypesetting\else + \ifcase\c_module_pre_steps_nesting_steps\or + \StopStep + \PrevStep + \fi + \global\advance\c_module_pre_steps_nesting_steps\minusone + \fi} + +\unexpanded\def\StartBusy + {\iftrialtypesetting\else + \global\advance\c_module_pre_steps_nesting_busy\plusone + \ifcase\c_module_pre_steps_nesting_busy\or + \startviewerlayer[step:busy] + \fi + \fi + \ignorespaces} + +\unexpanded\def\StopBusy + {\removeunwantedspaces + \iftrialtypesetting\else + \ifcase\c_module_pre_steps_nesting_busy\or + \stopviewerlayer + \fi + \global\advance\c_module_pre_steps_nesting_busy\minusone + \fi} -\def\StepLayer {step:\StepCounter} -\def\NextStepLayer {step:\the\numexpr\StepCounter+1\relax} -\def\FirstStepLayer{step:1} +%D Handy: + +\unexpanded\def\StartLocalSteps + {\ResetStep} -\def\StartStep {\startviewerlayer[\StepLayer]\ignorespaces} -\def\StopStep {\removeunwantedspaces\stopviewerlayer} -\def\StartSteps {\iftrialtypesetting\else\ResetStep\NextStep\StartStep\fi} -\def\StopSteps {\iftrialtypesetting\else\StopStep \PrevStep \fi} -\def\FlushStep {\iftrialtypesetting\else\StopStep \NextStep\StartStep\fi} +\unexpanded\def\StopLocalSteps + {} -\def\StartBusy {\startviewerlayer[step:busy]\ignorespaces} -\def\StopBusy {\removeunwantedspaces\stopviewerlayer} +\unexpanded\def\StartLocalStep + {\NextStep + \StartStep} + +\unexpanded\def\StopLocalStep + {\StopStep} \appendtoks - \ResetStep + \ResetStep \to \everyaftershipout \setupinteraction @@ -112,14 +198,6 @@ [symbol={attach-normal,attach-down}, textlayer=\StepLayer] -%D Handy: - -\def\StartLocalSteps{\ResetStep} -\def\StopLocalSteps {} - -\def\StartLocalStep {\NextStep\StartStep} -\def\StopLocalStep {\StopStep} - %D used as (given some definitions): %D %D \starttyping @@ -131,4 +209,4 @@ %D \StopLocalSteps %D \stoptyping -\endinput +\protect \endinput diff --git a/tex/context/base/s-pre-61.tex b/tex/context/base/s-pre-61.tex index 21e461320..ea221fbcb 100644 --- a/tex/context/base/s-pre-61.tex +++ b/tex/context/base/s-pre-61.tex @@ -16,7 +16,7 @@ \usemodule[pre-60] \doifmodeelse {mkiv} { - \usetypescriptfile[type-hgz] + \usetypescriptfile[ghz] \definetypeface[mainface][ss][sans][optima-nova][default] } { \usetypescriptfile[type-ghz] diff --git a/tex/context/base/s-pre-62.tex b/tex/context/base/s-pre-62.tex index cc9762e12..a1a405c23 100644 --- a/tex/context/base/s-pre-62.tex +++ b/tex/context/base/s-pre-62.tex @@ -220,5 +220,5 @@ \long\def\StartTitlePage #1\StopTitlePage {\TitlePage {#1}} \long\def\StartSubTitlePage#1\StopSubTitlePage{\SubTitlePage{#1}} -\doifnotmode{demo} {\endinput} +\endinput diff --git a/tex/context/base/s-pre-63.tex b/tex/context/base/s-pre-63.tex index 0535fc1d0..974c67a5f 100644 --- a/tex/context/base/s-pre-63.tex +++ b/tex/context/base/s-pre-63.tex @@ -67,6 +67,7 @@ this module is under reconstruction \setupbodyfont[8pt] \definefont[BigFont][Normal sa 4] \starttext + \StartPage \StartPair \StartLeft ZAPF \StopLeft \StartRight \input zapf \StopRight \StopPair \StartPair \StartLeft DAVIS \StopLeft \StartRight \input davis \StopRight \StopPair diff --git a/tex/context/base/s-pre-67.tex b/tex/context/base/s-pre-67.tex index 88043aa24..84ea1a66c 100644 --- a/tex/context/base/s-pre-67.tex +++ b/tex/context/base/s-pre-67.tex @@ -119,7 +119,7 @@ \setupwhitespace [big] -\def\MyCommand#1#2% +\unexpanded\def\MyCommand#1#2% {\setlayer[title][preset=rightbottom,x=.75cm,y=.5cm]{#2}} \def\titlepage#1#2% diff --git a/tex/context/base/s-pre-69.mkiv b/tex/context/base/s-pre-69.mkiv index c87bcd537..cc6af9ad3 100644 --- a/tex/context/base/s-pre-69.mkiv +++ b/tex/context/base/s-pre-69.mkiv @@ -311,7 +311,7 @@ \setelementexporttag[paragraphs][nature][display] \setelementexporttag[paragraph] [nature][mixed] -\doifnotmode{demo}{\endinput} +\continueifinputfile{s-pre-69.mkiv} % finetuning: \StartText{\TEX\ and Reality\vskip2exClashing Mindsets?\vskip1ex}{Bacho\TEX, May 1, 2010} diff --git a/tex/context/base/scrn-fld.lua b/tex/context/base/scrn-fld.lua index 275fb4a9b..9836cbebe 100644 --- a/tex/context/base/scrn-fld.lua +++ b/tex/context/base/scrn-fld.lua @@ -73,13 +73,13 @@ function commands.setformsmethod(method) end function commands.doiffieldcategoryelse(name) - commands.testcase(codeinjections.validfieldcategory(name)) + commands.doifelse(codeinjections.validfieldcategory(name)) end function commands.doiffieldsetelse(tag) - commands.testcase(codeinjections.validfieldset(name)) + commands.doifelse(codeinjections.validfieldset(name)) end function commands.doiffieldelse(name) - commands.testcase(codeinjections.validfield(name)) + commands.doifelse(codeinjections.validfield(name)) end diff --git a/tex/context/base/scrn-fld.mkvi b/tex/context/base/scrn-fld.mkvi index 872099099..a811c6481 100644 --- a/tex/context/base/scrn-fld.mkvi +++ b/tex/context/base/scrn-fld.mkvi @@ -403,7 +403,7 @@ \setupfieldcontentframed [\c!align=\v!flushleft, \c!strut=\v!no, - \s!parent=\??ol] % needs checking + \s!parent=\??regularframed] % needs checking \setupfieldcontentframed % independent [\c!alternative=\v!normal, @@ -419,13 +419,13 @@ [\c!style=, \c!color=, \c!align=\v!flushleft, - \s!parent=\??ol] % needs checking + \s!parent=\??regularframed] % needs checking \setupfieldtotalframed [%\c!alternative={\v!label,\v!frame,\v!horizontal}, \c!strut=\v!no, \c!align=, - \s!parent=\??ol] % needs checking + \s!parent=\??regularframed] % needs checking % \setupcurrent @@ -616,9 +616,9 @@ \v!horizontal=>\settrue\fieldishorizontal, \v!vertical=>\settrue\fieldisvertical]% \ifconditional\fieldisvertical - \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\@@localoffset,\c!align=\v!right,\c!width=20em]% + \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\d_framed_local_offset,\c!align=\v!right,\c!width=20em]% \else\ifconditional\fieldishorizontal - \setupfieldtotalframed[\c!distance=\@@localoffset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]% + \setupfieldtotalframed[\c!distance=\d_framed_local_offset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]% \else \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=,\c!align=\c!left]% \fi\fi diff --git a/tex/context/base/scrn-ini.lua b/tex/context/base/scrn-ini.lua index 2836362df..8fe1e0cae 100644 --- a/tex/context/base/scrn-ini.lua +++ b/tex/context/base/scrn-ini.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['scrn-int'] = { +if not modules then modules = { } end modules ['scrn-ini'] = { version = 1.001, comment = "companion to scrn-int.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/scrn-ini.mkvi b/tex/context/base/scrn-ini.mkvi index daf0a1b91..a6cb495ee 100644 --- a/tex/context/base/scrn-ini.mkvi +++ b/tex/context/base/scrn-ini.mkvi @@ -144,16 +144,16 @@ \useinteractionstyleandcolor\c!style\c!color \fi} -\unexpanded\def\setlocationcolorspec#1#2% \resolver +\unexpanded\def\setlocationcolorspecspecified#1#2% \resolver {\ifnum#1=\plusone \edef\askedcontrastcolor{#2\c!contrastcolor}% \ifx\askedcontrastcolor\empty - \doactivatecolor{#2\c!color}% + \colo_helpers_activate{#2\c!color}% \else - \doactivatecolor\askedcontrastcolor + \colo_helpers_activate\askedcontrastcolor \fi \else - \doactivatecolor{#2\c!color}% + \colo_helpers_activate{#2\c!color}% \fi} \unexpanded\def\setlocationcolor {\setlocationcolorspecified \referencepagestate} @@ -184,9 +184,11 @@ \scrn_identity_synchronize \to \everysetupinteraction +% this comes before starttext + \appendtoks % not interfaced i.e. english - \doifvariable{document}{metadata:author}{\setupinteraction[author=\documentvariable{metadata:author}]}% - \doifvariable{document}{metadata:title}{\setupinteraction[title=\documentvariable{metadata:title}]}% + \doifvariable{document}{metadata:author} {\setupinteraction [author=\documentvariable{metadata:author}]}% + \doifvariable{document}{metadata:title} {\setupinteraction [title=\documentvariable{metadata:title}]}% \doifvariable{document}{metadata:subject}{\setupinteraction[subject=\documentvariable{metadata:subject}]}% \to \everysetupdocument diff --git a/tex/context/base/scrn-pag.mkvi b/tex/context/base/scrn-pag.mkvi index 66f197ffd..5bbdadda8 100644 --- a/tex/context/base/scrn-pag.mkvi +++ b/tex/context/base/scrn-pag.mkvi @@ -150,12 +150,6 @@ {\global\setfalse\c_scrn_canvas_tight_page}% \to \everysetupinteractionscreen -\appendtoks - \doifelse\@@pcstate\v!start - \scrn_canvas_synchronize_simple - \scrn_canvas_synchronize_complex -\to \everyshipout - \setupinteractionscreen [\c!width=\printpaperwidth, \c!height=\printpaperheight, diff --git a/tex/context/base/scrn-ref.lua b/tex/context/base/scrn-ref.lua index 0b1dff2c1..df71b6a97 100644 --- a/tex/context/base/scrn-ref.lua +++ b/tex/context/base/scrn-ref.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['scrn-int'] = { +if not modules then modules = { } end modules ['scrn-ref'] = { version = 1.001, comment = "companion to scrn-int.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/scrn-wid.lua b/tex/context/base/scrn-wid.lua index 6fdc4fca0..14d58a29a 100644 --- a/tex/context/base/scrn-wid.lua +++ b/tex/context/base/scrn-wid.lua @@ -167,11 +167,19 @@ function renderings.rendering(label) end end -function renderings.var(label,key) +local function var(label,key) local rn = renderings[label] - context(rn and rn[key] or "") + return rn and rn[key] or "" end +renderings.var = var + +function commands.renderingvar(label,key) + context(var(label,key)) +end + +commands.registerrendering = renderings.register + -- Rendering: function commands.insertrenderingwindow(specification) diff --git a/tex/context/base/scrn-wid.mkvi b/tex/context/base/scrn-wid.mkvi index 2b75f83cd..9b3f0cb78 100644 --- a/tex/context/base/scrn-wid.mkvi +++ b/tex/context/base/scrn-wid.mkvi @@ -421,7 +421,7 @@ \doifassignmentelse{#title} {\setupcurrentcomment[#title]} {\setupcurrentcomment[\c!title=#title,#settings]}% - \def\scrn_comment_stop{\scrn_comment_inject\egroup}% + \unexpanded\def\scrn_comment_stop{\scrn_comment_inject\egroup}% \grabbufferdatadirect\v!comment{\e!start\currentcomment}{\e!stop\currentcomment}} \def\scrn_comment_start_ignore @@ -432,7 +432,7 @@ \installcorenamespace{commentmethods} -\def\scrn_comment_inject +\unexpanded\def\scrn_comment_inject {\expandcheckedcsname\??commentmethods{\commentparameter\c!method}\v!normal} %D Beware: comments symbols don't scale in acrobat (cf. spec but somewhat @@ -476,35 +476,34 @@ \wd\b_scrn_comment_link\currentcommentwidth \ht\b_scrn_comment_link\currentcommentheight \dp\b_scrn_comment_link\currentcommentdepth - \scrn_comment_place} + \expandcheckedcsname\??commentlocation{\commentparameter\c!location}\s!unknown} \setvalue{\??commentmethods\v!hidden}% {} % todo: dedicated margin classes -\def\scrn_comment_place - {\executeifdefined - {\??commentlocation\commentparameter\c!location}\hbox - {\hbox{\box\b_scrn_comment_link}}} - -\setvalue{\??commentlocation\v!inmargin }{\inmargin } -\setvalue{\??commentlocation\v!leftedge }{\inleftedge } -\setvalue{\??commentlocation\v!rightedge }{\inrightedge } -\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin } -\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin} -\setvalue{\??commentlocation\v!high }{\high} -\setvalue{\??commentlocation\v!none }{\scrn_comment_collect} - -\def\scrn_comment_collect#content% +\setvalue{\??commentlocation\v!inmargin }{\inmargin {\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!high }{\high {\box\b_scrn_comment_link}} + +\setvalue{\??commentlocation\v!none}% {\global\setbox\b_scrn_comment_collect\hbox\bgroup \ifvoid\b_scrn_comment_collect\else \box\b_scrn_comment_collect \hskip\commentparameter\c!distance \fi - #content% + \box\b_scrn_comment_link \egroup} +\setvalue{\??commentlocation\s!unknown}% + {\ifvoid\b_scrn_comment_collect\else + \box\b_scrn_comment_collect + \fi} + \unexpanded\def\placecomments {\ifvoid\b_scrn_comment_collect\else \box\b_scrn_comment_collect @@ -529,6 +528,13 @@ %D Todo: like external figures, also search on path, %D although, they need to be present ar viewing time, so ... +\installcorenamespace{externalsoundtracks} + +\installsetuponlycommandhandler \??externalsoundtracks {externalsoundtracks} + +\setupexternalsoundtracks + [\c!option=] + \unexpanded\def\useexternalsoundtrack {\dodoubleargument\scrn_soundtrack_indeed} @@ -541,17 +547,11 @@ \def\checksoundtrack#tag% yet untested in mkiv (also move management to lua) {\iflocation \ctxcommand{insertsoundclip{ - tag = "#tag", - repeat = "\@@sdoption", % not entirely ok but works + tag = "#tag", + ["repeat"] = "\directexternalsoundtrackparameter\c!option", % todo: pass option as-is }}% \fi} -\unexpanded\def\setupexternalsoundtracks - {\dodoubleargument\getparameters[\??sd]} - -\setupexternalsoundtracks - [\c!option=] - %D Renderings (not yet tested in mkvi): % Todo: multiple instances and inheritance .. will be done when @@ -568,7 +568,7 @@ \def\setinternalrendering{\dodoubleempty \scrn_rendering_set} \def\scrn_rendering_use[#tag][#mime][#file][#option]% - {\ctxlua{interactions.renderings.register { + {\ctxcommand{registerrendering{ type = "external", label = "#tag", mime = "#mime", @@ -579,7 +579,7 @@ \def\scrn_rendering_set[#tag][#option]% {content} {\bgroup \dowithnextbox - {\ctxlua{interactions.renderings.register { + {\ctxcommand{registerrendering{ type = "internal", label = "#tag", mime = "IRO", % brrr @@ -591,28 +591,24 @@ \egroup}% \hbox} -\def\renderingtype #tag{\ctxlua{interactions.renderings.var("#tag","type")}} -\def\renderingoption#tag{\ctxlua{interactions.renderings.var("#tag","option")}} +\def\renderingtype #tag{\ctxcommand{renderingvar("#tag","type")}} +\def\renderingoption#tag{\ctxcommand{renderingvar("#tag","option")}} -\def\renderingwidth {8cm} % will become private -\def\renderingheight{6cm} % will become private +\newdimen\d_scrn_rendering_width \d_scrn_rendering_width 8cm +\newdimen\d_scrn_rendering_height \d_scrn_rendering_height 6cm -\unexpanded\def\definerenderingwindow - {\dodoubleempty\scrn_rendering_define_window} +\let\m_scrn_rendering_page\!!zerocount -\def\scrn_rendering_define_window[#tag][#settings]% - {\presetlocalframed[\??rw#tag]% - \getparameters - [\??rw#tag]% - [\c!openpageaction=,\c!closepageaction=,% - \c!width=\renderingwidth,\c!height=\renderingheight,% - #settings]} +\installcorenamespace{renderingwindow} -\unexpanded\def\setuprenderingwindow - {\dodoubleargument\scrn_rendering_setup_window} +\installframedcommandhandler \??renderingwindow {renderingwindow} \??renderingwindow -\def\scrn_rendering_setup_window[#tag]% - {\getparameters[\??rw#tag]} +\appendtoks + \letrenderingwindowparameter\c!openpageaction \empty + \letrenderingwindowparameter\c!closepageaction\empty + \setrenderingwindowparameter\c!width {\d_scrn_rendering_width }% + \setrenderingwindowparameter\c!height {\d_scrn_rendering_height}% +\to \everypresetrenderingwindow \unexpanded\def\placerenderingwindow {\dodoubleempty\scrn_rendering_place_window} @@ -622,31 +618,32 @@ \edef\currentrendering{\ifsecondargument#rendering\else#window\fi}% \doifelse{\renderingtype\currentrendering}{internal} % an object {\getobjectdimensions{IRO}\currentrendering - \edef\renderingheight{\the\dimexpr\objectheight+\objectdepth\relax}% - \edef\renderingwidth{\objectwidth}% - \dogetobjectreferencepage{IRO}\currentrendering\renderingpage}% - {\def\renderingheight{\vsize}% - \def\renderingwidth{\hsize}% - \def\renderingpage{\realpageno}}% + \d_scrn_rendering_height\dimexpr\objectheight+\objectdepth\relax + \d_scrn_rendering_width\objectwidth\relax + \dogetobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page}% + {\d_scrn_rendering_height\vsize + \d_scrn_rendering_width\hsize + \let\m_scrn_rendering_page\realpageno}% % create fall back if needed - \ifcsname\??rw#window\c!width\endcsname - \def\currentrenderingwindow{#window}% - \else + \edef\currentrenderingwindow{\namedrenderingwindowparameter{#window}\c!width}% stupid test, we need a proper one here + \ifx\currentrenderingwindow\empty \let\currentrenderingwindow\s!default - \definerenderingwindow[\currentrenderingwindow]% + \definerenderingwindow[\currentrenderingwindow]% why not global + \else + \edef\currentrenderingwindow{#window}% \fi -% todo -% \handlereferenceactions{\getvalue{\??rw\currentrenderingwindow\c!openpageaction }}\dosetuprenderingopenpageaction -% \handlereferenceactions{\getvalue{\??rw\currentrenderingwindow\c!closepageaction}}\dosetuprenderingclosepageaction - \localframed - [\??rw\currentrenderingwindow][\c!offset=\v!overlay]% + % todo: + % \handlereferenceactions{\renderingwindowparameter\c!openpageaction }\dosetuprenderingopenpageaction + % \handlereferenceactions{\renderingwindowparameter\c!closepageaction}\dosetuprenderingclosepageaction + \letrenderingwindowparameter\c!offset\v!overlay + \inheritedrenderingwindowframed {\vfill \ctxcommand{insertrenderingwindow { label = "\currentrendering", - width = \number\dimexpr\renderingwidth\relax, - height = \number\dimexpr\renderingheight\relax, + width = \number\d_scrn_rendering_width, + height = \number\d_scrn_rendering_height, option = "\renderingoption\currentrendering", - page = \number\renderingpage, + page = \number\m_scrn_rendering_page, }}\hfill}% \egroup} @@ -662,6 +659,8 @@ % %D \dorecurse{10}{\linkedlistelement[demo]{link \recurselevel} \page} % %D \stoptyping % +% \definesystemvariable {lk} % LinK +% % \installcommandhandler\??lk{linkedlist}\??lk % % \let\setupbutton\setuplinkedlists\setuplinkedlist diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua index 3463a8eb5..ab09ce9c8 100644 --- a/tex/context/base/scrp-cjk.lua +++ b/tex/context/base/scrp-cjk.lua @@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['scrp-cjk'] = { license = "see context related readme files" } +-- We can speed this up by preallocating nodes and copying them but the +-- gain is not that large. + local utfchar = utf.char local has_attribute = node.has_attribute diff --git a/tex/context/base/scrp-ini.lua b/tex/context/base/scrp-ini.lua index e55dc0780..9b0e9fc21 100644 --- a/tex/context/base/scrp-ini.lua +++ b/tex/context/base/scrp-ini.lua @@ -47,142 +47,152 @@ local hash = scripts.hash local handlers = allocate() scripts.handlers = handlers -storage.register("scripts/hash", hash, "scripts.hash") - -if not next(hash) then -- this might move to char-def - - hash = { -- no local - -- - -- half width opening parenthesis - [0x0028] = "half_width_open", - [0x005B] = "half_width_open", - [0x007B] = "half_width_open", - [0x2018] = "half_width_open", -- ‘ - [0x201C] = "half_width_open", -- “ - -- - -- full width opening parenthesis - -- - [0x3008] = "full_width_open", -- 〈 Left book quote - [0x300A] = "full_width_open", -- 《 Left double book quote - [0x300C] = "full_width_open", -- 「 left quote - [0x300E] = "full_width_open", -- 『 left double quote - [0x3010] = "full_width_open", -- 【 left double book quote - [0x3014] = "full_width_open", -- 〔 left book quote - [0x3016] = "full_width_open", --〖 left double book quote - [0x3018] = "full_width_open", -- left tortoise bracket - [0x301A] = "full_width_open", -- left square bracket - [0x301D] = "full_width_open", -- reverse double prime qm - [0xFF08] = "full_width_open", -- ( left parenthesis - [0xFF3B] = "full_width_open", -- [ left square brackets - [0xFF5B] = "full_width_open", -- { left curve bracket - -- - -- half width closing parenthesis - [0x0029] = "half_width_close", - [0x005D] = "half_width_close", - [0x007D] = "half_width_close", - [0x2019] = "half_width_close", -- ’ right quote, right - [0x201D] = "half_width_close", -- ” right double quote - -- - -- full width closing parenthesis - -- - [0x3009] = "full_width_close", -- 〉 book quote - [0x300B] = "full_width_close", -- 》 double book quote - [0x300D] = "full_width_close", -- 」 right quote, right - [0x300F] = "full_width_close", -- 』 right double quote - [0x3011] = "full_width_close", -- 】 right double book quote - [0x3015] = "full_width_close", -- 〕 right book quote - [0x3017] = "full_width_close", -- 〗 right double book quote - [0x3019] = "full_width_close", -- right tortoise bracket - [0x301B] = "full_width_close", -- right square bracket - [0x301E] = "full_width_close", -- double prime qm - [0x301F] = "full_width_close", -- low double prime qm - [0xFF09] = "full_width_close", -- ) right parenthesis - [0xFF3D] = "full_width_close", -- ] right square brackets - [0xFF5D] = "full_width_close", -- } right curve brackets - - [0xFF62] = "half_width_open", -- left corner bracket - [0xFF63] = "half_width_close", -- right corner bracket - -- - -- vertical opening vertical - -- - -- 0xFE35, 0xFE37, 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47, - -- - -- vertical closing - -- - -- 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42, 0xFE44, 0xFE48, - -- - -- half width opening punctuation - -- - -- <empty> - -- - -- full width opening punctuation - -- - -- 0x2236, -- ∶ - -- 0xFF0C, -- , - -- - -- half width closing punctuation_hw - -- - [0x0021] = "half_width_close", -- ! - [0x002C] = "half_width_close", -- , - [0x002E] = "half_width_close", -- . - [0x003A] = "half_width_close", -- : - [0x003B] = "half_width_close", -- ; - [0x003F] = "half_width_close", -- ? - [0xFF61] = "half_width_close", -- hw full stop - -- - -- full width closing punctuation - [0x3001] = "full_width_close", -- 、 - [0x3002] = "full_width_close", -- 。 - [0xFF0C] = "full_width_close", -- , - [0xFF0E] = "full_width_close", -- . - -- depends on font - [0xFF01] = "full_width_close", -- ! - [0xFF1F] = "full_width_close", -- ? - -- - [0xFF1A] = "full_width_punct", -- : - [0xFF1B] = "full_width_punct", -- ; - -- non starter - -- - [0x3005] = "non_starter", [0x3041] = "non_starter", [0x3043] = "non_starter", [0x3045] = "non_starter", [0x3047] = "non_starter", - [0x3049] = "non_starter", [0x3063] = "non_starter", [0x3083] = "non_starter", [0x3085] = "non_starter", [0x3087] = "non_starter", - [0x308E] = "non_starter", [0x3095] = "non_starter", [0x3096] = "non_starter", [0x309B] = "non_starter", [0x309C] = "non_starter", - [0x309D] = "non_starter", [0x309E] = "non_starter", [0x30A0] = "non_starter", [0x30A1] = "non_starter", [0x30A3] = "non_starter", - [0x30A5] = "non_starter", [0x30A7] = "non_starter", [0x30A9] = "non_starter", [0x30C3] = "non_starter", [0x30E3] = "non_starter", - [0x30E5] = "non_starter", [0x30E7] = "non_starter", [0x30EE] = "non_starter", [0x30F5] = "non_starter", [0x30F6] = "non_starter", - [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31F0] = "non_starter", [0x31F1] = "non_starter", - [0x30F2] = "non_starter", [0x30F3] = "non_starter", [0x30F4] = "non_starter", [0x31F5] = "non_starter", [0x31F6] = "non_starter", - [0x30F7] = "non_starter", [0x30F8] = "non_starter", [0x30F9] = "non_starter", [0x31FA] = "non_starter", [0x31FB] = "non_starter", - [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31FF] = "non_starter", - -- - -- hyphenation - -- - [0x2026] = "hyphen", -- … ellipsis - [0x2014] = "hyphen", -- — hyphen - } - - for i=0x03040,0x030FF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese' - for i=0x031F0,0x031FF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese' - for i=0x032D0,0x032FE do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese' - for i=0x03400,0x04DFF do if not hash[i] then hash[i] = "chinese" end end - for i=0x04E00,0x09FFF do if not hash[i] then hash[i] = "chinese" end end - for i=0x0F900,0x0FAFF do if not hash[i] then hash[i] = "chinese" end end - for i=0x0FF00,0x0FFEF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese' - for i=0x20000,0x2A6DF do if not hash[i] then hash[i] = "chinese" end end - for i=0x2F800,0x2FA1F do if not hash[i] then hash[i] = "chinese" end end - for i=0x0AC00,0x0D7A3 do if not hash[i] then hash[i] = "korean" end end - for i=0x01100,0x0115F do if not hash[i] then hash[i] = "jamo_initial" end end - for i=0x01160,0x011A7 do if not hash[i] then hash[i] = "jamo_medial" end end - for i=0x011A8,0x011FF do if not hash[i] then hash[i] = "jamo_final" end end - - for i=0x01200,0x0139F do hash[i] = "ethiopic_syllable" end - - hash[0x01361] = "ethiopic_word" - hash[0x01362] = "ethiopic_sentence" - - scripts.hash = hash +local hash = { -- we could put these presets in char-def.lua + -- + -- half width opening parenthesis + -- + [0x0028] = "half_width_open", + [0x005B] = "half_width_open", + [0x007B] = "half_width_open", + [0x2018] = "half_width_open", -- ‘ + [0x201C] = "half_width_open", -- “ + -- + -- full width opening parenthesis + -- + [0x3008] = "full_width_open", -- 〈 Left book quote + [0x300A] = "full_width_open", -- 《 Left double book quote + [0x300C] = "full_width_open", -- 「 left quote + [0x300E] = "full_width_open", -- 『 left double quote + [0x3010] = "full_width_open", -- 【 left double book quote + [0x3014] = "full_width_open", -- 〔 left book quote + [0x3016] = "full_width_open", --〖 left double book quote + [0x3018] = "full_width_open", -- left tortoise bracket + [0x301A] = "full_width_open", -- left square bracket + [0x301D] = "full_width_open", -- reverse double prime qm + [0xFF08] = "full_width_open", -- ( left parenthesis + [0xFF3B] = "full_width_open", -- [ left square brackets + [0xFF5B] = "full_width_open", -- { left curve bracket + -- + -- half width closing parenthesis + -- + [0x0029] = "half_width_close", + [0x005D] = "half_width_close", + [0x007D] = "half_width_close", + [0x2019] = "half_width_close", -- ’ right quote, right + [0x201D] = "half_width_close", -- ” right double quote + -- + -- full width closing parenthesis + -- + [0x3009] = "full_width_close", -- 〉 book quote + [0x300B] = "full_width_close", -- 》 double book quote + [0x300D] = "full_width_close", -- 」 right quote, right + [0x300F] = "full_width_close", -- 』 right double quote + [0x3011] = "full_width_close", -- 】 right double book quote + [0x3015] = "full_width_close", -- 〕 right book quote + [0x3017] = "full_width_close", -- 〗 right double book quote + [0x3019] = "full_width_close", -- right tortoise bracket + [0x301B] = "full_width_close", -- right square bracket + [0x301E] = "full_width_close", -- double prime qm + [0x301F] = "full_width_close", -- low double prime qm + [0xFF09] = "full_width_close", -- ) right parenthesis + [0xFF3D] = "full_width_close", -- ] right square brackets + [0xFF5D] = "full_width_close", -- } right curve brackets + -- + [0xFF62] = "half_width_open", -- left corner bracket + [0xFF63] = "half_width_close", -- right corner bracket + -- + -- vertical opening vertical + -- + -- 0xFE35, 0xFE37, 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47, + -- + -- vertical closing + -- + -- 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42, 0xFE44, 0xFE48, + -- + -- half width opening punctuation + -- + -- <empty> + -- + -- full width opening punctuation + -- + -- 0x2236, -- ∶ + -- 0xFF0C, -- , + -- + -- half width closing punctuation_hw + -- + [0x0021] = "half_width_close", -- ! + [0x002C] = "half_width_close", -- , + [0x002E] = "half_width_close", -- . + [0x003A] = "half_width_close", -- : + [0x003B] = "half_width_close", -- ; + [0x003F] = "half_width_close", -- ? + [0xFF61] = "half_width_close", -- hw full stop + -- + -- full width closing punctuation + -- + [0x3001] = "full_width_close", -- 、 + [0x3002] = "full_width_close", -- 。 + [0xFF0C] = "full_width_close", -- , + [0xFF0E] = "full_width_close", -- + -- + -- depends on font + -- + [0xFF01] = "full_width_close", -- ! + [0xFF1F] = "full_width_close", -- ? + -- + [0xFF1A] = "full_width_punct", -- : + [0xFF1B] = "full_width_punct", -- ; + -- + -- non starter + -- + [0x3005] = "non_starter", [0x3041] = "non_starter", [0x3043] = "non_starter", [0x3045] = "non_starter", [0x3047] = "non_starter", + [0x3049] = "non_starter", [0x3063] = "non_starter", [0x3083] = "non_starter", [0x3085] = "non_starter", [0x3087] = "non_starter", + [0x308E] = "non_starter", [0x3095] = "non_starter", [0x3096] = "non_starter", [0x309B] = "non_starter", [0x309C] = "non_starter", + [0x309D] = "non_starter", [0x309E] = "non_starter", [0x30A0] = "non_starter", [0x30A1] = "non_starter", [0x30A3] = "non_starter", + [0x30A5] = "non_starter", [0x30A7] = "non_starter", [0x30A9] = "non_starter", [0x30C3] = "non_starter", [0x30E3] = "non_starter", + [0x30E5] = "non_starter", [0x30E7] = "non_starter", [0x30EE] = "non_starter", [0x30F5] = "non_starter", [0x30F6] = "non_starter", + [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31F0] = "non_starter", [0x31F1] = "non_starter", + [0x30F2] = "non_starter", [0x30F3] = "non_starter", [0x30F4] = "non_starter", [0x31F5] = "non_starter", [0x31F6] = "non_starter", + [0x30F7] = "non_starter", [0x30F8] = "non_starter", [0x30F9] = "non_starter", [0x31FA] = "non_starter", [0x31FB] = "non_starter", + [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31FF] = "non_starter", + -- + -- hyphenation + -- + [0x2026] = "hyphen", -- … ellipsis + [0x2014] = "hyphen", -- — hyphen + -- + [0x1361] = "ethiopic_word", + [0x1362] = "ethiopic_sentence", + -- +} +local function provide(t,k) + local v + if not tonumber(k) then v = false + elseif (k >= 0x03040 and k <= 0x030FF) + or (k >= 0x031F0 and k <= 0x031FF) + or (k >= 0x032D0 and k <= 0x032FE) + or (k >= 0x0FF00 and k <= 0x0FFEF) then v = "katakana" + elseif (k >= 0x03400 and k <= 0x04DFF) + or (k >= 0x04E00 and k <= 0x09FFF) + or (k >= 0x0F900 and k <= 0x0FAFF) + or (k >= 0x20000 and k <= 0x2A6DF) + or (k >= 0x2F800 and k <= 0x2FA1F) then v = "chinese" + elseif (k >= 0x0AC00 and k <= 0x0D7A3) then v = "korean" + elseif (k >= 0x01100 and k <= 0x0115F) then v = "jamo_initial" + elseif (k >= 0x01160 and k <= 0x011A7) then v = "jamo_medial" + elseif (k >= 0x011A8 and k <= 0x011FF) then v = "jamo_final" + elseif (k >= 0x01200 and k <= 0x0139F) then v = "ethiopic_syllable" + else v = false + end + t[k] = v + return v end +table.setmetatableindex(hash,provide) + +scripts.hash = hash + local numbertodataset = allocate() local numbertohandler = allocate() diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua index 8640ba825..a6181f5e4 100644 --- a/tex/context/base/sort-ini.lua +++ b/tex/context/base/sort-ini.lua @@ -527,7 +527,7 @@ local function numify(s) return utfchar(s) end -function sorters.strip(str) -- todo: only letters and such utf.gsub("([^%w%d])","") +function sorters.strip(str) -- todo: only letters and such if str then str = gsub(str,"\\[\"\'~^`]*","") -- \"e str = gsub(str,"\\%S*","") -- the rest diff --git a/tex/context/base/sort-lan.lua b/tex/context/base/sort-lan.lua index 6a0cb8eab..d2fa276d7 100644 --- a/tex/context/base/sort-lan.lua +++ b/tex/context/base/sort-lan.lua @@ -3,9 +3,13 @@ if not modules then modules = { } end modules ['sort-lan'] = { comment = "companion to sort-lan.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" + license = "see context related readme files", + dataonly = true, } +-- todo: look into uts#10 (2012) ... some experiments ... something +-- to finish in winter. + -- Many vectors were supplied by Wolfgang Schuster and Philipp -- Gesang. However this is a quite adapted and reformatted variant -- so it needs some checking. Other users provides tables and @@ -86,8 +90,20 @@ definitions['Duden'] = { replacements = { { "ß", 's' } }, } -definitions['de'] = { parent = 'default' } -- new german +-- definitions['de'] = { parent = 'default' } -- new german + +definitions['de'] = { + parent = 'default', + replacements = { + { "ä", 'ae' }, { "Ä", 'Ae' }, + { "ö", 'oe' }, { "Ö", 'Oe' }, + { "ü", 'ue' }, { "Ü", 'Ue' }, + { "ß", 's' }, + }, +} + definitions['deo'] = { parent = 'de' } -- old german + definitions['de-DE'] = { parent = 'de' } -- german - Germany definitions['de-CH'] = { parent = 'de' } -- german - Swiss diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua index effd26fe4..998df3aa6 100644 --- a/tex/context/base/spac-ali.lua +++ b/tex/context/base/spac-ali.lua @@ -20,7 +20,7 @@ local unset_attribute = node.unset_attribute local slide_nodes = node.slide local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here -local link_nodes = nodes.link +local concat_nodes = nodes.concat local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes @@ -77,12 +77,12 @@ local function handler(head,leftpage,realpageno) action = leftpage and 2 or 1 end if action == 1 then - current.list = hpack_nodes(link_nodes(current.list,new_stretch(3)),current.width,"exactly") + current.list = hpack_nodes(concat_nodes{current.list,new_stretch(3)},current.width,"exactly") if trace_realign then report_realign("flush left: align %s, page %s, realpage %s",align,pageno,realpageno) end elseif action == 2 then - current.list = hpack_nodes(link_nodes(new_stretch(3),current.list),current.width,"exactly") + current.list = hpack_nodes(concat_nodes{new_stretch(3),current.list},current.width,"exactly") if trace_realign then report_realign("flush right: align %s, page %s, realpage %s",align,pageno,realpageno) end diff --git a/tex/context/base/spac-ali.mkiv b/tex/context/base/spac-ali.mkiv index 57806b6f2..100e3ab82 100644 --- a/tex/context/base/spac-ali.mkiv +++ b/tex/context/base/spac-ali.mkiv @@ -268,7 +268,7 @@ \newskip\s_zero_plus_one_fil \s_zero_plus_one_fil = 0pt plus 1fil \newskip\s_zero_plus_zero \s_zero_plus_zero = 0pt plus 0pt -% \!!plus ... slower than inline +% \s!plus ... slower than inline \unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips {\raggedstatus\zerocount @@ -285,8 +285,8 @@ {\setraggedness\spac_align_set_raggedness_left \raggedstatus\plusone \attribute\alignstateattribute\plusone - \leftskip \plusone\leftskip \!!plus\spac_align_set_raggedness_left - \rightskip \plusone\rightskip\!!plus\zeropoint + \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_left + \rightskip \plusone\rightskip\s!plus\zeropoint \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -297,8 +297,8 @@ {\setraggedness\spac_align_set_raggedness_middle \raggedstatus\plustwo \attribute\alignstateattribute\plustwo - \leftskip \plusone\leftskip \!!plus\spac_align_set_raggedness_middle - \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_middle + \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_middle + \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_middle \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -309,8 +309,8 @@ {\setraggedness\spac_align_set_raggedness_right \raggedstatus\plusthree \attribute\alignstateattribute\plusthree - \leftskip \plusone\leftskip \!!plus\zeropoint - \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_right + \leftskip \plusone\leftskip \s!plus\zeropoint + \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_right \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_one_fil @@ -320,8 +320,8 @@ \unexpanded\def\spac_align_set_horizontal_very_left {\raggedstatus\plusone \attribute\alignstateattribute\plusone - \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount - \rightskip \plusone\rightskip\!!plus\zeropoint + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount + \rightskip \plusone\rightskip\s!plus\zeropoint \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -331,8 +331,8 @@ \unexpanded\def\spac_align_set_horizontal_very_center {\raggedstatus\plustwo \attribute\alignstateattribute\plustwo - \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount - \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -342,8 +342,8 @@ \unexpanded\def\spac_align_set_horizontal_very_right {\raggedstatus\plusthree \attribute\alignstateattribute\plusthree - \leftskip \plusone\leftskip \!!plus\zeropoint - \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount + \leftskip \plusone\leftskip \s!plus\zeropoint + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -354,8 +354,8 @@ {\setraggedness\spac_align_set_raggedness_middle \raggedstatus\plustwo \attribute\alignstateattribute\plustwo - \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount_half - \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount_half + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount_half + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_half \spaceskip \v_spac_align_space_amount \xspaceskip \v_spac_align_space_amount_x \parfillskip\s_zero_plus_zero @@ -365,11 +365,11 @@ \unexpanded\def\spac_align_set_horizontal_centered_last_line {\raggedstatus\zerocount \attribute\alignstateattribute\attributeunsetvalue - \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount\relax - \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount_negative\relax + \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax + \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax \spaceskip \zeropoint\relax \xspaceskip \zeropoint\relax - \parfillskip\zeropoint\!!plus\v_spac_align_fill_amount_double\relax + \parfillskip\zeropoint\s!plus\v_spac_align_fill_amount_double\relax \parindent \zeropoint \relax} @@ -377,8 +377,8 @@ {\tttf % brrr \raggedstatus\plusthree \attribute\alignstateattribute\plusthree - \leftskip \plusone\leftskip \!!plus\zeropoint\relax - \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_right\relax + \leftskip \plusone\leftskip \s!plus\zeropoint\relax + \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_right\relax \spaceskip \zeropoint\relax \xspaceskip \zeropoint\relax \parfillskip\s_zero_plus_zero @@ -386,7 +386,7 @@ \relax} \unexpanded\def\spac_align_set_horizontal_extra - {\xspaceskip\zeropoint\!!plus\v_spac_align_fill_amount_space\relax} + {\xspaceskip\zeropoint\s!plus\v_spac_align_fill_amount_space\relax} \def\spac_align_flush_horizontal {\ifcase\c_spac_align_state_horizontal @@ -651,6 +651,10 @@ \let\forgetragged \spac_align_set_horizontal_none +\appendtoks + \spac_align_set_horizontal_none +\to \everyforgetall + % Box commands. \unexpanded\def\ibox#1#2#3% @@ -735,11 +739,11 @@ \def\dosetraggedskips#1#2#3#4#5#6#7% {\raggedstatus #1\relax - \leftskip 1\leftskip \!!plus#2\relax - \rightskip 1\rightskip\!!plus#3\relax + \leftskip 1\leftskip \s!plus#2\relax + \rightskip 1\rightskip\s!plus#3\relax \spaceskip #4\relax \xspaceskip #5\relax - \parfillskip \zeropoint\!!plus#6\relax + \parfillskip \zeropoint\s!plus#6\relax \parindent #7\relax \attribute\alignstateattribute\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi} diff --git a/tex/context/base/spac-cha.mkiv b/tex/context/base/spac-cha.mkiv new file mode 100644 index 000000000..a07c8f198 --- /dev/null +++ b/tex/context/base/spac-cha.mkiv @@ -0,0 +1,191 @@ +%D \module +%D [ file=spac-cha, % was supp-ali, +%D version=2012.06.08, % 2000.04.17, +%D title=\CONTEXT\ Spacing Macros, +%D subtitle=Character Alignment, +%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 Yet undocumented but nevertheless used. + +% 0 = centered +% 1 = left in before +% 2 = right in before +% 3 = left in after +% 4 = right in after + +\unprotect + +% \starttabulate[|cg{.}|cg{,}|cg{,}|] +% \NC period \NC comma \NC comma \NC\NR +% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR +% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR +% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR +% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR +% \NG 10\\ \NG 10\\ \NG 0,00 \NC\NR +% \NG 10 \NG 10 \NG 0,00 \NC\NR +% \NG 10 \NG 10 \NG 0,00 \NC\NR +% \stoptabulate + +% We gain not much by luafication and actually make things worse. + +\chardef\characteralignmentmode\plusfour +\chardef\characteralignmentslot\plusone + +\let\afterassignwidth \!!zeropoint +\let\beforeassignwidth\!!zeropoint + +\def\alignmentcharacter{.} + +\newdimen\d_supp_charalign_width +\newtoks \t_supp_charalign_list + +\let\alignmentclass\s!default % can be used to handle multiple mixed ones + +\installcorenamespace{characteralign} + +\unexpanded\def\supp_charalign_push + {\ifcsname\??characteralign\alignmentclass\endcsname\else + \normalexpanded{\global\t_supp_charalign_list{\the\t_supp_charalign_list\supp_charalign_do{\alignmentclass}}}% + \fi + \setxvalue{\??characteralign\alignmentclass}{\supp_charalign_do + {\afterassignwidth}{\beforeassignwidth}{\alignmentcharacter}}} + +\unexpanded\def\supp_charalign_pop_do#1#2#3% + {\def\afterassignwidth {#1}% + \def\beforeassignwidth {#2}% + \def\alignmentcharacter{#3}} + +\unexpanded\def\supp_charalign_pop + {\let\supp_charalign_do\supp_charalign_pop_do + \executeifdefined{\??characteralign\alignmentclass}\donothing} + +\unexpanded\def\supp_charalign_reset_do#1% + {\global\letbeundefined{\??characteralign#1}} % global ! + +\unexpanded\def\resetcharacteralign + {\let\supp_charalign_do\supp_charalign_reset_do + \the\t_supp_charalign_list + \global\t_supp_charalign_list\emptytoks} + +\unexpanded\def\supp_charalign_firstpass_one#1#2% + {\supp_charalign_pop + \let\\\empty + \setbox\scratchbox\hbox{#1}% + \d_supp_charalign_width\wd\scratchbox + \setbox\scratchbox\emptyhbox + \supp_charalign_check#2#1\relax\relax + \scratchdimen-\wd\scratchbox + \setbox\scratchbox\hbox{\ignorespaces#2\unskip}% + \advance\scratchdimen \wd\scratchbox + \ifdim\scratchdimen>\beforeassignwidth\relax + \edef\beforeassignwidth{\the\scratchdimen}% + \fi + \ifdim\scratchdimen=\zeropoint + \setbox\scratchbox\hbox{\ignorespaces#2\unskip}% + \scratchdimen\wd\scratchbox + \ifcase\characteralignmentmode + % do nothing + \else\ifnum\characteralignmentmode<\plusthree + \advance\scratchdimen\d_supp_charalign_width\relax + \ifdim\scratchdimen>\beforeassignwidth\relax + \edef\beforeassignwidth{\the\scratchdimen}% + \fi + \else + \ifdim\scratchdimen>\afterassignwidth\relax + \edef\afterassignwidth{\the\scratchdimen}% + \fi + \fi\fi + \fi + \supp_charalign_push} + +\unexpanded\def\supp_charalign_firstpass_two#1#2#3% + {\ifx#2\relax + \setbox\scratchbox\hbox{\ignorespaces#1\unskip}% + \ifdim\wd\scratchbox>\afterassignwidth + \edef\afterassignwidth{\the\wd\scratchbox}% + \fi + \else + \supp_charalign_check#2#3\relax\relax + \fi} + +\unexpanded\def\supp_charalign_secondpass_one#1#2% + {\supp_charalign_pop + \let\\\empty % beware, no grouping + \setbox\scratchbox\hbox{#1}% + \d_supp_charalign_width\wd\scratchbox + \setbox\scratchbox\emptyhbox + % new 12,34 vs 10\\ where 10 aligns on 12 if #1 = , + \ifcase\characteralignmentslot + \supp_charalign_check#2#1\relax\relax + \scratchdimen\wd\scratchbox + \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% + \else + \def\\{#1}% + \normalexpanded{\supp_charalign_check#2#1\relax\relax}% + \scratchdimen\wd\scratchbox + \setbox\scratchbox\hbox{\def\\{\hphantom{#1}}\ignorespaces#2\unskip}% + \fi + \noindent + \ifdim\scratchdimen=\wd\scratchbox + \ifcase\characteralignmentmode + \box\scratchbox + \else + \hbox + {\dontcomplain + \hbox to \beforeassignwidth + {\ifcase\characteralignmentmode\or + \box\scratchbox\hss + \or + \hss\box\scratchbox\hskip\d_supp_charalign_width + \or + \hss\rlap{\box\scratchbox}% + \or + \hss\rlap{\hbox to \afterassignwidth{\hss\box\scratchbox}}% + \fi}% + \hskip\afterassignwidth}% + \fi + \else + \hbox + {\hbox to \beforeassignwidth + {\hss\box\scratchbox\hskip-\scratchdimen}% + \hskip\afterassignwidth}% + \fi} + +\unexpanded\def\supp_charalign_secondpass_two#1#2#3% + {\ifx#2\relax + \setbox\scratchbox\hbox{\ignorespaces#1\unskip}% + \else + \supp_charalign_check#2#3\relax\relax + \fi} + +\unexpanded\def\supp_charalign_firstpass#1% + {\unexpanded\def\checkalignment ##1{\supp_charalign_firstpass_one{#1}{##1}}% + \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_firstpass_two{##1}{##2}{##3}}} + +\unexpanded\def\supp_charalign_secondpass#1% + {\unexpanded\def\checkalignment ##1{\supp_charalign_secondpass_one{#1}{##1}}% + \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_secondpass_two{##1}{##2}{##3}}} + +\unexpanded\def\setfirstpasscharacteralign + {\supp_charalign_pop + \normalexpanded{\supp_charalign_firstpass{\alignmentcharacter}}} + +\unexpanded\def\setsecondpasscharacteralign + {\supp_charalign_pop + \normalexpanded{\supp_charalign_secondpass{\alignmentcharacter}}} + +\unexpanded\def\startcharacteralign#1\stopcharacteralign + {\bgroup + \setfirstpasscharacteralign #1% + \setsecondpasscharacteralign#1% + \egroup} + +\let\stopcharacteralign\relax + +\protect \endinput diff --git a/tex/context/base/spac-def.mkiv b/tex/context/base/spac-def.mkiv index 4cd7b1d1c..312483cfa 100644 --- a/tex/context/base/spac-def.mkiv +++ b/tex/context/base/spac-def.mkiv @@ -13,80 +13,45 @@ \writestatus{loading}{ConTeXt Spacing Macros / Definitions} -% todo: move resetters to other modules +% Ideally these definitions should be moved to where they first appear and +% this will happen at some point. \unprotect -\unexpanded\def\forgeteverypar - {\everypar{\the\neverypar}} - -% worth trying: -% -% \unexpanded\def\forgeteverypar -% {\everypar\neverypar} - -\unexpanded\def\forgetparskip - {\s_spac_whitespace_parskip\zeropoint - \parskip\zeropoint - \let\v_spac_whitespace_current\v!none} - -\unexpanded\def\forgetbothskips - {\leftskip\zeropoint - \rightskip\zeropoint - \relax} - -\unexpanded\def\forgethorizontalstretch - {\emergencystretch\zeropoint} - -\unexpanded\def\forgetverticalstretch - {\spacing\plusone} - -\newif\ifforgotten % rather good signal for inner - -% This will become better: several resetters that do all in once as currently there is -% redundant code. - -\appendtoks \forgottentrue \to \everyforgetall -\appendtoks \forgetragged \to \everyforgetall -\appendtoks \forgetparskip \to \everyforgetall -\appendtoks \forgetparindent \to \everyforgetall -\appendtoks \forgetbothskips \to \everyforgetall -\appendtoks \forgethorizontalstretch \to \everyforgetall % needed in pagebody -\appendtoks \forgetverticalstretch \to \everyforgetall % needed in otr -\appendtoks \everypar\emptytoks \to \everyforgetall % indeed! - -\appendtoks \forgetverticalstretch \to \everybodyfont -\appendtoks \presetnormallineheight \to \everybodyfont -\appendtoks \setnormalbaselines \to \everybodyfont % check if redundant (\forgetverticalstretch does it too) -\appendtoks \setstrut \to \everybodyfont % check if redundant (\forgetverticalstretch does it too) -\appendtoks \settopskip \to \everybodyfont % factors set in \forgetverticalstretch -\appendtoks \setmaxdepth \to \everybodyfont % factors set in \forgetverticalstretch -\appendtoks \synchronizeindenting \to \everybodyfont -\appendtoks \synchronizeblank \to \everybodyfont -\appendtoks \synchronizewhitespace \to \everybodyfont -\appendtoks \synchronizespacecodes \to \everybodyfont % not needed, frozen factors -\appendtoks \setrelativeinterlinespace \to \everybodyfont - -\appendtoks \updateraggedskips \to \everyfontswitch % under test -\prependtoks \let\par\normalpar \to \everybeforepagebody % see \fillinline (was endgraf) -\appendtoks \synchronizespacecodes \to \everydefinedfont % not needed, frozen factors - -\setupwhitespace - [\v!none] +% maybe \everysynchronizeglobalspacing +% maybe \everysynchronizelocalspacing -\indenting - [\v!never] +\appendtoks + \forgetverticalstretch + \presetnormallineheight + \setnormalbaselines % check if redundant (\forgetverticalstretch does it too) + \setstrut % check if redundant (\forgetverticalstretch does it too) + \settopskip % factors set in \forgetverticalstretch + \setmaxdepth % factors set in \forgetverticalstretch + \synchronizeindenting + \synchronizeblank + \synchronizewhitespace + \synchronizespacecodes % not needed, frozen factors + \setrelativeinterlinespace +\to \everybodyfont -\setupindenting - [\v!none] +% why exception -\setupblank - [\v!big] % alternatively [\v!standard] +\appendtoks + \updateraggedskips % under test +\to \everyfontswitch + +% maybe more + +\prependtoks + \let\par\normalpar +\to \everybeforepagebody % see \fillinline (was endgraf) -\defineblank[\v!default] [\v!big] % todo: needs to adapt to \setupblank -\defineblank[\v!before] [\v!default] % but we need to avoid circular references -\defineblank[\v!inbetween][\v!default] % then -\defineblank[\v!after] [\v!before] +% needs checking: + +\appendtoks + \synchronizespacecodes +\to \everydefinedfont % not needed, frozen factors \setupinterlinespace [\c!minheight=\zeropoint, % only special purpose @@ -97,14 +62,11 @@ \c!bottom=0.4, \c!distance=\onepoint, \c!line=2.8\exheight, - \c!stretch=\zerocount] + \c!stretch=\zerocount, + \c!shrink=\zerocount] -\setupnarrower - [\c!before=\endgraf, - \c!after=\endgraf, - \c!left=1.5\emwidth, - \c!right=1.5\emwidth, - \c!middle=1.5\emwidth] +\setupblank + [\v!big] \setuptolerance [\v!horizontal,\v!verystrict] @@ -119,4 +81,10 @@ \setupspacing [\v!packed] +\indenting + [\v!never] + +\setupindenting + [\v!none] + \protect \endinput diff --git a/tex/context/base/spac-grd.mkiv b/tex/context/base/spac-grd.mkiv index 487521f6c..7b3ee6d6c 100644 --- a/tex/context/base/spac-grd.mkiv +++ b/tex/context/base/spac-grd.mkiv @@ -11,41 +11,42 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This module will be merged intio spac-ver.mkiv. +%D This module will be merged into spac-ver.mkiv. \writestatus{loading}{ConTeXt Spacing Macros / Grid Snapping} -% buff-ver.mkiv: halfline spacing -% strc-mat.mkiv: configure math grid (new code needed) -% page-one.mkiv: to be checked -% page-mul.mkiv: to be checked and redone -% page-sid.mkiv: to be checked -% page-set.mkiv: to be checked -% strc-not.mkiv: to be checked -% strc-ren.mkiv: to be checked -% strc-flt.mkiv: to be checked (captions, probably top/bottom) -% core-mis.mkiv: to be checked (placement, probbaly harmless) - \unprotect -%D Helpers: +%D A rather crappy macro that we need to avoid and as such it will probably +%D disappear: + +\installcorenamespace{lastnodepusher} \let\poplastnode\relax -\def\pushlastnode - {\ifdim\lastskip=\zeropoint - \ifnum\lastpenalty=\zerocount - \ifnum\lastkern=\zerocount - \let\poplastnode\relax - \else - \edef\poplastnode{\kern\the\lastkern\relax}\kern-\lastkern % untested - \fi +\unexpanded\def\pushlastnode + {\csname\??lastnodepusher + \ifcsname\??lastnodepusher\the\lastnodetype\endcsname + \the\lastnodetype \else - \edef\poplastnode{\penalty\the\lastpenalty\relax}\nobreak % untested + \s!unknown \fi - \else - \edef\poplastnode{\vskip\the\lastskip\relax}\vskip-\lastskip % \removelastskip - \fi} + \endcsname} + +\setvalue{\??lastnodepusher\number\kernnodecode}% + {\unexpanded\edef\poplastnode{\kern\the\lastkern\relax}% + \kern-\lastkern} + +\setvalue{\??lastnodepusher\number\gluenodecode}% + {\unexpanded\edef\poplastnode{\vskip\the\lastskip\relax}% + \vskip-\lastskip} + +\setvalue{\??lastnodepusher\number\penaltynodecode}% + {\unexpanded\edef\poplastnode{\penalty\the\lastpenalty\relax}% + \nobreak} + +\setvalue{\??lastnodepusher\s!unknown}% + {\let\poplastnode\relax} %D Moved from supp-box: @@ -133,13 +134,17 @@ % \startlinecorrection \framed{xxx} \stoplinecorrection % \input ward \par +% 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 ]} \def\showbaselinecorrection {\def\dobaselinecorrection % visualization is not watertight! {\bgroup -\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi + \ifdim\prevdepth>\zeropoint + \kern-\prevdepth + \fi \setbox\scratchbox\emptyhbox \wd\scratchbox\hsize \dp\scratchbox\strutdp @@ -149,9 +154,9 @@ \egroup \prevdepth\strutdp}% \def\dotopbaselinecorrection - {\hrule\!!height\d_spac_lines_correction_before}% + {\hrule\s!height\d_spac_lines_correction_before}% \def\dobotbaselinecorrection - {\hrule\!!height\d_spac_lines_correction_after}} + {\hrule\s!height\d_spac_lines_correction_after}} \def\dobaselinecorrection % beware, this one is redefined / used locally elsewhere {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi diff --git a/tex/context/base/spac-hor.mkiv b/tex/context/base/spac-hor.mkiv index eeb5cadfd..d0d4660bc 100644 --- a/tex/context/base/spac-hor.mkiv +++ b/tex/context/base/spac-hor.mkiv @@ -34,7 +34,7 @@ \unexpanded\def\setupindenting {\doifnextoptionalelse\spac_indentation_setup_options\spac_indentation_setup_size} -\def\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}} \let\synchronizeindenting\spac_indentation_setup_size @@ -286,6 +286,17 @@ \parindent\zeropoint \let\v_spac_indentation_current\v!none} +\appendtoks + \forgetparindent +\to \everyforgetall + +\unexpanded\def\forgethorizontalstretch + {\emergencystretch\zeropoint} + +\appendtoks + \forgethorizontalstretch +\to \everyforgetall % needed in pagebody + %D Helper: \unexpanded\def\softbreak @@ -406,7 +417,16 @@ \appendtoks \let~\space \let\ \space -\to \simplifiedcommands +\to \everysimplifycommands + +\newsignal\s_spac_keep_unwanted_space + +\unexpanded\def\keepunwantedspaces + {\ifhmode + \ifdim\lastskip=\s_spac_keep_unwanted_space\else + \hskip\s_spac_keep_unwanted_space\relax + \fi + \fi} \unexpanded\def\removeunwantedspaces {\ifhmode @@ -415,7 +435,12 @@ \def\spac_helpers_remove_unwantedspace {\ifnum\lastnodetype=\gluenodecode - \unskip \expandafter\spac_helpers_remove_unwantedspace + \ifdim\lastskip=\s_spac_keep_unwanted_space\relax + \unskip + \else + \unskip + \doubleexpandafter\spac_helpers_remove_unwantedspace + \fi \fi} % \startbuffer @@ -466,14 +491,19 @@ % Bovendien definieren we enkele extra \fill's: -\unexpanded\def\hfilll{\hskip\zeropoint\!!plus1filll\relax} -\unexpanded\def\vfilll{\vskip\zeropoint\!!plus1filll\relax} +\unexpanded\def\hfilll {\hskip\zeropoint\s!plus1\s!filll\relax} +\unexpanded\def\vfilll {\vskip\zeropoint\s!plus1\s!filll\relax} + +%unexpanded\def\hfilneg {\hskip\zeropoint\s!plus-1\s!fil\relax} +\unexpanded\def\hfillneg {\hskip\zeropoint\s!plus-1\s!fill\relax} +\unexpanded\def\hfilllneg{\hskip\zeropoint\s!plus-1\s!filll\relax} +%unexpanded\def\vfilneg {\vskip\zeropoint\s!plus-1\s!fil\relax} +\unexpanded\def\vfillneg {\vskip\zeropoint\s!plus-1\s!fill\relax} +\unexpanded\def\vfilllneg{\vskip\zeropoint\s!plus-1\s!filll\relax} \unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} \unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere -% needs a proper \definenarrower or installnarrower -% % maybe we should hash the analysis \installcorenamespace{narrower} @@ -576,9 +606,6 @@ \let\stopnarrow\spac_narrower_stop -% \def\v!narrower{narrower} -% \definenarrower[\v!narrower] - \newdimen\d_spac_effective_hsize \def\effectivehsize {\hsize} \newdimen\d_spac_effective_leftskip \def\effectiveleftskip {\leftskip} \newdimen\d_spac_effective_rightskip \def\effectiverightskip{\rightskip} @@ -613,6 +640,24 @@ \unexpanded\def\doadaptleftskip #1{\dosetleftskipadaption {#1}\advance\leftskip \leftskipadaption } \unexpanded\def\doadaptrightskip#1{\dosetrightskipadaption{#1}\advance\rightskip\rightskipadaption} +\unexpanded\def\forgetbothskips + {\leftskip\zeropoint + \rightskip\zeropoint + \relax} + +\appendtoks + \forgetbothskips +\to \everyforgetall + +\unexpanded\def\forgetparskip + {\s_spac_whitespace_parskip\zeropoint + \parskip\zeropoint + \let\v_spac_whitespace_current\v!none} + +\appendtoks + \forgetparskip +\to \everyforgetall + %D Tolerance (can also be set with align): \installcorenamespace{tolerancemethods} @@ -626,7 +671,7 @@ \installtolerancemethod \v!vertical \v!verytolerant {\def\bottomtolerance{.100}} \installtolerancemethod \v!horizontal \v!stretch {\emergencystretch\bodyfontsize} -\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\!!plus.25em\!!minus.25em\relax} +\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\s!plus.25em\s!minus.25em\relax} \installtolerancemethod \v!horizontal \v!verystrict {\tolerance 200 } \installtolerancemethod \v!horizontal \v!strict {\tolerance1500 } \installtolerancemethod \v!horizontal \v!tolerant {\tolerance3000 } @@ -861,8 +906,8 @@ \def\flexiblespaceamount#1#2#3% {#1\interwordspace - \!!plus#2\interwordstretch - \!!minus#3\interwordshrink} + \s!plus#2\interwordstretch + \s!minus#3\interwordshrink} \def\fixedspaceamount#1% {#1\interwordspace} @@ -947,7 +992,7 @@ \mskip#1% \else \scratchdimen#1\hspaceamount\empty{#2}% - \scratchskip\scratchdimen\!!plus.5\scratchdimen\!!minus.3\scratchdimen + \scratchskip\scratchdimen\s!plus.5\scratchdimen\s!minus.3\scratchdimen \hskip\scratchskip \fi \endgroup} @@ -956,4 +1001,68 @@ \unexpanded\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} \unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} +%D A rather unknown one: + +\unexpanded\def\widened % moved from cont-new + {\doifnextoptionalelse\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} + +%D \macros +%D {startignorespaces} +%D +%D I'll probably forget that this one exists: +%D +%D \starttyping +%D \ruledhbox +%D {\startignorespaces +%D \def\oeps{a} +%D \startignorespaces +%D \def\oeps{a} +%D \stopignorespaces +%D \def\oeps{a} +%D \stopignorespaces +%D \oeps} +%D \stoptyping + +\newsignal\s_spac_ignore_spaces +\newcount \c_spac_ignore_spaces + +\unexpanded\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 + {\ifcase\c_spac_ignore_spaces \or + \ifhmode + \doloop\spac_ignore_spaces_body + \fi + \fi + \advance\c_spac_ignore_spaces\minusone} + +\def\spac_ignore_spaces_body + {\ifdim\lastskip=\zeropoint + \exitloop + \else\ifdim\lastskip=\s_spac_ignore_spaces + \unskip + \exitloop + \else + \unskip + \fi\fi} + +%D \macros +%D {obeyfollowingtoken} + +\def\obeyfollowingtoken{{}} % end \cs scanning + \protect \endinput diff --git a/tex/context/base/spac-par.mkiv b/tex/context/base/spac-par.mkiv index af032a145..6b7ed4f7d 100644 --- a/tex/context/base/spac-par.mkiv +++ b/tex/context/base/spac-par.mkiv @@ -203,4 +203,11 @@ \fi \glet\flushpostponednodedata\relax} +\unexpanded\def\doflushatpar + {\ifvmode + \expandafter\flushatnextpar + \else + \expandafter\firstofoneargument + \fi} + \protect \endinput diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index 66698a49e..ace3ed8bb 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -42,16 +42,18 @@ local stoptiming = statistics.stoptiming -- vertical space handler -local trace_vbox_vspacing = false trackers.register("builders.vbox_vspacing", function(v) trace_vbox_vspacing = v end) -local trace_page_vspacing = false trackers.register("builders.page_vspacing", function(v) trace_page_vspacing = v end) -local trace_collect_vspacing = false trackers.register("builders.collect_vspacing", function(v) trace_collect_vspacing = v end) -local trace_vspacing = false trackers.register("builders.vspacing", function(v) trace_vspacing = v end) -local trace_vsnapping = false trackers.register("builders.vsnapping", function(v) trace_vsnapping = v end) -local trace_vpacking = false trackers.register("builders.vpacking", function(v) trace_vpacking = v end) +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_vpacking = false trackers.register("vspacing.packing", function(v) trace_vpacking = 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_page_builder = logs.reporter("builders","page") local a_skipcategory = attributes.private('skipcategory') local a_skippenalty = attributes.private('skippenalty') @@ -65,6 +67,7 @@ local unset_attribute = node.unset_attribute local set_attribute = node.set_attribute local find_node_tail = node.tail local free_node = node.free +local free_node_list = node.flush_list local copy_node = node.copy local traverse_nodes = node.traverse local traverse_nodes_id = node.traverse_id @@ -1216,7 +1219,6 @@ end function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then - -- starttiming(vspacing) local newtail = find_node_tail(newhead) local flush = false stackhack = true -- todo: only when grid snapping once enabled @@ -1266,7 +1268,6 @@ function vspacing.pagehandler(newhead,where) -- texlists.contrib_head = nil newhead = nil end - -- stoptiming(vspacing) end return newhead end @@ -1316,28 +1317,51 @@ function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction) else nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true) end - stoptiming(builders) else head, done = actions(head,groupcode) - stoptiming(builders) end + stoptiming(builders) end return head, done end --- This one is special in the sense that it has no head --- and we operate on the mlv. Also, we need to do the --- vspacing last as it removes items from the mvl. +-- This one is special in the sense that it has no head and we operate on the mlv. Also, +-- we need to do the vspacing last as it removes items from the mvl. local actions = nodes.tasks.actions("mvlbuilders") +local function report(groupcode,head) + report_page_builder("trigger: %s",groupcode) + report_page_builder(" vsize : %s",points(tex.vsize)) + report_page_builder(" pagegoal : %s",points(tex.pagegoal)) + report_page_builder(" pagetotal: %s",points(tex.pagetotal)) + report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>") +end + function builders.buildpage_filter(groupcode) - starttiming(builders) - local head = texlists.contrib_head - local head, done = actions(head,groupcode) - texlists.contrib_head = head - stoptiming(builders) - return (done and head) or true + local head, done = texlists.contrib_head, false +-- if head and head.next and head.next.id == hlist_code and head.next.width == 1 then +-- report_page_builder("trigger otr calculations") +-- free_node_list(head) +-- head = nil +-- end + if head then + starttiming(builders) + if trace_page_builder then + report(groupcode,head) + end + head, done = actions(head,groupcode) + stoptiming(builders) + -- -- doesn't work here (not passed on?) + -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom + texlists.contrib_head = head + return done and head or true + else + if trace_page_builder then + report(groupcode) + end + return nil, false + end end callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc") diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv index 72ee80d4f..7fdf2f70f 100644 --- a/tex/context/base/spac-ver.mkiv +++ b/tex/context/base/spac-ver.mkiv @@ -68,8 +68,8 @@ \def\normalskipamount {\openlineheight \ifgridsnapping \else \ifblankflexible - \!!plus \skipgluefactor\openlineheight - \!!minus\skipgluefactor\openlineheight + \s!plus \skipgluefactor\openlineheight + \s!minus\skipgluefactor\openlineheight \fi \fi \relax} @@ -91,15 +91,16 @@ \spac_linespacing_setup_specified_interline_space} \def\spac_linespacing_setup_specified_interline_space - {\edef\strutheightfactor {\interlinespaceparameter\c!height }% - \edef\strutdepthfactor {\interlinespaceparameter\c!depth }% - \edef\minimumstrutheight {\interlinespaceparameter\c!minheight}% - \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth }% - \edef\minimumlinedistance{\interlinespaceparameter\c!distance }% - \edef\normallineheight {\interlinespaceparameter\c!line }% - \edef\topskipfactor {\interlinespaceparameter\c!top }% - \edef\maxdepthfactor {\interlinespaceparameter\c!bottom }% - \edef\baselinegluefactor {\interlinespaceparameter\c!stretch }% + {\edef\strutheightfactor {\interlinespaceparameter\c!height }% + \edef\strutdepthfactor {\interlinespaceparameter\c!depth }% + \edef\minimumstrutheight {\interlinespaceparameter\c!minheight}% + \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth }% + \edef\minimumlinedistance {\interlinespaceparameter\c!distance }% + \edef\normallineheight {\interlinespaceparameter\c!line }% + \edef\topskipfactor {\interlinespaceparameter\c!top }% + \edef\maxdepthfactor {\interlinespaceparameter\c!bottom }% + \edef\m_spac_vertical_baseline_stretch_factor{\interlinespaceparameter\c!stretch }% + \edef\m_spac_vertical_baseline_shrink_factor {\interlinespaceparameter\c!shrink }% % often topskip does more bad than good, so: \ifx\topskipfactor\v!height \let\topskipfactor\strutheightfactor @@ -181,12 +182,12 @@ \localinterlinespacefalse} \unexpanded\def\dosetupcheckedinterlinespace#1% often a chain - {\edef\askedinterlinespace{#1}% - \ifx\askedinterlinespace\empty + {\edef\p_spac_checked_interlinespace{#1}% + \ifx\p_spac_checked_interlinespace\empty \spac_linespacing_synchronize_local - \else\ifcsname\namedinterlinespacehash\askedinterlinespace\s!parent\endcsname % we could have a \s!check + \else\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check \pushmacro\currentinterlinespace - \let\currentinterlinespace\askedinterlinespace + \let\currentinterlinespace\p_spac_checked_interlinespace \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed \iflocalinterlinespace \the\everysetuplocalinterlinespace @@ -197,8 +198,8 @@ \fi \popmacro\currentinterlinespace \else - \normalexpanded{\noexpand\doifassignmentelse{\askedinterlinespace}% - \setupspecifiedinterlinespace\setuprelativeinterlinespace[\askedinterlinespace]}% + \normalexpanded{\noexpand\doifassignmentelse{\p_spac_checked_interlinespace}% + \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}% \iflocalinterlinespace \the\everysetuplocalinterlinespace \else @@ -217,8 +218,6 @@ \let\switchtointerlinespace\setuplocalinterlinespace -% \definecomplexorsimple\setupinterlinespace - %D Helpers \newskip \s_spac_lastskip @@ -301,7 +300,7 @@ \def\spac_helpers_vglue_indeed {\par \d_spac_prevdepth\prevdepth - \hrule\!!height\zeropoint + \hrule\s!height\zeropoint \nobreak \vskip\s_spac_lastskip \prevdepth\d_spac_prevdepth} @@ -309,7 +308,7 @@ \def\spac_helpers_hglue_indeed {\dontleavehmode % \leavevmode \c_spac_spacefactor\spacefactor - \vrule\!!width\zeropoint + \vrule\s!width\zeropoint \nobreak \hskip\s_spac_lastskip \spacefactor\c_spac_spacefactor} @@ -414,6 +413,10 @@ \parskip\zeropoint \let\v_spac_whitespace_current\v!none} +\appendtoks + \forgetparskip +\to \everyforgetall + % \installwhitespacemethod \s!unknown {\s_spac_whitespace_parskip\commalistelement\relax} % % \def\spac_whitespace_setup_method#1% @@ -422,6 +425,9 @@ \unexpanded\def\nowhitespace{\vspacing[\v!nowhite]} \unexpanded\def\whitespace {\vspacing[\v!white]} +\setupwhitespace + [\v!none] + % Packed: % todo: when packed blocks blank, we need to enable forced @@ -527,8 +533,6 @@ {\removeunwantedspaces \egroup} -\newdimen\d_spac_prevdepth - \def\spac_lines_start_correction_yes[#1]% {\edef\m_spac_lines_around{#1}% \spac_lines_action_around @@ -628,6 +632,8 @@ % niet bepaald mooi. Een hele kleine waarde (0.025) voldoet, % omdat een positieve glue eindeloos rekbaar is. +% more of the next will become private: + \newdimen\strutdimen \newdimen\lineheight \newdimen\openlineheight @@ -640,12 +646,14 @@ \def\strutdepthfactor {.28} \def\baselinefactor {2.8} -\def\baselinegluefactor {0} + +\let\m_spac_vertical_baseline_stretch_factor \zerocount +\let\m_spac_vertical_baseline_shrink_factor \zerocount \def\minimumstrutheight {\zeropoint} \def\minimumstrutdepth {\zeropoint} -\def\normallineheight {\baselinefactor ex} +\def\normallineheight {\baselinefactor\exheight} \def\minimumlinedistance {\lineskip} \def\strutheight {\zeropoint} @@ -688,7 +696,7 @@ \else \systemtopskipfactor\globalbodyfontsize \ifcase\bottomraggednessmode % ragged bottom - \!!plus5\globalbodyfontsize + \s!plus5\globalbodyfontsize \fi \fi %\relax @@ -732,8 +740,8 @@ \fi \normalbaselineskip\openlineheight \ifgridsnapping\else - \!!plus \baselinegluefactor\openlineheight - \!!minus\baselinegluefactor\openlineheight + \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight + \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight \fi \normallineskip\minimumlinedistance\relax % \onepoint\relax \normallineskiplimit\zeropoint\relax @@ -750,6 +758,13 @@ \setnormalbaselines \setstrut} +\unexpanded\def\forgetverticalstretch % \forgetspacing + {\spacing\plusone} + +\appendtoks + \forgetverticalstretch +\to \everyforgetall % needed in otr + %D Sometimes one needs to freeze the interlinespacing %D %D \starttyping @@ -780,7 +795,7 @@ \newbox\strutbox -\setbox\strutbox\hbox{\vrule\!!height8.5pt\!!depth3.5pt\!!width\zeropoint} % just a start +\setbox\strutbox\hbox{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox} @@ -846,13 +861,13 @@ \unexpanded\def\charhtstrut {\begingroup \setcharstrut{GJY}% - \vrule\!!width\zeropoint\!!depth\zeropoint\!!height\strutht + \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht \endgroup} \unexpanded\def\chardpstrut {\begingroup \setcharstrut{gjy}% - \vrule\!!width\zeropoint\!!depth\strutdp\!!height\zeropoint + \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint \endgroup} % because of all the callbacks in mkiv, we avoid unnecessary boxes ... @@ -881,20 +896,22 @@ \def\spac_struts_set_hide {\setbox\strutbox\hbox {\vrule - \!!width \zeropoint - \!!height\strutht - \!!depth \strutdp}} + \s!width \zeropoint + \s!height\strutht + \s!depth \strutdp}} \def\spac_struts_set_vide {\setbox\strutbox\hbox - {\hbox to \zeropoint + {\spac_struts_vide_hbox to \zeropoint {% \hss % new, will be option \vrule - \!!width \strutwidth - \!!height\strutht - \!!depth \strutdp + \s!width \strutwidth + \s!height\strutht + \s!depth \strutdp \hss}}} +\let\spac_struts_vide_hbox\hbox % overloaded in trac-vis.mkiv + %D The dimen \type {\struttotal} holds the exact size of the %D strut; occasionally a one scaled point difference can show %D up with the lineheight. @@ -1245,7 +1262,6 @@ \definesystemattribute[skipcategory] [public] \definesystemattribute[skippenalty] [public] \definesystemattribute[skiporder] [public] -\definesystemattribute[displaymath] [public] \definesystemattribute[snapmethod] [public] \definesystemattribute[snapvbox] [public] %definesystemattribute[snapcategory] [public] @@ -1484,7 +1500,7 @@ \ruledvbox \fi} -\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\testrulewidth} +\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} \unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level {\setbox#1\gridboxvbox to #3 % given size @@ -1492,10 +1508,10 @@ \resetteststrut \offinterlineskip \hsize#2% - \baselinerulefalse \ifnum\gridboxlinenomode=\plusthree \gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi \fi + \topskipcorrection \gridboxvbox % calculated size {\getrawnoflines{#3}% \getnoflines{#3}% \scratchdimen\dimexpr#2+\lineheight\relax @@ -1504,17 +1520,17 @@ \hskip-.5\lineheight\relax \ifcase\gridboxlinenomode\or \rlap - {\hskip.2\bodyfontsize\hskip\scratchdimen - \infofont\hbox to 1em{\hss\recurselevel}}% + {\hskip\dimexpr.2\bodyfontsize+\scratchdimen\relax + \infofont\hbox to \emwidth{\hss\recurselevel}}% \or \llap - {\infofont\hbox to 1em{\hss\recurselevel}% + {\infofont\hbox to \emwidth{\hss\recurselevel}% \hskip.2\bodyfontsize}% \fi \vrule - \!!height \gridboxwidth - \!!depth \gridboxwidth - \!!width \scratchdimen + \s!height \gridboxwidth + \s!depth \gridboxwidth + \s!width \scratchdimen \par}} \vfill}} @@ -1587,7 +1603,8 @@ \newtoks\everybeforeblankhandling \newtoks\everyafterblankhandling -\newconditional\someblankdone +\newconditional\c_space_vspacing_done +\newconditional\c_space_vspacing_fixed \appendtoks \s_spac_vspacing_temp\zeropoint @@ -1595,40 +1612,41 @@ \attribute\skippenaltyattribute \attributeunsetvalue \attribute\skiporderattribute \attributeunsetvalue \ifgridsnapping - \settrue\blankisfixed + \settrue\c_space_vspacing_fixed \else - \setfalse\blankisfixed + \setfalse\c_space_vspacing_fixed \fi \to \everybeforeblankhandling \appendtoks \s_spac_vspacing_temp\plusone\s_spac_vspacing_temp - \ifconditional\blankisfixed \else - \!!plus \skipgluefactor\s_spac_vspacing_temp - \!!minus\skipgluefactor\s_spac_vspacing_temp + \ifconditional\c_space_vspacing_fixed \else + \s!plus \skipgluefactor\s_spac_vspacing_temp + \s!minus\skipgluefactor\s_spac_vspacing_temp \fi + \relax \to \everyafterblankhandling \def\setblankcategory#1% - {\settrue\someblankdone + {\settrue\c_space_vspacing_done \attribute\skipcategoryattribute#1\relax} \def\setblankorder#1% {\attribute\skiporderattribute#1\relax} \def\fixedblankskip - {\settrue\blankisfixed} + {\settrue\c_space_vspacing_fixed} \def\flexibleblankskip - {\setfalse\blankisfixed} + {\setfalse\c_space_vspacing_fixed} \def\addblankskip#1#2#3% - {\settrue\someblankdone + {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax} \def\setblankpenalty#1% {\flushblankhandling - \settrue\someblankdone + \settrue\c_space_vspacing_done \attribute\skipcategoryattribute \plusthree \attribute\skippenaltyattribute #1\relax \flushblankhandling} @@ -1646,30 +1664,30 @@ \def\dostartblankhandling {\begingroup - \setfalse\someblankdone + \setfalse\c_space_vspacing_done \the\everybeforeblankhandling} \unexpanded\def\stopblankhandling {\the\everyafterblankhandling - \ifconditional\someblankdone + \ifconditional\c_space_vspacing_done \vskip\s_spac_vspacing_temp \fi \endgroup} \def\flushblankhandling {\the\everyafterblankhandling - \ifconditional\someblankdone + \ifconditional\c_space_vspacing_done \vskip\s_spac_vspacing_temp \fi - \setfalse\someblankdone + \setfalse\c_space_vspacing_done \the\everybeforeblankhandling} \def\addpredefinedblankskip#1#2% - {\settrue\someblankdone + {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax} \def\addaskedblankskip#1#2% - {\settrue\someblankdone + {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr#2\relax} % The main spacer: @@ -1696,13 +1714,13 @@ \fi\fi} \def\spac_vspacing_yes_indeed[#1]% - {\ifmmode\else\ctxcommand{vspacing("#1")}\fi} + {\ifmmode\else\par\ctxcommand{vspacing("#1")}\fi} \def\spac_vspacing_yes_ignore[#1]% {\ifmmode\else\par\fi} \def\spac_vspacing_nop_indeed - {\ifmmode\else\ctxcommand{vspacing("\currentvspacing")}\fi} + {\ifmmode\else\par\ctxcommand{vspacing("\currentvspacing")}\fi} \def\spac_vspacing_nop_ignore {\ifmmode\else\par\fi} @@ -1730,17 +1748,6 @@ \let\synchronizevspacing\setupvspacing_nop -% used both - -\unexpanded\def\inhibitblank - {\vspacing[\v!disable]} % can be made faster - -\let\doinhibitblank\inhibitblank % keep this command, used in styles - -\let\setupblank \setupvspacing -\let\blank \vspacing -\let\synchronizeblank\synchronizevspacing - % category:4 is default % this interface might change (into an \install, buw we will then keep this one hidden) @@ -1790,12 +1797,27 @@ \dorecurse{10} % todo: other values < 4000 {\normalexpanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr4000+250*\recurselevel\relax]}} +\definevspacing[\v!default] [\v!big] % todo: needs to adapt to \setupblank +\definevspacing[\v!before] [\v!default] % but we need to avoid circular references +\definevspacing[\v!inbetween][\v!default] % then +\definevspacing[\v!after] [\v!before] + +\setupvspacing + [\v!big] % alternatively [\v!standard] + %D Maybe at some point we will differ between \type {\vspacing} and %D \type {\blank} (we needed the first one while playing with the %D new code). -\let\blank \vspacing +\unexpanded\def\inhibitblank + {\vspacing[\v!disable]} % can be made faster + +\let\doinhibitblank\inhibitblank % keep this command, used in styles + \let\defineblank \definevspacing +\let\setupblank \setupvspacing +\let\blank \vspacing +\let\synchronizeblank \synchronizevspacing \let\defineblankmethod\definevspacingamount %D The following command is for Wolfgang. It has to be used with @@ -1850,4 +1872,125 @@ \relax \fi} +%D Some preliminary code: a simple and fast hanger, for usage in +%D macros (moved from cont-new). + +\installcorenamespace {hanging} + +\installdirectcommandhandler \??hanging {hanging} + +\setuphanging + [\c!distance=.5em] + +\unexpanded\def\starthanging + {\noindent\bgroup + \dowithnextboxcs\spac_hanging_finish\hbox} + +\def\spac_hanging_finish + {\setbox\nextbox\hbox + {\box\nextbox + \hskip\directhangingparameter\c!distance}% + \hangindent\wd\nextbox + \hangafter\plusone + \box\nextbox + \ignorespaces} + +\unexpanded\def\stophanging + {\endgraf + \egroup} + +\unexpanded\def\starthangaround + {\noindent\bgroup + \dowithnextboxcs\spac_hanging_around_finish\hbox} + +\def\spac_hanging_around_finish + {\ifdim\nextboxht>\strutht + \setbox\nextbox\tbox + {\box\nextbox}% + \fi + \setbox\nextbox\hbox + {\box\nextbox + \hskip\directhangingparameter\c!distance}% + \getboxheight\scratchdimen\of\box\nextbox + \getnoflines\scratchdimen + \ht\nextbox\strutht + \dp\nextbox\strutdp + \hangindent\wd\nextbox + \hangafter-\noflines + \llap{\box\nextbox}% + \ignorespaces} + +\unexpanded\def\stophangaround + {\endgraf + \egroup} + +%D \macros +%D {startfixed} +%D +%D \starttyping +%D \startitemize +%D \startitem \externalfigure[cow][height=1cm] \stopitem +%D \startitem \externalfigure[cow][height=1cm] \stopitem +%D +%D \startitem \startfixed \externalfigure[cow][height=1cm]\stopfixed \stopitem +%D \startitem \startfixed[high]\externalfigure[cow][height=1cm]\stopfixed \stopitem +%D \startitem \startfixed[low] \externalfigure[cow][height=1cm]\stopfixed \stopitem +%D \startitem \startfixed[lohi]\externalfigure[cow][height=1cm]\stopfixed \stopitem +%D +%D \startitem test \par \startfixed \externalfigure[koe][height=1cm]\stopfixed \stopitem +%D \startitem test \par \startfixed[high]\externalfigure[koe][height=1cm]\stopfixed \stopitem +%D \startitem test \par \startfixed[low] \externalfigure[koe][height=1cm]\stopfixed \stopitem +%D \startitem test \par \startfixed[lohi]\externalfigure[koe][height=1cm]\stopfixed \stopitem +%D \stopitemize +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace{fixedalternatives} + +\unexpanded\def\startfixed + {\bgroup + \dosingleempty\typo_fixed_start} + +\def\typo_fixed_start + {\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 + \dowithnextbox{\typo_fixed_finish{#1}}% + \vbox\bgroup + %ignorespaces + \setlocalhsize} + +\unexpanded\def\typo_fixed_stop_h + {%removeunwantedspaces + \egroup + \egroup} + +\def\typo_fixed_start_v[#1]% + {\let\stopfixed\typo_fixed_stop_v + \startbaselinecorrection} + +\unexpanded\def\typo_fixed_stop_v + {\stopbaselinecorrection + \egroup} + +\letvalue{\??fixedalternatives \v!high}\bbox +\letvalue{\??fixedalternatives \v!low}\tbox +\letvalue{\??fixedalternatives \v!middle}\vcenter +\letvalue{\??fixedalternatives \v!lohi}\vcenter +\letvalue{\??fixedalternatives\s!unknown}\tbox +\letvalue{\??fixedalternatives\s!default}\tbox + +\unexpanded\def\typo_fixed_finish#1% + {\expandcheckedcsname\??fixedalternatives{#1}\s!default{\box\nextbox}} + +% %D Forgotten already: +% +% \def\shapefill{\vskip\zeropoint\s!plus\lineheight\s!minus\lineheight\relax} + \protect \endinput diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf Binary files differindex 8d2ac5857..fedf9a077 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex 0d58d1b16..acc1ebe16 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua index d7ab099a6..f8c6c692b 100644 --- a/tex/context/base/status-mkiv.lua +++ b/tex/context/base/status-mkiv.lua @@ -1,1515 +1,5873 @@ --- colo-run.mkiv colo-imp-*.mkiv ... - return { - core = { - { - filename = "syst-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "norm-ctx", - marktype = "mkiv", - status = "okay", - }, - { - filename = "syst-pln", - marktype = "mkiv", - status = "okay", - }, - { - filename = "syst-mes", - marktype = "mkiv", - status = "okay", - }, - { - filename = "luat-cod", - marktype = "mkiv", - status = "okay", - }, - { - filename = "luat-bas", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (3)", - }, - { - filename = "luat-lib", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (3)", - }, - { - filename = "catc-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "catc-act", - marktype = "mkiv", - status = "okay", - comment = "forward dependency", - }, - { - filename = "catc-def", - marktype = "mkiv", - status = "okay", - }, - { - filename = "catc-ctx", - marktype = "mkiv", - status = "okay", - }, - { - filename = "catc-sym", - marktype = "mkiv", - status = "okay", - }, - { - filename = "cldf-ini", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (1)", - }, - { - filename = "syst-aux", - marktype = "mkiv", - status = "okay", - comment = "will be better protected" - }, - { - filename = "syst-lua", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (1)", - }, - { - filename = "syst-con", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (1)", - }, - { - filename = "syst-fnt", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (1)", - }, - { - filename = "syst-rtp", - marktype = "mkiv", - status = "okay", - comment = "maybe combine (1)", - }, - { - filename = "file-ini", - marktype = "mkvi", - status = "okay", - comment = "maybe combine (2)", - }, - { - filename = "file-res", - marktype = "mkvi", - status = "okay", - comment = "maybe combine (2)", - }, - { - filename = "file-lib", - marktype = "mkvi", - status = "okay", - }, - { - filename = "supp-dir", - marktype = "mkiv", - status = "okay", - }, - { - filename = "char-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "char-utf", - marktype = "mkiv", - status = "okay", - }, - { - filename = "char-act", - marktype = "mkiv", - status = "okay", - comment = "forward dependency", - }, - { - filename = "mult-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mult-sys", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mult-def", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mult-chk", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mult-aux", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mult-dim", - marktype = "mkvi", - status = "okay", - }, - { - filename = "cldf-int", - marktype = "mkiv", - status = "okay", - }, - { - filename = "luat-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "toks-ini", - marktype = "mkiv", - status = "okay", - comment = "maybe this becomes a runtime module", - }, - { - filename = "attr-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-var", - marktype = "mkiv", - status = "unknown", - comment = "code might move from here", - }, - { - filename = "core-env", - marktype = "mkiv", - status = "okay", - comment = "might need more redoing", - }, - { - filename = "layo-ini", - marktype = "mkiv", - status = "todo", - comment = "more might move to here", - }, - { - filename = "node-ini", - marktype = "mkiv", - status = "okay", - comment = "maybe this becomes a runtime module", - }, - { - filename = "cldf-bas", - marktype = "mkiv", - status = "okay", - }, - { - filename = "node-fin", - marktype = "mkiv", - status = "okay", - comment = "might need more redoing", - }, - { - filename = "node-mig", - marktype = "mkiv", - status = "okay", - comment = "needs integration and configuration", - }, - { - filename = "node-par", - marktype = "mkiv", - status = "experimental", - }, - { - filename = "back-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "attr-col", - marktype = "mkiv", - status = "okay", - }, - { - filename = "attr-lay", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "attr-neg", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "attr-eff", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "trac-tex", - marktype = "mkiv", - status = "okay", - comment = "needs more usage", - }, - { - filename = "trac-deb", - marktype = "mkiv", - status = "okay", - }, - { - filename = "supp-box", - marktype = "mkiv", - status = "okay", - }, - { - filename = "supp-vis", - marktype = "mkiv", - status = "unknown", - comment = "will become a module (and part will stay in the core)", - }, - { - filename = "supp-fun", - marktype = "mkiv", - status = "unknown", - comment = "will be integrated elsewhere", - }, - { - filename = "supp-ran", - marktype = "mkiv", - status = "okay", - }, - { - filename = "supp-mat", - marktype = "mkiv", - status = "okay", - comment = "will be moved to the math-* modules", - }, - { - filename = "supp-ali", - marktype = "mkiv", - status = "unknown", - comment = "will be reimplemented", - }, - { - filename = "supp-num", - marktype = "mkiv", - status = "obsolete", - comment = "replaced by units", - }, - { - filename = "typo-ini", - marktype = "mkiv", - status = "okay", - comment = "will grow", - }, - { - filename = "page-ins", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "file-syn", - marktype = "mkvi", - status = "okay", - }, - { - filename = "file-mod", - marktype = "mkvi", - status = "okay", - }, - { - filename = "core-con", - marktype = "mkiv", - status = "okay", - }, - { - filename = "cont-fil", - marktype = "mkiv", - status = "okay", - }, - { - filename = "regi-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "enco-ini", - marktype = "mkiv", - status = "messy", - }, - { - filename = "hand-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-lab", - marktype = "mkiv", - status = "okay", - comment = "namespace should be languages", - }, - { - filename = "unic-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-uti", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-two", - marktype = "mkiv", - status = "okay", - comment = "maybe rename to core-two", - }, - { - filename = "core-dat", - marktype = "mkiv", - status = "okay", - }, - { - filename = "colo-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "colo-ext", - marktype = "mkiv", - status = "okay", - }, - { - filename = "colo-grp", - marktype = "mkiv", - status = "okay", - }, - { - filename = "node-bck", - marktype = "mkiv", - status = "okay", - }, - { - filename = "trac-vis", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "lang-mis", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-url", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-def", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-wrd", - marktype = "mkiv", - status = "okay", - }, - { - filename = "file-job", - marktype = "mkvi", - status = "okay", - comment = "might need more redoing", - }, - { - filename = "symb-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "sort-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "pack-mis", - marktype = "mkvi", - status = "okay", - }, - { - filename = "pack-rul", - marktype = "mkiv", - status = "okay", - comment = "namespace to be done", - }, - { - filename = "pack-mrl", - marktype = "mkiv", - status = "todo", - comment = "this is something to be done on a rainy day" - }, - { - filename = "pack-bck", - marktype = "mkvi", - status = "okay", - }, - { - filename = "pack-fen", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lxml-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lxml-sor", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-prc", - marktype = "mkvi", - status = "okay", - }, - { - filename = "strc-ini", - marktype = "mkvi", - status = "okay", - }, - { - filename = "strc-tag", - marktype = "mkiv", - status = "okay", - }, - { - filename = "strc-doc", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-num", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-mar", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-sbe", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-lst", - marktype = "mkiv", - status = "okay", - }, - { - filename = "strc-sec", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-pag", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-ren", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-xml", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-def", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-ref", - marktype = "mkvi", - status = "unknown", - }, - { - filename = "strc-reg", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-lev", - marktype = "mkvi", - status = "okay", - }, - { - filename = "spac-ali", - marktype = "mkiv", - status = "okay", - comment = "maybe some tuning is needed / will happen", - }, - { - filename = "spac-hor", - marktype = "mkiv", - status = "okay", - comment = "probably needs some more work", - }, - { - filename = "spac-ver", - marktype = "mkiv", - status = "okay", - comment = "maybe some changes will happen" - }, - { - filename = "spac-lin", - marktype = "mkiv", - status = "unknown", - comment = "could be improved if needed" - }, - { - filename = "spac-pag", - marktype = "mkiv", - status = "okay", - comment = "this needs to be checked occasionally", - }, - { - filename = "spac-par", - marktype = "mkiv", - status = "okay", - }, - { - filename = "spac-def", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "spac-grd", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "anch-pos", - marktype = "mkiv", - status = "okay", - comment = "in transition", - }, - { - filename = "anch-pgr", - marktype = "mkiv", - status = "okay", - comment = "in transition", - }, - { - filename = "scrn-ini", - marktype = "mkvi", - status = "okay", - comment = "maybe change locationattribute names" - }, - { - filename = "scrn-ref", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "pack-obj", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-itm", - marktype = "mkvi", - status = "okay", - }, - { - filename = "strc-des", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-des", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-enu", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-ind", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-lab", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "core-sys", - marktype = "mkiv", - status = "okay", - comment = "a funny mix", - }, - { - filename = "page-var", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-otr", - marktype = "mkvi", - status = "okay", - }, - { - filename = "page-ini", - marktype = "mkiv", - status = "okay", - comment = "code might end up elsewhere", - }, - { - filename = "page-fac", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-brk", - marktype = "mkiv", - status = "okay", - comment = "otr commands will be redone", - }, - { - filename = "page-col", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-inf", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-grd", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-flt", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-bck", - marktype = "mkiv", - status = "okay", - }, - { - filename = "page-not", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-one", - marktype = "mkiv", - status = "okay", - comment = "can probably be improved", - }, - { - filename = "page-lay", - marktype = "mkiv", - status = "okay", - }, - { - filename = "page-box", - marktype = "mkvi", - status = "okay", - }, - { - filename = "page-txt", - marktype = "mkvi", - status = "okay", - }, - { - filename = "page-sid", - marktype = "mkiv", - status = "okay", - }, - { - filename = "strc-flt", - marktype = "mkvi", - status = "unknown", - }, - { - filename = "page-mis", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-mbk", - marktype = "mkvi", - status = "okay", - comment = "might be extended", - }, - { - filename = "page-mul", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-set", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "pack-lyr", - marktype = "mkiv", - status = "okay", - }, - { - filename = "pack-pos", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-mak", - marktype = "mkvi", - status = "okay", - }, - { - filename = "page-lin", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-par", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "typo-pag", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-mar", - marktype = "mkiv", - status = "okay", - }, - { - filename = "buff-ini", - marktype = "mkiv", - status = "okay", - comment = "check other modules for buffer usage", - }, - { - filename = "buff-ver", - marktype = "mkiv", - status = "okay", - comment = "check obsolete processbuffer" - }, - { - filename = "buff-par", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "buff-imp-tex", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "buff-imp-mp", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "buff-imp-lua", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "buff-imp-xml", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "buff-imp-parsed-xml", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-blk", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-imp", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-sel", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-com", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "scrn-pag", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "scrn-wid", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "scrn-but", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "scrn-bar", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "strc-bkm", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-com", - marktype = "mkiv", - status = "okay", - comment = "somewhat weird", - }, - { - filename = "tabl-pln", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-tab", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-tbl", - marktype = "mkiv", - status = "okay", - comment = "can probably be improved (names and such)", - }, - { - filename = "tabl-ntb", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-nte", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-ltb", - marktype = "mkiv", - status = "unknown", - comment = "will be redone when needed", - }, - { - filename = "tabl-tsp", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "tabl-xtb", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "java-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "scrn-fld", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "scrn-hlp", - marktype = "mkvi", - status = "okay", - comment = "namespace needs checking" - }, - { - filename = "char-enc", - marktype = "mkiv", - status = "okay", - }, - { - filename = "font-lib", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-fil", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-fea", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-mat", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-ini", - marktype = "mkvi", - status = "okay", - comment = "needs occasional checking and upgrading", - }, - { - filename = "font-sym", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-sty", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-set", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-emp", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-col", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-pre", - marktype = "mkiv", - status = "okay", - }, - { - filename = "font-unk", - marktype = "mkiv", - status = "okay", - }, - { - filename = "font-tra", - marktype = "mkiv", - status = "okay", - comment = "likely this will become a module", - }, - { - filename = "font-uni", - marktype = "mkiv", - status = "okay", - comment = "this one might be merged", - }, - { - filename = "font-col", - marktype = "mkvi", - status = "okay", - }, - { - filename = "font-gds", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lxml-css", - marktype = "mkiv", - status = "okay", - comment = "this is work in progress", - }, - { - filename = "spac-chr", - marktype = "mkiv", - status = "okay", - }, - { - filename = "blob-ini", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "typo-cln", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-spa", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-krn", - marktype = "mkiv", - status = "okay", - comment = "do we keep the style and color or not" - }, - { - filename = "typo-itc", - marktype = "mkvi", - status = "okay", - }, - { - filename = "typo-dir", - marktype = "mkiv", - status = "okay", - comment = "maybe singular setup" - }, - { - filename = "typo-brk", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-cap", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-dig", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-rep", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-txt", - marktype = "mkvi", - status = "okay", - comment = "maybe there will be a nicer interface", - }, - { - filename = "typo-par", - marktype = "mkiv", - status = "okay", - comment = "might get extended", - }, - { - filename = "type-ini", - marktype = "mkvi", - status = "okay", - }, - { - filename = "type-set", - marktype = "mkiv", - status = "okay", - }, - { - filename = "scrp-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "prop-ini", - marktype = "mkiv", - status = "okay", - comment = "this module is obsolete", - }, - { - filename = "mlib-ctx", - marktype = "mkiv", - status = "okay", - }, - { - filename = "meta-ini", - marktype = "mkiv", - status = "okay", - comment = "metapost code is always evolving", - }, - { - filename = "meta-tex", - marktype = "mkiv", - status = "okay", - }, - { - filename = "meta-fun", - marktype = "mkiv", - status = "okay", - comment = "maybe this one will be merged" - }, - { - filename = "meta-pag", - marktype = "mkiv", - status = "okay", - comment = "might get updated when mp code gets cleaned up", - }, - { - filename = "page-mrk", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-flw", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-spr", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-plg", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-str", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "anch-pgr", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "anch-bck", - marktype = "mkvi", - status = "unknown", - }, - { - filename = "anch-tab", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "anch-bar", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "anch-snc", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "math-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "math-pln", - marktype = "mkiv", - status = "okay", - comment = "this file might merge into others", - }, - { - filename = "math-for", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "math-def", - marktype = "mkiv", - status = "okay", - comment = "eventually this will be split and spread", - }, - { - filename = "math-ali", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "math-arr", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "math-frc", - marktype = "mkiv", - status = "okay", - comment = "at least for the moment", - }, - { - filename = "math-scr", - marktype = "mkiv", - status = "okay", - }, - { - filename = "math-int", - marktype = "mkiv", - status = "okay", - }, - { - filename = "math-del", - marktype = "mkiv", - status = "okay", - comment = "code get replaced (by autodelimiters)", - }, - { - filename = "math-inl", - marktype = "mkiv", - status = "okay", - comment = "code might move to here", - }, - { - filename = "math-dis", - marktype = "mkiv", - status = "okay", - comment = "code might move to here", - }, - { - filename = "phys-dim", - marktype = "mkiv", - status = "okay", - }, - { - filename = "strc-mat", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "chem-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "chem-str", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-scr", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-fnt", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "node-rul", - marktype = "mkiv", - status = "okay", - comment = "maybe some cleanup is needed", - }, - { - filename = "node-spl", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-not", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "strc-lnt", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "core-mis", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "pack-com", - marktype = "mkiv", - status = "okay", - }, - { - filename = "typo-del", - marktype = "mkiv", - status = "okay", - }, - { - filename = "grph-trf", - marktype = "mkiv", - status = "okay", - comment = "namespace has to be made consistent" - }, - { - filename = "grph-inc", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "grph-fig", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "grph-raw", - marktype = "mkiv", - status = "okay", - }, - { - filename = "pack-box", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "pack-bar", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "page-app", - marktype = "mkiv", - status = "okay", - }, - { - filename = "meta-fig", - marktype = "mkiv", - status = "okay", - }, - { - filename = "lang-spa", - marktype = "mkiv", - status = "okay", - comment = "more or less obsolete" - }, - { - filename = "bibl-bib", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "bibl-tra", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "meta-xml", - marktype = "mkiv", - status = "okay", - comment = "not needed" - }, - { - filename = "cont-log", - marktype = "mkiv", - status = "okay", - }, - { - filename = "task-ini", - marktype = "mkiv", - status = "okay", - }, - { - filename = "cldf-ver", - marktype = "mkiv", - status = "okay", - }, - { - filename = "cldf-com", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-ctx", - marktype = "mkiv", - status = "okay", - }, - { - filename = "core-ini", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "core-def", - marktype = "mkiv", - status = "unknown", - }, - { - filename = "back-pdf", - marktype = "mkiv", - status = "okay", - comment = "object related code might move or change", - }, - { - filename = "mlib-pdf", - marktype = "mkiv", - status = "okay", - }, - { - filename = "mlib-pps", - marktype = "mkiv", - status = "okay", - }, - { - filename = "meta-pdf", - marktype = "mkiv", - status = "okay", - }, - { - filename = "grph-epd", - marktype = "mkiv", - status = "okay", - comment = "might need more work", - }, - { - filename = "back-exp", - marktype = "mkiv", - status = "okay", - comment = "some parameters might move from export to backend" - }, - }, - extra = { - { - filename = "tabl-xnt", - marktype = "mkvi", - status = "okay", - }, - } + todo = { + category = "lua", + filename = "core-run", + status = "idea", + }, + main = { + { + category = "mkiv", + filename = "context", + loading = "parent", + status = "okay", + }, + { + category = "lus", + comment = "stub file for context", + filename = "context", + loading = "parent", + status = "okay", + }, + { + category = "tex", + filename = "metatex", + loading = "parent", + status = "pending", + }, + { + category = "lus", + comment = "stub file for metatex", + filename = "metatex", + loading = "parent", + status = "pending", + }, + { + category = "mkiv", + filename = "cont-cs", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-de", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-en", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-fr", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-gb", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-it", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-nl", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-pe", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-ro", + loading = "parent", + status = "okay", + }, + { + category = "mpiv", + comment = "maybe more delayed loading", + filename = "metafun", + loading = "parent", + status = "okay", + }, + { + category = "mkiv", + comment = "we keep this around for historic reasons", + filename = "ppchtex", + loading = "never", + status = "okay", + }, + }, + core = { + { + category = "mkiv", + filename = "syst-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "norm-ctx", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "syst-pln", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "syst-mes", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "luat-cod", + loading = "luat-cod", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (3)", + filename = "luat-bas", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (3)", + filename = "luat-lib", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "catc-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "forward dependency", + filename = "catc-act", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "catc-def", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "catc-ctx", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "catc-sym", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "catc-xml", + loading = "module", + status = "okay", + comment = "only needed for mkii xml parser", + }, + { + category = "mkiv", + comment = "maybe combine (1)", + filename = "cldf-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "syst-aux", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (1)", + filename = "syst-lua", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (1)", + filename = "syst-con", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (1)", + filename = "syst-fnt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe combine (1)", + filename = "syst-rtp", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe combine (2)", + filename = "file-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe combine (2)", + filename = "file-res", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "file-lib", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "supp-dir", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "char-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "char-utf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "forward dependency", + filename = "char-act", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mult-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mult-sys", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mult-aux", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mult-def", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mult-chk", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "mult-dim", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cldf-int", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "luat-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe this becomes a runtime module", + filename = "toks-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "attr-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code might move from here", + filename = "core-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might need more redoing", + filename = "core-env", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "in due time more might move to here", + filename = "layo-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe this becomes a runtime module", + filename = "node-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe use context.generics/context.sprint here", + filename = "cldf-bas", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might need more redoing", + filename = "node-fin", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs integration and configuration", + filename = "node-mig", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-bld", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "node-pag", + loading = "never", + status = "okay", + }, + { + category = "mkiv", + filename = "back-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "attr-col", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "attr-lay", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "attr-neg", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "attr-eff", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs more usage", + filename = "trac-tex", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "trac-deb", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "trac-ctx", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "supp-box", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "supp-ran", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be moved to the math-* modules", + filename = "supp-mat", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will grow", + filename = "typo-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "file-syn", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "file-mod", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "core-con", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-fil", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-nop", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-yes", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "regi-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "enco-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "hand-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "namespace should be languages", + filename = "lang-lab", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "unic-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "core-uti", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe rename to core-two", + filename = "core-two", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "core-dat", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-ext", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-grp", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "node-bck", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-cut", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-mis", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-url", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-def", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-frq", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-frd", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "lang-wrd", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "might need more redoing", + filename = "file-job", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "sort-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "pack-mis", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-rul", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "endpar experimental code", + filename = "pack-mrl", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "pack-bck", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-fen", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lxml-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "lxml-sor", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "typo-prc", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "strc-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-tag", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this module migh tgo away when code has been moved", + filename = "strc-doc", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "still some rough edges", + filename = "strc-num", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-mar", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-sbe", + loading = "always", + status = "okay", + }, + { + category = "mkvI", + filename = "strc-lst", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "some of the local current and synchronization macros will be renamed", + filename = "strc-sec", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-pag", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "(support for) setups might get improved", + filename = "strc-ren", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this module might go away", + filename = "strc-xml", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-def", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "some more low level names might change", + filename = "strc-ref", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "use setups for rendering", + filename = "strc-reg", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "strc-lev", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe some tuning is needed / will happen", + filename = "spac-ali", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "probably needs some more work", + filename = "spac-hor", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe some changes will happen", + filename = "spac-ver", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "could be improved if needed", + filename = "spac-lin", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this needs to be checked occasionally", + filename = "spac-pag", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "spac-par", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "spac-def", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "needs thinking and redoing", + filename = "spac-grd", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "in transition", + filename = "anch-pos", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe change locationattribute names", + filename = "scrn-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-ref", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will change when we have objects at lua end", + filename = "pack-obj", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "strc-itm", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe more common counter code here and setups need to be improved", + filename = "strc-con", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "strc-des", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "(interactive) coupling is not yet working", + filename = "strc-enu", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-ind", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs to be adapted when strc-con/des/enu changes", + filename = "strc-lab", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-syn", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "a funny mix", + filename = "core-sys", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-var", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "page-otr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code might end up elsewhere", + filename = "page-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "dealing with insertions might change", + filename = "page-ins", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-fac", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "otr commands will be redone", + filename = "page-brk", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "helpers for columns", + filename = "page-col", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "room for improvement and extension", + filename = "page-inf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-grd", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be extended when columns are redone", + filename = "page-flt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-bck", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-not", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "can probably be improved", + filename = "page-one", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-lay", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "page-box", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "a few things left", + filename = "page-txt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-sid", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "in due time we need a further cleanup", + filename = "strc-flt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-pst", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "might be extended", + filename = "page-mbk", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be reimplemented", + filename = "page-mul", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "work in progress", + filename = "page-mix", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + comment = "will be reimplemented", + filename = "page-set", + loading = "always", + status = "todo", + }, + { + category = "mkiv", + filename = "pack-lyr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-pos", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "page-mak", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will probably be overhauled some day", + filename = "page-lin", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might get extended", + filename = "page-par", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-pag", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-mar", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-itm", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "check other modules for buffer usage", + filename = "buff-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "check obsolete processbuffer", + filename = "buff-ver", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "experimental code", + filename = "buff-par", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-tex", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-mp", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-lua", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-xml", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-parsed-xml", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-default", + loading = "indirect", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-escaped", + loading = "indirect", + status = "okay", + }, + { + category = "mkiv", + filename = "buff-imp-nested", + loading = "indirect", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-blk", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-imp", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe some extensions and delayed loading, needs checking", + filename = "page-sel", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-com", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-pag", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "functionality needs checking", + filename = "scrn-wid", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-but", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-bar", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "strc-bkm", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "somewhat weird", + filename = "tabl-com", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "unchecked", + filename = "tabl-pln", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "tabl-tab", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + comment = "can probably be improved (names and such)", + filename = "tabl-tbl", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "frozen functionaly so no drastic cleanup", + filename = "tabl-ntb", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "tabl-mis", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "tabl-nte", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be redone when needed", + filename = "tabl-ltb", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + comment = "will be adapted when needed (and rest is done)", + filename = "tabl-tsp", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "tabl-xtb", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "tabl-xnt", + loading = "module", + status = "okay", + loading = "always", + comment = "only when natural tables need a replacement", + }, + { + category = "mkiv", + filename = "java-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-fld", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "namespace needs checking", + filename = "scrn-hlp", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "char-enc", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-lib", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-fil", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-var", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-fea", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-mat", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "needs occasional checking and upgrading", + filename = "font-ini", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-sym", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-sty", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-set", + status = "okay", + }, + { + category = "mkvi", + filename = "font-emp", + status = "okay", + }, + { + category = "mkvi", + filename = "font-col", + status = "okay", + }, + { + category = "mkiv", + filename = "font-pre", + status = "okay", + }, + { + category = "mkiv", + filename = "font-unk", + status = "okay", + }, + { + category = "mkiv", + comment = "likely this will become a module", + filename = "font-tra", + status = "okay", + }, + { + category = "mkiv", + comment = "this could become a module", + filename = "font-chk", + status = "okay", + }, + { + category = "mkiv", + comment = "this one might be merged", + filename = "font-uni", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-col", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-gds", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "font-aux", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this is work in progress", + filename = "lxml-css", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "spac-chr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "spac-cha", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "work in progress", + filename = "blob-ini", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + filename = "trac-vis", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "trac-vis", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-cln", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-spa", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "do we keep the style and color or not", + filename = "typo-krn", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "typo-itc", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe singular setup", + filename = "typo-dir", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-brk", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-cap", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-dig", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-rep", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "maybe there will be a nicer interface", + filename = "typo-txt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might get extended", + filename = "typo-par", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + filename = "type-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "type-set", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "type-def", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-fbk", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-lua", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-one", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-otf", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-siz", + loading = "type-set", + status = "okay", + }, + { + category = "mkiv", + filename = "type-tmf", + loading = "never", + status = "okay", + comment = "placeholder to prevent other loading", + }, + { + category = "mkiv", + filename = "scrp-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this module is obsolete", + filename = "prop-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mlib-ctx", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "metapost code is always evolving", + filename = "meta-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code used in a project", + filename = "meta-lua", + loading = "experimental", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-tex", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe this one will be merged", + filename = "meta-fun", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might get updated when mp code gets cleaned up", + filename = "meta-pag", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-grd", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-mrk", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-flw", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-spr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be made better", + filename = "page-plg", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs more work (and thinking)", + filename = "page-str", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "in transition", + filename = "anch-pgr", + loading = "always", + status = "okay", + }, + { + category = "mkvi", + comment = "in transition", + filename = "anch-bck", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will stay experimental for a while", + filename = "anch-tab", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "anch-bar", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "interesting old mechanism to keep around (module?)", + filename = "anch-snc", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + filename = "math-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "this file might merge into others", + filename = "math-pln", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "math-for", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "eventually this will be split and spread", + filename = "math-def", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will be checked and improved", + filename = "math-ali", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs testing", + filename = "math-arr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "at least for the moment", + filename = "math-frc", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "math-scr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "math-int", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code get replaced (by autodelimiters)", + filename = "math-del", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code might move to here", + filename = "math-inl", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "code might move to here", + filename = "math-dis", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "phys-dim", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "some more functionality will end up here", + filename = "strc-mat", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "chem-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "chem-str", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-scr", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "maybe some cleanup is needed", + filename = "node-rul", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "needs testing", + filename = "font-sol", + loading = "always", + status = "okay", + }, + { + category = "mkvI", + filename = "strc-not", + loading = "always", + status = "todo", + }, + { + category = "mkvi", + comment = "will be extended as part of crited", + filename = "strc-lnt", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-com", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "typo-del", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "grph-trf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "grph-inc", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "grph-fig", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "grph-raw", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-box", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "pack-bar", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "page-app", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-fig", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "more or less obsolete", + filename = "lang-spa", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "bibl-bib", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + filename = "bibl-tra", + loading = "always", + status = "pending", + }, + { + category = "mkiv", + comment = "not needed", + filename = "meta-xml", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cont-log", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "task-ini", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cldf-ver", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "cldf-com", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "core-ctx", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "will always be messy", + filename = "core-def", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "object related code might move or change", + filename = "back-pdf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "back-swf", + loading = "never", + status = "okay", + comment = "no code, just an example of usage", + }, + { + category = "mkiv", + filename = "back-u3d", + loading = "never", + status = "okay", + comment = "no code, just an example of usage", + }, + { + category = "mkiv", + filename = "mlib-pdf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "mlib-pps", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-pdf", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "might need more work", + filename = "grph-epd", + loading = "always", + status = "okay", + }, + { + category = "mkiv", + comment = "some parameters might move from export to backend", + filename = "back-exp", + loading = "always", + status = "okay", + }, + }, + extras = { + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-arrange", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-combine", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-common", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-ideas", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-listing", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-markdown", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-select", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + comment = "add-on for mtx-context", + filename = "mtx-context-timing", + loading = "on demand", + status = "okay", + }, + }, + implementations = { + { + category = "mkiv", + filename = "colo-imp-dem", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-imp-ema", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-imp-rgb", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-imp-x11", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "colo-imp-xwi", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "java-imp-exa", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "java-imp-fil", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "java-imp-fld", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "java-imp-rhh", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "java-imp-stp", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-clp", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-dum", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-fen", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-mis", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-nav", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-pre", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "meta-imp-txt", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-cow", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-eur", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-jmn", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-mis", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-mvs", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "symb-imp-nav", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-antykwa", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-antykwapoltawskiego", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-asana", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-averia", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-buy", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-cambria", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-charter", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-cleartype", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-computer-modern-unicode", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-cow", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-dejavu", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-euler", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-ghz", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-hgz", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-husayni", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-hvmath", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-inconsolata", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-informal", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-iwona", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-kurier", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-latinmodern", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-liberation", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-libertine", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-lmnames", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-lucida-opentype", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-lucida-typeone", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-mathdesign", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-mathtimes", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-mscore", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-osx", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-postscript", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-punknova", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-texgyre", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-unfonts", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-xits", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-imp-xitsbidi", + loading = "on demand", + status = "okay", + }, + }, + lua = { + { + category = "lua", + filename = "anch-pgr", + loading = "anch-pgr", + status = "okay", + }, + { + category = "lua", + filename = "anch-pos", + loading = "anch-pos", + status = "okay", + }, + { + category = "lua", + filename = "attr-col", + loading = "attr-col", + status = "okay", + }, + { + category = "lua", + filename = "attr-eff", + loading = "attr-eff", + status = "okay", + }, + { + category = "lua", + filename = "attr-ini", + loading = "attr-ini", + status = "okay", + }, + { + category = "lua", + filename = "attr-lay", + loading = "attr-lay", + status = "okay", + }, + { + category = "lua", + filename = "attr-neg", + loading = "attr-neg", + status = "okay", + }, + { + category = "lua", + comment = "experimental code, maybe some will move elsewhere", + filename = "back-exp", + loading = "back-exp", + status = "pending", + }, + { + category = "lua", + filename = "back-ini", + loading = "back-ini", + status = "okay", + }, + { + category = "lua", + filename = "back-pdf", + loading = "back-pdf", + status = "okay", + }, + { + category = "lua", + filename = "bibl-bib", + status = "todo", + }, + { + category = "lua", + filename = "bibl-tra", + status = "todo", + }, + { + category = "lua", + filename = "blob-ini", + status = "todo", + }, + { + category = "lua", + filename = "buff-imp-default", + loading = "buff-imp-default", + status = "okay", + }, + { + category = "lua", + filename = "buff-imp-escaped", + loading = "buff-imp-escaped", + status = "okay", + }, + { + category = "lua", + comment = "todo: colorization and nesting as in scite", + filename = "buff-imp-lua", + loading = "buff-imp-lua", + status = "okay", + }, + { + category = "lua", + comment = "todo: colorization and nesting as in scite", + filename = "buff-imp-mp", + loading = "buff-imp-mp", + status = "okay", + }, + { + category = "lua", + filename = "buff-imp-nested", + loading = "buff-imp-nested", + status = "okay", + }, + { + category = "lua", + filename = "buff-imp-parsed-xml", + loading = "buff-imp-parsed-xml", + status = "okay", + }, + { + category = "lua", + comment = "todo: colorization and nesting as in scite", + filename = "buff-imp-tex", + loading = "buff-imp-tex", + status = "okay", + }, + { + category = "lua", + comment = "todo: colorization and nesting as in scite", + filename = "buff-imp-xml", + loading = "buff-imp-xml", + status = "okay", + }, + { + category = "lua", + filename = "buff-ini", + status = "okay", + }, + { + category = "lua", + filename = "buff-par", + status = "okay", + }, + { + category = "lua", + comment = "maybe we will provide a few more (nesting) methods", + filename = "buff-ver", + status = "okay", + }, + { + category = "lua", + filename = "catc-ini", + loading = "catc-ini", + status = "okay", + }, + { + category = "lua", + filename = "char-cjk", + loading = "char-ini", + status = "okay", + }, + { + category = "lua", + filename = "char-def", + loading = "char-ini", + status = "okay", + }, + { + category = "lua", + comment = "maybe dataonly", + filename = "char-enc", + loading = "char-enc", + status = "okay", + }, + { + category = "lua", + filename = "char-ent", + loading = "char-ent", + status = "okay", + }, + { + category = "lua", + comment = "maybe move blocks table to separate (dataonly) file", + filename = "char-ini", + loading = "char-ini", + status = "okay", + }, + { + category = "lua", + filename = "char-map", + loading = "char-ini", + status = "okay", + }, + { + category = "lua", + filename = "char-tex", + loading = "char-ini", + status = "okay", + }, + { + category = "lua", + filename = "char-utf", + loading = "char-utf", + status = "okay", + }, + { + category = "lua", + filename = "chem-ini", + loading = "chem-ini", + status = "okay", + }, + { + category = "lua", + filename = "chem-str", + loading = "chem-str", + status = "okay", + }, + { + category = "lua", + comment = "will be extended and can be optimized if needed", + filename = "cldf-bas", + loading = "cldf-bas", + status = "okay", + }, + { + category = "lua", + comment = "might change or even go away", + filename = "cldf-com", + loading = "cldf-com", + status = "okay", + }, + { + category = "lua", + filename = "cldf-ini", + loading = "cldf-ini", + status = "okay", + }, + { + category = "lua", + filename = "cldf-int", + loading = "cldf-int", + status = "pending", + }, + { + category = "lua", + comment = "maybe this code can be redone more efficiently/robust", + filename = "cldf-ver", + loading = "cldf-ver", + status = "pending", + }, + { + category = "lua", + comment = "also used in mtx-*", + filename = "colo-icc", + loading = "colo-ini", + status = "okay", + }, + { + category = "lua", + filename = "colo-ini", + loading = "colo-ini", + status = "okay", + }, + { + category = "lua", + comment = "this code might move to a module", + filename = "colo-run", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "core-con", + loading = "core-con", + status = "okay", + }, + { + category = "lua", + filename = "core-ctx", + loading = "core-ctx", + status = "okay", + }, + { + category = "lua", + filename = "core-dat", + loading = "core-dat", + status = "okay", + }, + { + category = "lua", + comment = "maybe abusing the tex namespace is wrong", + filename = "core-env", + loading = "core-env", + status = "okay", + }, + { + category = "lua", + filename = "core-sys", + loading = "core-sys", + status = "okay", + }, + { + category = "lua", + commands = "this is in fact replaced by core-dat", + filename = "core-two", + loading = "core-two", + status = "okay", + }, + { + category = "lua", + comment = "some code will move to better places", + filename = "core-uti", + loading = "core-uti", + status = "pending", + }, + { + category = "lua", + filename = "data-aux", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-bin", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-con", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-crl", + loading = "never", + status = "todo", + }, + { + category = "lua", + filename = "data-ctx", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-env", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-exp", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-fil", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-gen", + status = "todo", + }, + { + category = "lua", + filename = "data-ini", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-inp", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-lst", + status = "todo", + }, + { + category = "lua", + filename = "data-lua", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-met", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-out", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-pre", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-res", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-sch", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-tex", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-tmf", + status = "todo", + }, + { + category = "lua", + filename = "data-tmp", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-tre", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-use", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-vir", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "data-zip", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "file-ini", + loading = "file-ini", + status = "okay", + }, + { + category = "lua", + filename = "file-job", + loading = "file-job", + status = "okay", + }, + { + category = "lua", + filename = "file-lib", + loading = "file-lib", + status = "okay", + }, + { + category = "lua", + filename = "file-mod", + loading = "file-mod", + status = "okay", + }, + { + category = "lua", + filename = "file-res", + loading = "file-res", + status = "okay", + }, + { + category = "lua", + filename = "file-syn", + loading = "file-syn", + status = "okay", + }, + { + category = "lua", + filename = "font-afm", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-afk", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "only used in luatex-fonts", + filename = "font-age", + loading = "never", + status = "okay", + }, + { + category = "lua", + filename = "font-agl", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + comment = "needs some documentation in usage", + filename = "font-aux", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "move more to the commands namespace", + filename = "font-chk", + loading = "font-chk", + status = "okay", + }, + { + category = "lua", + filename = "font-cid", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-col", + loading = "font-col", + status = "okay", + }, + { + category = "lua", + filename = "font-con", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "will be improved over time", + filename = "font-ctx", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-def", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "part of this code is obsolete", + filename = "font-enc", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "needs documentation at the tex end", + filename = "font-enh", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "maybe some data tables can be be external", + filename = "font-ext", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "okay but can be improved", + filename = "font-fbk", + loading = "font-lib", + status = "pending", + }, + { + category = "lua", + filename = "font-gds", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-ini", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-ldr", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "font-log", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "currently rather minimalistic", + filename = "font-lua", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "the lum file support will be dropped / no map files anyway", + filename = "font-map", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-mis", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + comment = "when more scripts are supported we might end up with imp files", + filename = "font-ota", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otb", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otc", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otd", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otf", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-oth", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-oti", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otn", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-otp", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-ott", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + comment = "is mostly replaced by lfg files", + filename = "font-pat", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-sol", + loading = "font-sol", + status = "okay", + }, + { + category = "lua", + comment = "also loaded on demand", + filename = "font-syn", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-tfm", + loading = "font-lib", + status = "okay", + }, + { + category = "lua", + filename = "font-vf", + loading = "font-lib", + status = "pending", + }, + { + category = "lua", + filename = "grph-epd", + loading = "grph-epd", + status = "okay", + }, + { + category = "lua", + filename = "grph-fil", + loading = "grph-inc", + status = "okay", + }, + { + category = "lua", + filename = "grph-inc", + loading = "grph-inc", + status = "todo", + }, + { + category = "lua", + filename = "grph-raw", + loading = "grph-raw", + status = "okay", + }, + { + category = "lua", + filename = "grph-swf", + loading = "grph-swf", + status = "okay", + }, + { + category = "lua", + filename = "grph-u3d", + loading = "grph-u3d", + status = "okay", + }, + { + category = "lua", + comment = "experiment with graphic magick library", + filename = "grph-wnd", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "java-ini", + loading = "java-ini", + status = "okay", + }, + { + category = "lua", + filename = "l-boolean", + status = "todo", + }, + { + category = "lua", + filename = "l-dir", + status = "todo", + }, + { + category = "lua", + filename = "l-file", + status = "todo", + }, + { + category = "lua", + filename = "l-io", + status = "todo", + }, + { + category = "lua", + filename = "l-lpeg", + status = "todo", + }, + { + category = "lua", + filename = "l-math", + status = "todo", + }, + { + category = "lua", + filename = "l-md5", + status = "todo", + }, + { + category = "lua", + filename = "l-number", + status = "todo", + }, + { + category = "lua", + filename = "l-os", + status = "todo", + }, + { + category = "lua", + filename = "l-pdfview", + status = "todo", + }, + { + category = "lua", + filename = "l-set", + status = "todo", + }, + { + category = "lua", + filename = "l-string", + status = "todo", + }, + { + category = "lua", + filename = "l-table", + status = "todo", + }, + { + category = "lua", + filename = "l-unicode", + status = "todo", + }, + { + category = "lua", + filename = "l-url", + status = "todo", + }, + { + category = "lua", + filename = "l-xml", + status = "todo", + }, + { + category = "lua", + filename = "lang-def", + loading = "lang-def", + status = "okay", + }, + { + category = "lua", + filename = "lang-ini", + loading = "lang-ini", + status = "okay", + }, + { + category = "lua", + filename = "lang-lab", + loading = "lang-lab", + status = "okay", + }, + { + category = "lua", + filename = "lang-txt", + loading = "lang-lab", + status = "okay", + }, + { + category = "lua", + comment = "maybe another approach is nicer", + filename = "lang-url", + loading = "lang-url", + status = "pending", + }, + { + category = "lua", + filename = "lang-wrd", + loading = "lang-wrd", + status = "okay", + }, + { + category = "lua", + comment = "more will end up here", + filename = "layo-ini", + loading = "layo-ini", + status = "okay", + }, + { + category = "lua", + filename = "lpdf-ano", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-col", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-enc", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-epa", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-epd", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-fld", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-fmt", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-grp", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-ini", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-mis", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-mov", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-nod", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-ren", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-swf", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-tag", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-u3d", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-wid", + status = "todo", + }, + { + category = "lua", + filename = "lpdf-xmp", + status = "todo", + }, + { + category = "lua", + comment = "replacement code for wd/ht/dp", + filename = "luat-bwc", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-cbk", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-cnf", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + comment = "maybe some code should move", + filename = "luat-cod", + loading = "luat-cod", + status = "okay", + }, + { + category = "lua", + filename = "luat-env", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-exe", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-fio", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-fmt", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + comment = "will be upgraded when we have Lua 5.2", + filename = "luat-ini", + loading = "luat-lib", + status = "pending", + }, + { + category = "lua", + filename = "luat-iop", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + comment = "this is likely to change some day", + filename = "luat-lua", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-mac", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "luat-run", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + comment = "related to the socket code", + filename = "luat-soc", + loading = "on demand", + status = "pending", + }, + { + category = "lua", + filename = "luat-sta", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "luat-sto", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "lxml-aux", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "lxml-css", + status = "todo", + }, + { + category = "lua", + filename = "lxml-ctx", + status = "todo", + }, + { + category = "lua", + filename = "lxml-dir", + status = "todo", + }, + { + category = "lua", + filename = "lxml-ent", + status = "todo", + }, + { + category = "lua", + filename = "lxml-inf", + status = "todo", + }, + { + category = "lua", + filename = "lxml-lpt", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "lxml-mis", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "lxml-sor", + status = "todo", + }, + { + category = "lua", + filename = "lxml-tab", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "lxml-tex", + status = "todo", + }, + { + category = "lua", + filename = "lxml-xml", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "m-chart", + status = "todo", + }, + { + category = "lua", + filename = "m-database", + status = "todo", + }, + { + category = "lua", + filename = "m-markdown", + status = "todo", + }, + { + category = "lua", + filename = "m-pstricks", + status = "todo", + }, + { + category = "lua", + filename = "m-spreadsheet", + status = "todo", + }, + { + category = "lua", + filename = "m-steps", + status = "todo", + }, + { + category = "lua", + filename = "math-act", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + comment = "could be made look nicer, but who cares", + filename = "math-dim", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + comment = "the code is related to math-vfu", + filename = "math-ext", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-fbk", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + comment = "okay, but we might have a few more low level definers some day", + filename = "math-ini", + loading = "math-ini", + status = "pending", + }, + { + category = "lua", + filename = "math-map", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-noa", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-ren", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-tag", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-ttv", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + filename = "math-vfu", + loading = "math-ini", + status = "okay", + }, + { + category = "lua", + comment = "this is just a first version", + filename = "meta-fun", + loading = "meta-fun", + status = "okay", + }, + { + category = "lua", + filename = "meta-ini", + loading = "meta-ini", + status = "okay", + }, + { + category = "lua", + filename = "meta-lua", + loading = "meta-lua", + status = "okay", + }, + { + category = "lua", + comment = "could be done nicer nowadays but who needs it", + filename = "meta-pdf", + loading = "meta-pdf", + status = "okay", + }, + { + category = "lua", + filename = "meta-pdh", + loading = "meta-pdh", + status = "okay", + loading = "never", + comment = "this is historic code that we keep around", + }, + { + category = "lua", + filename = "meta-tex", + loading = "meta-tex", + status = "okay", + }, + { + category = "lua", + filename = "mlib-ctx", + loading = "mlib-ctx", + status = "okay", + }, + { + category = "lua", + filename = "mlib-pdf", + loading = "mlib-pdf", + status = "okay", + }, + { + category = "lua", + filename = "mlib-pps", + loading = "mlib-pdf", + status = "okay", + }, + { + category = "lua", + filename = "mlib-run", + loading = "mlib-ctx", + status = "okay", + }, + { + category = "lua", + comment = "this is an experiment, namespaces need to be dealt with properly", + filename = "mult-aux", + loading = "mult-aux", + status = "pending", + }, + { + category = "lua", + comment = "this is an experiment", + filename = "mult-chk", + loading = "mult-chk", + status = "pending", + }, + { + category = "lua", + filename = "mult-def", + loading = "mult-ini", + status = "okay", + }, + { + category = "lua", + comment = "used for generating editor lexing files", + filename = "mult-fun", + loading = "never", + status = "okay", + }, + { + category = "lua", + filename = "mult-ini", + loading = "mult-ini", + status = "okay", + }, + { + category = "lua", + comment = "used for generating editor lexing files", + filename = "mult-low", + loading = "never", + status = "okay", + }, + { + category = "lua", + comment = "all messages need to be checked", + filename = "mult-mes", + loading = "mult-ini", + status = "pending", + }, + { + category = "lua", + comment = "used for generating editor lexing files", + filename = "mult-mps", + loading = "never", + status = "okay", + }, + { + category = "lua", + comment = "used for generating editor lexing files", + filename = "mult-prm", + loading = "never", + status = "okay", + }, + { + category = "lua", + filename = "node-acc", + status = "todo", + }, + { + category = "lua", + filename = "node-aux", + status = "todo", + }, + { + category = "lua", + filename = "node-bck", + status = "todo", + }, + { + category = "lua", + filename = "node-dir", + status = "todo", + }, + { + category = "lua", + filename = "node-ext", + status = "todo", + }, + { + category = "lua", + filename = "node-fin", + status = "todo", + }, + { + category = "lua", + filename = "node-fnt", + loading = "font-lib", + status = "todo", + }, + { + category = "lua", + filename = "node-ini", + status = "todo", + }, + { + category = "lua", + filename = "node-inj", + loading = "font-lib", + status = "todo", + }, + { + category = "lua", + filename = "node-mig", + status = "todo", + }, + { + category = "lua", + filename = "node-pag", + status = "todo", + }, + { + category = "lua", + filename = "node-pro", + status = "todo", + }, + { + category = "lua", + filename = "node-ref", + status = "todo", + }, + { + category = "lua", + filename = "node-res", + status = "todo", + }, + { + category = "lua", + filename = "node-rul", + status = "todo", + }, + { + category = "lua", + filename = "node-ser", + status = "todo", + }, + { + category = "lua", + filename = "node-shp", + status = "todo", + }, + { + category = "lua", + filename = "node-tex", + status = "todo", + }, + { + category = "lua", + filename = "node-tra", + status = "todo", + }, + { + category = "lua", + filename = "node-tsk", + status = "todo", + }, + { + category = "lua", + filename = "node-tst", + status = "todo", + }, + { + category = "lua", + filename = "node-typ", + status = "todo", + }, + { + category = "lua", + comment = "will be extended when we have opened up pdf objects", + filename = "pack-obj", + loading = "pack-obj", + status = "okay", + }, + { + category = "lua", + filename = "pack-rul", + loading = "pack-rul", + status = "okay", + }, + { + category = "lua", + filename = "page-flt", + status = "todo", + }, + { + category = "lua", + filename = "page-ins", + status = "todo", + }, + { + category = "lua", + filename = "page-lin", + status = "todo", + }, + { + category = "lua", + filename = "page-mix", + status = "todo", + }, + { + category = "lua", + filename = "page-pst", + status = "todo", + }, + { + category = "lua", + filename = "page-str", + status = "todo", + }, + { + category = "lua", + filename = "phys-dim", + loading = "phys-dim", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-1", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-10", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-11", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-13", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-14", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-15", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-16", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-2", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-3", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-4", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-5", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-6", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-7", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-8", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-8859-9", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1250", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1251", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1252", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1253", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1254", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1255", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1256", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1257", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "regi-cp1258", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + comment = "just a demo file", + filename = "regi-demo", + loading = "never", + status = "okay", + }, + { + category = "lua", + filename = "regi-ini", + loading = "regi-ini", + status = "okay", + }, + { + category = "lua", + filename = "s-fonts-tables", + status = "todo", + }, + { + category = "lua", + filename = "s-pre-71", + status = "todo", + }, + { + category = "lua", + filename = "scrn-but", + status = "todo", + }, + { + category = "lua", + filename = "scrn-fld", + status = "todo", + }, + { + category = "lua", + filename = "scrn-hlp", + status = "todo", + }, + { + category = "lua", + filename = "scrn-ini", + status = "todo", + }, + { + category = "lua", + filename = "scrn-pag", + status = "todo", + }, + { + category = "lua", + filename = "scrn-ref", + status = "todo", + }, + { + category = "lua", + filename = "scrn-wid", + status = "todo", + }, + { + category = "lua", + comment = "we can speed this up", + filename = "scrp-cjk", + loading = "scrp-ini", + status = "okay", + }, + { + category = "lua", + comment = "we can speed this up", + filename = "scrp-eth", + loading = "scrp-ini", + status = "okay", + }, + { + category = "lua", + filename = "scrp-ini", + loading = "scrp-ini", + status = "okay", + }, + { + category = "lua", + filename = "sort-ini", + status = "todo", + }, + { + category = "lua", + filename = "sort-lan", + status = "todo", + }, + { + category = "lua", + filename = "spac-adj", + status = "todo", + }, + { + category = "lua", + filename = "spac-ali", + status = "todo", + }, + { + category = "lua", + filename = "spac-chr", + status = "todo", + }, + { + category = "lua", + filename = "spac-hor", + status = "todo", + }, + { + category = "lua", + filename = "spac-ver", + status = "todo", + }, + { + category = "lua", + filename = "status-mkiv", + status = "todo", + }, + { + category = "lua", + filename = "strc-bkm", + status = "todo", + }, + { + category = "lua", + filename = "strc-blk", + status = "todo", + }, + { + category = "lua", + filename = "strc-con", + status = "todo", + }, + { + category = "lua", + filename = "strc-doc", + status = "todo", + }, + { + category = "lua", + filename = "strc-flt", + status = "todo", + }, + { + category = "lua", + filename = "strc-ini", + status = "todo", + }, + { + category = "lua", + filename = "strc-itm", + status = "todo", + }, + { + category = "lua", + filename = "strc-lev", + status = "todo", + }, + { + category = "lua", + filename = "strc-lst", + status = "todo", + }, + { + category = "lua", + filename = "strc-mar", + status = "todo", + }, + { + category = "lua", + filename = "strc-mat", + status = "todo", + }, + { + category = "lua", + filename = "strc-not", + status = "todo", + }, + { + category = "lua", + filename = "strc-num", + status = "todo", + }, + { + category = "lua", + filename = "strc-pag", + status = "todo", + }, + { + category = "lua", + filename = "strc-ref", + status = "todo", + }, + { + category = "lua", + filename = "strc-reg", + status = "todo", + }, + { + category = "lua", + filename = "strc-rsc", + status = "todo", + }, + { + category = "lua", + filename = "strc-syn", + status = "todo", + }, + { + category = "lua", + filename = "strc-tag", + status = "todo", + }, + { + category = "lua", + filename = "supp-box", + loading = "supp-box", + status = "okay", + }, + { + category = "lua", + filename = "supp-ran", + loading = "supp-ran", + status = "okay", + }, + { + category = "lua", + filename = "symb-ini", + loading = "symb-ini", + status = "okay", + }, + { + category = "lua", + comment = "there will be more in here", + filename = "syst-aux", + loading = "syst-aux", + status = "okay", + }, + { + category = "lua", + comment = "do some tests with speedups (sprint)", + filename = "syst-con", + loading = "syst-con", + status = "pending", + }, + { + category = "lua", + comment = "do some tests with speedups (less tokens)", + filename = "syst-lua", + loading = "syst-lua", + status = "pending", + }, + { + category = "lua", + filename = "tabl-tbl", + loading = "tabl-tbl", + status = "okay", + }, + { + category = "lua", + comment = "work in progress", + filename = "tabl-xtb", + loading = "tabl-xtb", + status = "okay", + }, + { + category = "lua", + comment = "we need a well defined defintion moment", + filename = "task-ini", + loading = "task-ini", + status = "pending", + }, + { + category = "lua", + filename = "toks-ini", + status = "todo", + }, + { + category = "lua", + comment = "must be applied in more places", + filename = "trac-ctx", + loading = "trac-ctx", + status = "okay", + }, + { + category = "lua", + filename = "trac-deb", + loading = "trac-deb", + status = "okay", + }, + { + category = "lua", + comment = "for the moment somewhat private", + filename = "trac-fil", + loading = "never", + status = "okay", + }, + { + category = "lua", + filename = "trac-inf", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + comment = "will be redone and extended", + filename = "trac-lmx", + loading = "luat-lib", + status = "pending", + }, + { + category = "lua", + filename = "trac-log", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + comment = "experimental code, will be redone when lua 5.2", + filename = "trac-pro", + loading = "luat-lib", + status = "pending", + }, + { + category = "lua", + comment = "some code can better be in util-set", + filename = "trac-set", + loading = "luat-lib", + status = "pending", + }, + { + category = "lua", + filename = "trac-tex", + loading = "trac-tex", + status = "okay", + }, + { + category = "lua", + filename = "trac-tim", + loading = "on demand", + status = "okay", + }, + { + category = "lua", + filename = "trac-vis", + loading = "trac-vis", + status = "okay", + }, + { + category = "lua", + filename = "type-ini", + loading = "type-ini", + status = "okay", + }, + { + category = "lua", + filename = "typo-bld", + status = "todo", + }, + { + category = "lua", + filename = "typo-brk", + status = "todo", + }, + { + category = "lua", + filename = "typo-cap", + status = "todo", + }, + { + category = "lua", + filename = "typo-cln", + status = "todo", + }, + { + category = "lua", + filename = "typo-dig", + status = "todo", + }, + { + category = "lua", + filename = "typo-dir", + status = "todo", + }, + { + category = "lua", + filename = "typo-ini", + status = "todo", + }, + { + category = "lua", + filename = "typo-itc", + status = "todo", + }, + { + category = "lua", + filename = "typo-krn", + status = "todo", + }, + { + category = "lua", + filename = "typo-mar", + status = "todo", + }, + { + category = "lua", + filename = "typo-pag", + status = "todo", + }, + { + category = "lua", + filename = "typo-par", + status = "todo", + }, + { + category = "lua", + filename = "typo-prc", + status = "todo", + }, + { + category = "lua", + filename = "typo-rep", + status = "todo", + }, + { + category = "lua", + filename = "typo-spa", + status = "todo", + }, + { + category = "lua", + filename = "unic-ini", + loading = "unic-ini", + status = "okay", + }, + { + category = "lua", + filename = "util-deb", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-dim", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-fmt", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-jsn", + loading = "m-json", + status = "todo", + }, + { + category = "lua", + filename = "util-lua", + loading = "luat-lib", + status = "okay", + }, + { + category = "lua", + filename = "util-mrg", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-pck", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-prs", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-seq", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-sql", + loading = "m-sql", + status = "todo", + }, + { + category = "lua", + filename = "util-sta", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-sto", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-str", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-tab", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "util-tpl", + loading = "luat-lib", + status = "todo", + }, + { + category = "lua", + filename = "x-asciimath", + status = "todo", + }, + { + category = "lua", + filename = "x-calcmath", + status = "todo", + }, + { + category = "lua", + filename = "x-cals", + status = "todo", + }, + { + category = "lua", + filename = "x-chemml", + status = "todo", + }, + { + category = "lua", + filename = "x-ct", + status = "todo", + }, + { + category = "lua", + filename = "x-ldx", + status = "todo", + }, + { + category = "lua", + filename = "x-mathml", + status = "todo", + }, + }, + metafun = { + { + category = "mpiv", + filename = "mp-base", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-tool", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-mlib", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + comment = "sort of obsolete", + filename = "mp-core", + status = "okay", + }, + { + category = "mpiv", + comment = "maybe some nicer synonyms", + filename = "mp-page", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-butt", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-shap", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-grph", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-grid", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + comment = "a hack anyway", + filename = "mp-form", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-figs", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-func", + loading = "always", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-text", + loading = "on demand", + status = "todo", + }, + { + category = "mpiv", + filename = "mp-crop", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + comment = "follows m-chart", + filename = "mp-char", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + comment = "follows m-steps", + filename = "mp-step", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + filename = "mp-chem", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + comment = "maybe some namespace changes", + filename = "mp-abck", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + comment = "maybe some namespace changes", + filename = "mp-apos", + loading = "on demand", + status = "okay", + }, + { + category = "mpiv", + comment = "will be done when needed", + filename = "mp-asnc", + loading = "on demand", + status = "todo", + }, + }, + modules = { + { + category = "mkiv", + comment = "best use m-zint instead", + filename = "m-barcodes", + loading = "module", + status = "okay", + }, + { + category = "mkvi", + filename = "m-chart", + loading = "module", + status = "okay", + }, + { + category = "mkiv", + comment = "this is a placeholder (chemistry is built-in)", + filename = "m-chemic", + loading = "never", + status = "okay", + }, + { + category = "tex", + filename = "m-cweb", + status = "todo", + }, + { + category = "mkiv", + filename = "m-database", + status = "todo", + }, + { + category = "tex", + filename = "m-datastrc", + status = "todo", + }, + { + category = "mkiv", + comment = "add-on for mtx-context", + filename = "m-directives", + loading = "on demand", + status = "okay", + }, + { + category = "tex", + filename = "m-educat", + status = "todo", + }, + { + category = "mkiv", + filename = "m-fields", + status = "todo", + }, + { + category = "tex", + filename = "m-format", + status = "todo", + }, + { + category = "mkiv", + filename = "m-graph", + status = "todo", + }, + { + category = "mkiv", + filename = "m-ipsum", + loading = "module", + status = "okay", + }, + { + category = "mkiv", + filename = "m-json", + loading = "module", + status = "okay", + }, + { + category = "tex", + filename = "m-layout", + status = "todo", + }, + { + category = "mkiv", + comment = "add-on for mtx-context", + filename = "m-logcategories", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "m-markdown", + status = "todo", + }, + { + category = "mkiv", + filename = "m-mathcrap", + status = "todo", + }, + { + category = "mkiv", + filename = "m-mkii", + status = "todo", + }, + { + category = "mkiv", + filename = "m-mkivhacks", + status = "todo", + }, + { + category = "mkvi", + filename = "m-morse", + loading = "module", + status = "okay", + }, + { + category = "tex", + filename = "m-narrowtt", + loading = "module", + status = "okay", + }, + { + category = "tex", + filename = "m-newmat", + status = "todo", + }, + { + category = "mkiv", + filename = "m-ntb-to-xtb", + status = "okay", + }, + { + category = "mkiv", + filename = "m-obsolete", + status = "todo", + }, + { + category = "mkiv", + filename = "m-oldfun", + status = "todo", + }, + { + category = "mkiv", + filename = "m-oldnum", + status = "todo", + }, + { + category = "tex", + filename = "m-pictex", + status = "todo", + }, + { + category = "mkiv", + filename = "m-pstricks", + status = "todo", + }, + { + category = "mkiv", + comment = "keep an eye on changes in lua code", + filename = "m-punk", + status = "okay", + }, + { + category = "tex", + filename = "m-r", + status = "todo", + }, + { + category = "mkiv", + filename = "m-spreadsheet", + status = "okay", + }, + { + category = "mkvi", + filename = "m-steps", + status = "todo", + }, + { + category = "tex", + filename = "m-streams", + status = "todo", + }, + { + category = "tex", + filename = "m-subsub", + status = "todo", + }, + { + category = "mkiv", + filename = "m-sql", + loading = "module", + status = "okay", + }, + { + category = "mkiv", + filename = "m-timing", + status = "okay", + }, + { + category = "mkiv", + comment = "add-on for mtx-context", + filename = "m-trackers", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "m-translate", + status = "okay", + }, + { + category = "mkiv", + filename = "m-units", + status = "todo", + }, + { + category = "mkiv", + filename = "m-visual", + status = "todo", + }, + { + category = "mkiv", + filename = "m-zint", + status = "okay", + }, + { + category = "tex", + filename = "s-abr-01", + status = "todo", + }, + { + category = "tex", + filename = "s-abr-02", + status = "todo", + }, + { + category = "tex", + filename = "s-abr-03", + status = "todo", + }, + { + category = "tex", + filename = "s-abr-04", + status = "todo", + }, + { + category = "mkiv", + filename = "s-art-01", + status = "todo", + }, + { + category = "tex", + filename = "s-cdr-01", + status = "todo", + }, + { + category = "mkiv", + filename = "s-def-01", + status = "todo", + }, + { + category = "tex", + filename = "s-faq-00", + status = "todo", + }, + { + category = "tex", + filename = "s-faq-01", + status = "todo", + }, + { + category = "tex", + filename = "s-faq-02", + status = "todo", + }, + { + category = "tex", + filename = "s-faq-03", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-10", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-11", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-20", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-21", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-23", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-24", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-26", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-28", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-29", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-30", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-31", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fnt-32", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fonts-missing", + status = "todo", + }, + { + category = "mkiv", + filename = "s-fonts-tables", + status = "todo", + }, + { + category = "mkvi", + filename = "s-inf-01", + status = "okay", + }, + { + category = "mkiv", + filename = "s-inf-02", + status = "todo", + }, + { + category = "mkiv", + filename = "s-inf-03", + status = "todo", + }, + { + category = "mkiv", + filename = "s-inf-04", + status = "todo", + }, + { + category = "mkiv", + filename = "s-lan-03", + status = "todo", + }, + { + category = "mkiv", + filename = "s-lan-04", + status = "todo", + }, + { + category = "tex", + filename = "s-mag-01", + status = "todo", + }, + { + category = "mkiv", + filename = "s-map-10", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mat-10", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mat-11", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mat-12", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mod-00", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mod-01", + status = "todo", + }, + { + category = "mkiv", + filename = "s-mod-02", + status = "todo", + }, + { + category = "mkiv", + filename = "s-phy-01", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-00", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-01", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-02", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-03", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-04", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-05", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-06", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-07", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-08", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-09", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-10", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-11", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-12", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-13", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-14", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-15", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-16", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-17", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-18", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-19", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-22", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-23", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-26", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-27", + status = "todo", + }, + { + category = "mkiv", + filename = "s-pre-30", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-50", + status = "todo", + }, + { + category = "mkiv", + filename = "s-pre-60", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-61", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-62", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-63", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-64", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-66", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-67", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-68", + status = "todo", + }, + { + category = "mkiv", + filename = "s-pre-69", + status = "todo", + }, + { + category = "mkiv", + filename = "s-pre-70", + status = "todo", + }, + { + category = "mkiv", + filename = "s-pre-71", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-93", + status = "todo", + }, + { + category = "tex", + filename = "s-pre-96", + status = "todo", + }, + { + category = "tex", + filename = "s-ptj-01", + status = "todo", + }, + { + category = "mkiv", + filename = "s-reg-01", + status = "todo", + }, + { + category = "mkiv", + filename = "s-set-31", + status = "todo", + }, + { + category = "tex", + filename = "s-syn-01", + status = "todo", + }, + { + category = "mkiv", + filename = "x-asciimath", + status = "okay", + }, + { + category = "mkiv", + filename = "x-calcmath", + status = "todo", + }, + { + category = "mkiv", + filename = "x-cals", + status = "todo", + }, + { + category = "mkiv", + filename = "x-chemml", + status = "todo", + }, + { + category = "mkiv", + filename = "x-ct", + status = "todo", + }, + { + category = "tex", + filename = "x-dir-01", + status = "todo", + }, + { + category = "mkiv", + filename = "x-dir-05", + status = "todo", + }, + { + category = "mkiv", + filename = "x-entities", + status = "okay", + }, + { + category = "mkiv", + filename = "x-foxet", + status = "todo", + }, + { + category = "mkiv", + filename = "x-ldx", + status = "todo", + }, + { + category = "mkiv", + filename = "x-mathml", + status = "todo", + }, + { + category = "mkiv", + filename = "x-newmml", + status = "todo", + }, + { + category = "mkiv", + comment = "pfsense xml configuration rendering", + filename = "x-pfs-01", + status = "okay", + }, + { + category = "mkiv", + filename = "x-physml", + status = "todo", + }, + { + category = "mkiv", + filename = "x-res-01", + status = "todo", + }, + { + category = "mkiv", + filename = "x-res-50", + status = "todo", + }, + { + category = "mkiv", + filename = "x-set-11", + status = "todo", + }, + { + category = "mkiv", + filename = "x-set-12", + status = "todo", + }, + { + category = "mkiv", + filename = "x-udhr", + status = "okay", + }, + { + category = "mkiv", + filename = "x-xtag", + status = "todo", + }, + }, + optional = { + { + category = "mkiv", + filename = "bxml-apa", + status = "todo", + }, + { + category = "mkiv", + filename = "colo-run", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + comment = "always needs some work", + filename = "cont-new", + loading = "runtime", + status = "todo", + }, + { + category = "mkiv", + filename = "font-run", + loading = "on demand", + status = "todo", + }, + { + category = "mkiv", + filename = "lxml-ctx", + status = "okay", + comment = "this is an experimental module", + }, + { + category = "mkiv", + filename = "meta-pdh", + loading = "never", + status = "okay", + comment = "this is historic code that we keep around", + }, + { + category = "mkiv", + filename = "mult-prm", + loading = "never", + status = "okay", + comment = "this is just a helper for generating files", + }, + { + category = "mkiv", + filename = "page-run", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "spac-adj", + loading = "never", + status = "obsolete", + }, + { + category = "mkiv", + filename = "supp-vis", + loading = "never", + status = "obsolete", + comment = "replaced by a more modern variant", + }, + { + category = "mkiv", + filename = "symb-run", + loading = "on demand", + status = "okay", + }, + { + category = "mkiv", + filename = "type-run", + loading = "on demand", + status = "todo", + }, + }, + resources = { + { + category = "ori", + comment = "template for a user configuration file (with suffix mkiv)", + filename = "cont-sys", + loading = "runtime", + status = "okay", + }, + { + category = "lmx", + filename = "context-base", + status = "todo", + }, + { + category = "lmx", + filename = "context-characters", + status = "todo", + }, + { + category = "lmx", + filename = "context-debug", + status = "todo", + }, + { + category = "lmx", + filename = "context-error", + status = "todo", + }, + { + category = "lmx", + filename = "context-fonttest", + status = "todo", + }, + { + category = "lmx", + filename = "context-help", + status = "todo", + }, + { + category = "lmx", + filename = "context-timing", + status = "todo", + }, + { + category = "pdf", + filename = "context-version", + status = "todo", + }, + { + category = "png", + filename = "context-version", + status = "todo", + }, + { + category = "css", + comment = "layout specification for debug and error pages and web services", + filename = "context", + status = "okay", + }, + { + category = "rme", + comment = "readme file", + filename = "context", + status = "okay", + }, + { + category = "ctx", + comment = "example of a ctx file (for mtx-context)", + filename = "core-ctx", + status = "okay", + }, + { + category = "css", + filename = "export-example", + status = "todo", + }, + { + category = "rng", + filename = "export-example", + status = "todo", + }, + { + category = "tex", + filename = "export-example", + status = "todo", + }, + { + category = "xml", + comment = "this file is auto-generated by mtx-language", + filename = "lang-all", + status = "okay", + }, + { + category = "xml", + filename = "lpdf-pda", + status = "todo", + }, + { + category = "xml", + filename = "lpdf-pdx", + status = "todo", + }, + { + category = "rlx", + filename = "rlxcache", + status = "todo", + }, + { + category = "rlx", + filename = "rlxtools", + status = "todo", + }, + { + category = "ctx", + filename = "s-mod", + status = "todo", + }, + { + category = "pdf", + filename = "status-files", + status = "todo", + }, + { + category = "pdf", + filename = "status-lua", + status = "todo", + }, + { + category = "tex", + filename = "status-mkiv", + status = "todo", + }, + { + category = "xsd", + filename = "x-chemml", + status = "todo", + }, + { + category = "xsd", + filename = "x-contml", + status = "todo", + }, + { + category = "rng", + filename = "x-corres", + status = "todo", + }, + { + category = "dtd", + filename = "x-fig-00", + status = "todo", + }, + { + category = "xsd", + filename = "x-fig-00", + status = "todo", + }, + { + category = "ctx", + filename = "x-ldx", + status = "todo", + }, + { + category = "xsd", + filename = "x-mathml", + status = "todo", + }, + { + category = "xsl", + filename = "x-om2cml", + status = "todo", + }, + { + category = "xsl", + filename = "x-openmath", + status = "todo", + }, + { + category = "ctx", + comment = "runner for x-pfs-01", + filename = "x-pfsense", + status = "okay", + }, + { + category = "xsd", + filename = "x-physml", + status = "todo", + }, + { + category = "xsl", + filename = "x-sm2om", + status = "todo", + }, + }, } diff --git a/tex/context/base/status-mkiv.tex b/tex/context/base/status-mkiv.tex index 0d22d51a1..7ca394a19 100644 --- a/tex/context/base/status-mkiv.tex +++ b/tex/context/base/status-mkiv.tex @@ -1,38 +1,46 @@ - \setupbodyfont[dejavu,10pt] +\usemodule[abr-02] + +\setupbodyfont + [dejavu,9pt] + +\setuppapersize + [A4,landscape] \setuplayout [width=middle, height=middle, - backspace=1cm, - topspace=1cm, + backspace=.5cm, + topspace=.5cm, footer=0pt, header=1.25cm] \setuphead - [subject] + [title] [style=\bfa, - page=yes] + page=yes, + after={\blank[line]}] \setuppagenumbering [location=] \setupheadertexts - [\currentdate][MkIV cleanup Status / Page \pagenumber] + [\currentdate] + [MkIV Status / Page \pagenumber] + +% \showmakeup +% \showallmakeup \starttext -% anch attr back buff colo font grph java lang luat lxml math meta mlib mult node -% pack page phys scrn spac strc supp symb syst tabl toks typo +% logs.report (immediate) versus logs.messenger (in flow) -\startsubject[title=Todo] +\starttitle[title=Todo] \startitemize[packed] \startitem currently the new namespace prefixes are not consistent but this will be done when we're satisfied with one scheme \stopitem \startitem there will be additional columns in the table, like for namespace so we need another round of checking then \stopitem - \startitem the imp modules are not in the list and need checking too \stopitem - \startitem the s, x, m modules will be checked, redone and reorganized \stopitem \startitem the lua code will be cleaned up upgraded as some is quite old and experimental \stopitem \startitem we need a proper dependency tree and better defined loading order \stopitem @@ -40,122 +48,272 @@ \startitem we need to check what messages are gone (i.e.\ clean up mult-mes) \stopitem \startitem some commands can go from mult-def (and the xml file) \stopitem \startitem check for setuphandler vs simplesetuphandler \stopitem - \startitem all showcomposition etc can go (we can redo that in lua if needed) \stopitem \startitem for the moment we will go for \type {xxxx_} namespaces that (mostly) match the filename but later we can replace these by longer names (via a script) so module writers should {\bf not} use the core commands with \type{_} in the name \stopitem \startitem the message system will be unified \stopitem + \startitem maybe rename dowhatevertexcommand to fromluawhatevertexcommand \stopitem + \startitem consider moving setups directly to lua end (e.g. in characterspacing, breakpoint, bitmaps etc.) \stopitem + \startitem more local temporary \type {\temp...} will become \type {\p_...} \stopitem + \startitem check all ctxlua calls for ctxcommand \stopitem + \startitem rename all those \type {\current<whatever>}s in strc \stopitem + \startitem check \type {option} vs \type {options} \stopitem + \startitem check \type {type} vs \type {kind} \stopitem + \startitem check \type {label} vs \type {name} vs \type {tag} \stopitem + \startitem check \type {limop}, different limops should should be classes \stopitem + \startitem too many positions in simple files (itemize etc) \stopitem + \startitem math domains/dictionaries \stopitem + \startitem xtables don't span vertically with multilines (yet) \stopitem + \startitem notes in mixed columns \stopitem + \startitem floats in mixed columns \stopitem + \startitem check return values \type {os.execute} \stopitem + \startitem more r, d, k in xml code \stopitem + \startitem mathml, more in \LUA \stopitem + \startitem style: font-size, font, color handling in \HTML\ (lxml-css) \stopitem + \startitem a \type {\name {A.B.C DEF}} auto-nobreakspace \stopitem + \startitem redo \CWEB\ module with \LUA \stopitem + \startitem maybe move characters.blocks to its own file \stopitem + \startitem more local context = context in \LUA\ files \stopitem + \startitem check and optimize all storage.register and locals (cosmetics) \stopitem + \startitem check all used modules in \LUA\ (and local them) \stopitem + \startitem environment and basic lua helpers are now spread over too many files \stopitem + \startitem isolate tracers and showers \stopitem + \startitem check all possible usage of ctxcommand \stopitem + \startitem there are more s-* modules, like s-fnt-41 \stopitem + \startitem check (un)marked tables \stopitem \stopitemize -\stopsubject +\stoptitle -\startsubject[title=Status] +\definehighlight[notabenered] [color=darkred, style=bold] +\definehighlight[notabeneblue] [color=darkblue, style=bold] +\definehighlight[notabeneyellow] [color=darkyellow, style=bold] +\definehighlight[notabenemagenta][color=darkmagenta,style=bold] \startluacode local coremodules = dofile("status-mkiv.lua") + local valid = table.tohash { + "toks", "attr", "page", "buff", "font", "colo", "phys", "supp", "typo", "strc", + "syst", "tabl", "spac", "scrn", "lang", "lxml", "mlib", "java", "pack", "math", + "symb", "grph", "anch", "luat", "mult", "back", "node", "meta", "norm", "catc", + "cldf", "file", "char", "core", "layo", "trac", "cont", "regi", "enco", "hand", + "unic", "sort", "blob", "type", "scrp", "prop", "chem", "bibl", "task", + "whatever", "mp", "s", "x", "m", "mtx", + } + + local specialcategories = { + mkvi = true, + } + + local what = { + "main", "core", "lua", "optional", "implementations", "extra", "extras", "metafun", "modules", "resources" + } + + local totaltodo = 0 + local totalpending = 0 + local totalobsolete = 0 + local totalloaded = 0 + + local function summary(nofloaded,noftodo,nofpending,nofobsolete) + + local nofdone = nofloaded - noftodo - nofpending - nofobsolete + + context.starttabulate { "|B|r|" } + context.HL() + context.NC() context("done") context.NC() context(nofdone) context.NC() context.NR() + context.NC() context("todo") context.NC() context(noftodo) context.NC() context.NR() + context.NC() context("pending") context.NC() context(nofpending) context.NC() context.NR() + context.NC() context("obsolete") context.NC() context(nofobsolete) context.NC() context.NR() + context.HL() + context.NC() context("loaded") context.NC() context(nofloaded) context.NC() context.NR() + context.HL() + context.stoptabulate() + + end + if coremodules then local function tabelize(loaded,what) if loaded then - local nofunknown = 0 - local nofloaded = #loaded + local noftodo = 0 + local nofpending = 0 + local nofobsolete = 0 + local nofloaded = #loaded + local categories = { } + + for k, v in next, valid do + categories[k] = { } + end for i=1,nofloaded do - loaded[i].order = i + local l = loaded[i] + l.order = i + local category = string.match(l.filename,"([^%-]+)%-") or "whatever" + local c = categories[category] + if c then + c[#c+1] = l + end end - table.sort(loaded,function(a,b) return a.filename < b.filename end) + for k, loaded in table.sortedhash(categories) do + + local nofloaded = #loaded + + if nofloaded > 0 then + + table.sort(loaded,function(a,b) return a.filename < b.filename end) -- in place + + context.starttitle { title = string.format("%s: %s",what,k) } + + context.starttabulate { "|Tr|Tlw(3em)|Tlw(12em)|Tlw(12em)|Tlw(4em)|Tl|Tl|Tl|Tp|" } + context.NC() context.bold("order") + context.NC() context.bold("kind") + context.NC() context.bold("file") + context.NC() context.bold("loading") + context.NC() context.bold("status") + context.NC() context.bold("reference") + context.NC() context.bold("manual") + context.NC() context.bold("wiki") + context.NC() context.bold("comment") + context.NC() context.NR() + context.HL() + for i=1,nofloaded do + local module = loaded[i] + local status = module.status + local category = module.category + local filename = module.filename + context.NC() + context(module.order) + context.NC() + if specialcategories[category] then + context.notabeneblue(category) + else + context(category) + end + context.NC() + if #filename>20 then + context(string.sub(filename,1,18) .. "..") + else + context(filename) + end + context.NC() + context(module.loading) + context.NC() + if status == "todo" then + context.notabenered(status) + noftodo = noftodo + 1 + elseif status == "pending" then + context.notabeneyellow(status) + nofpending = nofpending + 1 + elseif status == "obsolete" then + context.notabenemagenta(status) + nofobsolete = nofobsolete + 1 + else + context(status) + end + context.NC() context(module.reference) + context.NC() context(module.manual) + context.NC() context(module.wiki) + context.NC() context(module.comment) + context.NC() context.NR() + end + context.stoptabulate() + + context.stoptitle() - context.starttabulate { "|Tr|Tl|Tl|l|p|" } - context.NC() -- context.bold("order") - context.NC() context.bold("file") - context.NC() context.bold("mark") - context.NC() context.bold("status") - context.NC() context.bold("comment") - context.NC() context.NR() - for i=1,nofloaded do - local module = loaded[i] - local status = module.status - context.NC() context(module.order) - context.NC() context(module.filename) - context.NC() context(module.marktype) - if status == "unknown" then - context.NC() context.bold(status) - nofunknown = nofunknown + 1 - else - context.NC() context(status) end - context.NC() context(module.comment) - context.NC() context.NR() + end - context.stoptabulate() - context.blank() + context.starttitle { title = string.format("summary of %s modules",what) } - context("Of the %s %s modules (so far) in this list %s have the status unknown",nofloaded,what,nofunknown) + summary(nofloaded,noftodo,nofpending,nofobsolete) + + context.stoptitle() + + totaltodo = totaltodo + noftodo + totalpending = totalpending + nofpending + totalobsolete = totalobsolete + nofobsolete + totalloaded = totalloaded + nofloaded end end - tabelize(coremodules.core, "core") - tabelize(coremodules.extra,"extra") + for i=1,#what do + tabelize(coremodules[what[i]],what[i]) + end end - local namespaces = dofile("status-namespaces.lua") + -- context.starttitle { title = "Valid prefixes" } + -- + -- for namespace, data in table.sortedhash(namespaces) do + -- if valid[namespace] then + -- context.type(namespace) + -- end + -- context.par() + -- end + -- + -- context.stoptitle() - local valid = table.tohash { - "toks", "attr", "page", "buff", "font", "colo", "phys", "supp", "typo", "strc", - "syst", "tabl", "spac", "scrn", "lang", "lxml", "mlib", "java", "pack", "math", - "symb", "grph", "anch", "luat", "mult", "back", "node", "meta", - "module", - } + context.starttitle { title = string.format("summary of all",what) } - context.startsubject { title = "Valid prefixes" } + summary(totalloaded,totaltodo,totalpending,totalobsolete) - for namespace, data in table.sortedhash(namespaces) do - if valid[namespace] then - context.type(namespace) - end - context.par() - end + context.stoptitle() - context.stopsubject() + if io.exists("status-namespaces.lua") then - context.startsubject { title = "Messy namespaces" } + context.starttitle { title = "messy namespaces" } - for namespace, data in table.sortedhash(namespaces) do - if valid[namespace] then - else - context(namespace) + local namespaces = dofile("status-namespaces.lua") + + for namespace, data in table.sortedhash(namespaces) do + if valid[namespace] then + else + context(namespace) + end + context.par() end - context.par() + + context.stoptitle() + end - context.stopsubject() + if io.exists("status-registers.lua") then - local registers = dofile("status-registers.lua") + context.starttitle { title = "messy registers" } - context.startsubject { title = "Messy registers" } - for register, data in table.sortedhash(registers) do - context(register) - context.par() - for name in table.sortedhash(data) do - context.quad() - context.type(name) + local registers = dofile("status-registers.lua") + + for register, data in table.sortedhash(registers) do + context(register) + context.par() + for name in table.sortedhash(data) do + context.quad() + context.type(name) + context.par() + end context.par() end - context.par() + + context.stoptitle() + end + context.starttitle { title = "callbacks" } + + commands.showcallbacks() + + context.stoptitle() + \stopluacode -\stopsubject \stoptext diff --git a/tex/context/base/strc-bkm.mkiv b/tex/context/base/strc-bkm.mkiv index 8ddf0a6df..8e1252329 100644 --- a/tex/context/base/strc-bkm.mkiv +++ b/tex/context/base/strc-bkm.mkiv @@ -11,93 +11,109 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This might become scrn-bkm.mkiv. - \writestatus{loading}{ConTeXt Structure Macros / Bookmarks} \registerctxluafile{strc-bkm}{1.001} \unprotect -%D Due to requests I finally decided to support bookmarks, a -%D driver dependant way of showing tables of content. The most -%D simple way of support is hooking bookmark generation into -%D the existing list mechanisms. That way users can generate -%D bookmarks automatically, although its entirely valid to add -%D bookmarks by defining alternative ones. These will be added -%D at the appropriate place in the list. - -% \hoofdstuk{het eerste hoofdstuk} -% -% \bookmark {de eerste bookmark} % optional overruled hoofdstuk -% -% .... text .... -% -% \placebookmarks [hoofdstuk,paragraaf,subparagraaf,subsubparagraaf,mylist] -% [open list] -% -% \bookmark[mylist]{whatever} - -%D This will go away. - -\let\flushpostponedbookmark\relax +%D Bookmarks are a very viewer dependent feature. They are mostly used +%D as additional table of contents and therefore relate directly to lists. +%D +%D A bookmark list is added to the document only when interaction is +%D enabled. The given lists are bookmarked and a second argument specifies +%D the opened bookmark trees. +%D +%D \starttyping +%D \placebookmarks +%D [chapter,section,subsection,mylist] +%D [chapter] +%D \stoptyping +%D +%D You can overloads the last set bookmark in a sectioning command: +%D +%D \starttyping +%D \chapter {the first chapter} +%D \bookmark {the first bookmark} +%D \stoptyping +%D +%D However, in practice you can better use \type {\startchapter} and set the +%D \type {bookmark} parameter. +%D +%D You can add entries to the bookmarklist: +%D +%D \starttyping +%D \bookmark[mylist]{whatever} +%D \stoptyping +%D +%D Use force to get titles in the bookmarklist. This is somewhat tricky as +%D one does not want "Contents" in a table of contents but it has to be in +%D the bookmark list. + +\installcorenamespace{bookmark} + +\installsetuponlycommandhandler \??bookmark {bookmark} % installdirectparametersethandler + +\setupbookmark + [\c!force=\v!no, % it's easier to force that to inhibit + \c!number=\v!yes] % might become v!no -%D We have better ways now. +\let\setupbookmarks\setupbookmark \unexpanded\def\bookmark - {\dosingleempty\dobookmark} + {\dosingleempty\strc_bookmarks_bookmark} -\def\dobookmark[#1]#2% +\def\strc_bookmarks_bookmark + {\iflocation + \expandafter\strc_bookmarks_bookmark_yes + \else + \expandafter\strc_bookmarks_bookmark_nop + \fi} + +\def\strc_bookmarks_bookmark_yes[#1]#2% {\begingroup \simplifycommands \ctxcommand{overloadbookmark("#1",\!!bs\detokenize\expandafter{\normalexpanded{#2}}\!!es)}% \endgroup} -%D Placement \unknown\ look how simple compared to \MKII: - -\newtoks \everysetupbookmarks - -\def\bookmarkparameter#1{\ifcsname\??bm#1\endcsname\csname\??bm#1\endcsname\fi} - -\unexpanded\def\setupbookmarks[#1]% - {\getparameters[\??bm][#1]% - \the\everysetupbookmarks} +\def\strc_bookmarks_bookmark_nop[#1]#2% + {} \unexpanded\def\placebookmarks - {\dotripleempty\doplacebookmarks} - -% Use force to get titles in the bookmarklist. This is somewhat tricky as one -% does not want "Contents" in a table of contents but it has to be in the -% bookmark list. + {\dotripleempty\strc_bookmarks_place} -\def\doplacebookmarks[#1][#2][#3]% +\def\strc_bookmarks_place {\iflocation - \begingroup - \edef\askednames{#1}% - \edef\askedopened{#2}% - \ifx\askednames\empty - \edef\askednames{\getvalue{\??ih\v!content\c!list}}% - \fi - \ifx\askednames\empty - \let\askednames\v!all - \fi - \ifthirdargument - \getparameters[\??bm][#3]% - \else\ifsecondargument - \doifassignmentelse{#2}{\let\askedopened\empty\getparameters[\??bm][#2]}\donothing - \fi\fi - \ctxcommand{registerbookmark { - names = "\askednames", - opened = "\askedopened", - force = "\bookmarkparameter\c!force", - number = "\bookmarkparameter\c!number", - }}% - \endgroup + \expandafter\strc_bookmarks_place_yes + \else + \expandafter\gobblethreeoptionals \fi} -\setupbookmarks - [\c!force=\v!no, % it's easier to force that to inhibit - \c!number=\v!yes] % might become v!no +\let\m_bookmarks_names \empty +\let\m_bookmarks_opened\empty + +\def\strc_bookmarks_place_yes[#1][#2][#3]% + {\begingroup + \edef\m_bookmarks_names{#1}% + \edef\m_bookmarks_opened{#2}% + \ifx\m_bookmarks_names\empty + \edef\m_bookmarks_names{\namedlistparameter\v!content\c!list}% + \fi + \ifx\m_bookmarks_names\empty + \let\m_bookmarks_names\v!all + \fi + \ifthirdargument + \setupcurrentbookmark[#3]% no every so not all possible + \else\ifsecondargument + \doifassignmentelse{#2}{\let\m_bookmarks_opened\empty\setupcurrentbookmark[#2]}\donothing + \fi\fi + \ctxcommand{registerbookmark { + names = "\m_bookmarks_names", + opened = "\m_bookmarks_opened", + force = "\bookmarkparameter\c!force", + number = "\bookmarkparameter\c!number", + }}% + \endgroup} \appendtoks \ctxcommand{setupbookmarks { @@ -107,7 +123,7 @@ stopper = \!!bs\bookmarkparameter\c!numberstopper\!!es, segments = "\bookmarkparameter\c!numbersegments", }}% -\to \everysetupbookmarks +\to \everysetupbookmark \protect \endinput diff --git a/tex/context/base/strc-blk.lua b/tex/context/base/strc-blk.lua index d2f25dfb3..791f8f99b 100644 --- a/tex/context/base/strc-blk.lua +++ b/tex/context/base/strc-blk.lua @@ -9,10 +9,9 @@ if not modules then modules = { } end modules ['strc-blk'] = { -- this one runs on top of buffers and structure local type = type -local gmatch, find = string.gmatch, string.find -local lpegmatch = lpeg.match +local find, format, validstring = string.find, string.format, string.valid local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate local structures, context = structures, context @@ -45,7 +44,7 @@ function blocks.print(name,data,hide) else context.dostartnormalblock(name) end - context.viafile(data) + context.viafile(data,format("block.%s",validstring(name,"noname"))) if hide then context.dostophiddenblock() else diff --git a/tex/context/base/strc-blk.mkiv b/tex/context/base/strc-blk.mkiv index 3bd5d04ed..1dd144aa9 100644 --- a/tex/context/base/strc-blk.mkiv +++ b/tex/context/base/strc-blk.mkiv @@ -22,92 +22,78 @@ % todo: prefix numbers (needs further integration elsewhere) % check functionality % alternative files (needs further integration elsewhere) +% +% order matters: \c!before (think of: \c!before=\startitemize) +% +% no \endgroups -\def\namedblockparameter#1#2{\ifcsname\??tb#1#2\endcsname\csname\??tb#1#2\endcsname\fi} - -\unexpanded\def\setupblockparameters{\dodoubleargument \dosetupblock} % fast one (for compatibility) -\unexpanded\def\setupblock {\dodoubleargumentwithset\dosetupblock} % handles set - -\def\dosetupblock[#1]{\getparameters[\??tb#1]} % [#1][#2]} +\installcorenamespace {block} +\installcorenamespace {blocktemp} -\unexpanded\def\defineblock[#1]% - {\processcommalist[#1]\dodefineblock} +\installcommandhandler \??block {block} \??block -\def\dodefineblock#1% - {\getparameters - [\??tb#1] - [\c!before=\blank, - \c!after=\blank, - \c!inner=, - \c!style=, - \c!file=]% todo - \ctxcommand{definestructureblock("#1")}% - \setuvalue{\e!begin#1}{\dodoubleempty\dobeginofblock[#1]}% - \letvalue{\e!end#1}\relax} +\appendtoks + \ctxcommand{definestructureblock("\currentblock")}% + \setuevalue{\e!begin\currentblock}{\dodoubleempty\strc_blocks_begin[\currentblock]}% + \setuevalue{\e!end \currentblock}{}% +\to \everydefineblock -\def\dobeginofblock[#1][#2]% +\unexpanded\def\strc_blocks_begin[#1][#2]% {\normalexpanded{\buff_pickup{@block@}{\e!begin#1}{\e!end#1}} {}% before {\ctxcommand{savestructureblock("#1","#2","@block@")}}}% after -\def\dostarthiddenblock +\let\strc_blocks_setup\relax + +\unexpanded\def\dostarthiddenblock % called at lua end {\startnointerference \dostartnormalblock} -\def\dostophiddenblock +\unexpanded\def\dostophiddenblock % called at lua end {\dostopnormalblock \stopnointerference} -% order matters: \c!before (think of: \c!before=\startitemize) - -% no \endgroups - -\let\doblocksetups\gobbleoneargument - -\def\dostartnormalblock#1% name +\unexpanded\def\dostartnormalblock#1% called at lua end {\bgroup - \visibletrue + \visibletrue % will change \edef\currentblock{#1}% - \doblocksetups\currentblock - \let\doblocksetups\gobbleoneargument - \namedblockparameter\currentblock\c!before - \dousestylehashparameter{\??tb\currentblock}\c!style - \dousecolorhashparameter{\??tb\currentblock}\c!color - \namedblockparameter\currentblock\c!inner + \strc_blocks_setup + \let\strc_blocks_setup\relax + \blockparameter\c!before + \useblockstyleandcolor\c!style\c!color % maybe moev one line up (font spacing) + \blockparameter\c!inner % better \c!setups \ignorespaces} -\def\dostopnormalblock +\unexpanded\def\dostopnormalblock % called at lua end {\removeunwantedspaces - \namedblockparameter\currentblock\c!after + \blockparameter\c!after \par % todo: alternative = text, paragraph \egroup} -\def\dosetblockstate[#1][#2][#3]% state name tag +\def\strc_blocks_set_state[#1][#2][#3]% state name tag {\ctxcommand{setstructureblockstate("#1","#2","#3")}} -\def\doselectblocks[#1][#2][#3][#4]% state name tag setups +\def\strc_blocks_select[#1][#2][#3][#4]% state name tag setups {\bgroup \doifassignmentelse{#3} - {\getparameters[\??tb\??tb][\c!criterium=\v!text,#3]% - \def\doblocksetups##1{\getparameters[\??tb##1][#3]}% - \ctxcommand{selectstructureblock("#1","#2","","\@@tb@@tbcriterium")}} - {\getparameters[\??tb\??tb][\c!criterium=\v!text,#4]% - \def\doblocksetups##1{\getparameters[\??tb##1][#4]}% - \ctxcommand{selectstructureblock("#1","#2","#3","\@@tb@@tbcriterium")}}% + {\getparameters[\??blocktemp][\c!criterium=\v!text,#3]% + \def\strc_blocks_setup{\setupcurrentblock[#3]}% + \ctxcommand{selectstructureblock("#1","#2","","\csname\??blocktemp\c!criterium\endcsname")}} + {\getparameters[\??blocktemp][\c!criterium=\v!text,#4]% + \def\strc_blocks_setup{\setupcurrentblock[#4]}% + \ctxcommand{selectstructureblock("#1","#2","#3","\csname\??blocktemp\c!criterium\endcsname")}}% \egroup} -% hide: save, if [+] also hidden execute -% keep: save and normal execute - -\def\hideblocks{\dotripleempty\dosetblockstate[hide]} -\def\keepblocks{\dotripleempty\dosetblockstate[keep]} - +% hide : save, if [+] also hidden execute +% keep : save and normal execute % use : normal execute unless [-] % process: hidden execute unless [-] % select : idem use -\def\useblocks {\doquadrupleempty\doselectblocks[use]} -\def\processblocks{\doquadrupleempty\doselectblocks[process]} -\def\selectblocks {\doquadrupleempty\doselectblocks[use]} +\unexpanded\def\hideblocks {\dotripleempty \strc_blocks_set_state[hide]} +\unexpanded\def\keepblocks {\dotripleempty \strc_blocks_set_state[keep]} +\unexpanded\def\useblocks {\doquadrupleempty\strc_blocks_select [use]} +\unexpanded\def\processblocks{\doquadrupleempty\strc_blocks_select [process]} +\unexpanded\def\selectblocks {\doquadrupleempty\strc_blocks_select [use]} \protect \endinput diff --git a/tex/context/base/strc-con.mkvi b/tex/context/base/strc-con.mkvi index 956acaae5..64371579a 100644 --- a/tex/context/base/strc-con.mkvi +++ b/tex/context/base/strc-con.mkvi @@ -27,17 +27,16 @@ % % todo: \currentconstructionattribute : can be a counter instead - -%D Constructions are just descriptions but a bit more abstract so that -%D we can conveniently build upon them. They are not really meant for -%D users but module writers might find them useful. We mention a -%D couple of parameters but these are only mentioned because in the -%D shared code we map all resolvers to constructions. +%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 -\ifdefined\v!construction \else \def\v!construction{construction} \fi - %D Todo: \installcorenamespace{construction} @@ -70,9 +69,9 @@ % \c!alternative=\v!left, \c!display=\v!yes, - \c!width=7em, - \c!distance=1em, - \c!titledistance=0.5em, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, %c!hang=, %c!sample=, \c!margin=\v!no, @@ -137,9 +136,9 @@ {\csname\??constructionstophandler\currentconstructionhandler\endcsname \endgroup} -%D As we will build on top of the generic construction mechanism we -%D have handlers as a sort of plug in mechanism. In order to have -%D some consistency we share some namespaces. +%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} @@ -154,7 +153,7 @@ \unexpanded\def\strc_constructions_initialize#1% class instance {\edef\currentconstruction{#1}% -\let\currentconstructionlistentry\!!zerocount + \let\currentconstructionlistentry\!!zerocount \expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname \expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname \expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname @@ -167,16 +166,16 @@ \newconditional\c_strc_constructions_number_state \newconditional\c_strc_constructions_title_state -\setvalue{\??constructioninitializer\v!construction}% +\unexpanded\setvalue{\??constructioninitializer\v!construction}% {\setfalse\c_strc_constructions_number_state \setfalse\c_strc_constructions_title_state} -\setvalue{\??constructionfinalizer\v!construction}% +\unexpanded\setvalue{\??constructionfinalizer\v!construction}% {} -% 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. +%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 @@ -190,10 +189,10 @@ \unexpanded\def\currentconstructionsample {\begstrut \constructionparameter\c!text - \constructionparameter\c!sample + \p_strc_constructions_sample \endstrut} -\setvalue{\??constructionmainhandler\v!construction}#1% +\unexpanded\setvalue{\??constructionmainhandler\v!construction}#1% {\iftrialtypesetting \else \begingroup \currentconstructionsynchronize % reinstated @@ -202,7 +201,7 @@ \endgroup \fi#1} -\setvalue{\??constructiontexthandler\v!construction}% +\unexpanded\setvalue{\??constructiontexthandler\v!construction}% {\begingroup \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext \the\everyconstruction @@ -224,36 +223,54 @@ \def\resetconstructions % to be used in e.g. footnotes {\c_strc_constructions_nested_state\zerocount} -\setvalue{\??constructioncommandhandler\v!construction}% +\unexpanded\setvalue{\??constructioncommandhandler\v!construction}% {\endgroup} -\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing +\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 + +\unexpanded\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing {\dostarttagged\t!construction\currentconstruction \dotagsetconstruction \constructionparameter\c!before \begingroup \edef\currentconstructionalternative{\constructionparameter\c!alternative}% % \checkconstructionalternativeparent % this catches an unknown alternative - \doifnotsetups{\constructionalternativeparameter\c!renderingsetup} + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% + \doifnotsetups\p_strc_constructions_renderingsetup {\letconstructionparameter\c!alternative\v!left \let\currentconstructionalternative\v!left}% \doadaptleftskip{\constructionparameter\c!margin}% \setlocalhsize % so we can use \localhsize in width assignments \constructionsheaddistance\constructionalternativeparameter\c!distance\relax + \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}% \ifdim\constructionsheaddistance=\zeropoint - \doif{\constructionalternativeparameter\c!width}\v!broad{\constructionsheaddistance\emwidth}% + \ifx\p_strc_constructions_width\v!broad + \constructionsheaddistance\emwidth + \fi \fi % inefficient and not always needed, for instance not with margins so we will make checkers - % per alternative + % per alternative some day (especially in labels this is unwanted overhead) \setbox\constructionheadbox\hbox {\forgetall \dontcomplain \settrialtypesetting - \doifelsenothing{\constructionparameter\c!sample} - {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext}% - {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructionsample}}% + \edef\p_strc_constructions_sample{\constructionparameter\c!sample}% + \ifx\p_strc_constructions_sample\empty + \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext + \else + \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructionsample + \fi}% \assignwidth - {\constructionalternativeparameter\c!width} + \p_strc_constructions_width \constructionsheadwidth {\unhcopy\constructionheadbox} \constructionsheaddistance @@ -266,15 +283,24 @@ \else \csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}% \fi}% - \doifelse{\constructionparameter\c!aligntitle}\v!no - {\leftconstructionskip \leftskip - \rightconstructionskip\rightskip} - {\ifcase\c_strc_constructions_nested_state - \leftconstructionskip \leftskip - \rightconstructionskip\rightskip - \fi}% - \doifsomething{\constructionparameter\c!align}{\setupalign[\constructionparameter\c!align]}% \use... - \indenting[\constructionparameter\c!indenting]% \use... + \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 + \edef\p_strc_constructions_indenting{\constructionparameter\c!indenting}% + \ifx\p_strc_constructions_indenting\empty \else + \indenting[\p_strc_constructions_indenting]% \use... + \fi \ifcase\c_strc_constructions_nested_state \c_strc_constructions_nested_state\plusone \or @@ -282,15 +308,15 @@ \fi \strc_constructions_close_symbol_reset % - % \doifnotsetups {\constructionalternativeparameter\c!renderingsetup} - % {\let\currentconstructionalternative\v!left}% - \directsetup{\constructionalternativeparameter\c!renderingsetup}\relax + \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}% + % + \directsetup\p_strc_constructions_renderingsetup\relax % \dostoptagged % tag \dostarttagged\t!constructioncontent\empty \ignorespaces} % args not needed -\setvalue{\??constructionstophandler\v!construction}% +\unexpanded\setvalue{\??constructionstophandler\v!construction}% {\strc_constructions_close_symbol_place \doifnot{\constructionparameter\c!display}\v!no\par \dostoptagged % content @@ -302,16 +328,21 @@ % \endgroup \dorechecknextindentation} -\def\boxedconstructionhead#1% +\unexpanded\def\boxedconstructionhead#1% {\vtop {\hsize\constructionsheadwidth - \doifsomething{\constructionparameter\c!headalign}{\setupalign[\constructionparameter\c!headalign]}% + \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 @@ -391,16 +422,15 @@ {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang {\forgetall \dontcomplain - \hsize\constructionsheadwidth - \edef\p_headalign{\constructionparameter\c!headalign}% - \ifx\p_headalign\empty + \hsize\constructionsheadwidth\relax + \ifx\p_strc_constructions_headalign\empty \setupalign[#1]% use fast one \else - \setupalign[\p_headalign]% use fast one + \setupalign[\p_strc_constructions_headalign]% use fast one \fi \advance\ifx#1\v!flushleft\rightskip\else\leftskip\fi\constructionsheaddistance % only difference and wrong anyway \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}% -\setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex + \setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex \ht\constructionheadbox\strutht \dp\constructionheadbox\strutdp} @@ -408,12 +438,11 @@ {\setbox\constructionheadbox\vtop {\forgetall \dontcomplain - \hsize\constructionsheadwidth - \edef\p_headalign{\constructionparameter\c!headalign}% - \ifx\p_headalign\empty + \hsize\constructionsheadwidth\relax + \ifx\p_strc_constructions_headalign\empty \setupalign[#1]% use fast one \else - \setupalign[\p_headalign]% use fast one + \setupalign[\p_strc_constructions_headalign]% use fast one \fi \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}% \setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex @@ -421,18 +450,18 @@ \dp\constructionheadbox\strutdp} \def\strc_constructions_set_hang#1% - {\edef\p_hang{\constructionparameter\c!hang}% - \ifx\p_hang\empty - \else\ifx\p_hang\v!fit + {\ifx\p_strc_constructions_hang\empty + % nothing + \else\ifx\p_strc_constructions_hang\v!fit \scratchdimen\htdp\constructionheadbox \getnoflines\scratchdimen \hangafter-\noflines - \else\ifx\p_hang\v!broad + \else\ifx\p_strc_constructions_hang\v!broad \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax \getnoflines\scratchdimen \hangafter-\noflines \else - \hangafter-\p_hang + \hangafter-\p_strc_constructions_hang \fi\fi\fi \relax \hangindent\ifx#1\v!right-\fi\constructionsheadwidth} @@ -441,18 +470,18 @@ % environment. The wrapping happens elsewhere. \startsetups[\??constructionrenderings:\v!left] - \edef\p_hang{\constructionparameter\c!hang} - \doifsetupselse{\??constructionrenderings:\v!left:\p_hang} { - \directsetup{\??constructionrenderings:\v!left:\p_hang} + \edef\p_strc_constructions_hang{\constructionparameter\c!hang}% + \doifsetupselse{\??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_hang{\constructionparameter\c!hang} - \doifsetupselse{\??constructionrenderings:\v!right:\p_hang} { - \directsetup{\??constructionrenderings:\v!right:\p_hang} + \edef\p_strc_constructions_hang{\constructionparameter\c!hang} + \doifsetupselse{\??constructionrenderings:\v!right:\p_strc_constructions_hang} { + \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang} } { \directsetup{\??constructionrenderings:\v!right:\v!hanging} } @@ -462,9 +491,8 @@ \let\\=\crlf \noindent \strc_constructions_set_pure_box\v!flushleft - \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth\relax - \rightskip\rightconstructionskip - \advance\leftskip\constructionsheaddistance + \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax + \rightskip\rightconstructionskip\relax \llap { \hbox to \leftskip { \hskip\leftconstructionskip @@ -573,13 +601,18 @@ \stopsetups \startsetups[\??constructionrenderings:\v!top] - \dohandlepagebreakX\plusone + \strc_sectioning_prevent_page_break\plusone \let\\=\space \noindent - \copy\constructionheadbox\par % copy ? - \nobreak - \doifelsenothing{\constructionparameter\c!inbetween}{\blank}{\constructionparameter\c!inbetween}% + \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 + \par + \nobreak + \fi \useconstructionstyleandcolor\c!style\c!color \ignorespaces \stopsetups @@ -639,9 +672,9 @@ \stopsetups \startsetups[\??constructionrenderings:\v!serried] - \edef\p_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace - \doifsetupselse{\??constructionrenderings:\v!serried:\p_width} { - \directsetup{\??constructionrenderings:\v!serried:\p_width} + \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace + \doifsetupselse{\??constructionrenderings:\v!serried:\p_strc_constructions_width} { + \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width} } { \directsetup{\??constructionrenderings:\v!serried:\v!wide} } @@ -687,7 +720,7 @@ \noindent \advance\leftskip-\leftskipadaption\relax \ifdim\leftskipadaption=\zeropoint - \leftskipadaption1.5em\relax % just some default + \leftskipadaption1.5\emwidth\relax % just some default \ifnum\c_strc_constructions_nested_state=\plusone \ifdim\leftskip>\zeropoint \relax \leftskipadaption\leftskip @@ -699,7 +732,7 @@ \fi \hskip-\leftskipadaption\relax \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox - \kern\ifdim\constructionsheaddistance=\zeropoint .75em\else\constructionsheaddistance\fi + \kern\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi \useconstructionstyleandcolor\c!style\c!color \ignorespaces \stopsetups @@ -731,9 +764,9 @@ \unexpanded\def\strc_constructions_close_symbol_place {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname - \edef\p_closesymbol{\constructionparameter\c!closesymbol}% - \ifx\p_closesymbol\empty \else - \constructionparameter\c!closecommand{\p_closesymbol}% hm why {} maybe because box expected + \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} diff --git a/tex/context/base/strc-def.mkiv b/tex/context/base/strc-def.mkiv index 7917b7d83..0738bdf29 100644 --- a/tex/context/base/strc-def.mkiv +++ b/tex/context/base/strc-def.mkiv @@ -16,59 +16,6 @@ \unprotect -\setupheads[% - %\c!after=, - %\c!align=, - %\c!aligntitle=, - \c!alternative=\v!normal, - %\c!before=, - %\c!color=, - \c!command=\normalplacehead, - \c!continue=\v!yes, - %\c!coupling=, - %\c!deepnumbercommand=, - %\c!deeptextcommand=, - %\c!default=, - \c!distance=\!!zeropoint, - \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 - ] - % \setupsectionblock[appendix][sectionconversionset=appendix] % \setuphead[chapter][sectionconversionset=\sectionblockparameter\c!sectionconversionset] % \sectionblockparameter] @@ -102,7 +49,7 @@ % \startsetups defaults:frontpart:pagenumbers:roman % \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals] -% \setupuserpagenumber[\c!way=\v!byblock] +% \setupuserpagenumber[\c!way=\v!by\v!block] % \stopsetups % \definesectionblock @@ -233,7 +180,7 @@ \c!marking=\v!page, \c!header=, \c!style=\tfc, - \c!distance=.75em, + \c!distance=.75\emwidth, \c!before={\blank[2*\v!big]}, \c!after={\blank[2*\v!big]}] @@ -242,7 +189,7 @@ [%\c!align=, %\c!indentnext=\v!no, \c!style=\tfa, - \c!distance=.75em, + \c!distance=.75\emwidth, \c!before={\blank[2*\v!big]}, \c!after=\blank] diff --git a/tex/context/base/strc-des.mkii b/tex/context/base/strc-des.mkii index 587ef13e7..e699df9ea 100644 --- a/tex/context/base/strc-des.mkii +++ b/tex/context/base/strc-des.mkii @@ -47,7 +47,7 @@ % Op die manier is meer mogelijk en worden \par's geskipt. % % De macro \??dd#1\s!do\c!commando levert de koppeling tussen -% \doornumberen en \doordefinieren. Deze constructie is nodig +% \doornummeren en \doordefinieren. Deze constructie is nodig % omdat doornummeren geen argument heeft en omdat subnummers % niet worden genest binnen het hogere niveau. % diff --git a/tex/context/base/strc-des.mkvi b/tex/context/base/strc-des.mkvi index 29072fbc6..5635ff0df 100644 --- a/tex/context/base/strc-des.mkvi +++ b/tex/context/base/strc-des.mkvi @@ -33,9 +33,9 @@ %\c!color=, %\c!headcolor=, %\c!titlecolor=, - \c!width=7em, - \c!distance=1em, - \c!titledistance=0.5em, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, %\c!hang=, %\c!sample=, %\c!align=, @@ -71,15 +71,17 @@ \setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}% \to \everydefinedescription -\setvalue{\??constructioninitializer\v!description}% +\let\p_strc_constructions_title \empty + +\unexpanded\setvalue{\??constructioninitializer\v!description}% {\let\currentdescription \currentconstruction \let\constructionparameter \descriptionparameter \let\detokenizedconstructionparameter\detokenizeddescriptionparameter \let\letconstructionparameter \letdescriptionparameter \let\useconstructionstyleandcolor \usedescriptionstyleandcolor \let\setupcurrentconstruction \setupcurrentdescription - \edef\p_title{\constructionparameter\c!title}% - \ifx\p_title\v!yes + \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 @@ -116,10 +118,6 @@ \expandafter\strc_descriptions_start_yes_normal \fi} -% \unexpanded\def\strc_descriptions_start_yes_titled[#1]#2% todo userdata -% {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]% -% \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - \unexpanded\def\strc_descriptions_start_yes_titled[#1]% {\doifnextbgroupelse {\strc_descriptions_start_yes_titled_indeed[#1]}% @@ -141,11 +139,6 @@ \expandafter\strc_descriptions_start_nop_normal \fi} -% \unexpanded\def\strc_descriptions_start_nop_titled#1% -% {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]% -% \csname\??constructionstarthandler\currentconstructionhandler\endcsname} -% \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - \unexpanded\def\strc_descriptions_start_nop_titled {\doifnextbgroupelse {\strc_descriptions_start_nop_titled_indeed}% @@ -203,10 +196,6 @@ \expandafter\strc_descriptions_nop_normal \fi} -% \unexpanded\def\strc_descriptions_nop_titled#1% -% {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]% -% \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} - \unexpanded\def\strc_descriptions_nop_titled {\doifnextbgroupelse {\strc_descriptions_nop_titled_indeed}% @@ -227,17 +216,36 @@ \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 -\setvalue{\??constructioncommandhandler\v!description}% +\unexpanded\setvalue{\??constructioncommandhandler\v!description}% {\dowithpar {\csname\??constructionstarthandler\v!construction\endcsname}% {\csname\??constructionstophandler \v!construction\endcsname\endgroup}} -\setvalue{\??constructionstarthandler\v!description}% +\unexpanded\setvalue{\??constructionstarthandler\v!description}% {\BeforePar{\csname\??constructionstarthandler\v!construction\endcsname}% \GotoPar} -\setvalue{\??constructionstophandler\v!description}% +\unexpanded\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=\hskip4\emwidth, + \c!before=, + \c!after=] + +\unexpanded\def\setuptab + {\setupdescription[tab]} + +%D Maybe we should remove this definition. + \protect \endinput diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index f10b175a4..98d69f4ce 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -22,7 +22,7 @@ local max, min = math.max, math.min local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable local catcodenumbers = catcodes.numbers -local ctxcatcodes = tex.ctxcatcodes +local ctxcatcodes = catcodenumbers.ctxcatcodes local variables = interfaces.variables local v_last = variables.last @@ -64,7 +64,7 @@ local a_internal = attributes.private('internal') local data function documents.initialize() - data = { + data = allocate { -- whole data is marked numbers = { }, forced = { }, ownnumbers = { }, @@ -204,7 +204,7 @@ end function sections.setblock(name) local block = name or data.block or "unknown" -- can be used to set the default data.block = block - context(block) + return block end function sections.pushblock(name) @@ -213,7 +213,7 @@ function sections.pushblock(name) data.blocks[#data.blocks+1] = block data.block = block documents.reset() - context(block) + return block end function sections.popblock() @@ -221,7 +221,7 @@ function sections.popblock() local block = data.blocks[#data.blocks] or data.block data.block = block documents.reset() - context(block) + return block end function sections.currentblock() @@ -253,7 +253,8 @@ function sections.somelevel(given) -- normally these are passed as argument but nowadays we provide several -- interfaces (we need this because we want to be compatible) if trace_detail then - report_structure("name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",givenname,mappedlevel,olddepth,newdepth,resetset) + report_structure("name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'", + givenname, mappedlevel or "unknown", olddepth, newdepth, resetset) end local u = given.userdata if u then @@ -767,27 +768,31 @@ function sections.findnumber(depth,what) -- needs checking (looks wrong and slow if what == v_first or what == v_previous then for i=index,1,-1 do local s = collected[i] - local n = s.numbers - if #n == depth and n[depth] and n[depth] ~= 0 then - sectiondata = s - if quit then + if s then + local n = s.numbers + if #n == depth and n[depth] and n[depth] ~= 0 then + sectiondata = s + if quit then + break + end + elseif #n < depth then break end - elseif #n < depth then - break end end elseif what == v_last or what == v_next then for i=index,#collected do local s = collected[i] - local n = s.numbers - if #n == depth and n[depth] and n[depth] ~= 0 then - sectiondata = s - if quit then + if s then + local n = s.numbers + if #n == depth and n[depth] and n[depth] ~= 0 then + sectiondata = s + if quit then + break + end + elseif #n < depth then break end - elseif #n < depth then - break end end end @@ -926,3 +931,10 @@ commands.structureautocatcodedget = function(name,catcode) sections.structured commands.namedstructurevariable = function(depth,name) sections.structuredata(depth,name) end commands.namedstructureuservariable = function(depth,name) sections.userdata (depth,name) end + +-- + +function commands.setsectionblock (name) context(sections.setblock(name)) end +function commands.pushsectionblock(name) context(sections.pushblock(name)) end +function commands.popsectionblock () context(sections.popblock()) end + diff --git a/tex/context/base/strc-doc.mkiv b/tex/context/base/strc-doc.mkiv index 4e9dec32e..c8dfae1e4 100644 --- a/tex/context/base/strc-doc.mkiv +++ b/tex/context/base/strc-doc.mkiv @@ -17,240 +17,10 @@ \unprotect -\def\c!xmlsetup{xmlsetup} +%D This will move: -% We operate in a \type {@@ns} namespace. All data is passed through -% variables. Of course we can built another interface on top of this -% that accepts multiple arguments. We might change this approach and -% remove this layer but it was needed for the transition. - -\installcorenamespace{structure} - -\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters - -% \definesystemvariable{ns} -% \def\structureparameter#1{\csname\??ns#1\endcsname} -% \def\detokenizedstructureparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??ns#1\endcsname}} - -\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!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, - \c!command=\showstructuredata] - -% maybe flags for list, bm, mark - -\def\structurereferenceprefixon {+} -\def\structurereferenceprefixoff{-} - -\def\setstructurereferenceprefix - {\ifx\currentstructurereferenceprefix\empty - % nothing - \else\ifx\currentstructurereferenceprefix\structurereferenceprefixon - \setupglobalreferenceprefix[\currentstructurereference]% - \else\ifx\currentstructurereferenceprefix\structurereferenceprefixoff - \setupglobalreferenceprefix[]% - \else - \setupglobalreferenceprefix[\currentstructurereferenceprefix]% - \fi\fi\fi - \let\currentstructurereferenceprefix\referenceprefix} - -% why xdef ? - -\unexpanded\def\structurecomponent - {\dodoubleempty\dostructurecomponent} - -\def\dostructurecomponent[#1][#2]% #1=interfaced-settings, #2=optional user data (not yet supported) - {\begingroup - \setupstructure[#1]% - \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}% - \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 - \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle - \fi - \globallet\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}% - \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 - \begingroup - \simplifycommands - \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}% - \endgroup - \fi \fi - \fi - \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle - \fi - \globallet\currentstructurecoding\s!tex - \fi - \setnextinternalreference - \setstructurereferenceprefix - \xdef\currentstructurenumber{\ctxlua{ % todo: combine with next call, adapt marks accordingly - structures.sections.somelevel { - references = { - internal = \nextinternalreference, - block = "\currentsectionblock", - reference = "\currentstructurereference", - referenceprefix = "\currentstructurereferenceprefix", - backreference = "\currentstructurebackreference", - }, - directives = { - resetset = "\structureparameter\c!sectionresetset", - }, - metadata = { - kind = "section", - name = "\currentstructurename", - catcodes = \the\ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi, - coding = "\currentstructurecoding", - \ifx\currentstructurecoding\s!xml - xmlroot = "\xmldocument", - \fi - \ifx\currentstructurexmlsetup\empty \else - xmlsetup = "\currentstructurexmlsetup", - \fi - \ifx\currentstructuresaveinlist\v!no - nolist = true, - \fi - \ifx\currentstructureincrementnumber\v!yes - increment = "\currentstructureincrementnumber", - \fi - }, - titledata = { % we can add mark and reference - label = \!!bs\detokenize\expandafter{\currentstructurelabel }\!!es, - title = \!!bs\detokenize\expandafter{\currentstructuretitle }\!!es, - \ifx\currentstructurebookmark\currentstructuretitle \else - bookmark = \!!bs\detokenize\expandafter{\currentstructurebookmark }\!!es, - \fi - \ifx\currentstructuremarking\currentstructuretitle \else - marking = \!!bs\detokenize\expandafter{\currentstructuremarking }\!!es, - \fi - \ifx\currentstructuresaveinlist\v!no \else - \ifx\currentstructurelist\currentstructuretitle \else - list = \!!bs\detokenize\expandafter{\currentstructurelist}\!!es, - \fi - \fi - }, - numberdata = { - % needed ? - block = "\currentsectionblock", - hidenumber = \ifx\currentstructureshownumber\v!no true\else nil\fi, % titles - % so far - separatorset = "\structureparameter\c!sectionseparatorset", - conversion = "\structureparameter\c!sectionconversion", % for good old times sake - conversionset = "\structureparameter\c!sectionconversionset", - starter = \!!bs\structureparameter\c!sectionstarter\!!es, - stopper = \!!bs\structureparameter\c!sectionstopper\!!es, - set = "\structureparameter\c!sectionset", - segments = "\structureparameter\c!sectionsegments", - ownnumber = "\currentstructureownnumber", - }, - userdata = \!!bs\detokenize{#2}\!!es % will be converted to table at the lua end - } - }}% - \xdef\currentstructurelistnumber{\ctxcommand{addtolist(structures.sections.current())}}% - % \currentstructuresynchronize has to be called someplace, since it introduces a node - \setstructuresynchronization\currentstructurelistnumber - \structureparameter\c!command - \endgroup} - -\let\currentstructurenumber \!!zerocount -\let\currentsectioncountervalue \!!zerocount % redefined later -\let\previoussectioncountervalue\!!zerocount % redefined later - -% todo: a direct flusher (needed when hidden) - -\def\setstructuresynchronization#1% todo: use ctxcontext +\unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext {\xdef\currentstructureattribute {\ctxlua {tex.write(structures.references.setinternalreference("\currentstructurereferenceprefix","\currentstructurereference",\nextinternalreference,"\interactionparameter\c!focus"))}}% \xdef\currentstructuresynchronize{\ctxlatecommand{enhancelist(#1)}}} -\def\reportcurrentstructure{\ctxlua{structures.sections.reportstructure()}} - -% Beware: we need to flush the data to the list explicitly. This is because -% node in inserted and we may want control over when that happens. - -\def\showstructuredata - {\par - \dontleavehmode\begingroup - \currentstructuresynchronize - \currentstructureattribute - [\currentstructurename: \showstructurelevel: \currentstructuretitle] - \endgroup\par} - -% 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 - -\def\structurenumber {\ctxcommand{structurenumber()}} -\def\structuretitle {\ctxcommand{structuretitle()}} -\def\structurevariable #1{\ctxcommand{structurevariable("#1")}} -\def\structureuservariable #1{\ctxcommand{structureuservariable("#1")}} -\def\structurecatcodedget #1{\ctxcommand{structurecatcodedget("#1")}} % bad name -\def\structuregivencatcodedget #1#2{\ctxcommand{structuregivencatcodedget("#1",\number#2)}} % bad name -\def\structureautocatcodedget #1#2{\ctxcommand{structureautocatcodedget ("#1","#2")}} - -\def\namedstructurevariable #1#2{\ctxcommand{namedstructurevariable ("#1","#2")}} -\def\namedstructureuservariable#1#2{\ctxcommand{namedstructureuservariable("#1","#2")}} - \protect \endinput diff --git a/tex/context/base/strc-enu.mkvi b/tex/context/base/strc-enu.mkvi index e3261fa35..7b3f04942 100644 --- a/tex/context/base/strc-enu.mkvi +++ b/tex/context/base/strc-enu.mkvi @@ -85,10 +85,10 @@ %\c!color=, %\c!headcolor=, %\c!titlecolor=, - \c!width=8em, - \c!distance=0pt, -\c!distance=1em, - \c!titledistance=0.5em, + \c!width=8\emwidth, + \c!distance=\zeropoint, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, %\c!hang=, %\c!sample=, %\c!align=, @@ -175,15 +175,18 @@ \strc_enumerations_setup_counter\currentenumeration \to \everydefineenumeration -\setvalue{\??constructioninitializer\v!enumeration}% +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\unexpanded\setvalue{\??constructioninitializer\v!enumeration}% {\let\currentenumeration \currentconstruction \let\constructionparameter \enumerationparameter \let\detokenizedconstructionparameter\detokenizedenumerationparameter \let\letconstructionparameter \letenumerationparameter \let\useconstructionstyleandcolor \useenumerationstyleandcolor \let\setupcurrentconstruction \setupcurrentenumeration - \edef\p_number{\constructionparameter\c!number}% - \ifx\p_number\v!yes + \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 @@ -192,14 +195,14 @@ \else \setfalse\c_strc_constructions_number_state \fi - \edef\p_title{\constructionparameter\c!title}% - \ifx\p_title\v!yes + \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!enumeration}% +\unexpanded\setvalue{\??constructionfinalizer\v!enumeration}% {\ifconditional\c_strc_constructions_number_state \iftrialtypesetting \strc_counters_restore\currentconstructionnumber @@ -218,7 +221,8 @@ %D Counters (maybe we can share this code): (not ok yet, messy with notes) -%%%%%%%%%%% BEGIN TODO (SEE NOTES) %%%%%%%%%%%%%%% +% Maybe we should move counters to the construction level as more derived mechanisms +% use it \unknown\ so don't depend on names here! \newtoks\everysetupenumerationcounter @@ -236,18 +240,15 @@ \strc_counter_setup_using_parameter\v_strc_enumerations_counter_name\enumerationparameter \to \everysetupenumerationcounter -% \def\currentconstructionnumber {\enumerationparameter\s!counter} -% \def\specificconstructionnumber#1{\namedenumerationparameter{#1}\s!counter} - \def\currentconstructionnumber {\constructionparameter\s!counter} \def\specificconstructionnumber#1{\namedconstructionparameter{#1}\s!counter} \appendtoks - \strc_enumerations_setup_counter\currentenumeration + \ifx\currentenumeration\empty \else + \strc_enumerations_setup_counter\currentenumeration + \fi \to \everysetupenumeration -%%%%%%%%%%% END TODO (SEE NOTES) %%%%%%%%%%%%%%% - %D Initializer: %D The handlers. @@ -263,7 +264,7 @@ \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 -\setvalue{\??constructiontexthandler\v!enumeration}% +\unexpanded\setvalue{\??constructiontexthandler\v!enumeration}% {\begingroup \useconstructionstyleandcolor\c!headstyle\c!headcolor \strc_enumerations_text @@ -363,23 +364,23 @@ % % we will provide some more control, like skipping etc or reference relates -% todo - - \unexpanded\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:\nextinternalorderreference)]% - \fi - \fi} - - \def\skipenumerationcoupling[#1]% e.g. for questions with no answer - {\ctxlua{structures.references.setnextorder("construction","#1")}} +% to do / to be checked + +\unexpanded\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:\nextinternalorderreference)]% + \fi + \fi} + +\unexpanded\def\strc_enumerations_skip_number_coupling[#1]% e.g. for questions with no answer + {\ctxlua{structures.references.setnextorder("construction","#1")}} \protect \endinput diff --git a/tex/context/base/strc-flt.mkvi b/tex/context/base/strc-flt.mkvi index 05cfa40e3..07013b292 100644 --- a/tex/context/base/strc-flt.mkvi +++ b/tex/context/base/strc-flt.mkvi @@ -23,8 +23,10 @@ % % todo: strc_floats_analyze_variables_two could trigger a setup % and we could have nofmethods of them - -% Less globals! +% +% todo: move variables from page-flt to strc-flt +% +% todo: less globals! %D This module is being converted into a mkvi one. %D @@ -44,7 +46,7 @@ \let\setupcaption \setupfloatcaption \let\setupcaptions\setupfloatcaption -\def\dohandlenextfloatindent +\unexpanded\def\dohandlenextfloatindent {\useindentnextparameter\floatparameter \dorechecknextindentation} @@ -118,7 +120,7 @@ \c!textmethod=\ifgridsnapping2\else0\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE \c!indentnext=\v!no, - \c!margin=1em, + \c!margin=1\emwidth, \c!method=1, \c!cache=\v!yes, % when no, then intermediate flush \c!leftmargin=\zeropoint, % displacement in 'normal floats' @@ -129,7 +131,7 @@ \c!rightmargindistance=\floatparameter\c!leftmargindistance, \c!ntop=2, \c!nbottom=0, - \c!nlines=4, + \c!nlines=4, % used? %\c!local=, %\c!bottombefore=, % e.g. \vfill %\c!bottomafter=, @@ -144,45 +146,44 @@ \let\currentfloat\currentfloatcaption \ifx\currentfloat\empty \else \strc_counter_setup_using_parameter\currentfloatcaption\floatcaptionparameter - \strc_counters_check_setup\currentfloatcaption \fi \to \everysetupfloatcaption %D Definitions: -\let\saveddefinefloat\definefloat +\let\strc_floats_define_saved\definefloat \unexpanded\def\definefloat - {\dotripleempty\dodefinefloat} + {\dotripleempty\strc_floats_define} -\def\dodefinefloat[#1][#2][#3]% #1=naam #2=meervoud #3=parent +\def\strc_floats_define[#1][#2][#3]% #1=naam #2=meervoud #3=parent {\ifthirdargument - \redodefinefloat[#1][#2][#3]% + \strc_floats_define_cloned[#1][#2][#3]% \else\ifsecondargument - \dododefinefloat[#1][#2]% + \strc_floats_define_normal[#1][#2]% \else - \dododefinefloat[#1][#1]% + \strc_floats_define_normal[#1][#1]% \fi\fi} -\def\dododefinefloat[#1][#2]% +\def\strc_floats_define_normal[#1][#2]% {\definefloatcaption[#1]% \definecounter[#1]% \definelist[#1]% \presetlabeltext[#1=\Word{#1}~]% \presetheadtext[#2=\Word{#2}]% - \saveddefinefloat[#1]% - \dodefinefloatcommands[#1][#2]} + \strc_floats_define_saved[#1]% + \strc_floats_define_commands{#1}{#2}} -\def\redodefinefloat[#1][#2][#3]% +\def\strc_floats_define_cloned[#1][#2][#3]% {\definefloatcaption[#1][#3]% \definecounter[#1][#3]% \definelist[#1][#3]% \presetlabeltext[#1=\Word{#3}~]% \presetheadtext[#2=\Word{#2}]% - \saveddefinefloat[#1][#3]% - \dodefinefloatcommands[#1][#2]} + \strc_floats_define_saved[#1][#3]% + \strc_floats_define_commands{#1}{#2}} -\def\dodefinefloatcommands[#1][#2]% +\def\strc_floats_define_commands#1#2% {\setuvalue {\e!place\e!listof#2}{\dodoubleempty\strc_lists_place[#1]}% call will change \setuvalue {\e!complete\e!listof#2}{\dotripleempty\strc_lists_complete_indeed[#1][#2]}% call will change \setuevalue {\e!place#1}{\strc_floats_place{#1}}% @@ -254,11 +255,11 @@ % begin of todo -\unexpanded\def\placefloatcaption{\dodoubleempty\doplacefloatcaption} -\unexpanded\def\setfloatcaption {\dodoubleempty\dodosetfloatcaption} +\unexpanded\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption} +\unexpanded\def\setfloatcaption {\dodoubleempty\strc_floats_set_caption} -\def\doplacefloatcaption[#tag][#reference]#caption{[not supported]} -\def\dodosetfloatcaption[#tag][#reference]#caption{[not supported]} % \dosetfloatcaption already in use +\def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]} +\def\strc_floats_set_caption [#tag][#reference]#caption{[not supported]} \unexpanded\def\placefloatcaptiontext [#tag]{[not suported yet]} \unexpanded\def\placefloatcaptionnumber [#tag]{[not suported yet]} @@ -441,11 +442,15 @@ % we're really dealing with the float. Some day I'll root out % the global settings. +\let\lastplacedfloat\empty + \def\strc_floats_set_current_tag#tag% {\edef\currentfloat{#tag}% \ifx\currentfloat\empty \let\currentfloat\v!figure % a bit of a hack \fi + \global\let\lastplacedfloat\currentfloat + \let\m_strc_floats_saved_userdata\empty \let\currentfloatcaption\currentfloat} \def\strc_floats_reset_variables @@ -483,22 +488,36 @@ % start-stop +% \startplacefigure[title=oeps][subtitle=whatever] +% \framed[width=10cm,height=5cm]{\floatuserdataparameter{subtitle}} +% \stopplacefigure + +\installcorenamespace{floatuserdata} + +\installsetuponlycommandhandler \??floatuserdata {floatuserdata} + +\let\m_strc_floats_saved_userdata\empty % todo: reset this in non start|stop cases + \unexpanded\def\strc_floats_start_place#tag% {\flushnotes \page_otr_command_flush_side_floats % here ! \strc_floats_begin_group \strc_floats_set_current_tag{#tag}% - \dosingleempty\strc_floats_start_place_indeed} + \dodoubleempty\strc_floats_start_place_indeed} -\def\strc_floats_start_place_indeed[#settings]% tricky ... saved not ok yet +\def\strc_floats_start_place_indeed[#settings][#userdata]% {\strc_floats_reset_variables \edef\savedfloatlocation{\floatcaptionparameter\c!location}% \setupcurrentfloatcaption[\c!location=,\c!reference=,\c!title=,\c!marking=,\c!list=,\c!bookmark=,#settings]% + \def\m_strc_floats_saved_userdata{#2}% \edef\floatlocation{\floatcaptionparameter\c!location}% \setupcurrentfloatcaption[\c!location=\savedfloatlocation]% \ifx\floatlocation\empty \edef\floatlocation{\floatparameter\c!default}% \fi + \ifsecondargument + \setupcurrentfloatuserdata[#userdata]% + \fi \doifinsetelse\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal \bgroup \ignorespaces} @@ -569,15 +588,18 @@ % special hack -\def\strc_floats_begin_group {\begingroup} -\def\strc_floats_end_group {\carryoverpar\endgroup} -\def\strc_floats_end_split_group {\endgroup} - -\def\strc_floats_begin_text_group {\begingroup\let\strc_floats_end_group\relax} -\def\strc_floats_end_text_group {\endgroup} +\def\strc_floats_begin_group {\begingroup} +\def\strc_floats_end_group {\carryoverpar\endgroup} +\def\strc_floats_end_split_group {\endgroup} +\def\strc_floats_begin_text_group{\begingroup\let\strc_floats_end_group\relax} +\def\strc_floats_end_text_group {\endgroup} % implementation +%setnewconstant\c_page_one_float_method \zerocount % 0=raw 1=safe (.99) 2=tight (-1pt) / belongs in page-one +\setnewconstant\c_strc_floats_rotation \zerocount % 0 90 180 270 +\newconditional\c_strc_floats_par_float + \ifdefined\page_margin_strc_floats_before \else \let\page_margin_strc_floats_before \relax \fi \ifdefined\page_margin_strc_floats_set_hsize \else \let\page_margin_strc_floats_set_hsize\relax \fi @@ -595,7 +617,7 @@ \splitfloat{\strc_floats_place_next_box_normal}} \unexpanded\def\strc_floats_place_next_box_normal - {\ifsomefloatwaiting + {\ifconditional\c_page_floats_some_waiting % this was \checkwaitingfloats spread all over \doifinsetelse\v!always\floatlocation {\showmessage\m!floatblocks5\empty} @@ -628,63 +650,58 @@ \strc_floats_place_packaged_boxes \dostoptagged % tricky ... needs checking % we need to carry over the par because of side floats - \global\sidefloatdownshift \zeropoint - \global\sidefloatextrashift\zeropoint - \ifparfloat + \global\d_page_sides_downshift \zeropoint + \global\d_page_sides_extrashift\zeropoint + \ifconditional\c_strc_floats_par_float \doifinset\v!reset\floatlocation\page_sides_forget_floats \doinhibitblank \fi \strc_floats_end_group} -\setnewconstant\textfloatmethod\zerocount % 0=raw 1=safe (.99) 2=tight (-1pt) -\setnewconstant\floatrotation \zerocount % 0 90 180 270 - % nicer is a bunch of states and one loop that sets those states \def\strc_floats_analyze_variables_two {\ifinsidecolumns - \global\parfloatfalse + \global\setfalse\c_strc_floats_par_float \else - \doifcommonelse - {\floatlocation} - {\flushfloatslist} - {\global\parfloattrue} - {\global\parfloatfalse}% + \doifcommonelse\floatlocation\flushfloatslist + {\global\settrue \c_strc_floats_par_float} + {\global\setfalse\c_strc_floats_par_float}% \fi - \global\sidefloatshift\zeropoint - \global\sidefloatmaximum\zeropoint - \global\sidefloatmethod\floatparameter\c!sidemethod - \global\textfloatmethod\floatparameter\c!textmethod - \global\sidefloatalign\zerocount - \global\floatrotation\zerocount + \global\d_page_sides_shift \zeropoint + \global\d_page_sides_maximum \zeropoint + \global\c_page_sides_method \floatparameter\c!sidemethod + \global\c_page_one_float_method \floatparameter\c!textmethod + \global\c_page_sides_align \zerocount + \global\c_strc_floats_rotation \zerocount \strc_floats_calculate_skips - \ifparfloat + \ifconditional\c_strc_floats_par_float \processaction [\floatparameter\c!sidealign] - [\v!height=>\global\sidefloatalign\plusone,% - \v!line=>\global\sidefloatalign\plustwo,% (***) - \v!depth=>\global\sidefloatalign\plusthree,% - \v!grid=>\global\sidefloatalign\plusfour,% - \v!halfline=>\global\sidefloatalign\plusfive]% - \ifcase\sidefloatalign\relax % todo: optie v!lokaal => \else - \doifinset\v!height \floatlocation{\global\sidefloatalign\plusone}% - \doifinset\v!line \floatlocation{\global\sidefloatalign\plustwo}% - \doifinset\v!depth \floatlocation{\global\sidefloatalign\plusthree}% - \doifinset\v!grid \floatlocation{\global\sidefloatalign\plusfour}% - \doifinset\v!halfline\floatlocation{\global\sidefloatalign\plusfive}% meant for 'none' + [\v!height=>\global\c_page_sides_align\plusone ,% + \v!line=>\global\c_page_sides_align\plustwo ,% (***) + \v!depth=>\global\c_page_sides_align\plusthree,% + \v!grid=>\global\c_page_sides_align\plusfour ,% + \v!halfline=>\global\c_page_sides_align\plusfive ]% + \ifcase\c_page_sides_align\relax % todo: optie v!lokaal => \else + \doifinset\v!height \floatlocation{\global\c_page_sides_align\plusone }% + \doifinset\v!line \floatlocation{\global\c_page_sides_align\plustwo }% + \doifinset\v!depth \floatlocation{\global\c_page_sides_align\plusthree}% + \doifinset\v!grid \floatlocation{\global\c_page_sides_align\plusfour }% + \doifinset\v!halfline\floatlocation{\global\c_page_sides_align\plusfive }% meant for 'none' \fi - \doifinset\v!high\floatlocation{\global\sidefloattopskip \zeropoint}% - \doifinset\v!low \floatlocation{\global\sidefloatbottomskip\zeropoint}% + \doifinset\v!high\floatlocation{\global\d_page_sides_topskip \zeropoint}% + \doifinset\v!low \floatlocation{\global\d_page_sides_bottomskip\zeropoint}% \doifinset\v!fit \floatlocation - {\global\sidefloattopskip \zeropoint - \global\sidefloatbottomskip\zeropoint - \global\floatsideskip \zeropoint}% + {\global\d_page_sides_topskip \zeropoint + \global\d_page_sides_bottomskip\zeropoint + \global\d_strc_floats_margin \zeropoint}% \else \processallactionsinset [\floatlocation] - [ 90=>\global\floatrotation\commalistelement\relax,% - 180=>\global\floatrotation\commalistelement\relax,% - 270=>\global\floatrotation\commalistelement\relax]% + [ 90=>\global\c_strc_floats_rotation\commalistelement\relax,% + 180=>\global\c_strc_floats_rotation\commalistelement\relax,% + 270=>\global\c_strc_floats_rotation\commalistelement\relax]% \fi \doifinsetelse\v!nonumber\floatlocation {\global\nofloatnumbertrue} @@ -703,19 +720,15 @@ % documenteren in details \def\strc_floats_analyze_variables_one - {\doifelse{\floatparameter\c!local}\v!yes % fout keyword - \globalcenterfloatboxtrue - \globalcenterfloatboxfalse - \ifglobalcenterfloatbox - \localcenterfloatboxtrue + {\doifelse{\floatparameter\c!local}\v!yes\settrue\setfalse\c_page_floats_center_box_global % fout keyword + \ifconditional\c_page_floats_center_box_global + \settrue\c_page_floats_center_box_local \else - \doifinsetelse\v!local\floatlocation - \localcenterfloatboxtrue - \localcenterfloatboxfalse + \doifinsetelse\v!local\floatlocation\settrue\setfalse\c_page_floats_center_box_local \fi \doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! ! - {\globalcenterfloatboxfalse - \localcenterfloatboxfalse}} + {\setfalse\c_page_floats_center_box_global + \setfalse\c_page_floats_center_box_local}} \let\naturalfloatheight\!!zeropoint \let\naturalfloatwidth \!!zeropoint @@ -762,6 +775,9 @@ \newconditional\usesamefloatnumber \def\strc_floats_place_packaged_boxes + {\expandafter\strc_floats_place_packaged_boxes_indeed\expandafter{\m_strc_floats_saved_userdata}} + +\def\strc_floats_place_packaged_boxes_indeed#userdata% {\bgroup \ifconditional\usesamefloatnumber \globallet\currentfloatnumber \previousfloatnumber @@ -784,7 +800,7 @@ \s!hascaption=\ifnofloatcaption \v!no\else\v!yes\fi,% \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,% \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]% - []% + [#userdata]% \globallet\previousfloatnumber \m_strc_counters_last_registered_index \globallet\currentfloatnumber \m_strc_counters_last_registered_index \globallet\currentfloatattribute \m_strc_counters_last_registered_attribute @@ -816,21 +832,11 @@ \strc_floats_get_box \global\insidefloatfalse} -% \def\strc_floats_set_local_hsize -% {\iflocalcenterfloatbox -% \seteffectivehsize -% \hsize\localhsize -% \else -% \doifinset\v!margin\floatlocation % brr, really needed! see wm will be redone -% {\let\currentmarginblock\empty -% \hsize\marginblockparameter\c!width}% -% \fi} - \newdimen\availablefloatwidth \newdimen\availablefloatheight \def\strc_floats_set_local_hsize - {\iflocalcenterfloatbox + {\ifconditional\c_page_floats_center_box_local % also available check here? \seteffectivehsize \hsize\localhsize @@ -878,18 +884,18 @@ % watch out: line alone aligns on the line ! ! ! \unexpanded\def\movesidefloat[#settings]% (-)n*line|x=,y= - {\global\sidefloatdownshift \zeropoint - \global\sidefloatextrashift\zeropoint + {\global\d_page_sides_downshift \zeropoint + \global\d_page_sides_extrashift\zeropoint \doifassignmentelse{#settings}% {\begingroup \setupcurrentfloat[\c!x=\zeropoint,\c!y=\zeropoint,#settings]% \ifgridsnapping \getnoflines{\floatparameter\c!y}% - \global\sidefloatdownshift\noflines\lineheight + \global\d_page_sides_downshift\noflines\lineheight \else - \global\sidefloatdownshift\floatparameter\c!y + \global\d_page_sides_downshift\floatparameter\c!y \fi - \global\sidefloatextrashift\floatparameter\c!x + \global\d_page_sides_extrashift\floatparameter\c!x \endgroup} {\movedownsidefloat[#settings]}} @@ -909,17 +915,17 @@ \def\strc_floats_move_down_line#sign% {\if!!donea \else - \global\sidefloatdownshift\zeropoint + \global\d_page_sides_downshift\zeropoint \!!doneatrue \fi - \global\advance\sidefloatdownshift#sign\lineheight} + \global\advance\d_page_sides_downshift#sign\lineheight} \def\strc_floats_move_down_hang#lines% {\if!!doneb \else - \global\sidefloatsidelines\zerocount + \global\c_page_sides_n_of_lines\zerocount \!!donebtrue \fi - \global\advance\sidefloatsidelines#lines\relax} + \global\advance\c_page_sides_n_of_lines#lines\relax} \unexpanded\def\movedownsidefloat[#settings]% already in core {\doifnotinstring{:}{#settings} @@ -930,7 +936,7 @@ \endgroup}} \unexpanded\def\hangsidefloat[#number]% - {\global\sidefloatsidelines#number\relax} + {\global\c_page_sides_n_of_lines#number\relax} \def\strc_floats_set_extra_action#rightpagelocation#leftpagelocation% {\rightorleftpageaction @@ -956,7 +962,7 @@ \def\strc_floats_check_extra_actions % less tracingthis way ... {\doifnotinset\v!text\floatlocation % fuzzy, text overloads left, since then it's a directive {\let\extrafloatlocation\empty - % \sidefloatdownshift will be reset afterwards, and can + % \d_page_sides_downshift will be reset afterwards, and can % already be set at this point \processcommacommand[\floatlocation]\strc_floats_check_extra_actions_step \ifx\extrafloatlocation\empty \else @@ -971,11 +977,11 @@ % pas op, maxbreedte niet instellen als plaats=links/rechts \def\strc_floats_set_local_dimensions - {\global\sidefloatshift \zeropoint % duplicate - \global\sidefloatmaximum\zeropoint\relax % duplicate - \ifdim\sidefloatdownshift=\zeropoint\else + {\global\d_page_sides_shift \zeropoint % duplicate + \global\d_page_sides_maximum\zeropoint\relax % duplicate + \ifdim\d_page_sides_downshift=\zeropoint\else \global\setbox\floatbox\vbox - {\vskip\sidefloatdownshift + {\vskip\d_page_sides_downshift \nointerlineskip \box\floatbox}% \fi @@ -1002,7 +1008,7 @@ \scratchwidth\p_maxwidth\relax \ifdim\wd\floatbox>\scratchwidth \doifcommonelse{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}\floatlocation - {\global\sidefloatmaximum\scratchwidth} + {\global\d_page_sides_maximum\scratchwidth} {\doifcommonelse{\v!right,\v!left}\floatlocation \strc_floats_realign_floatbox_horizontal_one \strc_floats_realign_floatbox_horizontal_two}% @@ -1024,20 +1030,9 @@ \unexpanded\def\placefloats {\page_otr_command_flush_floats} -\installinsertion\topins -\installinsertion\botins - -\newdimen\botinserted -\newdimen\topinserted - -\newif\iftestfloatbox - -\newdimen\floatsideskip \floatsideskip 12pt -\newdimen\floattopskip \floattopskip \floattopskip -\newdimen\floatbottomskip \floatbottomskip \floattopskip - -\newcount\noftopfloats \noftopfloats=2 -\newcount\nofbotfloats \nofbotfloats=0 +\newdimen\d_strc_floats_margin +\newdimen\d_strc_floats_top +\newdimen\d_strc_floats_bottom \def\strc_floats_calculate_skip#target#skip% {\edef\askedfloatskip{#skip}% @@ -1052,33 +1047,21 @@ \def\strc_floats_calculate_skips {\begingroup - \strc_floats_calculate_skip\floattopskip {\rootfloatparameter\c!spacebefore}% - \strc_floats_calculate_skip\floatbottomskip {\rootfloatparameter\c!spaceafter}% - \strc_floats_calculate_skip\sidefloattopskip {\rootfloatparameter\c!sidespacebefore}% - \strc_floats_calculate_skip\sidefloatbottomskip{\rootfloatparameter\c!sidespaceafter}% - \global\floatsideskip \rootfloatparameter\c!margin - \global\sidefloatleftshift \floatparameter\c!leftmargindistance - \global\sidefloatrightshift\floatparameter\c!rightmargindistance - \global\noftopfloats \rootfloatparameter\c!ntop\relax - \global\nofbotfloats \rootfloatparameter\c!nbottom\relax + \strc_floats_calculate_skip\d_strc_floats_top {\rootfloatparameter\c!spacebefore }% + \strc_floats_calculate_skip\d_strc_floats_bottom {\rootfloatparameter\c!spaceafter }% + \strc_floats_calculate_skip\d_page_sides_topskip {\rootfloatparameter\c!sidespacebefore}% + \strc_floats_calculate_skip\d_page_sides_bottomskip{\rootfloatparameter\c!sidespaceafter }% + \global\d_strc_floats_margin \rootfloatparameter\c!margin + \global\d_page_sided_leftshift \floatparameter \c!leftmargindistance + \global\d_page_sided_rightshift\floatparameter \c!rightmargindistance + \global\c_page_floats_n_of_top \rootfloatparameter\c!ntop + \global\c_page_floats_n_of_bottom \rootfloatparameter\c!nbottom \endgroup} -% beter de laatste skip buiten de \insert uitvoeren, -% bovendien bij volle flush onder baseline. - -% \def\betweenfloatblanko% assumes that spaceafter is present -% {\bgroup -% \setbox0\vbox{\strut\blank[\rootfloatparameter\c!spacebefore]\strut}% -% \setbox2\vbox{\strut\blank[\rootfloatparameter\c!spaceafter]\strut}% -% \ifdim\ht0>\ht2 -% \blank[-\rootfloatparameter\c!spaceafter,\rootfloatparameter\c!spacebefore]% -% \fi -% \egroup} - -\unexpanded\def\betweenfloatblanko% assumes that spaceafter is present +\unexpanded\def\betweenfloatblanko % assumes that spaceafter is present {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,.... -\def\doplacefloatbox % used elsewhere +\unexpanded\def\doplacefloatbox % used elsewhere {%\forgetall % NO \whitespace \blank[\rootfloatparameter\c!spacebefore] @@ -1096,20 +1079,16 @@ \def\page_one_place_float_text % this macro should be defined elsewhere {%\checkwaitingfloats\floatlocationmethod % todo: check if #1 is indeed \floatlocation or maybe more - \global\floattextwidth\hsize - \global\floatwidth\wd\floatbox - \global\floatheight\ht\floatbox % forget about the depth - \global\advance\floattextwidth -\floatwidth - \global\advance\floattextwidth -\rootfloatparameter\c!margin\relax + \global\floatwidth \wd\floatbox + \global\floatheight \ht\floatbox % forget about the depth + \global\floattextwidth\dimexpr\hsize-\floatwidth-\rootfloatparameter\c!margin\relax \edef\floatlocation{\floatlocationmethod}% to be sure .. why \doifinsetelse\v!tall\floatlocationmethod - {\floattextheight\pagegoal - \advance\floattextheight -\pagetotal - \advance\floattextheight -\bigskipamount % lelijk + {\floattextheight\dimexpr\pagegoal-\pagetotal-\bigskipamount\relax % ugly, this bigskip \ifdim\floattextheight>\textheight \floattextheight\textheight \fi - \boxmaxdepth\zeropoint \relax % toegevoegd + \boxmaxdepth\zeropoint\relax % toegevoegd \ifdim\floattextheight<\floatheight \floattextheight\floatheight \fi @@ -1126,11 +1105,7 @@ \def\strc_floats_stop_text_indeed {\egroup \doifnotinset\v!tall\floatlocation - {\ifdim\ht\floattext<\floatheight - \floattextheight\floatheight - \else - \floattextheight\ht\floattext - \fi}% + {\floattextheight\ifdim\ht\floattext<\floatheight\floatheight\else\ht\floattext\fi}% \setbox\floatbox\vbox to \floattextheight {\hsize\floatwidth \doifinsetelse\v!both\floatlocation @@ -1171,7 +1146,7 @@ \dostoptagged \blank[\rootfloatparameter\c!spaceafter]% \strc_floats_end_text_group - \doinsertfloatinfo} + \page_floats_report_total} \def\borderedfloatbox {\begingroup @@ -1197,11 +1172,16 @@ \alignedline{\floatparameter\c!location}\v!middle} \newdimen\d_strc_floats_content +\newdimen\d_strc_float_temp_height +\newdimen\d_strc_float_temp_width + +\def\captionminwidth {15\bodyfontsize} +\def\captionovershoot{2\emwidth} \def\strc_floats_set_page_variant {\bgroup \strc_floats_set_local_hsize - \ifcase\floatrotation\else + \ifcase\c_strc_floats_rotation\else \swapdimens\hsize\vsize \fi \forgetall @@ -1211,10 +1191,12 @@ \let\strc_floats_align_content\strc_floats_align_content_indeed \let\strc_floats_align_caption\strc_floats_align_caption_indeed \strc_floats_check_caption_content -\d_strc_floats_content\wd\b_strc_floats_content + \d_strc_floats_content\wd\b_strc_floats_content \ifcase\floatparameter\c!method - \or % automatic - \ifnofloatcaption + % nothing + \or + % automatic + \ifnofloatcaption \strc_floats_prepare_no_caption %\page_backgrounds_add_local_to_box\floatbox % was \doglobal but not needed \else @@ -1227,21 +1209,20 @@ %\page_backgrounds_add_local_to_box\b_strc_floats_caption \strc_floats_build_box \fi - \or % semi automatic - \or % manual + \or + % semi automatic + \or + % manual \fi - \ifcase\floatrotation + \ifcase\c_strc_floats_rotation \doifnotinset\v!margin\floatlocation % brr, really needed! see wm {\postcenterfloatbox\d_strc_floats_content}% \else \global\setbox\floatbox\vbox - {\rotate[\c!rotation=\number\floatrotation]{\box\floatbox}}% + {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\box\floatbox}}% \fi \egroup} -\def\captionminwidth {15\bodyfontsize} -\def\captionovershoot {2em} - \def\strc_floats_prepare_no_caption {\global\setbox\floatbox\vbox % pas op als wd groter dan hsize {\ifinsidecolumns\ifdim\wd\b_strc_floats_content>\hsize @@ -1250,86 +1231,54 @@ \strc_floats_align_content{\copy\b_strc_floats_content}}} \def\strc_floats_prepare_page_caption - {\dostarttagged\t!floatcaption\empty - \doifinsetelse{\floatcaptionparameter\c!location}{\v!top,\v!bottom} - {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max} - {\doifelse{\floatcaptionparameter\c!minwidth}\v!fit - {\doifelse{\floatcaptionparameter\c!width}\v!max - {\dopreparestackcaptionmax} - {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption - \doifelse{\floatcaptionparameter\c!width}\v!fit - {\dopreparestackcaptionaut} - {\dopreparestackcaptionwid}% - \else - \dopreparestackcaptionmin - \fi}} - {\dopreparestackcaptionfix}}% - {\dopreparesidewidthcaption}}% new, special effects (see icare) - {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max} - {\dopreparesideautocaption} - {\dopreparesidewidthcaption}}% - \dostoptagged} - -% makes sense if we preexpand more variables - -% \def\strc_floats_prepare_page_caption -% {\edef\p_caption_location{\floatcaptionparameter\c!location}% -% \edef\p_caption_width {\floatcaptionparameter\c!width}% -% \edef\p_caption_minwidth{\floatcaptionparameter\c!minwidth}% -% \edef\p_caption_align {\floatcaptionparameter\c!align}% -% \dostarttagged\t!floatcaption\empty -% \ifx\p_caption_location\v!top -% \strc_floats_prepare_page_caption_top_bottom -% \else\ifx\p_caption_location\v!bottom -% \strc_floats_prepare_page_caption_top_bottom -% \else\ifx\p_caption_width\v!fit -% \dopreparesideautocaption -% \else\ifx\p_caption_width\v!max -% \dopreparesideautocaption -% \else -% \dopreparesidewidthcaption -% \fi\fi\fi\fi -% \dostoptagged} + {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}% + \edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}% + \edef\p_strc_floats_caption_minwidth{\floatcaptionparameter\c!minwidth}% + \edef\p_strc_floats_caption_align {\floatcaptionparameter\c!align}% + \dostarttagged\t!floatcaption\empty + \ifx\p_strc_floats_caption_location\v!top + \strc_floats_prepare_page_caption_top_bottom + \else\ifx\p_strc_floats_caption_location\v!bottom + \strc_floats_prepare_page_caption_top_bottom + \else\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_side_auto_caption + \else\ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_side_auto_caption + \else + \strc_floats_prepare_side_width_caption + \fi\fi\fi\fi + \dostoptagged} -% \def\strc_floats_prepare_page_caption_top_bottom -% {\ifx\p_caption_width\v!fit -% \strc_floats_prepare_page_caption_top_bottom_fit_max -% \else\ifx\p_caption_width\v!max -% \strc_floats_prepare_page_caption_top_bottom_fit_max -% \else -% \dopreparesidewidthcaption % new, special effects (see icare) -% \fi\fi} - -% \def\strc_floats_prepare_page_caption_top_bottom_fit_max -% {\ifx\p_caption_minwidth\v!fit -% \ifx\p_caption_width\v!max -% \dopreparestackcaptionmax -% \else\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption -% \ifx\p_caption_width\v!fit -% \dopreparestackcaptionaut -% \else -% \dopreparestackcaptionwid -% \fi -% \else -% \dopreparestackcaptionmin -% \fi\fi -% \else -% \dopreparestackcaptionfix -% \fi} - -% \def\dopreparestackcaptionmin -% {\setbox\b_strc_floats_caption\vbox -% {\strc_floats_caption_set_align -% \hsize\wd\b_strc_floats_content -% \ifx\p_caption_align\empty -% \raggedcenter % on purpose overloads align ! -% \fi -% \strc_floats_make_complete_caption}} +\def\strc_floats_prepare_page_caption_top_bottom + {\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_page_caption_top_bottom_fit_max + \else\ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_page_caption_top_bottom_fit_max + \else + \strc_floats_prepare_side_width_caption % new, special effects (see icare) + \fi\fi} + +\def\strc_floats_prepare_page_caption_top_bottom_fit_max + {\ifx\p_strc_floats_caption_minwidth\v!fit + \ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_stack_caption_max + \else\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption + \ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_stack_caption_auto + \else + \strc_floats_prepare_stack_caption_width + \fi + \else + \strc_floats_prepare_stack_caption_min + \fi\fi + \else + \strc_floats_prepare_stack_caption_fixed + \fi} \def\strc_floats_caption_set_align - {\normalexpanded{\setupalign[\v!reset,\floatcaptionparameter\c!align]}} + {\normalexpanded{\setupalign[\v!reset,\p_strc_floats_caption_align]}} -\def\dopreparesideautocaption +\def\strc_floats_prepare_side_auto_caption {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax \ifdim\wd\b_strc_floats_caption>\scratchdimen \ifdim\wd\b_strc_floats_caption<1.3\scratchdimen @@ -1341,41 +1290,43 @@ \hsize\scratchdimen \strc_floats_make_complete_caption}} -\def\dopreparesidewidthcaption +\def\strc_floats_prepare_side_width_caption {\setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align \hsize\floatcaptionparameter\c!width \strc_floats_make_complete_caption}} -\def\dopreparestackcaptionfix +\def\strc_floats_prepare_stack_caption_fixed {\setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align \hsize\floatcaptionparameter\c!minwidth % special effects \strc_floats_make_complete_caption}} -\def\dopreparestackcaptionmax +\def\strc_floats_prepare_stack_caption_max {\setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align \hsize\wd\b_strc_floats_content \strc_floats_make_complete_caption}} -\def\dopreparestackcaptionwid +\def\strc_floats_prepare_stack_caption_width {\setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align \hsize\floatcaptionparameter\c!width \strc_floats_make_complete_caption}} -\def\dopreparestackcaptionmin +\def\strc_floats_prepare_stack_caption_min {\setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align \hsize\wd\b_strc_floats_content - \doifnothing{\floatcaptionparameter\c!align}\raggedcenter % on purpose overloads align ! + \ifx\p_strc_floats_caption_align\empty + \raggedcenter % on purpose overloads align ! + \fi \strc_floats_make_complete_caption}} -\def\dopreparestackcaptionaut - {\doifsomething{\floatcaptionparameter\c!align} - {\doifnotinset\v!middle{\floatcaptionparameter\c!align}% - {\let\captionovershoot\!!zeropoint}}% +\def\strc_floats_prepare_stack_caption_auto + {\ifx\p_strc_floats_caption_align\empty \else + \doifnotinset\v!middle\p_strc_floats_caption_align{\let\captionovershoot\!!zeropoint}% + \fi \edef\captionhsize{\the\wd\b_strc_floats_content}% \ifdim\captionhsize>\hsize % float is wider than \hsize @@ -1388,8 +1339,7 @@ \ifdim\ht\scratchbox>\lineheight % more lines \setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align - \hsize\captionhsize - \advance\hsize -\captionovershoot\relax + \hsize\dimexpr\captionhsize-\captionovershoot\relax \ifdim\hsize<\captionminwidth\relax \hsize\captionhsize \fi @@ -1408,175 +1358,192 @@ \fi \setbox\scratchbox\vbox % test with overshoot {\settrialtypesetting - \scratchdimen\captionhsize - \advance\scratchdimen \captionovershoot - \advance\scratchdimen 3em % an average word length - \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi + \scratchdimen\dimexpr\captionhsize+\captionovershoot+3\emwidth\relax % 3em is an average word length + \ifdim\scratchdimen<\hsize + \hsize\scratchdimen + \fi \notesenabledfalse \strc_floats_make_complete_caption}% \ifdim\ht\scratchbox>\lineheight % at least an average word longer than a line \setbox\b_strc_floats_caption\vbox {\strc_floats_caption_set_align - \scratchdimen\captionhsize - \advance\scratchdimen \captionovershoot - \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi + \scratchdimen\dimexpr\captionhsize+\captionovershoot\relax + \ifdim\scratchdimen<\hsize + \hsize\scratchdimen + \fi + \strc_floats_make_complete_caption}% + \else\ifx\p_strc_floats_caption_align\empty + \setbox\b_strc_floats_caption\vbox + {\strc_floats_caption_set_align + \hsize\captionhsize + \raggedcenter % overloads \strc_floats_make_complete_caption}% \else - % just over a line, don't use an overshoot % % % todo: outer/inner and such - \doifcommonelse{\floatcaptionparameter\c!align}{\v!left,\v!right,\v!flushleft,\v!flushright} - {\setbox\b_strc_floats_caption\vbox - {\strc_floats_caption_set_align - \hsize\captionhsize - % strange : \raggedcenter - \strc_floats_make_complete_caption}} - {% nicer - \setbox\b_strc_floats_caption\vbox - {\strc_floats_caption_set_align - \hsize\captionhsize - \doifnothing{\floatcaptionparameter\c!align}\raggedcenter% overloads - \strc_floats_make_complete_caption}}% - \fi + \setbox\b_strc_floats_caption\vbox + {\strc_floats_caption_set_align + \hsize\captionhsize + \strc_floats_make_complete_caption}% + \fi\fi \fi} -\newdimen\tempfloatheight -\newdimen\tempfloatwidth +\def\strc_floats_between_stack + {\endgraf + \nointerlineskip + \floatcaptionparameter\c!inbetween + \endgraf} -\def\dofloatboxbetweenstack - {\endgraf\nointerlineskip\floatcaptionparameter\c!inbetween\endgraf} - -\def\dofloatboxdefaultbuilder % done +\def\strc_floats_build_box_default % done {\strc_floats_align_content{\box\b_strc_floats_content}} -\def\dofloatboxnextrightbuilder#1% - {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi - {\tempfloatheight\ht\b_strc_floats_content +\def\strc_floats_build_box_next_right#1% + {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi + {\d_strc_float_temp_height\ht\b_strc_floats_content \box\b_strc_floats_content - \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}% - \vbox to\tempfloatheight{#1}}} - -\def\dofloatboxnextleftbuilder#1% - {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi - {\tempfloatheight\ht\b_strc_floats_content - \vbox to\tempfloatheight{#1}% - \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}% + \doifnotinset\v!hang{\floatcaptionparameter\c!location} + {\dotfskip{\floatcaptionparameter\c!distance}}% + \vbox to\d_strc_float_temp_height{#1}}} + +\def\strc_floats_build_box_next_left#1% + {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi + {\d_strc_float_temp_height\ht\b_strc_floats_content + \vbox to\d_strc_float_temp_height{#1}% + \doifnotinset\v!hang{\floatcaptionparameter\c!location} + {\dotfskip{\floatcaptionparameter\c!distance}}% \box\b_strc_floats_content}} -\def\dofloatboxnextouterbuilder - {\doifrightpagefloatelse\dofloatboxnextrightbuilder\dofloatboxnextleftbuilder} +\def\strc_floats_build_box_next_outer + {\doifrightpagefloatelse\strc_floats_build_box_next_right\strc_floats_build_box_next_left} -\def\dofloatboxnextinnerbuilder - {\doifrightpagefloatelse\dofloatboxnextleftbuilder\dofloatboxnextrightbuilder} +\def\strc_floats_build_box_next_inner + {\doifrightpagefloatelse\strc_floats_build_box_next_left\strc_floats_build_box_next_right} -\def\dofloatboxnextrighthangbuilder#1% - {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi - {\tempfloatheight\ht\b_strc_floats_content +\def\strc_floats_build_box_next_right_hang#1% + {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi + {\d_strc_float_temp_height\ht\b_strc_floats_content \box\b_strc_floats_content - \vbox to\tempfloatheight{#1}}} + \vbox to\d_strc_float_temp_height{#1}}} -\def\dofloatboxnextlefthangbuilder#1% - {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi - {\tempfloatheight\ht\b_strc_floats_content - \vbox to\tempfloatheight{#1}% +\def\strc_floats_build_box_next_left_hang#1% + {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi + {\d_strc_float_temp_height\ht\b_strc_floats_content + \vbox to\d_strc_float_temp_height{#1}% \box\b_strc_floats_content}} -\def\dodofloatboxnextrightmarginbuilder#1#2% - {\ifparfloat +\def\strc_floats_build_box_next_right_margin_indeed#1#2% + {\ifconditional\c_strc_floats_par_float \hbox\bgroup - \tempfloatheight\ht\b_strc_floats_content + \d_strc_float_temp_height\ht\b_strc_floats_content \box\b_strc_floats_content - \hsmash{\hskip#1\vbox to\tempfloatheight{#2}}% + \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}% \egroup \else \begingroup - \tempfloatheight\ht\b_strc_floats_content - \everyrightofalignedline{\hsmash{\hskip#1\vbox to\tempfloatheight{#2}}}% + \d_strc_float_temp_height\ht\b_strc_floats_content + \everyrightofalignedline{\hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}}% \strc_floats_align_content{\box\b_strc_floats_content}% \endgroup \fi} -\def\dodofloatboxnextleftmarginbuilder#1#2% - {\ifparfloat +\def\strc_floats_build_box_next_left_margin_indeed#1#2% + {\ifconditional\c_strc_floats_par_float \hbox\bgroup - \tempfloatheight\ht\b_strc_floats_content - \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\tempfloatheight{#2}}% + \d_strc_float_temp_height\ht\b_strc_floats_content + \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}% \box\b_strc_floats_content \egroup \else \begingroup - \tempfloatheight\ht\b_strc_floats_content - \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\tempfloatheight{#2}}}% + \d_strc_float_temp_height\ht\b_strc_floats_content + \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}}% \strc_floats_align_content{\box\b_strc_floats_content}% \endgroup \fi} -\def\dofloatboxnextrightmarginbuilder{\dodofloatboxnextrightmarginbuilder\rightmargindistance} -\def\dofloatboxnextleftmarginbuilder {\dodofloatboxnextleftmarginbuilder \leftmargindistance } +\def\strc_floats_build_box_next_right_margin + {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance} + +\def\strc_floats_build_box_next_left_margin + {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance } -\def\dofloatboxnextoutermarginbuilder +\def\strc_floats_build_box_next_outer_margin {\doifrightpagefloatelse - {\dodofloatboxnextrightmarginbuilder\rightmargindistance} - {\dodofloatboxnextleftmarginbuilder \rightmargindistance}} + {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance} + {\strc_floats_build_box_next_left_margin_indeed \rightmargindistance}} -\def\dofloatboxnextinnermarginbuilder +\def\strc_floats_build_box_next_inner_margin {\doifrightpagefloatelse - {\dodofloatboxnextleftmarginbuilder \leftmargindistance} - {\dodofloatboxnextrightmarginbuilder\leftmargindistance}} - -\def\dofloatboxnextbuilder % beware, we first check on left/rightmargin because there can be left/right also - {\let\next\dofloatboxnextleftbuilder - \normalexpanded{\noexpand\processallactionsinset[\floatcaptionparameter\c!location]} - [ \v!outermargin=>\let\next\dofloatboxnextoutermarginbuilder, - \v!innermargin=>\let\next\dofloatboxnextinnermarginbuilder, - \v!leftmargin=>\let\next\dofloatboxnextleftmarginbuilder, - \v!rightmargin=>\let\next\dofloatboxnextrightmarginbuilder, - \v!lefthanging=>\let\next\dofloatboxnextlefthangbuilder, - \v!righthanging=>\let\next\dofloatboxnextrighthangbuilder, - \v!outer=>\let\next\dofloatboxnextouterbuilder, - \v!inner=>\let\next\dofloatboxnextinnerbuilder, - \v!left=>\let\next\dofloatboxnextleftbuilder, - \v!right=>\let\next\dofloatboxnextrightbuilder]% + {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance} + {\strc_floats_build_box_next_right_margin_indeed\leftmargindistance}} + +\def\strc_floats_build_box_next % beware, we first check on left/rightmargin because there can be left/right also + {\let\next\strc_floats_build_box_next_left + \processallactionsinset[\floatcaptionparameter\c!location] + [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin, + \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin, + \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin, + \v!rightmargin=>\let\next\strc_floats_build_box_next_right_margin, + \v!lefthanging=>\let\next\strc_floats_build_box_next_left_hang, + \v!righthanging=>\let\next\strc_floats_build_box_next_right_hang, + \v!outer=>\let\next\strc_floats_build_box_next_outer, + \v!inner=>\let\next\strc_floats_build_box_next_inner, + \v!left=>\let\next\strc_floats_build_box_next_left, + \v!right=>\let\next\strc_floats_build_box_next_right]% \next} -\def\dofloatboxsidebuilder - {\ifparfloat - \let\next\dofloatboxhighbuilder +\def\strc_floats_build_box_side + {\ifconditional\c_strc_floats_par_float + \let\next\strc_floats_build_box_high \else - \let\next\dofloatboxmiddlebuilder - \expanded{\processallactionsinset[\floatcaptionparameter\c!location]} - [ \v!low=>\let\next\dofloatboxlowbuilder, - \v!middle=>\let\next\dofloatboxmiddlebuilder, - \v!high=>\let\next\dofloatboxhighbuilder]% + \let\next\strc_floats_build_box_middle + \processallactionsinset[\floatcaptionparameter\c!location] + [ \v!low=>\let\next\strc_floats_build_box_low, + \v!middle=>\let\next\strc_floats_build_box_middle, + \v!high=>\let\next\strc_floats_build_box_high]% \fi \next} -\def\doflushfloatleftcaptionhang - {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}} - -\def\doflushfloatrightcaptionhang +\def\strc_floats_flush_right_caption_hang {\hsmash{\rlap{\dotfskip{\floatcaptionparameter\c!distance}\box\b_strc_floats_caption}}} -\def\doflushfloatcaptionhang % expanded can go - {\expanded{\doifinsetelse{\v!righthanging}{\floatcaptionparameter\c!location}} - {\doflushfloatrightcaptionhang} - {\expanded{\doifinsetelse{\v!lefthanging}{\floatcaptionparameter\c!location}} - {\doflushfloatleftcaptionhang} - {\expanded{\doifinsetelse{\v!hang}{\floatcaptionparameter\c!location}} - {\expanded{\doifinsetelse{\v!outer}{\floatcaptionparameter\c!location}} - {\doifrightpagefloatelse{\doflushfloatrightcaptionhang}{\doflushfloatleftcaptionhang}} - {\expanded{\doifinsetelse{\v!right}{\floatcaptiondirectives}} - {\doflushfloatrightcaptionhang} - {\doflushfloatleftcaptionhang}}} +\def\strc_floats_flush_left_caption_hang + {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}} + +% \def\strc_floats_flush_caption_hang % expanded can go +% {\expanded{\doifinsetelse{\v!righthanging}{\floatcaptionparameter\c!location}} +% {\strc_floats_flush_right_caption_hang} +% {\expanded{\doifinsetelse{\v!lefthanging}{\floatcaptionparameter\c!location}} +% {\strc_floats_flush_left_caption_hang} +% {\expanded{\doifinsetelse{\v!hang}{\floatcaptionparameter\c!location}} +% {\expanded{\doifinsetelse{\v!outer}{\floatcaptionparameter\c!location}} +% {\doifrightpagefloatelse{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}} +% {\expanded{\doifinsetelse{\v!right}{\floatcaptiondirectives}} +% {\strc_floats_flush_right_caption_hang} +% {\strc_floats_flush_left_caption_hang}}} +% {\box\b_strc_floats_caption}}}} + +\def\strc_floats_flush_caption_hang % expanded can go + {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}% + \doifinsetelse\v!righthanging\p_strc_floats_caption_location + {\strc_floats_flush_right_caption_hang} + {\doifinsetelse\v!lefthanging\p_strc_floats_caption_location + {\strc_floats_flush_left_caption_hang} + {\doifinsetelse\v!hang\p_strc_floats_caption_location + {\doifinsetelse\v!outer\p_strc_floats_caption_location + {\doifrightpagefloatelse{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}} + {\doifinsetelse\v!right\floatcaptiondirectives + {\strc_floats_flush_right_caption_hang} + {\strc_floats_flush_left_caption_hang}}} {\box\b_strc_floats_caption}}}} -\def\dofloatboxhighbuilder - {\dofloatboxnextbuilder{\dofloatboxbetweenstack\doflushfloatcaptionhang\vfill}} +\def\strc_floats_build_box_high + {\strc_floats_build_box_next{\strc_floats_between_stack\strc_floats_flush_caption_hang\vfill}} -\def\dofloatboxlowbuilder - {\dofloatboxnextbuilder{\vfill\doflushfloatcaptionhang\dofloatboxbetweenstack}} +\def\strc_floats_build_box_low + {\strc_floats_build_box_next{\vfill\strc_floats_flush_caption_hang\strc_floats_between_stack}} -\def\dofloatboxmiddlebuilder - {\dofloatboxnextbuilder{\vfill\box\b_strc_floats_caption\vfill}} +\def\strc_floats_build_box_middle + {\strc_floats_build_box_next{\vfill\box\b_strc_floats_caption\vfill}} % \definefloat % [lefty][lefties][figure] @@ -1594,125 +1561,136 @@ % \placelefty{}{} \input tufte \input tufte % \stoptext -\def\bothangfloat#1{\ruledvbox to \ht\b_strc_floats_content{#1\vss}} -\def\tophangfloat#1{\ruledvbox to \ht\b_strc_floats_content{\vss#1}} +\def\strc_floats_build_box_top_stack_normal_overlay + {\vbox to \ht\b_strc_floats_content{\vss\strc_floats_build_box_top_stack_normal_content}} -\def\dofloatboxnormaltopstackbuilder - {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\tophangfloat - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat - \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}% - \dofloatboxbetweenstack - \hbox{\hbox{\box\b_strc_floats_content}}% - \else - \page_otr_command_set_float_hsize - \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}} - \dofloatboxbetweenstack - \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}% - \fi}} +\def\strc_floats_build_box_top_stack_normal_content + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float + \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}% + \strc_floats_between_stack + \hbox{\hbox{\box\b_strc_floats_content}}% + \else + \page_otr_command_set_float_hsize + \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}} + \strc_floats_between_stack + \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}% + \fi} -\def\dofloatboxnormalbotstackbuilder - {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\bothangfloat - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat - \hbox{\hbox{\box\b_strc_floats_content}}% - \dofloatboxbetweenstack - \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}% - \else - \page_otr_command_set_float_hsize - \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}% - \dofloatboxbetweenstack - \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}% - \fi}} +\def\strc_floats_build_box_bottom_stack_normal_overlay + {\vbox to \ht\b_strc_floats_content{\strc_floats_build_box_bottom_stack_normal_content\vss}} + +\def\strc_floats_build_box_bottom_stack_normal_content + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float + \hbox{\hbox{\box\b_strc_floats_content}}% + \strc_floats_between_stack + \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}% + \else + \page_otr_command_set_float_hsize + \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}% + \strc_floats_between_stack + \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}% + \fi} + +\def\strc_floats_build_box_top_stack_normal + {\doifinsetelse\v!overlay{\floatcaptionparameter\c!location} + \strc_floats_build_box_top_stack_normal_overlay + \strc_floats_build_box_top_stack_normal_content} + +\def\strc_floats_build_box_bottom_stack_normal + {\doifinset\v!overlay{\floatcaptionparameter\c!location} + \strc_floats_build_box_bottom_stack_normal_overlay + \strc_floats_build_box_bottom_stack_normal_content} -\def\dofloatboxgridtopstackbuilder +\def\strc_floats_build_box_top_stack_grid {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float \strc_floats_locate_side_float{\box\b_strc_floats_caption}% - \vss\dofloatboxbetweenstack + \vss\strc_floats_between_stack \hbox{\box\b_strc_floats_content}% \else \page_otr_command_set_float_hsize \strc_floats_locate_text_float{\box\b_strc_floats_caption}% - \vss\dofloatboxbetweenstack + \vss\strc_floats_between_stack \strc_floats_align_content{\box\b_strc_floats_content}% \fi}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight{\unvbox\scratchbox}} -\def\dofloatboxgridbotstackbuilder +\def\strc_floats_build_box_bottom_stack_grid {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float \hbox{\box\b_strc_floats_content}% - \vss\dofloatboxbetweenstack + \vss\strc_floats_between_stack \strc_floats_locate_side_float{\box\b_strc_floats_caption}% \else \page_otr_command_set_float_hsize \strc_floats_align_content{\box\b_strc_floats_content}% - \vss\dofloatboxbetweenstack + \vss\strc_floats_between_stack \strc_floats_locate_text_float{\box\b_strc_floats_caption}% \fi}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight{\unvbox\scratchbox}} -\def\dofloatboxstretchtopstackbuilder +\def\strc_floats_build_box_top_stack_stretch {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox {\strc_floats_align_caption{\copy\b_strc_floats_caption}% \strc_floats_align_content {\copy\b_strc_floats_content }}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float \strc_floats_locate_side_float{\box\b_strc_floats_caption}% - \vss\dofloatboxbetweenstack\vss + \vss\strc_floats_between_stack\vss \hbox{\box\b_strc_floats_content}% \else \page_otr_command_set_float_hsize \strc_floats_locate_text_float{\box\b_strc_floats_caption}% - \vss\dofloatboxbetweenstack\vss + \vss\strc_floats_between_stack\vss \strc_floats_align_content{\box\b_strc_floats_content}% \fi}} -\def\dofloatboxstretchbotstackbuilder +\def\strc_floats_build_box_bottom_stack_stretch {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox {\strc_floats_align_content{\copy\b_strc_floats_content }% \strc_floats_align_caption{\copy\b_strc_floats_caption}}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight - {\tempfloatwidth\wd\b_strc_floats_content - \ifparfloat + {\d_strc_float_temp_width\wd\b_strc_floats_content + \ifconditional\c_strc_floats_par_float \hbox{\box\b_strc_floats_content}% - \vss\dofloatboxbetweenstack\vss + \vss\strc_floats_between_stack\vss \strc_floats_locate_side_float{\box\b_strc_floats_caption} \else \page_otr_command_set_float_hsize \strc_floats_align_content{\box\b_strc_floats_content}% - \vss\dofloatboxbetweenstack\vss + \vss\strc_floats_between_stack\vss \strc_floats_locate_text_float{\box\b_strc_floats_caption}% \fi}} -\def\dofloatboxtopbuilder - {\let\next\dofloatboxnormaltopstackbuilder - \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]} - [ \v!grid=>\let\next\dofloatboxgridstackbuilder, - \v!stretch=>\let\next\dofloatboxstretchstackbuilder]% +\def\strc_floats_build_box_top + {\let\next\strc_floats_build_box_top_stack_normal + \processfirstactioninset[\floatcaptionparameter\c!location] + [ \v!grid=>\let\next\strc_floats_build_box_top_stack_grid, + \v!stretch=>\let\next\strc_floats_build_box_top_stack_stretch]% \next} -\def\dofloatboxbottombuilder - {\let\next\dofloatboxnormalbotstackbuilder - \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]} - [ \v!grid=>\let\next\dofloatboxgridstackbuilder, - \v!stretch=>\let\next\dofloatboxstretchstackbuilder]% +\def\strc_floats_build_box_bottom + {\let\next\strc_floats_build_box_bottom_stack_normal + \processfirstactioninset[\floatcaptionparameter\c!location] + [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid, + \v!stretch=>\let\next\strc_floats_build_box_bottom_stack_stretch]% \next} -\def\relocatecaptionright#1{\strc_floats_align_caption{\hbox to \tempfloatwidth{\hss#1}}} -\def\relocatecaptionleft #1{\strc_floats_align_caption{\hbox to \tempfloatwidth{#1\hss}}} +\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}} +\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}} \unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}} @@ -1721,31 +1699,32 @@ {\strc_floats_set_local_hsize \forgetall \let\floatcaptionarrangement\s!default - \def\docommand##1% - {\doifdefined{\??floatbuilder##1}{\def\floatcaptionarrangement{##1}\quitcommalist}}% - \processcommacommand[\floatcaptionparameter\c!location]\docommand + \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step \executeifdefined{\??floatbuilder\floatcaptionarrangement}{\getvalue{\??floatbuilder\s!default}}}} +\def\strc_floats_build_box_step#1% + {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}} + \def\strc_floats_locate_text_float {\let\next\strc_floats_align_caption - \expanded{\processallactionsinset[\floatcaptionparameter\c!location]} - [ \v!left=>\let\next\relocatecaptionleft, - \v!right=>\let\next\relocatecaptionright, - \v!inner=>\doifrightpagefloatelse{\let\next\relocatecaptionleft }{\let\next\relocatecaptionright}, - \v!outer=>\doifrightpagefloatelse{\let\next\relocatecaptionright}{\let\next\relocatecaptionleft }]% + \processallactionsinset[\floatcaptionparameter\c!location] + [ \v!left=>\let\next\strc_floats_relocate_caption_left, + \v!right=>\let\next\strc_floats_relocate_caption_right, + \v!inner=>\doifrightpagefloatelse{\let\next\strc_floats_relocate_caption_left }{\let\next\strc_floats_relocate_caption_right}, + \v!outer=>\doifrightpagefloatelse{\let\next\strc_floats_relocate_caption_right}{\let\next\strc_floats_relocate_caption_left }]% \next} -\installfloatboxbuilder \v!none \dofloatboxdefaultbuilder -\installfloatboxbuilder \s!default \dofloatboxdefaultbuilder -\installfloatboxbuilder \v!high \dofloatboxhighbuilder -\installfloatboxbuilder \v!low \dofloatboxlowbuilder -\installfloatboxbuilder \v!middle \dofloatboxmiddlebuilder +\installfloatboxbuilder \v!none \strc_floats_build_box_default +\installfloatboxbuilder \s!default \strc_floats_build_box_default +\installfloatboxbuilder \v!high \strc_floats_build_box_high +\installfloatboxbuilder \v!low \strc_floats_build_box_low +\installfloatboxbuilder \v!middle \strc_floats_build_box_middle -\installfloatboxbuilder \v!left \dofloatboxsidebuilder -\installfloatboxbuilder \v!right \dofloatboxsidebuilder +\installfloatboxbuilder \v!left \strc_floats_build_box_side +\installfloatboxbuilder \v!right \strc_floats_build_box_side -\installfloatboxbuilder \v!top \dofloatboxtopbuilder -\installfloatboxbuilder \v!bottom \dofloatboxbottombuilder +\installfloatboxbuilder \v!top \strc_floats_build_box_top +\installfloatboxbuilder \v!bottom \strc_floats_build_box_bottom % \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=] % @@ -1756,6 +1735,8 @@ % test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page % \stoptext +% This might move to page-flt: + \newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change \setnewconstant\postcenterfloatmethod\plusone @@ -1774,9 +1755,9 @@ \global\setbox\floatbox\hbox to \scratchdimen % {\hfill\box\floatbox\hfill}} % geen \hss, gaat mis in kolommen ! % {\hss \box\floatbox\hss }} % wel \hss, anders mis in colset - {\ifglobalcenterfloatbox + {\ifconditional\c_page_floats_center_box_global \donetrue - \else\iflocalcenterfloatbox + \else\ifconditional\c_page_floats_center_box_local \donetrue \else \donefalse @@ -1793,7 +1774,6 @@ \forgetall \postponenotes \dontcomplain - %\showcomposition \setbox\b_strc_floats_content\vbox{\borderedfloatbox}% %\page_backgrounds_add_local_to_box\b_strc_floats_content \ifnofloatcaption @@ -1808,33 +1788,106 @@ \fi \egroup} +% \def\strc_floats_prepare_side_caption +% {\dostarttagged\t!floatcaption\empty +% \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}% +% \doifelse{\floatcaptionparameter\c!width}\v!max +% {\setbox\b_strc_floats_caption\vbox +% {\strc_floats_caption_set_align +% \hsize\wd\b_strc_floats_content +% \strc_floats_make_complete_caption}}% +% {\doifelse{\floatcaptionparameter\c!width}\v!fit +% {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax +% \setbox\b_strc_floats_caption\vbox +% {\forgetall % needed? +% \hsize\wd\b_strc_floats_content +% \strc_floats_make_complete_caption}% +% \else +% \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content +% {\hss\hbox{\strc_floats_make_complete_caption}\hss}% +% \fi} +% {\setbox\b_strc_floats_caption\vbox +% {\strc_floats_caption_set_align +% \hsize\floatcaptionparameter\c!width % \wd\b_strc_floats_content +% \strc_floats_make_complete_caption}}}% +% \dostoptagged} + \def\strc_floats_prepare_side_caption {\dostarttagged\t!floatcaption\empty - \doifelse{\floatcaptionparameter\c!width}\v!max - {\setbox\b_strc_floats_caption\vbox - {\strc_floats_caption_set_align - \hsize\wd\b_strc_floats_content - \strc_floats_make_complete_caption}}% - {\doifelse{\floatcaptionparameter\c!width}\v!fit - {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax - \setbox\b_strc_floats_caption\vbox - {\forgetall % needed? - \hsize\wd\b_strc_floats_content - \strc_floats_make_complete_caption}% - \else - \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content - {\hss\hbox{\strc_floats_make_complete_caption}\hss}% - \fi} - {\setbox\b_strc_floats_caption\vbox - {\strc_floats_caption_set_align - \hsize\floatcaptionparameter\c!width % \wd\b_strc_floats_content - \strc_floats_make_complete_caption}}}% + \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}% + \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}% + \ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_side_caption_max + \else\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_side_caption_fit + \else + \strc_floats_prepare_side_caption_width + \fi\fi \dostoptagged} +% these could be \??floatpreparesidecaption + +\def\strc_floats_prepare_side_caption_max + {\setbox\b_strc_floats_caption\vbox + {\strc_floats_caption_set_align + \hsize\wd\b_strc_floats_content + \strc_floats_make_complete_caption}} + +\def\strc_floats_prepare_side_caption_fit + {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax + \setbox\b_strc_floats_caption\vbox + {\forgetall % needed? + \hsize\wd\b_strc_floats_content + \strc_floats_make_complete_caption}% + \else + \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content + {\hss\hbox{\strc_floats_make_complete_caption}\hss}% + \fi} + +\def\strc_floats_prepare_side_caption_width + {\setbox\b_strc_floats_caption\vbox + {\strc_floats_caption_set_align + \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content + \strc_floats_make_complete_caption}} + +% % maybe (but then also prepare_page that way): +% +% \installcorenamespace{floatpreparesidecaption} +% +% \def\strc_floats_prepare_side_caption +% {\dostarttagged\t!floatcaption\empty +% \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}% +% \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}% +% \expandcheckedcsname\??floatpreparesidecaption\p_strc_floats_caption_width\s!unknown +% \dostoptagged} +% +% \setvalue{\??floatpreparesidecaption\v!max}% +% {\setbox\b_strc_floats_caption\vbox +% {\strc_floats_caption_set_align +% \hsize\wd\b_strc_floats_content +% \strc_floats_make_complete_caption}} +% +% \setvalue{\??floatpreparesidecaption\v!fit}% +% {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax +% \setbox\b_strc_floats_caption\vbox +% {\forgetall % needed? +% \hsize\wd\b_strc_floats_content +% \strc_floats_make_complete_caption}% +% \else +% \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content +% {\hss\hbox{\strc_floats_make_complete_caption}\hss}% +% \fi} +% +% \setvalue{\??floatpreparesidecaption\s!unknown}% +% {\setbox\b_strc_floats_caption\vbox +% {\strc_floats_caption_set_align +% \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content +% \strc_floats_make_complete_caption}} + \def\strc_floats_locate_side_float#1% {\begingroup \alignstrutmode\zerocount - \hsize\tempfloatwidth \forgetall + \hsize\d_strc_float_temp_width \forgetall \alignedline{\floatparameter\c!location}\v!middle{#1}% \endgroup} @@ -1843,13 +1896,11 @@ \let\strc_floats_align_caption\relax \strc_floats_build_box} -\newif\ifparfloat - \def\strc_floats_set_box % todo : \global\setbox, currently messy {\ifvisible \par \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}% - \ifparfloat + \ifconditional\c_strc_floats_par_float \strc_floats_set_paragraph_variant \else \strc_floats_set_page_variant @@ -1872,9 +1923,7 @@ \fi \fi} -\newcounter\noxfloatlocations - -% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput +% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput \definefloat [\v!figure] @@ -1900,17 +1949,17 @@ \installcorenamespace{floatmethods} -\let\floatmethod \empty -\let\floatlabel \empty -\let\floatcolumn \empty -\let\floatrow \empty -\let\forcedfloatmethod\empty +\let\floatmethod \empty % set by lua +\let\floatlabel \empty % set by lua +\let\floatcolumn \empty % set by lua +\let\floatrow \empty % set by lua +\let\forcedfloatmethod\empty % set by lua \def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn {\ctxcommand{analysefloatmethod("#1")}} \def\somesomewherefloat[#1]% - {\dofloatssavesomewherefloat\s!somewhere{#1}} + {\page_floats_save_somewhere_float\s!somewhere{#1}} \def\strc_floats_get_box {\ifvisible @@ -2073,45 +2122,49 @@ %D Local floats: -\def\setuplocalfloats - {\getparameters[\??lf]} +\installcorenamespace{localfloats} +\installcorenamespace{localfloatstack} + +\installsetuponlycommandhandler \??localfloats {localfloats} \setuplocalfloats [%\c!before=\blank, %\c!after=\blank, \c!inbetween=\blank] -\initializeboxstack{localfloats} +\initializeboxstack\??localfloatstack -\newcounter\noflocalfloats +\newcount\c_strc_localfloats_n \let\noflocalfloats\c_strc_localfloats_n -\def\resetlocalfloats - {\doglobal\newcounter\noflocalfloats - \initializeboxstack{localfloats}} +\unexpanded\def\resetlocalfloats + {\global\c_strc_localfloats_n\zerocount + \initializeboxstack\??localfloatstack} -\def\somelocalfloat - {\doglobal\increment\noflocalfloats - \savebox{localfloats}{\noflocalfloats}{\box\floatbox}} +\unexpanded\def\somelocalfloat + {\global\advance\c_strc_localfloats_n\plusone + \savebox\??localfloatstack{\number\c_strc_localfloats_n}{\box\floatbox}} -\def\getlocalfloats - {\dorecurse\noflocalfloats +\unexpanded\def\getlocalfloats + {\dorecurse\c_strc_localfloats_n {\ifnum\recurselevel=\plusone % 1\relax - \getvalue{\??lf\c!before}% + \directlocalfloatsparameter\c!before \else - \getvalue{\??lf\c!inbetween}% + \directlocalfloatsparameter\c!inbetween \fi - \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}% - \ifnum\recurselevel=\noflocalfloats\relax - \getvalue{\??lf\c!after}% + \dontleavehmode\hbox{\foundbox\??localfloatstack\recurselevel}% + \ifnum\recurselevel=\c_strc_localfloats_n\relax + \directlocalfloatsparameter\c!after \fi}} -\def\flushlocalfloats +\unexpanded\def\flushlocalfloats {\getlocalfloats \resetlocalfloats} -\unexpanded\def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}} +\unexpanded\def\getlocalfloat#1% + {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}} -\def\forcelocalfloats{\let\forcedfloatmethod\v!local} +\unexpanded\def\forcelocalfloats + {\let\forcedfloatmethod\v!local} \installfloatmethod \s!singlecolumn \v!local \somelocalfloat \installfloatmethod \s!multicolumn \v!local \somelocalfloat diff --git a/tex/context/base/strc-ind.mkiv b/tex/context/base/strc-ind.mkiv index 4b65c7407..0098bff7d 100644 --- a/tex/context/base/strc-ind.mkiv +++ b/tex/context/base/strc-ind.mkiv @@ -57,6 +57,7 @@ \newcount\c_strc_indentedtexts_nesting \newdimen\d_strc_indentedtexts_width +\newdimen\d_strc_indentedtexts_distance \appendtoks \setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}% @@ -67,12 +68,13 @@ \setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}% \to \everydefineindentedtext -\unexpanded\def\strc_indentedtexts_start#1#2% +\unexpanded\def\strc_indentedtexts_start#1#2% we need to get rid of \spr {\par \begingroup - \c_strc_indentedtexts_nesting#2\relax \edef\currentindentedtext{#1}% + \c_strc_indentedtexts_nesting#2\relax \indentedtextparameter\c!before + \d_strc_indentedtexts_distance\indentedtextparameter\c!distance\relax \doifnothing{\indentedtextparameter\c!sample} {\setindentedtextparameter\c!sample{\indentedtextparameter\c!text}}% \assignwidth @@ -81,15 +83,15 @@ {\useindentedtextstyleandcolor\c!headstyle\c!headcolor \indentedtextparameter\c!sample \spr{\indentedtextparameter\c!separator}} - {\indentedtextparameter\c!distance}% - \advance\d_strc_indentedtexts_width \indentedtextparameter\c!distance + {\d_strc_indentedtexts_distance}% + \advance\d_strc_indentedtexts_width \d_strc_indentedtexts_distance \setbox\scratchbox\hbox to \d_strc_indentedtexts_width {\useindentedtextstyleandcolor\c!headstyle\c!headcolor \strut \indentedtextparameter\c!text \hss \spr{\indentedtextparameter\c!separator}% - \hskip\indentedtextparameter\c!distance}% + \hskip\d_strc_indentedtexts_distance}% \parindent\zeropoint \hskip\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width \advance\c_strc_indentedtexts_nesting\plusone diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua index 78efcad81..3f0a8768f 100644 --- a/tex/context/base/strc-ini.lua +++ b/tex/context/base/strc-ini.lua @@ -27,10 +27,17 @@ local type, next, tonumber = type, next, tonumber local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash local allocate = utilities.storage.allocate -local ctxcatcodes = tex.ctxcatcodes -local xmlcatcodes = tex.xmlcatcodes -local notcatcodes = tex.notcatcodes -local txtcatcodes = tex.txtcatcodes +local catcodenumbers = catcodes.numbers -- better use the context(...) way to switch + +local ctxcatcodes = catcodenumbers.ctxcatcodes +local xmlcatcodes = catcodenumbers.xmlcatcodes +local notcatcodes = catcodenumbers.notcatcodes +local txtcatcodes = catcodenumbers.txtcatcodes + +local context, commands = context, commands + +local pushcatcodes = context.pushcatcodes +local popcatcodes = context.popcatcodes local trace_processors = false local report_processors = logs.reporter("processors","structure") @@ -226,7 +233,15 @@ end if trace_processors then report_processors("cct: %s, txt: %s",catcodes,title) end - context.sprint(catcodes,title) -- was: texsprint(catcodes,title) + -- + -- context.sprint(catcodes,title) + -- + -- doesn't work when a newline is in there \section{Test\ A} so we do + -- it this way: + -- + pushcatcodes(catcodes) + context(title) + popcatcodes() end end else diff --git a/tex/context/base/strc-itm.mkvi b/tex/context/base/strc-itm.mkvi index 86acba33c..da81f37d5 100644 --- a/tex/context/base/strc-itm.mkvi +++ b/tex/context/base/strc-itm.mkvi @@ -182,6 +182,7 @@ \newconditional\c_strc_itemgroups_columns \newconditional\c_strc_itemgroups_concat \newconditional\c_strc_itemgroups_txt +\newconditional\c_strc_itemgroups_extra \newconditional\c_strc_itemgroups_repeat % 0 = before/after @@ -242,11 +243,17 @@ \strc_itemgroups_insert_reference_indeed \fi \fi} +\def\strc_itemgroups_insert_extra_reference + {\iftrialtypesetting \else \ifx\currentitemreference \empty \else + \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}% + \fi \fi} + \def\strc_itemgroups_insert_reference_indeed % maybe we need a 'frozen counter' numberdata blob / quick hack .. .mive this to strc-ref {%\setnextinternalreference % no need to collect nodes in \b_strc_destination_nodes here ... maybe at some point \strc_references_start_destination_nodes - \ctxlua {structures.references.setandgetattribute("\s!full", "\referenceprefix","\currentitemreference", + % this is somewhat over the top ... we should use the counter's reference + \ctxcommand{setreferenceattribute("\s!full", "\referenceprefix","\currentitemreference", { metadata = { kind = "item",% ? @@ -360,7 +367,7 @@ \def\strc_itemgroups_insert_break_indeed {\flushnotes \vspacing[\v!item @-5]} \def\strc_itemgroups_insert_nobreak_indeed {\flushnotes - \ifinsidecolumns + \ifinsidecolumns % todo \vspacing[\v!item @5]% \else \vspacing[\v!item @500]% @@ -452,6 +459,7 @@ % this will be a constant \setfalse\c_strc_itemgroups_head \setfalse\c_strc_itemgroups_sub + \setfalse\c_strc_itemgroups_symbol \setfalse\c_strc_itemgroups_columns % to be checked \let\m_strc_itemgroups_destination\empty @@ -584,9 +592,11 @@ {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}}} \def\strc_itemgroups_increment_item_counter - {\ifconditional\c_strc_itemgroups_sub \else \ifx\strc_itemgroups_extra_symbol\empty - \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel - \fi\fi} + {\ifconditional\c_strc_itemgroups_sub \else + \ifconditional\c_strc_itemgroups_symbol \else % \ifx\strc_itemgroups_extra_symbol\empty + \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel + \fi + \fi} \unexpanded\def\strc_itemgroups_insert_item_counter {\ifconditional\c_strc_itemgroups_repeat @@ -832,9 +842,6 @@ \let\startcollectitems\relax \let\stopcollectitems \relax -\ifdefined\startcolumns \else \unexpanded\def\startcolumns[#settings]{} \fi -\ifdefined\stopcolumns \else \unexpanded\def\stopcolumns {} \fi - \letvalue{\??itemgroupalign\v!flushleft }\relax \letvalue{\??itemgroupalign\v!right }\relax \letvalue{\??itemgroupalign\v!flushright}\hfill @@ -873,16 +880,31 @@ \def\strc_itemgroups_setup_symbol_asked {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}} -\def\strc_itemgroups_start_columns - {\startcolumns - [\c!n=\itemgroupparameter\c!n, - \c!height=, - \c!rule=\v!off, - \c!balance=\v!yes, - \c!align=\v!no]} +\ifdefined\strc_itemgroups_start_columns -\def\strc_itemgroups_stop_columns - {\stopcolumns} + % already defined in page-mix + +\else + + % will be redefined in page-mix + + \ifdefined\startcolumns \else + \unexpanded\def\startcolumns[#settings]{} + \unexpanded\def\stopcolumns {} + \fi + + \def\strc_itemgroups_start_columns + {\startcolumns + [\c!n=\itemgroupparameter\c!n, + \c!height=, + \c!rule=\v!off, + \c!balance=\v!yes, + \c!align=\v!no]} + + \def\strc_itemgroups_stop_columns + {\stopcolumns} + +\fi \unexpanded\def\stopitemgroup {\stopcollectitems @@ -1090,6 +1112,7 @@ \unexpanded\def\strc_itemgroups_start_symbol#text% {\def\strc_itemgroups_extra_symbol{#text}% + \settrue\c_strc_itemgroups_symbol \startitemgroupitem} \unexpanded\def\strc_itemgroups_start_dummy @@ -1117,6 +1140,7 @@ \unexpanded\def\strc_itemgroups_start_text#text% {\def\strc_itemgroups_extra_symbol{#text}% + \settrue\c_strc_itemgroups_symbol \settrue\c_strc_itemgroups_txt \startitemgroupitem} @@ -1219,29 +1243,33 @@ \unexpanded\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} \def\strc_itemgroups_make_symbol_box {\setbox\b_strc_itemgroups\hbox {\ifconditional\c_strc_itemgroups_head - \ifx\strc_itemgroups_extra_symbol\empty - \useitemgroupstyleandcolor\c!headstyle\c!headcolor - \strc_itemgroups_used_symbol - \else + \ifconditional\c_strc_itemgroups_symbol + \strc_itemgroups_insert_extra_reference \useitemgroupstyleandcolor\c!symstyle\c!symcolor \strc_itemgroups_extra_symbol + \else + \useitemgroupstyleandcolor\c!headstyle\c!headcolor + \strc_itemgroups_used_symbol \fi \else - \ifx\strc_itemgroups_extra_symbol\empty - \useitemgroupstyleandcolor\c!style\c!color - \strc_itemgroups_used_symbol - \else + \ifconditional\c_strc_itemgroups_symbol + \strc_itemgroups_insert_extra_reference \useitemgroupstyleandcolor\c!symstyle\c!symcolor \strc_itemgroups_extra_symbol + \else + \useitemgroupstyleandcolor\c!style\c!color + \strc_itemgroups_used_symbol \fi \fi}% - \let\strc_itemgroups_extra_symbol\empty} + \let\strc_itemgroups_extra_symbol\empty + \setfalse\c_strc_itemgroups_symbol} \def\strc_itemgroups_make_fitting_box {\ifdim\wd\b_strc_itemgroups>\itemgroupparameter\c!maxwidth\scaledpoint\relax % brr, sp @@ -1453,10 +1481,11 @@ \else \advance\c_strc_itemgroups_collected_current\plusone \fi - \doifdefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current} - {\getvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}% - \letbeundefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}% - \advance\c_strc_itemgroups_collected_done\plusone}% + \ifcsname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname + \getvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}% + \letbeundefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}% + \advance\c_strc_itemgroups_collected_done\plusone + \fi \ifnum\c_strc_itemgroups_collected_done<\c_strc_itemgroups_collected_stored \expandafter\strc_itemgroups_collected_flush \fi} diff --git a/tex/context/base/strc-lab.mkiv b/tex/context/base/strc-lab.mkiv index 483791462..0039a68fd 100644 --- a/tex/context/base/strc-lab.mkiv +++ b/tex/context/base/strc-lab.mkiv @@ -15,82 +15,175 @@ \unprotect -% labels, we could share with enumerations and forget about the text; anyhow, figure -% labels etc can use enumerations; we keep labels for compatibility reasons; we need -% the slightly different namespace; we can still define structure counters directly -% (multiple levels) and use an enumeration without following text - -% unfinished ... no longer okay - -\unexpanded\def\setuplabels - {\getparameters[\??db]} - -\unexpanded\def\definelabel - {\dotripleargumentwithset\dodefinelabel} - -\def\dodefinelabel[#1][#2][#3]% #2 or #3 assignment - {\doenumerationinit{#1}{1}\empty - \getparameters[\??dd#1][\c!command=,\c!state=\v!start,\c!location=,\c!text=#1]% - \ifsecondargument\doifassignmentelse{#2}\donetrue\donefalse\else\donetrue\fi - \ifdone - % an independent one - \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??db,#2]% - \dodefinelabelcommands{#1}{\??db}% - \dodefineenumerationcounter{#1}% +%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) + +\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] + +\unexpanded\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}}% + \setuevalue{\e!next #1}{\strc_labels_next }% + \setuevalue{\c!reset#1}{\strc_labels_reset }% + %setuevalue{\c!set #1}{\strc_labels_set }% + \setuevalue {#1}{\strc_labels_command{#1}}} + +\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 - \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??dd#2,#3]% - \dodefinelabelcommands{#1}{\??dd#2}% + % 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 + \doifcounterelse\p_counter\donothing{\strc_labels_define_counter\p_counter}% + \letlabelparameter\s!counter\p_counter + \strc_labels_setup_counter\currentlabel +\to \everydefinelabel + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\setvalue{\??constructioninitializer\v!label}% + {\let\currentlabel \currentconstruction + \let\constructionparameter \labelparameter + \let\detokenizedconstructionparameter\detokenizedlabelparameter + \let\letconstructionparameter \letlabelparameter + \let\useconstructionstyleandcolor \uselabelstyleandcolor + \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 + \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} -\def\dodefinelabelcommands#1#2% - {\setuevalue {#1}{\noexpand\dolabelnumbercommand {#1}}% - \setuevalue{\c!reset #1}{\noexpand\doresetlabelnumber {#1}}% - %\setuevalue{\c!set #1}{\noexpand\dosetlabelnumber {#1}}% [#2] or {#2} ? - \setuevalue{\e!next #1}{\noexpand\donextlabelnumber {#1}}% - \setuevalue{\e!increment#1}{\noexpand\doincrementlabelnumber{#1}}% - \setuevalue{\c!current #1}{\noexpand\docurrentlabelnumber {#1}}} - -% this is just for downward compatibility, we might drop it - -\setvalue{\??db:\c!location:\v!inmargin}{\inmargin} -\setvalue{\??db:\c!location:\v!inleft }{\inleft} -\setvalue{\??db:\c!location:\v!inright }{\inright} -\setvalue{\??db:\c!location:\v!margin }{\inmargin} - -\def\dolabelinit#1% - {\def\currentdescriptionmain{#1}% - \def\currentdescription {#1}% - \def\currentdescriptionlevel{1}} - -\def\docurrentlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodocurrentlabelnumber} -\def\donextlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodonextlabelnumber} -\def\dolabelnumbercommand #1{\dolabelinit{#1}\dosingleempty\dodolabelnumbercommand} - -\def\doresetlabelnumber #1{\dolabelinit{#1}\strc_counters_reset_sub \currentdescriptionnumber\currentdescriptionlevel} -\def\dosetlabelnumber #1#2{\dolabelinit{#1}\strc_counters_set_sub \currentdescriptionnumber\currentdescriptionlevel{#2}} -\def\doincrementlabelnumber #1{\dolabelinit{#1}\strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel} - -\def\dodocurrentlabelnumber[#1]% - {\dontleavehmode - \writestatus{!!!}{todo: reference of label}% - \dotextprefix{\descriptionparameter\c!text}% - \convertedsubcounter[\currentdescriptionnumber][\currentdescriptionlevel]} - -\def\dodonextlabelnumber[#1]% todo: ref - {\strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel - \dodocurrentlabelnumber[\currentdescriptionnumber]} - -\def\dodolabelnumbercommand[#1]% todo: ref - {\dontleavehmode - \descriptionparameter\c!before - \begingroup - \strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel - \usedescriptionstyleandcolor\c!headstyle\c!headcolor - \executeifdefined{\??db:\c!location:\descriptionparameter\c!location}{\descriptionparameter\c!command}{\dodocurrentlabelnumber[#1]}% - \endgroup - \descriptionparameter\c!after} - -\setuplabels - [\s!parent=\??dn] +\setvalue{\??constructionfinalizer\v!label}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Interfaces: + +\let\strc_labels_command\strc_descriptions_command +\let\strc_labels_next \strc_enumerations_next +\let\strc_labels_reset \strc_enumerations_reset +%let\strc_labels_set \strc_enumerations_set + +% similar to enumerations + +\newtoks\everysetuplabelcounter + +\let\v_strc_labels_counter_name\empty + +\def\strc_labels_setup_counter#1% + {\edef\v_strc_labels_counter_name{#1}% + \the\everysetuplabelcounter} + +\def\strc_labels_define_counter#1% + {\definecounter[#1]% + \strc_labels_setup_counter{#1}} + +\appendtoks + \strc_counter_setup_using_parameter\v_strc_labels_counter_name\labelparameter +\to \everysetuplabelcounter + +\appendtoks + \ifx\currentlabel\empty \else + \strc_labels_setup_counter\currentlabel + \fi +\to \everysetuplabel + +% no start stop here + +\expandafter\let\csname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname + +\unexpanded\setevalue{\??constructioncommandhandler\v!label}% + {\csname\??constructionstarthandler\v!construction\endcsname + \csname\??constructionstophandler \v!construction\endcsname + \endgroup} + +\unexpanded\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/strc-lnt.mkvi b/tex/context/base/strc-lnt.mkvi index f07ce7839..4160360d2 100644 --- a/tex/context/base/strc-lnt.mkvi +++ b/tex/context/base/strc-lnt.mkvi @@ -27,11 +27,20 @@ {\dotripleempty\strc_linenotes_define} \def\strc_linenotes_define[#1][#2][#3]% - {\definenote[#1][#2][#3]% - \expandafter\let\csname\??linenote#1\expandafter\endcsname\csname#1\endcsname % use copy command - \setuevalue {#1}{\strc_linenotes_direct{#1}}% - \setuevalue{\e!start#1}{\strc_linenotes_start {#1}}% - \setuevalue{\e!stop #1}{\strc_linenotes_stop }} + {\ifcsname\??linenote#1\endcsname + % there might be files that define the default 'linenote' + \ifthirdargument + \setupnote[#1][#3]% + \else\ifsecondargument + \setupnote[#1][#2]% + \fi\fi + \else + \definenote[#1][#2][#3]% + \expandafter\let\csname\??linenote#1\expandafter\endcsname\csname#1\endcsname % use copy command + \setuevalue {#1}{\strc_linenotes_direct{#1}}% + \setuevalue{\e!start#1}{\strc_linenotes_start {#1}}% + \setuevalue{\e!stop #1}{\strc_linenotes_stop }% + \fi} \unexpanded\def\strc_linenotes_direct#1#2% {\global\advance\c_strc_linenotes\plusone @@ -41,6 +50,7 @@ \unexpanded\def\strc_linenotes_start#1[#2]#3% {\global\advance\c_strc_linenotes\plusone + \keepunwantedspaces \strc_linenotes_indeed{#1}{#2}{#3}% \strc_linenotes_traced{#2}% \startline[#2]} @@ -48,19 +58,109 @@ \unexpanded\def\strc_linenotes_stop[#1]% {\stopline[#1]} -\unexpanded\def\strc_linenotes_indeed#1#2#3% will be redone +\let\m_page_lines_previous_to \relax +\let\m_page_lines_previous_from\relax + +\let\m_page_lines_current_to \relax +\let\m_page_lines_current_from \relax + +\newconditional\c_page_lines_current_to +\newconditional\c_page_lines_current_from + +\installcorenamespace{linenotespreviousfrom} +\installcorenamespace{linenotespreviousto} + +\letvalue\??linenotespreviousfrom\empty +\letvalue\??linenotespreviousto \empty + +\def\page_lines_in_from{\in[lr:b:\currentlinenotereference]} +\def\page_lines_in_to {\in[lr:e:\currentlinenotereference]} + +\unexpanded\def\strc_linenotes_range_normal#1% order + {\doifreferencefoundelse{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from + \ifconditional\c_page_lines_current_from + \xdef\m_page_lines_current_from{\currentreferencelinenumber}% + \doifreferencefoundelse{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to + \ifconditional\c_page_lines_current_to + \xdef\m_page_lines_current_to{\currentreferencelinenumber}% + \page_lines_in_from + \ifx\m_page_lines_current_from\m_page_lines_current_to \else + \endash + \page_lines_in_to + \fi + \else + \page_lines_in_from + \fi + \else + \page_lines_in_from + \fi} + +\unexpanded\def\strc_linenotes_range_sparse#1% order + {\doifreferencefoundelse{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from + \ifconditional\c_page_lines_current_from + \xdef\m_page_lines_current_from{\currentreferencelinenumber}% + \doifreferencefoundelse{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to + \ifconditional\c_page_lines_current_to + \xdef\m_page_lines_current_to{\currentreferencelinenumber}% + \ifx\m_page_lines_previous_from\m_page_lines_current_from + \ifx\m_page_lines_previous_to\m_page_lines_current_to + \notationparameter\c!compressseparator + \else + \page_lines_in_from + \fi + \else + \page_lines_in_from + \ifx\m_page_lines_current_from\m_page_lines_current_to + \else + \endash + \page_lines_in_to + \fi + \fi + \else + \page_lines_in_from + \fi + \else + \ifx\m_page_lines_previous_from\m_page_lines_current_from + \notationparameter\c!compressseparator + \else + \page_lines_in_from + \fi + \fi} + +\let\currentlinenotereference\empty + +\unexpanded\def\strc_linenotes_indeed#1#2#3% {\begingroup % we keep things local so we can use it as regular note too - \unexpanded\def\linenotelinenumber##1{\inlinerange[#2]}% ##1 == order -% \setupnotation[#1][\c!numbercommand=\linenotelinenumber]% todo: deep hook -% \setupnote[#1][\c!textcommand=\gobbleoneargument]% todo: deep hook \edef\currentnotation{#1}% + \edef\currentlinenotereference{#2}% + \xdef\m_page_lines_previous_from{\csname\??linenotespreviousfrom\ifcsname\??linenotespreviousfrom\currentnotation\endcsname\currentnotation\fi\endcsname}% + \xdef\m_page_lines_previous_to {\csname\??linenotespreviousto \ifcsname\??linenotespreviousto \currentnotation\endcsname\currentnotation\fi\endcsname}% + \doifelse{\notationparameter\c!compress}\v!yes + {\let\linenotelinenumber\strc_linenotes_range_sparse}% + {\let\linenotelinenumber\strc_linenotes_range_normal}% \let\currentnote\currentnotation \letnotationparameter\c!numbercommand\linenotelinenumber% todo: deep hook \letnoteparameter \c!textcommand \gobbleoneargument % todo: deep hook - \relax\getvalue{\??linenote#1}{#3}% + \getvalue{\??linenote\currentnotation}{#3}% + \expandafter\glet\csname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from + \expandafter\glet\csname\??linenotespreviousto \currentnotation\endcsname\m_page_lines_current_to \endgroup} +% where to hook this one in? resetcounter has no hook: + +\unexpanded\def\doresetlinenotecompression#1% \strc_linenotes_reset_previous + {\expandafter\glet\csname\??linenotespreviousfrom#1\endcsname\empty + \expandafter\glet\csname\??linenotespreviousto #1\endcsname\empty} + +\definesymbol + [\v!compressseparator] + [\space\hbox{\vl\thinspace\vl}] + +\setupnotations + [%c\compress=\v!no, + \c!compressseparator=\symbol\v!compressseparator] + \let\strc_linenotes_traced\gobbleoneargument \def\strc_linenotes_traced_indeed#1% @@ -79,9 +179,14 @@ \unexpanded\def\tracelinenotes {\let\strc_linenotes_traced\strc_linenotes_traced_indeed} +%D Use these when not properly nested: + +\let\fromlinenote\startlinenote +\let\tolinenote \stoplinenote + % We predefine one, namely \type {\linenote} cum suis. -% \definelinenote[\v!linenote] +\definelinenote[\v!linenote] % beware: line numbers are added later on so grouping setups is a bad idea % diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua index 48aab78db..424e9e05b 100644 --- a/tex/context/base/strc-lst.lua +++ b/tex/context/base/strc-lst.lua @@ -353,7 +353,6 @@ local function filtercollected(names, criterium, number, collected, forced, nest local cnumbers = sectionnumber.numbers local metadata = v.metadata if cnumbers then ---~ print(#cnumbers, depth, concat(cnumbers)) if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then local ok = true for d=1,depth do @@ -597,7 +596,7 @@ function lists.hasnumberdata(name,n) local data = lists.result[n] if data then local numberdata = data.numberdata - if numberdata then + if numberdata and not numberdata.hidenumber then -- th ehide number is true return true end end diff --git a/tex/context/base/strc-lst.mkvi b/tex/context/base/strc-lst.mkvi index 16544f866..965e53700 100644 --- a/tex/context/base/strc-lst.mkvi +++ b/tex/context/base/strc-lst.mkvi @@ -28,12 +28,6 @@ \unprotect -% To be added to mult-def.lua: - -\ifdefined\c!renderingsetup \else \def\c!renderingsetup{renderingsetup} \fi % maybe not interfaced -\ifdefined\c!filler \else \def\c!filler {filler} \fi -\ifdefined\v!interactive \else \def\v!interactive {interactive} \fi - %D Lists are mostly used for tables of contents but are in fact a rather generic %D feature of \CONTEXT. We seperate between storage and rendering and the current %D implementation is a reworked version of all that was added in steps. As lists @@ -247,7 +241,7 @@ \setupcurrentlist[#settings]% \the\everystructurelist % \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#tag}}% - \doplacestructurelist % maybe inline + \strc_lists_place_current % maybe inline {#list}% {\listparameter\c!criterium}% {\listparameter\c!number}% @@ -364,9 +358,15 @@ \ctxcommand{listuserdata("\currentlist",\currentlistindex,"#name")}% \dostoptagged} +\def\rawstructurelistuservariable#name% + {\ctxcommand{listuserdata("\currentlist",\currentlistindex,"#name")}} + \unexpanded\def\structurelistfirst {\structurelistuservariable\s!first } % s! \unexpanded\def\structurelistsecond{\structurelistuservariable\s!second} % s! +\unexpanded\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s! +\unexpanded\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s! + \unexpanded\def\doifstructurelisthaspageelse {\ctxcommand{doiflisthaspageelse("\currentlist",\currentlistindex)}} @@ -401,22 +401,22 @@ % TODO: pass extra tag name (contents, figures, bibliography ...) -\unexpanded\def\doplacestructurelist#list#criterium#number#extras#order% beware, not a user command +\unexpanded\def\strc_lists_place_current#list#criterium#number#extras#order% beware, not a user command {\dostarttagged\t!list\empty \ctxcommand{processlist{ names = "#list", criterium = "#criterium", - number = "\number#number", + number = "#number", extras = "#extras", order = "#order" }}% \dostoptagged} -\unexpanded\def\doanalyzestructurelist#list#criterium#number% +\unexpanded\def\strc_lists_analyze#list#criterium#number% {\ctxcommand{analyzelist{ names = "#list", criterium = "#criterium", - number = "\number#number" + number = "#number" }}} \def\firststructureelementinlist#list% @@ -1020,9 +1020,6 @@ % \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five} % \stoptext -% overrulen interactie kan sneller, bv door hulpconstanten -% te gebruiken en die te letten - \startsetups[\??listrenderings:d] \ifvmode \advance\leftskip\listparameter\c!margin @@ -1182,6 +1179,10 @@ \letvalue{\??listinteractions\v!all }\v!all \letvalue{\??listinteractions\v!yes }\v!all +\def\listboxproperties {\strc_lists_get_reference_attribute} +\def\listrenderingsetup {\the\t_lists_every_renderingtext} +\def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize} + \unexpanded\def\strc_lists_interaction_check {\iflocation \strc_lists_interaction_check_yes @@ -1288,7 +1289,7 @@ \let\listlength\!!zerocount \else \setupcurrentlist[#settings]% - \doanalyzestructurelist{#list}{\listparameter\c!criterium}{\listparameter\c!number}% + \strc_lists_analyze{#list}{\listparameter\c!criterium}{\listparameter\c!number}% \normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}% \fi \strc_lists_set_mode} diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua index 66ec04739..c7ef2d4e1 100644 --- a/tex/context/base/strc-mar.lua +++ b/tex/context/base/strc-mar.lua @@ -83,7 +83,7 @@ local function resolve(t,k) if trace_marks_set or trace_marks_get then report_marks("undefined: name=%s",k) end - local crap = { autodefined = true } + local crap = { autodefined = true } -- maybe set = 0 and reset = 0 t[k] = crap return crap else @@ -264,13 +264,16 @@ function marks.set(name,value) dn = data[name] end dn.set = topofstack + if not dn.reset then + dn.reset = 0 -- in case of selfdefined + end local top = stack[topofstack] local new = { } if top then for k, v in next, top do local d = data[k] - local r = d.reset - local s = d.set + local r = d.reset or 0 + local s = d.set or 0 if r <= topofstack and s < r then new[k] = false else @@ -689,6 +692,6 @@ commands.fetchtwomarks = marks.fetchtwomarks commands.fetchallmarks = marks.fetchallmarks function commands.doifelsemarking(str) -- can be shortcut - commands.testcase(marks.exists(str)) + commands.doifelse(marks.exists(str)) end diff --git a/tex/context/base/strc-mat.mkiv b/tex/context/base/strc-mat.mkiv index 121808cd1..ec4d7f643 100644 --- a/tex/context/base/strc-mat.mkiv +++ b/tex/context/base/strc-mat.mkiv @@ -1,4 +1,5 @@ %D \module +%D \module %D [ file=strc-mat, %D version=2008.10.20, %D title=\CONTEXT\ Structure Macros, @@ -39,12 +40,12 @@ \c!expansion=\v!yes, % maybe automatically \c!spacebefore=\v!big, \c!spaceafter=\formulaparameter\c!spacebefore, - \c!leftmargin=\!!zeropoint, - \c!rightmargin=\!!zeropoint, + \c!leftmargin=\zeropoint, + \c!rightmargin=\zeropoint, \c!indentnext=\v!no, \c!alternative=\s!default, \c!strut=\v!no, - \c!distance=1em] + \c!distance=\emwidth] \setupsubformulas % subformulas could be last in chain [\c!indentnext=\formulaparameter\c!indentnext] @@ -54,13 +55,12 @@ \defineconversionset [\v!formula] - [numbers,characters] + [numbers,characters] % no \v! ? \strc_counter_preset_using_parameter\setupformulas\sharedcounterparameter \appendtoks \strc_counter_setup_using_parameter\v!formula\formulaparameter - \strc_counters_check_setup\v!formula % yes or no \to \everysetupformula \setupformulas @@ -68,22 +68,22 @@ \appendtoks \normalexpanded{\definelist[\currentformula]}% is expansion needed? - \setuevalue{\e!start\currentformula\v!formula}{\dostartformula{\currentformula}}% - \setuevalue{\e!stop \currentformula\v!formula}{\dostopformula}% + \setuevalue{\e!start\currentformula\v!formula}{\strc_formulas_start_formula{\currentformula}}% + \setuevalue{\e!stop \currentformula\v!formula}{\strc_formulas_stop_formula}% \to \everydefineformula \definelist[\v!formula] -\setuvalue{\e!start\v!formula}{\dostartformula{}} -\setuvalue{\e!stop \v!formula}{\dostopformula} +\setuvalue{\e!start\v!formula}{\strc_formulas_start_formula{}} +\setuvalue{\e!stop \v!formula}{\strc_formulas_stop_formula} -\let\dostartformula\relax % defined later -\let\dostopformula \relax % defined later +\let\strc_formulas_start_formula\relax % defined later +\let\strc_formulas_stop_formula \relax % defined later -\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys - {\dotripleargument\dodefineformulaalternative} % to the general define .. s!startcommand +\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys + {\dotripleargument\strc_formulas_define_alternative} % to the general define .. s!startcommand -\def\dodefineformulaalternative[#1][#2][#3]% +\def\strc_formulas_define_alternative[#1][#2][#3]% {\setvalue{\e!start#1\v!formula}{#2}% \setvalue{\e!stop #1\v!formula}{#3}} @@ -126,8 +126,8 @@ % implementation -\def\storecurrentformulanumber#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float) - {\settrue\handleformulanumber +\unexpanded\def\strc_formulas_store_number#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float) + {\settrue\c_strc_formulas_handle_number \strc_counters_register_component {formula}% \setupcurrentformula \formulaparameter \detokenizedformulaparameter @@ -143,68 +143,75 @@ % modes: 0=unset, 1=forced, 2=none, 3=reference -\newconstant\placeformulanumbermode -\newconstant\formulasnumbermode -\newconstant\subformulasnumbermode -\newconstant\nestedformulanumbermode +\newconstant\c_strc_formulas_place_number_mode +\newconstant\c_strc_formulas_number_mode +\newconstant\c_strc_formulas_sub_number_mode +\newconstant\c_strc_formulas_nested_number_mode \appendtoks - \placeformulanumbermode \zerocount - \formulasnumbermode \zerocount - \subformulasnumbermode \zerocount - \nestedformulanumbermode\zerocount + \c_strc_formulas_place_number_mode \zerocount + \c_strc_formulas_number_mode \zerocount + \c_strc_formulas_sub_number_mode \zerocount + \c_strc_formulas_nested_number_mode\zerocount \to \everyresetformulas -\newconditional\handleformulanumber -\newconditional\incrementformulanumber - -\newconditional\insideplaceformula -\newconditional\insideplacesubformula -\newconditional\insideformulas -\newconditional\insidesubformulas +\newconditional\c_strc_formulas_handle_number +\newconditional\c_strc_formulas_increment +\newconditional\c_strc_formulas_inside_place +\newconditional\c_strc_formulas_inside_place_sub +\newconditional\c_strc_formulas_inside_formulas +\newconditional\c_strc_formulas_inside_formulas_sub \appendtoks - \global\setfalse\insideplaceformula - \global\setfalse\insideplacesubformula + \global\setfalse\c_strc_formulas_inside_place + \global\setfalse\c_strc_formulas_inside_place_sub \to \everyresetformulas -\def\handleplaceformulanumbering % place formula - {\settrue\handleformulanumber - \docheckformulareference\placeformulanumbermode\currentplaceformulareference - \glet\doplaceformulanumber \doplaceformulanumberindeed - \glet\donestedformulanumber\donestedformulanumberindeed} +\def\strc_formulas_place_numbering % place formula + {\settrue\c_strc_formulas_handle_number + \strc_formulas_check_reference\c_strc_formulas_place_number_mode\currentplaceformulareference + \glet\strc_formulas_place_number\strc_formulas_place_number_indeed + \glet\strc_formulas_place_number_nested\strc_formulas_place_number_nested_indeed} -\def\handleformulasnumbering % formulas - {\docheckformulareference\formulasnumbermode\currentformulareference} +\def\strc_formulas_handle_number % formulas + {\strc_formulas_check_reference\c_strc_formulas_number_mode\currentformulareference} -\def\handlesubformulasnumbering % sub formulas - {\docheckformulareference\subformulasnumbermode\currentsubformulasreference +\def\strc_formulas_handle_sub_number_indeed % sub formulas + {\strc_formulas_check_reference\c_strc_formulas_sub_number_mode\currentsubformulasreference \strc_counters_increment\v!formula - \storecurrentformulanumber + \strc_formulas_store_number \currentsubformulasreference \empty \currentsubformulasnumber \currentsubformulassynchronize - \currentsubformulasattribute - } + \currentsubformulasattribute} + +\def\strc_formulas_handle_sub_number % sub formulas + {\iftrialtypesetting + \strc_counters_save\v!formula + \strc_formulas_handle_sub_number_indeed + \strc_counters_restore\v!formula + \else + \strc_formulas_handle_sub_number_indeed + \fi} -\let\dotraceformulareferencestate\relax -\let\doshowformulareferencestate \relax +\let\strc_formulas_reference_trace\relax +\let\strc_formulas_reference_show \relax -% \def\dotraceformulareferencestate +% \def\strc_formulas_reference_trace % {\rlap{\hbox{\quad\tt\txx[% -% \number\placeformulanumbermode,% -% \number\formulasnumbermode,% -% \number\subformulasnumbermode,% -% \number\nestedformulanumbermode +% \number\c_strc_formulas_place_number_mode,% +% \number\c_strc_formulas_number_mode,% +% \number\c_strc_formulas_sub_number_mode,% +% \number\c_strc_formulas_nested_number_mode % ]}}} -% \def\doshowformulareferencestate +% \def\strc_formulas_reference_show % {\writestatus{\v!formula}% -% {place: \number\placeformulanumbermode,\space -% formula: \number\formulasnumbermode,\space -% subformula: \number\subformulasnumbermode,\space -% nested: \number\nestedformulanumbermode]}} +% {place: \number\c_strc_formulas_place_number_mode,\space +% formula: \number\c_strc_formulas_number_mode,\space +% subformula: \number\c_strc_formulas_sub_number_mode,\space +% nested: \number\c_strc_formulas_nested_number_mode]}} \unexpanded\def\placecurrentformulanumber {\rm % nodig ? @@ -216,12 +223,12 @@ \namedtaggedlabeltexts \t!formulalabel \v!formula \t!formulanumber\v!formula - {\ignorespaces\doplacecurrentformulanumber\removeunwantedspaces}% + {\ignorespaces\strc_formulas_place_current_number\removeunwantedspaces}% \formulaparameter\c!right}% \doif{\formulaparameter\c!location}\v!left{\hskip\formulaparameter\c!distance}} -\def\doplacecurrentformulanumber - {\dohandlecurrentformulareferences +\unexpanded\def\strc_formulas_place_current_number + {\strc_formulas_handle_current_references \labeltexts\currentformula{\convertedcounter[\v!formula][]}} % \def\theboxdestinationattribute#1{\iflocation\ifx#1\relax\else\ifx#1\empty\else attr \destinationattribute#1\fi\fi\fi} @@ -281,10 +288,10 @@ % currently we do the number, some day we will do the (sub) formula -\def\dohandlecurrentformulareferences - {\doshowformulareferencestate - \ifnum\placeformulanumbermode=\plusthree - \storecurrentformulanumber +\def\strc_formulas_handle_current_references + {\strc_formulas_reference_show + \ifnum\c_strc_formulas_place_number_mode=\plusthree + \strc_formulas_store_number \currentplaceformulareference \empty \currentplaceformulanumber @@ -294,8 +301,8 @@ \glet\currentplaceformulasynchronize\relax \theformuladestinationattribute\currentplaceformulaattribute \fi - \ifnum\formulasnumbermode=\plusthree - \storecurrentformulanumber + \ifnum\c_strc_formulas_number_mode=\plusthree + \strc_formulas_store_number \currentformulasreference \empty \currentformulasnumber @@ -305,12 +312,12 @@ \glet\currentformulassynchronize\relax \theformuladestinationattribute\currentformulasattribute \fi - \ifnum\subformulasnumbermode=\plusthree + \ifnum\c_strc_formulas_sub_number_mode=\plusthree \currentsubformulassynchronize \glet\currentsubformulassynchronize\relax \fi - \ifnum\nestedformulanumbermode=\plusthree - \storecurrentformulanumber + \ifnum\c_strc_formulas_nested_number_mode=\plusthree + \strc_formulas_store_number \currentnestedformulareference \empty \currentnestedformulanumber @@ -323,55 +330,74 @@ % needs checking ... too many: -\def\dohandleformulanumbering +\def\strc_formulas_handle_numbering_indeed {\strc_counters_increment\v!formula \doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}% \placecurrentformulanumber} -\def\dohandlesubformulanumbering - {\doiftextelse\currentsubformulasuffix +\def\strc_formulas_handle_numbering + {\iftrialtypesetting + \strc_counters_save\v!formula + \strc_formulas_handle_numbering_indeed + \strc_counters_restore\v!formula + \else + \strc_formulas_handle_numbering_indeed + \fi} + +\def\strc_formulas_handle_sub_numbering_indeed + {\let\strc_formulas_handle_sub_numbering\relax % else error: see math/numbering-001.tex + \doiftextelse\currentsubformulasuffix {\strc_counters_setown_sub\v!formula\plustwo\currentsubformulasuffix} {\strc_counters_increment_sub\v!formula\plustwo}% - \placecurrentformulanumber} + \placecurrentformulanumber} -\def\dododoformulanumber - {\ifconditional\handleformulanumber +\def\strc_formulas_handle_sub_numbering + {\iftrialtypesetting + \strc_counters_save\v!formula + \strc_formulas_handle_sub_numbering_indeed + \strc_counters_restore\v!formula + \else + \strc_formulas_handle_sub_numbering_indeed + \fi} + +\def\strc_formulas_number_indeed + {\ifconditional\c_strc_formulas_handle_number \hbox\bgroup % main counter - \ifconditional\insidesubformulas + \ifconditional\c_strc_formulas_inside_formulas_sub % nothing \else - \ifcase\formulasnumbermode - \ifcase\placeformulanumbermode - \dohandleformulanumbering + \ifcase\c_strc_formulas_number_mode + \ifcase\c_strc_formulas_place_number_mode + \strc_formulas_handle_numbering \or - \dohandleformulanumbering + \strc_formulas_handle_numbering \or % nothing \or - \dohandleformulanumbering + \strc_formulas_handle_numbering \fi \or - \dohandleformulanumbering + \strc_formulas_handle_numbering \or % nothing \or - \dohandleformulanumbering + \strc_formulas_handle_numbering \fi \fi % subcounter - \ifconditional\insidesubformulas - \ifcase\subformulasnumbermode + \ifconditional\c_strc_formulas_inside_formulas_sub + \ifcase\c_strc_formulas_sub_number_mode % nothing \or - \dohandlesubformulanumbering + \strc_formulas_handle_sub_numbering \or % nothing \or - \dohandlesubformulanumbering + \strc_formulas_handle_sub_numbering \fi \fi - \dotraceformulareferencestate + \strc_formulas_reference_trace \egroup \fi} @@ -393,10 +419,10 @@ %D %D Otherwise we get a missing \type {$$} error reported. -\def\resetdisplaymatheq +\unexpanded\def\resetdisplaymatheq % when used? {\let\normalleqno\gobbleoneargument \let\leqno\gobbleoneargument \let\normalreqno\gobbleoneargument \let\eqno \gobbleoneargument - \let\doplaceformulanumber\empty} + \let\strc_formulas_place_number\relax} %D \macros %D {startsubformulas} @@ -431,28 +457,36 @@ % we don't use the skip's -\def\forgetdisplayskips % to do +\unexpanded\def\strc_formulas_forget_display_skips {\abovedisplayskip \zeropoint \belowdisplayskip \zeropoint \abovedisplayshortskip\zeropoint \belowdisplayshortskip\zeropoint} -\def\predisplaysizethreshhold{2em} % was 3em +% \def\predisplaysizethreshhold{2\emwidth} % was 3\emwidth -\def\leftdisplayskip {\leftskip} -\def\rightdisplayskip {\rightskip} -\def\leftdisplaymargin {\formulaparameter\c!leftmargin} -\def\rightdisplaymargin {\formulaparameter\c!rightmargin} +\newdimen\d_strc_formulas_display_skip_left +\newdimen\d_strc_formulas_display_skip_right +\newdimen\d_strc_formulas_display_margin_left +\newdimen\d_strc_formulas_display_margin_right +\newdimen\d_strc_formulas_display_pre_threshold +\newskip \d_strc_formulas_display_skip_par -\def\beforedisplayspace - {\doifnot{\formulaparameter\c!spacebefore}\v!none{\blank[\formulaparameter\c!spacebefore]}} +\unexpanded\def\beforedisplayspace + {\edef\p_spacebefore{\formulaparameter\c!spacebefore}% + \ifx\p_spacebefore\v!none \else + \blank[\p_spacebefore]% + \fi} -\def\afterdisplayspace - {\doifnot{\formulaparameter\c!spaceafter }\v!none{\blank[\formulaparameter\c!spaceafter ]}} +\unexpanded\def\afterdisplayspace + {\edef\p_spaceafter{\formulaparameter\c!spaceafter}% + \ifx\p_spaceafter\v!none \else + \blank[\p_spaceafter]% + \fi} -\def\setdisplaydimensions - {\displayindent\leftdisplayskip - \advance\displayindent\leftdisplaymargin +\unexpanded\def\setdisplaydimensions + {\displayindent\d_strc_formulas_display_skip_left + \advance\displayindent\d_strc_formulas_display_margin_left \displaywidth\hsize %\setlocalhsize %\displaywidth\localhsize @@ -461,15 +495,14 @@ \else \advance\displaywidth\hangindent \fi - \advance\displaywidth\dimexpr-\displayindent-\rightdisplayskip-\rightdisplaymargin\relax + \advance\displaywidth\dimexpr-\displayindent-\d_strc_formulas_display_skip_right-\d_strc_formulas_display_margin_right\relax \hsize\displaywidth} % new, else overfull in itemize -\unexpanded\def\dostartformula#1% - {\dodoubleempty\dodostartformula[#1]} +\unexpanded\def\strc_formulas_start_formula#1% + {\dodoubleempty\strc_formulas_start_formula_indeed[#1]} -\newskip\formulaparskip -\newskip\formulastrutht -\newskip\formulastrutdp +% \newskip\formulastrutht +% \newskip\formulastrutdp %D \startbuffer %D \startformula[9pt] x = 1 \stopformula @@ -478,38 +511,56 @@ %D %D \typebuffer \getbuffer -\def\dodostartformula[#1][#2]% setting leftskip adaption is slow ! +\unexpanded\def\strc_formulas_start_formula_indeed[#1][#2]% setting leftskip adaption is slow ! {\bgroup % HERE \def\currentformula{#1}% \dostarttagged\t!formula\currentformula \the\everybeforedisplayformula - \formulaparskip\parskip - \formulastrutdp\strutdepth - \formulastrutht\strutheight - \doifsomething{#2}{\switchtoformulabodyfont[#2]}% - \parskip\formulaparskip - % may look better in itemizations - \doif{\formulaparameter\c!option}\v!middle - {\def\leftdisplayskip{\zeropoint}% - \def\rightdisplayskip{\zeropoint}}% - % this was an experiment - \doifsomething{\formulaparameter\c!margin}% so we test first - {\dosetleftskipadaption{\formulaparameter\c!margin}% - \edef\leftdisplaymargin{\the\leftskipadaption}}% overloaded - \long\def\dostartformula##1{\bgroup\dostarttagged\t!subformula\def\dostopformula{\dostoptagged\egroup}}% - \freezedimenmacro\leftdisplayskip - \freezedimenmacro\rightdisplayskip - \freezedimenmacro\leftdisplaymargin - \freezedimenmacro\rightdisplaymargin - \freezedimenmacro\predisplaysizethreshhold - \forgetdisplayskips + \d_strc_formulas_display_skip_par\parskip\relax + %\formulastrutdp\strutdepth + %\formulastrutht\strutheight + \edef\p_option {\formulaparameter\c!option}% + \edef\p_margin {\formulaparameter\c!margin}% + \edef\p_bodyfont{#2}% + %\ifx\p_bodyfont\empty + % \edef\p_bodyfont{\formulaparameter\c!bodyfont}% + %\fi + \ifx\p_bodyfont\empty \else + \switchtoformulabodyfont[#2]% + \fi + \parskip\d_strc_formulas_display_skip_par\relax + \ifx\p_option\v!middle + \d_strc_formulas_display_skip_left \zeropoint + \d_strc_formulas_display_skip_right\zeropoint + \else + \d_strc_formulas_display_skip_left \leftskip + \d_strc_formulas_display_skip_right\rightskip + \fi + \d_strc_formulas_display_margin_left \formulaparameter\c!leftmargin \relax + \d_strc_formulas_display_margin_right\formulaparameter\c!rightmargin\relax + \ifx\p_margin\empty \else + \dosetleftskipadaption\p_margin + \d_strc_formulas_display_margin_left\leftskipadaption + \fi + \let\strc_formulas_start_formula\strc_formulas_start_formula_nested + %\freezedimenmacro\predisplaysizethreshhold + \strc_formulas_forget_display_skips \getvalue{\e!start\formulaparameter\c!alternative\v!formula}} +\unexpanded\def\strc_formulas_start_formula_nested#1% + {\bgroup + \let\strc_formulas_stop_formula\strc_formulas_stop_formula_nested + \dostarttagged\t!subformula} + +\unexpanded\def\strc_formulas_stop_formula_nested + {\dostoptagged + \egroup} + % tagging of formulanumbers is not ok (we get two display maths blobs) -\unexpanded\def\dostopformula +\unexpanded\def\strc_formulas_stop_formula {\dostarttagged\t!formulacaption\empty - \doplaceformulanumber + \strc_formulas_place_number \dostoptagged \dostarttagged\t!formulacontent\empty \getvalue{\e!stop\formulaparameter\c!alternative\v!formula}% @@ -520,27 +571,31 @@ \egroup \hangafter\minusone % added for side floats \hangindent\zeropoint % added for side floats - \setfalse\handleformulanumber + \setfalse\c_strc_formulas_handle_number \the\everyresetformulas \dorechecknextindentation} % here ? % experiment: \appendtoks - \edef\currentformulagrid{\formulaparameter\c!grid}% - \ifx\currentformulagrid\empty \else - \spac_grids_snap_value_auto\currentformulagrid + \edef\p_grid{\formulaparameter\c!grid}% + \ifx\p_grid\empty \else + \spac_grids_snap_value_auto\p_grid \fi \to \everybeforedisplayformula -\def\switchtoformulabodyfont{\switchtobodyfont} +\unexpanded\def\switchtoformulabodyfont + {\switchtobodyfont} -\setuvalue{\v!formula}{\dosingleempty\doformula} +\setuvalue{\v!formula}{\dosingleempty\strc_formulas_formula} -\def\doformula[#1]#2% todo: tagged +\def\strc_formulas_formula[#1]#2% todo: tagged {\begingroup - \doifsomething{#1}{\switchtoformulabodyfont[#1]}% - % not : \def\doformula[##1]##2{\mathematics{##2}}% + \edef\p_bodyfont{#1}% + \ifx\p_bodyfont\empty \else + \switchtoformulabodyfont[\p_bodyfont]% + \fi + % not : \def\strc_formulas_formula[##1]##2{\mathematics{##2}}% \mathematics{#2}% \endgroup} @@ -558,7 +613,7 @@ \beforedisplayspace \par \ifvmode - \prevdepth-\maxdimen % texbook pagina 79-80 + \prevdepth-\maxdimen % texbook pagina 79-80 \fi \noindent % else funny hlist with funny baselineskip $$% \Ustartdisplaymath @@ -601,26 +656,26 @@ % \fakewords{20}{40} \unexpanded\def\startsubformulas - {\dosingleempty\dostartsubformulas} + {\dosingleempty\strc_formulas_start_sub_formulas} -\def\dostartsubformulas[#1]% +\def\strc_formulas_start_sub_formulas[#1]% {\edef\currentsubformulasreference{#1}% - \global\settrue\insidesubformulas - \handlesubformulasnumbering} + \global\settrue\c_strc_formulas_inside_formulas_sub + \strc_formulas_handle_sub_number} \unexpanded\def\stopsubformulas {\nonoindentation \useindentnextparameter\subformulaparameter \the\everyresetformulas % to be checked - \global\setfalse\insidesubformulas + \global\setfalse\c_strc_formulas_inside_formulas_sub \dorechecknextindentation} % here ? %D Named subformulas (to be redone) \unexpanded\def\startnamedsubformulas - {\dosingleempty\dostartnamedsubformulas} + {\dosingleempty\strc_formulas_start_named_sub_formulas} -\def\dostartnamedsubformulas[#1]#2% +\def\strc_formulas_start_named_sub_formulas[#1]#2% {\setformulalistentry{#2}% \startsubformulas[#1]} @@ -639,19 +694,19 @@ %D \typebuffer \getbuffer \unexpanded\def\startformulas - {\dosingleempty\dostartformulas} + {\dosingleempty\strc_formulas_start_formulas} -\def\dostartformulas[#1]#2\stopformulas % new / to be internationalized +\def\strc_formulas_start_formulas[#1]#2\stopformulas % new / to be internationalized {\bgroup \dostarttagged\t!formulaset\empty - \global\settrue\insideformulas + \global\settrue\c_strc_formulas_inside_formulas \edef\currentformulasreference{#1}% - \handleformulasnumbering + \strc_formulas_handle_number \let\currentformula\empty - \forgetdisplayskips + \strc_formulas_forget_display_skips \startdisplaymath \setlocalhsize - \long\unexpanded\def\startformula##1\stopformula + \unexpanded\def\startformula##1\stopformula {\advance\scratchcounter\plusone}% \scratchcounter\zerocount #2% preroll @@ -660,122 +715,135 @@ \fi \hbox to \localhsize \bgroup \hss - \def\normalstartformula{\vskip-\strutdepth\Ustartdisplaymath}% i hate this - \def\normalstopformula {\Ustopdisplaymath}% - \unexpanded\def\startformula {\Ustartmath\vcenter\bgroup\normalstartformula}% - \unexpanded\def\stopformula {\normalstopformula\egroup\Ustopmath\hss}% + \let\startformula\strc_formulas_nested_formula_start + \let\stopformula \strc_formulas_nested_formula_stop #2% \egroup \stopdisplaymath - \global\setfalse\insideformulas + \global\setfalse\c_strc_formulas_inside_formulas \dostoptagged \egroup \the\everyresetformulas \hangafter\minusone % added for side floats \hangindent\zeropoint} % added for side floats +\unexpanded\def\strc_formulas_nested_formula_start + {\Ustartmath + \vcenter\bgroup + \vskip-\strutdepth + \Ustartdisplaymath} + +\unexpanded\def\strc_formulas_nested_formula_stop + {\Ustopdisplaymath + \egroup + \Ustopmath + \hss} + % place -\def\inhibitformulanumberflag{-} -\def\forceformulanumberflag {+} +\def\m_strc_formulas_flag_inhibit{-} +\def\m_strc_formulas_flag_force {+} -\def\docheckformulareference#1#2% +\def\strc_formulas_check_reference#1#2% {#1\unless\ifx\namedformulaentry\empty % \relax % new 29/8/2010 \plusthree \else\ifx#2\empty \zerocount - \else\ifx#2\forceformulanumberflag + \else\ifx#2\m_strc_formulas_flag_force \plusone - \else\ifx#2\inhibitformulanumberflag + \else\ifx#2\m_strc_formulas_flag_inhibit \plustwo \else \plusthree \fi\fi\fi\fi} -\unexpanded\def\formulanumber{\doformulanumber} % for the moment +\unexpanded\def\formulanumber + {\strc_formulas_number} % for the moment -\def\doformulanumber - {\dosingleempty\dodoformulanumber} +\def\strc_formulas_number + {\dosingleempty\strc_formulas_number_again} -\def\dodoformulanumber[#1]% +\def\strc_formulas_number_again[#1]% {\def\currentformulareference{#1}% - \dosinglegroupempty\dododoformulanumber} - -\def\redoformulanumber#1% - {\def\currentformulasuffix{#1}% - \dododoformulanumber} + \dosinglegroupempty\strc_formulas_number_indeed} \unexpanded\def\placeformula - {\global\settrue\insideplaceformula - \settrue\incrementformulanumber - \dosingleempty\doplaceformula} + {\global\settrue\c_strc_formulas_inside_place + \settrue\c_strc_formulas_increment + \dosingleempty\strc_formulas_place} \unexpanded\def\placesubformula - {\global\settrue\insideplacesubformula - \setfalse\incrementformulanumber - \dosingleempty\doplaceformula} + {\global\settrue\c_strc_formulas_inside_place_sub + \setfalse\c_strc_formulas_increment + \dosingleempty\strc_formulas_place} -\def\doplaceformula[#1]% +\def\strc_formulas_place[#1]% {\def\currentplaceformulareference{#1}% \let\currentplaceformulasuffix\empty - \doifnextbgroupelse\moreplaceformula\redoplaceformula} % [ref]{} + \doifnextbgroupelse\strc_formulas_place_yes\strc_formulas_place_nop\strc_formulas_place_nop} % [ref]{} -\def\moreplaceformula#1% +\def\strc_formulas_place_yes#1% {\def\currentplaceformulasuffix{#1}% - \redoplaceformula} + \strc_formulas_place_nop} -\def\redoplaceformula - {\doifnextcharelse$\dispplaceformula\dodoplaceformula} % [ref]$$ [ref]\start +\def\strc_formulas_place_nop + {\doifnextcharelse$\strc_formulas_place_pickup\strc_formulas_place_indeed} % [ref]$$ [ref]\start -\def\dodoplaceformula - {\handleplaceformulanumbering} +\def\strc_formulas_place_indeed + {\strc_formulas_place_numbering} -\def\dispplaceformula$$#1$$% - {\handleplaceformulanumbering - \dostartformula{}#1\dostopformula} +\def\strc_formulas_place_pickup$$#1$$% + {\strc_formulas_place_numbering + \strc_formulas_start_formula{}#1\strc_formulas_stop_formula} \let\startplaceformula\placeformula \let\stopplaceformula \relax % to be checked -\let\doplaceformulanumber \relax -\let\donestedformulanumber\gobbletwoarguments +\let\strc_formulas_place_number \relax +\let\strc_formulas_place_number_nested\gobbletwoarguments -\def\donestedformulanumberindeed#1#2% +\def\strc_formulas_place_number_nested_indeed#1#2% {\def\currentnestedformulareference{#1}% \def\currentnestedformulasuffix{#2}% - \glet\doplaceformulanumber\relax - \docheckformulareference\nestedformulanumbermode\currentnestedformulareference - \ifcase\nestedformulanumbermode + \glet\strc_formulas_place_number\relax + \strc_formulas_check_reference\c_strc_formulas_nested_number_mode\currentnestedformulareference + \ifcase\c_strc_formulas_nested_number_mode % nothing \or - \doformulanumber + \strc_formulas_number % hm, looks ahead for [] \or % nothing \or - \doformulanumber + \strc_formulas_number % hm, looks ahead for [] \fi} -\def\doplaceformulanumberindeed - {\glet\doplaceformulanumber\relax +\def\strc_formulas_place_number_indeed + {\glet\strc_formulas_place_number\relax \doifelse{\formulaparameter\c!location}\v!left - {\normalleqno{\dododoformulanumber}} - {\normalreqno{\dododoformulanumber}}} + {\normalleqno{\strc_formulas_number_indeed}} + {\normalreqno{\strc_formulas_number_indeed}}} % todo \unexpanded\def\placenamedformula - {\dosingleempty\doplacenamedformula} + {\dosingleempty\strc_formulase_place_named} -\def\doplacenamedformula[#1]#2% +\def\strc_formulase_place_named {\iffirstargument - \def\next{\placeformula[#1]}% + \expandafter\strc_formulase_place_named_yes \else - \let\next\placeformula - \fi - \setformulalistentry{#2}% - \next} + \expandafter\strc_formulase_place_named_nop + \fi} + +\def\strc_formulase_place_named_yes[#1]#2% + {\setformulalistentry{#2}% + \placeformula[#1]} + +\def\strc_formulase_place_named_nop[#1]#2% + {\setformulalistentry{#2}% + \placeformula} \let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks diff --git a/tex/context/base/strc-not.lua b/tex/context/base/strc-not.lua index 6a3f3bfad..d71b371ab 100644 --- a/tex/context/base/strc-not.lua +++ b/tex/context/base/strc-not.lua @@ -13,18 +13,19 @@ local texcount = tex.count local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end) local trace_references = false trackers.register("structures.notes.references", function(v) trace_references = v end) -local report_notes = logs.reporter("structure","notes") +local report_notes = logs.reporter("structure","notes") -local structures = structures -local helpers = structures.helpers -local lists = structures.lists -local sections = structures.sections -local counters = structures.counters -local notes = structures.notes -local references = structures.references +local structures = structures +local helpers = structures.helpers +local lists = structures.lists +local sections = structures.sections +local counters = structures.counters +local notes = structures.notes +local references = structures.references +local counterspecials = counters.specials -notes.states = notes.states or { } -lists.enhancers = lists.enhancers or { } +notes.states = notes.states or { } +lists.enhancers = lists.enhancers or { } storage.register("structures/notes/states", notes.states, "structures.notes.states") @@ -33,10 +34,18 @@ local notedata = { } local variables = interfaces.variables local context = context +local commands = commands -- state: store, insert, postpone -function notes.store(tag,n) +local function store(tag,n) + -- somewhat weird but this is a cheap hook spot + if not counterspecials[tag] then + counterspecials[tag] = function(tag) + context.doresetlinenotecompression(tag) -- maybe flag that controls it + end + end + -- local nd = notedata[tag] if not nd then nd = { } @@ -53,7 +62,13 @@ function notes.store(tag,n) end state.start = state.start or nnd end - context(#nd) + return #nd +end + +notes.store = store + +function commands.storenote(tag,n) + context(store(tag,n)) end local function get(tag,n) -- tricky ... only works when defined @@ -84,16 +99,59 @@ notes.getn = getn -- we could make a special enhancer -function notes.listindex(tag,n) +local function listindex(tag,n) local ndt = notedata[tag] return ndt and ndt[n] end +notes.listindex = listindex + +function commands.notelistindex(tag,n) + context(listindex(tag,n)) +end + +local function setstate(tag,newkind) + local state = notestates[tag] + if trace_notes then + report_notes("setting state of '%s' from %s to %s",tag,(state and state.kind) or "unset",newkind) + end + if not state then + state = { + kind = newkind + } + notestates[tag] = state + elseif newkind == "insert" then + if not state.start then + state.kind = newkind + end + else + state.kind = newkind + end + -- state.start can already be set and will be set when an entry is added or flushed + return state +end + +local function getstate(tag) + local state = notestates[tag] + return state and state.kind or "unknown" +end + +notes.setstate = setstate +notes.getstate = getstate + +commands.setnotestate = setstate + +function commands.getnotestate(tag) + context(getstate(tag)) +end + function notes.define(tag,kind,number) - local state = notes.setstate(tag,kind) + local state = setstate(tag,kind) state.number = number end +commands.definenote = notes.define + function notes.save(tag,newkind) local state = notestates[tag] if state and not state.saved then @@ -121,33 +179,10 @@ function notes.restore(tag,forcedstate) end end -function notes.setstate(tag,newkind) - local state = notestates[tag] - if trace_notes then - report_notes("setting state of '%s' from %s to %s",tag,(state and state.kind) or "unset",newkind) - end - if not state then - state = { - kind = newkind - } - notestates[tag] = state - elseif newkind == "insert" then - if not state.start then - state.kind = newkind - end - else - state.kind = newkind - end - -- state.start can already be set and will be set when an entry is added or flushed - return state -end - -function notes.getstate(tag) - local state = notestates[tag] - context(state and state.kind or "unknown") -end +commands.savenote = notes.save +commands.restorenote = notes.restore -function notes.doifcontent(tag) +local function hascontent(tag) local ok = notestates[tag] if ok then if ok.kind == "insert" then @@ -160,17 +195,21 @@ function notes.doifcontent(tag) ok = ok.start end end - commands.doif(ok) + return ok and true or false +end + +notes.hascontent = hascontent + +function commands.doifnotecontent(tag) + commands.doif(hascontent(tag)) end local function internal(tag,n) local nd = get(tag,n) if nd then --- inspect(nd) local r = nd.references if r then local i = r.internal --- return i and lists.internals[i] return i and references.internals[i] -- dependency on references end end @@ -186,7 +225,7 @@ end notes.internal = internal notes.ordered = ordered -function notes.doifonsamepageasprevious(tag) +local function onsamepageasprevious(tag) local same = false local n = getn(tag,n) local current, previous = get(tag,n), get(tag,n-1) @@ -194,7 +233,13 @@ function notes.doifonsamepageasprevious(tag) local cr, pr = current.references, previous.references same = cr and pr and cr.realpage == pr.realpage end - commands.doifelse(same) + return same and true or false +end + +notes.doifonsamepageasprevious = onsamepageasprevious + +function commands.doifnoteonsamepageasprevious(tag) + commands.doifelse(onsamepageasprevious(tag)) end function notes.checkpagechange(tag) -- called before increment ! @@ -222,13 +267,15 @@ function notes.postpone() end for tag, state in next, notestates do if state.kind ~= "store" then - notes.setstate(tag,"postpone") + setstate(tag,"postpone") end end end +commands.postponenotes = notes.postpone + function notes.setsymbolpage(tag,n,l) - local l = l or notes.listindex(tag,n) + local l = l or listindex(tag,n) if l then local p = texcount.realpageno if trace_notes or trace_references then @@ -245,41 +292,32 @@ function notes.setsymbolpage(tag,n,l) end end --- function notes.getsymbolpage(tag,n) --- local nd = get(tag,n) --- local p = nd and nd.references.symbolpage or 0 --- if trace_notes or trace_references then --- report_notes("page number of note symbol %s of '%s' is %s",n,tag,p) --- end --- context(p) --- end +commands.setnotesymbolpage = notes.setsymbolpage -function notes.getsymbolpage(tag,n) +local function getsymbolpage(tag,n) local li = internal(tag,n) li = li and li.references li = li and (li.symbolpage or li.realpage) or 0 if trace_notes or trace_references then report_notes("page number of note symbol %s of '%s' is %s",n,tag,li) end - context(li) + return li end -function notes.getnumberpage(tag,n) +local function getnumberpage(tag,n) local li = internal(tag,n) li = li and li.references li = li and li.realpage or 0 if trace_notes or trace_references then report_notes("page number of note number %s of '%s' is %s",n,tag,li) end - context(li) + return li end -function notes.deltapage(tag,n) +local function getdeltapage(tag,n) -- 0:unknown 1:textbefore, 2:textafter, 3:samepage local what = 0 - --- references.internals[lists.tobesaved[nd].internal] - + -- references.internals[lists.tobesaved[nd].internal] local li = internal(tag,n) if li then local references = li.references @@ -301,10 +339,18 @@ function notes.deltapage(tag,n) -- nesting in a vbox end end - context(what) + return what end -function notes.flush(tag,whatkind,how) -- store and postpone +notes.getsymbolpage = getsymbolpage +notes.getnumberpage = getnumberpage +notes.getdeltapage = getdeltapage + +function commands.notesymbolpage(tag,n) context(getsymbolpage(tag,n)) end +function commands.notenumberpage(tag,n) context(getnumberpage(tag,n)) end +function commands.notedeltapage (tag,n) context(getdeltapage (tag,n)) end + +function commands.flushnotes(tag,whatkind,how) -- store and postpone local state = notestates[tag] local kind = state.kind if kind == whatkind then @@ -360,12 +406,12 @@ function notes.flush(tag,whatkind,how) -- store and postpone end end -function notes.flushpostponed() +function commands.flushpostponednotes() if trace_notes then report_notes("flushing all postponed notes") end for tag, _ in next, notestates do - notes.flush(tag,"postpone") + commands.flushnotes(tag,"postpone") end end diff --git a/tex/context/base/strc-not.mkvi b/tex/context/base/strc-not.mkvi index 0a57ed878..0a89edf3d 100644 --- a/tex/context/base/strc-not.mkvi +++ b/tex/context/base/strc-not.mkvi @@ -21,10 +21,6 @@ % todo: see if we can now use \insertpenalties (>0 == some left) -\ifdefined\v!notation \else \def\v!notation {notation} \fi -\ifdefined\v!endnote \else \def\v!endnote {endnote} \fi -\ifdefined\c!symbolcommand \else \def\c!symbolcommand{symbolcommand} \fi - \ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi \unexpanded\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often @@ -73,8 +69,6 @@ \let\setupnotations\setupnotation -% \unexpanded\def\lowllap#1{\low{\llap{#1}}} - \definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}] \definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}] @@ -123,29 +117,26 @@ \c!state=\v!start, \c!levels=3] -% mostly the same as enumersations but we want to keep them -% isolated and at some point we might differentiate - -% to be considered: -% -% \let\??construction\??notation -% -% with push/pop (also at definition time) - -\unexpanded\def\strc_define_commands_notation#1#2#3% current level parent - {\doifelsenothing{#3} - {\normalexpanded{\defineconstruction[#1][\s!handler=\v!notation,\c!level=#2]}% - \setevalue{\??notation#1:\s!parent}{\??notation}}% - {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!notation,\c!level=#2]}% - \setevalue{\??notation#1:\s!parent}{\??notation#3}}% - \setuevalue{\e!next #1}{\strc_notations_next }% - \setuevalue{\c!reset#1}{\strc_notations_reset }% - %setuevalue{\c!set #1}{\strc_notations_set }% -% \setuevalue {#1}{\strc_notations_command{\currentnotation}}% -% \setuevalue{\e!start#1}{\strc_notations_start {\currentnotation}{#1}}% - \setuevalue {#1}{\strc_notations_command{#1}}% - \setuevalue{\e!start#1}{\strc_notations_start {#1}{#1}}% okay? - \setuevalue{\e!stop #1}{\strc_notations_stop }} +%D The code here is mostly the same as enumersations but we want to keep them +%D isolated and at some point we might differentiate. + +% \installcorenamespace{noteclass} + +\unexpanded\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}}% + \setuevalue{\e!next #tag}{\strc_notations_next }% + \setuevalue{\c!reset#tag}{\strc_notations_reset }% + %setuevalue{\c!set #tag}{\strc_notations_set }% + %setuevalue {#tag}{\strc_notations_command{\currentnotation}}% + %setuevalue{\e!start#tag}{\strc_notations_start {\currentnotation}{#tag}}% + \setuevalue {#tag}{\strc_notations_command{#tag}}% + \setuevalue{\e!start#tag}{\strc_notations_start {#tag}{#tag}}% okay? + \setuevalue{\e!stop #tag}{\strc_notations_stop }} \appendtoks \ifx\currentnotationparent\empty @@ -179,23 +170,23 @@ \ifx\p_counter\empty % \let\p_counter\currentnotation \fi -% \doifcounterelse\p_counter\donothing{\strc_enumerations_define_counter\p_counter}% -% \letnotationparameter\s!counter\p_counter -% \strc_enumerations_setup_counter\currentnotation \doifcounterelse\p_counter\donothing{\strc_notes_define_counter\p_counter}% \letnotationparameter\s!counter\p_counter \strc_notes_setup_counter\currentnotation \to \everydefinenotation -\setvalue{\??constructioninitializer\v!notation}% +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\unexpanded\setvalue{\??constructioninitializer\v!notation}% {\let\currentnotation \currentconstruction \let\constructionparameter \notationparameter \let\detokenizedconstructionparameter\detokenizednotationparameter \let\letconstructionparameter \letnotationparameter \let\useconstructionstyleandcolor \usenotationstyleandcolor \let\setupcurrentconstruction \setupcurrentnotation - \edef\p_number{\constructionparameter\c!number}% - \ifx\p_number\v!yes + \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 @@ -204,14 +195,14 @@ \else \setfalse\c_strc_constructions_number_state \fi - \edef\p_title{\constructionparameter\c!title}% - \ifx\p_title\v!yes + \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!notation}% +\unexpanded\setvalue{\??constructionfinalizer\v!notation}% {\ifconditional\c_strc_constructions_number_state \iftrialtypesetting \strc_counters_restore\currentconstructionnumber @@ -232,58 +223,58 @@ \let\strc_notations_reset\strc_enumerations_reset %let\strc_notations_set \strc_enumerations_set -\unexpanded\def\strc_notations_command#1% +\unexpanded\def\strc_notations_command#tag% {\begingroup - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% \strc_notes_synchronize \ifnotesenabled \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel \fi \doifnextoptionalelse\strc_notations_command_yes\strc_notations_command_nop} -\unexpanded\def\strc_notations_command_nop#1% - {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]% +\unexpanded\def\strc_notations_command_nop#title% + {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=][]% \csname\??constructionnotehandler\currentconstructionhandler\endcsname \strc_constructions_finalize \normalexpanded{\endgroup\noteparameter\c!next}} -\unexpanded\def\strc_notations_command_yes[#1]% - {\doifassignmentelse{#1}\strc_notations_command_assignment\strc_notations_command_argument[#1]} +\unexpanded\def\strc_notations_command_yes[#optional]% + {\doifassignmentelse{#optional}\strc_notations_command_assignment\strc_notations_command_argument[#optional]} -\unexpanded\def\strc_notations_command_assignment[#1]% - {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1][]% +\unexpanded\def\strc_notations_command_assignment[#settings]% + {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#settings][]% \csname\??constructionnotehandler\currentconstructionhandler\endcsname \strc_constructions_finalize \normalexpanded{\endgroup\noteparameter\c!next}} -\unexpanded\def\strc_notations_command_argument[#1]#2% - {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]% +\unexpanded\def\strc_notations_command_argument[#reference]#title% + {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=][]% \csname\??constructionnotehandler\currentconstructionhandler\endcsname \strc_constructions_finalize \normalexpanded{\endgroup\noteparameter\c!next}} -\unexpanded\def\strc_notations_start#1#2% +\unexpanded\def\strc_notations_start#tag#stoptag% {\begingroup - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% \strc_notes_synchronize \ifnotesenabled \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel \fi \normalexpanded % not that efficient but also not that frequently used - {\def\noexpand\strc_pickup_yes[##1]##2\csname\e!stop#2\endcsname{\strc_notations_command_yes[##1]{##2}}% - \def\noexpand\strc_pickup_nop ##1\csname\e!stop#2\endcsname{\strc_notations_command_nop {##1}}}% + {\def\noexpand\strc_pickup_yes[##1]##2\csname\e!stop#stoptag\endcsname{\strc_notations_command_yes[##1]{##2}}% + \def\noexpand\strc_pickup_nop ##1\csname\e!stop#stoptag\endcsname{\strc_notations_command_nop {##1}}}% \doifnextoptionalelse\strc_pickup_yes\strc_pickup_nop} -\unexpanded\def\strc_notations_start_yes[#1]#2% - {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]% +\unexpanded\def\strc_notations_start_yes[#reference]#title% + {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=][]% \csname\??constructionnotehandler\currentconstructionhandler\endcsname \strc_constructions_finalize \normalexpanded{\endgroup\noteparameter\c!next}} -\unexpanded\def\strc_notations_start_nop#1% - {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]% +\unexpanded\def\strc_notations_start_nop#title% + {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=][]% \csname\??constructionnotehandler\currentconstructionhandler\endcsname \strc_constructions_finalize \normalexpanded{\endgroup\noteparameter\c!next}} @@ -296,10 +287,10 @@ %D level of indirectness. This way notations don't bark on undefined %D macros when used in combination. -\setvalue{\??constructionnotehandler\v!notation}% +\unexpanded\setvalue{\??constructionnotehandler\v!notation}% {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname} -\setvalue{\??constructionnotehandler\v!notation:}% empty case +\unexpanded\setvalue{\??constructionnotehandler\v!notation:}% empty case {[\currentconstructionhandler:\currentconstruction]} %D Here is a simple renderer for notes @@ -371,51 +362,65 @@ %D Insertions are part of notes. -\installcorenamespace{noteinsertion} - -\def\currentnoteins{\csname\??noteinsertion\currentnote\endcsname} +% \installcorenamespace{noteinsertion} + +\def\currentnoteinsertion {\noteparameter\s!insert} +\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}} + +% \appendtoks +% \doifinsertionelse\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 +% \ctxcommand{definenote("\currentnote","insert",\number\currentnoteinsertionnumber)}% +% \ifx\currentnoteparent\empty +% \definenotation[\currentnote][\c!type=\v!note]% +% \else +% \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]% +% \fi +% \to \everydefinenote \appendtoks - \ifcsname\??noteinsertion\currentnote\endcsname\else - \expandafter\installinsertion\csname\??noteinsertion\currentnote\endcsname\relax - \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}% - \fi - \ctxlua{structures.notes.define("\currentnote","insert",\number\currentnoteins)}% \ifx\currentnoteparent\empty + \doifinsertionelse\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 + \ctxcommand{definenote("\currentnote","insert",\number\currentnoteinsertionnumber)}% \to \everydefinenote -% maybe we will share this at some point - -%%%%%%%%%%% BEGIN TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%% +% maybe we will share this at some point: \newtoks\everysetupnotecounter \let\v_strc_note_counter_name\empty -\def\strc_notes_setup_counter#1% - {\edef\v_strc_note_counter_name{#1}% only used in the token list +\def\strc_notes_setup_counter#tag% + {\edef\v_strc_note_counter_name{#tag}% only used in the token list \the\everysetupnotecounter} -\def\strc_notes_define_counter#1% todo: fast inheritance (was mainparameter - {\definecounter[#1]% - \strc_notes_setup_counter{#1}} +\def\strc_notes_define_counter#tag% todo: fast inheritance (was mainparameter + {\definecounter[#tag]% + \strc_notes_setup_counter{#tag}} \appendtoks \strc_counter_setup_using_parameter\v_strc_note_counter_name\notationparameter \to \everysetupnotecounter \appendtoks - \strc_notes_setup_counter\currentnotation + \ifx\currentnotation\empty \else + \strc_notes_setup_counter\currentnotation + \fi \to \everysetupnotation -%%%%%%%%%%% END TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%% - -% \setvalue{\??constructionstarthandler\v!notation}% -% {\csname\??constructionstarthandler\v!construction\endcsname} +% 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 @@ -423,35 +428,42 @@ \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 -\setvalue{\??constructionmainhandler\v!notation}#1% +\unexpanded\setvalue{\??constructionmainhandler\v!notation}#following% {\iftrialtypesetting \else \begingroup \currentconstructionsynchronize \attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text \signalcharacter \endgroup - \fi#1} + \fi#following} -\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text +\unexpanded\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text {\ifnotesenabled - \let\currentnote\currentconstructionmain % do be done elsewhere + % do be done elsewhere + % + %let\currentnote\currentconstructionmain + \let\currentnote\currentconstruction % else wrong inheritance + % \iftrialtypesetting \strc_notes_inject_dummy \else \begingroup - \edef\currentnotenumber{\ctxlua{structures.notes.store("\currentnote",\currentconstructionlistentry)}}% + \edef\currentnotenumber{\ctxcommand{storenote("\currentnote",\currentconstructionlistentry)}}% \settrue\processingnote \ifconditional\c_strc_notes_skip - \globallet\lastnotesymbol\strc_notes_inject_symbol + \globallet\lastnotesymbol\strc_notes_inject_symbol_nop + \ifconditional\c_strc_notes_delayed + \strc_notes_inject_symbol_snc + \fi \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 + \strc_notes_inject_symbol_yes \else \unskip\unskip - \globallet\lastnotesymbol\strc_notes_inject_symbol + \globallet\lastnotesymbol\strc_notes_inject_symbol_yes \fi \fi \ifconditional\postponingnotes % todo: per note class @@ -514,7 +526,7 @@ \endcsname} \setvalue{\??noteinteractioninline\v!yes}% - {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getnumberpage("\currentnote",\currentnotenumber)})}% + {\strc_references_get_simple_page_reference{page(\ctxcommand{notenumberpage("\currentnote",\currentnotenumber)})}% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% \let \strc_notes_set_style_color_inline \strc_notes_set_style_color_inline_yes} @@ -531,8 +543,10 @@ \expandafter\let\csname\??noteinteractioninline\v!number\expandafter\endcsname\csname\??noteinteractioninline\v!yes\endcsname \expandafter\let\csname\??noteinteractioninline\v!text \expandafter\endcsname\csname\??noteinteractioninline\v!yes\endcsname +% page(...) : we could have a dedicated one + \setvalue{\??noteinteractiondisplay\v!yes}% - {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}% + {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\currentnote",\currentnotenumber)})}% \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}% \let \strc_notes_set_reference_attribute_text \donothing \let \strc_notes_set_destination_attribute_text\donothing @@ -545,7 +559,7 @@ \let\strc_notes_set_style_color_display \strc_notes_set_style_color_display_nop} \setvalue{\??noteinteractiondisplay\v!all}% - {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}% + {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\currentnote",\currentnotenumber)})}% \edef\strc_notes_set_reference_attribute_text {\attribute\referenceattribute\currentreferenceattribute}% %\strc_references_set_simple_page_reference{note:\cldcontext{structures.notes.internalid("\currentnote",\currentnotenumber)}}% \strc_references_set_simple_page_reference{note:\currentnote:\currentnotenumber}% @@ -554,7 +568,7 @@ \let \strc_notes_set_style_color_display \strc_notes_set_style_color_display_yes} \setvalue{\??noteinteractiondisplay\v!text}% - {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}% + {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\currentnote",\currentnotenumber)})}% \edef\strc_notes_set_reference_attribute_text {\attribute\referenceattribute\currentreferenceattribute}% %\strc_references_set_simple_page_reference{note:\cldcontext{structures.notes.internalid("\currentnote",\currentnotenumber)}}% \strc_references_set_simple_page_reference{note:\currentnote:\currentnotenumber}% @@ -567,19 +581,19 @@ \let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor \let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor -\unexpanded\def\strc_notes_set_style_color_inline_yes#1#2% - {\usenotestyleandcolor#1#2% +\unexpanded\def\strc_notes_set_style_color_inline_yes#style#color% + {\usenotestyleandcolor#style#color% \iflocation\strc_notes_set_style_color_special\fi} -\unexpanded\def\strc_notes_set_style_color_display_yes#1#2% - {\usenotationstyleandcolor#1#2% +\unexpanded\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 \else\ifx\currentcolorparameter\empty - \scratchcounter\ctxlua{structures.notes.deltapage("\currentnote",\currentnotenumber)}\relax % todo calculate once + \scratchcounter\ctxcommand{notedeltapage("\currentnote",\currentnotenumber)}\relax % todo calculate once \setlocationcolorspecified\scratchcounter \fi\fi} @@ -598,7 +612,7 @@ % in mkii the pointer only showed up in pagewise notes \unexpanded\def\strc_notes_inject_pointer % todo calculate once - {\ifcase\ctxlua{structures.notes.deltapage("\currentnote",\currentnotenumber)}\relax + {\ifcase\ctxcommand{notedeltapage("\currentnote",\currentnotenumber)}\relax % unknown \or % same page @@ -610,10 +624,19 @@ \unexpanded\def\strc_notes_register_note_page % called more often than needed {\iftrialtypesetting \else - \normalexpanded{\noexpand\ctxlatelua{structures.notes.setsymbolpage("\currentnote",\currentnotenumber)}}% + \normalexpanded{\noexpand\ctxlatecommand{setnotesymbolpage("\currentnote",\currentnotenumber)}}% \fi} -\unexpanded\def\strc_notes_inject_symbol +\unexpanded\def\strc_notes_inject_symbol_yes + {\strc_notes_inject_symbol_indeed\conditionaltrue} + +\unexpanded\def\strc_notes_inject_symbol_nop + {\strc_notes_inject_symbol_indeed\conditionalfalse} + +\unexpanded\def\strc_notes_inject_symbol_snc + {\currentconstructionsynchronize} % this flushes the data to the list + +\unexpanded\def\strc_notes_inject_symbol_indeed#synchronize% {\removeunwantedspaces \doifitalicelse\/\donothing % Charles IV \footnote{the fourth} \ifdim\lastkern=\notesignal @@ -622,7 +645,9 @@ \fi \nobreak \begingroup - \currentconstructionsynchronize % this flushes the data to the list + \ifconditional#synchronize\relax + \strc_notes_inject_symbol_snc % this flushes the data to the list + \fi \strc_notes_register_note_page % this registers the symbol page number (late) \strc_notes_interaction_check_inline \strc_notes_set_style_color_inline\c!textstyle\c!textcolor @@ -646,7 +671,7 @@ \strc_notes_inject_separator \fi \nobreak - \hbox to .5em{}% + \hbox to .5\emwidth{}% \globallet\lastnotesymbol\relax} \unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list @@ -751,8 +776,8 @@ \let\strc_notes_process_list\gobbleoneargument -\unexpanded\def\strc_notes_process#1% argument is a \macro that uses \currentnote - {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#1}% +\unexpanded\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 @@ -805,8 +830,8 @@ {\letcurrentnoterulecommand\relax % so we default to nothing \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step} -\def\strc_notes_set_rule_step#1% - {\csname\??noterule\ifcsname\??noterule#1\endcsname#1\else\s!unknown\fi\endcsname} +\def\strc_notes_set_rule_step#alternative% + {\csname\??noterule\ifcsname\??noterule#alternative\endcsname#alternative\else\s!unknown\fi\endcsname} \setvalue{\??noterule\v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand} \setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal} @@ -857,7 +882,7 @@ \ifx\p_factor\empty \else \ifnum\p_factor<\zerocount \else % \global - \count\currentnoteins\p_factor % new: global + \count\currentnoteinsertionnumber\p_factor % new: global \fi \fi} @@ -869,50 +894,81 @@ \installcorenamespace{notelocationvariant} \installcorenamespace{notepositionvariant} -\installcorenamespace{notedelayed} +\installcorenamespace{notedelayedvariant} \installcorenamespace{notelocation} \newconditional\c_strc_notes_delayed -\setvalue{\??notelocation\v!page }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page} -\setvalue{\??notelocation\v!columns }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns} -\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn} -\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn} -\setvalue{\??notelocation\v!none }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none} -\setvalue{\??notelocation\v!text }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text} +\unexpanded\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed} +\unexpanded\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} -\letvalue{\??notedelayed\v!page }\setfalse -\letvalue{\??notedelayed\v!columns }\setfalse -\letvalue{\??notedelayed\v!lastcolumn }\setfalse -\letvalue{\??notedelayed\v!firstcolumn }\setfalse -\letvalue{\??notedelayed\v!none }\settrue -\letvalue{\??notedelayed\v!text }\settrue +\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 \unexpanded\def\strc_notes_set_delayed - {\ifcsname\??notedelayed\currentnote\endcsname - \csname\??notedelayed\currentnote\endcsname\c_strc_notes_delayed - \else - \setfalse\c_strc_notes_delayed - \fi} + {\csname\??notedelayedvariant + \ifcsname\??notedelayedvariant\currentnote\endcsname + \currentnote + \else + \??notedelayedvariant + \fi + \endcsname} + +% \let\strc_notes_set_delayed_yes\truecondition +% \let\strc_notes_set_delayed_nop\falsecondition +% +% \def\c_strc_notes_delayed +% {\csname\??notedelayedvariant +% \ifcsname\??notedelayedvariant\currentnote\endcsname +% \currentnote +% \else +% \??notedelayedvariant +% \fi +% \endcsname} + +\unexpanded\def\strc_notes_set_position + {\csname\??notepositionvariant + \ifcsname\??notepositionvariant\currentnote\endcsname + \currentnote + \else + \??notepositionvariant + \fi + \endcsname} \unexpanded\def\strc_notes_set_location - {\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page - \letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom - \setfalse\c_strc_notes_delayed - \normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}} - -\unexpanded\def\strc_notes_set_location_step#1% - {\ifcsname\??notelocation#1\endcsname - \csname\??notelocation#1\endcsname - \fi - \ifcsname\??notedelayed#1\endcsname - \csname\??notedelayed#1\endcsname\c_strc_notes_delayed - \fi} + {\csname\??notelocationvariant + \ifcsname\??notelocationvariant\currentnote\endcsname + \currentnote + \else + \??notelocationvariant + \fi + \endcsname} + +\unexpanded\def\strc_notes_set_variants + {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}} + +\unexpanded\def\strc_notes_set_location_step#alternative% the insert related one + {\ifcsname\??notelocation#alternative\endcsname\csname\??notelocation#alternative\endcsname\fi} \appendtoks - \strc_notes_set_location + \strc_notes_set_variants + \strc_notes_set_delayed \to \everysynchronizenote \newskip \s_strc_notes_distance % we need to implement stretch @@ -940,9 +996,10 @@ {\setfalse\c_strc_notes_delayed \strc_notes_set_distance \strc_notes_set_columns - \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax - \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi - \global\skip \currentnoteins\s_strc_notes_distance} + \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]% + \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_columns {\setfalse\c_strc_notes_delayed @@ -951,33 +1008,38 @@ \ifnum\currentnofcolumns=\zerocount \c_strc_notes_columns\plusone \fi - \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax - \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi - \global\skip \currentnoteins\s_strc_notes_distance} + \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_firstcolumn +\def\strc_notes_set_location_somecolumn#whatcolumn% {\setfalse\c_strc_notes_delayed \strc_notes_set_distance \strc_notes_set_columns - \global\count\currentnoteins\plusthousand - \global\dimen\currentnoteins\ifnotelimit\noteparameter\c!height\else\maxdimen\fi - \global\skip \currentnoteins\s_strc_notes_distance} + \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} -\let\strc_notes_set_location_lastcolumn\strc_notes_set_location_firstcolumn +\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 - \ctxlua{structures.notes.setstate("\currentnote","store")}% - \global\dimen\currentnoteins\maxdimen - \global\count\currentnoteins\zerocount - \global\skip \currentnoteins\zeropoint} + \ctxcommand{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 - \csname\??notelocationvariant\currentnote\endcsname} + \strc_notes_set_location + \strc_notes_set_delayed} \let\strc_notes_set_position_high\relax @@ -993,8 +1055,8 @@ \newconditional\c_notes_bottom_present \def\strc_notes_check_if_bottom_present_indeed % in otr ! - {\ifvoid\currentnoteins\else - \csname\??notepositionvariant\currentnote\endcsname + {\ifvoid\currentnoteinsertionnumber\else + \strc_notes_set_position \fi} \def\strc_notes_check_if_bottom_present_step @@ -1105,39 +1167,39 @@ \newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used \newconditional\c_strc_notes_skip - \unexpanded\def\setnote [#1]{\getvalue{#1}} - \unexpanded\def\setnotetext[#1]{\global\settrue\c_strc_notes_skip\getvalue{#1}} +\unexpanded\def\setnote [#tag]{\getvalue{#tag}} +\unexpanded\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\getvalue{#tag}} -\unexpanded\def\handlenoteinsert#1#2% tg, id +\unexpanded\def\handlenoteinsert#tag#id% {\begingroup - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% \strc_notes_synchronize \the\everybeforenoteinsert - \insert\currentnoteins\bgroup + \insert\currentnoteinsertionnumber\bgroup \the\everyinsidenoteinsert\relax \doprocesslocalsetups{\noteparameter\c!setups}% experimental \doifelse{\noteparameter\c!paragraph}\v!yes {\nointerlineskip \startvboxtohbox - \handlenoteitself{#1}{#2}% + \handlenoteitself{#tag}{#id}% % add some slack \stopvboxtohbox} - {\handlenoteitself{#1}{#2}}% + {\handlenoteitself{#tag}{#id}}% \egroup \the\everyafternoteinsert \endgroup} -\unexpanded\def\betweennoteitself#1% tg - {\edef\currentnote{#1}% +\unexpanded\def\betweennoteitself#tag% + {\edef\currentnote{#tag}% \doif{\noteparameter\c!paragraph}\v!yes\strc_notes_between_paragraphs} -\unexpanded\def\handlenoteitself#1#2% tg, id - {\edef\currentnotenumber{#2}% - \edef\currentnote{#1}% - \strc_constructions_initialize{#1}% +\unexpanded\def\handlenoteitself#tag#id% + {\edef\currentnotenumber{#id}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% \strc_notes_synchronize - \edef\currentconstructionlistentry{\ctxlua{tex.write(structures.notes.listindex("#1",#2))}}% index in list cache + \edef\currentconstructionlistentry{\ctxcommand{notelistindex("\currentnote",#id)}}% index in list cache % as we can have collected notes (e.g. in tables) we need to recover % \currentdescriptionattribute and \currentdescriptionsynchronize % @@ -1157,7 +1219,7 @@ % \endgroup } -\unexpanded\def\strc_notes_inject_text +\unexpanded\def\strc_notes_inject_text % hm main? {\ctxcommand{savedlisttitle("\currentconstructionmain",\currentconstructionlistentry)}} \let\startpushnote\relax @@ -1216,14 +1278,14 @@ \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\currentnoteins>\zeropoint % or a faster delayed test + \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test \strc_notes_place_inserts_indeed \fi \fi} \def\strc_notes_place_inserts_indeed {\relax - \ifdim\ht\currentnoteins>\zeropoint + \ifdim\ht\currentnoteinsertionnumber>\zeropoint \endgraf \ifvmode \whitespace @@ -1271,13 +1333,11 @@ \fi} \def\strc_notes_flush_inserts_normal - {%\iftrialtypesetting\copy\else\box\fi\currentnoteins - \strc_notes_flush_global + {\strc_notes_flush_global \obeydepth} % (a) added , since split footnotes will not align properly \def\strc_notes_flush_inserts_columns {\startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% - %\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % compare with local \strc_notes_flush_global \stopsimplecolumns} @@ -1293,18 +1353,15 @@ {\doifelse{\noteparameter\c!paragraph}\v!yes {\vbox {\beginofshapebox - \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins + \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber \endofshapebox - %\doreshapebox{\box\shapebox}{}{}{}% get rid of penalties etc \let\strc_notes_between_paragraphs_indeed\strc_notes_between_paragraphs_first % shape works reverse \doreshapebox {\hbox{\unhbox\shapebox\strc_notes_between_paragraphs_indeed}} - {}% - {}% - {}% get rid of penalties etc + \donothing \donothing \donothing % get rid of penalties etc \innerflushshapebox \convertvboxtohbox}} - {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}} + {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}} %D Supporting end notes is surprisingly easy. Even better, we %D can combine this feature with solving the common \TEX\ @@ -1338,21 +1395,21 @@ % we need a proper state: normal, postponing, flushing -\def\postponenotes +\unexpanded\def\postponenotes {\ifconditional\postponingnotes\else \global\settrue\postponingnotes \global\let\flushnotes\doflushnotes - \ctxlua{structures.notes.postpone()}% + \ctxcommand{postponenotes()}% \fi} \let\flushnotes\relax -\def\doflushnotes +\unexpanded\def\doflushnotes {\ifconditional\postponingnotes \begingroup \let\flushnotes \relax \let\postponenotes\relax - \ctxlua{structures.notes.flushpostponed()}% this also resets the states ! + \ctxcommand{flushpostponednotes()}% this also resets the states ! \global\setfalse\postponednote \global\setfalse\postponingnotes \global\let\flushnotes\relax @@ -1382,8 +1439,8 @@ \unexpanded\def\startlocalnotes {\dosingleempty\strc_notes_local_start} -\def\strc_notes_local_start[#1]% - {\def\localnoteslist{#1}% +\def\strc_notes_local_start[#list]% grouping ? (we used to have a second argument ... settings) + {\def\localnoteslist{#list}% \settrue\inlocalnotes \processcommacommand[\localnoteslist]\strc_notes_local_start_step} @@ -1391,29 +1448,35 @@ {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step \setfalse\inlocalnotes} -\def\strc_notes_local_start_step#1% - {\doifnot{\noteparameter\c!continue}\v!yes - {\strc_counters_save{#1}% - \strc_counters_reset{#1}}% - \ctxlua{structures.notes.save("#1","store")}} +\let\p_strc_notes_continue\empty -\def\strc_notes_local_stop_step#1% - {\doifnot{\noteparameter\c!continue}\v!yes - {\strc_counters_restore{#1}}% - \ctxlua{structures.notes.restore("#1")}} +\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 + \ctxcommand{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 + \ctxcommand{restorenote("#tag")}} \unexpanded\def\placelocalnotes {\dodoubleempty\strc_notes_local_place} -\def\strc_notes_local_place[#1][#2]% - {\doif{\ctxlua{structures.notes.getstate("#1")}}{store}{\strc_notes_local_place_indeed{#2}{#1}}} +\def\strc_notes_local_place[#tag][#settings]% + {\doif{\ctxcommand{getnotestate("#tag")}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}} -\def\strc_notes_local_place_indeed#1#2% settings note +\def\strc_notes_local_place_indeed#settings#tag% {\begingroup - \edef\currentnote{#2}% is already set? + \edef\currentnote{#tag}% is already set? \the\everyplacelocalnotes % beware, we cannot trust setting \currentnote here - \setupcurrentnote[\c!width=\v!fit,\c!height=\v!fit,\c!strut=\v!no,\c!offset=\v!overlay,#1]% we only need a selective one + \setupcurrentnote[#settings]% later we set height etc for framed \strc_notes_place_local_alternative \strc_notes_set_properties % restore globals (if needed) \endgroup @@ -1460,19 +1523,19 @@ \unexpanded\def\placenotes {\dodoubleempty\strc_notes_place} -\def\strc_notes_place[#1][#2]% - {\processcommalist[#1]{\strc_notes_place_indeed{#2}}} +\def\strc_notes_place[#list][#settings]% + {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}} -\def\strc_notes_place_indeed#1#2% settings note - {\edef\currentnote{#2}% grouping ? - \doifelse{\ctxlua{structures.notes.getstate("#2")}}{store} +\def\strc_notes_place_indeed#settings#tag% settings note + {\edef\currentnote{#tag}% grouping ? + \doifelse{\ctxcommand{getnotestate("#tag")}}{store} \strc_notes_local_place_indeed \strc_notes_global_place_indeed - {#1}{#2}} + {#settings}{#tag}} -\def\strc_notes_global_place_indeed#1#2% +\def\strc_notes_global_place_indeed#settings#tag% {\begingroup - \setupnote[#2][#1]% + \setupnote[#tag][#settings]% \strc_notes_place_inserts \endgroup \the\everysetupnote} % to be checked .. synchronize @@ -1481,11 +1544,11 @@ \installcorenamespace{notealternative} -\unexpanded\def\installnotealternative#1#2% - {\setvalue{\??notealternative#1}{#2}} +\unexpanded\def\installnotealternative#alternative#command% + {\setvalue{\??notealternative#alternative}{#command}} -\unexpanded\def\doifnotescollected#1% - {\ctxlua{structures.notes.doifcontent("#1")}} +\unexpanded\def\doifnotescollected#tag% + {\ctxcommand{doifnotecontent("#tag")}} \def\strc_notes_place_local_alternative % will be a setup (wrapper) {\doifnotescollected\currentnote @@ -1512,8 +1575,7 @@ % setups ? -% \def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store")}} -\def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store","\noteparameter\c!criterium")}} +\def\flushlocalnotes#tag{\ctxcommand{flushnotes("#tag","store","\noteparameter\c!criterium")}} \installnotealternative \v!none {\flushlocalnotes\currentnote} @@ -1569,58 +1631,62 @@ \strc_notes_process\strc_notes_check_presence} \def\strc_notes_check_presence - {\ifdim\ht\currentnoteins>\zeropoint + {\ifdim\ht\currentnoteinsertionnumber>\zeropoint \notespresenttrue \fi} %D \macros %D {fakenotes} - % used in page-mul + % used in page-mul + + \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi - \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\@@kln} \fi + \unexpanded\def\fakenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalclevernoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} - \unexpanded\def\fakenotes - {\ifhmode\endgraf\fi\ifvmode - \calculatetotalclevernoteheight - \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi - \fi} + \unexpanded\def\fakepagenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalpagenoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} - \unexpanded\def\fakepagenotes - {\ifhmode\endgraf\fi\ifvmode - \calculatetotalpagenoteheight - \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi - \fi} + % used in page-not but not yet ok - \newdimen\totalnoteheight + \newdimen\totalnoteheight - \def\doaddtototalnoteheight#1% - {\ifdim\ht#1>\zeropoint - \ifcase\count#1\else - % todo: divide by count - \advance\totalnoteheight\ht #1% - \advance\totalnoteheight\skip#1% - \fi - \fi} + \unexpanded\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 ! ! ! - \doaddtototalnoteheight\currentnoteins - \else - % \doaddtototalnoteheight\currentbackupnoteins - \fi} + \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 ! ! ! - \doaddtototalnoteheight\currentnoteins - \fi} + \def\docalculatetotalclevernoteheight + {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! ! + \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% + \fi} - \def\docalculatetotalpagenoteheight - {\doaddtototalnoteheight\currentnoteins} + \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} + \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 %D explictly postponing footnotes? The solution turned out to @@ -1644,7 +1710,7 @@ %D \stoptyping % \def\dosynchronizenotes -% {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi} +% {\ifvoid\currentnoteinsertionnumber\else\insert\currentnoteinsertionnumber{\unvbox\currentnoteinsertionnumber}\fi} % % \def\synchronizenotes % {\strc_notes_process\dosynchronizenotes} @@ -1679,8 +1745,19 @@ \unexpanded\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote \unexpanded\def\stoplocalfootnotes {\stoplocalnotes } -\def\strc_notes_place_footnotes [#1][#2]{\ifsecondargument\placenotes [#1][#2,\c!height=\textheight]\else\placenotes [#1]\fi} -\def\strc_notes_place_local_footnotes[#1][#2]{\ifsecondargument\placelocalnotes[#1][#2,\c!height=\textheight]\else\placelocalnotes[#1]\fi} +\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 @@ -1690,7 +1767,7 @@ %D } %D \stoptyping -\def\doifnoteonsamepageelse[#1]{\ctxlua{structures.notes.doifonsamepageasprevious("#1")}} +\def\doifnoteonsamepageelse[#tag]{\ctxcommand{doifnoteonsamepageasprevious("#tag")}} %D New trickery: @@ -1711,15 +1788,15 @@ \unexpanded\def\notesymbol {\dodoubleempty\strc_notes_symbol} -\def\strc_notes_symbol[#1][#2]% +\def\strc_notes_symbol[#tag][#reference]% {\dontleavehmode \begingroup - \edef\currentnote{#1}% + \edef\currentnote{#tag}% \usenotestyleandcolor\c!textstyle\c!textcolor \ifnotesenabled \ifsecondargument \unskip - \noteparameter\c!textcommand{\in[#2]}% command here? + \noteparameter\c!textcommand{\in[#reference]}% command here? \else \noteparameter\c!textcommand\lastnotesymbol % check if command double \fi @@ -1729,30 +1806,30 @@ \unexpanded\def\note {\dodoubleempty\strc_notes_note} -\def\strc_notes_note[#1][#2]% +\def\strc_notes_note[#tag][#reference]% {\ifsecondargument - \strc_notes_symbol[#1][#2]% + \strc_notes_symbol[#tag][#reference]% \else \secondargumenttrue - \strc_notes_symbol[\v!footnote][#1]% + \strc_notes_symbol[\v!footnote][#tag]% \fi} % will be redone if needed % -% \def\ownnotesymbol#1% #1 gets number passed -% {\executeifdefined{\??notesymbol\currentnote}\empty} +% \def\ownnotesymbol#1% #1 gets number passed +% {\executeifdefined{\??notesymbol\currentnote}\empty} % -% \unexpanded\def\setnotesymbol[#1]#2#3% -% {\prewordbreak % prevent lookback -% \setgvalue{\??notesymbol#1}{#3} -% \strc_notes_inject_symbol} +% \unexpanded\def\setnotesymbol[#1]#2#3% +% {\prewordbreak % prevent lookback +% \setgvalue{\??notesymbol#1}{#3} +% \strc_notes_inject_symbol} % -% \unexpanded\def\ownnote[#1]#2#3#4% -% {\setnotesymbol[#1]{#2}{#3}% -% \setnotetext [#1]{#4}} +% \unexpanded\def\ownnote[#1]#2#3#4% +% {\setnotesymbol[#1]{#2}{#3}% +% \setnotetext [#1]{#4}} % -% \defineconversion -% [ownnote] -% [\ownnotesymbol] +% \defineconversion +% [ownnote] +% [\ownnotesymbol] \protect \endinput diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua index 0715a9e49..b82132a00 100644 --- a/tex/context/base/strc-num.lua +++ b/tex/context/base/strc-num.lua @@ -6,12 +6,13 @@ if not modules then modules = { } end modules ['strc-num'] = { license = "see context related readme files" } --- this will be reimplemented and some more will move to the commands namespace - local format = string.format local next, type = next, type local min, max = math.min, math.max -local texcount = tex.count +local texcount, texsetcount = tex.count, tex.setcount + +-- Counters are managed here. They can have multiple levels which makes it easier to synchronize +-- them. Synchronization is sort of special anyway, as it relates to document structuring. local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -26,8 +27,23 @@ local counters = structures.counters local documents = structures.documents local variables = interfaces.variables - --- state: start stop none reset +local v_start = variables.start +local v_page = variables.page +local v_reverse = variables.reverse +local v_first = variables.first +local v_next = variables.next +local v_previous = variables.previous +local v_prev = variables.prev +local v_last = variables.last +----- v_no = variables.no +local v_backward = variables.backward +local v_forward = variables.forward +----- v_subs = variables.subs or "subs" + +-- states: start stop none reset + +-- specials are used for counters that are set and incremented in special ways, like +-- pagecounters that get this treatment in the page builder counters.specials = counters.specials or { } local counterspecials = counters.specials @@ -66,54 +82,83 @@ end job.register('structures.counters.collected', tobesaved, initializer, finalizer) -local function constructor(t,s,name,i) -- variables ? - if s == "last" then +local constructor = { -- maybe some day we will provide an installer for more variants + + last = function(t,name,i) local cc = collected[name] - t.stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only + local stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only + t.stop = stop if t.offset then - return t.stop - t.step + return stop - t.step else - return t.stop + return stop end - elseif s == "first" then - if t.start > 0 then - return t.start -- brrr + end, + + first = function(t,name,i) + local start = t.start + if start > 0 then + return start -- brrr elseif t.offset then - return t.start + t.step + 1 + return start + t.step + 1 else - return t.start + 1 + return start + 1 end - elseif s == "prev" or s == "previous" then + end, + + prev = function(t,name,i) return max(t.first,t.number-1) -- todo: step - elseif s == "next" then + end, + + previous = function(t,name,i) + return max(t.first,t.number-1) -- todo: step + end, + + next = function(t,name,i) return min(t.last,t.number+1) -- todo: step - elseif s == "backward" then + end, + + backward =function(t,name,i) if t.number - 1 < t.first then return t.last else return t.previous end - elseif s == "forward" then + end, + + forward = function(t,name,i) if t.number + 1 > t.last then return t.first else return t.next end - elseif s == "subs" then + end, + + subs = function(t,name,i) local cc = collected[name] t.subs = (cc and cc[i+1] and cc[i+1][t.range]) or 0 return t.subs - else - return nil -- was 0, but that is fuzzy in testing for e.g. own - end + end, + +} + +local function dummyconstructor(t,name,i) + return nil -- was 0, but that is fuzzy in testing for e.g. own end +setmetatableindex(constructor,function(t,k) + if trace_counters then + report_counters("unknown constructor %q",tostring(k)) + end + return dummyconstructor +end) + local function enhance() for name, cd in next, counterdata do local data = cd.data for i=1,#data do local ci = data[i] - setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) + setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end) end end enhance = nil @@ -126,7 +171,7 @@ local function allocate(name,i) -- can be metatable level = 1, -- block = "", -- todo numbers = nil, - state = variables.start, -- true + state = v_start, -- true data = { }, saved = { }, } @@ -145,7 +190,7 @@ local function allocate(name,i) -- can be metatable offset = false, stop = 0, -- via metatable: last, first, stop only for tracing } - setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) + setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end) cd[i] = ci tobesaved[name][i] = { } else @@ -164,12 +209,12 @@ local function savevalue(name,i) local cs = tobesaved[name][i] local cc = collected[name] if trace_counters then - report_counters("saving value %s of counter named %s",cd.number,name) + report_counters("saving, counter: %s, value: %s",name,cd.number) end local cr = cd.range local old = (cc and cc[i] and cc[i][cr]) or 0 local number = cd.number - if cd.method == variables.page then + if cd.method == v_page then -- we can be one page ahead number = number - 1 end @@ -186,8 +231,8 @@ function counters.define(specification) if name and name ~= "" then -- todo: step local d = allocate(name,1) - d.start = specification.start - d.state = variables.start or "" + d.start = tonumber(specification.start) or 0 + d.state = v_state or "" local counter = specification.counter if counter and counter ~= "" then d.counter = counter -- only for special purposes, cannot be false @@ -202,18 +247,15 @@ end function counters.compact(name,level,onlynumbers) local cd = counterdata[name] ---~ print(name,cd) if cd then local data = cd.data local compact = { } for i=1,level or #data do local d = data[i] ---~ print(name,i,d.number) if d.number ~= 0 then compact[i] = (onlynumbers and d.number) or d end end ---~ print(table.serialize(compact)) return compact end end @@ -246,65 +288,76 @@ function counters.subs(name,n) return counterdata[name].data[n].subs or 0 end -function counters.setvalue(name,tag,value) +local function setvalue(name,tag,value) local cd = counterdata[name] if cd then cd[tag] = value end end +counters.setvalue = setvalue + function counters.setstate(name,value) -- true/false value = variables[value] if value then - counters.setvalue(name,"state",value) + setvalue(name,"state",value) end end function counters.setlevel(name,value) - counters.setvalue(name,"level",value) + setvalue(name,"level",value) end function counters.setoffset(name,value) - counters.setvalue(name,"offset",value) + setvalue(name,"offset",value) end local function synchronize(name,d) local dc = d.counter if dc then if trace_counters then - report_counters("setting counter %s with name %s to %s",dc,name,d.number) + report_counters("synchronize, counter: %s, name: %s, value: %s, action: setting",dc,name,d.number) end - tex.setcount("global",dc,d.number) + texsetcount("global",dc,d.number) end local cs = counterspecials[name] if cs then if trace_counters then - report_counters("invoking special for name %s",name) + report_counters("synchronize, counter: %s, name: %s, action: special",dc,name) end - cs() + cs(name) end end -function counters.reset(name,n) +local function reset(name,n) local cd = counterdata[name] if cd then for i=n or 1,#cd.data do local d = cd.data[i] savevalue(name,i) - d.number = d.start or 0 + local number = d.start or 0 + d.number = number d.own = nil + if trace_counters then + report_counters("resetting, name: %s, sub: %s, value: %s",name,i,number) + end synchronize(name,d) end cd.numbers = nil + else end end -function counters.set(name,n,value) +local function set(name,n,value) local cd = counterdata[name] if cd then local d = allocate(name,n) - d.number = value or 0 + local number = value or 0 + d.number = number d.own = nil + if trace_counters then + report_counters("setting, name: %s, value: %s",name,number) + end synchronize(name,d) end end @@ -313,12 +366,19 @@ local function check(name,data,start,stop) for i=start or 1,stop or #data do local d = data[i] savevalue(name,i) - d.number = d.start or 0 + local number = d.start or 0 + d.number = number d.own = nil + if trace_counters then + report_counters("checking, name: %s, sub: %s, value: %s",name,i,number) + end synchronize(name,d) end end +counters.reset = reset +counters.set = set + function counters.setown(name,n,value) local cd = counterdata[name] if cd then @@ -328,7 +388,7 @@ function counters.setown(name,n,value) local level = cd.level if not level or level == -1 then -- -1 is signal that we reset manually - elseif level > 0 then + elseif level > 0 or level == -3 then check(name,d,n+1) elseif level == 0 then -- happens elsewhere, check this for block @@ -345,7 +405,7 @@ function counters.restart(name,n,newstart,noreset) local d = allocate(name,n) d.start = newstart if not noreset then - counters.reset(name,n) -- hm + reset(name,n) -- hm end end end @@ -367,24 +427,38 @@ end function counters.add(name,n,delta) local cd = counterdata[name] --- inspect(cd) - if cd and (cd.state == variables.start or cd.state == "") then + if cd and (cd.state == v_start or cd.state == "") then local data = cd.data local d = allocate(name,n) d.number = (d.number or d.start or 0) + delta*(d.step or 0) -- d.own = nil local level = cd.level --- print(name,n,delta,level) if not level or level == -1 then -- -1 is signal that we reset manually + if trace_counters then + report_counters("adding, name: %s, level: manually, action: no checking",name) + end elseif level == -2 then -- -2 is signal that we work per text + if trace_counters then + report_counters("adding, name: %s, level: text, action: checking",name) + end check(name,data,n+1) - elseif level > 0 then + elseif level > 0 or level == -3 then -- within countergroup + if trace_counters then + report_counters("adding, name: %s, level: %s, action: checking within group",name,level) + end check(name,data,n+1) elseif level == 0 then -- happens elsewhere + if trace_counters then + report_counters("adding, name: %s, level: %s, action: no checking",name,level) + end + else + if trace_counters then + report_counters("adding, name: %s, level: unknown, action: no checking",name) + end end synchronize(name,d) return d.number -- not needed @@ -392,19 +466,23 @@ function counters.add(name,n,delta) return 0 end -function counters.check(level) -- not used (yet) +function counters.check(level) for name, cd in next, counterdata do - -- report_counters("%s %s %s",name,cd.level,level) - if cd.level == level then + if level > 0 and cd.level == -3 then -- could become an option if trace_counters then - report_counters("resetting %s at level %s",name,level) + report_counters("resetting, name: %s, level: %s (head)",name,level) end - counters.reset(name) + reset(name) + elseif cd.level == level then + if trace_counters then + report_counters("resetting, name: %s, level: %s (normal)",name,level) + end + reset(name) end end end -function counters.get(name,n,key) +local function get(name,n,key) local d = allocate(name,n) d = d and d[key] if not d then @@ -416,8 +494,10 @@ function counters.get(name,n,key) end end +counters.get = get + function counters.value(name,n) -- what to do with own - return counters.get(name,n or 1,'number') or 0 + return get(name,n or 1,'number') or 0 end function counters.converted(name,spec) -- name can be number and reference to storage @@ -431,9 +511,8 @@ function counters.converted(name,spec) -- name can be number and reference to st if cd then local spec = spec or { } local numbers, ownnumbers = { }, { } - local reverse = spec.order == variables.reverse + local reverse = spec.order == v_reverse local kind = spec.type or "number" - local v_first, v_next, v_previous, v_last = variables.first, variables.next, variables.previous, variables.last local data = cd.data for k=1,#data do local v = data[k] @@ -446,7 +525,7 @@ function counters.converted(name,spec) -- name can be number and reference to st vn = v.first elseif kind == v_next then vn = v.next - elseif kind == v_previous then + elseif kind == v_prev or kind == v_previous then vn = v.prev elseif kind == v_last then vn = v.last @@ -498,7 +577,7 @@ function commands.showcounter(name) local data = cd.data for i=1,#data do local d = data[i] - context(" (%s: %s,%s,%s s:%s r:%s)",i,(d.start or 0),d.number or 0,d.last,d.step or 0,d.range or 0) + context(" (%s: %s,%s,%s s:%s r:%s)",i,d.start or 0,d.number or 0,d.last,d.step or 0,d.range or 0) end context("]") end @@ -543,7 +622,7 @@ end --~ return cd, false, "no section data" --~ end --~ -- local preferences ---~ local no = variables.no +--~ local no = v_no --~ if counterspecification and counterspecification.prefix == no then --~ return cd, false, "current spec blocks prefix" --~ end diff --git a/tex/context/base/strc-num.mkiv b/tex/context/base/strc-num.mkiv index 9c08693be..d8815d423 100644 --- a/tex/context/base/strc-num.mkiv +++ b/tex/context/base/strc-num.mkiv @@ -19,6 +19,7 @@ % work in progress % to be checked: can we use the command handler code here? +% all settings will move to lua \installcorenamespace{counter} @@ -31,7 +32,7 @@ % \c!prefixstopper=, \c!prefixconnector=., \c!prefixsegments=\autostructureprefixsegments\sharedcounterparameter, - \c!start=0, + \c!start=\zerocount, \c!prefix=\v!yes, \c!state=\v!start] @@ -79,9 +80,10 @@ \def\strc_counters_define_yes[#1][#2]% {\getparameters[\??counter#1][\s!counter=,#2]% counter is for internal purposes + \edef\p_start{\counterparameter{#1}\c!start}% \ctxcommand{definecounter { name = "#1", - start = tonumber("\counterparameter{#1}\c!start") or 0, + start = \ifx\p_start\empty0\else\number\p_start\fi, counter = "\counterparameter{#1}\s!counter", method = "\counterparameter{#1}\c!method", }}% @@ -94,8 +96,12 @@ \unexpanded\def\setupcounter {\dodoubleargument\strc_counters_setup} +% \def\strc_counters_setup[#1][#2]% +% {\getparameters[\??counter#1][\c!start=,#2]% hm, start +% \strc_counters_check_setup{#1}} + \def\strc_counters_setup[#1][#2]% - {\getparameters[\??counter#1][\c!start=,#2]% + {\getparameters[\??counter#1][#2]% no start here \strc_counters_check_setup{#1}} % % % % @@ -109,20 +115,6 @@ \def\thenamedcounterlevel#1% {\xthenamedheadlevel{\strc_counters_way{#1}}} -\def\xthenamedheadlevel#1% - {\xsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}} - -\def\xsectionlevel#1#2% direct indirect - {\csname\??headlevel - \ifcsname\??headlevel#1\endcsname - #1% - \else\ifcsname\??headlevel#2\endcsname - #2% - \else - \v!none - \fi\fi - \endcsname} - \def\strc_counters_check_setup#1% does it have to happen here? {% this can be done at the lua end / a bit messy here ... todo ... \ifcsname\??counter#1\c!number\endcsname @@ -133,7 +125,8 @@ % it's a clone \else \edef\currentcounterlevel{\thenamedcounterlevel{#1}}% - \ctxcommand{checkcountersetup("#1",\currentcounterlevel,"\counterparameter{#1}\c!start","\counterparameter{#1}\c!state")}% + \edef\p_start{\counterparameter{#1}\c!start}% + \ctxcommand{checkcountersetup("#1",\currentcounterlevel,\ifx\p_start\empty0\else\number\p_start\fi,"\counterparameter{#1}\c!state")}% \fi} \unexpanded\def\doifcounterelse #1{\ctxcommand{doifelsecounter("\strc_counters_the{#1}")}} @@ -507,22 +500,20 @@ % \m_strc_counters_last_registered_attribute % \m_strc_counters_last_registered_synchronize -\newconditional\hascountercaption -\newconditional\hascountertitle -\newconditional\hascounternumber +% currentstructurecomponent => \strc_current_ or just \m_strc_ \unexpanded\def\strc_counters_register_component#1#2#3#4#5#6#7[#8][#9]% maybe also nolist {\begingroup % #2[\s!haslevel=1,#8]% - \edef\hascounterlevel {#3\s!haslevel}% - \edef\hascountercaption{#3\s!hascaption}% - \edef\hascountertitle {#3\s!hastitle}% - \edef\hascounternumber {#3\s!hasnumber}% + \edef\p_haslevel {#3\s!haslevel}% + \edef\p_hascaption{#3\s!hascaption}% + \edef\p_hastitle {#3\s!hastitle}% + \edef\p_hasnumber {#3\s!hasnumber}% % - \edef\askedprefixsegments{#3\c!prefixsegments}% - \ifx\askedprefixsegments\v!auto - \edef\askedprefixsegments{\autostructureprefixsegments#3}% + \edef\p_prefixsegments{#3\c!prefixsegments}% + \ifx\p_prefixsegments\v!auto + \edef\p_prefixsegments{\autostructureprefixsegments#3}% \fi % \edef\currentname{#3\c!name}% @@ -534,7 +525,7 @@ \let\currentcounter\currentname \fi % - \ifx\hascountercaption\v!yes + \ifx\p_hascaption\v!yes \xdef\currentstructurecomponentname {#3\c!name}% \xdef\currentstructurecomponentlevel {#3\c!level}% \edef\currentstructurecomponentexpansion {#3\c!expansion}% @@ -613,7 +604,7 @@ list = \!!bs\detokenize\expandafter{\currentstructurecomponentlist}\!!es, \fi }, - \ifx\hascounternumber\v!yes + \ifx\p_hasnumber\v!yes prefixdata = { prefix = "#3\c!prefix", separatorset = "#3\c!prefixseparatorset", @@ -621,7 +612,7 @@ conversionset = "#3\c!prefixconversionset", set = "#3\c!prefixset", % segments = "#3\c!prefixsegments", - segments = "\askedprefixsegments", + segments = "\p_prefixsegments", connector = \!!bs#3\c!prefixconnector\!!es, }, numberdata = { @@ -637,7 +628,7 @@ userdata = \!!bs\detokenize{#9}\!!es % will be converted to table at the lua end } }}% - \xdef\m_strc_counters_last_registered_attribute {\ctxlua {tex.write(structures.references.setinternalreference(nil,nil,\nextinternalreference))}}% + \xdef\m_strc_counters_last_registered_attribute {\ctxcommand {setinternalreference(nil,nil,\nextinternalreference)}}% \xdef\m_strc_counters_last_registered_synchronize{\ctxlatecommand{enhancelist(\m_strc_counters_last_registered_index)}}% \else \glet\m_strc_counters_last_registered_index \relax @@ -651,9 +642,10 @@ \let\m_strc_counters_last_registered_synchronize\relax \def\strc_counter_setup_using_parameter#1#2% name \someparameter - {\setupcounter + {\edef\p_start{#2\c!start}% + \normalexpanded{\setupcounter [#1] - [ \c!start=#2\c!start, + [ \c!start=\ifx\p_start\empty0\else\number\p_start\fi, \c!state=#2\c!state, % beware, "" == start \c!way=#2\c!way, % @@ -673,7 +665,7 @@ \c!numberconversionset=#2\c!numberconversionset, \c!numberstarter=#2\c!numberstarter, \c!numberstopper=#2\c!numberstopper, - \c!numbersegments=#2\c!numbersegments]} + \c!numbersegments=#2\c!numbersegments]}} \def\strc_counter_preset_using_parameter#1#2% \setupcommand \someparameter {#1% diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua index 460d4ff00..bce965546 100644 --- a/tex/context/base/strc-pag.lua +++ b/tex/context/base/strc-pag.lua @@ -69,6 +69,9 @@ function pages.save(prefixdata,numberdata) end end +-- We can set the pagenumber but as it only get incremented in the page +-- builder we have to make sure it starts at least at 1. + function counters.specials.userpage() local r = texcount.realpageno if r > 0 then @@ -78,7 +81,16 @@ function counters.specials.userpage() if trace_pages then report_pages("forcing pagenumber of realpage %s to %s",r,t.number) end + return + end + end + local u = texcount.userpageno + if u == 0 then + if trace_pages then + report_pages("forcing pagenumber of realpage %s to %s (probably a bug)",r,1) end + counters.setvalue("userpage",1) + texcount.userpageno = 1 end end diff --git a/tex/context/base/strc-pag.mkiv b/tex/context/base/strc-pag.mkiv index e3828464c..8071fbab1 100644 --- a/tex/context/base/strc-pag.mkiv +++ b/tex/context/base/strc-pag.mkiv @@ -19,11 +19,11 @@ % Allocation: -\countdef\realpageno = 0 \realpageno = 1 -\countdef\userpageno = 1 \userpageno = 1 -\countdef\subpageno = 2 \subpageno = 0 % !! -\countdef\arrangeno = 3 \arrangeno = 0 % !! -\countdef\pagenoshift = 4 \pagenoshift = 0 % !! +\countdef\realpageno \zerocount \realpageno \plusone +\countdef\userpageno \plusone \userpageno \plusone +\countdef\subpageno \plustwo \subpageno \zerocount % ! +\countdef\arrangeno \plusthree \arrangeno \zerocount % ! +\countdef\pagenoshift\plusfour \pagenoshift\zerocount % ! \let\pageno\userpageno @@ -33,7 +33,8 @@ \newtoks\everyinitializepagecounters -\def\initializepagecounters{\the\everyinitializepagecounters} +\unexpanded\def\initializepagecounters + {\the\everyinitializepagecounters} \appendtoks \initializepagecounters @@ -71,27 +72,30 @@ % \stopbodymatter % \stoptext -\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page] -\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page] -\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page] +\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page] +\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page] +\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page] \newtoks\everysetuprealpagenumber % todo: set state: none, start, stop, reset \newtoks\everysetupuserpagenumber % todo: set state: none, start, stop, reset \newtoks\everysetupsubpagenumber % todo: set state: none, start, stop, reset -\unexpanded\def\setuprealpagenumber{\dosingleargument\dosetuprealpagenumber} -\unexpanded\def\setupuserpagenumber{\dosingleargument\dosetupuserpagenumber} -\unexpanded\def\setupsubpagenumber {\dosingleargument\dosetupsubpagenumber} +\unexpanded\def\setuprealpagenumber{\dosingleargument\strc_pagenumbers_setup_realpage} +\unexpanded\def\setupuserpagenumber{\dosingleargument\strc_pagenumbers_setup_userpage} +\unexpanded\def\setupsubpagenumber {\dosingleargument\strc_pagenumbers_setup_subpage } -\def\dosavepagenumberstate#1{\edef\oldpagenumberstate{\counterparameter#1\c!state}} +\let\m_strc_pagenumbers_state_old\zerocount +\let\m_strc_pagenumbers_state_new\zerocount -\def\dosetuprealpagenumber[#1]{\dosavepagenumberstate\s!realpage\strc_counters_setup[\s!realpage][#1]\the\everysetuprealpagenumber} -\def\dosetupuserpagenumber[#1]{\dosavepagenumberstate\s!userpage\strc_counters_setup[\s!userpage][#1]\the\everysetupuserpagenumber} -\def\dosetupsubpagenumber [#1]{\dosavepagenumberstate\s!subpage \strc_counters_setup[\s!subpage ][#1]\the\everysetupsubpagenumber } +\def\strc_pagenumbers_save_state#1{\edef\m_strc_pagenumbers_state_old\m_strc_pagenumbers_state_old{\counterparameter#1\c!state}} -\def\resetrealpagenumber {} % not permitted -\def\resetuserpagenumber {\strc_counters_reset\s!userpage} -\def\resetsubpagenumber {\strc_counters_reset\s!subpage} +\def\strc_pagenumbers_setup_realpage[#1]{\strc_pagenumbers_save_state\s!realpage\strc_counters_setup[\s!realpage][#1]\the\everysetuprealpagenumber} +\def\strc_pagenumbers_setup_userpage[#1]{\strc_pagenumbers_save_state\s!userpage\strc_counters_setup[\s!userpage][#1]\the\everysetupuserpagenumber} +\def\strc_pagenumbers_setup_subpage [#1]{\strc_pagenumbers_save_state\s!subpage \strc_counters_setup[\s!subpage ][#1]\the\everysetupsubpagenumber } + +\unexpanded\def\resetrealpagenumber {} % not permitted +\unexpanded\def\resetuserpagenumber {\strc_counters_reset\s!userpage} +\unexpanded\def\resetsubpagenumber {\strc_counters_reset\s!subpage} \appendtoks \strc_counters_set\s!realpage\realpageno @@ -102,7 +106,7 @@ \let\setuppagenumber\setupuserpagenumber \let\resetpagenumber\resetuserpagenumber -\def\savecurrentpagestate % \normalexpanded? +\def\strc_pagenumbers_page_state_save % \normalexpanded? {\ctxlua{structures.pages.save({ prefix = "\counterparameter\s!userpage\c!prefix", separatorset = "\counterparameter\s!userpage\c!prefixseparatorset", @@ -120,11 +124,13 @@ )}} \prependtoks - \savecurrentpagestate + \strc_pagenumbers_page_state_save \to \everyshipout -\def\pushpagestate{\setxvalue{\??nm:\s!userpage:\c!state}{\counterparameter\s!userpage\c!state}} -\def\poppagestate {\normalexpanded{\setuppagenumber[\c!state=\getvalue{\??nm:\s!userpage:\c!state}]}} +\installcorenamespace{pagestatestack} % no level yet + +\unexpanded\def\strc_pagenumbers_page_state_push{\setxvalue{\??pagestatestack\c!state}{\counterparameter\s!userpage\c!state}} +\unexpanded\def\strc_pagenumbers_page_state_pop {\normalexpanded{\setuppagenumber[\c!state=\getvalue{\??pagestatestack\c!state}]}} \setuppagenumber [\c!way=\v!by\v!text, @@ -207,17 +213,17 @@ \def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next} \def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next} -\def\dodeincrementpageboundcounters % only at the end +\unexpanded\def\strc_pagenumbers_decrement_counters % only at the end {\strc_counters_decrement\s!realpage \strc_counters_decrement\s!userpage \strc_counters_decrement\s!subpage} -\def\doincrementpageboundcounters +\unexpanded\def\strc_pagenumbers_increment_counters {\incrementpagenumber \incrementsubpagenumber} \appendtoks - \dodeincrementpageboundcounters + \strc_pagenumbers_decrement_counters \to \everygoodbye % Equivalents (compatibility): @@ -238,61 +244,49 @@ % States: -\newif\ifrightpage \rightpagetrue \newif\ifdoublesided \newconditional\layoutisdoublesided \newif\ifsinglesided \newconditional\layoutissinglesided % Realpage and subpage numbers: -\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax} -\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax} +\unexpanded\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax} +\unexpanded\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax} % Page numbers: (can move to lua) ... inconsistent names -\def\dodecrementpagenumber {\global\userpageno\strc_counters_decremented\s!userpage\relax} -\def\doincrementpagenumber {\global\userpageno\strc_counters_incremented\s!userpage\relax} +\installcorenamespace{pagenumberinc} +\installcorenamespace{pagenumberdec} -\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax} -\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax} +\unexpanded\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax} +\unexpanded\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax} -\def\dosynchronizepagenumber{\global\let\@@pnstate\v!start} +\unexpanded\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax} +\unexpanded\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax} -\def\decrementpagenumber{\csname\??pn-\counterparameter\s!userpage\c!state\endcsname} -\def\incrementpagenumber{\csname\??pn+\counterparameter\s!userpage\c!state\endcsname} +\unexpanded\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible -\letvalue{\??pn-\v!start}\dodecrementpagenumber -\letvalue{\??pn-\v!none }\dodecrementpagenumber -\letvalue{\??pn-\v!empty}\dodecrementpagenumber +\unexpanded\def\decrementpagenumber{\csname\??pagenumberdec\counterparameter\s!userpage\c!state\endcsname} +\unexpanded\def\incrementpagenumber{\csname\??pagenumberinc\counterparameter\s!userpage\c!state\endcsname} -\letvalue{\??pn+\v!start}\doincrementpagenumber -\letvalue{\??pn+\v!none }\doincrementpagenumber -\setvalue{\??pn+\v!empty}{\doincrementpagenumber\dosynchronizepagenumber} -\letvalue{\??pn+\v!keep }\dosynchronizepagenumber +\letvalue{\??pagenumberdec\v!start}\strc_pagenumbers_decrement_userpage +\letvalue{\??pagenumberdec\v!none }\strc_pagenumbers_decrement_userpage +\letvalue{\??pagenumberdec\v!empty}\strc_pagenumbers_decrement_userpage -% Control: - -\def\getpagestatus % hierboven gebruiken - {\ifdoublesided - \global\rightpagetrue - % todo: \global\rightpagetrue or \global\rightpagefalse - \else - \global\rightpagetrue - \fi} +\letvalue{\??pagenumberinc\v!start}\strc_pagenumbers_increment_userpage +\letvalue{\??pagenumberinc\v!none }\strc_pagenumbers_increment_userpage +\setvalue{\??pagenumberinc\v!empty}{\strc_pagenumbers_increment_userpage\strc_pagenumbers_synchronize_userpage} +\letvalue{\??pagenumberinc\v!keep }\strc_pagenumbers_synchronize_userpage % Setup general page numbering -\newtoks\everysetuppagenumbering +\installcorenamespace{pagenumbering} -\unexpanded\def\setuppagenumbering - {\dosingleempty\dosetuppagenumbering} - -\def\dosetuppagenumbering[#1]% - {\getparameters[\??nm][#1]\the\everysetuppagenumbering} +\installdirectcommandhandler \??pagenumbering {pagenumbering} \appendtoks \singlesidedfalse \setfalse\layoutisdoublesided \doublesidedfalse \setfalse\layoutissinglesided - \normalexpanded{\noexpand\processallactionsinset[\@@nmalternative]} + \processallactionsinset[\directpagenumberingparameter\c!alternative] [ \v!singlesided=>\singlesidedtrue\settrue\layoutissinglesided, \v!doublesided=>\doublesidedtrue\settrue\layoutisdoublesided]% \ifdefined\trackingmarginnotestrue @@ -303,19 +297,24 @@ \fi \fi \page_backgrounds_recalculate - \dosetpagenumberlocation + \strc_pagenumbers_set_location \to \everysetuppagenumbering \ifdefined \page_backgrounds_recalculate \else \let\page_backgrounds_recalculate\relax \fi -\ifdefined \dosetpagenumberlocation \else - \let\dosetpagenumberlocation\relax +\ifdefined \strc_pagenumbers_set_location \else + \let\strc_pagenumbers_set_location\relax \fi -\def\flushfinallayoutpage - {\doifsomething\@@nmpage{\doifnot\@@nmpage\v!no{\page[\@@nmpage]}}} +\unexpanded\def\strc_pagenumbers_flush_final_page + {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}% + \ifx\p_strc_pagenumbers_page\empty \else + \ifx\p_strc_pagenumbers_page\v!no \else + \page[\p_strc_pagenumbers_page] + \fi + \fi} % The numbered location handler is there because we need to be downward % compatible. So, in fact there can be multiple handlers active at the @@ -323,28 +322,32 @@ % Rendering: -\unexpanded\def\placelocationpagenumber - {\ifnum\userpagenumberstate=\plustwo - \ifnum\overallpagenumberstate=\plusone - \doif\@@nmstrut\v!yes\strut +\unexpanded\def\strc_pagenumbers_place_location + {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo + \ifnum\c_strc_pagenumbers_state=\plusone + \doif{\directpagenumberingparameter\c!strut}\v!yes\strut \begingroup - \dousestyleparameter\@@nmstyle - \dousecolorparameter\@@nmcolor - \@@nmcommand{\@@nmleft\labeltexts\v!pagenumber{\prefixedpagenumber}\@@nmright}% + \usepagenumberingstyleandcolor\c!style\c!color + \directpagenumberingparameter\c!command + {\directpagenumberingparameter\c!left + \labeltexts\v!pagenumber\prefixedpagenumber + \directpagenumberingparameter\c!right}% \endgroup \fi \fi} \unexpanded\def\completepagenumber - {\ifnum\userpagenumberstate=\plustwo - \ifnum\overallpagenumberstate=\plusone - \@@nmleft\labeltexts\v!pagenumber\prefixedpagenumber\@@nmright + {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo + \ifnum\c_strc_pagenumbers_state=\plusone + \directpagenumberingparameter\c!left + \labeltexts\v!pagenumber\prefixedpagenumber + \directpagenumberingparameter\c!right \fi \fi} \unexpanded\def\placepagenumber - {\ifnum\userpagenumberstate=\plustwo - \ifnum\overallpagenumberstate=\plusone + {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo + \ifnum\c_strc_pagenumbers_state=\plusone \labeltexts\v!pagenumber\pagenumber \fi \fi} @@ -356,35 +359,35 @@ % compatible. So, in fact there can be multiple handlers active at the % same time, but only the current one does something. -\setnewconstant\realpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible -\setnewconstant\userpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible -\setnewconstant\subpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible -\setnewconstant\overallpagenumberstate\plusone % general number: 0=invisible, 1=visible +\setnewconstant\c_strc_pagenumbers_state_realpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible +\setnewconstant\c_strc_pagenumbers_state_userpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible +\setnewconstant\c_strc_pagenumbers_state_subpage \plustwo % counter state : 0=stop, 1=start, 2=start and visible +\setnewconstant\c_strc_pagenumbers_state \plusone % general number: 0=invisible, 1=visible -\def\checkpagenumberstatechange#1#2% - {\edef\newpagenumberstate{\counterparameter#1\c!state}% - \ifx\newpagenumberstate\oldpagenumberstate \else - \doifelse\newpagenumberstate\v!start +\unexpanded\def\strc_pagenumbers_check_state_change#1#2% + {\edef\m_strc_pagenumbers_state_new{\counterparameter#1\c!state}% + \ifx\m_strc_pagenumbers_state_new\m_strc_pagenumbers_state_old \else + \doifelse\m_strc_pagenumbers_state_new\v!start {#2\plustwo}% {#2\zerocount}% \fi} \appendtoks % todo: set state: none, start, stop, reset - \checkpagenumberstatechange\s!realpage\realpagenumberstate + \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage \to \everysetuprealpagenumber \appendtoks % todo: set state: none, start, stop, reset - \checkpagenumberstatechange\s!userpage\userpagenumberstate + \strc_pagenumbers_check_state_change\s!userpage\c_strc_pagenumbers_state_userpage \to \everysetupuserpagenumber \appendtoks % todo: set state: none, start, stop, reset - \checkpagenumberstatechange\s!subpage\subpagenumberstate + \strc_pagenumbers_check_state_change\s!subpage\c_strc_pagenumbers_state_subpage \to \everysetupsubpagenumber \appendtoks % todo: set state: none, start, stop, reset - \doifelse\@@nmstate\v!start - {\overallpagenumberstate\plusone }% - {\overallpagenumberstate\zerocount}% + \doifelse{\directpagenumberingparameter\c!state}\v!start + {\c_strc_pagenumbers_state\plusone }% + {\c_strc_pagenumbers_state\zerocount}% \to \everysetuppagenumbering % Done @@ -415,7 +418,7 @@ \appendtoks \edef\askeduserpagenumber{\counterparameter\s!userpage\c!number}% \ifx\askeduserpagenumber\empty \else - \normalexpanded{\setuppagenumber[\c!start=\counterparameter\s!userpage\c!number,\c!number=]}% + \normalexpanded{\setuppagenumber[\c!start=\askeduserpagenumber,\c!number=]}% \userpageno\strc_counters_raw\s!userpage \fi \to \everysetupuserpagenumber % todo: set state: none, start, stop, reset @@ -423,7 +426,7 @@ \appendtoks \edef\askedsubpagenumber{\counterparameter\s!subpage\c!number}% \ifx\askedsubpagenumber\empty \else - \normalexpanded{\setupsubpagenumber[\c!start=\counterparameter\s!subpage\c!number,\c!number=]}% + \normalexpanded{\setupsubpagenumber[\c!start=\askedsubpagenumber,\c!number=]}% \subpageno\strc_counters_raw\s!subpage\relax \fi \to \everysetupsubpagenumber % todo: set state: none, start, stop, reset @@ -433,7 +436,7 @@ % \setupuserpagenumber[start=2] % \starttext \dorecurse{20}{\input knuth \par} \stoptext -\def\checkpagenumbershift +\unexpanded\def\strc_pagenumbers_check_change_shift {\userpageno\strc_counters_raw\s!userpage\relax \ifnum\realpageno=\plusone \ifodd\userpageno @@ -444,12 +447,12 @@ \appendtoks % todo: set state: none, start, stop, reset % this makes starting at an even page possible - \checkpagenumbershift + \strc_pagenumbers_check_change_shift \to \everysetupuserpagenumber \appendtoks % todo: set state: none, start, stop, reset % this makes starting at an even page possible - \checkpagenumbershift + \strc_pagenumbers_check_change_shift \to \everysetuppagenumbering \initializepagecounters diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index 092babfae..ab2d366cc 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -29,6 +29,12 @@ local trace_analyzing = false trackers.register("structures.referencing.anal local trace_identifying = false trackers.register("structures.referencing.identifying", function(v) trace_identifying = v end) local trace_importing = false trackers.register("structures.referencing.importing", function(v) trace_importing = v end) +local check_duplicates = true + +directives.register("structures.referencing.checkduplicates", function(v) + check_duplicates = v +end) + local report_references = logs.reporter("references") local report_unknown = logs.reporter("unknown") local report_identifying = logs.reporter("references","identifying") @@ -38,6 +44,12 @@ local variables = interfaces.variables local constants = interfaces.constants local context = context +local v_default = variables.default +local v_url = variables.url +local v_file = variables.file +local v_unknown = variables.unknown +local v_yes = variables.yes + local texcount = tex.count local texconditionals = tex.conditionals @@ -237,11 +249,13 @@ references.setnextorder = setnextorder function references.setnextinternal(kind,name) setnextorder(kind,name) -- always incremented with internal - texsetcount("global","locationcount",texcount.locationcount + 1) + local n = texcount.locationcount + 1 + texsetcount("global","locationcount",n) + return n end function references.currentorder(kind,name) - context(orders[kind] and orders[kind][name] or lastorder) + return orders[kind] and orders[kind][name] or lastorder end local function setcomponent(data) @@ -257,6 +271,12 @@ local function setcomponent(data) -- but for the moment we do it here (experiment) end +commands.setnextinternalreference = references.setnextinternal + +function commands.currentreferenceorder(kind,name) + context(references.currentorder(kind,name)) +end + references.setcomponent = setcomponent function references.set(kind,prefix,tag,data) @@ -269,7 +289,7 @@ function references.set(kind,prefix,tag,data) local n = 0 for ref in gmatch(tag,"[^,]+") do if ref ~= "" then - if pd[ref] then + if check_duplicates and pd[ref] then if prefix and prefix ~= "" then report_references("redundant reference: %q in namespace %q",ref,prefix) else @@ -292,6 +312,8 @@ function references.enhance(prefix,tag) end end +commands.enhancereference = references.enhance + -- -- -- related to strc-ini.lua -- -- -- references.resolvers = references.resolvers or { } @@ -400,7 +422,9 @@ function references.urls.define(name,url,file,description) end end -local pushcatcodes, popcatcodes, txtcatcodes = context.pushcatcodes, context.popcatcodes, tex.txtcatcodes +local pushcatcodes = context.pushcatcodes +local popcatcodes = context.popcatcodes +local txtcatcodes = catcodes.numbers.txtcatcodes -- or just use "txtcatcodes" function references.urls.get(name) local u = urls[name] @@ -526,9 +550,7 @@ end function references.programs.get(name) local f = programs[name] - if f then - context(f[1]) - end + return f and f[1] end function references.checkedprogram(whatever) -- return whatever if not resolved @@ -542,10 +564,19 @@ function references.checkedprogram(whatever) -- return whatever if not resolved end end +commands.defineprogram = references.programs.define + +function commands.getprogram(name) + local f = programs[name] + if f then + context(f[1]) + end +end + -- shared by urls and files function references.whatfrom(name) - context((urls[name] and variables.url) or (files[name] and variables.file) or variables.unknown) + context((urls[name] and v_url) or (files[name] and v_file) or v_unknown) end function references.from(name) @@ -553,6 +584,31 @@ function references.from(name) if u then local url, file, description = u[1], u[2], u[3] if description ~= "" then + return description + -- ok + elseif file and file ~= "" then + return url .. "/" .. file + else + return url + end + else + local f = files[name] + if f then + local file, description = f[1], f[2] + if description ~= "" then + return description + else + return file + end + end + end +end + +function commands.from(name) + local u = urls[name] + if u then + local url, file, description = u[1], u[2], u[3] + if description ~= "" then context.dofromurldescription(description) -- ok elseif file and file ~= "" then @@ -578,10 +634,6 @@ function references.define(prefix,reference,list) d[reference] = { "defined", list } end ---~ function references.registerspecial(name,action,...) ---~ specials[name] = { action, ... } ---~ end - function references.reset(prefix,reference) local d = defined[prefix] if d then @@ -589,6 +641,9 @@ function references.reset(prefix,reference) end end +commands.definereference = references.define +commands.resetreference = references.reset + -- \primaryreferencefoundaction -- \secondaryreferencefoundaction -- \referenceunknownaction @@ -699,6 +754,8 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex end end +commands.expandcurrentreference = references.expandcurrent -- for the moment the same + local externals = { } -- we have prefixes but also components: @@ -1514,7 +1571,7 @@ references.identify = identify local unknowns, nofunknowns = { }, 0 -function references.doifelse(prefix,reference,highlight,newwindow,layer) +function references.valid(prefix,reference,highlight,newwindow,layer) local set, bug = identify(prefix,reference) local unknown = bug or #set == 0 if unknown then @@ -1533,7 +1590,11 @@ function references.doifelse(prefix,reference,highlight,newwindow,layer) currentreference = set[1] end -- we can do the expansion here which saves a call - commands.doifelse(not unknown) + return not unknown +end + +function commands.doifelsereference(prefix,reference,highlight,newwindow,layer) + commands.doifelse(references.valid(prefix,reference,highlight,newwindow,layer)) end function references.reportproblems() -- might become local @@ -1563,7 +1624,7 @@ function references.setinnermethod(m) if m then if m == "page" or m == "mixed" or m == "names" then innermethod = m - elseif m == true or m == variables.yes then + elseif m == true or m == v_yes then innermethod = "page" end end @@ -1612,13 +1673,13 @@ function references.setinternalreference(prefix,tag,internal,view) -- needs chec end function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here - if references.set(kind,prefix,tag,data) then - texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or unsetvalue - else - texcount.lastdestinationattribute = unsetvalue - end + local attr = references.set(kind,prefix,tag,data) and references.setinternalreference(prefix,tag,nil,view) or unsetvalue + texcount.lastdestinationattribute = attr + return attr end +commands.setreferenceattribute = references.setandgetattribute + function references.getinternalreference(n) -- n points into list (todo: registers) local l = lists.collected[n] return l and l.references.internal or n @@ -1637,7 +1698,11 @@ end function references.getcurrentmetadata(tag) local data = currentreference and currentreference.i - data = data and data.metadata and data.metadata[tag] + return data and data.metadata and data.metadata[tag] +end + +function commands.getcurrentreferencemetadata(tag) + local data = references.getcurrentmetadata(tag) if data then context(data) end @@ -1650,8 +1715,15 @@ end references.currentmetadata = currentmetadata -function references.getcurrentprefixspec(default) -- todo: message - context.getreferencestructureprefix(currentmetadata("kind") or "?",currentmetadata("name") or "?",default or "?") +local function getcurrentprefixspec(default) + -- todo: message + return currentmetadata("kind") or "?", currentmetadata("name") or "?", default or "?" +end + +references.getcurrentprefixspec = getcurrentprefixspec + +function commands.getcurrentprefixspec(default) + context.getreferencestructureprefix(getcurrentprefixspec(default)) end function references.filter(name,...) -- number page title ... @@ -1682,6 +1754,10 @@ function references.filter(name,...) -- number page title ... end end +function references.filterdefault() + return references.filter("default",getcurrentprefixspec(v_default)) +end + filters.generic = { } function filters.generic.title(data) @@ -2049,10 +2125,13 @@ end -- needs a better split ^^^ -commands.filterreference = references.filter +commands.filterreference = references.filter +commands.filterdefaultreference = references.filterdefault -- done differently now: function references.export(usedname) end function references.import(usedname) end function references.load (usedname) end + +commands.exportreferences = references.export diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi index ee45d76fa..7efc967b7 100644 --- a/tex/context/base/strc-ref.mkvi +++ b/tex/context/base/strc-ref.mkvi @@ -61,20 +61,42 @@ % \definespecial\dosetexecuteJScode % ... -%D This module deals with referencing. In \CONTEXT\ referencing -%D is one of the core features, although at a first glance -%D probably nobody will notice. This is good, because -%D referencing should be as hidden as possible. +%D This module deals with referencing. In \CONTEXT\ referencing is one of +%D the core features, although at a first glance probably nobody will +%D notice. This is good, because referencing should be as hidden as possible. %D -%D In paper documents, referencing comes down to cross -%D referencing, but in their interactive counterparts, is also -%D involves navigation. Many features implemented here are -%D therefore closely related to navigation. +%D Before we start implementing functionality we provide a way to set +%D up this mechanism. %D -%D Many \CONTEXT\ commands can optionally be fed with a -%D reference. Such a reference, when called upon, returns the -%D number of a figure, table, chapter etc, a piece of text, or -%D a pagenumber. +%D \showsetup{setupreferencing} +%D +%D In interactive documents verbose references don't always +%D make sense (what is a page number in an unnumbered +%D document). By setting the \type{interaction} variable, one +%D can influences the way interactive references are set. + +\installcorenamespace{referencing} + +\installdirectcommandhandler \??referencing {referencing} % \??referencing + +\newif\ifreferencing \referencingtrue + +\appendtoks + \edef\p_state{\referencingparameter\c!state}% + \ifx\p_state\v!start + \referencingtrue + \else + \referencingfalse + \fi +\to \everysetupreferencing + +%D In paper documents, referencing comes down to cross referencing, but in +%D their interactive counterparts, is also involves navigation. Many features +%D implemented here are therefore closely related to navigation. +%D +%D Many \CONTEXT\ commands can optionally be fed with a reference. Such a +%D reference, when called upon, returns the number of a figure, table, chapter +%D etc, a piece of text, or a pagenumber. %D %D There are three ways of defining a reference: %D @@ -96,10 +118,10 @@ %D These are implemented in a low level form as: -\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}} -\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}} -\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}} -\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}} +\unexpanded\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}} +\unexpanded\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}} +\unexpanded\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}} +\unexpanded\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}} %D Actually there is not much difference between a text and a %D full reference, but it's the concept that counts. The low @@ -108,15 +130,15 @@ \newcount\lastreferenceattribute \newcount\lastdestinationattribute -\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}} -\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}} +\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#label")}}} +\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#label",{})}}} \let\dofinishpagereference\dofinishfullreference \let\dofinishuserreference\dofinishfullreference \def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments} -\def\strc_references_set_named_reference +\unexpanded\def\strc_references_set_named_reference {\ifreferencing \expandafter\strc_references_set_named_reference_indeed \else @@ -143,7 +165,7 @@ \edef\currentreferencekind {#kind}% \edef\currentreferencelabels {#labels}% \edef\currentreferenceuserdata {#userdata}% - \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} + \edef\currentreferenceexpansion{\referencingparameter\c!expansion}% {\referenceparameter\c!expansion} \ifx\currentreferencelabels\empty \lastdestinationattribute\attributeunsetvalue \else @@ -163,7 +185,7 @@ % beware, the structures.references.set writes a % \setnextinternalreference \strc_references_start_destination_nodes - \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels", + \ctxcommand{setreferenceattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels", { references = { % internal = \nextinternalreference, % no need for an internal as we have an explicit @@ -210,7 +232,7 @@ \lastdestinationattribute\attributeunsetvalue \else \strc_references_start_destination_nodes - \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","\currentreferencelabels", + \ctxcommand{setreferenceattribute("\s!page", "\referenceprefix","\currentreferencelabels", { references = { block = "\currentsectionblock", @@ -248,7 +270,7 @@ \def\strc_references_set_simple_page_reference#label% {\iflocation \strc_references_start_destination_nodes - \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label", + \ctxcommand{setreferenceattribute("\s!page", "\referenceprefix","#label", { references = { % block = "\currentsectionblock", @@ -268,13 +290,74 @@ \def\strc_references_get_simple_page_reference#label% {\iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \xdef\currentreferenceattribute{\number\lastreferenceattribute}% \else \xdef\currentreferenceattribute{\number\attributeunsetvalue}% \fi} %D \macros +%D {contentreference} +%D +%D \starttyping +%D \setupinteraction +%D [state=start, +%D focus=standard] +%D +%D \setupheader +%D [state=stop] +%D +%D See page \goto{page 2}[page2] \page +%D +%D \contentreference +%D [page2] +%D [offset=1cm,toffset=2cm,frame=on] +%D {\externalfigure[cow.pdf][factor=fit]} +%D +%D \stoptyping + +\unexpanded\def\contentreference + {\hbox\bgroup + \dodoubleempty\strc_references_content_pickup} + +\def\strc_references_content_pickup + {\ifsecondargument + \expandafter\strc_references_content_pickup_yes + \else + \expandafter\strc_references_content_pickup_yes + \fi} + +\def\strc_references_content_pickup_yes[#1][#2]% + {\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox} + +\def\strc_references_content_pickup_nop[#1][#2]% + {\dowithnextbox{\strc_references_content_nop_finish{#1}{#2}}\hbox} + +\def\strc_references_content_yes_finish#1#2% + {\scratchwidth \wd\nextbox + \scratchheight\ht\nextbox + \scratchdepth \dp\nextbox + \setbox\nextbox\hbox + {\framed[\c!frame=\v!off,#2]{\box\nextbox}}% + \strc_references_set_simple_page_reference{#1}% + \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute + {\strc_references_flush_destination_nodes + \box\nextbox}% + \setbox\nextbox\hbox{\box\nextbox}% + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\scratchdepth + \box\nextbox + \egroup} + +\def\strc_references_content_nop_finish#1#2% + {\strc_references_set_simple_page_reference{#1}% + \hbox attr \destinationattribute \currentdestinationattribute + {\strc_references_flush_destination_nodes + \box\nextbox}% + \egroup} + +%D \macros %D {everyreference} %D %D For rather tricky purposes, one can assign sanitizing @@ -437,13 +520,13 @@ {\dodoubleempty\strc_references_define_reference} \def\strc_references_define_reference[#name][#specification]% - {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}} + {\ctxcommand{definereference("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}} \unexpanded\def\resetreference[#name]% - {\ctxlua{structures.references.reset("\referenceprefix","#name")}} + {\ctxcommand{resetreference("\referenceprefix","#name")}} \def\setpagereference#name#specification% hm,. low level ? - {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}} + {\ctxcommand{definereference("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}} %D Chained references are defined as: %D @@ -473,13 +556,13 @@ \newconditional\gotonewwindow \setfalse\gotonewwindow \def\expandtexincurrentreference % will happen in lua some time - {\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi} + {\ifcase\referencehastexstate\else\ctxcommand{expandcurrentreference()}\fi} \def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}} \def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}} \def\doifreferencefoundelse#labels#yes#nop% - {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% + {\ctxcommand{doifelsereference("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% {\expandtexincurrentreference #yes}% {#nop}} @@ -562,8 +645,8 @@ %D the special driver modules (see \type{spec-ini}). The flag %D \type{\iflocation} signals if we're in interactive mode. -\ifx\buttonheight\undefined \newdimen\buttonheight \fi -\ifx\buttonwidth \undefined \newdimen\buttonwidth \fi +\ifdefined\buttonheight \else \newdimen\buttonheight \fi +\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi %D Internal references can best be set using the next few %D macros. Setting such references to unique values is @@ -588,14 +671,14 @@ {\global\advance\locationcount\plusone} \def\setnextinternalreferences#kind#name% plural - {\ctxlua{structures.references.setnextinternal("#kind","#name")}} + {\ctxcommand{setnextinternalreference("#kind","#name")}} \def\getinternalorderreference#kind#name% - {\ctxlua{structures.references.currentorder("#kind","#name")}} + {\ctxcommand{currentreferenceorder("#kind","#name")}} \def\thisissomeinternal#kind#name% only for old time sake {\begingroup - \ctxlua{structures.references.setinternalreference("","#kind:#name")}% + \ctxcommand{setinternalreference("","#kind:#name")}% \hbox attr \destinationattribute\lastdestinationattribute{}% \endgroup} @@ -630,8 +713,6 @@ %D \goto{some text}[\v!action(PreviousJump] %D \stoptyping -\newif\ifreferencing \referencingtrue - %D One can also activate an automatic prefix mechanism. By %D setting the \type{\prefix} variable to \type{+}, the prefix %D is incremented, when set to \type{-} or empty, the prefix is @@ -639,64 +720,24 @@ \newcount\prefixcounter -%D These settings are accomplished by: -%D -%D \showsetup{setupreferencing} -%D -%D In interactive documents verbose references don't always -%D make sense (what is a page number in an unnumbered -%D document). By setting the \type{interaction} variable, one -%D can influences the way interactive references are set. - -\newtoks \everysetupreferencing - -\unexpanded\def\setupreferencing - {\dosingleargument\strc_references_setup_referencing} - -\def\strc_references_setup_referencing[#settings]% - {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]% - \the\everysetupreferencing} - -\appendtoks - \processaction - [\@@rfstate] - [ \v!stop=>\referencingfalse, - \v!start=>\referencingtrue]% -\to \everysetupreferencing - \newconditional\autocrossfilereferences \appendtoks - \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences + \edef\p_autofile{\referencingparameter\c!autofile}% + \ifx\p_autofile\v!yes + \settrue \autocrossfilereferences + \else + \setfalse\autocrossfilereferences + \fi \to \everysetupreferencing -\def\exportreferences - {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}} - \appendtoks - \exportreferences + \edef\p_export{\referencingparameter\c!export}% + \ifx\p_export\v!yes + \ctxcommand{exportreferences()}% + \fi \to \everygoodbye -\def\incrementreferenceprefix{+} -\def\decrementreferenceprefix{-} - -\unexpanded\def\setupreferenceprefix[#prefix]% - {\edef\@@rfprefix{#prefix}% - \ifx\@@rfprefix\empty - \let\referenceprefix\empty - \else\ifx\@@rfprefix\incrementreferenceprefix - \global\advance\prefixcounter \plusone - \edef\referenceprefix{\the\prefixcounter}% - \let\@@rfprefix\s!unknown - \else\ifx\@@rfprefix\decrementreferenceprefix - \let\referenceprefix\empty - \let\@@rfprefix\s!unknown - \else\ifx\@@rfprefix\s!unknown - % forget about it - \else - \edef\referenceprefix{\@@rfprefix}% expanded ! - \fi\fi\fi\fi} - \unexpanded\def\setupglobalreferenceprefix[#prefix]% {\xdef\referenceprefix{#prefix}} @@ -707,8 +748,28 @@ \unexpanded\def\popreferenceprefix {\popmacro\referenceprefix} +\def\m_strc_references_prefix_yes{+} +\def\m_strc_references_prefix_nop{-} + +\unexpanded\def\setupreferenceprefix[#prefix]% + {\edef\p_prefix{#prefix}% + \ifx\p_prefix\empty + \let\referenceprefix\empty + \else\ifx\p_prefix\m_strc_references_prefix_yes + \letreferencingparameter\c!prefix\s!unknown + \global\advance\prefixcounter\plusone + \edef\referenceprefix{\the\prefixcounter}% + \else\ifx\p_prefix\m_strc_references_prefix_nop + \letreferencingparameter\c!prefix\s!unknown + \let\referenceprefix\empty + \else\ifx\p_prefix\s!unknown + % forget about it + \else + \let\referenceprefix\p_prefix + \fi\fi\fi\fi} + \appendtoks - \setupreferenceprefix[\@@rfprefix] + \setupreferenceprefix[\referencingparameter\c!prefix] \to \everysetupreferencing %D We can typeset a reference using \type{\in}, \type{\at} and @@ -808,11 +869,11 @@ \let\crlf\space \let\\\space \postponenotes - \@@rfleft + \referencingparameter\c!left \doifreferencefoundelse{#label} - {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup) + {\goto{\limitatetext\currentreferencetitle{\referencingparameter\c!width}\unknown}[#label]}% not so efficient (dup lookup) {}% todo - \@@rfright + \referencingparameter\c!right \endgroup} %D The previously discussed setup macro lets us specify the @@ -883,7 +944,9 @@ \let\leftofreference \empty \let\rightofreference \empty -\setvalue{\??rf\c!interaction\v!all}% +\installcorenamespace{referencinginteraction} + +\setvalue{\??referencinginteraction\v!all}% {\the\leftreferencetoks \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing \leftofreference @@ -892,24 +955,24 @@ \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing \the\rightreferencetoks} -\setvalue{\??rf\c!interaction\v!label}% +\setvalue{\??referencinginteraction\v!label}% {\leftofreference \the\leftreferencetoks \the\rightreferencetoks \rightofreference} -\setvalue{\??rf\c!interaction\v!text}% +\setvalue{\??referencinginteraction\v!text}% {\leftofreference \currentreferencecontent \rightofreference} -\setvalue{\??rf\c!interaction\v!symbol}% +\setvalue{\??referencinginteraction\v!symbol}% {\referencesymbol} \def\referencesequence - {\csname \??rf\c!interaction - \ifcsname\??rf\c!interaction\@@rfinteraction\endcsname - \@@rfinteraction + {\csname\??referencinginteraction + \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname + \referencingparameter\c!interaction \else \v!all \fi @@ -1067,7 +1130,7 @@ \def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key \unexpanded\def\autoreferencelabeltext - {\ctxlua{structures.references.getcurrentmetadata("name")}} + {\ctxcommand{getcurrentreferencemetadata("name")}} % \starttext % \definereferenceformat[inxx] [left=(,right=),text=txt] @@ -1144,7 +1207,7 @@ \attribute\referenceattribute\attributeunsetvalue \global\lastsavedreferenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \setlocationattributes \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute @@ -1163,7 +1226,7 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% \setlocationattributes \attribute\referenceattribute\lastreferenceattribute \global\lastsavedreferenceattribute\lastreferenceattribute @@ -1182,9 +1245,9 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% + \ctxcommand{injectcurrentreference(\number\ht\strutbox,\number\dp\strutbox)}% \setlocationattributes \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute @@ -1205,9 +1268,9 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% + \ctxcommand{injectcurrentreference(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute @@ -1226,7 +1289,7 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty @@ -1243,7 +1306,7 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% \setlocationcolorspec{#resolver}% no consequence for strut \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty @@ -1260,7 +1323,7 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#content}% @@ -1276,9 +1339,9 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(nil,nil)}% + \ctxcommand{injectcurrentreference(nil,nil)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty @@ -1298,8 +1361,8 @@ \ht\scratchbox#height% \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue - \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% - {\ctxlua{structures.references.injectcurrentset(nil,nil)}% + \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}% + {\ctxcommand{injectcurrentreference(nil,nil)}% \global\lastsavedreferenceattribute\lastreferenceattribute \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} {\box\scratchbox}% @@ -1386,14 +1449,18 @@ %D %D \showsetup{setupurl} -\unexpanded\def\setupurl - {\dodoubleargument\getparameters[\??ur]} +\installcorenamespace{url} + +\installdirectcommandhandler \??url {url} + +\setupurl + [\c!style=\v!type, + \c!color=] \unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua) {\dontleavehmode \begingroup - \dousestyleparameter\@@urstyle - \dousecolorparameter\@@urcolor + \useurlstyleandcolor\c!style\c!color \hyphenatedurl{\ctxcommand{geturl("#label")}}% \endgroup} @@ -1425,14 +1492,13 @@ \def\strc_references_do_special_from[#label]% {\dontleavehmode - \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]} + \goto{\ctxcommand{from("#label")}}[fileorurl(#label)]} \def\dofromurldescription#content% called at the lua end {#content} \def\dofromurlliteral#content% called at the lua end - {\dousestyleparameter\@@urstyle - \dousecolorparameter\@@urcolor + {\useurlstyleandcolor\c!style\c!color \hyphenatedurl{#content}} \let\dofromfiledescription\dofromurldescription @@ -1463,21 +1529,21 @@ % also lua, like urls and files -\unexpanded\def\setupprograms - {\dodoubleargument\getparameters[\??pr]} +\installcorenamespace{programs} + +\installdirectcommandhandler \??programs {programs} \unexpanded\def\defineprogram {\dotripleargument\strc_references_define_program} \def\strc_references_define_program[#name][#program][#description]% - {\ctxlua{structures.references.programs.define("#name","#program","#description")}} + {\ctxcommand{defineprogram("#name","#program","#description")}} \def\program[#name]% incompatible, more consistent, hardy used anyway {\dontleavehmode \begingroup - \dousestyleparameter\@@prstyle - \dousecolorparameter\@@prcolor - \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}% + \useprogramsstyleandcolor\c!style\c!color + \ctxcommand{getprogram("#name","\directprogramsparameter\c!alternative","\directprogramsparameter\c!space")}% \endgroup} %D As we can see, we directly use the special reference @@ -1571,7 +1637,11 @@ \setbox\scratchbox\hbox{#text}% to be solved some day \ifdim\wd\scratchbox>\zeropoint \unhbox\scratchbox - \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new + \edef\p_separator{\referencingparameter\c!separator}% + \ifx\p_separator\empty \else + \removeunwantedspaces % remove is new + \p_separator + \fi \else \unhbox\scratchbox \fi @@ -1598,10 +1668,6 @@ \c!separator=\nonbreakablespace, \c!export=\v!no] -\setupurl - [\c!style=\v!type, - \c!color=] - \setupprograms [\c!directory=, \c!style=\v!type, @@ -1699,7 +1765,9 @@ % todo: parameterhandler -\def\getreferencestructureprefix#kind#name#category% +\installcorenamespace{referencingprefix} + +\def\getreferencestructureprefix#kind#name#category% name will change {{ prefix = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix", separatorset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset", @@ -1715,22 +1783,22 @@ \def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]% {\ifthirdargument - \getparameters[\??rf:\c!prefix:#kind:#category][#settings]% + \getparameters[\??referencingprefix#kind:#category][#settings]% \else\ifsecondargument - \getparameters[\??rf:\c!prefix::#kind][#category]% + \getparameters[\??referencingprefix:#kind][#category]% \fi\fi} \def\referencestructureprefixparameter#kind#name#category#parameter% - {\ifcsname\??rf:\c!prefix:#name:#category#parameter\endcsname - \csname\??rf:\c!prefix:#name:#category#parameter\endcsname - \else\ifcsname\??rf:\c!prefix:#kind:#category#parameter\endcsname - \csname \??rf:\c!prefix:#kind:#category#parameter\endcsname - \else\ifcsname\??rf:\c!prefix::#category#parameter\endcsname - \csname \??rf:\c!prefix::#category#parameter\endcsname + {\ifcsname\??referencingprefix#name:#category#parameter\endcsname + \csname\??referencingprefix#name:#category#parameter\endcsname + \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname + \csname \??referencingprefix#kind:#category#parameter\endcsname + \else\ifcsname\??referencingprefix:#category#parameter\endcsname + \csname \??referencingprefix:#category#parameter\endcsname \fi\fi\fi} \def\currentreferencedefault - {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}} + {\ctxcommand{filterdefaultreference()}} %D Not all support is visible by looking at the \TEX\ code; here is one of those:^ %D diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua index 6da58345b..23609cfd9 100644 --- a/tex/context/base/strc-reg.lua +++ b/tex/context/base/strc-reg.lua @@ -266,6 +266,10 @@ local function preprocessentries(rawdata) end rawdata.entries = nil end + local seeword = rawdata.seeword + if seeword then + seeword.processor, seeword.text = splitprocessor(seeword.text or "") + end end function registers.store(rawdata) -- metadata, references, entries @@ -826,10 +830,11 @@ function registers.flush(data,options,prefixspec,pagespec) context.startregisterseewords() for i=1,nt do local entry = t[i] - local processor = entry.processors and entry.processors[1] or "" + local seeword = entry.seeword + local seetext = seeword.text or "" + local processor = seeword.processor or (entry.processors and entry.processors[1]) or "" local seeindex = entry.references.seeindex or "" - local seeword = entry.seeword.text or "" - context.registerseeword(i,n,processor,0,seeindex,seeword) + context.registerseeword(i,n,processor,0,seeindex,seetext) end context.stopregisterseewords() end diff --git a/tex/context/base/strc-reg.mkiv b/tex/context/base/strc-reg.mkiv index e36556949..3940594c3 100644 --- a/tex/context/base/strc-reg.mkiv +++ b/tex/context/base/strc-reg.mkiv @@ -19,12 +19,7 @@ % todo: tag:: becomes rendering % todo: language, character, linked, location - -%D Helper: - -% \def\doflushatpar{\ifvmode\expandafter\dogotopar\else\expandafter\firstofoneargument\fi} - -\def\doflushatpar{\ifvmode\expandafter\flushatnextpar\else\expandafter\firstofoneargument\fi} +% todo: fonts etc at sublevels (already defined) % \starttext % \placeregister[index] @@ -34,9 +29,6 @@ % test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy] % \stoptext -% In plaats van + kan een & worden gebruikt. Ook kan als -% eerste karakter worden opgegeven wat de scheider is. -% % \index {entry} % \index[key] {entry} % \index[pageclass::] {entry} @@ -46,52 +38,34 @@ % \index[pageclass::] {textclass::entry} % \index[pageclass::key]{textclass::entry} -%D Parameters ... we set up levels so we need a slightly different command handler here .. okay, we -%D can use the childs for that ... but then we need to tweak the name in order to distinguis: -%D register -> register:1 (i.e. prefix) - -\let\currentregister\empty - -% \def\registerparameter#1{\csname\??id\currentregister#1\endcsname} - -\def\detokenizedregisterparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??id#1\endcsname}} % always root +% tzt variant with n entries, parameters and userdata (altnum) -\def\registerparameter #1{\csname\doregisterparameter{\??id\currentregister}{#1}\endcsname} -\def\registerparameterhash#1{\doregisterparameterhash {\??id\currentregister}#1} +\installcorenamespace{register} -\def\doregisterparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doregisterparentparameter \csname#1\s!parent\endcsname{#2}\fi} -\def\doregisterparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doregisterparentparameterhash\csname#1\s!parent\endcsname{#2}\fi} +\installcommandhandler\??register {register} \??register -\def\doregisterparentparameter #1#2{\ifx#1\relax\s!empty\else\doregisterparameter #1{#2}\fi} -\def\doregisterparentparameterhash#1#2{\ifx#1\relax \else\doregisterparameterhash#1{#2}\fi} +\let\strc_registers_setup_saved\setupregister -\def\useregisterstyleandcolor#1#2% style color - {\edef\currentstyleparameter{\registerparameter#1}% - \edef\currentcolorparameter{\registerparameter#2}% - \ifx\currentstyleparameter\empty\else\dousestyleparameter\currentstyleparameter\fi - \ifx\currentcolorparameter\empty\else\dousecolorparameter\currentcolorparameter\fi} +\unexpanded\def\setupregister % maybe we should drop the plural form + {\dotripleempty\strc_registers_setup} -%D Setup: - -\newtoks\everysetupregister - -\unexpanded\def\setupregisters - {\dotripleempty\dosetupregisters} - -\def\dosetupregisters[#1][#2][#3]% +\def\strc_registers_setup[#1][#2][#3]% {\ifthirdargument - \def\dodosetupregister##1{\getparameters[\??id##1#2][#3]}% - \processcommalist[#1]\dodosetupregister + \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}% + \processcommalist[#2]\strc_registers_setup_step \else\ifsecondargument - \def\dodosetupregister##1{\edef\currentregister{##1}\getparameters[\??id##1][#2]\the\everysetupregister}% - \processcommalist[#1]\dodosetupregister + \strc_registers_setup_saved[#1][#2]% \else - \getparameters[\??id][#1]% + \strc_registers_setup_saved[#1]% \fi\fi} -\let\setupregister\setupregisters +\unexpanded\def\setupregisters + {\dosingleempty\strc_registers_setup_root} + +\def\strc_registers_setup_root[#1]% + {\strc_registers_setup_saved[#1]\relax} -\setupregisters +\setupregister [\c!n=2, \c!balance=\v!yes, % \v!no komt niet zo vaak voor \c!align=\v!flushleft, @@ -102,7 +76,7 @@ \c!compress=\v!no, \c!interaction=\v!pagenumber, \c!alternative=\v!a, - \c!distance=1em, + \c!distance=\emwidth, \c!style=\v!bold, \c!pagestyle=\v!slanted, \c!indicator=\v!yes, @@ -115,7 +89,7 @@ \c!unknownreference=\v!empty, \c!prefix=\v!both, %\c!expansion=, -%\c!xmlsetup=, + %\c!xmlsetup=, \c!pagenumber=\v!yes, \c!pageprefixconnector=\endash, \c!pagesegments=2:2, @@ -125,48 +99,63 @@ \c!numberorder=\v!numbers, % \v!characters \s!language=\currentmainlanguage]% -%D Definition: +% yes or no shared ? -\unexpanded\def\defineregister - {\dodoubleargument\dodefineregister} +\setupregister + [\c!label=, + \c!entries=, + \c!alternative=] -\def\dodefineregister[#1][#2]% #2? - {\setupregister[#1][\s!parent=\??id]% - \ctxlua{structures.registers.define('#1')}% - \presetheadtext[#1=\Word{#1}]% - \setuvalue{#1}{\dodoubleempty\doregister[#1]}% - \setuvalue{\e!see#1}{\dodoubleempty\doseeregister[#1]}% -% \setuvalue{\e!coupled#1}{\dolinkedregister{#1}}% - \setvalue{\e!place#1}{\placeregister[#1]}% - \setvalue{\e!complete#1}{\completeregister[#1]}% - \setvalue{\e!setup#1\e!endsetup}[##1]{\getparameters[\??id#1][##1]}} +%D \starttyping +%D \setupregister[index][1][textcolor=darkred] +%D \setupregister[index][2][textcolor=darkgreen,textstyle=bold] +%D +%D \placeregister[index][n=1] \blank[3*big] +%D +%D test \index{test+one} test \index{test+two} more \index{more} +%D \stoptyping -%D Registering: +\newconditional\c_strc_registers_defining -\newif\ifwritetoregister \writetoregistertrue +\ifdefined\Word \else \unexpanded\def\Word#1{#1} \fi -% tzt variant met n entries, parameters en userdata (altnum) +\appendtoks + \ifconditional\c_strc_registers_defining \else + \settrue\c_strc_registers_defining + \ctxlua{structures.registers.define('\currentregister')}% + \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}% + \setuevalue{\currentregister}{\dodoubleempty\strc_registers_insert_entry[\currentregister]}% + \setuevalue{\e!see\currentregister}{\dodoubleempty\strc_registers_insert_see[\currentregister]}% + %setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}% + % historic ballast + \setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}% + \setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}% + \setuevalue{\e!setup\currentregister\e!endsetup}{\setupregister[\currentregister]}% + \dorecurse\plusthree {% weird, expanded should not be needed + \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}% +% \defineregister[\currentregister:\recurselevel][\currentregister]% + \letregisterparameter{\c!entries:\recurselevel}\empty % needed as we use detokenize (ok, we can + \letregisterparameter{\c!keys :\recurselevel}\empty % avoid it, but it's faster too) + }% + % + \setfalse\c_strc_registers_defining + \fi +\to \everydefineregister -\getparameters - [\??id] - [\c!label=, - \c!entries=, - \c!entries:1=,\c!entries:2=,\c!entries:3=, - \c!keys:1=,\c!keys:2=,\c!keys:3=, - \c!alternative=] +%D Registering: -\def\doregisterstructurepageregister +\def\strc_registers_register_page_entry {\iftrialtypesetting \expandafter\gobblethreearguments \else - \expandafter\dodoregisterstructurepageregister + \expandafter\strc_registers_register_page_entry_indeed \fi} -\def\dodoregisterstructurepageregister#1#2#3% register data userdata +\def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata {\begingroup \edef\currentregister{#1}% - %getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% - \getparameters[\??id][#2]% + %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% + \setupcurrentregister[#2]% \edef\currentregisterlabel {\registerparameter\c!label}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% \edef\currentregisterownnumber{\registerparameter\c!ownnumber}% @@ -245,7 +234,7 @@ section = structures.sections.currentid(), % hm, why then not also lastsection the same way label = "\currentregisterlabel", }, -% \ifx\currentregisterentries\empty \else + % \ifx\currentregisterentries\empty \else entries = { % we need a special one for xml, this is just a single one \ifx\currentregisterentries\empty @@ -259,10 +248,10 @@ \!!bs\currentregisterkeys\!!es, \fi }, -% \fi + % \fi userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es) } - } }% + }}% \ctxlua{structures.references.setinternalreference(nil,nil,\nextinternalreference)}% \ifx\currentregisterownnumber\v!yes \glet\currentregistersynchronize\relax @@ -275,45 +264,51 @@ \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup \endgroup} -\def\doregister[#1][#2]% +\unexpanded\def\strc_registers_insert_entry[#1][#2]% {\def\currentregister{#1}% - \doifelse{\registerparameter\c!ownnumber}\v!yes\dodoregister\donoregister{#1}{#2}} + \doifelse{\registerparameter\c!ownnumber}\v!yes + \strc_registers_insert_entry_yes + \strc_registers_insert_entry_nop + {#2}} + +\def\strc_registers_insert_entry_nop#1#2% + {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} -\def\donoregister #1#2#3{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!entries={#3}}{}}} -\def\dodoregister#1#2#3#4{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!alternative=#3,\c!entries={#4}}{}}} +\def\strc_registers_insert_entry_yes#1#2#3% + {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} -\unexpanded\def\startregister{\doquadrupleempty\dostartregister} -\unexpanded\def\stopregister {\dodoubleargument\dostopregister} +\unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry} +\unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry} % a synonym, so that we can nest with overlap without syntax check problems \let\openregisterrange \startregister \let\closeregisterrange\stopregister -\def\dostartregister[#1][#2][#3][#4]#5% +\def\strc_registers_start_entry[#1][#2][#3][#4]#5% {\iffourthargument % #1=register #2=tag #3=own #4=sortkey #5=entry - \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}% + \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}% \else % #1=register #2=tag #3=sortkey #5=entry - \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}% + \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}% \fi} -\def\dostopregister[#1][#2]% +\def\strc_registers_stop_entry[#1][#2]% {\normalexpanded{\ctxlatelua{structures.registers.extend("#1","#2")}}} -\def\setregisterentry {\dotripleempty\dosetregisterentry} -\def\finishregisterentry{\dotripleempty\dofinishregisterentry} +\def\setregisterentry {\dotripleempty\strc_registers_set_entry} +\def\finishregisterentry{\dotripleempty\strc_registers_finish_entry} % not yet document, not sure if this will stay: -\def\dosetregisterentry [#1][#2][#3]{\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}} -\def\dofinishregisterentry[#1][#2][#3]{\dofinishregisterstructurepageregister{#1}{#2}{#3}} +\def\strc_registers_set_entry [#1][#2][#3]{\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} +\def\strc_registers_finish_entry[#1][#2][#3]{\strc_registers_finish_entry_indeed{#1}{#2}{#3}} -\def\dofinishregisterstructurepageregister#1#2#3% register data userdata +\def\strc_registers_finish_entry_indeed#1#2#3% register data userdata {\begingroup \edef\currentregister{#1}% - \getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% + \setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]% \edef\currentregisterlabel {\registerparameter\c!label}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% \edef\currentregisterownnumber{\registerparameter\c!ownnumber}% @@ -336,7 +331,7 @@ \normalexpanded{\ctxlua{structures.registers.extend("\currentregister","\currentregisterlabel", { metadata = { \ifx\currentregisterownnumber\v!yes - own = "\registerparameter\c!alternative", % can be used instead of pagenumber + own = "\registerparameter\c!alternative", % can be used instead of pagenumber \fi }, userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es) @@ -353,7 +348,8 @@ }, entries = { % we need a special one for xml, this is just a single one - \!!bs\currentregisterentries\!!es, \!!bs\currentregisterkeys\!!es + \!!bs\currentregisterentries\!!es, + \!!bs\currentregisterkeys\!!es }, userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es) }) @@ -377,29 +373,32 @@ % \placeregister[index][n=1] % \stoptext -\def\setstructurepageregister{\dotripleempty\dosetstructurepageregister} +% some overlap wit previous + +\unexpanded\def\setstructurepageregister + {\dotripleempty\strc_registers_set} -\def\dosetstructurepageregister[#1][#2][#3]% [register][settings][userdata] - {\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}} +\def\strc_registers_set[#1][#2][#3]% [register][settings][userdata] + {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}} -\unexpanded\def\startstructurepageregister{\doquadrupleempty\dostartstructurepageregister} -\unexpanded\def\stopstructurepageregister {\dodoubleargument\dostopstructurepageregister} +\unexpanded\def\startstructurepageregister{\doquadrupleempty\strc_registers_start} +\unexpanded\def\stopstructurepageregister {\dodoubleargument\strc_registers_stop} \let\openstructurepageregisterrange \startstructurepageregister \let\closestructurepageregisterrange\stopstructurepageregister -\def\dostartstructurepageregister[#1][#2][#3][#4]% [register][tag][settings][userdata] - {\doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,#3}{#4}}} +\def\strc_registers_start[#1][#2][#3][#4]% [register][tag][settings][userdata] + {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}} -\def\dostopstructurepageregister[#1][#2]% +\def\strc_registers_stop[#1][#2]% {\normalexpanded{\ctxlatelua{structures.registers.extend("#1","#2")}}} % So far. -\def\doseeregister[#1][#2]#3#4% - {\doflushatpar{\doprocessseeregister{#1}{#2}{#3}{#4}}} +\unexpanded\def\strc_registers_insert_see[#1][#2]#3#4% + {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}} -\def\doprocessseeregister#1#2#3#4% register key entry seeword +\def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword {\begingroup \edef\currentregister{#1}% \edef\currentregisterexpansion{\registerparameter\c!expansion}% @@ -434,10 +433,11 @@ }, entries = { % we need a special one for xml, this is just a single one - "\currentregisterentries", "#2" + \!!bs\currentregisterentries\!!es, + \!!bs#2\!!es }, seeword = { - text = "\currentregisterseeword" + text = \!!bs\currentregisterseeword\!!es }, } }}% @@ -450,9 +450,9 @@ \let\utilityregisterlength\!!zerocount \def\determineregistercharacteristics - {\dodoubleempty\dodetermineregistercharacteristics} + {\dodoubleempty\strc_registers_determine_characteristics} -\def\dodetermineregistercharacteristics[#1][#2]% +\def\strc_registers_determine_characteristics[#1][#2]% {\begingroup \edef\currentregister{#1}% \setupregister[\currentregister][#2]% @@ -476,67 +476,85 @@ \to \everyplaceregister \unexpanded\def\placeregister - {\dodoubleempty\doplaceregister} + {\dodoubleempty\strc_registers_place} -\def\doplaceregister[#1][#2]% +\def\strc_registers_place[#1][#2]% {\iffirstargument \begingroup -% \forgetall + %\forgetall \edef\currentregister{#1}% \setupregister[\currentregister][#2]% \the\everyplaceregister - \startcolumns - [\c!n=\registerparameter\c!n, - \c!balance=\registerparameter\c!balance, - \c!align=\registerparameter\c!align, - \c!tolerance=\registerparameter\c!tolerance]% - \startpacked[\v!blank]% - \ctxlua{structures.registers.process('\currentregister',{ - language = "\registerparameter\s!language", - method = "\registerparameter\c!method", - numberorder = "\registerparameter\c!numberorder", - compress = "\registerparameter\c!compress", - criterium = "\registerparameter\c!criterium", - }, - { -% prefix = "\registerparameter\c!pageprefix", - separatorset = "\registerparameter\c!pageprefixseparatorset", - conversionset = "\registerparameter\c!pageprefixconversionset", - starter = \!!bs\registerparameter\c!pageprefixstarter\!!es, - stopper = \!!bs\registerparameter\c!pageprefixstopper\!!es, - set = "\registerparameter\c!pageprefixset", - segments = "\registerparameter\c!pageprefixsegments", - connector = \!!bs\registerparameter\c!pageprefixconnector\!!es, - }, - { - prefix = "\registerparameter\c!pageprefix", - separatorset = "\registerparameter\c!pageseparatorset", - conversionset = "\registerparameter\c!pageconversionset", - starter = \!!bs\registerparameter\c!pagestarter\!!es, - stopper = \!!bs\registerparameter\c!pagestopper\!!es, - segments = "\registerparameter\c!pagesegments", - } - )}% - \stoppacked - \stopcolumns + \ifnum\registerparameter\c!n>\plusone + \startcolumns + [\c!n=\registerparameter\c!n, + \c!balance=\registerparameter\c!balance, + \c!align=\registerparameter\c!align, + \c!tolerance=\registerparameter\c!tolerance]% + \strc_registers_place_indeed + \stopcolumns + \else + \strc_registers_place_indeed + \fi \endgroup \fi} -\def\dolimitedregisterentry#1{\limitatetext{#1}\currentregistermaxwidth\unknown}% +\def\strc_registers_place_columns + {\startcolumns + [\c!n=\registerparameter\c!n, + \c!balance=\registerparameter\c!balance, + \c!align=\registerparameter\c!align, + \c!tolerance=\registerparameter\c!tolerance]% + \startpacked[\v!blank]% + \strc_registers_place_indeed + \stoppacked + \stopcolumns} + +\def\strc_registers_place_normal + {\startpacked[\v!blank]% + \strc_registers_place_indeed + \stoppacked} + +\def\strc_registers_place_indeed + {\ctxlua{structures.registers.process('\currentregister',{ + language = "\registerparameter\s!language", + method = "\registerparameter\c!method", + numberorder = "\registerparameter\c!numberorder", + compress = "\registerparameter\c!compress", + criterium = "\registerparameter\c!criterium", + },{ + separatorset = "\registerparameter\c!pageprefixseparatorset", + conversionset = "\registerparameter\c!pageprefixconversionset", + starter = \!!bs\registerparameter\c!pageprefixstarter\!!es, + stopper = \!!bs\registerparameter\c!pageprefixstopper\!!es, + set = "\registerparameter\c!pageprefixset", + segments = "\registerparameter\c!pageprefixsegments", + connector = \!!bs\registerparameter\c!pageprefixconnector\!!es, + },{ + prefix = "\registerparameter\c!pageprefix", + separatorset = "\registerparameter\c!pageseparatorset", + conversionset = "\registerparameter\c!pageconversionset", + starter = \!!bs\registerparameter\c!pagestarter\!!es, + stopper = \!!bs\registerparameter\c!pagestopper\!!es, + segments = "\registerparameter\c!pagesegments", + })}} + +\def\strc_registers_limited_entry#1% + {\limitatetext{#1}\currentregistermaxwidth\unknown}% \appendtoks \edef\currentregistermaxwidth{\registerparameter\c!maxwidth}% \ifx\currentregistermaxwidth\empty \let\limitedregisterentry\firstofoneargument \else - \let\limitedregisterentry\dolimitedregisterentry + \let\limitedregisterentry\strc_registers_limited_entry \fi \to \everyplaceregister -\def\completeregister - {\dodoubleempty\docompleteregister} +\unexpanded\def\completeregister + {\dodoubleempty\strc_registers_complete} -\def\docompleteregister[#1][#2]% +\def\strc_registers_complete[#1][#2]% {\iffirstargument \begingroup \edef\currentregister{#1}% @@ -546,7 +564,7 @@ \stopnamedsection \endgroup \fi} - + % test case for collapsing (experimental, for Steffen Wolfrum) % % \starttext @@ -565,37 +583,36 @@ % xxxx \index{xxxx} % todo \index{todo} % \stoptext - + %D Character rendering (sections): +\installcorenamespace{registerindicator} + \def\defaultregistercharacter#1% - {\doifsomething{#1} - {\doifnot{#1}\s!unknown - {\doifelse{\registerparameter\c!indicator}\v!yes - {\doregistercharacter{#1}} - {\noregistercharacter{#1}}}}} - -% \def\doregistercharacter#1% -% {\expandcheckedcsname % why no \executeifdefined -% {\??id:\c!indicator:}% -% {\registerparameter\c!alternative}% -% {a}% -% {#1}} - -\def\doregistercharacter#1% - {\expandcheckedcsname % why no \executeifdefined - {\??id:\c!indicator:}% - {\registerparameter\c!alternative}% - {a}% - {#1}} - -\def\noregistercharacter#1% + {\edef\currentregistercharacter{#1}% + \ifx\currentregistercharacter\empty + % skip + \else\ifx\currentregistercharacter\s!unknown + % skip + \else + \edef\p_indicator{\registerparameter\c!indicator}% + \ifx\p_indicator\v!yes + \strc_registers_place_character_yes + \else + \strc_registers_place_character_nop + \fi + \fi\fi} + +\def\strc_registers_place_character_yes + {\expandcheckedcsname\??registerindicator{\registerparameter\c!alternative}\v!a{\currentregistercharacter}} + +\def\strc_registers_place_character_nop {\registerparameter\c!before \goodbreak} % a = <before> <goodbreak> <character> <par> <after> <nobreak> -\setvalue{\??id:\c!indicator:a}#1% +\setvalue{\??registerindicator a}#1% {\registerparameter\c!before % bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight \begingroup @@ -607,13 +624,14 @@ \fi \registerparameter\c!command{#1}% \endgroup + \blank[\v!samepage]% \registerparameter\c!after \par \nobreak} % b = <goodbreak> <before> <character> <after> <nobreak> -\setvalue{\??id:\c!indicator:b}#1% will be shared with a +\setvalue{\??registerindicator b}#1% will be shared with a {\registerparameter\c!before \begingroup \useregisterstyleandcolor\c!style\c!color @@ -627,9 +645,9 @@ \registerparameter\c!after \nobreak} -\setvalue{\??id:\c!indicator:A}#1{\getvalue{\??id:\c!indicator:a}{\WORD{#1}}} -\setvalue{\??id:\c!indicator:B}#1{\getvalue{\??id:\c!indicator:b}{\WORD{#1}}} - +\setvalue{\??registerindicator A}#1{\getvalue{\??registerindicator a}{\WORD{#1}}} +\setvalue{\??registerindicator B}#1{\getvalue{\??registerindicator b}{\WORD{#1}}} + %D The following macros are the interface to the rendering. These are %D generated by \LUA. This might change. @@ -637,9 +655,13 @@ %D placeindex as then flushing takes place inside the index. Took me hours %D to notice that. +\newconditional\c_strc_registers_page_done +\newdimen \d_strc_registers_distance + \unexpanded\def\startregisteroutput {\endgraf \begingroup + \d_strc_registers_distance\registerparameter\c!distance\relax \dostarttagged\t!register\currentregister \forgeteverypar \forgetparindent @@ -654,9 +676,13 @@ {\endgraf \begingroup \dostarttagged\t!registerentries\empty + \let\savedcurrentregister\currentregister + \edef\currentregister{\currentregister:#1}% \useregisterstyleandcolor\c!textstyle\c!textcolor - \advance\leftskip\numexpr#1-1\relax\dimexpr\registerparameter\c!distance\relax - \hangindent\registerparameter\c!distance\hangafter\plusone} + \advance\leftskip\numexpr#1-\plusone\relax\dimexpr\d_strc_registers_distance\relax + \hangindent\registerparameter\c!distance\relax + \hangafter\plusone + \let\currentregister\savedcurrentregister} \unexpanded\def\stopregisterentries {\endgraf @@ -673,12 +699,10 @@ {\dostoptagged \endgraf} -\newconditional\registerpagedone - \unexpanded\def\startregisterpages {\begingroup \dostarttagged\t!registerpages\empty - \setfalse\registerpagedone + \setfalse\c_strc_registers_page_done \useregisterstyleandcolor\c!pagestyle\c!pagecolor} \unexpanded\def\stopregisterpages @@ -688,7 +712,7 @@ \unexpanded\def\startregisterseewords {\ifhmode\crlf\fi \begingroup - \setfalse\registerpagedone + \setfalse\c_strc_registers_page_done \dostarttagged\t!registerpage\empty \useregisterstyleandcolor\c!pagestyle\c!pagecolor} @@ -696,15 +720,16 @@ {\dostoptagged \endgroup} -\def\registerpageseparator% todo: , configurable - {\ifconditional\registerpagedone +\unexpanded\def\registerpageseparator% todo: , configurable + {\ifconditional\c_strc_registers_page_done \registerpageseparatorsymbol \else - \hskip\registerparameter\c!distance\relax - \settrue\registerpagedone + \hskip\d_strc_registers_distance\relax + \settrue\c_strc_registers_page_done \fi} -\def\registeronepagerangeseparator{|\endash|} +\unexpanded\def\registeronepagerangeseparator + {|\endash|} \def\withregisterpagecommand#1#2#3#4% {\def\currentregisterpageindex{#2}% @@ -714,13 +739,13 @@ \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% \fi} -\def\registeronepage#1#2#3#4% #1:processor content +\unexpanded\def\registeronepage#1#2#3#4% #1:processor content {\registerpageseparator \dostarttagged\t!registerpage\empty \withregisterpagecommand{#1}{#2}{#3}{#4}% \dostoptagged} -\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable +\unexpanded\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable {\registerpageseparator \dostarttagged\t!registerpagerange\empty \dostarttagged\t!registerfrompage\empty @@ -732,7 +757,7 @@ \dostoptagged \dostoptagged} -\def\doapplyregisterentrycommand#1#2% processor text +\unexpanded\def\doapplyregisterentrycommand#1#2% processor text {\dostarttagged\t!registerentry\empty \ifx\currentregisterseeindex\empty \else \dontleavehmode @@ -741,7 +766,7 @@ \applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}% \dostoptagged} -\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word +\unexpanded\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word {\def\currentregisterpageindex{#2}% \iflocation \def\currentregisterseeindex{#3}% @@ -761,11 +786,11 @@ \goto{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]% \fi} -\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word +\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word {%\registerpageseparator \def\currentregisterpageindex{#4}% \dostarttagged\t!registersee\empty - \settrue\registerpagedone + \settrue\c_strc_registers_page_done \iflocation \def\currentregisterseeindex{#5}% \else @@ -805,41 +830,44 @@ % not yet ok : new internal handler names -\def\registerpagebuttonsymbol{\vrule\!!width1em\!!height1ex\!!depth\zeropoint\relax} +\unexpanded\def\registerpagebuttonsymbol + {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax} + +\installcorenamespace{registersymbol} -\setvalue{\??id:\c!symbol:\c!n}% +\setvalue{\??registersymbol n}% {\def\registerpageseparatorsymbol{, }} -\setvalue{\??id:\c!symbol:\c!a}% +\setvalue{\??registersymbol a}% {\def\registerpageseparatorsymbol{, }} % now done via conversion -\setvalue{\??id:\c!symbol:\v!none}% +\setvalue{\??registersymbol\v!none}% {\let\registerpageseparatorsymbol\empty \let\registeronepage \gobblefourarguments \let\registerpagerange \gobblesevenarguments} -\setvalue{\??id:\c!symbol:1}% +\setvalue{\??registersymbol 1}% {\let\registerpageseparatorsymbol\space - \def\registeronepage {\symbol[1]\gobblefourarguments}% - \def\registerpagerange {\symbol[1]\gobblesevenarguments}} + \def\registeronepage {\symbol[1]\gobblefourarguments}% + \def\registerpagerange{\symbol[1]\gobblesevenarguments}} -\setvalue{\??id:\c!symbol:2}% +\setvalue{\??registersymbol 2}% {\let\registerpageseparatorsymbol\space - \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}% - \def\registerpagerange {\registerpagebuttonsymbol\gobblesevenarguments}} + \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}% + \def\registerpagerange{\registerpagebuttonsymbol\gobblesevenarguments}} \def\setregisterpagerendering {\doifelse{\registerparameter\c!pagenumber}\v!no {\let \currentregisterpagesymbol\v!none} {\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}% \ifx\currentregisterpagesymbol\empty - \csname\??id:\c!symbol:\c!n\endcsname - \else\ifcsname\??id:\c!symbol:\currentregisterpagesymbol\endcsname - \csname\??id:\c!symbol:\currentregisterpagesymbol\endcsname + \csname\??registersymbol n\endcsname + \else\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname + \csname\??registersymbol\currentregisterpagesymbol\endcsname \else \let\registerpageseparatorsymbol\space - \def\registeronepage {\registerparameter\c!symbol\gobblefourarguments}% - \def\registerpagerange {\registerparameter\c!symbol\gobblesevenarguments}% + \def\registeronepage{\registerparameter\c!symbol\gobblefourarguments}% + \def\registerpagerange{\registerparameter\c!symbol\gobblesevenarguments}% \fi\fi} \appendtoks @@ -853,6 +881,6 @@ \defineregister [\v!index] - [\v!indices] +% [\v!indices] \protect \endinput diff --git a/tex/context/base/strc-ren.mkiv b/tex/context/base/strc-ren.mkiv index b7b4224cd..d9cebc17f 100644 --- a/tex/context/base/strc-ren.mkiv +++ b/tex/context/base/strc-ren.mkiv @@ -15,7 +15,10 @@ \unprotect -\newconstant\headtimingmode +\newbox\b_strc_rendering_head + +\newdimen\d_strc_rendering_local_leftoffset +\newdimen\d_strc_rendering_local_rightoffset % Martin Kolarik's problem: % @@ -23,90 +26,57 @@ % \def\doTitle#1#2{\ruledvbox{\forgetall \hsize=4cm \ruledhbox{\ruledvtop{#1}\ruledvtop{#2}}}} % \section{test test test test test test test test test test test test test test test test test} -\newevery \everyheadstart \relax +\newtoks\everyheadstart -\unexpanded\def\setupheadcomponentfont#1#2% +\unexpanded\def\strc_rendering_initialize_style_and_color + {\ifconditional\headisdisplay + \expandafter\strc_rendering_initialize_style_and_color_display + \else + \expandafter\strc_rendering_initialize_style_and_color_inline + \fi} + +\unexpanded\def\strc_rendering_initialize_style_and_color_display#1#2% {\dontconvertfont - \ifconditional\headisdisplay - \edef\askedheadinterlinespace{\headparameter\c!interlinespace}% - \ifx\askedheadinterlinespace\empty - % here the interline space is only set when style sets no space - \setfalse\fontattributeisset % use the currentfontparameter state instead - \setfalse\interlinespaceisset - \useheadstyleandcolor\c!style\c!color - \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else - \setupinterlinespace - \fi \fi - \setfalse\fontattributeisset \useheadstyleandcolor#1#2% - \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else - \setupinterlinespace - \fi \fi - \else - % here the set interline space overloads any other set space in the style - \setfalse\fontattributeisset - \useheadstyleandcolor\c!style\c!color - \ifconditional\fontattributeisset - \dosetupcheckedinterlinespace\askedheadinterlinespace - \fi - \setfalse\fontattributeisset - \useheadstyleandcolor#1#2% - \ifconditional\fontattributeisset - \dosetupcheckedinterlinespace\askedheadinterlinespace - \fi - \fi + \edef\p_strc_rendering_interlinespace{\headparameter\c!interlinespace}% + \ifx\p_strc_rendering_interlinespace\empty + % here the interline space is only set when style sets no space + \setfalse\fontattributeisset % use the currentfontparameter state instead + \setfalse\interlinespaceisset + \useheadstyleandcolor\c!style\c!color\relax + \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else + \setupinterlinespace + \fi \fi + \setfalse\fontattributeisset + \useheadstyleandcolor#1#2\relax + \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else + \setupinterlinespace + \fi \fi \else + % here the set interline space overloads any other set space in the style \setfalse\fontattributeisset - \useheadstyleandcolor\c!style\c!color + \useheadstyleandcolor\c!style\c!color\relax \ifconditional\fontattributeisset - \setupspacing + \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace \fi \setfalse\fontattributeisset - \useheadstyleandcolor#1#2% + \useheadstyleandcolor#1#2\relax \ifconditional\fontattributeisset - \setupspacing + \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace \fi \fi} -\def\doplaceheadtextcomponent#1% - {\begingroup - \setupheadcomponentfont\c!textstyle\c!textcolor - \headparameter\c!commandbefore - \ifcsname\currentheadhash\c!deeptextcommand\endcsname - \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname - \fi - \ifconditional\headisdisplay % \ifdisplaysectionhead - % struts can be nilled with \setnostrut - \headparameter\c!textcommand{\setstrut\begstrut#1\endstrut}% - \xdef\localheadheight {\the\strutht}% - \xdef\localheaddepth {\the\strutdp}% - \xdef\localheadlineheight{\the\lineheight}% - % == \globallet\localheaddepth\strutdepth - \else - \headparameter\c!textcommand{#1}% - \fi - \headparameter\c!commandafter - \ifconditional\headisdisplay % \ifdisplaysectionhead - \endgraf - \fi - \endgroup} - -\def\doplaceheadnumbercomponent#1% - {\begingroup - \setupheadcomponentfont\c!numberstyle\c!numbercolor - \ifcsname\currentheadhash\c!deepnumbercommand\endcsname - \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname - \fi - \ifconditional\headisdisplay % \ifdisplaysectionhead - % can be nilled with \setnostrut - \headparameter\c!numbercommand{\setstrut\begstrut#1\endstrut}% - \else - \headparameter\c!numbercommand{#1}% - \fi - \endgroup} - -% \newif\ifheadnumbercontent -% \newif\ifemptyhead -% \newif\ifdisplaysectionhead +\unexpanded\def\strc_rendering_initialize_style_and_color_inline#1#2% + {\dontconvertfont + \setfalse\fontattributeisset + \useheadstyleandcolor\c!style\c!color\relax + \ifconditional\fontattributeisset + \updateraggedskips % \setupspacing + \fi + \setfalse\fontattributeisset + \useheadstyleandcolor#1#2\relax + \ifconditional\fontattributeisset + \updateraggedskips % \setupspacing + \fi} \let\currentstructurereferenceattribute\attributeunsetvalue @@ -142,42 +112,45 @@ % maybe auto: backreference when given, else list \fi\fi} -\unexpanded\def\placecurrentheadtext - {\beginheadplacement +% a bit messy ... empty in place instead of self .. might change (or use special +% whatsig (invisible user one) + +\unexpanded\def\strc_rendering_place_head_text + {\strc_rendering_start_placement \setheadmarking \doresettructureheadnumbercontent - \ifconditional\headleaveempty - \setbox\sectionheadbox\hbox \headreferenceattributes to \zeropoint{}% - \makestrutofbox\sectionheadbox + \ifconditional\c_strc_sectioning_empty + \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}% \else \docheckheadreference - \setbox\sectionheadbox\hbox \headreferenceattributes + \setbox\b_strc_rendering_head\hbox \headreferenceattributes {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}% \doresettructureheadnumbercontent \useheadstyleparameter\c!style \setinlineheadreferenceattributes - \headparameter\c!command{}{\doplaceheadtextcomponent\getheadtitle}}% + \strc_rendering_inject_text}% \fi - \endheadplacement{\getheadsyncs}} + \strc_rendering_stop_placement} -\unexpanded\def\placecurrentheadnumbertext - {\beginheadplacement +\unexpanded\def\strc_rendering_place_head_number_and_text + {\strc_rendering_start_placement \setheadmarking - \doiftextelse{\getheadnumber}\dosettructureheadnumbercontent\doresettructureheadnumbercontent - \ifconditional\headleaveempty - \setbox\sectionheadbox\hbox \headreferenceattributes to \zeropoint{}% - \makestrutofbox\sectionheadbox + \doiftextelse\getheadnumber + \dosettructureheadnumbercontent + \doresettructureheadnumbercontent + \ifconditional\c_strc_sectioning_empty + \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}% \else % = needed \docheckheadreference - \setbox\sectionheadbox\hbox \headreferenceattributes + \setbox\b_strc_rendering_head\hbox \headreferenceattributes {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}% \useheadstyleparameter\c!style \setinlineheadreferenceattributes - \headparameter\c!command{\doplaceheadnumbercomponent\getheadnumber}{\doplaceheadtextcomponent\getheadtitle}}% + \strc_rendering_inject_number_and_text}% \fi - \endheadplacement{\getheadsyncs}} + \strc_rendering_stop_placement} -\unexpanded\def\placecurrentheadempty +\unexpanded\def\strc_rendering_place_head_empty {\hbox \headreferenceattributes {\getheadsyncs}} %D \starttyping @@ -192,54 +165,96 @@ %D \MySubject{feeling stretched feeling stretched feeling stretched feeling stretched} %D \stoptyping -\let\headlastlinewidth\!!zeropoint +% helpers -\def\localheadheight {\strutht} -\def\localheaddepth {\strutdp} -\def\localheadlineheight{\lineheight} +% \defineinmargin [ChapterInMargin] [outer] [normal] [distance=0.3em] +% +% \defineheadplacement[MyTest][horizontal]#1#2% +% {\startlocalheadsetup +% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay +% \ChapterInMargin{\strut#2}% zero destination, ref okay +% \stoplocalheadsetup} +% +% \setuphead +% [chapter] +% [alternative=MyTest] + +\unexpanded\def\headhbox{\hbox\headreferenceattributes} +\unexpanded\def\headvbox{\vbox\headreferenceattributes} -\def\dolocalheadsetup % koppeling met standaard kopcommando / engels - {\forgetall % traag dus ... - \doifsomething{\headparameter\c!align } {\normalexpanded{\noexpand\setupalign [\headparameter\c!align ]}}% - \doifsomething{\headparameter\c!tolerance} {\normalexpanded{\noexpand\setuptolerance[\headparameter\c!tolerance]}}% - \doif {\headparameter\c!strut }\v!no{\setnostrut}% new - \def\\{\crlf\strut\ignorespaces}} +\unexpanded\def\startlocalheadsetup{\bgroup\strc_rendering_initialize_spacing} +\unexpanded\def\stoplocalheadsetup {\egroup} -\def\beginheadplacement +\unexpanded\def\strc_rendering_initialize_spacing + {\forgetall % local ! + \edef\p_align{\headparameter\c!align}% + \ifx\p_align\empty \else + \setupalign[\p_align]% + \fi + \edef\p_tolerance{\headparameter\c!tolerance}% + \ifx\p_tolerance\empty \else + \setuptolerance[\p_tolerance]% + \fi + \edef\p_strut{\headparameter\c!strut}% + \ifx\p_strut\v!no + \setnostrut + \fi + \let\\\strc_rendering_shortcut_backslash} + +\unexpanded\def\strc_rendering_shortcut_backslash + {\crlf + \strut + \ignorespaces} + +\def\strc_rendering_start_placement {\bgroup \setsystemmode\currenthead - \xdef\localheadheight {\the\strutht}% - \xdef\localheaddepth {\the\strutdp}% - \xdef\localheadlineheight{\the\lineheight}% - % == \globallet\localheaddepth\strutdp - \everypar\emptytoks % needed indeed - \noindent % ipv \whitespace elders, na \forgetall ! + % + \strc_rendering_initialize_alternatives + \strc_rendering_initialize_dimensions + % + \strc_rendering_initialize_line_state + \reseteverypar % needed indeed + \noindent % ipv \whitespace elders, na \forgetall ! \bgroup - \doifinsetelse{\headparameter\c!aligntitle}{\v!yes,\v!float}% new - {\skip0 1\leftskip - \skip2 1\rightskip - \xdef\localheadskip{\the\skip0}% - \forgetall - \leftskip\skip0 - \rightskip\skip2 - \setlocalhsize\hsize\localhsize - \forgetbothskips} - {\globallet\localheadskip\!!zeropoint - \forgetall}% + \edef\p_aligntitle{\headparameter\c!aligntitle}% + \ifx\p_aligntitle\v!yes + \strc_rendering_initialize_hsize_local + \else\ifx\p_aligntitle\v!float + \strc_rendering_initialize_hsize_local + \else + \strc_rendering_initialize_hsize_global + \fi\fi \setfalse\inhibitmargindata % brrrr is set in forgetall \dontcomplain \postponenotes - \iflocation - \ifconditional\headisdisplay % \ifdisplaysectionhead - \else - % obsolete: \noninterferingmarks - \fi - \fi - \resetinteractionparameter\c!style + \strc_rendering_initialize_interaction + % delayed + \let\localheadsetup \strc_rendering_initialize_spacing % historic name + \let\headsetupspacing\strc_rendering_initialize_spacing} + +\def\strc_rendering_initialize_hsize_local + {\global\d_strc_rendering_local_leftoffset \leftskip + \global\d_strc_rendering_local_rightoffset\rightskip + % \forgetall + % \leftskip \d_strc_rendering_local_leftoffset % no stretch + % \rightskip\d_strc_rendering_local_rightoffset % no stretch + % \setlocalhsize + % \hsize\localhsize + % \forgetbothskips} + \scratchwidth\availablehsize + \forgetall + \hsize\scratchwidth} + +\def\strc_rendering_initialize_hsize_global + {\global\d_strc_rendering_local_leftoffset \zeropoint + \global\d_strc_rendering_local_rightoffset\zeropoint + \forgetall} + +\def\strc_rendering_initialize_interaction + {\resetinteractionparameter\c!style \resetinteractionparameter\c!color - \resetinteractionparameter\c!contrastcolor - %\strictouterreferencestrue % tzt instelling - \let\localheadsetup\dolocalheadsetup} + \resetinteractionparameter\c!contrastcolor} % \setuphead[chapter] [style=\bfd,after=,hang=line] % fit broad 2 % \setuphead[section] [style=\bfc,after=,hang=line] @@ -259,87 +274,106 @@ % \subsubsection {Test\\Test} \input tufte \page % \subsubsubsection{Test\\Test} \input tufte \page -\def\hangheadplacement - {\scratchdimen\localheadlineheight - \bgroup - \openlineheight\scratchdimen - \scratchdimen\htdp0% - \getnoflines\scratchdimen - \advance\noflines\minusone - \normalexpanded{\egroup\noflines\the\noflines}% brrr - \setbox0\hbox{\lower\noflines\scratchdimen\box0}% - \scratchdimen\dimexpr\htdp0-\localheadheight+\strutdp\relax - \ht0 \strutht - \dp0 \strutdp - \edef\localheaddepth{\the\strutdp}} - -\newconditional\continuoussectionhead % oeps, \newif\ifcontinuoushead got lost -\newbox\sectionheadbox - -\def\endheadplacement#1% - {\noflines\zerocount - \ifconditional\headisdisplay % \ifdisplaysectionhead - % new (todo tight == one following line up) - \processaction - [\headparameter\c!hang] - [ \v!line=>\hangheadplacement\noflines\zerocount, - \v!broad=>\hangheadplacement\getnoflines\scratchdimen, - \v!fit=>\hangheadplacement\getrawnoflines\scratchdimen, - \v!none=>\noflines\zerocount, - \v!default=>\noflines\zerocount, - \v!unknown=>\hangheadplacement\noflines\numexpr0\commalistelement-1\relax]% - % so far - \let\headlastlinewidth\!!zeropoint +\newdimen\d_strc_rendering_hang_height +\newcount\n_strc_rendering_hang_lines + +\newdimen\d_strc_rendering_local_height +\newdimen\d_strc_rendering_local_depth +\newdimen\d_strc_rendering_local_lineheight + +\def\strc_rendering_initialize_line_state + {\global\d_strc_rendering_local_height\strutht + \global\d_strc_rendering_local_depth\strutdp + \global\d_strc_rendering_local_lineheight\lineheight} + +\def\strc_rendering_check_hang + {\begingroup + \openlineheight\d_strc_rendering_local_lineheight + \d_strc_rendering_hang_height\htdp\b_strc_rendering_head + \getnoflines\d_strc_rendering_hang_height + \normalexpanded{\endgroup\n_strc_rendering_hang_lines\the\numexpr\noflines-\plusone\relax}% brrr + \setbox\b_strc_rendering_head\hbox{\lower\n_strc_rendering_hang_lines\d_strc_rendering_hang_height\box\b_strc_rendering_head}% + \d_strc_rendering_hang_height\dimexpr\htdp\b_strc_rendering_head-\d_strc_rendering_local_height+\strutdp\relax + \ht\b_strc_rendering_head\strutht + \dp\b_strc_rendering_head\strutdp + \d_strc_rendering_local_depth\strutdp} + +\installcorenamespace{headplacementcheckhang} + +\setvalue{\??headplacementcheckhang\v!line }{\strc_rendering_check_hang + \n_strc_rendering_hang_lines\zerocount} +\setvalue{\??headplacementcheckhang\v!broad }{\strc_rendering_check_hang + \getnoflines\d_strc_rendering_hang_height} +\setvalue{\??headplacementcheckhang\v!fit }{\strc_rendering_check_hang + \getrawnoflines\d_strc_rendering_hang_height} +\setvalue{\??headplacementcheckhang\v!none }{\n_strc_rendering_hang_lines\zerocount} +\setvalue{\??headplacementcheckhang }{\n_strc_rendering_hang_lines\zerocount} +\setvalue{\??headplacementcheckhang\s!unknown}{\strc_rendering_check_hang + \n_strc_rendering_hang_lines\numexpr\p_hang-\plusone\relax} + +\def\strc_rendering_initialize_line_hang + {\ifconditional\headisdisplay + \edef\p_hang{\headparameter\c!hang}% + \expandcheckedcsname\??headplacementcheckhang\p_hang\s!unknown + \relax + \else + \n_strc_rendering_hang_lines \zerocount + \d_strc_rendering_hang_height\zeropoint + \fi} + +\def\strc_rendering_stop_placement + {\n_strc_rendering_hang_lines\zerocount + \ifconditional\headisdisplay + \strc_rendering_initialize_line_hang % kind of special, we want to snap heads also according to local specs local \ifgridsnapping \hbox\bgroup % extra hbox will trigger global snapper on top of local - \edef\currentheadgridsnapping{\headparameter\c!grid}% + \edef\p_grid{\headparameter\c!grid}% \ifconditional\headisdisplay - \ifx\currentheadgridsnapping\empty\else + \ifx\p_grid\empty\else \useheadstyleandcolor\c!style\c!color \setupinterlinespace \useheadstyleandcolor\c!textstyle\c!textcolor \setupinterlinespace \fi \fi - \snaptogrid[\currentheadgridsnapping]\hbox - {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}% + \snaptogrid[\p_grid]\hbox + {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}% \egroup \else \hbox - {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}% + {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}% \fi \flushnotes % new, not really needed \endgraf \ifvmode - \ifnum\noflines>\zerocount - \dorecurse\noflines{\nointerlineskip\dosomebreak\nobreak\strut\endgraf}% to be checked + \ifnum\n_strc_rendering_hang_lines>\zerocount + \dorecurse\n_strc_rendering_hang_lines{\nointerlineskip\dosomebreak\nobreak\strut\endgraf}% to be checked \fi \nointerlineskip \dosomebreak\nobreak \fi - #1% + \getheadsyncs \else \strut \flushnotes % new, here since we're in par mode - \unhbox\sectionheadbox - \globallet\headlastlinewidth\!!zeropoint - #1% - \hskip\numberheaddistance\!!plus\numberheaddistance\!!minus.25\dimexpr\numberheaddistance\relax - \hskip\continuousheadsignal\ignorespaces + \unhbox\b_strc_rendering_head + \getheadsyncs + \hskip\headnumberdistance\s!plus\headnumberdistance\s!minus.25\dimexpr\headnumberdistance\relax + \strc_sectioning_inject_continuous_signal \fi - \ifconditional\headisdisplay % \ifdisplaysectionhead + \ifconditional\headisdisplay \ifvmode \ifgridsnapping % important, font related depth, see comment \prevdepth\strutdp \else - \prevdepth\localheaddepth + \prevdepth\d_strc_rendering_local_depth \fi \fi \fi \egroup \egroup - \ifconditional\headisdisplay % \ifdisplaysectionhead + \ifconditional\headisdisplay \useindentnextparameter\headparameter \else \nonoindentation % recently added, was a bug @@ -359,56 +393,168 @@ % \input tufte \par % \stopnarrower -\installcorenamespace{headplacementalternative} -\installcorenamespace{headplacementnature} - -\let\numberheadalternative\v!normal - -\unexpanded\def\defineheadplacement - {\dodoubleargument\dodefineheadplacement} - -% \def\dodefineheadplacement[#1][#2]% #3#4 -% {\setvalue{\??headplacementnature#1}{#2}% -% \setvalue{\??headplacementalternative#1}} - % \dodefineheadplacement[sectiona][vertical]{#1->#2} % \dodefineheadplacement[sectionb][vertical]#1#2{#1->#2} % % \setuphead[section][alternative=sectiona] % \setuphead[subsection][alternative=sectionb] -\def\dodefineheadplacementyes[#1][#2]%#3#4% - {\setvalue{\??headplacementnature#1}{#2}% - \setvalue{\??headplacementalternative#1}##1##2} +% \startsetups[\??headrenderings:\v!vertical:\v!sectiona] +% ... there will be a more public namespace +% \stopsetups + +\installcorenamespace{headplacementalternative} +\installcorenamespace{headrenderings} +\installcorenamespace{headalternative} -\def\dodefineheadplacementnop[#1][#2]% - {\setvalue{\??headplacementnature#1}{#2}% - \setvalue{\??headplacementalternative#1}} +\installcommandhandler \??headalternative {headalternative} \??headalternative % or just \??head -\def\dodefineheadplacement[#1][#2]% +\setupheadalternative + [%\c!width=\headparameter\c!width, + %\c!distance=\headparameter\c!distance, + \c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\currentheadalternative] + +\let\currentheadalternative \v!normal +\let\currentheadrenderingsetup \empty +\let\currentheadrenderingalternative\v!vertical + +\unexpanded\def\defineheadplacement % old mechanism + {\dodoubleargument\strc_rendering_define_placement} + +\def\strc_rendering_define_placement[#1][#2]% {\doifnextbgroupelse - {\dodefineheadplacementyes[#1][#2]}% - {\dodefineheadplacementnop[#1][#2]}} + {\strc_rendering_define_placement_yes[#1][#2]}% + {\strc_rendering_define_placement_nop[#1][#2]}} + +\def\strc_rendering_define_placement_yes[#1][#2]% + {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]% + \setuvalue{\??headplacementalternative#1}##1##2} + +\def\strc_rendering_define_placement_nop[#1][#2]% + {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]% + \setuvalue{\??headplacementalternative#1}} + +% these can be used in setups: +% +% \headnumbercontent +% \headtextcontent +% +% \headwidth +% \headtextwidth +% \headnumberdistance +% \headnumberwidth +% \headsetupspacing +% +% \headshownumber +% \headisdisplay + +\let\headnumbercontent\empty +\let\headtextcontent \empty + +\newdimen\headwidth +\newdimen\headtextwidth +\newdimen\headnumberdistance +\newdimen\headnumberwidth + +% \newconditional\headshownumber % defined already +% \newconditional\headisdisplay % defined already + +\unexpanded\def\strc_rendering_initialize_alternatives + {\edef\currentheadalternative {\headparameter \c!alternative}% + \edef\currentheadrenderingsetup {\headalternativeparameter\c!renderingsetup}% + \edef\currentheadrenderingalternative{\headalternativeparameter\c!alternative}% + \ifx\currentheadrenderingalternative\empty + \let\currentheadrenderingalternative\v!vertical + \fi + \ifx\currentheadrenderingalternative\v!horizontal + \global\setfalse\headisdisplay % global + \else + \global\settrue\headisdisplay % global + \fi} -\def\presetnumberheadalternative - {\doifelsevalue{\??headplacementnature\numberheadalternative}\v!horizontal\setfalse\settrue\headisdisplay} +\unexpanded\def\strc_rendering_initialize_dimensions + {\headwidth \headparameter\c!width \relax % \zeropoint == unset + \headnumberwidth \headparameter\c!numberwidth\relax % \zeropoint == unset + \headnumberdistance\headparameter\c!distance \relax + \headtextwidth \headparameter\c!textwidth \relax} % \zeropoint == unset -\def\normalplacehead - {\csname\??headplacementalternative\ifcsname\??headplacementalternative\numberheadalternative\endcsname\numberheadalternative\else\v!normal\fi\endcsname} +\unexpanded\def\headtextcontent + {\begingroup + \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor + \headparameter\c!commandbefore\relax + \ifcsname\currentheadhash\c!deeptextcommand\endcsname + \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname + \fi + \ifconditional\headisdisplay + % struts can be nilled with \setnostrut + \headparameter\c!textcommand{\setstrut\begstrut\getheadtitle\endstrut}% + \global\d_strc_rendering_local_height\strutht + \global\d_strc_rendering_local_depth\strutdp + \global\d_strc_rendering_local_lineheight\lineheight + \headparameter\c!commandafter\relax + \endgraf + \else + \headparameter\c!textcommand{\getheadtitle}% + \headparameter\c!commandafter\relax + \fi + \endgroup} + +\unexpanded\def\headnumbercontent + {\begingroup + \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor + \ifcsname\currentheadhash\c!deepnumbercommand\endcsname + \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname + \fi + \ifconditional\headisdisplay + % can be nilled with \setnostrut + \headparameter\c!numbercommand{\setstrut\begstrut\getheadnumber\endstrut}% + \else + \headparameter\c!numbercommand{\getheadnumber}% + \fi + \endgroup} + +\unexpanded\def\strc_rendering_inject_number_and_text + {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition + \ifx\p_command\empty + \directsetup\currentheadrenderingsetup + \else + \p_command\headnumbercontent\headtextcontent + \fi} + +\unexpanded\def\strc_rendering_inject_text + {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition + \ifx\p_command\empty + \directsetup\currentheadrenderingsetup + \else + \p_command\empty\headtextcontent + \fi} -\def\setheaddisplay % used in strc-sec - {\doifelsevalue{\??headplacementnature\headparameter\c!alternative}\v!horizontal - {\setfalse\headisdisplay} - {\settrue \headisdisplay}} +\startsetups[\??headrenderings:\v!command] + \csname\??headplacementalternative\currentheadalternative\endcsname \headnumbercontent \headtextcontent +\stopsetups -\defineheadplacement[\v!paragraph][\v!vertical]#1#2% - {\vbox - {\localheadsetup - \begstrut - \ifconditional\headshownumber % \ifheadnumbercontent - #1\hskip\numberheaddistance - \fi - #2}} +% obsolete +% +% \def\normalplacehead % hooks into \c!command +% {\csname\??headplacementalternative\ifcsname\??headplacementalternative\currentheadalternative\endcsname\currentheadalternative\else\v!normal\fi\endcsname} + +\defineheadalternative + [\v!paragraph] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!paragraph] + +\startsetups[\??headrenderings:\v!paragraph] + \vbox { + \headsetupspacing + \begstrut + \ifconditional\headshownumber % \ifheadnumbercontent + \headnumbercontent + \hskip\headnumberdistance + \fi + \headtextcontent + } +\stopsetups % \setuphead % [chapter] @@ -417,129 +563,183 @@ % \chapter{Oeps oeps oeps} \input tufte \section{Oeps} % \chapter{Oeps oeps oeps} \section{Oeps} \input tufte -\defineheadplacement[\v!normal][\v!vertical]#1#2% - {\vbox - {\localheadsetup - \edef\headwidth {\headparameter\c!width }% - \edef\headnumberwidth{\headparameter\c!numberwidth}% - \edef\headtextwidth {\headparameter\c!textwidth }% - \ifconditional\headshownumber - \ifx\headwidth\empty - \else - \ifx\headnumberwidth\empty - \ifx\headtextwidth\empty\else - \edef\headnumberwidth{\the\dimexpr\headwidth-\headtextwidth\relax}% +\defineheadalternative + [\v!normal] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!normal] + +\startsetups[\??headrenderings:\v!normal] + \vbox { + \headsetupspacing + \ifconditional\headshownumber + \ifdim\headwidth=\zeropoint \else + \ifdim\headnumberwidth=\zeropoint + \ifdim\headtextwidth=\zeropoint \else + \headnumberwidth\dimexpr\headwidth-\headtextwidth\relax + \fi + \else + \ifdim\headtextwidth=\zeropoint + \headtextwidth\dimexpr\headwidth-\headnumberwidth\relax + \fi + \fi + \hsize\headwidth \fi - \else - \ifx\headtextwidth\empty - \edef\headtextwidth{\the\dimexpr\headwidth-\headnumberwidth\relax}% + \ifdim\headnumberwidth=\zeropoint\else + \headnumberdistance\zeropoint \fi - \fi - \hsize\headwidth - \fi - \ifx\headnumberwidth\empty\else - \let\numberheaddistance\!!zeropoint + \setbox\scratchbox\hbox \ifdim\headnumberwidth=\zeropoint\else to \headnumberwidth\fi{\headnumbercontent} + \scratchdimen\dimexpr\wd\scratchbox+\headnumberdistance\relax + \ifdim\headtextwidth=\zeropoint\else + \hsize\dimexpr\scratchdimen+\headtextwidth\relax + \fi + \hangindent\scratchdimen + \hangafter \plusone + \noindent + \box\scratchbox + \hskip\headnumberdistance + \else + \ifdim\headtextwidth=\zeropoint + \ifdim\headwidth=\zeropoint \else + \hsize\headwidth + \fi + \else + \hsize\headtextwidth + \fi + \noindent \fi - \setbox\scratchbox\hbox \ifx\headnumberwidth\empty\else to \headnumberwidth\fi{{#1}}% - \scratchdimen\dimexpr\wd\scratchbox+\numberheaddistance\relax - \ifx\headtextwidth\empty\else - \hsize\dimexpr\scratchdimen+\headparameter\c!textwidth\relax + \headtextcontent + } +\stopsetups + +\defineheadalternative + [\v!inmargin] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!inmargin] + +\startsetups[\??headrenderings:\v!inmargin] + \vbox { + \headsetupspacing + \begstrut % use one \strut here! + \dontleavehmode % in case there is no strut, else side effects with llap + \ifconditional\headshownumber + \llap { + \hbox { + \hfill + \headnumbercontent + \hskip\dimexpr\d_strc_rendering_local_leftoffset+\doifoddpageelse\leftmargindistance\rightmargindistance\relax + } + } \fi - \hangindent\scratchdimen - \hangafter \plusone - \noindent - \box\scratchbox\hskip\numberheaddistance - \else - \ifx\headtextwidth\empty - \ifx\headwidth\empty - \else - \hsize\headwidth - \fi - \else - \hsize\headtextwidth + \headtextcontent + } +\stopsetups + +\defineheadalternative + [\v!margin] + [\v!inmargin] + +% \startsetups[\??headrenderings:\v!vertical:\v!margin] +% \directsetup{\??headrenderings:\v!vertical:\v!inmargin} +% \stopsetups + +\defineheadalternative + [\v!middle] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!middle] + +\startsetups[\??headrenderings:\v!middle] + \vbox { + \headsetupspacing + \veryraggedcenter + \let\\\endgraf + \let\crlf\endgraf + \ifconditional\headshownumber + \strut + \headnumbercontent + \par \fi - \noindent - \fi - #2}} - -% \unexpanded\def\placeheadmarginalternative#1#2% -% {\vbox -% {\localheadsetup -% \begstrut % use one \strut here! -% \dontleavehmode % in case there is no strut, else side effects with llap -% \ifconditional\headshownumber -% \llap{\hbox{\hfill{#1}\hskip\localheadskip\hskip\leftmargindistance}}% introduces whitespace -% % maybe better: -% % \inleftmargin{\hbox{\hss{#1}\hskip\localheadskip}}% -% \fi -% {#2}}} - -\unexpanded\def\placeheadmarginalternative#1#2% - {\vbox - {\localheadsetup - \begstrut % use one \strut here! - \dontleavehmode % in case there is no strut, else side effects with llap - \ifconditional\headshownumber - \llap{\hbox{\hfill{#1}\hskip\dimexpr\localheadskip+\doifoddpageelse\leftmargindistance\rightmargindistance\relax}}% introduces whitespace - \fi - {#2}}} - -\defineheadplacement[\v!inmargin][\v!vertical]#1#2{\placeheadmarginalternative{#1}{#2}} -\defineheadplacement[\v!margin] [\v!vertical]#1#2{\placeheadmarginalternative{#1}{#2}} - -\defineheadplacement[\v!middle][\v!vertical]#1#2% - {\vbox - {\localheadsetup - \veryraggedcenter - \let\\\endgraf - \let\crlf\endgraf - \ifconditional\headshownumber - \strut#1\par - \fi - \begstrut#2}} - -\defineheadplacement[\v!text][\v!horizontal]#1#2% - {\bgroup - \localheadsetup % no stretch in distance - \ifconditional\headshownumber - {#1}\kern\numberheaddistance - \fi - {\begstrut#2}% - \egroup} - -\unexpanded\def\placeheadlohialternative#1#2#3% - {\ifconditional\headshownumber - \setbox0\hbox{#2} - \setbox2=#1{\localheadsetup\advance\hsize-\wd0\relax#3}% - \hbox{\box0\hskip\numberheaddistance\box2}% - \else - #1{\localheadsetup\noindent#3}% - \fi} - -% onder/boven lijnt het nummer op de onderste/bovenste regel -% uit van een meerregelige kop - -\defineheadplacement[\v!bottom][\v!vertical]#1#2{\placeheadlohialternative\vbox{#1}{#2}} -\defineheadplacement[\v!top] [\v!vertical]#1#2{\placeheadlohialternative\vtop{#1}{#2}} - -% helpers - -% \defineinmargin [ChapterInMargin] [outer] [normal] [distance=0.3em] -% -% \defineheadplacement[MyTest][horizontal]#1#2% -% {\startlocalheadsetup -% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay -% \ChapterInMargin{\strut#2}% zero destination, ref okay -% \stoplocalheadsetup} -% -% \setuphead -% [chapter] -% [alternative=MyTest] - -\unexpanded\def\headhbox{\hbox\headreferenceattributes} -\unexpanded\def\headvbox{\vbox\headreferenceattributes} - -\unexpanded\def\startlocalheadsetup{\bgroup\localheadsetup} -\unexpanded\def\stoplocalheadsetup {\egroup} + \begstrut + \headtextcontent + \endstrut + } +\stopsetups + +\defineheadalternative + [\v!text] + [\c!alternative=\v!horizontal, + \c!renderingsetup=\??headrenderings:\v!text] + +\startsetups[\??headrenderings:\v!text] + \begingroup + \headsetupspacing % no stretch in distance + \ifconditional\headshownumber + \headnumbercontent + \kern\headnumberdistance + \fi + \begstrut + \headtextcontent + \endstrut + \endgroup +\stopsetups + +% onder/boven lijnt het nummer op de onderste/bovenste regel uit van een meerregelige kop + +\defineheadalternative + [\v!bottom] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!bottom] + +\startsetups[\??headrenderings:\v!bottom] + \ifconditional\headshownumber + \setbox0\hbox { + \headnumbercontent + } + \setbox2\vbox { + \headsetupspacing + \advance\hsize-\wd0\relax + \headtextcontent + } + \hbox { + \box0 + \hskip\headnumberdistance + \box2 + } + \else + \vbox { + \headsetupspacing + \noindent + \headtextcontent + } + \fi +\stopsetups + +\defineheadalternative + [\v!top] + [\c!alternative=\v!vertical, + \c!renderingsetup=\??headrenderings:\v!top] + +\startsetups[\??headrenderings:\v!top] + \ifconditional\headshownumber + \setbox0\hbox { + \headnumbercontent + } + \setbox2\vtop { + \headsetupspacing + \advance\hsize-\wd0\relax + \headtextcontent + } + \hbox { + \box0 + \hskip\headnumberdistance + \box2 + } + \else + \vtop{ + \headsetupspacing + \noindent + \headtextcontent + } + \fi +\stopsetups \protect \endinput diff --git a/tex/context/base/strc-sbe.mkiv b/tex/context/base/strc-sbe.mkiv index a98b67885..4ea08b30c 100644 --- a/tex/context/base/strc-sbe.mkiv +++ b/tex/context/base/strc-sbe.mkiv @@ -27,78 +27,76 @@ % \chapter{second} \section{alpha} test \section{beta} test \page % \stopbodymatter % optional -\unexpanded\def\definesectionblock{\dotripleargument\dodefinesectionblock} -\unexpanded\def\setupsectionblock {\dodoubleargument\dosetupsectionblock} -\def\setsectionblock {\dosingleargument\dosetsectionblock} - -\def\sectionblockparameter#1% - {\csname - \ifcsname\??sb\currentsectionblock#1\endcsname\??sb\currentsectionblock#1\else\s!empty\fi - \endcsname} - -\newtoks \everybeforesectionblock -\newtoks \everyaftersectionblock - -\def\dodefinesectionblock[#1][#2][#3]% singular plural settings - {\getparameters - [\??sb#1] - [\c!number=\v!yes, - \c!page=\v!right, % anders worden marks te vroeg gereset ! - #3]% - \expandafter\newif\csname if#2\endcsname % better a mode - \setsectionblockenvironment{#1}\empty - \setvalue {\e!start#2}{\startsectionblock[#1]}% - \setvalue {\e!stop #2}{\stopsectionblock}} +\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 + +\unexpanded\def\definesectionblock + {\dotripleargument\strc_sectionblock_define} + +\def\strc_sectionblock_define[#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 - \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}% + \strc_sectionblock_handle_page \resetallstructuremarks - \getsectionblockenvironment\currentsectionblock + \strc_sectionblock_get_environment\currentsectionblock \sectionblockparameter\c!before % don't move \dostarttagged\t!division\currentsectionblock \to \everybeforesectionblock \appendtoks \sectionblockparameter\c!after % don't move - \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}% + \strc_sectionblock_handle_page \dostoptagged \resetallstructuremarks \to \everyaftersectionblock -\def\dosetupsectionblock[#1]% - {\getparameters[\??sb#1]}% [#2] +\unexpanded\def\setsectionblock + {\dosingleargument\strc_sectionblock_set} -\def\dosetsectionblock[#1]% used to set the default - {\edef\currentsectionblock{\ctxlua{structures.sections.setblock("#1")}}} +\def\strc_sectionblock_set[#1]% used to set the default + {\edef\currentsectionblock{\ctxcommand{setsectionblock("#1")}}} \let\currentsectionblock\empty % was \s!unknown \unexpanded\def\startsectionblock[#1]% {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push) \begingroup - \edef\currentsectionblock{\ctxlua{structures.sections.pushblock("#1")}}% - \csname #1true\endcsname % for old times sake + \edef\currentsectionblock{\ctxcommand{pushsectionblock("#1")}}% + \csname #1true\endcsname % obsolete \setsystemmode\currentsectionblock \the\everybeforesectionblock\relax \showmessage\m!structures1\currentsectionblock} \unexpanded\def\stopsectionblock - {\showmessage\m!structures2\currentsectionblock - \the\everyaftersectionblock\relax - \edef\currentsectionblock{\ctxlua{structures.sections.popblock()}}% - \endgroup} - -\long\def\setsectionblockenvironment#1#2% - {\long\setvalue{\??sb\s!do#1}{\do{#2}}} - -\def\getsectionblockenvironment#1% - {\let\do\firstofoneargument - %\sectionblockparameter{\s!do#1}} - \csname\??sb\s!do#1\endcsname} + {\showmessage\m!structures2\currentsectionblock + \the\everyaftersectionblock\relax + \edef\currentsectionblock{\ctxcommand{popsectionblock()}}% + \endgroup} %D \starttyping %D \startsectionblockenvironment[frontpart] @@ -120,10 +118,20 @@ %D \stoptext %D \stoptyping -\setvalue{\e!start\v!sectionblockenvironment}% - {\dosingleargument\dostartsectionblockenvironment} +\installcorenamespace{sectionblockenvironment} + +\unexpanded\def\strc_sectionblock_set_environment#1#2% + {\setvalue{\??sectionblockenvironment#1}{#2}} + +\unexpanded\def\strc_sectionblock_get_environment#1% + {\csname\??sectionblockenvironment#1\endcsname} + +\unexpanded\setvalue{\e!start\v!sectionblockenvironment}% + {\dosingleargument\strc_sectionblock_environment_start} + +\letvalue{\e!stop\v!sectionblockenvironment}\relax -\def\dostartsectionblockenvironment[#1]% evt \pushendofline \popendofline - {\grabuntil{\e!stop\v!sectionblockenvironment}{\setsectionblockenvironment{#1}}} +\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/strc-sec.mkiv b/tex/context/base/strc-sec.mkiv index e9b613f21..826de59bf 100644 --- a/tex/context/base/strc-sec.mkiv +++ b/tex/context/base/strc-sec.mkiv @@ -15,7 +15,227 @@ \unprotect -\ifdefined \v!block \else \def\v!block{block} \fi +\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!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{-} + +\def\strc_sectioning_set_reference_prefix + {\ifx\currentstructurereferenceprefix\empty + % nothing + \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes + \global\advance\prefixcounter \plusone % temp here + \setupglobalreferenceprefix[\the\prefixcounter]% + \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop + \setupglobalreferenceprefix[]% + \else + \setupglobalreferenceprefix[\currentstructurereferenceprefix]% + \fi\fi\fi + \let\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] + +\unexpanded\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}% + \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 + \ifx\currentstructurelist\empty + \globallet\currentstructurelist\currentstructuretitle + \fi + \globallet\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}% + \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 + \begingroup + \simplifycommands + \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}% + \endgroup + \fi \fi + \fi + \ifx\currentstructurelist\empty + \globallet\currentstructurelist\currentstructuretitle + \fi + \globallet\currentstructurecoding\s!tex + \fi + \setnextinternalreference + \strc_sectioning_set_reference_prefix + \xdef\currentstructurenumber{\ctxlua{ % todo: combine with next call, adapt marks accordingly + structures.sections.somelevel { + references = { + internal = \nextinternalreference, + block = "\currentsectionblock", + reference = "\currentstructurereference", + referenceprefix = "\currentstructurereferenceprefix", + backreference = "\currentstructurebackreference", + }, + directives = { + resetset = "\structureparameter\c!sectionresetset", + }, + metadata = { + kind = "section", + name = "\currentstructurename", + catcodes = \the\ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi, + coding = "\currentstructurecoding", + \ifx\currentstructurecoding\s!xml + xmlroot = "\xmldocument", + \fi + \ifx\currentstructurexmlsetup\empty \else + xmlsetup = "\currentstructurexmlsetup", + \fi + \ifx\currentstructuresaveinlist\v!no + nolist = true, + \fi + \ifx\currentstructureincrementnumber\v!yes + increment = "\currentstructureincrementnumber", + \fi + }, + titledata = { % we can add mark and reference + label = \!!bs\detokenize\expandafter{\currentstructurelabel }\!!es, + title = \!!bs\detokenize\expandafter{\currentstructuretitle }\!!es, + \ifx\currentstructurebookmark\currentstructuretitle \else + bookmark = \!!bs\detokenize\expandafter{\currentstructurebookmark }\!!es, + \fi + \ifx\currentstructuremarking\currentstructuretitle \else + marking = \!!bs\detokenize\expandafter{\currentstructuremarking }\!!es, + \fi + \ifx\currentstructuresaveinlist\v!no \else + \ifx\currentstructurelist\currentstructuretitle \else + list = \!!bs\detokenize\expandafter{\currentstructurelist}\!!es, + \fi + \fi + }, + numberdata = { + % needed ? + block = "\currentsectionblock", + hidenumber = \ifx\currentstructureshownumber\v!no true\else nil\fi, % titles + % so far + separatorset = "\structureparameter\c!sectionseparatorset", + conversion = "\structureparameter\c!sectionconversion", % for good old times sake + conversionset = "\structureparameter\c!sectionconversionset", + starter = \!!bs\structureparameter\c!sectionstarter\!!es, + stopper = \!!bs\structureparameter\c!sectionstopper\!!es, + set = "\structureparameter\c!sectionset", + segments = "\structureparameter\c!sectionsegments", + ownnumber = "\currentstructureownnumber", + }, + userdata = \!!bs\detokenize{#3}\!!es % will be converted to table at the lua end + } + }}% + \xdef\currentstructurelistnumber{\ctxcommand{addtolist(structures.sections.current())}}% + % \currentstructuresynchronize has to be called someplace, since it introduces a node + \setstructuresynchronization\currentstructurelistnumber + \endgroup} + +\let\currentstructurenumber \!!zerocount +\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 + +\def\structurenumber {\ctxcommand{structurenumber()}} +\def\structuretitle {\ctxcommand{structuretitle()}} +\def\structurevariable #1{\ctxcommand{structurevariable("#1")}} +\def\structureuservariable #1{\ctxcommand{structureuservariable("#1")}} +\def\structurecatcodedget #1{\ctxcommand{structurecatcodedget("#1")}} % bad name +\def\structuregivencatcodedget #1#2{\ctxcommand{structuregivencatcodedget("#1",\number#2)}} % bad name +\def\structureautocatcodedget #1#2{\ctxcommand{structureautocatcodedget ("#1","#2")}} + +\def\namedstructurevariable #1#2{\ctxcommand{namedstructurevariable ("#1","#2")}} +\def\namedstructureuservariable#1#2{\ctxcommand{namedstructureuservariable("#1","#2")}} % compatibility issue: % @@ -43,6 +263,8 @@ % lua interface / names and interface might change +\newconditional\c_strc_rendering_continuous % not used (mkii ?) + \def\setstructurelevel #1#2{\ctxlua{structures.sections.setlevel("#1","#2")}} % name, level|parent \def\getstructurelevel #1{\ctxlua{structures.sections.getcurrentlevel("#1")}}% name \def\setstructurenumber #1#2{\ctxlua{structures.sections.setnumber(#1,"#2")}} % level, number (+/-) @@ -74,6 +296,62 @@ \installcommandhandler \??head {head} \??head +\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!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 @@ -132,28 +410,28 @@ \appendtoks % \setevalue{\e!next \currenthead}{\donexthead [\currenthead]}% - \setevalue{\e!start\currenthead}{\dostarthead[\currenthead]}% - \setevalue{\e!stop \currenthead}{\dostophead [\currenthead]}% + \setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}% + \setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}% \to \everydefinehead \appendtoks \doifelse{\headparameter\c!ownnumber}\v!yes - {\setevalue\currenthead{\dohandleheadown[\currenthead]}} - {\setevalue\currenthead{\dohandleheadnop[\currenthead]}}% + {\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}} + {\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}% \to \everysetuphead \let\currentnamedsection\empty \unexpanded\def\startnamedsection - {\dotripleempty\dostartnamedsection} + {\dotripleempty\strc_sectioning_start_named_section} -\def\dostartnamedsection[#1]% [#2][#3] +\unexpanded\def\strc_sectioning_start_named_section[#1]% [#2][#3] {\pushmacro\currentnamedsection \edef\currentnamedsection{#1}% - \normalexpanded{\dodostarthead[\currentnamedsection]}} % [#2][#3] + \normalexpanded{\strc_sectioning_start_named_section_indeed[\currentnamedsection]}} % [#2][#3] \unexpanded\def\stopnamedsection - {\normalexpanded{\dostophead[\currentnamedsection]}% + {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}% \popmacro\currentnamedsection} % structure sections (the parents of chapter etc) @@ -169,20 +447,38 @@ \def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option %def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option -% -2=text -1=manual 0=block 1+=structurelevel +% 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). -\newcount\maxstructuredepth +% -2 = text +% -1 = manual +% 0 = block +% +1 = structurelevel 1 .. n -\def\setnextsectionlevel#1% - {\global\advance\maxstructuredepth\plusone - \setevalue{\??headlevel#1}{\the\maxstructuredepth}} +\newcount\maxstructuredepth \def\sectionlevel#1% {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname} +\def\namedsectionlevel#1#2% direct indirect + {\csname\??headlevel + \ifcsname\??headlevel#1\endcsname + #1% + \else\ifcsname\??headlevel#2\endcsname + #2% + \else + \v!none + \fi\fi + \endcsname} + +\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 @@ -190,14 +486,15 @@ {\ifcsname\??headlevel#1\endcsname \else \edef\currentsection{#1}% not used, will go \edef\currenthead{#1}% - \setnextsectionlevel{#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{\noexpand\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child + \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child \fi \xdef\lastsectionname{#1}% \ifx\firstsectionname\empty @@ -206,16 +503,16 @@ \fi} \unexpanded\def\setupsection - {\dotripleempty\dosetupsection} + {\dotripleempty\strc_sectioning_setup} -\def\dosetupsection[#1][#2][#3]% +\def\strc_sectioning_setup[#1][#2][#3]% {\ifcsname\??headlevel#1\endcsname - \dodosetupsection[#1][#2][#3]% + \strc_sectioning_setup_indeed[#1][#2][#3]% \else - \dodosetupsection[\sectionheadsection{#1}][#2][#3]% + \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]% \fi} -\def\dodosetupsection[#1][#2][#3]% +\def\strc_sectioning_setup_indeed[#1][#2][#3]% {\pushmacro\currenthead \ifthirdargument \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now) @@ -251,42 +548,42 @@ % head construction -\unexpanded\def\dohandleheadown{\dodoubleempty\dodohandleheadown} % [ref] {nr} {title} -\unexpanded\def\dohandleheadnop{\dodoubleempty\dodohandleheadnop} % [ref] {title} -\unexpanded\def\dostarthead {\dotripleempty\dodostarthead} % [settings] [userdata] !!! also used at lua end +\unexpanded\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed} % [ref] {nr} {title} +\unexpanded\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed} % [ref] {title} +\unexpanded\def\strc_sectioning_start {\dotripleempty\strc_sectioning_start_named_section_indeed} % [settings] [userdata] !!! also used at lua end \newconditional\currentstructureown \newtoks\everybeforehead % hook, todo: before/after keys \newtoks\everyafterhead % hook, todo: before/after keys -\unexpanded\def\dodohandleheadown[#1][#2]#3#4% +\unexpanded\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4% {\settrue\currentstructureown \triggerautostructurelevel - \dohandlehead{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title -- + \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title -- -\unexpanded\def\dodohandleheadnop[#1][#2]% for taco: [key=value] variant +\unexpanded\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant {\setfalse\currentstructureown \triggerautostructurelevel - \doifassignmentelse{#2}\dodohandleheadnopA\dodohandleheadnopB{#1}{#2}} + \doifassignmentelse{#2}\strc_sectioning_handle_nop_indeed_yes\strc_sectioning_handle_nop_indeed_nop{#1}{#2}} -\unexpanded\def\dodohandleheadnopA#1#2% - {\dohandlehead{#1}{#2}{}} +\unexpanded\def\strc_sectioning_handle_nop_indeed_yes#1#2% + {\strc_sectioning_handle{#1}{#2}{}} -\unexpanded\def\dodohandleheadnopB#1#2#3% - {\dohandlehead{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- +\unexpanded\def\strc_sectioning_handle_nop_indeed_nop#1#2#3% + {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- -\unexpanded\def\dodostarthead[#1][#2][#3]% for the moment no grouping, too annoying with page breaks +\unexpanded\def\strc_sectioning_start_named_section_indeed[#1][#2][#3]% for the moment no grouping, too annoying with page breaks {\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 - \dohandlehead{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here) + \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here) \headparameter\c!insidesection} -\unexpanded\def\dostophead[#1]% !!! also used at lua end +\unexpanded\def\strc_sectioning_stop[#1]% !!! also used at lua end {\dostoptagged \dostoptagged %\globalpopmacro\currenthead % so we do a hard recover @@ -295,70 +592,64 @@ \the\everyafterhead \resetsystemmode\currenthead} % new, also here now -% \unexpanded\def\donexthead[#1][#2][#3]% obsolete -% {\setfalse\currentstructureown -% \xdef\currenthead{#1}% -% \dohandlehead{#1}{#2}{#3}} % name -- -- -- userdata +\let\dostarthead\strc_sectioning_start % used at lua end +\let\dostophead \strc_sectioning_stop % used at lua end % \newconditional\structurereversesectionnumbers % todo: key/val -\newconditional\headtolist -\newconditional\headdoincrement -\newconditional\headdoplace -\newconditional\headleaveempty -\newconditional\headhidden -\newconditional\headshownumber -\newconditional\headisdisplay +\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\headshownumber % public +\newconditional\headisdisplay % public -\setvalue{\??headincrement\v!yes }{\settrue \headdoincrement\settrue \headtolist} -\setvalue{\??headincrement\v!no }{\setfalse\headdoincrement\setfalse\headtolist} -\setvalue{\??headincrement\v!list }{\setfalse\headdoincrement\settrue \headtolist} -\setvalue{\??headincrement\s!empty}{\settrue \headdoincrement\settrue \headtolist} +\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} -\def\setheadincrement +\unexpanded\def\strc_sectioning_initialize_increment {\edef\currentheadincrement{\headparameter\c!incrementnumber}% \ifcsname\??headincrement\currentheadincrement\endcsname \csname\??headincrement\currentheadincrement\endcsname \else - \settrue \headdoincrement\settrue \headtolist + \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list % \filterheadnumber \fi} \def\filterheadnumber - {\settrue\headdoincrement - \settrue\headtolist + {\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\headleaveempty - \settrue \headdoplace - \setfalse\headhidden} + {\setfalse\c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden} \setvalue{\??headplace\v!empty}% - {\settrue \headleaveempty - \settrue \headdoplace - \setfalse\headhidden} + {\settrue \c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden} \setvalue{\??headplace\v!no}% - {\settrue \headleaveempty - \setfalse\headdoplace - \setfalse\headhidden} + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden} \setvalue{\??headplace\v!hidden}% - {\settrue \headleaveempty - \setfalse\headdoplace - \settrue \headhidden} + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \settrue \c_strc_sectioning_hidden} -\def\setheadplacement - {\executeifdefined - {\??headplace\headparameter\c!placehead} - {\getvalue{\??headplace\v!yes}}} - - -\ifdefined\setheaddisplay \else \let\setheaddisplay\relax \fi +\unexpanded\def\strc_sectioning_initialize_placement + {\expandcheckedcsname\??headplace{\headparameter\c!placehead}\v!yes} \newmode\v!sectionnumber @@ -370,12 +661,18 @@ {\resetsystemmode\v!sectionnumber \setfalse\headshownumber} % why ? -\def\setheadnumber - {\doifelse{\sectionblockparameter\c!number}\v!yes % todo - {\doifelse{\headparameter\c!number}\v!yes - {\settrue\headshownumber} - {\setfalse\headshownumber}} - {\setfalse\headshownumber}} +\unexpanded\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} \unexpanded\def\theheadsynchonization {\currentstructuresynchronize} @@ -416,45 +713,15 @@ \let\currentheadlevel \!!zerocount \let\currentheadcounter \!!zerocount -% here we could inherit as well but it's a bit complex - -\def\doregisterhead#1#2#3% name data userdata - {\structurecomponent - %[\c!label={\headparameter\c!label}, % why { } - [\c!label={\headparameter{\currentsectionblock\c!label}}, - \c!incrementnumber=\ifconditional\headdoincrement\v!yes\else\v!no\fi, % not that needed - \c!saveinlist=\ifconditional\headtolist\v!yes\else\v!no\fi, - \c!level=\currentheadlevel, - \c!name=#1, - \c!number=\ifconditional\headdoincrement\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi, - \c!bookmark=, - \c!marking=, - \c!list=, - \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!backreference=, - \c!command=, - #2]% - [#3]% - \reportcurrentstructure} - -\unexpanded\def\placeheadtext {\dosingleempty\strc_sections_place_head_text } % use with care -\unexpanded\def\placeheadnumber{\dosingleempty\strc_sections_place_head_number} % use with care - -\ifdefined\setupheadcomponentfont \else - - \unexpanded\def\setupheadcomponentfont#1#2% +\unexpanded\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care +\unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care + + +\unexpanded\def\strc_sectioning_report{\ctxlua{structures.sections.reportstructure()}} + +\ifdefined\strc_rendering_initialize_style_and_color \else + + \unexpanded\def\strc_rendering_initialize_style_and_color#1#2% {\dontconvertfont \useheadstyleandcolor\c!style\c!color \useheadstyleandcolor#1#2% @@ -462,131 +729,134 @@ \fi -\def\strc_sections_place_head_text[#1]% +\def\strc_sectioning_place_head_text[#1]% {\dontleavehmode \begingroup + \settrue\headisdisplay % triggers interlinespace checking \edef\currenthead{#1}% - \setupheadcomponentfont\c!textstyle\c!textcolor + \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor \relax \getspecificstructuretitle{\thenamedheadlevel{#1}}% \endgraf \endgroup} -\def\strc_sections_place_head_number[#1]% +\def\strc_sectioning_place_head_number[#1]% {\dontleavehmode \begingroup + \settrue\headisdisplay % triggers interlinespace checking \edef\currenthead{#1}% - \setupheadcomponentfont\c!numberstyle\c!numbercolor + \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor \relax \getfullstructurenumber{\thenamedheadlevel{#1}}% \endgraf \endgroup} -\ifdefined\presetnumberheadalternative \else \let\presetnumberheadalternative\relax \fi -\ifdefined\setautostructurelevel \else \let\setautostructurelevel \relax \fi -\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel \relax \fi +\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi -\def\dohandlehead#1#2#3% name data userdata (we can move #1 to the caller) +\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}% % - \setautostructurelevel - \setheadincrement - \setheadplacement - \setheaddisplay - \setheadnumber + %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}% + % + \strc_sectioning_initialize_autolevel + \strc_sectioning_initialize_increment + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + % + \unexpanded\def\\{\space}% messy here % - \unexpanded\def\\{\space}% \flushingcolumnfloatsfalse % % todo: also mark (for header) % % we might remove the lower level % - % not here, after optional \page: \doregisterhead\currenthead{#2}{#3}% + % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}% % % \xdef\currentheadcounter{\currentsectioncountervalue}% lua call % % \currentstructuresynchronize % will move % - \edef\numberheaddistance {\headparameter\c!distance }% compatibility - \edef\numberheadalternative{\headparameter\c!alternative}% compatibility - \presetnumberheadalternative - % \let\getheadnumber\empty \let\getheadtitle \empty \let\getheadsyncs \empty - \ifconditional\headdoincrement - \ifconditional\headdoplace - \doheadspacingbeforeyes - \doregisterhead\currenthead{#2}{#3}% after optional \page + \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 \let\getheadsyncs\theheadsynchonization \let\getheadtitle\fullheadtitle \ifconditional\headshownumber \let\getheadnumber\fullheadnumber - \placecurrentheadnumbertext + \strc_rendering_place_head_number_and_text \else - \placecurrentheadtext + \strc_rendering_place_head_text \fi - \doheadspacingafteryes - \else\ifconditional\headhidden - \doregisterhead\currenthead{#2}{#3}% after optional \page + \strc_sectioning_after_yes + \else\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report \let\getheadsyncs\theheadsynchonization - \placecurrentheadhidden % only something when tracing + \strc_rendering_place_head_hidden % only something when tracing \else - \doheadspacingbeforenop % toegevoegd ivm subpaginanr / tug sheets - \doregisterhead\currenthead{#2}{#3}% after optional \page + \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report \let\getheadsyncs\theheadsynchonization - \placecurrentheadempty % just flush 'm - \doheadspacingafternop + \strc_rendering_place_head_empty % just flush 'm + \strc_sectioning_after_nop \fi\fi \else - \ifconditional\headdoplace - \doheadspacingbeforeyes - \doregisterhead\currenthead{#2}{#3}% after optional \page + \ifconditional\c_strc_sectioning_place + \strc_sectioning_before_yes + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report \let\getheadsyncs\theheadsynchonization \let\getheadtitle\fullheadtitle - \placecurrentheadtext - \doheadspacingafteryes - \else\ifconditional\headhidden - \doregisterhead\currenthead{#2}{#3}% after optional \page + \strc_rendering_place_head_text + \strc_sectioning_after_yes + \else\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report \let\getheadsyncs\theheadsynchonization - \placecurrentheadhidden % only something when tracing + \strc_rendering_place_head_hidden % only something when tracing \else % do nothing / should be vbox to 0pt - \doheadspacingbeforenop - \doregisterhead\currenthead{#2}{#3}% after optional \page + \strc_sectioning_before_nop + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report \let\getheadsyncs\theheadsynchonization - \placecurrentheadempty % just flush 'm - \doheadspacingafternop + \strc_rendering_place_head_empty % just flush 'm + \strc_sectioning_after_nop \fi\fi \fi \flushingcolumnfloatstrue - \setfalse\ignorehandlepagebreak + \setfalse\c_strc_sectioniong_ignore_page % ignorespaces prevents spaces creeping in when after=\dontleavehmode \dostarttagged\t!sectioncontent\empty - \ifconditional\headisdisplay % \ifdisplaysectionhead + \ifconditional\headisdisplay \ignorespaces \else \expandafter\GotoPar \fi} -% typesetting +% typesetting (the getters are public) -\unexpanded\def\placecurrentheadnumbertext +\unexpanded\def\strc_rendering_place_head_number_and_text {\setheadmarking \getheadnumber/\getheadtitle \getheadsyncs} -\unexpanded\def\placecurrentheadtext +\unexpanded\def\strc_rendering_place_head_text {\setheadmarking \getheadtitle \getheadsyncs} -\unexpanded\def\placecurrentheadempty +\unexpanded\def\strc_rendering_place_head_empty {\setheadmarking \getheadsyncs} @@ -596,7 +866,7 @@ % todo: when in the page builder we need to resolve the marking immediately % because otherwise we have an async -\unexpanded\def\placecurrentheadhidden % maybe trialtypesetting check +\unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check {\setxvalue{\??hiddenheadattr\currenthead}% {\headreferenceattributes}% can be used when making a box \setxvalue{\??hiddenheadsync\currenthead}% @@ -625,138 +895,144 @@ % pagebreaks -\newcount\precedingstructurelevel \precedingstructurelevel\plusone -\newconditional\ignorehandlepagebreak +\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 + {\expandcheckedcsname\??headmarknop{\headparameter\c!marking}\s!unknown} + +\def\strc_sectioning_check_layout_yes + {\page[\p_page]% + \expandcheckedcsname\??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_sectioniong_preceding_level \c_strc_sectioniong_preceding_level\plusone +\newconditional\c_strc_sectioning_auto_break \settrue\c_strc_sectioning_auto_break +\newconditional\c_strc_sectioniong_ignore_page +\newsignal \s_strc_sectioniong_continuous_signal -\def\doheadspacingbeforeyes - {\docheckheadbefore - \dohandleheadpagebreakyes +\unexpanded\def\strc_sectioning_inject_continuous_signal + {\ifhmode + \hskip\s_strc_sectioniong_continuous_signal\relax + \fi} + +\def\strc_sectioning_before_yes + {\strc_sectioning_check_before\strc_sectioning_handle_page_yes \headparameter\c!inbetween \dostarttagged\t!section\currenthead} -\def\doheadspacingbeforenop - {\docheckheadbefore - \dohandleheadpagebreaknop +\def\strc_sectioning_before_nop + {\strc_sectioning_check_before\strc_sectioning_handle_page_nop \headparameter\c!inbetween \dostarttagged\currenthead\empty} -\def\emptyheadcorrection - {\ifconditional\headleaveempty % inlined \emptyheadcorrection (with after=\blank) - \penalty10000 % first ... we need to adapt this all to vspacing +\def\strc_sectioning_empty_correction + {\ifconditional\c_strc_sectioning_empty + % this needs checking + \penalty\plustenthousand \vskip-\lineheight \kern\zeropoint \prevdepth\strutdepth \fi} -\def\doheadspacingafteryes +\def\strc_sectioning_after_yes {\ifconditional\headisdisplay - \dosomebreak\nobreak % needs to be adapted to vspacing - \emptyheadcorrection + \ifconditional\c_strc_sectioning_auto_break + \vspacing[\v!samepage-\currentheadlevel]% + \fi + \strc_sectioning_empty_correction \headparameter\c!after \fi} -\def\doheadspacingafternop +\def\strc_sectioning_after_nop {} -\newsignal\continuousheadsignal - -\def\docheckheadbefore#1% +\def\strc_sectioning_check_before#1% {\ifhmode - \scratchcounter\lastpenalty\unpenalty % no beauty in this - \ifdim\lastskip=\continuousheadsignal + \scratchcounter\lastpenalty + \unpenalty % no beauty in this + \ifdim\lastskip=\s_strc_sectioniong_continuous_signal % no page break - \ifconditional\ignorehandlepagebreak - \setfalse\ignorehandlepagebreak + \ifconditional\c_strc_sectioniong_ignore_page + \setfalse\c_strc_sectioniong_ignore_page \else - \global\precedingstructurelevel\currentheadlevel + \global\c_strc_sectioniong_preceding_level\currentheadlevel \nobreak \fi - \global\settrue\continuoussectionhead + \global\settrue\c_strc_rendering_continuous \else \penalty\scratchcounter - \global\setfalse\continuoussectionhead + \global\setfalse\c_strc_rendering_continuous #1% \fi \else - \global\setfalse\continuoussectionhead + \global\setfalse\c_strc_rendering_continue #1% \fi} -\def\dodocheckheadlayout#1#2% - {\doifelselayouttextline{#1} - {\doifsomething{\headparameter#2}{\expanded{\setuplayouttext[#1][\c!state=\headparameter#2]}}} - \donothing} - -\setvalue{\??headmarknop\v!page }{} -\setvalue{\??headmarknop\v!reset}{\resetcurrentstructuremarks} -\setvalue{\??headmarkyes\v!page }{} % to be checked: {\resetcurrentstructuremarks} -\setvalue{\??headmarkyes\v!reset}{\resetcurrentstructuremarks} - -\def\docheckheadlayout - {\doifelsenothing{\headparameter\c!page} - {\getvalue{\??headmarknop\headparameter\c!marking}} - {\page[\headparameter\c!page]% - \getvalue{\??headmarkyes\headparameter\c!marking}% - \dodocheckheadlayout\v!header\c!header - \dodocheckheadlayout\v!text \c!text - \dodocheckheadlayout\v!footer\c!footer}} - \def\currentsectioncountervalue {\ctxlua{structures.sections.depthnumber(\thenamedheadlevel\currenthead)}} \def\previoussectioncountervalue{\ctxlua{structures.sections.depthnumber(\thenamedheadlevel\currenthead-1)}} -\def\dohandleheadpagebreaknop - {\doifelse{\headparameter\c!continue}\v!yes - {\ifnum\previoussectioncountervalue=\zerocount - \docheckheadlayout - \else\ifnum\currentsectioncountervalue>\zerocount - \docheckheadlayout - \fi\fi}% - {\docheckheadlayout}} +\def\strc_sectioning_handle_page_nop + {\edef\p_continue{\headparameter\c!continue}% + \ifx\p_continue\v!yes + \ifnum\previoussectioncountervalue=\zerocount + \strc_sectioning_check_layout + \else\ifnum\currentsectioncountervalue>\zerocount + \strc_sectioning_check_layout + \fi\fi + \else + \strc_sectioning_check_layout + \fi} -\def\dohandleheadpagebreakyes +\def\strc_sectioning_handle_page_yes {%[[\currenthead @\thenamedheadlevel\currenthead/prev:\previoussectioncountervalue/curr:\currentsectioncountervalue]] - \ifconditional\ignorehandlepagebreak - \setfalse\ignorehandlepagebreak + \ifconditional\c_strc_sectioniong_ignore_page + \setfalse\c_strc_sectioniong_ignore_page \else -% \ifnum\lastpenalty>\zerocount -% \global\pagebreakdisabledtrue -% \fi % beware, these numbers are not yet know here - \doifelse{\headparameter\c!continue}\v!yes - {\ifnum\previoussectioncountervalue=\zerocount - \docheckheadlayout - \else\ifnum\currentsectioncountervalue>\zerocount - \docheckheadlayout - \fi\fi}% - {\docheckheadlayout}% - \doifnot{\headparameter\c!aligntitle}\v!float\page_otr_command_flush_side_floats - \headparameter\c!before - \relax -% \ifpagebreakdisabled -% \global\pagebreakdisabledfalse -% \else -% \dopreventbreakafterheadauto % not ok as it binds the prev par -% \fi - \doif{\headparameter\c!aligntitle}\v!float\indent - \global\precedingstructurelevel\currentheadlevel - \fi} - -\settrue\autoheadbreak % todo: \vspacing[category:8] == keep_together - -\def\dopreventbreakafterheadauto % used after \c!before - {\ifconditional\autoheadbreak - \vspacing[\v!samepage-\currentheadlevel]% + \strc_sectioning_handle_page_nop + \edef\p_aligntitle{\headparameter\c!aligntitle}% + \ifx\p_aligntitle\v!float + \headparameter\c!before\relax + \indent + \else + \page_otr_command_flush_side_floats + \headparameter\c!before\relax + \fi + \global\c_strc_sectioniong_preceding_level\currentheadlevel \fi} -\def\dopreventbreakafterheadspec#1% see enumerations etc - {\ifconditional\autoheadbreak - \vspacing[\v!samepage-\the\numexpr\currentheadlevel+1\relax]% todo #1 +\unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con + {\ifconditional\c_strc_sectioning_auto_break + \vspacing[\v!samepage-\the\numexpr\currentheadlevel+\ifx#1\empty\plusone\else#1\fi\relax]% \fi} -\def\dohandlepagebreakX{\dopreventbreakafterheadspec} % no \let so we can redefine - -% we do support negative numbers but it can have side effects that we won't -% catch +% 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} @@ -765,9 +1041,9 @@ {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}} \unexpanded\def\setupheadnumber - {\dodoubleargument\dosetupheadnumber} + {\dodoubleargument\strc_sectioning_setup_number} -\def\dosetupheadnumber[#1][#2]% todo: reset if at other level +\def\strc_sectioning_setup_number[#1][#2]% todo: reset if at other level {\setstructurenumber{\thenamedheadlevel{#1}}{#2}} \def\currentheadnumber{0} % ==> \currentheadnumber @@ -781,15 +1057,15 @@ \def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}} \unexpanded\def\headnumber - {\dodoubleempty\doheadnumber} + {\dodoubleempty\strc_sectioning_number} -\def\doheadnumber[#1][#2]% simple case is just a number +\def\strc_sectioning_number[#1][#2]% simple case is just a number {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}} -\def\someheadnumber - {\dodoubleempty\dosomeheadnumber} +\unexpanded\def\someheadnumber + {\dodoubleempty\strc_sectioning_number_some} -\def\dosomeheadnumber[#1][#2]% +\def\strc_sectioning_number_some[#1][#2]% {\dontleavehmode \begingroup \edef\currenthead{#1}% @@ -807,22 +1083,22 @@ % experimental -\newconditional\c_strc_sections_auto_levels +\newconditional\c_strc_sectioning_auto_levels \appendtoks - \settrue\c_strc_sections_auto_levels + \settrue\c_strc_sectioning_auto_levels \to \everyenableelements -\def\setautostructurelevel - {\ifconditional\c_strc_sections_auto_levels +\unexpanded\def\strc_sectioning_initialize_autolevel + {\ifconditional\c_strc_sectioning_auto_levels \ctxcommand{autonextstructurelevel(\number\currentheadlevel)}% - \global\setfalse\c_strc_sections_auto_levels + \global\setfalse\c_strc_sectioning_auto_levels \fi} -\def\triggerautostructurelevel - {\global\settrue\c_strc_sections_auto_levels} +\unexpanded\def\triggerautostructurelevel + {\global\settrue\c_strc_sectioning_auto_levels} -\def\finalizeautostructurelevels +\unexpanded\def\finalizeautostructurelevels {\ctxcommand{autofinishstructurelevels()}} \unexpanded\def\finalizeautostructurelevel diff --git a/tex/context/base/strc-syn.lua b/tex/context/base/strc-syn.lua index c2b5251d0..ca4b3ac18 100644 --- a/tex/context/base/strc-syn.lua +++ b/tex/context/base/strc-syn.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['str-syn'] = { +if not modules then modules = { } end modules ['strc-syn'] = { version = 1.001, comment = "companion to str-syn.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/strc-syn.mkiv b/tex/context/base/strc-syn.mkiv index 535eab04b..e0087d450 100644 --- a/tex/context/base/strc-syn.mkiv +++ b/tex/context/base/strc-syn.mkiv @@ -65,8 +65,8 @@ %\c!headcolor=, %\c!criterium=, \c!location=\v!left, - \c!width=5em, - \c!distance=0pt, + \c!width=5\emwidth, + \c!distance=\zeropoint, %\c!sample=, %\c!hang=, %\c!align=, diff --git a/tex/context/base/strc-tag.lua b/tex/context/base/strc-tag.lua index 78b807487..7e5c6f993 100644 --- a/tex/context/base/strc-tag.lua +++ b/tex/context/base/strc-tag.lua @@ -161,6 +161,7 @@ local properties = allocate { metadata = { pdf = "Div", nature = "display" }, metavariable = { pdf = "Span", nature = "mixed" }, + mid = { pdf = "Span", nature = "inline" }, sub = { pdf = "Span", nature = "inline" }, sup = { pdf = "Span", nature = "inline" }, subsup = { pdf = "Span", nature = "inline" }, diff --git a/tex/context/base/strc-tag.mkiv b/tex/context/base/strc-tag.mkiv index 84d6fb2d3..6563e884e 100644 --- a/tex/context/base/strc-tag.mkiv +++ b/tex/context/base/strc-tag.mkiv @@ -126,6 +126,7 @@ \def\t!ignore {ignore} % Span +\def\t!mid {mid} % Span \def\t!sub {sub} % Span \def\t!sup {sup} % Span \def\t!subsup {subsup} % Span @@ -332,4 +333,12 @@ \unexpanded\def\settaggedmetadata[#1]% {\ctxlua{structures.tags.registermetadata(\!!bs#1\!!es)}} +%D An overload: + +\let\strc_tagged_saved_bpar\bpar +\let\strc_tagged_saved_epar\epar + +\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar} +\unexpanded\def\epar{\strc_tagged_saved_epar\dostoptagged} + \protect diff --git a/tex/context/base/supp-ali.mkiv b/tex/context/base/supp-ali.mkiv deleted file mode 100644 index 54a7b77e4..000000000 --- a/tex/context/base/supp-ali.mkiv +++ /dev/null @@ -1,173 +0,0 @@ -%D \module -%D [ file=supp-ali, -%D version=2000.04.17, -%D title=\CONTEXT\ Support Macros, -%D subtitle=Alignment, -%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 Yet undocumented. - -% 0 = centered -% 1 = left in before -% 2 = right in before -% 3 = left in after -% 4 = right in after - -\unprotect - -% \starttabulate[|cg{.}|cg{,}|cg{,}|] -% \NC period \NC comma \NC comma \NC\NR -% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR -% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR -% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR -% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR -% \NG 10\\ \NG 10\\ \NG 0,00 \NC\NR -% \NG 10 \NG 10 \NG 0,00 \NC\NR -% \NG 10 \NG 10 \NG 0,00 \NC\NR -% \stoptabulate - -\chardef\characteralignmentmode=4 -\chardef\characteralignmentslot=1 - -\newtoks\@@characteralignlst - -\let\afterassignwidth \!!zeropoint -\let\beforeassignwidth\!!zeropoint - -\def\alignmentcharacter{.} - -\let\alignmentclass\s!default % can be used to handle multiple mixed ones - -\def\setfirstpasscharacteralign - {\popcharacteralign - \expanded{\dosetfirstpasscharacteralign{\alignmentcharacter}}} - -\def\dosetfirstpasscharacteralign#1% - {\def\checkalignment##1% - {\popcharacteralign - \let\\\empty - \setbox\scratchbox\hbox{#1}% - \edef\characterassignwidth{\the\wd\scratchbox}% - \setbox\scratchbox\emptyhbox - \docheckalignment##1#1\relax\relax - \scratchdimen-\wd\scratchbox - \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% - \advance\scratchdimen \wd\scratchbox - \ifdim\scratchdimen>\beforeassignwidth\relax - \edef\beforeassignwidth{\the\scratchdimen}% - \fi - \ifdim\scratchdimen=\zeropoint - \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% - \scratchdimen\wd\scratchbox - \ifcase\characteralignmentmode - % do nothing - \else\ifnum\characteralignmentmode<\plusthree - \advance\scratchdimen \characterassignwidth - \ifdim\scratchdimen>\beforeassignwidth\relax - \edef\beforeassignwidth{\the\scratchdimen}% - \fi - \else - \ifdim\scratchdimen>\afterassignwidth\relax - \edef\afterassignwidth{\the\scratchdimen}% - \fi - \fi\fi - \fi - \pushcharacteralign}% - \def\docheckalignment##1#1##2##3\relax - {\ifx##2\relax - \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% - \ifdim\wd\scratchbox>\afterassignwidth - \edef\afterassignwidth{\the\wd\scratchbox}% - \fi - \else - \docheckalignment##2##3\relax\relax - \fi}} - -\def\setsecondpasscharacteralign - {\popcharacteralign - \expanded{\dosetsecondpasscharacteralign{\alignmentcharacter}}} - -\def\dosetsecondpasscharacteralign#1% - {\def\checkalignment##1% - {\popcharacteralign - \let\\\empty % beware, no grouping - \setbox\scratchbox\hbox{#1}% - \edef\characterassignwidth{\the\wd\scratchbox}% - \setbox\scratchbox\emptyhbox - % new 12,34 vs 10\\ where 10 aligns on 12 if #1 = , - \ifcase\characteralignmentslot - \docheckalignment##1#1\relax\relax - \scratchdimen\wd\scratchbox - \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% - \else - \def\\{#1}% - \expanded{\docheckalignment##1#1\relax\relax}% - \scratchdimen\wd\scratchbox - \setbox\scratchbox\hbox{\def\\{\hphantom{#1}}\ignorespaces##1\unskip}% - \fi - \noindent - \ifdim\scratchdimen=\wd\scratchbox - \ifcase\characteralignmentmode - \box\scratchbox - \else - \hbox - {\dontcomplain - \hbox to \beforeassignwidth - {\ifcase\characteralignmentmode\or - \box\scratchbox\hss - \or - \hss\box\scratchbox\hskip\characterassignwidth - \or - \hss\rlap{\box\scratchbox}% - \or - \hss\rlap{\hbox to \afterassignwidth{\hss\box\scratchbox}}% - \fi}% - \hskip\afterassignwidth}% - \fi - \else - \hbox - {\hbox to \beforeassignwidth - {\hss\box\scratchbox\hskip-\scratchdimen}% - \hskip\afterassignwidth}% - \fi}% - \def\docheckalignment##1#1##2##3\relax - {\ifx##2\relax - \setbox\scratchbox\hbox{\ignorespaces##1\unskip}% - \else - \docheckalignment##2##3\relax\relax - \fi}} - -% provide a means to use multiple alignments mixed - -\def\pushcharacteralign - {\ifcsname @cac@\alignmentclass\endcsname\else - \doglobal\appendetoks\noexpand\do{\alignmentclass}\to\@@characteralignlst - \fi - \setxvalue{@cac@\alignmentclass}{\noexpand\do - {\afterassignwidth}{\beforeassignwidth}{\alignmentcharacter}}} - -\def\popcharacteralign - {\def\do##1##2##3% - {\def\afterassignwidth {##1}% - \def\beforeassignwidth {##2}% - \def\alignmentcharacter{##3}}% - \executeifdefined{@cac@\alignmentclass}\donothing} - -\def\resetcharacteralign % does not work well nested - {\def\do##1{\global\letbeundefined{@cac@##1}}% global ! - \the\@@characteralignlst - \global\@@characteralignlst\emptytoks} - -\long\def\startcharacteralign#1\stopcharacteralign - {\bgroup - \setfirstpasscharacteralign #1% - \setsecondpasscharacteralign#1% - \egroup} - -\protect \endinput diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua index 853de4cbe..c7382834a 100644 --- a/tex/context/base/supp-box.lua +++ b/tex/context/base/supp-box.lua @@ -10,6 +10,9 @@ if not modules then modules = { } end modules ['supp-box'] = { local report_hyphenation = logs.reporter("languages","hyphenation") +local tex, node = tex, node +local context, commands, nodes = context, commands, nodes + local nodecodes = nodes.nodecodes local disc_code = nodecodes.disc @@ -19,6 +22,7 @@ local glue_code = nodecodes.glue local glyph_code = nodecodes.glyph local new_penalty = nodes.pool.penalty + local free_node = node.free local copynodelist = node.copy_list local copynode = node.copy @@ -65,10 +69,9 @@ local function applytochars(list,what,nested) while current do local id = current.id if nested and (id == hlist_code or id == vlist_code) then - context.hbox() - context.bgroup() + context.beginhbox() applytochars(current.list,what,nested) - context.egroup() + context.endhbox() elseif id ~= glyph_code then noaction(copynode(current)) else @@ -92,8 +95,7 @@ local function applytowords(list,what,nested) end noaction(copynode(current)) elseif nested and (id == hlist_code or id == vlist_code) then - context.hbox() - context.bgroup() + context.beginhbox() applytowords(current.list,what,nested) context.egroup() elseif not start then diff --git a/tex/context/base/supp-box.mkiv b/tex/context/base/supp-box.mkiv index de1da677a..a8774e482 100644 --- a/tex/context/base/supp-box.mkiv +++ b/tex/context/base/supp-box.mkiv @@ -75,9 +75,10 @@ %D core macros \type {\strutdepth} and alike, which are %D values. -\def\strutdp{\dp\strutbox} -\def\strutht{\ht\strutbox} -\def\strutwd{\wd\strutbox} +\def\strutdp {\dp\strutbox} +\def\strutht {\ht\strutbox} +\def\strutwd {\wd\strutbox} +\def\struthtdp{\dimexpr\ht\strutbox+\dp\strutbox\relax} %D \macros %D {voidbox,nextbox} @@ -1236,7 +1237,7 @@ \ifdone \else \parfillskip\zeropoint \rightskip\zeropoint - \hskip\zeropoint \!!plus 1\!!fill % \hsize + \hskip\zeropoint \s!plus 1\s!fill % \hsize \fi \unhcopy0}% \ifdim\ht\nextbox>\strutht @@ -1423,12 +1424,27 @@ {\setbox\nextbox\hbox {\strut \dp\nextbox\zeropoint - \lower\strutdepth\box\nextbox}% - \dp\nextbox\strutdepth - \ht\nextbox\strutheight + \lower\strutdp\box\nextbox}% + \dp\nextbox\strutdp + \ht\nextbox\strutht \box\nextbox \egroup} +%D A variant on this: + +\unexpanded\def\inlinedbox + {\bgroup + \dowithnextbox + {\setbox\nextbox\hbox + {\lower + \dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax + \box\nextbox}% + \ht\nextbox\strutht + \dp\nextbox\strutdp + \box\nextbox + \egroup}% + \hbox} + %D \macros %D {struttedbox} %D @@ -1513,8 +1529,8 @@ \bgroup \dontcomplain \forgetall - \setbox0\hbox{\vrule\!!width \zeropoint#1}% - \setbox2\vbox{\hrule\!!height\zeropoint#1}% + \setbox0\hbox{\vrule\s!width \zeropoint#1}% + \setbox2\vbox{\hrule\s!height\zeropoint#1}% \advance\vsize \ht2 \advance\hsize \wd0 \vbox to \vsize @@ -1573,9 +1589,9 @@ {\bgroup \dowithnextbox {\setlocalhsize - \setbox\scratchbox\hbox{\vrule\!!width \zeropoint#1}% + \setbox\scratchbox\hbox{\vrule\s!width \zeropoint#1}% \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi - \setbox\scratchbox\vbox{\hrule\!!height\zeropoint#1}% + \setbox\scratchbox\vbox{\hrule\s!height\zeropoint#1}% \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi \vbox to \vsize{\vss\hbox to \hsize{\hss\box\nextbox\hss}\vss}% \egroup}% @@ -1791,7 +1807,7 @@ \ifvoid\unhhedbox \exitloop \else - \hskip\zeropoint \!!plus \zeropoint + \hskip\zeropoint \s!plus \zeropoint \fi}% \egroup} @@ -2169,7 +2185,7 @@ \newbox\fakedboxcursor \setbox\fakedboxcursor\hbox - {\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint} + {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} \unexpanded\def\boxcursor % overloaded in core-vis {\iftraceboxplacement @@ -2178,9 +2194,9 @@ \setbox\scratchbox\hbox to \zeropoint {\hss \vrule - \!!width \scratchdimen - \!!height\scratchdimen - \!!depth \scratchdimen + \s!width \scratchdimen + \s!height\scratchdimen + \s!depth \scratchdimen \hss}% \smashedbox\scratchbox \egroup @@ -2431,15 +2447,14 @@ %D \macros %D {makestrutofbox} %D -%D This macro sets the dimensions of a box to those of a -%D strut. +%D This macro sets the dimensions of a box to those of a strut. \def\domakestrutofbox {\ht\c_boxes_register\strutht \dp\c_boxes_register\strutdp \wd\c_boxes_register\zeropoint} -\unexpanded\def\makestrutofbox +\unexpanded\def\makestrutofbox % not used {\afterassignment\domakestrutofbox\c_boxes_register} %D \macros @@ -2615,6 +2630,21 @@ % \showboxbreadth\maxdimen % \showboxdepth \maxdimen +%D Moved from cont-new: +%D +%D \starttyping +%D \minimalhbox 100pt {test} +%D \stoptyping + +\unexpanded\def\minimalhbox#1#% + {\dowithnextbox + {\bgroup + \setbox\scratchbox\hbox#1{\hss}% + \ifdim\wd\nextbox<\wd\scratchbox\wd\nextbox\wd\scratchbox\fi + \box\nextbox + \egroup} + \hbox} + \protect \endinput % a bit of test code: diff --git a/tex/context/base/supp-mat.mkiv b/tex/context/base/supp-mat.mkiv index bc26611ae..f77ee3454 100644 --- a/tex/context/base/supp-mat.mkiv +++ b/tex/context/base/supp-mat.mkiv @@ -51,32 +51,27 @@ \let\normalstartimath \Ustartmath \let\normalstopimath \Ustopmath \let\normalstartdmath \Ustartdisplaymath -\let\normalstopdmath \Ustopmath +\let\normalstopdmath \Ustopdisplaymath + \def\normalmathaligntab{&} % \let\normalmathaligntab\aligntab does to work well in a let to & (a def works ok) -\let\normalsuper \Usuperscript % obsolete -\let\normalsuber \Usubscript % obsolete -\let\startimath \Ustartmath % obsolete, less safe -\let\stopimath \Ustopmath % obsolete, less safe -\let\startdmath \Ustartdisplaymath % obsolete, less safe -\let\stopdmath \Ustopmath % obsolete, less safe +\let\normalsuper \Usuperscript % obsolete +\let\normalsuber \Usubscript % obsolete + +\let\startimath \Ustartmath +\let\stopimath \Ustopmath +\let\startdmath \Ustartdisplaymath +\let\stopdmath \Ustopmath \unexpanded\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi} \unexpanded\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi} \unexpanded\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi} \unexpanded\def\textmath #1{\dontleavehmode\ifmmode#1\else\begingroup\everymath\emptytoks\normalstartimath#1\normalstopimath\endgroup\fi} % \mathsurround\zeropoint -\let\m\mathematics % unexpanded? +\let\m\mathematics \let\stopmathmode\relax -% \unexpanded\def\startmathmode % cannot be used nested -% {\relax\ifmmode -% \let\stopmathmode\relax -% \else -% \normalstartimath\let\stopmathmode\normalstopimath -% \fi} - \unexpanded\def\startmathmode % nested variant {\relax\ifmmode \begingroup @@ -96,7 +91,12 @@ %D %D An example of usage of the following can be found in the MathML module: -\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\dostartformula{}#1\dostopformula\fi} +\ifdefined\strc_formulas_start_formula \else + \def\strc_formulas_start_formula{\normalstartdmath} + \def\strc_formulas_stop_formula {\normalstopdmath } +\fi + +\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\strc_formulas_start_formula{}#1\strc_formulas_stop_formula\fi} \unexpanded\def\inlinemathematics {\dontleavehmode\mathematics} \unexpanded\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi} @@ -128,7 +128,8 @@ \def\dimensionhalfspace {\,} \unexpanded\def\dimension#1% - {\def\dodimensionsignal{\kern\dimensionsignal}% + {\pushmacro\dodimensionsignal + \gdef\dodimensionsignal{\kern\dimensionsignal}% \ifdim\lastskip=\zeropoint\relax \ifdim\lastkern=\zeropoint\relax \ifmmode @@ -144,70 +145,16 @@ \else \unskip\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}% \fi - \dodimensionsignal} + \dodimensionsignal + \popmacro\dodimensionsignal} \unexpanded\def\nodimension#1% {\unskip#1\global\let\dodimensionsignal\relax} -% %D \macros -% %D {super, suber} -% %D -% %D \TEX\ uses \type{^} and \type{_} for entering super- and -% %D subscript mode. We want however a bit more control than -% %D normally provided, and therefore provide \type {\super} -% %D and \type{\suber} (\type {\sub} is already taken). -% -% \global\let\normalsuper=\normalsuperscript % will become obsolete -% \global\let\normalsuber=\normalsubscript % will become obsolete -% -% \newcount\supersubmode -% -% \newevery\everysupersub \EverySuperSub -% -% \appendtoks \advance\supersubmode\plusone \to \everysupersub -% -% \def\super#1{\normalsuperscript{\the\everysupersub#1}} -% \def\suber#1{\normalsubscript {\the\everysupersub#1}} -% -% %D \macros -% %D {enablesupsub} -% %D -% %D We can let \type {^} and \type {_} act like \type {\super} -% %D and \type {\suber} by saying \type {\enablesupsub}. -% -% \bgroup -% \catcode\circumflexasciicode\activecatcode -% \catcode\underscoreasciicode\activecatcode -% \gdef\enablesupsub -% {\catcode\circumflexasciicode\activecatcode -% \catcode\underscoreasciicode\activecatcode -% \def^{\ifmmode\expandafter\super\else\expandafter\normalsuper\fi}% -% \def_{\ifmmode\expandafter\suber\else\expandafter\normalsuber\fi}} -% \egroup -% -% %D \macros -% %D {restoremathstyle} -% %D -% %D We can pick up the current math style by calling \type -% %D {\restoremathstyle}. -% -% \def\restoremathstyle -% {\ifmmode -% \ifcase\supsubmode -% \textstyle -% \or -% \scriptstyle -% \else -% \scriptscriptstyle -% \fi -% \fi} - %D \macros %D {cramped} %D -%D \TEX provides no primitive to force in cramped math mode. Here is -%D a macro that does so. It is based on a solution by Don Knuth (\useurl -%D {http://www.ctan.org/tex-archive/digests/tex-implementors/042}). +%D Cramped math: %D %D \startbuffer %D \ruledhbox{$\left\{{x^2\over y^2}\right\}$} @@ -245,25 +192,47 @@ % \ht\scratchbox-\scratchdimen % \box\scratchbox} -\def\math_cramped#1#2% +% mkii: +% +% \def\math_cramped#1#2% +% {\begingroup % added HH, made even more cramped +% \setbox\scratchbox\hbox +% {\nulldelimiterspace\zeropoint +% \normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}% +% \ht\scratchbox-\dimexpr +% \ifx#1\displaystyle +% \fontdimen\pluseight\textfont\plusthree +% +.25\fontdimen\plusfive\textfont\plustwo +% \else +% 1.25\fontdimen\pluseight +% \ifx#1\textstyle +% \textfont +% \else\ifx#1\scriptstyle +% \scriptfont +% \else +% \scriptscriptfont +% \fi \fi +% \plusthree +% \fi +% -\ht\scratchbox +% \relax +% \box\scratchbox +% \endgroup} + +\def\math_cramped#1#2% we have all in one family {\begingroup % added HH, made even more cramped \setbox\scratchbox\hbox {\nulldelimiterspace\zeropoint \normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}% \ht\scratchbox-\dimexpr \ifx#1\displaystyle - \fontdimen8\textfont3 - +.25\fontdimen5\textfont2 + \fontdimen\pluseight\textfont\plusone + + .25\fontdimen\plusfive \textfont\plusone \else - 1.25\fontdimen8 - \ifx#1\textstyle - \textfont - \else\ifx#1\scriptstyle - \scriptfont - \else - \scriptscriptfont - \fi \fi - \plusthree + 1.25\fontdimen\pluseight + \ifx#1\textstyle \textfont \else + \ifx#1\scriptstyle\scriptfont \else + \scriptscriptfont\fi\fi \plusone \fi -\ht\scratchbox \relax @@ -305,7 +274,7 @@ % experiment, not yet to be used -% \def\displaybreak +% \unexpanded\def\displaybreak % {\ifhmode % \removeunwantedspaces % \ifcase\raggedstatus\hfill\fi diff --git a/tex/context/base/supp-ran.lua b/tex/context/base/supp-ran.lua index 75202f696..7997db8f6 100644 --- a/tex/context/base/supp-ran.lua +++ b/tex/context/base/supp-ran.lua @@ -6,32 +6,34 @@ if not modules then modules = { } end modules ['supp-ran'] = { license = "see context related readme files" } --- We cannot ask for the current seed, so we need some messy hack --- here. +-- We cannot ask for the current seed, so we need some messy hack here. local report_system = logs.reporter("system","randomizer") -commands = commands or { } -local commands = commands - local math = math +local context, commands = context, commands + local random, randomseed, round, seed, last = math.random, math.randomseed, math.round, false, 1 -function math.setrandomseedi(n,comment) +local maxcount = 2^30-1 -- 1073741823 + +local function setrandomseedi(n,comment) if not n then ---~ n = 0.5 -- hack + -- n = 0.5 -- hack end if n <= 1 then - n = n*1073741823 -- maxcount + n = n * maxcount end n = round(n) if false then report_system("setting seed to %s (%s)",n,comment or "normal") end randomseed(n) - last = random(0,1073741823) -- we need an initial value + last = random(0,maxcount) -- we need an initial value end +math.setrandomseedi = setrandomseedi + function commands.getrandomcounta(min,max) last = random(min,max) context(last) @@ -44,7 +46,7 @@ end function commands.setrandomseed(n) last = n - math.setrandomseedi(n) + setrandomseedi(n) end function commands.getrandomseed(n) @@ -54,10 +56,9 @@ end -- maybe stack function commands.freezerandomseed(n) - -- print("<<<<",seed,last) if seed == false or seed == nil then seed = last - math.setrandomseedi(seed,"freeze",seed) + setrandomseedi(seed,"freeze",seed) end if n then randomseed(n) @@ -65,9 +66,8 @@ function commands.freezerandomseed(n) end function commands.defrostrandomseed() - -- print(">>>>",seed,last) if seed ~= false then - math.setrandomseedi(seed,"defrost",seed) -- was last (bug) + setrandomseedi(seed,"defrost",seed) -- was last (bug) seed = false end end diff --git a/tex/context/base/supp-ran.mkiv b/tex/context/base/supp-ran.mkiv index 356ed580f..f5466a0e1 100644 --- a/tex/context/base/supp-ran.mkiv +++ b/tex/context/base/supp-ran.mkiv @@ -18,8 +18,8 @@ \registerctxluafile{supp-ran}{1.001} -\unexpanded\def\getrandomcount #1#2#3{#1=\ctxcommand{getrandomcounta(\number#2,\number#3)}} -\unexpanded\def\getrandomdimen #1#2#3{#1=\ctxcommand{getrandomcounta(\number\dimexpr#2,\number\dimexpr#3)}\scaledpoint} +\unexpanded\def\getrandomcount #1#2#3{#1=\ctxcommand{getrandomcounta(\number#2,\number#3)}\relax} +\unexpanded\def\getrandomdimen #1#2#3{#1=\ctxcommand{getrandomcounta(\number\dimexpr#2,\number\dimexpr#3)}\scaledpoint\relax} \unexpanded\def\getrandomnumber#1#2#3{\edef#1{\ctxcommand{getrandomcounta(\number#2,\number#3)}}} \unexpanded\def\getrandomfloat #1#2#3{\edef#1{\ctxcommand{getrandomcountb(\number\dimexpr#2\points,\number\dimexpr#3\points)}}} \unexpanded\def\setrandomseed #1{\ctxcommand{setrandomseed(\number#1)}} diff --git a/tex/context/base/supp-vis.mkiv b/tex/context/base/supp-vis.mkiv index 1b0253162..de7c4288d 100644 --- a/tex/context/base/supp-vis.mkiv +++ b/tex/context/base/supp-vis.mkiv @@ -96,8 +96,7 @@ %D off with \type{\dontinterfere}. \unexpanded\def\dontinterfere % or maybe just forgetall - {\everypar \emptytoks - \let\par \endgraf + {\reseteverypar \parindent\zeropoint \parskip \zeropoint \leftskip \zeropoint @@ -186,12 +185,12 @@ %D offers \type{\hfilneg} and \type{\vfilneg}, we define our %D own alternative double \type{ll}'ed ones. -\def\hfilneg {\normalhskip\zeropoint\!!plus-1fil\relax} -\def\vfilneg {\normalvskip\zeropoint\!!plus-1fil\relax} -\def\hfillneg {\normalhskip\zeropoint\!!plus-1fill\relax} -\def\vfillneg {\normalvskip\zeropoint\!!plus-1fill\relax} -\def\hfilllneg{\normalhskip\zeropoint\!!plus-1filll\relax} -\def\vfilllneg{\normalvskip\zeropoint\!!plus-1filll\relax} +\def\hfilneg {\normalhskip\zeropoint\s!plus-1\s!fil\relax} +\def\vfilneg {\normalvskip\zeropoint\s!plus-1\s!fil\relax} +\def\hfillneg {\normalhskip\zeropoint\s!plus-1\s!fill\relax} +\def\vfillneg {\normalvskip\zeropoint\s!plus-1\s!fill\relax} +\def\hfilllneg{\normalhskip\zeropoint\s!plus-1\s!filll\relax} +\def\vfilllneg{\normalvskip\zeropoint\s!plus-1\s!filll\relax} %D \macros %D {normalhss,normalhfil,normalhfill, @@ -323,14 +322,14 @@ {\dontcomplain \normaloffinterlineskip \visualhrule - \!!height\boxrulewidth - \iftoprule\else\!!width\zeropoint\fi + \s!height\boxrulewidth + \iftoprule\else\s!width\zeropoint\fi \normalvskip-\boxrulewidth \normalhbox to \boxrulewd {\visualvrule - \!!height\boxruleht - \!!depth \boxruledp - \!!width \ifleftrule\boxrulewidth\else\zeropoint\fi + \s!height\boxruleht + \s!depth \boxruledp + \s!width \ifleftrule\boxrulewidth\else\zeropoint\fi \ifdim\boxruleht>\zeropoint \else \baselinerulefalse \fi \ifdim\boxruledp>\zeropoint \else \baselinerulefalse \fi \ifbaselinerule @@ -340,23 +339,23 @@ \cleaders \ifbaselinefill \visualhrule - \!!height\boxrulewidth + \s!height\boxrulewidth \else \normalhbox {\normalhskip2.5\boxrulewidth \visualvrule - \!!height\boxrulewidth - \!!width5\boxrulewidth + \s!height\boxrulewidth + \s!width5\boxrulewidth \normalhskip2.5\boxrulewidth}% \fi \fi \normalhfill \visualvrule - \!!width\ifrightrule\boxrulewidth\else\zeropoint\fi}% + \s!width\ifrightrule\boxrulewidth\else\zeropoint\fi}% \normalvskip-\boxrulewidth \visualhrule - \!!height\boxrulewidth - \ifbottomrule\else\!!width\zeropoint\fi}% + \s!height\boxrulewidth + \ifbottomrule\else\s!width\zeropoint\fi}% \wd#1\zeropoint \setbox#1=\ifhbox#1\normalhbox\else\normalvbox\fi {\normalhbox @@ -726,9 +725,9 @@ \def\setvisiblehfilbox#1\to#2#3#4% {\setbox#1\normalhbox {\visualvrule - \!!width #2\testrulewidth - \!!height#3\testrulewidth - \!!depth #4\testrulewidth}% + \s!width #2\testrulewidth + \s!height#3\testrulewidth + \s!depth #4\testrulewidth}% \smashbox#1} \def\doruledhfiller#1#2#3#4% @@ -827,9 +826,9 @@ \def\setvisiblevfilbox#1\to#2#3#4% {\setbox#1\normalhbox {\visualvrule - \!!width #2\testrulewidth - \!!height#3\testrulewidth - \!!depth #4\testrulewidth}% + \s!width #2\testrulewidth + \s!height#3\testrulewidth + \s!depth #4\testrulewidth}% \smashbox#1}% \def\doruledvfiller#1#2#3% @@ -940,22 +939,22 @@ \setbox0\normalhbox {\normalhskip-\testrulewidth \visualvrule - \!!width4\testrulewidth - \!!height16\testrulewidth - \!!depth16\testrulewidth}% + \s!width4\testrulewidth + \s!height16\testrulewidth + \s!depth16\testrulewidth}% \else \setbox0\normalhbox to \ifnegative-\fi\scratchskip {\visualvrule - \!!width2\testrulewidth - \ifnegative\!!depth\else\!!height\fi16\testrulewidth + \s!width2\testrulewidth + \ifnegative\s!depth\else\s!height\fi16\testrulewidth \cleaders \visualhrule \ifnegative - \!!depth2\testrulewidth - \!!height\zeropoint + \s!depth2\testrulewidth + \s!height\zeropoint \else - \!!height2\testrulewidth - \!!depth\zeropoint + \s!height2\testrulewidth + \s!depth\zeropoint \fi \normalhfill \ifflexible @@ -965,15 +964,15 @@ \normalhbox {\normalhskip 2\testrulewidth \visualvrule - \!!width2\testrulewidth - \!!height\ifnegative-7\else9\fi\testrulewidth - \!!depth\ifnegative9\else-7\fi\testrulewidth + \s!width2\testrulewidth + \s!height\ifnegative-7\else9\fi\testrulewidth + \s!depth\ifnegative9\else-7\fi\testrulewidth \normalhskip 2\testrulewidth}% \normalhfill \fi \visualvrule - \!!width2\testrulewidth - \ifnegative\!!depth\else\!!height\fi16\testrulewidth}% + \s!width2\testrulewidth + \ifnegative\s!depth\else\s!height\fi16\testrulewidth}% \setbox0\normalhbox {\ifnegative\else\normalhskip-\scratchskip\fi \box0}% @@ -1076,14 +1075,14 @@ \ifzero \setbox0\normalvcue {\visualvrule - \!!width32\testrulewidth - \!!height2\testrulewidth - \!!depth2\testrulewidth}% + \s!width32\testrulewidth + \s!height2\testrulewidth + \s!depth2\testrulewidth}% \else \setbox0\normalvbox to \ifnegative-\fi\scratchskip {\visualhrule - \!!width16\testrulewidth - \!!height2\testrulewidth + \s!width16\testrulewidth + \s!height2\testrulewidth \ifflexible \cleaders \normalhbox to 16\testrulewidth @@ -1091,8 +1090,8 @@ \normalvbox {\normalvskip 2\testrulewidth \visualhrule - \!!width2\testrulewidth - \!!height2\testrulewidth + \s!width2\testrulewidth + \s!height2\testrulewidth \normalvskip 2\testrulewidth}% \normalhss}% \normalvfill @@ -1100,12 +1099,12 @@ \normalvfill \fi \visualhrule - \!!width16\testrulewidth - \!!height2\testrulewidth}% + \s!width16\testrulewidth + \s!height2\testrulewidth}% \setbox2\normalvbox to \ht0 {\visualhrule - \!!width2\testrulewidth - \!!height\ht0}% + \s!width2\testrulewidth + \s!height\ht0}% \ifnegative \ht0\zeropoint \setbox0\normalhbox @@ -1192,25 +1191,25 @@ \ifzero \setbox0\ruledhbox to 8\testrulewidth {\visualvrule - \!!width\zeropoint - \!!height16\testrulewidth - \!!depth16\testrulewidth}% + \s!width\zeropoint + \s!height16\testrulewidth + \s!depth16\testrulewidth}% \setbox0\normalhbox {\normalhskip-4\testrulewidth\box0}% \else \setbox0\ruledhbox to \ifnegative-\fi\scratchskip {\visualvrule - \!!width\zeropoint - \ifnegative\!!depth\else\!!height\fi16\testrulewidth + \s!width\zeropoint + \ifnegative\s!depth\else\s!height\fi16\testrulewidth \ifflexible \normalhskip2\testrulewidth \cleaders \normalhbox {\normalhskip 2\testrulewidth \visualvrule - \!!width2\testrulewidth - \!!height\ifnegative-7\else9\fi\testrulewidth - \!!depth\ifnegative9\else-7\fi\testrulewidth + \s!width2\testrulewidth + \s!height\ifnegative-7\else9\fi\testrulewidth + \s!depth\ifnegative9\else-7\fi\testrulewidth \normalhskip 2\testrulewidth}% \normalhfill \else @@ -1268,9 +1267,9 @@ \ifzero \setbox0\ruledhbox to 32\testrulewidth {\visualvrule - \!!width\zeropoint - \!!height4\testrulewidth - \!!depth4\testrulewidth}% + \s!width\zeropoint + \s!height4\testrulewidth + \s!depth4\testrulewidth}% \else \setbox0\ruledvbox to \ifnegative-\fi\scratchskip {\hsize16\testrulewidth @@ -1281,15 +1280,15 @@ \normalvbox {\normalvskip 2\testrulewidth \visualhrule - \!!width2\testrulewidth - \!!height2\testrulewidth + \s!width2\testrulewidth + \s!height2\testrulewidth \normalvskip 2\testrulewidth}% \normalhss}% \normalvfill \else \visualvrule - \!!width\zeropoint - \!!height\ifnegative-\fi\scratchskip + \s!width\zeropoint + \s!height\ifnegative-\fi\scratchskip \normalhfill \fi} \fi @@ -1363,7 +1362,7 @@ \def\supp_visualizers_hglue_indeed {\leavevmode \scratchcounter\spacefactor - \visualvrule\!!width\zeropoint + \visualvrule\s!width\zeropoint \normalpenalty\plustenthousand \ruledhkern\normalhskip\scratchskip \spacefactor\scratchcounter @@ -1393,7 +1392,7 @@ \def\supp_visualizers_vglue_indeed {\endgraf % \par \nextdepth\prevdepth - \visualhrule\!!height\zeropoint + \visualhrule\s!height\zeropoint \normalpenalty\plustenthousand \ruledvkern\normalvskip\scratchskip \prevdepth\nextdepth @@ -1419,26 +1418,26 @@ {$\normalmkern\ifnegative-\fi\scratchskip$}% \setbox\boxrulescratchbox\normalhbox to \wd\boxrulescratchbox {\visualvrule - \!!height16\testrulewidth - \!!depth 16\testrulewidth - \!!width \testrulewidth + \s!height16\testrulewidth + \s!depth 16\testrulewidth + \s!width \testrulewidth \leaders \visualhrule - \!!height\ifpositive 16\else-14\fi\testrulewidth - \!!depth \ifpositive-14\else 16\fi\testrulewidth + \s!height\ifpositive 16\else-14\fi\testrulewidth + \s!depth \ifpositive-14\else 16\fi\testrulewidth \normalhfill \ifflexible \normalhskip-\wd\boxrulescratchbox \leaders \visualhrule - \!!height\testrulewidth - \!!depth \testrulewidth + \s!height\testrulewidth + \s!depth \testrulewidth \normalhfill \fi \visualvrule - \!!height16\testrulewidth - \!!depth 16\testrulewidth - \!!width \testrulewidth}% + \s!height16\testrulewidth + \s!depth 16\testrulewidth + \s!width \testrulewidth}% \smashbox0% \ifnegative #1\scratchskip @@ -1569,19 +1568,19 @@ \normalhskip-\scratchdimen \normalhskip-2\testrulewidth \visualvrule - \!!width 2\testrulewidth - \!!height#3\testrulewidth - \!!depth #4\testrulewidth + \s!width 2\testrulewidth + \s!height#3\testrulewidth + \s!depth #4\testrulewidth \fi \visualvrule - \!!width \scratchdimen - \!!height#5\testrulewidth - \!!depth #6\testrulewidth + \s!width \scratchdimen + \s!height#5\testrulewidth + \s!depth #6\testrulewidth \ifnum#2>\zerocount \visualvrule - \!!width 2\testrulewidth - \!!height#3\testrulewidth - \!!depth #4\testrulewidth + \s!width 2\testrulewidth + \s!height#3\testrulewidth + \s!depth #4\testrulewidth \fi \fi}% \smashbox#1} @@ -1600,8 +1599,8 @@ \setbox0\ruledhbox to 8\testrulewidth {\ifnegative\else\normalhss\fi \visualvrule - \!!depth8\testrulewidth - \!!width\ifzero\zeropoint\else4\testrulewidth\fi + \s!depth8\testrulewidth + \s!width\ifzero\zeropoint\else4\testrulewidth\fi \ifpositive\else\normalhss\fi}% \supp_visualizers_penalty_box{2}{\scratchcounter}{0}{8}{-3.5}{4.5}% \normalpenalty\plustenthousand @@ -1651,13 +1650,13 @@ \boxrulewidth\testrulewidth \setbox0\ruledhbox {\visualvrule - \!!height4\testrulewidth - \!!depth 4\testrulewidth - \!!width \zeropoint + \s!height4\testrulewidth + \s!depth 4\testrulewidth + \s!width \zeropoint \visualvrule - \!!height\ifnegative.5\else4\fi\testrulewidth + \s!height\ifnegative.5\else4\fi\testrulewidth \!!dept \ifpositive.5\else4\fi\testrulewidth - \!!width 8\testrulewidth}% + \s!width 8\testrulewidth}% \supp_visualizers_penalty_box{2}{\scratchcounter}{4}{4}{.5}{.5}% \setbox0\normalhbox {\normalhskip-4\testrulewidth diff --git a/tex/context/base/symb-run.mkiv b/tex/context/base/symb-run.mkiv index 4bd2cecca..3d92c4416 100644 --- a/tex/context/base/symb-run.mkiv +++ b/tex/context/base/symb-run.mkiv @@ -44,10 +44,10 @@ \unprotect -\gdef\doshowsymbolset[#1]% - {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}} +\unexpanded\gdef\showsymbolset + {\dosingleargument\symb_show_set} -\gdef\showsymbolset - {\dosingleargument\doshowsymbolset} +\gdef\symb_show_set[#1]% + {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}} \protect \endinput diff --git a/tex/context/base/syst-aux.lua b/tex/context/base/syst-aux.lua index 7fd25d6ab..cda340cb6 100644 --- a/tex/context/base/syst-aux.lua +++ b/tex/context/base/syst-aux.lua @@ -6,19 +6,37 @@ if not modules then modules = { } end modules ['syst-aux'] = { license = "see context related readme files" } +-- slower than lpeg: +-- +-- utfmatch(str,"(.?)(.*)$") +-- utf.sub(str,1,1) + +local commands, context = commands, context + local settings_to_array = utilities.parsers.settings_to_array local concat = table.concat +local format = string.format +local utfsub = utf.sub +local P, C, Carg, lpegmatch, utf8char = lpeg.P, lpeg.C, lpeg.Carg, lpeg.match, lpeg.patterns.utf8char local setvalue = context.setvalue +local pattern = C(utf8char^-1) * C(P(1)^0) + function commands.getfirstcharacter(str) - local first, rest = utf.match(str,"(.?)(.*)$") + local first, rest = lpegmatch(pattern,str) setvalue("firstcharacter",first) setvalue("remainingcharacters",rest) end +local pattern = C(utf8char^-1) + function commands.doiffirstcharelse(chr,str) - commands.doifelse(utf.sub(str,1,1) == chr) + commands.doifelse(lpegmatch(pattern,str) == chr) +end + +function commands.getsubstring(str,first,last) + context(utfsub(str,tonumber(first),tonumber(last))) end -- function commands.addtocommalist(list,item) @@ -50,3 +68,14 @@ end -- end -- end -- end + +local pattern = (C((1-P("%"))^1) * Carg(1)) /function(n,d) return format("%.0fsp",d * tonumber(n)/100) end * P("%") * P(-1) + +-- commands.percentageof("10%",65536*10) + +function commands.percentageof(str,dim) + context(lpegmatch(pattern,str,1,dim) or str) +end + +-- \gdef\setpercentdimen#1#2% +-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} diff --git a/tex/context/base/syst-aux.mkiv b/tex/context/base/syst-aux.mkiv index 0e43a6202..058a251cb 100644 --- a/tex/context/base/syst-aux.mkiv +++ b/tex/context/base/syst-aux.mkiv @@ -11,10 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D Some of the macros will move to syst-obs as they might become -%D obsolete once we've redone the bibliography module. Of course -%D the handy helpers will stay. -%D %D There are some references to \LUA\ variants here but these concern %D (often old) experiments, moved from local test modules to here, %D cleaned up, but not really used. After all it's not that urgent @@ -38,13 +34,13 @@ %D is used in \CONTEXT\ and therefore we might also assume that %D some basic functionality is available. %D -%D Some of the macros here are used in the bibliography module. They -%D will be moved to a separate syst module some once the bib module -%D is made \MKIV. -%D %D The original files contain previous implementations and notes about %D performance. This file will be stripped down in due time. +%D Some of the macros here were only used in the bibliography module. They +%D have been be moved to a separate syst module since the bib module is no +%D longer using them. Some more will go away. + \unprotect %D \macros @@ -62,6 +58,21 @@ \let\unexpanded\normalprotected +%D As we don't have namespace definers yet, we use a special one: + +\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes + +\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 + +\unexpanded\def\installsystemnamespace#1% maybe move this to syst-ini + {\ifcsname ??#1\endcsname + \writestatus\m!system{duplicate system namespace '#1'}\wait + \else + \global\advance\c_syst_helpers_n_of_namespaces\plusone + \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}% + \fi} + %D \macros %D {normalspace} %D @@ -150,34 +161,35 @@ \let\@NX \noexpand \def\@EAEA {\expandafter\expandafter} % can often be avoided -%D Sometimes we pass macros as arguments to commands that -%D don't expand them before interpretation. Such commands can -%D be enclosed with \type{\expanded}, like: +%D Sometimes we pass macros as arguments to commands that don't expand them +%D before interpretation. Such commands can be enclosed with \type {\expanded}, +%D like: %D %D \starttyping %D \expanded{\setupsomething[\alfa]} %D \stoptyping %D -%D Such situations occur for instance when \type{\alfa} is a -%D commalist or when data stored in macros is fed to index of -%D list commands. If needed, one should use \type{\noexpand} -%D inside the argument. Later on we will meet some more clever -%D alternatives to this command. Beware, only the simple one -%D has \type {\noexpand} before its argument. +%D Such situations occur for instance when \type{\alfa} is a commalist or when data +%D stored in macros is fed to index of list commands. If needed, one should use +%D \type{\noexpand} inside the argument. Later on we will meet some more clever +%D alternatives to this command. Beware, only the simple one has \type {\noexpand} +%D before its argument. -\let\@@expanded\empty % always long and global (less restores) +\let\m_syst_helpers_expanded\empty \unexpanded\def\expanded#1% - {\xdef\@@expanded{\noexpand#1}\@@expanded} + {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded} -\unexpanded\def\startexpanded#1\stopexpanded % see x-fo for example - {\xdef\@@expanded{#1}\@@expanded} +\unexpanded\def\startexpanded#1\stopexpanded + {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded} \let\stopexpanded\relax -%D Recent \TEX's have a primitive \expanded +%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. -% not yet as we need to adapt ##'s in calls +% We cannot use the next variant as first we need to adapt \type {##}'s +% in callers: % % \def\expanded#1% % {\normalexpanded{\noexpand#1}} @@ -188,8 +200,8 @@ %D \macros %D {gobbleoneargument,gobble...arguments} %D -%D The next set of macros just do nothing, except that they -%D get rid of a number of arguments. +%D The next set of macros just do nothing, except that they get rid of a number of +%D arguments. \def\gobbleoneargument #1{} \def\gobbletwoarguments #1#2{} @@ -208,6 +220,18 @@ \def\gobblefouroptionals [#1][#2][#3][#4]{} \def\gobblefiveoptionals [#1][#2][#3][#4][#5]{} +%D Reserved macros for tests: + +\let\donothing\empty + +\let\m_syst_string_one \empty +\let\m_syst_string_two \empty +\let\m_syst_string_three\empty +\let\m_syst_string_four \empty + +\let\m_syst_action_yes \empty +\let\m_syst_action_nop \empty + %D \macros %D {doifnextcharelse} %D @@ -235,8 +259,8 @@ \unexpanded\def\doifnextcharelse#1#2#3% #1 should not be {} ! {\let\charactertoken=#1% = needed here - \def\!!stringa{#2}% - \def\!!stringb{#3}% + \def\m_syst_action_yes{#2}% + \def\m_syst_action_nop{#3}% \futurelet\nexttoken\syst_helpers_inspect_next_character} \def\syst_helpers_inspect_next_character @@ -248,9 +272,9 @@ \def\syst_helpers_inspect_next_character_indeed {\ifx\nexttoken\charactertoken - \expandafter\!!stringa + \expandafter\m_syst_action_yes \else - \expandafter\!!stringb + \expandafter\m_syst_action_nop \fi} %D Because we will mostly use this macro for testing if the next @@ -274,14 +298,14 @@ \let\syst_helpers_next_optional_character_token=[ \unexpanded\def\doifnextoptionalelse#1#2% - {\def\syst_helpers_next_optional_command_yes{#1}% - \def\syst_helpers_next_optional_command_nop{#2}% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% \let\if_next_blank_space_token\iffalse \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} \unexpanded\def\doifnextoptionalcselse#1#2% \cs \cs (upto 10% faster) - {\let\syst_helpers_next_optional_command_yes#1% - \let\syst_helpers_next_optional_command_nop#2% + {\let\m_syst_action_yes#1% + \let\m_syst_action_nop#2% \let\if_next_blank_space_token\iffalse \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} @@ -294,16 +318,16 @@ \def\syst_helpers_inspect_next_optional_character_indeed {\ifx\nexttoken\syst_helpers_next_optional_character_token - \expandafter\syst_helpers_next_optional_command_yes + \expandafter\m_syst_action_yes \else - \expandafter\syst_helpers_next_optional_command_nop + \expandafter\m_syst_action_nop \fi} \let\syst_helpers_next_bgroup_character_token\bgroup \unexpanded\def\doifnextbgroupelse#1#2% - {\def\syst_helpers_next_bgroup_command_yes{#1}% - \def\syst_helpers_next_bgroup_command_nop{#2}% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% \let\if_next_blank_space_token\iffalse \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character} @@ -316,16 +340,16 @@ \def\syst_helpers_inspect_next_bgroup_character_indeed {\ifx\nexttoken\syst_helpers_next_bgroup_character_token - \expandafter\syst_helpers_next_bgroup_command_yes + \expandafter\m_syst_action_yes \else - \expandafter\syst_helpers_next_bgroup_command_nop + \expandafter\m_syst_action_nop \fi} \let\syst_helpers_next_parenthesis_character_token( \unexpanded\def\doifnextparenthesiselse#1#2% - {\def\syst_helpers_next_parenthesis_command_yes{#1}% - \def\syst_helpers_next_parenthesis_command_nop{#2}% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% \let\if_next_blank_space_token\iffalse \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character} @@ -338,44 +362,39 @@ \def\syst_helpers_inspect_next_parenthesis_character_indeed {\ifx\nexttoken\syst_helpers_next_parenthesis_character_token - \expandafter\syst_helpers_next_parenthesis_command_yes + \expandafter\m_syst_action_yes \else - \expandafter\syst_helpers_next_parenthesis_command_nop + \expandafter\m_syst_action_nop \fi} %D The next one is handy in predictable situations: \unexpanded\def\doiffastoptionalcheckelse#1#2% - {\def\syst_helpers_next_optional_command_yes{#1}% - \def\syst_helpers_next_optional_command_nop{#2}% + {\def\m_syst_action_yes{#1}% + \def\m_syst_action_nop{#2}% \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else} \unexpanded\def\doiffastoptionalcheckcselse#1#2% \cs \cs - {\let\syst_helpers_next_optional_command_yes#1% - \let\syst_helpers_next_optional_command_nop#2% + {\let\m_syst_action_yes#1% + \let\m_syst_action_nop#2% \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else} \def\syst_helpers_do_if_fast_optional_check_else {\ifx\nexttoken\syst_helpers_next_optional_character_token - \expandafter\syst_helpers_next_optional_command_yes + \expandafter\m_syst_action_yes \else - \expandafter\syst_helpers_next_optional_command_nop + \expandafter\m_syst_action_nop \fi} -%D This macro uses some auxiliary macros. Although we were able -%D to program quite complicated things, I only understood these -%D after rereading the \TEX book. The trick is in using a -%D command with a one character name. Such commands differ from -%D the longer ones in the fact that trailing spaces are {\em -%D not} skipped. This enables us to indirectly define a long -%D named macro that gobbles a space. -%D -%D In the first line we define \type{\blankspace}. Next we -%D make \type{\:} equivalent to \type{\reinspect...}. This -%D one||character command is expanded before the next -%D \type{\def} comes into action. This way the space after -%D \type{\:} becomes a delimiter of the longer named -%D \type{\reinspectnextcharacter}. +%D This macro uses some auxiliary macros. Although we were able to program quite +%D complicated things, I only understood these after rereading the \TEX book. The +%D trick is in using a command with a one character name. Such commands differ from +%D the longer ones in the fact that trailing spaces are {\em not} skipped. This +%D enables us to indirectly define a long named macro that gobbles a space. In the +%D first line we define \type {\blankspace}. Next we make \type {\:} equivalent to +%D \type {\reinspect...}. This one||character command is expanded before the next +%D \type {\def} comes into action. This way the space after \type {\:} becomes a +%D delimiter of the longer named \type {\reinspectnextcharacter}. % try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...} @@ -402,10 +421,9 @@ %D letvalue,letgvalue,getvalue,resetvalue, %D undefinevalue,ignorevalue} %D -%D \TEX's primitive \type{\csname} can be used to construct -%D all kind of commands that cannot be defined with -%D \type{\def} and \type{\let}. Every macro programmer sooner -%D or later wants macros like these. +%D \TEX's primitive \type {\csname} can be used to construct all kind of commands +%D that cannot be defined with \type {\def} and \type {\let}. Every macro programmer +%D sooner or later wants macros like these. %D %D \starttyping %D \setvalue {name}{...} = \def\name{...} @@ -418,9 +436,8 @@ %D \resetvalue {name} = \def\name{} %D \stoptyping %D -%D As we will see, \CONTEXT\ uses these commands many times, -%D which is mainly due to its object oriented and parameter -%D driven character. +%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} @@ -441,22 +458,20 @@ %D \macros %D {globallet,glet} %D -%D In \CONTEXT\ of May 2000 using \type {\globallet} -%D instead of the two tokens will save us some -%D $300\times4=1200$ bytes of format file on a 32~bit -%D system. So: +%D In \CONTEXT\ of May 2000 using \type {\globallet} instead of the two +%D tokens will save us some $300\times4=1200$ bytes of format file on a 32~bit +%D system. Not that it matters much today. This shortcut is already defined: -\def\globallet{\global\let} \let\glet\globallet +\unexpanded\def\glet{\global\let} \let\globallet\glet %D \macros %D {doifundefined,doifdefined, %D doifundefinedelse,doifdefinedelse, %D doifalldefinedelse} %D -%D The standard way of testing if a macro is defined is -%D comparing its meaning with another undefined one, usually -%D \type{\undefined}. To garantee correct working of the next -%D set of macros, \type{\undefined} may never be defined! +%D The standard way of testing if a macro is defined is comparing its meaning with +%D another undefined one, usually \type{\undefined}. To garantee correct working of +%D the next set of macros, \type{\undefined} may never be defined! %D %D \starttyping %D \doifundefined {string} {...} @@ -466,13 +481,12 @@ %D \doifalldefinedelse {commalist} {then ...} {else ...} %D \stoptyping %D -%D Every macroname that \TEX\ builds gets an entry in the hash -%D table, which is of limited size. It is expected that e-\TeX\ -%D will offer a less memory||consuming alternative. +%D Every macroname that \TEX\ builds gets an entry in the hash table, which is of +%D limited size. It is expected that \ETEX\ will offer a less memory||consuming +%D alternative. -%D Although it will probably never be a big problem, it is good -%D to be aware of the difference between testing on a macro -%D name to be build by using \type{\csname} and +%D Although it will probably never be a big problem, it is good to be aware of the +%D difference between testing on a macro name to be build by using \type{\csname} and %D \type{\endcsname} and testing the \type{\name} directly. %D %D \starttyping @@ -481,11 +495,6 @@ %D \ifundefined\NameB ... \else ... \fi %D \stoptyping -% \def\ifundefined#1% obsolete -% {\unless\ifcsname#1\endcsname} -% -% use a real if like \ifcsname#1\endcsname\else instead - \suppressifcsnameerror\plusone \def\doifundefinedelse#1% @@ -511,12 +520,10 @@ %D \macros %D {letbeundefined} %D -%D Testing for being undefined comes down to testing on \type -%D {\relax} when we use \type {\csname}, but when using \type -%D {\ifx}, we test on being \type {\undefined}! In \ETEX\ we -%D have \type {\ifcsname} and that way of testing on existance -%D is not the same as the one described here. Therefore we -%D introduce: +%D Testing for being undefined comes down to testing on \type {\relax} when we use +%D \type {\csname}, but when using \type {\ifx}, we test on being \type +%D {\undefined}! In \ETEX\ we have \type {\ifcsname} and that way of testing on +%D existance is not the same as the one described here. Therefore we introduce: \def\letbeundefined#1% potential stack buildup when used \global {\expandafter\let\csname#1\endcsname\undefined} @@ -527,13 +534,11 @@ \def\globalundefine#1% conditional {\ifcsname#1\endcsname\expandafter\global\let\csname#1\endcsname\undefined\fi} -%D Beware, being \type {\undefined} in \ETEX\ means that the macro -%D {\em is} defined! - -%D When we were developing the scientific units module, we -%D encountered different behavior in text and math mode, which -%D was due to this grouping subtilities. We therefore decided -%D to use \type{\begingroup} instead of \type{\bgroup}. +%D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined! +%D +%D When we were developing the scientific units module, we encountered different +%D behavior in text and math mode, which was due to this grouping subtilities. We +%D therefore decided to use \type{\begingroup} instead of \type{\bgroup}. \unexpanded\def\doifalldefinedelse#1% {\begingroup @@ -554,15 +559,13 @@ %D \macros %D {doif,doifelse,doifnot} %D -%D Programming in \TEX\ differs from programming in procedural -%D languages like \MODULA. This means that one --- well, let me -%D speek for myself --- tries to do the things in the well -%D known way. Therefore the next set of \type{\ifthenelse} -%D commands were between the first ones we needed. A few years -%D later, the opposite became true: when programming in -%D \MODULA, I sometimes miss handy things like grouping, -%D runtime redefinition, expansion etc. While \MODULA\ taught -%D me to structure, \TEX\ taught me to think recursive. +%D Programming in \TEX\ differs from programming in procedural languages like +%D \MODULA. This means that one --- well, let me speek for myself --- tries to do +%D the things in the well known way. Therefore the next set of \type{\ifthenelse} +%D commands were between the first ones we needed. A few years later, the opposite +%D became true: when programming in \MODULA, I sometimes miss handy things like +%D grouping, runtime redefinition, expansion etc. While \MODULA\ taught me to +%D structure, \TEX\ taught me to think recursive. %D %D \starttyping %D \doif {string1} {string2} {...} @@ -571,27 +574,27 @@ %D \stoptyping \unexpanded\def\doif#1#2% - {\edef\!!stringa{#1}% - \edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} \unexpanded\def\doifnot#1#2% - {\edef\!!stringa{#1}% - \edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} \unexpanded\def\doifelse#1#2% - {\edef\!!stringa{#1}% - \edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments @@ -611,24 +614,24 @@ %D This time, the string is not expanded. \unexpanded\def\doifemptyelse#1% - {\def\!!stringa{#1}% - \ifx\!!stringa\empty + {\def\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \unexpanded\def\doifempty#1% - {\def\!!stringa{#1}% - \ifx\!!stringa\empty + {\def\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} \unexpanded\def\doifnotempty#1% - {\def\!!stringa{#1}% - \ifx\!!stringa\empty + {\def\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\gobbleoneargument \else \expandafter\firstofoneargument @@ -637,9 +640,8 @@ %D \macros %D {doifinset,doifnotinset,doifinsetelse} %D -%D We can check if a string is present in a comma separated -%D set of strings. Depending on the result, some action is -%D taken. +%D We can check if a string is present in a comma separated set of strings. +%D Depending on the result, some action is taken. %D %D \starttyping %D \doifinset {string} {string,...} {...} @@ -680,119 +682,119 @@ \def\syst_helpers_do_quit_if_item_in_set #1],\relax{\firstofoneargument} \def\syst_helpers_do_quit_if_item_not_in_set #1],\relax{\gobbleoneargument} -\def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\!!stringb,],\relax} -\def\syst_helpers_re_do_if_in_set {\expandafter\syst_helpers_do_check_if_item_in_set \!!stringb,],\relax} -\def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \!!stringb,],\relax} +\def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\m_syst_string_two,],\relax} +\def\syst_helpers_re_do_if_in_set {\expandafter\syst_helpers_do_check_if_item_in_set \m_syst_string_two,],\relax} +\def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \m_syst_string_two,],\relax} \unexpanded\def\doifinsetelse#1% make this two step too - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\thirdofthreearguments \else \expandafter\syst_helpers_do_if_in_set_else \fi} \def\syst_helpers_do_if_in_set_else#1% - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\secondoftwoarguments \else \expandafter\syst_helpers_re_do_if_in_set_else \fi} \unexpanded\def\doifinset#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\gobbletwoarguments \else \expandafter\syst_helpers_do_if_in_set \fi} \def\syst_helpers_do_if_in_set#1% - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\gobbleoneargument \else \expandafter\syst_helpers_re_do_if_in_set \fi} \unexpanded\def\doifnotinset#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\secondoftwoarguments \else \expandafter\syst_helpers_do_if_not_in_set \fi} \def\syst_helpers_do_if_not_in_set#1% - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\firstofoneargument \else \expandafter\syst_helpers_re_do_if_not_in_set % ...]{true} \fi} \def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\syst_helpers_do_check_if_item_in_set_else \else \expandafter\syst_helpers_do_do_check_if_item_in_set_else \fi#2} \def\syst_helpers_do_do_check_if_item_in_set_else - {\ifx\!!stringb\v_syst_helpers_right_optional_bracket + {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket \expandafter\thirdofthreearguments \else \expandafter\syst_helpers_do_do_do_check_if_item_in_set_else \fi} \def\syst_helpers_do_do_do_check_if_item_in_set_else - {\ifx\!!stringa\!!stringb + {\ifx\m_syst_string_one\m_syst_string_two \expandafter\syst_helpers_do_quit_if_item_in_set_else \else \expandafter\syst_helpers_do_check_if_item_in_set_else \fi} \def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\syst_helpers_do_check_if_item_in_set \else \expandafter\syst_helpers_do_do_check_if_item_in_set \fi#2} \def\syst_helpers_do_do_check_if_item_in_set - {\ifx\!!stringb\v_syst_helpers_right_optional_bracket + {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket \expandafter\gobbletwoarguments \else \expandafter\syst_helpers_do_do_do_check_if_item_in_set \fi} \def\syst_helpers_do_do_do_check_if_item_in_set - {\ifx\!!stringa\!!stringb + {\ifx\m_syst_string_one\m_syst_string_two \expandafter\syst_helpers_do_quit_if_item_in_set \else \expandafter\syst_helpers_do_check_if_item_in_set \fi} \def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space - {\edef\!!stringb{#1}% - \ifx\!!stringb\empty + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\empty \expandafter\syst_helpers_do_check_if_item_not_in_set \else \expandafter\syst_helpers_do_do_check_if_item_not_in_set \fi#2} \def\syst_helpers_do_do_check_if_item_not_in_set - {\ifx\!!stringb\v_syst_helpers_right_optional_bracket + {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket \expandafter\secondoftwoarguments \else \expandafter\syst_helpers_do_do_do_check_if_item_not_in_set \fi} \def\syst_helpers_do_do_do_check_if_item_not_in_set - {\ifx\!!stringa\!!stringb + {\ifx\m_syst_string_one\m_syst_string_two \expandafter\syst_helpers_do_quit_if_item_not_in_set \else \expandafter\syst_helpers_do_check_if_item_not_in_set @@ -801,8 +803,8 @@ %D \macros %D {doifcommon,doifnotcommon,doifcommonelse} %D -%D Probably the most time consuming tests are those that test -%D for overlap in sets of strings. +%D Probably the most time consuming tests are those that test for overlap in sets +%D of strings. %D %D \starttyping %D \doifcommon {string,...} {string,...} {...} @@ -890,16 +892,16 @@ %D {processcommalist,processcommacommand,quitcommalist, %D processcommalistwithparameters} %D -%D We've already seen some macros that take care of comma -%D separated lists. Such list can be processed with +%D We've already seen some macros that take care of comma separated lists. Such +%D list can be processed with %D %D \starttyping %D \processcommalist[string,string,...]\commando %D \stoptyping %D -%D The user supplied command \type{\commando} receives one -%D argument: the string. This command permits nesting and -%D spaces after commas are skipped. Empty sets are no problem. +%D The user supplied command \type{\commando} receives one argument: the string. +%D This command permits nesting and spaces after commas are skipped. Empty sets +%D are no problem. %D %D \startbuffer %D \def\dosomething#1{(#1)} @@ -920,8 +922,10 @@ \newcount\commalevel +\installsystemnamespace{nextcommalevel} + \def\syst_helpers_do_do_do_process_comma_item - {\csname\s!next\the\commalevel\endcsname} + {\csname\??nextcommalevel\the\commalevel\endcsname} \def\syst_helpers_do_do_process_comma_item {\ifx\nexttoken\blankspace @@ -940,9 +944,8 @@ \def\syst_helpers_do_process_comma_item {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item} -%D Empty arguments are not processed. Empty items (\type{,,}) -%D however are treated. We have to check for the special case -%D \type{[{a,b,c}]}. +%D Empty arguments are not processed. Empty items (\type {,,}) however are +%D treated. We have to check for the special case \type {[{a,b,c}]}. \unexpanded\def\processcommalist[% {\futurelet\nexttoken\syst_helpers_do_check_comma_item} @@ -957,27 +960,27 @@ \def\syst_helpers_do_process_comma_list#1]#2% {\global\advance\commalevel \plusone - \expandafter\def\csname\s!next\the\commalevel\endcsname##1,% + \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,% {#2{##1}\syst_helpers_do_process_comma_item}% \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument#1,]\relax \global\advance\commalevel \minusone } %D One way of quitting a commalist halfway is: -\def\quitcommalist +\unexpanded\def\quitcommalist {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list} \def\syst_helpers_do_quit_comma_list#1]% {\endgroup} -\def\quitprevcommalist +\unexpanded\def\quitprevcommalist {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_prev_comma_list} \def\syst_helpers_do_quit_prev_comma_list#1]% {\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list} -%D The hack we used for checking the next character -%D \type {\doifnextcharelse} is also used here. +%D The hack we used for checking the next character \type {\doifnextcharelse} +%D is also used here. \let\next\: @@ -991,15 +994,13 @@ %D %D \getbuffer -%D When a list is saved in a macro, we can use a construction -%D like: +%D When a list is saved in a macro, we can use a construction like: %D %D \starttyping %D \expandafter\processcommalist\expandafter[\list]\command %D \stoptyping %D -%D Such solutions suit most situations, but we wanted a bit -%D more. +%D Such solutions suit most situations, but we wanted a bit more. %D %D \starttyping %D \processcommacommand[string,\stringset,string]\commando @@ -1016,14 +1017,14 @@ %D \processcommacommand[\first,between,\second]\message %D \stoptyping %D -%D Commands that are part of the list are expanded, so the -%D use of this macro has its limits. +%D Commands that are part of the list are expanded, so the use of +%D this macro has its limits. \unexpanded\def\processcommacommand[#1]% {\normalexpanded{\processcommalist[#1]}} -%D The argument to \type{\command} is not delimited. Because -%D we often use \type{[]} as delimiters, we also have: +%D The argument to \type{\command} is not delimited. Because we often +%D use \type{[]} as delimiters, we also have: %D %D \starttyping %D \processcommalistwithparameters[string,string,...]\command @@ -1044,13 +1045,18 @@ %D %D Two more: +\let\syst_helpers_comma_list_step\relax + \unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist - {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}% - \processcommalist[#1]\currentcommalistcommand} + {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% + \processcommalist[#1]\syst_helpers_comma_list_step} \unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand - {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}% - \normalexpanded{\processcommalist[#1]}\currentcommalistcommand} + {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}% + \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step} + +\let\stopprocesscommalist \relax +\let\stopprocesscommacommand\relax %D \macros %D {processaction, @@ -1097,8 +1103,8 @@ % obsolete: \def\expandactions{\let\expandedaction\edef} \expandactions (see mkii) \unexpanded\def\syst_helpers_do_compare_process_action_a[#1=>#2][#3]% - {\edef\!!stringb{#1}% - \ifx\!!stringb\s!default + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_two\s!default \let\commalistelement\empty #2% \fi} @@ -1106,19 +1112,19 @@ % met \quitcommalist tot meer dan 25\% sneller \unexpanded\def\syst_helpers_do_compare_process_action_b[#1=>#2][#3]% - {\edef\!!stringb{#1}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_two{#1}% + \ifx\m_syst_string_one\m_syst_string_two \def\commalistelement{#3}% #2% \expandafter\quitcommalist - \else\ifx\!!stringb\s!unknown + \else\ifx\m_syst_string_two\s!unknown \def\commalistelement{#3}% beware of loops #2% \fi\fi} \unexpanded\def\processaction[#1]#2[% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_a \else \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b @@ -1127,23 +1133,23 @@ \processnextcommalist\relax\relax\syst_helpers_do_process_action[} \unexpanded\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]% - {\edef\!!stringa{#1}% - \edef\!!stringb{#3}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#3}% + \ifx\m_syst_string_one\m_syst_string_two \def\commalistelement{#3}% #2% \expandafter\quitprevcommalist \else - \edef\!!stringa{#1}% - \ifx\!!stringa\s!unknown + \edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\s!unknown \def\commalistelement{#3}% #2% \fi \fi} \unexpanded\def\processfirstactioninset[#1]% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\processaction \else \expandafter\syst_helpers_process_first_action_in_set_indeed @@ -1157,26 +1163,28 @@ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action} \unexpanded\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]% - {\edef\!!stringa{#1}% - \edef\!!stringb{#3}% - \ifx\!!stringa\!!stringb + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#3}% + \ifx\m_syst_string_one\m_syst_string_two \def\commalistelement{#3}% #2% \expandafter\quitcommalist \else - \edef\!!stringa{#1}% - \ifx\!!stringa\s!unknown + \edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\s!unknown \def\commalistelement{#3}% #2% \fi \fi} +\installsystemnamespace{nextactionlevel} + \unexpanded\def\syst_helpers_do_process_all_actions_in_set - {\csname\s!do\the\processlevel\endcsname} + {\csname\??nextactionlevel\the\processlevel\endcsname} \unexpanded\def\processallactionsinset[#1]% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\processaction \else \expandafter\syst_helpers_process_all_actions_in_set_indeed @@ -1185,7 +1193,7 @@ \unexpanded\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]% {\advance\processlevel \plusone - \expandafter\def\csname\s!do\the\processlevel\endcsname##1% + \expandafter\def\csname\??nextactionlevel\the\processlevel\endcsname##1% {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_d[####1][##1]}% \processcommalist[#3]\syst_helpers_do_do_process_action}% \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_all_actions_in_set @@ -1197,7 +1205,7 @@ {#1% \let\nexttoken#4% \global\advance\commalevel \plusone - \expandafter\def\csname\s!next\the\commalevel\endcsname##1,% + \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname##1,% {#3{##1}\syst_helpers_do_process_comma_item}% \syst_helpers_do_do_process_comma_item#4#5,]\relax \global\advance\commalevel\minusone @@ -1231,46 +1239,48 @@ %D \doifinsetelse {substring} {string} {then ...} {else ...} %D \stoptyping +\let\m_syst_sub_string\empty + \unexpanded\def\doifinstringelse#1% - {\edef\@@@instring{#1}% expand #1 here - \ifx\@@@instring\empty + {\edef\m_syst_sub_string{#1}% expand #1 here + \ifx\m_syst_sub_string\empty \expandafter\thirdofthreearguments \else \expandafter\syst_helpers_do_if_in_string_else_indeed \fi} \unexpanded\def\syst_helpers_do_if_in_string_else_indeed#1% - {\syst_helpers_do_if_in_string_else\@@@instring{#1}% + {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \unexpanded\def\doifinstring#1%% - {\edef\@@@instring{#1}% expand #1 here - \ifx\@@@instring\empty + {\edef\m_syst_sub_string{#1}% expand #1 here + \ifx\m_syst_sub_string\empty \expandafter\gobbletwoarguments \else \expandafter\syst_helpers_do_if_in_string_indeed \fi} \unexpanded\def\syst_helpers_do_if_in_string_indeed#1% - {\syst_helpers_do_if_in_string_else\@@@instring{#1}% + {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}% \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} \unexpanded\def\doifnotinstring#1%% - {\edef\@@@instring{#1}% expand #1 here - \ifx\@@@instring\empty + {\edef\m_syst_sub_string{#1}% expand #1 here + \ifx\m_syst_sub_string\empty \expandafter\gobbletwoarguments \else \expandafter\syst_helpers_do_if_not_in_string_indeed \fi} \unexpanded\def\syst_helpers_do_if_not_in_string_indeed#1% - {\syst_helpers_do_if_in_string_else\@@@instring{#1}% + {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}% \expandafter\gobbleoneargument \else \expandafter\firstofoneargument @@ -1280,8 +1290,8 @@ \unexpanded\def\syst_helpers_do_if_in_string_else#1#2% ##2 can be {abc} {\expandafter\def\expandafter\syst_helpers_do_do_if_in_string_else - \expandafter##\expandafter1#1##2##3\war{\unless\if##2@}% expand #1 here - \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@\war} % expand #2 here + \expandafter##\expandafter1#1##2##3\_e_o_s_{\unless\if##2@}% expand #1 here + \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@\_e_o_s_} % expand #2 here %D The next alternative proved to be upto twice as fast on %D tasks like checking reserved words in pretty verbatim @@ -1297,33 +1307,31 @@ %D expansion. \unexpanded\def\syst_helpers_do_if_in_csname_else#1#2% - {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3\war + {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3\_e_o_s_ {\unless\if##2@}% - \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\war} + \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\_e_o_s_} \unexpanded\def\doifincsnameelse#1#2% - {\edef\@@@instring{#1}% - \expandafter\syst_helpers_do_if_in_csname_else\expandafter{\@@@instring}{#2}% + {\normalexpanded{\syst_helpers_do_if_in_csname_else{#1}}{#2}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} %D \macros -%D {doifnumberelse} +%D {doifnumberelse,doifnumber,doifnotnumber} %D -%D The next macro executes a command depending of the outcome -%D of a test on numerals. This is probably one of the fastest -%D test possible, exept from a less robust 10||step -%D \type{\if}||ladder or some tricky \type{\lcode} checking. +%D The next macro executes a command depending of the outcome of a test on +%D numerals. This is probably one of the fastest test possible, exept from +%D a less robust 10||step \type {\if}||ladder or some tricky \type {\lcode} +%D checking. %D %D \starttyping %D \doifnumberelse {string} {then ...} {else ...} %D \stoptyping %D -%D The macro accepts \type{123}, \type{abc}, \type{{}}, -%D \type{\getal} and \type{\the\count...}. This macro is a -%D rather dirty one. +%D The macro accepts \type {123}, \type {abc}, \type {{}}, \type {\getal} and +%D \type {\the\count...}. This macro is a rather dirty one. \def\doifnumberelse#1% does not accept counters (fully expandable) {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space @@ -1332,6 +1340,35 @@ \expandafter\firstoftwoarguments \fi} +\def\doifnumber#1% + {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\def\doifnotnumber#1% + {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +%D \macros +%D {setpercentdimen} +%D +%D \starttyping +%D \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent} +%D \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt} +%D \scratchdimen \percentdimen \hsize {10\letterpercent} +%D \stoptyping + +\def\percentdimen#1#2% dimen percentage (with %) + {\dimexpr\ctxcommand{percentageof("#2",\number#1)}\relax} + +\unexpanded\def\setpercentdimen#1#2% dimen percentage (with %) + {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} + %D \macros %D {makerawcommalist, %D rawdoinsetelse, @@ -1372,13 +1409,13 @@ \def\syst_helpers_raw_process_comma_item#1,#2% #2 eats up preceding space {\if]#1\else - \csname\s!next\the\commalevel\endcsname{#1}% + \csname\??nextcommalevel\the\commalevel\endcsname{#1}% \expandafter\syst_helpers_raw_process_comma_item \fi#2} \unexpanded\def\rawprocesscommalist[#1]#2% accepteert ook [\cs] {\global\advance\commalevel \plusone - \expandafter\let\csname\s!next\the\commalevel\endcsname#2% + \expandafter\let\csname\??nextcommalevel\the\commalevel\endcsname#2% \expandafter\syst_helpers_raw_process_comma_item#1,],% \relax \global\advance\commalevel \minusone } @@ -1388,33 +1425,33 @@ % \def\rawdoifinsetelse#1#2{\doifinstringelse{,#1,}{,#2,}} % \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}} -\def\@@rawempty{,,} +\def\m_syst_two_commas{,,} \unexpanded\def\rawdoifinsetelse#1% - {\edef\@@@instring{,#1,}% expand #1 here - \ifx\@@@instring\@@rawempty + {\edef\m_syst_sub_string{,#1,}% expand #1 here + \ifx\m_syst_sub_string\m_syst_two_commas \expandafter\thirdofthreearguments \else \expandafter\syst_helpers_raw_do_if_in_set_else \fi} \unexpanded\def\syst_helpers_raw_do_if_in_set_else#1% - {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}% + {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \unexpanded\def\rawdoifinset#1% - {\edef\@@@instring{,#1,}% expand #1 here - \ifx\@@@instring\@@rawempty + {\edef\m_syst_sub_string{,#1,}% expand #1 here + \ifx\m_syst_sub_string\m_syst_two_commas \expandafter\gobbletwoarguments \else \expandafter\syst_helpers_raw_do_if_in_set \fi} \unexpanded\def\syst_helpers_raw_do_if_in_set#1%% - {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}% + {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}% \expandafter\firstofoneargument \else \expandafter\gobbleoneargument @@ -1423,42 +1460,40 @@ %D Some more raw material: \def\syst_helpers_do_raw_process_action[#1][#2]% - {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\war + {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\_e_o_s_ {\if##3@\else - \def\!!processaction{##2}% + \def\m_syst_helpers_process_action{##2}% \fi}% - \syst_helpers_do_do_raw_process_action,#2,#1=>,@\war} + \syst_helpers_do_do_raw_process_action,#2,#1=>,@\_e_o_s_} \unexpanded\def\rawprocessaction[#1]#2[#3]% - {\edef\!!stringa{#1}% - \edef\!!stringb{undefined}% better \!!undefined - \let\!!processaction\!!stringb - \ifx\!!stringa\empty + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{undefined}% better \!!undefined + \let\m_syst_helpers_process_action\m_syst_string_two + \ifx\m_syst_string_one\empty \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!default][#3]% \else - \expandafter\syst_helpers_do_raw_process_action\expandafter[\!!stringa][#3]% - \ifx\!!processaction\!!stringb + \expandafter\syst_helpers_do_raw_process_action\expandafter[\m_syst_string_one][#3]% + \ifx\m_syst_helpers_process_action\m_syst_string_two \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!unknown][#3]% \fi \fi - \ifx\!!processaction\!!stringb + \ifx\m_syst_helpers_process_action\m_syst_string_two \else - \!!processaction + \m_syst_helpers_process_action \fi} -%D When we process the list \type{a,b,c,d,e}, the raw routine -%D takes over 30\% less time, when we feed $20+$ character -%D strings we gain about 20\%. Alternatives which use -%D \type{\futurelet} perform worse. Part of the speedup is -%D due to the \type{\let} and \type{\expandafter} in the test. +%D When we process the list \type{a,b,c,d,e}, the raw routine takes over 30\% less +%D time, when we feed $20+$ character strings we gain about 20\%. Alternatives which +%D use \type{\futurelet} perform worse. Part of the speedup is due to the +%D \type{\let} and \type{\expandafter} in the test. %D \macros %D {dosetvalue,dosetevalue,dosetgvalue,docopyvalue,doresetvalue, %D dogetvalue} %D -%D When we are going to do assignments, we have to take -%D multi||linguality into account. For the moment we keep -%D things simple and single||lingual. +%D When we are going to do assignments, we have to take multi||linguality into account. +%D For the moment we keep things simple and single||lingual. %D %D \starttyping %D \dosetvalue {label} {variable} {value} @@ -1468,8 +1503,8 @@ %D \doresetvalue {label} {variable} %D \stoptyping %D -%D These macros are in fact auxiliary ones and are not meant -%D for use outside the assignment macros. +%D These macros are in fact auxiliary ones and are not meant for use outside the +%D assignment macros. \def\dosetvalue#1#2% #3 {\expandafter\def\csname#1#2\endcsname} % {#3}} @@ -1492,13 +1527,11 @@ %D \macros %D {doassign,undoassign,doassignempty} %D -%D Assignments are the backbone of \CONTEXT. Abhorred by the -%D concept of style file hacking, we took a considerable effort -%D in building a parameterized system. Unfortunately there is a -%D price to pay in terms of speed. Compared to other packages -%D and taking the functionality of \CONTEXT\ into account, the -%D total size of the format file is still very acceptable. Now -%D how are these assignments done. +%D Assignments are the backbone of \CONTEXT. Abhorred by the concept of style file +%D hacking, we took a considerable effort in building a parameterized system. +%D Unfortunately there is a price to pay in terms of speed. Compared to other +%D packages and taking the functionality of \CONTEXT\ into account, the total size +%D of the format file is still very acceptable. Now how are these assignments done. %D %D Assignments can be realized with: %D @@ -1519,38 +1552,36 @@ %D \def\labelvariable{value} %D \stoptyping %D -%D We do check for the presence of an \type{=} and loudly -%D complain of it's missed. We will redefine this macro later -%D on, when a more advanced message mechanism is implemented. +%D We do check for the presence of an \type{=} and loudly complain of it's missed. We +%D will redefine this macro later on, when a more advanced message mechanism is +%D implemented. \newif\iferrorisfatal -\def\waitonfatalerror +\unexpanded\def\waitonfatalerror {\iferrorisfatal\wait\fi} -\def\showassignerror#1#2% +\unexpanded\def\showassignerror#1#2% {\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}% \waitonfatalerror} -\def\doassignempty[#1][#2=#3]% +\unexpanded\def\doassignempty[#1][#2=#3]% {\ifcsname#1#2\endcsname\else\dosetvalue{#1}{#2}{#3}\fi} %D \macros %D {getparameters,geteparameters,getgparameters, %D forgetparameters} %D -%D Using the assignment commands directly is not our -%D ideal of user friendly interfacing, so we take some further -%D steps. +%D Using the assignment commands directly is not our ideal of user friendly interfacing, +%D so we take some further steps. %D %D \starttyping %D \getparameters [label] [...=...,...=...] %D \forgetparameters [label] [...=...,...=...] %D \stoptyping %D -%D Again, the label identifies the category a variable -%D belongs to. The second argument can be a comma separated -%D list of assignments. +%D Again, the label identifies the category a variable belongs to. The second argument +%D can be a comma separated list of assignments. %D %D \starttyping %D \getparameters @@ -1567,8 +1598,7 @@ %D \stoptyping %D %D -%D In the pre||multi||lingual stadium \CONTEXT\ took the next -%D approach. With +%D In the pre||multi||lingual stadium \CONTEXT\ took the next approach. With %D %D \starttyping %D \def\??demo {@@demo} @@ -1592,20 +1622,16 @@ %D \def\@@demobeta{2} %D \stoptyping %D -%D Because we want to be able to distinguish the \type{!!} -%D pre||tagged user supplied variables from internal -%D counterparts, we will introduce a slightly different tag in -%D the multi||lingual modules. There we will use \type{c!} or -%D \type{v!}, depending on the context. -%D -%D By calling \type{\p!doassign} directly, we save ourselves -%D some argument passing and gain some speed. Whatever -%D optimizations we do, this command will always be one of the -%D bigger bottlenecks. +%D Because we want to be able to distinguish the \type{!!} pre||tagged user supplied +%D variables from internal counterparts, we will introduce a slightly different tag +%D in the multi||lingual modules. There we will use \type{c!} or \type{v!}, +%D depending on the context. %D -%D The alternative \type{\geteparameters} --- it's funny to -%D see that this alternative saw the light so lately --- can be -%D used to do expanded assigments. +%D By calling \type{doassign} directly, we save ourselves some argument passing +%D and gain some speed. Whatever optimizations we do, this command will always be +%D one of the bigger bottlenecks. The alternative \type{\geteparameters} --- it's +%D funny to see that this alternative saw the light so lately --- can be used to do +%D expanded assigments. \let\currentvalue\empty @@ -1617,46 +1643,46 @@ \let\getexpandedparameters\geteparameters -\def\dogetparameters#1[#2]#3[#4% +\unexpanded\def\dogetparameters#1[#2]#3[#4% {\if\noexpand#4]% \expandafter\gobbleoneargument \else \let\setsomevalue#1% - \def\p!dogetparameter{\p!doassign#2}% - \expandafter\xdogetparameters + \def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#2}% + \expandafter\syst_helpers_get_parameters \fi#4} -\def\xdogetparameters#1]% - {\xprocesscommaitem#1,],\@relax@} +\def\syst_helpers_get_parameters#1]% + {\xprocesscommaitem#1,],\_e_o_p_} -\def\xprocesscommaitem#1,#2% #2 takes space before , +\def\syst_helpers_process_comma_item#1,#2% #2 takes space before , {\if,#1,% dirty trick for testing #1=empty - \expandafter\xprocesscommaitem + \expandafter\syst_helpers_process_comma_item \else\if]#1% \doubleexpandafter\gobbleoneargument \else - \p!dogetparameter\@relax@#1==\empty\@relax@ - \doubleexpandafter\xprocesscommaitem + \syst_helpers_get_parameters_assign\_e_o_p_#1==\empty\_e_o_p_ + \doubleexpandafter\syst_helpers_process_comma_item \fi\fi#2} -\def\xshowassignerror#1#2#3% +\def\syst_helpers_assign_error#1#2#3% {\showassignerror{#2}{\the\inputlineno\space(#1)}} -\def\p!n!doassign#1\@relax@#2=#3=#4#5\@relax@ +\def\syst_helpers_get_parameters_assign_normal#1\_e_o_p_#2=#3=#4#5\_e_o_p_ {\ifx\empty#2\empty - \expandafter\xshowassignerror + \expandafter\syst_helpers_assign_error \else\ifx#4\empty - \doubleexpandafter\xshowassignerror + \doubleexpandafter\syst_helpers_assign_error \else \doubleexpandafter\setsomevalue \fi\fi {#1}{#2}{#3}} -\def\p!e!doassign#1\@relax@#2=#3=#4#5\@relax@ +\def\syst_helpers_get_parameters_assign_error#1\_e_o_p_#2=#3=#4#5\_e_o_p_ {\ifx\empty#2\empty - \expandafter\xshowassignerror + \expandafter\syst_helpers_assign_error \else\ifx#4\empty - \doubleexpandafter\xshowassignerror + \doubleexpandafter\syst_helpers_assign_error \else \ifcsname#1#2\endcsname \expandafter\let\expandafter\currentvalue\csname#1#2\endcsname @@ -1667,11 +1693,11 @@ \fi\fi {#1}{#2}{#3}} -\let\p!doassign\p!n!doassign +\let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal -\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \p!doassign#1\@relax@#2==\empty\@relax@} -\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \p!doassign#1\@relax@#2==\empty\@relax@} -\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\p!doassign#1\@relax@#2==\empty\@relax@} +\unexpanded\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_} +\unexpanded\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_} +\unexpanded\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_} %D \macros %D {processassignmentlist,processassignmentcommand, @@ -1688,8 +1714,8 @@ %D worth the trouble and tokens. \unexpanded\def\processassignmentlist[#1]#2% #2 == \command{key}{value] - {\def\doprocessassignmententry##1{#2}% {##2}{##3} % namespace is ignored - \dogetparameters\doprocessassignmententry[][#1]} + {\def\syst_helpers_process_assignment_entry##1{#2}% {##2}{##3} % namespace is ignored + \dogetparameters\syst_helpers_process_assignment_entry[][#1]} \unexpanded\def\processassignmentcommand[#1]% {\normalexpanded{\processassignmentlist[#1]}} @@ -1704,9 +1730,8 @@ %D \macros{currentvalue} %D -%D Just in case a \type{\getparameter} argument itself ends up -%D inside a \type{\write} or other expandable location, our -%D new macro needs a default value. +%D Just in case a \type{\getparameter} argument itself ends up inside a \type +%D {\write} or other expandable location, our new macro needs a default value. %D %D \starttyping %D \getparameters[xxx][aaa=bbb]\par @@ -1716,7 +1741,8 @@ %D \getparameters[xxx][aaa]\par %D \stoptyping -%D \macros {expandparameters} +%D \macros +%D {expandparameters} %D %D Example usage: %D @@ -1733,26 +1759,27 @@ %D \startlines %D \getbuffer %D \stoplines - +%D %D Here we hook in the code (beware, this is the optimized get **): -\def\xdoget@n@parameters#1]% - {\xprocesscommaitem#1,],\@relax@} +\def\syst_helpers_get_parameters_normal#1]% + {\syst_helpers_process_comma_item#1,],\_e_o_p_} -\def\xdoget@e@parameters#1]% +\def\syst_helpers_get_parameters_expanded#1]% {\let\dosetnvalue\setsomevalue \let\setsomevalue\dosetevalue - \let\p!doassign\p!e!doassign + \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_error \let\setsomevalue\dosetevalue - \xprocesscommaitem#1,],\@relax@ - \let\p!doassign\p!n!doassign + \syst_helpers_process_comma_item#1,],\_e_o_p_ + \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal \let\setsomevalue\dosetnvalue - \let\xdogetparameters\xdoget@n@parameters + \let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal \let\currentvalue\empty} -\let\xdogetparameters\xdoget@n@parameters % ** +\let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal % ** -\def\expandparameters{\let\xdogetparameters\xdoget@e@parameters} +\unexpanded\def\expandparameters + {\let\syst_helpers_get_parameters\syst_helpers_get_parameters_expanded} %D \macros %D {getemptyparameters} @@ -1764,9 +1791,9 @@ %D \getemptyparameters [label] [...=...,...=...] %D \stoptyping -\def\getemptyparameters[#1]#2[#3]% - {\def\p!dogetemptyparameter##1{\doassignempty[#1][##1]}% - \processcommalist[#3]\p!dogetemptyparameter} +\unexpanded\def\getemptyparameters[#1]#2[#3]% + {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}% + \processcommalist[#3]\syst_helpers_get_empty_parameters} %D \macros %D {copyparameters} @@ -1801,8 +1828,8 @@ \unexpanded\def\copyparameters[#1]#2[#3]#4[#5]% {\doifnot{#1}{#3} - {\def\docopyparameter{\docopyvalue{#1}{#3}}% ##1 - \processcommalist[#5]\docopyparameter}} + {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#3}}% ##1 + \processcommalist[#5]\syst_helpers_copy_parameter}} %D \macros %D {ifparameters,checkparameters} @@ -1820,58 +1847,60 @@ \newif\ifparameters -\def\p!checkparameters#1=#2#3\war% +\def\syst_helpers_check_parameters#1=#2#3\_e_o_s_ {\if#2@\parametersfalse\else\parameterstrue\fi} -\def\checkparameters[#1]% - {\p!checkparameters#1=@@\war} +\unexpanded\def\checkparameters[#1]% + {\syst_helpers_check_parameters#1=@@\_e_o_s_} %D \macros %D {getfromcommalist,getfromcommacommand, %D commalistelement, %D getcommalistsize,getcommacommandsize} %D -%D It's possible to get an element from a commalist or a -%D command representing a commalist. +%D It's possible to get an element from a commalist or a command representing +%D a commalist. %D %D \starttyping %D \getfromcommalist [string] [n] %D \getfromcommacommand [string,\strings,string,...] [n] %D \stoptyping %D -%D The difference betwee the two of them is the same as the -%D difference between \type{\processcomma...}. The found string -%D is stored in \type{\commalistelement}. +%D The difference betwee the two of them is the same as the difference between +%D \type {\processcomma...}. The found string is stored in \type +%D {\commalistelement}. %D -%D We can calculate the size of a comma separated list by -%D using: +%D We can calculate the size of a comma separated list by using: %D %D \starttyping %D \getcommalistsize [string,string,...] %D \getcommacommandsize [string,\strings,string,...] %D \stoptyping %D -%D Afterwards, the length is available in the macro -%D \type{\commalistsize} (not a \COUNTER). +%D Afterwards, the length is available in the macro \type {\commalistsize} +%D (not a \COUNTER). \newcount\commalistcounter \def\commalistsize{0} -\def\p!dogetcommalistsize#1% +\def\syst_helpers_get_comma_list_size#1% {\advance\commalistcounter\plusone} -\def\getcommalistsize#1]% don't loose [{#1}] +\unexpanded\def\getcommalistsize#1]% don't loose [{#1}] {\commalistcounter\zerocount - \processcommalist#1]\p!dogetcommalistsize % was [{#1}] + \processcommalist#1]\syst_helpers_get_comma_list_size % was [{#1}] \edef\commalistsize{\the\commalistcounter}} -\def\getcommacommandsize[#1]% - {\edef\commacommand{#1}% - \scratchtoks\expandafter{\expandafter[\commacommand]}% - \expandafter\getcommalistsize\the\scratchtoks } +% \def\getcommacommandsize[#1]% +% {\edef\commacommand{#1}% +% \scratchtoks\expandafter{\expandafter[\commacommand]}% +% \expandafter\getcommalistsize\the\scratchtoks } -\def\p!dogetfromcommalist#1% +\unexpanded\def\getcommacommandsize[#1]% + {\normalexpanded{\getcommalistsize[#1]}} + +\def\syst_helpers_get_from_comma_list#1% {\advance\commalistcounter \minusone \ifcase\commalistcounter \def\commalistelement{#1}% @@ -1881,7 +1910,7 @@ \unexpanded\def\getfromcommalist[#1]#2[#3]% {\let\commalistelement\empty \commalistcounter#3\relax - \processcommalist[#1]\p!dogetfromcommalist} + \processcommalist[#1]\syst_helpers_get_from_comma_list} \unexpanded\def\getfromcommacommand[#1]% {\normalexpanded{\getfromcommalist[#1]}} @@ -1919,16 +1948,11 @@ %D \dogetcommalistelement1\from a,b,c\to\commalistelement %D \stoptyping -\def\dodogetcommalistelement#1\from#2,#3,#4,#5,#6,#7,#8\to#9% +\def\syst_helpers_get_comma_list_element#1\from#2,#3,#4,#5,#6,#7,#8\to#9% {\edef#9{\ifcase#1\relax\or#2\or#3\or#4\or#5\or#6\or#7\or#8\fi}} -\def\dogetcommalistelement#1\from#2\to% - {\dodogetcommalistelement#1\from#2,,,,,,\to} - -% check sources - \def\dogetcommacommandelement#1\from#2\to% - {\expandafter\dodogetcommalistelement\expandafter#1\expandafter\from#2,,,,,,\to} + {\expandafter\syst_helpers_get_comma_list_element\expandafter#1\expandafter\from#2,,,,,,\to} %D \macros %D {dosingleargument,dodoubleargument,dotripleargument, @@ -1984,13 +2008,15 @@ %D us to do some checking, we reimplemented the non||empty %D ones. -\unexpanded\def\dosingleargument {\let\expectedarguments\plusone \dosingleempty } -\unexpanded\def\dodoubleargument {\let\expectedarguments\plustwo \dodoubleempty } -\unexpanded\def\dotripleargument {\let\expectedarguments\plusthree \dotripleempty } -\unexpanded\def\doquadrupleargument {\let\expectedarguments\plusfour \doquadrupleempty } -\unexpanded\def\doquintupleargument {\let\expectedarguments\plusfive \doquintupleempty } -\unexpanded\def\dosixtupleargument {\let\expectedarguments\plussix \dosixtupleempty } -\unexpanded\def\doseventupleargument{\let\expectedarguments\plusseven \doseventupleempty} +% no longer a mesage: +% +% \unexpanded\def\dosingleargument {\let\expectedarguments\plusone \dosingleempty } +% \unexpanded\def\dodoubleargument {\let\expectedarguments\plustwo \dodoubleempty } +% \unexpanded\def\dotripleargument {\let\expectedarguments\plusthree \dotripleempty } +% \unexpanded\def\doquadrupleargument {\let\expectedarguments\plusfour \doquadrupleempty } +% \unexpanded\def\doquintupleargument {\let\expectedarguments\plusfive \doquintupleempty } +% \unexpanded\def\dosixtupleargument {\let\expectedarguments\plussix \dosixtupleempty } +% \unexpanded\def\doseventupleargument{\let\expectedarguments\plusseven \doseventupleempty} %D \macros %D {iffirstagument,ifsecondargument,ifthirdargument, @@ -2013,8 +2039,7 @@ %D doquadrupleempty,doquintupleempty,dosixtupeempty, %D doseventupleempty} %D -%D The empty argument supplying macros mentioned before, look -%D like: +%D The empty argument supplying macros mentioned before, look like: %D %D \starttyping %D \dosingleempty \command @@ -2022,11 +2047,11 @@ %D \dotripleempty \command %D \doquadrupleempty \command %D \doquintupleempty \command -%D \dosixtupleempty \command +%D \dosixtuple_empty \command %D \doseventupleempty\command %D \stoptyping %D -%D So \type{\dodoubleempty} leades to: +%D So \type{\dodoubleempty} leads to: %D %D \starttyping %D \command[#1][#2] @@ -2041,16 +2066,16 @@ \setnewconstant\noexpectedarguments\zerocount \setnewconstant\expectedarguments \zerocount -\def\showargumenterror#1#2% +\unexpanded\def\showargumenterror#1#2% {\writestatus{system}{\number#1 argument(s) expected in line #2}} -\def\doshowargumenterror +\unexpanded\def\syst_helpers_argument_error {\ifnum\expectedarguments>\noexpectedarguments \showargumenterror{\number\expectedarguments}{\number\inputlineno}% \fi - \noshowargumenterror} + \syst_helpers_argument_reset} -\def\noshowargumenterror +\unexpanded\def\syst_helpers_argument_reset {\let\expectedarguments\noexpectedarguments} % \def\test[#1]{(#1)} @@ -2074,193 +2099,193 @@ %D Single: \unexpanded\def\dosingleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse {\firstargumenttrue#1}% - {\dosingleemptyNOPone#1}} + {\syst_helpers_single_empty_one_nop#1}} -\def\dosingleemptyNOPone#1% +\def\syst_helpers_single_empty_one_nop#1% {\firstargumentfalse #1[]} %D Double \unexpanded\def\dodoubleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\dodoubleemptyYESone#1}% - {\dodoubleemptyNOPone#1}} + {\syst_helpers_double_empty_one_yes#1}% + {\syst_helpers_double_empty_one_nop#1}} -\def\dodoubleemptyYESone#1[#2]% +\def\syst_helpers_double_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse {\secondargumenttrue#1[{#2}]}% - {\dodoubleemptyNOPtwo#1{#2}}} + {\syst_helpers_double_empty_two_nop#1{#2}}} -\def\dodoubleemptyNOPone#1% +\def\syst_helpers_double_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse #1[][]} -\def\dodoubleemptyNOPtwo +\def\syst_helpers_double_empty_two_nop {\secondargumentfalse \if_next_blank_space_token - \expandafter\dodoubleemptyonespaced + \expandafter\syst_helpers_double_empty_one_spaced \else - \expandafter\dodoubleemptyonenormal + \expandafter\syst_helpers_double_empty_one_normal \fi} -\def\dodoubleemptyonespaced#1#2{#1[{#2}][] } -\def\dodoubleemptyonenormal#1#2{#1[{#2}][]} +\def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] } +\def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]} % Three \unexpanded\def\dotripleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\dotripleemptyYESone#1}% - {\dotripleemptyNOPone#1}} + {\syst_helpers_triple_empty_one_yes#1}% + {\syst_helpers_triple_empty_one_nop#1}} -\def\dotripleemptyYESone#1[#2]% +\def\syst_helpers_triple_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse - {\dotripleemptyYEStwo#1{#2}}% - {\dotripleemptyNOPtwo#1{#2}}} + {\syst_helpers_triple_empty_two_yes#1{#2}}% + {\syst_helpers_triple_empty_two_nop#1{#2}}} -\def\dotripleemptyYEStwo#1#2[#3]% +\def\syst_helpers_triple_empty_two_yes#1#2[#3]% {\secondargumenttrue \doifnextoptionalelse {\thirdargumenttrue#1[{#2}][{#3}]}% - {\dotripleemptyNOPthree#1{#2}{#3}}} + {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}} -\def\dotripleemptyNOPone#1% +\def\syst_helpers_triple_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse \thirdargumentfalse #1[][][]} -\def\dotripleemptyNOPtwo +\def\syst_helpers_triple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \if_next_blank_space_token - \expandafter\dotripleemptytwospaced + \expandafter\syst_helpers_triple_empty_two_spaced \else - \expandafter\dotripleemptytwonormal + \expandafter\syst_helpers_triple_empty_two_normal \fi} -\def\dotripleemptyNOPthree +\def\syst_helpers_triple_empty_three_nop {\thirdargumentfalse \if_next_blank_space_token - \expandafter\dotripleemptythreespaced + \expandafter\syst_helpers_triple_empty_three_spaced \else - \expandafter\dotripleemptythreenormal + \expandafter\syst_helpers_triple_empty_three_normal \fi} -\def\dotripleemptytwospaced #1#2{#1[{#2}][][] } -\def\dotripleemptytwonormal #1#2{#1[{#2}][][]} -\def\dotripleemptythreespaced#1#2#3{#1[{#2}][{#3}][] } -\def\dotripleemptythreenormal#1#2#3{#1[{#2}][{#3}][]} +\def\syst_helpers_triple_empty_two_spaced #1#2{#1[{#2}][][] } +\def\syst_helpers_triple_empty_two_normal #1#2{#1[{#2}][][]} +\def\syst_helpers_triple_empty_three_spaced#1#2#3{#1[{#2}][{#3}][] } +\def\syst_helpers_triple_empty_three_normal#1#2#3{#1[{#2}][{#3}][]} %D Four: \unexpanded\def\doquadrupleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\doquadrupleemptyYESone#1}% - {\doquadrupleemptyNOPone#1}} + {\syst_helpers_quadruple_empty_one_yes#1}% + {\syst_helpers_quadruple_empty_one_nop#1}} -\def\doquadrupleemptyYESone#1[#2]% +\def\syst_helpers_quadruple_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse - {\doquadrupleemptyYEStwo#1{#2}}% - {\doquadrupleemptyNOPtwo#1{#2}}} + {\syst_helpers_quadruple_empty_two_yes#1{#2}}% + {\syst_helpers_quadruple_empty_two_nop#1{#2}}} -\def\doquadrupleemptyYEStwo#1#2[#3]% +\def\syst_helpers_quadruple_empty_two_yes#1#2[#3]% {\secondargumenttrue \doifnextoptionalelse - {\doquadrupleemptyYESthree#1{#2}{#3}}% - {\doquadrupleemptyNOPthree#1{#2}{#3}}} + {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}% + {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}} -\def\doquadrupleemptyYESthree#1#2#3[#4]% +\def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]% {\thirdargumenttrue \doifnextoptionalelse {\fourthargumenttrue#1[{#2}][{#3}][{#4}]}% - {\doquadrupleemptyNOPfour#1{#2}{#3}{#4}}} + {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}} -\def\doquadrupleemptyNOPone#1% +\def\syst_helpers_quadruple_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse \thirdargumentfalse \fourthargumentfalse #1[][][][]} -\def\doquadrupleemptyNOPtwo +\def\syst_helpers_quadruple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \fourthargumentfalse \if_next_blank_space_token - \expandafter\doquadrupleemptytwospaced + \expandafter\syst_helpers_quadruple_empty_two_spaced \else - \expandafter\doquadrupleemptytwonormal + \expandafter\syst_helpers_quadruple_empty_two_normal \fi} -\def\doquadrupleemptyNOPthree +\def\syst_helpers_quadruple_empty_three_nop {\thirdargumentfalse \fourthargumentfalse \if_next_blank_space_token - \expandafter\doquadrupleemptythreespaced + \expandafter\syst_helpers_quadruple_empty_three_spaced \else - \expandafter\doquadrupleemptythreenormal + \expandafter\syst_helpers_quadruple_empty_three_normal \fi} -\def\doquadrupleemptyNOPfour +\def\syst_helpers_quadruple_empty_four_nop {\fourthargumentfalse \if_next_blank_space_token - \expandafter\doquadrupleemptyfourspaced + \expandafter\syst_helpers_quadruple_empty_four_spaced \else - \expandafter\doquadrupleemptyfournormal + \expandafter\syst_helpers_quadruple_empty_four_normal \fi} -\def\doquadrupleemptytwospaced #1#2{#1[{#2}][][][] } -\def\doquadrupleemptytwonormal #1#2{#1[{#2}][][][]} -\def\doquadrupleemptythreespaced #1#2#3{#1[{#2}][{#3}][][] } -\def\doquadrupleemptythreenormal #1#2#3{#1[{#2}][{#3}][][]} -\def\doquadrupleemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] } -\def\doquadrupleemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][]} +\def\syst_helpers_quadruple_empty_two_spaced #1#2{#1[{#2}][][][] } +\def\syst_helpers_quadruple_empty_two_normal #1#2{#1[{#2}][][][]} +\def\syst_helpers_quadruple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][] } +\def\syst_helpers_quadruple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][]} +\def\syst_helpers_quadruple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] } +\def\syst_helpers_quadruple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][]} %D Five: \unexpanded\def\doquintupleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\doquintupleemptyYESone#1}% - {\doquintupleemptyNOPone#1}} + {\syst_helpers_quintuple_empty_one_yes#1}% + {\syst_helpers_quintuple_empty_one_nop#1}} -\def\doquintupleemptyYESone#1[#2]% +\def\syst_helpers_quintuple_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse - {\doquintupleemptyYEStwo#1{#2}}% - {\doquintupleemptyNOPtwo#1{#2}}} + {\syst_helpers_quintuple_empty_two_yes#1{#2}}% + {\syst_helpers_quintuple_empty_two_nop#1{#2}}} -\def\doquintupleemptyYEStwo#1#2[#3]% +\def\syst_helpers_quintuple_empty_two_yes#1#2[#3]% {\secondargumenttrue \doifnextoptionalelse - {\doquintupleemptyYESthree#1{#2}{#3}}% - {\doquintupleemptyNOPthree#1{#2}{#3}}} + {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}% + {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}} -\def\doquintupleemptyYESthree#1#2#3[#4]% +\def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]% {\thirdargumenttrue \doifnextoptionalelse - {\doquintupleemptyYESfour#1{#2}{#3}{#4}}% - {\doquintupleemptyNOPfour#1{#2}{#3}{#4}}} + {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}% + {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}} -\def\doquintupleemptyYESfour#1#2#3#4[#5]% +\def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]% {\fourthargumenttrue \doifnextoptionalelse {\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}% - {\doquintupleemptyNOPfive#1{#2}{#3}{#4}{#5}}} + {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} -\def\doquintupleemptyNOPone#1% +\def\syst_helpers_quintuple_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse \thirdargumentfalse @@ -2268,92 +2293,92 @@ \fifthargumentfalse #1[][][][][]} -\def\doquintupleemptyNOPtwo +\def\syst_helpers_quintuple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\doquintupleemptytwospaced + \expandafter\syst_helpers_quintuple_empty_two_spaced \else - \expandafter\doquintupleemptytwonormal + \expandafter\syst_helpers_quintuple_empty_two_normal \fi} -\def\doquintupleemptyNOPthree +\def\syst_helpers_quintuple_empty_three_nop {\thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\doquintupleemptythreespaced + \expandafter\syst_helpers_quintuple_empty_three_spaced \else - \expandafter\doquintupleemptythreenormal + \expandafter\syst_helpers_quintuple_empty_three_normal \fi} -\def\doquintupleemptyNOPfour +\def\syst_helpers_quintuple_empty_four_nop {\fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\doquintupleemptyfourspaced + \expandafter\syst_helpers_quintuple_empty_four_spaced \else - \expandafter\doquintupleemptyfournormal + \expandafter\syst_helpers_quintuple_empty_four_normal \fi} -\def\doquintupleemptyNOPfive +\def\syst_helpers_quintuple_empty_five_nop {\fifthargumentfalse \if_next_blank_space_token - \expandafter\doquintupleemptyfivespaced + \expandafter\syst_helpers_quintuple_empty_five_spaced \else - \expandafter\doquintupleemptyfivenormal + \expandafter\syst_helpers_quintuple_empty_five_normal \fi} -\def\doquintupleemptytwospaced #1#2{#1[{#2}][][][][] } -\def\doquintupleemptytwonormal #1#2{#1[{#2}][][][][]} -\def\doquintupleemptythreespaced #1#2#3{#1[{#2}][{#3}][][][] } -\def\doquintupleemptythreenormal #1#2#3{#1[{#2}][{#3}][][][]} -\def\doquintupleemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] } -\def\doquintupleemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]} -\def\doquintupleemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] } -\def\doquintupleemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]} +\def\syst_helpers_quintuple_empty_two_spaced #1#2{#1[{#2}][][][][] } +\def\syst_helpers_quintuple_empty_two_normal #1#2{#1[{#2}][][][][]} +\def\syst_helpers_quintuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][] } +\def\syst_helpers_quintuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][]} +\def\syst_helpers_quintuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] } +\def\syst_helpers_quintuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]} +\def\syst_helpers_quintuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] } +\def\syst_helpers_quintuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]} %D Six \unexpanded\def\dosixtupleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\dosixtupleemptyYESone#1} - {\dosixtupleemptyNOPone#1}} + {\syst_helpers_sixtuple_empty_one_yes#1} + {\syst_helpers_sixtuple_empty_one_nop#1}} -\def\dosixtupleemptyYESone#1[#2]% +\def\syst_helpers_sixtuple_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse - {\dosixtupleemptyYEStwo#1{#2}}% - {\dosixtupleemptyNOPtwo#1{#2}}} + {\syst_helpers_sixtuple_empty_two_yes#1{#2}}% + {\syst_helpers_sixtuple_empty_two_nop#1{#2}}} -\def\dosixtupleemptyYEStwo#1#2[#3]% +\def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]% {\secondargumenttrue \doifnextoptionalelse - {\dosixtupleemptyYESthree#1{#2}{#3}}% - {\dosixtupleemptyNOPthree#1{#2}{#3}}} + {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}% + {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}} -\def\dosixtupleemptyYESthree#1#2#3[#4]% +\def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]% {\thirdargumenttrue \doifnextoptionalelse - {\dosixtupleemptyYESfour#1{#2}{#3}{#4}}% - {\dosixtupleemptyNOPfour#1{#2}{#3}{#4}}} + {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}% + {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}} -\def\dosixtupleemptyYESfour#1#2#3#4[#5]% +\def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]% {\fourthargumenttrue \doifnextoptionalelse - {\dosixtupleemptyYESfive#1{#2}{#3}{#4}{#5}}% - {\dosixtupleemptyNOPfive#1{#2}{#3}{#4}{#5}}} + {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% + {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} -\def\dosixtupleemptyYESfive#1#2#3#4#5[#6]% +\def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]% {\fifthargumenttrue \doifnextoptionalelse {\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}% - {\dosixtupleemptyNOPsix#1{#2}{#3}{#4}{#5}{#6}}} + {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} -\def\dosixemptyNOPone#1% +\def\syst_helpers_sixtuple_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse \thirdargumentfalse @@ -2362,112 +2387,112 @@ \sixthargumentfalse #1[][][][][][]} -\def\dosixtupleemptyNOPtwo +\def\syst_helpers_sixtuple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\dosixemptytwospaced + \expandafter\syst_helpers_sixtuple_empty_two_spaced \else - \expandafter\dosixemptytwonormal + \expandafter\syst_helpers_sixtuple_empty_two_normal \fi} -\def\dosixtupleemptyNOPthree +\def\syst_helpers_sixtuple_empty_three_nop {\thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\dosixemptythreespaced + \expandafter\syst_helpers_sixtuple_empty_three_spaced \else - \expandafter\dosixemptythreenormal + \expandafter\syst_helpers_sixtuple_empty_three_normal \fi} -\def\dosixtupleemptyNOPfour +\def\syst_helpers_sixtuple_empty_four_nop {\fourthargumentfalse \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\dosixemptyfourspaced + \expandafter\syst_helpers_sixtuple_empty_four_spaced \else - \expandafter\dosixemptyfournormal + \expandafter\syst_helpers_sixtuple_empty_four_normal \fi} -\def\dosixtupleemptyNOPfive +\def\syst_helpers_sixtuple_empty_five_nop {\fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\dosixemptyfivespaced + \expandafter\syst_helpers_sixtuple_empty_five_spaced \else - \expandafter\dosixemptyfivenormal + \expandafter\syst_helpers_sixtuple_empty_five_normal \fi} -\def\dosixtupleemptyNOPsix +\def\syst_helpers_sixtuple_empty_six_nop {\sixthargumentfalse \if_next_blank_space_token - \expandafter\dosixemptysixspaced + \expandafter\syst_helpers_sixtuple_empty_six_spaced \else - \expandafter\dosixemptysixnormal + \expandafter\syst_helpers_sixtuple_empty_six_normal \fi} -\def\dosixemptytwospaced #1#2{#1[{#2}][][][][][] } -\def\dosixemptytwonormal #1#2{#1[{#2}][][][][][]} -\def\dosixemptythreespaced #1#2#3{#1[{#2}][{#3}][][][][] } -\def\dosixemptythreenormal #1#2#3{#1[{#2}][{#3}][][][][]} -\def\dosixemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] } -\def\dosixemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]} -\def\dosixemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] } -\def\dosixemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]} -\def\dosixemptysixspaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] } -\def\dosixemptysixnormal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]} +\def\syst_helpers_sixtuple_empty_two_spaced #1#2{#1[{#2}][][][][][] } +\def\syst_helpers_sixtuple_empty_two_normal #1#2{#1[{#2}][][][][][]} +\def\syst_helpers_sixtuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][] } +\def\syst_helpers_sixtuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][]} +\def\syst_helpers_sixtuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] } +\def\syst_helpers_sixtuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]} +\def\syst_helpers_sixtuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] } +\def\syst_helpers_sixtuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]} +\def\syst_helpers_sixtuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] } +\def\syst_helpers_sixtuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]} %D Seven: \unexpanded\def\doseventupleempty#1% - {\noshowargumenterror + {\syst_helpers_argument_reset \doifnextoptionalelse - {\doseventupleemptyYESone#1}% - {\doseventupleemptyNOPone#1}} + {\syst_helpers_seventuple_empty_one_yes#1}% + {\syst_helpers_seventuple_empty_one_nop#1}} -\def\doseventupleemptyYESone#1[#2]% +\def\syst_helpers_seventuple_empty_one_yes#1[#2]% {\firstargumenttrue \doifnextoptionalelse - {\doseventupleemptyYEStwo#1{#2}}% - {\doseventupleemptyNOPtwo#1{#2}}} + {\syst_helpers_seventuple_empty_two_yes#1{#2}}% + {\syst_helpers_seventuple_empty_two_nop#1{#2}}} -\def\doseventupleemptyYEStwo#1#2[#3]% +\def\syst_helpers_seventuple_empty_two_yes#1#2[#3]% {\secondargumenttrue \doifnextoptionalelse - {\doseventupleemptyYESthree#1{#2}{#3}}% - {\doseventupleemptyNOPthree#1{#2}{#3}}} + {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}% + {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}} -\def\doseventupleemptyYESthree#1#2#3[#4]% +\def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]% {\thirdargumenttrue \doifnextoptionalelse - {\doseventupleemptyYESfour#1{#2}{#3}{#4}}% - {\doseventupleemptyNOPfour#1{#2}{#3}{#4}}} + {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}% + {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}} -\def\doseventupleemptyYESfour#1#2#3#4[#5]% +\def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]% {\fourthargumenttrue \doifnextoptionalelse - {\doseventupleemptyYESfive#1{#2}{#3}{#4}{#5}}% - {\doseventupleemptyNOPfive#1{#2}{#3}{#4}{#5}}} + {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% + {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} -\def\doseventupleemptyYESfive#1#2#3#4#5[#6]% +\def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]% {\fifthargumenttrue \doifnextoptionalelse - {\doseventupleemptyYESsix#1{#2}{#3}{#4}{#5}{#6}}% - {\doseventupleemptyNOPsix#1{#2}{#3}{#4}{#5}{#6}}} + {\syst_helpers_seventuple_empty_six_yes#1{#2}{#3}{#4}{#5}{#6}}% + {\syst_helpers_seventuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} -\def\doseventupleemptyYESsix#1#2#3#4#5#6[#7]% +\def\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]% {\sixthargumenttrue \doifnextoptionalelse {\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}% - {\doseventupleemptyNOPseven#1{#2}{#3}{#4}{#5}{#6}{#7}}} + {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}} -\def\dosevenemptyNOPone#1% +\def\syst_helpers_seventuple_empty_one_nop#1% {\firstargumentfalse \secondargumentfalse \thirdargumentfalse @@ -2477,7 +2502,7 @@ \seventhargumentfalse #1[][][][][][][]} -\def\doseventupleemptyNOPtwo +\def\syst_helpers_seventuple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \fourthargumentfalse @@ -2485,73 +2510,81 @@ \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptytwospaced + \expandafter\syst_helpers_seventuple_empty_two_spaced \else - \expandafter\dosevenemptytwonormal + \expandafter\syst_helpers_seventuple_empty_two_normal \fi} -\def\doseventupleemptyNOPthree +\def\syst_helpers_seventuple_empty_three_nop {\thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptythreespaced + \expandafter\syst_helpers_seventuple_empty_three_spaced \else - \expandafter\dosevenemptythreenormal + \expandafter\syst_helpers_seventuple_empty_three_normal \fi} -\def\doseventupleemptyNOPfour +\def\syst_helpers_seventuple_empty_four_nop {\fourthargumentfalse \fifthargumentfalse \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptyfourspaced + \expandafter\syst_helpers_seventuple_empty_four_spaced \else - \expandafter\dosevenemptyfournormal + \expandafter\syst_helpers_seventuple_empty_four_normal \fi} -\def\doseventupleemptyNOPfive +\def\syst_helpers_seventuple_empty_five_nop {\fifthargumentfalse \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptyfivespaced + \expandafter\syst_helpers_seventuple_empty_five_spaced \else - \expandafter\dosevenemptyfivenormal + \expandafter\syst_helpers_seventuple_empty_five_normal \fi} -\def\doseventupleemptyNOPsix +\def\syst_helpers_seventuple_empty_six_nop {\sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptysixspaced + \expandafter\syst_helpers_seventuple_empty_six_spaced \else - \expandafter\dosevenemptysixnormal + \expandafter\syst_helpers_seventuple_empty_six_normal \fi} -\def\doseventupleemptyNOPseven +\def\syst_helpers_seventuple_empty_seven_nop {\seventhargumentfalse \if_next_blank_space_token - \expandafter\dosevenemptysevenspaced - \else - \expandafter\dosevenemptysevennormal - \fi} - -\def\dosevenemptytwospaced #1#2{#1[{#2}][][][][][][] } -\def\dosevenemptytwonormal #1#2{#1[{#2}][][][][][][]} -\def\dosevenemptythreespaced #1#2#3{#1[{#2}][{#3}][][][][][] } -\def\dosevenemptythreenormal #1#2#3{#1[{#2}][{#3}][][][][][]} -\def\dosevenemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] } -\def\dosevenemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]} -\def\dosevenemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] } -\def\dosevenemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]} -\def\dosevenemptysixspaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] } -\def\dosevenemptysixnormal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]} -\def\dosevenemptysevenspaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] } -\def\dosevenemptysevennormal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]} + \expandafter\syst_helpers_seventuple_empty_seven_spaced + \else + \expandafter\syst_helpers_seventuple_empty_seven_normal + \fi} + +\def\syst_helpers_seventuple_empty_two_spaced #1#2{#1[{#2}][][][][][][] } +\def\syst_helpers_seventuple_empty_two_normal #1#2{#1[{#2}][][][][][][]} +\def\syst_helpers_seventuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][][] } +\def\syst_helpers_seventuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][][]} +\def\syst_helpers_seventuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] } +\def\syst_helpers_seventuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]} +\def\syst_helpers_seventuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] } +\def\syst_helpers_seventuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]} +\def\syst_helpers_seventuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] } +\def\syst_helpers_seventuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]} +\def\syst_helpers_seventuple_empty_seven_spaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] } +\def\syst_helpers_seventuple_empty_seven_normal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]} + +\let\dosingleargument \dosingleempty +\let\dodoubleargument \dodoubleempty +\let\dotripleargument \dotripleempty +\let\doquadrupleargument \doquadrupleempty +\let\doquintupleargument \doquintupleempty +\let\dosixtupleargument \dosixtupleempty +\let\doseventupleargument\doseventupleempty %D \macros %D {strippedcsname} @@ -2628,22 +2661,20 @@ %D worthwile to offer two more alternatives. Watch the build %D in protection. -\def\docomplexorsimple#1#2% +\unexpanded\def\syst_helpers_complex_or_simple#1#2% {\doifnextoptionalelse{\firstargumenttrue#1}{\firstargumentfalse#2}} -\def\docomplexorsimpleempty#1% +\unexpanded\def\syst_helpers_complex_or_simple_empty#1% {\doifnextoptionalelse{\firstargumenttrue#1}{\firstargumentfalse#1[]}} \unexpanded\def\definecomplexorsimple#1% - {\unexpanded\edef#1% - {\noexpand\docomplexorsimple - \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname - \expandafter\noexpand\csname\s!simple \strippedcsname#1\endcsname}} + {\unexpanded\edef#1{\syst_helpers_complex_or_simple + \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname + \expandafter\noexpand\csname\s!simple \strippedcsname#1\endcsname}} \unexpanded\def\definecomplexorsimpleempty#1% - {\unexpanded\edef#1% - {\noexpand\docomplexorsimpleempty - \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}} + {\unexpanded\edef#1{\syst_helpers_complex_or_simple_empty + \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}} %D These commands are called as: %D @@ -2679,8 +2710,10 @@ %D We can add additional definitions later when we have defined %D \type {\appendtoks}. -\def \permitspacesbetweengroups{\let\@@permitspacesbetweengroups\zerocount} -\def\dontpermitspacesbetweengroups{\let\@@permitspacesbetweengroups\plusone} +\newconditional\c_syst_helpers_permit_spaces_between_groups + +\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups} +\def\dontpermitspacesbetweengroups{\setfalse\c_syst_helpers_permit_spaces_between_groups} \dontpermitspacesbetweengroups @@ -2689,94 +2722,94 @@ %D potentially being an \type {conditional} token. Okay, these macros %D are not called that often but it saves crap when tracing. -\def\dodogetgroupargument +\unexpanded\def\syst_helpers_get_grouped_argument#1#2% + {\let\syst_helpers_get_grouped_argument_yes#1% + \let\syst_helpers_get_grouped_argument_nop#2% + \futurelet\nextargument\syst_helpers_get_grouped_argument_indeed} + +\def\syst_helpers_get_grouped_argument_indeed {\ifx\nextargument\bgroup - \expandafter\dodogetgroupargumentA + \expandafter\syst_helpers_get_grouped_argument_a \else - \expandafter\dodogetgroupargumentB + \expandafter\syst_helpers_get_grouped_argument_b \fi} -\def\dodogetgroupargumentA - {\noshowargumenterror - \dogroupargumentyes\dodogetargument} +\def\syst_helpers_get_grouped_argument_a + {\syst_helpers_argument_reset + \syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nested} -\def\dodogetgroupargumentB - {\ifcase\@@permitspacesbetweengroups - \expandafter\dodogetgroupargumentF +\def\syst_helpers_get_grouped_argument_b + {\ifconditional\c_syst_helpers_permit_spaces_between_groups + \expandafter\syst_helpers_get_grouped_argument_f \else - \expandafter\dodogetgroupargumentD + \expandafter\syst_helpers_get_grouped_argument_d \fi} -\def\dodogetgroupargumentD - {\doshowargumenterror - \dogroupargumentnop\dodogetargument{}} +\def\syst_helpers_get_grouped_argument_d + {\syst_helpers_argument_error + \syst_helpers_get_grouped_argument_nop\syst_helpers_get_grouped_argument_nested{}} \begingroup - \def\\ {\dogetgroupargument\dogroupargumentyes\dogroupargumentnop} - \global\let\dodogetgroupargumentE\\ + \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop} + \global\let\syst_helpers_get_grouped_argument_e\\ \endgroup -\def\dodogetgroupargumentF +\def\syst_helpers_get_grouped_argument_f {\ifx\nextargument\blankspace - \expandafter\dodogetgroupargumentE % G + \expandafter\syst_helpers_get_grouped_argument_e % g \else - \expandafter\dodogetgroupargumentD % H + \expandafter\syst_helpers_get_grouped_argument_d % h \fi} -\def\dogetgroupargument#1#2% - {\let\dogroupargumentyes#1% - \let\dogroupargumentnop#2% - \futurelet\nextargument\dodogetgroupargument} - \def\dosinglegroupempty#1% - {\def\dodogetargument% + {\def\syst_helpers_get_grouped_argument_nested {\dontpermitspacesbetweengroups #1}% - \dogetgroupargument\firstargumenttrue\firstargumentfalse} + \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse} \def\dodoublegroupempty#1% - {\def\dodogetargument##1% - {\def\dodogetargument% + {\def\syst_helpers_get_grouped_argument_nested##1% + {\def\syst_helpers_get_grouped_argument_nested {\dontpermitspacesbetweengroups #1{##1}}% - \dogetgroupargument\secondargumenttrue\secondargumentfalse}% - \dogetgroupargument\firstargumenttrue\firstargumentfalse} + \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}% + \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse} \def\dotriplegroupempty#1% - {\def\dodogetargument##1% - {\def\dodogetargument####1% - {\def\dodogetargument% + {\def\syst_helpers_get_grouped_argument_nested##1% + {\def\syst_helpers_get_grouped_argument_nested####1% + {\def\syst_helpers_get_grouped_argument_nested {\dontpermitspacesbetweengroups #1{##1}{####1}}% - \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}% - \dogetgroupargument\secondargumenttrue\secondargumentfalse}% - \dogetgroupargument\firstargumenttrue\firstargumentfalse} + \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}% + \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}% + \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse} \def\doquadruplegroupempty#1% - {\def\dodogetargument##1% - {\def\dodogetargument####1% - {\def\dodogetargument########1% - {\def\dodogetargument% + {\def\syst_helpers_get_grouped_argument_nested##1% + {\def\syst_helpers_get_grouped_argument_nested####1% + {\def\syst_helpers_get_grouped_argument_nested########1% + {\def\syst_helpers_get_grouped_argument_nested {\dontpermitspacesbetweengroups #1{##1}{####1}{########1}}% - \dogetgroupargument\fourthargumenttrue\fourthargumentfalse}% - \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}% - \dogetgroupargument\secondargumenttrue\secondargumentfalse}% - \dogetgroupargument\firstargumenttrue\firstargumentfalse} + \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}% + \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}% + \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}% + \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse} \def\doquintuplegroupempty#1% - {\def\dodogetargument##1% - {\def\dodogetargument####1% - {\def\dodogetargument########1% - {\def\dodogetargument################1% - {\def\dodogetargument% + {\def\syst_helpers_get_grouped_argument_nested##1% + {\def\syst_helpers_get_grouped_argument_nested####1% + {\def\syst_helpers_get_grouped_argument_nested########1% + {\def\syst_helpers_get_grouped_argument_nested################1% + {\def\syst_helpers_get_grouped_argument_nested {\dontpermitspacesbetweengroups #1{##1}{####1}{########1}{################1}}% - \dogetgroupargument\fifthargumenttrue\fifthargumentfalse}% - \dogetgroupargument\fourthargumenttrue\fourthargumentfalse}% - \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}% - \dogetgroupargument\secondargumenttrue\secondargumentfalse}% - \dogetgroupargument\firstargumenttrue\firstargumentfalse} + \syst_helpers_get_grouped_argument\fifthargumenttrue\fifthargumentfalse}% + \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}% + \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}% + \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}% + \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse} %D These macros can explictly take care of spaces, which means %D that the next definition and calls are valid: @@ -2857,7 +2890,7 @@ %D nesting is to be expected, we can reuse \type{\wait} within %D \type{\wait} itself. -\def\wait +\unexpanded\def\wait {\begingroup \read16 to \wait \endgroup} @@ -2888,24 +2921,24 @@ \newtoks\everywritestring - \def\writedirect {\immediate\write\statuswrite} - \def\writeline {\writedirect{}} - \def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup} + \def\writedirect {\immediate\write\statuswrite} + \def\writeline {\writedirect{}} + \unexpanded\def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup} \fi -\def\normalwritestatus#1#2% - {\writestring{\expandafter\dosplitstatus\expandafter\statuswidth#1% +\unexpanded\def\normalwritestatus#1#2% + {\writestring{\expandafter\syst_helpers_split_status_yes\expandafter\statuswidth#1% \space\space\space\space\space\space\space \space\space\space\space\space\space\space \space\space\space\space\space\space\end \space:\space#2}} -\def\dosplitstatus#1#2% - {\ifcase#1 \expandafter\nosplitstatus\fi#2% - \expandafter\dosplitstatus\expandafter{\the\numexpr#1+\minusone\relax}} +\def\syst_helpers_split_status_yes#1#2% + {\ifcase#1 \expandafter\syst_helpers_split_status_nop\fi#2% + \expandafter\syst_helpers_split_status_yes\expandafter{\the\numexpr#1+\minusone\relax}} -\def\nosplitstatus#1\end +\def\syst_helpers_split_status_nop#1\end {} %D \macros @@ -2925,13 +2958,13 @@ \newif\ifdebuggerinfo -\def\debuggerinfo#1#2% +\unexpanded\def\debuggerinfo#1#2% {\ifdebuggerinfo \writestatus{debugger}{#1:: #2}% \fi} -\ifdefined\writestatus \else \let\writestatus\normalwritestatus \fi -\ifdefined\writebanner \else \def\writebanner{\writestring} \fi +\ifdefined\writestatus \else \let\writestatus\normalwritestatus \fi +\ifdefined\writebanner \else \unexpanded\def\writebanner{\writestring} \fi % % % % % % % % % % % % % % % % % % % % % % % % @@ -2941,13 +2974,13 @@ %D A raw and dirty alternative for \type {\getparameters}; no %D checking is done! -\def\rawsetparameter#1=#2,% +\unexpanded\def\rawsetparameter#1=#2,% {\if]#1\else \expandafter\def\csname\rawparameterprefix#1\endcsname{#2}% \expandafter\rawsetparameter \fi} -\def\rawgetparameters[#1][#2% some 5-10% faster +\unexpanded\def\rawgetparameters[#1][#2% some 5-10% faster {\ifx#2]% test is needed, else bomb on [#1][] \expandafter\gobbleoneargument \else @@ -2970,28 +3003,28 @@ %D \type {\redoglobal}. When using only alternatives, one can %D reset this mechanism with \type {\resetglobal}. -\def\resetglobal +\unexpanded\def\resetglobal {\let\redoglobal\relax \let\dodoglobal\relax} \resetglobal -\def\doglobal +\unexpanded\def\doglobal {\ifx\redoglobal\relax \let\redoglobal\global - \let\dodoglobal\@@dodoglobal + \let\dodoglobal\syst_helpers_dodo_global \fi} -\def\@@dodoglobal +\def\syst_helpers_dodo_global {\resetglobal\global} \def\saveglobal - {\let\@@dodoglobal\dodoglobal - \let\@@redoglobal\redoglobal} + {\let\syst_helpers_dodo_global\dodoglobal + \let\syst_helpers_redo_global\redoglobal} \def\restoreglobal - {\let\redoglobal\@@redoglobal - \let\dodoglobal\@@dodoglobal} + {\let\redoglobal\syst_helpers_redo_global + \let\dodoglobal\syst_helpers_dodo_global} %D A very useful application of this macro is \type {\newif}, %D \TEX's fake boolean type. Not being a primitive, @@ -3034,7 +3067,7 @@ \unexpanded\expandafter\def \fi#1} -\def\redefine#1% +\unexpanded\def\redefine#1% {\ifdefined#1% \message{[\noexpand#1is redefined]}% \fi @@ -3062,76 +3095,46 @@ % % [\test] -% todo: pick up keywords: -% -% \starttexdefinition unexpanded bagger .... - -% \bgroup \obeylines -% -% \gdef\starttexdefinition% -% {\bgroup% -% \obeylines% -% \dostarttexdefinition} -% -% \gdef\dostarttexdefinition #1 -% {\catcode\endoflineasciicode\ignorecatcode% -% \doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1 -% } -% -% \gdef\dodostarttexdefinition#1 #2 -% {\dododostarttexdefinition{#1}{#2}} -% -% \gdef\dododostarttexdefinition#1#2#3\stoptexdefinition% -% {\egroup% -% \expandafter\def\csname#1\endcsname#2{#3}} -% -% \gdef\nonostarttexdefinition#1 -% {\nononostarttexdefinition{#1}{}} -% -% \gdef\nononostarttexdefinition#1#2#3\stoptexdefinition% -% {\egroup% -% \expandafter\def\csname#1\endcsname{#3}} -% -% \egroup - \def\s!unexpanded{unexpanded} \bgroup \obeylines -\gdef\starttexdefinition% +\global\let\stoptexdefinition\relax + +\unexpanded\gdef\starttexdefinition% {\bgroup% \obeylines% - \dostarttexdefinition} + \syst_helpers_start_tex_definition} -\gdef\dostarttexdefinition #1 +\gdef\syst_helpers_start_tex_definition #1 {\catcode\endoflineasciicode\ignorecatcode% - \doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1 + \doifinstringelse\letterhash{\detokenize{#1}}\syst_helpers_start_tex_definition_yes\syst_helpers_start_tex_definition_nop#1 } -\gdef\dodostarttexdefinition#1 #2 +\gdef\syst_helpers_start_tex_definition_yes#1 #2 {\edef\texdefinitionname{#1}% \ifx\texdefinitionname\s!unexpanded% - \expandafter\dododostarttexdefinitionU% + \expandafter\syst_helpers_start_tex_definition_yes_unexpanded% \else% - \expandafter\dododostarttexdefinitionN% + \expandafter\syst_helpers_start_tex_definition_yes_normal% \fi% {#1}#2 } -\gdef\dododostarttexdefinitionU#1#2 #3 +\gdef\syst_helpers_start_tex_definition_yes_unexpanded#1#2 #3 #4\stoptexdefinition% {\egroup% #1=unexpanded \unexpanded\expandafter\def\csname#2\endcsname#3{#4}} -\gdef\dododostarttexdefinitionN#1#2 +\gdef\syst_helpers_start_tex_definition_yes_normal#1#2 #3\stoptexdefinition% {\egroup% \expandafter\def\csname#1\endcsname#2{#3}} -\gdef\nonostarttexdefinition#1 - {\nononostarttexdefinition{#1}{}} +\gdef\syst_helpers_start_tex_definition_nop#1 + {\syst_helpers_start_tex_definition_nop_indeed{#1}{}} -\gdef\nononostarttexdefinition#1#2#3\stoptexdefinition% +\gdef\syst_helpers_start_tex_definition_nop_indeed#1#2#3\stoptexdefinition% {\egroup% \expandafter\def\csname#1\endcsname{#3}} @@ -3141,8 +3144,8 @@ % This is a first variant, more might be added: -\def\starttexcode{\unprotect} -\def\stoptexcode {\protect} +\unexpanded\def\starttexcode{\unprotect} +\unexpanded\def\stoptexcode {\protect} %D \macros %D {newcounter, @@ -3202,7 +3205,7 @@ \def\zerocountervalue{0} -\def\newcounter#1% +\unexpanded\def\newcounter#1% {\dodoglobal\let#1\zerocountervalue} %D Nowadays we don't mind a few more tokens if we can gain a @@ -3217,14 +3220,14 @@ \def\syst_helpers_do_do_increment(#1{\doifnextcharelse,{\syst_helpers_do_do_do_increment#1}{\syst_helpers_do_do_do_increment#1,\plusone}} \def\syst_helpers_do_do_decrement(#1{\doifnextcharelse,{\syst_helpers_do_do_do_decrement#1}{\syst_helpers_do_do_do_decrement#1,\plusone}} -\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}} -\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}} +\unexpanded\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}} +\unexpanded\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}} -\def\increment{\doifnextcharelse(\syst_helpers_do_do_increment\syst_helpers_do_increment} -\def\decrement{\doifnextcharelse(\syst_helpers_do_do_decrement\syst_helpers_do_decrement} +\unexpanded\def\increment{\doifnextcharelse(\syst_helpers_do_do_increment\syst_helpers_do_increment} +\unexpanded\def\decrement{\doifnextcharelse(\syst_helpers_do_do_decrement\syst_helpers_do_decrement} -\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname} -\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname} +\unexpanded\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname} +\unexpanded\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname} %D \macros %D {newsignal} @@ -3245,9 +3248,9 @@ \newdimen\maximumsignal % step is about 0.00025pt -\def\newsignal#1% +\unexpanded\def\newsignal#1% {\ifdefined#1\else - \advance\maximumsignal 2sp % to be save in rounding + \advance\maximumsignal 2\scaledpoint % to be save in rounding \edef#1{\the\maximumsignal}% \fi} @@ -3262,9 +3265,9 @@ %D \stoptyping \def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx} - {\expandafter\docheckedstrippedcsname\string#1} + {\expandafter\syst_helpers_checked_stripped_csname\string#1} -\def\docheckedstrippedcsname#1% +\def\syst_helpers_checked_stripped_csname#1% {\if\noexpand#1\letterbackslash\else#1\fi} %D \macros @@ -3272,15 +3275,14 @@ %D %D We will use this one in: -\def\savenormalmeaning#1% +\unexpanded\def\savenormalmeaning#1% {\ifcsname normal\strippedcsname#1\endcsname \else - \letvalue{normal\strippedcsname#1}#1% + \expandafter\let\csname normal\strippedcsname#1\endcsname#1% \fi} %D \macros %D {dorecurse,recurselevel,recursedepth, -%D dostepwiserecurse, -%D for} +%D dostepwiserecurse} %D %D \TEX\ does not offer us powerfull for||loop mechanisms. On %D the other hand its recursion engine is quite unique. We @@ -3326,77 +3328,79 @@ \def\recursedepth{\the\outerrecurse} \def\recurselevel{0} -\let\nextrecurse\relax +\let\syst_helpers_stepwise_next\relax -\def\@@irecurse{@@ir@@} % ecurse} % stepper -\def\@@arecurse{@@ar@@} % ecurse} % action +\installsystemnamespace{recurseindex} +\installsystemnamespace{recurseaction} \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname{#4}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \ifnum#3>0\relax + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname{#4}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \ifnum#3>\zerocount\relax \ifnum#2<#1\relax - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \else - \let\nextrecurse\dodostepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse \fi \else - \ifnum#3<0\relax + \ifnum#3<\zerocount\relax \ifnum#1<#2\relax - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \else - \let\nextrecurse\dodostepwisereverse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse \fi \else - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \fi - \fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}} + \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}} -\def\dodostepwiserecurse#1#2#3% from to step +\unexpanded\def\syst_helpers_stepwise_recurse#1#2#3% from to step {\ifnum#1>#2\relax - \expandafter\nodostepwiserecurse + \expandafter\syst_helpers_stepwise_recurse_nop \else \def\recurselevel{#1}% - \doubleexpandafter\redostepwiserecurse\expandafter + \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} -\unexpanded\def\expandrecursecontent - {\csname\@@arecurse\recursedepth\endcsname} +\unexpanded\def\syst_helpers_recurse_content + {\csname\??recurseaction\recursedepth\endcsname} -\unexpanded\def\redostepwiserecurse - {\expandrecursecontent\dodostepwiserecurse} +\unexpanded\def\syst_helpers_stepwise_recurse_yes + {\syst_helpers_recurse_content + \syst_helpers_stepwise_recurse} -\unexpanded\def\dodostepwisereverse#1#2#3% from to step +\unexpanded\def\syst_helpers_stepwise_reverse#1#2#3% from to step {\ifnum#1<#2\relax - \expandafter\nodostepwiserecurse + \expandafter\syst_helpers_stepwise_recurse_nop \else \def\recurselevel{#1}% \innerrecurse#1\relax \advance\innerrecurse#3\relax - \doubleexpandafter\redostepwisereverse\expandafter + \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter \fi\expandafter{\the\innerrecurse}{#2}{#3}} -\unexpanded\def\redostepwisereverse - {\expandrecursecontent\dodostepwisereverse} +\unexpanded\def\syst_helpers_stepwise_reverse_yes + {\syst_helpers_recurse_content + \syst_helpers_stepwise_reverse} -\unexpanded\def\exitstepwiserecurse - {\nodostepwiserecurse\relax} +\unexpanded\def\syst_helpers_stepwise_exit + {\syst_helpers_stepwise_recurse_nop\relax} -\unexpanded\def\nodostepwiserecurse#1#2#3#4% - {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname - \global\advance\outerrecurse \minusone} +\unexpanded\def\syst_helpers_stepwise_recurse_nop#1#2#3#4% + {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + \global\advance\outerrecurse\minusone} -\unexpanded\def\nonostepwiserecurse#1#2#3% - {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname - \global\advance\outerrecurse \minusone} +% \unexpanded\def\nonostepwiserecurse#1#2#3% +% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname +% \global\advance\outerrecurse\minusone} \unexpanded\def\dorecurse#1% - {\dostepwiserecurse1{#1}1} + {\dostepwiserecurse\plusone{#1}\plusone} -\def\doexpandedrecurse#1#2% +\def\doexpandedrecurse#1#2% user macro (also was \doxprecurse) {\ifnum#1>\zerocount - #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-1\relax}{#2}% + #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-\plusone\relax}{#2}% \fi} %D As we can see here, the simple command \type{\dorecurse} is @@ -3422,47 +3426,48 @@ {\ifcase#1\relax \expandafter\gobbletwoarguments \or - \expandafter\ydorecurse + \expandafter\syst_helpers_recurse_y \else - \expandafter\xdorecurse + \expandafter\syst_helpers_recurse_x \fi{#1}} -\unexpanded\def\xdorecurse#1#2% +\unexpanded\def\syst_helpers_recurse_x#1#2% {\global\advance\outerrecurse \plusone - \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#2}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \expandafter\dodorecurse\expandafter1\expandafter{\number#1}} + \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#2}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}} -\unexpanded\def\ydorecurse#1#2% +\unexpanded\def\syst_helpers_recurse_y#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel \let\recurselevel\!!plusone #2% - \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname \global\advance\outerrecurse \minusone} -\unexpanded\def\dodorecurse#1#2% from to +\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to {\ifnum#1>#2\relax - \expandafter\nodorecurse + \expandafter\syst_helpers_recurse_indeed_nop \else \def\recurselevel{#1}% - \doubleexpandafter\redorecurse + \doubleexpandafter\syst_helpers_recurse_indeed_yes \fi\expandafter{\the\numexpr\recurselevel+\plusone\relax}{#2}} -\unexpanded\def\dodorecurse#1#2% from to +\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to {\ifnum#1>#2\relax - \expandafter\nodorecurse + \expandafter\syst_helpers_recurse_indeed_nop \else \def\recurselevel{#1}% \innerrecurse#1\advance\innerrecurse\plusone - \doubleexpandafter\redorecurse + \doubleexpandafter\syst_helpers_recurse_indeed_yes \fi\expandafter{\the\innerrecurse}{#2}} -\unexpanded\def\redorecurse - {\expandrecursecontent\dodorecurse} +\unexpanded\def\syst_helpers_recurse_indeed_yes + {\syst_helpers_recurse_content + \syst_helpers_recurse_indeed} -\unexpanded\def\nodorecurse#1#2#3% - {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname +\unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3% + {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname \global\advance\outerrecurse \minusone } %D \macros @@ -3483,32 +3488,33 @@ %D When needed, one can call for \type{\looplevel} and %D \type{\loopdepth}. -\let\endofloop\donothing +\let\endofloop\donothing % maybe \syst_helpers_loop_end \unexpanded\def\doloop#1% {\global\advance\outerrecurse \plusone - \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#1}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \let\endofloop\dodoloop - \dodoloop1} % no \plusone else \recurselevel wrong + \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#1}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \let\endofloop\syst_helpers_loop + \syst_helpers_loop1} % no \plusone else \recurselevel wrong -\unexpanded\def\dodoloop#1% +\unexpanded\def\syst_helpers_loop#1% {\def\recurselevel{#1}% - \expandafter\redoloop\expandafter{\the\numexpr\recurselevel+\plusone\relax}} + \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}} -\unexpanded\def\redoloop - {\expandrecursecontent\endofloop} +\unexpanded\def\syst_helpers_loop_yes + {\syst_helpers_recurse_content + \endofloop} -\unexpanded\def\nodoloop#1% - {\let\endofloop\dodoloop % new, permits nested \doloop's - \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname +\unexpanded\def\syst_helpers_loop_nop#1% + {\let\endofloop\syst_helpers_loop % new, permits nested \doloop's + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname \global\advance\outerrecurse\minusone} \unexpanded\def\exitloop % \exitloop quits at end - {\let\endofloop\nodoloop} + {\let\endofloop\syst_helpers_loop_nop} \unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly - {\nodoloop} + {\syst_helpers_loop_nop} %D The loop is executed at least once, so beware of situations %D like: @@ -3548,94 +3554,113 @@ %D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}} %D \stoptyping -\def\expandrecursecontent - {\csname\@@arecurse\recursedepth\expandafter\expandafter\expandafter\endcsname +\def\syst_helpers_recurse_content + {\csname\??recurseaction\recursedepth\expandafter\expandafter\expandafter\endcsname \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}} -\unexpanded\def\xdorecurse#1#2% +\unexpanded\def\syst_helpers_recurse_x#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \expandafter\dodorecurse\expandafter1\expandafter{\number#1}} + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}} -\unexpanded\def\ydorecurse#1#2% +\unexpanded\def\syst_helpers_recurse_y#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel \let\recurselevel\!!plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}% - \expandrecursecontent - \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}% + \syst_helpers_recurse_content + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname \global\advance\outerrecurse \minusone} \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \ifnum#3>0\relax + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \ifnum#3>\zerocount\relax \ifnum#2<#1\relax - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \else - \let\nextrecurse\dodostepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse \fi \else - \ifnum#3<0\relax + \ifnum#3<\zerocount\relax \ifnum#1<#2\relax - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \else - \let\nextrecurse\dodostepwisereverse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse \fi \else - \let\nextrecurse\exitstepwiserecurse + \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit \fi - \fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}} + \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}} \unexpanded\def\doloop#1% {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#1}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \let\endofloop\dodoloop - \dodoloop1} % no \plusone else \recurselevel wrong + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#1}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \let\endofloop\syst_helpers_loop + \syst_helpers_loop1} % no \plusone else \recurselevel wrong % faster +% \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 +% {\global\advance\outerrecurse \plusone +% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% +% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel +% \csname @swr% +% \ifnum#3>\zerocount +% \ifnum#2<#1\else d\fi +% \else\ifnum#3<\zerocount +% \ifnum#1<#2\else r\fi +% \fi\fi +% \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}} + +% \let\@swr \syst_helpers_stepwise_exit +% \let\@swrd\syst_helpers_stepwise_recurse +% \let\@swrr\syst_helpers_stepwise_reverse + +\installsystemnamespace{recursestepwise} + \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}% - \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel - \csname @swr% + \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% + \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \csname\??recursestepwise \ifnum#3>\zerocount \ifnum#2<#1\else d\fi \else\ifnum#3<\zerocount \ifnum#1<#2\else r\fi \fi\fi \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}} + % \expandafter\endcsname\expandafter{\number#1\expandafter}\expandafter{\number#2\expandafter}\expandafter{\number#3}} -\let\@swr \exitstepwiserecurse -\let\@swrd\dodostepwiserecurse -\let\@swrr\dodostepwisereverse +\letvalue{\??recursestepwise }\syst_helpers_stepwise_exit +\letvalue{\??recursestepwise d}\syst_helpers_stepwise_recurse +\letvalue{\??recursestepwise r}\syst_helpers_stepwise_reverse % quite okay too, but untested % % \def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 % {\global\advance\outerrecurse \plusone -% \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}% -% \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel +% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% +% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel % \normalexpanded % {\ifnum#3>\zerocount % \ifnum#2<#1 -% \exitstepwiserecurse +% \syst_helpers_stepwise_exit % \else -% \dodostepwiserecurse +% \syst_helpers_stepwise_recurse % \fi % \else % \ifnum#3<\zerocount % \ifnum#1<#2 -% \exitstepwiserecurse +% \syst_helpers_stepwise_exit % \else -% \dodostepwisereverse +% \syst_helpers_stepwise_reverse % \fi % \else -% \exitstepwiserecurse +% \syst_helpers_stepwise_exit % \fi % \fi{\number#1}{\number#2}{\number#3}}} @@ -3643,21 +3668,22 @@ \newcount\fastloopindex \newcount\fastloopfinal -\let\fastloopcs\relax + +\let\m_syst_helpers_fast_loop_cs\relax \unexpanded\def\dofastloopcs#1#2% - {\let\fastloopcs#2 + {\let\m_syst_helpers_fast_loop_cs#2% \fastloopindex\plusone \fastloopfinal#1\relax - \dodofastloopcs} + \syst_helpers_fast_loop_cs} -\unexpanded\def\dodofastloopcs +\unexpanded\def\syst_helpers_fast_loop_cs {\ifnum\fastloopindex>\fastloopfinal - \let\fastloopcs\relax + \let\m_syst_helpers_fast_loop_cs\relax \else - \fastloopcs + \m_syst_helpers_fast_loop_cs \advance\fastloopindex\plusone - \expandafter\dodofastloopcs + \expandafter\syst_helpers_fast_loop_cs \fi} % Helper: @@ -3693,10 +3719,10 @@ \unexpanded\def\doloopoverlist#1#2% {\global\advance\outerrecurse\plusone - \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname##1{\edef\recursestring{##1}#2}% - \expandafter\glet\csname\@@irecurse\recursedepth\endcsname\recursestring - \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\@@arecurse\recursedepth\endcsname}}% - \expandafter\let\expandafter\recursestring\csname\@@irecurse\recursedepth\endcsname + \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname##1{\edef\recursestring{##1}#2}% + \expandafter\glet\csname\??recurseindex\recursedepth\endcsname\recursestring + \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\recursedepth\endcsname}}% + \expandafter\let\expandafter\recursestring\csname\??recurseindex\recursedepth\endcsname \global\advance\outerrecurse\minusone} %D \macros @@ -3724,20 +3750,20 @@ % \EveryPar{y } \everypar{before } [before] \par % } -% retrofit this into mkii - -\def\dowithevery#1% - {\expandafter\removetoks\expandafter\the\csname t\strippedcsname#1\endcsname\from#1% - \expandafter\appendtoks\expandafter\the\csname t\strippedcsname#1\endcsname\to #1% - \csname t\strippedcsname#1\endcsname} +\installsystemnamespace{extraevery} -\def\newevery#1#2% +\unexpanded\def\newevery#1#2% {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere \ifx#2\relax\else\ifdefined#2\else - \expandafter\newtoks\csname t\strippedcsname#1\endcsname - \def#2{\dowithevery#1}% + \expandafter\newtoks\csname\??extraevery\strippedcsname#1\endcsname + \def#2{\syst_helpers_every#1}% \fi\fi} +\unexpanded\def\syst_helpers_every#1% + {\expandafter\removetoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\from#1% + \expandafter\appendtoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\to #1% + \csname\??extraevery\strippedcsname#1\endcsname} + %D This one permits definitions like: \newevery \everypar \EveryPar % we get a warning which is ok @@ -3745,7 +3771,23 @@ %D and how about: -\newevery \neverypar \NeveryPar +% \newtoks \neverypar +% \newtoks \neveryendpar +% +% \normalprotected\def\syst_helpers_forgotten_endpar +% {\the\neveryendpar\normalpar} +% +% \unexpanded\def\forgeteverypar +% {\everypar{\the\neverypar}% +% \let\endpar\syst_helpers_forgotten_endpar} +% +% \unexpanded\def\finishpar +% {\ifvmode\else\par\fi} + +\newtoks \neverypar + +\unexpanded\def\forgeteverypar + {\everypar{\the\neverypar}} %D Which we're going to use indeed! When the second argument %D equals \type {\relax}, the first token list is created @@ -3817,10 +3859,10 @@ %D Both commands accept the prefix \type{\doglobal} for global %D assignments. -\def\convertvalue#1\to +\unexpanded\def\convertvalue#1\to {\expandafter\convertcommand\csname#1\endcsname\to} -\def\defconvertedvalue#1#2% less sensitive for \to +\unexpanded\def\defconvertedvalue#1#2% less sensitive for \to {\expandafter\defconvertedcommand\expandafter#1\csname#2\endcsname} %D \macros @@ -3843,10 +3885,10 @@ %D \doifassignmentelse {...} {then ...} {else ...} %D \stoptyping -\def\docheckifassignmentelse#1=#2#3\@end@{\if#2@}% +\def\syst_helpers_check_if_assignment_else#1=#2#3\_e_o_p_{\if#2@}% -\def\doifassignmentelse#1% expandable - {\expandafter\docheckifassignmentelse\detokenize{#1}=@@\@end@ +\unexpanded\def\doifassignmentelse#1% expandable + {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_ \expandafter\secondoftwoarguments \else \expandafter\firstoftwoarguments @@ -3854,23 +3896,12 @@ \newif\ifassignment -% \def\docheckassignmentindeed#1=#2#3\@end@{\if#2@\assignmentfalse\else\assignmenttrue\fi} -% -% \def\docheckassignment#1% -% {\expandafter\docheckassignmentindeed\detokenize{#1}=@@\@end@} - -% D \macros -% D {convertasciiafter} -% D -% D Sometimes we need to convert an argument to a string (letters -% D only), for instance when we compare it with another string: -% D -% D \starttyping -% D \convertasciiafter\doifinstringelse{em}{\ascii}{...} -% D \stoptyping -% -% \def\convertasciiafter#1#2% -% {\expandafter#1\expandafter{\detokenize{#2}}} +\unexpanded\def\docheckassignment#1% + {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_ + \assignmentfalse + \else + \assignmenttrue + \fi} %D In \ETEX\ we can use \type {\detokenize} and gain some %D speed, but in general far less that 1\% for \type @@ -3879,17 +3910,17 @@ %D something I found out when primitives like \type %D {\jobname} were fed (or something undefined). -\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}} -\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok +\unexpanded\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}} +\unexpanded\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok -\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}} -\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}} -\def\edefconvertedargument#1#2{\edef#1{#2}% - \edef#1{\detokenize\expandafter{#1}}} -\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}} -\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}} -\def\xdefconvertedargument#1#2{\xdef#1{#2}% - \xdef#1{\detokenize\expandafter{#1}}} +\unexpanded\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}} +\unexpanded\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}} +\unexpanded\def\edefconvertedargument#1#2{\edef#1{#2}% + \edef#1{\detokenize\expandafter{#1}}} +\unexpanded\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}} +\unexpanded\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}} +\unexpanded\def\xdefconvertedargument#1#2{\xdef#1{#2}% + \xdef#1{\detokenize\expandafter{#1}}} %D When you try to convert a primitive command, you'll find %D out that the \ETEX\ method fails on for instance \type @@ -3910,14 +3941,11 @@ %D argument are completely redundant. %D \macros -%D {showvalue,showargument} +%D {showvalue} %D -%D Two handy macros for testing purposes only: - -\def\showvalue#1% - {\expandafter\show\csname#1\endcsname} +%D Ahandy macro, for testing purposes only: -\def\showvalue#1% +\unexpanded\def\showvalue#1% {\ifcsname#1\endcsname \expandafter\show\csname#1\endcsname \else @@ -3938,11 +3966,11 @@ %D %D Watch the one level expansion of the second argument. -\def\doifmeaningelse#1#2% - {\edef\!!stringa{\meaning#1}% - \def \!!stringb{#2}% - \edef\!!stringb{\meaning\!!stringb}% - \ifx\!!stringa\!!stringb +\unexpanded\def\doifmeaningelse#1#2% + {\edef\m_syst_string_one{\meaning#1}% + \def \m_syst_string_two{#2}% + \edef\m_syst_string_two{\meaning\m_syst_string_two}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments @@ -3960,14 +3988,14 @@ %D \doifsamestringelse{\jobname}{oeps}{YES}{NO} %D \stoptyping -\def\@@doifsamestringelse#1#2#3#4% - {\edef\!!stringa{\detokenize\expandafter{\normalexpanded{#3}}}% - \edef\!!stringb{\detokenize\expandafter{\normalexpanded{#4}}}% - \ifx\!!stringa\!!stringb\expandafter#1\else\expandafter#2\fi} +\def\syst_helpers_if_samestring_else#1#2#3#4% + {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#3}}}% + \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#4}}}% + \ifx\m_syst_string_one\m_syst_string_two\expandafter#1\else\expandafter#2\fi} -\def\doifsamestringelse{\@@doifsamestringelse\firstoftwoarguments\secondoftwoarguments} -\def\doifsamestring {\@@doifsamestringelse\firstofoneargument \gobbleoneargument } -\def\doifnotsamestring {\@@doifsamestringelse\gobbleoneargument \firstofoneargument } +\unexpanded\def\doifsamestringelse{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments} +\unexpanded\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument } +\unexpanded\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument } %D \macros %D {ConvertToConstant,ConvertConstantAfter} @@ -3995,10 +4023,10 @@ %D In examples~2 and~3 both arguments equal, in~1 and~4 %D they differ. -\def\ConvertToConstant#1#2#3% - {\edef\!!stringa{\expandafter\detokenize\expandafter{#2}}% - \edef\!!stringb{\expandafter\detokenize\expandafter{#3}}% - #1{\!!stringa}{\!!stringb}} +\unexpanded\def\ConvertToConstant#1#2#3% + {\edef\m_syst_string_one{\expandafter\detokenize\expandafter{#2}}% + \edef\m_syst_string_two{\expandafter\detokenize\expandafter{#3}}% + #1{\m_syst_string_one}{\m_syst_string_two}} %D When the argument \type{#1} consists of commands, we had %D better use @@ -4027,14 +4055,14 @@ %D %D where \type{...} can be anything legally \TEX. -\def\CheckConstantAfter#1#2% +\unexpanded\def\CheckConstantAfter#1#2% {\expandafter\convertargument\v!prefix!\to\ascii \convertargument#1\to#2\relax \doifinstringelse\ascii{#2} {\expandafter\convertargument#1\to#2} {}} -\def\ConvertConstantAfter#1#2#3% +\unexpanded\def\ConvertConstantAfter#1#2#3% {\CheckConstantAfter{#2}\asciia \CheckConstantAfter{#3}\asciib #1{\asciia}{\asciib}} @@ -4050,7 +4078,7 @@ %D %D We don't explicitly test if the macro is defined. -\def\assignifempty#1#2% can be sped up +\unexpanded\def\assignifempty#1#2% can be sped up {\doifsomething{#1}{\def#1{#2}}} % {\doifnot{#1}{}{\def#1{#2}}} %D \macros @@ -4094,11 +4122,13 @@ %D %D results in: \type{\message{Hello world!}}. -\def\dograbuntil#1#2% - {\def\next##1#1{#2{##1}}\next} +\let\syst_helpers_grab_indeed\relax -\def\grabuntil#1% - {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}} +\unexpanded\def\syst_helpers_grab#1#2% + {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed} + +\unexpanded\def\grabuntil#1% + {\expandafter\syst_helpers_grab\expandafter{\csname#1\endcsname}} %D The next command build on this mechanism: %D @@ -4122,13 +4152,15 @@ %D is related to these commands. This one simply throws away %D everything preceding \type{\command}. -\def\processbetween#1#2% +\let\syst_helpers_gobble_indeed\relax + +\unexpanded\def\processbetween#1#2% {\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}} -\def\gobbleuntil#1% - {\def\next##1#1{}\next} +\unexpanded\def\gobbleuntil#1% + {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed} -\def\gobbleuntilrelax#1\relax +\unexpanded\def\gobbleuntilrelax#1\relax {} %D The next one simply expands the pickup up tokens. @@ -4137,8 +4169,10 @@ %D \processuntil{sequence} %D \stoptyping -\def\processuntil#1% - {\def\next##1#1{##1}\next} +\let\syst_helpers_until_indeed\relax + +\unexpanded\def\processuntil#1% + {\def\syst_helpers_until_indeed##1#1{##1}\syst_helpers_until_indeed} %D \macros %D {groupedcommand} @@ -4183,7 +4217,7 @@ %D %D \starttyping %D \def\rightword% -%D {\groupedcommand{\hfill\hbox}{\parfillskip\!!zeropoint}} +%D {\groupedcommand{\hfill\hbox}{\parfillskip\zeropoint}} %D %D .......... \rightword{the right way} %D \stoptyping @@ -4202,45 +4236,85 @@ %D to be {\bold bold} or not, that's the question %D \stoptyping %D -%D This alternative checks for a \type{\bgroup} token first. -%D The internal alternative does not accept the box handling -%D mentioned before, but further nesting works all right. The -%D extra \type{\bgroup}||\type{\egroup} is needed to keep -%D \type{\AfterGroup} both into sight and local. +%D This alternative checks for a \type {\bgroup} token first. The internal +%D alternative does not accept the box handling mentioned before, but further +%D nesting works all right. The extra \type {\bgroup}||\type {\egroup} is needed to +%D keep \type {\m_syst_helpers_handle_group_after} both into sight and local. + +\let\m_syst_helpers_handle_group_after \relax +\let\m_syst_helpers_handle_group_before\relax -\def\HandleGroup#1#2% +% keep: +% +% \unexpanded\def\syst_helpers_handle_group_normal#1#2% +% {\bgroup +% \def\m_syst_helpers_handle_group_before{\bgroup#1\bgroup\aftergroup\m_syst_helpers_handle_group_after}% can't we remove the second \bgroup +% \def\m_syst_helpers_handle_group_after {#2\egroup\egroup}% and one \egroup here? +% \afterassignment\m_syst_helpers_handle_group_before +% \let\next=} + +\unexpanded\def\syst_helpers_handle_group_normal#1#2% {\bgroup - \def\BeforeGroup{\bgroup#1\bgroup\aftergroup\AfterGroup}% can't we remove the second \bgroup - \def\AfterGroup {#2\egroup\egroup}% % and one \egroup here? - \afterassignment\BeforeGroup + \def\m_syst_helpers_handle_group_before{#1}% + \def\m_syst_helpers_handle_group_after {#2}% + \afterassignment\m_syst_helpers_handle_group_normal_before \let\next=} -\def\HandleSimpleGroup#1#2% no inner group (so no kerning interference) +\def\m_syst_helpers_handle_group_normal_before {\bgroup - %def\BeforeGroup{\bgroup#1\aftergroup\AfterGroup}% interferes - \def\BeforeGroup{\bgroup\aftergroup\AfterGroup#1}% - \def\AfterGroup {#2\egroup}% - \afterassignment\BeforeGroup + \m_syst_helpers_handle_group_before + \bgroup + \aftergroup\m_syst_helpers_handle_group_normal_after} + +\def\m_syst_helpers_handle_group_normal_after + {\m_syst_helpers_handle_group_after + \egroup + \egroup} + +% keep: +% +% \unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference) +% {\bgroup +% %def\m_syst_helpers_handle_group_before{\bgroup#1\aftergroup\m_syst_helpers_handle_group_after}% interferes +% \def\m_syst_helpers_handle_group_before{\bgroup\aftergroup\m_syst_helpers_handle_group_after#1}% +% \def\m_syst_helpers_handle_group_after {#2\egroup}% +% \afterassignment\m_syst_helpers_handle_group_before +% \let\next=} + +\unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference) + {\bgroup + \def\m_syst_helpers_handle_group_before{#1}% + \def\m_syst_helpers_handle_group_after {#2}% + \afterassignment\m_syst_helpers_handle_group_simple_before \let\next=} -% \def\HandleNoGroup#1#2% -% {\def\AfterGroup{#2\egroup}% -% \bgroup\aftergroup\AfterGroup#1} +\def\m_syst_helpers_handle_group_simple_before + {\bgroup + \aftergroup\m_syst_helpers_handle_group_simple_after + \m_syst_helpers_handle_group_before} -\def\HandleNoGroup % retrofit into mkii +\def\m_syst_helpers_handle_group_simple_after + {\m_syst_helpers_handle_group_after + \egroup}% + +\unexpanded\def\syst_helpers_handle_group_nop {\ifnum\currentgrouptype=\semisimplegroupcode - \expandafter\HandleNoGroupA + \expandafter\syst_helpers_handle_group_nop_a \else - \expandafter\HandleNoGroupB + \expandafter\syst_helpers_handle_group_nop_b \fi} -\def\HandleNoGroupA#1#2% - {\def\AfterGroup{#2\endgroup}% - \begingroup\aftergroup\AfterGroup#1} +\def\syst_helpers_handle_group_nop_a#1#2% + {\def\m_syst_helpers_handle_group_after{#2\endgroup}% + \begingroup + \aftergroup\m_syst_helpers_handle_group_after + #1} -\def\HandleNoGroupB#1#2% - {\def\AfterGroup{#2\egroup}% - \bgroup\aftergroup\AfterGroup#1} +\def\syst_helpers_handle_group_nop_b#1#2% + {\def\m_syst_helpers_handle_group_after{#2\egroup}% + \bgroup + \aftergroup\m_syst_helpers_handle_group_after + #1} %D I considered it a nuisance that %D @@ -4255,10 +4329,10 @@ %D implementation became: \unexpanded\def\groupedcommand#1#2% - {\doifnextbgroupelse{\HandleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}} + {\doifnextbgroupelse{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} \unexpanded\def\simplegroupedcommand#1#2% - {\doifnextbgroupelse{\HandleSimpleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}} + {\doifnextbgroupelse{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} %D Users should be aware of the fact that grouping can %D interfere with ones paragraph settings that are executed @@ -4288,10 +4362,10 @@ %D \type{CAPITALS}. This suggestion is feasible, because %D \CONTEXT only defines lowcased macros. -\def\showdefinederror#1#2% +\unexpanded\def\showdefinederror#1#2% {\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}} -\def\checkdefined#1#2#3% +\unexpanded\def\checkdefined#1#2#3% {\doifdefined{#3}{\showdefinederror{#2}{#3}}} %D \macros @@ -4413,10 +4487,13 @@ %D ... \par %D \stoptyping +\let\syst_helpers_next_par\relax +\let\syst_helpers_next_arg\relax + \unexpanded\def\dowithpargument#1% - {\def\nextpar##1 \par{#1{##1}}% - \def\nextarg##1{#1{##1}}% - \doifnextbgroupelse\nextarg{\doifnextcharelse\par{#1{}}\nextpar}} + {\def\syst_helpers_next_par##1 \par{#1{##1}}% + \def\syst_helpers_next_arg##1{#1{##1}}% + \doifnextbgroupelse\syst_helpers_next_arg{\doifnextcharelse\par{#1{}}\syst_helpers_next_par}} %D The \type{p} in the previous command stands for paragraph. %D When we want to act upon words we can use the \type{w} @@ -4440,10 +4517,13 @@ %D ... %D \stoptyping +\let\syst_helpers_next_war\relax +\let\syst_helpers_next_arg\relax + \unexpanded\def\dowithwargument#1% - {\def\nextwar##1 {#1{##1}}% - \def\nextarg##1{#1{##1}}% - \doifnextbgroupelse\nextarg\nextwar} + {\def\syst_helpers_next_war##1 {#1{##1}}% + \def\syst_helpers_next_arg##1{#1{##1}}% + \doifnextbgroupelse\syst_helpers_next_arg\syst_helpers_next_war} %D \macros %D {dorepeat,dorepeatwithcommand} @@ -4476,12 +4556,12 @@ %D specification is missing, the command executes once. \unexpanded\def\dorepeatwithcommand[#1]% - {\dodorepeatwithcommand#1*\empty*\relax} + {\syst_helpers_repeat_with_command#1*\empty*\relax} -\def\dodorepeatwithcommand#1*#2#3*#4\relax#5% - {\ifx#2\empty\redorepeatwithcommand[#1]#5\else\dododorepeatwithcommand{#1}{#2}{#3}#5\fi} +\def\syst_helpers_repeat_with_command#1*#2#3*#4\relax#5% + {\ifx#2\empty\syst_helpers_repeat_with_command_again[#1]#5\else\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5\fi} -\def\dododorepeatwithcommand#1#2#3#4% +\def\syst_helpers_repeat_with_command_indeed#1#2#3#4% {\ifx#2\empty % redundant but gives cleaner extensions #4{#1}% \else\ifnum#1<\zerocount @@ -4493,7 +4573,7 @@ \dorecurse{#1}{#4{#2#3}}% \fi\fi\fi} -\def\redorepeatwithcommand[#1]#2% +\def\syst_helpers_repeat_with_command_again[#1]#2% {#2{#1}} %D The extension hook permits something like: @@ -4503,11 +4583,11 @@ %D %D \catcode`\*=\superscriptcatcode %D -%D \gdef\redorepeatwithcommand[#1]% +%D \gdef\syst_helpers_repeat_with_command_again[#1]% %D {\redodorepeatwithcommand#1*\empty*\relax} %D %D \gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5% -%D {\dododorepeatwithcommand{#1}{#2}{#3}#5} +%D {\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5} %D %D \egroup %D \stoptyping @@ -4515,14 +4595,6 @@ %D although one may wonder if changing the catcode of \type {*} is wise. %D \macros -%D {normalbgroup,normalgroup} -%D -%D No comment. - -\let\normalbgroup\bgroup -\let\normalegroup\egroup - -%D \macros %D {doifstringinstringelse} %D %D The next macro is meant for situations where both strings @@ -4539,7 +4611,7 @@ %D %D A bit faster is: -\def\pp!doifstringinstringelse#1% +\def\syst_helpers_if_instring_else_indeed#1% {\if#1@% \expandafter\secondoftwoarguments \else @@ -4547,9 +4619,9 @@ \fi} \def\doifstringinstringelse#1#2% - {\expandafter\def\expandafter\p!doifstringinstringelse\expandafter##\expandafter1#1##2##3\war - {\pp!doifstringinstringelse##2}% - \expandafter\expandafter\expandafter\p!doifstringinstringelse\expandafter#2#1@@\war} + {\expandafter\def\expandafter\syst_helpers_if_instring_else\expandafter##\expandafter1#1##2##3\_e_o_s_ + {\syst_helpers_if_instring_else_indeed##2}% + \expandafter\expandafter\expandafter\syst_helpers_if_instring_else\expandafter#2#1@@\_e_o_s_} %D \macros %D {appendtoks,prependtoks,appendtoksonce,prependtoksonce, @@ -4569,36 +4641,39 @@ %D These macros are clones of the ones implemented in page~378 of %D Knuth's \TeX book. -\newtoks\@@scratchtoks +\newtoks\t_syst_helpers_scratch +\let \m_syst_helpers_scratch\empty + +% no longer \def but \let to target toks -\unexpanded\def\appendtoks {\doappendtoks \relax} -\unexpanded\def\prependtoks {\doprependtoks \relax} -\unexpanded\def\appendtoksonce {\doappendtoksonce \relax} -\unexpanded\def\prependtoksonce{\doprependtoksonce\relax} +\unexpanded\def\appendtoks {\syst_helpers_append_toks \relax} +\unexpanded\def\prependtoks {\syst_helpers_prepend_toks \relax} +\unexpanded\def\appendtoksonce {\syst_helpers_append_toks_once \relax} +\unexpanded\def\prependtoksonce{\syst_helpers_prepend_toks_once\relax} -\def\dodoappendtoks - {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@toks\the\@@scratchtoks}} +\def\syst_helpers_append_toks_indeed + {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\m_syst_helpers_scratch\the\t_syst_helpers_scratch}} -\def\dodoprependtoks - {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@scratchtoks\the\@@toks}} +\def\syst_helpers_prepend_toks_indeed + {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\t_syst_helpers_scratch\the\m_syst_helpers_scratch}} -\def\doappendtoks#1\to#2% - {\def\@@toks{#2}% - \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoappendtoks} +\def\syst_helpers_append_toks#1\to#2% + {\let\m_syst_helpers_scratch#2% + \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_append_toks_indeed} -\def\doprependtoks#1\to#2% - {\def\@@toks{#2}% - \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoprependtoks} +\def\syst_helpers_prepend_toks#1\to#2% + {\let\m_syst_helpers_scratch#2% + \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_prepend_toks_indeed} -\def\doappendtoksonce#1\to#2% - {\def\@@toks{#2}% - \@@scratchtoks\expandafter{\gobbleoneargument#1}% - \doifintokselse\@@scratchtoks\@@toks\donothing\dodoappendtoks} +\def\syst_helpers_append_toks_once#1\to#2% + {\let\m_syst_helpers_scratch#2% + \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}% + \doifintokselse\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_append_toks_indeed} -\def\doprependtoksonce#1\to#2% - {\def\@@toks{#2}% - \@@scratchtoks\expandafter{\gobbleoneargument#1}% - \doifintokselse\@@scratchtoks\@@toks\donothing\dodoprependtoks} +\def\syst_helpers_prepend_toks_once#1\to#2% + {\let\m_syst_helpers_scratch#2% + \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}% + \doifintokselse\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_prepend_toks_indeed} %D The test macro: @@ -4616,70 +4691,27 @@ % {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]} \unexpanded\def\removetoks#1\from#2% - {\def\doremovetoks##1#1##2\empty\empty\empty##3\\% - {\def\!!stringa{##3}% - \ifx\!!stringa\empty#2{##1}\else#2{##1##2}\fi}% - \expandafter\doremovetoks\the#2\empty\empty\empty#1\empty\empty\empty\\} + {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3\_e_o_t_ + {\def\m_syst_string_one{##3}% + \ifx\m_syst_string_one\empty#2{##1}\else#2{##1##2}\fi}% + \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty\_e_o_t_} %D Also: -\unexpanded\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to} -\unexpanded\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to} +\unexpanded\def\appendetoks #1\to{\normalexpanded{\appendtoks #1}\to} +\unexpanded\def\prependetoks#1\to{\normalexpanded{\prependtoks#1}\to} %D Hm. -\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness - {\@@scratchtoks#1\relax +\unexpanded\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness + {\t_syst_helpers_scratch#1\relax \dodoglobal#1\emptytoks - \the\@@scratchtoks\relax} + \the\t_syst_helpers_scratch\relax} % better: \def\flushtoks#1{\normalexpanded{\noexpand\dodoglobal#1\emptytoks\the#\relax}} \let\dotoks\the -% The following code is obsolete (and names are reused for the more -% advanced counter mechanism and those macros are not compatible! -% -% %D \macros -% %D {makecounter,pluscounter,minuscounter, -% %D resetcounter,setcounter,countervalue} -% %D -% %D Declaring, setting and resetting \COUNTERS\ can be done -% %D with the next set of commands. -% %D -% %D \starttyping -% %D \makecounter {name} -% %D \pluscounter {name} -% %D \minuscounter {name} -% %D \resetcounter {name} -% %D \setcounter {name} {value} -% %D \countervalue {name} -% %D \stoptyping -% -% \def\makecounter#1% -% {\global\expandafter\let\csname#1\endcsname\zerocountervalue} % see earlier -% -% \def\countervalue#1% -% {\ifcsname#1\endcsname\csname#1\endcsname\fi} -% -% \def\pluscounter#1% -% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname+\plusone\relax}} -% -% \def\minuscounter#1% -% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname-\plusone\relax}} -% -% \def\resetcounter#1% -% {\global\expandafter\let\csname#1\endcsname\zerocountervalue} -% -% \def\setcounter#1#2% -% {\expandafter\xdef\csname#1\endcsname{\the\numexpr#2\relax}} -% -% \def\savecounter#1% -% {\expandafter\xdef\csname ! #1 !\endcsname{\the\numexpr\csname#1\endcsname\relax}} -% -% \def\restorecounter#1% -% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname ! #1 !\endcsname\relax}} - %D \macros %D {beforesplitstring,aftersplitstring} %D @@ -4697,33 +4729,35 @@ %D Both implementations show some insight in the manipulation %D of arguments. -\def\beforesplitstring#1\at#2\to#3% - {\def\dosplitstring##1#2##2#2##3\\% +\let\syst_helpers_split_string\relax + +\unexpanded\def\beforesplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##1#2##2#2##3\\% {\def#3{##1}}% - \expandafter\dosplitstring#1#2#2\\} + \expandafter\syst_helpers_split_string#1#2#2\\} -\def\aftersplitstring#1\at#2\to#3% - {\def\dosplitstring##1#2##2@@@##3\\% +\unexpanded\def\aftersplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##1#2##2@@@##3\\% {\def#3{##2}}% - \expandafter\dosplitstring#1@@@#2@@@\\} + \expandafter\syst_helpers_split_string#1@@@#2@@@\\} %D \macros %D {splitstring,greedysplitstring} %D %D A bonus macro. -\def\splitstring#1\at#2\to#3\and#4% - {\def\dosplitstring##1#2##2\empty\empty\empty##3\\% +\unexpanded\def\splitstring#1\at#2\to#3\and#4% + {\def\syst_helpers_split_string##1#2##2\empty\empty\empty##3\\% {\def#3{##1}% - \def\dosplitstring{##3}% - \ifx\dosplitstring\empty + \def\syst_helpers_split_string{##3}% + \ifx\syst_helpers_split_string\empty \let#4\empty \else \def#4{##2}% \fi}% - \expandafter\dosplitstring#1\empty\empty\empty#2\empty\empty\empty\\} + \expandafter\syst_helpers_split_string#1\empty\empty\empty#2\empty\empty\empty\\} -\def\greedysplitstring#1\at#2\to#3\and#4% +\unexpanded\def\greedysplitstring#1\at#2\to#3\and#4% {\edef\asciib{#1}% \let\asciic\asciib \let#3\empty @@ -4745,20 +4779,20 @@ %D aftertestandsplitstring, %D testandsplitstring} -\def\beforetestandsplitstring#1\at#2\to#3% - {\def\dosplitstring##1#2##2#2##3##4\\% +\unexpanded\def\beforetestandsplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string##1#2##2#2##3##4\\% {\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}% - \expandafter\dosplitstring#1#2#2\empty\\} + \expandafter\syst_helpers_split_string#1#2#2\empty\\} -\def\aftertestandsplitstring#1\at#2\to#3% - {\def\dosplitstring ##1#2##2@@@##3##4\\% +\unexpanded\def\aftertestandsplitstring#1\at#2\to#3% + {\def\syst_helpers_split_string ##1#2##2@@@##3##4\\% {\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}% - \expandafter\dosplitstring #1@@@#2@@@\empty\\} + \expandafter\syst_helpers_split_string #1@@@#2@@@\empty\\} \def\testandsplitstring#1\at#2\to#3\and#4% - {\def\dosplitstring##1#2##2#2##3##4\\% + {\def\syst_helpers_split_string##1#2##2#2##3##4\\% {\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}% - \expandafter\dosplitstring#1#2#2\empty\\} + \expandafter\syst_helpers_split_string#1#2#2\empty\\} %D \macros %D {removesubstring} @@ -4771,9 +4805,9 @@ %D %D Which in terms of \TEX\ looks like: -\def\removesubstring#1\from#2\to#3% - {\splitstring#2\to\!!stringa\and\!!stringb - \dodoglobal#3{\!!stringa\!!stringb}} +\unexpanded\def\removesubstring#1\from#2\to#3% + {\splitstring#2\to\m_syst_string_one\and\m_syst_string_two + \dodoglobal#3{\m_syst_string_one\m_syst_string_two}} %D \macros %D {appendtocommalist,prependtocommalist, @@ -4848,9 +4882,9 @@ {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}} \unexpanded\def\robustdoifinsetelse#1#2% - {\edef\!!stringa{\detokenize\expandafter{\normalexpanded{#1}}}% - \edef\!!stringb{\detokenize\expandafter{\normalexpanded{#2}}}% - \rawdoifinsetelse\!!stringa\!!stringb} + {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#1}}}% + \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#2}}}% + \rawdoifinsetelse\m_syst_string_one\m_syst_string_two} \unexpanded\def\robustaddtocommalist#1#2% {item} \cs {\robustdoifinsetelse{#1}#2\resetglobal @@ -4860,11 +4894,11 @@ {\robustdoifinsetelse{#1}#2\resetglobal {\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}} -\def\xsplitstring#1#2% \cs {str} - {\def\dosplitstring##1,#2,##2,#2,##3\\% - {\edef\!!stringa{\bcleanedupcommalist##1\empty\empty\relax}% - \edef\!!stringb{\acleanedupcommalist##2,,\relax}}% - \expandafter\dosplitstring\expandafter,#1,,#2,,#2,\\} +\unexpanded\def\xsplitstring#1#2% \cs {str} + {\def\syst_helpers_split_string##1,#2,##2,#2,##3\\% + {\edef\m_syst_string_one{\bcleanedupcommalist##1\empty\empty\relax}% + \edef\m_syst_string_two{\acleanedupcommalist##2,,\relax}}% + \expandafter\syst_helpers_split_string\expandafter,#1,,#2,,#2,\\} \def\bcleanedupcommalist#1#2#3\relax{\if#1,\else#1\fi\if#2,\else#2\fi#3} \def\bcleanedupcommalist#1#2\relax{\if#1,\else#1\fi#2} @@ -4872,12 +4906,12 @@ \unexpanded\def\removefromcommalist#1#2% to be sped up {\rawdoifinsetelse{#1}#2% - {\normalexpanded{\noexpand\xsplitstring\noexpand#2{#1}}% + {\normalexpanded{\xsplitstring\noexpand#2{#1}}% \dodoglobal\edef#2% - {\ifx\!!stringa\empty - \!!stringb + {\ifx\m_syst_string_one\empty + \m_syst_string_two \else - \!!stringa\ifx\!!stringb\empty\else,\!!stringb\fi + \m_syst_string_one\ifx\m_syst_string_two\empty\else,\m_syst_string_two\fi \fi}} \resetglobal} @@ -4897,52 +4931,35 @@ %D \substituteincommalist{old}{new}{list} %D \stoptyping -\def\substituteincommalist#1#2#3% old, new, list (slooow) - {\edef\!!stringb{#1}% - \edef\!!stringd{#2}% - \let\!!stringa#3% - \let#3\empty - \def\dosubstituteincommalist##1% - {\edef\!!stringc{##1}% - \ifx\!!stringb\!!stringc - \ifx\!!stringd\empty\else - \edef#3{#3\ifx#3\empty\else,\fi\!!stringd}% - \fi - \def\docommand####1{\edef#3{#3,####1}}% - \else - \edef#3{#3\ifx#3\empty\else,\fi##1}% - \fi}% - \expandafter\rawprocesscommacommand\expandafter[\!!stringa]\dosubstituteincommalist} - -%D A not so useful macro: - -\def\dodofrontstrip[#1#2]#3% - {\ifx#1\space - \def#3{#2}% +\def\syst_helpers_substitute_in_comma_list_step#1% + {\edef\m_syst_string_three{#1}% + \ifx\m_syst_string_one\m_syst_string_three + \ifx\m_syst_string_two\empty \else + \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi\m_syst_string_two}% + \fi \else - \def#3{#1#2}% + \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi#1}% \fi} -\def\dofrontstrip#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty \else - \expandafter\dodofrontstrip\expandafter[#1]#1% - \fi} +\unexpanded\def\substituteincommalist#1#2#3% old, new, list (slooow) + {\edef\m_syst_string_one{#1}% + \edef\m_syst_string_two{#2}% + \let\m_syst_string_four\empty + \normalexpanded{\rawprocesscommacommand[#3]}\syst_helpers_substitute_in_comma_list_step + \let#3\m_syst_string_four} %D \macros %D {replaceincommalist} %D -%D The next macro can be used to replace an indexed element -%D in a commalist: +%D The next macro can be used to replace an indexed element in a commalist: %D %D \starttyping %D \replaceincommalist\MyList{2} %D \stoptyping %D -%D Element~2 will be replaced by the current meaning of the macro -%D \type {\newcommalistelement}. The old meaning is saved in -%D \type {\commalistelement}. The replacement honors grouped items, -%D like in: +%D Element~2 will be replaced by the current meaning of the macro \type +%D {\newcommalistelement}. The old meaning is saved in \type {\commalistelement}. +%D The replacement honors grouped items, like in: %D %D \starttyping %D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3} @@ -4950,43 +4967,50 @@ %D \def\MyList{a,{b,c},d,e,f} \replaceincommalist\MyList{3} %D \def\MyList{a,b,c,{d,e,f}} \replaceincommalist\MyList{3} %D \stoptyping +%D +%D This macro was used in the bibtex code (and is probably no longer needed). + +\newcount\c_syst_helpers_comma_list_index +\let \m_syst_helpers_comma_list_target\empty \let\newcommalistelement\empty -\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1 - {\def\doreplaceincommalist##1% - {\ifnum\commalistcounter=#2\relax - \ifx\newcommalistelement\empty\else - \ifx\newcommalist\empty - \let\newcommalist\newcommalistelement - \else - \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter - \newcommalist\expandafter\expandafter\expandafter - {\expandafter\newcommalist\expandafter,\newcommalistelement}% - \fi - \fi - \def\commalistelement{##1}% - \else - \ifx\newcommalist\empty - \ifx\nexttoken\bgroup % is known -) - \def\newcommalist{{##1}}% - \else - \def\newcommalist{##1}% - \fi - \else - \ifx\nexttoken\bgroup % is known -) - \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,{##1}}% - \else - \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,##1}% - \fi - \fi - \fi - \advance\commalistcounter\plusone}% +\def\syst_helpers_replace_in_comma_list_step#1% + {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax + \ifx\newcommalistelement\empty\else + \ifx\m_syst_helpers_comma_list_target\empty + \let\m_syst_helpers_comma_list_target\newcommalistelement + \else + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter + \m_syst_helpers_comma_list_target\expandafter\expandafter\expandafter + {\expandafter\m_syst_helpers_comma_list_target\expandafter,\newcommalistelement}% + \fi + \fi + \def\commalistelement{#1}% + \else + \ifx\m_syst_helpers_comma_list_target\empty + \ifx\nexttoken\bgroup % is known -) + \def\m_syst_helpers_comma_list_target{{#1}}% + \else + \def\m_syst_helpers_comma_list_target{#1}% + \fi + \else + \ifx\nexttoken\bgroup % is known -) + \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,{#1}}% + \else + \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,#1}% + \fi + \fi + \fi + \advance\commalistcounter\plusone} + +\unexpanded\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1 + {\c_syst_helpers_comma_list_index#2\relax + \let\m_syst_helpers_comma_list_target\empty \let\commalistelement\empty - \let\newcommalist\empty \commalistcounter\plusone - \expandafter\processcommalist\expandafter[#1]\doreplaceincommalist - \dodoglobal\let#1\newcommalist} + \expandafter\processcommalist\expandafter[#1]\syst_helpers_replace_in_comma_list_step + \dodoglobal\let#1\m_syst_helpers_comma_list_target} %D \macros %D {globalprocesscommalist} @@ -4997,15 +5021,17 @@ %D handling comma lists in alignments. In these situations the %D next macro can be of use. -\def\globalprocesscommaitem#1,% +\let\m_syst_helpers_comma_list_command_global\empty + +\def\syst_helpers_comma_list_command_global_step#1,% {\if]#1\else - \globalcommacommand{#1}% - \expandafter\globalprocesscommaitem + \m_syst_helpers_comma_list_command_global{#1}% + \expandafter\syst_helpers_comma_list_command_global_step \fi} -\def\globalprocesscommalist[#1]#2% - {\global\let\globalcommacommand#2% - \expandafter\globalprocesscommaitem#1,],} +\unexpanded\def\globalprocesscommalist[#1]#2% + {\global\let\m_syst_helpers_comma_list_command_global#2% + \expandafter\syst_helpers_comma_list_command_global_step#1,],} %D \macros %D {withoutpt,PtToCm, @@ -5082,36 +5108,36 @@ %D %D Beware: global! -\def\@sl@{@sl@} -\def\@sg@{@sg@} +\installsystemnamespace{localpushedmacro} +\installsystemnamespace{globalpushedmacro} -\let\@@pushedmacro\empty +\let\m_syst_helpers_push_macro\empty -\def\globalpushmacro#1% - {\xdef\@@pushedmacro{\string#1}% - \ifcsname\@sg@\@@pushedmacro\endcsname \else - \expandafter\newcount\csname\@sg@\@@pushedmacro\endcsname +\unexpanded\def\globalpushmacro#1% + {\xdef\m_syst_helpers_push_macro{\string#1}% + \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \else + \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \fi - \global\advance\csname\@sg@\@@pushedmacro\endcsname \plusone - \global\expandafter\let\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1} - -\def\globalpopmacro#1% - {\xdef\@@pushedmacro{\string#1}% - \global\expandafter\let\expandafter#1\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname - \global\advance\csname\@sg@\@@pushedmacro\endcsname \minusone} - -\def\localpushmacro#1% this one can be used to push a value over an \egroup - {\xdef\@@pushedmacro{\string#1}% - \ifcsname\@sl@\@@pushedmacro\endcsname \else - \expandafter\newcount\csname\@sl@\@@pushedmacro\endcsname + \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone + \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} + +\unexpanded\def\globalpopmacro#1% + {\xdef\m_syst_helpers_push_macro{\string#1}% + \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname + \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone} + +\unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup + {\xdef\m_syst_helpers_push_macro{\string#1}% + \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \else + \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \fi - \global\advance\csname\@sl@\@@pushedmacro\endcsname \plusone - \global\expandafter\let\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1} + \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \plusone + \global\expandafter\let\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} -\def\localpopmacro#1% - {\xdef\@@pushedmacro{\string#1}% - \expandafter\let\expandafter#1\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname - \global\advance\csname\@sl@\@@pushedmacro\endcsname \minusone } +\unexpanded\def\localpopmacro#1% + {\xdef\m_syst_helpers_push_macro{\string#1}% + \expandafter\let\expandafter#1\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname + \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \minusone } \let\pushmacro\localpushmacro \let\popmacro \localpopmacro @@ -5133,49 +5159,28 @@ %D These examples show us that an optional can be used. The %D value provided is added to \type{\localhsize}. -% todo: a fast non argument variant - \newdimen\localhsize -% \def\complexsetlocalhsize[#1]% don't change ! -% {\localhsize\hsize -% \ifnum\hangafter<\zerocount -% \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent -% \fi -% \advance\localhsize -\leftskip -% \advance\localhsize -\rightskip -% \advance\localhsize #1\relax} -% -% \def\simplesetlocalhsize -% {\complexsetlocalhsize[\zeropoint]} -% -% \definecomplexorsimple\setlocalhsize - \unexpanded\def\setlocalhsize % don't change ! {\doifnextoptionalelse \syst_helpers_set_local_hsize_yes \syst_helpers_set_local_hsize_nop} -% \def\syst_helpers_set_local_hsize_nop -% {\localhsize\hsize -% \ifnum\hangafter<\zerocount -% \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent -% \fi -% \advance\localhsize -\leftskip -% \advance\localhsize -\rightskip} - \def\syst_helpers_set_local_hsize_nop - {\localhsize\dimexpr - \hsize -\leftskip -\rightskip - \ifnum\hangafter<\zerocount - \ifdim\hangindent>\zeropoint-\else+\fi\hangindent - \fi - \relax} + {\localhsize\availablehsize} \def\syst_helpers_set_local_hsize_yes[#1]% {\syst_helpers_set_local_hsize_nop \advance\localhsize#1\relax} +\def\availablehsize + {\dimexpr + \hsize-\leftskip-\rightskip + \ifnum\hangafter<\zerocount + \ifdim\hangindent>\zeropoint-\else+\fi\hangindent + \fi + \relax} + %D \macros %D {doifvalue,doifnotvalue,doifelsevalue, %D doifnothing,doifsomething,doifelsenothing, @@ -5187,81 +5192,84 @@ %D tokens per call. Anyone familiar with the not||values %D ones, can derive their meaning from the definitions. -\def\doifvalue#1#2% - {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb +\unexpanded\def\doifvalue#1#2% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} -\def\doifnotvalue#1#2% - {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb +\unexpanded\def\doifnotvalue#1#2% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} -\def\doifelsevalue#1#2% - {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}% - \ifx\!!stringa\!!stringb +\unexpanded\def\doifelsevalue#1#2% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\def\doifnothing#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty +\unexpanded\def\doifnothing#1% + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} -\def\doifsomething#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty +\unexpanded\def\doifsomething#1% + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} -\def\doifelsenothing#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty +\unexpanded\def\doifelsenothing#1% + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\def\doifsomethingelse#1% - {\edef\!!stringa{#1}% - \ifx\!!stringa\empty +\unexpanded\def\doifsomethingelse#1% + {\edef\m_syst_string_one{#1}% + \ifx\m_syst_string_one\empty \expandafter\secondoftwoarguments \else \expandafter\firstoftwoarguments \fi} -\def\doifvaluenothing#1% - {\edef\!!stringa{\csname#1\endcsname}% - \ifx\!!stringa\empty +\unexpanded\def\doifvaluenothing#1% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \ifx\m_syst_string_one\empty \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} -\def\doifvaluesomething#1% - {\edef\!!stringa{\csname#1\endcsname}% - \ifx\!!stringa\empty +\unexpanded\def\doifvaluesomething#1% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \ifx\m_syst_string_one\empty \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} -\def\doifelsevaluenothing#1% - {\edef\!!stringa{\csname#1\endcsname}% - \ifx\!!stringa\empty +\unexpanded\def\doifelsevaluenothing#1% + {\edef\m_syst_string_one{\csname#1\endcsname}% + \ifx\m_syst_string_one\empty \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments @@ -5308,9 +5316,9 @@ \processcommalist[#3]\syst_helpers_do_common_check_all \ifdone\expandafter#1\else\expandafter#2\fi} -\def\doifallcommonelse{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments} -\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument } -\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments } +\unexpanded\def\doifallcommonelse{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments} +\unexpanded\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument } +\unexpanded\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments } %D \macros %D {DOIF,DOIFELSE,DOIFNOT} @@ -5328,39 +5336,42 @@ %D %D We have to use a two||step implementation, because the %D expansion has to take place outside \type{\uppercase}. +%D +%D These might up as \LUA based helpers (i.e. considere these +%D obsolete: \unexpanded\def\syst_helpers_do_IF#1#2% - {\uppercase{{$#1$}{$#2$}}% + {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}% \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} \unexpanded\def\syst_helpers_do_IF_NOT#1#2% - {\uppercase{{$#1$}{$#2$}}% + {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}% \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} \unexpanded\def\syst_helpers_do_IF_ELSE#1#2% - {\uppercase{{$#1$}{$#2$}}% + {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \unexpanded\def\syst_helpers_do_IF_INSTRING_ELSE#1#2% - {\uppercase{{$#1$}{$#2$}}% + {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}} -\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}} -\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}} -\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}} +\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete +\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete +\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete +\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}}% will become obsolete %D \macros %D {dosingleargumentwithset, @@ -5396,25 +5407,25 @@ %D \starttyping %D \definesomething[alfa,beta,...][variable=...,...] %D \stoptyping -%D -%D Now a whole bunch of variables like \type{\@@xxalfavariable} -%D and \type{\@@xxbetavariable} is defined. -\def\dodoublewithset[#1][#2]% +\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\@@dodowithsetcommand##1{\@@dowithsetcommand[##1][#2]}% - \processcommalist[#1]\@@dodowithsetcommand}} + {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}% + \processcommalist[#1]\syst_helpers_with_set_step}} -\def\dotriplewithset[#1][#2][#3]% +\def\syst_helpers_with_set_triple[#1][#2][#3]% {\doifsomething{#1} - {\def\@@dodowithsetcommand##1{\@@dowithsetcommand[##1][#2][#3]}% - \processcommalist[#1]\@@dodowithsetcommand}} + {\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\@@dowithsetcommand#1\dodoubleempty \dodoublewithset} % \command -\def\dodoubleargumentwithset#1{\let\@@dowithsetcommand#1\dodoubleargument\dodoublewithset} % \command +\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\@@dowithsetcommand#1\dotripleempty \dotriplewithset} % \command -\def\dotripleargumentwithset#1{\let\@@dowithsetcommand#1\dotripleargument\dotriplewithset} % \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 %D \macros %D {stripcharacters,stripspaces} @@ -5441,16 +5452,18 @@ %D As we can see below, spaces following a control sequence are %D to enclosed in \type{{}}. -\def\stripcharacter#1\from#2\to#3% - {\def\dostripcharacter##1#1##2\end - {\edef\!!strippedstring{\!!strippedstring##1}% - \doifnotempty{##2}{\dostripcharacter##2\end}}% - \let\!!strippedstring\empty - \edef\!!stringa{#2}% - \expandafter\dostripcharacter\!!stringa#1\end - \dodoglobal\let#3\!!strippedstring} +\let\m_syst_helpers_strip_character\empty + +\unexpanded\def\stripcharacter#1\from#2\to#3% + {\def\syst_helpers_strip_character##1#1##2\end + {\edef\m_syst_helpers_strip_character{\m_syst_helpers_strip_character##1}% + \doifnotempty{##2}{\syst_helpers_strip_character##2\end}}% + \let\m_syst_helpers_strip_character\empty + \edef\m_syst_string_one{#2}% + \expandafter\syst_helpers_strip_character\m_syst_string_one#1\end + \dodoglobal\let#3\m_syst_helpers_strip_character} -\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2 +\unexpanded\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2 {\stripcharacter{ }\from#1\to#2} %D \macros @@ -5459,7 +5472,7 @@ %D The next macro does the same but is more compatible with other macros, %D like \type {\convert...}. -\def\unspacestring#1\to#2% +\unexpanded\def\unspacestring#1\to#2% {\stripcharacter{ }\from#1\to#2} %D \macros @@ -5482,8 +5495,6 @@ %D We can of course gobble more arguments using the %D appropriate gobbling command. -\newif\ifexecuted % general purpose - \def\executeifdefined#1% #2 / never change this one again {\ifcsname#1\endcsname \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument @@ -5510,65 +5521,15 @@ %D Is this one still needed? -\def\p!doifsomespaceelse#1 #2#3\war{\if\noexpand#2@} +\def\syst_helpers_if_some_space_else#1 #2#3\_e_o_s_{\if\noexpand#2@} -\def\doifsomespaceelse#1% % #2#3% - {\p!doifsomespaceelse#1 @ @\war % #3\else#2\fi} +\def\doifsomespaceelse#1% % #2#3% + {\syst_helpers_if_some_space_else#1 @ @\_e_o_s_ % #3\else#2\fi} \expandafter\secondoftwoarguments \else \expandafter\firstoftwoarguments \fi} -% %D \macros -% %D {adaptdimension,balancedimensions} -% %D -% %D Again we introduce some macros that are closely related to -% %D an interface aspect of \CONTEXT. The first command can be -% %D used to adapt a \DIMENSION. -% %D -% %D \starttyping -% %D \adaptdimension {dimension} {value} -% %D \stoptyping -% %D -% %D When the value is preceed by a \type{+} or minus, the -% %D dimension is advanced accordingly, otherwise it gets the -% %D value. -% -% \def\doadaptdimension#1#2\\#3\\% -% {\if#1+% -% \dodoglobal\advance -% \else\if#1-% -% \dodoglobal\advance -% \else -% \dodoglobal -% \fi\fi -% #3 #1#2\relax} -% -% \def\adaptdimension#1#2% -% {\expandafter\doadaptdimension#2\\#1\\} -% -% %D A second command takes two \DIMENSIONS. Both are adapted, -% %D depending on the sign of the given value. -% %D maat. This time we take the value as it is, and don't look -% %D explicitly at the preceding sign. -% %D -% %D \starttyping -% %D \balancedimensions {dimension 1} {dimension 2} {value} -% %D \stoptyping -% %D -% %D When a positive value is given, the first dimension is -% %D incremented, the second ond is decremented. A negative value -% %D has the opposite result. -% -% \def\balancedimensions#1#2#3% -% {\scratchdimen#3\relax -% \redoglobal\advance#1 \scratchdimen -% \dodoglobal\advance#2 -\scratchdimen} -% -% %D Both commands can be preceded by \type{\doglobal}. Here we -% %D use \type{\redo} first, because \type{\dodo} resets the -% %D global character. - %D \macros %D {processseparatedlist} %D @@ -5600,56 +5561,61 @@ %D Therefore we smuggle a \type {\relax} in front of the %D argument, which we remove afterwards. -\def\doprocessseparatedlist#1]#2[#3]#4% - {\def\dodoprocessseparatedlist##1##2#3% - {\def\!!stringa{##2}% suggested by VZ +\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\m_syst_string_one{##2}% suggested by VZ \if]##1% - \let\dodoprocessseparatedlist\relax - \else\ifx\blankspace\!!stringa + \let\syst_helpers_process_separated_list_step\relax + \else\ifx\blankspace\m_syst_string_one #4{##1}% \else\if]##2% - \let\dodoprocessseparatedlist\relax + \let\syst_helpers_process_separated_list_step\relax \else #4{##1##2}% \fi\fi\fi - \dodoprocessseparatedlist}% - \expandafter\dodoprocessseparatedlist\gobbleoneargument#1#3]#3} + \syst_helpers_process_separated_list_step}% + \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3} -\def\processseparatedlist[% - {\doprocessseparatedlist\relax} +\unexpanded\def\processseparatedlist[% + {\syst_helpers_process_separated_list\relax} %D \macros %D {processlist} %D -%D An even more general list processing macro is the -%D following one: +%D An even more general list processing macro is the following one: %D %D \starttyping %D \processlist{beginsym}{endsym}{separator}\docommand list %D \stoptyping %D -%D This one supports arbitrary open and close symbols as well -%D as user defined separators. +%D This one supports arbitrary open and close symbols as well as user +%D defined separators. %D %D \starttyping %D \processlist(){=>}\docommand(a=>b=>c=>d) %D \stoptyping -\def\processlist#1#2#3#4% no blank skipping ! - {\def\doprocesslist##1#2% - {\def\dodoprocesslist####1####2#3% +\let\syst_helpers_process_any_list \relax +\let\syst_helpers_process_any_list_indeed\relax +\let\syst_helpers_process_any_list_step \relax + +\unexpanded\def\processlist#1#2#3#4% no blank skipping ! + {\def\syst_helpers_process_any_list_indeed##1#2% + {\def\syst_helpers_process_any_list_step####1####2#3% {\ifx#2####1% - \let\dodoprocesslist\relax + \let\syst_helpers_process_any_list_step\relax \else\ifx#2####2% - \let\dodoprocesslist\relax + \let\syst_helpers_process_any_list_step\relax \else #4{####1####2}% \fi\fi - \dodoprocesslist}% - \expandafter\dodoprocesslist\gobbleoneargument##1#3#2#3}% - \def\dodoprocesslist#1% - {\doprocesslist\relax}% - \dodoprocesslist} + \syst_helpers_process_any_list_step}% + \expandafter\syst_helpers_process_any_list_step\gobbleoneargument##1#3#2#3}% + \def\syst_helpers_process_any_list#1% + {\syst_helpers_process_any_list_indeed\relax}% + \syst_helpers_process_any_list} %D \macros %D {processassignlist} @@ -5665,12 +5631,12 @@ %D This command can be integrated in \type{\getparameters}, but %D we decided best not to do so. -\def\processassignlist#1[#2]#3% - {\def\p!dodogetparameter[##1=##2=##3]% +\unexpanded\def\processassignlist#1[#2]#3% + {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]% {\doifnot{##3}\relax{#3{##1}}}% - \def\p!dogetparameter##1% - {\p!dodogetparameter[##1==\relax]}% - \processcommalist[#2]\p!dogetparameter} + \def\syst_helpers_process_assign_list_step##1% + {\syst_helpers_process_assign_list_assign[##1==\relax]}% + \processcommalist[#2]\syst_helpers_process_assign_list_step} %D \macros %D {untextargument @@ -5687,20 +5653,22 @@ %D They remove braces and backslashes and give us something to %D sort. -\def\untexsomething +\let\m_syst_helpers_untexed\empty + +\unexpanded\def\untexsomething {\begingroup \catcode\leftbraceasciicode \ignorecatcode \catcode\rightbraceasciicode\ignorecatcode \escapechar\minusone - \dountexsomething} + \syst_helpers_untex_something} -\def\dountexsomething#1#2\to#3% - {\doglobal#1#2\to\untexedargument +\def\syst_helpers_untex_something#1#2\to#3% + {\doglobal#1#2\to\m_syst_helpers_untexed \endgroup - \let#3\untexedargument} + \let#3\m_syst_helpers_untexed} -\def\untexargument{\untexsomething\convertargument} -\def\untexcommand {\untexsomething\convertcommand} +\unexpanded\def\untexargument{\untexsomething\convertargument} +\unexpanded\def\untexcommand {\untexsomething\convertcommand} %D \macros %D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints} @@ -5725,14 +5693,14 @@ % \PointsToWholeBigPoints{10.53941pt}\test \test % \PointsToWholeBigPoints{10.53942pt}\test \test -\def\PointsToBigPoints#1#2% +\unexpanded\def\PointsToBigPoints#1#2% {\edef#2{\withoutpt\the\dimexpr.996264\dimexpr#1\relax\relax}} -\def\PointsToWholeBigPoints#1#2% +\unexpanded\def\PointsToWholeBigPoints#1#2% {\edef#2{\the\numexpr\dimexpr.996264\dimexpr#1\relax\relax/\maxcard\relax}} -\def\ScaledPointsToBigPoints #1{\PointsToBigPoints {\number#1\scaledpoint}} -\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}} +\unexpanded\def\ScaledPointsToBigPoints #1{\PointsToBigPoints {\number#1\scaledpoint}} +\unexpanded\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}} %D \macros %D {PointsToReal} @@ -5744,9 +5712,8 @@ %D \PointsToReal {dimension} \target %D \stoptyping -\def\PointsToReal#1#2% - {\scratchdimen#1% - \edef#2{\withoutpt\the\scratchdimen}} +\unexpanded\def\PointsToReal#1#2% + {\edef#2{\withoutpt\the\dimexpr#1}} %D \macros %D {dontleavehmode} @@ -5777,16 +5744,17 @@ %D %D And finaly we got the following alternative, one that avoids %D interfering grouping at the cost of a box. - -\newbox\@@dlhbox - -\unexpanded\def\dontleavehmode - {\ifhmode\else \ifmmode\else - \setbox\@@dlhbox\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\@@dlhbox - \fi \fi} - -%D But, if you run a recent version of \TEX, we can use the new -%D primitive: +%D +%D \starttyping +%D \newbox\b_syst_helpers_dlh +%D +%D \unexpanded\def\dontleavehmode +%D {\ifhmode\else \ifmmode\else +%D \setbox\b_syst_helpers_dlh\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\b_syst_helpers_dlh +%D \fi \fi} +%D \stoptyping +%D +%D But, as we run a recent version of \TEX, we can use the new primitive: \ifdefined\normalquitvmode \let\dontleavehmode\normalquitvmode \fi @@ -5800,14 +5768,17 @@ %D \lowercasestring somestring\to\somestring %D \stoptyping %D -%D the first argument may be a \type{\macro}. +%D The first argument may be a \type{\macro}. -\def\uppercasestring#1\to#2% +\unexpanded\def\uppercasestring#1\to#2% {\uppercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}} -\def\lowercasestring#1\to#2% +\unexpanded\def\lowercasestring#1\to#2% {\lowercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}} +%D These macros are sort of obsolete as we never use uppercase this +%D way. + %D \macros %D {handletokens} %D @@ -5843,25 +5814,26 @@ %D takes a real counter. The macro can be preceded by \type %D {\doglobal}. -\def\counttoken#1\in#2\to#3% +\def\syst_helpers_count_token#1% obeys {} + {\def\m_syst_string_three{#1}% + \ifx\m_syst_string_two\m_syst_string_three \else + \ifx\m_syst_string_one\m_syst_string_three + \advance\scratchcounter\plusone + \fi + \expandafter\syst_helpers_count_token + \fi} + +\unexpanded\def\counttoken#1\in#2\to#3% {\scratchcounter\zerocount - \def\!!stringa{#1}% - \def\!!stringb{\end}% - \def\docounttoken##1% obeys {} - {\def\!!stringc{##1}% - \ifx\!!stringb\!!stringc \else - \ifx\!!stringa\!!stringc - \advance\scratchcounter\plusone - \fi - \expandafter\docounttoken - \fi}% - \docounttoken#2\end + \def\m_syst_string_one{#1}% + \def\m_syst_string_two{\end}% + \syst_helpers_count_token#2\end \dodoglobal#3\scratchcounter} -\def\counttokens#1\to#2% +\unexpanded\def\counttokens#1\to#2% {\scratchcounter\zerocount - \def\docounttoken##1{\advance\scratchcounter\plusone}% - \handletokens#1\with\docounttoken + \def\syst_helpers_count_token##1{\advance\scratchcounter\plusone}% + \handletokens#1\with\syst_helpers_count_token \dodoglobal#2\scratchcounter} %D \macros @@ -5871,17 +5843,17 @@ %D Consider for instance the macro for which I originally %D wrote this token handler. -\def\splitofftokens#1\from#2\to#3% slow but hardly used +\unexpanded\def\splitofftokens#1\from#2\to#3% slow but hardly used {\ifnum#1>\zerocount \scratchcounter#1\relax - \def\dosplitofftokens##1% + \def\syst_helpers_split_off_tokens##1% {\ifnum\scratchcounter>\zerocount \advance\scratchcounter \minusone \edef#3{#3##1}% \fi}% % \let#3\empty % #3 can be #2, so: \expandafter\let\expandafter#3\expandafter\empty - \expandafter\handletokens#2\with\dosplitofftokens + \expandafter\handletokens#2\with\syst_helpers_split_off_tokens \else \edef#3{#2}% \fi} @@ -5918,27 +5890,27 @@ %D way we can handle the sentinal, a blank space and grouped %D tokens. -\def\dohandletokens % \nexthandledtoken is part of interface - {\futurelet\nexthandledtoken\dodohandletokens} +\unexpanded\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface + {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed} \def\handletokens#1\with#2% - {\gdef\dododohandletokens{#2}% permits more complex #2's - \dohandletokens#1\end} + {\gdef\syst_helpers_handle_tokens_command{#2}% permits more complex #2's + \syst_helpers_handle_tokens#1\end} -\def\dodohandletokens +\def\syst_helpers_handle_tokens_indeed {\ifx\nexthandledtoken\blankspace - \expandafter\dodohandletokensone + \expandafter\syst_helpers_handle_tokens_indeed_one \else\ifx\nexthandledtoken\end \expandafter\expandafter\expandafter\gobbletwoarguments % also gobble the \end \else - \expandafter\expandafter\expandafter\dodohandletokenstwo + \expandafter\expandafter\expandafter\syst_helpers_handle_tokens_indeed_two \fi\fi *} -\def\dodohandletokensone * % - {\dododohandletokens{ }\dohandletokens} +\def\syst_helpers_handle_tokens_indeed_one * % + {\syst_helpers_handle_tokens_command{ }\syst_helpers_handle_tokens} -\def\dodohandletokenstwo *#1% - {\dododohandletokens{#1}\dohandletokens} +\def\syst_helpers_handle_tokens_indeed_two *#1% + {\syst_helpers_handle_tokens_command{#1}\syst_helpers_handle_tokens} %D This macro is tested on: %D @@ -6021,130 +5993,35 @@ %D This macro is first used in the tabulation macros. \unexpanded\def\processcontent#1% - {\begingroup\expandafter\doprocesscontent\csname#1\endcsname} + {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname} -\unexpanded\def\doprocesscontent#1#2#3% - {\unexpanded\def\doprocesscontent##1#1% +\unexpanded\def\syst_helpers_process_content#1#2#3% + {\unexpanded\def\syst_helpers_process_content##1#1% {\endgroup\def#2{##1}#3}% - \doprocesscontent} + \syst_helpers_process_content} %D \macros %D {dogobblesingleempty, dogobbledoubleempty} %D %D These two macros savely grab and dispose two arguments. -\def\dogobblesingleempty{\dosingleempty\dodogobblesingleempty} -\def\dogobbledoubleempty{\dodoubleempty\dodogobbledoubleempty} +\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty} +\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty} -\def\dodogobblesingleempty [#1]{} -\def\dodogobbledoubleempty[#1][#2]{} +\def\syst_helpers_gobble_single_empty [#1]{} +\def\syst_helpers_gobble_double_empty[#1][#2]{} \let\gobblesingleempty\dogobblesingleempty % also used \let\gobbledoubleempty\dogobbledoubleempty % also used %D \macros -%D {sortcommalist,sortcommacommand, -%D donumericcompare,comparedresult} -%D -%D Sometimes we need to sort a commalist, so here is Taco's -%D solution. This will in many cases be a list that is stored -%D in a \type{\csname}, so both commalist and commacommands are -%D supported. The sorting algorithm is very simple, so the list -%D should not be too long or sorting will be very slow. -%D -%D \starttyping -%D \sortcommalist[10,2,4,5,6,1,2,3,4,10,20]\donumericcompare -%D -%D \def\test{10,2,4,5,6,1,2,3,4,10,20} -%D -%D \sortcommacommand[\test]\donumericcompare -%D \stoptyping -%D -%D In both cases, the result is available in the macro \type -%D {\sortedcommalist}. -%D -%D Parameter \type{#2} is a macro that should accept two -%D parameters, and it has to decide which one is larger, by -%D setting the counter \type{\comparedresult} to~0 (for equal), -%D 1~(if it's first argument is larger), or~2 (if it's second -%D argument is larger). -%D -%D As said, these macro are largely written by Taco, and are -%D (maybe therefore) also the first application of \type -%D {\replaceincommalist}. - -\newcount\comparedresult - -\def\sortcommacommand[#1]% - {\expandafter\sortcommalist\expandafter[#1]} - -\def\sortcommalist[#1]#2% - {\getcommalistsize[#1]% - \ifnum\commalistsize>1 - \let\sortedcommalist\empty - \let\comparecommand#2% - \processcommalist[#1]\dosortcommacommand - \else - \def\sortedcommalist{#1}% - \fi} - -\def\dosortcommacommand#1% - {\ifx\sortedcommalist\empty - \def\sortedcommalist{#1}% - \else - \def\!!tempa{#1}% - \ifx\!!tempa\empty\else - \scratchcounter\plusone - \expandafter\getcommalistsize\expandafter[\sortedcommalist]% - \expandafter\processcommalist\expandafter[\sortedcommalist]\docompareitems - \fi - \fi} - -%D All those \type{\expandafter}'s are there because I do not -%D want to use \type{\edef}. - -\def\docompareitems#1% - {\doifnotempty{#1} - {\expandafter\comparecommand\expandafter{\!!tempa}{#1}\relax - %\ifcase\compareresult % equal - \ifnum\comparedresult<2 - \ifnum\scratchcounter=\commalistsize - \expandafter\expandafter\expandafter\def - \expandafter\expandafter\expandafter\sortedcommalist - \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}% - \fi - %\or % new element larger - % \ifnum\scratchcounter=\commalistsize - % \expandafter\expandafter\expandafter\def - % \expandafter\expandafter\expandafter\sortedcommalist - % \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}% - % \fi - \else % old element larger - \expandafter\def\expandafter\newcommalistelement\expandafter{\!!tempa,#1}% - \replaceincommalist\sortedcommalist\scratchcounter - \expandafter\quitcommalist - \fi}% - \advance\scratchcounter \plusone} % bug, was \minusone - -%D The macro \type{\donumericcompare} considers everything -%D that is not a number to be larger than any number. - -% 0: both are equal, 1: #1 is larger, 2: #2 is larger - -\def\thenumericcompare#1#2% no \relax es inside hee - {\doifnumberelse{#1} - {\doifnumberelse{#2}{\ifnum#1>#2 \plusone\else\ifnum#1<#2 \plustwo\else\zerocount\fi\fi}\plustwo} - \plusone} - -\def\donumericcompare - {\comparedresult\thenumericcompare} - -%D \macros %D {@True, @False, @Not, @And} %D %D Some predicate logic functions, used in for instance the %D math module. +% These have rather ugly names ... will change: + \def\@True {00} \def\@False {01} \def\@Not #1{0\ifcase#11 \or\expandafter 1\else \expandafter 0\fi} @@ -6167,10 +6044,10 @@ %D assignment inside a box. The \type{\empty}'s permits %D gobbling while preventing spurious \type{\relax}'s. -\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick +\unexpanded\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty} -\def\freezedimensionwithunit#1#2% +\unexpanded\def\freezedimensionwithunit#1#2% {\setdimensionwithunit\scratchdimen#1{#2}\edef#1{\the\scratchdimen}} %D \macros @@ -6179,25 +6056,25 @@ %D Not that fast I guess, but here's a way to test for token %D registers being empty. -\def\doifsometokselse#1% - {\edef\!!stringa{\the#1}% one level expansion so quite ok - \ifx\!!stringa\empty +\unexpanded\def\doifsometokselse#1% + {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok + \ifx\m_syst_string_one\empty \expandafter\secondoftwoarguments \else \expandafter\firstoftwoarguments \fi} -\def\doifsometoks#1% - {\edef\!!stringa{\the#1}% one level expansion so quite ok - \ifx\!!stringa\empty +\unexpanded\def\doifsometoks#1% + {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok + \ifx\m_syst_string_one\empty \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} -\def\doifemptytoks#1% - {\edef\!!stringa{\the#1}% one level expansion so quite ok - \ifx\!!stringa\empty +\unexpanded\def\doifemptytoks#1% + {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok + \ifx\m_syst_string_one\empty \expandafter\firstofoneargument \else \expandafter\gobbleoneargument @@ -6212,9 +6089,9 @@ \def\syst_helpers_strict_inspect_next_character% no user macro ! {\ifx\nexttoken\charactertoken - \expandafter\!!stringa + \expandafter\m_syst_action_yes \else - \expandafter\!!stringb + \expandafter\m_syst_action_nop \fi} % better: push/pop @@ -6267,10 +6144,14 @@ %D %D Concatenate commalists: -\def\serializecommalist[#1]% +\let\syst_helpers_serialize_comma_list_step\relax + +\def\syst_helpers_serialize_comma_list_step#1% + {\edef\serializedcommalist{\serializedcommalist#1}} + +\unexpanded\def\serializecommalist[#1]% {\let\serializedcommalist\empty - \def\docommand##1{\edef\serializedcommalist{\serializedcommalist##1}}% - \processcommacommand[#1]\docommand} + \processcommacommand[#1]\syst_helpers_serialize_comma_list_step} %D \macros %D {purenumber} @@ -6346,7 +6227,7 @@ \def\filterfromvalue#1#2#3% value max n {\expandafter\doubleexpandafter\csname % we use the fact that an \expandafter\ifx\csname#1\endcsname\relax % undefined cs has become \relax - \strippedcsname\gobbleoneargument % which we then gobble here + \strippedcsname\gobbleoneargument % which we then gobble here \else \dofilterfromstr{#2}{#3}% \fi @@ -6364,13 +6245,27 @@ %D ... \measure{mywidth} ... %D \stoptyping -\def\??dm{@@dm} % brrr +\installsystemnamespace{measure} \unexpanded\def\definemeasure - {\dodoubleargument\dodefinemeasure} + {\dodoubleargument\syst_helpers_define_measure} -\def\dodefinemeasure[#1][#2]% - {\expandafter\def\csname\??dm#1\endcsname{#2}} +\def\syst_helpers_define_measure[#1][#2]% + {\expandafter\def\csname\??measure#1\endcsname{#2}} + +\unexpanded\def\freezemeasure + {\dodoubleargument\syst_helpers_freeze_measure} + +\def\syst_helpers_freede_measure[#1][#2]% + {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} + +\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way +\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way +\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way +\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way + +\def\measure#1% maybe \dimexpr ... \relax + {\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi} % #2 could be omitted, but we want to support spaces % @@ -6378,13 +6273,21 @@ % \setmeasure {xx} {1cm} % \setmeasure {xxx}{1cm} -\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??dm#1\endcsname{#2}} % quick way -\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??dm#1\endcsname{#2}} % quick way -\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??dm#1\endcsname{#2}} % quick way -\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??dm#1\endcsname{#2}} % quick way +%D \macros +%D {dividedsize} +%D +%D This one can be used inside a measure (used in m4all): +%D +%D \starttyping +%D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}] +%D \stoptyping -\def\measure#1% maybe \dimexpr ... \relax - {\ifcsname\??dm#1\endcsname\csname\??dm#1\endcsname\else\zeropoint\fi} +\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% + \fi + \relax} %D \macros %D {doifdimensionelse} @@ -6392,9 +6295,9 @@ %D This is a dirty one: we simply append a unit and discard it when needed. \def\doifdimensionelse#1% - {\afterassignment\dodoifdimensionelse\scratchdimen#1pt\relax} + {\afterassignment\syst_helpers_if_dimension_else\scratchdimen#1pt\relax} -\def\dodoifdimensionelse#1% +\def\syst_helpers_if_dimension_else#1% {\ifx#1\relax \expandafter\secondoftwoarguments \else % #1=p ... t\relax @@ -6418,53 +6321,57 @@ %D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR %D \stoptabulate +\installsystemnamespace{dimenchecka} +\installsystemnamespace{dimencheckb} +\installsystemnamespace{dimencheckc} + \def\doifdimenstringelse#1{\normalexpanded{\noexpand\dodimenteststageone#1}\empty\empty]} -\def\dodimenteststageone #1#2{\csname d!1!\ifcsname d!1!#2\endcsname#2\else x\fi\endcsname#2} -\def\dodimenteststagetwo #1#2{\csname d!2!\ifcsname d!2!#2\endcsname#2\else x\fi\endcsname#2} -\def\dodimenteststagethree #1]{\csname d!3!\ifcsname d!3!#1\endcsname#1\else x\fi\endcsname} - -\expandafter\let\csname d!1!x\endcsname\dodimenteststagethree -\expandafter\let\csname d!2!x\endcsname\dodimenteststagethree -\expandafter\let\csname d!3!x\endcsname\secondoftwoarguments - -\expandafter\let\csname d!1!.\endcsname\dodimenteststagetwo -\expandafter\let\csname d!1!,\endcsname\dodimenteststagetwo -\expandafter\let\csname d!1!1\endcsname\dodimenteststageone -\expandafter\let\csname d!1!2\endcsname\dodimenteststageone -\expandafter\let\csname d!1!3\endcsname\dodimenteststageone -\expandafter\let\csname d!1!4\endcsname\dodimenteststageone -\expandafter\let\csname d!1!5\endcsname\dodimenteststageone -\expandafter\let\csname d!1!6\endcsname\dodimenteststageone -\expandafter\let\csname d!1!7\endcsname\dodimenteststageone -\expandafter\let\csname d!1!8\endcsname\dodimenteststageone -\expandafter\let\csname d!1!9\endcsname\dodimenteststageone -\expandafter\let\csname d!1!0\endcsname\dodimenteststageone - -\expandafter\let\csname d!2!1\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!2\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!3\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!4\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!5\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!6\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!7\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!8\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!9\endcsname\dodimenteststagetwo -\expandafter\let\csname d!2!0\endcsname\dodimenteststagetwo - -\expandafter\let\csname d!3!pt\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!pc\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!in\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!bp\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!cm\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!mm\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!dd\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!cc\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!sp\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!ex\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!em\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!nd\endcsname\firstoftwoarguments -\expandafter\let\csname d!3!nc\endcsname\firstoftwoarguments +\def\dodimenteststageone #1#2{\csname \??dimenchecka\ifcsname \??dimenchecka#2\endcsname#2\else x\fi\endcsname#2} +\def\dodimenteststagetwo #1#2{\csname \??dimencheckb\ifcsname \??dimencheckb#2\endcsname#2\else x\fi\endcsname#2} +\def\dodimenteststagethree #1]{\csname \??dimencheckc\ifcsname \??dimencheckc#1\endcsname#1\else x\fi\endcsname} + +\expandafter\let\csname \??dimenchecka x\endcsname\dodimenteststagethree +\expandafter\let\csname \??dimencheckb x\endcsname\dodimenteststagethree +\expandafter\let\csname \??dimencheckc x\endcsname\secondoftwoarguments + +\expandafter\let\csname \??dimenchecka.\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimenchecka,\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimenchecka1\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka2\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka3\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka4\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka5\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka6\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka7\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka8\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka9\endcsname\dodimenteststageone +\expandafter\let\csname \??dimenchecka0\endcsname\dodimenteststageone + +\expandafter\let\csname \??dimencheckb1\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb2\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb3\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb4\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb5\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb6\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb7\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb8\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb9\endcsname\dodimenteststagetwo +\expandafter\let\csname \??dimencheckb0\endcsname\dodimenteststagetwo + +\expandafter\let\csname \??dimencheckc pt\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc pc\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc in\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc bp\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc cm\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc mm\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc dd\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc cc\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc sp\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc ex\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc em\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc nd\endcsname\firstoftwoarguments +\expandafter\let\csname \??dimencheckc nc\endcsname\firstoftwoarguments %D \macros %D {comparedimension,comparedimensioneps} @@ -6502,51 +6409,51 @@ % \copycsname xxx\endcsname\csname ..\endcsname -\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} +\unexpanded\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} % \letcscsname \crap \csname ..\endcsname % \letcsnamecs \csname ..\endcsname\crap % \letcsnamecsname\csname ..\endcsname\csname ..\endcsname -\def\letcscsname {\expandafter\let\expandafter} -\def\letcsnamecs {\expandafter\let} -\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} +\unexpanded\def\letcscsname {\expandafter\let\expandafter} +\unexpanded\def\letcsnamecs {\expandafter\let} +\unexpanded\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} % another one, add an item to a commalist -\def\addvalue#1#2% cs item +\unexpanded\def\addvalue#1#2% cs item {\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi \normalexpanded{\noexpand\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}} \def\unspaced#1% - {\dounspaced#1\end} + {\syst_helpers_unspaced#1\end} -\def\dounspaced#1% +\def\syst_helpers_unspaced#1% {\ifx#1\end \expandafter\gobbleoneargument \else \ifx#1\blankspace\else#1\fi \fi - \dounspaced} + \syst_helpers_unspaced} -\def\unspaceargument#1\to#2% +\unexpanded\def\unspaceargument#1\to#2% {\scratchcounter\catcode\spaceasciicode \catcode\spaceasciicode\ignorecatcode \scantextokens{\edef#2{#1}}% \catcode\spaceasciicode\scratchcounter} -\def\unspaceafter#1#2% +\unexpanded\def\unspaceafter#1#2% {\unspaceargument#2\to\ascii \expandafter#1\expandafter{\ascii}} % sometimes handy: -\def\doifhasspaceelse#1% - {\edef\!!stringa{#1}% - \normalexpanded{\noexpand\dodoifhasspaceelse#1\space}\empty\relax} +\unexpanded\def\doifhasspaceelse#1% + {\edef\m_syst_string_one{#1}% + \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax} -\def\dodoifhasspaceelse#1 #2#3\relax % \space\empty\relax - {\ifx\!!stringa\space +\unexpanded\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax + {\ifx\m_syst_string_one\space \expandafter\firstoftwoarguments \else\ifx#2\empty \doubleexpandafter\secondoftwoarguments @@ -6556,67 +6463,35 @@ % this will replace loadfile once and alike !!! todo -\def\@flg@{@flg@} - -\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\zerocount} -\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\plusone} +\installsystemnamespace{flag} -\let\ifflagged\ifcase +\unexpanded\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\zerocount} +\unexpanded\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\plusone} -\def\flag#1{\csname\@flg@#1\endcsname} +\def\flag#1{\csname\??flag#1\endcsname} \def\doifelseflagged#1% - {\expandafter\ifx\csname\@flg@#1\endcsname\relax + {\expandafter\ifx\csname\??flag#1\endcsname\relax \expandafter\secondoftwoarguments - \else\ifcase\csname\@flg@#1\endcsname + \else\ifcase\csname\??flag#1\endcsname \doubleexpandafter\firstoftwoarguments \else \doubleexpandafter\secondoftwoarguments \fi\fi} \def\doifnotflagged#1% - {\expandafter\ifx\csname\@flg@#1\endcsname\relax + {\expandafter\ifx\csname\??flag#1\endcsname\relax \expandafter\firstofoneargument - \else\ifcase\csname\@flg@#1\endcsname + \else\ifcase\csname\??flag#1\endcsname \doubleexpandafter\gobbleoneargument \else \doubleexpandafter\firstofoneargument \fi\fi} -\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey +\unexpanded\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter{\csname#1#5\endcsname}} -% \buildarray[test][aa,bb,cc,dd,ee,ff] -% \setarrayelement{test}{1}{qq} -% \arrayelement{test}{1} -% \arraylength{test} -% -% \def\buildarray[#1][#2]% -% {\scratchcounter=0 -% \def\docommand##1% -% {\advance\scratchcounter by 1 -% \setvalue{@@aa#1\the\scratchcounter}{##1}}% -% \processcommalist[#2]\docommand -% \setevalue{@@aa#1}{\the\scratchcounter}}% -% -% \def\setarrayelement#1#2{\setvalue{@@aa#1#2}} -% \def\arrayelement #1#2{\getvalue{@@aa#1#2}} -% \def\arraylength #1{\getvalue{@@aa#1}} - -% \newsignal\junksignal -% -% \def\setjunksignal% -% {\ifhmode -% \hskip\junksignal -% \let\removejunkspaces\doremovejunkspaces -% \else -% \let\removejunkspaces\relax -% \fi} -% -% \def\doremovejunkspaces% -% {\doloop{\ifdim\lastskip=\junksignal\unskip\else\exitloop\fi}} - -\def\dodoifnonzeropositiveelse#1#2\end % #3#4% +\def\syst_helpers_if_non_zero_positive_else#1#2\end % #3#4% {\ifx#1\relax \ifcase\scratchcounter \endgroup @@ -6631,45 +6506,42 @@ \fi} \def\doifnonzeropositiveelse#1% - {\begingroup\afterassignment\dodoifnonzeropositiveelse\scratchcounter=0#1\relax\empty\end} + {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\scratchcounter=0#1\relax\empty\end} % here ? -\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}} -\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}} -\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}} -\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}} +\unexpanded\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}} +\unexpanded\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}} +\unexpanded\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}} +\unexpanded\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}} -\def\getrawparameters {\dogetparameters\dosetrawvalue } -\def\getraweparameters {\dogetparameters\dosetrawevalue} -\def\getrawgparameters {\dogetparameters\dosetrawgvalue} -\def\getrawxparameters {\dogetparameters\dosetrawxvalue} +\unexpanded\def\getrawparameters {\dogetparameters\dosetrawvalue } +\unexpanded\def\getraweparameters {\dogetparameters\dosetrawevalue} +\unexpanded\def\getrawgparameters {\dogetparameters\dosetrawgvalue} +\unexpanded\def\getrawxparameters {\dogetparameters\dosetrawxvalue} -\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete - -\def\splitskip#1% - {\scratchskip#1\relax - \dimen0\scratchskip - \dimen2\gluestretch\scratchskip - \dimen4\glueshrink\scratchskip} +\unexpanded\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete -\newcount\modcounter +%D Sort of obsolete: -\def\dosetmodulo#1#2#3% - {\modcounter#1\divide\modcounter#2\multiply\modcounter#2% - #3#1\advance#3-\modcounter} +\newcount\c_syst_helpers_mod -\def\dosetdivision#1#2#3% +\unexpanded\def\dosetmodulo#1#2#3% + {\c_syst_helpers_mod#1\divide\c_syst_helpers_mod#2\multiply\c_syst_helpers_mod#2% + #3#1\advance#3-\c_syst_helpers_mod} + +\unexpanded\def\dosetdivision#1#2#3% {#3#1\divide#3 #2\relax} -\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}} -\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}} +\unexpanded\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}} +\unexpanded\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}} -\def\dounprotected#1\par +\def\syst_helpers_unprotected#1\par {#1\protect} -\def\unprotected - {\unprotect\dounprotected} +\unexpanded\def\unprotected + {\unprotect + \syst_helpers_unprotected} % awaiting the definitive implementation @@ -6683,20 +6555,21 @@ \def\elapsedtime {\ctxcommand{elapsedtime()}} \let\elapsedseconds \elapsedtime -\newcount\featuretest +\newcount\c_syst_helpers_test_feature_n \unexpanded\def\testfeature#1#2% - {\def\dotestfeature - {\advance\featuretest \plusone - \ifnum\featuretest>#1\else#2\expandafter\dotestfeature\fi}% + {\def\syst_helpers_test_feature_step + {\advance\c_syst_helpers_test_feature_n\plusone + \ifnum\c_syst_helpers_test_feature_n>#1\else#2\expandafter\syst_helpers_test_feature_step\fi}% \retestfeature} -\def\retestfeature % timer support is new per 10/5/2005 +\unexpanded\def\retestfeature % timer support is new per 10/5/2005 {\bgroup \ifcase\interactionmode\let\wait\relax\fi \writestatus\m!system{starting feature test}\wait \resettimer - \featuretest\zerocount \dotestfeature + \c_syst_helpers_test_feature_n\zerocount + \syst_helpers_test_feature_step \writestatus\m!system{feature test done (\elapsedseconds s)}% \wait \egroup} @@ -6719,7 +6592,7 @@ %D \freezedimenmacro\leftmargindistance %D \stoptyping -\def\freezedimenmacro#1% +\unexpanded\def\freezedimenmacro#1% {\edef#1{\the\dimexpr#1}} %D The next macro negates a macro (dimension or number, or actually, whatever. @@ -6735,191 +6608,19 @@ \def\gobbleassigndimen#1\\{} \def\assigndimen#1#2% - {\afterassignment\gobbleassigndimen#1=#2\!!zeropoint\\} - -\def\setusage#1% - {\expandafter\let\csname#1\endcsname\iftrue} - -\def\resetusage#1% - {\expandafter\let\csname#1\endcsname\iffalse} - -\def\ifusage#1% - {\ifcsname#1\endcsname\else - \resetusage{#1}% - \fi - \csname#1\endcsname} - -%D Very handy, more efficient than \type{{}}, and more readable -%D than \type {\empty}. - -\let\donothing\empty - -% The following macros are used in XML handling. - -\setvalue{@u@s@"}#1#2"{#2} \setvalue{@g@s@"}#1#2"{\scratchtoks{#2}} -\setvalue{@u@s@'}#1#2'{#2} \setvalue{@g@s@'}#1#2'{\scratchtoks{#2}} -\setvalue{@u@s@ }#1#2 {#2} \setvalue{@g@s@ }#1#2 {\scratchtoks{#2}} - -\def\unstringed#1{\csname\ifcsname @u@s@#1\endcsname @u@s@#1\else\s!empty\fi\endcsname#1} -\def\grabstring#1{\csname\ifcsname @g@s@#1\endcsname @g@s@#1\else\s!empty\fi\endcsname#1} - -\def\dowithgrabbedstring#1% - {\def\@@dowithgrabbedstring{#1}% - \afterassignment\@@dowithgrabbedstring\grabstring} - -\def\expifequalelse#1#2% - {\@@ifequal#1\relax\relax\@@and#2\relax\relax\@@then} - -\def\@@ifequal#1#2\@@and#3% - {\ifx#1\relax - \ifx#3\relax - \doubleexpandafter\@@if@@equal@@true - \else - \doubleexpandafter\@@if@@equal@@false - \fi - \else - \ifx#3\relax - \tripleexpandafter\@@if@@equal@@false - \else\ifx#1#3% - % go on - \else - \tripleexpandafter\@@if@@equal@@false - \fi\fi - \fi - \@@ifequal#2\@@and} - -\def\@@if@@equal@@true #1\@@then#2#3{#2} -\def\@@if@@equal@@false#1\@@then#2#3{#3} + {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\} -\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}} -\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname} -\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname} +\unexpanded\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}} +\unexpanded\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname} +\unexpanded\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname} -\def\prepended#1#2#3% - {\scratchtoks{#3}% +\unexpanded\def\prepended#1#2#3% + {\t_syst_helpers_scratch{#3}% \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter#2\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\scratchtoks#2}} - -\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname} -\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname} - -%D \macros -%D {compresscommacommandnrs,compresscommalistnrs,compressedcommalistnrs, -%D compresscommacommand,compresscommalist,compressedcommalist, -%D reversecommacommand,reversecommalist,reversedcommalist} -%D -%D The following two list processing macros are needed by Taco's -%D bibliography module. The numbers compressor converts the -%D list in a list of ranges. The normal compressor remove duplicate -%D and empty entries. -%D -%D This is now obsolete (and more a \LUA\ thing anyway). - -\def\compresscommalistnrs[#1]% - {\let\compressedlist\empty - \!!counta\maxdimen - \!!countb\maxdimen - \processcommalist[#1]\docompresslistnrs - \ifnum\!!counta=\maxdimen\else\dodocompresslistnrs\fi} - -\def\compresscommacommandnrs[#1]% - {\normalexpanded{\noexpand\compresscommalistnrs[#1]}} - -\def\docompresslistnrs#1% - {\edef\commalistelement{#1}% - \ifx\commalistelement\empty\else - \ifnum\!!counta=\maxdimen - \!!counta\commalistelement\relax - \!!countb\!!counta - \else - \advance\!!countb\plusone - \ifnum\commalistelement>\!!countb - \advance\!!countb\minusone - \dodocompresslistnrs - \!!counta\commalistelement\relax - \!!countb\!!counta - \fi - \fi - \fi} - -\def\dodocompresslistnrs - {\edef\compressedlist - {\ifx\compressedlist\empty\else\compressedlist,\fi - {\the\!!counta}{\ifnum\!!countb>\!!counta\the\!!countb\fi}}} - -%D \def\test#1{{\tttf#1->\compresscommalistnrs[#1]\defconvertedcommand\ascii\compressedlist\ascii}} -%D \startlines -%D \test{} -%D \test{1} -%D \test{1,3} -%D \test{1,3,4} -%D \test{1,3,3,4,5} -%D \test{1,3,3,4,5,8} -%D \test{1,3,3,4,5,5,8,10} -%D \test{1,3,4,5,8,10,11} -%D \test{1,,3,,4,,5,,8,,10,,11,} -%D \stoplines - -\def\compresscommalist[#1]% - {\let\compressedlist\empty - \let\!!stringa\empty - \processcommalist[#1]\docompresslist} - -\def\compresscommacommand[#1]% - {\normalexpanded{\noexpand\compresscommalist[#1]}} - -\def\docompresslist#1% - {\edef\commalistelement{#1}% - \ifx\commalistelement\empty \else - \ifx\!!stringa\commalistelement \else - \ifx\compressedlist\empty - \def\compressedlist{#1}% - \else - \appended\def\compressedlist{,#1}% - \fi - \let\!!stringa\commalistelement - \fi - \fi} - -%D \def\test#1{{\tttf#1->\compresscommalist[#1]\defconvertedcommand\ascii\compressedlist\ascii}} -%D \startlines -%D \test{} -%D \test{1} -%D \test{1,3} -%D \test{1,3,4} -%D \test{1,3,3,4,5} -%D \test{1,3,3,4,5,8} -%D \test{1,3,3,4,5,5,8,10} -%D \test{1,3,4,5,8,10,11} -%D \test{1,,3,,4,,5,,8,,10,,11,} -%D \stoplines - -\def\reversecommalist[#1]% - {\let\reversedlist\empty - \processcommalist[#1]\doreverselist} + {\expandafter\the\expandafter\t_syst_helpers_scratch#2}} -\def\doreverselist#1% - {\ifx\reversedlist\empty - \def\reversedlist{#1}% - \else - \prepended\def\reversedlist{#1,}% - \fi} - -\def\reversecommacommand[#1]% - {\normalexpanded{\noexpand\reversecommalist[#1]}} - -%D \def\test#1{{\tttf#1->\reversecommalist[#1]\defconvertedcommand\ascii\reversedlist\ascii}} -%D \startlines -%D \test{} -%D \test{1} -%D \test{1,3} -%D \test{1,3,4} -%D \test{1,3,3,4,5} -%D \test{1,3,3,4,5,8} -%D \test{1,3,3,4,5,5,8,10} -%D \test{1,3,4,5,8,10,11} -%D \test{1,,3,,4,,5,,8,,10,,11,} -%D \stoplines +\unexpanded\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname} +\unexpanded\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname} %D \macros %D {dowithrange} @@ -6927,44 +6628,11 @@ %D This one is for Mojca Miklavec, who made me aware of the fact that %D \type {page-imp.tex} was not the best place to hide it. -\def\dowithrange#1#2% #2 takes number +\unexpanded\def\dowithrange#1#2% #2 takes number {\splitstring#1\at:\to\fromrange\and\torange \ifx\torange\empty\let\torange\fromrange\fi \dostepwiserecurse\fromrange\torange1{#2{\recurselevel}}} - -%D \macros {uncompresslist} -%D -%D When given a list like \type{1,4-7,9} as argument, this macro -%D will store the expanded commalist in \type{\uncompressedlist}. -%D -%D \startbuffer -%D \def\MojcaHasToDoTheTasks[#1]#2% -%D {{\uncompresslist[#1]% -%D \def\processitem##1{I have to do ##1 #2\par}% -%D \processcommacommand[\uncompressedlist]\processitem}} -%D -%D \MojcaHasToDoTheTasks [1-4,7,9-11] {until tomorrow} -%D \stopbuffer -%D -%D Here is an example of how to use \type {\uncompresslist}: -%D \typebuffer -%D -%D The output of this is: -%D -%D \getbuffer -\def\uncompresslist[#1]% by TH - {\let\uncompressedlist\empty - \def\docompressedlistitem##1-##2-% - {\expandafter\dorecurse\expandafter - {\the\numexpr1+##2-##1\relax}% - {\expandafter\appendtocommalist\expandafter{\the\numexpr##1-1+####1\relax}\uncompressedlist}}% - \def\douncompresslist##1% - {\doifinstringelse{-}{##1} - {\docompressedlistitem##1-} - {\appendtocommalist{##1}\uncompressedlist}}% - \processcommalist[#1]\douncompresslist} - %D \macros %D {ignoreimplicitspaces} %D @@ -6977,7 +6645,7 @@ %D %D \typebuffer \getbuffer -\def\ignoreimplicitspaces +\unexpanded\def\ignoreimplicitspaces {\doifnextcharelse\relax\relax\relax} %D \macros @@ -6985,74 +6653,39 @@ %D %D Not that sophisticated but sometimes users (like in metafun). -\def\doprocesswords#1 #2\od - {\doifsomething{#1}{\processword{#1} \doprocesswords#2 \od}} -% {\doifsomething{\detokenize{#1}}{\processword{#1} \doprocesswords#2 \od}} % to be tested +\def\syst_helpers_process_word#1 #2\_e_o_w_ + {\doifsomething{#1}{\processword{#1} \syst_helpers_process_word#2 \_e_o_w_}} \def\processwords#1% - {\doprocesswords#1 \od}% no \unskip + {\syst_helpers_process_word#1 \_e_o_w_}% no \unskip \let\processword\relax -% new -% -% \startnointerference -% all kind of code -% \stopnointerference +%D \macros +%D {startnointerference} +%D +%D \starttyping +%D \startnointerference +%D all kind of code +%D \stopnointerference +%D \stoptyping -\newbox\nointerferencebox +\newbox\b_syst_helpers_no_interference \unexpanded\def\startnointerference % not even grouped ! - {\setbox\nointerferencebox\vbox + {\setbox\b_syst_helpers_no_interference\vbox \bgroup} \unexpanded\def\stopnointerference {\egroup - \setbox\nointerferencebox\emptybox} - -% \def\appendtovaluelist#1#2% -% {\ifcsname#1\endcsname -% \expandafter\ifx\csname#1\endcsname\empty -% \expandafter\def\csname#1\endcsname{#2}% -% \else -% \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname -% \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}% -% \fi -% \else -% \expandafter\def\csname#1\endcsname{#2}% -% \fi} -% -% or -% -% \def\appendtovaluelist#1% -% {\ifcsname#1\endcsname -% \expandafter\ifx\csname#1\endcsname\empty -% \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname -% \else -% \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname -% \fi -% \else -% \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname -% \fi} - -% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}} -% \def\noappendtovaluelist#1#2{\def#1{#2}} - -% \appendtovaluelist{mylist}{aap} -% \appendtovaluelist{mylist}{noot} -% \appendtovaluelist{mylist}{mies} - -% \showvalue{mylist} + \setbox\b_syst_helpers_no_interference\emptybox} %D A variant for \type {\executeifdefined}: -% \def\expandcheckedcsname#1#2#3% -% {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} - \def\expandcheckedcsname#1#2% #2 is often a \xxxparameter so let's expand it once - {\normalexpanded{\noexpand\doexpandcheckedcsname{#1}{#2}}} + {\normalexpanded{\noexpand\syst_helpers_expand_checked_csname{#1}{#2}}} -\def\doexpandcheckedcsname#1#2#3% +\def\syst_helpers_expand_checked_csname#1#2#3% {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} %D Signal. Some fonts have a char0 rendering so we need to make sure that it @@ -7060,7 +6693,41 @@ \unexpanded\def\signalcharacter{\char\zerocount} % \zwj -%D Here are some nasty helpers: +%D A few secial variants of commands defined here. Some more will be moved here (e.g. +%D from table modules. + +\def\dodirectdoubleempty#1#2% used in math (lookahead issues) + {\ifx#2[% + \expandafter\syst_helpers_direct_double_empty_one_yes + \else + \expandafter\syst_helpers_direct_double_empty_one_nop + \fi#1#2} + +\def\syst_helpers_direct_double_empty_one_yes#1[#2]#3% + {\ifx#3[\else\expandafter\syst_helpers_direct_double_empty_two_nop\fi#1[#2]#3} + +\def\syst_helpers_direct_double_empty_one_nop#1{#1[][]} +\def\syst_helpers_direct_double_empty_two_nop#1[#2]{#1[#2][]} + +%D Used in math definitions (in an type {\edef}): + +%D \startbuffer +%D [\docheckedpair{}] +%D [\docheckedpair{a}] +%D [\docheckedpair{a,b}] +%D [\docheckedpair{a,b,c}] +%D \stopbuffer +%D +%D \typebuffer \startlines \getbuffer \stoplines + +\def\docheckedpair#1% + {\syst_helpers_checked_pair#1,,\_o_e_p_} + +\def\syst_helpers_checked_pair#1,#2,#3\_o_e_p_ + {#1,#2} + +%D Here are some nasty helpers. They can be used to fill often expanded token +%D lists efficiently (see tabulate for an example). \def\constantnumber#1% {\ifcase#1\zerocount @@ -7111,8 +6778,53 @@ {#1}% \fi} -%D These can be used when constructing often reused token lists, -%D as we do with tabulates. +% %D Maybe some day (moved from cont-new): +% %D +% %D \starttyping +% %D \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) +% %D \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) +% %D \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}}) +% %D \stoptyping +% +% \def\syst_helpers_choice_finish#1\empty{} +% +% \def\syst_helpers_choice_dim#1#2#3% +% {\ifdim#1#2% +% #3\expandafter\syst_helpers_choice_finish +% \else +% \expandafter\syst_helpers_choice_dim +% \fi{#1}} +% +% \def\syst_helpers_choice_num#1#2#3% +% {\ifnum#1#2% +% #3\expandafter\syst_helpers_choice_finish +% \else +% \expandafter\syst_helpers_choice_num +% \fi{#1}} +% +% \def\dimchoice#1#2{\syst_helpers_choice_dim{#1}#2{=#1}{#1}\empty} +% \def\numchoice#1#2{\syst_helpers_choice_num{#1}#2{=#1}{#1}\empty} + +%D \macros +%D {getsubstring} +%D \startbuffer +%D +%D \getsubstring{4}{}{Who Wants This} +%D \getsubstring{4}{9}{Who Wants This} +%D \getsubstring{9}{-2}{Who Wants This} +%D \getsubstring{1}{5}{Who Wants This} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlines +%D \getbuffer +%D \stoplines + +% expandable: + +%def\getsubstring#1#2#3{\cldcontext{utf.sub([[#3]],tonumber("#1"),tonumber("#2"))}} +\def\getsubstring#1#2#3{\ctxcommand{getsubstring(\!!bs#3\!!es,"#1","#2")}} \protect \endinput @@ -7174,3 +6886,37 @@ % nothing % } % \stopchoice + +% \def\appendtovaluelist#1#2% +% {\ifcsname#1\endcsname +% \expandafter\ifx\csname#1\endcsname\empty +% \expandafter\def\csname#1\endcsname{#2}% +% \else +% \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname +% \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}% +% \fi +% \else +% \expandafter\def\csname#1\endcsname{#2}% +% \fi} +% +% or +% +% \def\appendtovaluelist#1% +% {\ifcsname#1\endcsname +% \expandafter\ifx\csname#1\endcsname\empty +% \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname +% \else +% \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname +% \fi +% \else +% \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname +% \fi} +% +% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}} +% \def\noappendtovaluelist#1#2{\def#1{#2}} +% +% \appendtovaluelist{mylist}{aap} +% \appendtovaluelist{mylist}{noot} +% \appendtovaluelist{mylist}{mies} +% +% \showvalue{mylist} diff --git a/tex/context/base/syst-fnt.mkiv b/tex/context/base/syst-fnt.mkiv index f5c9ea349..625b952b7 100644 --- a/tex/context/base/syst-fnt.mkiv +++ b/tex/context/base/syst-fnt.mkiv @@ -38,7 +38,7 @@ \def\mathsubcombined {\fontdimen17 } % to be remapped \def\mathaxisheight {\fontdimen22 } % to be remapped -\def\currentspaceskip {\interwordspace\!!plus\interwordstretch\!!minus\interwordshrink\relax} +\def\currentspaceskip {\interwordspace\s!plus\interwordstretch\s!minus\interwordshrink\relax} \def\mathstacktotal {\dimexpr\Umathstacknumup\scriptstyle+\Umathstackdenomdown\scriptstyle\relax} \def\mathstackvgap {\Umathstackvgap\scriptstyle} diff --git a/tex/context/base/syst-gen.mkii b/tex/context/base/syst-gen.mkii index bb0f54d11..8b71b77d5 100644 --- a/tex/context/base/syst-gen.mkii +++ b/tex/context/base/syst-gen.mkii @@ -657,6 +657,11 @@ \def\resetvalue #1{\expandafter\let\csname#1\endcsname\empty} \def\ignorevalue#1#2{\expandafter\let\csname#1\endcsname\empty} +\def\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname} +\def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname} +\def\setugvalue #1{\normalprotected\expandafter\gdef\csname#1\endcsname} +\def\setuxvalue #1{\normalprotected\expandafter\xdef\csname#1\endcsname} + %D \macros %D {globallet,glet} %D diff --git a/tex/context/base/syst-ini.mkiv b/tex/context/base/syst-ini.mkiv index 983bedc52..1c87c4ed4 100644 --- a/tex/context/base/syst-ini.mkiv +++ b/tex/context/base/syst-ini.mkiv @@ -11,16 +11,14 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D We used to load plain \TEX\ in a special way, but redefining -%D a couple of primitives so that for instance font loading was -%D ignored. For those interested, this loader is found in -%D \type {syst-tex.tex}. Some of the comment's are Don Knuth's -%D and more of it can be found in the plain \TEX\ format. - -%D Characters can have special states, that can be triggered -%D by setting their category coded. Some are preset, others -%D are to be set as soon as possible, otherwise we cannot -%D define any useful macros. +%D We used to load plain \TEX\ in a special way, but redefining a couple of +%D primitives so that for instance font loading was ignored. For those interested, +%D this loader is found in \type {syst-tex.tex}. Some of the comment's are Don +%D Knuths and more of it can be found in the plain \TEX\ format. +%D +%D Characters can have special states, that can be triggered by setting their +%D category coded. Some are preset, others are to be set as soon as possible, +%D otherwise we cannot define any useful macros. %catcode`\^^@ = 9 % ascii null is ignored %catcode`\\ = 0 % backslash is TeX escape character @@ -58,8 +56,7 @@ \catcode`\^^Z=9 -%D It makes sense to know what engine we're running so let's -%D try to deduce it. +%D It makes sense to know what engine we're running so let's try to deduce it. \chardef\unknownengine = 0 \chardef\pdftexengine = 1 @@ -117,16 +114,15 @@ } \fi -%D \ETEX\ has a not so handy way of telling you the version number, -%D i.e. the revision number has a period in it: +%D \ETEX\ has a not so handy way of telling you the version number, i.e. the revision +%D number has a period in it: \long\def\gobbleoneargument#1{} % will be defined later on anyway \mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax -%D First we define a simplified version of the \CONTEXT\ -%D protection mechanism. Later we will implement a better -%D variant. +%D First we define a simplified version of the \CONTEXT\ protection mechanism. +%D Later we will implement a better variant. \def\unprotect {\edef\protect @@ -149,18 +145,21 @@ \let\bgroup={ \let\egroup=} -%D Allocation of registers is done slightly different than in plain -%D \TEX. First of all we use different reserved counters. We also -%D don't implement a family handler because users are not supposed -%D to implement their own math. We reserve the lowest 31 registers -%D for scratch purposes. Keep in mind that in the core engine -%D some registers are reserved: counters 0 upto 9, and counter 255. +%D \macros +%D {normalbgroup,normalgroup} %D -%D As with plain \TEX\ we recommend that macro designers always use -%D \type {\global} assignments with respect to registers numbered 1, -%D 3, 5 \unknown\ 31, and always non||\type {\global} assignments -%D with respect to registers 0, 2, 4, \unknown\ 30. This will prevent -%D \quote {save stack buildup} that might otherwise occur. +%D No comment. + +%D Allocation of registers is done slightly different than in plain \TEX. First of +%D all we use different reserved counters. We also don't implement a family handler +%D because users are not supposed to implement their own math. We reserve the lowest +%D 31 registers for scratch purposes. Keep in mind that in the core engine some +%D registers are reserved: counters 0 upto 9, and counter 255. +%D +%D As with plain \TEX\ we recommend that macro designers always use \type {\global} +%D assignments with respect to registers numbered 1, 3, 5 \unknown\ 31, and always +%D non||\type {\global} assignments with respect to registers 0, 2, 4, \unknown\ 30. +%D This will prevent \quote {save stack buildup} that might otherwise occur. %D %D We reserve some registers for special (management) purposes: @@ -212,11 +211,10 @@ \dimendef \dimen@i = 1 % global only \dimendef \dimen@ii = 2 -%D So, effectively we start allocating from 256 and upwards. The -%D inserts sit in the range 128 upto 254. Page numbers use the -%D counters 0 upto 9 and the pagebox is 255. Users can use the -%D scratch registers upto 31 without problem but all others are -%D reserved. +%D So, effectively we start allocating from 256 and upwards. The inserts sit in the +%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is +%D 255. Users can use the scratch registers upto 31 without problem but all others +%D are reserved. \let\wlog\gobbleoneargument % Let's get rid of this one. @@ -254,12 +252,11 @@ %newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}} \newlinechar=10 \edef\outputnewlinechar{^^J} -%D One reason to start high with allocation is that it permits us to -%D allocate consecutive ranges more easily, for instance if for \MPLIB\ -%D we want to allocate a continuous range of boxes. It also permits us -%D to do a proper upward allocation for inserts. The current code -%D evolved from code that dealt with older engines but as all engines -%D now provide many registers we removed all traces. +%D One reason to start high with allocation is that it permits us to allocate +%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a +%D continuous range of boxes. It also permits us to do a proper upward allocation +%D for inserts. The current code evolved from code that dealt with older engines but +%D as all engines now provide many registers we removed all traces. \ifdefined\writestatus \else \normalprotected\def\writestatus#1#2{\immediate\write16{#1: #2}} @@ -286,29 +283,27 @@ \fi\fi #1#2#3#4#5} -%D Since the number of chars exceed 256 now, we can use \type -%D {\chardef} instead of the more limited \type {\mathchardef}. +%D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of +%D the more limited \type {\mathchardef}. \ifnum\texengine>\pdftexengine \normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register} \normalprotected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register} \fi -%D Attributes are something very \LUATEX. In \CONTEXT\ you are not -%D supposed to use the attributes directly but always allocate then -%D first. For instance attribute~0 is reserved for special purposes -%D (this might change). Attributes in the range 128-1023 are private -%D and should not be touched. +%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. \ifnum\texengine=\luatexengine \let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone \normalprotected\def\newattribute{\syst_basics_allocate\c_syst_min_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} \fi -%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a -%D trick to force strings instead of tokens that take more memory. -%D It's a trick to trick to force strings. This macro is never used -%D in \CONTEXT. +%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. \normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}} @@ -318,8 +313,8 @@ %D scratchbox, %D scratchtoks} %D -%D We now define a few scratch registers, so that successive -%D loads at least have some available. +%D We now define a few scratch registers, so that successive loads at least have +%D some available. \newcount \scratchcounter \newcount \globalscratchcounter \newdimen \scratchdimen \newdimen \globalscratchdimen @@ -343,21 +338,49 @@ \newdimen\scratchwidth \newdimen\scratchheight \newdimen\scratchdepth + \newdimen\scratchoffset +\newdimen\scratchleftoffset +\newdimen\scratchrightoffset +\newdimen\scratchtopoffset +\newdimen\scratchbottomoffset + \newdimen\scratchdistance + \newdimen\scratchhsize \newdimen\scratchvsize +\newdimen\scratchxoffset +\newdimen\scratchyoffset +\newdimen\scratchhoffset +\newdimen\scratchvoffset + +\newdimen\scratchxposition +\newdimen\scratchyposition + +\newcount\scratchnx +\newcount\scratchny + +\newcount\scratchmx +\newcount\scratchmy + +\newdimen\scratchleftskip +\newdimen\scratchrightskip +\newdimen\scratchtopskip +\newdimen\scratchbottomskip + %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 -\newdimen\onebasepoint \onebasepoint = 1bp -\newdimen\scaledpoint \scaledpoint = 1sp -\newdimen\thousandpoint \thousandpoint = 1000pt +\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 +\newdimen \onebasepoint \onebasepoint = 1bp +\newdimen \scaledpoint \scaledpoint = 1sp +\newdimen \thousandpoint \thousandpoint = 1000pt +\newmuskip\zeromuskip \zeromuskip = 0mu +\newmuskip\onemuskip \onemuskip = 1mu \let\points \onepoint \let\halfpoint\halfapoint @@ -410,8 +433,8 @@ \def\doubleexpandafter{\expandafter\expandafter\expandafter} \def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter} -%D We prefer the more readable variant than in plain -%D \TEX. User should only use \type {\emptybox}: +%D We prefer the more readable variant than in plain \TEX. User should only +%D use \type {\emptybox}: \newbox\voidbox % public @@ -425,8 +448,19 @@ \let\leavevmode\unvoidbox % we prefer to use \dontleavehmode -%D Some expected plain variants follow. We don't reuse registers -%D because we don't want clashes. +%D \macros +%D {dontcomplain} +%D +%D We need this one soon: + +\normalprotected\def\dontcomplain + {\hbadness\plustenthousand + \vbadness\plustenthousand + \hfuzz \maxdimen + \vfuzz \maxdimen} + +%D Some expected plain variants follow. We don't reuse registers because we +%D don't want clashes. \newdimen\p@ \p@ \onepoint \newcount\m@ne \m@ne \minusone @@ -440,8 +474,8 @@ \newbox \voidb@x \newtoks \toks@ -%D We define \type {\newif} a la plain \TEX, but will -%D redefine it later. As Knuth says: +%D We define \type {\newif} a la plain \TEX, but will redefine it later. As +%D Knuth says: %D %D \startnarrower %D And here's a different sort of allocation: for example, @@ -450,8 +484,7 @@ %D \newif\iffoo %D \stoptyping %D -%D creates \type {\footrue}, \type {\foofalse} to go -%D with \type {\iffoo}. +%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}. %D \stopnarrower \normalprotected\def\newif#1% @@ -479,8 +512,16 @@ \ifdefined\htdp \else \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi -%D The catcode constants will be redefined in later catcode -%D related modules but they can be used in the same way. +%D A few shortcuts: + +\normalprotected\def\glet {\global \let } +\normalprotected\def\udef {\normalprotected\def } +\normalprotected\def\ugdef{\normalprotected\gdef} +\normalprotected\def\uedef{\normalprotected\edef} +\normalprotected\def\uxdef{\normalprotected\xdef} + +%D The catcode constants will be redefined in later catcode related modules +%D but they can be used in the same way. \chardef\escapecatcode = 0 \chardef\begingroupcatcode = 1 @@ -499,6 +540,11 @@ \chardef\commentcatcode = 14 \chardef\invalidcatcode = 15 +%D For a while we keep the following, as systems like tikz need it. Best +%D not use that one \CONTEXT. + +\let\active\activecatcode + %D Constants to be used with \type {\currentgrouptype}. \chardef\bottomlevelgroupcode = 0 @@ -527,13 +573,12 @@ \chardef\scrollmodecode = 2 \chardef\errorstopmodecode = 3 -%D Constants to be used with \type {\lastnodetype}. The \type -%D {\lastnodetype} primitive is \ETEX\ compliant. The valid range is -%D still -1 .. 15 and glyph nodes have number 0 (used to be char -%D node) and ligature nodes are mapped to 7. That way macro packages -%D can use the same symbolic names as in traditional \ETEX. Keep in -%D mind that the internal node numbers are different and that there -%D are more node types that 15. +%D Constants to be used with \type {\lastnodetype}. The \type {\lastnodetype} +%D primitive is \ETEX\ compliant. The valid range is still -1 .. 15 and glyph nodes +%D have number 0 (used to be char node) and ligature nodes are mapped to 7. That way +%D macro packages can use the same symbolic names as in traditional \ETEX. Keep in +%D mind that the internal node numbers are different and that there are more node +%D types that 15. \chardef\charnodecode = 0 \chardef\hlistnodecode = 1 @@ -552,8 +597,8 @@ \chardef\unsetnodecode = 14 \chardef\mathsnodecode = 15 -%D Constants to be used with \type {\currentiftype}. I wonder if -%D we will ever use these in \CONTEXT. +%D Constants to be used with \type {\currentiftype}. I wonder if we will ever +%D use these in \CONTEXT. \chardef\charifcode = 1 \chardef\catifcode = 2 @@ -576,11 +621,11 @@ \chardef\csnameifcode = 19 \chardef\fontcharifcode = 20 -%D Of course we want even bigger log files, so we copied this -%D from the \ETEX\ source files. +%D Of course we want even bigger log files, so we copied this from the \ETEX\ +%D source files. %D -%D When watching such logs, beware of nasty side effects of -%D \type {\scantokens}, as in: +%D When watching such logs, beware of nasty side effects of \type {\scantokens}, +%D as in: %D %D \starttyping %D \bgroup @@ -641,14 +686,13 @@ \ifdefined\normalinput \else \let\normalinput\input \fi -%D We don't like outer commands, and we always want access -%D to the original \type {\input} primitive. +%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 To circumvent dependencies, we can postpone certain -%D initializations to dumping time, by appending them to the -%D \type {\everydump} token register. +%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 @@ -669,11 +713,10 @@ %D settrue, setfalse, %D ifconditional,then} %D -%D \TEX's lacks boolean variables, although the \PLAIN\ format -%D implements \type{\newif}. The main disadvantage of this -%D scheme is that it takes three hash table entries. A more -%D memory saving alternative is presented here. A conditional -%D is defined by: +%D \TEX's lacks boolean variables, although the \PLAIN\ format implements \type +%D {\newif}. The main disadvantage of this scheme is that it takes three hash table +%D entries. A more memory saving alternative is presented here. A conditional is +%D defined by: %D %D \starttyping %D \newconditional\doublesided @@ -699,9 +742,8 @@ %D \def\setfalse#1{\let#1=\iffalse} %D \stoptyping %D -%D Such an implementation gives problems with nested -%D conditionals. The next implementation is about as fast -%D and just as straightforward: +%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 @@ -717,8 +759,8 @@ %D \macros %D {newmacro,setnewmacro,newfraction} %D -%D Let's be complete and also introduce some definers. These are -%D not mandate but handy for grepping. +%D Let's be complete and also introduce some definers. These are not mandate +%D but handy for grepping. \normalprotected\def\newmacro #1{\let#1\empty} \normalprotected\def\setnewmacro#1{\let#1} @@ -727,17 +769,15 @@ \normalprotected\def\newfraction#1{\let#1\!!plusone} -%D It would be handy to have a primitive \unless\ifcase because -%D then we could use nicer values. Anyhow, this conditional code -%D used to be in the \type {syst-aux} module but is now promoted -%D to here. +%D It would be handy to have a primitive \unless\ifcase because then we could +%D use nicer values. Anyhow, this conditional code used to be in the \type +%D {syst-aux} module but is now promoted to here. %D \macros %D {ifzeropt} %D -%D The next macro is both cosmetic and byte saving. It is -%D pretty \type{\if}||safe too. It can be used in cases -%D like: +%D The next macro is both cosmetic and byte saving. It is pretty \type +%D {\if}||safe too. It can be used in cases like: %D %D \starttyping %D \ifzeropt \somedimen ... \else ... \fi @@ -785,7 +825,23 @@ \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi} -%D Now come a few macros that might be needed in successive loading: +%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. + +% too tricky: \par is use more often than a par starts so we have too much change +% that we get assymetrical behaviour +% +% \newtoks\everyendpar +% +% \normalprotected\def\endpar{\the\everyendpar\normalpar} +% \normalprotected\def\par {\endpar} +% +% \normalprotected\def\reseteverypar +% {\everypar \emptytoks +% \everyendpar\emptytoks} + +\normalprotected\def\reseteverypar + {\everypar\emptytoks} \let\endgraf\par \let\endline\cr @@ -794,9 +850,8 @@ \def\empty{} \def\null {\hbox{}} -%D The following two might be overloaded later on but some modules need -%D then earlier. These functionality is reflected in the name and will not -%D change. +%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. \bgroup \catcode`\^^M=\activecatcode% @@ -813,16 +868,15 @@ \let\endoflinetoken=^^M -%D Also needed might be a simple loop structure and we borrow -%D plain \TEX's one as it is often expected to be present and -%D it is about the fastest you can get. Beware: this macro -%D does not support nested loops. We use a namespace prefix -%D \type {@@pln}. +%D Also needed might be a simple loop structure and we borrow plain \TEX's one +%D as it is often expected to be present and it is about the fastest you can +%D get. Beware: this macro does not support nested loops. We use a namespace +%D prefix \type {@@pln}. \long\def\loop#1\repeat{\long\def\@@plnbody{#1}\@@plniterate} % might go -%D The following makes \type {\loop} \unknown\ \type {\if} -%D \unknown\ \type {\repeat} skippable (clever trick): +%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! @@ -842,23 +896,22 @@ \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\fi} -%D We don't define a real output routine yet but at least get rid -%D of pages: +%D We don't define a real output routine yet but at least get rid of pages: \output{\shipout\box\normalpagebox} -%D Although we don't add pagenumbers yet we alias the default -%D register used for counting pages: +%D Although we don't add pagenumbers yet we alias the default register used +%D for counting pages: \countdef\pageno=0 \pageno=1 % first page is number 1 -%D Beside the raw counter \type {\pageno} the \type {\folio} -%D macro provides the value. +%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 -%D The following registers are kind of standard and (for the moment) -%D we define them here. This might change. +%D The following registers are kind of standard and (for the moment) we define +%D them here. This might change. \newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt \newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt @@ -893,9 +946,8 @@ \spanomit \advance\mscount\minusone \repeat} -%D The next section deals with selective definitions in -%D later modules. One can of course use the \type {\texengine} -%D number that we defined earlier instead. +%D The next section deals with selective definitions in later modules. One can of +%D course use the \type {\texengine} number that we defined earlier instead. \bgroup \obeylines \gdef\pickupSOMETEX#1% @@ -927,19 +979,19 @@ \fi %D \macros -%D {bindprimitive} +%D {bindprimitive} %D -%D We can remap primitives (which is needed because of changes in -%D for instance \PDFTEX). +%D We can remap primitives (which is needed because of changes in for instance +%D \PDFTEX). \def\bindprimitive#1 #2 % new old {\ifcsname#1\endcsname \else \ifcsname#2\endcsname \expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname \fi \fi} -%D Because \XETEX\ also implements some \PDFTEX\ functionality, we take -%D care of this here instead of a dedicated module. Later modules need -%D to handle the undefined cases. +%D Because \XETEX\ also implements some \PDFTEX\ functionality, we take care of this +%D here instead of a dedicated module. Later modules need to handle the undefined +%D cases. %D These messy checks will disappear. @@ -997,8 +1049,8 @@ \newif\ifproductionrun -%D We need to make sure that we start up in \DVI\ mode, so, -%D after testing for running \PDFTEX, we default to \DVI. +%D We need to make sure that we start up in \DVI\ mode, so, after testing for running +%D \PDFTEX, we default to \DVI. \ifx\pdftexversion\undefined \newcount\pdfoutput \fi \pdfoutput=0 @@ -1044,15 +1096,14 @@ \let\synctex\undefined \newcount\synctex -%D We get rid of the funny \TEX\ offset defaults of one -%D inch by setting them to zero. +%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero. -\voffset \zeropoint \newdimen\voffset % prevent messing up -\hoffset \zeropoint \newdimen\hoffset % prevent messing up +\voffset\zeropoint \let\voffset\relax \newdimen\voffset % prevent messing up +\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset % prevent messing up -%D While cleaning this code up a bit I was listening to Heather -%D Nova's \CD\ Redbird. The first song on that \CD\ ends with -%D a few lines suitable for ending this initialization module: +%D While cleaning this code up a bit I was listening to Heather Nova's \CD\ Redbird. +%D The first song on that \CD\ ends with a few lines suitable for ending this +%D initialization module: %D %D \startlines %D And there's so much I can do for you @@ -1065,7 +1116,6 @@ %D Come inside %D \stoplines %D -%D So let's see what \TEX\ can do now that we've opened up -%D the basic machinery. +%D So let's see what \TEX\ can do now that we've opened up the basic machinery. \protect \endinput diff --git a/tex/context/base/syst-lua.lua b/tex/context/base/syst-lua.lua index f735b1962..ef524c339 100644 --- a/tex/context/base/syst-lua.lua +++ b/tex/context/base/syst-lua.lua @@ -16,14 +16,17 @@ commands = commands or { } function commands.writestatus(...) logs.status(...) end -- overloaded later --- todo: use shorter names i.e. less tokenization, like prtcatcodes + f_o_t_a - local firstoftwoarguments = context.firstoftwoarguments -- context.constructcsonly("firstoftwoarguments" ) local secondoftwoarguments = context.secondoftwoarguments -- context.constructcsonly("secondoftwoarguments") local firstofoneargument = context.firstofoneargument -- context.constructcsonly("firstofoneargument" ) local gobbleoneargument = context.gobbleoneargument -- context.constructcsonly("gobbleoneargument" ) -local function testcase(b) +-- contextsprint(prtcatcodes,[[\ui_fo]]) -- firstofonearguments +-- contextsprint(prtcatcodes,[[\ui_go]]) -- gobbleonearguments +-- contextsprint(prtcatcodes,[[\ui_ft]]) -- firstoftwoarguments +-- contextsprint(prtcatcodes,[[\ui_st]]) -- secondoftwoarguments + +function commands.doifelse(b) if b then firstoftwoarguments() else @@ -47,33 +50,45 @@ function commands.doifnot(b) end end -commands.testcase = testcase -commands.doifelse = testcase +commands.testcase = commands.doifelse -- obsolete function commands.boolcase(b) context(b and 1 or 0) end function commands.doifelsespaces(str) - return testcase(find(str,"^ +$")) + if find(str,"^ +$") then + firstoftwoarguments() + else + secondoftwoarguments() + end end local s = lpegtsplitat(",") local h = { } -function commands.doifcommonelse(a,b) +function commands.doifcommonelse(a,b) -- often the same test local ha = h[a] local hb = h[b] - if not ha then ha = lpegmatch(s,a) h[a] = ha end - if not hb then hb = lpegmatch(s,b) h[b] = hb end - for i=1,#ha do - for j=1,#hb do + if not ha then + ha = lpegmatch(s,a) + h[a] = ha + end + if not hb then + hb = lpegmatch(s,b) + h[b] = hb + end + local na = #ha + local nb = #hb + for i=1,na do + for j=1,nb do if ha[i] == hb[j] then - return testcase(true) + firstoftwoarguments() + return end end end - return testcase(false) + secondoftwoarguments() end function commands.doifinsetelse(a,b) @@ -81,16 +96,21 @@ function commands.doifinsetelse(a,b) if not hb then hb = lpegmatch(s,b) h[b] = hb end for i=1,#hb do if a == hb[i] then - return testcase(true) + firstoftwoarguments() + return end end - return testcase(false) + secondoftwoarguments() end local pattern = lpeg.patterns.validdimen function commands.doifdimenstringelse(str) - testcase(lpegmatch(pattern,str)) + if lpegmatch(pattern,str) then + firstoftwoarguments() + else + secondoftwoarguments() + end end function commands.firstinset(str) diff --git a/tex/context/base/syst-lua.mkiv b/tex/context/base/syst-lua.mkiv index 0d72e4a01..004655b74 100644 --- a/tex/context/base/syst-lua.mkiv +++ b/tex/context/base/syst-lua.mkiv @@ -40,4 +40,11 @@ %def\luaexpr#1{\ctxlua {context(tostring(#1))}} \def\luaexpr#1{\directlua\zerocount{context(tostring(#1))}} % wrap in global function ? +% helpers: + +\def\ui_fo #1{#1} +\def\ui_go #1{} +\def\ui_ft#1#2{#1} +\def\ui_st#1#2{#2} + \protect \endinput diff --git a/tex/context/base/tabl-ltb.mkiv b/tex/context/base/tabl-ltb.mkiv index 542d256f2..f7fbc0390 100644 --- a/tex/context/base/tabl-ltb.mkiv +++ b/tex/context/base/tabl-ltb.mkiv @@ -63,6 +63,8 @@ \newconstant\linetableheadstate \newconstant\linetablemode +\definesystemvariable {le} % LinetablE + \edef\??ler{\??le:r:} \edef\??lec{\??le:c:} \edef\??lew{\??le:w:} @@ -721,10 +723,10 @@ \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun \egroup} -\protect \endinput +\protect + +\continueifinputfile{tabl-ltb.mkiv} -\doifnotmode{demo}{\endinput} - \setuplinetable[n=6,m={2,2,2},lines=25] % m ? \setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red] diff --git a/tex/context/base/tabl-mis.mkiv b/tex/context/base/tabl-mis.mkiv new file mode 100644 index 000000000..9a0f13853 --- /dev/null +++ b/tex/context/base/tabl-mis.mkiv @@ -0,0 +1,288 @@ +%D \module +%D [ file=tabl-mis, +%D version=2012.06.28, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Miscellaneous, +%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 / Miscellaneous} + +\unprotect + +%D \macros +%D {somekindoftab,kindoftabposition} +%D +%D This macro can be used to create tabs: +%D +%D \starttyping +%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\kindoftabposition}}}] +%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\kindoftabposition}}}] +%D +%D \starttext +%D \showframe \dorecurse{10}{test\page} +%D \stoptext +%D \stoptyping +%D +%D (This rather old but updated code used to be in \type {core-mis.mkiv}.) + +\let\kindoftabposition\!!zerocount + +\unexpanded\def\somekindoftab + {\dosingleempty\typo_kindoftab} + +\def\typo_kindoftab[#1]% + {\bgroup + \getdummyparameters + [\c!alternative=\v!vertical, + \c!width=\textwidth,\c!height=\textheight, + \c!n=\lastpage,\c!m=\realpageno, + #1]% + \doifelse{\directdummyparameter\c!alternative}\v!vertical + {\typo_kindoftab_indeed\vbox\vskip\c!height} + {\typo_kindoftab_indeed\hbox\hskip\c!width }} + +\def\typo_kindoftab_indeed#1#2#3#4% + {#1 to \directdummyparameter#3 \bgroup + \forgetall + \scratchnx\directdummyparameter\c!n\relax + \scratchmx\directdummyparameter\c!m\relax + \edef\kindoftabposition{\the\scratchmx}% + \ifnum\scratchmx>\plusone + #2\zeropoint \s!plus \the\numexpr\scratchmx-\plusone \relax\s!fill\relax + \fi + #4% can use \kindoftabposition + \ifnum\scratchmx<\scratchnx\relax + #2\zeropoint \s!plus \the\numexpr\scratchnx-\scratchmx\relax\s!fill\relax + \fi + \egroup + \egroup} + +%D The following paragraphs mechanism is probably one of the oldest of +%D \CONTEXT\ and mostly served as a table mechanism capable of dealing +%D with paragraphs. Nowadays one can also use tabulate or natural tables. +%D +%D \startbuffer +%D \defineparagraphs[sample][n=2,rule=on] +%D +%D \startsample +%D first \nextsample +%D second \nextsample +%D third +%D \stopsample +%D +%D \startsample +%D \input tufte \nextsample +%D \input ward \nextsample +%D \input davis \nextsample +%D \input zapf +%D \stopsample +%D +%D \startparagraphs[sample] +%D first \nextsample +%D second \nextsample +%D third +%D \stopparagraphs +%D +%D \startparagraphs[sample] +%D \startparagraphscell +%D first +%D \stopparagraphscell +%D \startparagraphscell +%D second +%D \stopparagraphscell +%D \startparagraphscell +%D third +%D \stopparagraphscell +%D \stopparagraphs +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace{paragraphs} + +\installcommandhandler \??paragraphs {paragraphs} \??paragraphs + +\setupparagraphs + [\c!n=3, + \c!before=\blank, + \c!after=\blank, + \c!distance=\emwidth, + \c!height=\v!fit, + \c!width=\availablehsize, + \c!rule=\v!off, + \c!command=, + \c!align=, + \c!tolerance=\v!tolerant, % obsolete + \c!rulethickness=\linewidth, + \c!rulecolor=, + \c!style=, + \c!color=, + \c!top=\vss, + \c!bottom=\vfill] + +\let\typo_paragraphs_setup_saved\setupparagraphs + +\unexpanded\def\setupparagraphs + {\dotripleempty\typo_paragraphs_setup} + +\def\typo_paragraphs_setup[#1][#2][#3]% we are downward compatible with [each] and [1,3] + {\ifthirdargument + \doifelse{#2}\v!each + {\typo_paragraphs_setup_saved[#1][#3]} + {\def\typo_paragraphs_setup_step##1{\typo_paragraphs_setup_saved[#1:##1][#3]}% + \processcommalist[#2]\typo_paragraphs_setup_step}% + \else\ifsecondargument + \typo_paragraphs_setup_saved[#1][#2]% + \else\iffirstargument + \typo_paragraphs_setup_saved[#1]% + \fi\fi\fi} + +\appendtoks + \letvalue{\e!next \currentparagraphs}\nextparagraphs + \letvalue\currentparagraphs\nextparagraphs + \setuevalue{\e!start\currentparagraphs}{\startparagraphs[\currentparagraphs]}% + \letvalue{\e!stop \currentparagraphs}\stopparagraphs + %setuevalue{\e!setup\currentparagraph\e!endsetup}{\typo_paragraphs_setup_saved[\currentparagraphs]}% + \dorecurse{\paragraphsparameter\c!n} + {\normalexpanded{\typo_paragraphs_setup_saved[\currentparagraphs:\recurselevel][\c!width=,\s!parent=\??paragraphs\currentparagraphs]}}% + \typo_paragraphs_setup_saved[\currentparagraphs:1][\c!distance=\zeropoint]% +\to \everydefineparagraphs + +\newcount\c_typo_paragraphs_n +\newcount\c_typo_paragraphs_max +\newdimen\d_typo_paragraphs_width +\newdimen\d_typo_paragraphs_auto + +\unexpanded\def\startparagraphs[#1]% quite slow + {\bgroup % (1) + \edef\currentparagraphs{#1}% + \paragraphsparameter\c!before + \edef\p_width{\paragraphsparameter\c!width}% + \ifx\p_width\empty + \d_typo_paragraphs_width\availablehsize + \else + \d_typo_paragraphs_width\p_width\relax + \fi + \c_typo_paragraphs_max\paragraphsparameter\c!n\relax + \d_typo_paragraphs_auto\d_typo_paragraphs_width\relax + \scratchcounter\zerocount + \dorecurse\c_typo_paragraphs_max + {\edef\p_width{\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!width}% + \ifx\p_width\empty + \advance\scratchcounter\plusone + \else + \advance\d_typo_paragraphs_auto-\p_width\relax + \fi + \ifnum\recurselevel>\plusone + \advance\d_typo_paragraphs_auto-\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!distance\relax + \fi}% + \ifnum\scratchcounter>\zerocount + \divide\d_typo_paragraphs_auto\scratchcounter + \else + \d_typo_paragraphs_auto\zeropoint + \fi + \parindent\zeropoint + \c_typo_paragraphs_n\zerocount + \let\\=\typo_paragraphs_next % downward compatible + \dontleavehmode\hbox + \bgroup % (2) + \forgetall + \let\typo_paragraphs_start_cell\typo_paragraphs_start_cell_indeed + \let\typo_paragraphs_stop_cell \typo_paragraphs_stop_cell_indeed + \typo_paragraphs_start_cell_indeed} + +\unexpanded\def\stopparagraphs + {\stopparagraphscell + \egroup % (2) + \paragraphsparameter\c!after + \egroup} % (1) + +\unexpanded\def\nextparagraphs + {\stopparagraphscell + \startparagraphscell} + +\unexpanded\def\startparagraphscell + {\typo_paragraphs_start_cell} + +\def\typo_paragraphs_start_cell_indeed + {\removeunwantedspaces + \advance\c_typo_paragraphs_n\plusone + \ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max + \expandafter\typo_paragraphs_start_cell_nop + \else + \expandafter\typo_paragraphs_start_cell_yes + \fi} + +\def\typo_paragraphs_start_cell_nop + {\begingroup + % message: too many cells in paragraphs + \let\typo_paragraphs_start_cell\relax + \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed + \setbox\scratchbox\vbox\bgroup} + +\def\typo_paragraphs_start_cell_yes + {\begingroup + \let\typo_paragraphs_start_cell\relax + \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed + \edef\currentparagraphs{\currentparagraphs:\the\c_typo_paragraphs_n}% + \ifnum\c_typo_paragraphs_n>\plusone + \typo_paragraphs_separator + \fi + \edef\p_height{\paragraphsparameter\c!height}% + \edef\p_width {\paragraphsparameter\c!width }% + \useparagraphsstyleandcolor\c!style\c!color + \setbox\scratchbox\vtop \ifx\p_height\empty \else\ifx\p_height\v!fit \else to \p_height \fi\fi + \bgroup % (2) + \blank[\v!disable]% + \paragraphsparameter\c!top + \hsize\ifx\p_width\empty \d_typo_paragraphs_auto \else \p_width \fi \relax + \usealignparameter\paragraphsparameter + \paragraphsparameter\c!inner + \everypar{\begstrut\everypar\emptytoks}% + \ignorespaces + \paragraphsparameter\c!command} + +\unexpanded\def\stopparagraphscell + {\typo_paragraphs_stop_cell + \let\typo_paragraphs_stop_cell\relax} + +\def\typo_paragraphs_stop_cell_indeed + {\ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max + \expandafter\typo_paragraphs_stop_cell_nop + \else + \expandafter\typo_paragraphs_stop_cell_yes + \fi} + +\def\typo_paragraphs_stop_cell_nop + {\egroup + \endgroup} + +\def\typo_paragraphs_stop_cell_yes + {\ifvmode + \removelastskip + \else + \removeunwantedspaces + \endstrut + \endgraf + \fi + \paragraphsparameter\c!bottom + \egroup % (2) + \dontleavehmode\hbox{\raise\strutheight\box\scratchbox}% + \endgroup} + +\def\typo_paragraphs_separator + {\scratchdistance\paragraphsparameter\c!distance + \doif{\paragraphsparameter\c!rule}\v!on + {\scratchwidth\paragraphsparameter\c!rulethickness + \scratchdistance\dimexpr(\scratchdistance-\scratchwidth)/2\relax + \hskip\scratchdistance + \color[\paragraphsparameter\c!rulecolor]{\vrule\s!width\scratchwidth}}% + \hskip\scratchdistance} + +\protect \endinput diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv index 99da4b5e8..9c7864184 100644 --- a/tex/context/base/tabl-ntb.mkiv +++ b/tex/context/base/tabl-ntb.mkiv @@ -1,5 +1,5 @@ %D \module -%D [ file=core-ntb, +%D [ file=tabl-ntb, %D version=2000.04.18, %D title=\CONTEXT\ Table Macros, %D subtitle=Natural Tables, @@ -11,16 +11,15 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This is an unfinished, preliminary module. At least two -%D runs are needed to get the table fixed. Ugly code. +%D This module as a more modern variant in xtables but as we follow a bit +%D different approach with settings there, this mechanism will stay. In fact +%D each of them has its advantages. This module could be sped up a bit and made +%D more efficient by delegating some housekeeping to \LUA\ but it's not worth +%D the effort. The code could me made more readable but again, there is no +%D real purpose in it. If needed I can squeeze out a few more percentages +%D runtime. -% todo: TABLE TBL -> ntb -% todo: special parsetb for argless variant -% todo: protect \tbl... -% todo: tblnx also count -% todo: get rid of recurse -% todo: fast if -% todo: avoid halign (just do it manual) and thereby globals +\writestatus{loading}{ConTeXt Table Macros / Natural Tables} % bug: width 3cm is not honored and column becomes too wide % as given width is added to distributed width @@ -56,65 +55,14 @@ % \stopcelltable % \stoptext -% optie=rek beschrijven - -\writestatus{loading}{ConTeXt Table Macros / Natural Tables} - -%D As always, this is the nth version. Much time went in +%D As always, this is the n\high{th} version. Much time went in %D trying to speed up the many cell calculations, some %D optimizations were rejected in order not to complicate this -%D module too much (and in order to prevail extensibility). +%D module too much (and in order to prevail extensibility). In the +%D meantime we've sacrified some speed for readability. -% shapebox fails here in mkii -% -% \setupcolors[state=start] -% \bTABLE -% \bTR [align=middle]\bTH Range\eTH{}\bTH Value\eTH{}\eTR -% \bTR \bTD \type{<} 12\eTD{}\bTD 3\eTD{}\eTR -% \bTR \bTD 12--16\eTD{}\bTD 2\eTD{}\eTR -% \bTR \bTD \type{>}16\eTD{}\bTD 1\eTD{}\eTR -% \eTABLE - -% \starttext -% \placefigure[left]{}{} -% \startlinecorrection \dontleavehmode \bTABLE -% \bTR \bTD oeps \eTD \eTR -% \eTABLE \stoplinecorrection -% \placefigure[right]{}{} -% \startlinecorrection \dontleavehmode \bTABLE -% \bTR \bTD oeps \eTD \eTR -% \eTABLE \stoplinecorrection -% \stoptext - -%D To Do: -%D -%D \starttyping -%D break over pagina -%D kop herhalen -%D reset settings -%D -%D \setupTABLE [c|column|x] [nx|odd|even|first|last][a=b] -%D \setupTABLE [r|row |y] [nx|odd|even|first|last][a=b] -%D \setupTABLE [nx|odd|even|first|last][ny|odd|even|first|last][a=b] -%D \setupTABLE [nx|odd|even|first|last] [a=b] -%D \setupTABLE [a=b] -%D -%D \bTH \eTH -%D \stoptyping - -% the section setup does not work yet, data needs to be stored, -% i.e.each row should know if it's a head/body/foot, and there -% should be \setupTABLE[head]... and alike - \unprotect -%D A simple way to force equal line spacing is to say: -%D -%D \starttyping -%D \def\bTBLCELL{\begstrut} -%D \def\eTBLCELL{\endstrut} -%D \stoptyping -%D %D The next alternative also takes care of preceding and following %D white space. %D @@ -126,22 +74,25 @@ %D %D \typebuffer \getbuffer -\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi -\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi +\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi % todo: namespace +\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi % todo: namespace + +\let\tabl_tnb_next_level\relax -\def\bTBLCELL % why not \doinhibitblank +\unexpanded\def\tabl_tnb_cell_start {\inhibitblank \dotagTABLEcell - \dousestyleparameter\tbltblstyle - \everypar{\tbltblleft\delayedbegstrut}} +% \tabl_tnb_next_level + \usenaturaltablelocalstyleandcolor\c!style\c!color + \everypar{\naturaltablelocalparameter\c!left\delayedbegstrut}} -\def\eTBLCELL +\unexpanded\def\tabl_tnb_cell_stop {\ifhmode \delayedendstrut - \tbltblright + \naturaltablelocalparameter\c!right \par % added 13/4/2006 \else - % not sure yet:\tbltblright + % not sure yet:\naturaltablelocalparameter\c!right \par \ifdim\prevdepth<\zeropoint % =-1000pt ? \vskip-\strutdp @@ -150,92 +101,195 @@ \fi \fi} -\newcount\currenttbl +\newcount\c_tabl_ntb_row +\newcount\c_tabl_ntb_col +\newcount\c_tabl_ntb_spn -\def\@@tbl{tbl} \def\tblcell{1} \def\tblnone{2} +\newcount\c_tabl_ntb_nx +\newcount\c_tabl_ntb_ny -\def\@@tblprefix{tbl:} \let\@@rawtblprefix\@@tblprefix +\setnewconstant\c_tabl_ntb_cell \plusone +\setnewconstant\c_tabl_ntb_none \plustwo -%D This should be done more efficient: soon +\newcount\c_tabl_ntb_current_row +\newcount\c_tabl_ntb_current_col +\newcount\c_tabl_ntb_current_row_one +\newcount\c_tabl_ntb_current_col_one +\newcount\c_tabl_ntb_current_row_two +\newcount\c_tabl_ntb_current_col_two +\newcount\c_tabl_ntb_current_row_three +\newcount\c_tabl_ntb_current_col_three +\newcount\c_tabl_ntb_current_row_four +\newcount\c_tabl_ntb_current_col_four -% \let as well as \expandafter\edef's +\newcount\c_tabl_ntb_running_col +\newcount\c_tabl_ntb_maximum_row +\newcount\c_tabl_ntb_maximum_col +\newcount\c_tabl_ntb_maximum_row_span +\newcount\c_tabl_ntb_maximum_col_span -\newcounter\TBLlevel +\newtoks\t_tabl_ntb +\newtoks\t_tabl_ntb_row -\def\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi} +\newconstant\c_tabl_tbl_pass -% \def\tblsetprefix % not yet used, figure out when .. may interfere with setup -% {\edef\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi}} +\newtoks\t_tabl_ntb_head +\newtoks\t_tabl_ntb_next +\newtoks\t_tabl_ntb_body +\newtoks\t_tabl_ntb_foot -\def\settblnob#1{\expandafter\let\csname\@@tblprefix\number#1:b\endcsname\plusone} -\def\gettblnob#1{\ifcsname\@@tblprefix\number#1:b\endcsname\plusone\else\zerocount\fi} +\newcount\c_tabl_ntb_n_of_head_lines +\newcount\c_tabl_ntb_n_of_next_lines +\newcount\c_tabl_ntb_n_of_hdnx_lines -\def\settbltag#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:s\endcsname} -\def\settblcol#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:c\endcsname} -\def\settblrow#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:r\endcsname} +\newdimen\d_tabl_ntb_height +\newdimen\d_tabl_ntb_width -\def\lettbltag#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:s\endcsname} -\def\lettblcol#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:c\endcsname} -\def\lettblrow#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:r\endcsname} +\newtoks\everyTABLEpass % public -\def\settblwd#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global ! -\def\settblht#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global ! -\def\lettblwd#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global ! -\def\lettblht#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global ! +\newcount\tablecellrows % public (needs checking) +\newcount\tablecellcolumns % public (needs checking) -\def\gettbltag#1#2{\csname\@@tblprefix\number#1:\number#2:s\endcsname} -\def\gettblcol#1#2{\csname\@@tblprefix\number#1:\number#2:c\endcsname} -\def\gettblrow#1#2{\csname\@@tblprefix\number#1:\number#2:r\endcsname} +\newbox\b_tabl_ntb_final -\def\gettblwd #1#2{\csname\@@tblprefix\number#1:\number#2:wd\endcsname} -\def\gettblht #1#2{\csname\@@tblprefix\number#1:\number#2:ht\endcsname} +%D We have already prepared the previous macros for nesting, +%D so we only have to pop in the right ones: -\def\settblwid#1{\expandafter\xdef\csname\@@tblprefix\number#1:w\endcsname} % {#2} global ! -\def\settblhei#1{\expandafter\xdef\csname\@@tblprefix\number#1:h\endcsname} % {#2} global ! -\def\settbldis#1{\expandafter\xdef\csname\@@tblprefix\number#1:d\endcsname} % {#2} global ! -\def\settblaut#1{\expandafter\xdef\csname\@@tblprefix\number#1:a\endcsname} % {#2} global ! +\newcount\c_tabl_level -\def\lettblwid#1{\global\expandafter\let\csname\@@tblprefix\number#1:w\endcsname} % {#2} global ! -\def\lettblhei#1{\global\expandafter\let\csname\@@tblprefix\number#1:h\endcsname} % {#2} global ! -\def\lettbldis#1{\global\expandafter\let\csname\@@tblprefix\number#1:d\endcsname} % {#2} global ! -\def\lettblaut#1{\global\expandafter\let\csname\@@tblprefix\number#1:a\endcsname} % {#2} global ! +\unexpanded\def\tabl_ntb_table_push + {\ifnum\m_tabl_tbl_level>\plusone + \tabl_ntb_parameters_reset + % we need a proper count push/pop + \xdef\m_tabl_ntb_saved_row{\the\c_tabl_ntb_row}\globalpushmacro\m_tabl_ntb_saved_row + \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\globalpushmacro\m_tabl_ntb_saved_col + \else + \global\intabletrue + \fi} -\def\gettblwid#1{\ifcsname\@@tblprefix\number#1:w\endcsname\csname\@@tblprefix\number#1:w\endcsname\else\zeropoint\fi} -\def\gettblhei#1{\ifcsname\@@tblprefix\number#1:h\endcsname\csname\@@tblprefix\number#1:h\endcsname\else\zeropoint\fi} -\def\gettbldis#1{\ifcsname\@@tblprefix\number#1:d\endcsname\csname\@@tblprefix\number#1:d\endcsname\else\zeropoint\fi} -\def\gettblaut#1{\csname \@@tblprefix\number#1:a\endcsname} +\unexpanded\def\tabl_ntb_table_pop + {\ifnum\m_tabl_tbl_level>\plusone + \globalpopmacro\m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row + \globalpopmacro\m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col + \else + \global\intablefalse + \fi} -\def\doiftbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} -\def\doifnottbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi} -\def\doifelsetbltag#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi} -\def\doiftblrow #1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} -\def\doiftblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} -\def\doifnottblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi} +\unexpanded\def\tabl_tnb_next_level + {\advance\c_tabl_level\plusone + \edef\m_tabl_tbl_level{\the\c_tabl_level}} + +\unexpanded\def\tabl_tnb_prev_level + {\advance\c_tabl_level\minusone + \edef\m_tabl_tbl_level{\the\c_tabl_level}} + +\tabl_tnb_next_level % go to level 1 + +\installcorenamespace{naturaltable} % was tbl +\installcorenamespace{naturaltablelocal} % was tbltbl + +\installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable +\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal + +\installcorenamespace{naturaltablenob} +\installcorenamespace{naturaltabletag} +\installcorenamespace{naturaltablecol} +\installcorenamespace{naturaltablerow} +\installcorenamespace{naturaltablewd} +\installcorenamespace{naturaltableht} +\installcorenamespace{naturaltabledp} +\installcorenamespace{naturaltablewid} +\installcorenamespace{naturaltablehei} +\installcorenamespace{naturaltabledis} +\installcorenamespace{naturaltableaut} +\installcorenamespace{naturaltabletxt} +\installcorenamespace{naturaltablespn} +\installcorenamespace{naturaltableref} +\installcorenamespace{naturaltableset} +\installcorenamespace{naturaltablecell} + +\def\tabl_ntb_set_nob#1{\expandafter\let\csname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone} +\def\tabl_ntb_get_nob#1{\ifcsname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone\else\zerocount\fi} + +\def\tabl_ntb_set_tag#1#2{\expandafter\edef\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_set_col#1#2{\expandafter\edef\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_set_row#1#2{\expandafter\edef\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_let_tag#1#2{\expandafter\let\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_let_col#1#2{\expandafter\let\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_let_row#1#2{\expandafter\let\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_set_wd#1#2{\expandafter\xdef\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +\def\tabl_ntb_set_ht#1#2{\expandafter\xdef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! + +\def\tabl_ntb_let_wd#1#2{\global\expandafter\let\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +\def\tabl_ntb_let_ht#1#2{\global\expandafter\let\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! + +\def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} +\def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} + +\def\tabl_ntb_set_wid#1{\expandafter\xdef\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_hei#1{\expandafter\xdef\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_dis#1{\expandafter\xdef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_set_aut#1{\expandafter\xdef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! + +\def\tabl_ntb_let_wid#1{\global\expandafter\let\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_hei#1{\global\expandafter\let\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_dis#1{\global\expandafter\let\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_aut#1{\global\expandafter\let\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! + +\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi} +\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi} +\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi} +\def\tabl_ntb_get_aut#1{\csname \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} + +\def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2} +\def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2} +\def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2} + +\def\tabl_ntb_tag_doif #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} +\def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} +\def\tabl_ntb_row_doif #1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\def\tabl_ntb_col_doif #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \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\tbltagstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\zerocount\else\plusone\fi} -\def\tblrowstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\zerocount\else\plusone\fi} -\def\tblcolstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\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\settblspn #1{\expandafter\let\csname\@@tblprefix\number#1:s\endcsname \!!plusone} -\def\doifelsetblspn#1{\doifelse {\csname\@@tblprefix\number#1:s\endcsname}\!!plusone} -% \def\doifelsetblspn#1{\@EA\ifx\csname\@@tblprefix\number#1:s\endcsname\plusone\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi} +\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\settblspn #1{\setvalue {\@@tblprefix\number#1:s}{1}} -\def\doifelsetblspn#1{\doifelsevalue{\@@tblprefix\number#1:s}{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} -\long\def\settbltxt#1#2#3% - {\long\@EA\def\csname\@@tblprefix\number#1:\number#2:t\@EA\endcsname\@EA{\@EA\def\@EA\TBLlevel\@EA{\TBLlevel}#3}} +% keep for a while: +% +% \unexpanded\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}}} -\def\gettbltxt#1#2% - {\csname\@@tblprefix\number#1:\number#2:t\endcsname} +\unexpanded\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_tnb_next_level#6\tabl_tnb_prev_level}}} -\newtoks\tbltoks -\newtoks\tblrowtoks +\def\tabl_ntb_get_txt#1#2% + {\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname} -\let\pushTBLparameters\relax -\let\popTBLparameters \relax +% to be changed: -\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells +\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells \newif\ifautosqueezeTBLspan \autosqueezeTBLspantrue % unless explicit widths are given \newif\ifautoTBLspread \autoTBLspreadfalse \newif\ifautoTBLhsize \autoTBLhsizetrue @@ -249,78 +303,90 @@ \newif\iftraceTABLE \traceTABLEfalse -\def\noftblheadlines{0} -\def\noftblnextlines{0} -\def\noftblhdnxlines{0} - -\long\def\handleTBLcell#1#2[#3]{} +% so far -\long\def\bTC#1\eTC{\bTD#1\eTD} -\long\def\bTX#1\eTX{\bTD#1\eTD} -\long\def\bTY#1\eTY{\bTR#1\eTR} +\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{} -\let\getTABLEparameters\getparameters +\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 \unexpanded\def\setupTABLE - {\dotripleempty\dosetupTABLE} + {\dotripleempty\tabl_ntb_setup} -\def\dosetupTABLE[#1][#2][#3]% +\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal + +\def\tabl_ntb_setup {\ifthirdargument - \processaction - [#1] - [ \v!row=>{\dosetupTABLExy[\c!y][#2][#3]},% - \v!column=>{\dosetupTABLExy[\c!x][#2][#3]},% - r=>{\dosetupTABLExy[\c!y][#2][#3]},% - c=>{\dosetupTABLExy[\c!x][#2][#3]},% - y=>{\dosetupTABLExy[\c!y][#2][#3]},% - x=>{\dosetupTABLExy[\c!x][#2][#3]},% - \v!start=>{\dosetupTABLExy[#1][#2][#3]},% - \v!header=>{\dosetupTABLExy[#1][#2][#3]},% - \s!unknown=>{\dosetupTABLEzz[#1][#2][#3]}]% + \expandafter\tabl_ntb_setup_three \else\ifsecondargument - \processaction - [#1] - [ \v!row=>{\dosetupTABLExy[\c!y][\v!each][#2]},% - \v!column=>{\dosetupTABLExy[\c!x][\v!each][#2]},% - r=>{\dosetupTABLExy[\c!y][\v!each][#2]},% - c=>{\dosetupTABLExy[\c!x][\v!each][#2]},% - y=>{\dosetupTABLExy[\c!y][\v!each][#2]},% - x=>{\dosetupTABLExy[\c!x][\v!each][#2]},% - \v!start=>{\dosetupTABLExy[#1][\v!each][#2]},% - \v!header=>{\dosetupTABLExy[#1][\v!each][#2]},% - \s!unknown=>{\dosetupTABLEzz[\c!x][#1][#2]}]% + \doubleexpandafter\tabl_ntb_setup_two \else - \getparameters[\@@tbl\@@tbl][#1]% + \doubleexpandafter\tabl_ntb_setup_one \fi\fi} -\def\dosetupTABLExy[#1][#2][#3]% - {\def\dodosetupTABLE##1{\setTABLEparameters[#1##1][#3]}% - \processcommalist[#2]\dodosetupTABLE} - -\def\dosetupTABLEzz[#1][#2][#3]% - {\def\dodosetupTABLE##1% - {\def\dododosetupTABLE####1{\setTABLEparameters[\c!x##1\c!y####1][#3]}% - \processcommalist[#2]\dododosetupTABLE}% - \processcommalist[#1]\dodosetupTABLE} - -\def\nopTABLEparameters[#1][#2]% - {\letvalueempty{\@@tblprefix#1}} % can be made faster - -\def\setTABLEparameters[#1][#2]% - {\pushTBLparameters - \ifappendTBLsetups - \doifdefinedelse{\@@tblprefix#1} - {\def\getTABLEparameters[##1][##2]% - {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][##2,#2]}}% - \getvalue{\@@tblprefix#1}% - \let\getTABLEparameters\getparameters} - {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}}% +\def\tabl_ntb_setup_one[#1][#2][#3]% + {\setupcurrentnaturaltablelocal[#1]} + +\def\tabl_ntb_setup_xy[#1][#2][#3]% + {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[#1##1][#3]}% + \processcommalist[#2]\tabl_ntb_setup_step} + +\def\tabl_ntb_setup_un[#1][#2][#3]% + {\def\tabl_ntb_setup_step##1% + {\def\tabl_ntb_setup_step_step####1{\tabl_ntb_parameters_set[\c!x##1\c!y####1][#3]}% + \processcommalist[#2]\tabl_ntb_setup_step_step}% + \processcommalist[#1]\tabl_ntb_setup_step} + +\def\tabl_ntb_setup_each[#1][#2][#3]% ignores #3 + {\tabl_ntb_parameters_set[#1\v!each][#2]} + +\def\tabl_ntb_setup_ux[#1][#2][#3]% ignores #3 + {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[\c!x##1][#2]}% + \processcommalist[#1]\tabl_ntb_setup_step} + +\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]} + +\setvalue{\??naturaltablesetupthree \v!row}[#1]{\tabl_ntb_setup_xy [\c!y]} +\setvalue{\??naturaltablesetupthree \v!column}[#1]{\tabl_ntb_setup_xy [\c!x]} +\setvalue{\??naturaltablesetupthree \v!start}[#1]{\tabl_ntb_setup_xy [\v!start]} +\setvalue{\??naturaltablesetupthree \v!header}[#1]{\tabl_ntb_setup_xy [\v!header]} + +\setvalue{\??naturaltablesetuptwo \v!row}[#1]{\tabl_ntb_setup_each[\c!y]} +\setvalue{\??naturaltablesetuptwo \v!column}[#1]{\tabl_ntb_setup_each[\c!x]} +\setvalue{\??naturaltablesetuptwo \v!start}[#1]{\tabl_ntb_setup_each[\v!start]} +\setvalue{\??naturaltablesetuptwo \v!header}[#1]{\tabl_ntb_setup_each[\v!header]} + +\letvalue{\??naturaltablesetupthree\s!unknown}\tabl_ntb_setup_un +\letvalue{\??naturaltablesetuptwo \s!unknown}\tabl_ntb_setup_ux + +\letcsnamecsname\csname\??naturaltablesetupthree r\endcsname\csname\??naturaltablesetupthree \v!row\endcsname +\letcsnamecsname\csname\??naturaltablesetupthree c\endcsname\csname\??naturaltablesetupthree\v!column\endcsname +\letcsnamecsname\csname\??naturaltablesetupthree y\endcsname\csname\??naturaltablesetupthree \v!row\endcsname +\letcsnamecsname\csname\??naturaltablesetupthree x\endcsname\csname\??naturaltablesetupthree\v!column\endcsname + +\letcsnamecsname\csname\??naturaltablesetuptwo r\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname +\letcsnamecsname\csname\??naturaltablesetuptwo c\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname +\letcsnamecsname\csname\??naturaltablesetuptwo y\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname +\letcsnamecsname\csname\??naturaltablesetuptwo x\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname + +\def\tabl_ntb_parameters_set[#1][#2]% + {\ifappendTBLsetups + \ifcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname + \def\tabl_ntb_parameters_get[##1]% + {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}% + \getvalue{\??naturaltableset\m_tabl_tbl_level:#1}% + \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal + \else + \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}% + \fi \else - \setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}% - \fi - \popTBLparameters} - -\let\setupTBLsection\relax + \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}% + \fi} % % \setupTABLE [y] [first][background=color,backgroundcolor=blue,frame=off,bottomframe=on,topframe=on,framecolor=white] % \setupTABLE [first][first][backgroundcorner=2,corner=10,frame=on] @@ -382,87 +448,91 @@ %D %D \start \tightTBLrowspanfalse \getbuffer \stop -\unexpanded\def\setupTBLcell#1#2% cell over col over row - {\setupTBLsection % already forgotten - \edef\positiverow{\number#1}% - \edef\positivecol{\number#2}% - \edef\negativerow{\the\numexpr-\maximumrow+#1+\minusone\relax}% - \edef\negativecol{\the\numexpr-\maximumcol+#2+\minusone\relax}% +\let\tabl_ntb_setup_section\relax + +\unexpanded\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}% + \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}% + \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}% + % saves tokens (no speed gain) + \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}% % each each - \csname\@@tblprefix\c!x\v!each\c!y\v!each\endcsname - \csname\@@tblprefix\c!y\v!each\endcsname - \csname\@@tblprefix\c!x\v!each\endcsname + \csname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname + \csname\m_tabl_ntb_prefix\c!y\v!each\endcsname + \csname\m_tabl_ntb_prefix\c!x\v!each\endcsname % odd even - \csname\@@tblprefix\c!y\v!oddeven\positiverow\endcsname - \csname\@@tblprefix\c!x\v!oddeven\positivecol\endcsname - \csname\@@tblprefix\c!x\v!oddeven\positivecol\c!y\v!oddeven\positiverow\endcsname + \csname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname + \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname + \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname % row/col number combinations - \ifcsname\@@tblprefix\c!y\positiverow\endcsname\csname\@@tblprefix\c!y\positiverow\endcsname\fi - \ifcsname\@@tblprefix\c!y\negativerow\endcsname\csname\@@tblprefix\c!y\negativerow\endcsname\fi - \csname\@@tbl\@@tbl\c!extras\endcsname - \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo - \ifcsname\@@tblprefix\c!x\positivecol\endcsname\csname\@@tblprefix\c!x\positivecol\endcsname\fi - \ifcsname\@@tblprefix\c!x\negativecol\endcsname\csname\@@tblprefix\c!x\negativecol\endcsname\fi - \csname\@@tbl\@@tbl\c!extras\endcsname - \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo + \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\fi + \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\fi + \naturaltablelocalparameter\c!extras + \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\fi + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\fi + \naturaltablelocalparameter\c!extras + \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo % first/last combinations - \ifnum\positiverow=\plusone - \csname\@@tblprefix\c!y\v!first\endcsname - \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\fi + \ifnum\m_tabl_ntb_positive_row=\plusone + \csname\m_tabl_ntb_prefix\c!y\v!first\endcsname + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\fi \fi - \ifnum\positivecol=\plusone - \csname\@@tblprefix\c!x\v!first\endcsname - \ifcsname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\fi + \ifnum\m_tabl_ntb_positive_col=\plusone + \csname\m_tabl_ntb_prefix\c!x\v!first\endcsname + \ifcsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\fi \fi - \ifnum\positiverow=\maximumrow\relax - \csname\@@tblprefix\c!y\v!last\endcsname - \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\fi + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax + \csname\m_tabl_ntb_prefix\c!y\v!last\endcsname + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\fi \fi - \ifnum\positivecol=\maximumcol\relax - \csname\@@tblprefix\c!x\v!last\endcsname - \ifcsname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\fi + \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax + \csname\m_tabl_ntb_prefix\c!x\v!last\endcsname + \ifcsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\fi \fi - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax - \csname\@@tblprefix\c!x\v!last\c!y\v!last\endcsname + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax + \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname \fi\fi - \ifnum\positiverow=\plusone \ifnum\positivecol=\plusone - \csname\@@tblprefix\c!x\v!first\c!y\v!first\endcsname + \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone + \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname \fi\fi - \ifnum\positiverow=\plusone \ifnum\positivecol=\maximumcol\relax - \csname\@@tblprefix\c!x\v!last\c!y\v!first\endcsname + \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax + \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname \fi\fi - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone - \csname\@@tblprefix\c!x\v!first\c!y\v!last\endcsname + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone + \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname \fi\fi % special case: two rows and last row : two&first and two&last (round corners) - \ifnum\maximumrow=\plustwo\relax - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone - \csname\@@tblprefix\c!x\v!first\c!y\v!two\endcsname + \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone + \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname \fi\fi - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax - \csname\@@tblprefix\c!x\v!last\c!y\v!two\endcsname + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax + \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname \fi\fi \fi - \ifnum\gettblcol\positiverow\positivecol=\maximumcol\relax % top span over whole width - \ifnum\positiverow=\plusone - \csname\@@tblprefix\c!x\v!one\c!y\v!first\endcsname + \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width + \ifnum\m_tabl_ntb_positive_row=\plusone + \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname \fi - \ifnum\positiverow=\maximumrow\relax - \csname\@@tblprefix\c!x\v!one\c!y\v!last\endcsname + \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax + \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname \fi \fi % header things - \ifnum#1>\noftblhdnxlines\else - \ifcsname\@@tblprefix\v!header\v!each \endcsname\csname\@@tblprefix\v!header\v!each \endcsname\fi - \ifcsname\@@tblprefix\v!header\positivecol\endcsname\csname\@@tblprefix\v!header\positivecol\endcsname\fi + \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else + \ifcsname\m_tabl_ntb_prefix\v!header\v!each \endcsname\csname\m_tabl_ntb_prefix\v!header\v!each \endcsname\fi + \ifcsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\fi \fi % explicit cells - \ifcsname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\fi - \ifcsname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\csname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\fi + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\fi + \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\fi % local - \ifcsname\@@tblprefix\c!y++\positiverow\endcsname\csname\@@tblprefix\c!y++\positiverow\endcsname\fi + \ifcsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\fi % done - \global\letcscsname\@@tblsplitafter\csname\@@tbl\@@tbl\c!after\endcsname + \xdef\m_tabl_ntb_after_split{\naturaltablelocalparameter\c!after}% to be checked \relax} % we cannot use +n (checking on number/last/first would slow down too much) @@ -478,7 +548,7 @@ % \dorecurse{10}{\bTR \dorecurse{6}{\bTD xxx \eTD} \eTR} % \eTABLE -\globallet\@@tblsplitafter\relax +\let\m_tabl_ntb_after_split\relax % split + page: % @@ -488,101 +558,152 @@ % \bTR \bTD left \eTD\bTD right \eTD\eTR % \eTABLE -% todo: protect counters +\unexpanded\def\tabl_ntb_tr + {\c_tabl_ntb_running_col\zerocount + \advance\c_tabl_ntb_maximum_row\plusone + \iffirstargument + \expandafter\tabl_ntb_tr_yes + \else + \expandafter\gobbleoneoptional + \fi} -\newcount\row \newcount\col -\newcount\xrow \newcount\xcol -\newcount\xxrow \newcount\xxcol -\newcount\maximumrow \newcount\maximumcol \newcount\maximumrowspan - \newcount\currentcol -\newcount\tblspn +\def\tabl_ntb_tr_yes[#1]% + {\setvalue{\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_maximum_row}{\setupcurrentnaturaltablelocal[#1]}} -\def\settblref#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:x\endcsname} -\def\gettblref#1#2{\ifcsname\@@tblprefix\number#1:\number#2:x\endcsname\csname\@@tblprefix\number#1:\number#2:x\endcsname\fi} +\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr} +\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc} -\def\parseTR[#1]% - {\currentcol\zerocount - \advance\maximumrow\plusone - \iffirstargument - \setvalue{\@@tblprefix\c!y++\number\maximumrow}{\getparameters[\@@tbl\@@tbl][#1]}% maybe also in mkii +\unexpanded\def\tabl_ntb_td + {\iffirstargument + \expandafter\tabl_ntb_td_yes + \else + \expandafter\tabl_ntb_td_nop \fi} -\long\def\parseTD[#1]#2\eTD - {\def\tblny{\tblnr}% - \def\tblnx{\tblnc}% - \let\tblnc\plusone - \let\tblnr\plusone - \let\tbln\currentcol - \let\tblm\empty - \iffirstargument - \getparameters[\@@tbl][#1]% - \fi - % goto first cell % NEW, n/m=cellnumber - \edef\@@tblnindeed{\csname\@@tbl\c!n\endcsname}% - \ifx\@@tblnindeed\empty - \global\advance\tblspn\tblnx\relax - \else\ifnum\@@tblnindeed=\currentcol\else - \scratchcounter\numexpr\@@tblnindeed-\currentcol+\minusone-\tblspn\relax - \ifnum\scratchcounter>\zerocount - \normalexpanded{\noexpand\parseTD[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD - \fi - % can also be made faster - \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% +\def\tabl_ntb_td_yes[#1]#2\eTD + {\letnaturaltableparameter\c!ny \m_tabl_ntb_default_nr + \letnaturaltableparameter\c!nx \m_tabl_ntb_default_nc + \letnaturaltableparameter\c!nc \plusone + \letnaturaltableparameter\c!nr \plusone + \letnaturaltableparameter\c!n \c_tabl_ntb_running_col + \letnaturaltableparameter\c!m \empty + \letnaturaltableparameter\c!action\empty % not that important + \setupcurrentnaturaltable[#1]% + % + \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax + \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax + % goto first cell n/m=cellnumber + \edef\m_tabl_ntb_n{\naturaltableparameter\c!n}% + \edef\m_tabl_ntb_m{\naturaltableparameter\c!m}% + % + \ifx\m_tabl_ntb_n\empty + \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax + \else\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else + \tabl_ntb_td_pass_n{#1}% \fi\fi - \edef\@@tblmindeed{\csname\@@tbl\c!m\endcsname}% - \ifx\@@tblmindeed\empty \else - \ifnum\@@tblmindeed=\currentcol \else - \scratchcounter\numexpr\@@tblmindeed-\currentcol+\minusone-\tblspn\relax - \dorecurse\scratchcounter{\normalexpanded{\noexpand\parseTD[\c!n=,\c!m=]}\eTD}% - % can be sped up - \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% kind of double, see prev + \ifx\m_tabl_ntb_m\empty \else + \ifnum\m_tabl_ntb_m=\c_tabl_ntb_running_col\else + \tabl_ntb_td_pass_m{#1}% \fi \fi \doloop % skip over columns that result from earlier span - {\advance\currentcol\plusone - \doifnottbltag\maximumrow\currentcol\exitloop}% - % == \def\next{\advance\currentcol\plusone\doiftbltag\maximumrow\currentcol\next}\next + {\advance\c_tabl_ntb_running_col\plusone + \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else + \exitloop + \fi}% % fill r*c cells and set span - \ifnum\tblnx=\plusone - \ifnum\tblny=\plusone - \ifnum\currentcol>\maximumcol\relax - \maximumcol\currentcol + \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax + \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax + \ifnum\c_tabl_ntb_nx=\plusone + \ifnum\c_tabl_ntb_ny=\plusone + \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax + \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col \fi \else - \presetTBLcell + \tabl_ntb_cell_preset \fi \else - \presetTBLcell + \tabl_ntb_cell_preset \fi % set values - \lettbltag\maximumrow\currentcol\tblcell - \settblcol\maximumrow\currentcol{\number\tblnx}% - \settblrow\maximumrow\currentcol{\number\tblny}% + \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell + \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}% + \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}% % the action key will change! - \settblref\maximumrow\currentcol{\ifcsname\@@tbl\c!action\endcsname\csname\@@tbl\c!action\endcsname\fi}% + \tabl_ntb_set_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\naturaltableparameter\c!action}% % save text - \edef\celltag{{\number\maximumrow}{\number\currentcol}}% - \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA{\@EA\handleTBLcell\celltag[#1]{#2}}} - -\def\presetTBLcell - {\row\maximumrow - \col\currentcol - \dorecurse\tblny - {\col\currentcol - \settblcol\row\col{\number\tblnx}% - \ifnum\tblnx>\maximumrowspan\relax - \maximumrowspan\tblnx - \fi - \dorecurse\tblnx - {\lettbltag\row\col\tblnone - \advance\col\plusone}% - \advance\row\plusone}% + \normalexpanded + {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}% + {#1}{#2}} + +\def\tabl_ntb_td_nop[#1]#2\eTD + {\global\advance\c_tabl_ntb_spn\plusone\relax + \doloop + {\advance\c_tabl_ntb_running_col\plusone + \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else + \exitloop + \fi}% + \c_tabl_ntb_nx\plusone + \c_tabl_ntb_ny\plusone + \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax + \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col + \fi + \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell + \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}% + \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}% + \tabl_ntb_let_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\empty + \normalexpanded + {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}% + {#1}{#2}} + +\def\tabl_ntb_td_pass_n#1% + {\scratchcounter\numexpr\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax + \ifnum\scratchcounter>\zerocount + \normalexpanded{\tabl_ntb_td[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD + \fi + \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr + \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc + \letnaturaltableparameter\c!nc\plusone + \letnaturaltableparameter\c!nr\plusone + \setupcurrentnaturaltable[#1]% + \letnaturaltableparameter\c!n \empty + \letnaturaltableparameter\c!m \empty} + +\def\tabl_ntb_td_pass_m#1% + {\scratchcounter\numexpr\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax + \dorecurse\scratchcounter{\normalexpanded{\tabl_ntb_td[\c!n=,\c!m=]}\eTD}% + % can be sped up + \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr + \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc + \letnaturaltableparameter\c!nc\plusone + \letnaturaltableparameter\c!nr\plusone + \setupcurrentnaturaltable[#1]% + \letnaturaltableparameter\c!n \empty + \letnaturaltableparameter\c!m \empty} + +\def\tabl_ntb_cell_preset + {\c_tabl_ntb_current_row\c_tabl_ntb_maximum_row + \c_tabl_ntb_current_col\c_tabl_ntb_running_col + \dorecurse\c_tabl_ntb_ny\tabl_ntb_cell_preset_rows % check max column - \advance\col\minusone - \ifnum\col>\maximumcol\relax - \maximumcol\col + \advance\c_tabl_ntb_current_col\minusone + \ifnum\c_tabl_ntb_current_col>\c_tabl_ntb_maximum_col\relax + \c_tabl_ntb_maximum_col\c_tabl_ntb_current_col \fi} +\def\tabl_ntb_cell_preset_rows + {\c_tabl_ntb_current_col\c_tabl_ntb_running_col + \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_nx}% + \ifnum\c_tabl_ntb_nx>\c_tabl_ntb_maximum_row_span\relax + \c_tabl_ntb_maximum_row_span\c_tabl_ntb_nx + \fi + \dorecurse\c_tabl_ntb_nx\tabl_ntb_cell_preset_cells + \advance\c_tabl_ntb_current_row\plusone} + +\def\tabl_ntb_cell_preset_cells + {\tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none + \advance\c_tabl_ntb_current_col\plusone} + %D The usage of n and m: %D %D \startbuffer @@ -617,13 +738,13 @@ %D \stopbuffer %D %D \typebuffer \getbuffer - -\long\def\parseTH[#1]#2\eTH - {\parseTD[#1,\c!color=\tbltblheadcolor,\c!style=\tbltblheadstyle,\c!aligncharacter=\v!no]#2\eTD} -\long\def\parseTN[#1]#2\eTN - {\parseTD[#1]\digits#2\relax\eTD} - +\def\tabl_ntb_th[#1]#2\eTH + {\tabl_ntb_td[#1,\c!color=\naturaltablelocalparameter\c!headcolor,\c!style=\naturaltablelocalparameter\c!headstyle,\c!aligncharacter=\v!no]#2\eTD} + +\def\tabl_ntb_tn[#1]#2\eTN + {\tabl_ntb_td[#1]\digits#2\relax\eTD} + %D Vit Zyka needed the option to create a distance between columns, so I %D added support for individual column distances. %D @@ -668,86 +789,94 @@ %D \stopbuffer %D %D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection - -\newtoks\TBLhead -\newtoks\TBLnext -\newtoks\TBLbody -\newtoks\TBLfoot % to be done: head <raw> foot, dus state var -\unexpanded\def\bTABLEhead{\dosingleempty\doTABLEhead} \let\eTABLEhead\relax -\unexpanded\def\bTABLEnext{\dosingleempty\doTABLEnext} \let\eTABLEnext\relax -\unexpanded\def\bTABLEbody{\dosingleempty\doTABLEbody} \let\eTABLEbody\relax -\unexpanded\def\bTABLEfoot{\dosingleempty\doTABLEfoot} \let\eTABLEfoot\relax +\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 -\long\def\doTABLEhead[#1]#2\eTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead} -\long\def\doTABLEnext[#1]#2\eTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext} -\long\def\doTABLEbody[#1]#2\eTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody} -\long\def\doTABLEfoot[#1]#2\eTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot} +\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} -\long\def\doTABLEsection[#1]#2% - {\unexpanded\def\setupTBLsection{\getparameters[\@@tbl\@@tbl][#1]}% +\def\tabl_ntb_section[#1]#2% also used in tabl-nte + {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}% #2% - \let\setupTBLsection\relax} - -\let\pushTBL\relax -\let\popTBL \relax - -\newconstant\tblpass + \let\tabl_ntb_setup_section\relax} -\def\presetallTABLEparameters% each odd|even level / can be sped up but only once per table - {\executeifdefined{\@@rawtblprefix\v!start\v!each}\relax - \executeifdefined{\@@rawtblprefix\v!start\v!oddeven\TBLlevel}\relax - \executeifdefined{\@@rawtblprefix\v!start\number\TBLlevel}\relax} +\def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table + {\ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname + \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname + \fi + \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname % hm + \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname + \fi + \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname % hm + \csname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname + \fi} \unexpanded\def\bTABLE - {\dosingleempty\dobTABLE} + {\dosingleempty\tabl_ntb_table} -\def\dobTABLE[#1]% - {\pushTBL +\def\tabl_ntb_table[#1]% + {\tabl_ntb_table_push % box not here \bgroup - \TBLhead\emptytoks - \TBLnext\emptytoks - \TBLbody\emptytoks - \TBLfoot\emptytoks + \t_tabl_ntb_head\emptytoks + \t_tabl_ntb_next\emptytoks + \t_tabl_ntb_body\emptytoks + \t_tabl_ntb_foot\emptytoks \ifhmode\kern\zeropoint\fi % blocks \removeunwantedspaces: check this on icare handelingsschema \resetcharacteralign % new - \getparameters - [\@@tbl\@@tbl] - [\c!align={\v!right,\v!broad,\v!high},#1]% - \ifx\tbltblsetups\empty\else - \doprocesslocalsetups\tbltblsetups - \fi - \hsize\tbltbltextwidth + \setupcurrentnaturaltablelocal[\c!align={\v!right,\v!broad,\v!high},#1]% + \doifsomething{\naturaltablelocalparameter\c!setups}\doprocesslocalsetups{\naturaltablelocalparameter\c!setups}% + \doifelse{\naturaltablelocalparameter\c!textwidth}\v!local + {\hsize\availablehsize} + {\hsize\naturaltablelocalparameter\c!textwidth}% \processaction - [\tbltblsplit] + [\naturaltablelocalparameter\c!split] [ \v!yes=>\enableTBLbreaktrue, \v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue, \v!auto=>\ifinsidesplitfloat\enableTBLbreaktrue\fi] \processaction - [\tbltblheader] + [\naturaltablelocalparameter\c!header] [\v!repeat=>\multipleTBLheadstrue]% - \presetallTABLEparameters + \tabl_ntb_preset_parameters \processallactionsinset - [\tbltbloption] + [\naturaltablelocalparameter\c!option] [\v!stretch=>\autoTBLspreadtrue]% - \linewidth\tbltblrulethickness % needs to be frozen + \linewidth\naturaltablelocalparameter\c!rulethickness % needs to be frozen \dontcomplain - \currentcol\zerocount - \maximumrowspan\plusone - \maximumcol\zerocount - \maximumrow\zerocount + \c_tabl_ntb_running_col \zerocount + \c_tabl_ntb_maximum_col \zerocount + \c_tabl_ntb_maximum_row \zerocount + \c_tabl_ntb_maximum_row_span\plusone + \let\currentTABLErow \tabl_ntb_current_row + \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} -\unexpanded\def\dobTR{\dosingleempty\parseTR} -\unexpanded\def\dobTD{\dosingleempty\parseTD} -\unexpanded\def\dobTH{\dosingleempty\parseTH} -\unexpanded\def\dobTN{\dosingleempty\parseTN} +\def\tabl_ntb_current_row {\m_tabl_ntb_positive_row} +\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col} +\def\tabl_ntb_n_of_rows {\number\c_tabl_ntb_maximum_row} +\def\tabl_ntb_n_of_columns {\number\c_tabl_ntb_maximum_col} + +\let\currentTABLErow \!!zerocount +\let\currentTABLEcolumn\!!zerocount +\let\nofTABLErows \!!zerocount +\let\nofTABLEcolumns \!!zerocount + +\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 % permits \expanded{\bTD ... \eTD} @@ -758,302 +887,348 @@ \unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode {% tricky and dirty order -) - \doifsometokselse\TBLhead % slow, better a flag - {\the\TBLhead - \edef\noftblheadlines{\number\maximumrow}% - \doifsometokselse\TBLnext - {\the\TBLnext - \edef\noftblnextlines{\number\numexpr\maximumrow-\noftblheadlines\relax}}% - {\let\noftblnextlines\zerocount}% was 1 - \edef\noftblhdnxlines{\number\maximumrow}} - {\let\noftblheadlines\zerocount % was 1 - \let\noftblnextlines\zerocount - \let\noftblhdnxlines\zerocount}% - \the\TBLbody - \the\TBLfoot + \doifsometokselse\t_tabl_ntb_head % slow, better a flag + {\the\t_tabl_ntb_head + \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax + \doifsometokselse\t_tabl_ntb_next + {\the\t_tabl_ntb_next + \c_tabl_ntb_n_of_next_lines\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines\relax}% + {\c_tabl_ntb_n_of_next_lines\zerocount}% was 1 + \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row} + {\c_tabl_ntb_n_of_head_lines\zerocount % was 1 + \c_tabl_ntb_n_of_next_lines\zerocount + \c_tabl_ntb_n_of_hdnx_lines\zerocount}% + \the\t_tabl_ntb_body + \the\t_tabl_ntb_foot \removeunwantedspaces % only if hmode % finish cells - \dorecurse\maximumrow - {\row\recurselevel\relax - \dorecurse\maximumcol - {\col\recurselevel\relax - \doifnottbltag\row\col - {\xxcol\col - \xxrow\row - \xrow\row - \doloop - {\xcol\col - \doloop - {\doifelsetbltag\xrow\xcol \exitloop - {\advance\xcol\plusone - \ifnum\xcol>\maximumcol\relax \exitloop \fi}}% - \doifelsetbltag\xrow\xcol \exitloop - {\xxrow\xrow \xxcol\xcol \advance\xrow\plusone - \ifnum\xrow>\maximumrow \exitloop \fi}}% - \ifnum\xxrow>\maximumrow\xxrow\maximumrow\fi - \ifnum\xxcol>\maximumcol\xxcol\maximumcol\fi - \xxrow\numexpr\xxrow-\row+\plusone\relax - \xxcol\numexpr\xxcol-\col+\plusone\relax - \xrow\row - \dorecurse\xxrow - {\xcol\col \settblcol\xrow\xcol{\number\xxcol}% - \dorecurse\xxcol - {\lettbltag\xrow\xcol\tblnone \advance\xcol\plusone}% - \advance\xrow\plusone}% - \lettbltag\row\col\tblcell - \settblcol\row\col{\the\xxcol}% - \settblrow\row\col{\the\xxrow}% - \ifautoTBLemptycell - \edef\celltag{{\number\row}{\number\col}}% - \@EA\settbltxt\@EA\row\@EA\col\@EA{\@EA\handleTBLcell\celltag[]{\strut}}% - \fi}}}% + \tabl_ntb_loop_one % to be sure - \dorecurse\maximumrow - {\row\recurselevel\relax - \dorecurse\maximumcol - {\col\recurselevel\relax - \doiftblrow\row\col - {\scratchcounter\numexpr\maximumrow-\row+\plusone\relax - \ifnum\gettblrow\row\col>\scratchcounter - \settblrow\row\col{\the\scratchcounter}% - \fi}% - \lettblht\row\col\zeropoint - \lettblwd\row\col\zeropoint - \doifnottblcol\row\col{\lettblcol\row\col\zerocount}% - \doifnottbltag\row\col{\lettbltag\row\col\tblnone}}}% + \tabl_ntb_loop_two % check and do - \ifcase\maximumcol\else + \ifcase\c_tabl_ntb_maximum_col\else \startTBLprocessing - \begTBL - \dorecurse\maximumrow - {\bTBL - \row\recurselevel\relax - \dorecurse\maximumcol - {\col\recurselevel\relax - \normalexpanded{\noexpand\doTBL{\number\row}{\number\col}}}% - \eTBL}% + \tabl_ntb_table_start + \dorecurse\c_tabl_ntb_maximum_row + {\tabl_ntb_row_start + \c_tabl_ntb_current_row\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_col + {\c_tabl_ntb_current_col\recurselevel\relax + \normalexpanded{\tabl_ntb_cell{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}}% + \tabl_ntb_row_stop}% \removeunwantedspaces % only if hmode - \endTBL + \tabl_ntb_table_stop \stopTBLprocessing % wrong ! ! ! better to have an auto-offset-overlay - % \ifnum\TBLlevel>1 + % \ifnum\m_tabl_tbl_level>1 % \vskip-\strutdp % \fi \fi % tracing % \iftrue % \blank \tttf - % \dorecurse\maximumrow - % {\row\recurselevel\relax - % \dorecurse\maximumcol - % {\col\recurselevel\relax - % [r=\the\row,c=\the\col,h=\the\dimexpr\gettblht\row\col,w=\the\dimexpr\gettblwd\row\col]}% + % \dorecurse\c_tabl_ntb_maximum_row + % {\c_tabl_ntb_current_row\recurselevel\relax + % \dorecurse\c_tabl_ntb_maximum_col + % {\c_tabl_ntb_current_col\recurselevel\relax + % [r=\the\c_tabl_ntb_current_row,c=\the\c_tabl_ntb_current_col,h=\the\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col,w=\the\dimexpr\tabl_ntb_get_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col]}% % \par}% % \blank % \fi \egroup - \popTBL} + \tabl_ntb_table_pop} -\let\startTBLprocessing\relax -\let\stopTBLprocessing \relax +\def\tabl_ntb_loop_one + {\dorecurse\c_tabl_ntb_maximum_row{\tabl_ntb_loop_one_rows}} -\newcount\prelocatedTBLrows % \prelocateTBLrows{1000} may speed up large tables +\def\tabl_ntb_loop_one_rows + {\c_tabl_ntb_current_row\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_one_cells} -\def\bTBL{\tblrowtoks\emptytoks} -\def\eTBL{\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\the\tblrowtoks\endtblrow}}% - -\def\prelocateTBLerror - {\writestatus\m!system{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \number\prelocatedTBLrows)}} +\def\tabl_ntb_loop_one_cells + {\c_tabl_ntb_current_col\recurselevel\relax + \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else + \tabl_ntb_loop_one_cells_indeed + \fi} -\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway - {\dostepwiserecurse\prelocatedTBLrows{#1}\plusone{\expandafter\newtoks\csname tbl:\recurselevel\endcsname}% - \def\bTBL - {\ifnum\tblrow<\prelocatedTBLrows\relax - \@EA\let\@EA\tblrowtoks\csname tbl:\the\tblrow\endcsname\tblrowtoks\emptytoks +\def\tabl_ntb_loop_one_cells_indeed + {\c_tabl_ntb_current_col_two\c_tabl_ntb_current_col + \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row + \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row + \doloop + {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col + \doloop + {\ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname + \exitloop + \else + \advance\c_tabl_ntb_current_col_one\plusone + \ifnum\c_tabl_ntb_current_col_one>\c_tabl_ntb_maximum_col\relax + \exitloop + \fi + \fi}% + \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname + \exitloop \else - \prelocateTBLerror + \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row_one + \c_tabl_ntb_current_col_two\c_tabl_ntb_current_col_one + \advance\c_tabl_ntb_current_row_one\plusone + \ifnum\c_tabl_ntb_current_row_one>\c_tabl_ntb_maximum_row + \exitloop + \fi \fi}% - \def\eTBL - {\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\@EA\the\csname tbl:\the\tblrow\endcsname\endtblrow}}% - \global\prelocatedTBLrows#1\relax} + \ifnum\c_tabl_ntb_current_row_two>\c_tabl_ntb_maximum_row\c_tabl_ntb_current_row_two\c_tabl_ntb_maximum_row\fi + \ifnum\c_tabl_ntb_current_col_two>\c_tabl_ntb_maximum_col\c_tabl_ntb_current_col_two\c_tabl_ntb_maximum_col\fi + \c_tabl_ntb_current_row_two\numexpr\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone\relax + \c_tabl_ntb_current_col_two\numexpr\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone\relax + \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row + \dorecurse\c_tabl_ntb_current_row_two + {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col + \tabl_ntb_set_col\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one{\the\c_tabl_ntb_current_col_two}% + \dorecurse\c_tabl_ntb_current_col_two + {\tabl_ntb_let_tag\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_none + \advance\c_tabl_ntb_current_col_one\plusone}% + \advance\c_tabl_ntb_current_row_one\plusone}% + \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_cell + \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_col_two}% + \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row_two}% + \ifautoTBLemptycell + \normalexpanded + {\tabl_ntb_set_txt_process\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}% + {}{\strut}% + \fi} + +\def\tabl_ntb_loop_two + {\dorecurse\c_tabl_ntb_maximum_row\tabl_ntb_loop_two_rows} + +\def\tabl_ntb_loop_two_rows + {\c_tabl_ntb_current_row\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_two_cells} + +\def\tabl_ntb_loop_two_cells + {\c_tabl_ntb_current_col\recurselevel\relax + \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname + \scratchcounter\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone\relax + \ifnum\tabl_ntb_get_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col>\scratchcounter + \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\scratchcounter}% + \fi + \fi + \tabl_ntb_let_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint + \tabl_ntb_let_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint + \ifcsname\tabl_ntb_col_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else + \tabl_ntb_let_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zerocount + \fi + \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else + \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none + \fi} + +\let\startTBLprocessing\relax % public +\let\stopTBLprocessing \relax % public + +\newcount\c_tabl_prelocated_rows % \prelocateTBLrows{1000} may speed up large tables + +\def\tabl_ntb_row_start{\t_tabl_ntb_row\emptytoks} +\def\tabl_ntb_row_stop {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\t_tabl_ntb_row\tabl_ntb_row_align_stop}}} + +\def\tabl_ntb_prelocate_error + {\writestatus\m!system{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}} % \prelocateTBLrows{1000} % may speed up large tables +\installcorenamespace{naturaltabletok} + +\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 + {\ifnum\c_tabl_ntb_row<\c_tabl_prelocated_rows\relax + \expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks + \else + \tabl_ntb_prelocate_error + \fi}% + \def\tabl_ntb_row_stop + {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\tabl_ntb_row_align_stop}}}% + \global\c_tabl_prelocated_rows#1\relax} + % We use aligments to handle the empty (skipped) columns, so % that we don't have to (re|)|calculate these. -\def\skiptblcol - {\global\advance\tblcol\plusone} +\def\tabl_ntb_column_skip + {\global\advance\c_tabl_ntb_col\plusone} -\def\nexttblcol - {\global\advance\tblcol\plusone - \kern\tbltblcolumndistance - &} +\def\tabl_ntb_column_next + {\global\advance\c_tabl_ntb_col\plusone + \kern\naturaltablelocalparameter\c!columndistance + \aligntab} -\def\spantblcol +\def\tabl_ntb_column_span {\span} -\newcount\tblrow -\newcount\tblcol +\let\m_tabl_ntb_saved_row\!!zerocount +\let\m_tabl_ntb_saved_col\!!zerocount -\let\savedtblrow\!!zerocount -\let\savedtblcol\!!zerocount +\def\tabl_ntb_row_align_start + {\noalign{\tabl_ntb_row_align_reset}% + \tabl_ntb_column_next + \kern\dimexpr\naturaltablelocalparameter\c!leftmargindistance-\naturaltablelocalparameter\c!columndistance\relax} -\def\begintblrow - {\noalign - {\global\advance\tblrow\plusone - \global\tblcol\zerocount - \global\tblspn\zerocount}% - % \iftrue - % \bgroup\tbox{\tttf[\number\tblrow]}\egroup - % \fi - \nexttblcol - \kern\dimexpr\tbltblleftmargindistance-\tbltblcolumndistance\relax} +\unexpanded\def\tabl_ntb_row_align_reset + {\global\advance\c_tabl_ntb_row\plusone + \global\c_tabl_ntb_col\zerocount + \global\c_tabl_ntb_spn\zerocount} -\def\endtblrow - {\kern\dimexpr\tbltblrightmargindistance-\tbltblcolumndistance\relax +\unexpanded\def\tabl_ntb_row_align_stop + {\kern\dimexpr\naturaltablelocalparameter\c!rightmargindistance-\naturaltablelocalparameter\c!columndistance\relax \crcr \noalign {\nointerlineskip - \ifnum\tblrow>\noftblheadlines - \ifnum\gettblnob\tblrow=\zerocount + \ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines + \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount \allowbreak \fi \else \allowbreak % else no proper head split off \fi \bgroup % protect local vars - \@@tblsplitafter + \m_tabl_ntb_after_split \egroup \bgroup % protect local vars - \scratchcounter\numexpr\tblrow+\plusone\relax - \ifnum\scratchcounter>\noftblhdnxlines\relax - \ifnum\scratchcounter<\maximumrow\relax - \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}% + \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 + \doifsomething{\naturaltablelocalparameter\c!spaceinbetween} + {\blank[\naturaltablelocalparameter\c!spaceinbetween]}% \fi \fi \egroup}} -\def\begintbl - {\global\tblspn\zerocount - \global\tblcol\zerocount - \global\tblrow\zerocount - \global\advance\tblrow\minusone +\def\tabl_ntb_flush_content + {\the\everyTABLEpass + \global\c_tabl_ntb_spn\zerocount + \global\c_tabl_ntb_col\zerocount + \global\c_tabl_ntb_row\zerocount + \global\advance\c_tabl_ntb_row\minusone \tabskip\zeropoint \dostarttagged\t!table\empty \dostarttagged\t!tablerow\empty \appendtoks\dostoptagged\dostarttagged\t!tablerow\empty\to\everycr \halign\bgroup - \registerparoptions - % watch out: tagging the cell happens at the outer level (faster) -% \ignorespaces##\unskip&&\dostarttagged\t!tablecell\empty\ignorespaces##\unskip\dostoptagged\cr} % one too many - \ignorespaces##\unskip&&\ignorespaces##\unskip\cr} % one too many - -\def\endtbl - {\dostoptagged + \registerparoptions + % watch out: tagging the cell happens at the outer level (faster) + \ignorespaces\alignmark\alignmark\unskip + \aligntab\aligntab + \ignorespaces\alignmark\alignmark\unskip + \cr % one too many + \the\t_tabl_ntb + \dostoptagged \egroup \dostoptagged} -\setvalue{\tblnone TBL}#1#2% - {\spanTBL{#1}{#2}} - -\setvalue{\tblcell TBL}#1#2% - {\tblrowtoks\expandafter{\the\tblrowtoks\makeTBL #1 #2 }% space delimited -> less tokens - \spanTBL{#1}{#2}} - -\def\spanTBL#1#2% - {\scratchcounter\gettblcol{#1}{#2}\relax +\setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2% + {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax \ifnum\scratchcounter>\zerocount - \advance\scratchcounter \minusone - \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\spantblcol}}% - \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\skiptblcol}}% - \tblrowtoks\expandafter{\the\tblrowtoks\nexttblcol}% + \advance\scratchcounter\minusone + \ifnum\scratchcounter>\zerocount + \tabl_ntb_span + \fi + \t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_next} \fi} -\def\doTBL#1#2% - {\csname\gettbltag{#1}{#2}TBL\endcsname{#1}{#2}} +\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2% + {\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_pass #1 #2 }% space delimited -> less tokens + \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax + \ifnum\scratchcounter>\zerocount + \advance\scratchcounter\minusone + \ifnum\scratchcounter>\zerocount + \tabl_ntb_span + \fi + \t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_next} + \fi} -\def\begTBL - {\global\tblspn\zerocount - \global\tblrow\zerocount - \global\tblcol\zerocount - \tblpass\zerocount - \tbltoks\emptytoks} +\def\tabl_ntb_span + {\dorecurse\scratchcounter{\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_span}}% + \dorecurse\scratchcounter{\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_skip}}} -\newtoks\everyTABLEpass +\unexpanded\def\tabl_ntb_cell#1#2% + {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}} -\def\flushtbltoks - {\the\everyTABLEpass - \begintbl - \the\tbltoks - \endtbl} +\unexpanded\def\tabl_ntb_table_start + {\global\c_tabl_ntb_spn\zerocount + \global\c_tabl_ntb_row\zerocount + \global\c_tabl_ntb_col\zerocount + \c_tabl_tbl_pass\zerocount + \t_tabl_ntb\emptytoks} -\def\domakeTBLone#1 #2 % - {\gettbltxt{#1}{#2}}% +\def\tabl_ntb_pass_one#1 #2 % + {\tabl_ntb_get_txt{#1}{#2}}% -\def\domakeTBLtwo#1 #2 % meer in cellD - {\scratchdimen\zeropoint - \scratchcounter\tblcol - \!!counta\gettblcol{#1}{#2}\relax +\def\tabl_ntb_pass_two#1 #2 % meer in cellD + {\d_tabl_ntb_width\zeropoint + \scratchcounter\c_tabl_ntb_col + \!!counta\tabl_ntb_get_col{#1}{#2}\relax \dorecurse\!!counta - {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax - \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi + {\advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + +\naturaltablelocalparameter\c!columndistance + \ifnum\recurselevel<\!!counta + +\tabl_ntb_get_dis\scratchcounter + \fi + \relax \advance\scratchcounter\plusone}% - \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}% - \setbox\scratchbox\hbox{\gettbltxt{#1}{#2}}% - \settblht{#1}{#2}{\the\ht\scratchbox}% - \settblwd{#1}{#2}{\the\wd\scratchbox}% - \ifdim\ht\scratchbox>\gettblhei{#1}\relax - \settblhei{#1}{\the\ht\scratchbox}% + \advance\d_tabl_ntb_width-\naturaltablelocalparameter\c!columndistance\relax + \setbox\scratchbox\hbox{\tabl_ntb_get_txt{#1}{#2}}% + \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}% + \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}% + \ifdim\ht\scratchbox>\tabl_ntb_get_hei{#1}\relax + \tabl_ntb_set_hei{#1}{\the\ht\scratchbox}% \fi}% -\newcount\tablecellrows -\newcount\tablecellcolumns - -\def\domakeTBLthree#1 #2 % +\def\tabl_ntb_pass_three#1 #2 % {% height \dostarttagged\t!tablecell\empty - \!!counta \gettblcol{#1}{#2}\relax - \!!countb \gettblrow{#1}{#2}\relax - \!!heighta\gettblht {#1}{#2}\relax + \!!counta \tabl_ntb_get_col{#1}{#2}\relax + \!!countb \tabl_ntb_get_row{#1}{#2}\relax + \!!heighta\tabl_ntb_get_ht {#1}{#2}\relax \tablecellcolumns\!!counta % used later so don't adapt these \tablecellrows \!!countb % used later so don't adapt these - \scratchdimen\zeropoint - \ifnum\!!counta=\maximumcol\relax + \d_tabl_ntb_height\zeropoint + \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax % case: nc=maxcolumns \else \scratchcounter#1\relax \dorecurse\!!countb - {\advance\scratchdimen\gettblhei\scratchcounter + {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter \advance\scratchcounter\plusone}% - \ifdim\scratchdimen<\!!heighta\relax - \scratchdimen\!!heighta + \ifdim\d_tabl_ntb_height<\!!heighta\relax + \d_tabl_ntb_height\!!heighta \fi \fi - \edef\heightTBL{\the\scratchdimen}% % width - \scratchdimen\zeropoint - \scratchcounter\tblcol + \d_tabl_ntb_width\zeropoint + \scratchcounter\c_tabl_ntb_col \dorecurse\!!counta - {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax - \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi + {\advance\d_tabl_ntb_width\dimexpr + \tabl_ntb_get_wid\scratchcounter + +\naturaltablelocalparameter\c!columndistance + \ifnum\recurselevel<\!!counta + +\tabl_ntb_get_dis\scratchcounter + \fi + \relax \advance\scratchcounter\plusone}% - \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}% + \advance\d_tabl_ntb_width-\naturaltablelocalparameter\c!columndistance\relax % cell \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute \bgroup \dotagTABLEsignal % maybe we need to add some packaging in this case - \gettbltxt{#1}{#2}% + \tabl_ntb_get_txt{#1}{#2}% \egroup - \ifnum\!!counta=\maximumcol\relax + \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax % case: nc=maxcolumns \else - \scratchdimen\gettblhei{#1}% + \scratchdimen\tabl_ntb_get_hei{#1}% \setbox\scratchbox\hbox {\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}% \ht\scratchbox\scratchdimen \fi \dp\scratchbox\zeropoint - \edef\!!stringa{\gettblref{#1}{#2}}% + \edef\!!stringa{\tabl_ntb_get_ref{#1}{#2}}% \ifx\!!stringa\empty \box\scratchbox \else @@ -1061,108 +1236,103 @@ \fi \dostoptagged} % right spot -\def\inTBLcell#1#2% hm, do we need #1 #2 ? we use tblcol anyway +\def\tabl_tnb_cell_finalize {\doifnotinset\localwidth{\v!fit,\v!broad}% user set - {\scratchdimen\gettblaut\tblcol\relax + {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax \ifdim\localwidth>\scratchdimen - \settblaut\tblcol{\the\dimexpr\localwidth\relax}% - \fi}}% + \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}% + \fi}} -\def\endTBL +\def\tabl_ntb_table_stop {\setbox\scratchbox\hbox - {\localframed - [\@@tbl\@@tbl] - [\c!frame=\v!off,\c!background=,\c!align=\v!no] - {\strut}}% - \edef\minimalcellheight{\the\ht\scratchbox}% - \dorecurse\maximumcol - {\lettblaut\recurselevel\zeropoint + {\setupcurrentnaturaltablelocal[\c!frame=\v!off,\c!background=,\c!align=\v!no]% + \inheritednaturaltablelocalframed{\strut}}% + \edef\minimalcellheight{\the\ht\scratchbox}% not used + \dorecurse\c_tabl_ntb_maximum_col + {\tabl_ntb_let_aut\recurselevel\zeropoint % new - \xcol\recurselevel\relax - \dorecurse\maximumrow - {\lettblwd\recurselevel\xcol\zeropoint - \lettblht\recurselevel\xcol\zeropoint}% + \c_tabl_ntb_current_col_one\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_row + {\tabl_ntb_let_wd\recurselevel\c_tabl_ntb_current_col_one\zeropoint + \tabl_ntb_let_ht\recurselevel\c_tabl_ntb_current_col_one\zeropoint}% % till here - \lettblwid\recurselevel\zeropoint - \lettbldis\recurselevel\zeropoint}% - \dorecurse\maximumrow - {\lettblhei\recurselevel\maxdimen}% - \tblpass\plusone - \let\makeTBL\domakeTBLone - \let\handleTBLcell\dohandleTBLcellA - \setbox0\vbox{\settrialtypesetting \flushtbltoks}% -% \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}% - \lettbldis\maximumcol\zeropoint + \tabl_ntb_let_wid\recurselevel\zeropoint + \tabl_ntb_let_dis\recurselevel\zeropoint}% + \dorecurse\c_tabl_ntb_maximum_row + {\tabl_ntb_let_hei\recurselevel\maxdimen}% + \c_tabl_tbl_pass\plusone + \let\tabl_ntb_pass\tabl_ntb_pass_one + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a + \setbox0\vbox{\settrialtypesetting \tabl_ntb_flush_content}% + \tabl_ntb_let_dis\c_tabl_ntb_maximum_col\zeropoint \ifautoTBLspread % experimental, stretch non fixed cells to \hsize - \checktblwidthsone % trial run - \checktblwidthstwo % real run - \stretchtblwidths - \let\handleTBLcell\dohandleTBLcellB - \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}% + \tabl_ntb_check_widths_one % trial run + \tabl_ntb_check_widths_two % real run + \tabl_ntb_stretch_widths + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b + \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}% \else\ifdim\wd0>\hsize \ifautoTBLhsize - \checktblwidthsone % trial run - \checktblwidthstwo % real run - \let\handleTBLcell\dohandleTBLcellB - \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}% + \tabl_ntb_check_widths_one % trial run + \tabl_ntb_check_widths_two % real run + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b + \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}% \fi - \else\ifautoTBLrowspan\ifnum\maximumrowspan>1 % max ? + \else\ifautoTBLrowspan\ifnum\c_tabl_ntb_maximum_row_span>1 % max ? % added jan 2002 because nx=* did no longer work \edef\savedhsize{\the\hsize}% \hsize\wd0\relax % new per 17/04/2006 - \checktblwidthsone % trial run - \checktblwidthstwo % real run + \tabl_ntb_check_widths_one % trial run + \tabl_ntb_check_widths_two % real run \hsize\savedhsize % - \let\handleTBLcell\dohandleTBLcellC - \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}% + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_c + \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}% \fi\fi\fi\fi - \let\handleTBLcell\dohandleTBLcellD - \tblpass\plustwo - \let\makeTBL\domakeTBLtwo - \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}% - \checktblheightsone - \checktblheightstwo - \let\handleTBLcell\dohandleTBLcellE - \tblpass\plusthree - \let\makeTBL\domakeTBLthree - \ifnum\TBLlevel>\plusone - \@EA\notsplittblbox + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_d + \c_tabl_tbl_pass\plustwo + \let\tabl_ntb_pass\tabl_ntb_pass_two + \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}% + \tabl_ntb_check_heights_one + \tabl_ntb_check_heights_two + \let\tabl_ntb_cell_process\tabl_ntb_cell_process_e + \c_tabl_tbl_pass\plusthree + \let\tabl_ntb_pass\tabl_ntb_pass_three + \ifnum\m_tabl_tbl_level>\plusone + \expandafter\tabl_tbl_split_nop \else\ifenableTBLbreak - \@EAEAEA\splittblbox + \doubleexpandafter\tabl_tbl_split_yes \else - \@EAEAEA\notsplittblbox - \fi\fi{\flushtbltoks}} + \doubleexpandafter\tabl_tbl_split_nop + \fi\fi{\tabl_ntb_flush_content}} -\def\stretchtblwidths % more variants, e.g. a max to \dimend - {\ifcase\maximumcol\else % else division by zero +\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend + {\ifcase\c_tabl_ntb_maximum_col\else % else division by zero \!!dimend\zeropoint \!!dimene\hsize - \dorecurse\maximumcol - {\advance\!!dimend\dimexpr\gettblwid\recurselevel+\tbltblcolumndistance\relax - \advance\!!dimene-\gettbldis\recurselevel}% - \advance\!!dimend\dimexpr-\tbltblcolumndistance+\tbltblleftmargindistance+\tbltblrightmargindistance\relax + \dorecurse\c_tabl_ntb_maximum_col + {\advance\!!dimend\dimexpr\tabl_ntb_get_wid\recurselevel+\naturaltablelocalparameter\c!columndistance\relax + \advance\!!dimene-\tabl_ntb_get_dis\recurselevel}% + \advance\!!dimend\dimexpr-\naturaltablelocalparameter\c!columndistance+\naturaltablelocalparameter\c!leftmargindistance+\naturaltablelocalparameter\c!rightmargindistance\relax % distribute width (stretch) \ifdim\!!dimend<\!!dimene \advance\!!dimend-\!!dimene \!!dimend-\!!dimend - \divide\!!dimend\maximumcol - \dorecurse\maximumcol - {\settblwid\recurselevel{\the\dimexpr\gettblwid\recurselevel+\!!dimend\relax}}% + \divide\!!dimend\c_tabl_ntb_maximum_col + \dorecurse\c_tabl_ntb_maximum_col + {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel+\!!dimend\relax}}% \fi \fi} -\newbox\finaltblbox - -\def\notsplittblbox#1% - {\setbox\finaltblbox\vbox{#1}% - \postprocessTABLEbox\finaltblbox +\def\tabl_tbl_split_nop#1% + {\setbox\b_tabl_ntb_final\vbox{#1}% + \postprocessTABLEbox\b_tabl_ntb_final \beforeTABLEbox - \box\finaltblbox + \box\b_tabl_ntb_final \afterTABLEbox} -\def\splittblbox#1% +\def\tabl_tbl_split_yes % #1 {\ifinsidesplitfloat \donetrue \else\ifinsidefloat @@ -1171,33 +1341,33 @@ \donetrue \fi\fi \ifdone - \executeifdefined{dosplittblbox\tbltblsplitmethod}\dosplittblbox{#1}% + \expandafter\tabl_ntb_split_box \else - \notsplittblbox{#1}% + \expandafter\tabl_tbl_split_nop \fi} \newbox\TABLEsplitbox % public, don't change \let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox -\def\dosplittblbox#1% +\def\tabl_ntb_split_box#1% {\resettsplit \def\tsplitminimumfreelines{2}% - \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\tbltblsplitoffset\relax}% + \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax}% \def\tsplitbeforeresult {\beforeTABLEsplitbox}% \def\tsplitafterresult {\afterTABLEsplitbox}% - \def\tsplitafter {\@@tblsplitafter}% + \def\tsplitafter {\m_tabl_ntb_after_split}% \setbox\tsplitcontent\vbox{#1}% \ifmultipleTBLheads - \dorecurse\noftblheadlines + \dorecurse\c_tabl_ntb_n_of_head_lines {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight \setbox\tsplithead\vbox{\unvcopy\tsplithead\unvcopy\scratchbox}}% - \dorecurse\noftblnextlines + \dorecurse\c_tabl_ntb_n_of_next_lines {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight \setbox\tsplitnext\vbox{\unvcopy\tsplitnext\unvcopy\scratchbox}}% \fi - \doifsomething\tbltblspaceinbetween - {\def\tsplitinbetween{\blank[\tbltblspaceinbetween]}}% + \doifsomething{\naturaltablelocalparameter\c!spaceinbetween} + {\def\tsplitinbetween{\blank[\naturaltablelocalparameter\c!spaceinbetween]}}% \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\tsplitresult}}% \handletsplit} @@ -1211,22 +1381,22 @@ \let\beforeTABLEbox \relax \let\afterTABLEbox \relax -\def\checktblwidthsone{\dochecktblwidths0} % 0 = trial run -\def\checktblwidthstwo{\dochecktblwidths1} % 1 = real run +\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed0} % 0 = trial run +\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed1} % 1 = real run -\def\dochecktblwidths#1% - {\iftraceTABLE\showtblwids{B#1}\fi +\def\tabl_ntb_check_widths_indeed#1% + {\iftraceTABLE\tabl_ntb_show_widths{B#1}\fi \!!counta\zerocount - \!!dimena\dimexpr\hsize-\tbltblleftmargindistance-\tbltblrightmargindistance-\tbltblcolumndistance\relax - \dorecurse\maximumcol - {\scratchdimen\gettblaut\recurselevel\relax - \advance\!!dimena-\gettbldis\recurselevel\relax + \!!dimena\dimexpr\hsize-\naturaltablelocalparameter\c!leftmargindistance-\naturaltablelocalparameter\c!rightmargindistance-\naturaltablelocalparameter\c!columndistance\relax + \dorecurse\c_tabl_ntb_maximum_col + {\scratchdimen\tabl_ntb_get_aut\recurselevel\relax + \advance\!!dimena-\tabl_ntb_get_dis\recurselevel\relax \ifdim\scratchdimen>\zeropoint\relax \advance\!!dimena -\scratchdimen \else - \scratchdimen\gettblwid\recurselevel\relax - \ifdim\scratchdimen>\tbltblmaxwidth\relax - \ifcase#1\else\lettblwid\recurselevel\zeropoint\fi + \scratchdimen\tabl_ntb_get_wid\recurselevel\relax + \ifdim\scratchdimen>\naturaltablelocalparameter\c!maxwidth\relax + \ifcase#1\else\tabl_ntb_let_wid\recurselevel\zeropoint\fi \advance\!!counta \plusone \else \ifdim\scratchdimen>\zeropoint\relax @@ -1239,163 +1409,157 @@ \fi \fi}% \ifcase\!!counta \else \divide\!!dimena \!!counta \fi - \dorecurse\maximumcol - {\scratchdimen\gettblwid\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_col + {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax \ifcase#1\relax \ifdim\scratchdimen<\!!dimena % take natural width - \settblaut\recurselevel{\the\scratchdimen}% + \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}% \fi \else \ifdim\scratchdimen=\zeropoint % auto set width - \settblwid\recurselevel{\the\!!dimena}% + \tabl_ntb_set_wid\recurselevel{\the\!!dimena}% \fi \fi}% - \iftraceTABLE\showtblwids{E#1}\fi} - -\newcount\xrowTBL -\newcount\xcolTBL -\newcount\xxrowTBL + \iftraceTABLE\tabl_ntb_show_widths{E#1}\fi} -% dikke arg naar recurse wegwerken - -\def\dochecktblheightsone - {\!!countb\gettblrow\xrowTBL\xcolTBL\relax +\def\tabl_ntb_check_heights_one_indeed + {\!!countb\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax % check row span \ifnum\!!countb>\plusone % current height in row - \dimen0=\gettblht\xrowTBL\xcolTBL + \dimen0=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three % find nearest height in row \dimen2=\zeropoint - \dorecurse\maximumcol - {\ifnum\recurselevel=\xcolTBL\else - \doiftblrow\xrowTBL\recurselevel - {\!!countc=\gettblrow\xrowTBL\recurselevel\relax - \ifnum\!!countc=\plusone - \dimen4=\gettblht\xrowTBL\recurselevel\relax - \ifdim\dimen2<\dimen4 - \dimen2=\dimen4 - \fi - \fi}% + \dorecurse\c_tabl_ntb_maximum_col + {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else + \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\recurselevel\endcsname + \!!countc=\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax + \ifnum\!!countc=\plusone + \dimen4=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\recurselevel\relax + \ifdim\dimen2<\dimen4 + \dimen2=\dimen4 + \fi + \fi + \fi \fi}% - \xxrowTBL\xrowTBL + \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three % calculate cummulative height \dimen4=\dimen2 - \!!countc\xrowTBL + \!!countc\c_tabl_ntb_current_row_three \advance\!!countc\minusone \dorecurse\!!countb - {\ifnum\xxrowTBL=\xrowTBL\else - \advance\dimen4 \gettblhei\xxrowTBL + {\ifnum\c_tabl_ntb_current_row_four=\c_tabl_ntb_current_row_three\else + \advance\dimen4 \tabl_ntb_get_hei\c_tabl_ntb_current_row_four \fi \ifnum\recurselevel=\!!countb\else - \settblnob\!!countc + \tabl_ntb_set_nob\!!countc \advance\!!countc\plusone \fi - \advance\xxrowTBL\plusone}% + \advance\c_tabl_ntb_current_row_four\plusone}% % distribute overshoot equally \ifdim\dimen2>\zeropoint % new: test on natural-003 \ifdim\dimen4<\dimen0 \advance\dimen0 -\dimen4 \divide\dimen0 \!!countb - \xxrowTBL\xrowTBL - \settblhei\xrowTBL{\the\dimen2}% + \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three + \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}% \dorecurse\!!countb - {\dorecurse\maximumcol - {\ifnum\recurselevel=\xcolTBL\else - \scratchdimen\dimexpr\gettblht\xxrowTBL\recurselevel+\dimen0\relax - \settblht\xxrowTBL\recurselevel{\the\scratchdimen}% - \ifdim\gettblhei\xxrowTBL<\scratchdimen - \settblhei\xxrowTBL{\the\scratchdimen}% + {\dorecurse\c_tabl_ntb_maximum_col + {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else + \scratchdimen\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\recurselevel+\dimen0\relax + \tabl_ntb_set_ht\c_tabl_ntb_current_row_four\recurselevel{\the\scratchdimen}% + \ifdim\tabl_ntb_get_hei\c_tabl_ntb_current_row_four<\scratchdimen + \tabl_ntb_set_hei\c_tabl_ntb_current_row_four{\the\scratchdimen}% \fi \fi}% - \advance\xxrowTBL\plusone}% + \advance\c_tabl_ntb_current_row_four\plusone}% \else\ifdim\dimen4>\dimen0 \iftightTBLrowspan - \settblhei\xrowTBL{\the\dimen2}% + \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}% \fi \fi\fi \fi \fi} -\def\checktblheightsone - {\dorecurse\maximumrow - {\xrowTBL\recurselevel\relax - \dorecurse\maximumcol - {\xcolTBL\recurselevel\relax - \doiftblrow\xrowTBL\xcolTBL\dochecktblheightsone}}} -\def\checktblheightstwo +\def\tabl_ntb_check_heights_one + {\dorecurse\c_tabl_ntb_maximum_row + {\c_tabl_ntb_current_row_three\recurselevel\relax + \dorecurse\c_tabl_ntb_maximum_col + {\c_tabl_ntb_current_col_three\recurselevel\relax + \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\endcsname + \tabl_ntb_check_heights_one_indeed + \fi}}} + +\def\tabl_ntb_check_heights_two {} -\def\showtblwids#1% +\def\tabl_ntb_show_widths#1% {\vbox - {\forgetall\tttf[#1]\dorecurse\maximumcol - {\scratchdimen\gettblwid\recurselevel\relax + {\forgetall\tttf[#1]\dorecurse\c_tabl_ntb_maximum_col + {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax [\recurselevel:\the\scratchdimen]}}} -\def\TBLcharalign - {\doifelse\tbltblaligncharacter\v!yes - \doTBLcharalign\gobbleoneargument} +\def\tabl_ntb_char_align + {\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes + \tabl_ntb_char_align_indeed\gobbleoneargument} -\long\def\doTBLcharalign#1#2% column data +\def\tabl_ntb_char_align_indeed#1#2% column data {\edef\alignmentclass{#1}% - \edef\alignmentcharacter{\tbltblalignmentcharacter}% - \ifcase\tblpass\or + \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}% + \ifcase\c_tabl_tbl_pass\or \setfirstpasscharacteralign\checkalignment{#2}% {\strut#2\unskip}% \fi % force hsize, so always a second \setsecondpasscharacteralign \checkalignment{#2}% {\strut#2\unskip}% \ignorespaces} -% new, needed for icare first col of 'doeltabel', experimental - -\long\def\dohandleTBLcellA#1#2[#3]#4% grouping added ! ! ! +\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! ! {\bgroup - \setupTBLcell{#1}{#2}% + \tabl_ntb_setup_cell{#1}{#2}% \setbox\scratchbox\hbox - {\scratchdimen\tbltbldistance\relax - \ifdim\scratchdimen>\gettbldis{#2}\relax - \settbldis{#2}{\the\scratchdimen}% + {\scratchdimen\naturaltablelocalparameter\c!distance\relax + \ifdim\scratchdimen>\tabl_ntb_get_dis{#2}\relax + \tabl_ntb_set_dis{#2}{\the\scratchdimen}% \fi - \localframed - [\@@tbl\@@tbl] - [#3,\c!background=,\c!frame=\v!off]% 25% faster - {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL\inTBLcell{#1}{#2}}}% - \scratchdimen\gettblwid\tblcol\relax + \setupcurrentnaturaltablelocal[#3,\c!background=,\c!frame=\v!off]% 25% faster + \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop\tabl_tnb_cell_finalize}}% + \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax \ifdim\wd\scratchbox>\scratchdimen \ifsqueezeTBLspan \ifautosqueezeTBLspan - \doifinsetelse\tbltblwidth{\v!fit,\v!fixed,\v!broad,\v!local} + \doifinsetelse{\naturaltablelocalparameter\c!width}{\v!fit,\v!fixed,\v!broad,\v!local} \donetrue \donefalse \else \donetrue \fi \ifdone % brr, 0 - \ifnum\number\gettblcol{#1}{#2}>\plusone \settblspn\tblcol\fi + \ifnum\tabl_ntb_get_col{#1}{#2}>\plusone \tabl_ntb_set_spn\c_tabl_ntb_col\fi \fi \fi - \doifelsetblspn\tblcol + \tabl_ntb_spn_doifelse\c_tabl_ntb_col \donothing - {\ifdim\gettblwid\tblcol<\wd\scratchbox - \settblwid\tblcol{\the\wd\scratchbox}% + {\ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox + \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}% \fi}% auto set \fi - \scratchcounter\numexpr\tblrow+\plusone\relax - \scratchdimen\gettblhei\scratchcounter\relax + \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax + \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax \ifdim\ht\scratchbox<\scratchdimen - \settblhei\scratchcounter{\the\ht\scratchbox}% auto set + \tabl_ntb_set_hei\scratchcounter{\the\ht\scratchbox}% auto set \fi - \settblht{#1}{#2}{\the\ht\scratchbox}% - \settblwd{#1}{#2}{\the\wd\scratchbox}% + \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}% + \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}% \ifautoTBLcheckwidth \ifdim\wd\scratchbox<.75\hsize % fuzzy guess \ifdim\ht\scratchbox>2\openlineheight % honor width since this - \scratchdimen\gettblaut\tblcol\relax % can be a figure or so + \scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax % can be a figure or so \ifdim\scratchdimen=\zeropoint % side effect: when width is set to 0pt, % we can force a span that fits the sum of spans widths - \settblaut\tblcol{\the\scratchdimen}% + \tabl_ntb_set_aut\c_tabl_ntb_col{\the\scratchdimen}% \else\ifdim\wd\scratchbox>\scratchdimen % unless span - \settblaut\tblcol{\the\wd\scratchbox}% + \tabl_ntb_set_aut\c_tabl_ntb_col{\the\wd\scratchbox}% % to be translated \writestatus\m!TABLE {no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}% @@ -1404,155 +1568,102 @@ \fi \fi \setbox2\emptyhbox - \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox + \wd2\wd\scratchbox + \ht2\ht\scratchbox + \dp2\dp\scratchbox \box2 \egroup} -\long\def\dohandleTBLcellBC#1#2#3[#4]#5% +\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5% {\setbox\scratchbox\hbox - {\setupTBLcell{#2}{#3}% - \localframed - [\@@tbl\@@tbl] - [#4,#1,\c!frame=\v!off,\c!background=] - {\bTBLCELL#5\eTBLCELL}}% + {\tabl_ntb_setup_cell{#2}{#3}% + \setupcurrentnaturaltablelocal[#4,#1,\c!frame=\v!off,\c!background=]% + \inheritednaturaltablelocalframed{\tabl_tnb_cell_start#5\tabl_tnb_cell_stop}}% \setbox2\emptyhbox - \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox + \wd2\wd\scratchbox + \ht2\ht\scratchbox + \dp2\dp\scratchbox \ifautoTBLrowspan - \scratchcounter\numexpr\tblrow+\plusone\relax - \doiftblrow\scratchcounter\tblcol - {\scratchdimen\gettblhei\scratchcounter\relax % moved inside test - \ifnum\gettblrow\scratchcounter\tblcol>\plusone \ifdim\ht\scratchbox>\scratchdimen - \scratchdimen-\scratchdimen \advance\scratchdimen -\ht\scratchbox - \ht2\scratchdimen - \fi \fi}% + \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax + \ifcsname\tabl_ntb_row_pattern\scratchcounter\c_tabl_ntb_col\endcsname + \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax + \ifnum\tabl_ntb_get_row\scratchcounter\c_tabl_ntb_col>\plusone + \ifdim\ht\scratchbox>\scratchdimen + \ht2\dimexpr-\scratchdimen-\ht\scratchbox\relax + \fi + \fi + \fi \fi \box2 } -\long\def\dohandleTBLcellB#1#2[#3]#4% - {\scratchdimen\gettblaut\tblcol\relax +\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4% + {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax \ifdim\scratchdimen>\zeropoint\relax - \let\tblwidthkey\c!width - \edef\tblwidth{\the\scratchdimen}% \else - \scratchdimen\gettblwid\tblcol\relax + \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax \ifdim\scratchdimen>\zeropoint\relax - \ifnum\gettblcol{#1}{#2}=\maximumcol\relax + \ifnum\tabl_ntb_get_col{#1}{#2}=\c_tabl_ntb_maximum_col\relax \scratchdimen\hsize \fi - \let\tblwidthkey\c!width - \edef\tblwidth{\the\scratchdimen}% - \else - \let\tblwidthkey\s!unknown - \let\tblwidth\zeropoint \fi \fi - \dohandleTBLcellBC{\tblwidthkey=\tblwidth}{#1}{#2}[#3]{\TBLcharalign{#2}{#4}}} + \normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}% + {#1}{#2}[#3]{\tabl_ntb_char_align{#2}{#4}}} -\long\def\dohandleTBLcellC - {\dohandleTBLcellBC{}} +\unexpanded\def\tabl_ntb_cell_process_c + {\tabl_ntb_cell_process_b_c{}} -\long\def\dohandleTBLcellD#1#2[#3]#4% - {\setupTBLcell{#1}{#2}% +\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4% + {\tabl_ntb_setup_cell{#1}{#2}% \bgroup - \localframed - [\@@tbl\@@tbl] - [#3,\c!width=\widthTBL,\c!background=,\c!frame=\v!off]% 25% faster - {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}% + \setupcurrentnaturaltablelocal[#3,\c!width=\d_tabl_ntb_width,\c!background=,\c!frame=\v!off]% 25% faster + \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop}% \egroup} -\long\def\dohandleTBLcellE#1#2[#3]#4% - {\setupTBLcell{#1}{#2}% - \getparameters[\@@tbl\@@tbl][#3]% to get the color right, the way we +\unexpanded\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 - [\tbltblcolor] % as well as permits local colors to take precedence - {\ifdim\heightTBL=\zeropoint\relax % case: nc=maxcolumns - \localframed - [\@@tbl\@@tbl] - [\c!color=,\c!width=\widthTBL] - {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}% + [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence + {\ifdim\d_tabl_ntb_height=\zeropoint\relax % case: nc=maxcolumns + \setupcurrentnaturaltablelocal[\c!color=,\c!width=\d_tabl_ntb_width]% \else - \localframed - [\@@tbl\@@tbl] - [\c!color=,\c!width=\widthTBL,\c!height=\heightTBL] - {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}% - \fi}% - \hskip\gettbldis{#2}} - -\presetlocalframed % todo: tableparameter etc - [\@@tbl\@@tbl] - -\setupTABLE [% - \c!frameoffset=.5\linewidth, - \c!backgroundoffset=\v!frame, - \c!framecolor=\s!black, - \c!width=\v!fit, - \c!height=\v!fit, - \c!autowidth=\v!yes, - \c!rulethickness=\linewidth, - \c!strut=\v!yes, - \c!autostrut=\v!no, - % - \c!color=, - \c!style=, - \c!headstyle=\v!bold, - \c!headcolor=, - \c!aligncharacter=\v!no, - \c!alignmentcharacter={,}, - \c!option=, % \v!stretch - \c!header=, - \c!spaceinbetween=, - \c!maxwidth=8em, - \c!textwidth=\hsize, - \c!split=\v!auto, - \c!splitoffset=0pt, - \c!distance=\zeropoint, % individual column - \c!columndistance=\zeropoint, % each column (whole table) - \c!leftmargindistance=\zeropoint, % whole table - \c!rightmargindistance=\zeropoint,% whole table - \c!left=, - \c!right=, - \c!setups=, - \c!splitmethod=a% -] - -%D We have already prepared the previous macros for nesting, -%D so we only have to pop in the right ones: - -%D New: - -\def\pushTBLparameters - {\globalpushmacro\TBLlevel - \ifcase\tblpass - % we're just after \bTABLE - \else\ifnum\TBLlevel>\zerocount - \doglobal\increment\TBLlevel\relax - \fi\fi} - -\def\popTBLparameters - {\globalpopmacro\TBLlevel} - -\def\pushTBL - {\ifnum\TBLlevel=\zerocount - \global\advance\currenttbl\plusone - \fi - \doglobal\increment\TBLlevel\relax - \ifnum\TBLlevel>\plusone - \resetallTABLEparameters - % we need a proper count push/pop - \xdef\savedtblrow{\the\tblrow}\globalpushmacro\savedtblrow - \xdef\savedtblcol{\the\tblcol}\globalpushmacro\savedtblcol - \else - \global\intabletrue - \fi} - -\def\popTBL - {\ifnum\TBLlevel>\plusone - \globalpopmacro\savedtblrow\global\tblrow\savedtblrow - \globalpopmacro\savedtblcol\global\tblcol\savedtblcol - \else - \global\intablefalse - \fi - \doglobal\decrement\TBLlevel\relax} + \setupcurrentnaturaltablelocal[\c!color=,\c!width=\d_tabl_ntb_width,\c!height=\d_tabl_ntb_height]% + \fi + \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop}}% + \hskip\tabl_ntb_get_dis{#2}} + +\setupTABLE + [\c!frameoffset=.5\linewidth, + \c!backgroundoffset=\v!frame, + \c!framecolor=\s!black, + \c!width=\v!fit, + \c!height=\v!fit, + \c!autowidth=\v!yes, + \c!rulethickness=\linewidth, + \c!strut=\v!yes, + \c!autostrut=\v!no, + % + \c!color=, + \c!style=, + \c!headstyle=\v!bold, + \c!headcolor=, + \c!aligncharacter=\v!no, + \c!alignmentcharacter={,}, + \c!option=, % \v!stretch + \c!header=, + \c!spaceinbetween=, + \c!maxwidth=8\emwidth, + \c!textwidth=\v!local, % was \hsize + \c!split=\v!auto, + \c!splitoffset=\zeropoint, + \c!distance=\zeropoint, % individual column + \c!columndistance=\zeropoint, % each column (whole table) + \c!leftmargindistance=\zeropoint, % whole table + \c!rightmargindistance=\zeropoint,% whole table + \c!left=, + \c!right=, + \c!setups=] % \bgroup % \setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}] @@ -1570,23 +1681,21 @@ \newconditional\resetTABLEmode \settrue\resetTABLEmode -\def\resetallTABLEparameters% moet genest wel werken - {\ifnum\TBLlevel>\plusone % in ieder geval +\def\tabl_ntb_parameters_reset + {\ifnum\m_tabl_tbl_level>\plusone % in ieder geval \ifconditional\resetTABLEmode -% \presetlocalframed % breedte hoogte diepte offset -% [\@@tbl\@@tbl]% % achtergrond, achtergrondraster, achtergrondkleur % not ok yet - \setupTABLE [% - \c!frameoffset=.5\linewidth, + \setupTABLE + [\c!frameoffset=.5\linewidth, \c!backgroundoffset=\v!frame, \c!framecolor=\s!black, \c!width=fit, \c!height=fit, -\c!autowidth=\v!yes, -% \c!rulethickness=\linewidth, + \c!autowidth=\v!yes, + % \c!rulethickness=\linewidth, \c!strut=\v!no, -\c!strut=\v!yes, % needed for mathml, but ... maybe we need another resetTABLEmode -\c!autostrut=\v!no, + \c!strut=\v!yes, % needed for mathml, but ... maybe we need another resetTABLEmode + \c!autostrut=\v!no, \c!color=, \c!style=, \c!headstyle=, @@ -1611,21 +1720,22 @@ % \bTRs[xx] \bTD oeps \eTD \bTD oeps \eTD \eTRs % \eTABLE +\installcorenamespace{naturaltablesetup} + \unexpanded\def\defineTABLEsetup - {\dodoubleargument\dodefineTABLEsetup} + {\dodoubleargument\tabl_ntb_define_setup} + +\def\tabl_ntb_define_setup[#1][#2]% + {\setvalue{\??naturaltablesetup#1}{#2}} -\def\dodefineTABLEsetup[#1][#2]% - {\setvalue{\@@tbl:set:#1}{#2}} +\let\eTDs\relax +\let\eTRs\relax -\long\def\bTDs[#1]#2\eTDs - {\doifdefinedelse{\@@tbl:set:#1} - {\@EA\@EA\@EA\bTD\@EA\@EA\@EA[\csname\@@tbl:set:#1\endcsname]#2\eTD} - {\bTD[]#2\eTD}} +\unexpanded\def\bTDs[#1]#2\eTDs + {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD} -\long\def\bTRs[#1]#2\eTRs - {\doifdefinedelse{\@@tbl:set:#1} - {\@EA\@EA\@EA\bTR\@EA\@EA\@EA[\csname\@@tbl:set:#1\endcsname]#2\eTR} - {\bTR[]#2\eTR}} +\unexpanded\def\bTRs[#1]#2\eTRs + {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR} \protect \endinput diff --git a/tex/context/base/tabl-nte.mkiv b/tex/context/base/tabl-nte.mkiv index 08ab34f0f..4a9774cb0 100644 --- a/tex/context/base/tabl-nte.mkiv +++ b/tex/context/base/tabl-nte.mkiv @@ -28,7 +28,7 @@ %D %D Let us start with the original macros: %D -%D \starttyping +%D \startbuffer %D \bTABLE %D \bTR %D \bTD Text 1 \eTD @@ -39,65 +39,72 @@ %D \bTD Text 4 \eTD %D \eTR %D \eTABLE -%D \stoptyping +%D \stopbuffer +%D +%D \typebuffer \getbuffer %D %D Watch how the new macros use less code: %D -%D \starttyping +%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 \stoptyping +%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. -\def\startTABLE - {\dosingleempty\dostartTABLE} +\newconditional\c_tabl_nte_in_nc -\def\dostartTABLE[#1]% +\unexpanded\def\startTABLE + {\dosingleempty\tabl_nte_start} + +\def\tabl_nte_start[#1]% {\bgroup \bTABLE[#1]% - \let\NC\doTABLENC - \let\NR\doTABLENR + \let\NC\tabl_nte_start_nc + \let\NR\tabl_nte_start_nr \let\bTR\relax \let\bTD\relax \let\bTH\relax \let\bTN\relax} -\def\stopTABLE +\unexpanded\def\stopTABLE {\eTABLE \egroup} -\newconditional\inTABLEnc - -\unexpanded\def\doTABLENR +\unexpanded\def\tabl_nte_start_nr {\eTR - \setfalse\inTABLEnc} + \setfalse\c_tabl_nte_in_nc} -\unexpanded\def\doTABLENC - {\futurelet\next\dodoTABLENC} +\unexpanded\def\tabl_nte_start_nc + {\futurelet\next\tabl_nte_start_nc_indeed} -\def\dodoTABLENC - {\ifx\next\doTABLENR \else - \expandafter\dododoTABLENC +\def\tabl_nte_start_nc_indeed + {\ifx\next\tabl_nte_start_nr \else + \expandafter\tabl_nte_start_nc_finish \fi} -\long\def\dododoTABLENC#1\NC - {\ifconditional\inTABLEnc\else\settrue\inTABLEnc\dobTR[]\fi - \dobTD#1\eTD\NC} +\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: -\unexpanded\def\startTABLEhead{\dosingleempty\dostartTABLEhead} \let\stopTABLEhead\relax -\unexpanded\def\startTABLEnext{\dosingleempty\dostartTABLEnext} \let\stopTABLEnext\relax -\unexpanded\def\startTABLEbody{\dosingleempty\dostartTABLEbody} \let\stopTABLEbody\relax -\unexpanded\def\startTABLEfoot{\dosingleempty\dostartTABLEfoot} \let\stopTABLEfoot\relax +\unexpanded\def\startTABLEhead{\dosingleempty\tabl_nte_start_head} \let\stopTABLEhead\relax +\unexpanded\def\startTABLEnext{\dosingleempty\tabl_nte_start_next} \let\stopTABLEnext\relax +\unexpanded\def\startTABLEbody{\dosingleempty\tabl_nte_start_body} \let\stopTABLEbody\relax +\unexpanded\def\startTABLEfoot{\dosingleempty\tabl_nte_start_foot} \let\stopTABLEfoot\relax -\long\def\dostartTABLEhead[#1]#2\stopTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead} -\long\def\dostartTABLEnext[#1]#2\stopTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext} -\long\def\dostartTABLEbody[#1]#2\stopTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody} -\long\def\dostartTABLEfoot[#1]#2\stopTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot} +\def\tabl_nte_start_head[#1]#2\stopTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead} +\def\tabl_nte_start_next[#1]#2\stopTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext} +\def\tabl_nte_start_body[#1]#2\stopTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody} +\def\tabl_nte_start_foot[#1]#2\stopTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot} \protect \endinput diff --git a/tex/context/base/tabl-pln.mkiv b/tex/context/base/tabl-pln.mkiv index 9e65f7e40..3638006c7 100644 --- a/tex/context/base/tabl-pln.mkiv +++ b/tex/context/base/tabl-pln.mkiv @@ -9,83 +9,124 @@ \writestatus{loading}{ConTeXt Table Macros / Plain Tabular} +%D This code might become a module. + \unprotect -\newif \if@@plnusetab -\newif \if@@plncr -\newbox \@@plntabs -\newbox \@@plntabsyet -\newbox \@@plntabsdone -\newdimen \@@plntabdimen +\newconditional \c_tabl_plain_cr +\newconditional \c_tabl_plain_use_tab +\newbox \b_tabl_plain_tabs +\newbox \b_tabl_plain_tabs_yet +\newbox \b_tabl_plain_tabs_done +\newdimen \d_tabl_plain_tab + +\let\m_tabl_plain_next\relax \def\cleartabs % visible - {\global\setbox\@@plntabsyet\emptyhbox - \setbox\@@plntabs\emptyhbox} + {\global\setbox\b_tabl_plain_tabs_yet\emptyhbox + \setbox\b_tabl_plain_tabs\emptyhbox} \def\settabs % visible - {\setbox\@@plntabs\emptyhbox - \futurelet\next\@@plnsettabs} + {\setbox\b_tabl_plain_tabs\emptyhbox + \futurelet\m_tabl_plain_next\tabl_plain_set_tabs} \def\tabalign % visible - {\@@plnusetabtrue\@@plnmaketabbox} + {\settrue\c_tabl_plain_use_tab + \tabl_plain_make_tab_box} -\let\+\tabalign % no outer here (can be overloaded) +\ifdefined\+ \else + \let\+\tabalign % no outer here (can be overloaded) +\fi -\def\@@plnsettabs - {\ifx\next\+% - \def\nxt{\afterassignment\@@plnsettab\let\nxt}% +\def\tabl_plain_set_tabs + {\ifx\m_tabl_plain_next\+% + \let\tabl_plain_nxt\tabl_plain_align + \else\ifx\m_tabl_plain_next\tabalign % added hh + \let\tabl_plain_nxt\tabl_plain_align \else - \let\nxt\@@plnsetcols - \fi - \let\next\relax - \nxt} + \let\tabl_plain_nxt\tabl_plain_set_cols + \fi\fi + \let\m_tabl_plain_next\relax + \tabl_plain_nxt} -\def\@@plnsettab - {\let\nxt\relax - \@@plnusetabfalse\@@plnmaketabbox} +\def\tabl_plain_align + {\afterassignment\tabl_plain_set_tab + \let\tabl_plain_nxt} -\def\@@plnsetcols#1\columns - {\scratchcounter#1% - \@@plntabdimen\hsize +\def\tabl_plain_set_tab + {\let\tabl_plain_nxt\relax + \setfalse\c_tabl_plain_use_tab + \tabl_plain_make_tab_box} + +\def\tabl_plain_set_cols#1\columns + {\scratchcounter#1\relax + \d_tabl_plain_tab\hsize \loop - \ifnum\scratchcounter>\zerocount \@nother + \ifnum\scratchcounter>\zerocount + \tabl_plain_other \repeat} -\def\@nother - {\scratchdimen\@@plntabdimen +\def\tabl_plain_other + {\scratchdimen\d_tabl_plain_tab \divide\scratchdimen\scratchcounter - \setbox\@@plntabs\hbox{\hbox to\scratchdimen{}\unhbox\@@plntabs}% - \advance\@@plntabdimen-\scratchdimen + \setbox\b_tabl_plain_tabs\hbox + {\hbox to\scratchdimen{}% + \unhbox\b_tabl_plain_tabs}% + \advance\d_tabl_plain_tab-\scratchdimen \advance\scratchcounter\minusone} -\def\@@plnmaketabbox +\def\tabl_plain_make_tab_box {\begingroup - \global\setbox\@@plntabsyet\copy\@@plntabs - \global\setbox\@@plntabsdone\emptyhbox - \def\cr - {\@@plncrtrue\crcr\egroup\egroup - \if@@plnusetab\unvbox\zerocount\lastbox\fi\endgroup - \setbox\@@plntabs\hbox{\unhbox\@@plntabsyet\unhbox\@@plntabsdone}}% - \setbox\zerocount\vbox\bgroup\@@plncrfalse - \ialign\bgroup&\@@plnbegintabbox##\@@plnendtabbox\crcr} - -\def\@@plnbegintabbox - {\setbox\zerocount\hbox\bgroup} - -\def\@@plnendtabbox - {\if@@plncr - \egroup % now \box\zerocount holds the column + \let\+\tabalign % added hh + \global\setbox\b_tabl_plain_tabs_yet\copy\b_tabl_plain_tabs + \global\setbox\b_tabl_plain_tabs_done\emptyhbox + \let\cr\tabl_plain_cr + \setbox\scratchbox\vbox\bgroup + \setfalse\c_tabl_plain_cr + \ialign\bgroup + \aligntab + \tabl_plain_begin_tab_box + \alignmark\alignmark + \tabl_plain_end_tab_box + \crcr} + +\def\tabl_plain_cr + {\settrue\c_tabl_plain_cr + \crcr + \egroup + \egroup + \ifconditional\c_tabl_plain_use_tab + \unvbox\scratchbox + \lastbox % okay? + \fi + \endgroup + \setbox\b_tabl_plain_tabs\hbox + {\unhbox\b_tabl_plain_tabs_yet + \unhbox\b_tabl_plain_tabs_done}} + +\def\tabl_plain_begin_tab_box + {\setbox\scratchbox\hbox\bgroup} + +\def\tabl_plain_end_tab_box + {\ifconditional\c_tabl_plain_cr + \egroup % now \box\scratchbox holds the column \else - \hss\egroup - \global\setbox\@@plntabsyet\hbox - {\unhbox\@@plntabsyet\global\setbox\plusone\lastbox}% now \box\plusone holds its size - \ifvoid\plusone - \global\setbox\plusone\hbox to\wd\zerocount{}% - \else - \setbox\zerocount\hbox to\wd\plusone{\unhbox\zerocount}% - \fi - \global\setbox\@@plntabsdone\hbox{\box\plusone\unhbox\@@plntabsdone}% - \fi - \box\zerocount} + \hss + \egroup + \global\setbox\b_tabl_plain_tabs_yet\hbox + {\unhbox\b_tabl_plain_tabs_yet + \global\setbox\globalscratchbox\lastbox}% now \box\globalscratchbox holds its size + \ifvoid\globalscratchbox + \global\setbox\globalscratchbox\hbox to \wd\scratchbox + {}% + \else + \setbox\scratchbox\hbox to \wd\globalscratchbox + {\unhbox\scratchbox}% + \fi + \global\setbox\b_tabl_plain_tabs_done\hbox + {\box\globalscratchbox + \unhbox\b_tabl_plain_tabs_done}% + \fi + \box\scratchbox} \protect \endinput diff --git a/tex/context/base/tabl-tab.mkiv b/tex/context/base/tabl-tab.mkiv index b50be8531..b9b519620 100644 --- a/tex/context/base/tabl-tab.mkiv +++ b/tex/context/base/tabl-tab.mkiv @@ -80,7 +80,7 @@ \appendtoks \parindent\zeropoint \raggedright - \rightskip\zeropoint \!!plus 4em \relax + \rightskip\zeropoint \s!plus 4em \relax \to \everytableparbox \newskip \tablelefttabskip @@ -854,11 +854,8 @@ \lineskiplimit\zeropoint \lineskip \zeropoint \tabskip \zeropoint - \doifelsenothing\@@titextwidth - {\halign} - {\doifelse\@@titextwidth\v!max - {\halign to \hsize} - {\halign to \@@titextwidth}}% + \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}% + \halign \ifx\p_tabl_table_textwidth\empty \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi % \the\!taTableSpread \bgroup \span @@ -878,9 +875,9 @@ \def\donormaltablelineformat#1#2% {\vrule - \!!width \zeropoint - \!!height\dimexpr\tablestrutheightfactor\tablestrutunit+#1\tablestrutunit\relax - \!!depth \dimexpr\tablestrutdepthfactor \tablestrutunit+#2\tablestrutunit\relax + \s!width \zeropoint + \s!height\dimexpr\tablestrutheightfactor\tablestrutunit+#1\tablestrutunit\relax + \s!depth \dimexpr\tablestrutdepthfactor \tablestrutunit+#2\tablestrutunit\relax \relax \cr} @@ -977,7 +974,7 @@ \def\donormaltablefullrule {\starttablenoalign \!ttGetHalfRuleThickness - \hrule\!!height\scratchdimen\!!depth\scratchdimen + \hrule\s!height\scratchdimen\s!depth\scratchdimen \stoptablenoalign} \def\donormaltableshortrule % was: \!ttShortHrule @@ -986,7 +983,7 @@ \ifx\tablecurrenthrulecolor\empty\else \switchtocolor[\tablecurrenthrulecolor]% see *DL* \fi - \leaders\hrule\!!height\scratchdimen\!!depth\scratchdimen\hfill + \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill \emptyhbox \ignorespaces} @@ -1022,7 +1019,7 @@ % SetTableToWidth -> textwidth=dimension [to dimension] % Expand -> textwidth=max [to \hsize] % WidenTableBy -> [spread #1] -% \tablelefttabskip\zeropoint\!!plus1fill +% \tablelefttabskip\zeropoint\s!plus1\s!fill % \tablerighttabskip\tablelefttabskip % LongLines -> [spread \hsize] @@ -1330,26 +1327,38 @@ \newconditional\tablerepeathead \newconditional\tablerepeattail - \unexpanded\def\starttable {\bgroup \dodoubleempty\dostarttable} \unexpanded\def\dostarttable[#1][#2]% preamble optional-settings {\ifsecondargument - \getparameters[\??ti][#2]% + \setupcurrenttables[#2]% \fi \let\stoptable\dostoptable - \doif\@@tisplit\v!auto - {\ifinsidesplitfloat\let\@@tisplit\v!yes\fi}% - \doifinsetelse\@@tisplit{\v!yes,\v!repeat} - {\unexpanded\def\stoptable{\stoptables\egroup}% - \starttables} - {\doifelsenothing\@@tiframe - {\ifinsidefloat\else\startbaselinecorrection\fi} - {\startframedcontent[\@@tiframe]}% - \postponenotes - \firststagestarttable}% + \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 + \def\stoptable{\dostoptables\egroup}% not \unexpanded as we look ahead + \expandafter\starttables + \else\ifx\p_tabl_table_split\v!repeat + \def\stoptable{\dostoptables\egroup}% not \unexpanded as we look ahead + \doubleexpandafter\starttables + \else + \ifx\p_tabl_table_frame\empty + \ifinsidefloat\else\startbaselinecorrection\fi + \else + \startframedcontent[\p_tabl_table_frame]% + \fi + \postponenotes + \doubleexpandafter\firststagestarttable + \fi\fi [#1]} % We cannot define \unexpanded\def\dostoptable a ssomehow lookahead @@ -1365,12 +1374,14 @@ \globalletempty\dotabletail \stoptablenoalign \dofinishtable - \doifelsenothing\@@tiframe - {\ifinsidefloat\else + \ifx\p_tabl_table_frame\empty + \ifinsidefloat\else \stopbaselinecorrection \goodbreak % compensates all the nobreaks - \fi} + \fi + \else \stopframedcontent + \fi \egroup} %D Before we can grab the argument, we have to make sure that @@ -1465,7 +1476,7 @@ % \def\doverysimpletableHL % todo % {\starttablenoalign -% \expandafter\donormaltablefullrule\@@tiHLheight +% \normalexpanded{\noexpand\donormaltablefullrule\m_tabl_table_HLheight}% % \stoptablenoalign} \def\dorestarttable#1% @@ -1565,9 +1576,14 @@ {\bgroup \let\stoptables\dostoptables \splittablestrue - \doifelse\@@tisplit\v!repeat - {\settrue \tablerepeathead\settrue \tablerepeattail} - {\setfalse\tablerepeathead\setfalse\tablerepeattail}% + \edef\p_tabl_table_split{\directtablesparameter\c!split}% + \ifx\p_tabl_table_split\v!repeat + \settrue\tablerepeathead + \settrue\tablerepeattail + \else + \setfalse\tablerepeathead + \setfalse\tablerepeattail + \fi \flushnotes \setbox\tablecontentbox\vbox\bgroup \forgetall @@ -1575,7 +1591,7 @@ \let\stoptables\relax % needed for \noalign -\def\dostoptables +\def\dostoptables % not \unexpanded as we need the lookahead (brrr) {\dochucktableautorow % AM: before the tail, else noalign problem \ifconditional\tablerepeattail\else\doinserttabletail\fi \dofinishtable @@ -1899,7 +1915,7 @@ \def\dotablevrulecommand#1% global assignments {\doifnumberelse{#1} {\global\tablevrulethicknessfactor#1\relax - \global\multiply\tablevrulethicknessfactor\@@tiVLwidth\relax} + \global\multiply\tablevrulethicknessfactor\m_tabl_table_VLwidth\relax} {\xdef\tablecurrentvrulecolor{#1}}} \unexpanded\def\dotableVL @@ -1909,7 +1925,7 @@ \def\dodotableVL[#1]% {\global\let\tablecurrentvrulecolor\empty - \global\tablevrulethicknessfactor\@@tiVLwidth\relax + \global\tablevrulethicknessfactor\m_tabl_table_VLwidth\relax \iffirstargument \rawprocesscommalist[#1]\dotablevrulecommand \fi @@ -1933,7 +1949,7 @@ \def\dotablehrulecommand#1% global assignments {\doifnumberelse{#1} {\global\tablehrulethicknessfactor#1\relax - \global\multiply\tablehrulethicknessfactor\@@tiHLheight\relax} + \global\multiply\tablehrulethicknessfactor\m_tabl_table_HLheight\relax} {\xdef\tablecurrenthrulecolor{#1}}} \unexpanded\def\dotableHL @@ -1953,7 +1969,7 @@ \writestatus\m!TABLE{change \string\MR\space into \string\SR}% \fi\fi \bgroup - \global\tablehrulethicknessfactor\@@tiHLheight\relax + \global\tablehrulethicknessfactor\m_tabl_table_HLheight\relax \iffirstargument \global\let\tablecurrenthrulecolor\empty \rawprocesscommalist[#1]\dotablehrulecommand @@ -2004,10 +2020,10 @@ {\dochucktableautorow \dofinishtablerow \starttablenoalign - \dosingleempty\dotableTB} + \dosingleempty\dodotableTB} -\def\dotableTB[#1]% - {\blank[\iffirstargument#1\else\@@tiNL\fi]% +\def\dodotableTB[#1]% + {\blank[\iffirstargument#1\else\directtablesparameter\c!NL\fi]% \nobreak \stoptablenoalign} @@ -2056,7 +2072,7 @@ \global\tabledrulespan#1\relax \else \global\tablehrulethicknessfactor#1\relax - \global\multiply\tablehrulethicknessfactor\@@tiVLwidth\relax + \global\multiply\tablehrulethicknessfactor\m_tabl_table_VLwidth\relax \fi} {\xdef\tablecurrenthrulecolor{#1}}} @@ -2074,7 +2090,7 @@ \writestatus\m!TABLE{change \string\MR\space into \string\SR}% \fi\fi \dosettableaction\tableunknownstate - \global\tablehrulethicknessfactor\@@tiHLheight\relax + \global\tablehrulethicknessfactor\m_tabl_table_HLheight\relax \global\tabledrulespan\zerocount \iffirstargument \global\let\tablecurrenthrulecolor\empty @@ -2136,17 +2152,28 @@ \let\REF \dotablereformat \to \localtabledefinitions -\setvalue{\??ti:\c!distance:\v!none }{\dotableOpenUp00\def\LOW{\Lower6 }} -\setvalue{\??ti:\c!distance:\v!small }{\dotableOpenUp00\def\LOW{\Lower6 }} % == baseline -\setvalue{\??ti:\c!distance:\v!medium}{\dotableOpenUp11\def\LOW{\Lower7 }} -\setvalue{\??ti:\c!distance:\v!big }{\dotableOpenUp22\def\LOW{\Lower8 }} +\installcorenamespace{tables} +\installcorenamespace{tabledistance} +\installcorenamespace{tablealign} + +\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables + +\setvalue{\??tabledistance\v!none }{\dotableOpenUp00\def\LOW{\Lower6 }} +\setvalue{\??tabledistance\v!small }{\dotableOpenUp00\def\LOW{\Lower6 }} % == baseline +\setvalue{\??tabledistance\v!medium}{\dotableOpenUp11\def\LOW{\Lower7 }} +\setvalue{\??tabledistance\v!big }{\dotableOpenUp22\def\LOW{\Lower8 }} \appendtoks - \getvalue{\??ti:\c!distance:\@@tidistance}% + \expandcheckedcsname\??tabledistance{\directtablesparameter\c!distance}\v!medium \to \localtabledefinitions +\setvalue{\??tablealign\v!right }{\def\dotableparalignment{\raggedright}} +\setvalue{\??tablealign\v!left }{\def\dotableparalignment{\raggedleft}} +\setvalue{\??tablealign\v!middle }{\def\dotableparalignment{\raggedcenter}} +\setvalue{\??tablealign\s!unknown}{\def\dotableparalignment{\notragged}} + \appendtoks - \doifelse\@@tidistance\v!none + \doifelse{\directtablesparameter\c!distance}\v!none {\tablerowfactor\zerocount} {\tablerowfactor\plustwo }% \to \localtabledefinitions @@ -2160,31 +2187,28 @@ \@EAEAEA\dotextmodebar \fi\fi} -\unexpanded\def\setuptables - {\dosingleargument\dosetuptables} - -\def\dosetuptables[#1]% - {\getparameters[\??ti][#1]% - \processaction % we have a command for this - [\@@tialign] - [ \v!right=>\def\dotableparalignment{\raggedright}, - \v!left=>\def\dotableparalignment{\raggedleft}, - \v!middle=>\def\dotableparalignment{\raggedcenter}, - \s!default=>\def\dotableparalignment{\notragged}, - \s!unknown=>\def\dotableparalignment{\notragged}]% - \assignalfadimension\@@tiVL\@@tiVLwidth 246% - \assignalfadimension\@@tiHL\@@tiHLheight246} +\appendtoks + \expandcheckedcsname\??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\dolocaltablesetup - {\@@ticommands\relax - \doifsomething\@@tibodyfont{\switchtobodyfont[\@@tibodyfont]}% - \tablelinethicknessunit\dimexpr\@@tirulethickness/\tablelinethicknessfactor\relax - \doifelse\@@tiheight\v!strut - {\let\tablestrutheightfactor\tablestrutheightfactor} - {\let\tablestrutheightfactor\@@tiheight}% - \doifelse\@@tidepth\v!strut - {\let\tablestrutdepthfactor\tablestrutdepthfactor} - {\let\tablestrutdepthfactor\@@tidepth}% + {\directtablesparameter\c!commands\relax + \doifsomething{\directtablesparameter\c!bodyfont}{\switchtobodyfont[\directtablesparameter\c!bodyfont]}% + \tablelinethicknessunit\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}% \tablestrutunit\dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont @@ -2243,9 +2267,9 @@ %D \stopcombination \setuptables - [HL=\v!medium, - VL=\v!medium, - NL=\v!small, + [\c!HL=\v!medium, + \c!VL=\v!medium, + \c!NL=\v!small, \c!frame=, \c!align=\v!right, \c!depth=.40, % \v!strut @@ -2256,8 +2280,8 @@ \c!distance=\v!medium, \c!bodyfont=, \c!commands=, - \c!background=\v!screen, - \c!backgroundscreen=\@@rsscreen, + \c!background=\v!screen, % huh? + \c!backgroundscreen=\defaultbackgroundscreen, \c!backgroundcolor=, \c!split=\v!auto] diff --git a/tex/context/base/tabl-tbl.lua b/tex/context/base/tabl-tbl.lua index c48c5100d..7291facd3 100644 --- a/tex/context/base/tabl-tbl.lua +++ b/tex/context/base/tabl-tbl.lua @@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['tabl-tbl'] = { license = "see context related readme files" } --- A couple of hacks ... easier to do in Lua than in regular --- TeX. More will follow. +-- A couple of hacks ... easier to do in Lua than in regular TeX. More will +-- follow. + +local context, commands = context, commands local tonumber = tonumber local gsub, rep, sub, find = string.gsub, string.rep, string.sub, string.find diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv index 20ddac461..0bd2fb05e 100644 --- a/tex/context/base/tabl-tbl.mkiv +++ b/tex/context/base/tabl-tbl.mkiv @@ -221,6 +221,8 @@ \newconstant \c_tabl_tabulate_localcolorspan \newconstant \c_tabl_tabulate_modus +\let\tabulatesplitlinemode\c_tabl_tabulate_splitlinemode % temp hack, we need an interface + \let \m_tabl_tabulate_separator_factor \empty % fraction \newif \iftracetabulate % will become a tracker @@ -305,7 +307,7 @@ \def\tabl_tabulate_nobreak_inject_tracer {\red % maybe use the fast color switcher here - \hrule\!!height.5\linewidth\!!depth.5\linewidth + \hrule\s!height.5\linewidth\s!depth.5\linewidth \par \kern-\linewidth \nobreak} @@ -1044,17 +1046,48 @@ \def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[]} \def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[]} +% \unexpanded\def\tabl_start_defined[#1]% +% {\bgroup +% \edef\currenttabulationparent{#1}% +% \let\currenttabulation\currenttabulationparent +% \doifnextoptionalelse\tabl_start_defined_yes\tabl_start_defined_nop} +% +% \def\tabl_start_defined_yes[#1]% +% {\edef\currenttabulation{\currenttabulation:#1}% +% \tabl_tabulate_start_building} +% +% \def\tabl_start_defined_nop +% {\tabl_tabulate_start_building} + \unexpanded\def\tabl_start_defined[#1]% {\bgroup \edef\currenttabulationparent{#1}% \let\currenttabulation\currenttabulationparent - \doifnextoptionalelse\tabl_start_defined_yes\tabl_start_defined_nop} + \dodoubleargument\tabl_start_defined_indeed} + +\def\tabl_start_defined_indeed + {\iffirstargument + \ifsecondargument + \doubleexpandafter\tabl_start_defined_two + \else + \doubleexpandafter\tabl_start_defined_one + \fi + \else + \singleexpandafter\tabl_start_defined_zero + \fi} + +\def\tabl_start_defined_one[#1][#2]% + {\doifassignmentelse{#1} + {\setuptabulation[\currenttabulation][#1]}% + {\edef\currenttabulation{\currenttabulation:#1}}% + \tabl_tabulate_start_building} -\def\tabl_start_defined_yes[#1]% +\def\tabl_start_defined_two[#1][#2]% {\edef\currenttabulation{\currenttabulation:#1}% + \setuptabulation[\currenttabulation][#2]% \tabl_tabulate_start_building} -\def\tabl_start_defined_nop +\def\tabl_start_defined_zero[#1][#2]% {\tabl_tabulate_start_building} % \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one @@ -1261,11 +1294,11 @@ \tabl_tabulate_column_normal#1} \def\tabl_tabulate_column_vruled_normal - {\vrule\!!width\d_tabl_tabulate_vrulethickness\relax} + {\vrule\s!width\d_tabl_tabulate_vrulethickness\relax} \def\tabl_tabulate_column_vruled_colored {\dousecolorparameter\m_tabl_tabulate_vrule_color - \vrule\!!width\d_tabl_tabulate_vrulethickness\relax} + \vrule\s!width\d_tabl_tabulate_vrulethickness\relax} \unexpanded\def\tabl_tabulate_column_vrule_inject_first {\ifcase\d_tabl_tabulate_vrulethickness\else @@ -1303,7 +1336,7 @@ \expandafter\ignorespaces % interferes with the more tricky hooks \fi} -\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public) +\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 @@ -1354,8 +1387,8 @@ \def\tabl_tabulate_hrule_inject_normal {\hrule - \!!height.5\d_tabl_tabulate_hrulethickness_local - \!!depth .5\d_tabl_tabulate_hrulethickness_local + \s!height.5\d_tabl_tabulate_hrulethickness_local + \s!depth .5\d_tabl_tabulate_hrulethickness_local \relax} \def\tabl_tabulate_hrule_inject_colored @@ -1390,8 +1423,8 @@ % % \def\donormaltabulatehlinerule % {\leaders \hrule -% \!!height\dimexpr.5\lineheight-\strutdepth -% \!!depth-\dimexpr.5\lineheight-\strutdepth+\d_tabl_tabulate_hrulethickness_local +% \s!height\dimexpr.5\lineheight-\strutdepth +% \s!depth-\dimexpr.5\lineheight-\strutdepth+\d_tabl_tabulate_hrulethickness_local % \hfill} % % \def\docoloredtabulatehlinerule @@ -1904,10 +1937,10 @@ {\c_tabl_tabulate_pass\plusone \tabl_tabulate_check_full_content \edef\v_tabl_tabulate_align{\executeifdefined{\??tabulatealigning\p_align}0}% - \s_tabl_tabulate_post\zeropoint - \s_tabl_tabulate_pre\zeropoint \s_tabl_tabulate_first.5\d_tabl_tabulate_unit \s_tabl_tabulate_last\s_tabl_tabulate_first + \s_tabl_tabulate_pre\zeropoint + \s_tabl_tabulate_post\s_tabl_tabulate_first % was: \zeropoint \global\c_tabl_tabulate_columns\zerocount \global\c_tabl_tabulate_nofauto\zerocount \global\c_tabl_tabulate_noflines\zerocount @@ -2029,6 +2062,7 @@ % \dostarttagged\t!tabulate\empty \dostarttagged\t!tabulaterow\empty + \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}% \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}% \dostoptagged @@ -2150,6 +2184,26 @@ \let\TB\tabl_tabulate_TB \to \everytabulate +% %D Between alignment lines certain rules apply, and even a simple test can mess +% %D up a table, which is why we have a special test facilityL +% %D +% %D \startbuffer +% %D \starttabulate[|l|p|] +% %D \NC 1test \NC test \NC \NR +% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}% +% %D \stoptabulate +% %D \stopbuffer +% %D +% %D \typebuffer \getbuffer +% +% \def\tableifelse#1% should be tabulatenoalign then +% {\tablenoalign +% {#1% +% {\aftergroup \firstoftwoarguments}% +% {\aftergroup\secondoftwoarguments}}} +% +% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}} + %D Some new trickery: %D %D \startbuffer @@ -2237,4 +2291,53 @@ % \NC \digits $@@@.@@1,@@$ \NC\NR % \stoptabulatie +%D Predefined categories (moved from core-mis): + +\definetabulate + [\v!legend] + [|emj1|i1|mR|] + +\setuptabulate + [\v!legend] + [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}] + +\definetabulate + [\v!legend][\v!two] + [|emj1|emk1|i1|mR|] + +\definetabulate + [\v!fact] + [|R|ecmj1|i1mR|] + +\setuptabulate + [\v!fact] + [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}] + +%D Another example: +%D +%D \starttyping +%D \definetabulate +%D [whatever] +%D [|l|r|] +%D +%D \definetabulate +%D [whatever][else] +%D [|l|c|r|] +%D +%D \startwhatever +%D \NC l \NC r \NC \NR +%D \NC left \NC right \NC \NR +%D \stopwhatever +%D +%D \startwhatever[else] +%D \NC l \NC m \NC r \NC \NR +%D \NC left \NC middle \NC right \NC \NR +%D \stopwhatever +%D +%D \startwhatever[else][format={|c|c|c|c|}] +%D \NC l \NC m \NC m \NC r \NC \NR +%D \NC left \NC middle \NC middle \NC right \NC \NR +%D \stopwhatever +%D \stoptyping + \protect \endinput diff --git a/tex/context/base/tabl-tsp.mkiv b/tex/context/base/tabl-tsp.mkiv index 21182a988..0138697af 100644 --- a/tex/context/base/tabl-tsp.mkiv +++ b/tex/context/base/tabl-tsp.mkiv @@ -13,8 +13,11 @@ \writestatus{loading}{ConTeXt Table Macros / Splitting} -%D The code in this file is move here from other places and needs -%D a mkiv cleanup. +%D The code in this file is moved here from other places and needs +%D a mkiv cleanup. As it mostly targets at tables the code lives in +%D the tabl and page namespaces. + +% work in progress \unprotect @@ -26,8 +29,6 @@ % \splitfloat [settings] {\placetable[optional args]{test}} {content} -% there is no need for a tracked structure number here - %D When \type {inbetween} is made empty instead of the %D default \type {\page}, we will get delayed flushing %D and text may continue below the graphic. @@ -55,61 +56,81 @@ %D \dorecurse{10}{\input tufte } %D \stoptyping -\newcount\noffloatssplits - -\settrue \onlyonesplitofffloat -\setfalse\somenextsplitofffloat +\installcorenamespace{floatsplitting} -\newconditional\splitfloatdone - -\newif\ifinsidesplitfloat % will become chardef +\installdirectcommandhandler \??floatsplitting {floatsplitting} % \??floatsplitting -\newtoks\everysplitfloatsetup +\setupfloatsplitting + [\c!conversion=\v!character, % \v!romannumerals + \c!lines=3, + \c!before=, + \c!inbetween=\page, + \c!after=] -\def\extrasplitfloatlines{0} +\newconditional\splitfloatfirstdone +\newconditional\somenextsplitofffloat +\newconditional\splitfloatdone +\newconditional\onlyonesplitofffloat \settrue\onlyonesplitofffloat -\let\splitfloatfinalizer\relax +\newif \ifinsidesplitfloat % will become conditional -\ifx\floatcaptionsuffix\undefined \else - \let\floatcaptionsuffix\empty % will become \splitfloatcaptionsuffix -\fi +\newcount \noffloatssplits +\newtoks \everysplitfloatsetup -\unexpanded\def\setupfloatsplitting - {\dodoubleargument\getparameters[\??si]} +\let \extrasplitfloatlines \!!zerocount +\let \splitfloatfinalizer \relax +\let \floatcaptionsuffix \empty \unexpanded\def\splitfloat - {\dosingleempty\dosplitfloat} + {\dosingleempty\page_split_float} -\def\dosplitfloat[#1]#2% nog dubbele refs +\def\page_split_float[#1]#2% nog dubbele refs {\bgroup \global\setfalse\splitfloatdone - \aftergroup\checksplitfloat + \aftergroup\page_split_float_check \insidefloattrue \insidesplitfloattrue - \getparameters[\??si][#1]% + \setupcurrentfloatsplitting[#1]% \global\noffloatssplits\zerocount - \def\floatcaptionsuffix{\convertnumber\@@siconversion\noffloatssplits}% - \let\extrasplitfloatlines\@@silines + \let\floatcaptionsuffix\page_split_float_suffix + \edef\extrasplitfloatlines{\floatsplittingparameter\c!lines}% \the\everysplitfloatsetup \def\splitfloatcommand{#2}% \global\settrue \onlyonesplitofffloat \global\setfalse\somenextsplitofffloat - \dopushsavedfloats - \@@sibefore + \page_floats_push_saved + \floatsplittingparameter\c!before \let\next} % \bgroup -\unexpanded\def\checksplitfloat +\unexpanded\def\page_split_float_suffix + {\begingroup + \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix + \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits + \endgroup} + +\unexpanded\def\page_split_float_check {\ifconditional\splitfloatdone \splitfloatfinalizer % a weird place (could interfere with flushing) \else - \blank{\tttf \getmessage\m!floatblocks{13}\empty}\blank + \blank + \begingroup + \tttf \dontleavehmode \getmessage\m!floatblocks{13}\empty + \endgroup + \blank \showmessage\m!floatblocks{13}\empty \fi} -\def\dodowithsplitofffloat - {\dowithnextboxcs\dodowithsplitofffloatfinish\vbox} +\def\page_split_float_process % nextbox + {\ifinsidesplitfloat + \expandafter\page_split_float_process_yes + \else + \expandafter\page_split_float_process_nop + \fi} + +\def\page_split_float_process_yes + {\dowithnextboxcs\page_split_float_process_finish\vbox} -\def\dodowithsplitofffloatfinish +\def\page_split_float_process_finish {\forgetall \dontcomplain \global\settrue\splitfloatdone @@ -127,26 +148,29 @@ \splitfloatcommand{\box\nextbox}% \egroup \ifconditional\somenextsplitofffloat - \doifelsenothing\@@siinbetween - {\ifconditional\splitfloatfirstdone\else\page\fi} - \@@siinbetween + \edef\p_inbetween{\floatsplittingparameter\c!inbetween}% + \ifx\p_inbetween\empty + \ifconditional\splitfloatfirstdone\else\page\fi + \else + \p_inbetween + \fi \else - \@@siafter - \dopopsavedfloats - \doflushsavedfloats + \floatsplittingparameter\c!after + \page_floats_pop_saved + \page_floats_flush_saved \fi \global\settrue\splitfloatfirstdone} -\def\nodowithsplitofffloat - {\dowithnextboxcs\nodowithsplitofffloatfinish\vbox} +\def\page_split_float_process_nop + {\dowithnextboxcs\page_split_float_process_nop_finish\vbox} -\def\nodowithsplitofffloatfinish +\def\page_split_float_process_nop_finish {\forgetall \dontcomplain \box\nextbox % maybe an option to unvbox \global\settrue\splitfloatfirstdone} -\def\dochecksplitofffloat#1% box +\def\page_split_float_check_content#1% box {\ifinsidesplitfloat % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow \ifcase\ht#1\relax @@ -157,7 +181,7 @@ \fi \fi} -\def\analyzesplitfloatcaption#1% depends on page-flt .. pretty messy +\def\page_split_float_check_caption#1% depends on page-flt .. pretty messy {\edef\extrasplitfloatlines{\extrasplitfloatlines}% \ifx\extrasplitfloatlines\v!auto \bgroup @@ -174,27 +198,15 @@ \doifnumberelse\extrasplitfloatlines\donothing{\def\extrasplitfloatlines{1}}% \fi} -\def\dowithsplitofffloat % nextbox +\unexpanded\def\doifnotinsidesplitfloat {\ifinsidesplitfloat - \expandafter\dodowithsplitofffloat - \else - \expandafter\nodowithsplitofffloat + \expandafter\gobbleoneargument \fi} -\def\doifnotinsidesplitfloat - {\ifinsidesplitfloat\expandafter\gobbleoneargument\fi} - -%D Some defaults: - -\setupfloatsplitting - [\c!conversion=\v!character, % \v!romannumerals - \c!lines=3, - \c!before=, - \c!inbetween=\page, - \c!after=] - %D Table splitter, on top of previous code: +% todo: keep tail to rest, so we need a lookahead + \newbox\tsplitcontent \newbox\tsplitresult \newbox\tsplithead @@ -203,198 +215,216 @@ \newtoks\everyresettsplit -\def\resettsplit{\the\everyresettsplit} - \appendtoks - \def\tsplitminimumfreelines{0}% - \def\tsplitminimumfreespace{0pt}% - \setbox\tsplitcontent\emptyvbox - \setbox\tsplitresult \emptyvbox - \setbox\tsplithead \emptyvbox - \setbox\tsplitnext \emptyvbox - \setbox\tsplittail \emptyvbox - \let\tsplitbeforeresult\donothing - \let\tsplitafterresult \donothing - \let\tsplitinbetween \donothing - \let\tsplitbefore \donothing - \let\tsplitafter \donothing - \let\postprocesstsplit \donothing + \let \tsplitminimumfreelines\!!zerocount + \let \tsplitminimumfreespace\!!zeropoint + \setbox\tsplitcontent \emptyvbox + \setbox\tsplitresult \emptyvbox + \setbox\tsplithead \emptyvbox + \setbox\tsplitnext \emptyvbox + \setbox\tsplittail \emptyvbox + \let \tsplitbeforeresult \donothing + \let \tsplitafterresult \donothing + \let \tsplitinbetween \donothing + \let \tsplitbefore \donothing + \let \tsplitafter \donothing + \let \postprocesstsplit \donothing \to \everyresettsplit +\unexpanded\def\resettsplit + {\the\everyresettsplit} + \resettsplit -% todo: keep tail to rest, so we need a lookahead +\def\tsplitdirectwidth{\hsize} -\newconditional\splitfloatfirstdone +\newconditional\c_tabl_split_done +\newconditional\c_tabl_split_head +\newconditional\c_tabl_split_full -\def\handletsplit - {\analyzesplitfloatcaption{\wd\tsplitcontent}% +\newdimen \d_tabl_split_available + +\unexpanded\def\handletsplit + {\page_split_float_check_caption{\wd\tsplitcontent}% \global\setfalse\splitfloatfirstdone \testpagesync % new, sync, but still tricky [\tsplitminimumfreelines] [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]% \setbox\scratchbox\vbox{\tsplitinbetween}% \edef\tsplitinbetweenheight{\the\htdp\scratchbox}% etex - \!!doneafalse - \doloop - {\ifinsidecolumns - % brrr, assumes empty columns - \global\setfalse\splitfloatfirstdone - \scratchdimen\textheight - \!!donectrue - \else - \ifconditional\splitfloatfirstdone - \scratchdimen\textheight - \!!donectrue - \else\ifdim\pagegoal<\maxdimen - \scratchdimen\dimexpr\pagegoal-\pagetotal\relax - \!!donecfalse - \else - \scratchdimen\textheight - \!!donectrue - \fi\fi - \fi - \scratchdimen\dimexpr\scratchdimen-\tsplitinbetweenheight-\tsplitminimumfreespace-\extrasplitfloatlines\lineheight\relax - \ifdim\htdp\tsplittail>\zeropoint - \advance\scratchdimen-\htdp\tsplittail - \fi - \setbox\tsplitresult\vbox - {\ifdim\ht\tsplithead>\zeropoint - \unvcopy\tsplithead + \setfalse\c_tabl_split_done + \doloop\tabl_split_loop_body + \global\setfalse\usesamefloatnumber % new, prevent next increment + \global\setfalse\splitfloatfirstdone} % we can use this one for tests + +\def\tabl_split_loop_body + {\ifinsidecolumns + % brrr, assumes empty columns + \global\setfalse\splitfloatfirstdone + \d_tabl_split_available\textheight + \settrue\c_tabl_split_full + \else + \ifconditional\splitfloatfirstdone + \d_tabl_split_available\textheight + \settrue\c_tabl_split_full + \else\ifdim\pagegoal<\maxdimen + \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax + \setfalse\c_tabl_split_full + \else + \d_tabl_split_available\textheight + \settrue\c_tabl_split_full + \fi\fi + \fi + \d_tabl_split_available \dimexpr + \d_tabl_split_available + -\tsplitinbetweenheight + -\tsplitminimumfreespace + -\extrasplitfloatlines\lineheight + \relax + \ifdim\htdp\tsplittail>\zeropoint + \advance\d_tabl_split_available-\htdp\tsplittail + \fi + \setbox\tsplitresult\vbox + {\ifdim\ht\tsplithead>\zeropoint + \unvcopy\tsplithead + \tsplitinbetween + \fi}% + \ifconditional\c_tabl_split_done \else + \ifdim\ht\tsplitnext>\zeropoint + \setbox\tsplithead\box\tsplitnext + \fi + \fi + \settrue\c_tabl_split_done + \ifdim\ht\tsplitresult>\zeropoint + \settrue\c_tabl_split_head % table head + \else + \setfalse\c_tabl_split_head % no tablehead + \fi + \splittopskip\zeropoint + \doloop % inner loop + {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight + \setbox\scratchbox\vbox{\unvbox\scratchbox}% + \ifdim\dimexpr\d_tabl_split_available-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint + \setbox\tsplitresult\vbox + {\unvbox\tsplitresult \tsplitinbetween - \fi}% - \if!!donea\else\ifdim\ht\tsplitnext>\zeropoint - \setbox\tsplithead\box\tsplitnext - \fi\fi - \!!doneatrue - \ifdim\ht\tsplitresult>\zeropoint - \!!donedtrue % table head - \else - \!!donedfalse % no tablehead - \fi - \splittopskip\zeropoint - \doloop - {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight - \setbox\scratchbox\vbox{\unvbox\scratchbox}% - \ifdim\dimexpr\scratchdimen-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint - \setbox\tsplitresult\vbox - {\unvbox\tsplitresult - \tsplitinbetween - \unvbox\scratchbox}% - \ifvoid\tsplitcontent \exitloop \fi - \else\if!!doned - % we only have a tablehead so far - \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}% - \exitloop - \else\if!!donec - % we have text height available, but the (one) cell is too - % large to fit, so, in order to avoid loops/deadcycles we do: - \setbox\tsplitresult\vbox - {\unvbox\tsplitresult - \tsplitinbetween - \unvbox\scratchbox}% - \exitloop - \else - \setbox\tsplitcontent\vbox - {\unvbox\scratchbox - \tsplitinbetween - \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}% - \exitloop - \fi\fi\fi - \!!donedfalse - \!!donecfalse}% - \postprocesstsplit - \dochecksplitofffloat\tsplitcontent - \ifvoid\tsplitcontent + \unvbox\scratchbox}% + \ifvoid\tsplitcontent \exitloop \fi + \else\ifconditional\c_tabl_split_head + % we only have a tablehead so far + \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}% + \exitloop + \else\ifconditional\c_tabl_split_full + % we have text height available, but the (one) cell is too + % large to fit, so, in order to avoid loops/deadcycles we do: \setbox\tsplitresult\vbox {\unvbox\tsplitresult \tsplitinbetween - \unvcopy\tsplittail}% - \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% - \doifnotinsidesplitfloat\tsplitafter - \endgraf + \unvbox\scratchbox}% \exitloop \else - % hack - \ifdim\pagegoal<\maxdimen - \global\pagegoal\dimexpr\pagegoal+\lineheight\relax % etex - \fi - % brrr - \ifdim\ht\tsplitresult>\zeropoint - \setbox\tsplitresult\vbox - {\unvbox\tsplitresult - \tsplitinbetween - \unvcopy\tsplittail}% - \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% - \doifnotinsidesplitfloat\tsplitafter - \endgraf - \fi - \ifinsidecolumns - \goodbreak % was \doifnotinsidesplitfloat\goodbreak - \else - \page % was \doifnotinsidesplitfloat\page - \fi - \global\settrue\usesamefloatnumber % new, prevent next increment - \fi}% - \global\setfalse\usesamefloatnumber % new, prevent next increment - \global\setfalse\splitfloatfirstdone} % we can use this one for tests + \setbox\tsplitcontent\vbox + {\unvbox\scratchbox + \tsplitinbetween + \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}% + \exitloop + \fi\fi\fi + \setfalse\c_tabl_split_head + \setfalse\c_tabl_split_full}% + \postprocesstsplit + \page_split_float_check_content\tsplitcontent + \ifvoid\tsplitcontent + \setbox\tsplitresult\vbox + {\unvbox\tsplitresult + \tsplitinbetween + \unvcopy\tsplittail}% + \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% + \doifnotinsidesplitfloat\tsplitafter + \endgraf + \exitloop + \else + % hack + \ifdim\pagegoal<\maxdimen + \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex + \fi + % brrr + \ifdim\ht\tsplitresult>\zeropoint + \setbox\tsplitresult\vbox + {\unvbox\tsplitresult + \tsplitinbetween + \unvcopy\tsplittail}% + \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% + \doifnotinsidesplitfloat\tsplitafter + \endgraf + \fi + \ifinsidecolumns + \goodbreak % was \doifnotinsidesplitfloat\goodbreak + \else + \page % was \doifnotinsidesplitfloat\page + \fi + \global\settrue\usesamefloatnumber % new, prevent next increment + \fi} %D The next one assumes that the split takes place elsewhere. This is %D used in xtables. \let\resetdirecttsplit\resettsplit -\def\tsplitdirectwidth{\hsize} - -\def\handledirecttsplit - {\analyzesplitfloatcaption{\tsplitdirectwidth}% +\unexpanded\def\handledirecttsplit + {\page_split_float_check_caption{\tsplitdirectwidth}% \global\setfalse\splitfloatfirstdone \testpagesync % new, sync, but still tricky [\tsplitminimumfreelines] [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]% - \doloop - {\ifinsidecolumns - \global\setfalse\splitfloatfirstdone - \scratchdimen\textheight - \else\ifconditional\splitfloatfirstdone - \scratchdimen\textheight - \else\ifdim\pagegoal<\maxdimen - \scratchdimen\dimexpr\pagegoal-\pagetotal\relax - \else - \scratchdimen\textheight - \fi\fi\fi - \scratchdimen\dimexpr\scratchdimen-\tsplitminimumfreespace-\extrasplitfloatlines\lineheight\relax - \tsplitdirectsplitter\scratchdimen % also sets state - \ifdim\ht\tsplitresult>\zeropoint - \ifconditional\somenextsplitofffloat - \global\setfalse\onlyonesplitofffloat - \fi - \ifdim\pagegoal<\maxdimen - \global\pagegoal\dimexpr\pagegoal+\lineheight\relax % etex - \fi - \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% - \global\settrue\usesamefloatnumber % new, prevent next increment - \endgraf - \ifconditional\somenextsplitofffloat - \ifinsidecolumns - \goodbreak - \else - \page - \fi - \fi - \global\settrue\splitfloatfirstdone - \else\ifconditional\somenextsplitofffloat - \ifinsidecolumns - \goodbreak - \else - \page % no room - \fi - \else - \exitloop - \fi\fi}% - \global\setfalse\usesamefloatnumber % new, prevent next increment + \doloop\tabl_split_direct_loop_body + \global\setfalse\usesamefloatnumber % new, prevent next increment \global\setfalse\splitfloatfirstdone} % we can use this one for tests +\def\tabl_split_direct_loop_body + {\ifinsidecolumns + \global\setfalse\splitfloatfirstdone + \d_tabl_split_available\textheight + \else\ifconditional\splitfloatfirstdone + \d_tabl_split_available\textheight + \else\ifdim\pagegoal<\maxdimen + \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax + \else + \d_tabl_split_available\textheight + \fi\fi\fi + \d_tabl_split_available\dimexpr + \d_tabl_split_available + -\tsplitminimumfreespace + -\extrasplitfloatlines\lineheight + \relax + \tsplitdirectsplitter\d_tabl_split_available % also sets state + \ifdim\ht\tsplitresult>\zeropoint + \ifconditional\somenextsplitofffloat + \global\setfalse\onlyonesplitofffloat + \fi + \ifdim\pagegoal<\maxdimen + \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex + \fi + \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% + \global\settrue\usesamefloatnumber % new, prevent next increment + \endgraf + \ifconditional\somenextsplitofffloat + \ifinsidecolumns + \goodbreak + \else + \page + \fi + \fi + \global\settrue\splitfloatfirstdone + \else\ifconditional\somenextsplitofffloat + \ifinsidecolumns + \goodbreak + \else + \page % no room + \fi + \else + \exitloop + \fi\fi} + \protect \endinput % test cases diff --git a/tex/context/base/tabl-xnt.mkvi b/tex/context/base/tabl-xnt.mkvi index 35451abe0..ffa1f501e 100644 --- a/tex/context/base/tabl-xnt.mkvi +++ b/tex/context/base/tabl-xnt.mkvi @@ -129,7 +129,7 @@ \unexpanded\def\tabl_x_TABLE_start_indeed[#settings]% {\bgroup \tabl_x_prepare{#settings}% - \edef\tabl_x_current_buffer{\x_table_default_buffer}% + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process} \protect \endinput diff --git a/tex/context/base/tabl-xtb.lua b/tex/context/base/tabl-xtb.lua index 395d65a03..01b7ef9eb 100644 --- a/tex/context/base/tabl-xtb.lua +++ b/tex/context/base/tabl-xtb.lua @@ -25,6 +25,8 @@ this mechamism will be improved so that it can replace its older cousin. -- todo: use linked list instead of r/c array +local commands, context, tex, node = commands, context, tex, node + local texdimen = tex.dimen local texcount = tex.count local texbox = tex.box @@ -391,7 +393,7 @@ function xtables.reflow_width() for c=1,nofcolumns do local drc = row[c] if drc.list then - --- flush_node_list(drc.list) + -- flush_node_list(drc.list) drc.list = false end end @@ -512,7 +514,6 @@ function xtables.reflow_width() end -- maybe also options[v_width] here but tricky as width does not say -- much about amount - if options[v_width] then -- not that much (we could have a clever vpack loop balancing .. no fun) local factor = (widetotal + delta) / width if trace_xtable then diff --git a/tex/context/base/tabl-xtb.mkvi b/tex/context/base/tabl-xtb.mkvi index 2382cae21..fae4d1615 100644 --- a/tex/context/base/tabl-xtb.mkvi +++ b/tex/context/base/tabl-xtb.mkvi @@ -59,8 +59,6 @@ \unprotect -% \def\v!xtable{xtable} - % option=stretch : equal distribution % option={stretch,width} : proportional distribution % option={max} : prefer max over forced width/height @@ -97,6 +95,8 @@ \newcount\c_tabl_x_nesting \newcount\c_tabl_x_skip_mode % 1 = skip +\newdimen\d_tabl_x_textwidth + % \setupxtable[one][parent][a=b,c=d] % \setupxtable[one] [a=b,c=d] % \setupxtable [a=b,c=d] @@ -111,10 +111,10 @@ \to \everysetupxtable \setupxtable[% - \c!nr=1, - \c!nc=1, - \c!nx=1, % slow - \c!ny=1, % slow + \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, @@ -124,7 +124,7 @@ % \c!bodyfont=, \c!width=\v!fit, \c!height=\v!fit, - \c!maxwidth=8em, + \c!maxwidth=8\emwidth, \c!autowidth=\v!yes, % controls framed \c!rulethickness=\linewidth, \c!strut=\v!yes, @@ -137,8 +137,8 @@ % \c!footer=, % \c!header=, \c!spaceinbetween=, - \c!textwidth=\hsize, - \c!textheight=\vsize, + \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 @@ -164,7 +164,9 @@ % 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. +% 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. \def\tabl_x_process_buffer_directly[#name]% {\bgroup @@ -179,9 +181,10 @@ \def\tabl_x_process_buffer[#settings]% {\tabl_x_prepare{#settings}% \let\tabl_x_start_table\tabl_x_start_ignore - \gobbleuntil\stopxtable} + \gobbleuntil\stopxtable} % nested xtables are not supported, -%D A bonus: you can use the following construct inside a macro. +%D A bonus: you have to use the following construct inside a macro or +%D direct buffer. \unexpanded\def\startembeddedxtable {\dosingleempty\tabl_x_embedded_start} @@ -211,10 +214,11 @@ \unexpanded\def\tabl_x_start_named_indeed[#settings]% {\advance\c_tabl_x_nesting\plusone \dostarttagged\t!table\empty - \forgetall \iffirstargument \setupcurrentxtable[#settings]% \fi + \tabl_x_check_textwidth + \forgetall \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}} @@ -223,17 +227,28 @@ %D Now we come to processing: +\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} + \def\tabl_x_prepare#settings% assumes \iffirstargument to be set {\advance\c_tabl_x_nesting\plusone \dostarttagged\t!table\empty - \forgetall \iffirstargument \tabl_x_set_checked{#settings}% - \fi} + \fi + \tabl_x_check_textwidth + \forgetall} \def\tabl_x_get_buffer {\ctxcommand{gettexbuffer("\tabl_x_current_buffer")}} +\let\tabl_x_stop_cell\relax + \unexpanded\def\tabl_x_process {\begingroup % * \doifsomething{\xtableparameter\c!bodyfont} @@ -242,7 +257,7 @@ {\xtableparameter\c!spaceinbetween}% \ctxcommand{x_table_create { option = "\xtableparameter\c!option", - textwidth = \number\dimexpr\xtableparameter\c!textwidth, + textwidth = \number\d_tabl_x_textwidth, textheight = \number\dimexpr\xtableparameter\c!textheight, maxwidth = \number\dimexpr\xtableparameter\c!maxwidth, lineheight = \number\openlineheight, @@ -296,15 +311,64 @@ \else\ifinsidefloat \tabl_x_flush_float_normal \else - \doifelse{\xtableparameter\c!split}\v!yes - \tabl_x_flush_flow_split - \tabl_x_flush_flow_normal + \tabl_x_flush_text_checked \fi\fi \ctxcommand{x_table_cleanup()}% \dostoptagged \resetbuffer[\tabl_x_current_buffer]% \egroup} +% text flow split modes + +\installcorenamespace{xtableflushsplit} + +\def\tabl_x_flush_text_checked + {\expandcheckedcsname\??xtableflushsplit{\xtableparameter\c!split}\v!no} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!yes}% + {\ctxcommand{x_table_flush{ method = "\v!split" }}} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!no}% + {\dontleavehmode % else no leftskip etc + \ctxcommand{x_table_flush{ method = "\v!normal" }}} + +% in text flow: headers and footers get repeated + +\setvalue{\??xtableflushsplit\v!repeat}% + {\doloop + {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi }}% + \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 +% +% \unexpanded\def\xtablesplitflush +% {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\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 \def\tabl_x_flush_float_normal @@ -319,12 +383,6 @@ \let\tsplitdirectwidth \d_tabl_x_final_width \handledirecttsplit} -\def\tabl_x_flush_flow_normal - {\ctxcommand{x_table_flush{ method = "\v!normal" }}} - -\def\tabl_x_flush_flow_split - {\ctxcommand{x_table_flush{ method = "\v!split" }}} - \def\tabl_x_split_splitter#vsize% {\setbox\tsplitresult\vbox {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\dimexpr#vsize }}}% diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua index 1ec38e181..37e01996d 100644 --- a/tex/context/base/task-ini.lua +++ b/tex/context/base/task-ini.lua @@ -20,7 +20,7 @@ local freezegroup = tasks.freezegroup local freezecallbacks = callbacks.freeze appendaction("processors", "normalizers", "typesetters.characters.handler") -- always on -appendaction("processors", "normalizers", "fonts.collections.process") -- todo +appendaction("processors", "normalizers", "fonts.collections.process") -- disabled appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled @@ -59,7 +59,9 @@ appendaction("shipouts", "normalizers", "structures.tags.handler") appendaction("shipouts", "normalizers", "nodes.handlers.accessibility") -- disabled appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds") -- disabled ---~ appendaction("shipouts", "normalizers", "nodes.handlers.export") -- disabled +-- appendaction("shipouts", "normalizers", "nodes.handlers.export") -- disabled + +appendaction("shipouts", "finishers", "nodes.visualizers.handler") -- disabled appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled @@ -81,6 +83,7 @@ appendaction("math", "normalizers", "noads.handlers.tags", nil, "noh appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on +------------("math", "builders", "noads.handlers.italics", nil, "nohead") -- disabled -- quite experimental (nodes.handlers.graphicvadjust might go away) @@ -98,6 +101,7 @@ appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler") -- speedup: only kick in when used +disableaction("processors", "fonts.collections.process") disableaction("processors", "fonts.checkers.missing") disableaction("processors", "chars.handle_breakpoints") disableaction("processors", "typesetters.cleaners.handler") @@ -122,6 +126,7 @@ disableaction("shipouts", "attributes.effects.handler") disableaction("shipouts", "attributes.negatives.handler") disableaction("shipouts", "attributes.viewerlayers.handler") disableaction("shipouts", "structures.tags.handler") +disableaction("shipouts", "nodes.visualizers.handler") disableaction("shipouts", "nodes.handlers.accessibility") disableaction("shipouts", "nodes.handlers.backgrounds") disableaction("shipouts", "nodes.handlers.cleanuppage") diff --git a/tex/context/base/trac-ctx.lua b/tex/context/base/trac-ctx.lua new file mode 100644 index 000000000..813443816 --- /dev/null +++ b/tex/context/base/trac-ctx.lua @@ -0,0 +1,36 @@ +if not modules then modules = { } end modules ['trac-ctx'] = { + version = 1.001, + comment = "companion to trac-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local commands, context = commands, context + +tex.trackers = tex.trackers or { } + +local textrackers = tex.trackers +local register = trackers.register + +storage.register("tex/trackers",textrackers,"tex.trackers") + +local function doit(tag,v) + local tt = textrackers[tag] + if tt then + context.unprotect() + context(v and tt[1] or tt[2]) + context.protect() + end +end + +function commands.initializetextrackers() + for tag, commands in next, textrackers do + register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller + end +end + +function commands.installtextracker(tag,enable,disable) + textrackers[tag] = { enable, disable } + register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller +end diff --git a/tex/context/base/trac-ctx.mkiv b/tex/context/base/trac-ctx.mkiv new file mode 100644 index 000000000..4aeb99116 --- /dev/null +++ b/tex/context/base/trac-ctx.mkiv @@ -0,0 +1,28 @@ + +%D \module +%D [ file=trac-ctx, +%D version=2012.07.13, +%D title=\CONTEXT\ Tracing Macros, +%D subtitle=TeX Trackers, +%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 Tracing Macros / TeX Trackers} + +\registerctxluafile{trac-ctx}{1.001} + +\unprotect + +\unexpanded\def\installtextracker#1#2#3% + {\ctxcommand{installtextracker("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}} + +\appendtoks + \ctxcommand{initializetextrackers()}% +\to \everyjob + +\protect \endinput diff --git a/tex/context/base/trac-deb.lua b/tex/context/base/trac-deb.lua index 87434a13d..9e724f9fa 100644 --- a/tex/context/base/trac-deb.lua +++ b/tex/context/base/trac-deb.lua @@ -94,6 +94,15 @@ end function tracers.showlines(filename,linenumber,offset,errorstr) local data = io.loaddata(filename) + if not data or data == "" then + local hash = url.hashed(filename) + if not hash.noscheme then + local ok, d, n = resolvers.loaders.byscheme(hash.scheme,filename) + if ok and n > 0 then + data = d + end + end + end local lines = data and string.splitlines(data) if lines and #lines > 0 then -- this does not work yet as we cannot access the last lua error @@ -134,7 +143,9 @@ function tracers.showlines(filename,linenumber,offset,errorstr) end function tracers.printerror(offset) - local filename, linenumber = status.filename, tonumber(status.linenumber) or 0 + local inputstack = resolvers.inputstack + local filename = inputstack[#inputstack] or status.filename + local linenumber = tonumber(status.linenumber) or 0 if not filename then report_system("error not related to input file: %s ...",status.lasterrorstring) elseif type(filename) == "number" then diff --git a/tex/context/base/trac-deb.mkiv b/tex/context/base/trac-deb.mkiv index 4f5f0e931..fe5dd02dc 100644 --- a/tex/context/base/trac-deb.mkiv +++ b/tex/context/base/trac-deb.mkiv @@ -13,7 +13,7 @@ \writestatus{loading}{ConTeXt Tracing Macros / Debugger} -\registerctxluafile{trac-lmx}{1.001} +%registerctxluafile{trac-lmx}{1.001} \registerctxluafile{trac-deb}{1.001} \unexpanded\def\breakpoint{\showdebuginfo\wait} @@ -31,7 +31,7 @@ \unexpanded\def\enableexperiments [#1]{\ctxlua{experiments.enable("#1")}} \unexpanded\def\disableexperiments[#1]{\ctxlua{experiments.disable("#1")}} -\unexpanded\def\showdebuginfo{\ctxlua{lmx.showdebuginfo()}} -\unexpanded\def\overloaderror{\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror] +\unexpanded\def\showdebuginfo {\ctxlua{lmx.showdebuginfo()}} +\unexpanded\def\overloaderror {\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror] \unexpanded\def\showlogcategories {\ctxlua{logs.show()}} diff --git a/tex/context/base/trac-fil.lua b/tex/context/base/trac-fil.lua index bf291ff6b..8cc903e2a 100644 --- a/tex/context/base/trac-fil.lua +++ b/tex/context/base/trac-fil.lua @@ -6,18 +6,20 @@ if not modules then modules = { } end modules ['trac-fil'] = { license = "see context related readme files" } +local rawset, tonumber, type, pcall = rawset, tonumber, type, pcall local format, concat = string.format, table.concat local openfile = io.open local date = os.date -local rawset, tonumber = rawset, tonumber +local sortedpairs = table.sortedpairs -local P, C, Cc, Cg, Cf, Ct, Cs = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs +local P, C, Cc, Cg, Cf, Ct, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs, lpeg.Carg +local lpegmatch = lpeg.match local patterns = lpeg.patterns local cardinal = patterns.cardinal local whitespace = patterns.whitespace^0 -patterns.timestamp = Cf(Ct("") * ( +local timestamp = Cf(Ct("") * ( Cg (Cc("year") * (cardinal/tonumber)) * P("-") * Cg (Cc("month") * (cardinal/tonumber)) * P("-") * Cg (Cc("day") * (cardinal/tonumber)) * P(" ") @@ -28,53 +30,65 @@ patterns.timestamp = Cf(Ct("") * ( * Cg (Cc("tminute") * (cardinal/tonumber)) )^0, rawset) -patterns.keysvalues = Cf(Ct("") * ( +local keysvalues = Cf(Ct("") * ( Cg(C(patterns.letter^0) * whitespace * "=" * whitespace * Cs(patterns.unquoted) * whitespace) )^0, rawset) -patterns.statusline = Cf(Ct("") * ( - whitespace * P("[") * Cg(Cc("timestamp") * patterns.timestamp ) * P("]") - * whitespace * Cg(Cc("status" ) * patterns.keysvalues) +local statusline = Cf(Ct("") * ( + whitespace * P("[") * Cg(Cc("timestamp") * timestamp ) * P("]") + * whitespace * Cg(Cc("status" ) * keysvalues) ),rawset) +patterns.keysvalues = keysvalues +patterns.statusline = statusline +patterns.timestamp = timestamp loggers = loggers or { } -local tz = os.timezone(true) - -local bugged = { } - -function loggers.message(filename,t) - if not bugged[filename] then - local f = openfile(filename,"a+") - if not f then - dir.mkdirs(file.dirname(filename)) - f = openfile(filename,"a+") - end - if f then - f:write("[",date("!%Y-%m-%d %H:%M:%S"),tz,"]") - for k, v in table.sortedpairs(t) do - f:write(" ",k,'="',v,'"') +local timeformat = format("[%%s%s]",os.timezone(true)) +local dateformat = "!%Y-%m-%d %H:%M:%S" + +function loggers.makeline(t) + local result = { } -- minimize time that file is open + result[#result+1] = format(timeformat,date(dateformat)) + for k, v in sortedpairs(t) do + local tv = type(v) + if tv == "string" then + if v ~= "password" then + result[#result+1] = format(" %s=%q",k,v) end - f:write("\n") - f:close() - else - bugged[filename] = true + elseif tv == "number" or tv == "boolean" then + result[#result+1] = format(" %s=%q",k,tostring(v)) end end + return concat(result," ") +end + +local function append(filename,...) + local f = openfile(filename,"a+") + if not f then + dir.mkdirs(file.dirname(filename)) + f = openfile(filename,"a+") + end + if f then + f:write(...) + f:close() + return true + else + return false + end end ---~ function loggers.collect(filename) ---~ if lfs.isfile(filename) then ---~ return lpeg.match(Ct(patterns.statusline^0),io.loaddata(filename)) ---~ else ---~ return { } ---~ end ---~ end +function loggers.store(filename,data) -- a log service is nicer + if type(data) == "table"then + data = loggers.makeline(data) + end + pcall(append,filename,data,"\n") +end function loggers.collect(filename,result) if lfs.isfile(filename) then - local r = lpeg.match(Ct(patterns.statusline^0),io.loaddata(filename)) + local r = lpegmatch(Ct(statusline^0),io.loaddata(filename)) if result then -- append local nofresult = #result for i=1,#r do @@ -90,60 +104,78 @@ function loggers.collect(filename,result) end end ---~ local template = [[ ---~ <table> ---~ <tr>%s</tr> ---~ %s ---~ </table> ---~ ]] - ---~ function loggers.tohtml(entries,fields) ---~ if not fields or #fields == 0 then ---~ return "" ---~ end ---~ if type(entries) == "string" then ---~ entries = loggers.collect(entries) ---~ end ---~ local scratch, lines = { }, { } ---~ for i=1,#entries do ---~ local entry = entries[i] ---~ local status = entry.status ---~ for i=1,#fields do ---~ local field = fields[i] ---~ local v = status[field.name] ---~ if v ~= nil then ---~ v = tostring(v) ---~ local f = field.format ---~ if f then v = format(f,v) end ---~ scratch[i] = format("<td nowrap='nowrap' align='%s'>%s</td>",field.align or "left",v) ---~ else ---~ scratch[i] = "<td/>" ---~ end ---~ end ---~ lines[i] = "<tr>" .. concat(scratch) .. "</tr>" ---~ end ---~ for i=1,#fields do ---~ local field = fields[i] ---~ scratch[i] = format("<th nowrap='nowrap' align='left'>%s</th>", field.label or field.name) ---~ end ---~ local result = format(template,concat(scratch),concat(lines,"\n")) ---~ return result, entries ---~ end - ---~ -- loggers.message("test.log","name","whatever","more",123) - ---~ local fields = { ---~ -- { name = "id", align = "left" }, ---~ -- { name = "timestamp", align = "left" }, ---~ { name = "assessment", align = "left" }, ---~ { name = "assessmentname", align = "left" }, ---~ -- { name = "category", align = "left" }, ---~ { name = "filesize", align = "right" }, ---~ { name = "nofimages", align = "center" }, ---~ -- { name = "product", align = "left" }, ---~ { name = "resultsize", align = "right" }, ---~ { name = "fetchtime", align = "right", format = "%2.3f" }, ---~ { name = "runtime", align = "right", format = "%2.3f" }, ---~ { name = "organization", align = "left" }, ---~ -- { name = "username", align = "left" }, ---~ } +function loggers.fields(results) -- returns hash of fields with counts so that we can decide on importance + local fields = { } + if results then + for i=1,#results do + local r = results[i] + for k, v in next, r do + local f = fields[k] + if not f then + fields[k] = 1 + else + fields[k] = f + 1 + end + end + end + end + return fields +end + +local template = [[<!-- log entries: begin --!> +<table> +<tr>%s</tr> +%s +</table> +<!-- log entries: end --!> +]] + +function loggers.tohtml(entries,fields) + if not fields or #fields == 0 then + return "" + end + if type(entries) == "string" then + entries = loggers.collect(entries) + end + local scratch, lines = { }, { } + for i=1,#entries do + local entry = entries[i] + local status = entry.status + for i=1,#fields do + local field = fields[i] + local v = status[field.name] + if v ~= nil then + v = tostring(v) + local f = field.format + if f then + v = format(f,v) + end + scratch[i] = format("<td nowrap='nowrap' align='%s'>%s</td>",field.align or "left",v) + else + scratch[i] = "<td/>" + end + end + lines[i] = format("<tr>%s</tr>",concat(scratch)) + end + for i=1,#fields do + local field = fields[i] + scratch[i] = format("<th nowrap='nowrap' align='left'>%s</th>", field.label or field.name) + end + local result = format(template,concat(scratch),concat(lines,"\n")) + return result, entries +end + +-- loggers.store("test.log", { name = "whatever", more = math.random(1,100) }) + +-- local fields = { +-- { name = "name", align = "left" }, +-- { name = "more", align = "right" }, +-- } + +-- local entries = loggers.collect("test.log") +-- local html = loggers.tohtml(entries,fields) + +-- inspect(entries) +-- inspect(fields) +-- inspect(html) + diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua index cbc9d13f8..6ba3d348e 100644 --- a/tex/context/base/trac-inf.lua +++ b/tex/context/base/trac-inf.lua @@ -13,7 +13,7 @@ if not modules then modules = { } end modules ['trac-inf'] = { local format, lower = string.format, string.lower local clock = os.gettimeofday or os.clock -- should go in environment -local write_nl = texio.write_nl +local write_nl = texio and texio.write_nl or print statistics = statistics or { } local statistics = statistics @@ -96,7 +96,7 @@ statistics.elapsedtime = elapsedtime statistics.elapsedindeed = elapsedindeed statistics.elapsedseconds = elapsedseconds --- general function +-- general function .. we might split this module function statistics.register(tag,fnc) if statistics.enable and type(fnc) == "function" then diff --git a/tex/context/base/trac-lmx.lua b/tex/context/base/trac-lmx.lua index 452d03002..97938fb77 100644 --- a/tex/context/base/trac-lmx.lua +++ b/tex/context/base/trac-lmx.lua @@ -6,42 +6,62 @@ if not modules then modules = { } end modules ['trac-lmx'] = { license = "see context related readme files" } --- todo: use lpeg instead (although not really needed) +local type, tostring, rawget, loadstring, pcall = type, tostring, rawget, loadstring, pcall +local format, sub, gsub = string.format, string.sub, string.gsub +local concat = table.concat +local P, Cc, Cs, C, Carg, lpegmatch = lpeg.P, lpeg.Cc, lpeg.Cs, lpeg.C, lpeg.Carg, lpeg.match -local gsub, format, concat, byte = string.gsub, string.format, table.concat, string.byte +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local allocate = utilities.storage.allocate +----- trace_templates = false trackers .register("lmx.templates", function(v) trace_templates = v end) +local trace_variables = false trackers .register("lmx.variables", function(v) trace_variables = v end) -lmx = lmx or { } -local lmx = lmx +local cache_templates = true directives.register("lmx.cache.templates",function(v) cache_templates = v end) +local cache_files = true directives.register("lmx.cache.files", function(v) cache_files = v end) -lmx.variables = allocate() -local lmxvariables = lmx.variables +local report_lmx = logs.reporter("lmx") +local report_error = logs.reporter("lmx","error") -local escapes = allocate { - ['&'] = '&', - ['<'] = '<', - ['>'] = '>', - ['"'] = '"' -} +lmx = lmx or { } +local lmx = lmx + +-- This will change: we will just pass the global defaults as argument, but then we need +-- to rewrite some older code or come up with an ugly trick. --- variables +local lmxvariables = { + ['title-default'] = 'ConTeXt LMX File', + ['color-background-green'] = '#4F6F6F', + ['color-background-blue'] = '#6F6F8F', + ['color-background-yellow'] = '#8F8F6F', + ['color-background-purple'] = '#8F6F8F', + ['color-background-body'] = '#808080', + ['color-background-main'] = '#3F3F3F', +} -lmxvariables['title-default'] = 'ConTeXt LMX File' -lmxvariables['title'] = lmx.variables['title-default'] -lmxvariables['color-background-green'] = '#4F6F6F' -lmxvariables['color-background-blue'] = '#6F6F8F' -lmxvariables['color-background-yellow'] = '#8F8F6F' -lmxvariables['color-background-purple'] = '#8F6F8F' -lmxvariables['color-background-body'] = '#808080' -lmxvariables['color-background-main'] = '#3F3F3F' -lmxvariables['color-background-one'] = lmxvariables['color-background-green'] -lmxvariables['color-background-two'] = lmxvariables['color-background-blue'] +local lmxinherited = { + ['title'] = 'title-default', + ['color-background-one'] = 'color-background-green', + ['color-background-two'] = 'color-background-blue', + ['color-background-three'] = 'color-background-one', + ['color-background-four'] = 'color-background-two', +} -lmxvariables['color-background-three'] = function() return lmxvariables['color-background-one'] end -lmxvariables['color-background-four'] = function() return lmxvariables['color-background-two'] end +lmx.variables = lmxvariables +lmx.inherited = lmxinherited + +setmetatableindex(lmxvariables,function(t,k) + k = lmxinherited[k] + while k do + local v = rawget(lmxvariables,k) + if v then + return v + end + k = lmxinherited[k] + end +end) -function lmx.set(key, value) +function lmx.set(key,value) lmxvariables[key] = value end @@ -49,9 +69,16 @@ function lmx.get(key) return lmxvariables[key] or "" end +lmx.report = report_lmx + -- helpers -local variables, result = { } -- we assume no nesting +-- the variables table is an empty one that gets linked to a defaults table +-- that gets passed with a creation (first time only) and that itself links +-- to one that gets passed to the converter + +local variables = { } -- we assume no nesting +local result = { } -- we assume no nesting local function do_print(one,two,...) if two then @@ -61,40 +88,125 @@ local function do_print(one,two,...) end end -local function do_escape(str) - str = tostring(str) - str = gsub(str,'&','&') - str = gsub(str,'[<>"]',escapes) - return str +-- Although it does not make much sense for most elements, we provide a mechanism +-- to print wrapped content, something that is more efficient when we are constructing +-- tables. + +local html = { } +lmx.html = html + +function html.td(str) + if type(str) == "table" then + for i=1,#str do -- spoils t ! + str[i] = format("<td>%s</td>",str[i] or "") + end + result[#result+1] = concat(str) + else + result[#result+1] = format("<td>%s</td>",str or "") + end end -local function do_urlescaped(str) - return (gsub(str,"[^%a%d]",format("%%0x",byte("%1")))) +function html.th(str) + if type(str) == "table" then + for i=1,#str do -- spoils t ! + str[i] = format("<th>%s</th>",str[i]) + end + result[#result+1] = concat(str) + else + result[#result+1] = format("<th>%s</th>",str or "") + end end -local function do_type(str) - if str then do_print("<tt>" .. do_escape(str) .. "</tt>") end +function html.a(text,url) + result[#result+1] = format("<a href=%q>%s</a>",url,text) +end + +setmetatableindex(html,function(t,k) + local f = format("<%s>%%s</%s>",k,k) + local v = function(str) result[#result+1] = format(f,str or "") end + t[k] = v + return v +end) + +-- Loading templates: + +local function loadedfile(name) + name = (resolvers and resolvers.findfile and resolvers.findfile(name)) or name + local data = io.loaddata(name) + if not data or data == "" then + report_lmx("empty file: %s",name) + end + return data +end + +lmx.loadedfile = loadedfile + +-- A few helpers (the next one could end up in l-lpeg): + +local pattern = lpeg.replacer { + ["&"] = "&", + [">"] = ">", + ["<"] = "<", + ['"'] = """, +} + +local function do_escape(str) + return lpegmatch(pattern,str) or str end local function do_variable(str) - local value = variables[str] or lmxvariables[str] -- or format("<!-- unset lmx instance variable: %s -->",str or "?") - if type(value) == "function" then + local value = variables[str] + if not trace_variables then + -- nothing + elseif type(value) == "string" then + if #value > 80 then + report_lmx("variable %q => %s ...",str,string.collapsespaces(sub(value,1,80))) + else + report_lmx("variable %q => %s",str,string.collapsespaces(value)) + end + elseif type(value) == "nil" then + report_lmx("variable %q => <!-- unset -->",str) + else + report_lmx("variable %q => %q",str,tostring(value)) + end + if type(value) == "function" then -- obsolete ... will go away return value(str) else return value end end -function lmx.loadedfile(name) - name = (resolvers and resolvers.findfile and resolvers.findfile(name)) or name - return io.loaddata(name) +local function do_type(str) + if str and str ~= "" then + result[#result+1] = format("<tt>%s</tt>",do_escape(str)) + end +end + +local function do_fprint(str,...) + if str and str ~= "" then + result[#result+1] = format(str,...) + end end -local function do_include(filename) - local stylepath = do_variable('includepath') -- todo: store paths of loaded files - local data = lmx.loadedfile(filename) +local function do_print_variable(str) + local str = do_variable(str) -- variables[str] + if str and str ~= "" then + result[#result+1] = str + end +end + +local function do_type_variable(str) + local str = do_variable(str) -- variables[str] + if str and str ~= "" then + result[#result+1] = format("<tt>%s</tt>",do_escape(str)) + end +end + +local function do_include(filename) -- todo: store paths of loaded files + local stylepath = lmxvariables.includepath + local data = loadedfile(filename) if (not data or data == "") and stylepath and stylepath ~= "" then - data = lmx.loadedfile(file.join(stylepath,filename)) + data = loadedfile(file.join(stylepath,filename)) end if not data or data == "" then data = format("<!-- unknown lmx include file: %s -->",filename) @@ -102,132 +214,400 @@ local function do_include(filename) return data end +-- Flushers: + lmx.print = do_print lmx.type = do_type +lmx.fprint = do_fprint + lmx.escape = do_escape -lmx.urlescape = do_escape +lmx.urlescape = url.escape lmx.variable = do_variable lmx.include = do_include -function lmx.pv(str) - do_print(do_variable(str) or "") +lmx.inject = do_print +lmx.finject = do_fprint + +lmx.pv = do_print_variable +lmx.tv = do_type_variable + +-- The next functions set up the closure. + +function lmx.initialize(d,v) + if not v then + setmetatableindex(d,lmxvariables) + if variables ~= d then + setmetatableindex(variables,d) + if trace_variables then + report_lmx("variables => given defaults => lmx variables") + end + elseif trace_variables then + report_lmx("variables == given defaults => lmx variables") + end + elseif d ~= v then + setmetatableindex(v,d) + if d ~= lmxvariables then + setmetatableindex(d,lmxvariables) + if variables ~= v then + setmetatableindex(variables,v) + if trace_variables then + report_lmx("variables => given variables => given defaults => lmx variables") + end + elseif trace_variables then + report_lmx("variables == given variables => given defaults => lmx variables") + end + else + if variables ~= v then + setmetatableindex(variables,v) + if trace_variables then + report_lmx("variabes => given variables => given defaults") + end + elseif trace_variables then + report_lmx("variables == given variables => given defaults") + end + end + else + setmetatableindex(v,lmxvariables) + if variables ~= v then + setmetatableindex(variables,v) + if trace_variables then + report_lmx("variables => given variables => lmx variables") + end + elseif trace_variables then + report_lmx("variables == given variables => lmx variables") + end + end + result = { } +end + +function lmx.finalized() + local collapsed = concat(result) + result = { } -- free memory + return collapsed +end + +function lmx.getvariables() + return variables end -function lmx.tv(str) - lmx.type(do_variable(str) or "") +function lmx.reset() + -- obsolete end +-- Creation: (todo: strip <!-- -->) + local template = [[ - local definitions = { } - local p, v, e, t, pv, tv = lmx.print, lmx.variable, lmx.escape, lmx.type, lmx.pv, lmx.tv - %s +return function(defaults,variables) + +-- initialize + +lmx.initialize(defaults,variables) + +-- interface + +local definitions = { } +local variables = lmx.getvariables() +local html = lmx.html +local inject = lmx.print +local finject = lmx.fprint +local escape = lmx.escape +local verbose = lmx.type + +-- shortcuts (sort of obsolete as there is no gain) + +local p = lmx.print +local f = lmx.fprint +local v = lmx.variable +local e = lmx.escape +local t = lmx.type +local pv = lmx.pv +local tv = lmx.tv + +-- generator + +%s + +-- finalize + +return lmx.finalized() + +end ]] +local function savedefinition(definitions,tag,content) + definitions[tag] = content + return "" +end + +local function getdefinition(definitions,tag) + return definitions[tag] or "" +end + +local whitespace = lpeg.patterns.whitespace +local optionalspaces = whitespace^0 + +local begincomment = P("<!--") +local endcomment = P("-->") + +local beginembedxml = P("<?") +local endembedxml = P("?>") + +local beginembedcss = P("/*") +local endembedcss = P("*/") + +local gobbledend = (optionalspaces * endembedxml) / "" +local argument = (1-gobbledend)^0 + +local comment = (begincomment * (1-endcomment)^0 * endcomment) / "" + +local beginluaxml = (beginembedxml * P("lua")) / "" +local endluaxml = endembedxml / "" + +local luacodexml = beginluaxml + * (1-endluaxml)^1 + * endluaxml + +local beginluacss = (beginembedcss * P("lua")) / "" +local endluacss = endembedcss / "" + +local luacodecss = beginluacss + * (1-endluacss)^1 + * endluacss + +local othercode = (1-beginluaxml-beginluacss)^1 / " p[==[%0]==] " + +local include = ((beginembedxml * P("lmx-include") * optionalspaces) / "") + * (argument / lmx.include) + * gobbledend + +local define_b = ((beginembedxml * P("lmx-define-begin") * optionalspaces) / "") + * argument + * gobbledend + +local define_e = ((beginembedxml * P("lmx-define-end") * optionalspaces) / "") + * argument + * gobbledend + +local define_c = C((1-define_e)^0) + +local define = (Carg(1) * C(define_b) * define_c * define_e) / savedefinition + +local resolve = ((beginembedxml * P("lmx-resolve") * optionalspaces) / "") + * ((Carg(1) * C(argument)) / getdefinition) + * gobbledend + +local pattern_1 = Cs((comment + include + P(1))^0) -- get rid of comments asap +local pattern_2 = Cs((define + resolve + P(1))^0) +local pattern_3 = Cs((luacodexml + luacodecss + othercode)^0) + local cache = { } -local trace = false +local function lmxerror(str) + report_error(str) + return html.tt(str) +end + +local function wrapper(converter,defaults,variables) + local outcome, message = pcall(converter,defaults,variables) + if not outcome then + return lmxerror(format("error in conversion: %s",message)) + else + return message + end +end -function lmx.new(data,variables) +function lmxnew(data,defaults,nocache) -- todo: use defaults in calling routines data = data or "" local known = cache[data] if not known then - local definitions = { } - data = gsub(data,"<%?lmx%-include%s+(.-)%s-%?>", function(filename) - return lmx.include(filename) - end) - local definitions = { } - data = gsub(data,"<%?lmx%-define%-begin%s+(%S-)%s-%?>(.-)<%?lmx%-define%-end%s-%?>", function(tag,content) - definitions[tag] = content - return "" - end) - data = gsub(data,"<%?lmx%-resolve%s+(%S-)%s-%?>", function(tag) - return definitions[tag] or "" - end) - data = gsub(data .. "<?lua ?>","(.-)<%?lua%s+(.-)%s*%?>", function(txt,lua) - txt = gsub(txt,"%c+","\n") - return format("p(%q)%s ",txt,lua) -- nb! space - end) - data = format(template,data) + data = lpegmatch(pattern_1,data) + data = lpegmatch(pattern_2,data,1,{}) + data = lpegmatch(pattern_3,data) + local converted = loadstring(format(template,data)) + if converted then + converted = converted() + end + defaults = defaults or { } + local converter + if converted then + converter = function(variables) + return wrapper(converted,defaults,variables) + end + else + converter = function() lmxerror("error in template") end + end known = { - data = trace and data, - variables = variables or { }, - converter = loadstring(data), + data = defaults.trace and data or "", + variables = defaults, + converter = converter, } + if cache_templates and nocache ~= false then + cache[data] = known + end elseif variables then known.variables = variables end return known, known.variables end -function lmx.reset(self) - self.variables = { } -end - -function lmx.result(self) - if trace then - return self.data +local function lmxresult(self,variables) + if self then + local converter = self.converter + if converter then + local converted = converter(variables) + if trace_variables then -- will become templates + report_lmx("converted size: %s",#converted) + end + return converted or lmxerror("no result from converter") + else + return lmxerror("invalid converter") + end else - variables, result = self.variables, { } - self.converter() - return concat(result) + return lmxerror("invalid specification") end end --- file converter +lmx.new = lmxnew +lmx.result = lmxresult -local loaded = { } +local loadedfiles = { } -function lmx.convert(templatefile,resultfile,variables) - local data = loaded[templatefile] - if not data then - data = lmx.new(lmx.loadedfile(templatefile),variables) - loaded[template] = data - elseif variables then - data.variables = variables +function lmx.convertstring(templatestring,variables,nocache) + return lmxresult(lmxnew(templatestring,nil,nocache),variables) +end + +function lmx.convertfile(templatefile,variables,nocache) + if trace_variables then -- will become templates + report_lmx("converting file: %s",templatefile) + end + local converter = loadedfiles[templatefile] + if not converter then + converter = lmxnew(loadedfile(templatefile),nil,nocache) + loadedfiles[templatefile] = converter end - local result = lmx.result(data) + return lmxresult(converter,variables) +end + +function lmxconvert(templatefile,resultfile,variables,nocache) -- or (templatefile,variables) + if trace_variables then -- will become templates + report_lmx("converting file: %s",templatefile) + end + if not variables and type(resultfile) == "table" then + variables = resultfile + end + local converter = loadedfiles[templatefile] + if not converter then + converter = lmxnew(loadedfile(templatefile),nil,nocache) + if cache_files then + loadedfiles[templatefile] = converter + end + end + local result = lmxresult(converter,variables) if resultfile then io.savedata(resultfile,result) else - return lmx.result(data,result) + return result end end --- these can be overloaded; we assume that the os handles filename associations +lmx.convert = lmxconvert + +-- helpers + +local nocomment = (beginembedcss * (1 - endembedcss)^1 * endembedcss) / "" +local nowhitespace = whitespace^1 / " " -- "" +local semistripped = whitespace^1 / "" * P(";") +local stripper = Cs((nocomment + semistripped + nowhitespace + 1)^1) -lmx.lmxfile = function(filename) return filename end -- beware, these can be set! -lmx.htmfile = function(filename) return filename end -- beware, these can be set! +function lmx.stripcss(str) + return lpegmatch(stripper,str) +end -if os.type == "windows" then - lmx.popupfile = function(filename) os.execute("start " .. filename) end -else - lmx.popupfile = function(filename) os.execute(filename) end +function lmx.color(r,g,b,a) + if r > 1 then + r = 1 + end + if g > 1 then + g = 1 + end + if b > 1 then + b = 1 + end + if not a then + a= 0 + elseif a > 1 then + a = 1 + end + if a > 0 then + return string.format("rgba(%s%%,%s%%,%s%%,%s)",r*100,g*100,b*100,a) + else + return string.format("rgb(%s%%,%s%%,%s%%)",r*100,g*100,b*100) + end end -function lmx.make(name,variables) + +-- these can be overloaded + +lmx.lmxfile = string.itself +lmx.htmfile = string.itself +lmx.popupfile = os.launch + +function lmxmake(name,variables) local lmxfile = lmx.lmxfile(name) local htmfile = lmx.htmfile(name) if lmxfile == htmfile then - htmfile = gsub(lmxfile, "%.%a+$", "html") + htmfile = file.replacesuffix(lmxfile,"html") end - lmx.convert(lmxfile,htmfile,variables) + lmxconvert(lmxfile,htmfile,variables) return htmfile end +lmxmake = lmx.make + function lmx.show(name,variables) - local htmfile = lmx.make(name,variables) + local htmfile = lmxmake(name,variables) lmx.popupfile(htmfile) return htmfile end --- test - ---~ print(lmx.result(lmx.new(io.loaddata("t:/sources/context-timing.lmx")))) - --- command line +-- Command line (will become mtx-lmx): if arg then if arg[1] == "--show" then if arg[2] then lmx.show (arg[2]) end elseif arg[1] == "--convert" then if arg[2] then lmx.convert(arg[2], arg[3] or "temp.html") end end end + +-- Test 1: + +-- inspect(lmx.result(lmx.new(io.loaddata("t:/sources/context-timing.lmx")))) + +-- Test 2: + +-- local str = [[ +-- <?lmx-include somefile.css ?> +-- <test> +-- <?lmx-define-begin whatever?>some content a<?lmx-define-end ?> +-- <?lmx-define-begin somemore?>some content b<?lmx-define-end ?> +-- <more> +-- <?lmx-resolve whatever ?> +-- <?lua +-- for i=1,10 do end +-- ?> +-- <?lmx-resolve somemore ?> +-- </more> +-- <td><?lua p(100) ?></td> +-- <td><?lua p(variables.a) ?></td> +-- <td><?lua p(variables.b) ?></td> +-- <td><?lua p(variables.c) ?></td> +-- <td><?lua pv('title-default') ?></td> +-- </test> +-- ]] +-- +-- local defaults = { trace = true, a = 3, b = 3 } +-- local result = lmx.new(str,defaults) +-- inspect(result.data) +-- inspect(result.converter(defaults)) +-- inspect(result.converter { a = 1 }) +-- inspect(lmx.result(result, { b = 2 })) +-- inspect(lmx.result(result, { a = 20000, b = 40000 })) diff --git a/tex/context/base/trac-set.lua b/tex/context/base/trac-set.lua index bc0070eb4..bac448f77 100644 --- a/tex/context/base/trac-set.lua +++ b/tex/context/base/trac-set.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u license = "see context related readme files" } +-- maybe this should be util-set.lua + local type, next, tostring = type, next, tostring local concat = table.concat local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern @@ -205,7 +207,7 @@ function setters.show(t) local value, default, modules = functions.value, functions.default, #functions value = value == nil and "unset" or tostring(value) default = default == nil and "unset" or tostring(default) - t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value) + t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value) end end t.report() @@ -297,17 +299,31 @@ end) -- experiment -local flags = environment and environment.engineflags +if environment then -if flags then - if trackers and flags.trackers then - setters.initialize("flags","trackers", settings_to_hash(flags.trackers)) - -- t_enable(flags.trackers) - end - if directives and flags.directives then - setters.initialize("flags","directives", settings_to_hash(flags.directives)) - -- d_enable(flags.directives) + -- The engineflags are known earlier than environment.arguments but maybe we + -- need to handle them both as the later are parsed differently. The c: prefix + -- is used by mtx-context to isolate the flags from those that concern luatex. + + local engineflags = environment.engineflags + + if engineflags then + if trackers then + local list = engineflags["c:trackers"] or engineflags["trackers"] + if type(list) == "string" then + setters.initialize("flags","trackers",settings_to_hash(list)) + -- t_enable(list) + end + end + if directives then + local list = engineflags["c:directives"] or engineflags["directives"] + if type(list) == "string" then + setters.initialize("flags","directives", settings_to_hash(list)) + -- d_enable(list) + end + end end + end -- here diff --git a/tex/context/base/trac-tex.lua b/tex/context/base/trac-tex.lua index 7920bd1cb..362a1dd67 100644 --- a/tex/context/base/trac-tex.lua +++ b/tex/context/base/trac-tex.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['trac-hsh'] = { +if not modules then modules = { } end modules ['trac-tex'] = { version = 1.001, comment = "companion to trac-deb.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", diff --git a/tex/context/base/trac-tim.lua b/tex/context/base/trac-tim.lua index de7ceca46..adc8e01b5 100644 --- a/tex/context/base/trac-tim.lua +++ b/tex/context/base/trac-tim.lua @@ -59,7 +59,7 @@ end local processed = { } local function convert(name) - name = ((name ~= "") and name) or progress.defaultfilename + name = name ~= "" and name or progress.defaultfilename if not processed[name] then local names, top, bot, pages, paths, keys = { }, { }, { }, 0, { }, { } local data = io.loaddata(name .. ".lut") diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua new file mode 100644 index 000000000..3876d0907 --- /dev/null +++ b/tex/context/base/trac-vis.lua @@ -0,0 +1,859 @@ +if not modules then modules = { } end modules ['trac-vis'] = { + version = 1.001, + 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 string, number, table = string, number, table +local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex + +local format = string.format + +-- 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. + +-- We could use pdf literals and re stream codes but it's not worth the +-- trouble because we would end up in color etc mess. Maybe one day I'll +-- make a nodeinjection variant. + +-- todo: global switch (so no attributes) +-- todo: maybe also xoffset, yoffset of glyph +-- todo: inline concat (more efficient) + +local nodecodes = nodes.nodecodes +local disc_code = nodecodes.disc +local kern_code = nodecodes.kern +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local whatsit_code = nodecodes.whatsit +local user_code = nodecodes.user + +local kerncodes = nodes.kerncodes +local font_kern_code = kerncodes.fontkern +local user_kern_code = kerncodes.userkern + +local gluecodes = nodes.gluecodes +local cleaders_code = gluecodes.cleaders +local userskip_code = gluecodes.userskip +local space_code = gluecodes.space +local xspace_code = gluecodes.xspace +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip + +local whatsitcodes = nodes.whatsitcodes + +local concat_nodes = nodes.concat +local hpack_nodes = node.hpack +local vpack_nodes = node.vpack +local hpack_string = typesetters.hpack +local fast_hpack_string = typesetters.fast_hpack +local copy_node = node.copy +local copy_list = node.copy_list +local free_node = node.free +local free_node_list = node.flush_list +local has_attribute = node.has_attribute +local set_attribute = node.set_attribute +local unset_attribute = node.unset_attribute +local insert_before = node.insert_before +local insert_after = node.insert_after +local fast_hpack = nodes.fasthpack + +local tex_attribute = tex.attribute +local unsetvalue = attributes.unsetvalue + +local current_font = font.current + +local exheights = fonts.hashes.exheights +local emwidths = fonts.hashes.emwidths +local pt_factor = number.dimenfactors.pt + +local nodepool = nodes.pool +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_glue = nodepool.glue +local new_penalty = nodepool.penalty + +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 function setlistattribute(list,a,v) +-- while list do +-- set_attribute(list,a,v) +-- list = list.next +-- end +-- end + +local a_visual = attributes.private("visual") +local a_fontkern = attributes.private("fontkern") +local a_layer = attributes.private("viewerlayer") + +local hasbit = number.hasbit +local bit = number.bit +local setbit = number.setbit +local clearbit = number.clearbit + +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 report_visualize = logs.reporter("visualize") + +local modes = { + hbox = 1, + vbox = 2, + vtop = 4, + kern = 8, + glue = 16, + penalty = 32, + fontkern = 64, + strut = 128, + whatsit = 256, + glyph = 512, + simple = 1024, + simplehbox = 1024 + 1, + simplevbox = 1024 + 2, + simplevtop = 1024 + 4, + user = 2048, +} + +local modes_makeup = { "hbox", "vbox", "kern", "glue", "penalty" } +local modes_boxes = { "hbox", "vbox" } +local modes_all = { "hbox", "vbox", "kern", "glue", "penalty", "fontkern", "whatsit", "glyph", "user" } + +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 + +local enabled = false +local layers = { } + +function visualizers.setfont(id) + usedfont = id or current_font() + exheight = exheights[usedfont] + emwidth = emwidths[usedfont] +end + +local function setvisual(n,a,what) -- this will become more efficient when we have the bit lib linked in + if not n or n == "reset" then + return unsetvalue + elseif n == "makeup" then + for i=1,#modes_makeup do + a = setvisual(modes_makeup[i],a) + end + elseif n == "boxes" then + for i=1,#modes_boxes do + a = setvisual(modes_boxes[i],a) + end + elseif n == "all" then + if what == false then + return unsetvalue + else + for i=1,#modes_all do + a = setvisual(modes_all[i],a) + end + end + else + local m = modes[n] + if m then + if a == unsetvalue then + if what == false then + return unsetvalue + else + a = setbit(0,m) + end + elseif what == false then + a = clearbit(a,m) + else + a = setbit(a,m) + end + elseif not a then + return unsetvalue + end + end + if a == unsetvalue or a == 0 then + return unsetvalue + elseif not enabled then -- must happen at runtime (as we don't store layers yet) + if not usedfont then + -- we use a narrow monospaced font + visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") }) + end + for mode, value in next, modes do + local tag = format("v_%s",mode) + attributes.viewerlayers.define { + tag = format(tag), + title = format("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 + nodes.tasks.enableaction("shipouts","nodes.visualizers.handler") + report_visualize("enabled") + enabled = true + end + return a +end + +function visualizers.setvisual(n) + tex_attribute[a_visual] = setvisual(n,tex_attribute[a_visual]) +end + +function visualizers.setlayer(n) + tex_attribute[a_layer] = layers[n] or unsetvalue +end + +commands.setvisual = visualizers.setvisual +commands.setlayer = visualizers.setlayer + +function commands.visual(n) + context(setvisual(n,0)) +end + +local function set(mode,v) + tex_attribute[a_visual] = setvisual(mode,tex_attribute[a_visual],v) +end + +for mode, value in next, modes do + trackers.register(format("visualizers.%s",mode), function(v) set(mode,v) end) +end + +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) + +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_skip_a = "trace:c" +local c_skip_b = "trace:m" +local c_glyph = "trace:o" + +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_skip_a_d = "trace:dc" +local c_skip_b_d = "trace:dm" +local c_glyph_d = "trace:do" + +local function sometext(str,layer,color) + local text = fast_hpack_string(str,usedfont) + local size = text.width + local rule = new_rule(size,2*exheight,exheight/2) + local kern = new_kern(-size) + setcolor(rule,color) + local info = concat_nodes { + rule, + kern, + text, + } + setlisttransparency(info,c_zero) + info = fast_hpack(info) + if layer then + set_attribute(info,a_layer,layer) + end + local width = info.width + info.width = 0 + info.height = 0 + info.depth = 0 + return info, width +end + +local f_cache = { } + +local function fontkern(head,current) + local kern = current.kern + local info = f_cache[kern] + if info then + -- print("hit fontkern") + else + local text = fast_hpack_string(format(" %0.3f",kern*pt_factor),usedfont) + local rule = new_rule(emwidth/10,6*exheight,2*exheight) + local list = text.list + 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,c_text_d) + settransparency(rule,c_text_d) + text.shift = -5 * exheight + info = concat_nodes { + rule, + text, + } + info = fast_hpack(info) + set_attribute(info,a_layer,l_fontkern) + info.width = 0 + info.height = 0 + info.depth = 0 + f_cache[kern] = info + end + head = insert_before(head,current,copy_list(info)) + return head, current +end + +local w_cache = { } + +local tags = { + open = "FIC", + write = "FIW", + close = "FIC", + special = "SPE", + localpar = "PAR", + dir = "DIR", + pdfliteral = "PDF", + pdfrefobj = "PDF", + pdfrefxform = "PDF", + pdfrefximage = "PDF", + pdfannot = "PDF", + pdfstartlink = "PDF", + pdfendlink = "PDF", + pdfdest = "PDF", + pdfthread = "PDF", + pdfstartthread = "PDF", + pdfendthread = "PDF", + pdfsavepos = "PDF", + pdfthreaddata = "PDF", + pdflinkdata = "PDF", + pdfcolorstack = "PDF", + pdfsetmatrix = "PDF", + pdfsave = "PDF", + pdfrestore = "PDF", + latelua = "LUA", + closelua = "LUA", + cancelboundary = "CBD", + userdefined = "USR", +} + +local function whatsit(head,current) + local what = current.subtype + local info = w_cache[what] + if info then + -- print("hit whatsit") + else + local tag = whatsitcodes[what] + info = sometext(format("W:%s",tag and tags[tag] or what),usedfont) + set_attribute(info,a_layer,l_whatsit) + w_cache[what] = info + end + head, current = insert_after(head,current,copy_list(info)) + return head, current +end + +local function user(head,current) + local what = current.subtype + local info = w_cache[what] + if info then + -- print("hit user") + else + info = sometext(format("U:%s",what),usedfont) + set_attribute(info,a_layer,l_user) + w_cache[what] = info + end + head, current = insert_after(head,current,copy_list(info)) + return head, current +end + +local b_cache = { } + +local function ruledbox(head,current,vertical,layer,what,simple) + local wd = current.width + if wd ~= 0 then + local ht, dp = current.height, current.depth + local next, prev = current.next, current.prev + current.next, current.prev = nil, nil + local linewidth = emwidth/10 + local baseline, baseskip + if dp ~= 0 and ht ~= 0 then + if wd > 20*linewidth then + baseline = b_cache.baseline + if not baseline then + -- due to an optimized leader color/transparency we need to set the glue node in order + -- to trigger this mechanism + local leader = concat_nodes { + new_glue(2*linewidth), -- 2.5 + new_rule(6*linewidth,linewidth,0), -- 5.0 + new_glue(2*linewidth), -- 2.5 + } + -- setlisttransparency(leader,c_text) + leader = fast_hpack(leader) + -- setlisttransparency(leader,c_text) + baseline = new_glue(0) + baseline.leader = leader + baseline.subtype = cleaders_code + baseline.spec.stretch = 65536 + baseline.spec.stretch_order = 2 + setlisttransparency(baseline,c_text) + b_cache.baseline = baseline + end + baseline = copy_list(baseline) + baseline = fast_hpack(baseline,wd-2*linewidth) + -- or new hpack node, set head and also: + -- baseline.width = wd + -- baseline.glue_set = wd/65536 + -- baseline.glue_order = 2 + -- baseline.glue_sign = 1 + baseskip = new_kern(-wd+linewidth) + else + baseline = new_rule(wd-2*linewidth,linewidth,0) + baseskip = new_kern(-wd+2*linewidth) + end + end + local this + if not simple then + this = b_cache[what] + if not this then + local text = fast_hpack_string(what,usedfont) + this = concat_nodes { + new_kern(-text.width), + text, + } + setlisttransparency(this,c_text) + this = fast_hpack(this) + this.width = 0 + this.height = 0 + this.depth = 0 + b_cache[what] = this + end + end + local info = concat_nodes { + this and copy_list(this) or nil, -- this also triggers the right mode (else sometimes no whatits) + new_rule(linewidth,ht,dp), + new_rule(wd-2*linewidth,-dp+linewidth,dp), + new_rule(linewidth,ht,dp), + new_kern(-wd+linewidth), + new_rule(wd-2*linewidth,ht,-ht+linewidth), + baseskip, + baseline, + } + setlisttransparency(info,c_text) + info = fast_hpack(info) + info.width = 0 + info.height = 0 + info.depth = 0 + set_attribute(info,a_layer,layer) + local info = concat_nodes { + current, + new_kern(-wd), + info, + } + info = fast_hpack(info,wd) + if vertical then + info = vpack_nodes(info) + end + if next then + info.next = next + next.prev = info + end + if prev then + info.prev = prev + prev.next = info + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end +end + +local function ruledglyph(head,current) + local wd = current.width + if wd ~= 0 then + local ht, dp = current.height, current.depth + local next, prev = current.next, current.prev + current.next, current.prev = nil, nil + local linewidth = emwidth/20 + local baseline + if dp ~= 0 and ht ~= 0 then + baseline = new_rule(wd-2*linewidth,linewidth,0) + end + local doublelinewidth = 2*linewidth + local info = concat_nodes { + new_rule(linewidth,ht,dp), + new_rule(wd-doublelinewidth,-dp+linewidth,dp), + new_rule(linewidth,ht,dp), + new_kern(-wd+linewidth), + new_rule(wd-doublelinewidth,ht,-ht+linewidth), + new_kern(-wd+doublelinewidth), + baseline, + } + setlistcolor(info,c_glyph) + setlisttransparency(info,c_glyph_d) + info = fast_hpack(info) + info.width = 0 + info.height = 0 + info.depth = 0 + set_attribute(info,a_layer,l_glyph) + local info = concat_nodes { + current, + new_kern(-wd), + info, + } + info = fast_hpack(info) + info.width = wd + if next then + info.next = next + next.prev = info + end + if prev then + info.prev = prev + prev.next = info + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end +end + +local g_cache = { } + +local tags = { + -- userskip = "US", + lineskip = "LS", + baselineskip = "BS", + parskip = "PS", + abovedisplayskip = "DA", + belowdisplayskip = "DB", + abovedisplayshortskip = "SA", + belowdisplayshortskip = "SB", + leftskip = "LS", + rightskip = "RS", + topskip = "TS", + splittopskip = "ST", + tabskip = "AS", + spaceskip = "SS", + xspaceskip = "XS", + parfillskip = "PF", + thinmuskip = "MS", + medmuskip = "MM", + thickmuskip = "ML", + leaders = "NL", + cleaders = "CL", + xleaders = "XL", + gleaders = "GL", + -- true = "VS", + -- false = "HS", +} + +local function ruledglue(head,current,vertical) + local spec = current.spec + local width = spec.width + local subtype = current.subtype + local amount = format("%s:%0.3f",tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) + local info = g_cache[amount] + if info then + -- print("glue hit") + else + if subtype == space_code or subtype == xspace_code then -- not yet all space + 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 == 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 + g_cache[amount] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_before(head,current,info) + return head, current.next +end + +local k_cache = { } + +local function ruledkern(head,current,vertical) + local kern = current.kern + local info = k_cache[kern] + if info then + -- print("kern hit") + else + local amount = format("%s:%0.3f",vertical and "VK" 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 + k_cache[kern] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_before(head,current,info) + return head, current.next +end + +local p_cache = { } + +local function ruledpenalty(head,current,vertical) + local penalty = current.penalty + local info = p_cache[penalty] + if info then + -- print("penalty hit") + else + local amount = format("%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 + p_cache[penalty] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_before(head,current,info) + return head, current.next +end + +local function visualize(head,vertical) + 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 current = head + local prev_trace_fontkern = nil + local attr = unsetvalue + while current do + local id = current.id + local a = has_attribute(current,a_visual) or unsetvalue + if a ~= attr then + prev_trace_fontkern = trace_fontkern + 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 + else -- dead slow: + trace_hbox = hasbit(a, 1) + trace_vbox = hasbit(a, 2) + trace_vtop = hasbit(a, 4) + trace_kern = hasbit(a, 8) + trace_glue = hasbit(a, 16) + trace_penalty = hasbit(a, 32) + trace_fontkern = hasbit(a, 64) + trace_strut = hasbit(a, 128) + trace_whatsit = hasbit(a, 256) + trace_glyph = hasbit(a, 512) + trace_simple = hasbit(a,1024) + trace_user = hasbit(a,2048) + end + attr = a + end + if trace_strut then + set_attribute(current,a_layer,l_strut) + elseif id == glyph_code then + if trace_glyph then + head, current = ruledglyph(head,current) + end + elseif id == disc_code then + if trace_glyph then + local pre = current.pre + if pre then + current.pre = ruledglyph(pre,pre) + end + local post = current.post + if post then + current.post = ruledglyph(post,post) + end + local replace = current.replace + if replace then + current.replace = ruledglyph(replace,replace) + end + end + elseif id == kern_code then + local subtype = current.subtype + -- tricky ... we don't copy the trace attribute in node-inj (yet) + if subtype == font_kern_code or has_attribute(current,a_fontkern) then + if trace_fontkern or prev_trace_fontkern then + head, current = fontkern(head,current) + end + elseif subtype == user_kern_code then + if trace_kern then + head, current = ruledkern(head,current,vertical) + end + end + elseif id == glue_code then + local content = current.leader + if content then + current.leader = visualize(content,false) + elseif trace_glue then + head, current = ruledglue(head,current,vertical) + end + elseif id == penalty_code then + if trace_penalty then + head, current = ruledpenalty(head,current,vertical) + end + elseif id == disc_code then + current.pre = visualize(current.pre) + current.post = visualize(current.post) + current.replace = visualize(current.replace) + elseif id == hlist_code then + local content = current.list + if content then + current.list = visualize(content,false) + end + if trace_hbox then + head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple) + end + elseif id == vlist_code then + local content = current.list + if content then + current.list = visualize(content,true) + end + if trace_vtop then + head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple) + elseif trace_vbox then + head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple) + end + elseif id == whatsit_code then + if trace_whatsit then + head, current = whatsit(head,current) + end + elseif id == user_code then + if trace_whatsit then + head, current = user(head,current) + end + end + current = current.next + end + return head +end + +local function freed(cache) + local n = 0 + for k, v in next, cache do + free_node_list(v) + n = n + 1 + end + if n == 0 then + return 0, cache + else + return n, { } + end +end + +local function cleanup() + local hf, ng, np, nk, nw + nf, f_cache = freed(f_cache) + ng, g_cache = freed(g_cache) + np, p_cache = freed(p_cache) + nk, k_cache = freed(k_cache) + nw, w_cache = freed(w_cache) + nb, b_cache = freed(b_cache) + -- report_visualize("cache: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes",nf,ng,np,nk,nw,nb) +end + +function visualizers.handler(head) + if usedfont then + starttiming(visualizers) + -- local l = tex_attribute[a_layer] + -- local v = tex_attribute[a_visual] + -- tex_attribute[a_layer] = unsetvalue + -- tex_attribute[a_visual] = unsetvalue + head = visualize(head) + -- tex_attribute[a_layer] = l + -- tex_attribute[a_visual] = v + -- -- cleanup() + stoptiming(visualizers) + end + return head, false +end + +function visualizers.box(n) + tex.box[n].list = visualizers.handler(tex.box[n].list) +end + +statistics.register("visualization time",function() + if enabled then + cleanup() -- in case we don't don't do it each time + return format("%s seconds",statistics.elapsedtime(visualizers)) + end +end) diff --git a/tex/context/base/trac-vis.mkiv b/tex/context/base/trac-vis.mkiv index e906bb50d..0e4993853 100644 --- a/tex/context/base/trac-vis.mkiv +++ b/tex/context/base/trac-vis.mkiv @@ -1,7 +1,7 @@ %D \module -%D [ file=trac-vis, % was core-vis, -%D version=1996.06.01, -%D title=\CONTEXT\ Tracking Macros, +%D [ file=trac-vis, % replaces supp-vis plus some s-* modules +%D version=2112.06.23, % 1996.10.21, +%D title=\CONTEXT\ Tracing Macros, %D subtitle=Visualization, %D author=Hans Hagen, %D date=\currentdate, @@ -11,711 +11,119 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This module adds some more visualization cues to the ones -%D supplied in the support module. +%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 %\everypar dual character, \the\everypar and \everypar= -%D %\hrule cannot be grabbed in advance, switches mode -%D %\vrule cannot be grabbed in advance, switches mode -%D % -%D %\indent only explicit ones -%D %\noindent only explicit ones -%D %\par only explicit ones +%D Control over what gets visualized happens with the tracker command: %D -%D %\leftskip only if explicit one -%D %\rightskip only if explicit one - -\writestatus{loading}{ConTeXt Tracking Macros / Visualization} - -\unprotect - -%D \macros -%D {indent, noindent, par} -%D -%D \TeX\ acts upon paragraphs. In mosts documents paragraphs -%D are separated by empty lines, which internally are handled as -%D \type{\par}. Paragraphs can be indented or not, depending on -%D the setting of \type{\parindent}, the first token of a -%D paragraph and/or user suppressed or forced indentation. -%D -%D Because the actual typesetting is based on both explicit -%D user and implicit system actions, visualization is only -%D possible for the user supplied \type{\indent}, -%D \type{\noindent}, and \type{\par}. Other -%D 'clever' tricks will quite certainly lead to more failures -%D than successes, so we only support these three explicit -%D primitives and one macro: - -\def\showparagraphcue#1#2#3#4#5% - {\bgroup - \scratchdimen#1\relax - \dontinterfere - \dontcomplain - \boxrulewidth5\testrulewidth - #3#4\relax - \setbox\scratchbox\normalhbox to \scratchdimen - {#2{\ruledhbox to \scratchdimen - {\vrule #5 20\testrulewidth \!!width \zeropoint - \normalhss}}}% - \smashbox\scratchbox - \normalpenalty\plustenthousand - \box\scratchbox - \egroup} - -\def\ruledhanging - {\ifdim\hangindent>\zeropoint - \ifnum\hangafter<\zerocount - \normalhbox - {\boxrulewidth5\testrulewidth - \setbox\scratchbox\ruledhbox to \hangindent - {\scratchdimen\strutht - \advance\scratchdimen \strutdp - \vrule - \!!width \zeropoint - \!!height \zeropoint - \!!depth -\hangafter\scratchdimen}% - \normalhskip-\hangindent - \smashbox\scratchbox - \raise\strutht\box\scratchbox}% - \fi - \fi} - -\def\ruledparagraphcues - {\bgroup - \dontcomplain - \normalhbox to \zeropoint - {\ifdim\leftskip>\zeropoint\relax - \showparagraphcue\leftskip\llap\relax\relax\!!depth - \normalhskip-\leftskip - \fi - \ruledhanging - \normalhskip\hsize - \ifdim\rightskip>\zeropoint\relax - \normalhskip-\rightskip - \showparagraphcue\rightskip\relax\relax\relax\!!depth - \fi}% - \egroup} - -\def\ruledpar - {\relax - \ifhmode - \showparagraphcue{40\testrulewidth}\relax\rightrulefalse\relax\!!height - \fi - \normalpar} - -\def\rulednoindent - {\relax - \normalnoindent - \ruledparagraphcues - \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\relax\!!height} - -\def\ruledindent - {\relax - \normalnoindent - \ruledparagraphcues - \ifdim\parindent>\zeropoint - \showparagraphcue\parindent\relax\relax\relax\!!height - \else - \showparagraphcue{40\testrulewidth}\llap\relax\relax\!!height - \fi - \normalhskip\parindent} - -\def\dontshowimplicits - {\let\noindent \normalnoindent - \let\indent \normalindent - \let\par \normalpar} - -\def\showimplicits - {\testrulewidth \defaulttestrulewidth - \let\noindent \rulednoindent - \let\indent \ruledindent - \let\par \ruledpar} - -%D The next few||line examples show the four cues. Keep in -%D mind that we only see them when we explicitly open or close -%D a paragraph. -%D -%D \bgroup -%D \def\voorbeeld#1% -%D {#1Visualizing some \TeX\ primitives and Plain \TeX\ -%D macros can be very instructive, at least it is to me. -%D Here we see {\tt\string#1} and {\tt\string\ruledpar} in -%D action, while {\tt\string\parindent} equals -%D {\tt\the\parindent}.\ruledpar} -%D -%D \showimplicits -%D -%D \voorbeeld \indent -%D \voorbeeld \noindent -%D -%D \parindent=60pt -%D -%D \voorbeeld \indent -%D \voorbeeld \noindent -%D -%D \startnarrower -%D \voorbeeld \indent -%D \voorbeeld \noindent -%D \stopnarrower -%D \egroup -%D -%D These examples also demonstrate the visualization of -%D \type {\leftskip} and \type {\rightskip}. The macro -%D \type {\nofruledbaselines} determines the number of lines -%D shown. - -\newcounter\ruledbaselines - -\def\nofruledbaselines{3} - -\def\debuggertext#1% - {\ifx\ttxx\undefined - $\scriptscriptstyle#1$% - \else - {\ttxx#1}% - \fi} - -\def\ruledbaseline - {\vrule \!!width \zeropoint - \bgroup - \dontinterfere - \doglobal\increment\ruledbaselines - \scratchdimen\nofruledbaselines\baselineskip - \setbox\scratchbox\normalvbox to 2\scratchdimen - {\leaders - \normalhbox - {\strut - \vrule - \!!height \testrulewidth - \!!depth \testrulewidth - \!!width 120\points} - \normalvfill}% - \smashbox\scratchbox - \advance\scratchdimen \strutheightfactor\baselineskip - \setbox\scratchbox\normalhbox - {\normalhskip -48\points - \normalhbox to 24\points - {\normalhss\debuggertext\ruledbaselines\normalhskip6\points}% - \raise\scratchdimen\box\scratchbox}% - \smashbox\scratchbox - \box\scratchbox - \egroup} - -\def\showbaselines - {\testrulewidth\defaulttestrulewidth - \EveryPar{\ruledbaseline}} - -%D \macros -%D {showpagebuilder} -%D -%D The next tracing option probaly is only of use to me and a -%D few \CONTEXT\ hackers. - -\def\showpagebuilder - {\EveryPar{\doshowpagebuilder}} - -\def\doshowpagebuilder - {\strut\llap - {\startcolor[blue]\vl - \high{\infofont v:\the\vsize }\vl - \high{\infofont g:\the\pagegoal }\vl - \high{\infofont t:\the\pagetotal}\vl - \stopcolor}} - -%D \macros -%D {makecutbox, cuthbox, cutvbox, cutvtop} -%D -%D Although mainly used for marking the page, these macros can -%D also serve local use. -%D -%D \startbuffer -%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0 -%D \stopbuffer -%D -%D \typebuffer -%D -%D This marked \type{\vbox} shows up as: -%D -%D \startlinecorrection -%D \getbuffer -%D \stoplinecorrection -%D -%D The alternative macros are used as: -%D -%D \startbuffer -%D \cuthbox{a made cut box} -%D \stopbuffer -%D -%D \typebuffer -%D -%D This is typeset as: -%D -%D \startlinecorrection -%D \getbuffer -%D \stoplinecorrection -%D -%D By setting the next macros one can influence the length of -%D the marks as well as the horizontal and vertical divisions. - -\newdimen\tractempwidth -\newdimen\tractempheight -\newdimen\tractempdepth - -\def \cutmarklength {2\bodyfontsize} - -\newcount\horizontalcutmarks \horizontalcutmarks = 2 -\newcount\verticalcutmarks \verticalcutmarks = 2 -\newcount\cutmarkoffset \cutmarkoffset = 1 - -\let \cutmarksymbol \relax -\let \cutmarktoptext \empty -\let \cutmarkbottomtext \empty -\let \cutmarkhoffset \empty -\let \cutmarkvoffset \empty - -\def\horizontalcuts - {\normalhbox to \tractempwidth - {\dorecurse\horizontalcutmarks{\vrule\!!width\boxrulewidth\!!height\cutmarklength\normalhfill}% - \unskip}} - -\def\verticalcuts - {\normalvbox to \dimexpr\tractempheight+\tractempdepth\relax - {\hsize\cutmarklength - \dorecurse\verticalcutmarks{\vrule\!!height\boxrulewidth\!!width\hsize\normalvfill}% - \unskip}} - -\def\baselinecuts - {\ifdim\tractempdepth>\zeropoint - \normalvbox to \dimexpr\tractempheight+\tractempdepth\relax - {\hsize\dimexpr\cutmarklength/2\relax - \normalvskip\zeropoint\!!plus\tractempheight - \vrule\!!height\boxrulewidth\!!width\hsize - \normalvskip\zeropoint\!!plus\tractempdepth}% - \fi} - -\def\cutmarksymbols#1% - {\normalhbox to \tractempwidth - {\setbox\scratchbox\normalhbox to \cutmarklength - {\normalhss\infofont\cutmarksymbol\normalhss}% - \normalhss - \normalvbox to \cutmarklength - {\scratchdimen\dimexpr\cutmarklength/2\relax - \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi - \normalvss - \hbox to \tractempwidth - {\llap{\copy\scratchbox\normalhskip\scratchskip}% - \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen - \rlap{\normalhskip\scratchskip\copy\scratchbox}}% - \normalvss}% - \normalhss}} - -\def\makecutbox#1% simplier with layers, todo - {\tractempheight\ht#1% - \tractempdepth \dp#1% - \tractempwidth \wd#1% - \setbox#1\normalhbox - {\dontcomplain - \forgetall - \boxmaxdepth\maxdimen - \offinterlineskip - \scratchdimen\dimexpr\cutmarklength/2\relax - \hsize\tractempwidth - \setbox\scratchbox\normalvbox - {\setbox\scratchbox\normalhbox{\horizontalcuts}% - \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi -% \normalvskip\dimexpr-\scratchskip-2\scratchdimen\relax -% \copy\scratchbox -% \normalvskip\scratchskip - \tlap{\copy\scratchbox\normalvskip\scratchskip}% - \hbox to \tractempwidth - {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi - \setbox\scratchbox\normalhbox{\verticalcuts}% - \llap{\copy\scratchbox\normalhskip\scratchskip}% - \ifdim\tractempdepth=\zeropoint - \normalhfill - \else - \bgroup - \setbox\scratchbox\normalhbox{\baselinecuts}% - \llap{\copy\scratchbox\normalhskip\scratchskip}% - \normalhfill - \rlap{\normalhskip\scratchskip\copy\scratchbox}% - \egroup - \fi - \rlap{\normalhskip\scratchskip\copy\scratchbox}}% -% \normalvskip\scratchskip -% \copy\scratchbox}% - \blap{\normalvskip\scratchskip\copy\scratchbox}}% - \ht\scratchbox\tractempheight - \dp\scratchbox\tractempdepth - \wd\scratchbox\zeropoint - \startcolor[\defaulttextcolor]% - \box\scratchbox - \ifx\cutmarksymbol\relax \else - \setbox\scratchbox\normalvbox - {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi - \vskip-\scratchskip - \vskip-\cutmarklength - \normalhbox{\cutmarksymbols\cutmarktoptext}% - \vskip\scratchskip - \vskip\tractempheight - \vskip\tractempdepth - \vskip\scratchskip - \normalhbox{\cutmarksymbols\cutmarkbottomtext}}% - \ht\scratchbox\tractempheight - \dp\scratchbox\tractempdepth - \wd\scratchbox\zeropoint - \box\scratchbox - \fi - \stopcolor - \box#1}% - \wd#1\tractempwidth - \ht#1\tractempheight - \dp#1\tractempdepth} - -\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox} -\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox} -\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop} - -%D \macros -%D {colormarkbox,rastermarkbox} -%D -%D This macro is used in the pagebody routine. No other use -%D is advocated here. -%D -%D \starttyping -%D \colormarkbox0 -%D \stoptyping - -\def\colormarkoffset{\cutmarkoffset} -\def\colormarklength{\cutmarklength} - -\def\dodocolorrangeA#1% - {\fastcolored[#1]{\hrule\!!width3em\!!height\scratchdimen\!!depth\zeropoint}} - -\def\docolorrangeA#1 #2 % - {\vbox - {\hsize3em % \scratchdimen - \ifcase#1\or - \dodocolorrangeA{c=#2}\or - \dodocolorrangeA{m=#2}\or - \dodocolorrangeA{y=#2}\or - \dodocolorrangeA{m=#2,y=#2}\or - \dodocolorrangeA{c=#2,y=#2}\or - \dodocolorrangeA{c=#2,m=#2}\fi - \ifdim\scratchdimen>1ex - \vskip-\scratchdimen - \vbox to \scratchdimen - {\vss\hbox to 3em{\hss#2\hss}\vss}% - \fi}} - -\def\colorrangeA#1% - {\vbox - {\startcolor[\s!white]% - \scratchdimen\dimexpr(-\colormarklength*4+\tractempheight+\tractempdepth)/21\relax - \offinterlineskip - \docolorrangeA #1 1.00 \docolorrangeA #1 0.95 - \docolorrangeA #1 0.75 - \docolorrangeA #1 0.50 - \docolorrangeA #1 0.25 \docolorrangeA #1 0.05 - \docolorrangeA #1 0.00 - \stopcolor}} - -\def\docolorrangeB #1 #2 #3 #4 #5 % - {\fastcolored - [\c!c=#2,\c!m=#3,\c!y=#4,\c!k=#5] - {\vrule\!!width\scratchdimen\!!height\colormarklength\!!depth\zeropoint}% - \ifdim\scratchdimen>2em - \hskip-\scratchdimen - \vbox to \colormarklength - {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}% - \fi} - -\def\colorrangeB - {\hbox - {\startcolor[\s!white]% - \scratchdimen\dimexpr(-\colormarklength*\plustwo+\tractempwidth)/11\relax - \docolorrangeB .5~C .5 0 0 0 - \docolorrangeB .5~M 0 .5 0 0 - \docolorrangeB .5~Y 0 0 .5 0 - \docolorrangeB .5~K 0 0 0 .5 - \docolorrangeB C 1 0 0 0 - \docolorrangeB G 1 0 1 0 - \docolorrangeB Y 0 0 1 0 - \docolorrangeB R 0 1 1 0 - \docolorrangeB M 0 1 0 0 - \docolorrangeB B 1 1 0 0 - \docolorrangeB K 0 0 0 1 - \stopcolor}} - -\def\docolorrangeC#1 % - {\fastcolored - [\c!s=#1]% - {\vrule\!!width\scratchdimen\!!height\colormarklength\!!depth\zeropoint}% - \ifdim\scratchdimen>2em - \hskip-\scratchdimen - \vbox to \colormarklength - {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}% - \fi} - -\def\colorrangeC - {\hbox - {\startcolor[\s!white]% - \scratchdimen\dimexpr(-\colormarklength*2+\tractempwidth)/14\relax - \docolorrangeC 1 \docolorrangeC .95 - \docolorrangeC .9 \docolorrangeC .85 - \docolorrangeC .8 \docolorrangeC .75 - \docolorrangeC .7 - \docolorrangeC .6 - \docolorrangeC .5 - \docolorrangeC .4 - \docolorrangeC .3 - \docolorrangeC .2 - \docolorrangeC .1 - \docolorrangeC 0 - \stopcolor}} - -\def\docolormarkbox#1#2% - {\tractempheight\ht#2% - \tractempdepth \dp#2% - \tractempwidth \wd#2% - \setbox#2\hbox - {\scratchdimen\dimexpr\colormarklength/2\relax - \forgetall - \ssxx - \setbox\scratchbox\vbox - {\offinterlineskip - \vskip\dimexpr-\colormarkoffset\scratchdimen-2\scratchdimen\relax - \ifcase#1\relax - \vskip\dimexpr\colormarklength+\scratchdimen+\tractempheight\relax - \else - \hbox to \tractempwidth{\hss\hbox{\colorrangeB}\hss}% - \vskip\colormarkoffset\scratchdimen - \vbox to \tractempheight - {\vss - \hbox to \tractempwidth - {\llap{\colorrangeA1\hskip\colormarkoffset\scratchdimen}\hfill - \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA4}}% - \vss - \hbox to \tractempwidth - {\llap{\colorrangeA2\hskip\colormarkoffset\scratchdimen}\hfill - \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA5}}% - \vss - \hbox to \tractempwidth - {\llap{\colorrangeA3\hskip\colormarkoffset\scratchdimen}\hfill - \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA6}}% - \vss}% - \fi - \vskip\colormarkoffset\scratchdimen - \hbox to \tractempwidth - {\hss\lower\tractempdepth\hbox{\colorrangeC}\hss}}% - \ht\scratchbox\tractempheight - \dp\scratchbox\tractempdepth - \wd\scratchbox\zeropoint - \box\scratchbox - \box#2}% - \wd#2\tractempwidth - \ht#2\tractempheight - \dp#2\tractempdepth} - -\def\colormarkbox {\docolormarkbox\plusone } % #1 -\def\rastermarkbox{\docolormarkbox\zerocount} % #1 - -%D \macros -%D {showwhatsits, dontshowwhatsits} -%D -%D \TEX\ has three so called whatsits: \type {\mark}, \type -%D {\write} and \type {\special}. The first one keeps track of -%D the current state at page boundaries, the last two are used -%D to communicate to the outside world. Due to fact that -%D especially \type {\write} is often used in conjunction with -%D \type {\edef}, we can only savely support that one in \ETEX. -%D -%D \bgroup \showwhatsits \setupcolors[state=start] +%D \enabletrackers[visualizer.*] %D -%D Whatsits show up \color[blue]{in color} and are -%D characterized bij their first character.\footnote [some note] -%D {So we may encounter \type {w}, \type {m} and \type{s}.} -%D They are \writestatus{dummy}{demo}\color[yellow]{stacked}. -%D -%D \egroup - -\newif\ifimmediatewrite - -\ifx\eTeXversion\undefined - - \let\showwhatsits \relax - \let\dontshowwhatsits\relax - -\else - - \let\supernormalmark \normalmark % mark may already been superseded - \let\supernormalmarks \normalmarks % mark may already been superseded - - \def\showwhatsits - {\protected\def\normalmark {\visualwhatsit100+m\supernormalmark }% - \protected\def\normalmarks{\visualwhatsit100+m\supernormalmarks}% - \protected\def\special {\visualwhatsit0100s\normalspecial }% - \protected\def\write {\visualwhatsit001-w\normalwrite }% - \let\immediate\immediatewhatsit - \appendtoks\dontshowwhatsits\to\everystoptext} - - \def\immediatewhatsit - {\bgroup\futurelet\next\doimmediatewhatsit} - - \def\doimmediatewhatsit - {\ifx\next\write - \egroup\immediatewritetrue - \else - \egroup\expandafter\normalimmediate - \fi} - - \def\dontshowwhatsits - {\let\immediate \normalimmediate - \let\normalmark\supernormalmark - \let\special \normalspecial - \let\write \normalwrite} - - \def\visualwhatsit#1#2#3#4#5% - {\bgroup - \pushwhatsit - \dontinterfere - \dontcomplain - \dontshowcomposition - \dontshowwhatsits - \ttx - \ifvmode\donetrue\else\donefalse\fi - \setbox\scratchbox\hbox - {\ifdone - \colored[r=#1,g=#2,b=#3]{#5}% temp hack - \else - \colored[s=0]{#5}% temp hack - \fi}% - \setbox\scratchbox\hbox - {\ifdone - \colored[r=#1,g=#2,b=#3]{\vrule\!!width\wd\scratchbox}% temp hack - \else - \colored[s=0]{\vrule\!!width\wd\scratchbox}% temp hack - \fi - \hskip-\wd\scratchbox\box\scratchbox}% - \scratchdimen1ex - \setbox\scratchbox\hbox - {\ifdone\hskip\else\raise#4\fi\scratchdimen\box\scratchbox}% - \smashbox\scratchbox - \ifdone\nointerlineskip\fi - \box\scratchbox - \ifvmode\nointerlineskip\fi - \popwhatsit - \egroup - \ifimmediatewrite - \immediatewritefalse - \expandafter\normalimmediate - \fi} - - \def\pushwhatsit - {\ifzeropt\lastskip - \ifcase\lastpenalty - \ifzeropt\lastkern - \ifhmode - \let\popwhatsit\relax - \else - \edef\popwhatsit{\prevdepth\the\prevdepth}% - \fi - \else - \ifhmode - \edef\popwhatsit{\kern\the\lastkern}\unkern - \else - \edef\popwhatsit{\kern\the\lastkern\prevdepth\the\prevdepth}% - \kern-\lastkern - \fi - \fi - \else - \ifhmode - \edef\popwhatsit{\the\lastpenalty}% - \unpenalty - \else - \edef\popwhatsit{\penalty\the\lastpenalty\prevdepth\the\prevdepth}% - %\nobreak - \fi - \fi - \else - \ifhmode - \edef\popwhatsit{\hskip\the\lastskip}\unskip - \else - \edef\popwhatsit{\vskip\the\lastskip\prevdepth\the\prevdepth}% - \vskip-\lastskip - \fi - \fi} - -\fi - -%D The next macro can be used to keep track of classes of -%D boxes (handy for development cq.\ tracing). - -\def\dodotagbox#1#2#3% can be reimplemented - {\def\next##1##2##3##4% - {\vbox to \ht#2{##3\hbox to \wd#2{##1#3##2}##4}}% - \processaction - [#1] - [ l=>\next\relax\hfill\vfill\vfill, - r=>\next\hfill\relax\vfill\vfill, - t=>\next\hfill\hfill\relax\vfill, - b=>\next\hfill\hfill\vfill\relax, - lt=>\next\relax\hfill\relax\vfill, - lb=>\next\relax\hfill\vfill\relax, - rt=>\next\hfill\relax\relax\vfill, - rb=>\next\hfill\relax\vfill\relax, - tl=>\next\relax\hfill\relax\vfill, - bl=>\next\relax\hfill\vfill\relax, - tr=>\next\hfill\relax\relax\vfill, - br=>\next\hfill\relax\vfill\relax, - \s!default=>\next\hfill\hfill\vfill\vfill, - \s!unknown=>\next\hfill\hfill\vfill\vfill]} - -\def\dotagbox[#1]#2% - {\bgroup - \dowithnextbox - {\setbox\scratchbox\flushnextbox - \setbox\nextbox\ifhbox\nextbox\hbox\else\vbox\fi - \bgroup - \startoverlay - {\copy\scratchbox} - {\dodotagbox{#1}\scratchbox{\framed - [\c!background=\v!screen,\c!backgroundscreen=1]{#2}}} - \stopoverlay - \egroup - \nextboxwd\the\wd\scratchbox - \nextboxht\the\ht\scratchbox - \nextboxdp\the\dp\scratchbox - \flushnextbox - \egroup}} - -\def\tagbox - {\dosingleempty\dotagbox} - -%D \macros -%D {coloredhbox,coloredvbox,coloredvtop, -%D coloredstrut} +%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 The following visualizations are used in some of the manuals: +%D In due time some special visualzation of math will move here as well. -\definecolor[boxcolor:ht][r=.5,g=.75,b=.5] -\definecolor[boxcolor:dp][r=.5,g=.5,b=.75] -\definecolor[boxcolor:wd][r=.75,g=.5,b=.5] -\definecolor[strutcolor] [r=.5,g=.25,b=.25] +\writestatus{loading}{ConTeXt Tracing Macros / Visualization} -\def\coloredbox#1% - {\dowithnextbox{#1{\hbox - {\blackrule[\c!width=\nextboxwd,\c!height=\nextboxht,\c!depth=\zeropoint,\c!color=boxcolor:ht]% - \hskip-\nextboxwd - \blackrule[\c!width=\nextboxwd,\c!height=\zeropoint,\c!depth=\nextboxdp,\c!color=boxcolor:dp]% - \hskip-\nextboxwd - \box\nextbox}}}#1} +\registerctxluafile{trac-vis}{1.001} -\def\coloredhbox{\coloredbox\hbox} -\def\coloredvbox{\coloredbox\vbox} -\def\coloredvtop{\coloredbox\vtop} +\unprotect -\def\coloredstrut - {\color[strutcolor]{\def\strutwidth{2\points}\setstrut\strut}} +\definesystemattribute[visual][public,global] + +%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. + +\let\syst_visualizers_hbox\hbox +\let\syst_visualizers_vbox\vbox +\let\syst_visualizers_vtop\vtop + +\unexpanded\def\ruledhbox{\syst_visualizers_hbox attr \visualattribute \ctxcommand{visual("simplehbox")} } +\unexpanded\def\ruledvbox{\syst_visualizers_vbox attr \visualattribute \ctxcommand{visual("simplevbox")} } +\unexpanded\def\ruledvtop{\syst_visualizers_vtop attr \visualattribute \ctxcommand{visual("simplevtop")} } % special case +\unexpanded\def\ruledtopv{\syst_visualizers_vtop attr \visualattribute \ctxcommand{visual("vtop")} } + +\unexpanded\def\showmakeup + {\ctxcommand{setvisual("makeup")}% + \let\normalvtop\ruledtopv + \let\vtop \ruledtopv} + +\unexpanded\def\showallmakeup + {\ctxcommand{setvisual("all")}% + \let\normalvtop\ruledtopv + \let\vtop \ruledtopv + \showstruts} + +\unexpanded\def\showboxes + {\ctxcommand{setvisual("boxes")}% + \let\normalvtop\ruledtopv + \let\vtop \ruledtopv} + +\unexpanded\def\showglyphs + {\ctxcommand{setvisual("glyph")}} + +\unexpanded\def\showfontkerns + {\ctxcommand{setvisual("fontkern")}} + +\unexpanded\def\setvisualizerfont + {\dosingleempty\syst_visualizers_setfont} + +\def\syst_visualizers_setfont[#1]% somename at 4pt + {\begingroup + \doifelsenothing{#1}{\definedfont[Mono at 4pt]}{\definedfont[#1]}% + \ctxlua{nodes.visualizers.setfont()}% + \endgroup} + +%D Overload: + +% \def\spac_struts_vide_hbox +% {\hbox attr \visualattribute \ctxcommand{visual("strut")} } + +\def\spac_struts_vide_hbox + {\edef\spac_struts_vide_hbox{\hbox attr \visualattribute \ctxcommand{visual("strut")} }% + \spac_struts_vide_hbox} + +%D We keep this one: + +\unexpanded\def\dontinterfere + {\reseteverypar + \parindent\zeropoint + \parskip \zeropoint + \leftskip \zeropoint + \rightskip\zeropoint + \relax} + +%D We keep these for a while: + +\let\ruledvcenter \vcenter +\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/type-imp-husayni.mkiv b/tex/context/base/type-imp-husayni.mkiv index b3c1af5b7..b81996c33 100644 --- a/tex/context/base/type-imp-husayni.mkiv +++ b/tex/context/base/type-imp-husayni.mkiv @@ -1,137 +1,144 @@ -\definefontfeature +%D \module +%D [ file=type-imp-husayni, +%D version=2008.08.08, % or whatever ... onwards +%D title=\CONTEXT\ Typescript Macros, +%D subtitle=Husayni, +%D author=Idris Samawi Hamid \& 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 a detailed list of features and names, see husayni.lfg. In fact, the following +%D sets will go there. + +\definefontfeature [husayni-default] - [analyze=yes,mode=node, - language=dflt,script=arab, - ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement - init=yes,medi=yes,fina=yes, % contextual analysis - % dlig=yes, % Hamzahbelow under YaaHamzahabove - rlig=yes, % indispensable - calt=yes, % ayah+numerals - salt=yes, % includes manual justification with Tatwiil - % fchr=yes % formatting chars - anum=yes, % replace latin numerals with arabic-script ones - ss01=yes, % Allah, Muhammad, - % ss02=yes, % ss01 + Allah_final - ss03=yes, % level-1 stack over Jiim, initial entry only - % ss04=yes, % level-1 stack over Jiim, initial/medial entry - % ss05=yes, % multi-level Jiim stacking, initial/medial entry - % ss06=yes, % aesthetic Faa/Qaaf for FJ_mm, FJ_mf connection - ss07=yes, % initial-entry stacking over Haa - % ss08=yes, % initial/medial stacking over Haa, minus HM_mf strings - % ss09=yes, % initial/medial Haa stacking plus HM_mf strings - ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim - % ss11=yes, % full dipped Miim, initial-entry B_S-stack over Miim - ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim, - % ss13=yes, % full initial-medial entry B_S-stacked Miim - % ss14=yes, initial entry, stacked Laam on Miim - ss15=yes, % full stacked Laam-on-Miim - ss16=yes, % initial entry, stacked Ayn-on-Miim - % ss17=yes, % full stacked Ayn-on-Miim - % ss18=yes, % LMJ_im % already contained in ss03--05, may remove - ss19=yes, % LM_im - % ss20=yes, % KLM_m, sloped Miim - % ss21=yes, % KLM_i_mm/LM_mm, sloped Miim - % ss22=yes, % filled sloped Miim - % ss23=yes, % LM_mm, non-sloped Miim - ss24=yes, % BR_i_mf, BN_i_mf - ss25=yes, % basic LH_im % might merge with ss24 - ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf - ss27=yes, % basic thin Miim.final - % ss28=yes, % full thin Miim.final % to be moved to jsnn - % ss29=yes, % basic short Miim.final - % ss30=yes, % full short Miim.final % to be moved to jsnn - ss31=yes, % basic Raa.final strings: JR and SR - % ss32=yes, % basic Raa.final strings: JR, SR, and BR - % ss33=yes, % TtR % to be moved to jsnn - ss34=yes, % AyR style % also available in jsnn - ss35=yes, % full Kaaf contexts - ss36=yes, % full Laam contexts - ss37=yes, % Miim-Miim contexts - ss38=yes, % basic dipped Haa, B_SH_mm - % ss39=yes, % full dipped Haa, B_S_LH_i_mm_Mf - % ss40=yes, % aesthetic dipped medial Haa - ss41=yes, % high and low Baa strings - ss42=yes, % diagonal entry - ss43=yes, % initial alternates - % ss44=yes, % hooked final alif - % ss45=yes, % BMA_f - % ss46=yes, % BM_mm_alt, for JBM combinations - % ss47=yes, % Shaddah-<kasrah> combo - % ss48=yes, % Auto-sukuun - % ss49=yes, % No vowels - % ss50=yes, % Shaddah/MaaddahHamzah only - % ss51=yes, % No Skuun - % ss52=yes, % No Waslah - % ss53=yes, % No Waslah - % ss54=yes, % chopped finals - % ss55=yes, % idgham-tanwin - ss60=yes, % - % js01=yes, % Raawide - % js02=yes, % Yaawide - % js03=yes, % Kaafwide - % js04=yes, % Nuunwide - % js05=yes, % Kaafwide Nuunwide Siinwide Baawide - % js06=yes, % final Haa wide - % js07=yes, % thin Miim - % js08=yes, % short Miim - % js09=yes, % wide Siin - % js10=yes, % thuluth-style initial Haa, final Miim, MRw_mf - % js11=yes, % level-1 stretching - % js12=yes, % level-2 stretching - % js13=yes, % level-3 stretching - % js14=yes, % final Alif - % js15=yes, % hooked final Alif - js16=yes, % aesthetic medial Faa/Qaaf - % js17=yes, % fancy isol Haa after Daal, Raa, and Waaw - % js18=yes, % Laamwide, alternate substitution - % js19=yes, % level-4 stretching, only siin and Hhaa for basmalah - % js20=yes, % level-5 stretching, only siin and Hhaa for basmalah - % js21=yes, % Haa.final_alt2 - % calt=yes, % to be used for vowel/dot-based dynamics - % ttwl=yes, % for simple, horizontal stretching, not yet implemented in luatex/mkiv - % flts=yes, % Final Glyph On Line Alternates Short: Baa-like - % fltw=yes, % Final Glyph On Line Alternates Wide: Baa-like - % gclr=yes, % Geometric Cursive LR : for testing GPOS only! - % gcrl=yes, % Geometric Cursive RL - % gklr=yes, % Geometric Kerning LR - % gkrl=yes, % Geometric Kerning RL - kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings - curs=yes, % we don't curs final pairs, padj for that - mark=yes, % vowels - mkmk=yes, % stacked vowels + [analyze=yes, + mode=node, + language=dflt, + script=arab, + ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement + init=yes, % contextual analysis + medi=yes, % contextual analysis + fina=yes, % contextual analysis + rlig=yes, % indispensable + calt=yes, % ayah+numerals + salt=yes, % includes manual justification with Tatwiil + anum=yes, % replace latin numerals with arabic-script ones + ss01=yes, % Allah, Muhammad, + ss03=yes, % level-1 stack over Jiim, initial entry only + ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim + ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim, + ss15=yes, % full stacked Laam-on-Miim + ss16=yes, % initial entry, stacked Ayn-on-Miim + ss19=yes, % LM_im + ss24=yes, % BR_i_mf, BN_i_mf + ss25=yes, % basic LH_im % might merge with ss24 + ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf + ss27=yes, % basic thin Miim.final + ss31=yes, % basic Raa.final strings: JR and SR + ss34=yes, % AyR style % also available in jsnn + ss35=yes, % full Kaaf contexts + ss36=yes, % full Laam contexts + ss37=yes, % Miim-Miim contexts + ss38=yes, % basic dipped Haa, B_SH_mm + ss41=yes, % high and low Baa strings + ss42=yes, % diagonal entry + ss43=yes, % initial alternates + ss60=yes, % + js16=yes, % aesthetic medial Faa/Qaaf + kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings + curs=yes, % we don't curs final pairs, padj for that + mark=yes, % vowels + mkmk=yes, % stacked vowels tlig=yes, - colorscheme=husayni:default] + goodies=husayni, + colorscheme=default] + +\definefontfeature + [husayni-alternative] % was husayni-default2 + [analyze=yes, + mode=node, + language=dflt, + script=arab, + ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement + init=yes, % contextual analysis + medi=yes, % contextual analysis + fina=yes, % contextual analysis + rlig=yes, % indispensable + calt=yes, % ayah+numerals + salt=yes, % includes manual justification with Tatwiil + anum=yes, % replace latin numerals with arabic-script ones + ss01=yes, % Allah, Muhammad, + ss03=yes, % level-1 stack over Jiim, initial entry only + ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim + ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim, + ss15=yes, % full stacked Laam-on-Miim + ss16=yes, % initial entry, stacked Ayn-on-Miim + ss19=yes, % LM_im + ss24=yes, % BR_i_mf, BN_i_mf + ss25=yes, % basic LH_im % might merge with ss24 + ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf + ss27=yes, % basic thin Miim.final + ss31=yes, % basic Raa.final strings: JR and SR + ss34=yes, % AyR style % also available in jsnn + ss35=yes, % full Kaaf contexts + ss36=yes, % full Laam contexts + ss37=yes, % Miim-Miim contexts + ss38=yes, % basic dipped Haa, B_SH_mm + ss41=yes, % high and low Baa strings + ss42=yes, % diagonal entry + ss43=yes, % initial alternates + ss60=yes, % + js16=yes, % aesthetic medial Faa/Qaaf + kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings + curs=yes, % we don't curs final pairs, padj for that + mark=yes, % vowels + mkmk=yes, % stacked vowels + tlig=yes] \definefontfeature [husayni-tt] - [analyze=yes,mode=node, - language=dflt,script=arab, - ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement - init=yes,medi=yes,fina=yes, % contextual analysis - rlig=yes, % indispensable + [analyze=yes, + mode=node, + language=dflt, + script=arab, + ccmp=yes, + init=yes, + medi=yes, + fina=yes, + rlig=yes, fchr=yes, - kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings - curs=yes, % we don't curs final pairs, padj for that - mark=yes, % vowels - mkmk=yes] % stacked vowels + kern=yes, + curs=yes, + mark=yes, + mkmk=yes] \definefontfeature [husayni-mono] - [analyze=yes,mode=node, - language=dflt,script=arab,ccmp=no, - init=yes,medi=yes,fina=yes,isol=yes, - rlig=yes,liga=yes, + [analyze=yes, + mode=node, + language=dflt, + script=arab, + ccmp=no, + init=yes, + medi=yes, + fina=yes, + isol=yes, mset=yes] - + \definedelimitedtext [ornatequote] [left={\char"FD3F\penalty10000}, - right={\char"FD3E\penalty10000}] - + right={\char"FD3E\penalty10000}] + \definedelimitedtext [arparenthesis] [left={\char"0028}, - right={\char"0029}] + right={\char"0029}] \definedelimitedtext [arquotation] @@ -143,4 +150,49 @@ [arquote] [left={\symbol[rightquote]}, right={\symbol[leftquote]}, - leftmargin=standard]
\ No newline at end of file + leftmargin=standard] + +\definebodyfontenvironment + [husayni-default] + [default] + [interlinespace=4.4ex] + +\definefontfallback + [husayni-latin] + [file:lmroman12-regular*default] + [basiclatin,latin-1supplement,latinextended-A,latinextendedadditional] + [force=no, + rscale=.7] + +\definefontfallback + [husayni-mono] + [file:cour*husayni-mono] + [arabic,arabicpresentationformsa,arabicpresentationformsb,arabicsupplement,0x200C,0x200D,0x200E,0x200F] + % [force=no] + +\definebodyfontenvironment[20.7pt] +\definebodyfontenvironment[24.8pt] +\definebodyfontenvironment[29.8pt] +\definebodyfontenvironment[35.8pt] + +\starttypescriptcollection[husayni] + + \starttypescript [naskh] [husayni] [name] + \definefontsynonym [Arabic-Light] [name:husayni] [goodies=husayni,features=husayni-default] + \definefontsynonym [Arabic-Bold] [name:husayni] [goodies=husayni,features=husayni-default] + \definefontsynonym [Arabic-Italic] [name:husayni] [goodies=husayni,features=husayni-default] + \definefontsynonym [Arabic-Bold-Italic] [name:husayni] [goodies=husayni,features=husayni-default] + + \definefontsynonym [Serif] [Arabic-Light] + \definefontsynonym [SerifItalic] [Arabic-Italic] + \definefontsynonym [SerifBold] [Arabic-Bold] + \definefontsynonym [SerifBoldItalic] [Arabic-Bold-Italic] + \stoptypescript + + \starttypescript [husayni-default] + \definetypeface [husayni-default] [rm] [naskh] [husayni] [default] [fallbacks=husayni-latin] + \definetypeface [husayni-default] [tt] [mono] [modern] [default] [fallbacks=husayni-latin] + \definetypeface [husayni-default] [mm] [math] [xitsbidi] [default] + \stoptypescript + +\stoptypescriptcollection diff --git a/tex/context/base/type-ini.lua b/tex/context/base/type-ini.lua index 4ce953168..758fb5683 100644 --- a/tex/context/base/type-ini.lua +++ b/tex/context/base/type-ini.lua @@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['type-ini'] = { -- more code will move here +local commands, context = commands, context + local gsub = string.gsub local report_typescripts = logs.reporter("fonts","typescripts") @@ -15,13 +17,14 @@ local report_typescripts = logs.reporter("fonts","typescripts") local patterns = { "type-imp-%s.mkiv", "type-imp-%s.tex", "type-%s.mkiv", "type-%s.tex" } -- this will be imp only local function action(name,foundname) - context.startreadingfile() - context.pushendofline() - context.unprotect() - context.input(foundname) - context.protect() - context.popendofline() - context.stopreadingfile() + -- context.startreadingfile() + -- context.pushendofline() + -- context.unprotect() + -- context.input(foundname) + -- context.protect() + -- context.popendofline() + -- context.stopreadingfile() + context.loadfoundtypescriptfile(foundname) end local name_one, name_two diff --git a/tex/context/base/type-ini.mkvi b/tex/context/base/type-ini.mkvi index 8ca42854f..8345a97f9 100644 --- a/tex/context/base/type-ini.mkvi +++ b/tex/context/base/type-ini.mkvi @@ -27,6 +27,8 @@ \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 @@ -134,15 +136,21 @@ % The next will change .. we can load a file inside a typescript but as the state is % 1 then, it doesn't get stored without doing that explicitly -% \unexpanded\def\loadtypescriptfile[#1]% -% {\ctxcommand{loadtypescriptfile("#1")}} - \unexpanded\def\loadtypescriptfile[#1]% {\pushmacro\typescriptstate \let\typescriptstate\plustwo % assumes 2 at the outer level \ctxcommand{loadtypescriptfile("#1")}% \popmacro\typescriptstate} +\unexpanded\def\loadfoundtypescriptfile#1% + {\startreadingfile + \pushendofline + \unprotect + \input{#1}% + \protect + \popendofline + \stopreadingfile} + \unexpanded\def\quittypescriptscanning {\settrue\c_font_typescripts_quit} % public diff --git a/tex/context/base/node-par.lua b/tex/context/base/typo-bld.lua index 8eafd1f6e..87d280541 100644 --- a/tex/context/base/node-par.lua +++ b/tex/context/base/typo-bld.lua @@ -1,11 +1,13 @@ -if not modules then modules = { } end modules ['node-par'] = { +if not modules then modules = { } end modules ['typo-bld'] = { -- was node-par version = 1.001, - comment = "companion to node-par.mkiv", + comment = "companion to typo-bld.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } +local insert, remove = table.insert, table.remove + local builders, nodes, node = builders, nodes, node builders.paragraphs = builders.paragraphs or { } @@ -23,10 +25,20 @@ local numbers = constructors.numbers constructors.methods = constructors.methods or { } local methods = constructors.methods -local p_attribute = attributes.numbers['parbuilder'] or 999 -constructors.attribute = p_attribute +local a_parbuilder = attributes.numbers['parbuilder'] or 999 -- why 999 +constructors.attribute = a_parbuilder +local unsetvalue = attributes.unsetvalue +local texsetattribute = tex.setattribute local has_attribute = node.has_attribute +local texnest = tex.nest + +local nodepool = nodes.pool +local new_baselineskip = nodepool.baselineskip +local new_lineskip = nodepool.lineskip +local insert_node_before = node.insert_before +local hpack_node = node.hpack + local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming @@ -36,14 +48,46 @@ storage.register("builders/paragraphs/constructors/numbers", numbers, "builders. local report_parbuilders = logs.reporter("parbuilders") local mainconstructor = nil -- not stored in format +local nofconstructors = 0 +local stack = { } + +function constructors.define(name) + nofconstructors = nofconstructors + 1 + names[nofconstructors] = name + numbers[name] = nofconstructors +end + +function constructors.set(name) --- will go + if name then + mainconstructor = numbers[name] or unsetvalue + else + mainconstructor = stack[#stack] or unsetvalue + end + texsetattribute(a_parbuilder,mainconstructor) + if mainconstructor ~= unsetvalue then + constructors.enable() + end +end -function constructors.register(name,number) - names[number] = name - numbers[name] = number +function constructors.start(name) + local number = numbers[name] + insert(stack,number) + mainconstructor = number or unsetvalue + texsetattribute(a_parbuilder,mainconstructor) + if mainconstructor ~= unsetvalue then + constructors.enable() + end +-- report_parbuilders("start %s",name) end -function constructors.set(name) - mainconstructor = numbers[name] +function constructors.stop() + remove(stack) + mainconstructor = stack[#stack] or unsetvalue + texsetattribute(a_parbuilder,mainconstructor) + if mainconstructor == unsetvalue then + constructors.disable() + end +-- report_parbuilders("stop") end -- return values: @@ -56,7 +100,7 @@ function constructors.handler(head,followed_by_display) if type(head) == "boolean" then return head else - local attribute = has_attribute(head,p_attribute) or mainconstructor + local attribute = has_attribute(head,a_parbuilder) -- or mainconstructor if attribute then local method = names[attribute] if method then @@ -79,10 +123,20 @@ function constructors.methods.default(head,followed_by_display) return true -- let tex break end --- also for testing (no surrounding spacing done) - -function constructors.methods.oneline(head,followed_by_display) - return node.hpack(head) +-- also for testing (now also surrounding spacing done) + +function builders.paragraphs.constructors.methods.oneline(head,followed_by_display) + -- when needed we will turn this into a helper + local t = texnest[texnest.ptr] + local h = hpack_node(head) + local d = tex.baselineskip.width - t.prevdepth - h.height + t.prevdepth = h.depth + t.prevgraf = 1 + if d < tex.lineskiplimit then + return insert_node_before(h,h,new_lineskip(tex.lineskip)) + else + return insert_node_before(h,h,new_baselineskip(d)) + end end -- It makes no sense to have a sequence here as we already have @@ -90,17 +144,13 @@ end -- -- local actions = nodes.tasks.actions("parbuilders") -- --- yet (maybe some day). --- --- todo: enable one as main +-- yet ... maybe some day. local actions = constructors.handler local enabled = false -function constructors.enable () enabled = true end -function constructors.disable() enabled = false end - local function processor(head,followed_by_display) + -- todo: not again in otr so we need to flag if enabled then starttiming(parbuilders) local head = actions(head,followed_by_display) @@ -111,8 +161,26 @@ local function processor(head,followed_by_display) end end +function constructors.enable() + enabled = true +end + +function constructors.disable() + enabled = false +end + + callbacks.register('linebreak_filter', processor, "breaking paragraps into lines") statistics.register("linebreak processing time", function() return statistics.elapsedseconds(parbuilders) end) + +-- interface + +commands.defineparbuilder = constructors.define +commands.startparbuilder = constructors.start +commands.stopparbuilder = constructors.stop +commands.setparbuilder = constructors.set +commands.enableparbuilder = constructors.enable +commands.disableparbuilder = constructors.disable diff --git a/tex/context/base/typo-bld.mkiv b/tex/context/base/typo-bld.mkiv new file mode 100644 index 000000000..10502005b --- /dev/null +++ b/tex/context/base/typo-bld.mkiv @@ -0,0 +1,64 @@ +%D \module +%D [ file=typo-bld, % was node-par, +%D version=2008.09.30, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Paragraph Building, +%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 Node Macros / Paragraph Building} + +%D This is very experimental, undocumented, subjected to changes, etc. just as +%D the underlying interfaces. But at least it's cleaned as part of the status-mkiv +%D cleanup. + +% \startparbuilder[default] +% \input tufte \par +% \startparbuilder[oneline] +% \input tufte \par +% \stopparbuilder +% \input tufte \par +% \stopparbuilder +% +% \startparbuilder[oneline] +% \dorecurse{100}{\input ward \par} +% \stopparbuilder + +\unprotect + +\registerctxluafile{typo-bld}{1.001} + +\definesystemattribute[parbuilder][public] + +\installcorenamespace {parbuilder} + +\unexpanded\def\defineparbuilder[#1]% + {\ctxcommand{defineparbuilder("#1")}} + +\unexpanded\def\startparbuilder[#1]% + {\ifhmode\par\fi + \ctxcommand{startparbuilder("#1")}} + +\unexpanded\def\stopparbuilder + {\ifhmode\par\fi + \ctxcommand{stopparbuilder()}} + +\unexpanded\def\setmainparbuilder[#1]% + {\ctxcommand{setparbuilder("#1")}} + +% no high level interface, after all implementing a linebreaker is not something that +% the average user will do + +\defineparbuilder[default] % just for testing +\defineparbuilder[oneline] % just for testing +\defineparbuilder[basic] % just for testing + +\def\enableparbuilders {\ctxcommand{enableparbuilder()}} % hooks in otr so we need to pickup +\def\disableparbuilders{\ctxcommand{disableparbuilder()}} % hooks in otr so we need to pickup + +\protect \endinput diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua index 14f0b8b47..726518a85 100644 --- a/tex/context/base/typo-brk.lua +++ b/tex/context/base/typo-brk.lua @@ -29,7 +29,8 @@ local free_node = node.free local insert_node_before = node.insert_before local insert_node_after = node.insert_after local remove_node = nodes.remove -- ! nodes -local link_nodes = nodes.link + +local tonodes = nodes.tonodes local texattribute = tex.attribute local unsetvalue = attributes.unsetvalue @@ -139,10 +140,18 @@ methods[5] = function(head,start,settings) -- x => p q r head, start, tmp = remove_node(head,start) head, start = insert_node_before(head,start,new_disc()) local attr = tmp.attr + local font = tmp.font start.attr = copy_nodelist(attr) -- todo: critical only - start.pre = link_nodes(settings.right,tmp,attr) - start.post = link_nodes(settings.left,tmp,attr) - start.replace = link_nodes(settings.middle,tmp,attr) + local left, right, middle = settings.left, settings.right, settings.middle + if left then + start.pre = tonodes(tostring(left),font,attr) -- was right + end + if right then + start.post = tonodes(tostring(right),font,attr) -- was left + end + if middle then + start.replace = tonodes(tostring(middle),font,attr) + end free_node(tmp) insert_break(head,start,10000,10000) end diff --git a/tex/context/base/typo-brk.mkiv b/tex/context/base/typo-brk.mkiv index 029f4402f..af498bfec 100644 --- a/tex/context/base/typo-brk.mkiv +++ b/tex/context/base/typo-brk.mkiv @@ -38,14 +38,14 @@ \def\typo_breakpoints_define_character[#1][#2][#3]% name char settings {\begingroup - \getparameters[\??bp][\c!type=1,\c!nleft=3,\c!nright=3,\s!language=,\c!left=,\c!right=,\c!middle=,#3]% - \ctxcommand{definebreakpoint("#1", "#2", "\reallanguagetag\@@bplanguage", { - type = \@@bptype, - nleft = "\@@bpnleft", - nright = "\@@bpnright", - right = "\@@bpright", - left = "\@@bpleft", - middle = "\@@bpmiddle" + \getdummyparameters[\c!type=1,\c!nleft=3,\c!nright=3,\s!language=,\c!left=,\c!right=,\c!middle=,#3]% + \ctxcommand{definebreakpoint("#1", "#2", "\reallanguagetag{\directdummyparameter\s!language}", { % maybe deal with #3 at the lua end + type = \directdummyparameter\c!type, + nleft = "\directdummyparameter\c!nleft", + nright = "\directdummyparameter\c!nright", + right = "\directdummyparameter\c!right", + left = "\directdummyparameter\c!left", + middle = "\directdummyparameter\c!middle" } )}% \endgroup} @@ -77,6 +77,8 @@ % \setbreakpoints[compound] % \start \hsize 1mm test-test \par \stop +%D Maybe some day default: +% % \setbreakpoints[compound] \protect \endinput diff --git a/tex/context/base/typo-cap.mkiv b/tex/context/base/typo-cap.mkiv index 28ced7c42..25a0ff9ee 100644 --- a/tex/context/base/typo-cap.mkiv +++ b/tex/context/base/typo-cap.mkiv @@ -15,6 +15,9 @@ \unprotect +%D Maybe we need a more clever system: either command or style mode etc. so +%D that we can avoid the grouped mess in a simple style switch. + \registerctxluafile{typo-cap}{1.001} \definesystemattribute[case][public] @@ -146,6 +149,14 @@ \unexpanded\def\realSmallcapped {\groupedcommand{\sc\setcharactercasing[\v!Word ]}{}} % one upper + font \unexpanded\def\realSmallCapped {\groupedcommand{\sc\setcharactercasing[\v!Words ]}{}} % some upper +\unexpanded\def\font_style_pseudosmallcapped{\setcharactercasing [\v!WORD ]\signalcharacter\tx} % all upper +\unexpanded\def\font_style_pseudoSmallcapped{\setcharactercasing [\v!capital]\signalcharacter\tx} % one upper + font +\unexpanded\def\font_style_pseudoSmallCapped{\setcharactercasing [\v!Capital]\signalcharacter\tx} % some upper + font + +\unexpanded\def\font_style_realsmallcapped {\sc\setcharactercasing[\v!WORD ]} % all lower +\unexpanded\def\font_style_realSmallcapped {\sc\setcharactercasing[\v!Word ]} % one upper + font +\unexpanded\def\font_style_realSmallCapped {\sc\setcharactercasing[\v!Words ]} % some upper + \unexpanded\def\typo_capitals_smallcaps {\ifconditional\c_typo_capitals_pseudo \expandafter\firstoftwoarguments @@ -157,6 +168,10 @@ \unexpanded\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped} \unexpanded\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped} +\unexpanded\def\font_style_smallcapped{\typo_capitals_smallcaps\font_style_pseudosmallcapped\font_style_realsmallcapped} +\unexpanded\def\font_style_Smallcapped{\typo_capitals_smallcaps\font_style_pseudoSmallcapped\font_style_realSmallcapped} +\unexpanded\def\font_style_SmallCapped{\typo_capitals_smallcaps\font_style_pseudoSmallCapped\font_style_realSmallCapped} + \unexpanded\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi} \appendtoks @@ -171,6 +186,10 @@ \let\normalWORD \WORD \let\normalword \word +\let\font_style_normalsmallcapped\font_style_smallcapped +\let\font_style_normalWORD \WORD +\let\font_style_normalword \word + %D As suggested by WS: \unexpanded\def\notsmallcapped{\groupedcommand{\setcharactercasing[\v!word]\signalcharacter}{}} @@ -183,21 +202,22 @@ %D %D \showsetup{setupcapitals} -\let\normalsmallcapped\smallcapped +\installcorenamespace{capitals} -\definesystemvariable{kk} +\installsetuponlycommandhandler \??capitals {capitals} -\unexpanded\def\setupcapitals - {\dosingleempty\typo_capitals_setup} +\let\normalsmallcapped\smallcapped -\def\typo_capitals_setup[#1]% todo: don't use grouping just a switch - {\getparameters[\??kk][#1]% - \doifelse\@@kktitle\v!yes - {\definealternativestyle[\v!capital ][\normalsmallcapped][\normalsmallcapped]% - \definealternativestyle[\v!smallcaps][\sc ][\sc ]} - {\definealternativestyle[\v!capital ][\normalsmallcapped][\normalWORD ]% - \definealternativestyle[\v!smallcaps][\sc ][\normalWORD ]}% - \doifelse\@@kksc\v!yes\userealcaps\usepseudocaps} +\appendtoks + \doifelse{\directcapitalsparameter\c!title}\v!yes + {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalsmallcapped]% + \definealternativestyle[\v!smallcaps][\sc][\sc]} + {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalWORD]% + \definealternativestyle[\v!smallcaps][\sc][\font_style_normalWORD]}% + \doifelse{\directcapitalsparameter\s!sc}\v!yes + \userealcaps + \usepseudocaps +\to \everysetupcapitals \let\uppercased\normalWORD \let\lowercased\normalword diff --git a/tex/context/base/typo-del.mkiv b/tex/context/base/typo-del.mkiv index b2213db65..7c36ef3c8 100644 --- a/tex/context/base/typo-del.mkiv +++ b/tex/context/base/typo-del.mkiv @@ -17,14 +17,19 @@ % THIS IS OBSOLETE: -\unexpanded\def\setuphyphenmark - {\dodoubleargument\getparameters[\??kp]} +\installcorenamespace{hyphenmarksign} % let's not waste a setuphandler (yet) \unexpanded\def\setuphyphenmark[#1]% sign=normal|wide - {\dodoubleargument\getparameters[\??kp][#1]% - \doifelse\@@kpsign {\v!normal}% was inset? - {\let\textmodehyphen\normalhyphen \let\textmodehyphendiscretionary\normalhyphendiscretionary} - {\let\textmodehyphen\composedhyphen\let\textmodehyphendiscretionary\composedhyphendiscretionary}} + {\getdummyparameters[#1]% + \expandcheckedcsname\??hyphenmarksign{\dummyparameter\c!sign}\v!normal} + +\setvalue{\??hyphenmarksign\v!normal}% + {\let\textmodehyphen\normalhyphen + \let\textmodehyphendiscretionary\normalhyphendiscretionary} + +\setvalue{\??hyphenmarksign\v!wide}% + {\let\textmodehyphen\composedhyphen + \let\textmodehyphendiscretionary\composedhyphendiscretionary} \setuphyphenmark[\c!sign=\v!wide] @@ -32,19 +37,19 @@ \definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen] \definesymbol[\c!hyphen] [\languageparameter\c!hyphen] -\def\normalhyphen +\unexpanded\def\normalhyphen {\hbox{\directsymbol\empty\c!hyphen}} -\def\composedhyphen +\unexpanded\def\composedhyphen {\hbox{\directsymbol\empty\c!compoundhyphen}} -\def\normalhyphendiscretionary +\unexpanded\def\normalhyphendiscretionary {\discretionary {\hbox{\directsymbol\empty\c!righthyphen}} {\hbox{\directsymbol\empty\c!lefthyphen}} {\hbox{\directsymbol\empty\c!hyphen}}} -\def\composedhyphendiscretionary +\unexpanded\def\composedhyphendiscretionary {\discretionary {\hbox{\directsymbol\empty\c!rightcompoundhyphen}} {\hbox{\directsymbol\empty\c!leftcompoundhyphen}} @@ -219,8 +224,10 @@ [\c!middlespeech] [\leftboundarycharacter\c!middlespeech{speech}] -\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands -\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands +\appendtoks + \def\quotation#1{"#1"}% + \def\quote #1{'#1'}% +\to \everysimplifycommands %D The next features was so desperately needed by Giuseppe %D Bilotta that he made a module for it. Since this is a diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua index 620862e85..13c0aec97 100644 --- a/tex/context/base/typo-dir.lua +++ b/tex/context/base/typo-dir.lua @@ -276,7 +276,7 @@ function directions.process(namespace,attribute,start) -- todo: make faster end end elseif d == "l" or d == "en" then -- european number - if autodir <= 0 then + if autodir <= 0 then -- could be option force_auto_left_before() end elseif d == "r" or d == "al" then -- arabic number @@ -285,9 +285,11 @@ function directions.process(namespace,attribute,start) -- todo: make faster end elseif d == "an" then -- arabic number -- actually this is language dependent ... - if autodir <= 0 then ---~ force_auto_right_before() - force_auto_left_before() +-- if autodir <= 0 then +-- force_auto_left_before() +-- end + if autodir >= 0 then + force_auto_right_before() end elseif d == "lro" then -- Left-to-Right Override -> right becomes left if trace_directions then diff --git a/tex/context/base/typo-itm.mkiv b/tex/context/base/typo-itm.mkiv new file mode 100644 index 000000000..eb47e4076 --- /dev/null +++ b/tex/context/base/typo-itm.mkiv @@ -0,0 +1,273 @@ +%D \module +%D [ file=typo-itm, % comes from core-mis +%D version=2012.06.28, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Item Lists, +%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 Node Macros / Item Lists} + +\unprotect + +%D This is a real old mechanism that we once used for questionaries. As it is documented +%D we keep it around. A more modern implementation would probably use another approach +%D but I don't want to spend too much time on it now. There are a couple of changes: +%D +%D \startitemize +%D \startitem textwidth sets the combined width \stopitem +%D \startitem width sets the symbolwidth \stopitem +%D \startitem alternative is used instead of location \stopitem +%D \stopitemize +%D +%D \startbuffer +%D \items[alternative=left]{a,b,c} +%D \items[alternative=left,align=middle,textalign=flushright,distance=1em]{a,b,c} +%D \items[alternative=right]{a,b,c} +%D \items[alternative=inmargin]{a,b,c} +%D \items[alternative=top]{a,b,c} +%D \items[alternative=bottom]{a,b,c} +%D \items[alternative=bottom,align=flushleft,textstyle=bold,color=red,textcolor=green]{a,b,c} +%D \stopbuffer +%D +%D \typebuffer +%D +%D This renders as: +%D +%D \getbuffer + +\installcorenamespace{items} +\installcorenamespace{itemsalternatives} +\installcorenamespace{itemshorizontal} +\installcorenamespace{itemsvertical} + +\installcommandhandler \??items {items} \??items + +\setupitems + [\c!alternative=\v!left, + \c!symbol=5, + \c!textwidth=\availablehsize, + \c!align=\v!middle, + \c!textalign=\v!flushleft, + \c!distance=\zeropoint, + %\c!n=, + \c!before=\blank, + \c!inbetween={\blank[\v!medium]}, + \c!after=\blank] + +\unexpanded\def\items + {\dosingleempty\typo_items_process} + +\newcount\c_typo_items_n +\newcount\c_typo_items_m +\newdimen\d_typo_items_text_width +\newdimen\d_typo_items_symbol_width +\newdimen\d_typo_items_distance +\newbox \b_typo_items_symbols +\newbox \b_typo_items_texts + +\def\typo_items_process[#1]#2% + {\bgroup + \setupitems[#1]% + \edef\p_typo_items_alternative{\itemsparameter\c!alternative}% + \ifcsname\??itemsalternatives\p_typo_items_alternative\endcsname \else + \let\p_typo_items_alternative\v!left + \fi + \let\currentitems\p_typo_items_alternative + \setupcurrentitems[#1]% + % + \edef\p_typo_items_textwidth{\itemsparameter\c!textwidth}% + \ifx\p_typo_items_textwidth\empty + \d_typo_items_text_width\availablehsize + \else + \d_typo_items_text_width\p_typo_items_textwidth\relax + \fi + % + \edef\p_typo_items_width{\itemsparameter\c!width}% + \ifx\p_typo_items_width\empty + \d_typo_items_symbol_width1.5\emwidth + \else + \d_typo_items_symbol_width\p_typo_items_width\relax + \fi + % + \edef\p_typo_items_distance{\itemsparameter\c!distance}% + \ifx\p_typo_items_distance\empty + \d_typo_items_distance\zeropoint + \else + \d_typo_items_distance\p_typo_items_distance\relax + \fi + % + \edef\p_typo_items_symbol{\itemsparameter\c!symbol}% + \ifx\p_typo_items_symbol\empty + \let\m_typo_items_symbol\firstofoneargument + \else\ifx\p_typo_items_symbol\v!none + \let\p_typo_items_symbol\empty + \let\m_typo_items_symbol\firstofoneargument + \else + \doifconversiondefinedelse\p_typo_items_symbol + {\def\m_typo_items_symbol{\convertnumber\p_typo_items_symbol}} + {\doifsymboldefinedelse\p_typo_items_symbol + {\def\m_typo_items_symbol{\symbol[\p_typo_items_symbol]\gobbleoneargument}} + {\let\m_typo_items_symbol\firstofoneargument}}% + \fi\fi + % + \edef\p_typo_items_align{\itemsparameter\c!align}% + \edef\p_typo_items_textalign{\itemsparameter\c!textalign}% + % + \edef\p_typo_items_n{\itemsparameter\c!n}% + \ifx\p_typo_items_n\empty + \getcommalistsize[#2]% + \c_typo_items_n\commalistsize\relax + \else + \c_typo_items_n\p_typo_items_n\relax + \fi + % + \parindent\zeropoint + \dontcomplain + % + \itemsparameter\c!before + \csname\??itemsalternatives\p_typo_items_alternative\endcsname{#2}% + \itemsparameter\c!after + \egroup} + +% rendering + +\setvalue{\??itemshorizontal\v!margin}#1% + {\ifnum\c_typo_items_m=\plusone\hss\else\hfill\fi + \strut#1% + \ifnum\c_typo_items_m=\c_typo_items_n\hss\else\hfill\fi} + +\setvalue{\??itemshorizontal\s!unknown}% + {\simplealignedbox\scratchwidth\m_typo_items_align} + +\def\typo_items_item_horizontal + {\advance\c_typo_items_m\plusone + \csname\??itemshorizontal + \ifcsname\??itemshorizontal\p_typo_items_align\endcsname + \p_typo_items_align + \else + \s!unknown + \fi + \endcsname} + +\setvalue{\??itemsvertical\s!unknown}% + {\simplealignedbox\scratchwidth\m_typo_items_align} + +\def\typo_items_item_vertical + {\advance\c_typo_items_m\plusone + \csname\??itemsvertical + \ifcsname\??itemsvertical\p_typo_items_align\endcsname + \p_typo_items_align + \else + \s!unknown + \fi + \endcsname} + +\def\typo_items_make_horizontal#1% + {\divide\scratchwidth\c_typo_items_n + \hbox{#1}} + +\def\typo_items_make_vertical#1% + {\vbox{#1}} + +\def\typo_items_construct_items_boxes#1% + {\setbox\b_typo_items_texts\hbox + {\c_typo_items_m\zerocount + \let\m_typo_items_align\p_typo_items_textalign + \scratchwidth\d_typo_items_text_width + \useitemsstyleandcolor\c!textstyle\c!textcolor + \typo_items_make{\processcommalist[#1]\typo_items_item}}% + \ifx\p_typo_items_symbol\empty + \setbox\b_typo_items_symbols\emptyhbox + \else + \setbox\b_typo_items_symbols\hbox + {\c_typo_items_m\zerocount + \let\m_typo_items_align\p_typo_items_align + \scratchwidth\d_typo_items_symbol_width + \useitemsstyleandcolor\c!style\c!color + \typo_items_make{\dorecurse\c_typo_items_n{\typo_items_item{\strut\m_typo_items_symbol\recurselevel}}}}% + \fi} + +% alternatives: + +\defineitems[\v!top][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align] + +\setvalue{\??itemsalternatives\v!top}#1% + {\let\typo_items_make\typo_items_make_horizontal + \let\typo_items_item\typo_items_item_horizontal + \typo_items_construct_items_boxes{#1}% + \noindent\vbox\bgroup + \forgetall + \ifvoid\b_typo_items_symbols \else + \box\b_typo_items_symbols + \itemsparameter\c!inbetween + \nointerlineskip + \fi + \box\b_typo_items_texts\ + \egroup} + +\defineitems[\v!bottom][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align] + +\setvalue{\??itemsalternatives\v!bottom}#1% + {\let\typo_items_make\typo_items_make_horizontal + \let\typo_items_item\typo_items_item_horizontal + \typo_items_construct_items_boxes{#1}% + \noindent\vbox\bgroup + \forgetall + \box\b_typo_items_texts + \ifvoid\b_typo_items_symbols \else + \itemsparameter\c!inbetween + \nointerlineskip + \box\b_typo_items_symbols + \fi + \egroup} + +\defineitems[\v!inmargin][\c!width=1.5\emwidth,\c!align=\v!flushright,\c!distance=\leftmargindistance] + +\setvalue{\??itemsalternatives\v!inmargin}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \ifvoid\b_typo_items_symbols \else + \llap{\box\b_typo_items_symbols\hskip\d_typo_items_distance}% + \fi + \box\b_typo_items_texts + \egroup} + +\defineitems[\v!left][\c!width=1.5\emwidth,\c!align=\v!flushleft] + +\setvalue{\??itemsalternatives\v!left}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \ifvoid\b_typo_items_symbols \else + \box\b_typo_items_symbols + \kern\d_typo_items_distance + \fi + \box\b_typo_items_texts + \egroup} + +\defineitems[\v!right][\c!width=1.5\emwidth,\c!align=\v!flushright] + +\setvalue{\??itemsalternatives\v!right}#1% + {\let\typo_items_make\typo_items_make_vertical + \let\typo_items_item\typo_items_item_vertical + \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax + \typo_items_construct_items_boxes{#1}% + \noindent\hbox\bgroup + \box\b_typo_items_texts + \ifvoid\b_typo_items_symbols \else + \kern\d_typo_items_distance + \box\b_typo_items_symbols + \fi + \egroup} + +\protect \endinput diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua index 54b1fd2d3..e9b9f1f45 100644 --- a/tex/context/base/typo-krn.lua +++ b/tex/context/base/typo-krn.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['typo-krn'] = { local utf = unicode.utf8 -local next, type = next, type +local next, type, tonumber = next, type, tonumber local utfchar = utf.char local nodes, node, fonts = nodes, node, fonts @@ -31,6 +31,7 @@ local tasks = nodes.tasks local new_gluespec = nodepool.gluespec local new_kern = nodepool.kern +local new_glue = nodepool.glue local nodecodes = nodes.nodecodes local kerncodes = nodes.kerncodes @@ -55,6 +56,8 @@ local chardata = fonthashes.characters local quaddata = fonthashes.quads local markdata = fonthashes.marks +local v_max = interfaces.variables.max + typesetters = typesetters or { } local typesetters = typesetters @@ -86,16 +89,45 @@ kerns.keeptogether = false -- just for fun (todo: control setting with key/value -- can be optimized .. the prev thing .. but hardly worth the effort +local function kern_injector(fillup,kern) + if fillup then + local g = new_glue(kern) + local s = g.spec + s.stretch = kern + s.stretch_order = 1 + return g + else + return new_kern(kern) + end +end + +local function spec_injector(fillup,width,stretch,shrink) + if fillup then + local s = new_gluespec(width,2*stretch,2*shrink) + s.stretch_order = 1 + return s + else + return new_gluespec(width,stretch,shrink) + end +end + local function do_process(namespace,attribute,head,force) -- todo: glue so that we can fully stretch local start, done, lastfont = head, false, nil local keepligature = kerns.keepligature local keeptogether = kerns.keeptogether + local fillup = false while start do -- faster to test for attr first local attr = force or has_attribute(start,attribute) if attr and attr > 0 then unset_attribute(start,attribute) local krn = mapping[attr] + if krn == v_max then + krn = .25 + fillup = true + else + fillup = false + end if krn and krn ~= 0 then local id = start.id if id == glyph_code then @@ -155,12 +187,12 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that local kerns = chardata[lastfont][prevchar].kerns local kern = kerns and kerns[lastchar] or 0 krn = kern + quaddata[lastfont]*krn -- here - insert_node_before(head,start,new_kern(krn)) + insert_node_before(head,start,kern_injector(fillup,krn)) done = true end else krn = quaddata[lastfont]*krn -- here - insert_node_before(head,start,new_kern(krn)) + insert_node_before(head,start,kern_injector(fillup,krn)) done = true end elseif pid == disc_code then @@ -218,7 +250,7 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that else krn = quaddata[lastfont]*krn -- here end - disc.replace = new_kern(krn) + disc.replace = kern_injector(fillup,krn) end end end @@ -229,7 +261,7 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that local w = s.width if w > 0 then local width, stretch, shrink = w+gluefactor*w*krn, s.stretch, s.shrink - start.spec = new_gluespec(width,stretch*width/w,shrink*width/w) + start.spec = spec_injector(fillup,width,stretch*width/w,shrink*width/w) done = true end end @@ -244,12 +276,12 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that elseif lastfont and (id == hlist_code or id == vlist_code) then -- todo: lookahead local p = start.prev if p and p.id ~= glue_code then - insert_node_before(head,start,new_kern(quaddata[lastfont]*krn)) + insert_node_before(head,start,kern_injector(fillup,quaddata[lastfont]*krn)) done = true end local n = start.next if n and n.id ~= glue_code then - insert_node_after(head,start,new_kern(quaddata[lastfont]*krn)) + insert_node_after(head,start,kern_injector(fillup,quaddata[lastfont]*krn)) done = true end end @@ -265,7 +297,10 @@ end local enabled = false function kerns.set(factor) - if factor ~= 0 then + if factor ~= v_max then + factor = tonumber(factor) or 0 + end + if factor == v_max or factor ~= 0 then if not enabled then tasks.enableaction("processors","typesetters.kerns.handler") enabled = true diff --git a/tex/context/base/typo-krn.mkiv b/tex/context/base/typo-krn.mkiv index e1e404a7b..cb1dcdd18 100644 --- a/tex/context/base/typo-krn.mkiv +++ b/tex/context/base/typo-krn.mkiv @@ -40,7 +40,7 @@ \def\typo_kerning_set {\usecharacterkerningstyleandcolor\c!style\c!color % goodie, maybe also strut - \ctxcommand{setcharacterkerning(\characterkerningparameter\c!factor)}} + \ctxcommand{setcharacterkerning("\characterkerningparameter\c!factor")}} \unexpanded\def\resetcharacterkerning % fast one {\attribute\kernattribute\attributeunsetvalue} @@ -62,8 +62,6 @@ %D then we always would get a command defined which is not beforehand %D a good idea. -\def\v!kerncharacters{kerncharacters} % no time now for translations - \definecharacterkerning [\v!kerncharacters] [\c!factor=.125] % Here we need to keep the groupedcommand solution as it is @@ -87,4 +85,57 @@ {\let\currentcharacterkerning\v!kerncharacters \typo_kerning_set} +%D \macros +%D {stretched} +%D +%D Stretching characters in a word is a sort of typographical +%D murder. Nevertheless we support this manipulation for use in +%D for instance titles. +%D +%D \starttyping +%D \hbox to 5cm{\stretched{to the limit}} +%D \stretched{to the limit} +%D \stretched[width=10cm]{to the limit} +%D \stoptyping +%D +%D \typebuffer +%D +%D or +%D +%D \startexample +%D \getbuffer +%D \stopexample +%D +%D \showsetup{stretched} +%D +%D This command replaces the old \MKII\ variant. + +\definecharacterkerning + [\v!stretched] + [\c!factor=\v!max, + \c!width=\availablehsize] + +\unexpanded\def\setupstretched + {\setupcharacterkerning[\v!stretched]} + +\unexpanded\def\stretched + {\dosingleempty\typo_kerning_stretched} + +\unexpanded\def\typo_kerning_stretched[#1]#2% + {\begingroup + \let\currentcharacterkerning\v!stretched + \iffirstargument + \setupcurrentcharacterkerning[#1]% + \fi + \edef\p_width{\characterkerningparameter\c!width}% + \ifx\p_width\empty \else + \hbox to \p_width + \fi + \bgroup + \usecharacterkerningstyleandcolor\c!style\c!color + \typo_kerning_set + #2% + \egroup + \endgroup} + \protect \endinput diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua index a21d9b70a..9252ef874 100644 --- a/tex/context/base/typo-mar.lua +++ b/tex/context/base/typo-mar.lua @@ -73,7 +73,7 @@ if not modules then modules = { } end modules ['typo-mar'] = { -- so far -local format = string.format +local format, validstring = string.format, string.valid local insert, remove = table.insert, table.remove local setmetatable, next = setmetatable, next @@ -81,6 +81,7 @@ local attributes, nodes, node, variables = attributes, nodes, node, variables local trace_margindata = false trackers.register("typesetters.margindata", function(v) trace_margindata = v end) local trace_marginstack = false trackers.register("typesetters.margindata.stack", function(v) trace_marginstack = v end) +local trace_margingroup = false trackers.register("typesetters.margindata.group", function(v) trace_margingroup = v end) local report_margindata = logs.reporter("typesetters","margindata") @@ -92,6 +93,7 @@ local enableaction = tasks.enableaction local variables = interfaces.variables local conditionals = tex.conditionals +local systemmodes = tex.systemmodes local v_top = variables.top local v_depth = variables.depth @@ -124,7 +126,7 @@ local free_node_list = node.flush_list local insert_node_after = node.insert_after local insert_node_before = node.insert_before -local link_nodes = nodes.link +local concat_nodes = nodes.concat local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes @@ -138,6 +140,8 @@ local kern_code = nodecodes.kern local penalty_code = nodecodes.penalty local whatsit_code = nodecodes.whatsit local line_code = listcodes.line +local cell_code = listcodes.cell +local alignment_code = listcodes.alignment local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip local userdefined_code = whatsitcodes.userdefined @@ -229,23 +233,28 @@ local defaults = { local enablelocal, enableglobal -- forward reference (delayed initialization) -local function showstore(store,banner) +local function showstore(store,banner,location) if next(store) then for i, si in table.sortedpairs(store) do local si =store[i] - report_margindata("%s: stored at %s: %s => %s",banner,i,si.name or "no name",nodes.toutf(si.box.list)) + report_margindata("%s: stored in %s at %s: %s => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(si.box.list)) end else - report_margindata("%s: nothing stored",banner) + report_margindata("%s: nothing stored in %s",banner,location) end end function margins.save(t) setmetatable(t,defaults) - local inline = t.inline + local content = texbox[t.number] local location = t.location local category = t.category - local scope = t.scope + local inline = t.inline + local scope = t.scope or v_global + if not content then + report_margindata("ignoring empty margin data: %s",location or "unknown") + return + end local store if inline then store = inlinestore @@ -263,15 +272,17 @@ function margins.save(t) end if enablelocal and scope == v_local then enablelocal() - end - if enableglobal and scope == v_global then + if enableglobal then + enableglobal() -- is the fallback + end + elseif enableglobal and scope == v_global then enableglobal() end nofsaved = nofsaved + 1 nofstored = nofstored + 1 local name = t.name if trace_marginstack then - showstore(store,"before ") + showstore(store,"before",location) end if name and name ~= "" then if inlinestore then -- todo: inline store has to be done differently (not sparse) @@ -292,12 +303,12 @@ function margins.save(t) end end if trace_marginstack then - showstore(store,"between") + showstore(store,"between",location) end end if t.number then -- better make a new table and make t entry in t - t.box = copy_node_list(texbox[t.number]) + t.box = copy_node_list(content) t.n = nofsaved -- used later (we will clean up this natural mess later) -- nice is to make a special status table mechanism @@ -327,7 +338,7 @@ function margins.save(t) end end if trace_marginstack then - showstore(store,"after ") + showstore(store,"after",location) end if trace_margindata then report_margindata("saved: %s, location: %s, scope: %s, inline: %s",nofsaved,location,scope,tostring(inline)) @@ -409,7 +420,8 @@ local function realign(current,candidate) if not anchor or anchor == "" then anchor = v_text end - if inline or anchor ~= v_text then + if inline or anchor ~= v_text or candidate.psubtype == alignment_code then + -- the alignment_code check catches margintexts ste before a tabulate h_anchors = h_anchors + 1 anchornode = new_latelua(format("_plib_.set('md:h',%i,{x=true,c=true})",h_anchors)) local blob = jobpositions.get('md:h', h_anchors) @@ -438,7 +450,7 @@ local function realign(current,candidate) end end - current.list = hpack_nodes(link_nodes(anchornode,new_kern(-delta),current.list,new_kern(delta))) -- anchor == nil is ok in link_nodes + current.list = hpack_nodes(concat_nodes{anchornode,new_kern(-delta),current.list,new_kern(delta)}) current.width = 0 end @@ -481,7 +493,7 @@ local function markovershoot(current) v_anchors = v_anchors + 1 cache[v_anchors] = stacked local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line - current.list = hpack_nodes(link_nodes(anchor,current.list)) + current.list = hpack_nodes(concat_nodes{anchor,current.list}) end local function getovershoot(location) @@ -516,6 +528,7 @@ local function inject(parent,head,candidate) local baseline = candidate.baseline local strutheight = candidate.strutheight local strutdepth = candidate.strutdepth + local psubtype = parent.subtype local offset = stacked[location] local firstonstack = offset == false or offset == nil nofstatus = nofstatus + 1 @@ -538,8 +551,9 @@ local function inject(parent,head,candidate) end candidate.width = width candidate.hsize = parent.width -- we can also pass textwidth + candidate.psubtype = psubtype if trace_margindata then - report_margindata("processing, index %s, height: %s, depth: %s",candidate.n,height,depth) + report_margindata("processing, index %s, height: %s, depth: %s, parent: %s",candidate.n,height,depth,listcodes[psubtype]) end if firstonstack then offset = 0 @@ -613,7 +627,7 @@ local function inject(parent,head,candidate) elseif head.id == whatsit_code and head.subtype == localpar_code then -- experimental if head.dir == "TRT" then - box.list = hpack_nodes(link_nodes(new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize))) + box.list = hpack_nodes(concat_nodes{new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)}) end insert_node_after(head,head,box) else @@ -708,11 +722,11 @@ local function flushed(scope,parent) -- current is hlist done = done or don end if done then -local a = has_attribute(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism + local a = has_attribute(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism parent.list = hpack_nodes(head,parent.width,"exactly") -if a then - set_attribute(parent.list,a_linenumber,a) -end + if a then + set_attribute(parent.list,a_linenumber,a) + end -- resetstacked() end return done, continue @@ -754,29 +768,44 @@ local function handler(scope,head,group) end end -function margins.localhandler(head,group) - if conditionals.inhibitmargindata then +function margins.localhandler(head,group) -- sometimes group is "" which is weird + local inhibit = conditionals.inhibitmargindata + if inhibit then + if trace_margingroup then + report_margindata("ignored: 3, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit)) + end return head, false elseif nofstored > 0 then return handler(v_local,head,group) else + if trace_margingroup then + report_margindata("ignored: 4, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit)) + end return head, false end end function margins.globalhandler(head,group) -- check group --- print(group) - if conditionals.inhibitmargindata or nofstored == 0 then + local inhibit = conditionals.inhibitmargindata + if inhibit or nofstored == 0 then + if trace_margingroup then + report_margindata("ignored: 1, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit)) + end return head, false elseif group == "hmode_par" then return handler("global",head,group) elseif group == "vmode_par" then -- experiment (for alignments) return handler("global",head,group) - -- this needs checking as we then get quite some one liners to process and - -- we cannot look ahead then: + -- this needs checking as we then get quite some one liners to process and + -- we cannot look ahead then: elseif group == "box" then -- experiment (for alignments) return handler("global",head,group) + elseif group == "alignment" then -- experiment (for alignments) + return handler("global",head,group) else + if trace_margingroup then + report_margindata("ignored: 2, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit)) + end return head, false end end @@ -823,12 +852,12 @@ end -- go horizontal. So this needs more testing. prependaction("finalizers", "lists", "typesetters.margins.localhandler") --- prependaction("vboxbuilders", "normalizers", "typesetters.margins.localhandler") +-- ("vboxbuilders", "normalizers", "typesetters.margins.localhandler") prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler") disableaction("finalizers", "typesetters.margins.localhandler") --- disableaction("vboxbuilders", "typesetters.margins.localhandler") +-- ("vboxbuilders", "typesetters.margins.localhandler") disableaction("mvlbuilders", "typesetters.margins.globalhandler") disableaction("shipouts", "typesetters.margins.finalhandler") diff --git a/tex/context/base/typo-mar.mkiv b/tex/context/base/typo-mar.mkiv index a393fc250..08d8b0cf0 100644 --- a/tex/context/base/typo-mar.mkiv +++ b/tex/context/base/typo-mar.mkiv @@ -110,7 +110,7 @@ % \c!align=, % \c!method=, \c!style=\v!bold, - \c!color=, % maybe textcolor + \c!color=, % maybe \maintextcolor % \c!name=, % \c!category=, \c!threshold=.25ex, @@ -148,7 +148,7 @@ \appendtoks \forgetall \tf - \deactivatecolor + \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor \to \everymargindatacontent % trialtypesetting: no need for margin stuff while trialing as @@ -243,7 +243,7 @@ \hsize\currentmargindatawidth \raggedcommand \ifx\currentmargindatastrut\empty \else - \dosetupstrut[\currentmargindatastrut]% + \synchronizestrut\currentmargindatastrut \fi \begstrut \strc_references_flush_destination_nodes @@ -299,6 +299,7 @@ category = "\margindataparameter\c!category", name = "\margindataparameter\c!name", scope = "\margindataparameter\c!scope", + number = \number\nextbox, }}% \fi \endgroup} diff --git a/tex/context/base/typo-scr.mkiv b/tex/context/base/typo-scr.mkiv index 4b4487522..6249c390a 100644 --- a/tex/context/base/typo-scr.mkiv +++ b/tex/context/base/typo-scr.mkiv @@ -19,7 +19,7 @@ %D \type {shiftup} and \type {shiftdown} that can work across paragraphs. %D \macros -%D {low, high, lohi, hilo} +%D {low, high, definelow, definehigh, setuplow, setuphigh} %D %D Although \TEX\ is pretty well aware of super- and subscripts, its mechanism %D is mainly tuned for math mode. The next few commands take care of script @@ -36,69 +36,233 @@ %D space. The implementation looks a bit fuzzy, since some \type {\fontdimen}'s %D are involved to determine the optimal placement. -% These might become parameters: \setupscripts but we need fo come up with -% nice keys. +\installcorenamespace {low} +\installcorenamespace {high} -\def\highvfraction {0} -\def\lowvfraction {0} -\def\highlowvfraction{.1} -\def\highlowhfraction{.1} +\installcommandhandler \??low {low} \??low +\installcommandhandler \??high {high} \??high -\unexpanded\def\low {\typo_scripts_high_low\lower\mathsubnormal{.48}\lowvfraction \t!sub} -\unexpanded\def\high{\typo_scripts_high_low\raise\mathsupnormal{.86}\highvfraction\t!sup} +\setuplow [\c!style=\tx,\c!distance=\zeropoint,\c!down=.48\exheight] % historical +\setuphigh[\c!style=\tx,\c!distance=\zeropoint,\c!up =.86\exheight] % values -\def\typo_scripts_high_low#1#2#3#4#5#6% textscript mathscript fraction extra tag +\appendtoks \setuevalue\currentlow {\typo_scripts_low {\currentlow }}\to \everydefinelow +\appendtoks \setuevalue\currenthigh{\typo_scripts_high{\currenthigh}}\to \everydefinehigh + +\unexpanded\def\typo_scripts_low#1#2% + {\dontleavehmode + \begingroup + \edef\currentlow{#1}% + \kern\lowparameter\c!distance\relax + \setbox\scratchbox\hbox\bgroup + \lower\lowparameter\c!down\hbox\bgroup + \ifx\fontsize\empty + \ifmmode + \mr % no color yet + \else + \uselowstyleandcolor\c!style\c!color + \fi + \else + \uselowstyleandcolor\c!style\c!color + \fi + \dostarttagged\t!sub\currentlow + #2% + \dostoptagged + \egroup + \egroup + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \box\scratchbox + \endgroup} + +\unexpanded\def\typo_scripts_high#1#2% {\dontleavehmode \begingroup - \scratchdimen\dimexpr#3\exheight+#4\exheight\relax - \kern\highlowhfraction\exheight - \setbox\scratchbox\hbox{#1\scratchdimen\hbox - {\ifx\fontsize\empty\ifmmode\mr\else\tx\fi\else\tx\fi - \dostarttagged - #5\empty#6% - \dostoptagged}}% - \ht\scratchbox\strutheight - \dp\scratchbox\strutdepth + \edef\currenthigh{#1}% + \kern\highparameter\c!distance\relax + \setbox\scratchbox\hbox\bgroup + \raise\highparameter\c!up\hbox\bgroup + \ifx\fontsize\empty + \ifmmode + \mr % no color yet + \else + \usehighstyleandcolor\c!style\c!color + \fi + \else + \usehighstyleandcolor\c!style\c!color + \fi + \dostarttagged\t!sup\currenthigh + #2% + \dostoptagged + \egroup + \egroup + \ht\scratchbox\strutht + \dp\scratchbox\strutdp \box\scratchbox \endgroup} +\unexpanded\def\low {\typo_scripts_low \empty} +\unexpanded\def\high{\typo_scripts_high\empty} + +%D \macros +%D {lohi, hilo, definelohi, setuplohi} +%D %D You can provide an optional keyword \type {left}, in which case the super and %D subscripts will be aligned in a way that permits placement at the left of a word %D (which means that it will be right aligned). %D %D \startbuffer -%D \lohi{aha}{ah} test \lohi{aha}{ah} test -%D \lohi[left]{aha}{ah} test \lohi[left]{aha}{ah} test -%D \lohi{aha}{ah} test\lohi{aha}{ah} test -%D \lohi[left]{aha}{ah}test \lohi[left]{aha}{ah}test +%D \lohi {aha} {ah} test \lohi {aha} {ah} test +%D \lohi [left] {aha} {ah} test \lohi [left] {aha} {ah} test +%D \lohi {aha} {ah} test \lohi {aha} {ah} test +%D \lohi [left] {aha} {ah}test \lohi [left] {aha} {ah} test %D \stopbuffer %D %D \typebuffer %D \getbuffer -\unexpanded\def\lohi{\dosingleempty\typo_scripts_lohi} -\unexpanded\def\hilo{\dosingleempty\typo_scripts_hilo} +\installcorenamespace {lowhigh} + +\installcommandhandler \??lowhigh {lowhigh} \??lowhigh + +\setuplowhigh + [\c!style=\tx, + \c!distance=.1\exheight, % these are + \c!up=.96\exheight, % historical + \c!down=.58\exheight] % values -\def\typo_scripts_lohi[#1]#2#3% +\appendtoks + \setuevalue\currentlowhigh{\typo_scripts_lowhigh{\currentlowhigh}\typo_scripts_lowhigh_indeed}% +\to \everydefinelowhigh + +\unexpanded\def\typo_scripts_lowhigh#1% #2 {\dontleavehmode - \hbox - {\dostarttagged\t!subsup\empty - \setbox4\hbox{\typo_scripts_high_low\lower\mathsubnormal{.48}\highlowvfraction\t!sub{#2}}% - \setbox6\hbox{\typo_scripts_high_low\raise\mathsupnormal{.86}\highlowvfraction\t!sup{#3}}% - \doif{#1}{\v!left} - {\ifdim\wd4<\wd6 - \setbox4\hbox to \wd6{\hss\box4}% - \else - \setbox6\hbox to \wd4{\hss\box6}% - \fi}% - \ifdim\wd4<\wd6 - \wd4=\zeropoint\box4\box6 + \hbox\bgroup + \edef\currentlowhigh{#1}% + \dosingleempty} % #2 + +\unexpanded\def\typo_scripts_lowhigh_indeed[#1]#2#3% todo: align .. [#1] is compatible hack + {\dostarttagged\t!subsup\currentlowhigh + \setbox\plusfour\hbox{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}% + \setbox\plussix \hbox{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}% + \doif{#1}{\v!left} + {\ifdim\wd\plusfour<\wd\plussix + \setbox\plusfour\hbox to \wd\plussix {\hss\box\plusfour}% \else - \wd6=\zeropoint\box6\box4 - \fi - \dostoptagged}} + \setbox\plussix \hbox to \wd\plusfour{\hss\box\plussix }% + \fi}% + \ifdim\wd\plusfour<\wd\plussix + \wd\plusfour\zeropoint + \box\plusfour + \box\plussix + \else + \wd\plussix\zeropoint + \box\plussix + \box\plusfour + \fi + \dostoptagged + \egroup} + +\def\typo_scripts_lowhigh_low_high#1#2#3#4% + {\dontleavehmode + \begingroup + \kern\lowhighparameter\c!distance\relax + \setbox\scratchbox\hbox\bgroup + #1\lowhighparameter#2\hbox\bgroup + \ifx\fontsize\empty + \ifmmode + \mr % no color yet + \else + \uselowhighstyleandcolor\c!style\c!color + \fi + \else + \uselowhighstyleandcolor\c!style\c!color + \fi + \dostarttagged#3\empty + #4% + \dostoptagged + \egroup + \egroup + \ht\scratchbox\strutht + \dp\scratchbox\strutdp + \box\scratchbox + \endgroup} + +\unexpanded\def\typo_scripts_highlow_indeed[#1]#2#3% + {\typo_scripts_lowhigh_indeed[#1]{#3}{#2}} + +\unexpanded\def\lohi{\typo_scripts_lowhigh\empty\typo_scripts_lowhigh_indeed} +\unexpanded\def\hilo{\typo_scripts_lowhigh\empty\typo_scripts_highlow_indeed} + +%D \macros +%D {lowmidhigh, definelowmidhigh, setuplowmidhigh} +%D +%D The previous command originally didn't have definers. These were introduced when +%D the next showed up: +%D +%D \startbuffer +%D \definelow [MyLow] [style=\txx] +%D \definehigh [MyHigh] [style=\txx] +%D \definelowhigh [MyLoHi] [style=\txx] +%D \definelowmidhigh[MyLoMiHi][style=\txx] +%D +%D We have +%D \ruledhbox{\low {L}} and \ruledhbox{\MyLow {L}} and +%D \ruledhbox{\high {H}} and \ruledhbox{\MyHigh {H}} and +%D \ruledhbox{\lohi {L}{H}} and \ruledhbox{\MyLoHi {L}{H}} and +%D \ruledhbox{\lomihi{L}{M}{H}} and \ruledhbox{\MyLoMiHi{L}{M}{H}}. +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace {lowmidhigh} + +\installcommandhandler \??lowmidhigh {lowmidhigh} \??lowmidhigh + +\setuplowmidhigh + [\c!style=\tx, + \c!up=.8\struthtdp, + \c!down=.8\struthtdp] + +\appendtoks + \setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh{\currentlowmidhigh}}% +\to \everydefinelowmidhigh + +\unexpanded\def\typo_scripts_lowmidhigh#1#2#3#4% + {\dontleavehmode \hbox \bgroup + \edef\currentlowmidhigh{#1}% + \dostarttagged\t!subsup\currentlowmidhigh + \uselowmidhighstyleandcolor\c!style\c!color + \setstrut + \setbox\plustwo \hbox{\strut\dostarttagged\t!sub\empty#2\dostoptagged}% + \setbox\plusfour\hbox{\strut\dostarttagged\t!mid\empty#3\dostoptagged}% inefficient + \setbox\plussix \hbox{\strut\dostarttagged\t!sup\empty#4\dostoptagged}% + \scratchdimen \wd + \ifdim\wd\plustwo>\wd\plusfour + \ifdim\wd\plustwo>\wd\plussix + \plustwo + \else + \plussix + \fi + \else + \ifdim\wd\plusfour>\wd\plussix + \plusfour + \else + \plussix + \fi + \fi + \relax + \setbox\plustwo \hbox to \scratchdimen{\hss\lower\lowmidhighparameter\c!down\box\plustwo \hss}% + \setbox\plusfour\hbox to \scratchdimen{\hss \box\plusfour\hss}% + \setbox\plussix \hbox to \scratchdimen{\hss\raise\lowmidhighparameter\c!up \box\plussix \hss}% + \wd\plustwo \zeropoint + \wd\plusfour\zeropoint + \box\plusfour + \box\plustwo + \box\plussix + \dostoptagged + \egroup} -\def\typo_scripts_hilo[#1]#2#3% - {\typo_scripts_lohi[#1]{#3}{#2}} +\unexpanded\def\lomihi {\typo_scripts_lowmidhigh\empty} +\unexpanded\def\himilo#1#2#3{\typo_scripts_lowmidhigh\empty{#3}{#2}{#1}} \protect \endinput diff --git a/tex/context/base/typo-spa.mkiv b/tex/context/base/typo-spa.mkiv index 0cfe44610..df2dab47c 100644 --- a/tex/context/base/typo-spa.mkiv +++ b/tex/context/base/typo-spa.mkiv @@ -25,7 +25,12 @@ \installcorenamespace{characterspacing} -\definesystemvariable{cs} % maybe a dummy namespace +\installsetuponlycommandhandler \??characterspacing {_p_characterspacing} % private + +\setup_p_characterspacing + [\c!left=0, + \c!right=0, + \c!alternative=0] \unexpanded\def\definecharacterspacing[#1]% {\ctxcommand{definecharacterspacing("#1")}} @@ -35,11 +40,11 @@ \def\typo_characterspacing_setup[#1][#2][#3]% todo: #2 list {\begingroup - \getparameters[\??cs][\c!left=0,\c!right=0,\c!alternative=0,#3]% - \ctxcommand{setupcharacterspacing("#1",\number#2, { - left = \@@csleft, - right = \@@csright, - alternative = \@@csalternative + \setupcurrent_p_characterspacing[#3]% + \ctxcommand{setupcharacterspacing("#1",\number#2, { % todo: just pass #3 to the lua end + left = \direct_p_characterspacingparameter\c!left, + right = \direct_p_characterspacingparameter\c!right, + alternative = \direct_p_characterspacingparameter\c!alternative })}% \endgroup} diff --git a/tex/context/base/typo-txt.mkvi b/tex/context/base/typo-txt.mkvi index f2859b58f..f1c80c1bd 100644 --- a/tex/context/base/typo-txt.mkvi +++ b/tex/context/base/typo-txt.mkvi @@ -2,7 +2,7 @@ %D [ file=typo-txt, %D version=2011.10.27, %D title=\CONTEXT\ Typesetting Macros, -%D subtitle=Texts, +%D subtitle=Text Hacks, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -13,12 +13,63 @@ %D This module replaces the by now rather old supp-fun module. +\writestatus{loading}{ConTeXt Typesetting Macros / Text Hacks} + \unprotect -%D \NormalizeFontHeight \name {sample text} {height} {font} -%D \NormalizeFontWidth \name {sample text} {width} {font} -%D \NormalizeTextHeight {font} {height} {text} -%D \NormalizeTextWidth {font} {width} {text} +\registerctxluafile{typo-txt}{1.001} + +%D \macros +%D {normalizefontheight,normalizefontwidth,normalizedfontsize} +%D +%D Next we introduce some font manipulation macros. When we +%D want to typeset some text spread in a well defined area, it +%D can be considered bad practice to manipulate character and +%D word spacing. In such situations the next few macros can be +%D of help: +%D +%D \starttyping +%D \normalizefontheight \name {sample text} {height} {font} +%D \normalizefontwidth \name {sample text} {width} {font} +%D \stoptyping +%D +%D Consider for instance: +%D +%D \startbuffer[a] +%D \NormalizeFontHeight \TempFont {X} {2\baselineskip} {Serif} +%D \stopbuffer +%D +%D \startbuffer[b] +%D \ruledhbox{\TempFont To Be Or Not To Be} +%D \stopbuffer +%D +%D \typebuffer[a,b] \getbuffer[a] +%D +%D This shows up as: +%D +%D \startlinecorrection +%D \ruledhbox{\getbuffer[b]} +%D \stoplinecorrection +%D +%D The horizontal counterpart is: +%D +%D \startbuffer[a] +%D \NormalizeFontWidth \TempFont {This Line Fits} {\hsize} {Serif} +%D \stopbuffer +%D +%D \startbuffer[b] +%D \ruledhbox{\TempFont This Line Fits} +%D \stopbuffer +%D +%D \typebuffer[a,b] \getbuffer[a] +%D +%D This gives: +%D +%D \startlinecorrection +%D \ruledhbox{\getbuffer[b]} +%D \stoplinecorrection +%D +%D The calculated font scale is avaliable in \type {\normalizedfontsize}. \newbox\b_typo_normalizers @@ -26,14 +77,14 @@ {\dimexpr\ifdim#1\b_typo_normalizers=\zeropoint \bodyfontsize \else - \cldcontext{\number\dimexpr10pt\relax*\number\dimexpr#size\relax/\number#axis\b_typo_normalizers}\scaledpoint + \luaexpr{\number\dimexpr10pt\relax*\number\dimexpr#size\relax/\number#axis\b_typo_normalizers}\scaledpoint \fi\relax} \def\typo_normalizers_font_at_size#axis#cs#text#size#font% avoid overflow by using lua {\begingroup \setbox\b_typo_normalizers\hbox{\definedfont[#font at 10pt]\settrialtypesetting#text}% - \normalexpanded{\endgroup\edef\noexpand\TheNormalizedFontSize{\the\typo_normalizers_size{#axis}{#size}}}% - \edef#cs{\noexpand\definedfont[#font at \TheNormalizedFontSize]}} + \normalexpanded{\endgroup\edef\noexpand\normalizedfontsize{\the\typo_normalizers_size{#axis}{#size}}}% + \definefont[\strippedcsname#cs][#font at \normalizedfontsize]} \unexpanded\def\typo_normalizers_text_at_size#axis#font#size#text% {\dontleavehmode @@ -42,30 +93,105 @@ \definedfont[#font at \the\typo_normalizers_size{#axis}{#size}]#text% \endgroup} -\let\TheNormalizedFontSize\!!zeropoint +\def\normalizedfontsize{\bodyfontsize} + +\unexpanded\def\normalizetextwidth {\typo_normalizers_text_at_size\wd} +\unexpanded\def\normalizetextheight{\typo_normalizers_text_at_size\ht} +\unexpanded\def\normalizetextdepth {\typo_normalizers_text_at_size\dp} +\unexpanded\def\normalizetextline {\typo_normalizers_text_at_size\htdp} + +\unexpanded\def\normalizefontwidth {\typo_normalizers_font_at_size\wd} +\unexpanded\def\normalizefontheight{\typo_normalizers_font_at_size\ht} +\unexpanded\def\normalizefontdepth {\typo_normalizers_font_at_size\dp} +\unexpanded\def\normalizefontline {\typo_normalizers_font_at_size\htdp} -%D Traditionally we use UpperCasedNames for this kind of -%D functionality. +\unexpanded\def\widthspanningtext #text#size#specification{\hbox{\normalizefontwidth \temp{#text}{#size}{#specification}\temp#text}} +\unexpanded\def\heightspanningtext#text#size#specification{\hbox{\normalizefontheight\temp{#text}{#size}{#specification}\temp#text}} +\unexpanded\def\depthspanningtext #text#size#specification{\hbox{\normalizefontdepth \temp{#text}{#size}{#specification}\temp#text}} +\unexpanded\def\linespanningtext #text#size#specification{\hbox{\normalizefontline \temp{#text}{#size}{#specification}\temp#text}} -\unexpanded\def\NormalizeFontHeight{\typo_normalizers_font_at_size\ht} -\unexpanded\def\NormalizeFontWidth {\typo_normalizers_font_at_size\wd} +%D Traditionally we use UpperCasedNames for this kind of functionality. -\unexpanded\def\NormalizeTextHeight{\typo_normalizers_text_at_size\ht} -\unexpanded\def\NormalizeTextWidth {\typo_normalizers_text_at_size\wd} +\let\NormalizeFontHeight \normalizefontheight +\let\NormalizeFontWidth \normalizefontwidth +\let\NormalizeTextHeight \normalizetextheight +\let\NormalizeTextWidth \normalizetextwidth -\unexpanded\def\WidthSpanningText#text#width#font% compatibility macro - {\hbox{\NormalizeFontWidth\temp{#text}{#width}{#font}\temp\the\everydefinedfont#1}} +\let\WidthSpanningText \widthspanningtext +\def\TheNormalizedFontSize{\normalizedfontsize} + +%D \macros +%D {vulgarfraction} +%D +%D This code is moved from \type {cor-mis.mkiv}. We show three versions. First +%D the simple one using \type {\low} and \type {high}: +%D %D \startbuffer -%D \NormalizeFontWidth \MyFontName {sample text} {10cm} {Serif*default} +%D \def\vfrac#1#2% +%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}} +%D +%D test \vfrac{1}{2} test \vfrac{123}{456} test +%D \stopbuffer +%D +%D \typebuffer {\showmakeup\getbuffer} +%D +%D A better way to handle the kerning is the following, here we kind of assume +%D that tye slash is symmetrical and has nearly zero width. %D -%D \ruledhbox{\MyFontName sample text} -%D \blank -%D \blackrule[width=10cm] -%D \blank -%D \ruledhbox{\NormalizeTextWidth {Serif*default} {10cm} {sample text}} +%D \startbuffer +%D \def\vfract#1#2% +%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}} %D \stopbuffer %D -%D \typebuffer \getbuffer +%D \typebuffer {\showmakeup\getbuffer} +%D +%D The third and best alternative is the following: +%D +%D {\showmakeup\getbuffer}\crlf\getbuffer +%D +%D This time we measure the height of the \type {/} and shift over the maximum +%D height and depths of this character and the fractional digits (we use 57 as +%D sample). Here we combine all methods in one macros. + +\setnewconstant\vulgarfractionmethod\plusthree + +\definehspace[\v!vulgarfraction][.25em] % [.15em] +\definesymbol[\v!vulgarfraction][/] % [\raise.2ex\hbox{/}] + +\unexpanded\def\vulgarfraction#1#2% + {\dontleavehmode + \hbox + {\def\vulgarfraction{vulgarfraction}% + \ifcase\vulgarfractionmethod + #1\symbol[\v!vulgarfraction]#2% + \or + \high{\tx#1\kern-\hspaceamount\empty\v!vulgarfraction}% + \symbol[\vulgarfraction]% + \low {\kern-\hspaceamount\empty\v!vulgarfraction\tx#2}% + \or + \high{\tx#1}% + \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}% + \low{\tx#2}% + \or + \setbox0\hbox{\symbol[\vulgarfraction]}% + \setbox2\hbox{\txx57}% + \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}% + \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}% + \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}% + \fi}} + +\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi + +%D \starttabulate[|l|l|] +%D \HL +%D \NC \bf method \NC \bf visualization \NC\NR +%D \HL +%D \NC 0 \NC \vulgarfractionmethod0 \vulgarfraction{1}{2} \NC\NR +%D \NC 1 \NC \vulgarfractionmethod1 \vulgarfraction{1}{2} \NC\NR +%D \NC 2 \NC \vulgarfractionmethod2 \vulgarfraction{1}{2} \NC\NR +%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR +%D \HL +%D \stoptabulate \protect \endinput diff --git a/tex/context/base/unic-ini.mkiv b/tex/context/base/unic-ini.mkiv index 55764dbdc..ece0da283 100644 --- a/tex/context/base/unic-ini.mkiv +++ b/tex/context/base/unic-ini.mkiv @@ -30,7 +30,7 @@ \def\unicodechar#1{\ctxcommand{unicodechar("#1")}} \unexpanded\def\unknownchar - {\dontleavehmode\hbox{\vrule\!!width.5em\!!height1ex\!!depth\zeropoint}} + {\dontleavehmode\hbox{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}} \ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace diff --git a/tex/context/base/util-deb.lua b/tex/context/base/util-deb.lua index d82c1a114..33d43b25f 100644 --- a/tex/context/base/util-deb.lua +++ b/tex/context/base/util-deb.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['util.deb'] = { +if not modules then modules = { } end modules ['util-deb'] = { version = 1.001, comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -122,6 +122,7 @@ function inspect(i) -- global function else print(tostring(i)) end + return i -- so that we can inline the inspect end -- from the lua book: diff --git a/tex/context/base/util-dim.lua b/tex/context/base/util-dim.lua index 47e43c386..4bae2d099 100644 --- a/tex/context/base/util-dim.lua +++ b/tex/context/base/util-dim.lua @@ -16,7 +16,7 @@ table.</p> --ldx]]-- local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable -local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match +local P, S, R, Cc, C, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.C, lpeg.match local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -141,6 +141,12 @@ local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is lpeg.patterns.dimenpair = dimenpair +local splitter = amount/tonumber * C(unit^1) + +function number.splitdimen(str) + return lpegmatch(splitter,str) +end + --[[ldx-- <p>We use a metatable to intercept errors. When no key is found in the table with factors, the metatable will be consulted for an @@ -430,12 +436,12 @@ probably use a hash instead of a one-element table.</p> <p>Goodie:s</p> --ldx]]-- -function number.percent(n) -- will be cleaned up once luatex 0.30 is out - local hsize = tex.hsize - if type(hsize) == "string" then - hsize = stringtodimen(hsize) +function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out + d = d or tex.hsize + if type(d) == "string" then + d = stringtodimen(d) end - return (n/100) * hsize + return (n/100) * d end number["%"] = number.percent diff --git a/tex/context/base/util-jsn.lua b/tex/context/base/util-jsn.lua new file mode 100644 index 000000000..7493f108d --- /dev/null +++ b/tex/context/base/util-jsn.lua @@ -0,0 +1,145 @@ +if not modules then modules = { } end modules ['util-jsn'] = { + version = 1.001, + comment = "companion to m-json.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Of course we could make a nice complete parser with proper error messages but +-- as json is generated programmatically errors are systematic and we can assume +-- a correct stream. If not, we have some fatal error anyway. So, we can just rely +-- on strings being strings (apart from the unicode escape which is not in 5.1) and +-- as we first catch known types we just assume that anything else is a number. + +local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg +local lpegmatch = lpeg.match +local format = string.format +local utfchar = utf.char +local concat = table.concat + +local tonumber, tostring, rawset, type = tonumber, tostring, rawset, type + +local json = utilities.json or { } +utilities.json = json + +-- moduledata = moduledata or { } +-- moduledata.json = json + +-- \\ \/ \b \f \n \r \t \uHHHH + +local lbrace = P("{") +local rbrace = P("}") +local lparent = P("[") +local rparent = P("]") +local comma = P(",") +local colon = P(":") +local dquote = P('"') + +local whitespace = lpeg.patterns.whitespace +local optionalws = whitespace^0 + +local escape = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end +local jstring = dquote * Cs((escape + (1-dquote))^0) * dquote +local jtrue = P("true") * Cc(true) +local jfalse = P("false") * Cc(false) +local jnull = P("null") * Cc(nil) +local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber + +local key = jstring + +local jsonconverter = { "value", + object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace, + pair = Cg(optionalws * key * optionalws * colon * V("value")), + array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent), + value = optionalws * (jstring + V("object") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws, +} + +-- local jsonconverter = { "value", +-- object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace, +-- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")), +-- array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent), +-- string = jstring, +-- value = optionalws * (V("string") + V("object") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, +-- } + +-- lpeg.print(jsonconverter) -- size 181 + +function json.tolua(str) + return lpegmatch(jsonconverter,str) +end + +local function tojson(value,t) -- we could optimize #t + local kind = type(value) + if kind == "table" then + local done = false + local size = #value + if size == 0 then + for k, v in next, value do + if done then + t[#t+1] = "," + else + t[#t+1] = "{" + done = true + end + t[#t+1] = format("%q:",k) + tojson(v,t) + end + if done then + t[#t+1] = "}" + else + t[#t+1] = "{}" + end + elseif size == 1 then + -- we can optimize for non tables + t[#t+1] = "[" + tojson(value[1],t) + t[#t+1] = "]" + else + for i=1,size do + if done then + t[#t+1] = "," + else + t[#t+1] = "[" + done = true + end + tojson(value[i],t) + end + t[#t+1] = "]" + end + elseif kind == "string" then + t[#t+1] = format("%q",value) + elseif kind == "number" then + t[#t+1] = value + elseif kind == "boolean" then + t[#t+1] = tostring(value) + end + return t +end + +function json.tostring(value) + -- todo optimize for non table + local kind = type(value) + if kind == "table" then + return concat(tojson(value,{}),"") + elseif kind == "string" or kind == "number" then + return value + else + return tostring(value) + end +end + +-- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] + +-- tmp = json.tolua(tmp) +-- inspect(tmp) +-- tmp = json.tostring(tmp) +-- inspect(tmp) +-- tmp = json.tolua(tmp) +-- inspect(tmp) +-- tmp = json.tostring(tmp) +-- inspect(tmp) + +-- inspect(json.tostring(true)) + +return json diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua index b49e93beb..2baeaa854 100644 --- a/tex/context/base/util-lua.lua +++ b/tex/context/base/util-lua.lua @@ -2,36 +2,208 @@ if not modules then modules = { } end modules ['util-lua'] = { version = 1.001, comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + comment = "the strip code is written by Peter Cawley", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -utilities = utilities or {} -utilities.lua = utilities.lua or { } -utilities.report = logs and logs.reporter("system") or print +local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format +local loadstring, loadfile, type = loadstring, loadfile, type -local function stupidcompile(luafile,lucfile) - local data = io.loaddata(luafile) - if data and data ~= "" then - data = string.dump(data) - if data and data ~= "" then - io.savedata(lucfile,data) +utilities = utilities or {} +utilities.lua = utilities.lua or { } +local luautilities = utilities.lua + +utilities.report = logs and logs.reporter("system") or print -- can be overloaded later + +local tracestripping = false +local forcestupidcompile = true -- use internal bytecode compiler +luautilities.stripcode = true -- support stripping when asked for +luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12) +luautilities.nofstrippedchunks = 0 +luautilities.nofstrippedbytes = 0 + +-- The next function was posted by Peter Cawley on the lua list and strips line +-- number information etc. from the bytecode data blob. We only apply this trick +-- when we store data tables. Stripping makes the compressed format file about +-- 1MB smaller (and uncompressed we save at least 6MB). +-- +-- You can consider this feature an experiment, so it might disappear. There is +-- no noticeable gain in runtime although the memory footprint should be somewhat +-- smaller (and the file system has a bit less to deal with). +-- +-- Begin of borrowed code ... works for Lua 5.1 which LuaTeX currently uses ... + +local function strip_code_pc(dump,name) + local before = #dump + local version, format, endian, int, size, ins, num = byte(dump,5,11) + local subint + if endian == 1 then + subint = function(dump, i, l) + local val = 0 + for n = l, 1, -1 do + val = val * 256 + byte(dump,i + n - 1) + end + return val, i + l + end + else + subint = function(dump, i, l) + local val = 0 + for n = 1, l, 1 do + val = val * 256 + byte(dump,i + n - 1) + end + return val, i + l + end + end + local strip_function + strip_function = function(dump) + local count, offset = subint(dump, 1, size) + local stripped, dirty = rep("\0", size), offset + count + offset = offset + count + int * 2 + 4 + offset = offset + int + subint(dump, offset, int) * ins + count, offset = subint(dump, offset, int) + for n = 1, count do + local t + t, offset = subint(dump, offset, 1) + if t == 1 then + offset = offset + 1 + elseif t == 4 then + offset = offset + size + subint(dump, offset, size) + elseif t == 3 then + offset = offset + num + end + end + count, offset = subint(dump, offset, int) + stripped = stripped .. sub(dump,dirty, offset - 1) + for n = 1, count do + local proto, off = strip_function(sub(dump,offset, -1)) + stripped, offset = stripped .. proto, offset + off - 1 + end + offset = offset + subint(dump, offset, int) * int + int + count, offset = subint(dump, offset, int) + for n = 1, count do + offset = offset + subint(dump, offset, size) + size + int * 2 + end + count, offset = subint(dump, offset, int) + for n = 1, count do + offset = offset + subint(dump, offset, size) + size + end + stripped = stripped .. rep("\0", int * 3) + return stripped, offset + end + dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1)) + local after = #dump + local delta = before-after + if tracestripping then + utilities.report("stripped bytecode: %s, before %s, after %s, delta %s",name or "unknown",before,after,delta) + end + luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1 + luautilities.nofstrippedbytes = luautilities.nofstrippedbytes + delta + return dump, delta +end + +-- ... end of borrowed code. + +local function strippedbytecode(code,forcestrip,name) + if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then + return strip_code_pc(code,name) + else + return code, 0 + end +end + +luautilities.stripbytecode = strip_code_pc +luautilities.strippedbytecode = strippedbytecode + +local function fatalerror(name) + utilities.report(format("fatal error in %q",name or "unknown")) +end + +-- quite subtle ... doing this wrong incidentally can give more bytes + + +function luautilities.loadedluacode(fullname,forcestrip,name) + -- quite subtle ... doing this wrong incidentally can give more bytes + name = name or fullname + local code = loadfile(fullname) + if code then + code() + end + if forcestrip and luautilities.stripcode then + if type(forcestrip) == "function" then + forcestrip = forcestrip(fullname) + end + if forcestrip then + local code, n = strip_code_pc(dump(code,name)) + return loadstring(code), n + elseif luautilities.alwaysstripcode then + return loadstring(strip_code_pc(dump(code),name)) + else + return code, 0 + end + elseif luautilities.alwaysstripcode then + return loadstring(strip_code_pc(dump(code),name)) + else + return code, 0 + end +end + +function luautilities.strippedloadstring(code,forcestrip,name) -- not executed + local n = 0 + if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then + code = loadstring(code) + if not code then + fatalerror(name) end + code, n = strip_code_pc(dump(code),name) end + return loadstring(code), n end -function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true +local function stupidcompile(luafile,lucfile,strip) + local code = io.loaddata(luafile) + local n = 0 + if code and code ~= "" then + code = loadstring(code) + if not code then + fatalerror() + end + code = dump(code) + if strip then + code, n = strippedbytecode(code,true,luafile) -- last one is reported + end + if code and code ~= "" then + io.savedata(lucfile,code) + end + end + return n +end + +local luac_normal = "texluac -o %q %q" +local luac_strip = "texluac -s -o %q %q" + +function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true utilities.report("lua: compiling %s into %s",luafile,lucfile) os.remove(lucfile) - local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile) + local done = false if strip ~= false then - command = "-s " .. command + strip = true + end + if forcestupidcompile then + fallback = true + elseif strip then + done = os.spawn(format(luac_strip, lucfile,luafile)) == 0 + else + done = os.spawn(format(luac_normal,lucfile,luafile)) == 0 end - local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0 if not done and fallback then - utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile) - stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere - cleanup = false -- better see how worse it is + local n = stupidcompile(luafile,lucfile,strip) + if n > 0 then + utilities.report("lua: %s dumped into %s (%i bytes stripped)",luafile,lucfile,n) + else + utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile) + end + cleanup = false -- better see how bad it is end if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then utilities.report("lua: removing %s",luafile) @@ -39,16 +211,15 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaul end return done end - --~ local getmetatable, type = getmetatable, type --~ local types = { } ---~ function utilities.lua.registerdatatype(d,name) +--~ function luautilities.registerdatatype(d,name) --~ types[getmetatable(d)] = name --~ end ---~ function utilities.lua.datatype(d) +--~ function luautilities.datatype(d) --~ local t = type(d) --~ if t == "userdata" then --~ local m = getmetatable(d) @@ -58,6 +229,6 @@ end --~ end --~ end ---~ utilities.lua.registerdatatype(lpeg.P("!"),"lpeg") +--~ luautilities.registerdatatype(lpeg.P("!"),"lpeg") ---~ print(utilities.lua.datatype(lpeg.P("oeps"))) +--~ print(luautilities.datatype(lpeg.P("oeps"))) diff --git a/tex/context/base/util-mrg.lua b/tex/context/base/util-mrg.lua index acf04fead..8d6c5dd31 100644 --- a/tex/context/base/util-mrg.lua +++ b/tex/context/base/util-mrg.lua @@ -13,11 +13,10 @@ local concat = table.concat local type, next = type, next utilities = utilities or {} -utilities.merger = utilities.merger or { } -- maybe mergers +local merger = utilities.merger or { } +utilities.merger = merger utilities.report = logs and logs.reporter("system") or print -local merger = utilities.merger - merger.strip_comment = true local m_begin_merge = "begin library merge" @@ -63,9 +62,11 @@ end local function self_save(name, data) if data ~= "" then if merger.strip_comment then - -- saves some 20K local n = #data + -- saves some 20K .. scite comments data = gsub(data,"%-%-~[^\n\r]*[\r\n]","") + -- saves some 20K .. ldx comments + data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","") utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data) end io.savedata(name,data) diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua index ab1bfb8eb..e7191d0e9 100644 --- a/tex/context/base/util-prs.lua +++ b/tex/context/base/util-prs.lua @@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['util-prs'] = { license = "see context related readme files" } -local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg -local lpegmatch = lpeg.match +local lpeg, table, string = lpeg, table, string + +local P, R, V, S, C, Ct, Cs, Carg, Cc = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc +local lpegmatch, patterns = lpeg.match, lpeg.patterns local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find local tostring, type, next = tostring, type, next @@ -19,29 +21,39 @@ parsers.patterns = parsers.patterns or { } local setmetatableindex = table.setmetatableindex local sortedhash = table.sortedhash +-- we share some patterns + +local space = P(' ') +local equal = P("=") +local comma = P(",") +local lbrace = P("{") +local rbrace = P("}") +local period = S(".") +local punctuation = S(".,:;") +local spacer = patterns.spacer +local whitespace = patterns.whitespace +local newline = patterns.newline +local anything = patterns.anything +local endofstring = patterns.endofstring + -- we could use a Cf Cg construct local escape, left, right = P("\\"), P('{'), P('}') -lpeg.patterns.balanced = P { +patterns.balanced = P { [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, [2] = left * V(1) * right } -local space = P(' ') -local equal = P("=") -local comma = P(",") -local lbrace = P("{") -local rbrace = P("}") local nobrace = 1 - (lbrace+rbrace) local nested = P { lbrace * (nobrace + V(1))^0 * rbrace } local spaces = space^0 local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/"")) -local content = (1-P(-1))^0 +local content = (1-endofstring)^0 -lpeg.patterns.nested = nested -- no capture -lpeg.patterns.argument = argument -- argument after e.g. = -lpeg.patterns.content = content -- rest after e.g = +patterns.nested = nested -- no capture +patterns.argument = argument -- argument after e.g. = +patterns.content = content -- rest after e.g = local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0) @@ -60,10 +72,6 @@ local function set(key,value) hash[key] = value end -local function set(key,value) - hash[key] = value -end - local pattern_a_s = (pattern_a/set)^1 local pattern_b_s = (pattern_b/set)^1 local pattern_c_s = (pattern_c/set)^1 @@ -114,7 +122,7 @@ end local separator = comma * space^0 local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0) -local pattern = Ct(value*(separator*value)^0) +local pattern = spaces * Ct(value*(separator*value)^0) -- "aap, {noot}, mies" : outer {} removes, leading spaces ignored @@ -237,3 +245,34 @@ end function parsers.listitem(str) return gmatch(str,"[^, ]+") end + +-- +local digit = R("09") + +local pattern = Cs { "start", + start = V("one") + V("two") + V("three"), + rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0, + thousand = digit * digit * digit, + one = digit * V("rest"), + two = digit * digit * V("rest"), + three = V("thousand") * V("rest"), +} + +patterns.splitthousands = pattern -- maybe better in the parsers namespace ? + +function parsers.splitthousands(str) + return lpegmatch(pattern,str) or str +end + +-- print(parsers.splitthousands("11111111111.11")) + +local optionalwhitespace = whitespace^0 + +patterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1) +patterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1) +patterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1) + +-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n " +-- inspect(lpegmatch(patterns.paragraphs,str)) +-- inspect(lpegmatch(patterns.sentences,str)) +-- inspect(lpegmatch(patterns.words,str)) diff --git a/tex/context/base/util-sql-imp-client.lua b/tex/context/base/util-sql-imp-client.lua new file mode 100644 index 000000000..8e174fc99 --- /dev/null +++ b/tex/context/base/util-sql-imp-client.lua @@ -0,0 +1,253 @@ +if not modules then modules = { } end modules ['util-sql-client'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- todo: make a converter + +local rawset, setmetatable = rawset, setmetatable +local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) +local report_state = logs.reporter("sql","client") + +local sql = require("util-sql") +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local splitdata = helpers.splitdata +local replacetemplate = utilities.templates.replace +local serialize = sql.serialize +local deserialize = sql.deserialize + +-- Experiments with an p/action demonstrated that there is not much gain. We could do a runtime +-- capture but creating all the small tables is not faster and it doesn't work well anyway. + +local separator = P("\t") +local newline = patterns.newline +local empty = Cc("") + +local entry = C((1-separator-newline)^0) -- C 10% faster than Cs + +local unescaped = P("\\n") / "\n" + + P("\\t") / "\t" + + P("\\0") / "\000" + + P("\\\\") / "\\" + +local entry = Cs((unescaped + (1-separator-newline))^0) -- C 10% faster than Cs but Cs needed due to nesting + +local getfirst = Ct( entry * (separator * (entry+empty))^0) + newline +local skipfirst = (1-newline)^1 * newline +local getfirstline = C((1-newline)^0) + +local cache = { } + +local function splitdata(data) -- todo: hash on first line ... maybe move to client module + if data == "" then + if trace_sql then + report_state("no data") + end + return { }, { } + end + local first = lpegmatch(getfirstline,data) + if not first then + if trace_sql then + report_state("no data") + end + return { }, { } + end + local p = cache[first] + if p then + -- report_state("reusing: %s",first) + local entries = lpegmatch(p.parser,data) + return entries or { }, p.keys + elseif p == false then + return { }, { } + elseif p == nil then + local keys = lpegmatch(getfirst,first) or { } + if #keys == 0 then + if trace_sql then + report_state("no banner") + end + cache[first] = false + return { }, { } + end + -- quite generic, could be a helper + local n = #keys + if n == 0 then + report_state("no fields") + cache[first] = false + return { }, { } + end + if n == 1 then + local key = keys[1] + if trace_sql then + report_state("one field with name",key) + end + p = Cg(Cc(key) * entry) + else + for i=1,n do + local key = keys[i] + if trace_sql then + report_state("field %s has name %q",i,key) + end + local s = Cg(Cc(key) * entry) + if p then + p = p * separator * s + else + p = s + end + end + end + p = Cf(Ct("") * p,rawset) * newline^1 + p = skipfirst * Ct(p^0) + cache[first] = { parser = p, keys = keys } + local entries = lpegmatch(p,data) + return entries or { }, keys + end +end + +local splitter = skipfirst * Ct((Ct(entry * (separator * entry)^0) * newline^1)^0) + +local function getdata(data) + return lpegmatch(splitter,data) +end + +helpers.splitdata = splitdata +helpers.getdata = getdata + +local function dataprepared(specification) + local query = preparetemplate(specification) + if query then + io.savedata(specification.queryfile,query) + os.remove(specification.resultfile) + if trace_queries then + report_state("query: %s",query) + end + return true + else + -- maybe push an error + os.remove(specification.queryfile) + os.remove(specification.resultfile) + end +end + +local function datafetched(specification,runner) + local command = replacetemplate(runner,specification) + if trace_sql then + local t = osclock() + report_state("command: %s",command) + local okay = os.execute(command) + report_state("fetchtime: %.3f sec",osclock()-t) -- not okay under linux + return okay == 0 + else + return os.execute(command) == 0 + end +end + +local function dataloaded(specification) + if trace_sql then + local t = osclock() + local data = io.loaddata(specification.resultfile) or "" + report_state("datasize: %.3f MB",#data/1024/1024) + report_state("loadtime: %.3f sec",osclock()-t) + return data + else + return io.loaddata(specification.resultfile) or "" + end +end + +local function dataconverted(data,converter) + if converter then + local data = getdata(data) + if data then + converter.client(data) + end + return data + elseif trace_sql then + local t = osclock() + local data, keys = splitdata(data) + report_state("converttime: %.3f",osclock()-t) + report_state("keys: %s ",#keys) + report_state("entries: %s ",#data) + return data, keys + else + return splitdata(data) + end +end + +-- todo: new, etc + +local function execute(specification) + if trace_sql then + report_state("executing client") + end + if not validspecification(specification) then + report_state("error in specification") + return + end + if not dataprepared(specification) then + report_state("error in preparation") + return + end + if not datafetched(specification,methods.client.runner) then + report_state("error in fetching, query: %s",string.collapsespaces(io.loaddata(specification.queryfile))) + return + end + local data = dataloaded(specification) + if not data then + report_state("error in loading") + return + end + local data, keys = dataconverted(data,specification.converter) + if not data then + report_state("error in converting") + return + end + local one = data[1] + if one then + setmetatable(data,{ __index = one } ) + end + return data, keys +end + +-- The following is not that (memory) efficient but normally we will use +-- the lib anyway. Of course we could make a dedicated converter and/or +-- hook into the splitter code but ... it makes not much sense because then +-- we can as well move the builder to the library modules. + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(data) + for i=1,#data do + local cells = data[i] + data[i] = { + %s + } + end + return data +end +]] + +local celltemplate = "cells[%s]" + +methods.client = { + runner = [[mysql --batch --user="%username%" --password="%password%" --host="%host%" --port=%port% --database="%database%" --default-character-set=utf8 < "%queryfile%" > "%resultfile%"]], + execute = execute, + usesfiles = true, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} diff --git a/tex/context/base/util-sql-imp-library.lua b/tex/context/base/util-sql-imp-library.lua new file mode 100644 index 000000000..f16739085 --- /dev/null +++ b/tex/context/base/util-sql-imp-library.lua @@ -0,0 +1,283 @@ +if not modules then modules = { } end modules ['util-sql-library'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- For some reason the sql lib partially fails in luatex when creating hashed row. So far +-- we couldn't figure it out (some issue with adapting the table that is passes as first +-- argument in the fetch routine. Apart from this it looks like the mysql binding has some +-- efficiency issues (like creating a keys and types table for each row) but that could be +-- optimized. Anyhow, fecthing results can be done as follows: + +-- local function collect_1(r) +-- local t = { } +-- for i=1,r:numrows() do +-- t[#t+1] = r:fetch({},"a") +-- end +-- return t +-- end +-- +-- local function collect_2(r) +-- local keys = r:getcolnames() +-- local n = #keys +-- local t = { } +-- for i=1,r:numrows() do +-- local v = { r:fetch() } +-- local r = { } +-- for i=1,n do +-- r[keys[i]] = v[i] +-- end +-- t[#t+1] = r +-- end +-- return t +-- end +-- +-- local function collect_3(r) +-- local keys = r:getcolnames() +-- local n = #keys +-- local t = { } +-- for i=1,r:numrows() do +-- local v = r:fetch({},"n") +-- local r = { } +-- for i=1,n do +-- r[keys[i]] = v[i] +-- end +-- t[#t+1] = r +-- end +-- return t +-- end +-- +-- On a large table with some 8 columns (mixed text and numbers) we get the following +-- timings (the 'a' alternative is already using the more efficient variant in the +-- binding). +-- +-- collect_1 : 1.31 +-- collect_2 : 1.39 +-- collect_3 : 1.75 +-- +-- Some, as a workaround for this 'bug' the second alternative can be used. + +local format = string.format +local lpegmatch = lpeg.match +local setmetatable, type = setmetatable, type + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) +local report_state = logs.reporter("sql","library") + +local sql = require("util-sql") +local mysql = require("luasql.mysql") +local cache = { } +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local querysplitter = helpers.querysplitter +local dataprepared = helpers.preparetemplate +local serialize = sql.serialize +local deserialize = sql.deserialize + +local initialize = mysql.mysql + +local function connect(session,specification) + return session:connect( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) +end + +local function datafetched(specification,query,converter) + if not query or query == "" then + report_state("no valid query") + return { }, { } + end + local id = specification.id + local session, connection + if id then + local c = cache[id] + if c then + session = c.session + connection = c.connection + end + if not connection then + session = initialize() + connection = connect(session,specification) + cache[id] = { session = session, connection = connection } + end + else + session = initialize() + connection = connect(session,specification) + end + if not connection then + report_state("error in connection: %s@%s to %s:%s", + specification.database or "no database", + specification.username or "no username", + specification.host or "no host", + specification.port or "no port" + ) + return { }, { } + end + query = lpegmatch(querysplitter,query) + local result, message, okay + for i=1,#query do + local q = query[i] + local r, m = connection:execute(q) + if m then + report_state("error in query, stage 1: %s",string.collapsespaces(q)) + message = message and format("%s\n%s",message,m) or m + end + local t = type(r) + if t == "userdata" then + result = r + okay = true + elseif t == "number" then + okay = true + end + end + if not okay and id then -- can go + if session then + session:close() + end + if connection then + connection:close() + end + session = initialize() -- maybe not needed + connection = connect(session,specification) + if connection then + cache[id] = { session = session, connection = connection } + for i=1,#query do + local q = query[i] + local r, m = connection:execute(q) + if m then + report_state("error in query, stage 2: %s",string.collapsespaces(q)) + message = message and format("%s\n%s",message,m) or m + end + local t = type(r) + if t == "userdata" then + result = r + okay = true + elseif t == "number" then + okay = true + end + end + else + message = "unable to connect" + report_state(message) + end + end + local data, keys + if result then + if converter then + data = converter.library(result) + -- data = converter(result) + else + keys = result:getcolnames() + if keys then + local n = result:numrows() or 0 + if n == 0 then + data = { } + -- elseif n == 1 then + -- -- data = { result:fetch({},"a") } + else + data = { } + -- for i=1,n do + -- data[i] = result:fetch({},"a") + -- end + local k = #keys + for i=1,n do + local v = { result:fetch() } + local d = { } + for i=1,k do + d[keys[i]] = v[i] + end + data[#data+1] = d + end + end + end + end + result:close() + elseif message then + report_state("message %s",message) + end + if not keys then + keys = { } + end + if not data then + data = { } + end + if not id then + connection:close() + session:close() + end + return data, keys +end + +local function execute(specification) + if trace_sql then + report_state("executing library") + end + if not validspecification(specification) then + report_state("error in specification") + return + end + local query = dataprepared(specification) + if not query then + report_state("error in preparation") + return + end + local data, keys = datafetched(specification,query,specification.converter) + if not data then + report_state("error in fetching") + return + end + local one = data[1] + if one then + setmetatable(data,{ __index = one } ) + end + return data, keys +end + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(result) + if not result then + return { } + end + local nofrows = result:numrows() or 0 + if nofrows == 0 then + return { } + end + local data = { } + for i=1,nofrows do + local cells = { result:fetch() } + data[i] = { + %s + } + end + return data +end +]] + +local celltemplate = "cells[%s]" + +methods.library = { + runner = function() end, -- never called + execute = execute, + initialize = initialize, -- returns session + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} diff --git a/tex/context/base/util-sql-imp-swiglib.lua b/tex/context/base/util-sql-imp-swiglib.lua new file mode 100644 index 000000000..25723ee84 --- /dev/null +++ b/tex/context/base/util-sql-imp-swiglib.lua @@ -0,0 +1,426 @@ +if not modules then modules = { } end modules ['util-sql-swiglib'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- As the regular library is flawed (i.e. there are crashes in the table +-- construction code) and also not that efficient, Luigi Scarso looked into +-- a swig binding. This is a bit more low level approach but as we stay +-- closer to the original library it's also less dependant. + +local concat = table.concat +local format = string.format +local lpegmatch = lpeg.match +local setmetatable, type = setmetatable, type + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) +local report_state = logs.reporter("sql","swiglib") + +local sql = require("util-sql") +local mysql = require("swigluamysql") +local cache = { } +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local querysplitter = helpers.querysplitter +local dataprepared = helpers.preparetemplate +local serialize = sql.serialize +local deserialize = sql.deserialize + +local mysql_initialize = mysql.mysql_init + +local mysql_open_connection = mysql.mysql_real_connect +local mysql_execute_query = mysql.mysql_real_query +local mysql_close_connection = mysql.mysql_close + +local mysql_field_seek = mysql.mysql_field_seek +local mysql_num_fields = mysql.mysql_num_fields +local mysql_fetch_field = mysql.mysql_fetch_field +local mysql_num_rows = mysql.mysql_num_rows +local mysql_fetch_row = mysql.mysql_fetch_row +local mysql_fetch_lengths = mysql.mysql_fetch_lengths +local mysql_init = mysql.mysql_init +local mysql_store_result = mysql.mysql_store_result +local mysql_free_result = mysql.mysql_free_result +local mysql_use_result = mysql.mysql_use_result + +local mysql_error_message = mysql.mysql_error +local mysql_options_argument = mysql.mysql_options_argument + +local instance = mysql.MYSQL() + +local mysql_constant_false = mysql_options_argument(false) -- 0 "\0" +local mysql_constant_true = mysql_options_argument(true) -- 1 "\1" + +-- print(swig_type(mysql_constant_false)) +-- print(swig_type(mysql_constant_true)) + +mysql.mysql_options(instance,mysql.MYSQL_OPT_RECONNECT,mysql_constant_true); + +local typemap = { + [mysql.MYSQL_TYPE_VAR_STRING ] = "string", + [mysql.MYSQL_TYPE_STRING ] = "string", + [mysql.MYSQL_TYPE_DECIMAL ] = "number", + [mysql.MYSQL_TYPE_SHORT ] = "number", + [mysql.MYSQL_TYPE_LONG ] = "number", + [mysql.MYSQL_TYPE_FLOAT ] = "number", + [mysql.MYSQL_TYPE_DOUBLE ] = "number", + [mysql.MYSQL_TYPE_LONGLONG ] = "number", + [mysql.MYSQL_TYPE_INT24 ] = "number", + [mysql.MYSQL_TYPE_YEAR ] = "number", + [mysql.MYSQL_TYPE_TINY ] = "number", + [mysql.MYSQL_TYPE_TINY_BLOB ] = "binary", + [mysql.MYSQL_TYPE_MEDIUM_BLOB] = "binary", + [mysql.MYSQL_TYPE_LONG_BLOB ] = "binary", + [mysql.MYSQL_TYPE_BLOB ] = "binary", + [mysql.MYSQL_TYPE_DATE ] = "date", + [mysql.MYSQL_TYPE_NEWDATE ] = "date", + [mysql.MYSQL_TYPE_DATETIME ] = "datetime", + [mysql.MYSQL_TYPE_TIME ] = "time", + [mysql.MYSQL_TYPE_TIMESTAMP ] = "time", + [mysql.MYSQL_TYPE_ENUM ] = "set", + [mysql.MYSQL_TYPE_SET ] = "set", + [mysql.MYSQL_TYPE_NULL ] = "null", +} + +-- real_escape_string + +local function finish(t) + mysql_free_result(t._result_) +end + +-- will become metatable magic + +-- local function analyze(result) +-- mysql_field_seek(result,0) +-- local nofrows = mysql_num_rows(result) or 0 +-- local noffields = mysql_num_fields(result) +-- local names = { } +-- local types = { } +-- for i=1,noffields do +-- local field = mysql_fetch_field(result) +-- names[i] = field.name +-- types[i] = field.type +-- end +-- return names, types, noffields, nofrows +-- end + +local function getcolnames(t) + return t.names +end + +local function getcoltypes(t) + return t.types +end + +local function numrows(t) + return t.nofrows +end + +-- swig_type + +-- local ulongArray_getitem = mysql.ulongArray_getitem +-- local util_getbytearray = mysql.util_getbytearray + +-- local function list(t) +-- local result = t._result_ +-- local row = mysql_fetch_row(result) +-- local len = mysql_fetch_lengths(result) +-- local result = { } +-- for i=1,t.noffields do +-- local r = i - 1 -- zero offset +-- result[i] = util_getbytearray(row,r,ulongArray_getitem(len,r)) +-- end +-- return result +-- end + +-- local function hash(t) +-- local list = util_mysql_fetch_fields_from_current_row(t._result_) +-- local result = t._result_ +-- local fields = t.names +-- local row = mysql_fetch_row(result) +-- local len = mysql_fetch_lengths(result) +-- local result = { } +-- for i=1,t.noffields do +-- local r = i - 1 -- zero offset +-- result[fields[i]] = util_getbytearray(row,r,ulongArray_getitem(len,r)) +-- end +-- return result +-- end + +local util_mysql_fetch_fields_from_current_row = mysql.util_mysql_fetch_fields_from_current_row +local util_mysql_fetch_all_rows = mysql.util_mysql_fetch_all_rows + +local function list(t) + return util_mysql_fetch_fields_from_current_row(t._result_) +end + +local function hash(t) + local list = util_mysql_fetch_fields_from_current_row(t._result_) + local fields = t.names + local data = { } + for i=1,t.noffields do + data[fields[i]] = list[i] + end + return data +end + +local function wholelist(t) + return util_mysql_fetch_all_rows(t._result_) +end + +local mt = { __index = { + -- regular + finish = finish, + list = list, + hash = hash, + wholelist = wholelist, + -- compatibility + numrows = numrows, + getcolnames = getcolnames, + getcoltypes = getcoltypes, + } +} + +-- session + +local function close(t) + mysql_close_connection(t._connection_) +end + +local function execute(t,query) + if query and query ~= "" then + local connection = t._connection_ + local result = mysql_execute_query(connection,query,#query) + if result == 0 then + local result = mysql_store_result(connection) + mysql_field_seek(result,0) + local nofrows = mysql_num_rows(result) or 0 + local noffields = mysql_num_fields(result) + local names = { } + local types = { } + for i=1,noffields do + local field = mysql_fetch_field(result) + names[i] = field.name + types[i] = field.type + end + local t = { + _result_ = result, + names = names, + types = types, + noffields = noffields, + nofrows = nofrows, + } + return setmetatable(t,mt) + end + end + return false +end + +local mt = { __index = { + close = close, + execute = execute, + } +} + +local function open(t,database,username,password,host,port) + local connection = mysql_open_connection(t._session_,host or "localhost",username or "",password or "",database or "",port or 0,0,0) + if connection then + local t = { + _connection_ = connection, + } + return setmetatable(t,mt) + end +end + +local function message(t) + return mysql_error_message(t._session_) +end + +local function close(t) + -- dummy, as we have a global session +end + +local mt = { + __index = { + connect = open, + close = close, + message = message, + } +} + +local function initialize() + local session = { + _session_ = mysql_initialize(instance) -- maybe share, single thread anyway + } + return setmetatable(session,mt) +end + +-- -- -- -- + +local function connect(session,specification) + return session:connect( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) +end + +local function datafetched(specification,query,converter) + if not query or query == "" then + report_state("no valid query") + return { }, { } + end + local id = specification.id + local session, connection + if id then + local c = cache[id] + if c then + session = c.session + connection = c.connection + end + if not connection then + session = initialize() + connection = connect(session,specification) + cache[id] = { session = session, connection = connection } + end + else + session = initialize() + connection = connect(session,specification) + end + if not connection then + report_state("error in connection: %s@%s to %s:%s", + specification.database or "no database", + specification.username or "no username", + specification.host or "no host", + specification.port or "no port" + ) + return { }, { } + end + query = lpegmatch(querysplitter,query) + local result, message, okay + for i=1,#query do + local q = query[i] + local r, m = connection:execute(q) + if m then + report_state("error in query, stage: %s",string.collapsespaces(q)) + message = message and format("%s\n%s",message,m) or m + end + if type(r) == "table" then + result = r + okay = true + elseif not m then + okay = true + end + end + local data, keys + if result then + if converter then + data = converter.swiglib(result) + else + keys = result.names + data = { } + for i=1,result.nofrows do + data[i] = result:hash() + end + end + result:finish() -- result:close() + elseif message then + report_state("message %s",message) + end + if not keys then + keys = { } + end + if not data then + data = { } + end + if not id then + connection:close() + session:close() + end + return data, keys +end + +local function execute(specification) + if trace_sql then + report_state("executing library") + end + if not validspecification(specification) then + report_state("error in specification") + return + end + local query = dataprepared(specification) + if not query then + report_state("error in preparation") + return + end + local data, keys = datafetched(specification,query,specification.converter) + if not data then + report_state("error in fetching") + return + end + local one = data[1] + if one then + setmetatable(data,{ __index = one } ) + end + return data, keys +end + +local wraptemplate = [[ +local mysql = require("swigluamysql") -- will be stored in method + +----- mysql_fetch_row = mysql.mysql_fetch_row +----- mysql_fetch_lengths = mysql.mysql_fetch_lengths +----- util_unpackbytearray = mysql.util_unpackbytearray +local util_mysql_fetch_fields_from_current_row + = mysql.util_mysql_fetch_fields_from_current_row + +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(result) + if not result then + return { } + end + local nofrows = result.nofrows or 0 + if nofrows == 0 then + return { } + end + local noffields = result.noffields or 0 + local data = { } + result = result._result_ + for i=1,nofrows do + -- local row = mysql_fetch_row(result) + -- local len = mysql_fetch_lengths(result) + -- local cells = util_unpackbytearray(row,noffields,len) + local cells = util_mysql_fetch_fields_from_current_row(result) + data[i] = { + %s + } + end + return data +end +]] + +local celltemplate = "cells[%s]" + +methods.swiglib = { + runner = function() end, -- never called + execute = execute, + initialize = initialize, -- returns session + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} diff --git a/tex/context/base/util-sql-loggers.lua b/tex/context/base/util-sql-loggers.lua new file mode 100644 index 000000000..b2dccf4b5 --- /dev/null +++ b/tex/context/base/util-sql-loggers.lua @@ -0,0 +1,277 @@ +if not modules then modules = { } end modules ['util-sql-loggers'] = { + version = 1.001, + comment = "companion to lmx-*", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code and currently part of the base installation simply +-- because it's easier to dirtribute this way. Eventually it will be documented +-- and the related scripts will show up as well. + +local tonumber = tonumber +local format = string.format +local concat = table.concat +local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime +local random = math.random + +local sql = utilities.sql +local loggers = { } +sql.loggers = loggers + +local trace_sql = false trackers.register("sql.loggers.trace", function(v) trace_sql = v end) +local report = logs.reporter("sql","loggers") + +loggers.newtoken = sql.tokens.new +local makeconverter = sql.makeconverter + +local function checkeddb(presets,datatable) + return sql.usedatabase(presets,datatable or presets.datatable or "loggers") +end + +loggers.usedb = checkeddb + +local totype = { + ["error"] = 1, [1] = 1, ["1"] = 1, + ["warning"] = 2, [2] = 2, ["2"] = 2, + ["debug"] = 3, [3] = 3, ["3"] = 3, + ["info"] = 4, [4] = 4, ["4"] = 4, +} + +local fromtype = { + ["error"] = "error", [1] = "error", ["1"] = "error", + ["warning"] = "warning", [2] = "warning", ["2"] = "warning", + ["debug"] = "debug", [3] = "debug", ["3"] = "debug", + ["info"] = "info", [4] = "info", ["4"] = "info", +} + +table.setmetatableindex(totype, function() return 4 end) +table.setmetatableindex(fromtype,function() return "info" end) + +loggers.totype = totype +loggers.fromtype = fromtype + +local template =[[ + CREATE TABLE IF NOT EXISTS %basename% ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `time` int(11) NOT NULL, + `type` int(11) NOT NULL, + `action` varchar(15) NOT NULL, + `data` longtext, + PRIMARY KEY (`id`), + UNIQUE KEY `id_unique_key` (`id`) + ) + DEFAULT CHARSET = utf8 ; +]] + +function loggers.createdb(presets,datatable) + + local db = checkeddb(presets,datatable) + + db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q created in %q",db.name,db.base) + + return db + +end + +local template =[[ + DROP TABLE IF EXISTS %basename% ; +]] + +function loggers.deletedb(presets,datatable) + + local db = checkeddb(presets,datatable) + + db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q removed in %q",db.name,db.base) + +end + +local template =[[ + INSERT INTO %basename% ( + `time`, + `type`, + `action`, + `data` + ) VALUES ( + %time%, + %type%, + '%action%', + '%[data]%' + ) ; +]] + +function loggers.save(db,data) -- beware, we pass type and action in the data (saves a table) + + if data then + + local time = ostime() + local kind = totype[data.type] + local action = data.action or "unknown" + + data.type = nil + data.action = nil + + db.execute { + template = template, + variables = { + basename = db.basename, + time = ostime(), + type = kind, + action = action, + data = data and db.serialize(data,"return") or "", + }, + } + + end + +end + +-- local template =[[ +-- REMOVE FROM +-- %basename% +-- WHERE +-- `token` = '%token%' ; +-- ]] +-- +-- function loggers.remove(db,token) +-- +-- db.execute { +-- template = template, +-- variables = { +-- basename = db.basename, +-- token = token, +-- }, +-- } +-- +-- if trace_sql then +-- report("removed: %s",token) +-- end +-- +-- end + +local template_nop =[[ + SELECT + `time`, + `type`, + `action`, + `data` + FROM + %basename% + ORDER BY + `time`, `type`, `action` + DESC LIMIT + %limit% ; +]] + +local template_yes =[[ + SELECT + `time`, + `type`, + `action`, + `data` + FROM + %basename% + %WHERE% + ORDER BY + `time`, `type`, `action` + DESC LIMIT + %limit% ; +]] + +local converter = makeconverter { + -- { name = "time", type = os.localtime }, + { name = "time", type = "number" }, + { name = "type", type = fromtype }, + { name = "action", type = "string" }, + { name = "data", type = "deserialize" }, +} + +function loggers.collect(db,specification) + + specification = specification or { } + + local start = specification.start + local stop = specification.stop + local limit = specification.limit or 100 + local kind = specification.type + local action = specification.action + + local filtered = start or stop + + local where = { } + + if filtered then + local today = os.date("*t") + + if type(start) ~= "table" then + start = { } + end + start = os.time { + day = start.day or today.day, + month = start.month or today.month, + year = start.year or today.year, + hour = start.hour or 0, + minute = start.minute or 0, + second = start.second or 0, + isdst = true, + } + + if type(stop) ~= "table" then + stop = { } + end + stop = os.time { + day = stop.day or today.day, + month = stop.month or today.month, + year = stop.year or today.year, + hour = stop.hour or 24, + minute = stop.minute or 0, + second = stop.second or 0, + isdst = true, + } + + -- report("filter: %s => %s",start,stop) + + where[#where+1] = format("`time` BETWEEN %s AND %s",start,stop) + + end + + if kind then + where[#where+1] = format("`type` = %s",totype[kind]) + end + + if action then + where[#where+1] = format("`action` = '%s'",action) + end + + local records = db.execute { + template = filtered and template_yes or template_nop, + converter = converter, + variables = { + basename = db.basename, + limit = limit, + WHERE = #where > 0 and format("WHERE\n%s",concat(where," AND ")) or "", + }, + } + + if trace_sql then + report("collected: %s loggers",#records) + end + + return records, keys + +end diff --git a/tex/context/base/util-sql-sessions.lua b/tex/context/base/util-sql-sessions.lua new file mode 100644 index 000000000..40556dd5e --- /dev/null +++ b/tex/context/base/util-sql-sessions.lua @@ -0,0 +1,349 @@ +if not modules then modules = { } end modules ['util-sql-sessions'] = { + version = 1.001, + comment = "companion to lmx-*", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code and currently part of the base installation simply +-- because it's easier to dirtribute this way. Eventually it will be documented +-- and the related scripts will show up as well. + +-- maybe store threshold in session (in seconds) + +local tonumber = tonumber +local format = string.format +local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime +local random = math.random + +-- In older frameworks we kept a session table in memory. This time we +-- follow a route where we store session data in a sql table. Each session +-- has a token (similar to what we do on q2p and pod services), a data +-- blob which is just a serialized lua table (we could consider a dump instead) +-- and two times: the creation and last accessed time. The first one is handy +-- for statistics and the second one for cleanup. Both are just numbers so that +-- we don't have to waste code on conversions. Anyhow, we provide variants so that +-- we can always choose what is best. + +local sql = utilities.sql +local sessions = { } +sql.sessions = sessions + +local trace_sql = false trackers.register("sql.sessions.trace", function(v) trace_sql = v end) +local report = logs.reporter("sql","sessions") + +sessions.newtoken = sql.tokens.new + +local function checkeddb(presets,datatable) + return sql.usedatabase(presets,datatable or presets.datatable or "sessions") +end + +sessions.usedb = checkeddb + +local template =[[ + CREATE TABLE IF NOT EXISTS %basename% ( + `token` varchar(50) NOT NULL, + `data` longtext NOT NULL, + `created` int(11) NOT NULL, + `accessed` int(11) NOT NULL, + UNIQUE KEY `token_unique_key` (`token`) + ) + DEFAULT CHARSET = utf8 ; +]] + +function sessions.createdb(presets,datatable) + + local db = checkeddb(presets,datatable) + + db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q created in %q",db.name,db.base) + + return db + +end + +local template =[[ + DROP TABLE IF EXISTS %basename% ; +]] + +function sessions.deletedb(presets,datatable) + + local db = checkeddb(presets,datatable) + + db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q removed in %q",db.name,db.base) + +end + +local template =[[ + INSERT INTO %basename% ( + `token`, + `created`, + `accessed`, + `data` + ) VALUES ( + '%token%', + %time%, + %time%, + '%[data]%' + ) ; +]] + +function sessions.create(db,data) + + local token = sessions.newtoken() + local time = ostime() + + db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + time = time, + data = db.serialize(data or { },"return") + }, + } + + if trace_sql then + report("created: %s at %s",token,osfulltime(time)) + end + + return { + token = token, + created = time, + accessed = time, + data = data, + } +end + +local template =[[ + UPDATE + %basename% + SET + `data` = '%[data]%', + `accessed` = %time% + WHERE + `token` = '%token%' ; +]] + +function sessions.save(db,session) + + local time = ostime() + local data = db.serialize(session.data or { },"return") + local token = session.token + + session.accessed = time + + db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + time = ostime(), + data = data, + }, + } + + if trace_sql then + report("saved: %s at %s",token,osfulltime(time)) + end + + return session +end + +local template = [[ + UPDATE + %basename% + SET + `accessed` = %time% + WHERE + `token` = '%token%' ; +]] + +function sessions.touch(db,token) + + db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + time = ostime(), + }, + } + +end + +local template = [[ + UPDATE + %basename% + SET + `accessed` = %time% + WHERE + `token` = '%token%' ; + SELECT + * + FROM + %basename% + WHERE + `token` = '%token%' ; +]] + +function sessions.restore(db,token) + + local records, keys = db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + time = ostime(), + }, + } + + local record = records and records[1] + + if record then + if trace_sql then + report("restored: %s",token) + end + record.data = db.deserialize(record.data or "") + return record, keys + elseif trace_sql then + report("unknown: %s",token) + end + +end + +local template =[[ + DELETE FROM + %basename% + WHERE + `token` = '%token%' ; +]] + +function sessions.remove(db,token) + + db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + }, + } + + if trace_sql then + report("removed: %s",token) + end + +end + +local template_collect_yes =[[ + SELECT + * + FROM + %basename% + ORDER BY + `created` ; +]] + +local template_collect_nop =[[ + SELECT + `accessed`, + `created`, + `accessed`, + `token` + FROM + %basename% + ORDER BY + `created` ; +]] + +function sessions.collect(db,nodata) + + local records, keys = db.execute { + template = nodata and template_collect_nop or template_collect_yes, + variables = { + basename = db.basename, + }, + } + + if not nodata then + db.unpackdata(records) + end + + if trace_sql then + report("collected: %s sessions",#records) + end + + return records, keys + +end + +local template_cleanup_yes =[[ + SELECT + * + FROM + %basename% + WHERE + `accessed` < %time% + ORDER BY + `created` ; + DELETE FROM + %basename% + WHERE + `accessed` < %time% ; +]] + +local template_cleanup_nop =[[ + SELECT + `accessed`, + `created`, + `accessed`, + `token` + FROM + %basename% + WHERE + `accessed` < %time% + ORDER BY + `created` ; + DELETE FROM + %basename% + WHERE + `accessed` < %time% ; +]] + +function sessions.cleanupdb(db,delta,nodata) + + local time = ostime() + + local records, keys = db.execute { + template = nodata and template_cleanup_nop or template_cleanup_yes, + variables = { + basename = db.basename, + time = time - delta + }, + } + + if not nodata then + db.unpackdata(records) + end + + if trace_sql then + report("cleaned: %s seconds before %s",delta,osfulltime(time)) + end + + return records, keys + +end diff --git a/tex/context/base/util-sql-tickets.lua b/tex/context/base/util-sql-tickets.lua new file mode 100644 index 000000000..1dfe1e376 --- /dev/null +++ b/tex/context/base/util-sql-tickets.lua @@ -0,0 +1,698 @@ +if not modules then modules = { } end modules ['util-sql-tickets'] = { + version = 1.001, + comment = "companion to lmx-*", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code and currently part of the base installation simply +-- because it's easier to dirtribute this way. Eventually it will be documented +-- and the related scripts will show up as well. + +local tonumber = tonumber +local format = string.format +local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime +local random = math.random +local concat = table.concat + +local sql = utilities.sql +local tickets = { } +sql.tickets = tickets + +local trace_sql = false trackers.register("sql.tickets.trace", function(v) trace_sql = v end) +local report = logs.reporter("sql","tickets") + +local serialize = sql.serialize +local deserialize = sql.deserialize +local execute = sql.execute + +tickets.newtoken = sql.tokens.new + +local statustags = { [0] = -- beware index can be string or number, maybe status should be a string in the database + "unknown", + "pending", + "busy", + "finished", + "error", + "deleted", +} + +local status = table.swapped(statustags) + +tickets.status = status +tickets.statustags = statustags + +local function checkeddb(presets,datatable) + return sql.usedatabase(presets,datatable or presets.datatable or "tickets") +end + +tickets.usedb = checkeddb + +local template =[[ + CREATE TABLE IF NOT EXISTS %basename% ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `token` varchar(50) NOT NULL, + `subtoken` INT(11) NOT NULL, + `created` int(11) NOT NULL, + `accessed` int(11) NOT NULL, + `category` int(11) NOT NULL, + `status` int(11) NOT NULL, + `usertoken` varchar(50) NOT NULL, + `data` longtext NOT NULL, + `comment` longtext NOT NULL, + + PRIMARY KEY (`id`), + UNIQUE INDEX `id_unique_index` (`id` ASC), + KEY `token_unique_key` (`token`) + ) + DEFAULT CHARSET = utf8 ; +]] + +function tickets.createdb(presets,datatable) + + local db = checkeddb(presets,datatable) + + local data, keys = db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q created in %q",db.name,db.base) + + return db + +end + +local template =[[ + DROP TABLE IF EXISTS %basename% ; +]] + +function tickets.deletedb(presets,datatable) + + local db = checkeddb(presets,datatable) + + local data, keys = db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q removed in %q",db.name,db.base) + +end + +local template =[[ + LOCK TABLES + %basename% + WRITE ; + INSERT INTO %basename% ( + `token`, + `subtoken`, + `created`, + `accessed`, + `status`, + `category`, + `usertoken`, + `data`, + `comment` + ) VALUES ( + '%token%', + %subtoken%, + %time%, + %time%, + %status%, + %category%, + '%usertoken%', + '%[data]%', + '%[comment]%' + ) ; + SELECT + LAST_INSERT_ID() AS `id` ; + UNLOCK TABLES ; +]] + +function tickets.create(db,ticket) + + local token = ticket.token or tickets.newtoken() + local time = ostime() + local status = ticket.status or 0 + local category = ticket.category or 0 + local subtoken = ticket.subtoken or 0 + local usertoken = ticket.usertoken or "" + local comment = ticket.comment or "" + + local result, message = db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + subtoken = subtoken, + time = time, + status = status, + category = category, + usertoken = usertoken, + data = db.serialize(ticket.data or { },"return"), + comment = comment, + }, + } + + if trace_sql then + report("created: %s at %s",token,osfulltime(time)) + end + + local id = result and result.id + + if id then + + return { + id = id, + token = token, + subtoken = subtoken, + created = time, + accessed = time, + status = status, + category = category, + usertoken = usertoken, + data = data, + comment = comment, + } + + end +end + +local template =[[ + LOCK TABLES + %basename% + WRITE ; + UPDATE %basename% SET + `data` = '%[data]%', + `status` = %status%, + `accessed` = %time% + WHERE + `id` = %id% ; + UNLOCK TABLES ; +]] + +function tickets.save(db,ticket) + + local time = ostime() + local data = db.serialize(ticket.data or { },"return") + local status = ticket.status or 0 + local id = ticket.id + + if not status then + status = 0 + ticket.status = 0 + end + + ticket.accessed = time + + db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + time = ostime(), + status = status, + data = data, + }, + } + + if trace_sql then + report("saved: id %s, time %s",id,osfulltime(time)) + end + + return ticket +end + +local template =[[ + UPDATE + %basename% + SET + `accessed` = %time% + WHERE + `token` = '%token%' ; + + SELECT + * + FROM + %basename% + WHERE + `id` = %id% ; +]] + +function tickets.restore(db,id) + + local record, keys = db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + time = ostime(), + }, + } + + local record = record and record[1] + + if record then + if trace_sql then + report("restored: id %s",id) + end + record.data = db.deserialize(record.data or "") + return record + elseif trace_sql then + report("unknown: id %s",id) + end + +end + +local template =[[ + DELETE FROM + %basename% + WHERE + `id` = %id% ; +]] + +function tickets.remove(db,id) + + db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + }, + } + + if trace_sql then + report("removed: id %s",id) + end + +end + +local template_yes =[[ + SELECT + * + FROM + %basename% + ORDER BY + `created` ; +]] + +local template_nop =[[ + SELECT + `created`, + `usertoken`, + `accessed`, + `status` + FROM + %basename% + ORDER BY + `created` ; +]] + +function tickets.collect(db,nodata) + + local records, keys = db.execute { + template = nodata and template_nop or template_yes, + variables = { + basename = db.basename, + token = token, + }, + } + + if not nodata then + db.unpackdata(records) + end + + if trace_sql then + report("collected: %s tickets",#records) + end + + return records, keys + +end + +local template =[[ + DELETE FROM + %basename% + WHERE + `accessed` < %time% OR `status` = 5 ; +]] + +local template_cleanup_yes =[[ + SELECT + * + FROM + %basename% + WHERE + `accessed` < %time% + ORDER BY + `created` ; + DELETE FROM + %basename% + WHERE + `accessed` < %time% OR `status` = 5 ; +]] + +local template_cleanup_nop =[[ + SELECT + `accessed`, + `created`, + `accessed`, + `token` + `usertoken` + FROM + %basename% + WHERE + `accessed` < %time% + ORDER BY + `created` ; + DELETE FROM + %basename% + WHERE + `accessed` < %time% OR `status` = 5 ; +]] + +function tickets.cleanupdb(db,delta,nodata) -- maybe delta in db + + local time = delta and (ostime() - delta) or 0 + + local records, keys = db.execute { + template = nodata and template_cleanup_nop or template_cleanup_yes, + variables = { + basename = db.basename, + time = time, + }, + } + + if not nodata then + db.unpackdata(records) + end + + if trace_sql then + report("cleaned: %s seconds before %s",delta,osfulltime(time)) + end + + return records, keys + +end + +-- status related functions + +local template =[[ + SELECT + `status` + FROM + %basename% + WHERE + `token` = '%token%' ; +]] + +function tickets.getstatus(db,token) + + local record, keys = db.execute { + template = template, + variables = { + basename = db.basename, + token = token, + }, + } + + local record = record and record[1] + + return record and record.status or 0 + +end + +local template =[[ + SELECT + `status` + FROM + %basename% + WHERE + `status` = 5 OR `accessed` < %time% ; +]] + +function tickets.getobsolete(db,delta) + + local time = delta and (ostime() - delta) or 0 + + local records = db.execute { + template = template, + variables = { + basename = db.basename, + time = time, + }, + } + + db.unpackdata(records) + + return records + +end + +local template =[[ + SELECT + `id` + FROM + %basename% + WHERE + `status` = %status% + LIMIT + 1 ; +]] + +function tickets.hasstatus(db,status) + + local record = db.execute { + template = template, + variables = { + basename = db.basename, + status = status or 0, + }, + } + + return record and #record > 0 or false + +end + +local template =[[ + UPDATE + %basename% + SET + `status` = %status%, + `accessed` = %time% + WHERE + `id` = %id% ; +]] + +function tickets.setstatus(db,id,status) + + local record, keys = db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + time = ostime(), + status = status or 0, + }, + } + +end + +local template =[[ + DELETE FROM + %basename% + WHERE + `status` IN (%status%) ; +]] + +function tickets.prunedb(db,status) + + if type(status) == "table" then + status = concat(status,",") + end + + local data, keys = db.execute { + template = template, + variables = { + basename = db.basename, + status = status or 0, + }, + } + + if trace_sql then + report("pruned: status %s removed",status) + end + +end + +local template_a = [[ + LOCK TABLES + %basename% + WRITE ; + SET + @first_token = "?" ; + SELECT + `token` + INTO + @first_token + FROM + %basename% + WHERE + `status` = %status% + ORDER BY + `id` + LIMIT 1 ; + UPDATE + %basename% + SET + `status` = %newstatus%, + `accessed` = %time% + WHERE + `token` = @first_token ; + SELECT + * + FROM + %basename% + WHERE + `token` = @first_token + ORDER BY + `id` ; + UNLOCK TABLES ; +]] + +local template_b = [[ + SET + @first_token = "?" ; + SELECT + `token` + INTO + @first_token + FROM + %basename% + WHERE + `status` = %status% + ORDER BY + `id` + LIMIT 1 ; + SELECT + * + FROM + %basename% + WHERE + `token` = @first_token + ORDER BY + `id` ; +]] + +function tickets.getfirstwithstatus(db,status,newstatus) + + local records + + if type(newstatus) == "number" then + + records = db.execute { + template = template_a, + variables = { + basename = db.basename, + status = status or 0, + newstatus = newstatus, + time = ostime(), + }, + } + + + else + + records = db.execute { + template = template_b, + variables = { + basename = db.basename, + status = status or 0, + }, + } + + end + + if type(records) == "table" and #records > 0 then + + for i=1,#records do + local record = records[i] + record.data = db.deserialize(record.data or "") + record.status = newstatus + end + + return records + + end +end + +local template =[[ + SELECT + * + FROM + %basename% + WHERE + `usertoken` = '%usertoken%' AND `status` != 5 + ORDER BY + `created` ; +]] + +function tickets.getusertickets(db,usertoken) + + -- todo: update accessed + -- todo: get less fields + -- maybe only data for status changed (hard to check) + + local records, keys = db.execute { + template = template, + variables = { + basename = db.basename, + usertoken = usertoken, + }, + } + + db.unpackdata(records) + + return records + +end + +local template =[[ + LOCK TABLES + %basename% + WRITE ; + UPDATE %basename% SET + `status` = 5 + WHERE + `usertoken` = '%usertoken%' ; + UNLOCK TABLES ; +]] + +function tickets.removeusertickets(db,usertoken) + + db.execute { + template = template, + variables = { + basename = db.basename, + usertoken = usertoken, + }, + } + + if trace_sql then + report("removed: usertoken %s",usertoken) + end + +end + +-- -- left-overs -- + +-- LOCK TABLES `m4alltickets` WRITE ; +-- CREATE TEMPORARY TABLE ticketset SELECT * FROM m4alltickets WHERE token = @first_token ; +-- DROP TABLE ticketset ; +-- UNLOCK TABLES ; diff --git a/tex/context/base/util-sql-users.lua b/tex/context/base/util-sql-users.lua new file mode 100644 index 000000000..8147f532d --- /dev/null +++ b/tex/context/base/util-sql-users.lua @@ -0,0 +1,391 @@ +if not modules then modules = { } end modules ['util-sql-users'] = { + version = 1.001, + comment = "companion to lmx-*", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code and currently part of the base installation simply +-- because it's easier to dirtribute this way. Eventually it will be documented +-- and the related scripts will show up as well. + +local sql = require("util-sql") +local md5 = require("md5") + +local format, upper, find, gsub, escapedpattern = string.format, string.upper, string.find, string.gsub, string.escapedpattern +local sumhexa = md5.sumhexa +local booleanstring = string.booleanstring + +local users = { } +sql.users = users + +local trace_sql = false trackers.register("sql.users.trace", function(v) trace_sql = v end) +local report = logs.reporter("sql","users") + +local function encryptpassword(str) + if not str or str == "" then + return "" + elseif find(str,"^MD5:") then + return str + else + return upper(format("MD5:%s",sumhexa(str))) + end +end + +local function cleanuppassword(str) + return (gsub(str,"^MD5:","")) +end + +local function samepasswords(one,two) + if not one or not two then + return false + end + if not find(one,"^MD5:") then + one = encryptpassword(one) + end + if not find(two,"^MD5:") then + two = encryptpassword(two) + end + return one == two +end + +local function validaddress(address,addresses) + if address and addresses and address ~= "" and addresses ~= "" then + if find(address,"^" .. escapedpattern(addresses,true)) then -- simple escapes + return true, "valid remote address" + end + return false, "invalid remote address" + else + return true, "no remote address check" + end +end + + +users.encryptpassword = encryptpassword +users.cleanuppassword = cleanuppassword +users.samepasswords = samepasswords +users.validaddress = validaddress + +-- print(users.encryptpassword("test")) -- MD5:098F6BCD4621D373CADE4E832627B4F6 + +local function checkeddb(presets,datatable) + return sql.usedatabase(presets,datatable or presets.datatable or "users") +end + +users.usedb = checkeddb + +local groupnames = { } +local groupnumbers = { } + +local function registergroup(name) + local n = #groupnames + 1 + groupnames [n] = name + groupnames [tostring(n)] = name + groupnames [name] = name + groupnumbers[n] = n + groupnumbers[tostring(n)] = n + groupnumbers[name] = n + return n +end + +registergroup("superuser") +registergroup("administrator") +registergroup("user") +registergroup("guest") + +users.groupnames = groupnames +users.groupnumbers = groupnumbers + +-- password 'test': +-- +-- INSERT insert into users (`name`,`password`,`group`,`enabled`) values ('...','MD5:098F6BCD4621D373CADE4E832627B4F6',1,1) ; + +local template =[[ + CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(80) NOT NULL, + `password` varchar(50) DEFAULT NULL, + `group` int(11) NOT NULL, + `enabled` int(11) DEFAULT '1', + `email` varchar(80) DEFAULT NULL, + `address` varchar(256) DEFAULT NULL, + `data` longtext, + PRIMARY KEY (`id`), + UNIQUE KEY `name_unique` (`name`) + ) DEFAULT CHARSET = utf8 ; +]] + +local converter, fields = sql.makeconverter { + { name = "id", type = "number" }, + { name = "name", type = "string" }, + { name = "password", type = "string" }, + { name = "group", type = groupnames }, + { name = "enabled", type = "boolean" }, + { name = "email", type = "string" }, + { name = "address", type = "string" }, + { name = "data", type = "deserialize" }, +} + +function users.createdb(presets,datatable) + + local db = checkeddb(presets,datatable) + + db.execute { + template = template, + variables = { + basename = db.basename, + }, + } + + report("datatable %q created in %q",db.name,db.base) + + return db + +end + +local template =[[ + SELECT + %fields% + FROM + %basename% + WHERE + `name` = '%name%' + AND + `password` = '%password%' + ; +]] + +local template =[[ + SELECT + %fields% + FROM + %basename% + WHERE + `name` = '%name%' + ; +]] + +function users.valid(db,username,password,address) + + local data = db.execute { + template = template, + converter = converter, + variables = { + basename = db.basename, + fields = fields, + name = username, + }, + } + + local data = data and data[1] + + if not data then + return false, "unknown user" + elseif not data.enabled then + return false, "disabled user" + elseif data.password ~= encryptpassword(password) then + return false, "wrong password" + elseif not validaddress(address,data.address) then + return false, "invalid address" + else + data.password = nil + return data, "okay" + end + +end + +local template =[[ + INSERT INTO %basename% ( + `name`, + `password`, + `group`, + `enabled`, + `email`, + `address`, + `data` + ) VALUES ( + '%name%', + '%password%', + '%group%', + '%enabled%', + '%email%', + '%address%', + '%[data]%' + ) ; +]] + +function users.add(db,specification) + + local name = specification.username or specification.name + + if not name or name == "" then + return + end + + local data = specification.data + + db.execute { + template = template, + variables = { + basename = db.basename, + name = name, + password = encryptpassword(specification.password or ""), + group = groupnumbers[specification.group] or groupnumbers.guest, + enabled = booleanstring(specification.enabled) and "1" or "0", + email = specification.email, + address = specification.address, + data = type(data) == "table" and db.serialize(data,"return") or "", + }, + } + +end + +local template =[[ + SELECT + %fields% + FROM + %basename% + WHERE + `name` = '%name%' ; +]] + +function users.getbyname(db,name) + + local data = db.execute { + template = template, + converter = converter, + variables = { + basename = db.basename, + fields = fields, + name = name, + }, + } + + return data and data[1] or nil + +end + +local template =[[ + SELECT + %fields% + FROM + %basename% + WHERE + `id` = '%id%' ; +]] + +local function getbyid(db,id) + + local data = db.execute { + template = template, + converter = converter, + variables = { + basename = db.basename, + fields = fields, + id = id, + }, + } + + return data and data[1] or nil + +end + +users.getbyid = getbyid + +local template =[[ + UPDATE + %basename% + SET + `password` = '%password%', + `group` = '%group%', + `enabled` = '%enabled%', + `email` = '%email%', + `address` = '%address%', + `data` = '%[data]%' + WHERE + `id` = '%id%' + ; +]] + +function users.save(db,id,specification) + + if not tonumber(id) then + return + end + + local user = getbyid(db,id) + + if user.id ~= id then + return + end + + local password = specification.password == nil and user.password or specification.password + local group = specification.group == nil and user.group or specification.group + local enabled = specification.enabled == nil and user.enabled or specification.enabled + local email = specification.email == nil and user.email or specification.email + local address = specification.address == nil and user.address or specification.address + local data = specification.data == nil and user.data or specification.data + +-- table.print(data) + + db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + password = encryptpassword(password), + group = groupnumbers[group], + enabled = booleanstring(enabled) and "1" or "0", + email = email, + address = address, + data = type(data) == "table" and db.serialize(data,"return") or "", + }, + } + + return getbyid(db,id) + +end + +local template =[[ + DELETE FROM + %basename% + WHERE + `id` = '%id%' ; +]] + +function users.remove(db,id) + + db.execute { + template = template, + variables = { + basename = db.basename, + id = id, + }, + } + +end + +local template =[[ + SELECT + %fields% + FROM + %basename% + ORDER BY + `name` ; +]] + +function users.collect(db) -- maybe also an id/name only variant + + local records, keys = db.execute { + template = template, + converter = converter, + variables = { + basename = db.basename, + fields = fields, + }, + } + + return records, keys + +end diff --git a/tex/context/base/util-sql.lua b/tex/context/base/util-sql.lua new file mode 100644 index 000000000..70c7d4be6 --- /dev/null +++ b/tex/context/base/util-sql.lua @@ -0,0 +1,425 @@ +if not modules then modules = { } end modules ['util-sql'] = { + version = 1.001, + comment = "companion to m-sql.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Of course we could use a library but we don't want another depedency and there is +-- a bit of flux in these libraries. Also, we want the data back in a way that we +-- like. +-- +-- This is the first of set of sql related modules that are providing functionality +-- for a web based framework that we use for typesetting (related) services. We're +-- talking of session management, job ticket processing, storage, (xml) file processing +-- and dealing with data from databases (often ambitiously called database publishing). +-- +-- There is no generic solution for such services, but from our perspective, as we use +-- context in a regular tds tree (the standard distribution) it makes sense to put shared +-- code in the context distribution. That way we don't need to reinvent wheels every time. + +-- We use the template mechanism from util-tpl which inturn is just using the dos cq +-- windows convention of %whatever% variables that I've used for ages. + +-- util-sql-imp-client.lua +-- util-sql-imp-library.lua +-- util-sql-imp-swiglib.lua +-- util-sql-imp-lmxsql.lua + +-- local sql = require("util-sql") +-- +-- local converter = sql.makeconverter { +-- { name = "id", type = "number" }, +-- { name = "data",type = "string" }, +-- } +-- +-- local execute = sql.methods.swiglib.execute +-- -- local execute = sql.methods.library.execute +-- -- local execute = sql.methods.client.execute +-- -- local execute = sql.methods.lmxsql.execute +-- +-- result = execute { +-- presets = { +-- host = "localhost", +-- username = "root", +-- password = "test", +-- database = "test", +-- id = "test", -- forces persistent session +-- }, +-- template = "select * from `test` where `id` > %criterium% ;", +-- variables = { +-- criterium = 2, +-- }, +-- converter = converter +-- } +-- +-- inspect(result) + +local format, match = string.format, string.match +local random = math.random +local rawset, setmetatable, getmetatable, loadstring, type = rawset, setmetatable, getmetatable, loadstring, type +local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match +local concat = table.concat + +local osuuid = os.uuid +local osclock = os.clock or os.time +local ostime = os.time + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) +local report_state = logs.reporter("sql") + +-- trace_sql = true +-- trace_queries = true + +utilities.sql = utilities.sql or { } +local sql = utilities.sql + +local replacetemplate = utilities.templates.replace +local loadtemplate = utilities.templates.load + +local methods = { } +sql.methods = methods + +local helpers = { } +sql.helpers = helpers + +local serialize = table.fastserialize +local deserialize = table.deserialize + +sql.serialize = serialize +sql.deserialize = deserialize + +helpers.serialize = serialize -- bonus +helpers.deserialize = deserialize -- bonus + +local defaults = { __index = + { + resultfile = "result.dat", + templatefile = "template.sql", + queryfile = "query.sql", + variables = { }, + username = "default", + password = "default", + host = "localhost", + port = 3306, + database = "default", + }, +} + +table.setmetatableindex(sql.methods,function(t,k) + require("util-sql-imp-"..k) + return rawget(t,k) +end) + +-- converters + +local converters = { } +sql.converters = converters + +local function makeconverter(entries,celltemplate,wraptemplate) + local shortcuts = { } + local assignments = { } + local function cell(i) + return format(celltemplate,i,i) + end + for i=1,#entries do + local entry = entries[i] + local nam = entry.name + local typ = entry.type + if typ == "boolean" then + assignments[i] = format("[%q] = booleanstring(%s),",nam,cell(i)) + elseif typ == "number" then + assignments[i] = format("[%q] = tonumber(%s),",nam,cell(i)) + elseif type(typ) == "function" then + local c = #converters + 1 + converters[c] = typ + shortcuts[#shortcuts+1] = format("local fun_%s = converters[%s]",c,c) + assignments[i] = format("[%q] = fun_%s(%s),",nam,c,cell(i)) + elseif type(typ) == "table" then + local c = #converters + 1 + converters[c] = typ + shortcuts[#shortcuts+1] = format("local tab_%s = converters[%s]",c,c) + assignments[i] = format("[%q] = tab_%s[%s],",nam,#converters,cell(i)) + elseif typ == "deserialize" then + assignments[i] = format("[%q] = deserialize(%s),",nam,cell(i)) + else + assignments[i] = format("[%q] = %s,",nam,cell(i)) + end + end + local code = format(wraptemplate,concat(shortcuts,"\n"),concat(assignments,"\n ")) + local func = loadstring(code) + return func and func() +end + +function sql.makeconverter(entries) + local fields = { } + for i=1,#entries do + fields[i] = format("`%s`",entries[i].name) + end + fields = concat(fields, ", ") + local converter = { + fields = fields + } + table.setmetatableindex(converter, function(t,k) + local sqlmethod = methods[k] + local v = makeconverter(entries,sqlmethod.celltemplate,sqlmethod.wraptemplate) + t[k] = v + return v + end) + return converter, fields +end + +-- helper for libraries: + +local function validspecification(specification) + local presets = specification.presets + if type(presets) == "string" then + presets = dofile(presets) + end + if type(presets) == "table" then + setmetatable(presets,defaults) + setmetatable(specification,{ __index = presets }) + else + setmetatable(specification,defaults) + end + return true +end + +helpers.validspecification = validspecification + +local whitespace = patterns.whitespace^0 +local eol = patterns.eol +local separator = P(";") +local escaped = patterns.escaped +local dquote = patterns.dquote +local squote = patterns.squote +local dsquote = squote * squote +---- quoted = patterns.quoted +local quoted = dquote * (escaped + (1-dquote))^0 * dquote + + squote * (escaped + dsquote + (1-squote))^0 * squote +local comment = P("--") * (1-eol) / "" +local query = whitespace + * Cs((quoted + comment + 1 - separator)^1 * Cc(";")) + * whitespace +local splitter = Ct(query * (separator * query)^0) + +helpers.querysplitter = splitter + +-- I will add a bit more checking. + +local function validspecification(specification) + local presets = specification.presets + if type(presets) == "string" then + presets = dofile(presets) + end + if type(presets) == "table" then + local m = getmetatable(presets) + if m then + setmetatable(m,defaults) + else + setmetatable(presets,defaults) + end + setmetatable(specification,{ __index = presets }) + else + setmetatable(specification,defaults) + end + local templatefile = specification.templatefile or "query" + local queryfile = specification.queryfile or presets.queryfile or file.nameonly(templatefile) .. "-temp.sql" + local resultfile = specification.resultfile or presets.resultfile or file.nameonly(templatefile) .. "-temp.dat" + specification.queryfile = queryfile + specification.resultfile = resultfile + if trace_sql then + report_state("template file: %q",templatefile or "<none>") + report_state("query file: %q",queryfile) + report_state("result file: %q",resultfile) + end + return true +end + +local function preparetemplate(specification) + local template = specification.template + if template then + local query = replacetemplate(template,specification.variables,'sql') + if not query then + report_state("error in template: %s",template) + elseif trace_queries then + report_state("query from template: %s",query) + end + return query + end + local templatefile = specification.templatefile + if templatefile then + local query = loadtemplate(templatefile,specification.variables,'sql') + if not query then + report_state("error in template file %q",templatefile) + elseif trace_queries then + report_state("query from template file %q: %s",templatefile,query) + end + return query + end + report_state("no query template or templatefile") +end + +helpers.preparetemplate = preparetemplate + +-- -- -- we delay setting this -- -- -- + +local currentmethod + +local function firstexecute(...) + local execute = methods[currentmethod].execute + sql.execute = execute + return execute(...) +end + +function sql.setmethod(method) + currentmethod = method + sql.execute = firstexecute +end + +sql.setmethod("client") + +-- helper: + +function sql.usedatabase(presets,datatable) + local name = datatable or presets.datatable + if name then + local method = presets.method and sql.methods[presets.method] or sql.methods.client + local base = presets.database or "test" + local basename = format("`%s`.`%s`",base,name) + local execute = nil + local m_execute = method.execute + if method.usesfiles then + local queryfile = presets.queryfile or format("%s-temp.sql",name) + local resultfile = presets.resultfile or format("%s-temp.dat",name) + execute = function(specification) -- variables template + if not specification.presets then specification.presets = presets end + if not specification.queryfile then specification.queryfile = queryfile end + if not specification.resultfile then specification.resultfile = queryfile end + return m_execute(specification) + end + else + execute = function(specification) -- variables template + if not specification.presets then specification.presets = presets end + return m_execute(specification) + end + end + local function unpackdata(records,name) + if records then + name = name or "data" + for i=1,#records do + local record = records[i] + local data = record[name] + if data then + record[name] = deserialize(data) + end + end + end + end + return { + presets = preset, + base = base, + name = name, + basename = basename, + execute = execute, + serialize = serialize, + deserialize = deserialize, + unpackdata = unpackdata, + } + end +end + + +-- local data = utilities.sql.prepare { +-- templatefile = "test.sql", +-- variables = { }, +-- host = "...", +-- username = "...", +-- password = "...", +-- database = "...", +-- } + +-- local presets = { +-- host = "...", +-- username = "...", +-- password = "...", +-- database = "...", +-- } +-- +-- local data = utilities.sql.prepare { +-- templatefile = "test.sql", +-- variables = { }, +-- presets = presets, +-- } + +-- local data = utilities.sql.prepare { +-- templatefile = "test.sql", +-- variables = { }, +-- presets = dofile(...), +-- } + +-- local data = utilities.sql.prepare { +-- templatefile = "test.sql", +-- variables = { }, +-- presets = "...", +-- } + +-- for i=1,10 do +-- local dummy = uuid() -- else same every time, don't ask +-- end + +sql.tokens = { + length = 42, -- but in practice we will reserve some 50 characters + new = function() + return format("%s-%x06",osuuid(),random(0xFFFFF)) -- 36 + 1 + 6 = 42 + end, +} + +-- -- -- + +-- local func, code = sql.makeconverter { +-- { name = "a", type = "number" }, +-- { name = "b", type = "string" }, +-- { name = "c", type = "boolean" }, +-- { name = "d", type = { x = "1" } }, +-- { name = "e", type = os.fulltime }, +-- } +-- +-- print(code) + +-- -- -- + +if tex and tex.systemmodes then + + local droptable = table.drop + local threshold = 16 * 1024 -- use slower but less memory hungry variant + + function sql.prepare(specification,tag) + -- could go into tuc if needed + -- todo: serialize per column + local filename = format("%s-sql-result-%s.tuc",tex.jobname,tag or "last") + if tex.systemmodes["first"] then + local data, keys = sql.execute(specification) + if not data then + data = { } + end + if not keys then + keys = { } + end + io.savedata(filename,droptable({ data = data, keys = keys },#keys*#data>threshold)) + return data, keys + else + local result = table.load(filename) + return result.data, result.keys + end + end + +else + + sql.prepare = sql.execute + +end + +return sql diff --git a/tex/context/base/util-sta.lua b/tex/context/base/util-sta.lua new file mode 100644 index 000000000..f94c1acdf --- /dev/null +++ b/tex/context/base/util-sta.lua @@ -0,0 +1,342 @@ +if not modules then modules = { } end modules ['util-sta'] = { + version = 1.001, + comment = "companion to util-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat +local format = string.format + +local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end) + +local stacker = stacker or { } + +utilities.stacker = stacker + +local function start(s,t,first,last) + if s.mode == "switch" then + local n = tostring(t[last]) + if trace_stacker then + s.report("start: %s",n) + end + return n + else + local r = { } + for i=first,last do + r[#r+1] = tostring(t[i]) + end + local n = concat(r," ") + if trace_stacker then + s.report("start: %s",n) + end + return n + end +end + +local function stop(s,t,first,last) + if s.mode == "switch" then + local n = tostring(false) + if trace_stacker then + s.report("stop: %s",n) + end + return n + else + local r = { } + for i=last,first,-1 do + r[#r+1] = tostring(false) + end + local n = concat(r," ") + if trace_stacker then + s.report("stop: %s",n) + end + return n + end +end + +local function change(s,t1,first1,last1,t2,first2,last2) + if s.mode == "switch" then + local n = tostring(t2[last2]) + if trace_stacker then + s.report("change: %s",n) + end + return n + else + local r = { } + for i=last1,first1,-1 do + r[#r+1] = tostring(false) + end + local n = concat(r," ") + for i=first2,last2 do + r[#r+1] = tostring(t2[i]) + end + if trace_stacker then + s.report("change: %s",n) + end + return n + end +end + +function stacker.new(name) + + local s + + local stack = { } + local list = { } + local ids = { } + local hash = { } + + local hashing = true + + local function push(...) + local t = { ... } + for i=1,#t do + insert(stack,t[i]) + end + if hashing then + local c = concat(stack,"|") + local n = hash[c] + if not n then + n = #list+1 + hash[c] = n + list[n] = fastcopy(stack) + end + insert(ids,n) + return n + else + local n = #list+1 + list[n] = fastcopy(stack) + insert(ids,n) + return n + end + end + + local function pop() + remove(stack) + remove(ids) + return ids[#ids] or s.unset or -1 + end + + local function clean() + if #stack == 0 then + if trace_stacker then + s.report("%s list entries, %s stack entries",#list,#stack) + end + end + end + + local tops = { } + local top, switch + + local function resolve_begin(mode) + if mode then + switch = mode == "switch" + else + switch = s.mode == "switch" + end + top = { switch = switch } + insert(tops,top) + end + + local function resolve_step(ti) -- keep track of changes outside function ! + -- todo: optimize for n=1 etc + local result = nil + local noftop = #top + if ti > 0 then + local current = list[ti] + if current then + local noflist = #current + local nofsame = 0 + if noflist > noftop then + for i=1,noflist do + if current[i] == top[i] then + nofsame = i + else + break + end + end + else + for i=1,noflist do + if current[i] == top[i] then + nofsame = i + else + break + end + end + end + local plus = nofsame + 1 + if plus <= noftop then + if plus <= noflist then + if switch then + result = s.change(s,top,plus,noftop,current,nofsame,noflist) + else + result = s.change(s,top,plus,noftop,current,plus,noflist) + end + else + if switch then + result = s.change(s,top,plus,noftop,current,nofsame,noflist) + else + result = s.stop(s,top,plus,noftop) + end + end + elseif plus <= noflist then + if switch then + result = s.start(s,current,nofsame,noflist) + else + result = s.start(s,current,plus,noflist) + end + end + top = current + else + if 1 <= noftop then + result = s.stop(s,top,1,noftop) + end + top = { } + end + return result + else + if 1 <= noftop then + result = s.stop(s,top,1,noftop) + end + top = { } + return result + end + end + + local function resolve_end() + -- resolve_step(s.unset) + local noftop = #top + if noftop > 0 then + local result = s.stop(s,top,1,#top) + remove(tops) + top = tops[#tops] + switch = top and top.switch + return result + end + end + + local function resolve(t) + resolve_begin() + for i=1,#t do + resolve_step(t[i]) + end + resolve_end() + end + + local report = logs.reporter("stacker",name or nil) + + s = { + name = name or "unknown", + unset = -1, + report = report, + start = start, + stop = stop, + change = change, + push = push, + pop = pop, + clean = clean, + resolve = resolve, + resolve_begin = resolve_begin, + resolve_step = resolve_step, + resolve_end = resolve_end, + } + + return s -- we can overload functions + +end + +-- local s = utilities.stacker.new("demo") +-- +-- local unset = s.unset +-- local push = s.push +-- local pop = s.pop +-- +-- local t = { +-- unset, +-- unset, +-- push("a"), -- a +-- push("b","c"), -- a b c +-- pop(), -- a b +-- push("d"), -- a b d +-- pop(), -- a b +-- unset, +-- pop(), -- a +-- pop(), -- b +-- unset, +-- unset, +-- } +-- +-- s.resolve(t) + +-- demostacker = utilities.stacker.new("demos") +-- +-- local whatever = { +-- one = "1 0 0 RG 1 0 0 rg", +-- two = "1 1 0 RG 1 1 0 rg", +-- [false] = "0 G 0 g", +-- } +-- +-- local concat = table.concat +-- +-- local pdfliteral = nodes.pool.pdfliteral +-- +-- function demostacker.start(s,t,first,last) +-- local n = whatever[t[last]] +-- -- s.report("start: %s",n) +-- return pdfliteral(n) +-- end +-- +-- function demostacker.stop(s,t,first,last) +-- local n = whatever[false] +-- -- s.report("stop: %s",n) +-- return pdfliteral(n) +-- end +-- +-- function demostacker.change(s,t1,first1,last1,t2,first2,last2) +-- local n = whatever[t2[last2]] +-- -- s.report("change: %s",n) +-- return pdfliteral(n) +-- end +-- +-- demostacker.mode = "switch" +-- +-- local whatever = { +-- one = "/OC /test1 BDC", +-- two = "/OC /test2 BDC", +-- [false] = "EMC", +-- } +-- +-- demostacker = utilities.stacker.new("demos") +-- +-- function demostacker.start(s,t,first,last) +-- local r = { } +-- for i=first,last do +-- r[#r+1] = whatever[t[i]] +-- end +-- -- s.report("start: %s",concat(r," ")) +-- return pdfliteral(concat(r," ")) +-- end +-- +-- function demostacker.stop(s,t,first,last) +-- local r = { } +-- for i=last,first,-1 do +-- r[#r+1] = whatever[false] +-- end +-- -- s.report("stop: %s",concat(r," ")) +-- return pdfliteral(concat(r," ")) +-- end +-- +-- function demostacker.change(s,t1,first1,last1,t2,first2,last2) +-- local r = { } +-- for i=last1,first1,-1 do +-- r[#r+1] = whatever[false] +-- end +-- for i=first2,last2 do +-- r[#r+1] = whatever[t2[i]] +-- end +-- -- s.report("change: %s",concat(r," ")) +-- return pdfliteral(concat(r," ")) +-- end +-- +-- demostacker.mode = "stack" diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua index 75cf443fb..377dd163f 100644 --- a/tex/context/base/util-str.lua +++ b/tex/context/base/util-str.lua @@ -62,11 +62,8 @@ function strings.newrepeater(str,offset) return t end ---~ local dashes = strings.newrepeater("--",-1) - ---~ print(dashes[2]) ---~ print(dashes[3]) ---~ print(dashes[1]) +-- local dashes = strings.newrepeater("--",-1) +-- print(dashes[2],dashes[3],dashes[1]) local extra, tab, start = 0, 0, 4, 0 diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index 28a6b8cc5..7a2da298e 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -10,10 +10,11 @@ utilities = utilities or {} utilities.tables = utilities.tables or { } local tables = utilities.tables -local format, gmatch, rep = string.format, string.gmatch, string.rep +local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub local concat, insert, remove = table.concat, table.insert, table.remove local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring -local type, next, rawset, tonumber = type, next, rawset, tonumber +local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring +local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs function tables.definetable(target) -- defines undefined tables local composed, t, n = nil, { }, 0 @@ -166,3 +167,118 @@ function tables.encapsulate(core,capsule,protect) } ) end end + +local function serialize(t,r,outer) -- no mixes + r[#r+1] = "{" + local n = #t + if n > 0 then + for i=1,n do + local v = t[i] + local tv = type(v) + if tv == "string" then + r[#r+1] = format("%q,",v) + elseif tv == "number" then + r[#r+1] = format("%s,",v) + elseif tv == "table" then + serialize(v,r) + elseif tv == "boolean" then + r[#r+1] = format("%s,",tostring(v)) + end + end + else + for k, v in next, t do + local tv = type(v) + if tv == "string" then + r[#r+1] = format("[%q]=%q,",k,v) + elseif tv == "number" then + r[#r+1] = format("[%q]=%s,",k,v) + elseif tv == "table" then + r[#r+1] = format("[%q]=",k) + serialize(v,r) + elseif tv == "boolean" then + r[#r+1] = format("[%q]=%s,",k,tostring(v)) + end + end + end + if outer then + r[#r+1] = "}" + else + r[#r+1] = "}," + end + return r +end + +function table.fastserialize(t,prefix) + return concat(serialize(t,{ prefix or "return" },true)) +end + +function table.deserialize(str) + if not str or str == "" then + return + end + local code = loadstring(str) + if not code then + return + end + code = code() + if not code then + return + end + return code +end + +-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } }) + +function table.load(filename) + if filename then + local t = io.loaddata(filename) + if t and t ~= "" then + t = loadstring(t) + if type(t) == "function" then + t = t() + if type(t) == "table" then + return t + end + end + end + end +end + +local function slowdrop(t) + local r = { } + local l = { } + for i=1,#t do + local ti = t[i] + local j = 0 + for k, v in next, ti do + j = j + 1 + l[j] = format("%s=%q",k,v) + end + r[i] = format(" {%s},\n",concat(l)) + end + return format("return {\n%s}",concat(r)) +end + +local function fastdrop(t) + local r = { "return {\n" } + for i=1,#t do + local ti = t[i] + r[#r+1] = " {" + for k, v in next, ti do + r[#r+1] = format("%s=%q",k,v) + end + r[#r+1] = "},\n" + end + r[#r+1] = "}" + return concat(r) +end + +function table.drop(t,slow) + if #t == 0 then + return "return { }" + elseif slow == true then + return slowdrop(t) -- less memory + else + return fastdrop(t) -- some 15% faster + end +end diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua new file mode 100644 index 000000000..4cde1863b --- /dev/null +++ b/tex/context/base/util-tpl.lua @@ -0,0 +1,117 @@ +if not modules then modules = { } end modules ['util-tpl'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code. Coming from dos and windows, I've always used %whatever% +-- as template variables so let's stick to it. After all, it's easy to parse and stands +-- out well. A double %% is turned into a regular %. + +utilities.templates = utilities.templates or { } +local templates = utilities.templates + +local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end) +local report_template = logs.reporter("template") + +local format = string.format +local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match + +-- todo: make installable template.new + +local replacer + +local function replacekey(k,t,recursive) + local v = t[k] + if not v then + if trace_template then + report_template("unknown key %q",k) + end + return "" + else + if trace_template then + report_template("setting key %q to value %q",k,v) + end + if recursive then + return lpegmatch(replacer,v,1,t) + else + return v + end + end +end + +local sqlescape = lpeg.replacer { + { "'", "''" }, + { "\\", "\\\\" }, + { "\r\n", "\\n" }, + { "\r", "\\n" }, + -- { "\t", "\\t" }, +} + +local escapers = { + lua = function(s) + return format("%q",s) + end, + sql = function(s) + return lpegmatch(sqlescape,s) + end, +} + +local function replacekeyunquoted(s,t,how,recurse) -- ".. \" " + local escaper = how and escapers[how] or escapers.lua + return escaper(replacekey(s,t,recurse)) +end + +local single = P("%") -- test %test% test : resolves test +local double = P("%%") -- test 10%% test : %% becomes % +local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s +local rquoted = P("]%") -- + +local escape = double / '%%' +local nosingle = single / '' +local nodouble = double / '' +local nolquoted = lquoted / '' +local norquoted = rquoted / '' + +local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle +local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted +local any = P(1) + + replacer = Cs((unquoted + escape + key + any)^0) + +local function replace(str,mapping,how,recurse) + if mapping then + return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str + else + return str + end +end + +-- print(replace("test '%[x]%' test",{ x = [[a 'x' a]] })) +-- print(replace("test '%[x]%' test",{ x = [[a 'x' a]] },'sql')) + +templates.replace = replace + +function templates.load(filename,mapping,how,recurse) + local data = io.loaddata(filename) or "" + if mapping and next(mapping) then + return replace(data,mapping,how,recurse) + else + return data + end +end + +function templates.resolve(t,mapping,how,recurse) + if not mapping then + mapping = t + end + for k, v in next, t do + t[k] = replace(v,mapping,how,recurse) + end + return t +end + +-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" })) +-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" })) diff --git a/tex/context/base/x-asciimath.mkiv b/tex/context/base/x-asciimath.mkiv index 23caf13aa..ea6d5c3fa 100644 --- a/tex/context/base/x-asciimath.mkiv +++ b/tex/context/base/x-asciimath.mkiv @@ -68,7 +68,7 @@ \protect -\doifnotmode{demo}{\endinput} +\continueifinputfile{x-asciimath.mkiv} \enabletrackers[modules.asciimath.mapping] diff --git a/tex/context/base/x-chemml.lua b/tex/context/base/x-chemml.lua index 387935c8b..64bbb3408 100644 --- a/tex/context/base/x-chemml.lua +++ b/tex/context/base/x-chemml.lua @@ -28,7 +28,7 @@ function chemml.do_graphic(id) for r, d, k in xml.elements(lxml.id(id),"cml:graphic") do t[#t+1] = xml.tostring(d[k].dt) end - concat(concat(t,",")) + context(concat(t,",")) end function chemml.no_graphic(id) diff --git a/tex/context/base/x-chemml.mkiv b/tex/context/base/x-chemml.mkiv index 34aba3011..99a371107 100644 --- a/tex/context/base/x-chemml.mkiv +++ b/tex/context/base/x-chemml.mkiv @@ -11,34 +11,34 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% This needs an update! + \writestatus{loading}{ConTeXt XML Macros / Chemistry} \registerctxluafile{x-chemml}{} \def\ctxmodulechemml#1{\directlua\zerocount{moduledata.chemml.#1}} -\usemodule[pictex,chemic] % someday we will do structural fomulas in mp - %D The following code assumes a load||flush approach to \XML. \unprotect \startxmlsetups xml:cml:process - \xmlstrip {\xmldocument} {cml:chem|cml:ichem|cml:dchem|cml:reaction|cml:molecule|cml:ion|cml:structure} + \xmlstrip {#1} {cml:chem|cml:ichem|cml:dchem|cml:reaction|cml:molecule|cml:ion|cml:structure} - \xmlgrab {\xmldocument} {cml:*} {*} - \xmlgrab {\xmldocument} {cml:gives|cml:equilibrium|cml:mesomeric} {cml:arrow} - \xmlgrab {\xmldocument} {cml:plus|cml:minus|cml:equal} {cml:operator} - \xmlgrab {\xmldocument} {cml:bond|cml:singlebond|cml:doublebound|cml:triplebond} {cml:bond} + \xmlgrab {#1} {cml:*} {cml:*} + \xmlgrab {#1} {cml:gives|cml:equilibrium|cml:mesomeric} {cml:arrow} + \xmlgrab {#1} {cml:plus|cml:minus|cml:equal} {cml:operator} + \xmlgrab {#1} {cml:bond|cml:singlebond|cml:doublebound|cml:triplebond} {cml:bond} - \xmlgrab {\xmldocument} {pi::chemml} {cml:pi} + \xmlgrab {#1} {pi::chemml} {cml:pi} \stopxmlsetups \xmlregistersetup{xml:cml:process} \xmlregisterns{cml}{chemml} -\unexpanded\def\setupCMLappearance[#1]{\dodoubleargument\getparameters[@@CML#1]} +\unexpanded\def\setupCMLappearance[#1]{\dodoubleargument\getparameters[@@CML#1]} % old stuff \setupCMLappearance [ion] [\c!alternative=\v!a] @@ -67,7 +67,7 @@ \xmlflush{#1} \stopxmlsetups -\def\doCMLtext#1#2#3% main top bot +\unexpanded\def\doCMLtext#1#2#3% main top bot {\setbox0\hbox{\doifsomething{#2}{\txx\setstrut\strut\ignorespaces#2\unskip}}% \setbox2\hbox{\ignorespaces\strut#1\unskip}% \setbox4\hbox{\doifsomething{#3}{\txx\setstrut\strut\ignorespaces#3\unskip}}% @@ -163,7 +163,7 @@ \stopxmlsetups \def\doCMLbond - {\hrule\!!width\hsize\!!height.1ex\relax} + {\hrule\s!width\hsize\s!height.1ex\relax} \def\dodoCMLbond#1#2#3% {\begingroup diff --git a/tex/context/base/x-dir-05.mkiv b/tex/context/base/x-dir-05.mkiv index de1d3fa5f..379b3220a 100644 --- a/tex/context/base/x-dir-05.mkiv +++ b/tex/context/base/x-dir-05.mkiv @@ -52,13 +52,13 @@ \stopluacode \def\getfilestatevariable#1#2% - {\ctxlua{commands.getfilestatevariable("#1","#2")}} + {\ctxcommand{getfilestatevariable("#1","#2")}} \def\savefilestate {\dodoubleargument\dosavefilestate} \def\dosavefilestate[#1][#2]% - {\ctxlua{commands.savefilestate("#1","#2")}% + {\ctxcommand{savefilestate("#1","#2")}% \setxvariables [#1] [name={#2}, diff --git a/tex/context/base/x-mathml.lua b/tex/context/base/x-mathml.lua index 30e770190..cc7238f94 100644 --- a/tex/context/base/x-mathml.lua +++ b/tex/context/base/x-mathml.lua @@ -12,7 +12,7 @@ local type, next = type, next local utf = unicode.utf8 local format, lower, find, gsub = string.format, string.lower, string.find, string.gsub local strip = string.strip -local utfchar, utffind, utfgmatch, utfgsub = utf.char, utf.find, utf.gmatch, utf.gsub +local utfchar = utf.char local xmlsprint, xmlcprint, xmltext, xmlcontent = xml.sprint, xml.cprint, xml.text, xml.content local getid = lxml.getid local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues @@ -87,6 +87,8 @@ local o_replacements = { -- in main table } +local simpleoperatorremapper = utf.remapper(o_replacements) + --~ languages.data.labels.functions local i_replacements = { @@ -457,8 +459,7 @@ function xml.functions.remapopenmath(e) end function mathml.checked_operator(str) - str = utfgsub(str,".",o_replacements) - context(str) + context(simpleoperatorremapper(str)) end function mathml.stripped(str) @@ -481,10 +482,8 @@ end function mathml.mo(id) local str = xmlcontent(getid(id)) or "" - local rep = gsub(str,"&.-;","") - local rep = utfgsub(rep,".",o_replacements) - context(rep) - -- context.mo(rep) -- fails with \left etc + local rep = gsub(str,"&.-;","") -- todo + context(simpleoperatorremapper(rep)) end function mathml.mi(id) @@ -524,10 +523,7 @@ function mathml.mfenced(id) -- multiple separators elseif n == 1 then xmlsprint(collected[1]) -- to be checked else - local t = { } - for s in utfgmatch(separators,"[^%s]") do - t[#t+1] = s - end + local t = utf.split(separators,true) for i=1,n do xmlsprint(collected[i]) -- to be checked if i < n then @@ -646,8 +642,8 @@ function mathml.mcolumn(root) local tag = e.tg if tag == "mi" or tag == "mn" or tag == "mo" or tag == "mtext" then local str = xmltext(e) -str = gsub(str,"&.-;","") - for s in utfcharacters(str) do -- utf.gmatch(str,".") btw, the gmatch was bugged + str = gsub(str,"&.-;","") + for s in utfcharacters(str) do m[#m+1] = { tag, s } end if tag == "mn" then @@ -658,7 +654,7 @@ str = gsub(str,"&.-;","") end elseif tag == "mspace" or tag == "mline" then local str = e.at.spacing or "" - for s in utfcharacters(str) do -- utf.gmatch(str,".") btw, the gmatch was bugged + for s in utfcharacters(str) do m[#m+1] = { tag, s } end -- elseif tag == "mline" then diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv deleted file mode 100644 index f64fdbc74..000000000 --- a/tex/context/base/x-mathml.mkiv +++ /dev/null @@ -1,2366 +0,0 @@ -%D \module -%D [ file=x-mathml, -%D version=2008.05.29, -%D title=\CONTEXT\ XML Modules, -%D subtitle=Loading \MATHML\ Filters, -%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. - -% \xmlfilter{#1}{/*/name()} -> \xmltag - -% This module is under construction and will be cleaned up. We use a funny mix of -% xml, tex and lua. I could rewrite the lot but it also shows how context evolves. -% -% no m:text strip (needs checking, maybe nbsp is mandate - -\writestatus{loading}{ConTeXt XML Macros / MathML Renderer} - -\unprotect - -\usemodule[x][calcmath] -%usemodule[x][asciimath] - -\startmodule [mathml] - -\registerctxluafile{x-mathml}{} - -\def\ctxmodulemathml#1{\directlua\zerocount{moduledata.mathml.#1}} - -\startxmlsetups xml:mml:define - \xmlsetsetup{\xmldocument} {(formula|subformula)} {mml:formula} - \xmlfilter {\xmldocument} {omt:*/function(remapopenmath)} - \xmlfilter {\xmldocument} {mml:bind/function(remapmmlbind)} - \xmlfilter {\xmldocument} {mml:csymbol/function(remapmmlcsymbol)} - \xmlsetsetup{\xmldocument} {mml:*} {mml:*} - \xmlsetsetup{\xmldocument} {mml:apply/mml:apply/mml:inverse/../..} {mml:apply:inverse} - \xmlstrip {\xmldocument} {(mml:mi|mml:mo|mml:mn|mml:csymbol)} -\stopxmlsetups - -\xmlregisterns{omt}{openmath} -\xmlregisterns{mml}{mathml} - -\xmlregistersetup{xml:mml:define} - -\def\MMLhack{\let\MMLpar\par \let\par\relax \everyvbox{\let\par\MMLpar}} - -\xmlmapvalue {mml:math:mode} {display} {\displaymathematics} % we had this already -\xmlmapvalue {mml:math:mode} {inline} {\inlinemathematics } - -\xmlmapvalue {mml:math:display} {block} {\displaymathematics} % before this showed up -\xmlmapvalue {mml:math:display} {inline} {\inlinemathematics } - -\xmlmapvalue {mml:math:dir} {ltr} {\setfalse\c_math_right_to_left\math_basics_synchronize_direction} -\xmlmapvalue {mml:math:dir} {rtl} {\settrue \c_math_right_to_left\math_basics_synchronize_direction} - -\startxmlsetups mml:math - \begingroup - \xmlval {mml:math:dir} {\xmlatt{#1}{dir}} {} - \xmlval {mml:math:display} {\xmlatt{#1}{display}} { - \xmlval {mml:math:mode} {\xmlatt{#1}{mode}} { - \automathematics - } - } - { - \MMLhack\xmlflush{#1} - } - \endgroup -\stopxmlsetups - -\startxmlsetups mml:imath - \inlinemathematics{\MMLhack\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:dmath - \displaymathematics{\MMLhack\xmlflush{#1}} -\stopxmlsetups - -%D First we define some general formula elements. - -\startxmlsetups mml:formula - \edef\mmlformulalabel {\xmlatt{#1}{label}\xmlatt{#1}{id}} - \edef\mmlformulasublabel{\xmlatt{#1}{sublabel}\xmlatt{#1}{id}} - \doifsomething\mmlformulalabel{\placeformula[\mmlformulalabel]{\mmlformulasublabel}} - \startformula\MMLhack\xmlfirst{#1}{/mml:math}\stopformula -\stopxmlsetups - -\setfalse\mmlignoredelimiter -\settrue \mmlsomeleftdelimiter - -\def\MMLleftorright - {\ifconditional\mmlsomeleftdelimiter - \setfalse\mmlsomeleftdelimiter\expandafter\MMLleft - \else - \settrue \mmlsomeleftdelimiter\expandafter\MMLright - \fi} - -\ifx\MMLleft \undefined \let\MMLleft \firstofoneargument \fi -\ifx\MMLright \undefined \let\MMLright \firstofoneargument \fi -\ifx\MMLmiddle\undefined \let\MMLmiddle\firstofoneargument \fi - -\def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleft #1}\fi} -\def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLright #1}\fi} -\def\mmlmiddledelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLmiddle #1}\fi} -\def\mmlleftorrightdelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleftorright#1}\fi} - -\def\mmlchar#1{\char#1 } % used in lua code - -% \newcount\delimiternesting \appendtoks \delimiternesting\zerocount \to \everymathematics - -% \def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{% -% \advance\delimiternesting\plusone \MMLleft #1}\fi} -% \def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{% -% \advance\delimiternesting\plusone \MMLright#1}\fi} -% \def\mmlmiddledelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{% -% \ifcase\delimiternesting\MMLleft\else\MMLmiddle\fi#1}\fi} - - -%D Remark: from now on this is a module and no longer an xtag -%D filter. There is an intermediate cleaner module but it has -%D some namespace limitations. Here we do it the \MKIV\ way. - -\def\widevec#1% - {\vbox{\mathsurround\zeropoint\ialign{##\crcr - \rightarrowfill\crcr\noalign{\nointerlineskip}% - \startimath\hfil\displaystyle{#1}\hfil\stopimath\crcr}}} - -%D The rendering macros: - -\def\MMLrm{\mr} - -\def\MMLseparator#1{\removeunwantedspaces{#1}\ignorespaces} % nils space after separator -\def\MMLseparator#1{,} % todo, for europe we need to block the space - -%D Since I only had the draft of MathML 2 and later 3 as example of -%D rendering, there are probably a lot of omissions and -%D misinterpretations. At least I learned some bits and -%D pieces of math rendering. -%D -%D The main complications were not so much the math, but to -%D find the most efficient way to handle elements without -%D spacing beging messed up. The first implementation was -%D aimed at getting reasonable output, this second -%D implementation is already better in terms of handling -%D nesting, and I will definitely need a third one that has -%D more efficient and less ugly code. -%D -%D The \TEX\ part is not that complicated and once the -%D preprocessor was okay, the rest way just a lot of keying -%D and testing. It all comes down to gobbling, redefining, -%D and not so much to parsing. -%D -%D The second implementation expanded the whole math sequence -%D into an internal \TEX\ representation. This is a rather clean -%D and fast process. Filtering and testing takes place by -%D redefining teh internal representation macros. -%D -%D The third implementation may look a bit more messy in some -%D respects. This is because in \TEX\ it's not that trivial to -%D implement a tree handler. We use a stack for the \type {apply} -%D element and other sequential content. Occasionally we need to -%D peek into child elements which involves messy code. This -%D implementation is closer to the normal \XML\ handling in -%D \CONTEXT. - -%D We start with the parent elements and the option handler. - -\def\xmlmathmldirective#1{\dosetvalue{MML#1}} - -%def\xmlmathmldirective#1#2#3{[#1][#2][#3]\dosetvalue{MML#1}{#2}{#3}} - -%D In the styles, options can be set with: - -\unexpanded\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[MML#1]} % no @@ because passed to lua - -%D We will apply inner math to all bits and pieces made up by an -%D \type {apply}. - -\def\MMLmathinner - {\ifinner - \expandafter\firstofoneargument - \else - \expandafter\mathinner - \fi} - -%D Auxiliary MathML macros: (to be generalized) - -\def\mmlfirst #1{\xmlelement{#1}{1}} % we can move these inline if needed -\def\mmlsecond #1{\xmlelement{#1}{2}} -\def\mmlthird #1{\xmlelement{#1}{3}} -\def\mmlprelast#1{\xmlelement{#1}{-2}} -\def\mmllast #1{\xmlelement{#1}{-1}} - -\starttexdefinition doifelsemmlfunction #1 - \xmldoifelse {#1} {/mml:fn} { - \firstoftwoarguments - } { - \xmldoifelse {#1} {/mml:apply/mml:fn} { - \firstoftwoarguments - } { - \xmldoifelse {#1} {/mml:ci[@type=='fn']} { - \firstoftwoarguments - } { - \secondoftwoarguments - } - } - } -\stoptexdefinition - -%D Special features: - - \newtoks \@@postponedMMLactions \setfalse \somepostponedMMLactions - - \def\postponeMMLactions#1% - {\global\settrue\somepostponedMMLactions - \global\@@postponedMMLactions\expandafter{\the\@@postponedMMLactions#1}} - - \def\postponedMMLactions - {\global\setfalse\somepostponedMMLactions - \@EA\global\@EA\@@postponedMMLactions\@EA\emptytoks - \the\@@postponedMMLactions} - -%D A couple of lists: - -\convertargument - mml:times|mml:divide|mml:power|% - mml:lt|mml:gt|mml:eq|mml:leq|mml:geq|% - mml:in|mml:inverse|% - mml:fn|% - mml:floor|mml:ceiling|% - mml:mean|% - mml:selector|% - mml:abs|mml:int|mml:limit|mml:sum|mml:product|% - mml:outerproduct|mml:innerproduct|mml:scalarproduct% -\to \MMLcmainresetlist - -\convertargument - mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|% - mml:cos|mml:arccos|mml:cosh|mml:arccosh|% - mml:tan|mml:arctan|mml:tanh|mml:arctanh|% - mml:cot|mml:arccot|mml:coth|mml:arccoth|% - mml:csc|mml:arccsc|mml:csch|mml:arccsch|% - mml:sec|mml:arcsec|mml:sech|mml:arcsech|% - mml:ln|mml:exp|mml:log|% - mml:abs|mml:int|mml:limit|mml:sum|mml:product|% - mml:fn% -\to \MMLcfunctionlist - -\convertargument - mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|% - mml:cos|mml:arccos|mml:cosh|mml:arccosh|% - mml:tan|mml:arctan|mml:tanh|mml:arctanh|% - mml:cot|mml:arccot|mml:coth|mml:arccoth|% - mml:csc|mml:arccsc|mml:csch|mml:arccsch|% - mml:sec|mml:arcsec|mml:sech|mml:arcsech|% - mml:ln|mml:exp|mml:log|% - mml:abs% -\to \MMLcpurefunctionlist - -\convertargument - mml:diff|mml:partialdiff|mml:root% -\to \MMLcconstructlist - -%D We use inner and grouping (begin/end and no b/e) else we -%D get problems with 1/2(1+2) and alike (todo: ask taco). -%D -%D The problem with apply is that we need to take care of -%D several situations, like: -%D -%D \starttyping -%D <apply> <.../> ... -%D <apply> <fn> ... -%D <apply> <apply> <ci> ... -%D <apply> <apply> <fn> <ci> ... -%D \stoptyping -%D -%D Because we translated version 2 of this renderer into -%D version 3 the following definitions may be sub optimal or -%D more complex than actually needed. - -%D We will more more to lua ... - -% simple version - -\newcount\@MMLlevel \def\MMLcreset{\@MMLlevel\zerocount} - -\let\MMLctempresetlist\empty \def\setMMLcreset{\edef\MMLctempresetlist} - -\let\MMLdoL\donothing -\let\MMLdoR\donothing - -\newcount\mmlapplydepth \def\MMLcreset{\mmlapplydepth\zerocount} - -\startxmlsetups mml:apply - \MMLmathinner { - \xmldoif {#1} {/(\MMLcmainresetlist\string|\MMLctempresetlist)} { - % \MMLcreset - } - \edef\mmlapplyopentoken {\xmlatt{#1}{open}} - \edef\mmlapplyclosetoken{\xmlatt{#1}{close}} - \ifcase\mmlapplydepth \else - \ifx\mmlapplyopentoken\empty - \def\mmlapplyopentoken {(} - \def\mmlapplyclosetoken{)} - \fi - \fi - \advance\mmlapplydepth\plusone - \begingroup - \ifx\mmlapplyopentoken\empty - \let\MMLdoL\donothing - \let\MMLdoR\donothing - \else - \edef\MMLdoL{\noexpand\left \mmlapplyopentoken } - \edef\MMLdoR{\noexpand\right\mmlapplyclosetoken} - \fi - \let\MMLctempresetlist\empty - \xmldoifelse {#1} {/mml:apply} { -% % <apply> <apply> ... </apply> <ci> .. </ci> </apply> -% \xmldoifelse {#1} {/mml:apply(mml:plus|mml:minus)} {% [a] -% % yet incomplete and rather untested -% % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply> - } {% [b] -% \MMLcreset - } -% \MMLdoL -% \mmlfirst{#1} -% \ifconditional\somepostponedMMLactions -% \postponedMMLactions -% \else -% \left(\MMLcreset\mmlsecond{#1}\right) -% \fi -% \MMLdoR -% } { - \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}} - \doifsetupselse {mml:apply:mml:\mmlapplyaction} { - \xmlsetup{#1}{mml:apply:mml:\mmlapplyaction} - } { -% \MMLdoL - \xmlsetup{#1}{mml:\xmlfilter{#1}{/*/name()}} -% \MMLdoR - } -% } - \endgroup - \advance\mmlapplydepth\minusone - } -\stopxmlsetups - -\startxmlsetups mml:apply:mml:apply - \xmlflush{#1} - \xmlall{#1}{../[position()>1]} -\stopxmlsetups - -\startxmlsetups mml:apply:mml:fn - \xmldoifelse {#1} {/mml:fn/mml:ci} { - \edef\mmlfnci{\xmlstripped{#1}{/mml:fn/mml:ci}}% was xmlcontent - \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:... - \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin - } { - \MMLcreset - \MMLdoL - \mmlfirst{#1} - \ifnum\xmlcount{#1}{/*}>\plusone - \negthinspace % not enough - \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right) - \fi - \MMLdoR - } - } { - \MMLcreset - \MMLdoL - \xmlall{#1}{/*} - \MMLdoR - } -\stopxmlsetups - -\startxmlsetups mml:apply:mml:csymbol - \xmlsetup{#1}{mml:csymbol}% \MMLdoL/MMLdoR to be handled in plugin -\stopxmlsetups - -\startxmlsetups mml:apply:mml:ci - \xmlfirst{#1}{/mml:ci} - \ifnum\xmlcount{#1}{/*}>\plusone - \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right) - \fi -\stopxmlsetups - -% reln - -\startxmlsetups mml:reln - \writestatus{XML}{MathML element "reln" is obsolete} -\stopxmlsetups - -% fn - -% plusminus ± - -\startxmlsetups mmc:fn:\utfchar{"00B1} - \MMLdoL - \xmlconcat{#1}{/[position()>1]}{\utfchar{"00B1}} - \MMLdoR -\stopxmlsetups - -% minusplus - -\startxmlsetups mmc:fn:\utfchar{"2213} - \MMLdoL - \xmlconcat{#1}{/[position()>1]}{\utfchar{"2213}} - \MMLdoR -\stopxmlsetups - -\startxmlsetups mmc:fn - \begingroup - \edef\mmlnoffn{\xmlcount{#1}{/*}} - \ifnum\mmlnoffn>\plustwo - \def\MMCfnleft {\left(} - \def\MMCfnright{\right)} - \else - \let\MMCfnleft \relax - \let\MMCfnright\relax - \fi - \xmldoifelse {#1} {/mml:ci} { % first - \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent - \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:... - \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin - } { - \MMLcreset - \mmlfirst{#1} - } - } { - \xmldoifelse {#1} {/mml:apply} { % first - \xmldoifelse {#1} {/(mml:plus\string|mml:minus)} { - \left(\mmlfirst{#1}\right) - } { - \mmlfirst{#1} - } - \ifnum\mmlnoffn>\plusone - \left(\xmlall{#1}{/!mml:apply}\right) - \fi - } { - \MMLcreset - \negthinspace - \MMCfnleft - \ifnum\mmlnoffn=\plustwo,\fi - \xmlconcat{#1}{/*}{2}{}{\MMLseparator,} - \MMCfnright - } - } - \endgroup -\stopxmlsetups - -\startxmlsetups mmc:fn:apply % where used? - \xmldoifelse {#1} {/mml:ci} { % first - \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent - \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:... - \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin - } { - \MMLcreset - \mmlfirst{#1} - \ifnum\xmlcount{#1}{/*}>\plusone - \negthinspace - \left(\MMLcreset\xmlconcat{#1}{2}{}{\MMLseparator,}\right) - \fi - } - } { - \endgroup - \MMLcreset - \mmlfirst{#1} - } -\stopxmlsetups - -%D The next definition provide a kind of plug-in mechanism (see -%D the open math extension module). - -% http://www.publishers.com/somename -% -% called at the lua end - -\starttexdefinition mmlapplycsymbol #1#2#3#4 - % #1=full url, #2=name, #3=encoding, #4=text - \doifelse {#3} {text} { -% {\mr #4} - \text{#4} - } { - \doifsetupselse {mml:csymbol:#1} { - % full url - \directsetup{mml:csymbol:#1} - } { - % somename (fallback) - \doifsetupselse {mml:csymbol:#2} { - \directsetup{mml:csymbol:#2} - } { - \xmlval{mmc:cs}{#3}{}% todo - } - } - } -\stoptexdefinition - -\startxmlsetups mml:csymbol - \ctxmodulemathml{csymbol("#1")} -\stopxmlsetups - -\startxmlsetups mml:csymbol:cdots - \cdots -\stopxmlsetups - -% \startxmlsetups mml:csymbol:<url> \stopxmlsetups - -%D Alternative b will convert periods into comma's: - -\setupMMLappearance[cn] [\c!alternative=\v!a] -\setupMMLappearance[polar] [\c!alternative=\v!a] % a|b|c -\setupMMLappearance[float] [\c!symbol=\v!no] % \v!yes|dot -\setupMMLappearance[enotation][\c!symbol=\v!no] % \v!yes|dot -\setupMMLappearance[base] [\c!symbol=\v!numbers] % digits|characters|text|no - -\startxmlsetups mml:cs \xmlcommand{#1}{/}{mml:cs:\xmlattdef{#1}{type}{default}} \stopxmlsetups -\startxmlsetups mml:ci \xmlcommand{#1}{/}{mml:ci:\xmlattdef{#1}{type}{default}} \stopxmlsetups -\startxmlsetups mml:cn \xmlcommand{#1}{/}{mml:cn:\xmlattdef{#1}{type}{default}} \stopxmlsetups - -% helpers cn / todo: \mn{...} - -\startxmlsetups mml:cn:default - \mathopnolimits{\xmlflush{#1}} -\stopxmlsetups - -% helpers ci - -\startxmlsetups mml:ci:default - \xmlflush{#1} -\stopxmlsetups - -\startxmlsetups mml:ci:set - {\blackboard{\xmlflush{#1}}} % todo -\stopxmlsetups - -\startxmlsetups mml:ci:vector - \widevec{\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:ci:matrix - {\bi\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:ci:function - \xmlflush{#1}% \negthinspace -\stopxmlsetups - -\startxmlsetups mml:ci:fn - \xmlsetup{#1}{mml:ci:function} -\stopxmlsetups - -\startxmlsetups mml:ci:complex-cartesian - \xmlsetup{#1}{mml:cn:complex} -\stopxmlsetups - -\startxmlsetups mml:ci:complex - \xmlsetup{#1}{mml:cn:complex} -\stopxmlsetups - -\startxmlsetups mml:ci:complex-polar - \xmlsetup{#1}{mml:cn:polar} -\stopxmlsetups - -\startxmlsetups mml:ci:polar - \xmlsetup{#1}{mml:cn:polar} -\stopxmlsetups - -% helpers ci - -\startxmlsetups mml:cn:default - \xmlflush{#1} -\stopxmlsetups - -\startxmlsetups mml:cn:integer - \edef\mmlintegerbase{\xmlattdef{#1}{base}{}} - \ifx\mmlintegerbase\empty - \xmlflush{#1} - \else - \doifelse \MMLbasesymbol \v!no { - \MMLcCNbasedata{\xmlflush{#1}} - } { - \MMLcCNbasedata{\xmlflush{#1}}\normalsubscript{ - \hbox {\startimath - \mr - \scriptscriptstyle - \processaction - [\MMLbasesymbol] - [\v!characters=>\MMLcCNbasestring BODH, - \v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX}, - \s!unknown=>\mmlintegerbase] - \stopimath} - } - } - \fi -\stopxmlsetups - -\def\MMLcCNbasedata#1% - {\ifnum\mmlintegerbase>10 \relax{\mr#1}\else#1\fi} - -\def\MMLcCNbasestring#1#2#3#4% - {\ifnum\mmlintegerbase= 2 #1\else - \ifnum\mmlintegerbase= 8 #2\else - \ifnum\mmlintegerbase=10 #3\else - \ifnum\mmlintegerbase=16 #4\else - \mmlintegerbase \fi\fi\fi\fi} - -\startxmlsetups mml:cn:polar - \xmlsetup{#1}{mml:cn:polar:\MMLpolaralternative} -\stopxmlsetups - -\startxmlsetups mml:cn:polar:a - \ctxmodulemathml{cpolar_a("#1")} -\stopxmlsetups - -\startxmlsetups mml:cn:polar:b - {\mr e}\normalsuperscript{\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}} -\stopxmlsetups - -\startxmlsetups mml:cn:polar:c - \exp\left(\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}\right) -\stopxmlsetups - -\startxmlsetups mml:cn:complex-polar - \xmlsetup{#1}{mml:cn:polar} -\stopxmlsetups - -\startxmlsetups mml:cn:complex % todo ( ) - \left(\xmlsnippet{#1}{1} + \xmlsnippet{#1}{3}\thinspace{\mr i}\right) -\stopxmlsetups - -\startxmlsetups mml:cn:complex-cartesian - \xmlsetup{#1}{mml:cn:complex} -\stopxmlsetups - -\startxmlsetups mml:cn:float - \doifelse \MMLfloatsymbol \v!no { - % make sure that e shows up ok - \mathopnolimits{\xmlflush{#1}} - } { - % we should ignore \entities ! - \edef\mmlfloatstring{\xmlflush{#1}} - \splitstring\mmlfloatstring\at e\to\first\and\last - \ifx\first\empty - \mmlfloatstring - \else\ifx\last\empty - \mmlfloatstring - \else - \first - \doifelse \MMLfloatsymbol {dot} \cdot \times - 10\normalsuperscript{\last} - \fi \fi - } -\stopxmlsetups - -\startxmlsetups mml:cn:real - \xmlsetup{#1}{mml:cn:float} -\stopxmlsetups - -\startxmlsetups mml:cn:e-notation - \doifelse \MMLenotationsymbol \v!no { - \xmlsnippet{#1}{1} - \unskip\mathopnolimits{e}\ignorespaces - \xmlsnippet{#1}{3} - } { - \xmlsnippet{#1}{1} - \doifelse \MMLenotationsymbol {dot} \cdot - \times10\normalsuperscript{\xmlsnippet{#1}{3}} - } -\stopxmlsetups - -\startxmlsetups mml:cn:logical - \mathopnolimits{\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:cn:rational - \xmldoifelse {#1} {/mml:sep} { - \frac - {\xmlsnippet{#1}{1}} - {\xmlsnippet{#1}{3}} - } { - \xmlflush{#1} - } -\stopxmlsetups - -% interval - -\setupMMLappearance[interval][\c!alternative=\v!a,\c!separator={,}] - -% when empty element, then it's an apply - -\startxmlsetups mml:interval - \doifelse {\xmltag{#1}} {apply} { - % #1 == apply - \let\mmlintervalfirst \mmlsecond - \let\mmlintervalsecond\mmlthird - \xmlsetup{#1}{mml:interval:\xmlattributedef{#1}{/mml:interval}{closure}{closed}} - } { - % #1 == interval - \let\mmlintervalfirst \mmlfirst - \let\mmlintervalsecond\mmlsecond - \xmlsetup{#1}{mml:interval:\xmlattdef{#1}{closure}{closed}} - } -\stopxmlsetups - -\startxmlsetups mml:interval:closed - \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right] -\stopxmlsetups - -\startxmlsetups mml:interval:open-closed - \doifelse \MMLintervalalternative \v!b { - \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right] - } { - \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right] - } -\stopxmlsetups - -\startxmlsetups mml:interval:closed-open - \doifelse \MMLintervalalternative \v!b { - \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right> - } { - \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right) - } -\stopxmlsetups - -\startxmlsetups mml:interval:open - \doifelse \MMLintervalalternative \v!b { - \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right> - } { - \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right) - } -\stopxmlsetups - -% inverse - -\setfalse\xmlinversefunction - -\startxmlsetups mml:apply:inverse - \settrue\xmlinversefunction - \xmlsetup{#1}{mml:\xmlfilter{#1}{/mml:apply/*[2]/name()}} -\stopxmlsetups - -% condition - -% maybe a fast \xmlnonfirst - -% instead of the following we could do \xmlcontent{#1}{/mml:bvar} etc - -\startxmlsetups mml:bvar \xmlflush{#1} \stopxmlsetups -\startxmlsetups mml:lowlimit \xmlflush{#1} \stopxmlsetups -\startxmlsetups mml:uplimit \xmlflush{#1} \stopxmlsetups -\startxmlsetups mml:degree \xmlflush{#1} \stopxmlsetups -\startxmlsetups mml:logbase \xmlflush{#1} \stopxmlsetups -\startxmlsetups mml:fn \xmlflush{#1} \stopxmlsetups - -\startxmlsetups mml:condition -% \xmldoif {#1} {/mml:bvar} { -% \xmlfirst{#1}{/mml:bvar}\mid -% } - \xmlall{#1}{/!(mml:condition\string|mml:bvar)} -\stopxmlsetups - -% declare - -\setupMMLappearance[declare][\c!state=\v!start] - -\startxmlsetups mml:declare - \doif \MMLdeclarestate \v!start { - \mathopnolimits{declare} - \mmlfirst{#1} - \ifnum\xmlcount{#1}{/*}>\plusone - \thickspace - \mathopnolimits{as} - \thickspace - \fi - \mmlsecond{#1} - } -\stopxmlsetups - -% lambda - -\setupMMLappearance[lambda][\c!alternative=b] - -\startxmlsetups mml:lambda - \begingroup - \doifelse \MMLlambdaalternative \v!a { - \lambda\left(\xmlconcat{#1}{/!mml:lambda}{\MMLseparator,}\right) - } { - \ifnum\xmlcount{#1}{/mml:bvar}>\plusone - \left(\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}\right) - \else - \xmlfirst{#1}{/mml:bvar} - \fi - \mapsto - \MMLcreset - \xmlall{#1}{/!(mml:bvar|mml:lambda)} - } - \endgroup -\stopxmlsetups - -% compose - -\startxmlsetups mml:compose - \begingroup - \MMLcreset -% \let\MMLcCIfunction\firstofoneargument % brrr ? ? ? - \doifelsemmlfunction {#1} { - \left(\xmlconcat{#1}{/!mml:compose}{\circ}\right) - } { - \xmlconcat{#1}{/!mml:compose}{\circ} - } - \endgroup -\stopxmlsetups - -\startxmlsetups mml:image - \mathopnolimits{image} \left( {\mr\xmlfilter{#1}{/!mml:image/tag()}} \right) -\stopxmlsetups - -\setupMMLappearance[piece][\c!separator=] - -\startxmlsetups mml:piecewise - \processaction - [\MMLpieceseparator] - [ \v!yes=>\def\theMMLpieceseparator{,&}, - \v!no=>\def\theMMLpieceseparator{&}, - \s!default=>\def\theMMLpieceseparator{&}, - \s!unknown=>\def\theMMLpieceseparator{\,\,\hbox{\MMLpieceseparator}\,\,}] - \cases{\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:piece - \mmlfirst{#1}\theMMLpieceseparator\mathematics{\mmlsecond{#1}}\crcr -\stopxmlsetups - -\startxmlsetups mml:otherwise -% \xmlflush{#1}\MMLcPIECEseparator&{\mr otherwise}\crcr - \xmlflush{#1}&{\mr otherwise}\crcr -\stopxmlsetups - -% end of piece - -\startxmlsetups mml:quotient - \lfloor\mmlsecond{#1}/\mmlthird{#1}\rfloor -\stopxmlsetups - -\startxmlsetups mml:factorial - \xmlall{#1}{/!factorial}! -\stopxmlsetups - -\setupMMLappearance [divide] [\c!level=\!!maxcard,\c!alternative=\v!a] - -\newcount\mmldividelevel - -\startxmlsetups mml:divide - \advance\mmldividelevel\plusone - \doifelse \MMLdividealternative \v!b { - \mmlsecond{#1}/\mmlthird{#1} - } { - \ifnum \mmldividelevel > \MMLdividelevel \relax % threshold - \mmlsecond{#1}/\mmlthird{#1} - \else - \MMLcreset - \frac{\MMLcreset\mmlsecond{#1}}{\MMLcreset\mmlthird{#1}} - \fi - } - \advance\mmldividelevel\minusone -\stopxmlsetups - -% min max - -\startxmlsetups mml:min \mathopnolimits{min} \xmlsetup{#1}{mml:minmax} \stopxmlsetups -\startxmlsetups mml:max \mathopnolimits{max} \xmlsetup{#1}{mml:minmax} \stopxmlsetups - -\startxmlsetups mml:minmax - \xmldoif {#1} {/mml:bvar} { - {}\normalsubscript{\xmlfirst{#1}{/mml:bvar}} - } - \left\{ - \xmlconcat{#1}{/!(mml:bvar\string|mml:max\string|mml:min)}{\MMLseparator,} - \right\} -\stopxmlsetups - -% minus plus - -\setupMMLappearance [plus] [\c!alternative=\v!a] % b = no sign -> 3 1/4 -\setupMMLappearance [sign] [\c!reduction=\v!yes] - -% alternative b -> geen sign - -% branch needed, else (a-b) + (c-d) goes wrong -% reset check in case of (-x) + 37 -% reset check in case of (-x) + 37 - -\newcount\mmlpluscounter - -\startxmlsetups mml:plus - \doifelse \MMLsignreduction \v!yes { - \MMLdoL - \xmlsetup{#1}{mml:plus:reset} - \xmlcommand{#1}{/!mml:plus}{mml:plus:body} - \MMLdoR - } { - \ifnum\xmlcount{#1}{/!mml:plus}=\plusone - +\xmlfirst{#1}{/!mml:plus} - \else - \MMLdoL - \xmlconcat{#1}{/!mml:plus}{+} - \MMLdoR - \fi - } -\stopxmlsetups - -\startxmlsetups mml:plus:reset - \mmlpluscounter\zerocount -\stopxmlsetups - -\startxmlsetups mml:plus:body - \advance\mmlpluscounter\plusone - \ifnum\mmlpluscounter>\plusone - \xmldoifelse{#1}{/mml:minus} { - \ifnum\xmlcount{#1}{/!mml:minus}>\plusone - + - \fi - } { - \doifelse {\xmlatt{#1}{type}} {rational} { - % fraction - } { - + - } - } - \fi - \xmldirect{#1} -\stopxmlsetups - -\newcount\mmlminuscounter - -\startsetups mml:minus - \doifelse \MMLsignreduction \v!yes { - \ifnum\xmlcount{#1}{/!mml:minus}=\plusone - -\xmlfirst{#1}{/!mml:minus} - \else - \MMLdoL - \xmlsetup{#1}{mml:minus:reset} - \xmlcommand{#1}{/!mml:minus}{mml:minus:body} - \MMLdoR - \fi - } { - \left( % \MMLdoL - \ifnum\xmlcount{#1}{/!mml:minus}=\plusone - -\xmlfirst{#1}{/!mml:minus} - \else - \xmlsetup{#1}{mml:minus:reset} - \xmlcommand{#1}{/!mml:minus}{mml:minus:body} - \fi - \right) % \MMLdoR - } -\stopsetups - -\startxmlsetups mml:minus:reset - \mmlminuscounter\zerocount -\stopxmlsetups - -\startxmlsetups mml:minus:body - % we can slso use concat here - \advance\mmlminuscounter\plusone - \ifnum\mmlminuscounter>\plusone - - - \fi - \xmldirect{#1} -\stopxmlsetups - -% power - -\setupMMLappearance[power][\c!reduction=\v!yes] - -\let\MMLpowerelement\empty - -\startxmlsetups mml:power - \xmldoifelse {#1} {/mml:apply} { - \doifelse \MMLpowerreduction \v!yes { - \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist)} { - \gdef\MMLpowerelement{\mmlthird{#1}}% postpone, no xdef - \MMLcreset\mmlsecond{#1} - } { - \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}} - } - } { - \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}} - } - } { - \mmlsecond{#1}\normalsuperscript{\MMLcreset\mmlthird{#1}} - } -\stopxmlsetups - -% rem - -\startxmlsetups mml:rem - \xmlconcat{#1}{/!mml:rem}{\mathopnolimits{mod}} -\stopxmlsetups - -\setupMMLappearance [times] [\c!symbol=\v!no,\c!auto=\v!yes] % new, auto catches cn cn cn - -\startxmlsetups mml:times - \setMMLcreset{\MMLcfunctionlist\string|\MMLcconstructlist}% - \doifelse\MMLtimesauto\v!no { - \let\MMLtimes@@symbol\MMLtimessymbol - } { - \xmldoifelse {#1} {/mml:cn[name(1) == 'mml:cn']} {% name(1) is next one - \doifinsetelse\MMLtimessymbol{\v!yes,\v!no} { - \let\MMLtimes@@symbol\v!yes - } { - \let\MMLtimes@@symbol\MMLtimessymbol - } - } { - \let\MMLtimes@@symbol\MMLtimessymbol - } - } - \doifelse\MMLtimes@@symbol\v!yes { - \xmlconcat{#1}{/!mml:times}{\times} - } { - \doifelse\MMLtimes@@symbol{dot} { - \xmlconcat{#1}{/!mml:times}{\cdot} - } { - \doifelse\MMLtimes@@symbol{times} { - \xmlconcat{#1}{/!mml:times}{\times} - } { - \xmlall{#1}{/!mml:times} - } - } - } -\stopxmlsetups - -\setupMMLappearance[root][\c!symbol=\v!yes] - -\startxmlsetups mml:root - \xmldoifelse {#1} {/mml:degree} { - \root - \doifnot\MMLrootsymbol\v!no{\MMLcreset\xmltext{#1}{/mml:degree}} - \of - } { - \sqrt - } - {\MMLcreset\xmlall{#1}{/!(mml:degree\string|mml:root)}} -\stopxmlsetups - -% gcd - -\startxmlsetups mml:gcd - \begingroup - \gcd\left(\MMLcreset\xmlconcat{#1}{/!mml:gcd}{\MMLseparator,}\right) - \endgroup -\stopxmlsetups - -% and or xor implies, not - -\startxmlsetups mml:and \xmlconcat{#1}{/!mml:and} {\wedge} \stopxmlsetups -\startxmlsetups mml:or \xmlconcat{#1}{/!mml:or} {\vee} \stopxmlsetups -\startxmlsetups mml:xor \xmlconcat{#1}{/!mml:xor} {\mathopnolimits{xor}} \stopxmlsetups -\startxmlsetups mml:implies \xmlconcat{#1}{/!mml:implies}{\Rightarrow} \stopxmlsetups -\startxmlsetups mml:not \neg \xmlall {#1}{/!mml:not} \stopxmlsetups - -% forall exists - -%D We need to shift left below rotated A. - -\startxmlsetups mml:forall - \forall \negthinspace \xmlsetup{#1}{mml:forallexists} -\stopxmlsetups - -\startxmlsetups mml:exists - \exists \xmlsetup{#1}{mml:forallexists} -\stopxmlsetups - -\def\mmlforallexistslist{mml:bvar\string|mml:forall\string|mml:exists\string|mml:condition} - -\startxmlsetups mml:forallexists - \normalsubscript{\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}} - \xmldoifelse {#1} {/mml:condition} { - \thickspace - \begingroup - \xmlfirst{#1}{/mml:condition} - \endgroup - \ifcase\xmlcount{#1}{/!(\mmlforallexistslist)}\relax - % nothing - \or - % == snelle volgende - \left\vert - \MMLcreset \medspace \xmlconcat{#1}{/!(\mmlforallexistslist)}{} - \right. - \else - % special case - \left\vert - \matrix { - \xmlconcat{#1}{/!(\mmlforallexistslist)}{\hfill\crcr} - } - \right. - \fi - } { - :\xmlfirst{#1}{/!(\mmlforallexistslist)} - } -\stopxmlsetups - -\startxmlsetups mml:abs - \left\vert \MMLcreset\xmlall{#1}{/!mml:abs} \right\vert -\stopxmlsetups - -\startxmlsetups mml:conjugate % watch extra {} - {\overline{\MMLcreset\xmlall{#1}{/!mml:conjugate}}} -\stopxmlsetups - -\startxmlsetups mml:arg - \mathopnolimits{arg} \left( \MMLcreset\xmlall{#1}{/!mml:arg} \right) -\stopxmlsetups - -\startxmlsetups mml:real - \Re \left( \MMLcreset \xmlall{#1}{/!mml:real} \right) -\stopxmlsetups - -\startxmlsetups mml:imaginary - \Im \ left( \MMLcreset \xmlall{#1}{/!mml:imaginary} \right) -\stopxmlsetups - -\startxmlsetups mml:lcm - \mathopnolimits{lcm} \left( \xmlconcat{#1}{/!mml:lcm}{\MMLseparator,} \right) -\stopxmlsetups - -\startxmlsetups mml:floor - \lfloor \xmlall{#1}{/!mml:floor} \rfloor -\stopxmlsetups - -\startxmlsetups mml:ceiling - \lceiling \xmlall{#1}{/!mml:ceiling} \rceiling -\stopxmlsetups - -% relations - -% apply attr or eq - -\setupMMLappearance[relation][\c!align=\v!no] - -\xmlmapvalue {mml:relation} {eq} {=} -\xmlmapvalue {mml:relation} {neq} {\neq} -\xmlmapvalue {mml:relation} {gt} {>} -\xmlmapvalue {mml:relation} {lt} {<} -\xmlmapvalue {mml:relation} {geq} {\geq} -\xmlmapvalue {mml:relation} {leq} {\leq} -\xmlmapvalue {mml:relation} {equivalent} {\equiv} -\xmlmapvalue {mml:relation} {approx} {\approx} -\xmlmapvalue {mml:relation} {factorof} {\mid} - -\startxmlsetups mml:eq \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:neq \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:gt \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:lt \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:geq \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:leq \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:equivalent \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:approx \xmlsetup{#1}{mml:relation} \stopxmlsetups -\startxmlsetups mml:factorof \xmlsetup{#1}{mml:relation} \stopxmlsetups - -\startxmlsetups mml:relation - \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}} - \MMLcreset \xmlsetup{#1}{mml:relation:\xmlattdef{#1}{align}{\MMLrelationalign}} -\stopxmlsetups - -\startxmlsetups mml:relation:default - \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}} -\stopxmlsetups -\startxmlsetups mml:relation:last - \eqalign { - \xmlconcatrange{#1}{/*}{2}{-2}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr} - \mmlprelast{#1}&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}\mmllast{#1} - } -\stopxmlsetups -\startxmlsetups mml:relation:first - \eqalign { - \mmlsecond{#1}\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{} - &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&} - } -\stopxmlsetups -\startxmlsetups mml:relation:left - \eqalign { - \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr} - } -\stopxmlsetups -\startxmlsetups mml:relation:right - \eqalign { - &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&} - } -\stopxmlsetups -\startxmlsetups mml:relation:no - \xmlsetup{#1}{mml:relation:default} -\stopxmlsetups -\startxmlsetups mml:relation:yes - \xmlsetup{#1}{mml:relation:left} -\stopxmlsetups - -% personal goody: - -\edef\MMLcmainresetlist{\MMLcmainresetlist\string|becomes} - -\xmlmapvalue {mml:relation} {mml:becomes} {:=} - -\startxmlsetups mml:becomes \xmlsetup{#1}{mml:relation} \stopxmlsetups - -% calculus and vector calculus - -\startxmlsetups mml:domainofapplication - \xmlall{#1}{/!mml:domainofapplication} -\stopxmlsetups - -\setupMMLappearance[int][\c!location=\v!top] - -\def\doMMLlimits#1{\doifelsevalue{MML#1\c!location}\v!top\limits\nolimits} - -\startxmlsetups mml:int - \MMLcreset - \xmldoifelse {#1} {/mml:domainofapplication} { - \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:domainofapplication}}\relax - } { - \xmldoifelse {#1} {/mml:condition} { - \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:condition}}\relax - } { - \xmldoifelse {#1} {/mml:lowlimit} { - \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:lowlimit}}\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}} - } { - % funny, why do we have lowlimit/uplimit then - \xmldoifelse {#1} {/mml:apply/mml:interval} { - \int \doMMLlimits{int}\normalsubscript{\xmlindex{#1}{/mml:apply}{2}}\normalsuperscript{\xmlindex{#1}{/mml:apply}{3}} - } { - \int - } - } - } - } - \MMLcreset - \xmldoifelse {#1} {/mml:apply} { - \doifelsemmlfunction {#1} { % todo test - \xmlfirst{#1}{/mml:apply} - } { - % if there are too many () now, we need to be more clever - \left( \xmlfirst{#1}{/mml:apply} \right) - } - } { - \xmlfirst{#1}{/mml:ci} - } - \xmldoifelse {#1} {/mml:bvar} { - \thinspace {\mr d} \xmlfirst{#1}{/mml:bvar} - } { - % nothing - } -\stopxmlsetups - -\setupMMLappearance[diff][\c!location=\v!top,\c!alternative=\v!a] - -\startxmlsetups mml:diff - \MMLcreset - \doifelse \MMLdiffalternative \v!a { - \xmldoifelse {#1} {/mml:lambda} { - % a special case (mathadore/openmath) - \frac { - d - \normalsuperscript - {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}} - {\xmlfirst{#1}{/mml:lambda}\xmlfirst{#1}{/mml:ci}} - } { - d - {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}} - \normalsuperscript - {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}} - } - } { - \xmldoifelse {#1} {/mml:bvar} { - \frac { - {\mr d}{ - \xmldoifelse {#1} {/mml:degree} { - \normalsuperscript{\xmlconcat{#1}{/mml:degree}\empty} - } { - \xmldoif {#1} {/mml:bvar/mml:degree} { - \normalsuperscript{\xmlconcat{#1}{/mml:bvar/mml:degree}+} - } - } - } - \doif \MMLdifflocation \v!top { - \xmldoifelse {#1} {/mml:ci} { - \xmlfirst{#1}{/mml:ci} - } { - \MMLcreset -\ifnum\xmlcount{#1}{/mml:apply/*}>\plustwo % hack - \left( - \xmlfirst{#1}{/mml:apply} - \right) -\else - \xmlfirst{#1}{/mml:apply} -\fi - } - } - } { - {\mr d} - \xmlfirst{#1}{/mml:bvar/!mml:degree} - \xmldoif {#1} {/mml:bvar/mml:degree} { - \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}} - } - } - \doifnot \MMLdifflocation \v!top { - \left(\MMLcreset\xmlfirst{#1}{/(mml:apply\string|mml:ci)}\right) - } - } { - % beware, the second {} is needed for the superscript - \xmlconcatrange{#1}{/*}{2}{}{}\normalsuperscript\prime - } - } - } { - \MMLcreset - \xmlfirst{#1}{/(mml:apply\string|mml:ci)} - % there can be problems with nested diff's: \normalsuperscript\normalsuperscript{} error - % so we add an empty group here - {}\normalsuperscript - { - \xmldoifelse {#1} {/mml:degree} { - \edef\mmldegree{\xmlfirst{#1}{/mml:degree/mml:cn}} - \ifx\mmldegree\empty - % what to do here - \else - \dorecurse\mmldegree\prime - \fi - } { - \prime - } - } - } -\stopxmlsetups - -\startxmlsetups mml:partialdiff - \xmldoifelse {#1} {/mml:list} { - {\mr D}\normalsubscript{ - \begingroup - \setfalse\mmllistdelimiters - \xmlall{#1}{/mml:list} - \endgroup - } - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} - } { - \xmldoifelse {#1} {/mml:bvar} { - \frac { - {\mr d}\normalsuperscript{ - \xmldoifelse {#1} {/mml:degree} { - \xmlconcat{#1}{/mml:degree}\empty - } { - \xmlconcat{#1}{/mml:bvar/mml:degree}+ - } - } - \MMLcreset - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} - } { - \xmldoif {#1}{/mml:bvar/!mml:degree} { - \xmlfirst{#1}{/mml:bvar/!mml:degree} \, - } - {\mr d}\xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} - \xmldoif {#1} {/mml:bvar/mml:degree} { - \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}} - } - } - } { - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} - } - } -\stopxmlsetups - -\startxmlsetups mml:divergence \mathopnolimits{div} \xmlall{#1}{/!mml:divergence} \stopxmlsetups -\startxmlsetups mml:grad \mathopnolimits{grad} \xmlall{#1}{/!mml:grad} \stopxmlsetups -\startxmlsetups mml:curl \mathopnolimits{curl} \xmlall{#1}{/!mml:curl} \stopxmlsetups -\startxmlsetups mml:laplacian \nabla\normalsuperscript2 \xmlall{#1}{/!mml:laplacian} \stopxmlsetups -\startxmlsetups mml:ident \mathopnolimits{identity} \xmlall{#1}{/!mml:ident} \stopxmlsetups - -\setupMMLappearance[domain] [symbol=] -\setupMMLappearance[codomain][symbol=] - -\startxmlsetups mml:domain - \doifelsenothing \MMLdomainsymbol { - \mathopnolimits{domain}\MMLcreset\xmlall{#1}{/!mml:domain} - } { - \MMLdomainsymbol\normalsubscript{\xmlall{#1}{/!mml:domain}} - } -\stopxmlsetups - -\startxmlsetups mml:codomain - \doifelsenothing \MMLcodomainsymbol { - \mathopnolimits{codomain}\MMLcreset\xmlall{#1}{/!mml:codomain} - } { - \MMLcodomainsymbol\normalsubscript{\xmlall{#1}{/!mml:codomain}} - } -\stopxmlsetups - -% theory of sets - -\startxmlsetups mml:set - \left\{ - \xmldoifelse {#1} {/mml:condition} { - \xmlfirst{#1}{/mml:bvar}\,\middle\vert\,\xmlfirst{#1}{/mml:condition} - } { - \xmlconcat{#1}{/!mml:set}{\MMLseparator,} - } - \right\} - \relax % needed -\stopxmlsetups - -\settrue\mmllistdelimiters - -\startxmlsetups mml:list - \begingroup - \ifconditional\mmllistdelimiters\left [\fi - \begingroup - \settrue\mmllistdelimiters - \xmlconcat{#1}{/!mml:list}{\MMLseparator,} - \endgroup - \ifconditional\mmllistdelimiters\right]\fi - \endgroup -\stopxmlsetups - -\startxmlsetups mml:union \mmlsecond{#1} \cup \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:intersect \mmlsecond{#1} \cap \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:in \mmlsecond{#1} \in \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:notin \mmlsecond{#1} {\not\in} \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:subset \mmlsecond{#1} \subset \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:prsubset \mmlsecond{#1} \subseteq \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:notsubset \mmlsecond{#1} {\not\subset} \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:notprsubset \mmlsecond{#1} {\not\subseteq} \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:setdiff \mmlsecond{#1} \setminus \mmlthird{#1} \stopxmlsetups - -\startxmlsetups mml:card - \left\vert \xmlall{#1}{/!mml:card} \right\vert -\stopxmlsetups - -\startxmlsetups mml:cartesianproduct - \xmlconcat{#1}{/!mml:cartesianproduct}{\times} -\stopxmlsetups - -% sequences and series - -\setupMMLappearance[sum] [\c!location=\v!top] -\setupMMLappearance[product][\c!location=\v!top] - -\xmlmapvalue {mml:sumprod} {sum} {\sum} -\xmlmapvalue {mml:sumprod} {product} {\prod} - -\startxmlsetups mml:sum \edef\mmlsumprodname{sum} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups -\startxmlsetups mml:product \edef\mmlsumprodname{product} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups - -\def\mmlstackedsubscripts#1% - {\vbox - {\baselineskip\zeropoint % hack, taco vragen - \halign{\startimath\scriptstyle\hss\alignmark\alignmark\hss\stopimath\cr#1\crcr}}} - -% unfinished - -\startxmlsetups mml:sumprod - \begingroup - \xmldoifelse {#1} {/(mml:condition\string|mml:bvar\string|mml:lowlimit)} { - \def\mmlsumprodlower{ - \normalsubscript{ - \xmldoifelse {#1} {/mml:condition} { - \mmlstackedsubscripts{\xmlconcat{#1}{/mml:condition}{\crcr}} - } { - \xmldoif {#1} {/mml:bvar} { - \xmlfirst{#1}{/mml:bvar} - \xmldoif{#1}{/mml:lowlimit}{=} - } - \xmlfirst{#1}{/mml:lowlimit} - } - } - } - } { - \let\mmlsumprodlower\empty - } - \xmldoifelse {#1} {/mml:uplimit} { - \def\mmlsumprodupper{\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}} - } { - \let\mmlsumprodupper\empty - } - \xmldoif {#1} {/mml:interval} { % open math converter gives this - \edef\mmlintervalfrom{\xmlindex{#1}{/mml:interval}{1}} - \edef\mmlintervalto {\xmlindex{#1}{/mml:interval}{2}} - \ifx \mmlintervalfrom \empty \else - \def\mmlsumprodlower{\normalsubscript{\xmldoif{#1}{/mml:bvar}{\xmlfirst{#1}{/mml:bvar}{=}}\mmlintervalfrom}} - \fi - \ifx \mmlintervalto \empty \else - \def\mmlsumprodupper{\normalsuperscript{\mmlintervalto}} - \fi - } - \MMLcreset - \xmlval{mml:sumprod}{\mmlsumprodname}{}\doMMLlimits\mmlsumprodname\mmlsumprodupper\mmlsumprodlower - \MMLcreset - \xmldoifelse {#1} {/mml:lambda/mml:apply} { - \xmlfirst{#1}{/mml:lambda/mml:apply}% a bit of open math conversion mess - } { - \xmlfirst{#1}{/(mml:apply\string|mml:lambda\string|mml:ci)}% - } - \endgroup -\stopxmlsetups - -\setupMMLappearance[limit][\c!location=\v!top] - -\startxmlsetups mml:limit - \MMLcreset \lim - \doMMLlimits {limit}\normalsubscript{ - \MMLcreset - \xmldoifelse {#1} {/mml:condition} { - \xmlfirst{#1}{/mml:condition} - } { - \xmldoif {#1} {/mml:bvar} { - \xmlfirst{#1}{/mml:bvar}\rightarrow - } - \xmlfirst{#1}{/mml:lowlimit} - } - } - \begingroup - % a bit of open math conversion mess, lambda needed for openmath, ok? - \MMLcreset - \xmlfirst{#1}{/mml:lambda/mml:apply} - \xmlfirst{#1}{/(mml:apply\string|mml:lambda)} - \endgroup -\stopxmlsetups - -% consider a faster index - -\startxmlsetups mml:tendsto - \MMLcreset \mmlsecond{#1} - \xmlval {mml:tendsto:type} {\xmlattdef{#1}{type}{default}} {\rightarrow} - \MMLcreset \mmlthird{#1} -\stopxmlsetups - -\xmlmapvalue {mml:tendsto:type} {above} {\downarrow} -\xmlmapvalue {mml:tendsto:type} {below} {\uparrow} -\xmlmapvalue {mml:tendsto:type} {default} {\rightarrow} - -% elementary classical functions - -\setupMMLappearance[log][\c!location=\v!right] - -\startxmlsetups mml:exp -% {\mr e}\normalsuperscript{\xmlfirst{#1}{/mml:apply\string|mml:reln\string|mml:ci\string|mml:cn}} - {\mr e}\normalsuperscript{\xmlfirst{#1}{/!mml:exp}} -\stopxmlsetups - -\startxmlsetups mml:log - \xmldoifelse {#1} {/mml:logbase} { - \doifelse \MMLloglocation \v!left { - \mathop { - {}\normalsuperscript{\xmlfirst{#1}{/mml:logbase}}\negthinspace\mathopnolimits{log} - } - } { - \mathopnolimits{log}\normalsubscript{\xmlfirst{#1}{/mml:logbase}} - } -% \MMLcreset - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} -% \xmlsetup{#1}{mml:function} % todo, we start elsewhere -% \mmlthird{#1} - } { - \mathopnolimits{log} -% \MMLcreset -% \xmlsetup{#1}{mml:function} % todo, we start elsewhere - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)} -% \mmlsecond{#1} - } -\stopxmlsetups - -\startxmlsetups mml:ln - \mathopnolimits{ln} - \xmlsetup{#1}{mml:function} -\stopxmlsetups - -% statistics - -\startxmlsetups mml:mean \overline {\mmlsecond{#1}} \stopxmlsetups -\startxmlsetups mml:sdev \sigma \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups -\startxmlsetups mml:variance \sigma \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript2 \stopxmlsetups -\startxmlsetups mml:median \mathopnolimits{median}\left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups -\startxmlsetups mml:mode \mathopnolimits{mode} \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups - -% moments - -\startxmlsetups mml:moment - \left\langle - \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}\normalsuperscript{\xmlfirst{#1}{/mml:degree}} - \right\rangle - \xmldoif {#1} {mml:momentabout} { - \normalsubscript{\xmlfirst{#1}{mml:momentabout}} - } -\stopxmlsetups - -% linear algebra - -\setupMMLappearance [vector] [\c!direction=\v!horizontal,\c!separator={,}] - -\startxmlsetups mml:vector - \begingroup - \ifnum\xmlcount{#1}{/*}>\plusone - \doifelse\MMLvectordirection\v!horizontal { - \left(\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}\right) - } { - \MMLcreset\left(\matrix{\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}}\right) - } - \else - \overrightarrow{\charhtstrut\mmlfirst{#1}} - \fi - \endgroup -\stopxmlsetups - -\settrue\MMCdelmatrix % ( ) when true - -\startxmlsetups mml:matrix - \begingroup - \MMLcreset - \ifconditional\MMCdelmatrix - \left(\matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}\right) - \else - \settrue\MMCdelmatrix - \matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}} - \fi - \endgroup -\stopxmlsetups - -\startxmlsetups mml:matrixrow - \begingroup - \MMLcreset - \left(\xmlsetup{#1}{mml:matrixrow:do}\right) - \endgroup -\stopxmlsetups - -\startxmlsetups mml:matrixrow:do - \xmlconcat{#1}{/*}{&}\crcr -\stopxmlsetups - -\startxmlsetups mml:determinant - \begingroup - \setfalse\MMCdelmatrix - \left|\mmlsecond{#1}\right| - \endgroup -\stopxmlsetups - -\startxmlsetups mml:transpose - \mmlsecond{#1}\normalsuperscript{\mathopnolimits{T}} -\stopxmlsetups - -\startxmlsetups mml:selector - \MMLmathinner{\mmlsecond{#1}\normalsubscript{\MMLcreset\xmlconcatrange{#1}{/*}{3}{}{\MMLseparator,}}} -\stopxmlsetups - -\startxmlsetups mml:vectorproduct \mmlsecond{#1}\times \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:scalarproduct \mmlsecond{#1}\cdot \mmlthird{#1} \stopxmlsetups -\startxmlsetups mml:outerproduct \mmlsecond{#1}\otimes\mmlthird{#1} \stopxmlsetups - -% semantic mapping elements - -\setupMMLappearance[semantics][\c!state=\v!start] - -\startxmlsetups mml:semantics - \doifelse\MMLsemanticsstate\v!start { - \xmlall{#1}{/mml:annotation} - } { - \xmlall{#1}{/!mml:annotation} - } -\stopxmlsetups - -\startxmlsetups mml:annotation - \xmldoifelse {#1} {.[oneof(@encoding,'TeX','tex','TEX','ConTeXt','context','CONTEXT','ctx')]} { - \xmlflushcontext{#1} - } { - \xmldoifelse {#1} {.[oneof(@encoding,'calcmath','cm')]} { - \expanded{\calcmath{\xmlflush{#1}}} - } { - \xmldoifelse {#1} {.[oneof(@encoding,'asciimath','am')]} { - \ifdefined\asciimath - \expanded{\asciimath{\xmlflush{#1}}} - \else - \hbox{\tt no am loaded}% - \fi - } { - \xmlall{#1}{../!mml:annotation} - } - } - } -\stopxmlsetups - -\startxmlsetups mml:annotation-xml - % maybe diagnostics -\stopxmlsetups - -% misc - -\startxmlsetups mml:integers \integers \stopxmlsetups -\startxmlsetups mml:reals \reals \stopxmlsetups -\startxmlsetups mml:rationals \rationals \stopxmlsetups -\startxmlsetups mml:naturalnumbers \naturalnumbers \stopxmlsetups -\startxmlsetups mml:complexes \complexes \stopxmlsetups -\startxmlsetups mml:primes \primes \stopxmlsetups -\startxmlsetups mml:exponentiale \mathopnolimits{e} \stopxmlsetups -\startxmlsetups mml:imaginaryi \mathopnolimits{i} \stopxmlsetups -\startxmlsetups mml:notanumber \mathopnolimits{NaN} \stopxmlsetups -\startxmlsetups mml:true \mathopnolimits{true} \stopxmlsetups -\startxmlsetups mml:false \mathopnolimits{false} \stopxmlsetups -\startxmlsetups mml:emptyset \mathopnolimits{\O} \stopxmlsetups -\startxmlsetups mml:pi \pi \stopxmlsetups -\startxmlsetups mml:eulergamma \gamma \stopxmlsetups -\startxmlsetups mml:infinity \infty \stopxmlsetups - -% gonio functions - -\setupMMLappearance[function][\c!reduction=\v!yes] - -% todo: \mfunction which adapts itself when registered as command - -% todo: \def\mmlcfunction#1#2{\mathopnolimits{#2}\xmlsetup{#1}{mml:function}} - -\startxmlsetups mml:sin \mathcommand {sin}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:sinh \mathcommand {sinh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:cos \mathcommand {cos}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:cosh \mathcommand {cosh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:tan \mathcommand {tan}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:tanh \mathcommand {tanh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:cot \mathcommand {cot}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:coth \mathcommand {coth}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:csc \mathcommand {csc}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:csch \mathcommand {csch}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:sec \mathcommand {sec}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:sech \mathcommand {sech}\xmlsetup{#1}{mml:function} \stopxmlsetups - -\startxmlsetups mml:arcsin \mathcommand {arcsin}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arcsinh \mathcommand{arcsinh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccos \mathcommand {arccos}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccosh \mathcommand{arccosh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arctan \mathcommand {arctan}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arctanh \mathcommand{arctanh}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccot \mathcommand {arccot}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccoth \mathcommand{arccoth}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccsc \mathcommand {arccsc}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arccsch \mathcommand{arccsch}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arcsec \mathcommand {arcsec}\xmlsetup{#1}{mml:function} \stopxmlsetups -\startxmlsetups mml:arcsech \mathcommand{arcsech}\xmlsetup{#1}{mml:function} \stopxmlsetups - -\startxmlsetups mml:function - \ifx\MMLpowerelement\empty - \ifconditional\xmlinversefunction\normalsuperscript{-1}\fi - \setfalse\xmlinversefunction - \else - \normalsuperscript{\ifconditional\xmlinversefunction-\fi\MMLpowerelement} - \setfalse\xmlinversefunction - \glet\MMLpowerelement\empty - \fi - \xmlsetup{#1}{mml:function:argument} -\stopxmlsetups - -\startxmlsetups mml:function:argument - \doifelse \MMLfunctionreduction \v!yes { - \xmldoifelse {#1} {/mml:apply} { - \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist\string|mml:divide)} - \donefalse - \donetrue - } { - \donefalse - } - } { - \donetrue - } - % beware, we still flush from 2 up - \ifdone - \left( - \MMLcreset - \xmlall{#1}{/[position()>1]}% \xmlconcatrange{#1}{/*}{2}{}\empty - \right) - \else - \MMLcreset - \xmlall{#1}{/[position()>1]} - \fi -\stopxmlsetups - -% PRESENTATION MATHML -% -% there are some rough edges that need to be sorted out - -% helpers - -\xmlmapvalue {mml} {normal} {\tf} -\xmlmapvalue {mml} {double-struck} {\bf} -\xmlmapvalue {mml} {italic} {\it} -\xmlmapvalue {mml} {fraktur} {\bf} -\xmlmapvalue {mml} {script} {\tf} -\xmlmapvalue {mml} {bold} {\bf} -\xmlmapvalue {mml} {bold-italic} {\bi} -\xmlmapvalue {mml} {bold-fraktur} {\bf} -\xmlmapvalue {mml} {bold-script} {\bf} -\xmlmapvalue {mml} {sans-serif} {\ss} -\xmlmapvalue {mml} {bold-sans-serif} {\ss\bf} -\xmlmapvalue {mml} {sans-serif-italic} {\ss\it} -\xmlmapvalue {mml} {sans-serif-bold-italic} {\ss\bi} -\xmlmapvalue {mml} {monospace} {\tt} - -% todo: displaystyle=true/false (or whatever else shows up) - -\starttexdefinition setmmlmathstyle #1 - \xmlval {mml} {\xmlatt{#1}{mathvariant}} \empty % was: \mmmr -\stoptexdefinition - -\starttexdefinition applymmlmathcolor #1#2 - \edef\mmlmathcolor{\xmlatt{#1}{mathcolor}} - \ifx \mmlmathcolor \empty - #2 - \else - \color[\mmlmathcolor]{#2} - \fi -\stoptexdefinition - -% todo: textbackgrounds - -\starttexdefinition applymmlmathbackground #1#2 - \edef\mmlmathbackground{\xmlatt{#1}{mathbackground}} - \ifx \mmlmathbackground \empty - #2 - \else - \backgroundline[\mmlmathbackground]{#2} - \fi -\stoptexdefinition - -\newsignal\mmltextsignal % not used - -\starttexdefinition applymmlsometext #1#2 - \applymmlmathbackground {#1} { - \applymmlmathcolor {#1} { - \setmmlmathstyle {#1} - #2 - } - } -\stoptexdefinition - -% probably bugged: - -\starttexdefinition doMMLfiller #1 - \pushmacro\doMMLfiller - \let\doMMLfiller\gobbleoneargument - \gdef\dodoMMLfiller{% where used - \disablefiller - \mathematics{#1} - } - \hbox { - \def\normalorfiller##1##2{ - \gdef\dodoMMLfiller{\enablefiller#1}% - \let\normalorfiller\gobbletwoarguments - } - \mathematics{#1} - } - \popmacro\doMMLfiller -\stoptexdefinition - -% setups - -\startxmlsetups mml:mi % todo: mathvariant mathsize mathcolor mathbackground - \ctxmodulemathml{mi("#1")} -\stopxmlsetups - -\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground -% \begingroup -% \mr - \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest -% \endgroup -\stopxmlsetups - -% <m:mo>-</m:mo><m:mn>2</m:mn> and <m:mn>1</m:mn><m:mo>-</m:mo><m:mn>2</m:mn> -% -% spacing between - and 2 is taken care of by tex itself - -\startxmlsetups mml:mo - \doif {\xmlatt{#1}{maxsize}} {1} {\settrue\mmlignoredelimiter} - \doif {\xmlatt{#1}{stretchy}} {false} {\settrue\mmlignoredelimiter} - \ctxmodulemathml{mo("#1")} - \setfalse\mmlignoredelimiter -\stopxmlsetups - -\startxmlsetups mml:mfenced % {} around separator is needed for spacing - \def\MMLleft {\left }% weird - \def\MMLright {\right} - \def\MMLmiddle{\middle} - \ctxmodulemathml{mfenced("#1")} -\stopxmlsetups - -\defineoverlay [mml:enclose:box] [\useMPgraphic{mml:enclose:box}] -\defineoverlay [mml:enclose:roundedbox] [\useMPgraphic{mml:enclose:roundedbox}] -\defineoverlay [mml:enclose:circle] [\useMPgraphic{mml:enclose:circle}] -\defineoverlay [mml:enclose:left] [\useMPgraphic{mml:enclose:left}] -\defineoverlay [mml:enclose:right] [\useMPgraphic{mml:enclose:right}] -\defineoverlay [mml:enclose:top] [\useMPgraphic{mml:enclose:top}] -\defineoverlay [mml:enclose:bottom] [\useMPgraphic{mml:enclose:bottom}] -\defineoverlay [mml:enclose:updiagonalstrike] [\useMPgraphic{mml:enclose:updiagonalstrike}] -\defineoverlay [mml:enclose:downdiagonalstrike] [\useMPgraphic{mml:enclose:downdiagonalstrike}] -\defineoverlay [mml:enclose:horizontalstrike] [\useMPgraphic{mml:enclose:horizontalstrike}] -\defineoverlay [mml:enclose:verticalstrike] [\useMPgraphic{mml:enclose:verticalstrike}] - -\startuseMPgraphic{mml:enclose:box} - draw OverlayBox withpen pencircle scaled (ExHeight/10) ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:roundedbox} - draw OverlayBox cornered .5ExHeight withpen pencircle scaled (ExHeight/10) ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:circle} - draw fullcircle xysized(bbwidth(OverlayBox),bbheight(OverlayBox)) withpen pencircle scaled (ExHeight/10) ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:left} - draw leftboundary OverlayBox withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:right} - draw rightboundary OverlayBox withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:top} - draw topboundary OverlayBox withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:bottom} - draw bottomboundary OverlayBox withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:updiagonalstrike} - path p ; p := OverlayBox enlarged -.25ExHeight ; - draw llcorner p -- urcorner p withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:downdiagonalstrike} - path p ; p := OverlayBox enlarged -.25ExHeight ; - draw ulcorner p -- lrcorner p withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:horizontalstrike} - path p ; p := OverlayBox enlarged -.25ExHeight ; - draw .5[llcorner p,ulcorner p] -- .5[lrcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic -\startuseMPgraphic{mml:enclose:verticalstrike} - path p ; p := OverlayBox enlarged -.25ExHeight ; - draw .5[llcorner p,lrcorner p] -- .5[ulcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ; - setbounds currentpicture to OverlayBox ; -\stopuseMPgraphic - -\startxmlsetups mml:menclose - \edef\mmlmenclosenotation{\ctxmodulemathml{menclosepattern("#1")}} - \ifx\mmlmenclosenotation\empty - \xmlflush{#1} - \else - \doifelse \mmlmenclosenotation {mml:enclose:longdiv} { - \overline{\left)\strut\xmlflush{#1}\right.} - } { - \doifelse \mmlmenclosenotation {mml:enclose:actuarial} { - \overline{\left.\strut\xmlflush{#1}\right|} - } { - \doifelse \mmlmenclosenotation {mml:enclose:radical} { - \sqrt{\xmlflush{#1}} - } { - % todo: no framed when longdiv, actuarial or radical ? spec ? - \vcenter { - \framed - [frame=off,strut=no,background={\mmlmenclosenotation}] % offset is kind of undefined - {\startimath - \expanded{\doifinsetelse {mml:enclose:longdiv} {\mmlmenclosenotation}} { - \overline{\left)\strut\xmlflush{#1}\right.} - } { - \expanded{\doifinsetelse {mml:enclose:actuarial} {\mmlmenclosenotation}} { - \overline{\left.\strut\xmlflush{#1}\right|} - } { - \expanded{\doifinsetelse {mml:enclose:radical} {\mmlmenclosenotation}} { - \sqrt{\xmlflush{#1}} - } { - \xmlflush{#1} - } - } - } - \stopimath} - } - } - } - } - \fi -\stopxmlsetups - -\xmlmapvalue {mml:mfrac:linethickness} {thin} {.2pt} -\xmlmapvalue {mml:mfrac:linethickness} {medium} {.4pt} -\xmlmapvalue {mml:mfrac:linethickness} {thick} {.8pt} -\xmlmapvalue {mml:mfrac:linethickness} {0} {0pt} - -\startxmlsetups mml:mfrac % dodo: handle linethickness in lua + unit - \begingroup - \edef\mmlfraclinethickness{\xmlatt{#1}{linethickness}} - \ifx\mmlfraclinethickness\empty - \doifelse{\xmlatt{#1}{bevelled}}{true} { - \left.\mmlfirst{#1}\middle/\mmlsecond{#1}\right.% \thinspace\middle/\thinspace - } { - \frac{\mmlfirst{#1}}{\mmlsecond{#1}} - } - \else - \doifelse {\xmlval{mml:mfrac:linethickness}{\mmlfraclinethickness}{}} {} { - \scratchdimen\xmlval{mml:mfrac:linethickness}\mmlfraclinethickness{.4pt} - } { - % probably not yet ok - \setdimensionwithunit\scratchdimen\mmlfraclinethickness{pt} - } - { - {\mmlfirst{#1}} - \above\scratchdimen - {\mmlsecond{#1}} - } - \fi - \endgroup -\stopxmlsetups - -\startxmlsetups mml:ms - \hbox { - \tf % else encoding problems - \edef\mmllquote{\xmlatt{#1}{lquote}} - \edef\mmlrquote{\xmlatt{#1}{rquote}} - \ifx\mmllquote\empty\symbol[leftquotation]\else\mmllquote\fi - \applymmlsometext{#1}{\xmlflush{#1}} - \ifx\mmlrquote\empty\symbol[rightquotation]\else\mmlrquote\fi - } -\stopxmlsetups - -\startxmlsetups mml:mstyle - \begingroup - \setmmlmathstyle{#1} - \xmlflush{#1} - \endgroup -\stopxmlsetups - -\setupMMLappearance[text][\c!alternative=\v!b] % a=normal, b=keep spaces - -\startxmlsetups mml:mtext - \text { - \applymmlsometext{#1}{ - \doifelse \MMLtextalternative \v!a { - %\ctxmodulemathml{stripped(\!!bs\xmlflush{#1}\!!es)} - \ignorespaces - \xmlflush{#1} - \removeunwantedspaces - } { - \xmlflush{#1} - } - } - } -\stopxmlsetups - -\startxmlsetups mml:merror - \hbox{\startimath\displaystyle\xmlflush{#1}\stopimath} -\stopxmlsetups - -\startxmlsetups mml:mphantom -% \phantom{\ignorespaces{}\xmlflush{#1}\unskip} % watch spacing {} hack -% \phantom{\mathstyle{\ignorespaces{}\xmlflush{#1}\unskip}}% - \phantom{\triggermathstyle\normalmathstyle\ignorespaces\xmlflush{#1}\removeunwantedspaces} -% \mktriggereffect\v!hidden -% \ignorespaces{}\xmlflush{#1}\unskip % no attributes in math yet -% \mktriggereffect\v!normal -\stopxmlsetups - -\startxmlsetups mml:mpadded % todo - \xmlflush{#1} -\stopxmlsetups - -% mrow / option: no fenced - -\startxmlsetups mml:maction - \xmlflush{#1} -\stopxmlsetups - -\startxmlsetups mml:mrow - \begingroup - \edef\nofmmlrows{\xmlcount{#1}{/mml:mo}}% - \ifnum\nofmmlrows=\plustwo - \xmldoifelse {#1} {/mml:mo[position()==1 or position()==\nofmmlrows]} {% we need a {} - \def\MMLleft {\left } - \def\MMLright {\right} - \def\MMLmiddle{\middle} - \enabledelimiter - \checkdelimiters{\xmlall{#1}{/mml:mo}} - \fakeleftdelimiter - \xmlflush{#1} - \fakerightdelimiter - \disabledelimiter - } { - \xmlflush{#1} - } - \else - \xmlflush{#1} - \fi - \endgroup -\stopxmlsetups - -\startxmlsetups mml:msqrt - \sqrt{\xmlflush{#1}} -\stopxmlsetups - -\startxmlsetups mml:mroot - \root{\mmlsecond{#1}}\of{\mmlfirst{#1}} -\stopxmlsetups - -\setupMMLappearance[scripts][\c!alternative=\v!a] % {} rond base - -\startxmlsetups mml:msub - \doifelse\MMLscriptsalternative\v!a { - {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}} - } { - \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}} - } -\stopxmlsetups - -\startxmlsetups mml:msup - \doifelse\MMLscriptsalternative\v!a { - {\mmlfirst{#1}}\normalsuperscript{\mmlsecond{#1}} - } { - \mmlfirst{#1} \normalsuperscript{\mmlsecond{#1}} - } -\stopxmlsetups - -\startxmlsetups mml:msubsup - \doifelse\MMLscriptsalternative\v!a { - {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}} - } { - \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}} - } -\stopxmlsetups - -\def\mmlexecuteifdefined#1% - {\ifx#1\empty - \expandafter\secondoftwoarguments - \else\ifcsname#1\endcsname - \expandafter\expandafter\expandafter\firstoftwoarguments - \else - \expandafter\expandafter\expandafter\secondoftwoarguments - \fi\fi - {\csname#1\endcsname}} - -\startxmlsetups mml:mover -% \mathop { - \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelse{\utfmathclass\mmlovertoken}{accent} { - \edef\mmlovercommand{\utfmathcommand\mmlovertoken} - \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}} - } { - \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}} - \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken} - \edef\mmlovercommand{\utfmathfiller\mmlovertoken} - \vbox { - \mathsurround\zeropoint \ialign { - \hss##\hss\crcr - \noalign{\kern3\onepoint}% - \mmlexecuteifdefined\mmlovercommand{\mathematics{\mmlsecond{#1}}}\crcr - \noalign{\kern3\onepoint\nointerlineskip}% - \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}\crcr - } - } - } -% } -% \limits % spoils spacing -\stopxmlsetups - -\startxmlsetups mml:munder -% \mathop { - \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}} - \doifelse{\utfmathclass\mmlundertoken}{accent} { - \edef\mmlundercommand{\utfmathcommand\mmlundertoken} - \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}} - } { - \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}} - \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken} - \edef\mmlundercommand{\utfmathfiller\mmlundertoken} - \vtop { - \mathsurround\zeropoint \ialign { - \hss##\hss\crcr - \mmlexecuteifdefined\mmlbasecommand {\mathematics{\mmlfirst{#1}}}\crcr - \noalign{\kern3\onepoint\nointerlineskip}% - \mmlexecuteifdefined\mmlundercommand{\mathematics{\mmlsecond{#1}}}\crcr - \noalign{\kern3\onepoint} - } - } - } -% } -% \limits % spoils spacing -\stopxmlsetups - -\startxmlsetups mml:munderover - \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}} - \edef\mmlbasecommand{\utfmathcommand\mmlbasetoken} - \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}} -\stopxmlsetups - -% tables (mml:mtable, mml:mtr, mml:mlabledtr, mml:mtd) - -\startxmlsetups mml:mtable % some more attributes need to be supported - \vcenter{\ctxmodulemathml{mtable("#1")}} -\stopxmlsetups - -\startxmlsetups mml:mcolumn - \ctxmodulemathml{mcolumn("#1")} -\stopxmlsetups - -\def\mmlsetfakewidth#1{\setbox\scratchbox\hbox{#1}\scratchdimen\wd\scratchbox} - -\def\mmlmcolumndigitspace {\mmlsetfakewidth {0}\kern\scratchdimen} -\def\mmlmcolumndigitrule {\mmlsetfakewidth {0}\vrule width \scratchdimen height .2pt depth .2pt\relax} -\def\mmlmcolumnsymbolrule {\mmlsetfakewidth{\times}\vrule width \scratchdimen height .2pt depth .2pt\relax} -\def\mmlmcolumnpunctuationrule{\mmlsetfakewidth {.}\vrule width \scratchdimen height .2pt depth .2pt\relax} - -\startxmlsetups mml:mspace - \begingroup - \edef\mmlspacetext{\xmlatt{#1}{spacing}} - \ifx\mmlspacetext\empty - \!!widtha \xmlattdef{#1}{width} \!!zeropoint % must be string - \!!heighta\xmlattdef{#1}{height}\!!zeropoint - \!!deptha \xmlattdef{#1}{depth} \!!zeropoint - \ifdim\!!heighta=\zeropoint - \ifdim\!!deptha=\zeropoint\else - \hbox{\vrule\!!depth\!!deptha\!!height\zeropoint\!!width\zeropoint}% - \fi - \else - \hbox{\vrule\!!depth\zeropoint\!!height\!!heighta\!!width\zeropoint}% - \fi - \ifdim\!!widtha=\zeropoint\else - \hskip\!!widtha - \fi - \else - \phantom{\triggermathstyle\normalmathstyle\mmlspacetext} - \fi - \endgroup -\stopxmlsetups - -% later we can do a better job by manipulating node lists - -% \startxmlsetups mml:mline -% % new, rather undefined, we need to capture a few keywords -% \edef\mmllinewidth {\xmlatt{#1}{linethickness}} -% \edef\mmllinetext {\xmlatt{#1}{spacing}} -% \edef\mmllinelength{\xmlattdef{#1}{length}\!!zeropoint} -% \ifx\mmllinewidth\empty -% \!!deptha.5\linewidth -% \else -% \!!deptha.5\dimexpr\mmllinewidth\relax -% \fi -% \!!heighta\!!deptha -% \ifx\mmllinetext\empty -% \ifx\mmllinelength\empty -% \!!widtha\zeropoint -% \else -% \!!widtha\mmllinelength -% \fi -% \else -% \setbox\scratchbox\hbox{\mathematics{\mathstyle{\mmllinetext}}}% not ok -% \!!widtha\wd\scratchbox -% \fi -% \hbox{\vrule\!!width\!!widtha\!!depth\!!deptha\!!height\!!heighta} -% \stopxmlsetups - -\startxmlsetups mml:mglyph % probably never ok (hbox is needed in order to switch to normal font) - \begingroup - \edef\mmlglyphfontfamily{\xmlatt {#1}{fontfamily}} - \edef\mmlglyphalt {\xmlattdef{#1}{alt}{unknown}} - \edef\mmlglyphindex {\xmlatt {#1}{index}} - \ifx \mmlglyphfontfamily \empty - \hbox{\tttf[no fontfamily specified for \mmlglyphalt]} - \else\ifx\mmlglyphindex\empty - \hbox{\tttf[no index specified for \mmlglyphalt]} - \else - \hbox{\getglyph\mmlglyphfontfamily\mmlglyphindex} - \fi\fi - \endgroup -\stopxmlsetups - -\startxmlsetups mml:maligngroup \stopxmlsetups % will be done when needed -\startxmlsetups mml:malignmark \stopxmlsetups % will be done when needed - -\startxmlsetups mml:none \stopxmlsetups -\startxmlsetups mml:mprescripts \stopxmlsetups - -\startxmlsetups mml:mmultiscripts - \ctxmodulemathml{mmultiscripts("#1")} -\stopxmlsetups - -% goodie - -\definebuffer[mml] - -\def\stopmml{\xmlprocessbuffer{@mml@}{\thedefinedbuffer{mml}}{}} - -\stopmodule - -\protect \endinput - -% TODO: -% -% <apply><divide/> -% <apply><minus/> -% <apply><minus/><ci>b</ci></apply> -% <apply><minus/><ci>b</ci></apply> -% <apply><root/> <ci>a</ci></apply> -% </apply> -% <apply><minus/> -% <apply><minus/><ci>b</ci><ci>b</ci></apply> -% <apply><minus/><ci>b</ci></apply> -% <apply><root/> <ci>a</ci></apply> -% </apply> -% </apply> - -% \startmoduletestsection -% -% \def\xflushXMLstackwith#1#2#3#4% num bgroup egroup whatever -% {\dostepwiserecurse{#1}\XMLstacklevel\plusone -% {#2\relax -% \ifnum\recurselevel>#1\relax#4\fi -% \getXMLstackdata\recurselevel -% #3}} -% -% \def\xflushXMLstackfrom#1#2#3% -% {\dostepwiserecurse{#1}\XMLstacklevel\plusone -% {#2\getXMLstackdata\recurselevel#3}} -% -% \startxmlsetups mml:minus -% \doif \MMLsignreduction \v!yes { -% \setMMLcreset{fn,\MMLcfunctionlist} -% } -% \ifcase\XMLstacklevel -% \or -% % self -% \or -% -\getXMLstackdata\plustwo -% \else -% \dostepwiserecurse \plustwo \XMLstacklevel \plusone { -% \begingroup -% \doifelse {\getXMLstackname\recurselevel} {apply} { -% \ifnum\recurselevel=\plustwo -% \begingroup -% \dodoifelseMMCfunctioninapply \recurselevel {minus} { -% \ifnum\XMLstacklevel>\plustwo -% \endgroup -% \else -% \endgroup -% \MMLcreset -% \fi -% } { -% \endgroup -% } -% \else -% \doifelseMMCfunctioninapply \recurselevel {\MMLcfunctionlist,\MMLcconstructlist} { -% \MMLcreset -% } { -% } -% \fi -% } { -% } -% \getXMLstackdata\recurselevel -% \ifnum\recurselevel<\XMLstacklevel\relax -% - -% \fi -% \endgroup -% } -% \fi -% \stopxmlsetups -% -% \stopmoduletestsection diff --git a/tex/context/base/x-udhr.mkiv b/tex/context/base/x-udhr.mkiv index 81075ac70..e081bfd59 100644 --- a/tex/context/base/x-udhr.mkiv +++ b/tex/context/base/x-udhr.mkiv @@ -87,7 +87,7 @@ \setuptolerance [verytolerant] -\doifnotmode{demo}{\endinput} +\continueifinputfile{x-udhr.mkiv} % todo: when argument given then process it diff --git a/tex/context/base/x-xfdf.mkiv b/tex/context/base/x-xfdf.mkiv new file mode 100644 index 000000000..460220ed9 --- /dev/null +++ b/tex/context/base/x-xfdf.mkiv @@ -0,0 +1,72 @@ +%D \module +%D [ file=x-xfdf, +%D version=2011.09.07, +%D title=\CONTEXT\ XML Modules, +%D subtitle=\XFDF, +%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 a revival of using \XFDF, but now in a more \MKIV-ish way. We +%D supported it long ago already in \MKII\ but never used it at a large +%D scale (not that much user interest anyway). + +\startmodule[xfdf] + +% see xfdf-001.xfdf and xfdf-001.tex + +% %D Possible speedup but hardly worth the trouble. +% +% \startluacode +% +% local hashes = { } table.setmetatableindex(hashes,function(t,k) local v = { } t[k] = v return v end) +% +% function xml.functions.xfdf_collect_values(root) +% local hash = hashes[root] +% for c in xml.collected(root,"/xfdf/fields/field/value") do +% hash[xml.parent(c).at.name] = c +% end +% end +% +% function xml.functions.xfdf_get_values(root,name) +% return hashes[root][name] +% end +% +% function lxml.xfdf_get_values(root,name) +% xml.sprint(hashes[lxml.id(root)][name]) +% end +% +% \stopluacode +% +% \def\xfdfvalue#1#2% +% {\ctxlua{lxml.xfdf_get_values("#1","#2")}} + +\startxmlsetups xfdf:define + \xmlsetsetup{#1}{*}{xfdf:*} + % \xmlfilter {#1}{./function(xfdf_collect_values)} +\stopxmlsetups + +\xmlregisterns{xfdf}{http://ns.adobe.com/xfdf/} + +\xmlregisterdocumentsetup{xfdf}{xfdf:define} + +\startxmlsetups xfdf:value + \xmlflush{#1} +\stopxmlsetups + +\def\xfdfload #1#2{\xmlloadonly{#1}{#2}{xfdf}} +\def\xfdfvalue#1#2{\xmlfirst{#1}{/xfdf/fields/field[@name='#2']/value}} +\def\xfdftext #1#2{\xmlfirst{#1}{/xfdf/fields/field[@name='#2']/value/paragraphs()}} + +% \startxmlsetups xfdf:b +% \bold{\xmlflush{#1}} +% \stopxmlsetups + +% \xfdfload {whatever}{xfdf-001.xfdf} +% \xfdfvalue{whatever}{somefield} + +\stopmodule diff --git a/tex/context/base/xtag-ini.mkii b/tex/context/base/xtag-ini.mkii index 8f10c4f55..ce3cbacd0 100644 --- a/tex/context/base/xtag-ini.mkii +++ b/tex/context/base/xtag-ini.mkii @@ -395,22 +395,22 @@ % \def\disableXML % {\setnormalcatcodes\processingXMLfalse} -\defcatcodecommand\xmlcatcodese `\& \doXMLentity -\defcatcodecommand\xmlcatcodese `\< \doXMLelement -\defcatcodecommand\xmlcatcodesr `\& \doXMLentity -\defcatcodecommand\xmlcatcodesr `\< \doXMLelement -\defcatcodecommand\xmlcatcodesn `\& \doXMLentity -\defcatcodecommand\xmlcatcodesn `\< \doXMLelement - -\letcatcodecommand\xmlcatcodesr `\# \letterhash -\letcatcodecommand\xmlcatcodesr `\$ \letterdollar -\letcatcodecommand\xmlcatcodesr `\% \letterpercent -\letcatcodecommand\xmlcatcodesr `\\ \letterbackslash -\letcatcodecommand\xmlcatcodesr `\^ \letterhat -\letcatcodecommand\xmlcatcodesr `\_ \letterunderscore -\letcatcodecommand\xmlcatcodesr `\{ \letterleftbrace -\letcatcodecommand\xmlcatcodesr `\} \letterrightbrace -\letcatcodecommand\xmlcatcodesr `\| \letterbar +\defcatcodecommand\xmlcatcodese 046 \doXMLentity +\defcatcodecommand\xmlcatcodese 060 \doXMLelement +\defcatcodecommand\xmlcatcodesr 046 \doXMLentity +\defcatcodecommand\xmlcatcodesr 060 \doXMLelement +\defcatcodecommand\xmlcatcodesn 046 \doXMLentity +\defcatcodecommand\xmlcatcodesn 060 \doXMLelement + +\letcatcodecommand\xmlcatcodesr 035 \letterhash +\letcatcodecommand\xmlcatcodesr 036 \letterdollar +\letcatcodecommand\xmlcatcodesr 037 \letterpercent +\letcatcodecommand\xmlcatcodesr 092 \letterbackslash +\letcatcodecommand\xmlcatcodesr 094 \letterhat +\letcatcodecommand\xmlcatcodesr 095 \letterunderscore +\letcatcodecommand\xmlcatcodesr 123 \letterleftbrace +\letcatcodecommand\xmlcatcodesr 125 \letterrightbrace +\letcatcodecommand\xmlcatcodesr 124 \letterbar \bgroup \catcode`\&=13 \let&\relax @@ -426,15 +426,15 @@ \egroup -\letcatcodecommand\xmlcatcodese `\# \entityhash -\letcatcodecommand\xmlcatcodese `\$ \entitydollar -\letcatcodecommand\xmlcatcodese `\% \entitypercent -\letcatcodecommand\xmlcatcodese `\\ \entitybackslash -\letcatcodecommand\xmlcatcodese `\^ \entityhat -\letcatcodecommand\xmlcatcodese `\_ \entityunderscore -\letcatcodecommand\xmlcatcodese `\{ \entityleftbrace -\letcatcodecommand\xmlcatcodese `\} \entityrightbrace -\letcatcodecommand\xmlcatcodese `\| \entitybar +\letcatcodecommand\xmlcatcodese 035 \entityhash +\letcatcodecommand\xmlcatcodese 036 \entitydollar +\letcatcodecommand\xmlcatcodese 037 \entitypercent +\letcatcodecommand\xmlcatcodese 092 \entitybackslash +\letcatcodecommand\xmlcatcodese 094 \entityhat +\letcatcodecommand\xmlcatcodese 095 \entityunderscore +\letcatcodecommand\xmlcatcodese 123 \entityleftbrace +\letcatcodecommand\xmlcatcodese 125 \entityrightbrace +\letcatcodecommand\xmlcatcodese 124 \entitybar % we speed things up by explicitly setting the active char's < & diff --git a/tex/context/base/xtag-pre.mkii b/tex/context/base/xtag-pre.mkii index 63706d64c..5e75197b7 100644 --- a/tex/context/base/xtag-pre.mkii +++ b/tex/context/base/xtag-pre.mkii @@ -18,6 +18,19 @@ \unprotect +%D For \MKIV: + +\setvalue{@u@s@"}#1#2"{#2} \setvalue{@g@s@"}#1#2"{\scratchtoks{#2}} +\setvalue{@u@s@'}#1#2'{#2} \setvalue{@g@s@'}#1#2'{\scratchtoks{#2}} +\setvalue{@u@s@ }#1#2 {#2} \setvalue{@g@s@ }#1#2 {\scratchtoks{#2}} + +\def\unstringed#1{\csname\ifcsname @u@s@#1\endcsname @u@s@#1\else\s!empty\fi\endcsname#1} +\def\grabstring#1{\csname\ifcsname @g@s@#1\endcsname @g@s@#1\else\s!empty\fi\endcsname#1} + +\def\dowithgrabbedstring#1% + {\def\@@dowithgrabbedstring{#1}% + \afterassignment\@@dowithgrabbedstring\grabstring} + %D Let's get rid of ligatures: % \definefonthandling [default] [noligs] diff --git a/tex/context/fonts/demo.lfg b/tex/context/fonts/demo.lfg index 00ca3ee6e..06c59e644 100644 --- a/tex/context/fonts/demo.lfg +++ b/tex/context/fonts/demo.lfg @@ -30,11 +30,36 @@ return { comment = "An example of goodies.", author = "Hans Hagen", featuresets = { + simple = { + mode = "node", + script = "latn" + }, default = { - default, + mode = "node", + script = "latn", + kern = "yes", + }, + ligatures = { + mode = "node", + script = "latn", + kern = "yes", + liga = "yes", }, smallcaps = { - default, smallcaps, + mode = "node", + script = "latn", + kern = "yes", + smcp = "yes", + }, + }, + solutions = { -- here we have references to featuresets, so we use strings! + experimental = { + less = { + "ligatures", "simple", + }, + more = { + "smallcaps", + }, }, }, colorschemes = { diff --git a/tex/context/fonts/husayni.lfg b/tex/context/fonts/husayni.lfg index ff456f63c..2f45add21 100644 --- a/tex/context/fonts/husayni.lfg +++ b/tex/context/fonts/husayni.lfg @@ -17,6 +17,7 @@ local regular = { ss01 = yes, ss03 = yes, ss07 = yes, ss10 = yes, ss12 = yes, ss15 = yes, ss16 = yes, ss19 = yes, ss24 = yes, ss25 = yes, ss26 = yes, ss27 = yes, ss31 = yes, ss34 = yes, ss35 = yes, ss36 = yes, ss37 = yes, ss38 = yes, ss41 = yes, ss42 = yes, ss43 = yes, + ss55 = yes, js16 = yes, } @@ -31,6 +32,7 @@ local minimal_stretching = { local medium_stretching = { js12=yes, js05=yes, } + local maximal_stretching= { js13 = yes, js05 = yes, js09 = yes, } @@ -43,7 +45,7 @@ local shrink = { flts = yes, js17 = yes, ss05 = yes, ss11 = yes, ss06 = yes, ss09 = yes, } -local default = { +local default = { -- we need to merge the typescript definition in here basics, analysis, regular, positioning, -- xxxx = yes, yyyy = 2, } @@ -75,7 +77,7 @@ return { solutions = { -- here we have references to featuresets, so we use strings! experimental = { less = { - "shrink" + "shrink", -- we need an extra one }, more = { "minimal_stretching", "medium_stretching", "maximal_stretching", "wide_all" diff --git a/tex/context/interface/keys-cs.xml b/tex/context/interface/keys-cs.xml index cd95319e0..0fe7f4b4d 100644 --- a/tex/context/interface/keys-cs.xml +++ b/tex/context/interface/keys-cs.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='vycet'/> <cd:variable name='environment' value='prostredi'/> <cd:variable name='even' value='sude'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='externi'/> <cd:variable name='fact' value='fakt'/> <cd:variable name='february' value='unor'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='podvpred'/> <cd:variable name='subject' value='tema'/> <cd:variable name='subpage' value='podstranka'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='podsekce'/> <cd:variable name='subsubject' value='podtema'/> <cd:variable name='subsubsection' value='podpodsekce'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='prvnistranka'/> <cd:constant name='focus' value='zaostreni'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='popisek'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='poslednistrana'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='vlevo'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='podvetavlevo'/> <cd:constant name='lefttext' value='textvlevo'/> <cd:constant name='leftwidth' value='sirkavlevo'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='uroven'/> <cd:constant name='levels' value='urovne'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='minvyska'/> <cd:constant name='minwidth' value='minsirka'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='jmeno'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='oddelovac'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='pocitat'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='znak'/> <cd:constant name='size' value='velikost'/> <cd:constant name='small' value='male'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='zdroj'/> diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml index a28d23bcf..c14f7c526 100644 --- a/tex/context/interface/keys-de.xml +++ b/tex/context/interface/keys-de.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='nummerierung'/> <cd:variable name='environment' value='umgebung'/> <cd:variable name='even' value='gerade'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='extern'/> <cd:variable name='fact' value='gegeben'/> <cd:variable name='february' value='februar'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='untervorwaerts'/> <cd:variable name='subject' value='thema'/> <cd:variable name='subpage' value='unterseite'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='unterabsatz'/> <cd:variable name='subsubject' value='unterthema'/> <cd:variable name='subsubsection' value='unterunterabsatz'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='ersteseite'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='label'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='letzteseite'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='links'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='linkersubsatz'/> <cd:constant name='lefttext' value='linkertext'/> <cd:constant name='leftwidth' value='linkerbreite'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='niveau'/> <cd:constant name='levels' value='niveaus'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='minhoehe'/> <cd:constant name='minwidth' value='minbreite'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='name'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='seperator'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='objektabstand'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='zeichen'/> <cd:constant name='size' value='groesse'/> <cd:constant name='small' value='klein'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='quelle'/> diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml index 80ff3c2e1..d981143b0 100644 --- a/tex/context/interface/keys-en.xml +++ b/tex/context/interface/keys-en.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='enumeration'/> <cd:variable name='environment' value='environment'/> <cd:variable name='even' value='even'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='external'/> <cd:variable name='fact' value='fact'/> <cd:variable name='february' value='february'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='subforward'/> <cd:variable name='subject' value='subject'/> <cd:variable name='subpage' value='subpage'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='subsection'/> <cd:variable name='subsubject' value='subsubject'/> <cd:variable name='subsubsection' value='subsubsection'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='firstpage'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='label'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='lastpage'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='left'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='leftsubsentence'/> <cd:constant name='lefttext' value='lefttext'/> <cd:constant name='leftwidth' value='leftwidth'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='level'/> <cd:constant name='levels' value='levels'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='minheight'/> <cd:constant name='minwidth' value='minwidth'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='name'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='separator'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='side'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='sign'/> <cd:constant name='size' value='size'/> <cd:constant name='small' value='small'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='source'/> diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml index d97bf932a..3d25240bf 100644 --- a/tex/context/interface/keys-fr.xml +++ b/tex/context/interface/keys-fr.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='enumeration'/> <cd:variable name='environment' value='environement'/> <cd:variable name='even' value='paire'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='external'/> <cd:variable name='fact' value='fait'/> <cd:variable name='february' value='fevrier'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='sousavance'/> <cd:variable name='subject' value='sujet'/> <cd:variable name='subpage' value='souspage'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='soussection'/> <cd:variable name='subsubject' value='soussujet'/> <cd:variable name='subsubsection' value='soussoussection'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='premierepage'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='etiquette'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='dernierepage'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='gauche'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='sousphrasegauche'/> <cd:constant name='lefttext' value='textegauche'/> <cd:constant name='leftwidth' value='largeurgauche'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='niveau'/> <cd:constant name='levels' value='niveaux'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='hauteurmin'/> <cd:constant name='minwidth' value='largeurmin'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='nom'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='separateur'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='reglages'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='cote'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='signe'/> <cd:constant name='size' value='dimension'/> <cd:constant name='small' value='petit'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='origine'/> diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml index a03a88ba3..cc08f1e3e 100644 --- a/tex/context/interface/keys-it.xml +++ b/tex/context/interface/keys-it.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='enumerazione'/> <cd:variable name='environment' value='ambiente'/> <cd:variable name='even' value='pari'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='esterno'/> <cd:variable name='fact' value='fatto'/> <cd:variable name='february' value='febbraio'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='sottoavanti'/> <cd:variable name='subject' value='argomento'/> <cd:variable name='subpage' value='sottopagina'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='sottocapoverso'/> <cd:variable name='subsubject' value='sottoargomento'/> <cd:variable name='subsubsection' value='sottosottocapoverso'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='primapagina'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='etichetta'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='ultimapagina'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='sinistra'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='sottofrasesinistra'/> <cd:constant name='lefttext' value='testosinistro'/> <cd:constant name='leftwidth' value='ampiezzasinistra'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='livello'/> <cd:constant name='levels' value='livelli'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='altezzamin'/> <cd:constant name='minwidth' value='ampiezzamin'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='nome'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='separatore'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='lato'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='segno'/> <cd:constant name='size' value='dimensione'/> <cd:constant name='small' value='piccolo'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='origine'/> diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml index 2c9113c39..039d6e882 100644 --- a/tex/context/interface/keys-nl.xml +++ b/tex/context/interface/keys-nl.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='doornummering'/> <cd:variable name='environment' value='omgeving'/> <cd:variable name='even' value='even'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='extern'/> <cd:variable name='fact' value='gegeven'/> <cd:variable name='february' value='februari'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='subvooruit'/> <cd:variable name='subject' value='onderwerp'/> <cd:variable name='subpage' value='subpagina'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='subparagraaf'/> <cd:variable name='subsubject' value='subonderwerp'/> <cd:variable name='subsubsection' value='subsubparagraaf'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='eerstepagina'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusuit'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='label'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='laatstepagina'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='links'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='linkersubzin'/> <cd:constant name='lefttext' value='linkertekst'/> <cd:constant name='leftwidth' value='linkerbreedte'/> + <cd:constant name='less' value='minder'/> <cd:constant name='level' value='niveau'/> <cd:constant name='levels' value='niveaus'/> <cd:constant name='limittext' value='limiettekst'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='minhoogte'/> <cd:constant name='minwidth' value='minbreedte'/> <cd:constant name='monthconversion' value='maandconversie'/> + <cd:constant name='more' value='meer'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='naam'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='scheider'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='krimp'/> <cd:constant name='side' value='zij'/> <cd:constant name='sidealign' value='zijuitlijnen'/> <cd:constant name='sidemethod' value='zijmethode'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='teken'/> <cd:constant name='size' value='formaat'/> <cd:constant name='small' value='klein'/> + <cd:constant name='solution' value='oplossing'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sortering'/> <cd:constant name='source' value='bron'/> diff --git a/tex/context/interface/keys-pe.xml b/tex/context/interface/keys-pe.xml index 5f48acdd0..6615a3488 100644 --- a/tex/context/interface/keys-pe.xml +++ b/tex/context/interface/keys-pe.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='شمارهبندی'/> <cd:variable name='environment' value='محیط'/> <cd:variable name='even' value='زوج'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='خارجی'/> <cd:variable name='fact' value='fact'/> <cd:variable name='february' value='فوریه'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='زیرجلوگرد'/> <cd:variable name='subject' value='موضوع'/> <cd:variable name='subpage' value='زیرصفحه'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='زیربخش'/> <cd:variable name='subsubject' value='زیرموضوع'/> <cd:variable name='subsubsection' value='زیرزیربخش'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='صفحهاول'/> <cd:constant name='focus' value='تمرکز'/> <cd:constant name='focusin' value='تمرکزدرون'/> <cd:constant name='focusout' value='تمرکزبیرون'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='برچسب'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='صفحهآخر'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='چپ'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='زیرجملهچپ'/> <cd:constant name='lefttext' value='متنچپ'/> <cd:constant name='leftwidth' value='عرضخط'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='مرحله'/> <cd:constant name='levels' value='مرحلهها'/> <cd:constant name='limittext' value='مرزمتن'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='کمترینارتفاع'/> <cd:constant name='minwidth' value='کمترینعرض'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='نام'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='جداکننده'/> <cd:constant name='set' value='قراربده'/> <cd:constant name='setups' value='بارگذاریها'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='کنار'/> <cd:constant name='sidealign' value='تنظیمکنار'/> <cd:constant name='sidemethod' value='روشکنار'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='علامت'/> <cd:constant name='size' value='اندازه'/> <cd:constant name='small' value='کوچک'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='ترتیبتایپ'/> <cd:constant name='source' value='منبع'/> diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml index 22ccf09c0..fb827945e 100644 --- a/tex/context/interface/keys-ro.xml +++ b/tex/context/interface/keys-ro.xml @@ -160,6 +160,7 @@ <cd:variable name='enumeration' value='enumerare'/> <cd:variable name='environment' value='mediu'/> <cd:variable name='even' value='par'/> + <cd:variable name='export' value='export'/> <cd:variable name='external' value='extern'/> <cd:variable name='fact' value='fapt'/> <cd:variable name='february' value='februarie'/> @@ -458,6 +459,7 @@ <cd:variable name='subforward' value='subavans'/> <cd:variable name='subject' value='subiect'/> <cd:variable name='subpage' value='subpagina'/> + <cd:variable name='subs' value='subs'/> <cd:variable name='subsection' value='subsectiune'/> <cd:variable name='subsubject' value='subsubiect'/> <cd:variable name='subsubsection' value='subsubsectiune'/> @@ -690,6 +692,7 @@ <cd:constant name='filtercommand' value='filtercommand'/> <cd:constant name='finalnamesep' value='finalnamesep'/> <cd:constant name='firstnamesep' value='firstnamesep'/> + <cd:constant name='firstpage' value='primapagina'/> <cd:constant name='focus' value='focus'/> <cd:constant name='focusin' value='focusin'/> <cd:constant name='focusout' value='focusout'/> @@ -756,6 +759,7 @@ <cd:constant name='label' value='eticheta'/> <cd:constant name='labeloffset' value='labeloffset'/> <cd:constant name='lastnamesep' value='lastnamesep'/> + <cd:constant name='lastpage' value='ultimapagina'/> <cd:constant name='lastpubsep' value='lastpubsep'/> <cd:constant name='layout' value='layout'/> <cd:constant name='left' value='stanga'/> @@ -776,6 +780,7 @@ <cd:constant name='leftsubsentence' value='subpropozitiestanga'/> <cd:constant name='lefttext' value='textstanga'/> <cd:constant name='leftwidth' value='latimestanga'/> + <cd:constant name='less' value='less'/> <cd:constant name='level' value='nivel'/> <cd:constant name='levels' value='nivele'/> <cd:constant name='limittext' value='limittext'/> @@ -814,6 +819,7 @@ <cd:constant name='minheight' value='inaltimeminima'/> <cd:constant name='minwidth' value='latimeminima'/> <cd:constant name='monthconversion' value='monthconversion'/> + <cd:constant name='more' value='more'/> <cd:constant name='n' value='n'/> <cd:constant name='name' value='nume'/> <cd:constant name='namesep' value='namesep'/> @@ -968,6 +974,7 @@ <cd:constant name='separator' value='separator'/> <cd:constant name='set' value='set'/> <cd:constant name='setups' value='setups'/> + <cd:constant name='shrink' value='shrink'/> <cd:constant name='side' value='parte'/> <cd:constant name='sidealign' value='sidealign'/> <cd:constant name='sidemethod' value='sidemethod'/> @@ -976,6 +983,7 @@ <cd:constant name='sign' value='semn'/> <cd:constant name='size' value='dimensiune'/> <cd:constant name='small' value='mic'/> + <cd:constant name='solution' value='solution'/> <cd:constant name='sort' value='sort'/> <cd:constant name='sorttype' value='sorttype'/> <cd:constant name='source' value='sursa'/> diff --git a/tex/context/sample/lorem.tex b/tex/context/sample/lorem.tex new file mode 100644 index 000000000..0132f659f --- /dev/null +++ b/tex/context/sample/lorem.tex @@ -0,0 +1,11 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur massa turpis, +semper quis fringilla ut, viverra nec risus. Pellentesque habitant morbi +tristique senectus et netus et malesuada fames ac turpis egestas. Donec nunc +lorem, sollicitudin vel sodales eget, vehicula nec mi. Proin ullamcorper rutrum +nibh, at porttitor nunc euismod et. Donec faucibus nisi faucibus ipsum porttitor +pharetra. Sed elementum, lectus nec congue imperdiet, ipsum leo viverra nisi, sit +amet commodo odio odio id nisl. Fusce sagittis lobortis nisi sed consectetur. Nam +egestas, sem ut fermentum convallis, ipsum tellus venenatis augue, eget +condimentum risus quam id erat. Sed metus dui, sollicitudin pharetra pellentesque +sed, placerat eget augue. Mauris sodales pretium tortor vitae rutrum. Proin quam +sem, lobortis tincidunt pretium vitae, feugiat eu lacus. diff --git a/tex/context/test/pdf-x1a-2001.mkiv b/tex/context/test/pdf-x1a-2001.mkiv index a304c8963..f1c5ef531 100644 --- a/tex/context/test/pdf-x1a-2001.mkiv +++ b/tex/context/test/pdf-x1a-2001.mkiv @@ -1,6 +1,6 @@ % PDF/X-1a:2001 -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-1a:2001, diff --git a/tex/context/test/pdf-x1a-2003.mkiv b/tex/context/test/pdf-x1a-2003.mkiv index 89a0f6066..7fbec5acb 100644 --- a/tex/context/test/pdf-x1a-2003.mkiv +++ b/tex/context/test/pdf-x1a-2003.mkiv @@ -1,6 +1,6 @@ % PDF/X-1a:2003 -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-1a:2003, diff --git a/tex/context/test/pdf-x3-2002.mkiv b/tex/context/test/pdf-x3-2002.mkiv index 1e2310135..be757212e 100644 --- a/tex/context/test/pdf-x3-2002.mkiv +++ b/tex/context/test/pdf-x3-2002.mkiv @@ -1,6 +1,6 @@ % PDF/X-3:2002 -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-3:2002, diff --git a/tex/context/test/pdf-x3-2003.mkiv b/tex/context/test/pdf-x3-2003.mkiv index bedcde527..cbebe1033 100644 --- a/tex/context/test/pdf-x3-2003.mkiv +++ b/tex/context/test/pdf-x3-2003.mkiv @@ -1,6 +1,6 @@ % PDF/X-3:2003 -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-3:2003, diff --git a/tex/context/test/pdf-x4.mkiv b/tex/context/test/pdf-x4.mkiv index 0566475b5..062de3b34 100644 --- a/tex/context/test/pdf-x4.mkiv +++ b/tex/context/test/pdf-x4.mkiv @@ -2,7 +2,7 @@ % \nopdfcompression -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-4, diff --git a/tex/context/test/pdf-x4p.mkiv b/tex/context/test/pdf-x4p.mkiv index 9ec8897f8..bfee0b238 100644 --- a/tex/context/test/pdf-x4p.mkiv +++ b/tex/context/test/pdf-x4p.mkiv @@ -1,10 +1,10 @@ % PDF/X-4p -\enabletrackers[backend.pdfx] +\enabletrackers[backend.format,backend.variables] \setupbackend [format=PDF/X-4p, - intent=ISOcoated_v2_eci.icc, + intent={ISO Coated v2 (ECI)}, profile=sRGB.icc] % test for default colorspace \input pdf-x-common.mkiv diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua index bdbc3cf51..2f03efba8 100644 --- a/tex/generic/context/luatex/luatex-basics-gen.lua +++ b/tex/generic/context/luatex/luatex-basics-gen.lua @@ -87,7 +87,7 @@ local remapper = { function resolvers.findfile(name,fileformat) name = string.gsub(name,"\\","\/") fileformat = fileformat and string.lower(fileformat) - local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.extname(name,"tex")) + local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.suffix(name,"tex")) if not found or found == "" then found = kpse.find_file(name,"other text files") end @@ -96,7 +96,7 @@ end function resolvers.findbinfile(name,fileformat) if not fileformat or fileformat == "" then - fileformat = file.extname(name) -- string.match(name,"%.([^%.]-)$") + fileformat = file.suffix(name) -- string.match(name,"%.([^%.]-)$") end return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat) end diff --git a/tex/generic/context/luatex/luatex-fonts-ext.lua b/tex/generic/context/luatex/luatex-fonts-ext.lua index d8884ccc7..b60d04512 100644 --- a/tex/generic/context/luatex/luatex-fonts-ext.lua +++ b/tex/generic/context/luatex/luatex-fonts-ext.lua @@ -18,18 +18,14 @@ local otffeatures = fonts.constructors.newfeatures("otf") local function initializeitlc(tfmdata,value) if value then - -- the magic 40 and it formula come from Dohyun Kim - local parameters = tfmdata.parameters + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess + local parameters = tfmdata.parameters local italicangle = parameters.italicangle if italicangle and italicangle ~= 0 then - local uwidth = (parameters.uwidth or 40)/2 - for unicode, d in next, tfmdata.descriptions do - local it = d.boundingbox[3] - d.width + uwidth - if it ~= 0 then - d.italic = it - end - end - tfmdata.properties.hasitalics = true + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 end end end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index ea509c338..777defd88 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 05/30/12 11:26:34 +-- merge date : 10/19/12 00:06:05 do -- begin closure to overcome local limits and interference @@ -118,11 +118,28 @@ function string.topattern(str,lowercase,strict) end end + +function string.valid(str,default) + return (type(str) == "string" and str ~= "" and str) or default or nil +end + -- obsolete names: string.quote = string.quoted string.unquote = string.unquoted +-- handy fallback + +string.itself = function(s) return s end + +-- also handy (see utf variant) + +local pattern = Ct(C(1)^0) + +function string.totable(str) + return lpegmatch(pattern,str) +end + end -- closure do -- begin closure to overcome local limits and interference @@ -135,7 +152,8 @@ if not modules then modules = { } end modules ['l-table'] = { license = "see context related readme files" } -local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string +local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs +local table, string = table, string local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match local getmetatable, setmetatable = getmetatable, setmetatable @@ -146,6 +164,8 @@ local getinfo = debug.getinfo -- impact on ConTeXt was not that large; the remaining ipairs already -- have been replaced. In a similar fashion we also hardly used pairs. -- +-- Hm, actually ipairs was retained, but we no longer use it anyway. +-- -- Just in case, we provide the fallbacks as discussed in Programming -- in Lua (http://www.lua.org/pil/7.3.html): @@ -205,12 +225,16 @@ function table.strip(tab) end function table.keys(t) - local keys, k = { }, 0 - for key, _ in next, t do - k = k + 1 - keys[k] = key + if t then + local keys, k = { }, 0 + for key, _ in next, t do + k = k + 1 + keys[k] = key + end + return keys + else + return { } end - return keys end local function compare(a,b) @@ -223,41 +247,49 @@ local function compare(a,b) end local function sortedkeys(tab) - local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed - for key,_ in next, tab do - s = s + 1 - srt[s] = key - if category == 3 then - -- no further check - else - local tkey = type(key) - if tkey == "string" then - category = (category == 2 and 3) or 1 - elseif tkey == "number" then - category = (category == 1 and 3) or 2 + if tab then + local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed + for key,_ in next, tab do + s = s + 1 + srt[s] = key + if category == 3 then + -- no further check else - category = 3 + local tkey = type(key) + if tkey == "string" then + category = (category == 2 and 3) or 1 + elseif tkey == "number" then + category = (category == 1 and 3) or 2 + else + category = 3 + end end end - end - if category == 0 or category == 3 then - sort(srt,compare) + if category == 0 or category == 3 then + sort(srt,compare) + else + sort(srt) + end + return srt else - sort(srt) + return { } end - return srt end local function sortedhashkeys(tab) -- fast one - local srt, s = { }, 0 - for key,_ in next, tab do - if key then - s= s + 1 - srt[s] = key + if tab then + local srt, s = { }, 0 + for key,_ in next, tab do + if key then + s= s + 1 + srt[s] = key + end end + sort(srt) + return srt + else + return { } end - sort(srt) - return srt end table.sortedkeys = sortedkeys @@ -282,7 +314,7 @@ end table.sortedhash = sortedhash table.sortedpairs = sortedhash -function table.append(t, list) +function table.append(t,list) local n = #t for i=1,#list do n = n + 1 @@ -517,12 +549,26 @@ local function do_serialize(root,name,depth,level,indexed) end -- we could check for k (index) being number (cardinal) if root and next(root) then - local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) + -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) + -- if compact then + -- -- NOT: for k=1,#root do (we need to quit at nil) + -- for k,v in ipairs(root) do -- can we use next? + -- if not first then first = k end + -- last = last + 1 + -- end + -- end + local first, last = nil, 0 if compact then - -- NOT: for k=1,#root do (we need to quit at nil) - for k,v in ipairs(root) do -- can we use next? - if not first then first = k end - last = last + 1 + last = #root + for k=1,last do +-- if not root[k] then + if root[k] == nil then + last = k - 1 + break + end + end + if last > 0 then + first = 1 end end local sk = sortedkeys(root) @@ -1014,23 +1060,27 @@ function table.reversed(t) end end -function table.sequenced(t,sep,simple) -- hash only - local s, n = { }, 0 - for k, v in sortedhash(t) do - if simple then - if v == true then - n = n + 1 - s[n] = k - elseif v and v~= "" then +function table.sequenced(t,sep) -- hash only + if t then + local s, n = { }, 0 + for k, v in sortedhash(t) do + if simple then + if v == true then + n = n + 1 + s[n] = k + elseif v and v~= "" then + n = n + 1 + s[n] = k .. "=" .. tostring(v) + end + else n = n + 1 s[n] = k .. "=" .. tostring(v) end - else - n = n + 1 - s[n] = k .. "=" .. tostring(v) end + return concat(s, sep or " | ") + else + return "" end - return concat(s, sep or " | ") end function table.print(t,...) @@ -1110,6 +1160,8 @@ local lpeg = require("lpeg") -- tracing (only used when we encounter a problem in integration of lpeg in luatex) +-- some code will move to unicode and string + local report = texio and texio.write_nl or print -- local lpmatch = lpeg.match @@ -1146,8 +1198,8 @@ local report = texio and texio.write_nl or print -- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end -- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end -local type = type -local byte, char, gmatch = string.byte, string.char, string.gmatch +local type, next = type, next +local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format -- Beware, we predefine a bunch of patterns here and one reason for doing so -- is that we get consistent behaviour in some of the visualizers. @@ -1155,9 +1207,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch lpeg.patterns = lpeg.patterns or { } -- so that we can share local patterns = lpeg.patterns -local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match -local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc -local lpegtype = lpeg.type +local P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp +local lpegtype, lpegmatch = lpeg.type, lpeg.match local utfcharacters = string.utfcharacters local utfgmatch = unicode and unicode.utf8.gmatch @@ -1208,6 +1259,10 @@ patterns.utf8char = utf8char patterns.validutf8 = validutf8char patterns.validutf8char = validutf8char +local eol = S("\n\r") +local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) +local whitespace = eol + spacer + patterns.digit = digit patterns.sign = sign patterns.cardinal = sign^0 * digit^1 @@ -1227,16 +1282,16 @@ patterns.letter = patterns.lowercase + patterns.uppercase patterns.space = space patterns.tab = P("\t") patterns.spaceortab = patterns.space + patterns.tab -patterns.eol = S("\n\r") -patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto) +patterns.eol = eol +patterns.spacer = spacer +patterns.whitespace = whitespace patterns.newline = newline patterns.emptyline = newline^1 -patterns.nonspacer = 1 - patterns.spacer -patterns.whitespace = patterns.eol + patterns.spacer -patterns.nonwhitespace = 1 - patterns.whitespace +patterns.nonspacer = 1 - spacer +patterns.nonwhitespace = 1 - whitespace patterns.equal = P("=") patterns.comma = P(",") -patterns.commaspacer = P(",") * patterns.spacer^0 +patterns.commaspacer = P(",") * spacer^0 patterns.period = P(".") patterns.colon = P(":") patterns.semicolon = P(";") @@ -1251,6 +1306,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"") patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble patterns.unspacer = ((patterns.spacer^1)/"")^0 +patterns.singlequoted = squote * patterns.nosquote * squote +patterns.doublequoted = dquote * patterns.nodquote * dquote +patterns.quoted = patterns.doublequoted + patterns.singlequoted + patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1 patterns.beginline = #(1-newline) @@ -1261,8 +1320,17 @@ patterns.beginline = #(1-newline) -- print(string.unquoted('"test"')) -- print(string.unquoted('"test"')) -function lpeg.anywhere(pattern) --slightly adapted from website - return P { P(pattern) + 1 * V(1) } -- why so complex? +local function anywhere(pattern) --slightly adapted from website + return P { P(pattern) + 1 * V(1) } +end + +lpeg.anywhere = anywhere + +function lpeg.instringchecker(p) + p = anywhere(p) + return function(str) + return lpegmatch(p,str) and true or false + end end function lpeg.splitter(pattern, action) @@ -1311,13 +1379,13 @@ function string.splitup(str,separator) if not separator then separator = "," end - return match(splitters_m[separator] or splitat(separator),str) + return lpegmatch(splitters_m[separator] or splitat(separator),str) end ---~ local p = splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more ---~ local p = splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more ---~ local p = splitat("->",false) print(match(p,"oeps")) -- oeps ---~ local p = splitat("->",true) print(match(p,"oeps")) -- oeps +--~ local p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more +--~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more +--~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps +--~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps local cache = { } @@ -1327,16 +1395,20 @@ function lpeg.split(separator,str) c = tsplitat(separator) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end function string.split(str,separator) - local c = cache[separator] - if not c then - c = tsplitat(separator) - cache[separator] = c + if separator then + local c = cache[separator] + if not c then + c = tsplitat(separator) + cache[separator] = c + end + return lpegmatch(c,str) + else + return { str } end - return match(c,str) end local spacing = patterns.spacer^0 * newline -- sort of strip @@ -1349,7 +1421,7 @@ patterns.textline = content --~ local linesplitter = Ct(content^0) --~ --~ function string.splitlines(str) ---~ return match(linesplitter,str) +--~ return lpegmatch(linesplitter,str) --~ end local linesplitter = tsplitat(newline) @@ -1357,7 +1429,7 @@ local linesplitter = tsplitat(newline) patterns.linesplitter = linesplitter function string.splitlines(str) - return match(linesplitter,str) + return lpegmatch(linesplitter,str) end local utflinesplitter = utfbom^-1 * tsplitat(newline) @@ -1365,7 +1437,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline) patterns.utflinesplitter = utflinesplitter function string.utfsplitlines(str) - return match(utflinesplitter,str or "") + return lpegmatch(utflinesplitter,str or "") +end + +local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0) +local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0) + +function string.utfsplit(str,ignorewhitespace) -- new + if ignorewhitespace then + return lpegmatch(utfcharsplitter_iws,str or "") + else + return lpegmatch(utfcharsplitter_ows,str or "") + end +end + +-- inspect(string.utfsplit("a b c d")) +-- inspect(string.utfsplit("a b c d",true)) + +-- -- alternative 1: 0.77 +-- +-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0) +-- +-- function string.utflength(str) +-- return #lpegmatch(utfcharcounter,str or "") +-- end +-- +-- -- alternative 2: 1.70 +-- +-- local n = 0 +-- +-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow +-- +-- function string.utflength(str) +-- n = 0 +-- lpegmatch(utfcharcounter,str or "") +-- return n +-- end +-- +-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047) + +local n = 0 + +local utfcharcounter = utfbom^-1 * Cs ( ( + Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end + + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end + + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end + + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end +)^0 ) + +function string.utflength(str) + n = 0 + lpegmatch(utfcharcounter,str or "") + return n end --~ lpeg.splitters = cache -- no longer public @@ -1380,7 +1503,7 @@ function lpeg.checkedsplit(separator,str) c = Ct(separator^0 * other * (separator^1 * other)^0) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end function string.checkedsplit(str,separator) @@ -1391,7 +1514,7 @@ function string.checkedsplit(str,separator) c = Ct(separator^0 * other * (separator^1 * other)^0) cache[separator] = c end - return match(c,str) + return lpegmatch(c,str) end --~ from roberto's site: @@ -1406,10 +1529,10 @@ patterns.utf8byte = utf8byte --~ local str = " a b c d " ---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.stripper("ab") print("["..lpeg.match(s,str).."]") ---~ local s = lpeg.keeper("ab") print("["..lpeg.match(s,str).."]") +--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]") +--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]") local cache = { } @@ -1442,11 +1565,11 @@ function lpeg.keeper(str) end function lpeg.frontstripper(str) -- or pattern (yet undocumented) - return (P(str) + P(true)) * Cs(P(1)^0) + return (P(str) + P(true)) * Cs(anything^0) end function lpeg.endstripper(str) -- or pattern (yet undocumented) - return Cs((1 - P(str) * P(-1))^0) + return Cs((1 - P(str) * endofstring)^0) end -- Just for fun I looked at the used bytecode and @@ -1455,8 +1578,22 @@ end function lpeg.replacer(one,two) if type(one) == "table" then local no = #one - if no > 0 then - local p + local p + if no == 0 then + for k, v in next, one do + local pp = P(k) / v + if p then + p = p + pp + else + p = pp + end + end + return Cs((p + 1)^0) + elseif no == 1 then + local o = one[1] + one, two = P(o[1]), o[2] + return Cs(((1-one)^1 + one/two)^0) + else for i=1,no do local o = one[i] local pp = P(o[1]) / o[2] @@ -1469,11 +1606,16 @@ function lpeg.replacer(one,two) return Cs((p + 1)^0) end else + one = P(one) two = two or "" - return Cs((P(one)/two + 1)^0) + return Cs(((1-one)^1 + one/two)^0) end end +-- print(lpeg.match(lpeg.replacer("e","a"),"test test")) +-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test")) +-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test")) + local splitters_f, splitters_s = { }, { } function lpeg.firstofsplit(separator) -- always return value @@ -1501,14 +1643,14 @@ function lpeg.balancer(left,right) return P { left * ((1 - left - right) + V(1))^0 * right } end ---~ print(1,match(lpeg.firstofsplit(":"),"bc:de")) ---~ print(2,match(lpeg.firstofsplit(":"),":de")) -- empty ---~ print(3,match(lpeg.firstofsplit(":"),"bc")) ---~ print(4,match(lpeg.secondofsplit(":"),"bc:de")) ---~ print(5,match(lpeg.secondofsplit(":"),"bc:")) -- empty ---~ print(6,match(lpeg.secondofsplit(":",""),"bc")) ---~ print(7,match(lpeg.secondofsplit(":"),"bc")) ---~ print(9,match(lpeg.secondofsplit(":","123"),"bc")) +--~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de")) +--~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty +--~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc")) +--~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de")) +--~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty +--~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc")) +--~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc")) +--~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc")) --~ -- slower: --~ @@ -1522,7 +1664,7 @@ local nany = utf8char/"" function lpeg.counter(pattern) pattern = Cs((P(pattern)/" " + nany)^0) return function(str) - return #match(pattern,str) + return #lpegmatch(pattern,str) end end @@ -1536,7 +1678,7 @@ if utfgmatch then end return n else -- 4 times slower but still faster than / function - return #match(Cs((P(what)/" " + nany)^0),str) + return #lpegmatch(Cs((P(what)/" " + nany)^0),str) end end @@ -1551,9 +1693,9 @@ else p = Cs((P(what)/" " + nany)^0) cache[p] = p end - return #match(p,str) + return #lpegmatch(p,str) else -- 4 times slower but still faster than / function - return #match(Cs((P(what)/" " + nany)^0),str) + return #lpegmatch(Cs((P(what)/" " + nany)^0),str) end end @@ -1580,7 +1722,7 @@ local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0) local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0) function string.escapedpattern(str,simple) - return match(simple and s or p,str) + return lpegmatch(simple and s or p,str) end -- utf extensies @@ -1627,7 +1769,7 @@ else p = P(uc) end end - match((utf8char/f)^0,str) + lpegmatch((utf8char/f)^0,str) return p end @@ -1643,7 +1785,7 @@ function lpeg.UR(str,more) first = str last = more or first else - first, last = match(range,str) + first, last = lpegmatch(range,str) if not last then return P(str) end @@ -1679,11 +1821,15 @@ end --~ print(lpeg.count("äáàa",lpeg.UR("àá"))) --~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF))) -function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") +function lpeg.is_lpeg(p) + return p and lpegtype(p) == "pattern" +end + +function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order if type(list) ~= "table" then list = { list, ... } end - -- sort(list) -- longest match first + -- table.sort(list) -- longest match first local p = P(list[1]) for l=2,#list do p = p + P(list[l]) @@ -1691,10 +1837,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") return p end -function lpeg.is_lpeg(p) - return p and lpegtype(p) == "pattern" -end - -- For the moment here, but it might move to utilities. Beware, we need to -- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we -- loop back from the end cq. prepend. @@ -1852,6 +1994,24 @@ end -- utfchar(0x205F), -- math thinspace -- } ) +-- handy from within tex: + +local lpegmatch = lpeg.match + +local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg! + +function string.tformat(fmt,...) + return format(lpegmatch(replacer,fmt),...) +end + +-- strips leading and trailing spaces and collapsed all other spaces + +local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0) + +function string.collapsespaces(str) + return lpegmatch(pattern,str) +end + end -- closure do -- begin closure to overcome local limits and interference @@ -1874,28 +2034,49 @@ function boolean.tonumber(b) end function toboolean(str,tolerant) - if tolerant then - local tstr = type(str) - if tstr == "string" then - return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t" - elseif tstr == "number" then - return tonumber(str) ~= 0 - elseif tstr == "nil" then - return false - else - return str - end + if str == nil then + return false + elseif str == false then + return false + elseif str == true then + return true elseif str == "true" then return true elseif str == "false" then return false + elseif not tolerant then + return false + elseif str == 0 then + return false + elseif (tonumber(str) or 0) > 0 then + return true else - return str + return str == "yes" or str == "on" or str == "t" end end string.toboolean = toboolean +function string.booleanstring(str) + if str == nil then + return false + elseif str == false then + return false + elseif str == true then + return true + elseif str == "true" then + return true + elseif str == "false" then + return false + elseif str == 0 then + return false + elseif (tonumber(str) or 0) > 0 then + return true + else + return str == "yes" or str == "on" or str == "t" + end +end + function string.is_boolean(str,default) if type(str) == "string" then if str == "true" or str == "yes" or str == "on" or str == "t" then @@ -1986,7 +2167,7 @@ local function nameonly(name) return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$","")) end -local function extname(name,default) +local function suffixonly(name,default) return match(name,"^.+%.([^/\\]-)$") or default or "" end @@ -1995,11 +2176,16 @@ local function splitname(name) return n or name, s or "" end -file.basename = basename -file.dirname = dirname -file.nameonly = nameonly -file.extname = extname -file.suffix = extname +file.basename = basename + +file.pathpart = dirname +file.dirname = dirname + +file.nameonly = nameonly + +file.suffixonly = suffixonly +file.extname = suffixonly -- obsolete +file.suffix = suffixonly function file.removesuffix(filename) return (gsub(filename,"%.[%a%d]+$","")) @@ -2145,6 +2331,11 @@ end file.isreadable = file.is_readable -- depricated file.iswritable = file.is_writable -- depricated +function file.size(name) + local a = attributes(name) + return a and a.size or 0 +end + -- todo: lpeg \\ / .. does not save much local checkedsplit = string.checkedsplit @@ -2275,7 +2466,7 @@ end --~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1 ---~ function file.extname(name) +--~ function file.suffixonly(name) --~ return lpegmatch(pattern,name) or "" --~ end @@ -2337,7 +2528,7 @@ end --~ end --~ end ---~ local test = file.extname +--~ local test = file.suffixonly --~ local test = file.basename --~ local test = file.dirname --~ local test = file.addsuffix @@ -2383,6 +2574,7 @@ local drive = C(R("az","AZ")) * P(":") local path = C(((1-slash)^0 * slash)^0) local suffix = period * C(P(1-period)^0 * P(-1)) local base = C((1-suffix)^0) +local rest = C(P(1)^0) drive = drive + Cc("") path = path + Cc("") @@ -2391,7 +2583,8 @@ suffix = suffix + Cc("") local pattern_a = drive * path * base * suffix local pattern_b = path * base * suffix -local pattern_c = C(drive * path) * C(base * suffix) +local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures +local pattern_d = path * rest function file.splitname(str,splitdrive) if splitdrive then @@ -2401,6 +2594,10 @@ function file.splitname(str,splitdrive) end end +function file.splitbase(str) + return lpegmatch(pattern_d,str) -- returns path, base+suffix +end + function file.nametotable(str,splitdrive) -- returns table local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str) if splitdrive then @@ -2422,6 +2619,8 @@ function file.nametotable(str,splitdrive) -- returns table end end +-- print(file.splitbase("a/b/c.txt")) + -- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end -- -- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" } @@ -2468,14 +2667,14 @@ else io.fileseparator, io.pathseparator = "/" , ":" end -function io.loaddata(filename,textmode) +function io.loaddata(filename,textmode) -- return nil if empty local f = io.open(filename,(textmode and 'r') or 'rb') if f then local data = f:read('*all') f:close() - return data - else - return nil + if #data > 0 then + return data + end end end @@ -2497,6 +2696,45 @@ function io.savedata(filename,data,joiner) end end +function io.loadlines(filename,n) -- return nil if empty + local f = io.open(filename,'r') + if f then + if n then + local lines = { } + for i=1,n do + local line = f:read("*lines") + if line then + lines[#lines+1] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = f:read("*line") or "" + assert(f:close()) + if #line > 0 then + return line + end + end + end +end + +function io.loadchunk(filename,n) + local f = io.open(filename,'rb') + if f then + local data = f:read(n or 1024) + f:close() + if #data > 0 then + return data + end + end +end + function io.exists(filename) local f = io.open(filename) if f == nil then @@ -2802,7 +3040,7 @@ local remapper = { function resolvers.findfile(name,fileformat) name = string.gsub(name,"\\","\/") fileformat = fileformat and string.lower(fileformat) - local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.extname(name,"tex")) + local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.suffix(name,"tex")) if not found or found == "" then found = kpse.find_file(name,"other text files") end @@ -2811,7 +3049,7 @@ end function resolvers.findbinfile(name,fileformat) if not fileformat or fileformat == "" then - fileformat = file.extname(name) -- string.match(name,"%.([^%.]-)$") + fileformat = file.suffix(name) -- string.match(name,"%.([^%.]-)$") end return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat) end @@ -3235,36 +3473,30 @@ if not modules then modules = { } end modules ['font-ini'] = { license = "see context related readme files" } --- basemethods -> can also be in list --- presetcontext -> defaults --- hashfeatures -> ctx version - --[[ldx-- <p>Not much is happening here.</p> --ldx]]-- -local lower = string.lower -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate local report_defining = logs.reporter("fonts","defining") -fontloader.totable = fontloader.to_table - -fonts = fonts or { } -- already defined in context +fonts = fonts or { } local fonts = fonts --- some of these might move to where they are used first: - fonts.hashes = { identifiers = allocate() } + +fonts.tables = fonts.tables or { } +fonts.helpers = fonts.helpers or { } +fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata +fonts.specifiers = fonts.specifiers or { } -- in format ! + fonts.analyzers = { } -- not needed here fonts.readers = { } -fonts.tables = { } fonts.definers = { methods = { } } -fonts.specifiers = fonts.specifiers or { } -- in format ! fonts.loggers = { register = function() end } -fonts.helpers = { } -fonts.tracers = { } -- for the moment till we have move to moduledata +fontloader.totable = fontloader.to_table end -- closure @@ -3301,9 +3533,9 @@ local report_defining = logs.reporter("fonts","defining") --ldx]]-- local fonts = fonts -local constructors = { } +local constructors = fonts.constructors or { } fonts.constructors = constructors -local handlers = { } +local handlers = fonts.handlers or { } -- can have preloaded tables fonts.handlers = handlers local specifiers = fonts.specifiers @@ -3630,6 +3862,10 @@ function constructors.scale(tfmdata,specification) elseif forcedsize > 1000 then -- safeguard scaledpoints = forcedsize end + targetparameters.mathsize = mathsize -- context specific + targetparameters.textsize = textsize -- context specific + targetparameters.forcedsize = forcedsize -- context specific + targetparameters.extrafactor = extrafactor -- context specific -- local tounicode = resources.tounicode local defaultwidth = resources.defaultwidth or 0 @@ -4341,7 +4577,7 @@ setmetatableindex(formats, function(t,k) t[k] = l return l end - return rawget(t,file.extname(l)) + return rawget(t,file.suffix(l)) end) local locations = { } @@ -4438,19 +4674,31 @@ function constructors.getfeatureaction(what,where,mode,name) end end -function constructors.newfeatures(what) - local features = handlers[what].features +function constructors.newhandler(what) -- could be a metatable newindex + local handler = handlers[what] + if not handler then + handler = { } + handlers[what] = handler + end + return handler +end + +function constructors.newfeatures(what) -- could be a metatable newindex + local handler = handlers[what] + local features = handler.features if not features then - local tables = handlers[what].tables -- can be preloaded + local tables = handler.tables -- can be preloaded + local statistics = handler.statistics -- can be preloaded features = allocate { defaults = { }, descriptions = tables and tables.features or { }, + used = statistics and statistics.usedfeatures or { }, initializers = { base = { }, node = { } }, processors = { base = { }, node = { } }, manipulators = { base = { }, node = { } }, } features.register = function(specification) return register(features,specification) end - handlers[what].features = features -- will also become hidden + handler.features = features -- will also become hidden end return features end @@ -4652,17 +4900,17 @@ local format, match, lower = string.format, string.match, string.lower local tonumber = tonumber local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match -local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) +local fonts, logs, trackers = fonts, logs, trackers -local report_otf = logs.reporter("fonts","otf loading") +local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) -local fonts = fonts +local report_otf = logs.reporter("fonts","otf loading") -local cid = { } -fonts.cid = cid +local cid = { } +fonts.cid = cid -local cidmap = { } -local cidmax = 10 +local cidmap = { } +local cidmax = 10 -- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap -- @@ -4721,8 +4969,7 @@ local function loadcidfile(filename) end end -cid.loadfile = loadcidfile -- we use the frozen variant - +cid.loadfile = loadcidfile -- we use the frozen variant local template = "%s-%s-%s.cidmap" local function locate(registry,ordering,supplement) @@ -4818,18 +5065,20 @@ if not modules then modules = { } end modules ['font-map'] = { license = "see context related readme files" } +local tonumber = tonumber + local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match local utfbyte = utf.byte -local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) +local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end) local report_fonts = logs.reporter("fonts","loading") -- not otf only -local fonts = fonts -local mappings = { } -fonts.mappings = mappings +local fonts = fonts +local mappings = fonts.mappings or { } +fonts.mappings = mappings --[[ldx-- <p>Eventually this code will disappear because map files are kind @@ -4852,7 +5101,7 @@ end local hex = R("AF","09") local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end local hexsix = (hex^1) / function(s) return tonumber(s,16) end -local dec = (R("09")^1) / tonumber +local dec = (R("09")^1) / tonumber local period = P(".") local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) @@ -5263,15 +5512,16 @@ if not modules then modules = { } end modules ['font-oti'] = { local lower = string.lower -local allocate = utilities.storage.allocate - local fonts = fonts -local otf = { } -fonts.handlers.otf = otf +local constructors = fonts.constructors -local otffeatures = fonts.constructors.newfeatures("otf") +local otf = constructors.newhandler("otf") +local otffeatures = constructors.newfeatures("otf") +local otftables = otf.tables local registerotffeature = otffeatures.register +local allocate = utilities.storage.allocate + registerotffeature { name = "features", description = "initialization of feature handler", @@ -5280,8 +5530,6 @@ registerotffeature { -- these are later hooked into node and base initializaters -local otftables = otf.tables -- not always defined - local function setmode(tfmdata,value) if value then tfmdata.properties.mode = lower(value) @@ -6466,7 +6714,7 @@ actions["prepare lookups"] = function(data,filename,raw) end -- The reverse handler does a bit redundant splitting but it's seldom --- seen so we don' tbother too much. We could store the replacement +-- seen so we don't bother too much. We could store the replacement -- in the current list (value instead of true) but it makes other code -- uglier. Maybe some day. @@ -6484,6 +6732,22 @@ local function t_uncover(splitter,cache,covers) return result end +local function s_uncover(splitter,cache,cover) + if cover == "" then + return nil + else + local uncovered = cache[cover] + if not uncovered then + uncovered = lpegmatch(splitter,cover) +-- for i=1,#uncovered do +-- uncovered[i] = { [uncovered[i]] = true } +-- end + cache[cover] = uncovered + end + return { uncovered } + end +end + local function t_hashed(t,cache) if t then local ht = { } @@ -6505,22 +6769,6 @@ local function t_hashed(t,cache) end end -local function s_uncover(splitter,cache,cover) - if cover == "" then - return nil - else - local uncovered = cache[cover] - if not uncovered then - uncovered = lpegmatch(splitter,cover) - for i=1,#uncovered do - uncovered[i] = { [uncovered[i]] = true } - end - cache[cover] = uncovered - end - return uncovered - end -end - local s_hashed = t_hashed local function r_uncover(splitter,cache,cover,replacements) @@ -6545,11 +6793,15 @@ local function r_uncover(splitter,cache,cover,replacements) end end -actions["reorganize lookups"] = function(data,filename,raw) +actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0 -- we prefer the before lookups in a normal order if data.lookups then local splitter = data.helpers.tounicodetable - local cache, h_cache = { }, { } + local t_u_cache = { } + local s_u_cache = t_u_cache -- string keys + local t_h_cache = { } + local s_h_cache = t_h_cache -- table keys (so we could use one cache) + local r_u_cache = { } -- maybe shared for _, lookup in next, data.lookups do local rules = lookup.rules if rules then @@ -6557,15 +6809,15 @@ actions["reorganize lookups"] = function(data,filename,raw) if format == "class" then local before_class = lookup.before_class if before_class then - before_class = t_uncover(splitter,cache,reversed(before_class)) + before_class = t_uncover(splitter,t_u_cache,reversed(before_class)) end local current_class = lookup.current_class if current_class then - current_class = t_uncover(splitter,cache,current_class) + current_class = t_uncover(splitter,t_u_cache,current_class) end local after_class = lookup.after_class if after_class then - after_class = t_uncover(splitter,cache,after_class) + after_class = t_uncover(splitter,t_u_cache,after_class) end for i=1,#rules do local rule = rules[i] @@ -6575,7 +6827,7 @@ actions["reorganize lookups"] = function(data,filename,raw) for i=1,#before do before[i] = before_class[before[i]] or { } end - rule.before = t_hashed(before,h_cache) + rule.before = t_hashed(before,t_h_cache) end local current = class.current local lookups = rule.lookups @@ -6586,14 +6838,14 @@ actions["reorganize lookups"] = function(data,filename,raw) lookups[i] = false -- e.g. we can have two lookups and one replacement end end - rule.current = t_hashed(current,h_cache) + rule.current = t_hashed(current,t_h_cache) end local after = class.after if after then for i=1,#after do after[i] = after_class[after[i]] or { } end - rule.after = t_hashed(after,h_cache) + rule.after = t_hashed(after,t_h_cache) end rule.class = nil end @@ -6608,18 +6860,18 @@ actions["reorganize lookups"] = function(data,filename,raw) if coverage then local before = coverage.before if before then - before = t_uncover(splitter,cache,reversed(before)) - rule.before = t_hashed(before,h_cache) + before = t_uncover(splitter,t_u_cache,reversed(before)) + rule.before = t_hashed(before,t_h_cache) end local current = coverage.current if current then - current = t_uncover(splitter,cache,current) - rule.current = t_hashed(current,h_cache) + current = t_uncover(splitter,t_u_cache,current) + rule.current = t_hashed(current,t_h_cache) end local after = coverage.after if after then - after = t_uncover(splitter,cache,after) - rule.after = t_hashed(after,h_cache) + after = t_uncover(splitter,t_u_cache,after) + rule.after = t_hashed(after,t_h_cache) end rule.coverage = nil end @@ -6631,22 +6883,22 @@ actions["reorganize lookups"] = function(data,filename,raw) if reversecoverage then local before = reversecoverage.before if before then - before = t_uncover(splitter,cache,reversed(before)) - rule.before = t_hashed(before,h_cache) + before = t_uncover(splitter,t_u_cache,reversed(before)) + rule.before = t_hashed(before,t_h_cache) end local current = reversecoverage.current if current then - current = t_uncover(splitter,cache,current) - rule.current = t_hashed(current,h_cache) + current = t_uncover(splitter,t_u_cache,current) + rule.current = t_hashed(current,t_h_cache) end local after = reversecoverage.after if after then - after = t_uncover(splitter,cache,after) - rule.after = t_hashed(after,h_cache) + after = t_uncover(splitter,t_u_cache,after) + rule.after = t_hashed(after,t_h_cache) end local replacements = reversecoverage.replacements if replacements then - rule.replacements = r_uncover(splitter,cache,current,replacements) + rule.replacements = r_uncover(splitter,r_u_cache,current,replacements) end rule.reversecoverage = nil end @@ -6657,19 +6909,19 @@ actions["reorganize lookups"] = function(data,filename,raw) local glyphs = rule.glyphs if glyphs then local fore = glyphs.fore - if fore then - fore = s_uncover(splitter,cache,fore) - rule.before = s_hashed(fore,h_cache) + if fore and fore ~= "" then + fore = s_uncover(splitter,s_u_cache,fore) + rule.before = s_hashed(fore,s_h_cache) end local back = glyphs.back if back then - back = s_uncover(splitter,cache,back) - rule.after = s_hashed(back,h_cache) + back = s_uncover(splitter,s_u_cache,back) + rule.after = s_hashed(back,s_h_cache) end local names = glyphs.names if names then - names = s_uncover(splitter,cache,names) - rule.current = s_hashed(names,h_cache) + names = s_uncover(splitter,s_u_cache,names) + rule.current = s_hashed(names,s_h_cache) end rule.glyphs = nil end @@ -7324,7 +7576,7 @@ local function read_from_otf(specification) local allfeatures = tfmdata.shared.features or specification.features.normal constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf) constructors.setname(tfmdata,specification) -- only otf? - fonts.loggers.register(tfmdata,file.extname(specification.filename),specification) + fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification) end return tfmdata end @@ -7448,26 +7700,27 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring local lpegmatch = lpeg.match local utfchar = utf.char -local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end) -local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end) -local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end) -local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end) -local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end) -local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end) -local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end) +local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end) +local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end) +local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end) +local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end) +local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end) +local trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end) +local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end) +local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end) -local report_prepare = logs.reporter("fonts","otf prepare") +local report_prepare = logs.reporter("fonts","otf prepare") -local fonts = fonts -local otf = fonts.handlers.otf +local fonts = fonts +local otf = fonts.handlers.otf -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local otffeatures = otf.features +local registerotffeature = otffeatures.register -otf.defaultbasealternate = "none" -- first last +otf.defaultbasealternate = "none" -- first last -local wildcard = "*" -local default = "dflt" +local wildcard = "*" +local default = "dflt" local function gref(descriptions,n) if type(n) == "number" then @@ -7602,7 +7855,7 @@ local function finalize_ligatures(tfmdata,ligatures) if ligature then local unicode, lookupdata = ligature[1], ligature[2] if trace then - print("BUILDING",concat(lookupdata," "),unicode) + trace_ligatures_detail("building %q into %q",concat(lookupdata," "),unicode) end local size = #lookupdata local firstcode = lookupdata[1] -- [2] @@ -7615,7 +7868,7 @@ local function finalize_ligatures(tfmdata,ligatures) if not firstdata then firstcode = private if trace then - print(" DEFINING",firstname,firstcode) + trace_ligatures_detail("defining %q as %q",firstname,firstcode) end unicodes[firstname] = firstcode firstdata = { intermediate = true, ligatures = { } } @@ -7639,7 +7892,7 @@ local function finalize_ligatures(tfmdata,ligatures) end end if trace then - print("CODES",firstname,firstcode,secondname,secondcode,target) + trace_ligatures_detail("codes (%s,%s) + (%s,%s) -> %s",firstname,firstcode,secondname,secondcode,target) end local firstligs = firstdata.ligatures if firstligs then @@ -8112,7 +8365,6 @@ local traverse_id = node.traverse_id local unset_attribute = node.unset_attribute local has_attribute = node.has_attribute local set_attribute = node.set_attribute -local copy_node = node.copy local insert_node_before = node.insert_before local insert_node_after = node.insert_after @@ -8124,27 +8376,16 @@ local curscurs = attributes.private('curscurs') local cursdone = attributes.private('cursdone') local kernpair = attributes.private('kernpair') local ligacomp = attributes.private('ligacomp') -local fontkern = attributes.private('fontkern') - -if context then - - local kern = nodes.pool.register(newkern()) - - set_attribute(kern,fontkern,1) -- we can have several, attributes are shared - - newkern = function(k) - local c = copy_node(kern) - c.kern = k - return c - end - -end -- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as -- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner -- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure -- that this code is not 100% okay but examples are needed to figure things out. +function injections.installnewkern(nk) + newkern = nk or newkern +end + local cursives = { } local marks = { } local kerns = { } @@ -8430,16 +8671,13 @@ function injections.handler(head,where,keep) -- new per 2010-10-06, width adapted per 2010-02-03 -- we used to negate the width of marks because in tfm -- that makes sense but we no longer do that so as a - -- consequence the sign of p.width was changed (we need - -- to keep an eye on it as we don't have that many fonts - -- that enter this branch .. I'm still not sure if this - -- one is right + -- consequence the sign of p.width was changed local k = wx[p] if k then - n.xoffset = p.xoffset + p.width + d[1] - k[2] + -- brill roman: A\char"0300 (but ugly anyway) + n.xoffset = p.xoffset - p.width + d[1] - k[2] -- was + p.width else - -- n.xoffset = p.xoffset + p.width + d[1] - -- lucida U\char"032F (default+mark) + -- lucida: U\char"032F (default+mark) n.xoffset = p.xoffset - p.width + d[1] -- 01-05-2011 end else @@ -8579,6 +8817,371 @@ end -- closure do -- begin closure to overcome local limits and interference +if not modules then modules = { } end modules ['font-ota'] = { + version = 1.001, + comment = "companion to font-otf.lua (analysing)", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- this might become scrp-*.lua + +local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat + +if not trackers then trackers = { register = function() end } end + +local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) + +local fonts, nodes, node = fonts, nodes, node + +local allocate = utilities.storage.allocate + +local otf = fonts.handlers.otf + +local analyzers = fonts.analyzers +local initializers = allocate() +local methods = allocate() + +analyzers.initializers = initializers +analyzers.methods = methods +analyzers.useunicodemarks = false + +local nodecodes = nodes.nodecodes +local glyph_code = nodecodes.glyph + +local set_attribute = node.set_attribute +local has_attribute = node.has_attribute +local traverse_id = node.traverse_id +local traverse_node_list = node.traverse + +local fontdata = fonts.hashes.identifiers +local state = attributes.private('state') +local categories = characters and characters.categories or { } -- sorry, only in context + +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register + +--[[ldx-- +<p>Analyzers run per script and/or language and are needed in order to +process features right.</p> +--ldx]]-- + +analyzers.constants = { + init = 1, + medi = 2, + fina = 3, + isol = 4, + -- devanagari + rphf = 5, + half = 6, + pref = 7, + blwf = 8, + pstf = 9, +} + +-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script +-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace + +function analyzers.setstate(head,font) + local useunicodemarks = analyzers.useunicodemarks + local tfmdata = fontdata[font] + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean + while current do + local id = current.id + if id == glyph_code and current.font == font then + local char = current.char + local d = descriptions[char] + if d then + if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then + done = true + set_attribute(current,state,5) -- mark + elseif n == 0 then + first, last, n = current, current, 1 + set_attribute(current,state,1) -- init + else + last, n = current, n+1 + set_attribute(current,state,2) -- medi + end + else -- finish + if first and first == last then + set_attribute(last,state,4) -- isol + elseif last then + set_attribute(last,state,3) -- fina + end + first, last, n = nil, nil, 0 + end + elseif id == disc_code then + -- always in the middle + set_attribute(current,state,2) -- midi + last = current + else -- finish + if first and first == last then + set_attribute(last,state,4) -- isol + elseif last then + set_attribute(last,state,3) -- fina + end + first, last, n = nil, nil, 0 + end + current = current.next + end + if first and first == last then + set_attribute(last,state,4) -- isol + elseif last then + set_attribute(last,state,3) -- fina + end + return head, done +end + +-- in the future we will use language/script attributes instead of the +-- font related value, but then we also need dynamic features which is +-- somewhat slower; and .. we need a chain of them + +local function analyzeinitializer(tfmdata,value) -- attr + local script, language = otf.scriptandlanguage(tfmdata) -- attr + local action = initializers[script] + if not action then + -- skip + elseif type(action) == "function" then + return action(tfmdata,value) + else + local action = action[language] + if action then + return action(tfmdata,value) + end + end +end + +local function analyzeprocessor(head,font,attr) + local tfmdata = fontdata[font] + local script, language = otf.scriptandlanguage(tfmdata,attr) + local action = methods[script] + if not action then + -- skip + elseif type(action) == "function" then + return action(head,font,attr) + else + action = action[language] + if action then + return action(head,font,attr) + end + end + return head, false +end + +registerotffeature { + name = "analyze", + description = "analysis of (for instance) character classes", + default = true, + initializers = { + node = analyzeinitializer, + }, + processors = { + position = 1, + node = analyzeprocessor, + } +} + +-- latin + +methods.latn = analyzers.setstate + +-- this info eventually will go into char-def and we will have a state +-- table for generic then + +local zwnj = 0x200C +local zwj = 0x200D + +local isol = { + [0x0600] = true, [0x0601] = true, [0x0602] = true, [0x0603] = true, + [0x0608] = true, [0x060B] = true, [0x0621] = true, [0x0674] = true, + [0x06DD] = true, [zwnj] = true, +} + +local isol_fina = { + [0x0622] = true, [0x0623] = true, [0x0624] = true, [0x0625] = true, + [0x0627] = true, [0x0629] = true, [0x062F] = true, [0x0630] = true, + [0x0631] = true, [0x0632] = true, [0x0648] = true, [0x0671] = true, + [0x0672] = true, [0x0673] = true, [0x0675] = true, [0x0676] = true, + [0x0677] = true, [0x0688] = true, [0x0689] = true, [0x068A] = true, + [0x068B] = true, [0x068C] = true, [0x068D] = true, [0x068E] = true, + [0x068F] = true, [0x0690] = true, [0x0691] = true, [0x0692] = true, + [0x0693] = true, [0x0694] = true, [0x0695] = true, [0x0696] = true, + [0x0697] = true, [0x0698] = true, [0x0699] = true, [0x06C0] = true, + [0x06C3] = true, [0x06C4] = true, [0x06C5] = true, [0x06C6] = true, + [0x06C7] = true, [0x06C8] = true, [0x06C9] = true, [0x06CA] = true, + [0x06CB] = true, [0x06CD] = true, [0x06CF] = true, [0x06D2] = true, + [0x06D3] = true, [0x06D5] = true, [0x06EE] = true, [0x06EF] = true, + [0x0759] = true, [0x075A] = true, [0x075B] = true, [0x076B] = true, + [0x076C] = true, [0x0771] = true, [0x0773] = true, [0x0774] = true, + [0x0778] = true, [0x0779] = true, [0xFEF5] = true, [0xFEF7] = true, + [0xFEF9] = true, [0xFEFB] = true, + + -- syriac + + [0x0710] = true, [0x0715] = true, [0x0716] = true, [0x0717] = true, + [0x0718] = true, [0x0719] = true, [0x0728] = true, [0x072A] = true, + [0x072C] = true, [0x071E] = true, +} + +local isol_fina_medi_init = { + [0x0626] = true, [0x0628] = true, [0x062A] = true, [0x062B] = true, + [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true, + [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true, + [0x0638] = true, [0x0639] = true, [0x063A] = true, [0x063B] = true, + [0x063C] = true, [0x063D] = true, [0x063E] = true, [0x063F] = true, + [0x0640] = true, [0x0641] = true, [0x0642] = true, [0x0643] = true, + [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true, + [0x0649] = true, [0x064A] = true, [0x066E] = true, [0x066F] = true, + [0x0678] = true, [0x0679] = true, [0x067A] = true, [0x067B] = true, + [0x067C] = true, [0x067D] = true, [0x067E] = true, [0x067F] = true, + [0x0680] = true, [0x0681] = true, [0x0682] = true, [0x0683] = true, + [0x0684] = true, [0x0685] = true, [0x0686] = true, [0x0687] = true, + [0x069A] = true, [0x069B] = true, [0x069C] = true, [0x069D] = true, + [0x069E] = true, [0x069F] = true, [0x06A0] = true, [0x06A1] = true, + [0x06A2] = true, [0x06A3] = true, [0x06A4] = true, [0x06A5] = true, + [0x06A6] = true, [0x06A7] = true, [0x06A8] = true, [0x06A9] = true, + [0x06AA] = true, [0x06AB] = true, [0x06AC] = true, [0x06AD] = true, + [0x06AE] = true, [0x06AF] = true, [0x06B0] = true, [0x06B1] = true, + [0x06B2] = true, [0x06B3] = true, [0x06B4] = true, [0x06B5] = true, + [0x06B6] = true, [0x06B7] = true, [0x06B8] = true, [0x06B9] = true, + [0x06BA] = true, [0x06BB] = true, [0x06BC] = true, [0x06BD] = true, + [0x06BE] = true, [0x06BF] = true, [0x06C1] = true, [0x06C2] = true, + [0x06CC] = true, [0x06CE] = true, [0x06D0] = true, [0x06D1] = true, + [0x06FA] = true, [0x06FB] = true, [0x06FC] = true, [0x06FF] = true, + [0x0750] = true, [0x0751] = true, [0x0752] = true, [0x0753] = true, + [0x0754] = true, [0x0755] = true, [0x0756] = true, [0x0757] = true, + [0x0758] = true, [0x075C] = true, [0x075D] = true, [0x075E] = true, + [0x075F] = true, [0x0760] = true, [0x0761] = true, [0x0762] = true, + [0x0763] = true, [0x0764] = true, [0x0765] = true, [0x0766] = true, + [0x0767] = true, [0x0768] = true, [0x0769] = true, [0x076A] = true, + [0x076D] = true, [0x076E] = true, [0x076F] = true, [0x0770] = true, + [0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true, + [0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true, + [0x077E] = true, [0x077F] = true, + + -- syriac + + [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true, + [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true, + [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true, + [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true, + [0x0729] = true, [0x072B] = true, + + -- also + + [zwj] = true, +} + +local arab_warned = { } + +-- todo: gref + +local function warning(current,what) + local char = current.char + if not arab_warned[char] then + log.report("analyze","arab: character %s (U+%05X) has no %s class", char, char, what) + arab_warned[char] = true + end +end + +local function finish(first,last) + if last then + if first == last then + local fc = first.char + if isol_fina_medi_init[fc] or isol_fina[fc] then + set_attribute(first,state,4) -- isol + else + warning(first,"isol") + set_attribute(first,state,0) -- error + end + else + local lc = last.char + if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? + -- if laststate == 1 or laststate == 2 or laststate == 4 then + set_attribute(last,state,3) -- fina + else + warning(last,"fina") + set_attribute(last,state,0) -- error + end + end + first, last = nil, nil + elseif first then + -- first and last are either both set so we never com here + local fc = first.char + if isol_fina_medi_init[fc] or isol_fina[fc] then + set_attribute(first,state,4) -- isol + else + warning(first,"isol") + set_attribute(first,state,0) -- error + end + first = nil + end + return first, last +end + +function methods.arab(head,font,attr) -- maybe make a special version with no trace + local useunicodemarks = analyzers.useunicodemarks + local tfmdata = fontdata[font] + local marks = tfmdata.resources.marks + local first, last, current, done = nil, nil, head, false + while current do + if current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,state) then + done = true + local char = current.char + if marks[char] or (useunicodemarks and categories[char] == "mn") then + set_attribute(current,state,5) -- mark + elseif isol[char] then -- can be zwj or zwnj too + first, last = finish(first,last) + set_attribute(current,state,4) -- isol + first, last = nil, nil + elseif not first then + if isol_fina_medi_init[char] then + set_attribute(current,state,1) -- init + first, last = first or current, current + elseif isol_fina[char] then + set_attribute(current,state,4) -- isol + first, last = nil, nil + else -- no arab + first, last = finish(first,last) + end + elseif isol_fina_medi_init[char] then + first, last = first or current, current + set_attribute(current,state,2) -- medi + elseif isol_fina[char] then + if not has_attribute(last,state,1) then + -- tricky, we need to check what last may be ! + set_attribute(last,state,2) -- medi + end + set_attribute(current,state,3) -- fina + first, last = nil, nil + elseif char >= 0x0600 and char <= 0x06FF then + set_attribute(current,state,6) -- rest + first, last = finish(first,last) + else --no + first, last = finish(first,last) + end + else + first, last = finish(first,last) + end + current = current.next + end + first, last = finish(first,last) + return head, done +end + +methods.syrc = methods.arab + +directives.register("otf.analyze.useunicodemarks",function(v) + analyzers.useunicodemarks = v +end) + +end -- closure + +do -- begin closure to overcome local limits and interference + if not modules then modules = { } end modules ['font-otn'] = { version = 1.001, comment = "companion to font-ini.mkiv", @@ -8697,6 +9300,8 @@ results in different tables.</p> -- we now use only one hash. If needed we can have multiple again but in that -- case I will probably prefix (i.e. rename) the lookups in the cached font file. +-- Todo: make plugin feature that operates on char/glyphnode arrays + local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip local type, next, tonumber, tostring = type, next, tonumber, tostring @@ -8732,6 +9337,7 @@ local report_subchain = logs.reporter("fonts","otf subchain") local report_chain = logs.reporter("fonts","otf chain") local report_process = logs.reporter("fonts","otf process") local report_prepare = logs.reporter("fonts","otf prepare") +local report_warning = logs.reporter("fonts","otf warning") registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) @@ -8891,105 +9497,229 @@ local function pref(kind,lookupname) return format("feature %s, lookup %s",kind,lookupname) end --- we can assume that languages that use marks are not hyphenated --- we can also assume that at most one discretionary is present +-- We can assume that languages that use marks are not hyphenated. We can also assume +-- that at most one discretionary is present. -local function markstoligature(kind,lookupname,start,stop,char) - local n = copy_node(start) - local keep = start - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current +-- We do need components in funny kerning mode but maybe I can better reconstruct then +-- as we do have the font components info available; removing components makes the +-- previous code much simpler. Also, later on copying and freeing becomes easier. +-- However, for arabic we need to keep them around for the sake of mark placement +-- and indices. + +local function copy_glyph(g) -- next and prev are untouched ! + local components = g.components + if components then + g.components = nil + local n = copy_node(g) + g.components = components + return n + else + return copy_node(g) end - start.prev, stop.next = nil, nil - current.char, current.subtype, current.components = char, ligature_code, start - return keep end -local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head - if start == stop then - start.char = char +-- start is a mark and we need to keep that one + +-- local function markstoligature(kind,lookupname,start,stop,char) +-- -- [start]..[stop] +-- local keep = start +-- local prev = start.prev +-- local next = stop.next +-- local base = copy_glyph(start) +-- local current, start = insert_node_after(start,start,base) +-- -- [current][start]..[stop] +-- current.next = next +-- if next then +-- next.prev = current +-- end +-- start.prev = nil +-- stop.next = nil +-- current.char = char +-- current.subtype = ligature_code +-- current.components = start +-- return keep +-- end + +local function markstoligature(kind,lookupname,start,stop,char) + if start == stop and start.char == char then return start - elseif discfound then - -- print("start->stop",nodes.tosequence(start,stop)) - local components = start.components - if components then - flush_node_list(components) - start.components = nil - end - local lignode = copy_node(start) - lignode.font = start.font - lignode.char = char - lignode.subtype = ligature_code - local next = stop.next + else local prev = start.prev - stop.next = nil + local next = stop.next start.prev = nil - lignode.components = start - -- print("lignode",nodes.tosequence(lignode)) - -- print("components",nodes.tosequence(lignode.components)) - prev.next = lignode + stop.next = nil + local base = copy_glyph(start) + base.char = char + base.subtype = ligature_code + base.components = start + if prev then + prev.next = base + end if next then - next.prev = lignode + next.prev = base end - lignode.next = next - lignode.prev = prev - -- print("start->end",nodes.tosequence(start)) - return lignode + base.next = next + base.prev = prev + return base + end +end + +-- The next code is somewhat complicated by the fact that some fonts can have ligatures made +-- from ligatures that themselves have marks. This was identified by Kai in for instance +-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes +-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next +-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the +-- third component. + +local function getcomponentindex(start) + if start.id ~= glyph_code then + return 0 + elseif start.subtype == ligature_code then + local i = 0 + local components = start.components + while components do + i = i + getcomponentindex(components) + components = components.next + end + return i + elseif not marks[start.char] then + return 1 else - -- start is the ligature + return 0 + end +end + +-- local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head +-- if start == stop and start.char == char then +-- start.char = char +-- return start +-- elseif discfound then +-- local prev = start.prev +-- local next = stop.next +-- start.prev = nil +-- stop.next = nil +-- local base = copy_glyph(start) +-- base.char = char +-- base.subtype = ligature_code +-- base.components = start -- start can have components +-- if prev then +-- prev.next = base +-- end +-- if next then +-- next.prev = base +-- end +-- base.next = next +-- base.prev = prev +-- return base +-- else +-- -- start is the ligature +-- local deletemarks = markflag ~= "mark" +-- local prev = start.prev +-- local next = stop.next +-- local base = copy_glyph(start) +-- local current, start = insert_node_after(start,start,base) +-- -- [start->current][copyofstart->start]...[stop] +-- current.next = next +-- if next then +-- next.prev = current +-- end +-- start.prev = nil +-- stop.next = nil +-- current.char = char +-- current.subtype = ligature_code +-- current.components = start +-- local head = current +-- -- this is messy ... we should get rid of the components eventually +-- local baseindex = 0 +-- local componentindex = 0 +-- while start do +-- local char = start.char +-- if not marks[char] then +-- baseindex = baseindex + componentindex +-- componentindex = getcomponentindex(start) +-- elseif not deletemarks then -- quite fishy +-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) +-- if trace_marks then +-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) +-- end +-- head, current = insert_node_after(head,current,copy_glyph(start)) -- unlikely that mark has components +-- end +-- start = start.next +-- end +-- start = current.next +-- while start and start.id == glyph_code do -- hm, is id test needed ? +-- local char = start.char +-- if marks[char] then +-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) +-- if trace_marks then +-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) +-- end +-- else +-- break +-- end +-- start = start.next +-- end +-- return head +-- end +-- end + +local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head + if start == stop and start.char == char then + start.char = char + return start + end + local prev = start.prev + local next = stop.next + start.prev = nil + stop.next = nil + local base = copy_glyph(start) + base.char = char + base.subtype = ligature_code + base.components = start -- start can have components + if prev then + prev.next = base + end + if next then + next.prev = base + end + base.next = next + base.prev = prev + if not discfound then local deletemarks = markflag ~= "mark" - local n = copy_node(start) - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current - end - start.prev = nil - stop.next = nil - current.char = char - current.subtype = ligature_code - current.components = start - local head = current - -- this is messy ... we should get rid of the components eventually - local i = 0 -- is index of base + local components = start + local baseindex = 0 + local componentindex = 0 + local head = base + local current = base while start do - if not marks[start.char] then - i = i + 1 + local char = start.char + if not marks[char] then + baseindex = baseindex + componentindex + componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - set_attribute(start,ligacomp,i) + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end - head, current = insert_node_after(head,current,copy_node(start)) + head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components end start = start.next end - start = current.next - while start and start.id == glyph_code do - if marks[start.char] then - set_attribute(start,ligacomp,i) + local start = components + while start and start.id == glyph_code do -- hm, is id test needed ? + local char = start.char + if marks[char] then + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end else break end start = start.next end - -- - -- we do need components in funny kerning mode but maybe I can better reconstruct then - -- as we do have the font components info available; removing components makes the - -- previous code much simpler - -- - -- flush_node_list(head.components) - return head end + return base end function handlers.gsub_single(start,kind,lookupname,replacement) @@ -9044,7 +9774,7 @@ local function multiple_glyphs(start,multiple) -- marks ? if nofmultiples > 1 then local sn = start.next for k=2,nofmultiples do -- todo: use insert_node - local n = copy_node(start) + local n = copy_node(start) -- ignore components n.char = multiple[k] n.next = sn n.prev = start @@ -9069,12 +9799,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) local choice = get_alternative_glyph(start,alternative,value) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice) + logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),choice) end start.char = choice else if trace_alternatives then - logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char)) + logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char)) end end return start, true @@ -9568,6 +10298,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start repeat -- start x x m x x stop => start m local next = start.next if not marks[next.char] then +local components = next.components +if components then -- probably not needed + flush_node_list(components) +end delete_node(start,next) end n = n + 1 @@ -9575,6 +10309,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start else -- start x x x stop => start repeat local next = start.next +local components = next.components +if components then -- probably not needed + flush_node_list(components) +end delete_node(start,next) n = n + 1 until next == stop @@ -10303,7 +11041,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence break end prev = prev.prev - elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces + elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces n = n -1 else match = false @@ -10543,12 +11281,7 @@ end) -- fonts.hashes.lookups = lookuphashes -local special_attributes = { - init = 1, - medi = 2, - fina = 3, - isol = 4 -} +local constants = fonts.analyzers.constants local function initialize(sequence,script,language,enabled) local features = sequence.features @@ -10558,7 +11291,7 @@ local function initialize(sequence,script,language,enabled) if valid then local languages = scripts[script] or scripts[wildcard] if languages and (languages[language] or languages[wildcard]) then - return { valid, special_attributes[kind] or false, sequence.chain or 0, kind, sequence } + return { valid, constants[kind] or false, sequence.chain or 0, kind, sequence } end end end @@ -10566,7 +11299,7 @@ local function initialize(sequence,script,language,enabled) return false end -function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context +function otf.dataset(tfmdata,font) -- generic variant, overloaded in context local shared = tfmdata.shared local properties = tfmdata.properties local language = properties.language or "dflt" @@ -10584,12 +11317,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c end local rl = rs[language] if not rl then - rl = { } + rl = { + -- indexed but we can also add specific data by key + } rs[language] = rl + local sequences = tfmdata.resources.sequences setmetatableindex(rl, function(t,k) - local v = enabled and initialize(sequences[k],script,language,enabled) - t[k] = v - return v + if type(k) == "number" then + local v = enabled and initialize(sequences[k],script,language,enabled) + t[k] = v + return v + end end) end return rl @@ -10611,6 +11349,8 @@ end -- start = start.next -- end +-- there will be a new direction parser (pre-parsed etc) + local function featuresprocessor(head,font,attr) local lookuphash = lookuphashes[font] -- we can also check sequences here @@ -10638,7 +11378,7 @@ local function featuresprocessor(head,font,attr) local sequences = resources.sequences local done = false - local datasets = otf.dataset(tfmdata,sequences,font,attr) + local datasets = otf.dataset(tfmdata,font,attr) local dirstack = { } -- could move outside function @@ -10647,6 +11387,9 @@ local function featuresprocessor(head,font,attr) -- to keep track of directions anyway. Also at some point I want to play with -- font interactions and then we do need the full sweeps. + -- Keeping track of the headnode is needed for devanagari (I generalized it a bit + -- so that multiple cases are also covered. + for s=1,#sequences do local dataset = datasets[s] if dataset then @@ -10682,8 +11425,12 @@ local function featuresprocessor(head,font,attr) if lookupcache then local lookupmatch = lookupcache[start.char] if lookupmatch then + local headnode = start == head start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then + if headnode then + head = start + end break end end @@ -10727,10 +11474,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then success = true + if headnode then + head = start + end end end if start then start = start.next end @@ -10800,10 +11551,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then success = true + if headnode then + head = start + end break end end @@ -11130,6 +11885,10 @@ registerotffeature { } } +-- this will change but is needed for an experiment: + +otf.handlers = handlers + end -- closure do -- begin closure to overcome local limits and interference @@ -11757,388 +12516,6 @@ end -- closure do -- begin closure to overcome local limits and interference -if not modules then modules = { } end modules ['font-ota'] = { - version = 1.001, - comment = "companion to font-otf.lua (analysing)", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- this might become scrp-*.lua - -local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat - -if not trackers then trackers = { register = function() end } end - -local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) - -local fonts, nodes, node = fonts, nodes, node - -local allocate = utilities.storage.allocate - -local otf = fonts.handlers.otf - -local analyzers = fonts.analyzers -local initializers = allocate() -local methods = allocate() - -analyzers.initializers = initializers -analyzers.methods = methods -analyzers.useunicodemarks = false - -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph - -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute -local traverse_id = node.traverse_id -local traverse_node_list = node.traverse - -local fontdata = fonts.hashes.identifiers -local state = attributes.private('state') -local categories = characters and characters.categories or { } -- sorry, only in context - -local tracers = nodes.tracers -local colortracers = tracers and tracers.colors -local setnodecolor = colortracers and colortracers.set or function() end -local resetnodecolor = colortracers and colortracers.reset or function() end - -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register - ---[[ldx-- -<p>Analyzers run per script and/or language and are needed in order to -process features right.</p> ---ldx]]-- - --- todo: analyzers per script/lang, cross font, so we need an font id hash -> script --- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace - -local state = attributes.private('state') - -function analyzers.setstate(head,font) - local useunicodemarks = analyzers.useunicodemarks - local tfmdata = fontdata[font] - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean - while current do - local id = current.id - if id == glyph_code and current.font == font then - local char = current.char - local d = descriptions[char] - if d then - if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then - done = true - set_attribute(current,state,5) -- mark - elseif n == 0 then - first, last, n = current, current, 1 - set_attribute(current,state,1) -- init - else - last, n = current, n+1 - set_attribute(current,state,2) -- medi - end - else -- finish - if first and first == last then - set_attribute(last,state,4) -- isol - elseif last then - set_attribute(last,state,3) -- fina - end - first, last, n = nil, nil, 0 - end - elseif id == disc_code then - -- always in the middle - set_attribute(current,state,2) -- midi - last = current - else -- finish - if first and first == last then - set_attribute(last,state,4) -- isol - elseif last then - set_attribute(last,state,3) -- fina - end - first, last, n = nil, nil, 0 - end - current = current.next - end - if first and first == last then - set_attribute(last,state,4) -- isol - elseif last then - set_attribute(last,state,3) -- fina - end - return head, done -end - --- in the future we will use language/script attributes instead of the --- font related value, but then we also need dynamic features which is --- somewhat slower; and .. we need a chain of them - -local function analyzeinitializer(tfmdata,value) -- attr - local script, language = otf.scriptandlanguage(tfmdata) -- attr - local action = initializers[script] - if action then - if type(action) == "function" then - return action(tfmdata,value) - else - local action = action[language] - if action then - return action(tfmdata,value) - end - end - end -end - -local function analyzeprocessor(head,font,attr) - local tfmdata = fontdata[font] - local script, language = otf.scriptandlanguage(tfmdata,attr) - local action = methods[script] - if action then - if type(action) == "function" then - return action(head,font,attr) - else - action = action[language] - if action then - return action(head,font,attr) - end - end - end - return head, false -end - -registerotffeature { - name = "analyze", - description = "analysis of (for instance) character classes", - default = true, - initializers = { - node = analyzeinitializer, - }, - processors = { - position = 1, - node = analyzeprocessor, - } -} - --- latin - -methods.latn = analyzers.setstate - --- this info eventually will go into char-def and we will have a state --- table for generic then - -local zwnj = 0x200C -local zwj = 0x200D - -local isol = { - [0x0600] = true, [0x0601] = true, [0x0602] = true, [0x0603] = true, - [0x0608] = true, [0x060B] = true, [0x0621] = true, [0x0674] = true, - [0x06DD] = true, [zwnj] = true, -} - -local isol_fina = { - [0x0622] = true, [0x0623] = true, [0x0624] = true, [0x0625] = true, - [0x0627] = true, [0x0629] = true, [0x062F] = true, [0x0630] = true, - [0x0631] = true, [0x0632] = true, [0x0648] = true, [0x0671] = true, - [0x0672] = true, [0x0673] = true, [0x0675] = true, [0x0676] = true, - [0x0677] = true, [0x0688] = true, [0x0689] = true, [0x068A] = true, - [0x068B] = true, [0x068C] = true, [0x068D] = true, [0x068E] = true, - [0x068F] = true, [0x0690] = true, [0x0691] = true, [0x0692] = true, - [0x0693] = true, [0x0694] = true, [0x0695] = true, [0x0696] = true, - [0x0697] = true, [0x0698] = true, [0x0699] = true, [0x06C0] = true, - [0x06C3] = true, [0x06C4] = true, [0x06C5] = true, [0x06C6] = true, - [0x06C7] = true, [0x06C8] = true, [0x06C9] = true, [0x06CA] = true, - [0x06CB] = true, [0x06CD] = true, [0x06CF] = true, [0x06D2] = true, - [0x06D3] = true, [0x06D5] = true, [0x06EE] = true, [0x06EF] = true, - [0x0759] = true, [0x075A] = true, [0x075B] = true, [0x076B] = true, - [0x076C] = true, [0x0771] = true, [0x0773] = true, [0x0774] = true, - [0x0778] = true, [0x0779] = true, [0xFEF5] = true, [0xFEF7] = true, - [0xFEF9] = true, [0xFEFB] = true, - - -- syriac - - [0x0710] = true, [0x0715] = true, [0x0716] = true, [0x0717] = true, - [0x0718] = true, [0x0719] = true, [0x0728] = true, [0x072A] = true, - [0x072C] = true, [0x071E] = true, -} - -local isol_fina_medi_init = { - [0x0626] = true, [0x0628] = true, [0x062A] = true, [0x062B] = true, - [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true, - [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true, - [0x0638] = true, [0x0639] = true, [0x063A] = true, [0x063B] = true, - [0x063C] = true, [0x063D] = true, [0x063E] = true, [0x063F] = true, - [0x0640] = true, [0x0641] = true, [0x0642] = true, [0x0643] = true, - [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true, - [0x0649] = true, [0x064A] = true, [0x066E] = true, [0x066F] = true, - [0x0678] = true, [0x0679] = true, [0x067A] = true, [0x067B] = true, - [0x067C] = true, [0x067D] = true, [0x067E] = true, [0x067F] = true, - [0x0680] = true, [0x0681] = true, [0x0682] = true, [0x0683] = true, - [0x0684] = true, [0x0685] = true, [0x0686] = true, [0x0687] = true, - [0x069A] = true, [0x069B] = true, [0x069C] = true, [0x069D] = true, - [0x069E] = true, [0x069F] = true, [0x06A0] = true, [0x06A1] = true, - [0x06A2] = true, [0x06A3] = true, [0x06A4] = true, [0x06A5] = true, - [0x06A6] = true, [0x06A7] = true, [0x06A8] = true, [0x06A9] = true, - [0x06AA] = true, [0x06AB] = true, [0x06AC] = true, [0x06AD] = true, - [0x06AE] = true, [0x06AF] = true, [0x06B0] = true, [0x06B1] = true, - [0x06B2] = true, [0x06B3] = true, [0x06B4] = true, [0x06B5] = true, - [0x06B6] = true, [0x06B7] = true, [0x06B8] = true, [0x06B9] = true, - [0x06BA] = true, [0x06BB] = true, [0x06BC] = true, [0x06BD] = true, - [0x06BE] = true, [0x06BF] = true, [0x06C1] = true, [0x06C2] = true, - [0x06CC] = true, [0x06CE] = true, [0x06D0] = true, [0x06D1] = true, - [0x06FA] = true, [0x06FB] = true, [0x06FC] = true, [0x06FF] = true, - [0x0750] = true, [0x0751] = true, [0x0752] = true, [0x0753] = true, - [0x0754] = true, [0x0755] = true, [0x0756] = true, [0x0757] = true, - [0x0758] = true, [0x075C] = true, [0x075D] = true, [0x075E] = true, - [0x075F] = true, [0x0760] = true, [0x0761] = true, [0x0762] = true, - [0x0763] = true, [0x0764] = true, [0x0765] = true, [0x0766] = true, - [0x0767] = true, [0x0768] = true, [0x0769] = true, [0x076A] = true, - [0x076D] = true, [0x076E] = true, [0x076F] = true, [0x0770] = true, - [0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true, - [0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true, - [0x077E] = true, [0x077F] = true, - - -- syriac - - [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true, - [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true, - [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true, - [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true, - [0x0729] = true, [0x072B] = true, - - -- also - - [zwj] = true, -} - -local arab_warned = { } - - --- todo: gref - -local function warning(current,what) - local char = current.char - if not arab_warned[char] then - log.report("analyze","arab: character %s (U+%05X) has no %s class", char, char, what) - arab_warned[char] = true - end -end - -function methods.nocolor(head,font,attr) - for n in traverse_id(glyph_code,head) do - if not font or n.font == font then - resetnodecolor(n) - end - end - return head, true -end - -local function finish(first,last) - if last then - if first == last then - local fc = first.char - if isol_fina_medi_init[fc] or isol_fina[fc] then - set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end - else - warning(first,"isol") - set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end - end - else - local lc = last.char - if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? - -- if laststate == 1 or laststate == 2 or laststate == 4 then - set_attribute(last,state,3) -- fina - if trace_analyzing then setnodecolor(last,"font:fina") end - else - warning(last,"fina") - set_attribute(last,state,0) -- error - if trace_analyzing then resetnodecolor(last) end - end - end - first, last = nil, nil - elseif first then - -- first and last are either both set so we never com here - local fc = first.char - if isol_fina_medi_init[fc] or isol_fina[fc] then - set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end - else - warning(first,"isol") - set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end - end - first = nil - end - return first, last -end - -function methods.arab(head,font,attr) -- maybe make a special version with no trace - local useunicodemarks = analyzers.useunicodemarks - local tfmdata = fontdata[font] - local marks = tfmdata.resources.marks - local first, last, current, done = nil, nil, head, false - while current do - if current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,state) then - done = true - local char = current.char - if marks[char] or (useunicodemarks and categories[char] == "mn") then - set_attribute(current,state,5) -- mark - if trace_analyzing then setnodecolor(current,"font:mark") end - elseif isol[char] then -- can be zwj or zwnj too - first, last = finish(first,last) - set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end - first, last = nil, nil - elseif not first then - if isol_fina_medi_init[char] then - set_attribute(current,state,1) -- init - if trace_analyzing then setnodecolor(current,"font:init") end - first, last = first or current, current - elseif isol_fina[char] then - set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end - first, last = nil, nil - else -- no arab - first, last = finish(first,last) - end - elseif isol_fina_medi_init[char] then - first, last = first or current, current - set_attribute(current,state,2) -- medi - if trace_analyzing then setnodecolor(current,"font:medi") end - elseif isol_fina[char] then - if not has_attribute(last,state,1) then - -- tricky, we need to check what last may be ! - set_attribute(last,state,2) -- medi - if trace_analyzing then setnodecolor(last,"font:medi") end - end - set_attribute(current,state,3) -- fina - if trace_analyzing then setnodecolor(current,"font:fina") end - first, last = nil, nil - elseif char >= 0x0600 and char <= 0x06FF then - if trace_analyzing then setnodecolor(current,"font:rest") end - first, last = finish(first,last) - else --no - first, last = finish(first,last) - end - else - first, last = finish(first,last) - end - current = current.next - end - first, last = finish(first,last) - return head, done -end - -methods.syrc = methods.arab - -directives.register("otf.analyze.useunicodemarks",function(v) - analyzers.useunicodemarks = v -end) - -end -- closure - -do -- begin closure to overcome local limits and interference - if not modules then modules = { } end modules ['luatex-fonts-lua'] = { version = 1.001, comment = "companion to luatex-*.tex", @@ -12185,6 +12562,8 @@ if not modules then modules = { } end modules ['font-def'] = { license = "see context related readme files" } +-- We can overload some of the definers.functions so we don't local them. + local concat = table.concat local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub local tostring, next = tostring, next @@ -12221,7 +12600,6 @@ definers.methods = definers.methods or { } local internalized = allocate() -- internal tex numbers (private) - local loadedfonts = constructors.loadedfonts local designsizes = constructors.designsizes @@ -12251,7 +12629,7 @@ and prepares a table that will move along as we proceed.</p> -- name name(sub) name(sub)*spec name*spec -- name@spec*oeps -local splitter, splitspecifiers = nil, "" +local splitter, splitspecifiers = nil, "" -- not so nice local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc @@ -12262,7 +12640,7 @@ local space = P(" ") definers.defaultlookup = "file" -local prefixpattern = P(false) +local prefixpattern = P(false) local function addspecifier(symbol) splitspecifiers = splitspecifiers .. symbol @@ -12298,12 +12676,12 @@ function definers.registersplit(symbol,action,verbosename) end end -function definers.makespecification(specification,lookup,name,sub,method,detail,size) +local function makespecification(specification,lookup,name,sub,method,detail,size) size = size or 655360 if trace_defining then report_defining("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s", - specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-", - (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-") + specification, lookup ~= "" and lookup or "[file]", name ~= "" and name or "-", + sub ~= "" and sub or "-", method ~= "" and method or "-", detail ~= "" and detail or "-") end if not lookup or lookup == "" then lookup = definers.defaultlookup @@ -12323,10 +12701,13 @@ function definers.makespecification(specification,lookup,name,sub,method,detail, return t end + +definers.makespecification = makespecification + function definers.analyze(specification, size) -- can be optimized with locals local lookup, name, sub, method, detail = getspecification(specification or "") - return definers.makespecification(specification, lookup, name, sub, method, detail, size) + return makespecification(specification, lookup, name, sub, method, detail, size) end --[[ldx-- @@ -12373,7 +12754,7 @@ function resolvers.spec(specification) if resolved then specification.resolved = resolved specification.sub = sub - specification.forced = file.extname(resolved) + specification.forced = file.suffix(resolved) specification.name = file.removesuffix(resolved) end else @@ -12421,12 +12802,13 @@ specification yet.</p> function definers.applypostprocessors(tfmdata) local postprocessors = tfmdata.postprocessors if postprocessors then + local properties = tfmdata.properties for i=1,#postprocessors do local extrahash = postprocessors[i](tfmdata) -- after scaling etc if type(extrahash) == "string" and extrahash ~= "" then -- e.g. a reencoding needs this extrahash = gsub(lower(extrahash),"[^a-z]","-") - tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash) + properties.fullname = format("%s-%s",properties.fullname,extrahash) end end end @@ -12744,18 +13126,14 @@ local otffeatures = fonts.constructors.newfeatures("otf") local function initializeitlc(tfmdata,value) if value then - -- the magic 40 and it formula come from Dohyun Kim - local parameters = tfmdata.parameters + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess + local parameters = tfmdata.parameters local italicangle = parameters.italicangle if italicangle and italicangle ~= 0 then - local uwidth = (parameters.uwidth or 40)/2 - for unicode, d in next, tfmdata.descriptions do - local it = d.boundingbox[3] - d.width + uwidth - if it ~= 0 then - d.italic = it - end - end - tfmdata.properties.hasitalics = true + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 end end end diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index f5045a4e3..535519db7 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -176,9 +176,9 @@ else loadmodule('font-otf.lua') loadmodule('font-otb.lua') loadmodule('node-inj.lua') -- will be replaced (luatex >= .70) + loadmodule('font-ota.lua') loadmodule('font-otn.lua') -- loadmodule('luatex-fonts-chr.lua') - loadmodule('font-ota.lua') loadmodule('luatex-fonts-lua.lua') loadmodule('font-def.lua') loadmodule('luatex-fonts-def.lua') diff --git a/tex/generic/context/luatex/luatex-mplib.tex b/tex/generic/context/luatex/luatex-mplib.tex index ef6dfff95..8af9f2d8a 100644 --- a/tex/generic/context/luatex/luatex-mplib.tex +++ b/tex/generic/context/luatex/luatex-mplib.tex @@ -31,8 +31,15 @@ \def\setmplibformat#1{\def\mplibformat{#1}} \def\setupmplibcatcodes - {\catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\^=12 \catcode`\~=12 - \catcode`\_=12 \catcode`\%=12 \catcode`\&=12 \catcode`\$=12 } + {\catcode`\{=12 % could be optional .. not really needed + \catcode`\}=12 % could be optional .. not really needed + \catcode`\#=12 + \catcode`\^=12 + \catcode`\~=12 + \catcode`\_=12 + \catcode`\%=12 + \catcode`\&=12 + \catcode`\$=12 } \def\mplibcode {\bgroup |