summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--metapost/context/base/metafun.mp4
-rw-r--r--metapost/context/base/mp-grph.mp33
-rw-r--r--metapost/context/base/mp-mlib.mp130
-rw-r--r--metapost/context/base/mp-spec.mp3
-rw-r--r--metapost/context/base/mp-tool.mp127
-rw-r--r--scripts/context/lua/luatools.lua147
-rw-r--r--scripts/context/lua/mtx-context.lua4
-rw-r--r--scripts/context/lua/mtxrun.lua406
-rw-r--r--scripts/context/lua/scite-ctx.lua843
-rw-r--r--scripts/context/perl/makempy.pl2
-rw-r--r--tex/context/base/attr-ini.lua43
-rw-r--r--tex/context/base/char-def.lua17
-rw-r--r--tex/context/base/char-def.tex3
-rw-r--r--tex/context/base/char-ini.lua21
-rw-r--r--tex/context/base/char-utf.tex20
-rw-r--r--tex/context/base/colo-new.lua818
-rw-r--r--tex/context/base/colo-new.tex4
-rw-r--r--tex/context/base/cont-new.tex2
-rw-r--r--tex/context/base/context.tex22
-rw-r--r--tex/context/base/core-buf.lua100
-rw-r--r--tex/context/base/core-con.lua2
-rw-r--r--tex/context/base/core-fig.tex4
-rw-r--r--tex/context/base/core-fnt.tex6
-rw-r--r--tex/context/base/core-grd.tex2
-rw-r--r--tex/context/base/core-inc.mkiv2
-rw-r--r--tex/context/base/core-job.lua13
-rw-r--r--tex/context/base/core-mis.tex29
-rw-r--r--tex/context/base/core-pgr.tex29
-rw-r--r--tex/context/base/core-spa.lua4
-rw-r--r--tex/context/base/core-tab.tex2
-rw-r--r--tex/context/base/core-tbl.tex4
-rw-r--r--tex/context/base/core-var.tex4
-rw-r--r--tex/context/base/font-otf.lua10
-rw-r--r--tex/context/base/font-tfm.lua4
-rw-r--r--tex/context/base/l-aux.lua17
-rw-r--r--tex/context/base/l-dir.lua42
-rw-r--r--tex/context/base/l-lpeg.lua16
-rw-r--r--tex/context/base/l-number.lua2
-rw-r--r--tex/context/base/l-string.lua2
-rw-r--r--tex/context/base/l-table.lua44
-rw-r--r--tex/context/base/l-xml-edu.lua4
-rw-r--r--tex/context/base/l-xml.lua712
-rw-r--r--tex/context/base/lang-ini.lua14
-rw-r--r--tex/context/base/luat-env.tex3
-rw-r--r--tex/context/base/luat-inp.lua14
-rw-r--r--tex/context/base/luat-tex.lua6
-rw-r--r--tex/context/base/lxml-ini.lua456
-rw-r--r--tex/context/base/lxml-ini.tex35
-rw-r--r--tex/context/base/m-chart.tex3
-rw-r--r--tex/context/base/m-timing.tex2
-rw-r--r--tex/context/base/math-ini.lua70
-rw-r--r--tex/context/base/math-ini.mkiv17
-rw-r--r--tex/context/base/meta-dum.tex38
-rw-r--r--tex/context/base/meta-fig.mkii (renamed from tex/context/base/meta-fig.tex)0
-rw-r--r--tex/context/base/meta-fig.mkiv84
-rw-r--r--tex/context/base/meta-ini.mkii (renamed from tex/context/base/meta-ini.tex)47
-rw-r--r--tex/context/base/meta-ini.mkiv1110
-rw-r--r--tex/context/base/meta-pdf.lua4
-rw-r--r--tex/context/base/meta-tex.mkii (renamed from tex/context/base/meta-tex.tex)0
-rw-r--r--tex/context/base/meta-tex.mkiv35
-rw-r--r--tex/context/base/meta-txt.tex29
-rw-r--r--tex/context/base/mlib-ctx.lua39
-rw-r--r--tex/context/base/mlib-ctx.tex81
-rw-r--r--tex/context/base/mlib-pdf.lua469
-rw-r--r--tex/context/base/mlib-pdf.tex90
-rw-r--r--tex/context/base/mlib-pps.lua820
-rw-r--r--tex/context/base/mlib-pps.tex61
-rw-r--r--tex/context/base/mlib-run.lua219
-rw-r--r--tex/context/base/node-ini.lua21
-rw-r--r--tex/context/base/page-num.tex2
-rw-r--r--tex/context/base/s-abr-01.tex2
-rw-r--r--tex/context/base/s-map-10.tex6
-rw-r--r--tex/context/base/s-sys-01.tex13
-rw-r--r--tex/context/base/spec-dpx.tex31
-rw-r--r--tex/context/base/spec-fdf.tex9
-rw-r--r--tex/context/base/spec-tpd.tex4
-rw-r--r--tex/context/base/supp-box.tex5
-rw-r--r--tex/context/base/supp-mps.tex2
-rw-r--r--tex/context/base/supp-tpi.tex14
-rw-r--r--tex/context/base/symb-was.tex2
-rw-r--r--tex/context/base/syst-cat.tex1
-rw-r--r--tex/context/base/syst-etx.tex2
-rw-r--r--tex/context/base/syst-gen.tex2
-rw-r--r--tex/context/base/syst-mtx.tex2
-rw-r--r--tex/context/base/type-gyr.tex4
-rw-r--r--tex/context/base/type-otf.tex32
-rw-r--r--tex/context/base/x-cals.mkiv38
-rw-r--r--tex/context/base/x-mml.mkiv1
-rw-r--r--tex/context/base/x-mmp.mkiv111
-rw-r--r--tex/context/base/xtag-ent.tex9
-rw-r--r--tex/context/interface/keys-cz.xml2
-rw-r--r--tex/context/interface/keys-de.xml2
-rw-r--r--tex/context/interface/keys-en.xml2
-rw-r--r--tex/context/interface/keys-fr.xml2
-rw-r--r--tex/context/interface/keys-it.xml2
-rw-r--r--tex/context/interface/keys-nl.xml2
-rw-r--r--tex/context/interface/keys-ro.xml2
97 files changed, 6231 insertions, 1545 deletions
diff --git a/metapost/context/base/metafun.mp b/metapost/context/base/metafun.mp
index 98ea1980f..b828b8b9e 100644
--- a/metapost/context/base/metafun.mp
+++ b/metapost/context/base/metafun.mp
@@ -35,7 +35,7 @@ else :
fi ;
input mp-tool.mp ;
-input mp-spec.mp ;
+input mp-spec.mp ; % will be skipped in mkiv, some day
input mp-core.mp ;
input mp-page.mp ;
input mp-text.mp ;
@@ -47,6 +47,8 @@ input mp-step.mp ;
input mp-grph.mp ;
input mp-figs.mp ;
+input mp-mlib.mp ;
+
% mp-form.mp ;
input mp-grid.mp ;
input mp-func.mp ;
diff --git a/metapost/context/base/mp-grph.mp b/metapost/context/base/mp-grph.mp
index 18c43c57b..e2e7e7529 100644
--- a/metapost/context/base/mp-grph.mp
+++ b/metapost/context/base/mp-grph.mp
@@ -56,23 +56,24 @@ string graphictextformat ; graphictextformat := "plain" ;
string graphictextstring ; graphictextstring := "" ;
string graphictextfile ; graphictextfile := "dummy.mpo" ;
-def savegraphictext (expr str) =
- graphictextfile := jobname & ".mpo" ;
- if (graphictextstring<>"") :
- write graphictextstring to graphictextfile ;
- graphictextstring := "" ;
- fi ;
- write str to graphictextfile ;
- let erasegraphictextfile = relax ;
-enddef ;
+def data_mpo_file = job_name & "-mp.mpo" enddef ;
+def data_mpy_file = job_name & "-mp.mpy" enddef ;
-def erasegraphictextfile =
- graphictextfile := jobname & ".mpo" ;
- write EOF to graphictextfile ;
- let erasegraphictextfile = relax ;
-enddef ;
+% def savegraphictext (expr str) =
+% if (graphictextstring<>"") :
+% write graphictextstring to data_mpo_file ;
+% graphictextstring := "" ;
+% fi ;
+% write str to data_mpo_file ;
+% let erasegraphictextfile = relax ;
+% enddef ;
+
+% def erasegraphictextfile =
+% write EOF to data_mpo_file ;
+% let erasegraphictextfile = relax ;
+% enddef ;
-extra_beginfig := extra_beginfig & " erasegraphictextfile ;" ;
+% extra_beginfig := extra_beginfig & " erasegraphictextfile ;" ;
def begingraphictextfig (expr n) =
foundpicture := n ; scratchpicture := nullpicture ;
@@ -213,7 +214,7 @@ def dofinishgraphictext text x_op_x =
if (urcorner dashpart i) = origin : outline_fill := false ; fi ;
endfor ;
scratchpicture := nullpicture ;
- readfile(jobname & ".mpy") ;
+ readfile(data_mpy_file) ;
scratchpicture := (scratchpicture shifted -llcorner scratchpicture) scaled (1/10) ;
if not d_color and not f_color : d_color := true ; fi
if s_color : d_color := false ; f_color := false ; fi ;
diff --git a/metapost/context/base/mp-mlib.mp b/metapost/context/base/mp-mlib.mp
new file mode 100644
index 000000000..4ebe576e6
--- /dev/null
+++ b/metapost/context/base/mp-mlib.mp
@@ -0,0 +1,130 @@
+
+if unknown mplib : endinput ; fi ;
+if known context_mlib : endinput ; fi ;
+
+boolean context_mlib ; context_mlib := true ;
+
+numeric _tt_w_[], _tt_h_[], _tt_d_[] ;
+numeric _tt_n_ ; _tt_n_ := 0 ;
+boolean _trial_run_ ; _trial_run_ := false ;
+
+vardef textext(expr str) =
+ if _trial_run_ :
+ image (
+ draw unitsquare
+ withprescript "tf"
+ withpostscript str ;
+ )
+ else :
+ image (
+ _tt_n_ := _tt_n_ + 1 ;
+ draw unitsquare
+ xscaled _tt_w_[_tt_n_]
+ yscaled (_tt_h_[_tt_n_] + _tt_d_[_tt_n_])
+ withprescript "ts"
+ withpostscript decimal _tt_n_ ;
+ )
+ fi
+enddef ;
+
+def circular_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save ab, r ; pair ab ; numeric r ;
+ r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
+ set_circular_vector(ab,r)(p,n) ;
+ fill p withcircularshade(ab,ab,0,r,ca,cb) ;
+ if trace_shades :
+ drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+def linear_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save a, b, sh ; pair a, b ;
+ set_linear_vector(a,b)(p,n) ;
+ fill p withlinearshade(a,b,ca,cb) ;
+ if trace_shades :
+ drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+def withcircularshade (expr a, b, ra, rb, ca, cb) =
+ withprescript
+ "cs"
+ withpostscript
+ "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb
+enddef ;
+def withlinearshade (expr a, b, ca, cb) =
+ withprescript
+ "ls"
+ withpostscript
+ "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset)
+enddef ;
+string _defined_cs_pre_[], _defined_cs_post_[] ; numeric _defined_cs_ ; _defined_cs_:= 0 ;
+vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+ _defined_cs_ = _defined_cs_ + 1 ;
+ _defined_cs_pre_ [_defined_cs_] = "cs" ;
+ _defined_cs_post_[_defined_cs_] = "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ;
+ _defined_cs_
+enddef ;
+vardef define_linear_shade (expr a, b, ca, cb) =
+ _defined_cs_ = _defined_cs_ + 1 ;
+ _defined_cs_pre_ [_defined_cs_] = "ls" ;
+ _defined_cs_post_[_defined_cs_] = "0 1 " & decimal shadefactor & " " &
+ colordecimals ca & " " & ddecimal (a shifted shadeoffset) & " "
+ colordecimals cb & " " & ddecimal (b shifted shadeoffset) ;
+ _defined_cs_
+enddef ;
+def withshade(expr sc) =
+ withprescript _defined_cs_pre_[sc] withpostscript _defined_cs_post_[sc]
+enddef ;
+def shadecolor(expr sc) = % obsolete
+ 1 withprescript _defined_cs_pre_[sc] withpostscript _defined_cs_post_[sc]
+enddef ;
+
+% def _graphic_text_f_(expr t) text rest =
+% draw unitsquare withprescript "gt" withpostscript t ;
+% enddef ;
+% def _graphic_text_s_(expr t) =
+% begingroup ;
+% save figurepicture ; picture figurepicture ;
+% figurepicture := currentpicture ; currentpicture := nullpicture ;
+% currentgraphictext := currentgraphictext + 1 ;
+% dofinishgraphictext
+% enddef ;
+
+vardef graphictext primary t =
+ save next ;
+ if _trial_run_ :
+ let next = nographictext ;
+ else :
+ let next = dographictext ;
+ fi
+ next(t)
+enddef ;
+def dographictext (expr t) =
+ begingroup ;
+ save figurepicture ; picture figurepicture ;
+ figurepicture := currentpicture ; currentpicture := nullpicture ;
+ currentgraphictext := currentgraphictext + 1 ;
+ dofinishgraphictext
+enddef ;
+def nographictext (expr t) text rest =
+ draw unitsquare withprescript "gt" withpostscript t ;
+enddef ;
+
+
+def doexternalfigure (expr filename) text transformation =
+ draw unitsquare transformation withprescript "fg" withpostscript filename ;
+enddef ;
+
+extra_beginfig := extra_beginfig & "currentgraphictext := 0 ; " ;
+
+boolean cmykcolors ; cmykcolors := true ;
+boolean spotcolors ; spotcolors := true ;
diff --git a/metapost/context/base/mp-spec.mp b/metapost/context/base/mp-spec.mp
index 351f9fe1c..f28e5a5d3 100644
--- a/metapost/context/base/mp-spec.mp
+++ b/metapost/context/base/mp-spec.mp
@@ -495,7 +495,8 @@ vardef cmyk(expr c,m,y,k) =
ok := true ; % globally already defined
fi ;
if not ok :
- save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ;
+% save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ;
+ save s ; string s ; s := ddddecimal (c,m,y,k) ;
_cmyk_counter_ := _cmyk_counter_ + 1 ;
cmykcolorpattern[_cmyk_counter_/_special_div_] := s ;
cmykcolorhash[c][m][y][k] := _cmyk_counter_ ;
diff --git a/metapost/context/base/mp-tool.mp b/metapost/context/base/mp-tool.mp
index b8e2dd668..24f2e6676 100644
--- a/metapost/context/base/mp-tool.mp
+++ b/metapost/context/base/mp-tool.mp
@@ -102,16 +102,59 @@ vardef ddecimal primary p =
decimal xpart p & " " & decimal ypart p
enddef ;
-extra_endfig := extra_endfig
- & "special "
- & "("
- & ditto
- & "%%HiResBoundingBox: "
- & ditto
- & "&ddecimal llcorner currentpicture"
- & "&space"
- & "&ddecimal urcorner currentpicture"
- & ");";
+% is now built in
+
+% extra_endfig := extra_endfig
+% & "special "
+% & "("
+% & ditto
+% & "%%HiResBoundingBox: "
+% & ditto
+% & "&ddecimal llcorner currentpicture"
+% & "&space"
+% & "&ddecimal urcorner currentpicture"
+% & ");";
+
+%D Colors:
+
+nocolormodel := 1 ;
+greycolormodel := 3 ;
+rgbcolormodel := 5 ;
+cmykcolormodel := 7 ;
+
+let grayscale = numeric ;
+
+% def colorlike(expr c) text v = % colorlike(a) b, c, d ;
+% forsuffixes i=v : % save i ;
+% if cmykcolor c :
+% cmykcolor i ;
+% elseif rgbcolor c :
+% rgbcolor i ;
+% else :
+% grayscale i ;
+% fi ;
+% endfor ;
+% enddef ;
+
+vardef colorlike(text c) text v = % colorlike(a) b, c, d ;
+ save _p_ ; picture _p_ ;
+ forsuffixes i=v :
+ _p_ := image(draw origin withcolor c ;) ; % intercept pre and postscripts
+ if (colormodel _p_ = cmykcolormodel) :
+ cmykcolor i ;
+ elseif (colormodel _p_ = rgbcolormodel) :
+ rgbcolor i ;
+ else :
+ grayscale i ;
+ fi ;
+ endfor ;
+enddef ;
+
+% if (unknown colormodel) :
+% def colormodel =
+% rgbcolormodel
+% enddef ;
+% fi ;
%D Also handy (when we flush colors):
@@ -124,7 +167,7 @@ vardef ddddecimal primary c =
enddef ;
vardef colordecimals primary c =
- if cmykcolor c :
+ if cmykcolor c :
decimal cyanpart c & ":" & decimal magentapart c & ":" & decimal yellowpart c & ":" & decimal blackpart c
elseif rgbcolor c :
decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c
@@ -135,15 +178,12 @@ enddef ;
%D We have standardized data file names:
-if not known _data_prefix_ :
-
- string _data_prefix_ ; _data_prefix_ = "mpd-" ;
- string _data_suffix_ ; _data_suffix_ = ".tmp" ;
-
-fi ;
+def job_name =
+ jobname
+enddef ;
-def data_file =
- _data_prefix_ & decimal charcode & _data_suffix_
+def data_mpd_file =
+ job_name & "-mp.mpd"
enddef ;
%D Because \METAPOST\ has a hard coded limit of 4~datafiles,
@@ -157,12 +197,12 @@ boolean savingdata ; savingdata := false ;
def savedata expr txt =
if collapse_data :
+ write txt to data_mpd_file ;
+ else :
write if savingdata : txt else :
"\MPdata{" & decimal charcode & "}{" & txt & "}"
fi
- & "%" to jobname & _data_suffix_ ;
- else :
- write txt to data_file ;
+ & "%" to data_mpd_file ;
fi ;
enddef ;
@@ -172,15 +212,19 @@ def startsavingdata =
write
"\MPdata{" & decimal charcode & "}{%"
to
- jobname & _data_suffix_ ;
+ data_mpd_file ;
fi ;
enddef ;
def stopsavingdata =
- savingdata := false ;
if collapse_data :
- write "}%" to jobname & _data_suffix_ ;
+ write "}%" to data_mpd_file ;
fi ;
+ savingdata := false ;
+enddef ;
+
+def finishsavingdata =
+ write EOF to data_mpd_file ;
enddef ;
%D Instead of a keystroke eating save and allocation
@@ -664,6 +708,16 @@ color cyan ; cyan = (0,1,1) ;
color magenta ; magenta = (1,0,1) ;
color yellow ; yellow = (1,1,0) ;
+def colortype(expr c) =
+ if cmykcolor c : cmykcolor elseif rgbcolor c : rgbcolor else : grayscale fi
+enddef ;
+vardef whitecolor(expr c) =
+ if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi
+enddef ;
+vardef blackcolor(expr c) =
+ if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi
+enddef ;
+
%D Well, this is the dangerous and naive version:
def drawfill text t =
@@ -833,7 +887,18 @@ primarydef p randomized s =
fi
elseif pair p :
p randomshifted s
- elseif color p :
+ elseif cmykcolor p :
+ if color s :
+ (uniformdeviate cyanpart s * cyanpart p,
+ uniformdeviate magentapart s * magentapart p,
+ uniformdeviate yellowpart s * yellowpart p,
+ uniformdeviate blackpart s * blackpart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ elseif rgbcolor p :
if color s :
(uniformdeviate redpart s * redpart p,
uniformdeviate greenpart s * greenpart p,
@@ -843,6 +908,14 @@ primarydef p randomized s =
else :
(uniformdeviate s * p)
fi
+ elseif color p :
+ if color s :
+ (uniformdeviate graypart s * graypart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
else :
p + uniformdeviate s
fi)
@@ -1152,7 +1225,7 @@ def visualizedfill expr c =
enddef ;
def do_visualizeddraw text t =
- draworigin ;
+ draworigin ;
drawpath _c_ t ;
drawcontrollines _c_ ;
drawcontrolpoints _c_ ;
diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua
index 2d146149e..b38d0c4c1 100644
--- a/scripts/context/lua/luatools.lua
+++ b/scripts/context/lua/luatools.lua
@@ -1845,19 +1845,68 @@ dir = { }
if lfs then do
+--~ local attributes = lfs.attributes
+--~ local walkdir = lfs.dir
+--~
+--~ local function glob_pattern(path,patt,recurse,action)
+--~ local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+--~ if ok and type(scanner) == "function" then
+--~ if not path:find("/$") then path = path .. '/' end
+--~ for name in scanner do
+--~ local full = path .. name
+--~ local mode = attributes(full,'mode')
+--~ if mode == 'file' then
+--~ if name:find(patt) then
+--~ action(full)
+--~ end
+--~ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
+--~ glob_pattern(full,patt,recurse,action)
+--~ end
+--~ end
+--~ end
+--~ end
+--~
+--~ dir.glob_pattern = glob_pattern
+--~
+--~ local function glob(pattern, action)
+--~ local t = { }
+--~ local action = action or function(name) t[#t+1] = name end
+--~ local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$")
+--~ local recurse = path and patt
+--~ if not recurse then
+--~ path, patt = pattern:match("^(.*)/(.-)$")
+--~ if not (path and patt) then
+--~ path, patt = '.', pattern
+--~ end
+--~ end
+--~ patt = patt:gsub("([%.%-%+])", "%%%1")
+--~ patt = patt:gsub("%*", ".*")
+--~ patt = patt:gsub("%?", ".")
+--~ patt = "^" .. patt .. "$"
+--~ -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse))
+--~ glob_pattern(path,patt,recurse,action)
+--~ return t
+--~ end
+--~
+--~ dir.glob = glob
+
local attributes = lfs.attributes
local walkdir = lfs.dir
local function glob_pattern(path,patt,recurse,action)
- local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ local ok, scanner
+ if path == "/" then
+ ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ else
+ ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ end
if ok and type(scanner) == "function" then
if not path:find("/$") then path = path .. '/' end
for name in scanner do
-print(name)
local full = path .. name
local mode = attributes(full,'mode')
if mode == 'file' then
- if name:find(patt) then
+ if full:find(patt) then
action(full)
end
elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
@@ -1871,29 +1920,72 @@ print(name)
local function glob(pattern, action)
local t = { }
- local action = action or function(name) table.insert(t,name) end
- local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$")
- local recurse = path and patt
- if not recurse then
- path, patt = pattern:match("^(.*)/(.-)$")
- if not (path and patt) then
- path, patt = '.', pattern
- end
- end
- patt = patt:gsub("([%.%-%+])", "%%%1")
- patt = patt:gsub("%*", ".*")
- patt = patt:gsub("%?", ".")
- patt = "^" .. patt .. "$"
- -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse))
+ local path, rest, patt, recurse
+ local action = action or function(name) t[#t+1] = name end
+ local pattern = pattern:gsub("^%*%*","./**")
+ local pattern = pattern:gsub("/%*/","/**/")
+ path, rest = pattern:match("^(/)(.-)$")
+ if path then
+ path = path
+ else
+ path, rest = pattern:match("^([^/]*)/(.-)$")
+ end
+ if rest then
+ patt = rest:gsub("([%.%-%+])", "%%%1")
+ end
+ patt = patt:gsub("%*", "[^/]*")
+ patt = patt:gsub("%?", "[^/]")
+ patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
+ if path == "" then path = "." end
+ recurse = patt:find("%.%*/") ~= nil
glob_pattern(path,patt,recurse,action)
return t
end
+ local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+
+ local pattern = Ct {
+ [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+ }
+
+ local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%." +
+ P("+") / "%+" +
+ P("-") / "%-" +
+ P(1)
+ )^0 )
+
+ function glob(str)
+ local split = pattern:match(str)
+ if split then
+ local t = { }
+ local action = action or function(name) t[#t+1] = name end
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = base:find("**")
+ local start = root .. path
+ local result = filter:match(start .. base)
+ -- print(str, start, result)
+ glob_pattern(start,result,recurse,action)
+ return t
+ else
+ return { }
+ end
+ end
+
dir.glob = glob
- -- todo: speedup
+ --~ list = dir.glob("**/*.tif")
+ --~ list = dir.glob("/**/*.tif")
+ --~ list = dir.glob("./**/*.tif")
+ --~ list = dir.glob("oeps/**/*.tif")
+ --~ list = dir.glob("/oeps/**/*.tif")
- local function globfiles(path,recurse,func,files)
+ local function globfiles(path,recurse,func,files) -- func == pattern or function
if type(func) == "string" then
local s = func -- alas, we need this indirect way
func = function(name) return name:find(s) end
@@ -1935,23 +2027,6 @@ print(name)
--~ mkdirs(".","/a/b/c")
--~ mkdirs("a","b","c")
---~ function dir.mkdirs(...)
---~ local pth, err, lst = "", false, table.concat({...},"/")
---~ for _, s in ipairs(lst:split("/")) do
---~ if pth == "" then
---~ pth = (s == "" and "/") or s
---~ else
---~ pth = pth .. "/" .. s
---~ end
---~ if s == "" then
---~ -- can be network path
---~ elseif not lfs.isdir(pth) then
---~ lfs.mkdir(pth)
---~ end
---~ end
---~ return pth, not err
---~ end
-
local make_indeed = true -- false
if string.find(os.getenv("PATH"),";") then
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index e0aa7d086..a2ea27a9b 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -625,6 +625,10 @@ input.verbose = true
input.starttiming(scripts.context)
+if environment.argument("once") then
+ scripts.context.multipass.nofruns = 1
+end
+
if environment.argument("run") then
scripts.context.run()
elseif environment.argument("make") then
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index aa78a553e..f08c0f812 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -176,7 +176,7 @@ end
--~ split = lpeg.Ct(c*(p*c)^0)
--~ splitters[separator] = split
--~ end
---~ return lpeg.match(split,self) -- split:match(self)
+--~ return split:match(self)
--~ else
--~ return { }
--~ end
@@ -429,6 +429,8 @@ if not versions then versions = { } end versions['l-lpeg'] = 1.001
--~ lpeg.whitespace = lpeg.S(' \r\n\f\t')^1
--~ lpeg.nonwhitespace = lpeg.P(1-lpeg.whitespace)^1
+local hash = { }
+
function lpeg.anywhere(pattern) --slightly adapted from website
return lpeg.P { lpeg.P(pattern) + 1 * lpeg.V(1) }
end
@@ -444,6 +446,20 @@ function lpeg.splitter(pattern, action)
end
+local crlf = lpeg.P("\r\n")
+local cr = lpeg.P("\r")
+local lf = lpeg.P("\n")
+local space = lpeg.S(" \t\f\v")
+local newline = crlf + cr + lf
+local spacing = space^0 * newline
+local content = lpeg.Cs((1-spacing)^1) * spacing^-1 * (spacing * lpeg.Cc(""))^0
+
+local capture = lpeg.Ct(content^0)
+
+function string:splitlines()
+ return capture:match(self)
+end
+
-- filename : l-table.lua
-- comment : split off from luat-lib
@@ -517,15 +533,6 @@ function table.prepend(t, list)
end
end
---~ function table.merge(t, ...)
---~ for _, list in ipairs({...}) do
---~ for k,v in pairs(list) do
---~ t[k] = v
---~ end
---~ end
---~ return t
---~ end
-
function table.merge(t, ...) -- first one is target
t = t or {}
local lst = {...}
@@ -537,16 +544,6 @@ function table.merge(t, ...) -- first one is target
return t
end
---~ function table.merged(...)
---~ local tmp = { }
---~ for _, list in ipairs({...}) do
---~ for k,v in pairs(list) do
---~ tmp[k] = v
---~ end
---~ end
---~ return tmp
---~ end
-
function table.merged(...)
local tmp, lst = { }, {...}
for i=1,#lst do
@@ -557,15 +554,6 @@ function table.merged(...)
return tmp
end
---~ function table.imerge(t, ...)
---~ for _, list in ipairs({...}) do
---~ for _, v in ipairs(list) do
---~ t[#t+1] = v
---~ end
---~ end
---~ return t
---~ end
-
function table.imerge(t, ...)
local lst = {...}
for i=1,#lst do
@@ -577,16 +565,6 @@ function table.imerge(t, ...)
return t
end
---~ function table.imerged(...)
---~ local tmp = { }
---~ for _, list in ipairs({...}) do
---~ for _,v in pairs(list) do
---~ tmp[#tmp+1] = v
---~ end
---~ end
---~ return tmp
---~ end
-
function table.imerged(...)
local tmp, lst = { }, {...}
for i=1,#lst do
@@ -734,7 +712,6 @@ do
end
if n == #t then
local tt = { }
- -- for _,v in ipairs(t) do
for i=1,#t do
local v = t[i]
local tv = type(v)
@@ -789,7 +766,7 @@ do
local inline = compact and table.serialize_inline
local first, last = nil, 0 -- #root cannot be trusted here
if compact then
- for k,v in ipairs(root) do -- NOT: for k=1,#root do
+ for k,v in ipairs(root) do -- NOT: for k=1,#root do (why)
if not first then first = k end
last = last + 1
end
@@ -971,7 +948,8 @@ end
do
local function flatten(t,f,complete)
- for _,v in ipairs(t) do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
if complete or type(v[1]) == "table" then
flatten(v,f,complete)
@@ -1437,7 +1415,7 @@ do
local one = lpeg.C(1-lpeg.S(''))^1
function number.toset(n)
- return lpeg.match(one,tostring(n))
+ return one:match(tostring(n))
end
end
@@ -1839,17 +1817,53 @@ if lfs then do
else
path, rest = pattern:match("^([^/]*)/(.-)$")
end
- patt = rest:gsub("([%.%-%+])", "%%%1")
+ if rest then
+ patt = rest:gsub("([%.%-%+])", "%%%1")
+ end
patt = patt:gsub("%*", "[^/]*")
patt = patt:gsub("%?", "[^/]")
patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
if path == "" then path = "." end
- -- print(pattern, path, patt)
- recurse = patt:find("%.%*/")
+ recurse = patt:find("%.%*/") ~= nil
glob_pattern(path,patt,recurse,action)
return t
end
+ local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+
+ local pattern = Ct {
+ [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+ }
+
+ local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%." +
+ P("+") / "%+" +
+ P("-") / "%-" +
+ P(1)
+ )^0 )
+
+ function glob(str)
+ local split = pattern:match(str)
+ if split then
+ local t = { }
+ local action = action or function(name) t[#t+1] = name end
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = base:find("**")
+ local start = root .. path
+ local result = filter:match(start .. base)
+ -- print(str, start, result)
+ glob_pattern(start,result,recurse,action)
+ return t
+ else
+ return { }
+ end
+ end
+
dir.glob = glob
--~ list = dir.glob("**/*.tif")
@@ -2162,6 +2176,8 @@ xml.trace_lpath = false
xml.trace_print = false
xml.trace_remap = false
+local format, concat = string.format, table.concat
+
-- todo: some things per xml file, liek namespace remapping
--[[ldx--
@@ -2172,7 +2188,7 @@ find based solution where we loop over an array of patterns. Less code and
much cleaner.</p>
--ldx]]--
-xml.xmlns = { }
+xml.xmlns = xml.xmlns or { }
do
@@ -2312,9 +2328,9 @@ do
local toclose = remove(stack)
top = stack[#stack]
if #stack < 1 then
- errorstr = string.format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "")
+ errorstr = format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "")
elseif toclose.tg ~= tag then -- no namespace check
- errorstr = string.format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "")
+ errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "")
end
dt = top.dt
dt[#dt+1] = toclose
@@ -2438,8 +2454,10 @@ do
errorstr = "empty xml file"
elseif not grammar:match(data) then
errorstr = "invalid xml file"
+ else
+ errorstr = ""
end
- if errorstr then
+ if errorstr and errorstr ~= "" then
result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={}, er = true } }, error = true }
setmetatable(stack, mt)
if xml.error_handler then xml.error_handler("load",errorstr) end
@@ -2449,7 +2467,9 @@ do
if not no_root then
result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={} }
setmetatable(result, mt)
- for k,v in ipairs(result.dt) do
+ local rdt = result.dt
+ for k=1,#rdt do
+ local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
break
@@ -2560,138 +2580,141 @@ do
local fallbackhandle = (tex and tex.sprint) or io.write
- function xml.serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
+ local function serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
if not e then
- -- quit
- elseif not nocommands and e.command and xml.command then
- xml.command(e)
- else
- handle = handle or fallbackhandle
- local etg = e.tg
- if etg then
- -- local format = string.format
- if e.special then
- local edt = e.dt
- local spc = specialconverter and specialconverter[etg]
- if spc then
- local result = spc(edt[1])
- if result then
- handle(result)
- else
- -- no need to handle any further
+ return
+ elseif not nocommands then
+ local ec = e.command
+ if ec then
+ local xc = xml.command
+ if xc then
+ xc(e,ec)
+ return
+ end
+ end
+ end
+ handle = handle or fallbackhandle
+ local etg = e.tg
+ if etg then
+ if e.special then
+ local edt = e.dt
+ local spc = specialconverter and specialconverter[etg]
+ if spc then
+ local result = spc(edt[1])
+ if result then
+ handle(result)
+ else
+ -- no need to handle any further
+ end
+ elseif etg == "@pi@" then
+ -- handle(format("<?%s?>",edt[1]))
+ handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt)
+ elseif etg == "@cm@" then
+ -- handle(format("<!--%s-->",edt[1]))
+ handle("<!--" .. edt[1] .. "-->")
+ elseif etg == "@cd@" then
+ -- handle(format("<![CDATA[%s]]>",edt[1]))
+ handle("<![CDATA[" .. edt[1] .. "]]>")
+ elseif etg == "@dd@" then
+ -- handle(format("<!DOCTYPE %s>",edt[1]))
+ handle("<!DOCTYPE " .. edt[1] .. ">")
+ elseif etg == "@rt@" then
+ serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ else
+ local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { }
+ if ats then
+ if attributeconverter then
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ end
+ else
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,v)
end
- elseif etg == "@pi@" then
- -- handle(format("<?%s?>",edt[1]))
- handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt)
- elseif etg == "@cm@" then
- -- handle(format("<!--%s-->",edt[1]))
- handle("<!--" .. edt[1] .. "-->")
- elseif etg == "@cd@" then
- -- handle(format("<![CDATA[%s]]>",edt[1]))
- handle("<![CDATA[" .. edt[1] .. "]]>")
- elseif etg == "@dd@" then
- -- handle(format("<!DOCTYPE %s>",edt[1]))
- handle("<!DOCTYPE " .. edt[1] .. ">")
- elseif etg == "@rt@" then
- xml.serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
- else
- local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
- local ats = eat and next(eat) and { }
+ end
+ if ern and xml.trace_remap then
if ats then
- local format = string.format
- if attributeconverter then
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
- end
- else
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,v)
- end
- end
+ ats[#ats+1] = format("xmlns:remapped='%s'",ern)
+ else
+ ats = { format("xmlns:remapped='%s'",ern) }
end
- if ern and xml.trace_remap then
+ end
+ if ens ~= "" then
+ if edt and #edt > 0 then
if ats then
- ats[#ats+1] = string.format("xmlns:remapped='%s'",ern)
+ -- handle(format("<%s:%s %s>",ens,etg,concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. ">")
else
- ats = { string.format("xmlns:remapped='%s'",ern) }
+ -- handle(format("<%s:%s>",ens,etg))
+ handle("<" .. ens .. ":" .. etg .. ">")
end
- end
- if ens ~= "" then
- if edt and #edt > 0 then
- if ats then
- -- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
- handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. ">")
- else
- -- handle(format("<%s:%s>",ens,etg))
- handle("<" .. ens .. ":" .. etg .. ">")
- end
- local serialize = xml.serialize
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
- else
- handle(e)
- end
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ handle(e)
end
- end
- -- handle(format("</%s:%s>",ens,etg))
- handle("</" .. ens .. ":" .. etg .. ">")
- else
- if ats then
- -- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
- handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. "/>")
else
- -- handle(format("<%s:%s/>",ens,etg))
- handle("<" .. ens .. ":" .. "/>")
+ serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
+ -- handle(format("</%s:%s>",ens,etg))
+ handle("</" .. ens .. ":" .. etg .. ">")
else
- if edt and #edt > 0 then
- if ats then
- -- handle(format("<%s %s>",etg,table.concat(ats," ")))
- handle("<" .. etg .. " " .. table.concat(ats," ") .. ">")
- else
- -- handle(format("<%s>",etg))
- handle("<" .. etg .. ">")
- end
- local serialize = xml.serialize
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
- end
- -- handle(format("</%s>",etg))
- handle("</" .. etg .. ">")
+ if ats then
+ -- handle(format("<%s:%s %s/>",ens,etg,concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. "/>")
else
- if ats then
- -- handle(format("<%s %s/>",etg,table.concat(ats," ")))
- handle("<" .. etg .. " " .. table.concat(ats," ") .. "/>")
- else
- -- handle(format("<%s/>",etg))
- handle("<" .. etg .. "/>")
- end
+ -- handle(format("<%s:%s/>",ens,etg))
+ handle("<" .. ens .. ":" .. "/>")
end
end
- end
- elseif type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
else
- handle(e)
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s %s>",etg,concat(ats," ")))
+ handle("<" .. etg .. " " .. concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s>",etg))
+ handle("<" .. etg .. ">")
+ end
+ for i=1,#edt do
+ serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ -- handle(format("</%s>",etg))
+ handle("</" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s %s/>",etg,concat(ats," ")))
+ handle("<" .. etg .. " " .. concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s/>",etg))
+ handle("<" .. etg .. "/>")
+ end
+ end
end
+ end
+ elseif type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- local serialize = xml.serialize
- for i=1,#e do
- serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
- end
+ handle(e)
+ end
+ else
+ for i=1,#e do
+ serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
end
- function xml.checkbom(root)
+ xml.serialize = serialize
+
+ function xml.checkbom(root) -- can be made faster
if root.ri then
local dt, found = root.dt, false
for k,v in ipairs(dt) do
@@ -2707,24 +2730,24 @@ do
end
end
-end
-
---[[ldx--
-<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.</p>
---ldx]]--
+ --[[ldx--
+ <p>At the cost of some 25% runtime overhead you can first convert the tree to a string
+ and then handle the lot.</p>
+ --ldx]]--
-function xml.tostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- elseif next(root) then
- local result = { }
- xml.serialize(root,function(s) result[#result+1] = s end)
- return table.concat(result,"")
+ function xml.tostring(root) -- 25% overhead due to collecting
+ if root then
+ if type(root) == 'string' then
+ return root
+ elseif next(root) then
+ local result = { }
+ serialize(root,function(s) result[#result+1] = s end)
+ return concat(result,"")
+ end
end
-end
- return ""
+ return ""
+ end
+
end
--[[ldx--
@@ -2852,14 +2875,14 @@ do
[40] = "processing instruction",
}
- local function make_expression(str)
+ local function make_expression(str) --could also be an lpeg
str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')")
str = str:gsub("position%(%)", "i")
str = str:gsub("text%(%)", "t")
str = str:gsub("!=", "~=")
str = str:gsub("([^=!~<>])=([^=!~<>])", "%1==%2")
str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(")
- return str, loadstring(string.format("return function(functions,i,a,t) return %s end", str))()
+ return str, loadstring(format("return function(functions,i,a,t) return %s end", str))()
end
local map = { }
@@ -2945,6 +2968,9 @@ do
local expression = (is_one * is_expression)/ function(...) map[#map+1] = { 31, true, ... } end
local dont_expression = (is_none * is_expression)/ function(...) map[#map+1] = { 31, false, ... } end
+ local self_expression = ( is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end
+ local dont_self_expression = (exclam * is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end
+
local instruction = (instructiontag * text ) / function(...) map[#map+1] = { 40, ... } end
local nothing = (empty ) / function( ) map[#map+1] = { 15 } end -- 15 ?
local crap = (1-slash)^1
@@ -2970,6 +2996,7 @@ do
dont_match_and_eq + dont_match_and_ne +
match_and_eq + match_and_ne +
dont_expression + expression +
+dont_self_expression + self_expression +
has_attribute + has_value +
dont_match_one_of + match_one_of +
dont_match + match +
@@ -2981,7 +3008,7 @@ do
followup = ((slash + parenttag + childtag + selftag)^0 * selector)^1,
}
- function compose(str)
+ local function compose(str)
if not str or str == "" then
-- wildcard
return true
@@ -3003,7 +3030,7 @@ do
-- root
return false
end
- elseif #map == 2 and m == 12 and map[2][1] == 20 then
+ elseif #map == 2 and m == 12 and map[2][1] == 20 then
-- return { { 29, map[2][2], map[2][3], map[2][4], map[2][5] } }
map[2][1] = 29
return { map[2] }
@@ -3011,6 +3038,7 @@ do
if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
table.insert(map, 1, { 16 })
end
+ -- print((table.serialize(map)):gsub("[ \n]+"," "))
return map
end
end
@@ -3045,7 +3073,7 @@ do
report(" -: wildcard\n")
else
if type(pattern) == "string" then
- report(string.format("pattern: %s\n",pattern))
+ report(format("pattern: %s\n",pattern))
end
for k,v in ipairs(lp) do
if #v > 1 then
@@ -3058,9 +3086,9 @@ do
t[#t+1] = (vv and "==") or "<>"
end
end
- report(string.format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," ")))
+ report(format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," ")))
else
- report(string.format("%2i: %s %s\n", k,v[1],actions[v[1]]))
+ report(format("%2i: %s %s\n", k,v[1],actions[v[1]]))
end
end
end
@@ -3181,7 +3209,7 @@ do
start, stop, step = stop, start, -1
end
local idx = 0
- for k=start,stop,step do
+ for k=start,stop,step do -- we used to have functions for all but a case is faster
local e = rootdt[k]
local ns, tg = e.rn or e.ns, e.tg
if tg then
@@ -3256,15 +3284,19 @@ do
if tg == tg_a then matched = ns == action[3] elseif tg_a == '*' then matched, multiple = ns == action[3], true else matched = false end
if not action[2] then matched = not matched end
if matched then
- matched = action[6](functions,idx,e.at,edt[1])
+ matched = action[6](functions,idx,e.at or { },edt[1])
end
end
if matched then -- combine tg test and at test
if index == #pattern then
if handle(root,rootdt,root.ri or k) then return false end
---~ if wildcard and multiple then
-if wildcard or multiple then
- if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
+ if wildcard then
+ if multiple then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
+ else
+ -- maybe or multiple; anyhow, check on (section|title) vs just section and title in example in lxml
+ if not traverse(e,pattern,handle,reverse,index,root) then return false end
+ end
end
else
if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
diff --git a/scripts/context/lua/scite-ctx.lua b/scripts/context/lua/scite-ctx.lua
new file mode 100644
index 000000000..1b8329289
--- /dev/null
+++ b/scripts/context/lua/scite-ctx.lua
@@ -0,0 +1,843 @@
+-- version : 1.0.0 - 07/2005 (2008: lua 5.1)
+-- author : Hans Hagen - PRAGMA ADE - www.pragma-ade.com
+-- copyright : public domain or whatever suits
+-- remark : part of the context distribution, my first lua code
+
+-- todo: name space for local functions
+
+-- loading: scite-ctx.properties
+
+-- # environment variable
+-- #
+-- # CTXSPELLPATH=t:/spell
+-- #
+-- # auto language detection
+-- #
+-- # % version =1.0 language=uk
+-- # <?xml version='1.0' language='uk' ?>
+
+-- ext.lua.startup.script=$(SciteDefaultHome)/scite-ctx.lua
+--
+-- # extension.$(file.patterns.context)=scite-ctx.lua
+-- # extension.$(file.patterns.example)=scite-ctx.lua
+--
+-- # ext.lua.reset=1
+-- # ext.lua.auto.reload=1
+-- # ext.lua.startup.script=t:/lua/scite-ctx.lua
+--
+-- ctx.menulist.default=\
+-- wrap=wrap_text|\
+-- unwrap=unwrap_text|\
+-- sort=sort_text|\
+-- document=document_text|\
+-- quote=quote_text|\
+-- compound=compound_text|\
+-- check=check_text
+--
+-- ctx.spellcheck.language=auto
+-- ctx.spellcheck.wordsize=4
+-- ctx.spellcheck.wordpath=ENV(CTXSPELLPATH)
+--
+-- ctx.spellcheck.wordfile.all=spell-uk.txt,spell-nl.txt
+--
+-- ctx.spellcheck.wordfile.uk=spell-uk.txt
+-- ctx.spellcheck.wordfile.nl=spell-nl.txt
+-- ctx.spellcheck.wordsize.uk=4
+-- ctx.spellcheck.wordsize.nl=4
+--
+-- command.name.21.*=CTX Action List
+-- command.subsystem.21.*=3
+-- command.21.*=show_menu $(ctx.menulist.default)
+-- command.groupundo.21.*=yes
+-- command.shortcut.21.*=Shift+F11
+--
+-- command.name.22.*=CTX Check Text
+-- command.subsystem.22.*=3
+-- command.22.*=check_text
+-- command.groupundo.22.*=yes
+-- command.shortcut.22.*=Ctrl+L
+--
+-- command.name.23.*=CTX Wrap Text
+-- command.subsystem.23.*=3
+-- command.23.*=wrap_text
+-- command.groupundo.23.*=yes
+-- command.shortcut.23.*=Ctrl+M
+--
+-- # command.21.*=check_text
+-- # command.21.*=dofile e:\context\lua\scite-ctx.lua
+
+-- generic functions
+
+local crlf = "\n"
+
+function traceln(str)
+ trace(str .. crlf)
+ io.flush()
+end
+
+function table.found(tab, str)
+ local l, r, p
+ if #str == 0 then
+ return false
+ else
+ l, r = 1, #tab
+ while l <= r do
+ p = math.floor((l+r)/2)
+ if str < tab[p] then
+ r = p - 1
+ elseif str > tab[p] then
+ l = p + 1
+ else
+ return true
+ end
+ end
+ return false
+ end
+end
+
+function string:grab(delimiter)
+ local list = {}
+ for snippet in self:gmatch(delimiter) do
+ list[#list+1] = snippet
+ end
+ return list
+end
+
+function string:is_empty()
+ return not self:find("%S")
+end
+
+function string:expand()
+ return (self:gsub("ENV%((%w+)%)", os.envvar))
+end
+
+function string:strip()
+ return (self:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+do
+
+ local lower, gsub, sub = string.lower, string.gsub, string.sub
+
+ function table.alphasort(list,i)
+ if i and i > 0 then
+ local function alphacmp(a,b)
+ return lower(gsub(sub(a,i),'0',' ')) < lower(gsub(sub(b,i),'0',' '))
+ end
+ table.sort(list,alphacmp)
+ else
+ local function alphacmp(a,b)
+ return a:lower() < b:lower()
+ end
+ table.sort(list,alphacmp)
+ end
+ end
+
+end
+
+function io.exists(filename)
+ local ok, result, message = pcall(io.open,filename)
+ if result then
+ io.close(result)
+ return true
+ else
+ return false
+ end
+end
+
+function os.envvar(str)
+ local s = os.getenv(str)
+ if s ~= '' then
+ return s
+ end
+ s = os.getenv(str:upper())
+ if s ~= '' then
+ return s
+ end
+ s = os.getenv(str:lower())
+ if s ~= '' then
+ return s
+ end
+end
+
+-- support functions, maybe editor namespace
+
+-- function column_of_position(position)
+-- local line = editor:LineFromPosition(position)
+-- local oldposition = editor.CurrentPos
+-- local column = 0
+-- editor:GotoPos(position)
+-- while editor.CurrentPos ~= 0 and line == editor:LineFromPosition(editor.CurrentPos) do
+-- editor:CharLeft()
+-- column = column + 1
+-- end
+-- editor:GotoPos(oldposition)
+-- if line > 0 then
+-- return column -1
+-- else
+-- return column
+-- end
+-- end
+
+-- function line_of_position(position)
+-- return editor:LineFromPosition(position)
+-- end
+
+function extend_to_start()
+ local selectionstart = editor.SelectionStart
+ local selectionend = editor.SelectionEnd
+ local line = editor:LineFromPosition(selectionstart)
+ if line > 0 then
+ while line == editor:LineFromPosition(selectionstart-1) do
+ selectionstart = selectionstart - 1
+ editor:SetSel(selectionstart,selectionend)
+ end
+ else
+ selectionstart = 0
+ end
+ editor:SetSel(selectionstart,selectionend)
+ return selectionstart
+end
+
+function extend_to_end() -- editor:LineEndExtend() does not work
+ local selectionstart = editor.SelectionStart
+ local selectionend = editor.SelectionEnd
+ local line = editor:LineFromPosition(selectionend)
+ while line == editor:LineFromPosition(selectionend+1) do
+ selectionend = selectionend + 1
+ editor:SetSel(selectionstart,selectionend)
+ end
+ editor:SetSel(selectionstart,selectionend)
+ return selectionend
+end
+
+function getfiletype()
+ local firstline = editor:GetLine(0)
+ if editor.Lexer == SCLEX_TEX then
+ return 'tex'
+ elseif editor.Lexer == SCLEX_XML then
+ return 'xml'
+ elseif firstline:find("^%%") then
+ return 'tex'
+ elseif firstline:find("^<%?xml") then
+ return 'xml'
+ else
+ return 'unknown'
+ end
+end
+
+-- inspired by LuaExt's scite_Files
+
+function get_dir_list(mask)
+ local f
+ if props['PLAT_GTK'] and props['PLAT_GTK'] ~= "" then
+ f = io.popen('ls -1 ' .. mask)
+ else
+ mask = mask:gsub('/','\\')
+ local tmpfile = 'scite-ctx.tmp'
+ local cmd = 'dir /b "' .. mask .. '" > ' .. tmpfile
+ os.execute(cmd)
+ f = io.open(tmpfile)
+ end
+ local files = {}
+ if not f then -- path check added
+ return files
+ end
+ for line in f:lines() do
+ files[#files+1] = line
+ end
+ f:close()
+ return files
+end
+
+-- banner
+
+do
+
+ print("loading scite-ctx.lua definition file\n")
+ print("- see scite-ctx.properties for configuring info\n")
+ print("- ctx.spellcheck.wordpath set to " .. props['ctx.spellcheck.wordpath'])
+ if (props['ctx.spellcheck.wordpath']:lower()):find("ctxspellpath") then
+ if os.getenv('ctxspellpath') then
+ print("- ctxspellpath set to " .. os.getenv('CTXSPELLPATH'))
+ else
+ print("- 'ctxspellpath is not set")
+ end
+ print("- ctx.spellcheck.wordpath expands to " .. string.expand(props['ctx.spellcheck.wordpath']))
+ end
+ print("\n- ctx.wraptext.length is set to " .. props['ctx.wraptext.length'])
+ if props['ctx.helpinfo'] ~= '' then
+ print("\n- key bindings:\n")
+ print(((string.strip(props['ctx.helpinfo'])):gsub("%s*\|%s*","\n")))
+ end
+ print("\n- recognized first lines:\n")
+ print("xml <?xml version='1.0' language='nl'")
+ print("tex % language=nl")
+
+end
+
+-- text functions
+
+-- written while listening to Talk Talk
+
+local magicstring = string.rep("<ctx-crlf/>", 2)
+
+function wrap_text()
+
+ -- We always go to the end of a line, so in fact some of
+ -- the variables set next are not needed.
+
+ local length = props["ctx.wraptext.length"]
+
+ if length == '' then length = 80 else length = tonumber(length) end
+
+ local startposition = editor.SelectionStart
+ local endposition = editor.SelectionEnd
+
+ if startposition == endposition then return end
+
+ editor:LineEndExtend()
+
+ startposition = editor.SelectionStart
+ endposition = editor.SelectionEnd
+
+ -- local startline = line_of_position(startposition)
+ -- local endline = line_of_position(endposition)
+ -- local startcolumn = column_of_position(startposition)
+ -- local endcolumn = column_of_position(endposition)
+ --
+ -- editor:SetSel(startposition,endposition)
+
+ local startline = props['SelectionStartLine']
+ local endline = props['SelectionEndLine']
+ local startcolumn = props['SelectionStartColumn'] - 1
+ local endcolumn = props['SelectionEndColumn'] - 1
+
+ local replacement = { }
+ local templine = ''
+ local indentation = string.rep(' ',startcolumn)
+ local selection = editor:GetSelText()
+
+ selection = selection:gsub("[\n\r][\n\r]","\n")
+ selection = selection:gsub("\n\n+",' ' .. magicstring .. ' ')
+ selection = selection:gsub("^%s",'')
+
+ for snippet in selection:gmatch("%S+") do
+ if snippet == magicstring then
+ replacement[#replacement+1] = templine
+ replacement[#replacement+1] = ""
+ templine = ''
+ elseif #templine + #snippet > length then
+ replacement[#replacement+1] = templine
+ templine = indentation .. snippet
+ elseif #templine == 0 then
+ templine = indentation .. snippet
+ else
+ templine = templine .. ' ' .. snippet
+ end
+ end
+
+ replacement[#replacement+1] = templine
+ replacement[1] = replacement[1]:gsub("^%s+",'')
+
+ if endcolumn == 0 then
+ replacement[#replacement+1] = ""
+ end
+
+ editor:ReplaceSel(table.concat(replacement,"\n"))
+
+end
+
+function unwrap_text()
+
+ local startposition = editor.SelectionStart
+ local endposition = editor.SelectionEnd
+
+ if startposition == endposition then return end
+
+ editor:HomeExtend()
+ editor:LineEndExtend()
+
+ startposition = editor.SelectionStart
+ endposition = editor.SelectionEnd
+
+ local magicstring = string.rep("<multiplelines/>", 2)
+ local selection = string.gsub(editor:GetSelText(),"[\n\r][\n\r]+", ' ' .. magicstring .. ' ')
+ local replacement = ''
+
+ for snippet in selection:gmatch("%S+") do
+ if snippet == magicstring then
+ replacement = replacement .. "\n"
+ else
+ replacement = replacement .. snippet .. "\n"
+ end
+ end
+
+ if endcolumn == 0 then replacement = replacement .. "\n" end
+
+ editor:ReplaceSel(replacement)
+
+end
+
+function sort_text()
+
+ local startposition = editor.SelectionStart
+ local endposition = editor.SelectionEnd
+
+ if startposition == endposition then return end
+
+ -- local startcolumn = column_of_position(startposition)
+ -- local endcolumn = column_of_position(endposition)
+ --
+ -- editor:SetSel(startposition,endposition)
+
+ local startline = props['SelectionStartLine']
+ local endline = props['SelectionEndLine']
+ local startcolumn = props['SelectionStartColumn'] - 1
+ local endcolumn = props['SelectionEndColumn'] - 1
+
+ startposition = extend_to_start()
+ endposition = extend_to_end()
+
+ local selection = string.gsub(editor:GetSelText(), "%s*$", '')
+
+ list = string.grab(selection,"[^\n\r]+")
+ table.alphasort(list, startcolumn)
+ local replacement = table.concat(list, "\n")
+
+ editor:GotoPos(startposition)
+ editor:SetSel(startposition,endposition)
+
+ if endcolumn == 0 then replacement = replacement .. "\n" end
+
+ editor:ReplaceSel(replacement)
+
+end
+
+function document_text()
+
+ local startposition = editor.SelectionStart
+ local endposition = editor.SelectionEnd
+
+ if startposition == endposition then return end
+
+ startposition = extend_to_start()
+ endposition = extend_to_end()
+
+ editor:SetSel(startposition,endposition)
+
+ local filetype = getfiletype()
+
+ local replacement = ''
+ for i = editor:LineFromPosition(startposition), editor:LineFromPosition(endposition) do
+ local str = editor:GetLine(i)
+ if filetype == 'xml' then
+ if str:find("^<%!%-%- .* %-%->%s*$") then
+ replacement = replacement .. str:gsub("^<%!%-%- (.*) %-%->(%s*)$","%1\n")
+ elseif not str:is_empty() then
+ replacement = replacement .. '<!-- ' .. str:gsub("(%s*)$",'') .. " -->\n"
+ else
+ replacement = replacement .. str
+ end
+ else
+ if str:find("^%%D%s+$") then
+ replacement = replacement .. "\n"
+ elseif str:find("^%%D ") then
+ replacement = replacement .. str:gsub("^%%D ",'')
+ else
+ replacement = replacement .. '%D ' .. str
+ end
+ end
+ end
+
+ editor:ReplaceSel(replacement:gsub("[\n\r]$",''))
+
+end
+
+function quote_text()
+
+ local filetype, leftquotation, rightquotation = getfiletype(), '', ''
+
+ if filetype == 'xml' then
+ leftquotation, rightquotation = "<quotation>", "</quotation>"
+ leftquote, rightquote = "<quotation>", "</quote>"
+ else
+ leftquotation, rightquotation = "\\quotation {", "}"
+ leftquote, rightquote = "\\quote {", "}"
+ end
+
+ local replacement = editor:GetSelText()
+ replacement = replacement.gsub("\`\`(.-)\'\'", leftquotation .. "%1" .. rightquotation)
+ replacement = replacement.gsub("\"(.-)\"", leftquotation .. "%1" .. rightquotation)
+ replacement = replacement.gsub("\`(.-)\'", leftquote .. "%1" .. rightquote )
+ replacement = replacement.gsub("\'(.-)\'", leftquote .. "%1" .. rightquote )
+ editor:ReplaceSel(replacement)
+
+end
+
+function compound_text()
+
+ local filetype = getfiletype()
+
+ if filetype == 'xml' then
+ editor:ReplaceSel(string.gsub(editor:GetSelText(),"(>[^<%-][^<%-]+)([-\/])(%w%w+)","%1<compound token='%2'/>%3"))
+ else
+ editor:ReplaceSel(string.gsub(editor:GetSelText(),"([^\|])([-\/]+)([^\|])","%1|%2|%3"))
+ end
+
+end
+
+-- written while listening to Alanis Morissette's acoustic
+-- Jagged Little Pill and Tori Amos' Beekeeper after
+-- reinstalling on my good old ATH-7
+
+local language = props["ctx.spellcheck.language"]
+local wordsize = props["ctx.spellcheck.wordsize"]
+local wordpath = props["ctx.spellcheck.wordpath"]
+
+if language == '' then language = 'uk' end
+if wordsize == '' then wordsize = 4 else wordsize = tonumber(wordsize) end
+
+local wordfile = ""
+local wordlist = {}
+local worddone = 0
+
+-- we use wordlist as a hash so that we can add entries without the
+-- need to sort and also use a fast (built in) search
+
+-- function kpsewhich_file(filename,filetype,progname)
+-- local progflag, typeflag = '', ''
+-- local tempname = os.tmpname()
+-- if progname then
+-- progflag = " --progname=" .. progname .. " "
+-- end
+-- if filetype then
+-- typeflag = " --format=" .. filetype .. " "
+-- end
+-- local command = "kpsewhich" .. progflag .. typeflag .. " " .. filename .. " > " .. tempname
+-- os.execute(command)
+-- for line in io.lines(tempname) do
+-- return string.gsub(line, "\s*$", '')
+-- end
+-- end
+
+function check_text()
+
+ local dlanguage = props["ctx.spellcheck.language"]
+ local dwordsize = props["ctx.spellcheck.wordsize"]
+ local dwordpath = props["ctx.spellcheck.wordpath"]
+
+ if dlanguage ~= '' then dlanguage = tostring(language) end
+ if dwordsize ~= '' then dwordsize = tonumber(wordsize) end
+
+ local firstline, skipfirst = editor:GetLine(0), false
+ local filetype, wordskip, wordgood = getfiletype(), '', ''
+
+ if filetype == 'tex' then
+ wordskip = "\\"
+ elseif filetype == 'xml' then
+ wordskip = "<"
+ wordgood = ">"
+ end
+
+ if props["ctx.spellcheck.language"] == 'auto' then
+ if filetype == 'tex' then
+ -- % version =1.0 language=uk
+ firstline = firstline:gsub("^%%%s*",'')
+ firstline = firstline:gsub("%s*$",'')
+ for key, val in firstline:gmatch("(%w+)=(%w+)") do
+ if key == "language" then
+ language = val
+ traceln("auto document language " .. "'" .. language .. "' (tex)")
+ end
+ end
+ skipfirst = true
+ elseif filetype == 'xml' then
+ -- <?xml version='1.0' language='uk' ?>
+ firstline = firstline:gsub("^%<%?xml%s*", '')
+ firstline = firstline:gsub("%s*%?%>%s*$", '')
+ for key, val in firstline:gmatch("(%w+)=[\"\'](.-)[\"\']") do
+ if key == "language" then
+ language = val
+ traceln("auto document language " .. "'" .. language .. "' (xml)")
+ end
+ end
+ skipfirst = true
+ end
+ end
+
+ local fname = props["ctx.spellcheck.wordfile." .. language]
+ local fsize = props["ctx.spellcheck.wordsize." .. language]
+
+ if fsize ~= '' then wordsize = tonumber(fsize) end
+
+ if fname ~= '' and fname ~= wordfile then
+ wordfile, worddone, wordlist = fname, 0, {}
+ for filename in wordfile:gmatch("[^%,]+") do
+ if wordpath ~= '' then
+ filename = string.expand(wordpath) .. '/' .. filename
+ end
+ if io.exists(filename) then
+ traceln("loading " .. filename)
+ for line in io.lines(filename) do
+ if not line:find("^[\%\#\-]") then
+ str = line:gsub("%s*$", '')
+ rawset(wordlist,str,true)
+ worddone = worddone + 1
+ end
+ end
+ else
+ traceln("unknown file '" .. filename .."'")
+ end
+ end
+ traceln(worddone .. " words loaded")
+ end
+
+ reset_text()
+
+ if worddone == 0 then
+ traceln("no (valid) language or wordfile specified")
+ else
+ traceln("start checking")
+ if wordskip ~= '' then
+ traceln("ignoring " .. wordskip .. "..." .. wordgood)
+ end
+ local i, j, lastpos, startpos, endpos, snippet, len, first = 0, 0, -1, 0, 0, '', 0, 0
+ local ok, skip, ch = false, false, ''
+ if skipfirst then first = #firstline end
+ for k = first, editor.TextLength do
+ ch = editor:textrange(k,k+1)
+ if wordgood ~= '' and ch == wordgood then
+ skip = false
+ elseif ch == wordskip then
+ skip = true
+ end
+ if ch:find("%w") and not ch:find("%d") then
+ if not skip then
+ if ok then
+ endpos = k
+ else
+ startpos = k
+ endpos = k
+ ok = true
+ end
+ end
+ elseif ok and not skip then
+ len = endpos - startpos + 1
+ if len >= wordsize then
+ snippet = editor:textrange(startpos,endpos+1)
+ i = i + 1
+ if wordlist[snippet] or wordlist[snippet:lower()] then -- table.found(wordlist,snippet)
+ j = j + 1
+ else
+ editor:StartStyling(startpos,INDICS_MASK)
+ editor:SetStyling(len,INDIC2_MASK) -- INDIC0_MASK+2
+ end
+ end
+ ok = false
+ elseif wordgood == '' then
+ skip = (ch == wordskip)
+ end
+ end
+ traceln(i .. " words checked, " .. (i-j) .. " errors")
+ end
+
+end
+
+function reset_text()
+ editor:StartStyling(0,INDICS_MASK)
+ editor:SetStyling(editor.TextLength,INDIC_PLAIN)
+end
+
+-- menu
+
+local menuactions = {}
+local menufunctions = {}
+
+function UserListShow(menutrigger, menulist)
+ local menuentries = {}
+ local list = string.grab(menulist,"[^%|]+")
+ menuactions = {}
+ for i=1, #list do
+ if list[i] ~= '' then
+ for key, val in list[i]:gmatch("%s*(.+)=(.+)%s*") do
+ menuentries[#menuentries+1] = key
+ menuactions[key] = val
+ end
+ end
+ end
+ local menustring = table.concat(menuentries,'|')
+ if menustring == "" then
+ traceln("There are no templates defined for this file type.")
+ else
+ editor.AutoCSeparator = string.byte('|')
+ editor:UserListShow(menutrigger,menustring)
+ editor.AutoCSeparator = string.byte(' ')
+ end
+end
+
+function OnUserListSelection(trigger,choice)
+ if menufunctions[trigger] and menuactions[choice] then
+ return menufunctions[trigger](menuactions[choice])
+ else
+ return false
+ end
+end
+
+-- main menu
+
+local menutrigger = 12
+
+function show_menu(menulist)
+ UserListShow(menutrigger, menulist)
+end
+
+function process_menu(action)
+ if not action:find("%(%)$") then
+ assert(loadstring(action .. "()"))()
+ else
+ assert(loadstring(action))()
+ end
+end
+
+menufunctions[12] = process_menu
+
+-- templates
+
+local templatetrigger = 13
+
+local ctx_template_paths = { "./ctx-templates", "../ctx-templates", "../../ctx-templates" }
+local ctx_auto_templates = false
+local ctx_template_list = ""
+
+local ctx_path_list = {}
+local ctx_path_done = {}
+local ctx_path_name = {}
+
+function ctx_list_loaded(path)
+ return ctx_path_list[path] and #ctx_path_list[path] > 0
+end
+
+function insert_template(templatelist)
+ if props["ctx.template.scan"] == "yes" then
+ local path = props["FileDir"]
+ local rescan = props["ctx.template.rescan"] == "yes"
+ local suffix = props["ctx.template.suffix." .. props["FileExt"]] -- alas, no suffix expansion here
+ local current = path .. "+" .. props["FileExt"]
+ if rescan then
+ print("re-scanning enabled")
+ end
+ ctx_template_list = ""
+ if not ctx_path_done[path] or rescan then
+ local pattern = "*.*"
+ for i, pathname in ipairs(ctx_template_paths) do
+ print("scanning " .. path:gsub("\\","/") .. "/" .. pathname)
+ ctx_path_name[path] = pathname
+ ctx_path_list[path] = get_dir_list(pathname .. "/" .. pattern)
+ if ctx_list_loaded(path) then
+ print("finished locating template files")
+ break
+ end
+ end
+ if ctx_list_loaded(path) then
+ print(#ctx_path_list[path] .. " template files found")
+ else
+ print("no template files found")
+ end
+ end
+ if ctx_list_loaded(path) then
+ ctx_template_list = ""
+ local pattern = "%." .. suffix .. "$"
+ local n = 0
+ for j, filename in ipairs(ctx_path_list[path]) do
+ if filename:find(pattern) then
+ n = n + 1
+ local menuname = filename:gsub("%..-$","")
+ if ctx_template_list ~= "" then
+ ctx_template_list = ctx_template_list .. "|"
+ end
+ ctx_template_list = ctx_template_list .. menuname .. "=" .. ctx_path_name[path] .. "/" .. filename
+ end
+ end
+ if not ctx_path_done[path] then
+ print(n .. " suitable template files found")
+ end
+ end
+ ctx_path_done[path] = true
+ if ctx_template_list == "" then
+ ctx_auto_templates = false
+ else
+ ctx_auto_templates = true
+ templatelist = ctx_template_list
+ end
+ else
+ ctx_auto_templates = false
+ end
+ if templatelist ~= "" then
+ UserListShow(templatetrigger, templatelist)
+ end
+end
+
+
+-- ctx.template.[whatever].[filetype]
+-- ctx.template.[whatever].data.[filetype]
+-- ctx.template.[whatever].file.[filetype]
+-- ctx.template.[whatever].list.[filetype]
+
+function process_template_one(action)
+ local text = nil
+ if ctx_auto_templates then
+ local f = io.open(action,"r")
+ if f then
+ text = string.gsub(f:read("*all"),"\n$","")
+ f:close()
+ else
+ print("unable to auto load template file " .. text)
+ text = nil
+ end
+ end
+ if not text or text == "" then
+ text = props["ctx.template." .. action .. ".file"]
+ if not text or text == "" then
+ text = props["ctx.template." .. action .. ".data"]
+ if not text or text == "" then
+ text = props["ctx.template." .. action]
+ end
+ else
+ local f = io.open(text,"r")
+ if f then
+ text = string.gsub(f:read("*all"),"\n$","")
+ f:close()
+ else
+ print("unable to load template file " .. text)
+ text = nil
+ end
+ end
+ end
+ if text then
+ text = text:gsub("\\n","\n")
+ local pos = text:find("%?")
+ text = text:gsub("%?","")
+ editor:insert(editor.CurrentPos,text)
+ if pos then
+ editor.CurrentPos = editor.CurrentPos + pos - 1
+ editor.SelectionStart = editor.CurrentPos
+ editor.SelectionEnd = editor.CurrentPos
+ editor:GotoPos(editor.CurrentPos)
+ end
+ end
+end
+
+menufunctions[13] = process_template_one
+menufunctions[14] = process_template_two
+
+-- command.name.26.*=Open Logfile
+-- command.subsystem.26.*=3
+-- command.26.*=open_log
+-- command.save.before.26.*=2
+-- command.groupundo.26.*=yes
+-- command.shortcut.26.*=Ctrl+E
+
+function open_log()
+ scite.Open(props['FileName'] .. ".log")
+end
diff --git a/scripts/context/perl/makempy.pl b/scripts/context/perl/makempy.pl
index f263dd425..7cba2e1a6 100644
--- a/scripts/context/perl/makempy.pl
+++ b/scripts/context/perl/makempy.pl
@@ -289,7 +289,7 @@ sub construct_mpy_file
{ error("unable to open $mpyfile file") }
print MPY "% mpochecksum : $mpochecksum\n" ;
my $copying = my $n = 0 ;
- while (<TMP>)
+ while (<TMP>) # a simple sub is faster
{ if (s/beginfig/begingraphictextfig/o)
{ print MPY $_ ; $copying = 1 ; ++$n }
elsif (s/endfig/endgraphictextfig/o)
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index 7b379151a..a2e747902 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -17,6 +17,8 @@ if not modules then modules = { } end modules ['attr-ini'] = {
nodes = nodes or { }
+local format, concat = string.format, table.concat
+
-- This is not the most ideal place, but it will do. Maybe we need to move
-- attributes to node-att.lua.
@@ -222,7 +224,7 @@ do
end
end
else
- texio.write_nl(string.format("undefined attribute %s",name))
+ texio.write_nl(format("undefined attribute %s",name))
end
end
if done then
@@ -482,9 +484,6 @@ function states.collect(str)
end
function states.flush()
---~ for _, c in ipairs(states.collected) do
---~ tex.sprint(tex.ctxcatcodes,c)
---~ end
local collected = states.collected
if #collected > 0 then
for i=1,#collected do
@@ -495,7 +494,7 @@ function states.flush()
end
function states.check()
- texio.write_nl(table.concat(states.collected,"\n"))
+ texio.write_nl(concat(states.collected,"\n"))
end
--
@@ -529,7 +528,7 @@ colors.triggering = true
-- colors.strings = colors.strings or { }
--
-- if environment.initex then
--- colors.strings[color] = "return colors." .. colorspace .. "(" .. table.concat({...},",") .. ")"
+-- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")"
-- end
--
-- input.storage.register(true,"colors/data", colors.strings, "colors.data") -- evaluated
@@ -557,10 +556,8 @@ colors.model = "all"
do
- local min = math.min
- local max = math.max
- local format = string.format
- local concat = table.concat
+ local min = math.min
+ local max = math.max
local function rgbdata(r,g,b) -- dodo: backends.pdf.rgbdata
return backends.pdf.literal(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b))
@@ -644,7 +641,7 @@ do
if not v then
local gray = graydata(0)
d = { gray, gray, gray, gray }
- logs.report("attributes",string.format("unable to revive color %s",n or "?"))
+ logs.report("attributes",format("unable to revive color %s",n or "?"))
else
local kind, gray, rgb, cmyk = v[1], graydata(v[2]), rgbdata(v[3],v[4],v[5]), cmykdata(v[6],v[7],v[8],v[9])
if kind == 2 then
@@ -679,7 +676,7 @@ function colors.setmodel(attribute,name)
end
function colors.register(attribute, name, colorspace, ...) -- passing 9 vars is faster
- local stamp = string.format(colors.stamps[colorspace], ...)
+ local stamp = format(colors.stamps[colorspace], ...)
local color = colors.registered[stamp]
if not color then
color = #colors.values+1
@@ -722,18 +719,18 @@ input.storage.register(false, "transparencies/registered", transparencies.regist
input.storage.register(false, "transparencies/values", transparencies.values, "transparencies.values")
function transparencies.reference(n)
- return backends.pdf.literal(string.format("/Tr%s gs",n))
+ return backends.pdf.literal(format("/Tr%s gs",n))
end
function transparencies.register(name,a,t)
- local stamp = string.format(transparencies.template,a,t)
+ local stamp = format(transparencies.template,a,t)
local n = transparencies.registered[stamp]
if not n then
n = #transparencies.data+1
transparencies.data[n] = transparencies.reference(n)
transparencies.values[n] = { a, t }
transparencies.registered[stamp] = n
- states.collect(string.format("\\presetPDFtransparencybynumber{%s}{%s}{%s}",n,a,t)) -- too many, but experimental anyway
+ states.collect(format("\\presetPDFtransparencybynumber{%s}{%s}{%s}",n,a,t)) -- too many, but experimental anyway
end
return transparencies.registered[stamp]
end
@@ -744,10 +741,10 @@ function transparencies.reviver(n)
local v = transparencies.values[n]
if not v then
d = transparencies.reference(0)
- logs.report("attributes",string.format("unable to revive transparency %s",n or "?"))
+ logs.report("attributes",format("unable to revive transparency %s",n or "?"))
else
d = transparencies.reference(n)
- states.collect(string.format("\\presetPDFtransparencybynumber{%s}{%s}{%s}",n,v[1],v[2]))
+ states.collect(format("\\presetPDFtransparencybynumber{%s}{%s}{%s}",n,v[1],v[2]))
end
transparencies.data[n] = d
end
@@ -777,8 +774,8 @@ overprints = overprints or { }
overprints.data = overprints.data or { }
overprints.enabled = false
-overprints.data[1] = backends.pdf.literal(string.format("/GSoverprint gs"))
-overprints.data[2] = backends.pdf.literal(string.format("/GSknockout gs"))
+overprints.data[1] = backends.pdf.literal(format("/GSoverprint gs"))
+overprints.data[2] = backends.pdf.literal(format("/GSknockout gs"))
overprints.none = overprints.data[1]
@@ -805,8 +802,8 @@ negatives = netatives or { }
negatives.data = negatives.data or { }
negatives.enabled = false
-negatives.data[1] = backends.pdf.literal(string.format("/GSpositive gs"))
-negatives.data[2] = backends.pdf.literal(string.format("/GSnegative gs"))
+negatives.data[1] = backends.pdf.literal(format("/GSpositive gs"))
+negatives.data[2] = backends.pdf.literal(format("/GSnegative gs"))
negatives.none = negatives.data[1]
@@ -839,7 +836,7 @@ input.storage.register(false, "effects/registered", effects.registered, "effects
input.storage.register(false, "effects/data", effects.data, "effects.data")
function effects.register(effect,stretch,rulethickness)
- local stamp = string.format(effects.stamp,effect,stretch,rulethickness)
+ local stamp = format(effects.stamp,effect,stretch,rulethickness)
local n = effects.registered[stamp]
if not n then
n = #effects.data+1
@@ -862,7 +859,7 @@ function effects.reference(effect,stretch,rulethickness)
-- always, no zero test (removed)
rulethickness = number.dimenfactors["bp"]*rulethickness
effect = backends.pdf.effects[effect] or backends.pdf.effects['normal']
- return backends.pdf.literal(string.format("%s Tc %s w %s Tr",stretch,rulethickness,effect)) -- watch order
+ return backends.pdf.literal(format("%s Tc %s w %s Tr",stretch,rulethickness,effect)) -- watch order
end
effects.none = effects.reference(0,0,0) -- faster: backends.pdf.literal("0 Tc 0 w 0 Tr")
diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua
index 59f8ed4ac..b4ca759bf 100644
--- a/tex/context/base/char-def.lua
+++ b/tex/context/base/char-def.lua
@@ -226,6 +226,7 @@ characters.data={
["adobename"]="quotedbl",
["category"]="po",
["cjkwd"]="na",
+ ["contextname"]="quotedbl",
["description"]="QUOTATION MARK",
["linebreak"]="qu",
["unicodeslot"]=0x0022, -- "
@@ -792,6 +793,8 @@ characters.data={
["cjkwd"]="na",
["contextname"]="textasciicircum",
["description"]="CIRCUMFLEX ACCENT",
+ ["mathclass"]="accent",
+ ["mathname"]="widehat",
["linebreak"]="al",
["unicodeslot"]=0x005E, -- ^
},
@@ -1088,6 +1091,7 @@ characters.data={
["adobename"]="bar",
["category"]="sm",
["cjkwd"]="na",
+ ["contextname"]="textbar",
["description"]="VERTICAL LINE",
["linebreak"]="ba",
["mathclass"]="binary",
@@ -1112,6 +1116,8 @@ characters.data={
["contextname"]="textasciitilde",
["description"]="TILDE",
["linebreak"]="al",
+ ["mathclass"]="accent",
+ ["mathname"]="widetilde",
["unicodeslot"]=0x007E, -- ~
},
{
@@ -8129,7 +8135,7 @@ characters.data={
["description"]="GREEK SMALL LETTER EPSILON",
["linebreak"]="al",
["mathclass"]="variable",
- ["mathname"]="varepsilon",
+ ["mathname"]="epsilon",
["uccode"]=0x0395,
["unicodeslot"]=0x03B5, -- ε
},
@@ -8475,6 +8481,7 @@ characters.data={
["description"]="GREEK PHI SYMBOL",
["linebreak"]="al",
["mathclass"]="variable",
+ ["mathname"]="phi",
["specials"]={ "compat", 0x03C6 },
["uccode"]=0x03A6,
["unicodeslot"]=0x03D5, -- ϕ
@@ -8717,6 +8724,8 @@ characters.data={
["contextname"]="greekepsilonalt",
["description"]="GREEK LUNATE EPSILON SYMBOL",
["linebreak"]="al",
+ ["mathclass"]="variable",
+ ["mathname"]="varepsilon",
["specials"]={ "compat", 0x03B5 },
["uccode"]=0x0395,
["unicodeslot"]=0x03F5, -- ϵ
@@ -45705,6 +45714,8 @@ characters.data={
["cjkwd"]="a",
["description"]="N-ARY PRODUCT",
["linebreak"]="ai",
+ ["mathclass"]="limop",
+ ["mathname"]="prod",
["unicodeslot"]=0x220F, -- ∏
},
[0x2210]={
@@ -45719,6 +45730,8 @@ characters.data={
["cjkwd"]="a",
["description"]="N-ARY SUMMATION",
["linebreak"]="ai",
+ ["mathclass"]="limop",
+ ["mathname"]="sum",
["unicodeslot"]=0x2211, -- ∑
},
[0x2212]={
@@ -45903,6 +45916,8 @@ characters.data={
["cjkwd"]="a",
["description"]="INTEGRAL",
["linebreak"]="ai",
+ ["mathclass"]="limop",
+ ["mathname"]="intop",
["unicodeslot"]=0x222B, -- ∫
},
[0x222C]={
diff --git a/tex/context/base/char-def.tex b/tex/context/base/char-def.tex
index 1c0b061dc..39137241d 100644
--- a/tex/context/base/char-def.tex
+++ b/tex/context/base/char-def.tex
@@ -29,8 +29,9 @@
%D The codes are stored in the format, so we don't need to reinitialize
%D them (unless of course we have adapted the table).
+\ctxlua{characters.setcodes()}
+
% \startruntimeluacode
- \ctxlua{characters.setcodes()}
% \ctxlua{characters.setpdfunicodes()}% pdftounicode mappings can only be done runtime
% \stopruntimeluacode
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 4750e929a..f44eb8aca 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -9,9 +9,7 @@ if not modules then modules = { } end modules ['char-ini'] = {
utf = utf or unicode.utf
tex = tex or { }
-function tex.ctxprint(...)
- tex.sprint(tex.ctxcatcodes,...)
-end
+local format = string.format
--[[ldx--
<p>This module implements some methods and creates additional datastructured
@@ -133,9 +131,9 @@ function characters.context.show(n)
local d = characters.data[n]
if d then
local function entry(label,name)
- tex.ctxprint(string.format("\\NC %s\\NC %s\\NC\\NR",label,characters.valid(d[name])))
+ tex.sprint(tex.ctxcatcodes,format("\\NC %s\\NC %s\\NC\\NR",label,characters.valid(d[name])))
end
- tex.ctxprint("\\starttabulate[|Tl|Tl|]")
+ tex.sprint(tex.ctxcatcodes,"\\starttabulate[|Tl|Tl|]")
entry("unicode index" , "unicodeslot")
entry("context name" , "contextname")
entry("adobe name" , "adobename")
@@ -144,7 +142,7 @@ function characters.context.show(n)
entry("uppercase code", "uccode")
entry("lowercase code", "lccode")
entry("specials" , "specials")
- tex.ctxprint("\\stoptabulate ")
+ tex.sprint(tex.ctxcatcodes,"\\stoptabulate ")
end
end
@@ -154,7 +152,7 @@ use the table. After all, we have this information available anyway.</p>
--ldx]]--
function characters.makeactive(n,name)
- tex.sprint(string.format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utf.char(n),name))
+ tex.sprint(tex.ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utf.char(n),name))
end
function tex.uprint(n)
@@ -226,14 +224,14 @@ end
--ldx]]--
function characters.setcodes()
- local flush, tc = tex.sprint, tex.ctxcatcodes
+ local flush, tc, format = tex.sprint, tex.ctxcatcodes, string.format
for code, chr in pairs(characters.data) do
local cc = chr.category
if cc == 'll' or cc == 'lu' or cc == 'lt' then
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
- flush(tc, '\\setcclcuc '.. code .. ' ' .. lc .. ' ' .. uc .. ' ')
+ flush(tc, format("\\setcclcuc %i %i %i ",code,lc,uc))
end
end
end
@@ -298,7 +296,7 @@ to the checking.</p>
--ldx]]--
function characters.hexindex(n)
- return string.format("%04X", characters.valid(characters.data[characters.number(n)].unicodeslot))
+ return format("%04X", characters.valid(characters.data[characters.number(n)].unicodeslot))
end
function characters.contextname(n)
@@ -391,7 +389,6 @@ characters.pdftex.make_pdf_to_unicodetable("pdfr-def.tex")
characters.pdftex = characters.pdftex or { }
function characters.pdftex.make_pdf_to_unicodetable(filename)
---~ local sf = string.format
--~ f = io.open(filename,'w')
--~ if f then
--~ f:write("% This file is generated with Luatex using the\n")
@@ -400,7 +397,7 @@ function characters.pdftex.make_pdf_to_unicodetable(filename)
--~ f:write("\\ifx\\pdfglyphtounicode\\undefined\\endinput\\fi\n") -- just to be sure
--~ for _, v in pairs(characters.data) do
--~ if v.adobename then
---~ f:write(sf("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot))
+--~ f:write(format("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot))
--~ end
--~ end
--~ f:write("%\n")
diff --git a/tex/context/base/char-utf.tex b/tex/context/base/char-utf.tex
index 68036bf4c..2e7156962 100644
--- a/tex/context/base/char-utf.tex
+++ b/tex/context/base/char-utf.tex
@@ -35,15 +35,17 @@
}%
\to \everyjob
-%D This is a hack, and only meant for special situations. We don't
-%D support this in for instance verbatim. The active characters map
-%D onto the \CONTEXT\ names and font handling etc. is up to the user.
-
-\registerctxluafile{char-act}{1.001}
-
-\def\enableactiveutf {\ctxlua{characters.active.enable()}}
-\def\disableactiveutf{\ctxlua{characters.active.disable()}}
-\def\testactiveutf #1{\ctxlua{characters.active.test("#1")}}
+% %D This is a hack, and only meant for special situations. We don't
+% %D support this in for instance verbatim. The active characters map
+% %D onto the \CONTEXT\ names and font handling etc. is up to the user.
+%
+% %D This feature is obsolete.
+%
+% \registerctxluafile{char-act}{1.001}
+%
+% \def\enableactiveutf {\ctxlua{characters.active.enable()}}
+% \def\disableactiveutf{\ctxlua{characters.active.disable()}}
+% \def\testactiveutf #1{\ctxlua{characters.active.test("#1")}}
%D Usage:
%D
diff --git a/tex/context/base/colo-new.lua b/tex/context/base/colo-new.lua
index d039e47c7..fb1457070 100644
--- a/tex/context/base/colo-new.lua
+++ b/tex/context/base/colo-new.lua
@@ -22,160 +22,152 @@ backends = backends or { }
backends.pdf = backends.pdf or { }
backend = backends.pdf
-do
+local texsprint, format, concat = tex.sprint, string.format, table.concat
- -- maybe combine spotcolorname
+local s_template_g = "\\dodoPDFregistergrayspotcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
+local s_template_r = "\\dodoPDFregisterrgbspotcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
+local s_template_c = "\\dodoPDFregistercmykspotcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
- local s_template_g = "\\dodoPDFregistergrayspotcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
- local s_template_r = "\\dodoPDFregisterrgbspotcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
- local s_template_c = "\\dodoPDFregistercmykspotcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
+function backends.pdf.registergrayspotcolor(n,f,d,p,s) states.collect(s_template_g:format(n,f,d,p,s)) end
+function backends.pdf.registerrgbspotcolor (n,f,d,p,r,g,b) states.collect(s_template_r:format(n,f,d,p,r,g,b)) end
+function backends.pdf.registercmykspotcolor(n,f,d,p,c,m,y,k) states.collect(s_template_c:format(n,f,d,p,c,m,y,k)) end
- function backends.pdf.registergrayspotcolor(n,f,d,p,s) states.collect(s_template_g:format(n,f,d,p,s)) end
- function backends.pdf.registerrgbspotcolor (n,f,d,p,r,g,b) states.collect(s_template_r:format(n,f,d,p,r,g,b)) end
- function backends.pdf.registercmykspotcolor(n,f,d,p,c,m,y,k) states.collect(s_template_c:format(n,f,d,p,c,m,y,k)) end
+local m_template_g = "\\doPDFregistergrayindexcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
+local m_template_r = "\\doPDFregisterrgbindexcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
+local m_template_c = "\\doPDFregistercmykindexcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
- local m_template_g = "\\doPDFregistergrayindexcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
- local m_template_r = "\\doPDFregisterrgbindexcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
- local m_template_c = "\\doPDFregistercmykindexcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
+function backends.pdf.registergrayindexcolor(n,f,d,p,s) states.collect(m_template_g:format(n,f,d,p,s)) end
+function backends.pdf.registerrgbindexcolor (n,f,d,p,r,g,b) states.collect(m_template_r:format(n,f,d,p,r,g,b)) end
+function backends.pdf.registercmykindexcolor(n,f,d,p,c,m,y,k) states.collect(m_template_c:format(n,f,d,p,c,m,y,k)) end
- function backends.pdf.registergrayindexcolor(n,f,d,p,s) states.collect(m_template_g:format(n,f,d,p,s)) end
- function backends.pdf.registerrgbindexcolor (n,f,d,p,r,g,b) states.collect(m_template_r:format(n,f,d,p,r,g,b)) end
- function backends.pdf.registercmykindexcolor(n,f,d,p,c,m,y,k) states.collect(m_template_c:format(n,f,d,p,c,m,y,k)) end
+local s_template_e = "\\doPDFregisterspotcolorname{%s}{%s}" -- name, e
- local s_template_e = "\\doPDFregisterspotcolorname{%s}{%s}" -- name, e
-
- function backends.pdf.registerspotcolorname(name,e)
- if e and e ~= "" then
- tex.sprint(tex.ctxcatcodes,string.format(s_template_e,name,e)) -- todo in new backend: e:gsub(" ","#20")
- end
+function backends.pdf.registerspotcolorname(name,e)
+ if e and e ~= "" then
+ texsprint(tex.ctxcatcodes,format(s_template_e,name,e)) -- todo in new backend: e:gsub(" ","#20")
end
-
end
ctx = ctx or { }
ctx.aux = ctx.aux or { }
-do
-
- local format, sprint = string.format, tex.sprint
-
- local a_l_c_template = "\\setevalue{(ca:%s)}{%s}" ..
- "\\setevalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
- local a_g_c_template = "\\setxvalue{(ca:%s)}{%s}" ..
- "\\setxvalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
- local f_l_c_template = "\\setvalue {(ca:%s)}{\\doinheritca{%s}}" ..
- "\\setvalue {(cs:%s)}{\\doinheritcs{%s}}"
- local f_g_c_template = "\\setgvalue{(ca:%s)}{\\doinheritca{%s}}" ..
- "\\setgvalue{(cs:%s)}{\\doinheritcs{%s}}"
- local r_l_c_template = "\\letbeundefined{(ca:%s)}" ..
- "\\letbeundefined{(cs:%s)}"
- local r_g_c_template = "\\global\\letbeundefined{(ca:%s)}" ..
- "\\global\\letbeundefined{(cs:%s)}"
-
- local a_l_t_template = "\\setevalue{(ta:%s)}{%s}" ..
- "\\setevalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
- local a_g_t_template = "\\setxvalue{(ta:%s)}{%s}" ..
- "\\setxvalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
- local f_l_t_template = "\\setvalue {(ta:%s)}{\\doinheritta{%s}}" ..
- "\\setvalue {(ts:%s)}{\\doinheritts{%s}}"
- local f_g_t_template = "\\setgvalue{(ta:%s)}{\\doinheritta{%s}}" ..
- "\\setgvalue{(ts:%s)}{\\doinheritts{%s}}"
- local r_l_t_template = "\\letbeundefined{(ta:%s)}" ..
- "\\letbeundefined{(ts:%s)}"
- local r_g_t_template = "\\global\\letbeundefined{(ta:%s)}" ..
- "\\global\\letbeundefined{(ts:%s)}"
-
- function ctx.aux.definecolor(name, ca, global)
- if ca and ca > 0 then
- if global then
- sprint(tex.ctxcatcodes,a_g_c_template:format(name, ca, name, ca))
- else
- sprint(tex.ctxcatcodes,a_l_c_template:format(name, ca, name, ca))
- end
+local a_l_c_template = "\\setevalue{(ca:%s)}{%s}" ..
+ "\\setevalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
+local a_g_c_template = "\\setxvalue{(ca:%s)}{%s}" ..
+ "\\setxvalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
+local f_l_c_template = "\\setvalue {(ca:%s)}{\\doinheritca{%s}}" ..
+ "\\setvalue {(cs:%s)}{\\doinheritcs{%s}}"
+local f_g_c_template = "\\setgvalue{(ca:%s)}{\\doinheritca{%s}}" ..
+ "\\setgvalue{(cs:%s)}{\\doinheritcs{%s}}"
+local r_l_c_template = "\\letbeundefined{(ca:%s)}" ..
+ "\\letbeundefined{(cs:%s)}"
+local r_g_c_template = "\\global\\letbeundefined{(ca:%s)}" ..
+ "\\global\\letbeundefined{(cs:%s)}"
+
+local a_l_t_template = "\\setevalue{(ta:%s)}{%s}" ..
+ "\\setevalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
+local a_g_t_template = "\\setxvalue{(ta:%s)}{%s}" ..
+ "\\setxvalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
+local f_l_t_template = "\\setvalue {(ta:%s)}{\\doinheritta{%s}}" ..
+ "\\setvalue {(ts:%s)}{\\doinheritts{%s}}"
+local f_g_t_template = "\\setgvalue{(ta:%s)}{\\doinheritta{%s}}" ..
+ "\\setgvalue{(ts:%s)}{\\doinheritts{%s}}"
+local r_l_t_template = "\\letbeundefined{(ta:%s)}" ..
+ "\\letbeundefined{(ts:%s)}"
+local r_g_t_template = "\\global\\letbeundefined{(ta:%s)}" ..
+ "\\global\\letbeundefined{(ts:%s)}"
+
+function ctx.aux.definecolor(name, ca, global)
+ if ca and ca > 0 then
+ if global then
+ texsprint(tex.ctxcatcodes,a_g_c_template:format(name, ca, name, ca))
else
- if global then
- sprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
- else
- sprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
- end
+ texsprint(tex.ctxcatcodes,a_l_c_template:format(name, ca, name, ca))
+ end
+ else
+ if global then
+ texsprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
+ else
+ texsprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
end
end
- function ctx.aux.inheritcolor(name, ca, global)
- if ca and ca ~= "" then
- if global then
- sprint(tex.ctxcatcodes,f_g_c_template:format(name, ca, name, ca))
- else
- sprint(tex.ctxcatcodes,f_l_c_template:format(name, ca, name, ca))
- end
+end
+function ctx.aux.inheritcolor(name, ca, global)
+ if ca and ca ~= "" then
+ if global then
+ texsprint(tex.ctxcatcodes,f_g_c_template:format(name, ca, name, ca))
else
- if global then
- sprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
- else
- sprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
- end
+ texsprint(tex.ctxcatcodes,f_l_c_template:format(name, ca, name, ca))
+ end
+ else
+ if global then
+ texsprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
+ else
+ texsprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
end
end
- function ctx.aux.definetransparent(name, ta, global)
- if ta and ta > 0 then
- if global then
- sprint(tex.ctxcatcodes,a_g_t_template:format(name, ta, name, ta))
- else
- sprint(tex.ctxcatcodes,a_l_t_template:format(name, ta, name, ta))
- end
+end
+function ctx.aux.definetransparent(name, ta, global)
+ if ta and ta > 0 then
+ if global then
+ texsprint(tex.ctxcatcodes,a_g_t_template:format(name, ta, name, ta))
else
- if global then
- sprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
- else
- sprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
- end
+ texsprint(tex.ctxcatcodes,a_l_t_template:format(name, ta, name, ta))
+ end
+ else
+ if global then
+ texsprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
+ else
+ texsprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
end
end
- function ctx.aux.inherittransparent(name, ta, global)
- if ta and ta ~= "" then
- if global then
- sprint(tex.ctxcatcodes,f_g_t_template:format(name, ta, name, ta))
- else
- sprint(tex.ctxcatcodes,f_l_t_template:format(name, ta, name, ta))
- end
+end
+function ctx.aux.inherittransparent(name, ta, global)
+ if ta and ta ~= "" then
+ if global then
+ texsprint(tex.ctxcatcodes,f_g_t_template:format(name, ta, name, ta))
else
- if global then
- sprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
- else
- sprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
- end
+ texsprint(tex.ctxcatcodes,f_l_t_template:format(name, ta, name, ta))
+ end
+ else
+ if global then
+ texsprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
+ else
+ texsprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
end
end
+end
- local transparent = {
- none = 0,
- normal = 1,
- multiply = 2,
- screen = 3,
- overlay = 4,
- softlight = 5,
- hardlight = 6,
- colordodge = 7,
- colorburn = 8,
- darken = 9,
- lighten = 10,
- difference = 11,
- exclusion = 12,
- }
-
- -- By coupling we are downward compatible. When we decouple we need to do more tricky
- -- housekeeping (e.g. persist color independent transparencies when color bound ones
- -- are nil.
-
- ctx.couplecolors = true
-
- function ctx.definetransparency(name,n)
- transparent[name] = n
- end
+local transparent = {
+ none = 0,
+ normal = 1,
+ multiply = 2,
+ screen = 3,
+ overlay = 4,
+ softlight = 5,
+ hardlight = 6,
+ colordodge = 7,
+ colorburn = 8,
+ darken = 9,
+ lighten = 10,
+ difference = 11,
+ exclusion = 12,
+}
+
+-- By coupling we are downward compatible. When we decouple we need to do more tricky
+-- housekeeping (e.g. persist color independent transparencies when color bound ones
+-- are nil.
+
+ctx.couplecolors = true
- local registered = { }
+function ctx.definetransparency(name,n)
+ transparent[name] = n
+end
+
+local registered = { }
- local function registerspotcolor(parent,name,parentnumber,e,f,d,p)
-if not registered[parentnumber] then
+local function registerspotcolor(parent,name,parentnumber,e,f,d,p)
+ if not registered[parentnumber] then
local v = colors.values[parentnumber]
if v then
local kind = v[1]
@@ -188,12 +180,12 @@ if not registered[parentnumber] then
end
backends.pdf.registerspotcolorname(parent,e)
end
- registered[parentnumber] = true
-end
+ registered[parentnumber] = true
end
+end
- local function registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
-if not registered[parentnumber] then
+local function registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
+ if not registered[parentnumber] then
local v = colors.values[parentnumber]
if v then
local kind = v[1]
@@ -205,359 +197,351 @@ if not registered[parentnumber] then
backend.registercmykindexcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
end
end
- registered[parentnumber] = true
-end
+ registered[parentnumber] = true
end
+end
- function ctx.definesimplegray(name,s)
- return colors.register('color',name,'gray',s) -- we still need to get rid of 'color'
- end
+function ctx.definesimplegray(name,s)
+ return colors.register('color',name,'gray',s) -- we still need to get rid of 'color'
+end
- function ctx.defineprocesscolor(name,str,global,freeze) -- still inconsistent color vs transparent
- local t = str:split_settings()
- if t then
- if t.h then
- local r, g, b =string.match(t.h .. "000000","(..)(..)(..)")
- ctx.aux.definecolor(name, colors.register('color',name,'rgb',(tonumber(r,16) or 0)/256,(tonumber(g,16) or 0)/256,(tonumber(b,16) or 0)/256 ), global)
- elseif t.r or t.g or t.b then
- ctx.aux.definecolor(name, colors.register('color',name,'rgb', tonumber(t.r) or 0, tonumber(t.g) or 0, tonumber(t.b) or 0 ), global)
- elseif t.c or t.m or t.y or t.k then
- ctx.aux.definecolor(name, colors.register('color',name,'cmyk',tonumber(t.c) or 0, tonumber(t.m) or 0, tonumber(t.y) or 0, tonumber(t.k) or 0), global)
- else
- ctx.aux.definecolor(name, colors.register('color',name,'gray',tonumber(t.s) or 0), global)
- end
- if t.a and t.t then
- ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
- elseif ctx.couplecolors then
---~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
- ctx.aux.definetransparent(name, 0, global) -- can be sped up
- end
- elseif freeze then
- local ca = attributes.list[attributes.numbers['color']] [str]
- local ta = attributes.list[attributes.numbers['transparency']][str]
- if ca then
- ctx.aux.definecolor(name, ca, global)
- end
- if ta then
- ctx.aux.definetransparent(name, ta, global)
- end
+function ctx.defineprocesscolor(name,str,global,freeze) -- still inconsistent color vs transparent
+ local t = str:split_settings()
+ if t then
+ if t.h then
+ local r, g, b =string.match(t.h .. "000000","(..)(..)(..)")
+ ctx.aux.definecolor(name, colors.register('color',name,'rgb',(tonumber(r,16) or 0)/256,(tonumber(g,16) or 0)/256,(tonumber(b,16) or 0)/256 ), global)
+ elseif t.r or t.g or t.b then
+ ctx.aux.definecolor(name, colors.register('color',name,'rgb', tonumber(t.r) or 0, tonumber(t.g) or 0, tonumber(t.b) or 0 ), global)
+ elseif t.c or t.m or t.y or t.k then
+ ctx.aux.definecolor(name, colors.register('color',name,'cmyk',tonumber(t.c) or 0, tonumber(t.m) or 0, tonumber(t.y) or 0, tonumber(t.k) or 0), global)
else
- ctx.aux.inheritcolor(name, str, global)
- ctx.aux.inherittransparent(name, str, global)
+ ctx.aux.definecolor(name, colors.register('color',name,'gray',tonumber(t.s) or 0), global)
+ end
+ if t.a and t.t then
+ ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
+ elseif ctx.couplecolors then
+--~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ ctx.aux.definetransparent(name, 0, global) -- can be sped up
+ end
+ elseif freeze then
+ local ca = attributes.list[attributes.numbers['color']] [str]
+ local ta = attributes.list[attributes.numbers['transparency']][str]
+ if ca then
+ ctx.aux.definecolor(name, ca, global)
end
+ if ta then
+ ctx.aux.definetransparent(name, ta, global)
+ end
+ else
+ ctx.aux.inheritcolor(name, str, global)
+ ctx.aux.inherittransparent(name, str, global)
end
+end
- function ctx.definespotcolor(name,parent,str,global)
- if parent == "" or parent:find("=") then
- ctx.registerspotcolor(name, parent)
- elseif name ~= parent then
- local cp = attributes.list[attributes.numbers['color']][parent]
- if cp then
- local t = str:split_settings()
- if t then
- t.p = tonumber(t.p) or 1
- registerspotcolor(parent, name, cp, t.e, 1, "", t.p) -- p not really needed, only diagnostics
- if name and name ~= "" then
- ctx.aux.definecolor(name, colors.register('color',name,'spot', parent, 1, "", t.p), true)
- if t.a and t.t then
- ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
- elseif ctx.couplecolors then
- --~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
- ctx.aux.definetransparent(name, 0, global) -- can be sped up
- end
+function ctx.definespotcolor(name,parent,str,global)
+ if parent == "" or parent:find("=") then
+ ctx.registerspotcolor(name, parent)
+ elseif name ~= parent then
+ local cp = attributes.list[attributes.numbers['color']][parent]
+ if cp then
+ local t = str:split_settings()
+ if t then
+ t.p = tonumber(t.p) or 1
+ registerspotcolor(parent, name, cp, t.e, 1, "", t.p) -- p not really needed, only diagnostics
+ if name and name ~= "" then
+ ctx.aux.definecolor(name, colors.register('color',name,'spot', parent, 1, "", t.p), true)
+ if t.a and t.t then
+ ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
+ elseif ctx.couplecolors then
+ --~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
end
end
end
end
+end
+
+function ctx.registerspotcolor(parent, str)
+ local cp = attributes.list[attributes.numbers['color']][parent]
+ if cp then
+ local e = ""
+ if str then
+ local t = str:split_settings()
+ e = (t and t.e) or ""
+ end
+ registerspotcolor(parent, "dummy", cp, e, 1, "", 1) -- p not really needed, only diagnostics
+ end
+end
- function ctx.registerspotcolor(parent, str)
+function ctx.definemultitonecolor(name,multispec,colorspec,selfspec)
+ local dd, pp, nn = { }, { }, { }
+ for k,v in multispec:gmatch("(%a+)=([^%,]*)") do
+ dd[#dd+1] = k
+ pp[#pp+1] = v
+ nn[#nn+1] = k
+ nn[#nn+1] = format("%1.3g",tonumber(v))
+ end
+--~ v = tonumber(v) * p
+ local nof = #dd
+ if nof > 0 then
+ dd, pp, nn = concat(dd,','), concat(pp,','), concat(nn,'_')
+ local parent = (nn:lower()):gsub("[^%d%a%.]+","_")
+ ctx.defineprocesscolor(parent,colorspec..","..selfspec,true,true)
local cp = attributes.list[attributes.numbers['color']][parent]
if cp then
- local e = ""
- if str then
- local t = str:split_settings()
- e = (t and t.e) or ""
+ registerspotcolor (parent, name, cp, "", nof, dd, pp)
+ registermultitonecolor(parent, name, cp, "", nof, dd, pp)
+ ctx.aux.definecolor(name, colors.register('color', name, 'spot', parent, nof, dd, pp), true)
+ local t = selfspec:split_settings()
+ if t and t.a and t.t then
+ ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
+ elseif ctx.couplecolors then
+ -- ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
- registerspotcolor(parent, "dummy", cp, e, 1, "", 1) -- p not really needed, only diagnostics
end
end
+end
- function ctx.definemultitonecolor(name,multispec,colorspec,selfspec)
- local dd, pp, nn = { }, { }, { }
- for k,v in multispec:gmatch("(%a+)=([^%,]*)") do
- dd[#dd+1] = k
- pp[#pp+1] = v
- nn[#nn+1] = k
- nn[#nn+1] = format("%1.3g",tonumber(v))
- end
- --~ v = tonumber(v) * p
- local nof = #dd
- if nof > 0 then
- dd, pp, nn = table.concat(dd,','), table.concat(pp,','), table.concat(nn,'_')
- local parent = (nn:lower()):gsub("[^%d%a%.]+","_")
- ctx.defineprocesscolor(parent,colorspec..","..selfspec,true,true)
- local cp = attributes.list[attributes.numbers['color']][parent]
- if cp then
- registerspotcolor (parent, name, cp, "", nof, dd, pp)
- registermultitonecolor(parent, name, cp, "", nof, dd, pp)
- ctx.aux.definecolor(name, colors.register('color', name, 'spot', parent, nof, dd, pp), true)
- local t = selfspec:split_settings()
- if t and t.a and t.t then
- ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
- elseif ctx.couplecolors then
- -- ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
- ctx.aux.definetransparent(name, 0, global) -- can be sped up
- end
- end
+function ctx.mpcolor(model,ca,ta,default)
+ local cv = colors.value(ca) -- faster when direct colors.values[ca]
+ if cv then
+ local tv = transparencies.value(ta)
+ if model == 1 then
+ model = cv[1]
end
- end
-
- function ctx.mpcolor(model,ca,ta,default)
- local cv = colors.value(ca) -- faster when direct colors.values[ca]
- if cv then
- local tv = transparencies.value(ta)
- if model == 1 then
- model = cv[1]
- end
- if tv then
- if model == 2 then
- return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
- elseif model == 3 then
- return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
- elseif model == 4 then
- return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
- else
- return format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
- end
+ if tv then
+ if model == 2 then
+ return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ elseif model == 3 then
+ return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
else
- if model == 2 then
- return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
- elseif model == 3 then
- return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
- elseif model == 4 then
- return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
- else
- return format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
- end
+ return format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
end
else
- default = default or 0 -- rgb !
- return format("(%s,%s,%s)",default,default,default)
- end
- end
-
- function ctx.formatcolor(ca,separator)
- local cv = colors.value(ca)
- if cv then
- local model = cv[1]
if model == 2 then
- return tostring(cv[2])
+ return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 3 then
- return table.concat(cv,separator,3,5)
+ return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 4 then
- return table.concat(cv,separator,6,9)
+ return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
else
- return tostring(cv[13])
+ return format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
end
- else
- return tostring(0)
end
+ else
+ default = default or 0 -- rgb !
+ return format("(%s,%s,%s)",default,default,default)
end
+end
- function ctx.formatgray(ca,separator)
- local cv = colors.value(ca)
- if cv then
+function ctx.formatcolor(ca,separator)
+ local cv = colors.value(ca)
+ if cv then
+ local model = cv[1]
+ if model == 2 then
return tostring(cv[2])
+ elseif model == 3 then
+ return concat(cv,separator,3,5)
+ elseif model == 4 then
+ return concat(cv,separator,6,9)
else
- return tostring(0)
+ return tostring(cv[13])
end
+ else
+ return tostring(0)
end
+end
- function ctx.colorcomponents(ca)
- local cv = colors.value(ca)
- if cv then
- local model = cv[1]
- if model == 2 then
- return format("s=%1.3f",cv[2])
- elseif model == 3 then
- return format("r=%1.3f g=%1.3f b=%1.3f",cv[3],cv[4],cv[5])
- elseif model == 4 then
- return format("c=%1.3f m=%1.3f y=%1.3f k=%1.3f",cv[6],cv[7],cv[8],cv[9])
- elseif type(cv[13]) == "string" then
- return format("p=%s",cv[13])
- else
- return format("p=%1.3f",cv[13])
- end
- else
- return ""
- end
+function ctx.formatgray(ca,separator)
+ local cv = colors.value(ca)
+ if cv then
+ return tostring(cv[2])
+ else
+ return tostring(0)
end
+end
- function ctx.transparencycomponents(ta)
- local tv = transparencies.value(ta)
- if tv then
- return format("a=%1.3f t=%1.3f",tv[1],tv[2])
+function ctx.colorcomponents(ca)
+ local cv = colors.value(ca)
+ if cv then
+ local model = cv[1]
+ if model == 2 then
+ return format("s=%1.3f",cv[2])
+ elseif model == 3 then
+ return format("r=%1.3f g=%1.3f b=%1.3f",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("c=%1.3f m=%1.3f y=%1.3f k=%1.3f",cv[6],cv[7],cv[8],cv[9])
+ elseif type(cv[13]) == "string" then
+ return format("p=%s",cv[13])
else
- return ""
+ return format("p=%1.3f",cv[13])
end
+ else
+ return ""
end
+end
- function ctx.pdfcolor(model,ca,default) -- todo: use gray when no color
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- local s = cv[2]
- return format("%s g %s G",s,s)
- elseif model == 3 then
- local r, g, b = cv[3], cv[4], cv[5]
- return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)
- elseif model == 4 then
- local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
- return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)
- else
- local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
- if type(p) == "string" then
- p = p:gsub(","," ") -- brr misuse of spot
- end
- return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)
- end
- else
- return format("%s g %s G",default or 0)
- end
+function ctx.transparencycomponents(ta)
+ local tv = transparencies.value(ta)
+ if tv then
+ return format("a=%1.3f t=%1.3f",tv[1],tv[2])
+ else
+ return ""
end
+end
- function ctx.pdfcolorvalue(model,ca,default)
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- return format("%s",cv[2])
- elseif model == 3 then
- return format("%s %s %s",cv[3],cv[4],cv[5])
- elseif model == 4 then
- return format("%s %s %s %s",cv[6],cv[7],cv[8],cv[9])
- else
- return format("%s",cv[13])
- end
+function ctx.pdfcolor(model,ca,default) -- todo: use gray when no color
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ local s = cv[2]
+ return format("%s g %s G",s,s)
+ elseif model == 3 then
+ local r, g, b = cv[3], cv[4], cv[5]
+ return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)
+ elseif model == 4 then
+ local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
+ return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)
else
- return format("%s",default or 0)
+ local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
+ if type(p) == "string" then
+ p = p:gsub(","," ") -- brr misuse of spot
+ end
+ return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)
end
+ else
+ return format("%s g %s G",default or 0,default or 0)
end
+end
- function ctx.fdfcolor(model,ca,default)
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- return format("[%s]",cv[2])
- elseif model == 3 then
- return format("[%s %s %s]",cv[3],cv[4],cv[5])
- elseif model == 4 then
- return format("[%s %s %s %s]",cv[6],cv[7],cv[8],cv[9])
- elseif model == 4 then
- return format("[%s]",cv[13])
- end
+function ctx.pdfcolorvalue(model,ca,default)
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return format("%s",cv[2])
+ elseif model == 3 then
+ return format("%s %s %s",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("%s %s %s %s",cv[6],cv[7],cv[8],cv[9])
else
- return format("[%s]",default or 0)
+ return format("%s",cv[13])
end
+ else
+ return format("%s",default or 0)
end
+end
- function ctx.pdfcolorspace(model,ca)
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- return "DeviceGray"
- elseif model == 3 then
- return "DeviceRGB"
- elseif model == 4 then
- return "DeviceCMYK"
- end
+function ctx.fdfcolor(model,ca,default)
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
end
- return "DeviceGRAY"
- end
-
- function ctx.spotcolorname(ca,default)
- local cv, v = colors.value(ca), "unknown"
- if cv and cv[1] == 5 then
- v = cv[10]
+ if model == 2 then
+ return format("[%s]",cv[2])
+ elseif model == 3 then
+ return format("[%s %s %s]",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("[%s %s %s %s]",cv[6],cv[7],cv[8],cv[9])
+ elseif model == 4 then
+ return format("[%s]",cv[13])
end
- return tostring(v)
+ else
+ return format("[%s]",default or 0)
end
+end
- function ctx.spotcolorvalue(ca,default)
- local cv, v = colors.value(ca), 0
- if cv and cv[1] == 5 then
- v = cv[13]
+function ctx.pdfcolorspace(model,ca)
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return "DeviceGray"
+ elseif model == 3 then
+ return "DeviceRGB"
+ elseif model == 4 then
+ return "DeviceCMYK"
end
- return tostring(v)
end
+ return "DeviceGRAY"
+end
- -- unfortunately we have \cs's here but this will go anyway once we have mplib and such
-
- function ctx.resolvempgraycolor(csa,csb,model,s)
- local ca = colors.register('color',nil,'gray',s)
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
- end
- function ctx.resolvemprgbcolor(csa,csb,model,r,g,b)
- local ca = colors.register('color',nil,'rgb',r,g,b)
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
- end
- function ctx.resolvempcmykcolor(csa,csb,model,c,m,y,k)
- local ca = colors.register('color',nil,'cmyk',c,m,y,k)
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
+function ctx.spotcolorname(ca,default)
+ local cv, v = colors.value(ca), "unknown"
+ if cv and cv[1] == 5 then
+ v = cv[10]
end
- function ctx.resolvempspotcolor(csa,csb,model,n,f,d,p)
- local ca = colors.register('color',nil,'spot',n,f,d,p)
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
- tex.sprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
+ return tostring(v)
+end
+
+function ctx.spotcolorvalue(ca,default)
+ local cv, v = colors.value(ca), 0
+ if cv and cv[1] == 5 then
+ v = cv[13]
end
+ return tostring(v)
+end
+
+-- unfortunately we have \cs's here but this will go anyway once we have mplib and such
+function ctx.resolvempgraycolor(csa,csb,model,s)
+ local ca = colors.register('color',nil,'gray',s)
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
+end
+function ctx.resolvemprgbcolor(csa,csb,model,r,g,b)
+ local ca = colors.register('color',nil,'rgb',r,g,b)
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
+end
+function ctx.resolvempcmykcolor(csa,csb,model,c,m,y,k)
+ local ca = colors.register('color',nil,'cmyk',c,m,y,k)
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
+end
+function ctx.resolvempspotcolor(csa,csb,model,n,f,d,p)
+ local ca = colors.register('color',nil,'spot',n,f,d,p)
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
+ texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
end
-- literals needed to inject code in the mp stream, we cannot use attributes there
-- since literals may have qQ's, much may go away once we have mplib code in place
-do
+local intransparency = false
- local format, sprint = string.format, tex.sprint
-
- local intransparency = false
-
- function ctx.pdfrgbliteral(model,r,g,b)
- sprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'rgb',r,g,b))))
- end
- function ctx.pdfcmykliteral(model,c,m,y,k)
- sprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'cmyk',c,m,y,k))))
- end
- function ctx.pdfgrayliteral(model,s)
- sprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'gray',s))))
- end
- function ctx.pdfspotliteral(model,n,f,d,p)
- sprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'spot',n,f,d,p)))) -- incorrect
- end
- function ctx.pdftransparencyliteral(a,t)
- intransparency = true
- sprint(tex.ctxcatcodes,format("\\pdfliteral{/Tr%s gs}",transparencies.register(nil,a,t)))
- end
- function ctx.pdffinishtransparency()
- if intransparency then
- intransparency = false
- sprint(tex.ctxcatcodes,"\\pdfliteral{/Tr0 gs}") -- we happen to know this -)
- end
+function ctx.pdfrgbliteral(model,r,g,b)
+ texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'rgb',r,g,b))))
+end
+function ctx.pdfcmykliteral(model,c,m,y,k)
+ texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'cmyk',c,m,y,k))))
+end
+function ctx.pdfgrayliteral(model,s)
+ texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'gray',s))))
+end
+function ctx.pdfspotliteral(model,n,f,d,p)
+ texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'spot',n,f,d,p)))) -- incorrect
+end
+function ctx.pdftransparencyliteral(a,t)
+ intransparency = true
+ texsprint(tex.ctxcatcodes,format("\\pdfliteral{/Tr%s gs}",transparencies.register(nil,a,t)))
+end
+function ctx.pdffinishtransparency()
+ if intransparency then
+ intransparency = false
+ texsprint(tex.ctxcatcodes,"\\pdfliteral{/Tr0 gs}") -- we happen to know this -)
end
-
end
diff --git a/tex/context/base/colo-new.tex b/tex/context/base/colo-new.tex
index 417c54a52..04b2ef716 100644
--- a/tex/context/base/colo-new.tex
+++ b/tex/context/base/colo-new.tex
@@ -191,6 +191,10 @@
\newif\ifconverttoGRAY
\newif\ifweightGRAY \weightGRAYtrue
+\newif\ifconvertMPcolors
+\newif\ifreduceMPcolors
+\newif\ifforcegrayMPcolors
+
%D The last boolean controls reduction of \cap{CMYK} to
%D \cap{CMY} colors. When set to true, the black component
%D is added to the other ones.
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index be7393632..070b6e214 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2008.03.11 23:55}
+\newcontextversion{2008.04.11 00:07}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
index 6b126af9c..324c874e2 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -42,7 +42,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2008.03.11 23:55}
+\edef\contextversion{2008.04.11 00:07}
%D For those who want to use this:
@@ -194,7 +194,7 @@
\loadcorefile{mult-com.tex}
\loadmkivfile{luat-ini.tex}
-% \loadmkivfile{luat-lib.tex}
+%loadmkivfile{luat-lib.tex}
\loadmkivfile{luat-lmx.tex}
\loadmkivfile{luat-uni.tex}
@@ -224,11 +224,12 @@
\loadcorefile{supp-mrk.tex}
\loadcorefile{supp-vis.tex}
\loadcorefile{supp-fun.tex}
-\loadcorefile{supp-eps.tex}
+%loadcorefile{supp-eps.tex}
\loadcorefile{supp-spe.tex}
\loadcorefile{supp-ran.tex}
-\loadcorefile{supp-mps.tex}
-\loadcorefile{supp-tpi.tex}
+%loadcorefile{supp-mps.tex}
+\loadmkiifile{supp-mps.tex}
+\loadmkiifile{supp-tpi.tex}
\loadcorefile{supp-mat.tex}
\loadcorefile{supp-ali.tex}
\loadcorefile{supp-num.tex}
@@ -435,10 +436,15 @@
%D Like languages, fonts, encodings and symbols, \METAPOST\
%D support is also organized in its own class of modules.
-\loadcorefile{meta-ini.tex}
+\loadmkivfile{mlib-ctx.tex}
+\loadmkivfile{mlib-pdf.tex}
+\loadmkivfile{mlib-pps.tex}
+
+\loadmarkfile{meta-ini}
+\loadmarkfile{meta-tex}
+
\loadcorefile{meta-pdf.tex}
\loadcorefile{meta-pag.tex}
-\loadcorefile{meta-tex.tex}
%D Special page handling (maybe even later)
@@ -475,7 +481,7 @@
\loadcorefile{core-box.tex}
\loadcorefile{page-app.tex}
-\loadcorefile{meta-fig.tex}
+\loadmarkfile{meta-fig}
%D Language specific spacing.
diff --git a/tex/context/base/core-buf.lua b/tex/context/base/core-buf.lua
index 384a5608e..33ca8ebbf 100644
--- a/tex/context/base/core-buf.lua
+++ b/tex/context/base/core-buf.lua
@@ -7,6 +7,8 @@
-- ctx lua reference model / hooks and such
-- to be optimized
+-- redefine buffers.get
+
if not versions then versions = { } end versions['core-buf'] = 1.001
if unicode and not utf then utf = unicode.utf8 end
@@ -17,6 +19,10 @@ buffers.hooks = { }
buffers.flags = { }
buffers.commands = { }
+-- if needed we can make 'm local
+
+local concat, texsprint, texprint = table.concat, tex.sprint, tex.print
+
function buffers.erase(name)
buffers.data[name] = nil
end
@@ -52,7 +58,8 @@ function buffers.grab(name,begintag,endtag,data)
buffers.data[name] = buffers.data[name]:gsub("[\010\013]$","")
if buffers.flags.store_as_table then
-- todo: specific splitter, do we really want to erase the spaces?
- buffers.data[name] = string.split(buffers.data[name]," *[\010\013]")
+ --~ buffers.data[name] = string.split(buffers.data[name]," *[\010\013]")
+ buffers.data[name] = buffers.data[name]:splitlines()
end
end
cs.testcase(more)
@@ -78,39 +85,36 @@ buffers.commands.empty_line_command = "\\doverbatimemptyline"
function buffers.verbatimbreak(n,m)
if buffers.flags.optimize_verbatim then
if (n==2) or (n==m) then
- tex.sprint(buffers.commands.no_break)
+ texsprint(buffers.commands.no_break)
else
- tex.sprint(buffers.commands.do_break)
+ texsprint(buffers.commands.do_break)
end
end
end
function buffers.type(name)
- if buffers.data[name] then
- if type(buffers.data[name]) == "string" then
- -- todo: use linestepper (no need for a table)
- local lines = string.split(buffers.data[name]," *[\010\013]")
- local line, n, m = 0, 0, #lines
- for _,str in ipairs(lines) do
- n, line = buffers.typeline(str, n, m, line)
- end
- else
- local line, n, m = 0, 0, #buffers.data[name]
- for _,str in ipairs(buffers.data[name]) do
- n, line = buffers.typeline(str, n, m, line)
- end
+ local lines = buffers.data[name]
+ local action = buffers.typeline
+ if lines then
+ if type(lines) == "string" then
+ lines = lines:splitlines() -- lines:split(" *[\010\013]")
+ end
+ local line, n, m = 0, 0, #lines
+ for i=1,m do
+ n, line = action(lines[i], n, m, line)
end
end
end
function buffers.typefile(name)
local t = input.openfile(name)
+ local action = buffers.typeline
if t then
local line, n, m = 0, 0, t.noflines
while true do
str = t.reader(t)
if str then
- n, line = buffers.typeline(str, n, m, line)
+ n, line = action(str, n, m, line)
else
break
end
@@ -148,31 +152,57 @@ end
-- todo, use more locals
function buffers.get(name)
- if buffers.data[name] then
- if type(buffers.data[name]) == "table" then
- for _,v in ipairs(buffers.data[name]) do
- tex.print(v)
+ local b = buffers.data[name]
+ if b then
+ if type(b) == "table" then
+ for i=1,#b do
+ texprint(b[i])
end
else
- string.piecewise(buffers.data[name], " *[\010\013]", tex.print)
+ string.piecewise(b, " *[\010\013]", texprint) -- hm, can be faster
+ end
+ end
+end
+
+function buffers.content(name) -- no print
+ local b = buffers.data[name]
+ if b then
+ if type(b) == "table" then
+ return concat(b," ")
+ else
+ return b
+ end
+ else
+ return ""
+ end
+end
+
+function buffers.collect(names) -- no print
+ local t = { }
+ for i=1,#names do
+ local c = buffers.content(names[i])
+ if c ~= "" then
+ t[#t+1] = c
end
end
+ return concat(t," ")
end
function buffers.inspect(name)
- if buffers.data[name] then
- if type(buffers.data[name]) == "table" then
- for _,v in ipairs(buffers.data[name]) do
+ local b = buffers.data[name]
+ if b then
+ if type(b) == "table" then
+ for _,v in ipairs(b) do
if v == "" then
- tex.sprint(tex.ctxcatcodes,"[crlf]\\par ")
+ texsprint(tex.ctxcatcodes,"[crlf]\\par ")
else
- tex.sprint(tex.ctxcatcodes,(buffers.data[name]:gsub("(.)",function(c)
+ texsprint(tex.ctxcatcodes,(b:gsub("(.)",function(c)
return " [" .. string.byte(c) .. "] "
end)) .. "\\par")
end
end
else
- tex.sprint(tex.ctxcatcodes,(buffers.data[name]:gsub("(.)",function(c)
+ texsprint(tex.ctxcatcodes,(b:gsub("(.)",function(c)
return " [" .. string.byte(c) .. "] "
end)))
end
@@ -258,19 +288,19 @@ end
-- defaults
function buffers.visualizers.default.flush_line(str)
- tex.sprint(tex.ctxcatcodes,buffers.escaped(str))
+ texsprint(tex.ctxcatcodes,buffers.escaped(str))
end
function buffers.visualizers.default.begin_of_line(n)
- tex.sprint(tex.ctxcatcodes, buffers.commands.begin_of_line_command .. "{" .. n .. "}")
+ texsprint(tex.ctxcatcodes, buffers.commands.begin_of_line_command .. "{" .. n .. "}")
end
function buffers.visualizers.default.end_of_line()
- tex.sprint(tex.ctxcatcodes,buffers.commands.end_of_line_command)
+ texsprint(tex.ctxcatcodes,buffers.commands.end_of_line_command)
end
function buffers.visualizers.default.empty_line()
- tex.sprint(tex.ctxcatcodes,buffers.commands.empty_line_command)
+ texsprint(tex.ctxcatcodes,buffers.commands.empty_line_command)
end
function buffers.visualizers.default.line(str)
@@ -315,7 +345,7 @@ function buffers.visualizers.flush_nested(str, enable) -- no utf, kind of obsole
end
end
result = result .. "\\char" .. sb(ss(str,i,i)) .. " " .. string.rep("}",nested)
- tex.sprint(tex.ctxcatcodes,result)
+ texsprint(tex.ctxcatcodes,result)
end
-- handy helpers
@@ -363,9 +393,9 @@ end
function buffers.flush_result(result,nested)
if nested then
- tex.sprint(tex.ctxcatcodes,buffers.replace_nested(table.concat(result,"")))
+ texsprint(tex.ctxcatcodes,buffers.replace_nested(concat(result,"")))
else
- tex.sprint(tex.ctxcatcodes,table.concat(result,""))
+ texsprint(tex.ctxcatcodes,concat(result,""))
end
end
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
index b6af6be9a..be00accde 100644
--- a/tex/context/base/core-con.lua
+++ b/tex/context/base/core-con.lua
@@ -121,7 +121,7 @@ function converters.Character(n) converters.chr (n,64) end
function converters.characters(n) converters.chrs(n,96) end
function converters.Characters(n) converters.chrs(n,64) end
-function converters.weekday(year,month,day)
+function converters.weekday(day,month,year)
tex.sprint(os.date("%w",os.time{year=year,month=month,day=day})+1)
end
diff --git a/tex/context/base/core-fig.tex b/tex/context/base/core-fig.tex
index f701c0c9f..5eed8fbf1 100644
--- a/tex/context/base/core-fig.tex
+++ b/tex/context/base/core-fig.tex
@@ -485,10 +485,6 @@
\externalfigure[\typesetfilename.pdf][#2,#4]}
\appendtoks \setupexternalfigures[\c!option=\v!empty] \to \everyfastmode
-\appendtoks \runMPgraphicsfalse \to \everyfastmode
-\appendtoks \insertMPgraphicsfalse \to \everyfastmode
-
-\appendtoks \flushMPgraphics \to \everygoodbye % \everylastshipout
\setupexternalfigures
[\c!option=,
diff --git a/tex/context/base/core-fnt.tex b/tex/context/base/core-fnt.tex
index dea5d3571..920f1288b 100644
--- a/tex/context/base/core-fnt.tex
+++ b/tex/context/base/core-fnt.tex
@@ -436,9 +436,9 @@
%D \showsetup{setupunderbar}
%D
%D The alternatives show up as
-%D {\setupunderbar [alternativevariant=a]\underbar{alternative a}},
-%D {\setupunderbar [alternativevariant=b]\underbar{alternative b}},
-%D {\setupunderbar [alternativevariant=c]\underbar{alternative c}}
+%D {\setupunderbar [alternative=a]\underbar{alternative a}},
+%D {\setupunderbar [alternative=b]\underbar{alternative b}},
+%D {\setupunderbar [alternative=c]\underbar{alternative c}}
%D and
%D {\setupunderbar [rulethickness=1pt]\underbar{1pt width}},
%D {\setupunderbar [rulethickness=2pt]\underbar{2pt width}},
diff --git a/tex/context/base/core-grd.tex b/tex/context/base/core-grd.tex
index 864da8021..575ec4c2d 100644
--- a/tex/context/base/core-grd.tex
+++ b/tex/context/base/core-grd.tex
@@ -100,6 +100,7 @@
\wd0\hsize
\dp0\strutdp
\nointerlineskip
+ \forgetall
\ruledvbox{\box0}%
\egroup
\prevdepth\strutdp}%
@@ -704,6 +705,7 @@
\botbaselinecorrection
\vss}%
\setbox\nextbox\hbox{\lower\strutdp\flushnextbox}%
+ \forgeteverypar % new per 3/4/2008, prevents duplicate pos nodes resulting in extra whitespace
\noindent\snaptogrid\vbox{\flushnextbox}%
\egroup}
\vbox % was \hbox
diff --git a/tex/context/base/core-inc.mkiv b/tex/context/base/core-inc.mkiv
index 2d6075247..24a78e657 100644
--- a/tex/context/base/core-inc.mkiv
+++ b/tex/context/base/core-inc.mkiv
@@ -180,7 +180,7 @@
\doifseparatingcolorselse
{\let\@@efforegroundcolor\empty
\doifelsenothing\@@efsplit
- {\charde\splitexternalfigure\zerocount}
+ {\chardef\splitexternalfigure\zerocount}
{\doifcolorchannelelse\@@efsplit
{\let\@@efobject\v!no % why?
\chardef\splitexternalfigure\plusone}
diff --git a/tex/context/base/core-job.lua b/tex/context/base/core-job.lua
index 2493719e8..b963227a5 100644
--- a/tex/context/base/core-job.lua
+++ b/tex/context/base/core-job.lua
@@ -21,10 +21,14 @@ function commands.doifnot(b)
end
cs.testcase = commands.doifelse
-function commands. def(cs,value) tex.sprint(tex.ctxcatcodes, "\\def\\"..cs.."{"..value.."}") end
-function commands.edef(cs,value) tex.sprint(tex.ctxcatcodes,"\\edef\\"..cs.."{"..value.."}") end
-function commands.gdef(cs,value) tex.sprint(tex.ctxcatcodes,"\\gdef\\"..cs.."{"..value.."}") end
-function commands.xdef(cs,value) tex.sprint(tex.ctxcatcodes,"\\xdef\\"..cs.."{"..value.."}") end
+local format = string.format
+
+function commands. def(cs,value) tex.sprint(tex.ctxcatcodes,format( "\\def\\%s{%s}",cs,value)) end
+function commands.edef(cs,value) tex.sprint(tex.ctxcatcodes,format("\\edef\\%s{%s}",cs,value)) end
+function commands.gdef(cs,value) tex.sprint(tex.ctxcatcodes,format("\\gdef\\%s{%s}",cs,value)) end
+function commands.xdef(cs,value) tex.sprint(tex.ctxcatcodes,format("\\xdef\\%s{%s}",cs,value)) end
+
+function commands.cs(cs,args) tex.sprint(tex.ctxcatcodes,format("\\csname %s\\endcsname %s",cs,args or"")) end
-- main code
@@ -140,4 +144,3 @@ function commands.loadexamodes(filename)
commands.writestatus("examodes","no mode file " .. filename) -- todo: message system
end
end
-
diff --git a/tex/context/base/core-mis.tex b/tex/context/base/core-mis.tex
index 8459caab2..48bf85259 100644
--- a/tex/context/base/core-mis.tex
+++ b/tex/context/base/core-mis.tex
@@ -2801,12 +2801,33 @@
%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
\let\handlecommalistsentence\firstofoneargument
-\def\commalistsentence[#1]%
+\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}%
@@ -2819,9 +2840,9 @@
\scratchtoks{\handlecommalistsentence{##1}}%
\else
\ifnum\scratchcounter=\commalistsize
- \appendtoks\labeltext{and-2}\handlecommalistsentence{##1}\to\scratchtoks
+ \appendtoks\@@commalistsentencetwo\handlecommalistsentence{##1}\to\scratchtoks
\else
- \appendtoks\labeltext{and-1}\handlecommalistsentence{##1}\to\scratchtoks
+ \appendtoks\@@commalistsentenceone\handlecommalistsentence{##1}\to\scratchtoks
\fi
\fi}%
\processcommacommand[#1]\docommand
@@ -2830,6 +2851,8 @@
\serializedcommalist
\egroup}
+\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]}
+
\ifx\textcomma\undefined \def\textcomma{,} \fi
\setuplabeltext [\s!nl] [and-1=\textcomma\ , and-2= en ]
diff --git a/tex/context/base/core-pgr.tex b/tex/context/base/core-pgr.tex
index 65f1da061..145599cc3 100644
--- a/tex/context/base/core-pgr.tex
+++ b/tex/context/base/core-pgr.tex
@@ -278,15 +278,17 @@
\prepareMPvariables{#2}%
\prepareMPpositionvariables
\enableincludeMPgraphics
- \ifcollectMPpositiongraphics
+ \ifcollectMPpositiongraphics % no longer needed in mkiv
\expanded{\startMPdrawing#3\noexpand\stopMPdrawing}%
\global\MPdrawingdonetrue
+ \else\ifx\startMPgraphic\undefined
+ \startMPcode#3\stopMPcode
\else
\startMPgraphic#3\stopMPgraphic
\loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
\deallocateMPslot\currentMPgraphic
\placeMPgraphic
- \fi
+ \fi\fi
\egroup}
% Now we need a adapted action handler:
@@ -582,6 +584,14 @@
\iftracepositions show_multi_pars \else draw_multi_pars \fi ;
\stopuseMPgraphic
+\startuseMPgraphic{mpos:par:sideline}{linecolor,lineoffset}
+ for i=1 upto nofmultipars :
+ fill leftboundary multipars[i]
+ shifted (-\MPvar{lineoffset},0)
+ rightenlarged 1mm withcolor \MPvar{linecolor} ;
+ endfor ;
+\stopuseMPgraphic
+
\startMPpositionmethod{mpos:par:columnset}
\edef\MPparcounter{\MPv\MPbself{1}{0}}%
\startMPpositiongraphic{mpos:par}%
@@ -741,6 +751,7 @@
dashtype=\textbackgroundparameter{dash}, % to be internationalized
gridcolor=\textbackgroundparameter\c!framecolor,
linecolor=\textbackgroundparameter\c!framecolor,
+ lineoffset=\textbackgroundparameter\c!frameoffset,
fillcolor=\textbackgroundparameter\c!backgroundcolor,
filloffset=\textbackgroundparameter\c!backgroundoffset,
gridwidth=\textbackgroundparameter\c!rulethickness,
@@ -949,7 +960,7 @@
[\c!state,\c!location,\c!alternative,\c!mp,\c!method,
\c!background,\c!backgroundcolor,\c!corner,\c!level,
\c!backgroundoffset,\c!before,\c!after,\c!align,dash, % dash not yet internationalized
- \c!radius,\c!frame,\c!framecolor,\c!rulethickness,\c!voffset,
+ \c!radius,\c!frame,\c!framecolor,\c!rulethickness,\c!voffset,\c!frameoffset,
\c!leftoffset,\c!rightoffset,\c!topoffset,\c!bottomoffset]%
\getparameters[\??td#1][#2]%
\doifvalue{\??td#1\c!state}\v!start\checktextbackgrounds
@@ -1669,9 +1680,21 @@
[before={\starttextbackground[strikethrough]},
after=\stoptextbackground]
+\definetextbackground
+ [sideline]
+ [mp=mpos:par:sideline,
+ location=paragraph,
+ framecolor=red,
+ frameoffset=5mm]
+
+\definestartstop [sideline]
+ [before={\starttextbackground[sideline]},
+ after=\stoptextbackground]
+
\starttext
\startunderline \input tufte \stopunderline \blank
\startoverstrike \input tufte \stopoverstrike \blank
\startexlines \input tufte \stopexlines \blank
\startstrikethrough \input tufte \stopstrikethrough \blank
+ \startsideline \input tufte \stopsideline \blank
\stoptext
diff --git a/tex/context/base/core-spa.lua b/tex/context/base/core-spa.lua
index 22b392d4d..501ea28f2 100644
--- a/tex/context/base/core-spa.lua
+++ b/tex/context/base/core-spa.lua
@@ -791,7 +791,7 @@ do
if not prev or prev.id ~= glyph then
return upper(start)
else
- return start
+ return start, false
end
end
@@ -806,7 +806,7 @@ do
if (not prev or prev.id ~= glyph) and next and next.id == glyph then
return upper(start)
else
- return start
+ return start, false
end
end
diff --git a/tex/context/base/core-tab.tex b/tex/context/base/core-tab.tex
index 89e6a556d..2e843eae8 100644
--- a/tex/context/base/core-tab.tex
+++ b/tex/context/base/core-tab.tex
@@ -1640,7 +1640,7 @@
\bgroup
\catcode`\|=\@@other \gdef\@@otherbar {|}
- \catcode`\"=\@@other \gdef\@@otherquite {"}
+ \catcode`\"=\@@other \gdef\@@otherquote {"}
\catcode`\|=\@@active \gdef\@@useotherbar {\let|\@@otherbar}
\catcode`\"=\@@active \gdef\@@useotherquote{\let"\@@otherquote}
\egroup
diff --git a/tex/context/base/core-tbl.tex b/tex/context/base/core-tbl.tex
index 8081ff62a..55f40ecc7 100644
--- a/tex/context/base/core-tbl.tex
+++ b/tex/context/base/core-tbl.tex
@@ -1000,7 +1000,7 @@
&##\tabskip\zeropoint}%
\fi
\tabulatewidth\zeropoint
-% |#1X|\relax
+ % |#1X|\relax
\nexttabulate #1X|\relax
\scratchcounter\tabulatecolumns
\multiply\scratchcounter3%
@@ -1029,7 +1029,7 @@
\def\xeskip
{\par\egroup\egroup
\global\let\tabulatehook\dotabulatehook}%
-% \let|\savedbar
+ % \let|\savedbar
\global\let\tabulatehook\dotabulatehook
\doifvalue{\??tt\currenttabulate\c!indenting}\v!no\forgetparindent
\ifinsidefloat
diff --git a/tex/context/base/core-var.tex b/tex/context/base/core-var.tex
index 6b6583a8b..61a8c87e7 100644
--- a/tex/context/base/core-var.tex
+++ b/tex/context/base/core-var.tex
@@ -232,7 +232,7 @@
{\docheckforallmodes\donothing\dostopallmodes{#1}}
\long\def\dostartnotallmodes[#1]%
- {\docheckforallmodes\dostopallmodes\donothing{#1}}
+ {\docheckforallmodes\dostopnotallmodes\donothing{#1}}
\let\stopallmodes \donothing
\let\stopnotallmodes\donothing
@@ -380,6 +380,8 @@
%D This boolean can be used to bypass certain
%D initializations.
+\ifx\protectionlevel\undefined \newcount\protectionlevel \fi
+
\newif\ifproductionrun \appendtoks \productionruntrue \to \everydump
\appendtoks \ifcase\protectionlevel\else\reportunprotection\fi \to \everydump
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index f5e08ca6d..92f545e15 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -1030,7 +1030,7 @@ function fonts.otf.enhance.analyze(data,filename)
end
do
- -- original string parsr: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
+ -- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
--
-- 18964 18964 (leader)
-- 0 /.notdef
@@ -1048,21 +1048,21 @@ do
local tonumber = tonumber
- function do_one(a,b)
+ local function do_one(a,b)
unicodes[tonumber(a)] = tonumber(b,16)
end
- function do_range(a,b,c)
+ local function do_range(a,b,c)
c = tonumber(c,16)
for i=tonumber(a),tonumber(b) do
unicodes[i] = c
c = c + 1
end
end
- function do_name(a,b)
+ local function do_name(a,b)
names[tonumber(a)] = b
end
- grammar = lpeg.P { "start",
+ local grammar = lpeg.P { "start",
start = number * spaces * number * lpeg.V("series"),
series = (spaces * (lpeg.V("one") + lpeg.V("range") + lpeg.V("named")) )^1,
one = (number * spaces * number) / do_one,
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
index 88a85652e..1b0ed65d5 100644
--- a/tex/context/base/font-tfm.lua
+++ b/tex/context/base/font-tfm.lua
@@ -431,7 +431,7 @@ do
local characters = tfmdata.characters
local unicodes = afmdata.luatex.unicodes
local function remap(pattern,name)
- local p = lpeg.match(pattern,name)
+ local p = pattern:match(name)
if p then
local oldchr, newchr = unicodes[p], unicodes[name]
if oldchr and newchr then
@@ -459,7 +459,7 @@ do
local characters = tfmdata.characters
local unicodes = afmdata.luatex.unicodes
local function remap(pattern,name)
- local p = lpeg.match(pattern,name)
+ local p = pattern:match(name)
if p then
local oldchr, newchr = unicodes[p], unicodes[name]
if oldchr and newchr then
diff --git a/tex/context/base/l-aux.lua b/tex/context/base/l-aux.lua
index fdcc88e46..f81d807cd 100644
--- a/tex/context/base/l-aux.lua
+++ b/tex/context/base/l-aux.lua
@@ -10,7 +10,7 @@ do
local hash = { }
- local function set(key,value)
+ local function set(key,value) -- using Carg is slower here
hash[key] = value
end
@@ -31,7 +31,7 @@ do
function aux.settings_to_hash(str)
if str and str ~= "" then
hash = { }
- lpeg.match(pattern,str)
+ pattern:match(str)
return hash
else
return { }
@@ -39,17 +39,24 @@ do
end
local seperator = comma * space^0
- local value = lbrace * lpeg.C(nobrace^0) * rbrace + lpeg.C((1-seperator)^0)
+ local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
local pattern = lpeg.Ct(value*(seperator*value)^0)
-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
function aux.settings_to_array(str)
- return lpeg.match(pattern,str)
+ return pattern:match(str)
+ end
+
+ local function set(t,v)
+ t[#t+1] = v
end
+ local value = lpeg.P(lpeg.Carg(1)*value) / set
+ local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
function aux.add_settings_to_array(t,str)
- return table.merge(t, lpeg.match(pattern,str))
+ return pattern:match(str, nil, t)
end
end
diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua
index 0cc913d13..0600d72fa 100644
--- a/tex/context/base/l-dir.lua
+++ b/tex/context/base/l-dir.lua
@@ -97,17 +97,53 @@ if lfs then do
else
path, rest = pattern:match("^([^/]*)/(.-)$")
end
- patt = rest:gsub("([%.%-%+])", "%%%1")
+ if rest then
+ patt = rest:gsub("([%.%-%+])", "%%%1")
+ end
patt = patt:gsub("%*", "[^/]*")
patt = patt:gsub("%?", "[^/]")
patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
if path == "" then path = "." end
- -- print(pattern, path, patt)
- recurse = patt:find("%.%*/")
+ recurse = patt:find("%.%*/") ~= nil
glob_pattern(path,patt,recurse,action)
return t
end
+ local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+
+ local pattern = Ct {
+ [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+ }
+
+ local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%." +
+ P("+") / "%+" +
+ P("-") / "%-" +
+ P(1)
+ )^0 )
+
+ function glob(str)
+ local split = pattern:match(str)
+ if split then
+ local t = { }
+ local action = action or function(name) t[#t+1] = name end
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = base:find("**")
+ local start = root .. path
+ local result = filter:match(start .. base)
+ -- print(str, start, result)
+ glob_pattern(start,result,recurse,action)
+ return t
+ else
+ return { }
+ end
+ end
+
dir.glob = glob
--~ list = dir.glob("**/*.tif")
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
index 56893aaf2..1645912dc 100644
--- a/tex/context/base/l-lpeg.lua
+++ b/tex/context/base/l-lpeg.lua
@@ -24,6 +24,8 @@ if not versions then versions = { } end versions['l-lpeg'] = 1.001
--~ lpeg.whitespace = lpeg.S(' \r\n\f\t')^1
--~ lpeg.nonwhitespace = lpeg.P(1-lpeg.whitespace)^1
+local hash = { }
+
function lpeg.anywhere(pattern) --slightly adapted from website
return lpeg.P { lpeg.P(pattern) + 1 * lpeg.V(1) }
end
@@ -38,3 +40,17 @@ function lpeg.splitter(pattern, action)
return (((1-lpeg.P(pattern))^1)/action+1)^0
end
+
+local crlf = lpeg.P("\r\n")
+local cr = lpeg.P("\r")
+local lf = lpeg.P("\n")
+local space = lpeg.S(" \t\f\v")
+local newline = crlf + cr + lf
+local spacing = space^0 * newline
+local content = lpeg.Cs((1-spacing)^1) * spacing^-1 * (spacing * lpeg.Cc(""))^0
+
+local capture = lpeg.Ct(content^0)
+
+function string:splitlines()
+ return capture:match(self)
+end
diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua
index 35b58bda3..180b4c544 100644
--- a/tex/context/base/l-number.lua
+++ b/tex/context/base/l-number.lua
@@ -40,7 +40,7 @@ do
local one = lpeg.C(1-lpeg.S(''))^1
function number.toset(n)
- return lpeg.match(one,tostring(n))
+ return one:match(tostring(n))
end
end
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index b8059c0c9..0b2fac3a0 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -132,7 +132,7 @@ end
--~ split = lpeg.Ct(c*(p*c)^0)
--~ splitters[separator] = split
--~ end
---~ return lpeg.match(split,self) -- split:match(self)
+--~ return split:match(self)
--~ else
--~ return { }
--~ end
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 99c492f1f..ad2f11001 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -70,15 +70,6 @@ function table.prepend(t, list)
end
end
---~ function table.merge(t, ...)
---~ for _, list in ipairs({...}) do
---~ for k,v in pairs(list) do
---~ t[k] = v
---~ end
---~ end
---~ return t
---~ end
-
function table.merge(t, ...) -- first one is target
t = t or {}
local lst = {...}
@@ -90,16 +81,6 @@ function table.merge(t, ...) -- first one is target
return t
end
---~ function table.merged(...)
---~ local tmp = { }
---~ for _, list in ipairs({...}) do
---~ for k,v in pairs(list) do
---~ tmp[k] = v
---~ end
---~ end
---~ return tmp
---~ end
-
function table.merged(...)
local tmp, lst = { }, {...}
for i=1,#lst do
@@ -110,15 +91,6 @@ function table.merged(...)
return tmp
end
---~ function table.imerge(t, ...)
---~ for _, list in ipairs({...}) do
---~ for _, v in ipairs(list) do
---~ t[#t+1] = v
---~ end
---~ end
---~ return t
---~ end
-
function table.imerge(t, ...)
local lst = {...}
for i=1,#lst do
@@ -130,16 +102,6 @@ function table.imerge(t, ...)
return t
end
---~ function table.imerged(...)
---~ local tmp = { }
---~ for _, list in ipairs({...}) do
---~ for _,v in pairs(list) do
---~ tmp[#tmp+1] = v
---~ end
---~ end
---~ return tmp
---~ end
-
function table.imerged(...)
local tmp, lst = { }, {...}
for i=1,#lst do
@@ -287,7 +249,6 @@ do
end
if n == #t then
local tt = { }
- -- for _,v in ipairs(t) do
for i=1,#t do
local v = t[i]
local tv = type(v)
@@ -342,7 +303,7 @@ do
local inline = compact and table.serialize_inline
local first, last = nil, 0 -- #root cannot be trusted here
if compact then
- for k,v in ipairs(root) do -- NOT: for k=1,#root do
+ for k,v in ipairs(root) do -- NOT: for k=1,#root do (why)
if not first then first = k end
last = last + 1
end
@@ -524,7 +485,8 @@ end
do
local function flatten(t,f,complete)
- for _,v in ipairs(t) do
+ for i=1,#t do
+ local v = t[i]
if type(v) == "table" then
if complete or type(v[1]) == "table" then
flatten(v,f,complete)
diff --git a/tex/context/base/l-xml-edu.lua b/tex/context/base/l-xml-edu.lua
index adfc55e68..5aba46043 100644
--- a/tex/context/base/l-xml-edu.lua
+++ b/tex/context/base/l-xml-edu.lua
@@ -54,7 +54,7 @@ if false then
for _,v in ipairs(doctype_patterns) do
a = a:gsub(v, function(d)
text[#text+1] = d or ""
- return string.format("<@dd@>%s</@dd@>",#text)
+ return string.format("<@dt@>%s</@dt@>",#text)
end)
end
end
@@ -179,7 +179,7 @@ if false then
local t = { ns = "", tg = '@rt@', dt = stack[1].dt }
setmetatable(t, mt)
for k,v in ipairs(t.dt) do
- if type(v) == "table" and v.tg ~= "@pi@" and v.tg ~= "@dd@" and v.tg ~= "@cm@" then
+ if type(v) == "table" and v.tg ~= "@pi@" and v.tg ~= "@dt@" and v.tg ~= "@cm@" then
t.ri = k -- rootindex
break
end
diff --git a/tex/context/base/l-xml.lua b/tex/context/base/l-xml.lua
index 703a880ed..06f527cad 100644
--- a/tex/context/base/l-xml.lua
+++ b/tex/context/base/l-xml.lua
@@ -39,6 +39,10 @@ xml.trace_lpath = false
xml.trace_print = false
xml.trace_remap = false
+local format, concat = string.format, table.concat
+
+--~ local pairs, next, type = pairs, next, type
+
-- todo: some things per xml file, liek namespace remapping
--[[ldx--
@@ -49,7 +53,7 @@ find based solution where we loop over an array of patterns. Less code and
much cleaner.</p>
--ldx]]--
-xml.xmlns = { }
+xml.xmlns = xml.xmlns or { }
do
@@ -142,9 +146,13 @@ local x = xml.convert(somestring)
element.</p>
--ldx]]--
+xml.strip_cm_and_dt = false -- an extra global flag, in case we have many includes
+
do
- local remove, nsremap = table.remove, xml.xmlns
+ -- not just one big nested table capture (lpeg overflow)
+
+ local remove, nsremap, resolvens = table.remove, xml.xmlns, xml.resolvens
local stack, top, dt, at, xmlns, errorstr = {}, {}, {}, {}, {}, nil
@@ -154,6 +162,7 @@ do
return ""
end
+ local strip = false
local cleanup = false
function xml.set_text_cleanup(fnc)
@@ -162,7 +171,7 @@ do
local function add_attribute(namespace,tag,value)
if tag == "xmlns" then
- xmlns[#xmlns+1] = xml.resolvens(value)
+ xmlns[#xmlns+1] = resolvens(value)
at[tag] = value
elseif namespace == "xmlns" then
xml.checkns(tag,value)
@@ -189,9 +198,9 @@ do
local toclose = remove(stack)
top = stack[#stack]
if #stack < 1 then
- errorstr = string.format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "")
+ errorstr = format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "")
elseif toclose.tg ~= tag then -- no namespace check
- errorstr = string.format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "")
+ errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "")
end
dt = top.dt
dt[#dt+1] = toclose
@@ -220,93 +229,106 @@ do
dt[#dt+1] = text
end
end
+ --~ local function add_special(what, spacing, text)
+ --~ if #spacing > 0 then
+ --~ dt[#dt+1] = spacing
+ --~ end
+ --~ top = stack[#stack] -- hm, left over 1
+ --~ setmetatable(top, mt) -- hm, left over 2
+ --~ dt[#dt+1] = { special=true, ns="", tg=what, dt={text} }
+ --~ end
local function add_special(what, spacing, text)
if #spacing > 0 then
dt[#dt+1] = spacing
end
- top = stack[#stack]
- setmetatable(top, mt)
- dt[#dt+1] = { special=true, ns="", tg=what, dt={text} }
+ if strip and (what == "@cm@" or what == "@dt@") then
+ -- forget it
+ else
+ dt[#dt+1] = { special=true, ns="", tg=what, dt={text} }
+ end
end
local function set_message(txt)
errorstr = "garbage at the end of the file: " .. txt:gsub("([ \n\r\t]*)","")
end
- local space = lpeg.S(' \r\n\t')
- local open = lpeg.P('<')
- local close = lpeg.P('>')
- local squote = lpeg.S("'")
- local dquote = lpeg.S('"')
- local equal = lpeg.P('=')
- local slash = lpeg.P('/')
- local colon = lpeg.P(':')
- local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-.')
- local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1)
- local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local P, S, R, C, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V
+
+ local space = S(' \r\n\t')
+ local open = P('<')
+ local close = P('>')
+ local squote = S("'")
+ local dquote = S('"')
+ local equal = P('=')
+ local slash = P('/')
+ local colon = P(':')
+ local valid = R('az', 'AZ', '09') + S('_-.')
+ local name_yes = C(valid^1) * colon * C(valid^1)
+ local name_nop = C(P(true)) * C(valid^1)
local name = name_yes + name_nop
- local utfbom = lpeg.P('\000\000\254\255') + lpeg.P('\255\254\000\000') +
- lpeg.P('\255\254') + lpeg.P('\254\255') + lpeg.P('\239\187\191') -- no capture
+ local utfbom = P('\000\000\254\255') + P('\255\254\000\000') +
+ P('\255\254') + P('\254\255') + P('\239\187\191') -- no capture
- local spacing = lpeg.C(space^0)
- local justtext = lpeg.C((1-open)^1)
+ local spacing = C(space^0)
+ local justtext = C((1-open)^1)
local somespace = space^1
local optionalspace = space^0
- local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote)
local attribute = (somespace * name * optionalspace * equal * optionalspace * value) / add_attribute
local attributes = attribute^0
local text = justtext / add_text
- local balanced = lpeg.P { "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" } -- taken from lpeg manual, () example
+ local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
- local begincomment = open * lpeg.P("!--")
- local endcomment = lpeg.P("--") * close
- local begininstruction = open * lpeg.P("?")
- local endinstruction = lpeg.P("?") * close
- local begincdata = open * lpeg.P("![CDATA[")
- local endcdata = lpeg.P("]]") * close
+ local begincomment = open * P("!--")
+ local endcomment = P("--") * close
+ local begininstruction = open * P("?")
+ local endinstruction = P("?") * close
+ local begincdata = open * P("![CDATA[")
+ local endcdata = P("]]") * close
- local someinstruction = lpeg.C((1 - endinstruction)^0)
- local somecomment = lpeg.C((1 - endcomment )^0)
- local somecdata = lpeg.C((1 - endcdata )^0)
+ local someinstruction = C((1 - endinstruction)^0)
+ local somecomment = C((1 - endcomment )^0)
+ local somecdata = C((1 - endcdata )^0)
- local begindoctype = open * lpeg.P("!DOCTYPE")
+ local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
- local publicdoctype = lpeg.P("PUBLIC") * somespace * value * somespace * value * somespace * balanced^0
- local systemdoctype = lpeg.P("SYSTEM") * somespace * value * somespace * balanced^0
+ local publicdoctype = P("PUBLIC") * somespace * value * somespace * value * somespace * balanced^0
+ local systemdoctype = P("SYSTEM") * somespace * value * somespace * balanced^0
local simpledoctype = (1-close)^1 * balanced^0
- local somedoctype = lpeg.C((somespace * lpeg.P(publicdoctype + systemdoctype + simpledoctype) * optionalspace)^0)
+ local somedoctype = C((somespace * P(publicdoctype + systemdoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
local cdata = (spacing * begincdata * somecdata * endcdata ) / function(...) add_special("@cd@",...) end
- local doctype = (spacing * begindoctype * somedoctype * enddoctype ) / function(...) add_special("@dd@",...) end
+ local doctype = (spacing * begindoctype * somedoctype * enddoctype ) / function(...) add_special("@dt@",...) end
-- nicer but slower:
--
-- local instruction = (lpeg.Cc("@pi@") * spacing * begininstruction * someinstruction * endinstruction) / add_special
-- local comment = (lpeg.Cc("@cm@") * spacing * begincomment * somecomment * endcomment ) / add_special
-- local cdata = (lpeg.Cc("@cd@") * spacing * begincdata * somecdata * endcdata ) / add_special
- -- local doctype = (lpeg.Cc("@dd@") * spacing * begindoctype * somedoctype * enddoctype ) / add_special
+ -- local doctype = (lpeg.Cc("@dt@") * spacing * begindoctype * somedoctype * enddoctype ) / add_special
local trailer = space^0 * (justtext/set_message)^0
- -- comment + emptyelement + text + cdata + instruction + lpeg.V("parent"), -- 6.5 seconds on 40 MB database file
- -- text + comment + emptyelement + cdata + instruction + lpeg.V("parent"), -- 5.8
- -- text + lpeg.V("parent") + emptyelement + comment + cdata + instruction, -- 5.5
+ -- comment + emptyelement + text + cdata + instruction + V("parent"), -- 6.5 seconds on 40 MB database file
+ -- text + comment + emptyelement + cdata + instruction + V("parent"), -- 5.8
+ -- text + V("parent") + emptyelement + comment + cdata + instruction, -- 5.5
- local grammar = lpeg.P { "preamble",
- preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * lpeg.V("parent") * trailer,
- parent = beginelement * lpeg.V("children")^0 * endelement,
- children = text + lpeg.V("parent") + emptyelement + comment + cdata + instruction,
+ local grammar = P { "preamble",
+ preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * V("parent") * trailer,
+ parent = beginelement * V("children")^0 * endelement,
+ children = text + V("parent") + emptyelement + comment + cdata + instruction,
}
- function xml.convert(data, no_root)
+ function xml.convert(data, no_root, strip_cm_and_dt)
+ strip = strip_cm_and_dt or xml.strip_cm_and_dt
stack, top, at, xmlns, errorstr, result = {}, {}, {}, {}, nil, nil
stack[#stack+1] = top
top.dt = { }
@@ -315,8 +337,10 @@ do
errorstr = "empty xml file"
elseif not grammar:match(data) then
errorstr = "invalid xml file"
+ else
+ errorstr = ""
end
- if errorstr then
+ if errorstr and errorstr ~= "" then
result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={}, er = true } }, error = true }
setmetatable(stack, mt)
if xml.error_handler then xml.error_handler("load",errorstr) end
@@ -326,7 +350,9 @@ do
if not no_root then
result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={} }
setmetatable(result, mt)
- for k,v in ipairs(result.dt) do
+ local rdt = result.dt
+ for k=1,#rdt do
+ local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
break
@@ -403,24 +429,30 @@ generic table copier. Since we know what we're dealing with we
can speed up things a bit. The second argument is not to be used!</p>
--ldx]]--
-function xml.copy(old,tables)
- if old then
- tables = tables or { }
- local new = { }
- if not tables[old] then
- tables[old] = new
- end
- for k,v in pairs(old) do
- new[k] = (type(v) == "table" and (tables[v] or xml.copy(v, tables))) or v
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+do
+
+ function copy(old,tables)
+ if old then
+ tables = tables or { }
+ local new = { }
+ if not tables[old] then
+ tables[old] = new
+ end
+ for k,v in pairs(old) do
+ new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
+ end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
end
- return new
- else
- return { }
end
+
+ xml.copy = copy
+
end
--[[ldx--
@@ -437,138 +469,141 @@ do
local fallbackhandle = (tex and tex.sprint) or io.write
- function xml.serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
+ local function serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
if not e then
- -- quit
- elseif not nocommands and e.command and xml.command then
- xml.command(e)
- else
- handle = handle or fallbackhandle
- local etg = e.tg
- if etg then
- -- local format = string.format
- if e.special then
- local edt = e.dt
- local spc = specialconverter and specialconverter[etg]
- if spc then
- local result = spc(edt[1])
- if result then
- handle(result)
- else
- -- no need to handle any further
+ return
+ elseif not nocommands then
+ local ec = e.command
+ if ec ~= nil then -- we can have all kind of types
+ local xc = xml.command
+ if xc then
+ xc(e,ec)
+ return
+ end
+ end
+ end
+ handle = handle or fallbackhandle
+ local etg = e.tg
+ if etg then
+ if e.special then
+ local edt = e.dt
+ local spc = specialconverter and specialconverter[etg]
+ if spc then
+ local result = spc(edt[1])
+ if result then
+ handle(result)
+ else
+ -- no need to handle any further
+ end
+ elseif etg == "@pi@" then
+ -- handle(format("<?%s?>",edt[1]))
+ handle("<?" .. edt[1] .. "?>")
+ elseif etg == "@cm@" then
+ -- handle(format("<!--%s-->",edt[1]))
+ handle("<!--" .. edt[1] .. "-->")
+ elseif etg == "@cd@" then
+ -- handle(format("<![CDATA[%s]]>",edt[1]))
+ handle("<![CDATA[" .. edt[1] .. "]]>")
+ elseif etg == "@dt@" then
+ -- handle(format("<!DOCTYPE %s>",edt[1]))
+ handle("<!DOCTYPE " .. edt[1] .. ">")
+ elseif etg == "@rt@" then
+ serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ else
+ local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { } -- type test maybe faster
+ if ats then
+ if attributeconverter then
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ end
+ else
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,v)
end
- elseif etg == "@pi@" then
- -- handle(format("<?%s?>",edt[1]))
- handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt)
- elseif etg == "@cm@" then
- -- handle(format("<!--%s-->",edt[1]))
- handle("<!--" .. edt[1] .. "-->")
- elseif etg == "@cd@" then
- -- handle(format("<![CDATA[%s]]>",edt[1]))
- handle("<![CDATA[" .. edt[1] .. "]]>")
- elseif etg == "@dd@" then
- -- handle(format("<!DOCTYPE %s>",edt[1]))
- handle("<!DOCTYPE " .. edt[1] .. ">")
- elseif etg == "@rt@" then
- xml.serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
- else
- local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
- local ats = eat and next(eat) and { }
+ end
+ if ern and xml.trace_remap then
if ats then
- local format = string.format
- if attributeconverter then
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
- end
- else
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,v)
- end
- end
+ ats[#ats+1] = format("xmlns:remapped='%s'",ern)
+ else
+ ats = { format("xmlns:remapped='%s'",ern) }
end
- if ern and xml.trace_remap then
+ end
+ if ens ~= "" then
+ if edt and #edt > 0 then
if ats then
- ats[#ats+1] = string.format("xmlns:remapped='%s'",ern)
+ -- handle(format("<%s:%s %s>",ens,etg,concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. ">")
else
- ats = { string.format("xmlns:remapped='%s'",ern) }
+ -- handle(format("<%s:%s>",ens,etg))
+ handle("<" .. ens .. ":" .. etg .. ">")
end
- end
- if ens ~= "" then
- if edt and #edt > 0 then
- if ats then
- -- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
- handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. ">")
- else
- -- handle(format("<%s:%s>",ens,etg))
- handle("<" .. ens .. ":" .. etg .. ">")
- end
- local serialize = xml.serialize
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
- else
- handle(e)
- end
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ handle(e)
end
- end
- -- handle(format("</%s:%s>",ens,etg))
- handle("</" .. ens .. ":" .. etg .. ">")
- else
- if ats then
- -- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
- handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. "/>")
else
- -- handle(format("<%s:%s/>",ens,etg))
- handle("<" .. ens .. ":" .. "/>")
+ serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
+ -- handle(format("</%s:%s>",ens,etg))
+ handle("</" .. ens .. ":" .. etg .. ">")
else
- if edt and #edt > 0 then
- if ats then
- -- handle(format("<%s %s>",etg,table.concat(ats," ")))
- handle("<" .. etg .. " " .. table.concat(ats," ") .. ">")
- else
- -- handle(format("<%s>",etg))
- handle("<" .. etg .. ">")
- end
- local serialize = xml.serialize
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
- end
- -- handle(format("</%s>",etg))
- handle("</" .. etg .. ">")
+ if ats then
+ -- handle(format("<%s:%s %s/>",ens,etg,concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. "/>")
else
- if ats then
- -- handle(format("<%s %s/>",etg,table.concat(ats," ")))
- handle("<" .. etg .. " " .. table.concat(ats," ") .. "/>")
- else
- -- handle(format("<%s/>",etg))
- handle("<" .. etg .. "/>")
- end
+ -- handle(format("<%s:%s/>",ens,etg))
+ handle("<" .. ens .. ":" .. "/>")
end
end
- end
- elseif type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
else
- handle(e)
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s %s>",etg,concat(ats," ")))
+ handle("<" .. etg .. " " .. concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s>",etg))
+ handle("<" .. etg .. ">")
+ end
+ for i=1,#edt do
+ serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ -- handle(format("</%s>",etg))
+ handle("</" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s %s/>",etg,concat(ats," ")))
+ handle("<" .. etg .. " " .. concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s/>",etg))
+ handle("<" .. etg .. "/>")
+ end
+ end
end
+ end
+ elseif type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- local serialize = xml.serialize
- for i=1,#e do
- serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
- end
+ handle(e)
+ end
+ else
+ for i=1,#e do
+ serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
end
- function xml.checkbom(root)
+ xml.serialize = serialize
+
+ function xml.checkbom(root) -- can be made faster
if root.ri then
local dt, found = root.dt, false
for k,v in ipairs(dt) do
@@ -584,24 +619,24 @@ do
end
end
-end
-
---[[ldx--
-<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.</p>
---ldx]]--
+ --[[ldx--
+ <p>At the cost of some 25% runtime overhead you can first convert the tree to a string
+ and then handle the lot.</p>
+ --ldx]]--
-function xml.tostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- elseif next(root) then
- local result = { }
- xml.serialize(root,function(s) result[#result+1] = s end)
- return table.concat(result,"")
+ function xml.tostring(root) -- 25% overhead due to collecting
+ if root then
+ if type(root) == 'string' then
+ return root
+ elseif next(root) then -- next is faster than type (and >0 test)
+ local result = { }
+ serialize(root,function(s) result[#result+1] = s end)
+ return concat(result,"")
+ end
end
-end
- return ""
+ return ""
+ end
+
end
--[[ldx--
@@ -729,48 +764,50 @@ do
[40] = "processing instruction",
}
- local function make_expression(str)
+ local function make_expression(str) --could also be an lpeg
str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')")
str = str:gsub("position%(%)", "i")
str = str:gsub("text%(%)", "t")
str = str:gsub("!=", "~=")
str = str:gsub("([^=!~<>])=([^=!~<>])", "%1==%2")
str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(")
- return str, loadstring(string.format("return function(functions,i,a,t) return %s end", str))()
+ return str, loadstring(format("return function(functions,i,a,t) return %s end", str))()
end
local map = { }
- local space = lpeg.S(' \r\n\t')
- local squote = lpeg.S("'")
- local dquote = lpeg.S('"')
- local lparent = lpeg.P('(')
- local rparent = lpeg.P(')')
- local atsign = lpeg.P('@')
- local lbracket = lpeg.P('[')
- local rbracket = lpeg.P(']')
- local exclam = lpeg.P('!')
- local period = lpeg.P('.')
- local eq = lpeg.P('==') + lpeg.P('=')
- local ne = lpeg.P('<>') + lpeg.P('!=')
- local star = lpeg.P('*')
- local slash = lpeg.P('/')
- local colon = lpeg.P(':')
- local bar = lpeg.P('|')
- local hat = lpeg.P('^')
- local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-')
- local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1 + star) -- permits ns:*
- local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local P, S, R, C, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V
+
+ local space = S(' \r\n\t')
+ local squote = S("'")
+ local dquote = S('"')
+ local lparent = P('(')
+ local rparent = P(')')
+ local atsign = P('@')
+ local lbracket = P('[')
+ local rbracket = P(']')
+ local exclam = P('!')
+ local period = P('.')
+ local eq = P('==') + P('=')
+ local ne = P('<>') + P('!=')
+ local star = P('*')
+ local slash = P('/')
+ local colon = P(':')
+ local bar = P('|')
+ local hat = P('^')
+ local valid = R('az', 'AZ', '09') + S('_-')
+ local name_yes = C(valid^1) * colon * C(valid^1 + star) -- permits ns:*
+ local name_nop = C(P(true)) * C(valid^1)
local name = name_yes + name_nop
- local number = lpeg.C((lpeg.S('+-')^0 * lpeg.R('09')^1)) / tonumber
+ local number = C((S('+-')^0 * R('09')^1)) / tonumber
local names = (bar^0 * name)^1
local morenames = name * (bar^0 * name)^1
- local instructiontag = lpeg.P('pi::')
- local spacing = lpeg.C(space^0)
+ local instructiontag = P('pi::')
+ local spacing = C(space^0)
local somespace = space^1
local optionalspace = space^0
- local text = lpeg.C(valid^0)
- local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local text = C(valid^0)
+ local value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote)
local empty = 1-slash
local is_eq = lbracket * atsign * name * eq * value * rbracket
@@ -780,9 +817,9 @@ do
local is_number = lbracket * number * rbracket
local nobracket = 1-(lbracket+rbracket) -- must be improved
- local is_expression = lbracket * lpeg.C(((lpeg.C(nobracket^1))/make_expression)) * rbracket
+ local is_expression = lbracket * C(((C(nobracket^1))/make_expression)) * rbracket
- local is_expression = lbracket * (lpeg.C(nobracket^1))/make_expression * rbracket
+ local is_expression = lbracket * (C(nobracket^1))/make_expression * rbracket
local is_one = name
local is_none = exclam * name
@@ -822,18 +859,21 @@ do
local expression = (is_one * is_expression)/ function(...) map[#map+1] = { 31, true, ... } end
local dont_expression = (is_none * is_expression)/ function(...) map[#map+1] = { 31, false, ... } end
+ local self_expression = ( is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end
+ local dont_self_expression = (exclam * is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end
+
local instruction = (instructiontag * text ) / function(...) map[#map+1] = { 40, ... } end
local nothing = (empty ) / function( ) map[#map+1] = { 15 } end -- 15 ?
local crap = (1-slash)^1
-- a few ugly goodies:
- local docroottag = lpeg.P('^^') / function( ) map[#map+1] = { 12 } end
- local subroottag = lpeg.P('^') / function( ) map[#map+1] = { 13 } end
- local roottag = lpeg.P('root::') / function( ) map[#map+1] = { 12 } end
- local parenttag = lpeg.P('parent::') / function( ) map[#map+1] = { 11 } end
- local childtag = lpeg.P('child::')
- local selftag = lpeg.P('self::')
+ local docroottag = P('^^') / function( ) map[#map+1] = { 12 } end
+ local subroottag = P('^') / function( ) map[#map+1] = { 13 } end
+ local roottag = P('root::') / function( ) map[#map+1] = { 12 } end
+ local parenttag = P('parent::') / function( ) map[#map+1] = { 11 } end
+ local childtag = P('child::')
+ local selftag = P('self::')
-- there will be more and order will be optimized
@@ -847,18 +887,19 @@ do
dont_match_and_eq + dont_match_and_ne +
match_and_eq + match_and_ne +
dont_expression + expression +
+ dont_self_expression + self_expression +
has_attribute + has_value +
dont_match_one_of + match_one_of +
dont_match + match +
crap + empty
)
- local grammar = lpeg.P { "startup",
- startup = (initial + documentroot + subtreeroot + roottag + docroottag + subroottag)^0 * lpeg.V("followup"),
+ local grammar = P { "startup",
+ startup = (initial + documentroot + subtreeroot + roottag + docroottag + subroottag)^0 * V("followup"),
followup = ((slash + parenttag + childtag + selftag)^0 * selector)^1,
}
- function compose(str)
+ local function compose(str)
if not str or str == "" then
-- wildcard
return true
@@ -880,7 +921,7 @@ do
-- root
return false
end
- elseif #map == 2 and m == 12 and map[2][1] == 20 then
+ elseif #map == 2 and m == 12 and map[2][1] == 20 then
-- return { { 29, map[2][2], map[2][3], map[2][4], map[2][5] } }
map[2][1] = 29
return { map[2] }
@@ -888,6 +929,7 @@ do
if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
table.insert(map, 1, { 16 })
end
+ -- print((table.serialize(map)):gsub("[ \n]+"," "))
return map
end
end
@@ -922,7 +964,7 @@ do
report(" -: wildcard\n")
else
if type(pattern) == "string" then
- report(string.format("pattern: %s\n",pattern))
+ report(format("pattern: %s\n",pattern))
end
for k,v in ipairs(lp) do
if #v > 1 then
@@ -935,9 +977,9 @@ do
t[#t+1] = (vv and "==") or "<>"
end
end
- report(string.format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," ")))
+ report(format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],concat(t," ")))
else
- report(string.format("%2i: %s %s\n", k,v[1],actions[v[1]]))
+ report(format("%2i: %s %s\n", k,v[1],actions[v[1]]))
end
end
end
@@ -1058,7 +1100,7 @@ do
start, stop, step = stop, start, -1
end
local idx = 0
- for k=start,stop,step do
+ for k=start,stop,step do -- we used to have functions for all but a case is faster
local e = rootdt[k]
local ns, tg = e.rn or e.ns, e.tg
if tg then
@@ -1133,7 +1175,7 @@ do
if tg == tg_a then matched = ns == action[3] elseif tg_a == '*' then matched, multiple = ns == action[3], true else matched = false end
if not action[2] then matched = not matched end
if matched then
- matched = action[6](functions,idx,e.at,edt[1])
+ matched = action[6](functions,idx,e.at or { },edt[1])
end
end
if matched then -- combine tg test and at test
@@ -1225,53 +1267,25 @@ do
xml.filters = { }
- --[[ldx--
- <p>For splitting the filter function from the path specification, we can
- use string matching or lpeg matching. Here the difference in speed is
- neglectable but the lpeg variant is more robust.</p>
- --ldx]]--
-
- -- function xml.filter(root,pattern)
- -- local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$")
- -- if fun then
- -- return (xml.filters[fun] or xml.filters.default)(root,pat,arg)
- -- else
- -- pat, arg = pattern:match("^(.+)/@(.-)$")
- -- if arg then
- -- return xml.filters.attributes(root,pat,arg)
- -- else
- -- return xml.filters.default(root,pattern)
- -- end
- -- end
- -- end
-
- -- not faster but hipper ... although ... i can't get rid of the trailing / in the path
-
- local name = (lpeg.R("az","AZ")+lpeg.R("_-"))^1
- local path = lpeg.C(((1-lpeg.P('/'))^0 * lpeg.P('/'))^1)
- local argument = lpeg.P { "(" * lpeg.C(((1 - lpeg.S("()")) + lpeg.V(1))^0) * ")" }
- local action = lpeg.Cc(1) * path * lpeg.C(name) * argument
- local attribute = lpeg.Cc(2) * path * lpeg.P('@') * lpeg.C(name)
-
- local parser = action + attribute
-
- function xml.filter(root,pattern)
- local kind, a, b, c = parser:match(pattern)
- if kind == 1 then
- return (xml.filters[b] or xml.filters.default)(root,a,c)
- elseif kind == 2 then
- return xml.filters.attributes(root,a,b)
- else
- return xml.filters.default(root,pattern)
- end
- end
-
function xml.filters.default(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end)
return dt and dt[dk], rt, dt, dk
end
-
+ function xml.filters.attributes(root,pattern,arguments)
+ local rt, dt, dk
+ traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
+ local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
+ if ekat then
+ if arguments then
+ return ekat[arguments] or "", rt, dt, dk
+ else
+ return ekat, rt, dt, dk
+ end
+ else
+ return { }, rt, dt, dk
+ end
+ end
function xml.filters.reverse(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse')
@@ -1329,27 +1343,13 @@ do
end
return nil, nil, nil, nil
end
- function xml.filters.attributes(root,pattern,arguments)
- local rt, dt, dk
- traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
- local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
- if ekat then
- if arguments then
- return ekat[arguments] or "", rt, dt, dk
- else
- return ekat, rt, dt, dk
- end
- else
- return { }, rt, dt, dk
- end
- end
function xml.filters.attribute(root,pattern,arguments)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
return (ekat and (ekat[arguments] or ekat[arguments:gsub("^([\"\'])(.*)%1$","%2")])) or ""
end
- function xml.filters.text(root,pattern,arguments) -- ?? why index
+ function xml.filters.text(root,pattern,arguments) -- ?? why index, tostring slow
local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments)
if dtk then
local dtkdt = dtk.dt
@@ -1366,6 +1366,66 @@ do
end
--[[ldx--
+ <p>For splitting the filter function from the path specification, we can
+ use string matching or lpeg matching. Here the difference in speed is
+ neglectable but the lpeg variant is more robust.</p>
+ --ldx]]--
+
+ -- not faster but hipper ... although ... i can't get rid of the trailing / in the path
+
+ local P, S, R, C, V, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc
+
+ local name = (R("az","AZ")+R("_-"))^1
+ local path = C(((1-P('/'))^0 * P('/'))^1)
+ local argument = P { "(" * C(((1 - S("()")) + V(1))^0) * ")" }
+ local action = Cc(1) * path * C(name) * argument
+ local attribute = Cc(2) * path * P('@') * C(name)
+
+ local parser = action + attribute
+
+ local filters = xml.filters
+ local attribute_filter = xml.filters.attributes
+ local default_filter = xml.filters.default
+
+ function xml.filter(root,pattern)
+ local kind, a, b, c = parser:match(pattern)
+ if kind == 1 then
+ return (filters[b] or default_filter)(root,a,c)
+ elseif kind == 2 then
+ return attribute_filter(root,a,b)
+ else
+ return default_filter(root,pattern)
+ end
+ end
+
+ --~ slightly faster, but first we need a proper test file
+ --~
+ --~ local hash = { }
+ --~
+ --~ function xml.filter(root,pattern)
+ --~ local h = hash[pattern]
+ --~ if not h then
+ --~ local kind, a, b, c = parser:match(pattern)
+ --~ if kind == 1 then
+ --~ h = { kind, filters[b] or default_filter, a, b, c }
+ --~ elseif kind == 2 then
+ --~ h = { kind, attribute_filter, a, b, c }
+ --~ else
+ --~ h = { kind, default_filter, a, b, c }
+ --~ end
+ --~ hash[pattern] = h
+ --~ end
+ --~ local kind = h[1]
+ --~ if kind == 1 then
+ --~ return h[2](root,h[2],h[4])
+ --~ elseif kind == 2 then
+ --~ return h[2](root,h[2],h[3])
+ --~ else
+ --~ return h[2](root,pattern)
+ --~ end
+ --~ end
+
+ --[[ldx--
<p>The following functions collect elements and texts.</p>
--ldx]]--
@@ -1435,12 +1495,14 @@ do
<p>We use the function variants in the filters.</p>
--ldx]]--
+ local wrap, yield = coroutine.wrap, coroutine.yield
+
function xml.elements(root,pattern,reverse)
- return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
+ return wrap(function() traverse(root, lpath(pattern), yield, reverse) end)
end
function xml.elements_only(root,pattern,reverse)
- return coroutine.wrap(function() traverse(root, lpath(pattern), function(r,d,k) coroutine.yield(d[k]) end, reverse) end)
+ return wrap(function() traverse(root, lpath(pattern), function(r,d,k) yield(d[k]) end, reverse) end)
end
function xml.each_element(root, pattern, handle, reverse)
@@ -1466,7 +1528,7 @@ do
local ek = d[k]
local a = ek.at or { }
handle(a)
- if next(a) then
+ if next(a) then -- next is faster than type (and >0 test)
ek.at = a
else
ek.at = nil
@@ -1786,6 +1848,8 @@ end
do
+ local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
+
-- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
--
-- 1021:0335:0287:0247
@@ -1794,23 +1858,23 @@ do
--
-- 1559:0257:0288:0190 (last one suggested by roberto)
- -- escaped = lpeg.Cs((lpeg.S("<&>") / xml.escapes + 1)^0)
- -- escaped = lpeg.Cs((lpeg.S("<")/"&lt;" + lpeg.S(">")/"&gt;" + lpeg.S("&")/"&amp;" + 1)^0)
- local normal = (1 - lpeg.S("<&>"))^0
- local special = lpeg.P("<")/"&lt;" + lpeg.P(">")/"&gt;" + lpeg.P("&")/"&amp;"
- local escaped = lpeg.Cs(normal * (special * normal)^0)
+ -- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
+ -- escaped = Cs((S("<")/"&lt;" + S(">")/"&gt;" + S("&")/"&amp;" + 1)^0)
+ local normal = (1 - S("<&>"))^0
+ local special = P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;"
+ local escaped = Cs(normal * (special * normal)^0)
-- 100 * 1000 * "oeps&lt; oeps&gt; oeps&amp;" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
- -- unescaped = lpeg.Cs((lpeg.S("&lt;")/"<" + lpeg.S("&gt;")/">" + lpeg.S("&amp;")/"&" + 1)^0)
- -- unescaped = lpeg.Cs((((lpeg.P("&")/"") * (lpeg.P("lt")/"<" + lpeg.P("gt")/">" + lpeg.P("amp")/"&") * (lpeg.P(";")/"")) + 1)^0)
- local normal = (1 - lpeg.S"&")^0
- local special = lpeg.P("&lt;")/"<" + lpeg.P("&gt;")/">" + lpeg.P("&amp;")/"&"
- local unescaped = lpeg.Cs(normal * (special * normal)^0)
+ -- unescaped = Cs((S("&lt;")/"<" + S("&gt;")/">" + S("&amp;")/"&" + 1)^0)
+ -- unescaped = Cs((((P("&")/"") * (P("lt")/"<" + P("gt")/">" + P("amp")/"&") * (P(";")/"")) + 1)^0)
+ local normal = (1 - S"&")^0
+ local special = P("&lt;")/"<" + P("&gt;")/">" + P("&amp;")/"&"
+ local unescaped = Cs(normal * (special * normal)^0)
-- 100 * 5000 * "oeps <oeps bla='oeps' foo='bar'> oeps </oeps> oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
- local cleansed = lpeg.Cs(((lpeg.P("<") * (1-lpeg.P(">"))^0 * lpeg.P(">"))/"" + 1)^0)
+ local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
function xml.escaped (str) return escaped :match(str) end
function xml.unescaped(str) return unescaped:match(str) end
@@ -1825,9 +1889,9 @@ function xml.join(t,separator,lastseparator)
result[k] = xml.tostring(v)
end
if lastseparator then
- return table.join(result,separator or "",1,#result-1) .. (lastseparator or "") .. result[#result]
+ return concat(result,separator or "",1,#result-1) .. (lastseparator or "") .. result[#result]
else
- return table.join(result,separator)
+ return concat(result,separator)
end
else
return ""
@@ -1846,13 +1910,17 @@ do if unicode and unicode.utf8 then
xml.entities = xml.entities or { } -- xml.entities.handler == function
+ function xml.entities.handler(e)
+ return format("[s]",e)
+ end
+
local char = unicode.utf8.char
local function toutf(s)
return char(tonumber(s,16))
end
- function xml.utfize(root)
+ function utfize(root)
local d = root.dt
for k=1,#d do
local dk = d[k]
@@ -1862,22 +1930,26 @@ do if unicode and unicode.utf8 then
d[k] = dk:gsub("&#x(.-);",toutf)
end
else
- xml.utfize(dk)
+ utfize(dk)
end
end
end
+ xml.utfize = utfize
+
local entities = xml.entities
- local function resolve(e)
- local ee = entities[e]
- if ee then
- return ee
- elseif e:find("#x") then
+ local function resolve(e) -- hex encoded always first, just to avoid mkii fallbacks
+ if e:find("#x") then
return char(tonumber(e:sub(3),16))
else
- local h = entities.handler
- return (h and h(e)) or "&" .. e .. ";"
+ local ee = entities[e]
+ if ee then
+ return ee
+ else
+ local h = xml.entities.handler
+ return (h and h(e)) or "&" .. e .. ";"
+ end
end
end
@@ -1890,7 +1962,7 @@ do if unicode and unicode.utf8 then
d[k] = dk:gsub("&(.-);",resolve)
end
else
- xml.utfize(dk)
+ utfize(dk)
end
end
end
@@ -1903,7 +1975,7 @@ do if unicode and unicode.utf8 then
end
end
- function xml.resolve_text_entities(str)
+ function xml.resolve_text_entities(str) -- maybe an lpeg. maybe resolve inline
if str:find("&") then
return (str:gsub("&(.-);",resolve))
else
@@ -1919,11 +1991,11 @@ do if unicode and unicode.utf8 then
end
end
+end end
+
-- xml.set_text_cleanup(xml.show_text_entities)
-- xml.set_text_cleanup(xml.resolve_text_entities)
-end end
-
--~ xml.lshow("/../../../a/(b|c)[@d='e']/f")
--~ xml.lshow("/../../../a/!(b|c)[@d='e']/f")
--~ xml.lshow("/../../../a/!b[@d!='e']/f")
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index bc568ebff..83e9b899f 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -283,12 +283,12 @@ languages.words.colors = {
do
- spacing = lpeg.S(" \n\r\t")
- markup = lpeg.S("-=")
- lbrace = lpeg.P("{")
- rbrace = lpeg.P("}")
- disc = (lbrace * (1-rbrace)^0 * rbrace)^1 -- or just 3 times, time this
- word = lpeg.Cs((markup/"" + disc/"" + (1-spacing))^1)
+ local spacing = lpeg.S(" \n\r\t")
+ local markup = lpeg.S("-=")
+ local lbrace = lpeg.P("{")
+ local rbrace = lpeg.P("}")
+ local disc = (lbrace * (1-rbrace)^0 * rbrace)^1 -- or just 3 times, time this
+ local word = lpeg.Cs((markup/"" + disc/"" + (1-spacing))^1)
function languages.words.load(tag, filename)
local filename = input.find_file(texmf.instance,filename,'other text file') or ""
@@ -325,7 +325,7 @@ do
local bynode = node.traverse
local bychar = string.utfcharacters
- function mark_words(head,found) -- can be optimized
+ local function mark_words(head,found) -- can be optimized
local cd = characters.data
local uc = utf.char
local current, start, str, language, n = head, nil, "", nil, 0
diff --git a/tex/context/base/luat-env.tex b/tex/context/base/luat-env.tex
index 8fdfff295..0b6f24663 100644
--- a/tex/context/base/luat-env.tex
+++ b/tex/context/base/luat-env.tex
@@ -96,9 +96,10 @@
environment.formatname = "\contextformat" % tex.formatname
environment.initex = \ifproductionrun false \else true \fi % tex.formatname == ""
environment.version = "\contextversion"
--- dofile(input.find_file(texmf.instance,"luat-env.lua","tex"))
\stopruntimectxluacode
+% no longer needed: dofile(input.find_file(texmf.instance,"luat-env.lua","tex"))
+
\chardef\ctxluaexecutionmode \zerocount % private
% we start at 500, below this, we store predefined data (dumps)
diff --git a/tex/context/base/luat-inp.lua b/tex/context/base/luat-inp.lua
index 131b8b06b..9ab21000c 100644
--- a/tex/context/base/luat-inp.lua
+++ b/tex/context/base/luat-inp.lua
@@ -1245,6 +1245,8 @@ end
-- work that well; the parsing is ok, but dealing with the resulting
-- table is a pain because we need to work inside-out recursively
+-- get rid of piecewise here, just a gmatch is ok
+
function input.aux.splitpathexpr(str, t, validate)
-- no need for optimization, only called a few times, we can use lpeg for the sub
t = t or { }
@@ -1252,7 +1254,7 @@ function input.aux.splitpathexpr(str, t, validate)
while true do
local done = false
while true do
- ok = false
+ local ok = false
str = str:gsub("([^{},]+){([^{}]-)}", function(a,b)
local t = { }
b:piecewise(",", function(s) t[#t+1] = a .. s end)
@@ -1262,7 +1264,7 @@ function input.aux.splitpathexpr(str, t, validate)
if not ok then break end
end
while true do
- ok = false
+ local ok = false
str = str:gsub("{([^{}]-)}([^{},]+)", function(a,b)
local t = { }
a:piecewise(",", function(s) t[#t+1] = s .. b end)
@@ -1272,7 +1274,7 @@ function input.aux.splitpathexpr(str, t, validate)
if not ok then break end
end
while true do
- ok = false
+ local ok = false
str = str:gsub("([,{]){([^{}]+)}([,}])", function(a,b,c)
ok, done = true, true
return a .. b .. c
@@ -1282,7 +1284,7 @@ function input.aux.splitpathexpr(str, t, validate)
if not done then break end
end
while true do
- ok = false
+ local ok = false
str = str:gsub("{([^{}]-)}{([^{}]-)}", function(a,b)
local t = { }
a:piecewise(",", function(sa)
@@ -1296,7 +1298,7 @@ function input.aux.splitpathexpr(str, t, validate)
if not ok then break end
end
while true do
- ok = false
+ local ok = false
str = str:gsub("{([^{}]-)}", function(a)
ok = true
return a
@@ -2165,7 +2167,7 @@ do
resolvers.file = resolvers.filename
resolvers.path = resolvers.pathname
- function resolve(instance,str)
+ local function resolve(instance,str)
if type(str) == "table" then
for k, v in pairs(str) do
str[k] = resolve(instance,v) or v
diff --git a/tex/context/base/luat-tex.lua b/tex/context/base/luat-tex.lua
index 1081af517..894160bb6 100644
--- a/tex/context/base/luat-tex.lua
+++ b/tex/context/base/luat-tex.lua
@@ -207,7 +207,7 @@ if texconfig and not texlua then do
ws("fonts load time - %s seconds", input.loadtime(fonts))
end
if xml then
- ws("xml load time - %s seconds", input.loadtime(lxml))
+ ws("xml load time - %s seconds (backreferences: %i, outer filtering time: %s)", input.loadtime(xml), #lxml.self, input.loadtime(lxml))
end
if mptopdf then
ws("mps conversion time - %s seconds", input.loadtime(mptopdf))
@@ -245,6 +245,10 @@ if texconfig and not texlua then do
if fonts then
ws("loaded fonts - %s", fonts.logger.report()) -- last because it is often a long list
end
+ if xml then -- so we are in mkiv, we need a different check
+ -- todo: \nofshipouts
+ ws("shipped out pages - %i (of %i processed pages)", tex.count['nofshipouts'], tex.count['realpageno']-1) -- last because we want to see this
+ end
end
end end
diff --git a/tex/context/base/lxml-ini.lua b/tex/context/base/lxml-ini.lua
index 0c26e08e4..7963e73f6 100644
--- a/tex/context/base/lxml-ini.lua
+++ b/tex/context/base/lxml-ini.lua
@@ -6,15 +6,41 @@ if not modules then modules = { } end modules ['lxml-ini'] = {
license = "see context related readme files"
}
+-- todo: speed up
+
+local texsprint, texprint = tex.sprint or print, tex.print or print
+local format, concat = string.format, table.concat
+local type, next, tonumber = type, next, tonumber
+
document = document or { }
document.xml = document.xml or { }
lxml = { }
lxml.loaded = { }
-lxml.self = { }
+lxml.myself = { }
+
+local loaded = lxml.loaded
+local myself = lxml.myself
+
+lxml.self = myself -- be backward compatible for a while
+
+local function get_id(id)
+ return (type(id) == "table" and id) or loaded[id] or myself[tonumber(id)] -- no need for tonumber if we pass without ""
+end
+
+lxml.id = get_id
+
+function lxml.root(id)
+ return loaded[id]
+end
do
+ xml.specialhandler = xml.specialhandler or { }
+
+ local specialhandler = xml.specialhandler
+ local serialize = xml.serialize
+
local crlf = lpeg.P("\r\n")
local cr = lpeg.P("\r")
local lf = lpeg.P("\n")
@@ -25,35 +51,60 @@ do
local verbose = lpeg.C((1-(space+newline))^1)
local capture = (
- newline^2 * lpeg.Cc("") / tex.print +
- newline * lpeg.Cc(" ") / tex.sprint +
- content / tex.sprint
+ newline^2 * lpeg.Cc("") / texprint +
+ newline * lpeg.Cc(" ") / texsprint +
+ content / texsprint
)^0
- xml.specialhandler = { }
+--~ local function sprint(root)
+--~ if not root then
+--~ -- quit
+--~ elseif type(root) == 'string' then
+--~ capture:match(root)
+--~ elseif next(root) then
+--~ serialize(root,sprint,nil,nil,specialhandler)
+--~ end
+--~ end
local function sprint(root)
if not root then
-- quit
- elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root,sprint,nil,nil,xml.specialhandler)
+ else
+ local tr = type(root)
+ if tr == "string" then
+ capture:match(root)
+ elseif tr == "table" then
+ serialize(root,sprint,nil,nil,specialhandler)
+ end
end
end
xml.sprint = sprint
- function xml.tprint(root)
- if type(root) == "table" then
+ function xml.tprint(root) -- we can move sprint inline
+ local tr = type(root)
+ if tr == "table" then
for i=1,#root do
sprint(root[i])
end
- elseif type(root) == "string" then
+ elseif tr == "string" then
sprint(root)
end
end
+ function xml.cprint(root) -- content
+ if not root then
+ -- quit
+ elseif type(root) == 'string' then
+ capture:match(root)
+ elseif root.dt then -- the main one
+ serialize(root.dt,sprint,nil,nil,specialhandler)
+ else -- probably dt
+ serialize(root,sprint,nil,nil,specialhandler)
+ end
+ end
+
+
-- lines (untested)
local buffer = { }
@@ -68,9 +119,9 @@ do
if not root then
-- quit
elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root, lines)
+ capture:match(root)
+ elseif next(root) then -- tr == 'table'
+ serialize(root, lines)
end
end
@@ -88,15 +139,15 @@ do
local aftercommand = ""
local capture = (
- newline / function( ) tex.sprint(tex.texcatcodes,linecommand .. "{}") end +
- verbose / function(s) tex.sprint(tex.vrbcatcodes,s) end +
- space / function( ) tex.sprint(tex.texcatcodes,spacecommand .. "{}") end
+ newline / function( ) texsprint(tex.texcatcodes,linecommand .. "{}") end +
+ verbose / function(s) texsprint(tex.vrbcatcodes,s) end +
+ space / function( ) texsprint(tex.texcatcodes,spacecommand .. "{}") end
)^0
function toverbatim(str)
- if beforecommand then tex.sprint(tex.texcatcodes,beforecommand .. "{}") end
- lpeg.match(capture,str)
- if aftercommand then tex.sprint(tex.texcatcodes,aftercommand .. "{}") end
+ if beforecommand then texsprint(tex.texcatcodes,beforecommand .. "{}") end
+ capture:match(str)
+ if aftercommand then texsprint(tex.texcatcodes,aftercommand .. "{}") end
end
function lxml.set_verbatim(before,after,obeyedline,obeyedspace)
@@ -104,18 +155,18 @@ do
end
function lxml.set_cdata()
- xml.specialhandler['@cd@'] = toverbatim
+ specialhandler['@cd@'] = toverbatim
end
function lxml.reset_cdata()
- xml.specialhandler['@cd@'] = nil
+ specialhandler['@cd@'] = nil
end
function lxml.verbatim(id,before,after)
- local root = lxml.id(id)
- if before then tex.sprint(tex.ctxcatcodes,string.format("%s[%s]",before,root.tg)) end
- xml.serialize(root.dt,toverbatim,nil,nil,nil,true) -- was root
- if after then tex.sprint(tex.ctxcatcodes,after) end
+ local root = get_id(id)
+ if before then texsprint(tex.ctxcatcodes,format("%s[%s]",before,root.tg)) end
+ serialize(root.dt,toverbatim,nil,nil,nil,true) -- was root
+ if after then texsprint(tex.ctxcatcodes,after) end
end
function lxml.inlineverbatim(id)
lxml.verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
@@ -126,155 +177,169 @@ do
end
--- now comes the lxml one
-
-function lxml.id(id)
- return (type(id) == "table" and id) or lxml.loaded[id] or lxml.self[tonumber(id)]
-end
-
-function lxml.root(id)
- return lxml.loaded[id]
-end
+local xmlsprint = xml.sprint
+local xmltprint = xml.tprint
-- redefine xml load
xml.originalload = xml.load
---~ function xml.load(filename)
---~ input.starttiming(lxml)
---~ local x = xml.originalload(filename)
---~ input.stoptiming(lxml)
---~ return x
---~ end
-
function xml.load(filename)
- input.starttiming(lxml)
+ input.starttiming(xml)
local xmldata = xml.convert((filename and input.loadtexfile(texmf.instance,filename)) or "")
- input.stoptiming(lxml)
+ input.stoptiming(xml)
return xmldata
end
function lxml.load(id,filename)
- lxml.loaded[id] = xml.load(filename)
- return lxml.loaded[id], filename
+ loaded[id] = xml.load(filename)
+ return loaded[id], filename
end
function lxml.include(id,pattern,attribute,recurse)
- input.starttiming(lxml)
- xml.include(lxml.id(id),pattern,attribute,recurse,function(name) return (name and input.loadtexfile(texmf.instance,name)) or "" end)
- input.stoptiming(lxml)
+ input.starttiming(xml)
+ xml.include(get_id(id),pattern,attribute,recurse,function(name) return (name and input.loadtexfile(texmf.instance,name)) or "" end)
+ input.stoptiming(xml)
end
function lxml.utfize(id)
- xml.utfize(lxml.id(id))
+ xml.utfize(get_id(id))
end
+local xmlfilter, xmlfirst, xmllast, xmlall = xml.filter, xml.first, xml.last, xml.all
+local xmlcollect, xmlcontent, xmlcollect_texts = xml.collect, xml.content, xml.collect_texts
+local xmlattribute, xmlindex = xml.filters.attribute, xml.filters.index
+local xmlelements = xml.elements
+
function lxml.filter(id,pattern)
- xml.sprint(xml.filter(lxml.id(id),pattern))
+ xmlsprint(xmlfilter(get_id(id),pattern))
end
-
function lxml.first(id,pattern)
- xml.sprint(xml.first(lxml.id(id),pattern))
+ xmlsprint(xmlfirst(get_id(id),pattern))
end
-
function lxml.last(id,pattern)
- xml.sprint(xml.last(lxml.id(id),pattern))
+ xmlsprint(xmllast(get_id(id),pattern))
end
-
function lxml.all(id,pattern)
- xml.tprint(xml.collect(lxml.id(id),pattern))
+ xmltprint(xmlcollect(get_id(id),pattern))
end
-
function lxml.nonspace(id,pattern)
- xml.tprint(xml.collect(lxml.id(id),pattern,true))
+ xmltprint(xmlcollect(get_id(id),pattern,true))
+end
+function lxml.content(id,pattern)
+ xmlsprint(xmlcontent(get_id(id),pattern) or "")
end
function lxml.strip(id,pattern)
- xml.strip(lxml.id(id),pattern)
+ xml.strip(get_id(id),pattern)
end
function lxml.text(id,pattern)
- xml.tprint(xml.collect_texts(lxml.id(id),pattern) or {})
+ xmltprint(xmlcollect_texts(get_id(id),pattern) or {})
end
-function lxml.content(id,pattern)
- xml.sprint(xml.content(lxml.id(id),pattern) or "")
+function lxml.raw(id,pattern) -- the content, untouched by commands
+ local c = xmlfilter(get_id(id),pattern)
+ if c then
+ texsprint(concat(c.dt,""))
+ end
end
function lxml.stripped(id,pattern)
- local str = xml.content(lxml.id(id),pattern) or ""
- xml.sprint((str:gsub("^%s*(.-)%s*$","%1")))
+ local str = xmlcontent(get_id(id),pattern) or ""
+ xmlsprint((str:gsub("^%s*(.-)%s*$","%1")))
end
function lxml.flush(id)
- xml.sprint(lxml.id(id).dt)
+ xmlsprint(get_id(id).dt)
end
function lxml.index(id,pattern,i)
- xml.sprint((xml.filters.index(lxml.id(id),pattern,i)))
+ xmlsprint((xmlindex(get_id(id),pattern,i)))
end
function lxml.attribute(id,pattern,a,default) --todo: snelle xmlatt
- local str = xml.filters.attribute(lxml.id(id),pattern,a) or ""
- tex.sprint((str == "" and default) or str)
+ local str = xmlattribute(get_id(id),pattern,a) or ""
+ texsprint((str == "" and default) or str)
end
function lxml.count(id,pattern)
- tex.sprint(xml.count(lxml.id(id),pattern) or 0)
+ texsprint(xml.count(get_id(id),pattern) or 0)
end
function lxml.name(id) -- or remapped name?
- local r = lxml.id(id)
+ local r = get_id(id)
if r.ns then
- tex.sprint(r.ns .. ":" .. r.tg)
+ texsprint(r.ns .. ":" .. r.tg)
else
- tex.sprint(r.tg)
+ texsprint(r.tg)
end
end
function lxml.tag(id)
- tex.sprint(lxml.id(id).tg or "")
+ texsprint(get_id(id).tg or "")
end
function lxml.namespace(id) -- or remapped name?
- local root = lxml.id(id)
- tex.sprint(root.rn or root.ns or "")
+ local root = get_id(id)
+ texsprint(root.rn or root.ns or "")
end
--~ function lxml.concat(id,what,separator,lastseparator)
---~ tex.sprint(table.concat(xml.collect_texts(lxml.id(id),what,true),separator or ""))
+--~ texsprint(concat(xml.collect_texts(get_id(id),what,true),separator or ""))
--~ end
function lxml.concat(id,what,separator,lastseparator)
- local t = xml.collect_texts(lxml.id(id),what,true)
+ local t = xmlcollect_texts(get_id(id),what,true)
local separator = separator or ""
local lastseparator = lastseparator or separator or ""
for i=1,#t do
- tex.sprint(t[i])
+ texsprint(t[i])
if i == #t then
-- nothing
elseif i == #t-1 and lastseparator ~= "" then
- tex.sprint(tex.ctxcatcodes,lastseparator)
+ texsprint(tex.ctxcatcodes,lastseparator)
elseif separator ~= "" then
- tex.sprint(tex.ctxcatcodes,separator)
+ texsprint(tex.ctxcatcodes,separator)
end
end
end
-function xml.command(root) -- todo: free self after usage, so maybe hash after all
- -- no longer needed: xml.sflush()
- if type(root.command) == "string" then
- local n = #lxml.self + 1
- lxml.self[n] = root
- if xml.trace_print then
- texio.write_nl(string.format("tex.sprint: (((%s:%s)))",n,root.command))
- end
- -- problems with empty elements
- tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,root.command)) -- no sprint, else spaces go wrong
+-- string : setup
+-- true : text (no <self></self>)
+-- false : ignore
+-- function : call
+
+-- todo: free self after usage, i.e. after the setup, which
+-- means a call to lua; we can also choose a proper maximum
+-- and cycle or maybe free on demand
+
+-- problems with empty elements
+-- we use a real tex.sprint, else spaces go wrong
+-- maybe just a .. because this happens often
+
+function xml.command(root, command)
+ local tc = type(command)
+ if tc == "string" then
+ -- setup
+ local n = #myself + 1
+ myself[n] = root
+ texsprint(tex.ctxcatcodes,format("\\xmlsetup{%i}{%s}",n,command))
+ elseif tc == "function" then
+ -- function
+ command(root)
+ elseif command == true then
+ -- text (no <self></self>) / so, no mkii fallback then
+--~ local n = #myself + 1
+--~ myself[n] = root
+--~ texsprint(tex.ctxcatcodes,format("\\ctxlua{lxml.flush(%s)}",n)) -- hm, efficient?
+xmltprint(root.dt)
+ elseif command == false then
+ -- ignore
else
- root.command(root)
+ -- fuzzy, so ignore too
end
end
function lxml.setaction(id,pattern,action)
- for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
+ for rt, dt, dk in xmlelements(get_id(id),pattern) do
dt[dk].command = action
end
end
@@ -283,47 +348,62 @@ lxml.trace_setups = false
function lxml.setsetup(id,pattern,setup)
local trace = lxml.trace_setups
- if not setup or setup == "" or setup == "*" then
- for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
+ if not setup or setup == "" or setup == "*" or setup == "-" then
+ for rt, dt, dk in xmlelements(get_id(id),pattern) do
local dtdk = dt and dt[dk] or rt
local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg
- if ns == "" then
- dtdk.command = tg
+ local command = (ns == "" and tg) or (ns .. ":" .. tg)
+ if setup == "-" then
+ dtdk.command = false
+ if trace then
+ texio.write_nl(format("lpath matched -> %s -> skipped", command))
+ end
else
- dtdk.command = ns .. ":" .. tg
- end
- if trace then
- texio.write_nl(string.format("lpath matched -> %s -> %s", dtdk.command, dtdk.command))
+ dtdk.command = command
+ if trace then
+ texio.write_nl(format("lpath matched -> %s -> %s", command, command))
+ end
end
end
else
- local a, b = setup:match("^(.+:)(%*)$")
+ local a, b = setup:match("^(.+:)([%*%-])$")
if a and b then
- for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
+ for rt, dt, dk in xmlelements(get_id(id),pattern) do
local dtdk = (dt and dt[dk]) or rt
local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg
- dtdk.command = a .. tg
- if trace then
- if ns == "" then
- texio.write_nl(string.format("lpath matched -> %s -> %s", tg, dtdk.command))
- else
- texio.write_nl(string.format("lpath matched -> %s:%s -> %s", ns, tg, dtdk.command))
+ if b == "-" then
+ dtdk.command = false
+ if trace then
+ if ns == "" then
+ texio.write_nl(format("lpath matched -> %s -> skipped", tg))
+ else
+ texio.write_nl(format("lpath matched -> %s:%s -> skipped", ns, tg))
+ end
+ end
+ else
+ dtdk.command = a .. tg
+ if trace then
+ if ns == "" then
+ texio.write_nl(format("lpath matched -> %s -> %s", tg, dtdk.command))
+ else
+ texio.write_nl(format("lpath matched -> %s:%s -> %s", ns, tg, dtdk.command))
+ end
end
end
end
else
if trace then
- texio.write_nl(string.format("lpath pattern -> %s -> %s", pattern, setup))
+ texio.write_nl(format("lpath pattern -> %s -> %s", pattern, setup))
end
- for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
+ for rt, dt, dk in xmlelements(get_id(id),pattern) do
local dtdk = (dt and dt[dk]) or rt
dtdk.command = setup
if trace then
local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg
if ns == "" then
- texio.write_nl(string.format("lpath matched -> %s -> %s", tg, setup))
+ texio.write_nl(format("lpath matched -> %s -> %s", tg, setup))
else
- texio.write_nl(string.format("lpath matched -> %s:%s -> %s", ns, tg, setup))
+ texio.write_nl(format("lpath matched -> %s:%s -> %s", ns, tg, setup))
end
end
end
@@ -332,7 +412,7 @@ function lxml.setsetup(id,pattern,setup)
end
function lxml.idx(id,pattern,i)
- local r = lxml.id(id)
+ local r = get_id(id)
if r then
local rp = r.patterns
if not rp then
@@ -344,7 +424,7 @@ function lxml.idx(id,pattern,i)
end
local rpi = rp[pattern] and rp[pattern][i]
if rpi then
- xml.sprint(rpi)
+ xmlsprint(rpi)
end
end
end
@@ -358,14 +438,14 @@ do
command = command:gsub("^([\'\"])(.-)%1$", "%2")
traverse(root, lpath(pattern), function(r,d,k)
-- this can become pretty large
- local n = #lxml.self + 1
- lxml.self[n] = (d and d[k]) or r
- tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,command))
+ local n = #myself + 1
+ myself[n] = (d and d[k]) or r
+ texsprint(tex.ctxcatcodes,format("\\xmlsetup{%s}{%s}",n,command))
end)
end
function lxml.command(id,pattern,command)
- xml.filters.command(lxml.id(id),pattern,command)
+ xml.filters.command(get_id(id),pattern,command)
end
end
@@ -403,8 +483,7 @@ do
end
end
local root = xml.load(filename)
- local format = string.format
- for r, d, k in xml.elements(root,"directive") do
+ for r, d, k in xmlelements(root,"directive") do
local dk = d[k]
local at = dk.at
local attribute, value, element = at.attribute or "", at.value or "", at.element or '*'
@@ -431,7 +510,7 @@ do
end
function lxml.directives.handle_setup(category,root,attribute,element)
- root = lxml.id(root)
+ root = get_id(root)
attribute = attribute
if attribute then
local value = root.at[attribute]
@@ -444,20 +523,19 @@ do
element = ns .. ':' .. tg
end
end
- local format = string.format
local setup = data[format("%s::%s::%s",element,attribute,value)]
if setup then
setup = setup[category]
end
if setup then
- tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup))
+ texsprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup))
else
setup = data[format("%s::%s::*",element,attribute)]
if setup then
setup = setup[category]
end
if setup then
- tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup:gsub('%*',value)))
+ texsprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup:gsub('%*',value)))
end
end
end
@@ -467,14 +545,14 @@ do
end
function xml.getbuffer(name) -- we need to make sure that commands are processed
- xml.tostring(xml.convert(table.join(buffers.data[name] or {},"")))
+ xml.tostring(xml.convert(concat(buffers.data[name] or {},"")))
end
function lxml.loadbuffer(id,name)
- input.starttiming(lxml)
- lxml.loaded[id] = xml.convert(table.join(buffers.data[name or id] or {},""))
- input.stoptiming(lxml)
- return lxml.loaded[id], name or id
+ input.starttiming(xml)
+ loaded[id] = xml.convert(concat(buffers.data[name or id] or {},""))
+ input.stoptiming(xml)
+ return loaded[id], name or id
end
-- for the moment here:
@@ -482,7 +560,6 @@ end
lxml.set_verbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
lxml.set_cdata()
-
do
local traced = { }
@@ -500,10 +577,121 @@ do
if h then
local d = tonumber(h,16)
local u = unicode.utf8.char(d)
- texio.write_nl(string.format("entity: %s / %s / %s / n=%s",h,d,u,traced[v]))
+ texio.write_nl(format("entity: %s / %s / %s / n=%s",h,d,u,traced[v]))
else
- texio.write_nl(string.format("entity: %s / n=%s",v,traced[v]))
+ texio.write_nl(format("entity: %s / n=%s",v,traced[v]))
+ end
+ end
+ end
+
+end
+
+-- yes or no ...
+
+do
+
+ local function with_elements_only(e,handle)
+ if e and handle then
+ local etg = e.tg
+ if etg then
+ if e.special and etg ~= "@rt@" then
+ if resthandle then
+ resthandle(e)
+ end
+ else
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "table" then
+ handle(e)
+ with_elements_only(e,handle)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local function with_elements_only(e,handle,depth)
+ if e and handle then
+ local edt = e.dt
+ if edt then
+ depth = depth or 0
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "table" then
+ handle(e,depth)
+ with_elements_only(e,handle,depth+1)
+ end
+ end
+ end
+ end
+ end
+
+ xml.with_elements_only = with_elements_only
+
+ local function to_text(e)
+ if e.command == nil then
+ local etg = e.tg
+ if etg and e.special and etg ~= "@rt@" then
+ e.command = false -- i.e. skip
+ else
+ e.command = true -- i.e. no <self></self>
+ end
+ end
+ end
+ local function to_none(e)
+ if e.command == nil then
+ e.command = false -- i.e. skip
+ end
+ end
+
+ function lxml.set_command_to_text(id)
+ xml.with_elements_only(get_id(id),to_text)
+ end
+
+ function lxml.set_command_to_none(id)
+ xml.with_elements_only(get_id(id),to_none)
+ end
+
+ function lxml.get_command_status(id)
+ local status, stack = {}, {}
+ local function get(e,d)
+ local ns, tg = e.ns, e.tg
+ local name = tg
+ if ns ~= "" then name = ns .. ":" .. tg end
+ stack[d] = name
+ local ec = e.command
+ if ec == true then
+ ec = "system: text"
+ elseif ec == false then
+ ec = "system: skip"
+ elseif ec == nil then
+ ec = "system: not set"
+ elseif type(ec) == "string" then
+ ec = "setup: " .. ec
+ else -- function
+ ec = tostring(ec)
+ end
+ local tag = table.concat(stack," => ",1,d)
+ local s = status[tag]
+ if not s then
+ s = { }
+ status[tag] = s
+ end
+ s[ec] = (s[ec] or 0) + 1
+ end
+ if id then
+ xml.with_elements_only(get_id(id),get)
+ return status
+ else
+ local t = { }
+ for id, _ in pairs(lxml.loaded) do
+ t[id] = lxml.get_command_status(id)
end
+ return t
end
end
diff --git a/tex/context/base/lxml-ini.tex b/tex/context/base/lxml-ini.tex
index 750e242fc..93ab1b704 100644
--- a/tex/context/base/lxml-ini.tex
+++ b/tex/context/base/lxml-ini.tex
@@ -28,6 +28,7 @@
\def\xmlnonspace #1#2{\ctxlua{lxml.nonspace("#1","#2")}}
\def\xmltext #1#2{\ctxlua{lxml.text("#1","#2")}}
\def\xmlcontent #1#2{\ctxlua{lxml.content("#1","#2")}}
+\def\xmlraw #1#2{\ctxlua{lxml.raw("#1","#2")}}
\def\xmlstripped #1#2{\ctxlua{lxml.stripped("#1","#2")}}
\def\xmlstrip #1#2{\ctxlua{lxml.strip("#1","#2")}}
\def\xmlflush #1{\ctxlua{lxml.flush("#1")}}
@@ -51,10 +52,11 @@
\def\xmlremapname #1#2#3#4{\ctxlua{xml.remapname(lxml.id("#1"),"#2","#3","#4")}} % element
\def\xmlremapnamespace#1#2#3{\ctxlua{xml.rename_space(lxml.id("#1"),"#2","#3")}} % document
\def\xmldelete #1#2{\ctxlua{xml.delete(lxml.id("#1"),"#2")}}
-\def\xmlinclude #1#2#3{\ctxlua{lxml.include(lxml.id("#1"),"#2","#3",true)}}
-\def\xmldoifelse #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",false))}}
-\def\xmldoifelsetext #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",true ))}}
-\def\xmlverbatim #1{\ctxlua{lxml.verbatim(lxml.id("#1"))}}
+\def\xmlinclude #1#2#3{\ctxlua{lxml.include("#1","#2","#3",true)}}
+\def\xmlverbatim #1{\ctxlua{lxml.verbatim("#1")}}
+
+%def\xmldoifelse #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",false))}}
+%def\xmldoifelsetext #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",true ))}}
\def\xmldoifelse #1#2{\ctxlua{commands.doifelse(xml.found(lxml.id("#1"),"#2",false))}}
\def\xmldoifelsetext #1#2{\ctxlua{commands.doifelse(xml.found(lxml.id("#1"),"#2",true ))}}
@@ -63,6 +65,8 @@
\def\xmldoifnot #1#2{\ctxlua{commands.doifnot (xml.found(lxml.id("#1"),"#2",false))}}
\def\xmldoifnottext #1#2{\ctxlua{commands.doifnot (xml.found(lxml.id("#1"),"#2",true ))}}
+\def\xmldefaulttotext #1{\ifcase\xmlprocessingmode\or\or \ctxlua{lxml.set_command_to_text("#1")}\fi}
+\def\xmldefaulttonone #1{\ifcase\xmlprocessingmode\or\or\or\ctxlua{lxml.set_command_to_none("#1")}\fi}
% \startxmlsetups xml:include
% \xmlinclude{main}{include}{filename|href}
@@ -84,13 +88,25 @@
\let\xmlregistersetup\xmlappendsetup
\def\xmlregisteredsetups
- {\the\registeredxmlsetups\registeredxmlsetups\emptytoks}
+ {\xmlstarttiming
+ \the\registeredxmlsetups\registeredxmlsetups\emptytoks
+ \xmlstoptiming}
+
+\chardef\xmlprocessingmode=0 % 0=mixed, 1=mkivonly, 2=mkivonly-default-text, 3=mkivonly-default-none
+
+\def\xmlstarttiming{\ctxlua{input.starttiming(lxml)}}
+\def\xmlstoptiming {\ctxlua{input.stoptiming (lxml)}}
\def\doxmlprocess#1#2#3#4%
{\begingroup
\def\xmldocument{#2}%
#1{#2}{#3}%
- \enableXML
+ \ifcase\xmlprocessingmode
+ \enableXML
+ \fi
+ \xmlstarttiming
+ \xmldefaulttotext\xmldocument
+ \xmlstoptiming
\doifelsenothing{#4}
{\directsetup{xml:process}}
{\directsetup{#4}}%
@@ -104,9 +120,6 @@
\xmlall\xmldocument{/}
\stopsetups
-% \long\def\xmlloop#1#2#3%
-% {\dorecurse{\xmlcount{#1}{#2}}{\def\xmli####1####2{\xmlidx{#1}{#2/####1}{####2}}#3}}
-
\long\def\xmlloop#1#2#3%
{\def\xmli##1##2{\xmlidx{#1}{#2/##1}{##2}}%
\dorecurse{\xmlcount{#1}{#2}}{#3}}
@@ -180,7 +193,7 @@
% entities
\def\xmlresolveentities
- {\ctxlua{xml.set_text_cleanup(xml.set_text_cleanup(xml.resolve_text_entities))}}
+ {\ctxlua{xml.set_text_cleanup(xml.resolve_text_entities)}}
\def\xmltraceentities
{\ctxlua{xml.set_text_cleanup(lxml.trace_text_entities)}%
@@ -219,7 +232,7 @@
% % An example by Wolfgang Schuster:
%
% \startxmlsetups xml:mysetups
-% \xmlsetsetup{\xmldocument}{section{xml:*}
+% \xmlsetsetup{\xmldocument}{section}{xml:*}
% \xmlsetsetup{\xmldocument}{title|p}{xml:*}
% \stopxmlsetups
%
diff --git a/tex/context/base/m-chart.tex b/tex/context/base/m-chart.tex
index e08ff4276..f5d0ea7b9 100644
--- a/tex/context/base/m-chart.tex
+++ b/tex/context/base/m-chart.tex
@@ -13,7 +13,8 @@
% to do: \localpushmacro/\localpopmacro (dohandleflowchart etc)
-% will be redone with layers and dimexpr
+% will be redone with layers and dimexpr ro even better, by just using
+% textext
%D This is an experimental module. Pieces of code will be moved
%D to other modules. More features are possible but will be
diff --git a/tex/context/base/m-timing.tex b/tex/context/base/m-timing.tex
index 24c2d1e9a..e86e34ab4 100644
--- a/tex/context/base/m-timing.tex
+++ b/tex/context/base/m-timing.tex
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+\ifx\ShowNamedUsage\undefined \else \endinput \fi
+
%D Written at the end of 2007, this module is dedicated to Taco. Reaching this
%D point in \LUATEX\ was a non trivial effort. By visualizing a bit what happens
%D when pages come out of \LUATEX, you may get an idea what is involved. It took
diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
index b060095cf..c02be7455 100644
--- a/tex/context/base/math-ini.lua
+++ b/tex/context/base/math-ini.lua
@@ -103,14 +103,15 @@ function mathematics.setmathsymbol(name,class,family,slot,largefamily,largeslot,
class = mathematics.classes[class] or class -- no real checks needed
family = mathematics.families[family] or family
-- \unexpanded ? \relax needed for the codes?
+ local classes = mathematics.classes
if largefamily and largeslot then
largefamily = mathematics.families[largefamily] or largefamily
- if class == mathradical then
+ if class == classes.radical then
tex.sprint(("\\xdef\\%s{%s\\relax}"):format(name,mathematics.radical(class,family,slot,largefamily,largeslot)))
- else
+ elseif class == classes.open or class == classes.close then
tex.sprint(("\\xdef\\%s{%s\\relax}"):format(name,mathematics.delimiter(class,family,slot,largefamily,largeslot)))
end
- elseif class == mathaccent then
+ elseif class == classes.accent then
tex.sprint(("\\xdef\\%s{%s\\relax}"):format(name,mathematics.mathaccent(class,family,slot)))
elseif unicode then
tex.sprint(("\\xdef\\%s{%s}"):format(name,utf.char(unicode)))
@@ -136,9 +137,14 @@ end
mathematics.trace = false
+
+
function mathematics.define()
local slots = mathematics.slots.current
- local function trace(k,c,f,i,fe,ie)
+ local setmathcharacter = mathematics.setmathcharacter
+ local setmathsymbol = mathematics.setmathsymbol
+ local trace = mathematics.trace
+ local function report(k,c,f,i,fe,ie)
if fe then
logs.report("mathematics",string.format("a - symbol 0x%05X -> %s -> %s %s (%s %s)",k,c,f,i,fe,ie))
elseif c then
@@ -157,32 +163,32 @@ function mathematics.define()
local s = slots[k]
if s then
local f, i, fe, ie = s[1], s[2], s[3], s[4]
- if mathematics.trace then
- trace(k,c,f,i,fe,ie)
+ if trace then
+ report(k,c,f,i,fe,ie)
end
- mathematics.setmathcharacter(k,m,f,i,fe,ie)
+ setmathcharacter(k,m,f,i,fe,ie)
end
elseif c then
local s = slots[k]
if s then
local f, i, fe, ie = s[1], s[2], s[3], s[4]
- if mathematics.trace then
- trace(k,c,f,i,fe,ie)
+ if trace then
+ report(k,c,f,i,fe,ie)
end
- mathematics.setmathsymbol(c,m,f,i,fe,ie,k)
- mathematics.setmathcharacter(k,m,f,i,fe,ie)
+ setmathsymbol(c,m,f,i,fe,ie,k)
+ setmathcharacter(k,m,f,i,fe,ie)
end
elseif v.contextname then
local s = slots[k]
local c = v.contextname
if s then
local f, i, fe, ie = s[1], s[2], s[3], s[4]
- if mathematics.trace then
- trace(k,c,f,i,fe,ie)
+ if trace then
+ report(k,c,f,i,fe,ie)
end
-- todo: mathortext
- -- mathematics.setmathsymbol(c,m,f,i,fe,ie,k)
- mathematics.setmathcharacter(k,m,f,i,fe,ie)
+ -- setmathsymbol(c,m,f,i,fe,ie,k)
+ setmathcharacter(k,m,f,i,fe,ie)
end
else
local a = v.adobename
@@ -195,10 +201,10 @@ function mathematics.define()
elseif m == "number" then
f, i = mathematics.families.numbers, k
end
- if mathematics.trace then
- trace(k,a,f,i,fe,ie)
+ if trace then
+ report(k,a,f,i,fe,ie)
end
- mathematics.setmathcharacter(k,m,f,i,fe,ie)
+ setmathcharacter(k,m,f,i,fe,ie)
end
end
end
@@ -216,7 +222,7 @@ mathematics.slots.traditional = {
[0x03B2] = { "lcgreek", 0x0C },
[0x03B3] = { "lcgreek", 0x0D },
[0x03B4] = { "lcgreek", 0x0E },
--- [0x03B5] = { "lcgreek", 0x00 }, -- varepsilon
+ [0x03B5] = { "lcgreek", 0x0F }, -- epsilon
[0x03B6] = { "lcgreek", 0x10 },
[0x03B7] = { "lcgreek", 0x11 },
[0x03B8] = { "lcgreek", 0x12 },
@@ -233,7 +239,7 @@ mathematics.slots.traditional = {
[0x03C3] = { "lcgreek", 0x1B },
[0x03C4] = { "lcgreek", 0x1C },
[0x03C5] = { "lcgreek", 0x1D },
- [0x03C6] = { "lcgreek", 0x1E },
+-- [0x03C6] = { "lcgreek", 0x1E }, -- varphi
[0x03C7] = { "lcgreek", 0x1F },
[0x03C8] = { "lcgreek", 0x20 },
[0x03C9] = { "lcgreek", 0x21 },
@@ -263,14 +269,18 @@ mathematics.slots.traditional = {
[0x03A8] = { "ucgreek", 0x09 },
[0x03A9] = { "ucgreek", 0x0A },
- [0x03B5] = { "vargreek", 0x22 }, -- varepsilon
+ [0x03F5] = { "vargreek", 0x22 }, -- varepsilon
[0x03D1] = { "vargreek", 0x23 }, -- vartheta
[0x03D6] = { "vargreek", 0x24 }, -- varpi
[0x03F1] = { "vargreek", 0x25 }, -- varrho
[0x03C2] = { "vargreek", 0x26 }, -- varsigma
+
[0x03C6] = { "vargreek", 0x27 }, -- varphi
+ [0x03D5] = { "lcgreek", 0x1E }, -- phi
+
-- [0x03F0] = { "", 0x00 }, -- varkappa
+
[0x0021] = { "mr", 0x21 }, -- !
[0x0028] = { "mr", 0x28 }, -- (
[0x0029] = { "mr", 0x29 }, -- )
@@ -295,18 +305,15 @@ mathematics.slots.traditional = {
[0x00B7] = { "sy", 0x01 }, -- cdot
[0x00D7] = { "sy", 0x02 }, -- times
[0x2022] = { "sy", 0x0F }, -- bullet
-
[0x2190] = { "sy", 0x20 }, -- leftarrow
[0x2192] = { "sy", 0x21 }, -- rightarrow
[0x2194] = { "sy", 0x24 }, -- leftrightarrow
-
[0x21D0] = { "sy", 0x28 }, -- Leftarrow
[0x21D2] = { "sy", 0x29 }, -- Rightarrow
[0x21D4] = { "sy", 0x2C }, -- Leftrightarrow
-
[0x2135] = { "sy", 0x40 }, -- aleph
[0x2113] = { "mi", 0x60 }, -- ell
-
+ [0x22C5] = { "sy", 0x01 }, -- cdot
[0x25B3] = { "sy", 0x34 }, -- triangle up
[0x1D6A4] = { "mi", 0x7B }, -- imath
@@ -322,6 +329,12 @@ mathematics.slots.traditional = {
[0x007C] = { "sy", 0x6A, "ex", 0x0C }, -- |
[0x005C] = { "sy", 0x6E, "ex", 0x0F }, -- \
+ [0x220F] = { "ex", 0x51 }, -- prod
+ [0x2211] = { "ex", 0x50 }, -- sum
+ [0x222B] = { "ex", 0x52 }, -- intop
+ [0x005E] = { "mr", 0x5E, "ex", 0x62 }, -- widehat
+ [0x007E] = { "mr", 0x7E, "ex", 0x65 }, -- widetilde
+
}
mathematics.slots.current = mathematics.slots.traditional
@@ -343,3 +356,10 @@ mathematics.slots.current = mathematics.slots.traditional
--~ tex.sprint(tex.ctxcatcodes,"\\endgroup")
--~ end
--~ end
+
+function mathematics.utfmathclass(chr, default)
+ return characters.data[utf.byte(chr)].mathclass or default or "unknown"
+end
+function mathematics.utfmathcommand(chr, default)
+ return characters.data[utf.byte(chr)].mathname or default or "unknown"
+end
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 49539f79e..0b1b53caa 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -25,4 +25,21 @@
\ctxlua{mathematics.define()}
+\def\utfmathclass #1{\ctxlua{tex.sprint (mathematics.utfmathclass ("#1"))}}
+\def\utfmathcommand#1{\ctxlua{commands.cs(mathematics.utfmathcommand("#1"))}}
+
+\def\utfmathclassdefault #1#2{\ctxlua{
+ tex.sprint(mathematics.utfmathclass("#1","#2"))
+}}
+
+\def\utfmathcommanddefault#1#2#3{\ctxlua{
+ local cmd = mathematics.utfmathcommand("#1","") or ""
+ if cmd == "" then
+ commands.cs("#2","#3")
+ else
+ commands.cs(cmd)
+ end}}
+
+% \let\math@normal@int\int \def\int{\math@normal@int\intlimits}
+
\protect \endinput
diff --git a/tex/context/base/meta-dum.tex b/tex/context/base/meta-dum.tex
index d6a4525b2..1d03fb16d 100644
--- a/tex/context/base/meta-dum.tex
+++ b/tex/context/base/meta-dum.tex
@@ -37,25 +37,25 @@
% to transparent colors
\startuseMPgraphic{placeholder}{width,height,reduction,color}
- numeric w, h, d, r ; color c, b, cc ; path p ; boolean t ;
- t := is_transparent(\MPvar{color}) ;
- c := not_transparent(\MPvar{color}) ;
- b := not_transparent(white) ;
- w := \MPvar{width} ;
- h := \MPvar{height} ;
- r := \MPvar{reduction} ;
- d := max(w,h) ;
- p := unitsquare xyscaled (w,h) ;
- cc := r[.5c,b] ;
- fill p withcolor if t : transparent(1,.5,cc) else : cc fi ;
- for i := 1 upto 60 :
- cc := r[c randomized(.3,.9),b] ;
- fill fullcircle
- scaled (d/5 randomized (d/5))
- shifted (center p randomized (d))
- withcolor if t : transparent(1,.5,cc) else : cc fi ;
- endfor ;
- clip currentpicture to p ;
+ numeric w, h, d, r ; color c, b, cc ; path p ; boolean t ;
+ t := is_transparent(\MPvar{color}) ;
+ c := not_transparent(\MPvar{color}) ;
+ b := not_transparent(white) ;
+ w := \MPvar{width} ;
+ h := \MPvar{height} ;
+ r := \MPvar{reduction} ;
+ d := max(w,h) ;
+ p := unitsquare xyscaled (w,h) ;
+ cc := r[.5c,b] ;
+ fill p withcolor if t : transparent(1,.5,cc) else : cc fi ;
+ for i := 1 upto 60 :
+ cc := r[c randomized(.3,.9),b] ;
+ fill fullcircle
+ scaled (d/5 randomized (d/5))
+ shifted (center p randomized (d))
+ withcolor if t : transparent(1,.5,cc) else : cc fi ;
+ endfor ;
+ clip currentpicture to p ;
\stopuseMPgraphic
\definepalet
diff --git a/tex/context/base/meta-fig.tex b/tex/context/base/meta-fig.mkii
index 3edd73b57..3edd73b57 100644
--- a/tex/context/base/meta-fig.tex
+++ b/tex/context/base/meta-fig.mkii
diff --git a/tex/context/base/meta-fig.mkiv b/tex/context/base/meta-fig.mkiv
new file mode 100644
index 000000000..c2c2e127f
--- /dev/null
+++ b/tex/context/base/meta-fig.mkiv
@@ -0,0 +1,84 @@
+%D \module
+%D [ file=meta-fig,
+%D version=2000.09.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Stand Alone Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Stand Alone Graphics}
+
+\unprotect
+
+%D This module implements a method for defining
+%D stand||alone||graphics, that is, each graphic gets is own
+%D page. Because graphics are wrapped in a \type {\framed},
+%D you can add overlays to the graphic directly, and since the
+%D whole \CONTEXT\ machinery is available, you can also add
+%D page backgrounds.
+%D
+%D \starttyping
+%D \setupMPpage
+%D [offset=1pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \startMPpage
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopMPpage
+%D
+%D \startMPpage
+%D fill fullsquare rotated 45 scaled 8cm withcolor blue ;
+%D \stopMPpage
+%D \stoptyping
+%D
+%D Although this is hardly of any use, you can mix these
+%D definitions with the text flow, since all settings are
+%D kept local. The page is clipped to the image size.
+
+\presetlocalframed[\??mg]
+
+\def\setupMPpage
+ {\dodoubleargument\getparameters[\??mg]}
+
+\def\startMPpage
+ {\dodoubleempty\dostartMPpage}
+
+\long\def\dostartMPpage[#1][#2]#3\stopMPpage % second arg gobbles space
+ {\dostartfittingpage[\??mg][#1]%
+ \processMPgraphic{#3}%
+ \dostopfittingpage}
+
+\let\stopMPpage \relax % so that we can use it in \expanded
+
+\setupMPpage
+ [\c!scale=1000,
+ \c!strut=\v!no,
+ \c!align=,
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D \macros
+%D {MPfigure}
+%D
+%D A bit out of place, here but nevertheless:
+
+\def\MPfigure#1#2% test for dup figure, can be replaced by a textext
+ {\bgroup
+ \getfiguredimensionsonly[#1]% [\c!object=\v!no] already set
+ \startMPcode
+ externalfigure "#1"
+ xscaled \figurewidth\space
+ yscaled \figureheight\space
+ #2 ;
+ \stopMPcode
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/meta-ini.tex b/tex/context/base/meta-ini.mkii
index d807795be..302bdff99 100644
--- a/tex/context/base/meta-ini.tex
+++ b/tex/context/base/meta-ini.mkii
@@ -69,6 +69,12 @@
\maxnofMPgraphics = 4000 % metafun disables the 4K boundary
+\appendtoks \runMPgraphicsfalse \to \everyfastmode
+\appendtoks \insertMPgraphicsfalse \to \everyfastmode
+\appendtoks \flushMPgraphics \to \everygoodbye % \everylastshipout
+
+\def\@@MPG{@MPG@}
+
\startMPextensions
if unknown context_tool: input mp-tool; fi;
if unknown context_spec: input mp-spec; fi;
@@ -485,43 +491,36 @@
\def\MPrunfile#1%
{\bufferprefix mprun.#1}
-%D We also have to make sure that \METAPOST\ knows this:
-
-\startMPextensions
- if not known _data_prefix_:
- string _data_prefix_,_data_suffix_;
- fi;
- _data_prefix_:="\bufferprefix mpd-";
- _data_suffix_:=".mpd";
-\stopMPextensions
-
%D \macros
%D {getMPdata}
%D
-%D The current data is loaded with:
-
-\def\getMPdata
- {\startreadingfile
- \readlocfile\MPdatafile\donothing\donothing
- \stopreadingfile}
-
%D When we collect graphics in one file, we run into
%D troubles, since \METAPOST\ has a built in limit (of 4)
%D on the number of files it can handle. It's therefore
%D better to collect all data in one file and filter it.
+\def\MPdataMPDfile{\jobname-mp.mpd}
+\def\MPdataMPOfile{\jobname-mp.mpo}
+\def\MPdataMPYfile{\jobname-mp.mpy}
+
+\startMPextensions
+ boolean collapse_data; collapse_data:=true;
+ def data_mpd_file = "\MPdataMPDfile" enddef ;
+ def data_mpo_file = "\MPdataMPOfile" enddef ;
+ def data_mpy_file = "\MPdataMPYfile" enddef ;
+\stopMPextensions
+
\def\getMPdata
- {\long\def\MPdata##1##2%
- {\ifnum##1=\currentMPgraphic\relax##2\fi}%
+ {\long\def\MPdata##1##2{\ifnum##1=\currentMPgraphic\relax##2\fi}%
\startreadingfile
- \readlocfile{\MPgraphicfile.mpd}\donothing\donothing
+ \startnointerference
+ \readlocfile\MPdataMPDfile\donothing\donothing
+ \stopnointerference
\stopreadingfile}
%D We have to enable this mechanism with:
\startMPextensions
- boolean collapse_data; collapse_data:=true;
- _data_suffix_:=".mpd"; % overloads previous one
\stopMPextensions
%D For the moment, the next one is a private macro:
@@ -664,8 +663,8 @@
%D accomplished by:
\def\douseMPlibrary#1%
- {\ifundefined{\c!file\f!javascriptprefix#1}%
- \letvalueempty{\c!file\f!javascriptprefix#1}%
+ {\ifundefined{\c!file\f!metapostprefix#1}%
+ \letvalueempty{\c!file\f!metapostprefix#1}%
\makeshortfilename[\truefilename{\f!metapostprefix#1}]%
\startreadingfile
\readsysfile\shortfilename{\showmessage\m!metapost1{#1}}\donothing
diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv
new file mode 100644
index 000000000..a73c92911
--- /dev/null
+++ b/tex/context/base/meta-ini.mkiv
@@ -0,0 +1,1110 @@
+%D \module
+%D [ file=meta-ini,
+%D version=2008.03.25,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 / Initializations}
+
+\unprotect
+
+\startmessages dutch library: metapost
+ title: metapost
+ 1: metapost bibliotheek -- wordt geladen
+\stopmessages
+
+\startmessages english library: metapost
+ title: metapost
+ 1: loading metapost library --
+\stopmessages
+
+\startmessages german library: metapost
+ title: metapost
+ 1: loading metapost library --
+\stopmessages
+
+\startmessages czech library: metapost
+ title: metapost
+ 1: loading metapost library --
+\stopmessages
+
+\startmessages italian library: metapost
+ title: metapost
+ 1: caricamento della libreria metapost --
+\stopmessages
+
+\startmessages norwegian library: metapost
+ title: metapost
+ 1: metapost bibliotek -- blir lest inn
+\stopmessages
+
+\startmessages romanian library: metapost
+ title: metapost
+ 1: se incarca biblioteca metapost --
+\stopmessages
+
+\startmessages french library: metapost
+ title: metapost
+ 1: chargement de la bibliothèque metapost --
+\stopmessages
+
+%D Instead of sharing code with \MKII, I decided to copy
+%D the code. Otherwise maintainance becomes a pain and after all,
+%D the \MKII\ code will not change.
+
+\let\useMETAFUNformattrue \relax \let\useMETAFUNformatfalse\relax
+\let \longMPlinestrue \relax \let \longMPlinesfalse\relax
+\let \runMPgraphicstrue \relax \let \runMPgraphicsfalse\relax
+\let\runMPTEXgraphicstrue \relax \let\runMPTEXgraphicsfalse\relax
+\let \MPstaticgraphictrue \relax \let \MPstaticgraphicfalse\relax
+
+\let\maxnofMPgraphics\scratchcounter
+
+\newtoks \MPextensions % mp, once
+\newtoks \MPinitializations % tex, each
+\newtoks \MPuserinclusions % mp, user
+\newtoks \MPfinalizations % mp, user
+\newtoks \everyMPgraphic % mp
+\newtoks \everyMPTEXgraphic % tex
+
+\long\def\startMPextensions#1\stopMPextensions
+ {\global\MPextensions\expandafter{\the\MPextensions#1}}
+
+\long\def\startMPinitializations#1\stopMPinitializations
+ {\global\MPinitializations\expandafter{\the\MPinitializations#1}}
+
+\long\def\startMPinclusions
+ {\dosingleempty\dostartMPinclusions}
+
+\long\def\dostartMPinclusions[#1]#2\stopMPinclusions
+ {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
+ \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+
+\def\MPinclusions
+ {\dosingleempty\doMPinclusions}
+
+\long\def\doMPinclusions[#1]#2%
+ {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
+ \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+
+\ifx \overlaywidth \undefined \def \overlaywidth {4cm} \fi
+\ifx \overlayheight \undefined \def \overlayheight {3cm} \fi
+\ifx \overlaylinewidth \undefined \def \overlaylinewidth {0pt} \fi
+
+\def\presetMPdefinitions
+ {\edef\overlaywidth {\overlaywidth \space}%
+ \edef\overlayheight {\overlayheight \space}%
+ \edef\overlaylinewidth{\overlaylinewidth\space}%
+ \edef\currentwidth {\the\hsize \space}%
+ \edef\currentheight {\the\vsize \space}}
+
+\def\currentMPformat{metafun}
+
+\long\def\processMPgraphic#1% todo: extensions and inclusions outside beginfig
+ {\blabelgroup
+ \enableincludeMPgraphics
+ \the\everyMPgraphic
+ \presetMPdefinitions
+ \setMPrandomseed % this has to change
+ % we need to preexpand the token lists
+ \setbox\MPgraphicbox\hbox\bgroup
+ \ctxlua {
+ metapost.graphic(
+ "\currentMPformat",
+ \@EA\!!bs\the\MPinitializations;\theMPrandomseed;#1;\!!es, % code
+ \@EA\@EA\@EA\!!bs\@EA\the\@EA\MPextensions\@EA;\the\MPuserinclusions;\!!es % optional preamble
+ )
+ }%
+ \egroup
+ \placeMPgraphic
+ \global\MPextensions\emptytoks
+ \global\MPuserinclusions\emptytoks
+ \elabelgroup}
+
+\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default
+
+\def\setMPrandomseed
+ {\let\theMPrandomseed\empty
+ \ifsetMPrandomseed \ifx\getrandomnumber\undefined \else
+ \getrandomnumber\localMPseed\zerocount{4095}%
+ \def\theMPrandomseed{randomseed:=\localMPseed}%
+ \fi\fi}
+
+%D To be integrated
+
+\def\@@MPG{@MPG@}
+
+\def\doifMPgraphicelse#1%
+ {\blabelgroup
+ \doifdefinedelse{\@@MPG#1}%
+ {\elabelgroup\firstoftwoarguments}
+ {\elabelgroup\secondoftwoarguments}}
+
+\def\includeMPgraphic#1%
+ {\executeifdefined{\@@MPG#1};}
+
+\def\enableincludeMPgraphics
+ {\let\handleuseMPgraphic \secondoftwoarguments
+ \let\handlereusableMPgraphic\secondoftwoarguments}
+
+\let\MPdrawingdata\empty
+
+\newif\ifMPdrawingdone \MPdrawingdonefalse
+\newif\ifMPshiftdrawing \MPshiftdrawingfalse
+
+\def\resetMPdrawing
+ {\globallet\MPdrawingdata\empty
+ \global\MPdrawingdonefalse}
+
+\def\pushMPdrawing
+ {\globalpushmacro\MPdrawingdata
+ \globallet\MPdrawingdata\empty}
+
+\def\popMPdrawing
+ {\globalpopmacro\MPdrawingdata}
+
+\def\getMPdrawing
+ {\ifMPdrawingdone
+ \expandafter\processMPgraphic\expandafter{\MPdrawingdata}%
+ \fi}
+
+\def\startMPdrawing
+ {\dosingleempty\dostartMPdrawing}
+
+\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
+ {\relax
+ \bgroup
+ \enableincludeMPgraphics
+ \presetMPdefinitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
+ \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \egroup}
+
+\let\stopMPdrawing\relax
+
+\let\MPdrawingdata\empty
+
+\newif\ifMPdrawingdone \MPdrawingdonefalse
+\newif\ifMPshiftdrawing \MPshiftdrawingfalse
+
+\def\resetMPdrawing
+ {\globallet\MPdrawingdata\empty
+ \global\MPdrawingdonefalse}
+
+\def\pushMPdrawing
+ {\globalpushmacro\MPdrawingdata
+ \globallet\MPdrawingdata\empty}
+
+\def\popMPdrawing
+ {\globalpopmacro\MPdrawingdata}
+
+\def\getMPdrawing
+ {\ifMPdrawingdone
+ \expandafter\processMPgraphic\expandafter{\MPdrawingdata}%
+ \fi}
+
+\def\startMPdrawing
+ {\dosingleempty\dostartMPdrawing}
+
+\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
+ {\relax
+ \bgroup
+ \enableincludeMPgraphics
+ \presetMPdefinitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
+ \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \egroup}
+
+\let\stopMPdrawing\relax
+
+\long\def\startMPclip#1#2\stopMPclip
+ {\blabelgroup
+ \long\setgvalue{MPC:#1}{\ctxlua{metapost.getclippath(\!!bs#2\!!es)}}%
+ \elabelgroup}
+
+\let\stopMPclip\relax
+
+\def\grabMPclippath#1#2#3#4#5%
+ {\blabelgroup
+ \edef\width {#3\space}\let\overlaywidth \width
+ \edef\height{#4\space}\let\overlayheight\height
+ \doifundefined{MPC::#1}
+ {\doifdefinedelse{MPC:#1}
+ {\xdef\MPclippath{\getvalue{MPC:#1}}%
+ \ifx\MPclippath\empty\xdef\MPclippath{#5}\fi
+ \setxvalue{MPC::#1}{\MPclippath}}
+ {\setxvalue{MPC::#1}{#5}}}%
+ \xdef\MPclippath{\getvalue{MPC::#1}}%
+ % #2 : method is obsolete, only pdf now, we can always
+ % gsub the result to ps
+ \elabelgroup}
+
+%D Next we will use these support macros.
+
+\startMPextensions
+ if unknown context_tool: input mp-tool; fi;
+ if unknown context_spec: input mp-spec; fi;
+ if unknown context_grph: input mp-grph; fi;
+\stopMPextensions
+
+%D Since we want lables to follow the document settings, we
+%D also set the font related variables.
+
+\startMPinitializations % scale is not yet ok
+ defaultfont:="\truefontname{Regular}";
+ defaultscale:=\the\bodyfontsize/10pt;
+\stopMPinitializations
+
+\startMPinitializations % scale is not yet ok
+ defaultfont:="rm-lmtt10";
+\stopMPinitializations
+
+%D In order to support fancy text features (like outline
+%D fonts), we set:
+
+\startMPextensions
+ graphictextformat:="context";
+ graphictextdirective "\the\everyMPTEXgraphic";
+\stopMPextensions
+
+%D A signal that we're in combines \CONTEXT||\METAFUN mode:
+
+\startMPextensions
+ string contextversion;
+ contextversion:="\contextversion";
+\stopMPextensions
+
+%D Some safeguards:
+%D
+%D \starttyping
+%D \appendtoks \cleanupfeatures \to \everyMPgraphic
+%D \stoptyping
+%D
+%D No, we don't want that (else we loose UTF etc).
+
+%D Another one:
+
+\prependtoks \MPstaticgraphictrue \to \everyoverlay
+\prependtoks \MPstaticgraphictrue \to \everypagebody
+
+% %D We save the number of graphics for the sake of \TEXEXEC.
+%
+% \newcounter\totalnofMPgraphics
+%
+% \def\thenofMPgraphics{\the\nofMPgraphics} % from supp-mps
+%
+% \appendtoks
+% \savecurrentvalue\totalnofMPgraphics\thenofMPgraphics
+% \to \everybye
+
+%D \macros
+%D {setupMPvariables}
+%D
+%D When we build collections of \METAPOST\ graphics, like
+%D background and buttons, the need for passing settings
+%D arises. By (mis|)|using the local prefix that belongs to
+%D \type {\framed}, we get a rather natural interface to
+%D backgrounds. To prevent conflicts, we will use the \type
+%D {-} in \METAPOST\ specific variables, like:
+%D
+%D \starttyping
+%D \setupMPvariables[meta:button][size=20pt]
+%D \stoptyping
+
+\def\@@meta{meta:}
+
+\def\setupMPvariables
+ {\dodoubleempty\dosetupMPvariables}
+
+\def\dosetupMPvariables[#1][#2]%
+ {\ifsecondargument
+ \getrawparameters[#1:][#2]% brr, todo: [\@@meta#1:]
+ \else
+ \getrawparameters[\@@meta][#1]%
+ \fi}
+
+\let\@@framed\s!unknown
+
+\def\MPvariable#1%
+ {\csname
+ \ifcsname\@@framed\@@meta#1\endcsname\@@framed\fi\@@meta#1%
+ \endcsname}
+
+\let\MPvar\MPvariable
+
+\let\setMPvariables\setupMPvariables
+
+\def\MPrawvar#1#2{\csname#1:#2\endcsname}
+
+%D \macros
+%D {startuniqueMPgraphic, uniqueMPgraphic}
+%D
+%D This macros is probably of most use to myself, since I like
+%D to use graphics that adapt themselves. The next \METAPOST\
+%D kind of graphic is both unique and reused when possible.
+%D
+%D \starttyping
+%D \defineoverlay[example][\uniqueMPgraphic{test}]
+%D
+%D \startuniqueMPgraphic {test}
+%D draw unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D \stopuniqueMPgraphic
+%D \stoptyping
+
+\def\overlaystamp % watch the \MPcolor, since colors can be redefined
+ {\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+%D A better approach is to let additional variables play a role
+%D in determining the uniqueness. In the next macro, the
+%D second, optional, argument is used to guarantee the
+%D uniqueness, as well as prepare variables for passing them to
+%D \METAPOST.
+%D
+%D \starttyping
+%D \startuniqueMPgraphic{meta:hash}{gap,angle,...}
+%D \stoptyping
+%D
+%D The calling macro also accepts a second argument. For
+%D convenient use in overlay definitions, we use \type {{}}
+%D instead of \type {[]}.
+%D
+%D \starttyping
+%D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30}
+%D \stoptyping
+
+\newcount\MPobjectcounter
+\newif \ifMPshiftdrawing \MPshiftdrawingfalse
+\newbox \MPgraphicbox
+
+\def\placeMPgraphic
+ {\ifMPshiftdrawing
+ \edef\next
+ {\wd\MPgraphicbox\the\wd\MPgraphicbox
+ \ht\MPgraphicbox\the\ht\MPgraphicbox
+ \dp\MPgraphicbox\the\dp\MPgraphicbox}%
+ \setbox\MPgraphicbox\hbox
+ {\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}%
+ \next
+ \fi
+ \box\MPgraphicbox}
+
+\def\reuseMPbox#1#2#3#4#5% space delimiting would save some tokens
+ {\xdef\MPllx{#2}% but it's not worth the effort and looks
+ \xdef\MPlly{#3}% ugly as well
+ \xdef\MPurx{#4}%
+ \xdef\MPury{#5}%
+ \getobject{MP}{#1}}
+
+\long\def\handleuniqueMPgraphic#1#2#3%
+ {\blabelgroup
+ \def\@@meta{#1:}%
+ \extendMPoverlaystamp{#2}% incl prepare
+ \ifundefined{\@@MPG\overlaystamp:#1}%
+ \enableincludeMPgraphics
+ \forgetall
+ \global\advance\MPobjectcounter\plusone
+ \setobject{MP}{\number\MPobjectcounter}\vbox{\processMPgraphic{#3}}%
+ \setxvalue{\@@MPG\overlaystamp:#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
+ \fi
+ \getvalue{\@@MPG\overlaystamp:#1}%
+ \elabelgroup}
+
+\long\def\startuniqueMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuniqueMPgraphic}
+
+\long\def\dostartuniqueMPgraphic#1#2#3\stopuniqueMPgraphic%
+ {\long\setgvalue{\@@MPG#1}{\handleuniqueMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\unexpanded\def\uniqueMPgraphic
+ {\dodoublegroupempty\douniqueMPgraphic}
+
+\def\douniqueMPgraphic#1#2%
+ {\blabelgroup
+ \setupMPvariables[#1][#2]%
+ \getvalue{\@@MPG#1}\empty
+ \elabelgroup}
+
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\long\def\handleuseMPgraphic#1#2#3%
+ {\blabelgroup
+ \forgetall % check this
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics
+ \processMPgraphic{#3}%
+ \elabelgroup}
+
+\long\def\startuseMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuseMPgraphic}
+
+\long\def\dostartuseMPgraphic#1#2#3\stopuseMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\long\def\startusableMPgraphic % redundant but handy
+ {\blabelgroup
+ \dodoublegroupempty\dostartusableMPgraphic}
+
+\long\def\dostartusableMPgraphic#1#2#3\stopusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\let\stopuseMPgraphic \relax % so that we can use it in \expanded
+\let\stopusableMPgraphic \relax % so that we can use it in \expanded
+
+\long\def\handlereusableMPgraphic#1#2#3%
+ {\blabelgroup
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics
+ \global\advance\MPobjectcounter\plusone
+ \setobject{MP}{\number\MPobjectcounter}\vbox{\processMPgraphic{#3}}%
+ \setxvalue{\@@MPG#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
+ \getvalue{\@@MPG#1}%
+ \elabelgroup}
+
+\long\def\startreusableMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartreusableMPgraphic}
+
+\long\def\dostartreusableMPgraphic#1#2#3\stopreusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\let\stopreusableMPgraphic \relax % so that we can use it in \expanded
+
+\unexpanded\def\useMPgraphic
+ {\dodoublegroupempty\douseMPgraphic}
+
+\def\douseMPgraphic#1#2%
+ {\blabelgroup
+ \doifsomething{#2}{\setupMPvariables[#1][#2]}%
+ \getvalue{\@@MPG#1}\empty
+ \elabelgroup}
+
+\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
+\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed
+
+\let\stopuseMPcode \relax % so that we can use it in \expanded
+\let\stopusableMPcode \relax % so that we can use it in \expanded
+\let\stopreusableMPcode \relax % so that we can use it in \expanded
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\def\enableincludeMPgraphics
+ {\let\handleuseMPgraphic \thirdofthreearguments
+ \let\handlereusableMPgraphic\thirdofthreearguments}
+
+%D \macros
+%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
+%D
+%D Experimental.
+
+\def\MPpageprefix{\doifoddpageelse oe:}
+
+\def\overlaypagestamp
+ {\MPpageprefix\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+\long\def\startuniqueMPpagegraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuniqueMPpagegraphic}
+
+\long\def\dostartuniqueMPpagegraphic#1#2#3\stopuniqueMPpagegraphic
+ {\long\setgvalue{\@@MPG o:#1}{\handleuniqueMPgraphic{o:#1}{#2}{#3}}%
+ \long\setgvalue{\@@MPG e:#1}{\handleuniqueMPgraphic{e:#1}{#2}{#3}}%
+ \elabelgroup}
+
+\unexpanded\def\uniqueMPpagegraphic
+ {\dodoublegroupempty\douniqueMPpagegraphic}
+
+\def\douniqueMPpagegraphic#1#2%
+ {\blabelgroup
+ \let\overlaystamp\overlaypagestamp
+ \setupMPvariables[\MPpageprefix#1][#2]% prefix is new here
+ \getvalue{\@@MPG\MPpageprefix#1}{}%
+ \elabelgroup}
+
+%D One way of defining a stamp is:
+%D
+%D \starttyping
+%D \def\extendMPoverlaystamp#1%
+%D {\def\docommand##1%
+%D {\edef\overlaystamp{\overlaystamp:\MPvariable{##1}}}%
+%D \processcommalist[#1]\docommand}
+%D \stoptyping
+
+%D Since we need to feed \METAPOST\ with expanded dimensions,
+%D we introduce a dedicated expansion engine.
+
+\def\prepareMPvariable#1%
+ {\ifundefined{\@@framed\@@meta#1}%
+ \doprepareMPvariable{\@@meta#1}%
+ \else
+ \doprepareMPvariable{\@@framed\@@meta#1}%
+ \fi}
+
+% \startlines
+% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
+% \stoplines
+
+\def\doprepareMPvariable#1%
+ {\edef\theMPvariable{\getvalue{#1}}%
+ \doifelsenothing\theMPvariable
+ {\setevalue{#1}{\MPcolor{black}}}
+ {\defconvertedcommand\ascii\theMPvariable % otherwise problems
+ \doifcolorelse \ascii % with 2\bodyfontsize
+ {\setevalue{#1}{\MPcolor\theMPvariable}}
+ {% can be aux macro
+ \setbox\scratchbox\hbox{\scratchdimen\theMPvariable sp}%
+ \ifdim\wd\scratchbox=\zeropoint
+ % \scratchcounter\theMPvariable
+ % \setevalue{#1}{\the\scratchcounter}%
+ % also accepts 0.number :
+ \setevalue{#1}{\number\theMPvariable}%
+ \else
+ \scratchdimen\theMPvariable
+ \setevalue{#1}{\the\scratchdimen}%
+ \fi}}}
+
+%D We redefine \type {\extendMPoverlaystamp} to preprocess
+%D variables using \type {\prepareMPvariable}.
+
+\def\doextendMPoverlaystamp#1%
+ {\prepareMPvariable{#1}%
+ \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
+
+\def\extendMPoverlaystamp#1%
+ {\processcommalist[#1]\doextendMPoverlaystamp}
+
+\def\prepareMPvariables#1%
+ {\processcommalist[#1]\prepareMPvariable}
+
+%D \macros
+%D {MPdatafile}
+%D
+%D We redefine a macro from \type {supp-mps.tex}:
+
+\def\MPdataMPDfile{\jobname-mp.mpd}
+\def\MPdataMPOfile{\jobname-mp.mpo}
+\def\MPdataMPYfile{\jobname-mp.mpy}
+
+\startMPextensions
+ boolean collapse_data; collapse_data:=true;
+ def data_mpd_file = "\MPdataMPDfile" enddef ;
+ def data_mpo_file = "\MPdataMPOfile" enddef ;
+ def data_mpy_file = "\MPdataMPYfile" enddef ;
+\stopMPextensions
+
+\newcount\currentMPgraphic \currentMPgraphic\zerocount
+
+\def\getMPdata
+ {%\let\MPdata\secondoftwoarguments
+ \long\def\MPdata##1##2{\ifnum##1=\currentMPgraphic\relax##2\fi}%
+ \startreadingfile
+ \startnointerference
+ \readlocfile\MPdataMPDfile\donothing\donothing
+ \stopnointerference
+ \stopreadingfile}
+
+%D \macros
+%D {MPrunfile}
+%D
+%D This one is more abstract and does not assume knowledge
+%D of buffer prefixes.
+
+\def\MPrunfile#1%
+ {\bufferprefix mprun.#1}
+
+%D For the moment, the next one is a private macro:
+
+% TODO ! ! ! ! ! !
+
+\def\processMPbuffer
+ {\dosingleempty\doprocessMPbuffer}
+
+\def\doprocessMPbuffer[#1]%
+ {\doifelsenothing{#1}
+ {\doprocessMPbuffer[\jobname]}
+ {\processMPgraphic{\ctxlua{tex.sprint(tex.ctxcatcodes,buffers.collect(string.split("#1",",")))}}}}
+
+\def\runMPbuffer
+ {\dosingleempty\dorunMPbuffer}
+
+\def\dorunMPbuffer[#1]% processing only
+ {\startnointerference\doprocessMPbuffer[#1]\stopnointerference}
+
+%D \macros
+%D {startMPenvironment, resetMPenvironment}
+%D
+%D In order to synchronize the main \TEX\ run and the runs
+%D local to \METAPOST, environments can be passed.
+
+\ifx\everyMPTEXgraphic\undefined
+ \newtoks\everyMPTEXgraphic
+\fi
+
+%D A more general way of passing environments is:
+
+\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
+ {\bgroup
+ \catcode`\^^M=\@@space
+ \dodoubleempty\dostartMPenvironment}
+
+\long\def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
+ {\egroup
+ \doif{#1}\s!reset\resetMPenvironment % reset mp toks
+ \doif{#1}\v!global{#3}% % use in main doc too
+ \doif{#1}+{#3}% % use in main doc too
+ \defconvertedargument\ascii{#3}%
+ \expandafter\appendtoks\ascii\to\everyMPTEXgraphic}
+
+\def\resetMPenvironment
+ {\everyMPTEXgraphic\emptytoks % = is really needed !
+ \startMPenvironment
+ \global\loadfontfileoncetrue
+ \stopMPenvironment}
+
+\resetMPenvironment
+
+\def\useMPenvironmentbuffer[#1]%
+ {\expanded{\startMPenvironment\noexpand\readfile{\TEXbufferfile{\jobname}}{}{}}\stopMPenvironment}
+
+\useMPenvironmentbuffer[mp]
+
+%D This command takes \type {[reset]} as optional
+%D argument.
+%D
+%D \starttyping
+%D \startMPenvironment
+%D \setupbodyfont[pos,14.4pt]
+%D \stopMPenvironment
+%D
+%D \startMPcode
+%D draw btex \sl Hans Hagen etex scaled 5 ;
+%D \stopMPcode
+%D \stoptyping
+%D
+%D The most simple case:
+
+\long\def\startMPcode#1\stopMPcode
+ {\processMPgraphic{#1}}
+
+\let\stopMPcode\relax
+
+%D The \type {\resetMPenvironment} is a quick way to erase
+%D the token list.
+%D
+%D You should be aware of independencies. For instance, if you use a font
+%D in a graphic that is not used in the main document, you need to load the
+%D typescript at the outer level (either directly or by using the global
+%D option).
+%D
+%D \starttyping
+%D \usetypescript[palatino][texnansi]
+%D
+%D \startMPenvironment
+%D \usetypescript[palatino][texnansi]
+%D \enableregime[utf]
+%D \setupbodyfont[palatino]
+%D \stopMPenvironment
+%D
+%D \startMPpage
+%D draw btex aap‒noot coördinatie – één etex ;
+%D \stopMPpage
+%D \stoptyping
+
+%D Loading specific \METAPOST\ related definitions is
+%D accomplished by:
+
+\def\douseMPlibrary#1%
+ {\ifundefined{\c!file\f!metapostprefix#1}%
+ \letvalueempty{\c!file\f!metapostprefix#1}%
+ \makeshortfilename[\truefilename{\f!metapostprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename{\showmessage\m!metapost1{#1}}\donothing
+ \stopreadingfile
+ \fi}
+
+\def\useMPlibrary[#1]%
+ {\processcommalist[#1]\douseMPlibrary}
+
+%D \macros
+%D {setMPtext, MPtext, MPstring, MPbetex}
+%D
+%D To be documented:
+%D
+%D \starttyping
+%D \setMPtext{identifier}{text}
+%D
+%D \MPtext {identifier}
+%D \MPstring{identifier}
+%D \MPbetex {identifier}
+%D \stoptyping
+
+\def\@@MPT{@MPT@}
+
+\def\forceMPTEXgraphic
+ {\long\def\checkMPTEXgraphic##1{\global\MPTEXgraphictrue}}
+
+\def\setMPtext#1#2% todo : #1 must be made : safe
+ {%\forceMPTEXgraphic
+ \defconvertedargument\ascii{#2}%
+ \dodoglobal\letvalue{\@@MPT#1}\ascii}
+
+\def\MPtext #1{\executeifdefined{\@@MPT#1}\empty}
+\def\MPstring #1{"\executeifdefined{\@@MPT#1}\empty"}
+\def\MPbetex #1{btex \executeifdefined{\@@MPT#1}\empty\space etex}
+
+%D Unfortunately \METAPOST\ does not have \CMYK\ support
+%D built in, but by means of specials we can supply the
+%D information needed to handle them naturaly.
+
+\newif\ifMPcmykcolors \MPcmykcolorstrue
+\newif\ifMPspotcolors \MPspotcolorstrue
+
+\startMPinitializations
+ cmykcolors:=\ifMPcmykcolors true\else false\fi;
+ spotcolors:=\ifMPspotcolors true\else false\fi;
+\stopMPinitializations
+
+%D In order to communicate conveniently with the \TEX\
+%D engine, we introduce some typesetting variables.
+
+\startMPextensions
+ color OverlayColor,OverlayLineColor;
+\stopMPextensions
+
+\startMPinitializations
+ OverlayWidth:=\overlaywidth;
+ OverlayHeight:=\overlayheight;
+ OverlayDepth:=\overlayheight;
+ OverlayColor:=\MPcolor{\overlaycolor};
+ OverlayLineWidth:=\overlaylinewidth;
+ OverlayLineColor:=\MPcolor{\overlaylinecolor};
+ %
+ BaseLineSkip:=\the\baselineskip;
+ LineHeight:=\the\baselineskip;
+ BodyFontSize:=\the\bodyfontsize;
+ %
+ TopSkip:=\the\topskip;
+ StrutHeight:=\strutheight;
+ StrutDepth:=\strutdepth;
+ %
+ CurrentWidth:=\the\hsize;
+ CurrentHeight:=\the\vsize;
+ %
+ EmWidth:=\the\emwidth;
+ ExHeight:=\the\exheight;
+ %
+ PageNumber:=\the\pageno;
+ RealPageNumber:=\the\realpageno;
+ LastPageNumber:= \lastpage;
+\stopMPinitializations
+
+\appendtoks
+ \disablediscretionaries
+ \disablecompoundcharacters
+\to \everyMPgraphic
+
+\appendtoks
+ \expanded{\definecolor[currentcolor][\currentcolorname]}%
+\to \everyMPgraphic
+
+\appendtoks
+ \baselineskip1\baselineskip
+ \lineheight 1\lineheight
+ \topskip 1\topskip
+\to \everyMPgraphic
+
+\appendtoks
+ \let \# \letterhash
+ \let \_ \letterunderscore
+ \let \& \letterampersand
+ \let \{ \letteropenbrace
+ \let \} \letterclosebrace
+\to \everyMPgraphic
+
+%D Alas, the prologue settings differ per driver.
+
+\ifx\undefined\MPprologues \def\MPprologues{0} \fi
+
+\startMPinitializations
+ prologues:=\MPprologues;
+ mpprocset:=1;
+\stopMPinitializations
+
+\appendtoks
+ \def\MPprologues{0}%
+ \def\MPOSTdriver{dvips}%
+\to \everyresetspecials
+
+%D \macros
+%D {PDFMPformoffset}
+%D
+%D In \PDF, forms are clipped and therefore we have to take
+%D precautions to get this right. Since this is related to
+%D objects, we use the same offset as used there.
+
+\def\PDFMPformoffset{\objectoffset}
+
+%D \macros
+%D {insertMPfile}
+%D
+%D Bypassing the special driver and figure mechanism is not
+%D that nice but saves upto 5\% time in embedding \METAPOST\
+%D graphics by using the low level \PDF\ converter directly,
+%D given of course that we use \PDFTEX. As a result we need to
+%D fool around with the object trigger.
+
+\newtoks\everyinsertMPfile
+
+\let\insertMPfileARG\insertMPfile
+
+\def\insertMPfile#1#2% in context #2 is empty
+ {\doifelsenothing{#2}{\doinsertMPfile{#1}}{\insertMPfileARG{#1}{#2}}}
+
+\def\includeMPasEPS#1% untested !!
+ {\bgroup
+ \message{[MP as EPS #1]}%
+ \the\everyinsertMPfile
+ \dogetEPSboundingbox{#1}\!!widtha\!!heighta\!!widthb\!!heightb
+ \setbox\scratchbox\vbox to \!!heightb
+ {\vfill
+ \let \@@DriverImageType \c!mps
+ \def \@@DriverImageFile {#1}%
+ \edef\@@DriverImageWidth {\the\!!widthb }%
+ \edef\@@DriverImageHeight{\the\!!heightb}%
+ \doinsertfile}%
+ \wd\scratchbox\!!widthb
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \egroup}
+
+\def\includeMPasPDF#1%
+ {\bgroup
+ \the\everyinsertMPfile
+ \ifinobject \else \chardef\makeMPintoPDFobject\plustwo \fi % when needed
+ \convertMPtoPDF{#1}{1}{1}% no \plusone !
+ \egroup}
+
+%D So, using a low level approach (thereby avoiding the slower
+%D figure analysis macros) pays off. This kind of
+%D optimizations are a bit tricky since we must make sure that
+%D special resources end up in the (PDF) files. Because the
+%D \METAPOST\ to \PDF\ can handle objects itself, it is not
+%D that complicated.
+
+%D We hook a couple of initializations into the graphic
+%D macros.
+
+\appendtoks
+ \let\figuretypes\c!mps
+ \runutilityfilefalse
+ \consultutilityfilefalse
+\to \everyinsertMPfile
+
+%D One more: (still needed?)
+
+\startMPextensions
+ def initialize_form_numbers =
+ do_initialize_numbers;
+ enddef;
+\stopMPextensions
+
+\startMPinitializations
+ HSize:=\the\hsize ;
+ VSize:=\the\vsize ;
+\stopMPinitializations
+
+\startMPextensions
+ vardef ForegroundBox =
+ unitsquare xysized(HSize,VSize)
+ enddef ;
+ vardef PageFraction =
+ if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi
+ enddef ;
+\stopMPextensions
+
+%D And some more. These are not really needed since we
+%D don't use the normal figure inclusion macros any longer.
+
+\appendtoks
+ \externalfigurepostprocessors\emptytoks % safeguard
+\to \everyinsertMPfile
+
+%D We also take care of disabling fancy figure features, that
+%D can terribly interfere when dealing with symbols,
+%D background graphics and running (postponed) graphics.
+%D You won't believe me if I tell you what funny side effects
+%D can occur. One took me over a day to uncover when
+%D processing the screen version of the \METAFUN\ manual.
+
+%D For my eyes only:
+
+\def\doifelseMPgraphic#1{\doifdefinedelse{\@@MPG#1}}
+
+%D \macros
+%D {startMPcolor}
+%D
+%D The following time consuming method uses \METAPOST\ to
+%D calculate a color. This enables a match between colors
+%D resulting from a complex calculation (e.g. for a title
+%D page) and those in the text.
+
+% \startuseMPgraphic{somecolors}
+% color c[] ; c[1] := .7[red,green] ; c[2] := .7[blue,yellow] ;
+% \stopuseMPgraphic
+
+% \startMPcolor[shade-1][t=.2,a=1]
+% \includeMPgraphic{somecolors} ; fill fullcircle withcolor c[1] ;
+% \stopMPcolor
+
+% \startMPcolor[shade-2][t=.2,a=1]
+% \includeMPgraphic{somecolors} ; fill fullcircle withcolor c[2] ;
+% \stopMPcolor
+
+% \blackrule[width=\hsize,height=4cm,color=shade-1]
+% \blackrule[width=\hsize,height=4cm,color=shade-2]
+
+\def\startMPcolor
+ {\dodoubleempty\dostartMPcolor}
+
+\long\def\dostartMPcolor[#1][#2]#3\stopMPcolor % slow but sometimes handy
+ {\startnointerference
+ \def\handleMPgraycolor{\expanded{\defineglobalcolor[#1][s=\!MPgMPa1,#2]}}%
+ \def\handleMPrgbcolor {\expanded{\defineglobalcolor[#1][r=\!MPgMPa1,g=\!MPgMPa2,b=\!MPgMPa3,#2]}}%
+ \def\handleMPcmykcolor{\expanded{\defineglobalcolor[#1][c=\!MPgMPa1,m=\!MPgMPa2,y=\!MPgMPa3,k=\!MPgMPa4,#2]}}%
+ \processMPgraphic{#3}%
+ \stopnointerference}
+
+%D New:
+
+\definelayerpreset % no dx,dy - else nasty non-mp placement
+ [mp]
+ [\c!y=-\MPury bp,
+ \c!x=\MPllx bp,
+ \c!method=\v!fit]
+
+\definelayer
+ [mp]
+ [\c!preset=mp]
+
+%D Usage:
+%D
+%D \starttyping
+%D \defineproperty[one][layer][state=start]
+%D \defineproperty[two][layer][state=stop]
+%D
+%D \startuseMPgraphic{step-1}
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopuseMPgraphic
+%D
+%D \startuseMPgraphic{step-2}
+%D fill fullcircle scaled 5cm withcolor green ;
+%D \stopuseMPgraphic
+%D
+%D \setlayer[mp]{\property[one]{\useMPgraphic{step-1}}}
+%D \setlayer[mp]{\property[two]{\useMPgraphic{step-2}}}
+%D
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+%D
+%D Reusing graphics is also possible (now):
+%D
+%D \starttyping
+%D \startreusableMPgraphic{axis}
+%D tickstep := 1cm ; ticklength := 2mm ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D tickstep := tickstep/2 ; ticklength := ticklength/2 ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D \stopreusableMPgraphic
+%D
+%D \startuseMPgraphic{demo}
+%D drawpoint "1cm,1.5cm" ;
+%D \stopuseMPgraphic
+%D
+%D \definelayer[mp][preset=mp]
+%D \setlayer[mp]{\reuseMPgraphic{axis}}
+%D \setlayer[mp]{\useMPgraphic{demo}}
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+
+%D \macros
+%D {startstaticMPfigure,useMPstaticfigure}
+%D
+%D Static figures are processed only when there has been
+%D something changed. Here is Aditya Mahajan's testcase:
+%D
+%D \startbuffer
+%D \startstaticMPfigure{circle}
+%D fill fullcircle scaled 1cm withcolor blue;
+%D \stopstaticMPfigure
+%D
+%D \startstaticMPfigure{axis}
+%D drawarrow (0,0)--(2cm,0) ;
+%D drawarrow (0,0)--(0,2cm) ;
+%D label.llft(textext("(0,0)") ,origin) ;
+%D \stopstaticMPfigure
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\usestaticMPfigure
+ {\dodoubleempty\dousestaticMPfigure}
+
+\def\dousestaticMPfigure[#1][#2]%
+ {\ifsecondargument
+ \scale[#2]{\reuseMPgraphic{#1@S@}}%
+ \else
+ \reuseMPgraphic{#1@S@}%
+ \fi}
+
+\def\startstaticMPfigure#1#2\stopstaticMPfigure
+ {\startreusableMPgraphic{static:#1}#2\stopreusableMPgraphic}
+
+\long\def\startstaticMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartstaticMPgraphic}
+
+\long\def\dostartstaticMPgraphic#1#2#3\stopstaticMPgraphic
+ {\long\setgvalue{\@@MPG#1@S@}{\handlereusableMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+%D New:
+
+\newconditional\manyMPspecials % when set to true, > 1000 specials can be used
+
+\settrue \manyMPspecials % per 1/4/2006
+
+\prependtoks
+ _special_div_ := 1000\ifconditional\manyMPspecials0\fi ;
+\to \MPextensions
+
+%D Needed (will become default):
+
+\prependtoks
+ \resetlanguagespecifics
+\to \everyMPgraphic
+
+%D Needed too.
+
+\let\initializeMPgraphics\relax
+
+% Done.
+
+\protect \endinput
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
index 64c886950..648ff1afb 100644
--- a/tex/context/base/meta-pdf.lua
+++ b/tex/context/base/meta-pdf.lua
@@ -609,9 +609,9 @@ do
function mptopdf.parsers.lpeg()
if mptopdf.data:find("%%%%BeginResource: procset mpost") then
- lpeg.match(captures_new,mptopdf.data)
+ captures_new:match(mptopdf.data)
else
- lpeg.match(captures_old,mptopdf.data)
+ captures_old:match(mptopdf.data)
end
end
diff --git a/tex/context/base/meta-tex.tex b/tex/context/base/meta-tex.mkii
index 720de6fb3..720de6fb3 100644
--- a/tex/context/base/meta-tex.tex
+++ b/tex/context/base/meta-tex.mkii
diff --git a/tex/context/base/meta-tex.mkiv b/tex/context/base/meta-tex.mkiv
new file mode 100644
index 000000000..6afc7efc5
--- /dev/null
+++ b/tex/context/base/meta-tex.mkiv
@@ -0,0 +1,35 @@
+%D \module
+%D [ file=meta-tex,
+%D version=2006.06.07,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=\METAPOST\ fast text insertion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+\long\def\startTeXtexts#1\stopTeXtexts{[do we need TeXtexts in MkIV]}
+\long\def\doTeXtext[#1]#2{[do we need TeXtexts in MkIV]}
+\long\def\TeXtext{\dosingleempty\doTeXtext}
+
+\def\definetextext[#1]#2{\setvalue{textext@@#1}{#2}}
+
+% \definetextext[framed]{\framed}
+%
+% \startMPcode
+% draw \sometxt[framed]{black} rotated 45 ;
+% \stopMPcode
+
+\def\definetextext[#1]#2{\setvalue{@@st@@[#1]}{#2}}
+
+\long\def\sometxt#1#{\dosometxt{#1}} % grab optional [args]
+
+\long\def\dosometxt#1#2%
+ {textext("\ifcsname @@st@@#1\endcsname\csname @@st@@#1\endcsname{#2}\else#2\fi")}
+
+\protect \endinput
diff --git a/tex/context/base/meta-txt.tex b/tex/context/base/meta-txt.tex
index de4239e85..564a40752 100644
--- a/tex/context/base/meta-txt.tex
+++ b/tex/context/base/meta-txt.tex
@@ -24,6 +24,9 @@
% textext ipv btex ... etex
+\ifx\undefined\MPtoks \newtoks\MPtoks \fi
+\ifx\undefined\MPnox \newbox \MPbox \fi
+
\unprotect
\startMPextensions
@@ -46,16 +49,16 @@
\def\startshapetext[#1]%
{\global\newcounter\currentshapetext
- \global\setbox\shapetextbox=\vbox\bgroup
+ \global\setbox\shapetextbox\vbox\bgroup
\expanded{\switchtobodyfont[\@@shbodyfont]}%
\dontcomplain
\hsize\parwidth
\setuptolerance[\v!verytolerant,\v!stretch]%
- \!!counta=0
- \!!toksa=\emptytoks
+ \!!counta\zerocount
+ \!!toksa\emptytoks
\def\docommand##1%
- {\setbox\scratchbox=\hbox{\useMPgraphic{##1}}%
- \global\chardef\parfirst=0
+ {\setbox\scratchbox\hbox{\useMPgraphic{##1}}%
+ \global\chardef\parfirst\zerocount
\getMPdata % \readlocfile{\MPdatafile}{}{}%
\setshapecharacteristics
\advance\!!counta by \parlines
@@ -71,7 +74,7 @@
\ifparseries\def\par{\endgraf\adaptparshape}\fi
\EveryPar{\begstrut}}
-\def\stopshapetext%
+\def\stopshapetext
{\endstrut
%\removebottomthings
\egroup
@@ -104,8 +107,8 @@
\global\parhoffset \getvalue{parhoffset:\currentshapetext}%
\global\parwidth \getvalue{parwidth:\currentshapetext}%
\global\parheight \getvalue{parheight:\currentshapetext}}
- {\global\parlines 1
- \global\chardef\parfirst 0
+ {\global\parlines \plusone
+ \global\chardef\parfirst \zerocount
\global\parvoffset \zeropoint
\global\parhoffset \zeropoint
\global\parwidth \hsize
@@ -172,7 +175,7 @@
\MPtoks\emptytoks
\resetMPdrawing
\startMPdrawing
- \includeMPgraphic{followtokens}
+ \includeMPgraphic{followtokens} ;
picture pic[] ; numeric len[], n ; n := 0 ;
\stopMPdrawing
\handletokens#1\with\processfollowingtoken
@@ -268,10 +271,10 @@
[medium]
\startuniqueMPgraphic{EnglishRule}{height,width,color}
- height = \MPvar{height} ;
- x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ;
- y1 = y3 = 0 ; y2 = -y4 = height/2 ;
- fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ;
+ height = \MPvar{height} ;
+ x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ;
+ y1 = y3 = 0 ; y2 = -y4 = height/2 ;
+ fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ;
\stopuniqueMPgraphic
\def\EnglishRule%
diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua
new file mode 100644
index 000000000..6ada8ad19
--- /dev/null
+++ b/tex/context/base/mlib-ctx.lua
@@ -0,0 +1,39 @@
+if not modules then modules = { } end modules ['mlib-ctx'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- todo
+
+local format, join = string.format, table.concat
+local sprint = tex.sprint
+
+metapost = metapost or {}
+metapost.defaultformat = "metafun"
+
+function metapost.graphic(mpsformat,str,preamble)
+ local mpx = metapost.format(mpsformat or metapost.defaultformat)
+ metapost.graphic_base_pass(mpx,str,preamble)
+end
+
+function metapost.filterclippath(result)
+ if result then
+ local figures = result.fig
+ if figures and #figures > 0 then
+ local figure = figures[1]
+ local objects = figure:objects()
+ if objects then
+ for o=1,#objects do
+ local object = objects[o]
+ if object.type == "start_clip" then
+ return join(flushnormalpath(object.path,{ }),"\n")
+ end
+ end
+ end
+ end
+ end
+ return ""
+end
diff --git a/tex/context/base/mlib-ctx.tex b/tex/context/base/mlib-ctx.tex
new file mode 100644
index 000000000..6f56b7e68
--- /dev/null
+++ b/tex/context/base/mlib-ctx.tex
@@ -0,0 +1,81 @@
+%D \module
+%D [ file=mlib-ctx,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 file contains the \MPLIB\ variants of the by now ancient
+%D \MPTOPDF\ code.
+
+\writestatus{loading}{MetaPost Library Graphics / Initializations}
+
+\registerctxluafile{mlib-run}{1.001}
+\registerctxluafile{mlib-ctx}{1.001}
+
+\unprotect
+
+\protect \endinput
+
+% local mpgraphic = [[
+% for i=1 upto 1000 :
+% beginfig(0);
+% draw halfcircle scaled 1cm withcolor green ;
+% picture p ; p := "oeps" infont defaultfont scaled .75 rotated 45 ;
+% p := p shifted - (xpart center p,0) ;
+% draw p ; draw boundingbox p ;
+% endfig ;
+% beginfig(0);
+% draw halfcircle scaled 1cm dashed evenly withcolor green ;
+% endfig ;
+% beginfig(0);
+% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
+% draw halfcircle scaled 1cm withcolor red ;
+% endfig ;
+% beginfig(0);
+% draw halfcircle scaled 1cm ;
+% endfig ;
+% beginfig(0);
+% pickup pencircle xscaled .5mm yscaled .25mm rotated 45 ;
+% for k:=1 upto 10 :
+% draw halfcircle scaled uniformdeviate(1cm) withcolor (red/(k/4)) ;
+% endfor ;
+% endfig ;
+% endfor ;
+% ]]
+% -- local mpx = metapost.format("metafun")
+% metapost.process(metapost.format("metafun"),mpgraphic)
+
+% \starttext
+% \setupcolors[state=start]
+% \definecolor[red] [r=1]
+% \definecolor[cyan][c=1]
+% \setbox\scratchbox\hbox{\startMPcode\stopMPcode} % first specials are forgotten
+% \definecolor[sss][t=.5,a=1,r=1]
+% \definespotcolor[oeps1][green][p=.5]
+% \definespotcolor[oeps2][green][p=.25]
+% \definespotcolor[oeps3][green][p=.25,t=.5,a=1]
+% \startMPpage
+% fill fullcircle scaled 10cm withcolor \MPcolor{red} ;
+% fill fullcircle scaled 8cm withcolor cmyk(1,0,0,0) ;
+% fill fullcircle scaled 6cm withcolor cmyk(0,1,0,0) ;
+% fill fullcircle scaled 4cm withcolor cmyk(0,0,1,0) ;
+% fill fullcircle scaled 2cm withcolor cmyk(0,0,0,1) ;
+% currentpicture := currentpicture shifted (-7.5cm,0) ;
+% fill fullcircle scaled 10cm withcolor transparent(1,0.75,cmyk(0,0,1,0)) ;
+% fill fullcircle scaled 8cm withcolor \MPcolor{sss} ;
+% fill fullcircle scaled 6cm withcolor \MPcolor{oeps1} ;
+% fill fullcircle scaled 4cm withcolor \MPcolor{oeps2} ;
+% currentpicture := currentpicture shifted (-7.5cm,0) ;
+% fill fullcircle scaled 10cm withcolor \MPcolor{oeps3} ;
+% circular_shade(fullcircle scaled 8cm, 1, red, blue) ;
+% circular_shade(fullcircle scaled 6cm, 1, (1,0,0,0), (0,1,0,0)) ;
+% circular_shade(fullcircle scaled 4cm, 1, cmyk(.5,.5,1,0), (0,1,0,0)) ;
+% \stopMPpage
+% \stoptext
diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua
new file mode 100644
index 000000000..8b4cbdb19
--- /dev/null
+++ b/tex/context/base/mlib-pdf.lua
@@ -0,0 +1,469 @@
+if not modules then modules = { } end modules ['mlib-pdf'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local format, join = string.format, table.concat
+local sprint = tex.sprint
+local abs, sqrt, round = math.abs, math.sqrt, math.round
+
+metapost = metapost or { }
+
+function metapost.convert(result, trialrun)
+ if trialrun then
+ metapost.parse(result)
+ else
+ metapost.flush(result)
+ end
+end
+
+metapost.n = 0
+
+function metapost.comment(message)
+ if message then
+ sprint(tex.ctxcatcodes,format("\\MPLIBtoPDF{\\letterpercent\\space mps graphic %s: %s}", metapost.n, message))
+ end
+end
+
+function metapost.startfigure(llx,lly,urx,ury,message)
+ metapost.n = metapost.n + 1
+ sprint(tex.ctxcatcodes,format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
+ if message then metapost.comment(message) end
+end
+
+function metapost.stopfigure(message)
+ if message then metapost.comment(message) end
+ sprint(tex.ctxcatcodes,"\\stopMPLIBtoPDF")
+end
+
+function metapost.flushfigure(pdfliterals) -- table
+ if #pdfliterals > 0 then
+ sprint(tex.ctxcatcodes,"\\MPLIBtoPDF{",join(pdfliterals,"\n"),"}")
+ end
+end
+
+function metapost.textfigure(font,size,text,width,height,depth)
+ text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib)
+ sprint(tex.ctxcatcodes,format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-number.dimenfactors.bp*depth))
+end
+
+-- the pen calculations are taken from metapost, first converted by
+-- taco from c to lua, and then optimized by hans, so all errors are his
+
+local function pyth(a,b)
+ return sqrt(a*a + b*b) -- much faster than sqrt(a^2 + b^2)
+end
+
+local aspect_bound = 10/65536
+local aspect_default = 1/65536
+local bend_tolerance = 131/65536
+local eps = 0.0001
+
+local function coord_range_x(h, dz) -- direction x
+ local zlo, zhi = 0, 0
+ for i=1, #h do
+ local p = h[i]
+ local z = p.x_coord
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ z = p.right_x
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ z = p.left_x
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ end
+ return (zhi - zlo <= dz and aspect_bound) or aspect_default
+end
+
+local function coord_range_y(h, dz) -- direction y
+ local zlo, zhi = 0, 0
+ for i=1, #h do
+ local p = h[i]
+ local z = p.y_coord
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ z = p.right_y
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ z = p.left_y
+ if z < zlo then zlo = z elseif z > zhi then zhi = z end
+ end
+ return (zhi - zlo <= dz and aspect_bound) or aspect_default
+end
+
+local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+
+local function pen_characteristics(object)
+ local p = object.pen[1]
+ local x_coord, y_coord, left_x, left_y, right_x, right_y = p.x_coord, p.y_coord, p.left_x, p.left_y, p.right_x, p.right_y
+ local wx, wy, width
+ if right_x == x_coord and left_y == y_coord then
+ wx = abs(left_x - x_coord)
+ wy = abs(right_y - y_coord)
+ else
+ wx = pyth(left_x - x_coord, right_x - x_coord)
+ wy = pyth(left_y - y_coord, right_y - y_coord)
+ end
+ if wy/coord_range_x(object.path, wx) >= wx/coord_range_y(object.path, wy) then
+ width = wy
+ else
+ width = wx
+ end
+ sx, rx, ry, sy, tx, ty = left_x, left_y, right_x, right_y, x_coord, y_coord
+ if width ~= 1 then
+ if width == 0 then
+ sx, sy = 1, 1
+ else
+ rx, ry, sx, sy = rx/width, ry/width, sx/width, sy/width
+ end
+ end
+ -- sx rx ry sy tx ty -> 1 0 0 1 0 0 is ok, but 0 0 0 0 0 0 not
+ if true then
+ if abs(sx) < eps then sx = eps end
+ if abs(sy) < eps then sy = eps end
+ else
+ -- this block looks complicated but it only captures invalid transforms
+ -- to be checked rx vs sx and so
+ local det = sx/sy - ry/rx
+ local aspect = 4*aspect_bound + aspect_default
+ if abs(det) < aspect then
+ local s
+ if det >= 0 then
+ s, aspect = 1, aspect - det
+ else
+ s, aspect = -1, -aspect - det -- - ?
+ end
+ local absrx, absry, abssy, abssx = abs(rx), abs(ry), abs(sy), abs(sx)
+ if abssx + abssy >= absry + absrx then -- was yy
+ if abssx > abssy then
+ sy = sy + (aspect + s*abssx) / sx
+ else
+ sx = sx + (aspect + s*abssy) / sy
+ end
+ else
+ if absry > absrx then
+ rx = rx + (aspect + s*absry) / ry
+ else
+ ry = ry + (aspect + s*absrx) / rx
+ end
+ end
+ end
+ end
+ divider = sx*sy - rx*ry
+ return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), width
+end
+
+local function concat(px, py)
+ local dx, dy = px-tx, py-ty
+ return (sy*dx-ry*dy)/divider,(sx*dy-rx*dx)/divider
+end
+
+local function curved(ith,pth)
+ local d = pth.left_x - ith.right_x
+ if abs(ith.right_x-ith.x_coord-d) <= bend_tolerance and abs(pth.x_coord-pth.left_x-d) <= bend_tolerance then
+ d = pth.left_y - ith.right_y
+ if abs(ith.right_y-ith.y_coord-d) <= bend_tolerance and abs(pth.y_coord-pth.left_y-d) <= bend_tolerance then
+ return false
+ end
+ end
+ return true
+end
+
+local function flushnormalpath(path, t, open)
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ t[#t+1] = format("%f %f m",pth.x_coord,pth.y_coord)
+ elseif curved(ith,pth) then
+ t[#t+1] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+ else
+ t[#t+1] = format("%f %f l",pth.x_coord,pth.y_coord)
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ t[#t+1] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+ else
+ t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ end
+ end
+ return t
+end
+
+local function flushconcatpath(path, t, open)
+ t[#t+1] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ t[#t+1] = format("%f %f m",concat(pth.x_coord,pth.y_coord))
+ elseif curved(ith,pth) then
+ local a, b = concat(ith.right_x,ith.right_y)
+ local c, d = concat(pth.left_x,pth.left_y)
+ t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
+ else
+ t[#t+1] = format("%f %f l",concat(pth.x_coord, pth.y_coord))
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ local a, b = concat(pth.right_x,pth.right_y)
+ local c, d = concat(one.left_x,one.left_y)
+ t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
+ else
+ t[#t+1] = format("%f %f l",concat(one.x_coord,one.y_coord))
+ end
+ end
+ return t
+end
+
+metapost.specials = metapost.specials or { }
+
+-- we have two extension handlers, one for pre and postscripts, and one for colors
+
+function metapost.flush(result) -- pdf flusher, table en dan concat is sneller, 1 literal
+ if result then
+ local figures = result.fig
+ if figures then
+ local colorconverter = metapost.colorconverter() -- function !
+ local colorhandler = metapost.colorhandler
+ for f=1, #figures do
+ local figure = figures[f]
+ local objects = figure:objects()
+ 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
+ if urx < llx then
+ -- invalid
+ metapost.startfigure(0,0,0,0,"invalid")
+ metapost.stopfigure()
+ else
+ metapost.startfigure(llx,lly,urx,ury,"begin")
+ t[#t+1] = "q"
+ if objects then
+ for o=1,#objects do
+ local object = objects[o]
+ local objecttype = object.type
+ if objecttype == "start_bounds" or objecttype == "stop_bounds" then
+ -- skip
+ elseif objecttype == "start_clip" then
+ t[#t+1] = "q"
+ flushnormalpath(object.path,t,false)
+ t[#t+1] = "W n"
+ elseif objecttype == "stop_clip" then
+ t[#t+1] = "Q"
+ miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+ elseif objecttype == "special" then
+ metapost.specials.register(object.prescript)
+ elseif objecttype == "text" then
+ t[#t+1] = "q"
+ local ot = object.transform -- 3,4,5,6,1,2
+ t[#t+1] = format("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: format("%f %f m %f %f %f %f 0 0 cm",unpack(ot))
+ metapost.flushfigure(t)
+ t = { }
+ metapost.textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
+ t[#t+1] = "Q"
+ else
+ -- alternatively we can pass on the stack, could be a helper
+ local currentobject = { -- not needed when no extensions
+ type = object.type,
+ miterlimit = object.miterlimit,
+ linejoin = object.linejoin,
+ linecap = object.linecap,
+ color = object.color,
+ dash = object.dash,
+ path = object.path,
+ htap = object.htap,
+ pen = object.pen,
+ prescript = object.prescript,
+ postscript = object.postscript,
+ }
+ --
+ local before, inbetween, after = nil, nil, nil
+ --
+ local cs, cr = currentobject.color, nil
+ -- todo document why ...
+ if cs and colorhandler and round(cs[1]*10000) == 123 then -- test in function
+ currentobject, cr = colorhandler(cs,currentobject,t,colorconverter)
+ objecttype = currentobject.type
+ end
+ --
+ local prescript = currentobject.prescript
+ if prescript then
+ -- move test to function
+ local special = metapost.specials[prescript]
+ if special then
+ currentobject, before, inbetween, after = special(currentobject.postscript,currentobject,t)
+ objecttype = currentobject.type
+ end
+ end
+ --
+ cs = currentobject.color
+ if cs then
+ t[#t+1], cr = colorconverter(cs,objecttype)
+ end
+ --
+ if before then object, t = before() end
+ local ml = currentobject.miterlimit
+ if ml and ml ~= miterlimit then
+ miterlimit = ml
+ t[#t+1] = format("%f M",ml)
+ end
+ local lj = currentobject.linejoin
+ if lj and lj ~= linejoin then
+ linejoin = lj
+ t[#t+1] = format("%i j",lj)
+ end
+ local lc = currentobject.linecap
+ if lc and lc ~= linecap then
+ linecap = lc
+ t[#t+1] = format("%i J",lc)
+ end
+ local dl = currentobject.dash
+ if dl then
+ local d = format("[%s] %i d",join(dl.dashes or {}," "),dl.offset)
+ if d ~= dashed then
+ dashed = d
+ t[#t+1] = dashed
+ end
+ elseif dashed then
+ t[#t+1] = "[] 0 d"
+ dashed = false
+ end
+ if inbetween then object, t = inbetween() end
+ local path = currentobject.path
+ local transformed, penwidth = false, 1
+ local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
+ if path then
+ local pen = currentobject.pen
+ if pen and #pen==1 then
+ transformed, penwidth = pen_characteristics(object) -- boolean, value
+ t[#t+1] = format("%f w",penwidth) -- todo: only if changed
+ end
+ if transformed then
+ t[#t+1] = "q"
+ flushconcatpath(path,t,open)
+ else
+ flushnormalpath(path,t,open)
+ end
+ end
+ local path = currentobject.htap
+ if path then
+ flushnormalpath(path,t,open)
+ end
+ if objecttype == "fill" then
+ t[#t+1] = "h f"
+ elseif objecttype == "outline" then
+ t[#t+1] = (open and "S") or "h S"
+ end
+ if transformed then
+ t[#t+1] = "Q"
+ end
+ if cr and currentobject.color then -- and o < #objects
+ t[#t+1] = cr
+ end
+ if after then object, t = after() end
+ end
+ end
+ end
+ t[#t+1] = "Q"
+ metapost.flushfigure(t)
+ metapost.stopfigure("end")
+ end
+ end
+ end
+ end
+end
+
+function metapost.parse(result)
+ if result then
+ local figures = result.fig
+ if figures then
+ for f=1, #figures do
+ local figure = figures[f]
+ local objects = figure:objects()
+ if objects then
+ for o=1,#objects do
+ local object = objects[o]
+ if object.type == "outline" then
+ local prescript = object.prescript
+ if prescript then
+ local special = metapost.specials[prescript]
+ if special then
+ special(object.postscript,object)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function metapost.pdfliterals(result)
+ -- only simple graphics, tracing
+ local start = metapost.startfigure
+ local stop = metapost.stopfigure
+ local flush = metapost.flushfigure
+ local t = { }
+ function metapost.flushfigure(literals)
+ for i=1, #literals do
+ t[#t+1] = literals[i]
+ end
+ end
+ function metapost.startfigure()
+ tex.sprint(tex.ctxcatcodes,"\\startnointerference")
+ end
+ function metapost.stopfigure()
+ tex.sprint(tex.ctxcatcodes,"\\stopnointerference")
+ end
+ metapost.flush(result)
+ metapost.startfigure = start
+ metapost.stopfigure = stop
+ metapost.flushfigure = flush
+ return t
+end
+
+function metapost.totable(result)
+ local figure = result and result.fig and result.fig[1]
+ if figure then
+ local t = { }
+ local objects = figure:objects()
+ for _, object in ipairs(objects) do
+ local tt = { }
+ for _, field in ipairs(mplib.fields(object)) do
+ tt[field] = object[field]
+ end
+ t[#t+1] = tt
+ end
+ local b = figure:boundingbox()
+ return {
+ boundingbox = { llx = b[1], lly = b[2], urx = b[3], ury = b[4] },
+ objects = t
+ }
+ else
+ return nil
+ end
+end
+
+function metapost.colorconverter()
+ return function(c,type)
+ if type == "fill" then
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f k", c[1],c[2],c[3],c[4]), "0 g"
+ elseif #c == 3 then return format("%.3f %.3f %.3f rg", c[1],c[2],c[3]), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f K", c[1],c[2],c[3],c[4]), "0 G"
+ elseif #c == 3 then return format("%.3f %.3f %.3f RG", c[1],c[2],c[3]), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+end
diff --git a/tex/context/base/mlib-pdf.tex b/tex/context/base/mlib-pdf.tex
new file mode 100644
index 000000000..b7b8506ad
--- /dev/null
+++ b/tex/context/base/mlib-pdf.tex
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=mlib-pdf,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Conversion to PDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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
+
+\registerctxluafile{mlib-pdf}{1.001}
+
+\let\MPLIBtoPDF\pdfliteral
+
+\def\MPLIBboundingbox#1#2#3#4%
+ {\xdef\MPllx{#1}%
+ \xdef\MPlly{#2}%
+ \xdef\MPurx{#3}%
+ \xdef\MPury{#4}%
+ \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+
+\def\startMPLIBtoPDF#1#2#3#4% watch the transparency reset
+ {\hbox\bgroup
+ \MPLIBboundingbox{#1}{#2}{#3}{#4}%
+ \forgetall
+ \setbox\scratchbox\vbox\bgroup
+ \noindent % this is really needed in order to force tex into proper cm's
+ \startMPresources}
+
+\def\stopMPLIBtoPDF % watch the transparency reset
+ {%\dohandleMPresettransparency % not needed
+ \stopMPresources
+ \egroup
+ \setbox\scratchbox\hbox\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vbox to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup}
+
+% \def\MPLIBtextext#1#2#3#4#5%
+% {\begingroup
+% \def\MPtextdata{#3}% delegate the splitter to lua
+% \defconvertedcommand\MPtextdata\MPtextdata % no edef
+% \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
+% \executeifdefined{handleMPtext\MPtexttag}
+% {\setbox\scratchbox\hbox
+% {\font\temp=#1\space at #2\onebasepoint
+% \let\c\char
+% \temp
+% \MPfshowcommand{#3}}%
+% \setbox\scratchbox\hbox
+% {\hskip#4\onebasepoint
+% \raise#5\onebasepoint
+% \box\scratchbox}%
+% \smashbox\scratchbox
+% \box\scratchbox}%
+% \endgroup}
+
+\def\MPLIBtextext#1#2#3#4#5%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\font\temp=#1\space at #2\onebasepoint
+ \let\c\char
+ \temp
+ \MPfshowcommand{#3}}%
+ \setbox\scratchbox\hbox
+ {\hskip#4\onebasepoint
+ \raise#5\onebasepoint
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua
new file mode 100644
index 000000000..de658d21b
--- /dev/null
+++ b/tex/context/base/mlib-pps.lua
@@ -0,0 +1,820 @@
+if not modules then modules = { } end modules ['mlib-pps'] = { -- prescript, postscripts and specials
+ version = 1.001,
+ comment = "companion to mlib-ctx.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- todo
+
+local format, join = string.format, table.concat
+local sprint = tex.sprint
+local round = math.round
+
+local rgbtocmyk = colors.rgbtocmyk
+local rgbtogray = colors.rgbtogray
+local cmyktorgb = colors.cmyktorgb
+local cmyktogray = colors.cmyktogray
+
+metapost = metapost or { }
+metapost.specials = metapost.specials or { }
+metapost.specials.data = metapost.specials.data or { }
+
+local data = metapost.specials.data
+
+local colordata = { {}, {}, {}, {}, {} }
+
+--~ (r,g,b) => cmyk : r=123 g= 1 b=hash
+--~ => spot : r=123 g= 2 b=hash
+--~ => transparent rgb : r=123 g= 3 b=hash
+--~ => transparent cmyk : r=123 g= 4 b=hash
+--~ => transparent spot : r=123 g= 5 b=hash
+--~ => rest : r=123 g=n>10 b=whatever
+
+function metapost.specials.register(str) -- only colors
+ local size, content, n, class = str:match("^%%%%MetaPostSpecial: (%d+) (.*) (%d+) (%d+)$")
+ if class then
+ local data = { }
+ for s in content:gmatch("[^ ]+") do
+ data[#data+1] = s
+ end
+ class, n = tonumber(class), tonumber(n)
+ if class == 3 or class == 4 or class == 5 then -- weird
+ colordata[class][n] = data
+ else
+ colordata[class][tonumber(data[1])] = data
+ end
+ end
+end
+
+function metapost.colorhandler(cs, object, result, colorconverter)
+ local cr = "0 g 0 G"
+ local what = round(cs[2]*10000)
+ local data = colordata[what][round(cs[3]*10000)]
+ if not data then
+ --
+ elseif what == 1 then
+ result[#result+1], cr = colorconverter({ data[2], data[3], data[4], data[5]}, object.type)
+ elseif what == 2 then
+ ctx.registerspotcolor(data[2])
+ result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[2],data[3],data[4],data[5]))
+ else
+ if what == 3 then
+ result[#result+1], cr = colorconverter({ data[3], data[4], data[5]}, object.type)
+ elseif what == 4 then
+ result[#result+1], cr = colorconverter({ data[3], data[4], data[5], data[6]}, object.type)
+ elseif what == 5 then
+ ctx.registerspotcolor(data[3])
+ result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[3],data[4],data[5],data[6]))
+ end
+ object.prescript = "tr"
+ object.postscript = data[1] .. "," .. data[2]
+ end
+ object.color = nil
+ return object, cr
+end
+
+function metapost.colorspec(cs)
+ local what = round(cs[2]*10000)
+ local data = colordata[what][round(cs[3]*10000)]
+ if not data then
+ return { 0 }
+ elseif what == 1 then
+ return { data[2], data[3], data[4], data[5] }
+ elseif what == 2 then
+ ctx.registerspotcolor(data[2])
+ return ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[2],data[3],data[4],data[5]))
+ elseif what == 3 then
+ return { data[3], data[4], data[5] }
+ elseif what == 4 then
+ return { data[3], data[4], data[5], data[6] }
+ elseif what == 5 then
+ ctx.registerspotcolor(data[3])
+ return ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[3],data[4],data[5],data[6]))
+ end
+end
+
+function metapost.specials.tr(specification,object,result)
+ local a, t = specification:match("^(.+),(.+)$")
+ local before = a and t and function()
+ result[#result+1] = format("/Tr%s gs",transparencies.register('mp',a,t))
+ return object, result
+ end
+ local after = before and function()
+ result[#result+1] = "/Tr0 gs"
+ return object, result
+ end
+ return object, before, nil, after
+end
+
+--~ -- possible speedup: hash registered colors
+--~
+--~ function metapost.specials.sp(specification,object,result) -- todo: color conversion
+--~ local s = object.color[1]
+--~ object.color = nil
+--~ local before = function()
+--~ local spec = specification:split(" ")
+--~ ctx.registerspotcolor(spec[1])
+--~ result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',spec[1],spec[2],spec[3],s))
+--~ return object, result
+--~ end
+--~ local after = function()
+--~ result[#result+1] = "0 g 0 G"
+--~ return object, result
+--~ end
+--~ return object, before, nil, nil
+--~ end
+
+-- Unfortunately we cannot use cmyk colors natively because there is no
+-- generic color allocation primitive ... it's just an rgbcolor color.. This
+-- means that we cannot pass colors in either cmyk or rgb form.
+--
+-- def cmyk(expr c,m,y,k) =
+-- 1 withprescript "cc" withpostscript ddddecimal (c,m,y,k)
+-- enddef ;
+--
+-- This is also an example of a simple plugin.
+
+--~ function metapost.specials.cc(specification,object,result)
+--~ object.color = specification:split(" ")
+--~ return object, nil, nil, nil
+--~ end
+--~ function metapost.specials.cc(specification,object,result)
+--~ local c = specification:split(" ")
+--~ local o = object.color[1]
+--~ c[1],c[2],c[3],c[4] = o*c[1],o*c[2],o*c[3],o*c[4]
+--~ return object, nil, nil, nil
+--~ end
+
+-- thanks to taco's reading of the postscript manual:
+--
+-- x' = sx * x + ry * y + tx
+-- y' = rx * x + sy * y + ty
+
+function metapost.specials.fg(specification,object,result)
+ local op = object.path
+ local first, second, fourth = op[1], op[2], op[4]
+ local tx, ty = first.x_coord , first.y_coord
+ local sx, sy = second.x_coord - tx, fourth.y_coord - ty
+ local rx, ry = second.y_coord - ty, fourth.x_coord - tx
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ local before = specification and function()
+ metapost.flushfigure(result)
+ sprint(tex.ctxcatcodes,format("\\MPLIBfigure{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,specification))
+ return object, { }
+ end
+ return { } , before, nil, nil -- replace { } by object for tracing
+end
+
+local nofshades = 0 -- todo: hash resources, start at 1000 in order not to clash with older
+
+local function normalize(ca,cb)
+ if #cb == 1 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = 0, 0, 0, 1-cb[1]
+ else
+ cb[1], cb[2], cb[3] = cb[1], cb[1], cb[1]
+ end
+ elseif #cb == 3 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ else
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ end
+ end
+end
+
+function metapost.specials.cs(specification,object,result) -- spot colors?
+ nofshades = nofshades + 1
+ metapost.flushfigure(result)
+ result = { }
+ local t = specification:split(" ")
+ -- we need a way to move/scale
+ local ca = t[4]:split(":")
+ local cb = t[8]:split(":")
+ if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end
+ if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end
+ if type(ca) == "string" then
+ -- spot color, not supported, maybe at some point use the fallbacks
+ sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s %s %s}",
+ nofshades,
+ t[1], t[2], 0, 1, 1, "DeviceGray",
+ t[5], t[6], t[7], t[9], t[10], t[11]))
+ else
+ if #ca > #cb then
+ normalize(ca,cb)
+ elseif #ca < #cb then
+ normalize(cb,ca)
+ end
+ local model = colors.model
+ if model == "all" then
+ model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray"
+ end
+ if model == "rgb" then
+ if #ca == 4 then
+ ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4])
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 1 then
+ local a, b = 1-ca[1], 1-cb[1]
+ ca[1], ca[2], ca[3] = a, a, a
+ cb[1], cb[2], cb[3] = b, b, b
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f %.3f %.3f}{%.3f %.3f %.3f}{%s}{%s}{%s %s %s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], ca[2], ca[3], cb[1], cb[2], cb[3], 1, "DeviceRGB",
+ t[5], t[6], t[7], t[9], t[10], t[11]))
+ elseif model == "cmyk" then
+ if #ca == 3 then
+ ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3])
+ cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ elseif #ca == 1 then
+ ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1]
+ cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1]
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f %.3f %.3f %.3f}{%.3f %.3f %.3f %.3f}{%s}{%s}{%s %s %s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], ca[2], ca[3], ca[4], cb[1], cb[2], cb[3], cb[4], 1, "DeviceCMYK",
+ t[5], t[6], t[7], t[9], t[10], t[11]))
+ else
+ if #ca == 4 then
+ ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4])
+ cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 3 then
+ ca[1] = rgbtogray(ca[1],ca[2],ca[3])
+ cb[1] = rgbtogray(cb[1],cb[2],cb[3])
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], cb[1], 1, "DeviceGray",
+ t[5], t[6], t[7], t[9], t[10], t[11]))
+ end
+ end
+ local before = function()
+ result[#result+1] = "q /Pattern cs"
+ return object, result
+ end
+ local after = function()
+ result[#result+1] = format("W n /MpSh%s sh Q", nofshades)
+ return object, result
+ end
+ object.color, object.type = nil, nil
+ return object, before, nil, after
+end
+
+function metapost.specials.ls(specification,object,result)
+ nofshades = nofshades + 1
+ metapost.flushfigure(result)
+ result = { }
+ local t = specification:split(" ")
+ -- we need a way to move/scale
+ local ca = t[4]:split(":")
+ local cb = t[7]:split(":")
+ if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end
+ if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end
+ if type(ca) == "string" then
+ -- spot color, not supported, maybe at some point use the fallbacks
+ sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s}",
+ nofshades,
+ t[1], t[2], 0, 1, 1, "DeviceGray",
+ t[5], t[6], t[8], t[9]))
+ else
+ if #ca > #cb then
+ normalize(ca,cb)
+ elseif #ca < #cb then
+ normalize(cb,ca)
+ end
+ local model = colors.model
+ if model == "all" then
+ model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray"
+ end
+ if model == "rgb" then
+ if #ca == 4 then
+ ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4])
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 1 then
+ local a, b = 1-ca[1], 1-cb[1]
+ ca[1], ca[2], ca[3] = a, a, a
+ cb[1], cb[2], cb[3] = b, b, b
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f %.3f %.3f}{%.3f %.3f %.3f}{%s}{%s}{%s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], ca[2], ca[3], cb[1], cb[2], cb[3], 1, "DeviceRGB",
+ t[5], t[6], t[8], t[9]))
+ elseif model == "cmyk" then
+ if #ca == 3 then
+ ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3])
+ cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ elseif #ca == 1 then
+ ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1]
+ cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1]
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f %.3f %.3f %.3f}{%.3f %.3f %.3f %.3f}{%s}{%s}{%s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], ca[2], ca[3], ca[4], cb[1], cb[2], cb[3], cb[4], 1, "DeviceCMYK",
+ t[5], t[6], t[8], t[9]))
+ else
+ if #ca == 4 then
+ ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4])
+ cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 3 then
+ ca[1] = rgbtogray(ca[1],ca[2],ca[3])
+ cb[1] = rgbtogray(cb[1],cb[2],cb[3])
+ end
+ sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s}",
+ nofshades,
+ t[1], t[2], ca[1], cb[1], 1, "DeviceGray",
+ t[5], t[6], t[8], t[9]))
+ end
+ end
+ local before = function()
+ result[#result+1] = "q /Pattern cs"
+ return object, result
+ end
+ local after = function()
+ result[#result+1] = format("W n /MpSh%s sh Q", nofshades)
+ return object, result
+ end
+ object.color, object.type = nil, nil
+ return object, before, nil, after
+end
+
+-- no need for a before here
+
+local current_format, current_graphic
+
+--~ metapost.first_box, metapost.last_box = 1000, 1100
+
+metapost.textext_current = metapost.first_box
+
+function metapost.specials.tf(specification,object)
+--~ print("setting", metapost.textext_current)
+ sprint(tex.ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",metapost.textext_current,specification))
+ if metapost.textext_current < metapost.last_box then
+ metapost.textext_current = metapost.textext_current + 1
+ end
+ return { }, nil, nil, nil
+end
+
+function metapost.specials.ts(specification,object,result)
+ -- print("getting", metapost.textext_current)
+ local op = object.path
+ local first, second, fourth = op[1], op[2], op[4]
+ local tx, ty = first.x_coord , first.y_coord
+ local sx, sy = second.x_coord - tx, fourth.y_coord - ty
+ local rx, ry = second.y_coord - ty, fourth.x_coord - tx
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ local before = function()
+ --~ metapost.flushfigure(result)
+ --~ sprint(tex.ctxcatcodes,format("\\MPLIBgettext{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,metapost.textext_current))
+ --~ result = { }
+ result[#result+1] = format("q %f %f %f %f %f %f cm", sx,rx,ry,sy,tx,ty)
+ metapost.flushfigure(result)
+ local b = metapost.textext_current
+ sprint(tex.ctxcatcodes,format("\\MPLIBgettextscaled{%s}{%s}{%s}",b, metapost.sxsy(tex.wd[b],tex.ht[b],tex.dp[b])))
+ result = { "Q" }
+ if metapost.textext_current < metapost.last_box then
+ metapost.textext_current = metapost.textext_current + 1
+ end
+ return object, result
+ end
+ return { }, before, nil, nil -- replace { } by object for tracing
+end
+
+function metapost.colorconverter()
+ local model = colors.model
+ if model == "all" then
+ return function(c,type)
+ if type == "fill" then
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f k", c[1],c[2],c[3],c[4]), "0 g"
+ elseif #c == 3 then return format("%.3f %.3f %.3f rg", c[1],c[2],c[3]), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f K", c[1],c[2],c[3],c[4]), "0 G"
+ elseif #c == 3 then return format("%.3f %.3f %.3f RG", c[1],c[2],c[3]), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ elseif model == "rgb" then
+ return function(c,type)
+ if type == "fill" then
+ if #c == 4 then return format("%.3f %.3f %.3f rg",cmyktorgb(c[1],c[2],c[3],c[4])), "0 g"
+ elseif #c == 3 then return format("%.3f %.3f %.3f rg", c[1],c[2],c[3]), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if #c == 4 then return format("%.3f %.3f %.3f RG",cmyktorgb(c[1],c[2],c[3],c[4])), "0 G"
+ elseif #c == 3 then return format("%.3f %.3f %.3f RG", c[1],c[2],c[3]), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ elseif model == "cmyk" then
+ return function(c,type)
+ if type == "fill" then
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f k", c[1],c[2],c[3],c[4]), "0 g"
+ elseif #c == 3 then return format("%.3f %.3f %.3f %.3f k",rgbtocmyk(c[1],c[2],c[3])), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if #c == 4 then return format("%.3f %.3f %.3f %.3f K", c[1],c[2],c[3],c[4]), "0 G"
+ elseif #c == 3 then return format("%.3f %.3f %.3f %.3f K",rgbtocmyk(c[1],c[2],c[3])), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ else
+ return function(c,type)
+ if type == "fill" then
+ if #c == 4 then return format("%.3f g",cmyktogray(c[1],c[2],c[3],c[4])), "0 g"
+ elseif #c == 3 then return format("%.3f g",rgbtogray (c[1],c[2],c[3])), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if #c == 4 then return format("%.3f G",cmyktogray(c[1],c[2],c[3],colors[4])), "0 G"
+ elseif #c == 3 then return format("%.3f G",rgbtogray (c[1],c[2],c[3])), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ end
+end
+
+--~ local cmyk_fill = "%.3f %.3f %.3f %.3f k"
+--~ local rgb_fill = "%.3f %.3f %.3f rg"
+--~ local gray_fill = "%.3f g"
+--~ local reset_fill = "0 g"
+
+--~ local cmyk_stroke = "%.3f %.3f %.3f %.3f K"
+--~ local rgb_stroke = "%.3f %.3f %.3f RG"
+--~ local gray_stroke = "%.3f G"
+--~ local reset_stroke = "0 G"
+
+metapost.reducetogray = true
+
+function metapost.colorconverter()
+ local model = colors.model
+ local reduce = metapost.reducetogray
+ if model == "all" then
+ return function(c,type)
+ local n = #c
+ if reduce and n == 3 then if c[1] == c[2] and c[1] == c[3] then n = 1 end end
+ if type == "fill" then
+ if n == 4 then return format("%.3f %.3f %.3f %.3f k", c[1],c[2],c[3],c[4]), "0 g"
+ elseif n == 3 then return format("%.3f %.3f %.3f rg", c[1],c[2],c[3]), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if n == 4 then return format("%.3f %.3f %.3f %.3f K", c[1],c[2],c[3],c[4]), "0 G"
+ elseif n == 3 then return format("%.3f %.3f %.3f RG", c[1],c[2],c[3]), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ elseif model == "rgb" then
+ return function(c,type)
+ local n = #c
+ if reduce and n == 3 then if c[1] == c[2] and c[1] == c[3] then n = 1 end end
+ if type == "fill" then
+ if n == 4 then return format("%.3f %.3f %.3f rg",cmyktorgb(c[1],c[2],c[3],c[4])), "0 g"
+ elseif n == 3 then return format("%.3f %.3f %.3f rg", c[1],c[2],c[3]), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if n == 4 then return format("%.3f %.3f %.3f RG",cmyktorgb(c[1],c[2],c[3],c[4])), "0 G"
+ elseif n == 3 then return format("%.3f %.3f %.3f RG", c[1],c[2],c[3]), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ elseif model == "cmyk" then
+ return function(c,type)
+ local n = #c
+ if reduce and n == 3 then if c[1] == c[2] and c[1] == c[3] then n = 1 end end
+ if type == "fill" then
+ if n == 4 then return format("%.3f %.3f %.3f %.3f k", c[1],c[2],c[3],c[4]), "0 g"
+ elseif n == 3 then return format("%.3f %.3f %.3f %.3f k",rgbtocmyk(c[1],c[2],c[3])), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if n == 4 then return format("%.3f %.3f %.3f %.3f K", c[1],c[2],c[3],c[4]), "0 G"
+ elseif n == 3 then return format("%.3f %.3f %.3f %.3f K",rgbtocmyk(c[1],c[2],c[3])), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ else
+ return function(c,type)
+ local n = #c
+ if reduce and n == 3 then if c[1] == c[2] and c[1] == c[3] then n = 1 end end
+ if type == "fill" then
+ if n == 4 then return format("%.3f g",cmyktogray(c[1],c[2],c[3],c[4])), "0 g"
+ elseif n == 3 then return format("%.3f g",rgbtogray (c[1],c[2],c[3])), "0 g"
+ else return format("%.3f g", c[1]), "0 g"
+ end
+ else
+ if n == 4 then return format("%.3f G",cmyktogray(c[1],c[2],c[3],c[4])), "0 G"
+ elseif n == 3 then return format("%.3f G",rgbtogray (c[1],c[2],c[3])), "0 G"
+ else return format("%.3f G", c[1]), "0 G"
+ end
+ end
+ end
+ end
+end
+
+-- textext stuff
+
+--~ do
+--~
+--~ local P, V, Cs = lpeg.P, lpeg.V, lpeg.Cs
+--~
+--~ local btex = P("btex")
+--~ local etex = P("etex")
+--~ local vtex = P("verbatimtex")
+--~ local ttex = P("textext")
+--~ local gtex = P("graphictext")
+--~ local spacing = P(" \n\r\t\v")^0
+--~ local left = P("(")
+--~ local right = P(")")
+--~ local dquote = P('"')
+--~ local ddquote = P('\\"') / "\\\" & ditto & \""
+--~
+--~ local found, n = false, 0
+--~
+--~ local function textext_first(s)
+--~ local str = format('_tex_text_f_("%s")',s)
+--~ found, n = true, n + 1
+--~ return str
+--~ end
+--~ local function textext_second()
+--~ local str = format('_tex_text_s_(%s,%spt,%spt,%spt)',n,tex.wd[n]/65536,tex.ht[n]/65536,tex.dp[n]/65536)
+--~ found, n = true, n + 1
+--~ return str
+--~ end
+--~ local function graphictext_first(s)
+--~ local str = format('_graphic_text_f_("%s")',s)
+--~ found = true
+--~ return str
+--~ end
+--~ local function graphictext_second()
+--~ local str = format('_graphic_text_s_')
+--~ found = true
+--~ return str
+--~ end
+--~
+--~ -- the next lpegs can be more efficient (in code only) by not using a grammar
+--~
+--~ local first = P {
+--~ [1] = Cs(((V(2) + V(3))/textext_first + V(4)/graphictext_first + 1)^0),
+--~ [2] = (btex + vtex) * spacing * Cs((1-etex)^0) * spacing * etex,
+--~ [3] = ttex * spacing * left * spacing * V(5) * spacing * right,
+--~ [4] = gtex * spacing * V(5),
+--~ [5] = dquote * Cs((ddquote + (1-dquote))^0) * dquote,
+--~ }
+--~
+--~ local second = P {
+--~ [1] = Cs(((V(2) + V(3))/textext_second + V(4)/graphictext_second + 1)^0),
+--~ [2] = (btex + vtex) * spacing * Cs((1-etex)^0) * spacing * etex,
+--~ [3] = ttex * spacing * left * spacing * V(5) * spacing * right,
+--~ [4] = gtex * spacing * V(5),
+--~ [5] = dquote * Cs((ddquote + (1-dquote))^0) * dquote,
+--~ }
+--~
+--~ function metapost.texttext_first(str)
+--~ found, n = false, metapost.first_box -- or 0 no fallback, better an error
+--~ return first:match(str), found
+--~ end
+--~ function metapost.texttext_second(str)
+--~ found, n = false, metapost.first_box -- or 0 no fallback, better an error
+--~ return second:match(str), found
+--~ end
+--~
+--~ end
+--~
+--~ local factor = 65536*(7200/7227)
+--~
+--~ function metapost.edefsxsy(wd,ht,dp) -- helper for text
+--~ commands.edef("sx",(wd ~= 0 and 1/( wd /(factor))) or 0)
+--~ commands.edef("sy",(wd ~= 0 and 1/((ht+dp)/(factor))) or 0)
+--~ end
+--~
+--~ function metapost.sxsy(wd,ht,dp) -- helper for text
+--~ return (wd ~= 0 and 1/(wd/(factor))) or 0, (wd ~= 0 and 1/((ht+dp)/(factor))) or 0
+--~ end
+--~
+--~ metapost.intermediate = metapost.intermediate or {}
+--~ metapost.intermediate.actions = metapost.intermediate.actions or {}
+--~ metapost.intermediate.needed = false
+--~
+--~ function metapost.graphic_base_pass(mpsformat,str,preamble)
+--~ local prepared, done = metapost.texttext_first(str)
+--~ metapost.textext_current = metapost.first_box
+--~ metapost.intermediate.needed = false
+--~ if done then
+--~ current_format, current_graphic = mpsformat, str
+--~ metapost.process(mpsformat, {
+--~ preamble or "",
+--~ "beginfig(1); ",
+--~ prepared,
+--~ "endfig ;"
+--~ }, true ) -- true means: trialrun
+--~ if metapost.intermediate.needed then
+--~ for _, action in pairs(metapost.intermediate.actions) do
+--~ action()
+--~ end
+--~ end
+--~ sprint(tex.ctxcatcodes,"\\ctxlua{metapost.graphic_extra_pass()}")
+--~ else
+--~ metapost.process(mpsformat, {
+--~ preamble or "",
+--~ "beginfig(1); ",
+--~ str,
+--~ "endfig ;"
+--~ } )
+--~ end
+--~ end
+--~
+--~ function metapost.graphic_extra_pass()
+--~ local prepared, done = metapost.texttext_second(current_graphic)
+--~ metapost.textext_current = metapost.first_box
+--~ metapost.process(current_format, {
+--~ "beginfig(0); ",
+--~ prepared,
+--~ "endfig ;"
+--~ })
+--~ end
+
+--~ At the cost of passing data about the texts to MP, the following
+--~ solution also handles textexts that are more complex and part of
+--~ formats.
+
+do
+
+ local P, S, V, Cs = lpeg.P, lpeg.S, lpeg.V, lpeg.Cs
+
+ local btex = P("btex")
+ local etex = P(" etex")
+ local vtex = P("verbatimtex")
+ local ttex = P("textext")
+ local gtex = P("graphictext")
+ local spacing = S(" \n\r\t\v")^0
+ local dquote = P('"')
+
+ local found = false
+
+ local function convert(str)
+ found = true
+ return "textext(\"" .. str .. "\")"
+ end
+ local function ditto(str)
+ return "\" & ditto & \""
+ end
+ local function register()
+ found = true
+ end
+
+ local parser = P {
+ [1] = Cs((V(2)/register + V(3)/convert + 1)^0),
+ [2] = ttex + gtex,
+ [3] = (btex + vtex) * spacing * Cs((dquote/ditto + (1 - etex))^0) * etex,
+ }
+
+ -- currently a a one-liner produces less code
+
+ local parser = Cs(((ttex + gtex)/register + ((btex + vtex) * spacing * Cs((dquote/ditto + (1 - etex))^0) * etex)/convert + 1)^0)
+
+ function metapost.check_texts(str)
+ found = false
+ return parser:match(str), found
+ end
+
+end
+
+local factor = 65536*(7200/7227)
+
+function metapost.edefsxsy(wd,ht,dp) -- helper for text
+ commands.edef("sx",(wd ~= 0 and 1/( wd /(factor))) or 0)
+ commands.edef("sy",(wd ~= 0 and 1/((ht+dp)/(factor))) or 0)
+end
+
+function metapost.sxsy(wd,ht,dp) -- helper for text
+ return (wd ~= 0 and 1/(wd/(factor))) or 0, (wd ~= 0 and 1/((ht+dp)/(factor))) or 0
+end
+
+function metapost.text_texts_data()
+ local t, n = { }, 0
+ for i = metapost.first_box, metapost.last_box do
+ n = n + 1
+ if tex.box[i] then
+ t[#t+1] = format("_tt_w_[%i]:=%f;_tt_h_[%i]:=%f;_tt_d_[%i]:=%f;", n,tex.wd[i]/factor, n,tex.ht[i]/factor, n,tex.dp[i]/factor)
+ else
+ break
+ end
+ end
+ return t
+end
+
+metapost.intermediate = metapost.intermediate or {}
+metapost.intermediate.actions = metapost.intermediate.actions or {}
+metapost.intermediate.needed = false
+
+function metapost.graphic_base_pass(mpsformat,str,preamble)
+ local prepared, done = metapost.check_texts(str)
+ metapost.textext_current = metapost.first_box
+ metapost.intermediate.needed = false
+ if done then
+ current_format, current_graphic = mpsformat, prepared
+ metapost.process(mpsformat, {
+ preamble or "",
+ "beginfig(1); ",
+ "_trial_run_ := true ;",
+ prepared,
+ "endfig ;"
+ }, true ) -- true means: trialrun
+ if metapost.intermediate.needed then
+ for _, action in pairs(metapost.intermediate.actions) do
+ action()
+ end
+ end
+ sprint(tex.ctxcatcodes,"\\ctxlua{metapost.graphic_extra_pass()}")
+ else
+ metapost.process(mpsformat, {
+ preamble or "",
+ "beginfig(1); ",
+ "_trial_run_ := false ;",
+ str,
+ "endfig ;"
+ } )
+ end
+end
+
+function metapost.graphic_extra_pass()
+ metapost.textext_current = metapost.first_box
+ metapost.process(current_format, {
+ "beginfig(0); ",
+ "_trial_run_ := false ;",
+ join(metapost.text_texts_data()," ;\n"),
+ current_graphic,
+ "endfig ;"
+ })
+end
+
+function metapost.getclippath(data)
+ local mpx = metapost.format("metafun")
+ if mpx and data then
+ input.starttiming(metapost)
+ input.starttiming(metapost.exectime)
+ local result = mpx:execute(format("beginfig(1);%s;endfig;",data))
+ input.stoptiming(metapost.exectime)
+ if result.status > 0 then
+ print("error", result.status, result.error or result.term or result.log)
+ result = ""
+ else
+ result = metapost.filterclippath(result)
+ end
+ input.stoptiming(metapost)
+ sprint(result)
+ end
+end
+
+do -- not that beautiful but ok, we could save a md5 hash in the tui file !
+
+ local graphics = { }
+ local start = [[\starttext]]
+ local preamble = [[\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]]
+ local stop = [[\stoptext]]
+
+ function metapost.specials.gt(specification,object) -- number, so that we can reorder
+ graphics[#graphics+1] = format("\\MPLIBgraphictext{%s}",specification)
+ metapost.intermediate.needed = true
+ return { }, nil, nil, nil
+ end
+
+ function metapost.intermediate.actions.makempy()
+ if #graphics > 0 then
+ local mpofile = tex.jobname .. "-mp"
+ local mpyfile = file.replacesuffix(mpofile,"mpy")
+ local pdffile = file.replacesuffix(mpofile,"pdf")
+ local texfile = file.replacesuffix(mpofile,"tex")
+ io.savedata(texfile, { start, preamble, join(graphics,"\n"), stop }, "\n")
+ os.execute(format("context --once %s", texfile))
+ if io.exists(pdffile) then
+ os.execute(format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile))
+ local result = { }
+ if io.exists(mpyfile) then
+ local data = io.loaddata(mpyfile)
+ for figure in data:gmatch("beginfig(.-)endfig") do
+ result[#result+1] = format("begingraphictextfig%sendgraphictextfig ;\n", figure)
+ end
+ io.savedata(mpyfile,join(result,""))
+ end
+ end
+ graphics = { }
+ end
+ end
+
+end
diff --git a/tex/context/base/mlib-pps.tex b/tex/context/base/mlib-pps.tex
new file mode 100644
index 000000000..df325c316
--- /dev/null
+++ b/tex/context/base/mlib-pps.tex
@@ -0,0 +1,61 @@
+%D \module
+%D [ file=mlib-pps,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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
+
+\registerctxluafile{mlib-pps}{1.001}
+
+\def\MPLIBcircularshade#1#2#3#4#5#6#7% nr domain color-a color-b ? colorspace oordinates
+ {\immediate\pdfobj{<</FunctionType 2 /Domain [#2] /C0 [#3] /C1 [#4] /N #5>>}%
+ \immediate\pdfobj{<</ShadingType 3 /ColorSpace /#6 /Function \the\pdflastobj\space 0 R /Coords [#7] /Extend [true true]>>}%
+ \appendtoPDFdocumentshades{/MpSh#1 \the\pdflastobj\space0 R }}
+
+\def\MPLIBlinearshade#1#2#3#4#5#6#7% nr domain color-a color-b ? colorspace oordinates
+ {\immediate\pdfobj{<</FunctionType 2 /Domain [#2] /C0 [#3] /C1 [#4] /N #5>>}%
+ \immediate\pdfobj{<</ShadingType 2 /ColorSpace /#6 /Function \the\pdflastobj\space 0 R /Coords [#7] /Extend [true true]>>}%
+ \appendtoPDFdocumentshades{/MpSh#1 \the\pdflastobj\space0 R }}
+
+\def\MPLIBfigure#1#2#3#4#5#6#7% todo: move Q q to lua
+ {\setbox\scratchbox\hbox{\externalfigure[#7]}%
+ \ctxlua{metapost.edefsxsy(\number\wd\scratchbox,\number\ht\scratchbox,0)}%
+ \pdfliteral direct{q #1 #2 #3 #4 #5 #6 cm}% no direct
+ \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[sx=\sx,sy=\sy]{\box\scratchbox}\hss}}%
+ \pdfliteral direct{Q}}
+
+\def\MPLIBsettext#1% #2%
+ {\global\setbox#1\hbox}% {#2}}
+
+% \def\MPLIBgettext#1#2#3#4#5#6#7% we can also use this for the figure and pass sx/sy
+% {\ctxlua{metapost.edefsxsy(\number\wd#7,\number\ht#7,\number\dp#7)}%
+% \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}%
+% \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[sx=\sx,sy=\sy]{\raise\dp#7\box#7}\hss}}%
+% \pdfliteral{Q}}
+
+\def\MPLIBgettextscaled#1#2#3%
+ {\vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[sx=#2,sy=#3]{\raise\dp#1\box#1}\hss}}}
+
+\def\MPLIBallocate#1%
+ {\newbox\MPLIBfirst
+ \dorecurse{\numexpr#1-1\relax}{\newbox\MPLIBlast}%
+ \MPLIBregister}
+
+\def\MPLIBregister
+ {\ctxlua{metapost.first_box, metapost.last_box = \number\MPLIBfirst, \number\MPLIBlast}}
+
+\appendtoks \MPLIBallocate{500}\to \everydump
+\appendtoks \MPLIBregister \to \everyjob
+
+\def\MPLIBgraphictext#1%
+ {\startTEXpage[scale=10000]#1\stopTEXpage}
+
+\protect \endinput
diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua
new file mode 100644
index 000000000..aac7e030e
--- /dev/null
+++ b/tex/context/base/mlib-run.lua
@@ -0,0 +1,219 @@
+if not modules then modules = { } end modules ['mlib-run'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+--~ cmyk -> done, native
+--~ spot -> done, but needs reworking (simpler)
+--~ multitone ->
+--~ shade -> partly done, todo: cm
+--~ figure -> done
+--~ hyperlink -> low priority, easy
+
+-- new * run
+-- or
+-- new * execute^1 * finish
+
+-- a*[b,c] == b + a * (c-b)
+
+--[[ldx--
+<p>The directional helpers and pen analysis are more or less translated from the
+<l n='c'/> code. It really helps that Taco know that source so well. Taco and I spent
+quite some time on speeding up the <l n='lua'/> and <l n='c'/> code. There is not
+much to gain, especially if on ekeeps in mind that when integrated in <l n='tex'/>
+only a part of the time is spent in <l n='metapost'/>. Of course an integrated
+approach is way faster than an external <l n='metapost'/> and processing time
+nears zero.</p>
+--ldx]]--
+
+local format = string.format
+
+metapost = metapost or { }
+
+local function finder(name, mode, ftype)
+ if mode=="w" then
+ return name
+ elseif input.aux.qualified_path(name) then
+ return name
+ else
+ return input.find_file((texmf and texmf.instance) or instance,name,ftype)
+ end
+end
+
+metapost.finder = finder
+
+--~ statistics = {
+--~ ["hash_size"]=1774,
+--~ ["main_memory"]=50237,
+--~ ["max_in_open"]=5,
+--~ ["param_size"]=4,
+--~ }
+
+metapost.parameters = {
+ hash_size = 100000,
+ main_memory = 2000000,
+ max_in_open = 50,
+ param_size = 100000,
+}
+
+metapost.exectime = metapost.exectime or { } -- hack
+
+function metapost.make(name, target, version)
+ input.starttiming(mplib)
+ target = file.replacesuffix(target or name, "mem")
+ local mpx = mplib.new ( table.merged (
+ metapost.parameters,
+ {
+ ini_version = true,
+ find_file = finder,
+ job_name = file.stripsuffix(target),
+ }
+ ) )
+ if mpx then
+ input.starttiming(metapost.exectime)
+ local result = mpx:execute(format('\\ ; boolean mplib ; mplib := true ; string mp_parent_version ; mp_parent_version := "%s" ; show mp_parent_version ; input %s ;', version or "unknown", name))
+ input.stoptiming(metapost.exectime)
+ if mpx then
+ mpx:finish()
+ end
+ end
+ input.stoptiming(mplib)
+ return mpx -- mpx = nil will free memory
+end
+
+function metapost.load(name)
+ input.starttiming(mplib)
+ local mpx = mplib.new ( table.merged (
+ metapost.parameters,
+ {
+ mem_name = file.replacesuffix(name,"mem"),
+ find_file = finder,
+ }
+ ) )
+ if mpx then
+ input.starttiming(metapost.exectime)
+ mpx:execute("\\")
+ input.stoptiming(metapost.exectime)
+ end
+ input.stoptiming(mplib)
+ return mpx
+end
+
+function metapost.unload(mpx)
+ input.starttiming(mplib)
+ if mpx then
+ mpx:finish()
+ end
+ input.stoptiming(mplib)
+end
+
+function metapost.checkformat(mpsinput, mpsformat)
+ mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
+ mpsformat = file.stripsuffix(file.basename(mpsformat or texconfig.formatname or tex.formatname or mpsinput))
+ local mpsbase = file.stripsuffix(file.basename(mpsinput))
+ if mpsbase ~= mpsformat then
+ mpsformat = mpsformat .. "-" .. mpsbase
+ end
+ mpsformat = file.addsuffix(mpsformat, "mem")
+ local pth = file.dirname(texconfig.formatname or "")
+ if pth ~= "" then
+ mpsformat = file.join(pth,mpsformat)
+ end
+ local the_version = environment.version or "unset version"
+ if io.exists(mpsformat) then
+ commands.writestatus("mplib", format("loading format: %s, name: %s", mpsinput, mpsformat))
+ local mpx = metapost.load(mpsformat)
+ if mpx then
+ local result = mpx:execute(format("show mp_parent_version ;"))
+ local version = result.log:match(">> *(.-)[\n\r]") or "unknown"
+ version = version:gsub("[\'\"]","")
+ if version ~= the_version then
+ commands.writestatus("mplib", format("version mismatch: %s <> %s", version or "unknown", the_version))
+ else
+ return mpx
+ end
+ end
+ end
+ commands.writestatus("mplib", format("making format: %s, name: %s", mpsinput, mpsformat))
+ metapost.make(mpsinput,mpsformat,the_version) -- somehow return ... fails here
+ if io.exists(mpsformat) then
+ commands.writestatus("mplib", format("loading format: %s, name: %s", mpsinput, mpsformat))
+ return metapost.load(mpsformat)
+ else
+ commands.writestatus("mplib", format("problems with format: %s, name: %s", mpsinput, mpsformat))
+ end
+end
+
+--~ if environment.initex then
+--~ metapost.unload(metapost.checkformat("metafun"))
+--~ end
+
+local mpxformats = {}
+
+function metapost.format(name)
+ local mpx = mpxformats[name]
+ if not mpx then
+ mpx = metapost.checkformat(name)
+ mpxformats[name] = mpx
+ end
+ return mpx
+end
+
+function metapost.process(mpx, data, trialrun, showlog)
+ local result
+ if type(mpx) == "string" then
+ mpx = metapost.format(mpx) -- goody
+ end
+ if mpx and data then
+ input.starttiming(metapost)
+ if type(data) == "table" then
+ for i=1,#data do
+ local d = data[i]
+ if d then
+ input.starttiming(metapost.exectime)
+ result = mpx:execute(d)
+--~ print(">>>",d)
+ input.stoptiming(metapost.exectime)
+ if not result then
+ metapost.report("error", "no result object returned")
+ elseif result.status > 0 then
+ metapost.report("error",result.error or result.term or result.log or "unknown")
+ elseif showlog then
+ metapost.report("info",result.term or "unknown")
+ elseif result.fig then
+ metapost.convert(result, trialrun)
+ end
+ else
+ metapost.report("error", "invalid graphic component " .. i)
+ end
+ end
+ else
+ input.starttiming(metapost.exectime)
+ result = mpx:execute(data)
+ input.stoptiming(metapost.exectime)
+--~ print(">>>",data)
+ if not result then
+ metapost.report("error", "no result object returned")
+ elseif result.status > 0 then
+ metapost.report("error",result.error or result.term or result.log or "unknown")
+ elseif showlog then
+ metapost.report("info",result.term or "unknown")
+ elseif result.fig then
+ metapost.convert(result, trialrun)
+ end
+ end
+ input.stoptiming(metapost)
+ end
+ return result
+end
+
+function metapost.convert(result, trialrun)
+ metapost.report('Warning','no converter set')
+end
+
+function metapost.report(...)
+ logs.report(...)
+end
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 195c604d2..76cbe3b76 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -321,6 +321,7 @@ end
-- node-gly.lua
if not fonts then fonts = { } end
+if not fonts.otf then fonts.otf = { } end
if not fonts.tfm then fonts.tfm = { } end
if not fonts.tfm.id then fonts.tfm.id = { } end
@@ -761,17 +762,17 @@ do
local v = root[k]
local t = type(v)
if t == "number" then
-if v == 0 then
- -- skip
-else
- handle(("%s %s=%s,"):format(depth,key(k),v))
-end
+ if v == 0 then
+ -- skip
+ else
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ end
elseif t == "string" then
-if v == "" then
- -- skip
-else
- handle(("%s %s=%q,"):format(depth,key(k),v))
-end
+ if v == "" then
+ -- skip
+ else
+ handle(("%s %s=%q,"):format(depth,key(k),v))
+ end
elseif v then -- userdata or table
serialize(v,k,handle,depth,m+1)
end
diff --git a/tex/context/base/page-num.tex b/tex/context/base/page-num.tex
index 374cf89ef..404974f82 100644
--- a/tex/context/base/page-num.tex
+++ b/tex/context/base/page-num.tex
@@ -117,7 +117,7 @@
\global\resettingsubpagenumberfalse
\fi
\ifsubpaging
- \edef\oldsubpage{\the\subpageno}%
+ \xdef\oldsubpage{\the\subpageno}%
\incrementnumber[\s!subpage]%
\global\subpageno\rawnumber[\s!subpage]\relax
\ifnum\subpageno=\plusone
diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex
index 6d984ca31..f7665177d 100644
--- a/tex/context/base/s-abr-01.tex
+++ b/tex/context/base/s-abr-01.tex
@@ -28,6 +28,7 @@
%logo [FGBBS] {fgbbs}
\logo [ACROBAT] {Acro\-bat}
\logo [AFM] {afm}
+\logo [API] {api}
\logo [ALEPH] {Aleph} % {\mathematics{\aleph}}
\logo [ALGOL] {ALGOL}
\logo [AMS] {ams}
@@ -45,6 +46,7 @@
\logo [CCODE] {c}
\logo [CALCMATH] {CalcMath}
\logo [CD] {cd}
+\logo [CPU] {cpu}
\logo [CDROM] {cdrom}
\logo [CID] {cid}
\logo [CJK] {cjk}
diff --git a/tex/context/base/s-map-10.tex b/tex/context/base/s-map-10.tex
index ec7ef6128..362aa2700 100644
--- a/tex/context/base/s-map-10.tex
+++ b/tex/context/base/s-map-10.tex
@@ -385,9 +385,13 @@
\advance \rightskip 0pt plus 2em
\MapsSubTitle\par}
\fi
- \blank[30pt]
+ \doifmodeelse{newstyle}
+ {\blank[22pt]}
+ {\blank[30pt]}
\egroup
\switchtobodyfont[rm,10pt]
+ \doifmode{newstyle}
+ {\noindent\MapsAuthor\blank[line]}
\setupalign[width]
\ifMapsInColumns
\startcolumns\hyphenpenalty1000
diff --git a/tex/context/base/s-sys-01.tex b/tex/context/base/s-sys-01.tex
index f695bd618..b982be649 100644
--- a/tex/context/base/s-sys-01.tex
+++ b/tex/context/base/s-sys-01.tex
@@ -1,5 +1,18 @@
% engine=luatex
+%D \module
+%D [ file=s-sys-01,
+%D version=2008.03.32,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Generate List of Math Symbol,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
\startluacode
function showmath()
local slots = mathematics.slots.traditional
diff --git a/tex/context/base/spec-dpx.tex b/tex/context/base/spec-dpx.tex
index d8ec1e518..6c4d8e447 100644
--- a/tex/context/base/spec-dpx.tex
+++ b/tex/context/base/spec-dpx.tex
@@ -219,7 +219,7 @@
\def\dopresetPDFtransparency#1#2%
{\global\advance\PDFcurrenttransparency \plusone
- \doPDFreserveDPXobject{TR:\the\PDFcurrenttransparency}{<< >>}%
+ \doPDFreserveDPXobject{TR:\the\PDFcurrenttransparency}{<< >>}% hack
\special{pdf:\doPDFcheckedDPXobject{TR:\the\PDFcurrenttransparency}\PDFtransparancydictionary{#1}{#2}{}}%
\edef\PDFtransparencyidentifier{/Tr\the\PDFcurrenttransparency}%
\edef\PDFtransparencyreference {@TR:\the\PDFcurrenttransparency}%
@@ -230,7 +230,7 @@
\PDFtransparencyreference\space}}
\def\initializePDFtransparency
- {\doPDFreserveDPXobject{TR:0}{<< >>}%
+ {\doPDFreserveDPXobject{TR:0}{<< >>}% hack
\special{pdf:\doPDFcheckedDPXobject{TR:0}\PDFtransparancydictionary{1}{1}{/AIS false}}%
\xdef\PDFtransparencyresetidentifier{/Tr0}%
\xdef\PDFtransparencyresetreference{@TR:0}%
@@ -393,10 +393,10 @@
\global\let\currentPDFresources\empty
\fi
\special{pdf:exobj}}%
- \finalizeobjectbox\nextbox
- \smashbox\nextbox
- \flushatshipout{\box\nextbox}%
- \egroup}%
+ \finalizeobjectbox\nextbox
+ \smashbox\nextbox
+ \flushatshipout{\box\nextbox}%
+ \egroup}%
\hbox\bgroup}
\def\doDVIPDFMXstopobject
@@ -623,9 +623,24 @@
\def\doPDFcheckedDPXobject#1{\ifundefined{r:pdx:d:#1}object\else put\fi\space @#1\space}
-% todo when etex is fixed, \everyPDFpresets, leeg voor pdftex, nodig voor dvipdfmx
+% new, experimental, can save a run
-\doPDFreserveDPXobjectfirst{FDF::docuextgstates}{<< >>}
+\def\doreservePDFobject#1#2%
+ {\dosetobjectreference{#1}{#2}{@#1::#2}}
+
+\def\doPDFreserveddictionaryobject#1#2#3%
+ {\flushatshipout{\special{pdf:object @#1::#2 << #3 >>}}}
+
+\def\doPDFreservedarrayobject#1#2#3%
+ {\flushatshipout{\special{pdf:object @#1::#2 [ #3 ]}}}
+
+% maybe this is not needed
+
+\doreservePDFobject{FDF}{docuextgstates}
+\doreservePDFobject{FDF}{colorspaces}
+\doreservePDFobject{FDF}{docushades}
+
+% so this is to be checked
\def\doPDFdictionaryobject#1#2#3%
{\flushatshipout
diff --git a/tex/context/base/spec-fdf.tex b/tex/context/base/spec-fdf.tex
index f55cff7a7..0e7c62ec4 100644
--- a/tex/context/base/spec-fdf.tex
+++ b/tex/context/base/spec-fdf.tex
@@ -177,7 +177,8 @@
\def\checkPDFextgstates
{\ifx\docuPDFextgstates\empty \else
\ifnum\realpageno=\lastpage\relax
- \doPDFdictionaryobject{FDF}{docuextgstates}{\docuPDFextgstates}%
+ %\doreservePDFobject{FDF}{docuextgstates}%
+ \doPDFreserveddictionaryobject{FDF}{docuextgstates}{\docuPDFextgstates}%
\fi
\doPDFgetobjectreference{FDF}{docuextgstates}\PDFobjectreference
\doPDFpageresource{/ExtGState \PDFobjectreference}%
@@ -219,7 +220,8 @@
\def\checkPDFcolorspaces
{\ifx\docuPDFcolorspaces\empty \else
\ifnum\realpageno=\lastpage\relax
- \doPDFdictionaryobject{FDF}{colorspaces}{\docuPDFcolorspaces}%
+ %\doreservePDFobject{FDF}{colorspaces}%
+ \doPDFreserveddictionaryobject{FDF}{colorspaces}{\docuPDFcolorspaces}%
\fi
\doPDFgetobjectreference{FDF}{colorspaces}\PDFobjectreference
\doPDFpageresource{/ColorSpace \PDFobjectreference}%
@@ -239,7 +241,8 @@
\def\checkPDFshades
{\ifx\docuPDFshades\empty \else
\ifnum\realpageno=\lastpage\relax
- \doPDFdictionaryobject{FDF}{docushades}{\docuPDFshades}%
+ %\doreservePDFobject{FDF}{docushades}%
+ \doPDFreserveddictionaryobject{FDF}{docushades}{\docuPDFshades}%
\fi
\doPDFgetobjectreference{FDF}{docushades}\PDFobjectreference
\doPDFpageresource{/Shading \PDFobjectreference}%
diff --git a/tex/context/base/spec-tpd.tex b/tex/context/base/spec-tpd.tex
index d2a1d73a7..65fbcb06a 100644
--- a/tex/context/base/spec-tpd.tex
+++ b/tex/context/base/spec-tpd.tex
@@ -1256,6 +1256,10 @@
{\doPDFgetobjectnumber{#1}{#2}\PDFobjectnumber
\immediate\pdfobj useobjnum \PDFobjectnumber {[ #3 ]}}
+\doreservePDFobject{FDF}{docuextgstates}
+\doreservePDFobject{FDF}{colorspaces}
+\doreservePDFobject{FDF}{docushades}
+
%D \macros
%D {defaultobjectreference,doPDFgetobjectreference}
%D
diff --git a/tex/context/base/supp-box.tex b/tex/context/base/supp-box.tex
index 09c390309..1ba55b21e 100644
--- a/tex/context/base/supp-box.tex
+++ b/tex/context/base/supp-box.tex
@@ -1565,8 +1565,9 @@
\def\processisolatedwords##1##2{##2{##1}}% we split only once
\fi
\global\let\localbetweenisolatedwords\betweenisolatedwords
- \setbox0\normalhbox % we default to spaces, but from inside out
- {\ignorespaces#1% \localbetweenisolatedwords can be overruled
+ \setbox0\normalhbox % we default to spaces, but from inside out
+ {\normallanguage\minusone % needed for mkiv
+ \ignorespaces#1% \localbetweenisolatedwords can be overruled
\global\isolatedlastskip\lastskip}%
\setbox2\normalvbox
{%\hyphenpenalty10000 % this one fails in \url breaking,
diff --git a/tex/context/base/supp-mps.tex b/tex/context/base/supp-mps.tex
index 145681489..6b3cea88c 100644
--- a/tex/context/base/supp-mps.tex
+++ b/tex/context/base/supp-mps.tex
@@ -514,7 +514,7 @@
\newtoks\MPTEXgraphicchecks
\long\def\writecheckedMPgraphic#1%
- {\ifforceMPTEXgraphic
+ {\ifgrTEXgraphic
\global\MPTEXgraphictrue
\else
\global\MPTEXgraphicfalse
diff --git a/tex/context/base/supp-tpi.tex b/tex/context/base/supp-tpi.tex
index 2feeeac18..dc9d2e0e5 100644
--- a/tex/context/base/supp-tpi.tex
+++ b/tex/context/base/supp-tpi.tex
@@ -8,8 +8,8 @@
%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
%D This modules implements the conversion of graphic \TPIC\
%D specials using \METAPOST.
@@ -19,6 +19,8 @@
%D \type{supp-spe} as well as the \METAPOST\ run||time support
%D implemented in \type{supp-mps}.
+\beginLUATEX \endinput \endLUATEX % to be sure, we don't want to load the following
+
\ifx\undefined\writestatus \input supp-mis \relax \fi
\ifx\undefined\mimmickspecials \input supp-spe \relax \fi
\ifx\undefined\MPgraphicbox \input supp-mps \relax \fi
@@ -128,10 +130,10 @@
%D variable {\it currentpicture}, around the $x$-axis.
\def\stopTPICspecials
- {\startMPdrawing
+ {\startMPdrawing
currentpicture:=currentpicture reflectedabout ((0,0),(4095,0));
\stopMPdrawing
- \MPdrawingdonetrue
+ \MPdrawingdonetrue
\setbox\MPgraphicbox\hbox
{\getMPdrawing}%
\setbox\MPgraphicbox\hbox to \zeropoint
@@ -193,7 +195,7 @@
{\startTPICspecials
\bgroup
\dimen0=#1pt \dimen0=.07227\dimen0
- \startMPdrawing
+ \startMPdrawing
pickup pencircle scaled \the\dimen0;
\stopMPdrawing
\egroup}
@@ -271,7 +273,7 @@
\ifTPICdraw
\def\TPICgrayscale{}%
\fi
- \startMPdrawing
+ \startMPdrawing
\ifTPICfill fill\fi\ifTPICdraw draw\fi\space
for i:=1 upto \the\TPICcounter-1:
p[i]\ifTPICcurve..\else--\fi
diff --git a/tex/context/base/symb-was.tex b/tex/context/base/symb-was.tex
index ba2617306..d6c324864 100644
--- a/tex/context/base/symb-was.tex
+++ b/tex/context/base/symb-was.tex
@@ -136,7 +136,7 @@
\definesymbol [RIGHTarrow] [\WaldiSymbol {17}]
\definesymbol [UParrow] [\WaldiSymbol {75}]
\definesymbol [DOWNarrow] [\WaldiSymbol {76}]
- \definesymbol [Box] [\WaldiSymbol {32}]
+ \definesymbol [Box] [\WaldiSymbol {50}]
\definesymbol [APLbox] [\WaldiSymbol{126}]
\definesymbol [XBox] [\WaldiSymbol {52}]
\definesymbol [Bowtie] [\WaldiSymbol {49}]
diff --git a/tex/context/base/syst-cat.tex b/tex/context/base/syst-cat.tex
index e101bd78c..5f75ea2e7 100644
--- a/tex/context/base/syst-cat.tex
+++ b/tex/context/base/syst-cat.tex
@@ -410,7 +410,6 @@
%D \macros
%D {installactivecharacter}
-
\def\installactivecharacter#1 %
{\edef\temp{\detokenize{#1}}%
\cctcounterc\expandafter`\temp\relax % relax needed
diff --git a/tex/context/base/syst-etx.tex b/tex/context/base/syst-etx.tex
index 5d7ab9a65..13163a681 100644
--- a/tex/context/base/syst-etx.tex
+++ b/tex/context/base/syst-etx.tex
@@ -230,7 +230,7 @@
%D are needed, but, for critical editions, we may need many
%D more, so:
-\chardef\@@insallocation = 32
+\chardef\@@insallocation = 32
%D However, there's a bug in \ETEX\ versions smaller than 2.2,
%D so we need to play safe:
diff --git a/tex/context/base/syst-gen.tex b/tex/context/base/syst-gen.tex
index 739e0ed50..02d238a31 100644
--- a/tex/context/base/syst-gen.tex
+++ b/tex/context/base/syst-gen.tex
@@ -168,7 +168,7 @@
%D nesting deeper than one level, the system shows the
%D protection level.
-\newcount\protectionlevel
+\ifx\protectionlevel\undefined \newcount\protectionlevel \fi
\ifx\protect\undefined
\def\protect{\writestatus{protection}{too much protection}}
diff --git a/tex/context/base/syst-mtx.tex b/tex/context/base/syst-mtx.tex
index 0abd89e57..e2a978671 100644
--- a/tex/context/base/syst-mtx.tex
+++ b/tex/context/base/syst-mtx.tex
@@ -50,7 +50,7 @@
\mathchardef\@@minallocation = 16
\mathchardef\@@medallocation = 256
\mathchardef\@@maxallocation = 32767
-\chardef \@@insallocation = 32
+\chardef \@@insallocation = 128 % was 32, but if we want continuous ranges (mplib) we need to pass 256 soon 32
\def\myalloc@#1#2#3#4#5%
{\global\advance\count1#1by\@ne
diff --git a/tex/context/base/type-gyr.tex b/tex/context/base/type-gyr.tex
index 01d5c8202..80b391f77 100644
--- a/tex/context/base/type-gyr.tex
+++ b/tex/context/base/type-gyr.tex
@@ -11,6 +11,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% \beginNEWTEX already-otf-gyre
+% \endinput
+% \endNEWTEX
+
%D These definitions will eventually replace the ones in \type {type-one}!
% \usetypescriptfile[type-gyr]
diff --git a/tex/context/base/type-otf.tex b/tex/context/base/type-otf.tex
index 2b0a3dbdc..0449be878 100644
--- a/tex/context/base/type-otf.tex
+++ b/tex/context/base/type-otf.tex
@@ -131,13 +131,13 @@
\definefontsynonym [LMRoman12-Oblique] [file:lmromanslant12-regular][features=default]
\definefontsynonym [LMRoman17-Oblique] [file:lmromanslant17-regular][features=default]
\definefontsynonym [LMRoman10-BoldOblique] [file:lmromanslant10-bold] [features=default]
- \definefontsynonym [LMRoman10-Demi] [file:lmromandemi10-oblique] [features=default]
- \definefontsynonym [LMRoman10-DemiOblique] [file:lmromandemi10-regular] [features=default]
- \definefontsynonym [LMRoman10-CapsRegular] [file:lmromancaps10-oblique] [features=default] % features=smallcaps?
- \definefontsynonym [LMRoman10-CapsOblique] [file:lmromancaps10-regular] [features=default]
+ \definefontsynonym [LMRoman10-Demi] [file:lmromandemi10-regular] [features=default]
+ \definefontsynonym [LMRoman10-DemiOblique] [file:lmromandemi10-oblique] [features=default]
+ \definefontsynonym [LMRoman10-CapsRegular] [file:lmromancaps10-regular] [features=default] % features=smallcaps?
+ \definefontsynonym [LMRoman10-CapsOblique] [file:lmromancaps10-oblique] [features=default]
- \definefontsynonym [LMRoman10-Dunhill] [file:lmromandunh10-oblique] [features=default]
- \definefontsynonym [LMRoman10-DunhillOblique] [file:lmromandunh10-regular] [features=default]
+ \definefontsynonym [LMRoman10-Dunhill] [file:lmromandunh10-regular] [features=default]
+ \definefontsynonym [LMRoman10-DunhillOblique] [file:lmromandunh10-oblique] [features=default]
\definefontsynonym [LMRoman10-Unslanted] [file:lmromanunsl10-regular] [features=default]
\stoptypescript
@@ -298,16 +298,16 @@
\definetypescriptprefix [n:chorus] [TeXGyreChorus] \definetypescriptprefix [f:chorus] [chorus] % not the full set
\starttypescript [serif] [adventor,bonum,cursor,heros,pagella,schola,termes]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Slanted] [\typescriptprefix{n:\typescripttwo}-Italic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldSlanted] [\typescriptprefix{n:\typescripttwo}-BoldItalic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Slanted] [\typescriptprefix{n:\typescripttwo}-Italic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldSlanted] [\typescriptprefix{n:\typescripttwo}-BoldItalic] [features=default]
\stoptypescript
\starttypescript [serif] [pagella,termes,bonum,schola,chorus] [name]
diff --git a/tex/context/base/x-cals.mkiv b/tex/context/base/x-cals.mkiv
index 5d4a9b573..eba39cf64 100644
--- a/tex/context/base/x-cals.mkiv
+++ b/tex/context/base/x-cals.mkiv
@@ -19,6 +19,11 @@ do
lxml.cals = { }
lxml.cals.ignore_widths = false
+ local format = string.format
+ local texsprint = tex.sprint
+ local xmlsprint = xml.sprint
+ local xmlcprint = xml.cprint
+
local halignments = {
left = "flushleft",
right = "flushright",
@@ -65,26 +70,24 @@ do
end
end
- local texsprint = tex.sprint
- local xmlsprint = xml.sprint
-
--local function texsprint(a,b) print(b) end
--local function xmlsprint(a) print(a) end
function lxml.cals.table(root,namespace)
local prefix = (namespace or "cals") .. ":"
-
- local tgroupspec = "/" .. prefix .. "tgroup"
- local colspec = "/" .. prefix .. "colspec"
- local spanspec = "/" .. prefix .. "spanspec"
- local hcolspec = "/" .. prefix .. "thead" .. "/" ..prefix .. "colspec"
- local bcolspec = "/" .. prefix .. "tbody" .. "/" ..prefix .. "colspec"
- local fcolspec = "/" .. prefix .. "tfoot" .. "/" ..prefix .. "colspec"
- local entryspec = "/" .. prefix .. "entry" .. "|" ..prefix .. "entrytbl"
- local hrowspec = "/" .. prefix .. "thead" .. "/" ..prefix .. "row"
- local browspec = "/" .. prefix .. "tbody" .. "/" ..prefix .. "row"
- local frowspec = "/" .. prefix .. "tfoot" .. "/" ..prefix .. "row"
+ local p = "/" .. prefix
+
+ local tgroupspec = p .. "tgroup"
+ local colspec = p .. "colspec"
+ local spanspec = p .. "spanspec"
+ local hcolspec = p .. "thead" .. p .. "colspec"
+ local bcolspec = p .. "tbody" .. p .. "colspec"
+ local fcolspec = p .. "tfoot" .. p .. "colspec"
+ local entryspec = p .. "entry" .. "|" ..prefix .. "entrytbl"
+ local hrowspec = p .. "thead" .. p .. "row"
+ local browspec = p .. "tbody" .. p .. "row"
+ local frowspec = p .. "tfoot" .. p .. "row"
local function tablepart(root, xcolspec, xrowspec, before, after)
texsprint(tex.ctxcatcodes,before)
@@ -122,13 +125,13 @@ do
end
local width = widths[col]
if s or m or halign or valign or width then
- texsprint(tex.ctxcatcodes,string.format("\\bTD[nx=%s,ny=%s,align={%s,%s},width=%s]",
+ texsprint(tex.ctxcatcodes,format("\\bTD[nx=%s,ny=%s,align={%s,%s},width=%s]",
s or 1, (m or 0)+1, halign or "flushleft", valign or "high", width or "fit"))
else
texsprint(tex.ctxcatcodes,"\\bTD")
end
- -- xmlsprint(xml.content(dk))
- xmlsprint(dk)
+ -- xmlsprint(dk)
+ xmlcprint(dk)
texsprint(tex.ctxcatcodes,"\\eTD")
col = col + (s or 1)
end
@@ -140,7 +143,6 @@ do
for r, d, k in xml.elements(lxml.id(root),tgroupspec) do
local tgroup = d[k]
--- print(tgroupspec,"!!!!!!!!!!!!!!!!!", r, d, k)
lxml.directives.before(root,"cdx") -- "cals:table"
texsprint(tex.ctxcatcodes, "\\bgroup")
lxml.directives.setup(root,"cdx") -- "cals:table"
diff --git a/tex/context/base/x-mml.mkiv b/tex/context/base/x-mml.mkiv
index 8cbf07f08..ee042d010 100644
--- a/tex/context/base/x-mml.mkiv
+++ b/tex/context/base/x-mml.mkiv
@@ -26,7 +26,6 @@
% \xmlregistersetup{xml:mml:process}
-
\startxmlsetups xml:mml:process
% \xmlutfize {\xmldocument}
\xmlgrab {\xmldocument} {mml:*} {*}
diff --git a/tex/context/base/x-mmp.mkiv b/tex/context/base/x-mmp.mkiv
index 7b96b0d30..32bf4671c 100644
--- a/tex/context/base/x-mmp.mkiv
+++ b/tex/context/base/x-mmp.mkiv
@@ -14,15 +14,21 @@
% -- ignored: malignmark
% -- luacode will be moved to x-mmp.lua
+% \defineXMLentity[textspace] {\enspace}
+% \defineXMLentity[textcomma] {{,}}
+% \defineXMLentity[textperiod] {{.}}
+
\startluacode
do
lxml.mml = lxml.mml or { }
+ local texsprint = tex.sprint
+
local replacements = {
- [" "] = "&textspace;",
- ["."] = "&textperiod;",
- [","] = "&textcomma;",
+-- [" "] = utf.char(0x2002), -- "&textspace;" -> tricky, no &; in mkiv
+-- ["."] = "{.}",
+-- [","] = "{,}",
}
local reppattern = "([ %.%,])"
@@ -31,7 +37,7 @@
local str = xml.content(lxml.id(id),pattern) or ""
str = str:gsub("^%s*(.-)%s*$","%1")
str = str:gsub(reppattern,replacements)
- tex.sprint(str)
+ texsprint(str)
end
function lxml.mml.connect(id,pattern,separators)
@@ -42,14 +48,14 @@
lxml.all(id,pattern)
else
local t = { }
- for s in unicode.utf8.gmatch(separators,"([^%s])") do
+ for s in utf.gmatch(separators,"([^%s])") do
t[#t+1] = s
end
for i=1,n do
if i > 1 then
- tex.sprint(tex.ctxcatcodes,"{")
- tex.sprint(t[i] or t[#t] or "")
- tex.sprint(tex.ctxcatcodes,"}")
+ texsprint(tex.ctxcatcodes,"{")
+ texsprint(t[i] or t[#t] or "")
+ texsprint(tex.ctxcatcodes,"}")
end
lxml.idx(id,pattern,i) -- kind of slow, some day ...
end
@@ -57,21 +63,21 @@
end
local function flush(e,tag,toggle)
- -- tex.sprint(tex.ctxcatcodes,(toggle and "^{") or "_{")
+ -- texsprint(tex.ctxcatcodes,(toggle and "^{") or "_{")
if toggle then
- tex.sprint(tex.ctxcatcodes,"^{")
+ texsprint(tex.ctxcatcodes,"^{")
else
- tex.sprint(tex.ctxcatcodes,"_{")
+ texsprint(tex.ctxcatcodes,"_{")
end
if tag == "none" then
- tex.sprint(tex.ctxcatcodes,"{}")
+ texsprint(tex.ctxcatcodes,"{}")
else
xml.sprint(e.dt)
end
if not toggle then
- tex.sprint(tex.ctxcatcodes,"}")
+ texsprint(tex.ctxcatcodes,"}")
else
- tex.sprint(tex.ctxcatcodes,"}{}")
+ texsprint(tex.ctxcatcodes,"}{}")
end
return not toggle
end
@@ -84,7 +90,7 @@
local e = d[k]
local tag = e.tg
if tag == "mprescripts" then
- tex.sprint(tex.ctxcatcodes,"{}")
+ texsprint(tex.ctxcatcodes,"{}")
done = true
elseif done then
toggle = flush(e,tag,toggle)
@@ -172,12 +178,11 @@
% setups
-\defineXMLentity[textspace] {\enspace}
-\defineXMLentity[textcomma] {{,}}
-\defineXMLentity[textperiod] {{.}}
+% \defineXMLentity[_] {{\_{}}}
+% \defineXMLentity[^] {{\^{}}}
-\defineXMLentity[_] {{\_}}
-\defineXMLentity[^] {{\^}}
+% \defineXMLentity[_] {\string_}
+% \defineXMLentity[^] {\normalorfiller\hat\widehat}
\startsetups mml:semantics % todo: width=ex/ex/pt
\xmlflush{#1}
@@ -193,12 +198,16 @@
\stopxmlsetups
\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground
- % function and style
\begingroup
\rm \ctxlua{lxml.mml.prepare_number("#1","*")}
\endgroup
\stopxmlsetups
+\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground
+ \mathop{\hbox{\mr \ctxlua{lxml.mml.prepare_number("#1","*")}}}% we need . and , properly spaced
+\stopxmlsetups
+
+
\startxmlsetups mml:mo
\edef\MMPoperator{\xmlstripped{#1}{*}}
\doifXMLentityelse{\detokenize\expandafter{\MMPoperator}} {
@@ -332,15 +341,49 @@
{\xmlindex{#1}{/*}{1}}_{\xmlindex{#1}{/*}{2}}^{\xmlindex{#1}{/*}{3}}
\stopsetups
+% \startsetups mml:mover
+% \mathop {
+% \doifelse{\xmlatt{#1}{accent}}{true} {
+% \begingroup
+% \xmldoif{#1}{/*[position()==2 and @stretchy=='true']} {
+% \let\normalorfiller\secondoftwoarguments
+% }
+% \xmlindex{#1}{/*}{2}{\xmlindex{#1}{/*}{1}}
+% \endgroup
+% } {
+% \vbox {
+% \m@th\ialign {
+% \hss##\hss\crcr
+% \noalign{\kern3\p@}%
+% \disabledelimiter\doMMLfiller{\xmlindex{#1}{/*}{2}}\crcr
+% \noalign{\kern3\p@\nointerlineskip}%
+% \disabledelimiter\doMMLfiller{\xmlindex{#1}{/*}{1}}\crcr
+% }
+% }
+% }
+% }
+% \limits
+% \stopsetups
+
+
\startsetups mml:mover
\mathop {
- \vbox {
- \m@th\ialign {
- \hss##\hss\crcr
- \noalign{\kern3\p@}%
- \disabledelimiter\doMMLfiller{\xmlindex{#1}{/*}{2}}\crcr
- \noalign{\kern3\p@\nointerlineskip}%
- \disabledelimiter\doMMLfiller{\xmlindex{#1}{/*}{1}}\crcr
+ \edef\mmlovertoken{\xmlraw{#1}{/mml:mo[position()==2]}}
+ \doifelse{\utfmathclass\mmlovertoken}{accent} {
+ \utfmathcommand\mmlovertoken{\xmlindex{#1}{/*}{1}}
+ } {
+ \vbox {
+ \m@th\ialign {
+ \hss##\hss\crcr
+ \noalign{\kern3\p@}%
+ \disabledelimiter\doMMLfiller{
+ \xmlindex{#1}{/*}{2}
+ }\crcr
+ \noalign{\kern3\p@\nointerlineskip}%
+ \disabledelimiter\doMMLfiller{
+ \xmlindex{#1}{/*}{1}
+ }\crcr
+ }
}
}
}
@@ -363,9 +406,15 @@
\stopsetups
\startsetups mml:munderover
- \xmlindex{#1}{/*}{1}
- _{\disablefiller\disabledelimiter\xmlindex{#1}{/*}{2}}
- ^{\disablefiller\disabledelimiter\xmlindex{#1}{/*}{3}}
+ \edef\mmlunderovertoken{\xmlraw{#1}{/mml:mo[position()==1]}}
+% \doifelse{\utfmathclass\mmlunderovertoken}{limop} {
+% \utfmathcommand\mmlunderovertoken
+% } {
+% \xmlindex{#1}{/*}{1}
+% {
+ \utfmathcommanddefault\mmlunderovertoken{xmlindex}{{#1}{/*}{1}}
+ _{\disablefiller\disabledelimiter\xmlindex{#1}{/*}{2}}
+ ^{\disablefiller\disabledelimiter\xmlindex{#1}{/*}{3}}
\stopsetups
\startxmlsetups mml:mlabeledtr
diff --git a/tex/context/base/xtag-ent.tex b/tex/context/base/xtag-ent.tex
index 83f1b1139..a34fbab28 100644
--- a/tex/context/base/xtag-ent.tex
+++ b/tex/context/base/xtag-ent.tex
@@ -11,15 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% Here we also define fallbacks
-
-\defineXMLentities [tex] {tex} {\TeX}
-\defineXMLentities [latex] {latex} {\LaTeX}
-\defineXMLentities [context] {context} {\ConTeXt}
-\defineXMLentities [omega] {omega} {\Omega}
-
-\defineXMLentities [Omega] {Omega} {\Omega}
-
% We need this for French and Hungarian.
\defineXMLentity [colon] {\directdiscretionary{:}}
diff --git a/tex/context/interface/keys-cz.xml b/tex/context/interface/keys-cz.xml
index 66b5587be..894d25657 100644
--- a/tex/context/interface/keys-cz.xml
+++ b/tex/context/interface/keys-cz.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml
index 3e8c0991f..4ca09a22d 100644
--- a/tex/context/interface/keys-de.xml
+++ b/tex/context/interface/keys-de.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml
index 341f36028..102fcf0e6 100644
--- a/tex/context/interface/keys-en.xml
+++ b/tex/context/interface/keys-en.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml
index 4dfc85ce3..d843caba6 100644
--- a/tex/context/interface/keys-fr.xml
+++ b/tex/context/interface/keys-fr.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml
index 3231d2ee2..a97d897a6 100644
--- a/tex/context/interface/keys-it.xml
+++ b/tex/context/interface/keys-it.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml
index 816cf99c9..cc340e462 100644
--- a/tex/context/interface/keys-nl.xml
+++ b/tex/context/interface/keys-nl.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2008.03.11 23:55">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml
index 9eeb40772..bdc1a3358 100644
--- a/tex/context/interface/keys-ro.xml
+++ b/tex/context/interface/keys-ro.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2008.03.24 23:24">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2008.04.11 00:07">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>