summaryrefslogtreecommitdiff
path: root/tex/context
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-cs.mkii1
-rw-r--r--tex/context/base/mkii/mult-de.mkii1
-rw-r--r--tex/context/base/mkii/mult-it.mkii2
-rw-r--r--tex/context/base/mkii/mult-pe.mkii1
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua33
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/font-ctx.lua5
-rw-r--r--tex/context/base/mkiv/font-otj.lua4
-rw-r--r--tex/context/base/mkiv/l-string.lua12
-rw-r--r--tex/context/base/mkiv/lpdf-emb.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-lmt.lua4
-rw-r--r--tex/context/base/mkiv/math-noa.lua145
-rw-r--r--tex/context/base/mkiv/mlib-ctx.mkiv10
-rw-r--r--tex/context/base/mkiv/mlib-lmp.lua137
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua216
-rw-r--r--tex/context/base/mkiv/mlib-run.lua452
-rw-r--r--tex/context/base/mkiv/mtx-context-listing.tex8
-rw-r--r--tex/context/base/mkiv/mult-fun.lua3
-rw-r--r--tex/context/base/mkiv/mult-mps.lua4
-rw-r--r--tex/context/base/mkiv/node-nut.lua5
-rw-r--r--tex/context/base/mkiv/node-res.lua2
-rw-r--r--tex/context/base/mkiv/node-rul.lua6
-rw-r--r--tex/context/base/mkiv/node-syn.lua2
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26995 -> 26899 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin249058 -> 251955 bytes
-rw-r--r--tex/context/base/mkiv/strc-flt.mkvi10
-rw-r--r--tex/context/base/mkiv/tabl-tsp.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-wrp.lua4
-rw-r--r--tex/context/interface/mkii/keys-cs.xml1
-rw-r--r--tex/context/interface/mkii/keys-de.xml1
-rw-r--r--tex/context/interface/mkii/keys-it.xml2
-rw-r--r--tex/context/interface/mkii/keys-pe.xml1
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin973215 -> 973481 bytes
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin27520 -> 27517 bytes
-rw-r--r--tex/context/modules/mkiv/m-simulate.mkiv222
38 files changed, 984 insertions, 324 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index e19a3dfbb..ba4e48db1 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2019.06.20 18:47}
+\newcontextversion{2019.07.04 12:29}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 4a72dae8b..0caeb26a7 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2019.06.20 18:47}
+\edef\contextversion{2019.07.04 12:29}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-cs.mkii b/tex/context/base/mkii/mult-cs.mkii
index 902bd5445..23345c05c 100644
--- a/tex/context/base/mkii/mult-cs.mkii
+++ b/tex/context/base/mkii/mult-cs.mkii
@@ -731,6 +731,7 @@
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{compressdistance}{compressdistance}
\setinterfaceconstant{compressseparator}{compressseparator}
\setinterfaceconstant{concerns}{concerns}
\setinterfaceconstant{connector}{connector}
diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii
index 45a9ded24..d52003728 100644
--- a/tex/context/base/mkii/mult-de.mkii
+++ b/tex/context/base/mkii/mult-de.mkii
@@ -731,6 +731,7 @@
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{compressdistance}{compressdistance}
\setinterfaceconstant{compressseparator}{compressseparator}
\setinterfaceconstant{concerns}{concerns}
\setinterfaceconstant{connector}{connector}
diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii
index fe387aa1a..2bbf93141 100644
--- a/tex/context/base/mkii/mult-it.mkii
+++ b/tex/context/base/mkii/mult-it.mkii
@@ -570,6 +570,7 @@
\setinterfacevariable{temporary}{temporaneo}
\setinterfacevariable{test}{test}
\setinterfacevariable{text}{testo}
+\setinterfacevariable{textnote}{textnote}
\setinterfacevariable{three}{tre}
\setinterfacevariable{thursday}{giovedi}
\setinterfacevariable{tight}{tight}
@@ -730,6 +731,7 @@
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{compressdistance}{compressdistance}
\setinterfaceconstant{compressseparator}{compressseparator}
\setinterfaceconstant{concerns}{concerns}
\setinterfaceconstant{connector}{connector}
diff --git a/tex/context/base/mkii/mult-pe.mkii b/tex/context/base/mkii/mult-pe.mkii
index d2efcd7e9..0b121d288 100644
--- a/tex/context/base/mkii/mult-pe.mkii
+++ b/tex/context/base/mkii/mult-pe.mkii
@@ -731,6 +731,7 @@
\setinterfaceconstant{component}{مولفه}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{فشردن}
+\setinterfaceconstant{compressdistance}{compressdistance}
\setinterfaceconstant{compressseparator}{compressseparator}
\setinterfaceconstant{concerns}{concerns}
\setinterfaceconstant{connector}{connector}
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 0778ced4e..ff4f5e3b1 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -326,6 +326,39 @@ end
setmetatablecall(knownfunctions,function(t,n) return knownfunctions[n](n) end)
+-- some protection
+
+do
+
+ local stub = { }
+ local done = false
+ local message = function()
+ -- one time message
+ if not done then
+ report_cld("")
+ report_cld("use : slot = context.functions.register(f)")
+ report_cld("and : context.functions.unregister(slot)")
+ report_cld("")
+ done = true
+ end
+ end
+
+ setmetatable(stub, {
+ __index = message,
+ __newindex = message,
+ })
+
+ function lua.getfunctionstable()
+ message()
+ return stub
+ end
+
+ lua.get_functions_table = lua.getfunctionstable
+
+end
+
+-- so far
+
-- The next hack is a convenient way to define scanners at the Lua end and
-- get them available at the TeX end. There is some dirty magic needed to
-- prevent overload during format loading.
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index dbf340dc5..428ff4f95 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2019.06.20 18:47}
+\newcontextversion{2019.07.04 12:29}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 2d0bf8881..26a46a8bc 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -45,7 +45,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2019.06.20 18:47}
+\edef\contextversion{2019.07.04 12:29}
\edef\contextkind {beta}
%D Kind of special:
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 2d528728a..02cf6093c 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -3252,3 +3252,8 @@ function fonts.helpers.collectanchors(tfmdata)
return anchors
end
+
+if CONTEXTLMTXMODE > 0 then
+ fonts.constructors.addtounicode = false
+ fonts.constructors.autocleanup = false
+end
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index b8be2ec75..2e7878d3d 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -836,8 +836,8 @@ local function inject_positions_only(head,where)
if replace then
-- error, we expect an empty one
else
---KE setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
- replace = fontkern(rightkern) -- maybe also leftkern --KE
+ -- KE setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
+ replace = fontkern(rightkern) -- maybe also leftkern
done = true --KE
end
end
diff --git a/tex/context/base/mkiv/l-string.lua b/tex/context/base/mkiv/l-string.lua
index 8ae8d8d1d..1dee85e28 100644
--- a/tex/context/base/mkiv/l-string.lua
+++ b/tex/context/base/mkiv/l-string.lua
@@ -155,11 +155,13 @@ end
--- needs checking
local anything = patterns.anything
-local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
-local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
-local matchescapes = Cc(".") * S("*?") -- wildcard and single match
+local moreescapes = Cc("%") * S(".-+%?()[]*$^{}")
+local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
+local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?") -- wildcard and single match
-local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_m = Cs ( ( moreescapes + anything )^0 )
+local pattern_a = Cs ( ( allescapes + anything )^0 )
local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
@@ -170,6 +172,8 @@ end
function string.topattern(str,lowercase,strict)
if str == "" or type(str) ~= "string" then
return ".*"
+ elseif strict == "all" then
+ str = lpegmatch(pattern_m,str)
elseif strict then
str = lpegmatch(pattern_c,str)
else
diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua
index 5255eb038..88b323a3f 100644
--- a/tex/context/base/mkiv/lpdf-emb.lua
+++ b/tex/context/base/mkiv/lpdf-emb.lua
@@ -1848,10 +1848,6 @@ statistics.register("font embedding time",function()
end
end)
-updaters.register("backend.update.pdf",function()
- fonts.constructors.addtounicode = false
-end)
-
-- this is temporary
local done = false
diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua
index 0c6f1f3e4..25a73fe67 100644
--- a/tex/context/base/mkiv/lpdf-lmt.lua
+++ b/tex/context/base/mkiv/lpdf-lmt.lua
@@ -2350,9 +2350,7 @@ do
luatex.registerpageactions(1,function()
lpdf.finalizepage(true)
end)
- --
- fonts.constructors.autocleanup = false
- --
+ -- --
lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up")
end
--
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 112972d8f..29b5cbd7e 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -835,8 +835,8 @@ do
if chr == dummyfencechar then
chr = 0
end
- setfield(d,"small_char",chr)
- setfield(d,"small_fam",fam)
+ setchar(d,chr)
+ setfam(d,fam)
flush_node(sym)
end
setattrlist(d,char)
@@ -847,73 +847,61 @@ do
return f
end
- -- will become
+-- local function show(where,pointer)
+-- print("")
+-- local i = 0
+-- for n in nuts.traverse(pointer) do
+-- i = i + 1
+-- print(i,where,nuts.tonode(n))
+-- end
+-- print("")
+-- end
- -- local function makefence(what,char)
- -- local d = new_delimiter() -- todo: attr
- -- local f = new_fence() -- todo: attr
- -- if char then
- -- local sym = getnucleus(char)
- -- local chr = getchar(sym)
- -- local fam = getfam(sym)
- -- if chr == dummyfencechar then
- -- chr = 0
- -- end
- -- setchar(d,chr)
- -- setfam(d,fam)
- -- flush_node(sym)
- -- end
- -- setsubtype(f,what)
- -- setfield(f,"delim",d)
- -- setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what]
- -- return f
- -- end
-
- local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
+ local function makelist(middle, noad, f_o,o_next,c_prev,f_c)
local list = new_submlist()
- setlist(list,f_o)
setsubtype(noad,innernoad_code)
setnucleus(noad,list)
- setlink(f_o,o_next)
- setlink(c_prev,f_c)
+ setlist(list,f_o)
+ setlink(f_o,o_next) -- prev of list is nil
+ setlink(c_prev,f_c) -- next of list is nil
if middle and next(middle) then
local prev = f_o
local current = o_next
while current ~= f_c do
- local m = middle[current]
- if m then
- local next = getnext(current)
+ local midl = middle[current]
+ local next = getnext(current)
+ if midl then
local fence = makefence(middlefence_code,current)
setnucleus(current)
flush_node(current)
middle[current] = nil
-- replace_node
setlink(prev,fence,next)
- prev = fence
- current = next
+ prev = fence
else
prev = current
- current = getnext(current)
end
+ current = next
end
end
+ return noad
end
+ -- relinking is not somewhat overdone
+
local function convert_both(open,close,middle)
local o_prev, o_next = getboth(open)
- local c_prev, c_next = getboth(close)
if o_next == close then
return close
else
+ local c_prev, c_next = getboth(close)
local f_o = makefence(leftfence_code,open)
local f_c = makefence(rightfence_code,close)
- makelist(open,f_o,o_next,c_prev,f_c,middle)
+ makelist(middle, open, f_o,o_next,c_prev,f_c)
setnucleus(close)
flush_node(close)
- if c_next then
- setprev(c_next,open)
- end
- setnext(open,c_next)
+ -- open is now a list
+ setlink(open,c_next)
return open
end
end
@@ -923,24 +911,29 @@ do
local f_c = makefence(rightfence_code)
local o_prev, o_next = getboth(open)
local l_prev, l_next = getboth(last)
- makelist(open,f_o,o_next,last,f_c,middle)
- if l_next then
- setprev(l_next,open)
- end
- setnext(open,l_next)
+ makelist(middle, open, f_o,o_next,l_prev,f_c)
+ -- open is now a list
+ setlink(open,l_next)
return open
end
- local function convert_close(close,first,middle)
+ local function convert_close(first,close,middle)
local f_o = makefence(leftfence_code)
local f_c = makefence(rightfence_code,close)
- local c_prev = getprev(close)
- makelist(close,f_o,first,c_prev,f_c,middle)
+ local c_prev, c_next = getboth(close)
+ local f_prev, f_next = getboth(first)
+ makelist(middle, close, f_o,f_next,c_prev,f_c)
+ -- close is now a list
+ if c_prev ~= first then
+ setlink(first,close)
+ end
return close
end
local stacks = setmetatableindex("table")
+ -- 1=open 2=close 3=middle 4=both
+
local function processfences(pointer,n,parent)
local current = pointer
local last = pointer
@@ -950,47 +943,75 @@ do
local stack = nil
local middle = nil -- todo: use properties
while current do
+-- show("before",pointer)
local id = getid(current)
if id == noad_code then
local a = getattr(current,a_autofence)
if a and a > 0 then
local stack = stacks[n]
- setattr(current,a_autofence,0)
- if a == 1 or (a == 4 and (not stack or #stack == 0)) then
+ setattr(current,a_autofence,0) -- hm, better use a property
+ local level = #stack
+ if a == 1 then
if trace_fences then
- report_fences("%2i: pushing open on stack",n)
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"open","open")
end
insert(stack,current)
- elseif a == 2 or a == 4 then
+ elseif a == 2 then
local open = remove(stack)
if open then
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"both",#stack+1)
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","both")
end
current = convert_both(open,current,middle)
elseif current == start then
- -- skip
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","skip")
+ end
else
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"close",#stack+1)
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"close","close")
end
- current = convert_close(current,initial,middle)
+ current = convert_close(initial,current,middle)
if not parent then
initial = current
end
end
- if trace_fences then
- report_fences("%2i: popping close from stack",n)
- end
elseif a == 3 then
if trace_fences then
- report_fences("%2i: registering middle",n)
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"middle","middle")
end
if middle then
middle[current] = last
else
middle = { [current] = last }
end
+ elseif a == 4 then
+ if not stack or #stack == 0 then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","open")
+ end
+ insert(stack,current)
+ else
+ local open = remove(stack)
+ if open then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","both")
+ end
+ current = convert_both(open,current,middle)
+ elseif current == start then
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","skip")
+ end
+ else
+ if trace_fences then
+ report_fences("%2i: level %i, handling %s, action %s",n,level,"both","close")
+ end
+ current = convert_close(initial,current,middle)
+ if not parent then
+ initial = current
+ end
+ end
+ end
end
done = true
else
@@ -1000,6 +1021,7 @@ do
-- next at current level
processstep(current,processfences,n,id)
end
+-- show("after",pointer)
last = current
current = getnext(current)
end
@@ -1007,13 +1029,10 @@ do
local stack = stacks[n]
local s = #stack
if s > 0 then
- if trace_fences then
- report_fences("%2i: handling %s stack levels",n,s)
- end
for i=1,s do
local open = remove(stack)
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"open",#stack)
+ report_fences("%2i: level %i, handling %s, action %s",#stack,"flush","open")
end
last = convert_open(open,last,middle)
end
diff --git a/tex/context/base/mkiv/mlib-ctx.mkiv b/tex/context/base/mkiv/mlib-ctx.mkiv
index 1f05b6ef8..21d211c1b 100644
--- a/tex/context/base/mkiv/mlib-ctx.mkiv
+++ b/tex/context/base/mkiv/mlib-ctx.mkiv
@@ -19,7 +19,15 @@
\registerctxluafile{mlib-run}{}
\registerctxluafile{mlib-ctx}{}
\registerctxluafile{mlib-lua}{}
-\registerctxluafile{mlib-int}{} % here ?
+
+\doifelsefileexists{mlib-scn.lua} {
+ \registerctxluafile{mlib-scn}{}
+} {
+ % experimental code for Alan and me
+}
+
+\registerctxluafile{mlib-lmp}{}
+\registerctxluafile{mlib-int}{}
\unprotect
diff --git a/tex/context/base/mkiv/mlib-lmp.lua b/tex/context/base/mkiv/mlib-lmp.lua
new file mode 100644
index 000000000..292265be1
--- /dev/null
+++ b/tex/context/base/mkiv/mlib-lmp.lua
@@ -0,0 +1,137 @@
+if not modules then modules = { } end modules ['mlib-lmp'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local get = mp.get
+local aux = mp.aux
+local scan = mp.scan
+
+local mpnumeric = aux.numeric
+local mppair = aux.pair
+local mpquoted = aux.quoted
+
+local scannumber = scan.number
+local scanpath = scan.path
+
+local registerscript = metapost.registerscript
+
+do
+
+ -- todo: use a stack?
+
+ local p = nil
+ local n = 0
+
+ local function mf_path_reset()
+ p = nil
+ n = 0
+ end
+
+ if CONTEXTLMTXMODE > 0 then
+
+ local function mf_path_length()
+ p = scanpath()
+ n = p and #p or 1
+ mpnumeric(n)
+ end
+
+ local function mf_path_point()
+ local i = scannumber()
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[1],pi[2])
+ end
+ end
+
+ local function mf_path_left()
+ local i = scannumber()
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[5],pi[6])
+ end
+ end
+
+ local function mf_path_right()
+ local i = scannumber()
+ if i > 0 and i <= n then
+ local pn
+ if i == 1 then
+ pn = p[2] or p[1]
+ else
+ pn = p[i+1] or p[1]
+ end
+ mppair(pn[3],pn[4])
+ end
+ end
+
+ registerscript("pathreset", mf_path_reset)
+ registerscript("pathlengthof", mf_path_length)
+ registerscript("pathpointof", mf_path_point)
+ registerscript("pathleftof", mf_path_left)
+ registerscript("pathrightof", mf_path_right)
+
+ else
+
+ local mpgetpath = get.path
+
+ local function mf_path_length(name)
+ p = mpgetpath(name)
+ n = p and #p or 0
+ mpnumeric(n)
+ end
+
+ local function mf_path_point(i)
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[1],pi[2])
+ end
+ end
+
+ local function mf_path_left(i)
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[5],pi[6])
+ end
+ end
+
+ local function mf_path_right(i)
+ if i > 0 and i <= n then
+ local pn
+ if i == 1 then
+ pn = p[2] or p[1]
+ else
+ pn = p[i+1] or p[1]
+ end
+ mppair(pn[3],pn[4])
+ end
+ end
+
+ mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length
+ mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point
+ mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left
+ mp.mf_path_right = mf_path_right mp.pathright = mf_path_right
+ mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset
+
+ end
+
+end
+
+do
+
+ -- if needed we can optimize the sub (cache last split)
+
+ local utflen, utfsub = utf.len, utf.sub
+
+ function mp.utflen(s)
+ mpnumeric(utflen(s))
+ end
+
+ function mp.utfsub(s,f,t)
+ mpquoted(utfsub(s,f,t or f))
+ end
+
+end
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index b205946f9..3b08eb79a 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -21,6 +21,7 @@ local lpegpatterns = lpeg.patterns
local P, S, Ct, Cs, Cc, C = lpeg.P, lpeg.S, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.C
local report_luarun = logs.reporter("metapost","lua")
+local report_script = logs.reporter("metapost","script")
local report_message = logs.reporter("metapost")
local trace_luarun = false trackers.register("metapost.lua",function(v) trace_luarun = v end)
@@ -28,12 +29,13 @@ local trace_enabled = true
local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end)
-local get, set, aux = { }, { }, { }
+local get, set, aux, scan = { }, { }, { }, { }
mp = mp or { -- system namespace
- set = set,
- get = get,
- aux = aux,
+ set = set,
+ get = get,
+ aux = aux,
+ scan = scan,
}
MP = MP or { -- user namespace
@@ -56,22 +58,50 @@ table.setmetatablecall(MP,function(t,k,...) return t[k](...) end)
do
- local currentmpx = nil
- local stack = { }
+ local currentmpx = nil
+ local stack = { }
local get_numeric = mplib.get_numeric
local get_string = mplib.get_string
local get_boolean = mplib.get_boolean
local get_path = mplib.get_path
- local set_path = mplib.set_path
get.numeric = function(s) return get_numeric(currentmpx,s) end
+ get.number = function(s) return get_numeric(currentmpx,s) end
get.string = function(s) return get_string (currentmpx,s) end
get.boolean = function(s) return get_boolean(currentmpx,s) end
get.path = function(s) return get_path (currentmpx,s) end
- get.number = function(s) return get_numeric(currentmpx,s) end
- set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet
+ local set_path = mplib.set_path
+
+ set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet
+
+ local scan_next = mplib.scan_next
+ local scan_expression = mplib.scan_expression
+ local scan_token = mplib.scan_token
+ local scan_symbol = mplib.scan_symbol
+ local scan_numeric = mplib.scan_numeric
+ local scan_boolean = mplib.scan_boolean
+ local scan_string = mplib.scan_string
+ local scan_pair = mplib.scan_pair
+ local scan_color = mplib.scan_color
+ local scan_cmykcolor = mplib.scan_cmykcolor
+ local scan_transform = mplib.scan_transform
+ local scan_path = mplib.scan_path
+
+ scan.next = function(k) return scan_next (currentmpx,k) end
+ scan.expression = function(k) return scan_expression(currentmpx,k) end
+ scan.token = function(k) return scan_token (currentmpx,k) end
+ scan.symbol = function(k) return scan_symbol (currentmpx,k) end
+ scan.numeric = function() return scan_numeric (currentmpx) end
+ scan.number = function() return scan_numeric (currentmpx) end
+ scan.boolean = function() return scan_boolean (currentmpx) end
+ scan.string = function() return scan_string (currentmpx) end
+ scan.pair = function(t) return scan_pair (currentmpx,t) end
+ scan.color = function(t) return scan_color (currentmpx,t) end
+ scan.cmykcolor = function(t) return scan_cmykcolor (currentmpx,t) end
+ scan.transform = function(t) return scan_transform (currentmpx,t) end
+ scan.path = function(t) return scan_path (currentmpx,t) end
function metapost.pushscriptrunner(mpx)
insert(stack,mpx)
@@ -86,7 +116,6 @@ do
return currentmpx
end
-
end
do
@@ -101,14 +130,14 @@ do
if trace_enabled and trace_luarun then
local result = concat(buffer," ",1,n)
if n > max then
- buffer = { }
+ buffer = { } -- newtable(20,0)
end
n = 0
report_luarun("%i: data: %s",nesting,result)
return result
else
if n == 0 then
- return ""
+ return "" -- can be nil
end
local result
if n == 1 then
@@ -117,7 +146,7 @@ do
result = concat(buffer," ",1,n)
end
if n > max then
- buffer = { }
+ buffer = { } -- newtable(20,0)
end
n = 0
return result
@@ -464,31 +493,67 @@ do
local cache = table.makeweak()
+ local runscripts = { }
+ local runnames = { }
+ local nofscripts = 0
+
+ function metapost.registerscript(name,f)
+ nofscripts = nofscripts + 1
+ if f then
+ runscripts[nofscripts] = f
+ runnames[name] = nofscripts
+ else
+ runscripts[nofscripts] = name
+ end
+ return nofscripts
+ end
+
+ function metapost.scriptindex(name)
+ return runnames[name] or 0
+ end
+
function metapost.runscript(code)
nesting = nesting + 1
+ local index = type(code) == "number"
local trace = trace_enabled and trace_luarun
- if trace then
- report_luarun("%i: code: %s",nesting,code)
- end
runs = runs + 1
- local f = cache[code]
- if not f then
- f = loadstring(code .. " return mp._f_()")
- if f then
- cache[code] = f
- elseif be_tolerant then
- f = loadstring(code)
+ local f
+ if index then
+ f = runscripts[code]
+ if not f then
+ report_luarun("%i: bad index: %s",nesting,code)
+ elseif trace then
+ report_luarun("%i: index: %i",nesting,code)
+ end
+ else
+ if trace then
+ report_luarun("%i: code: %s",nesting,code)
+ end
+ f = cache[code]
+ if not f then
+ f = loadstring(code .. " return mp._f_()")
if f then
cache[code] = f
+ elseif be_tolerant then
+ f = loadstring(code)
+ if f then
+ cache[code] = f
+ end
end
end
end
+
+ -- returning nil is more efficient and a signel not to scan in mp
+
if f then
local _buffer_ = buffer
local _n_ = n
buffer = { }
n = 0
local result = f()
+ if index and not result then
+ result = _f_()
+ end
if result then
local t = type(result)
if t == "number" then
@@ -526,13 +591,45 @@ end
do
+ -- Another experimental feature:
+
+ local mpnumeric = mp.numeric
+ local scanstring = scan.string
+ local scriptindex = metapost.scriptindex
+
+ function mp.mf_script_index(name)
+ local index = scriptindex(name)
+ -- report_script("method %i, name %a, index %i",1,name,index)
+ mpnumeric(index)
+ end
+
+ -- once bootstrapped ... (needs pushed mpx instances)
+
+ metapost.registerscript("scriptindex",function()
+ local name = scanstring()
+ local index = scriptindex(name)
+ -- report_script("method %i, name %a, index %i",2,name,index)
+ mpnumeric(index)
+ end)
+
+end
+
+-- the next will move to mlib-lmp.lua
+
+do
+
local mpnamedcolor = attributes.colors.mpnamedcolor
local mpprint = aux.print
+ local scanstring = scan.string
mp.mf_named_color = function(str)
mpprint(mpnamedcolor(str))
end
+ metapost.registerscript("namedcolor",function()
+ mpprint(mpnamedcolor(scanstring()))
+ end)
+
end
function mp.n(t) -- used ?
@@ -978,76 +1075,3 @@ do
end
end
-
-do
-
- local mpnumeric = aux.numeric
- local mppair = aux.pair
- local mpgetpath = get.path
-
- local p = nil
- local n = 0
-
- local function mf_path_length(name)
- p = mpgetpath(name)
- n = p and #p or 0
- mpnumeric(n)
- end
-
- local function mf_path_point(i)
- if i > 0 and i <= n then
- local pi = p[i]
- mppair(pi[1],pi[2])
- end
- end
-
- local function mf_path_left(i)
- if i > 0 and i <= n then
- local pi = p[i]
- mppair(pi[5],pi[6])
- end
- end
-
- local function mf_path_right(i)
- if i > 0 and i <= n then
- local pn
- if i == 1 then
- pn = p[2] or p[1]
- else
- pn = p[i+1] or p[1]
- end
- mppair(pn[3],pn[4])
- end
- end
-
- local function mf_path_reset()
- p = nil
- n = 0
- end
-
- mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length
- mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point
- mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left
- mp.mf_path_right = mf_path_right mp.pathright = mf_path_right
- mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset
-
-end
-
-do
-
- -- if needed we can optimize the sub (cache last split)
-
- local utflen, utfsub = utf.len, utf.sub
-
- local mpnumeric = aux.numeric
- local mpquoted = aux.quoted
-
- function mp.utflen(s)
- mpnumeric(utflen(s))
- end
-
- function mp.utfsub(s,f,t)
- mpquoted(utfsub(s,f,t or f))
- end
-
-end
diff --git a/tex/context/base/mkiv/mlib-run.lua b/tex/context/base/mkiv/mlib-run.lua
index bd4818659..0118f6cbd 100644
--- a/tex/context/base/mkiv/mlib-run.lua
+++ b/tex/context/base/mkiv/mlib-run.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['mlib-run'] = {
license = "see context related readme files",
}
--- todo mpx :execute -> mlib.execute(mpx,)
-
-- cmyk -> done, native
-- spot -> done, but needs reworking (simpler)
-- multitone ->
@@ -32,7 +30,7 @@ nears zero.</p>
--ldx]]--
local type, tostring, tonumber, next = type, tostring, tonumber, next
-local striplines = utilities.strings.striplines
+local find, striplines = string.find, utilities.strings.striplines
local concat, insert, remove = table.concat, table.insert, table.remove
local emptystring = string.is_empty
@@ -40,8 +38,10 @@ local P = lpeg.P
local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
local trace_tracingall = false trackers.register("metapost.tracingall", function(v) trace_tracingall = v end)
+local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end)
local report_metapost = logs.reporter("metapost")
+local report_terminal = logs.reporter("metapost","terminal")
local texerrormessage = logs.texerrormessage
local starttiming = statistics.starttiming
@@ -55,11 +55,53 @@ local metapost = metapost
metapost.showlog = false
metapost.lastlog = ""
-metapost.collapse = true -- currently mplib cannot deal with begingroup/endgroup mismatch in stepwise processing
metapost.texerrors = false
metapost.exectime = metapost.exectime or { } -- hack
--- metapost.collapse = false
+local mpxformats = { }
+local mpxterminals = { }
+local nofformats = 0
+local mpxpreambles = { }
+local mpxextradata = { }
+
+-- The flatten hack is needed because the library currently barks on \n\n and the
+-- collapse because mp cannot handle snippets due to grouping issues.
+
+-- todo: pass tables to executempx instead of preparing beforehand,
+-- as it's more efficient for the terminal
+
+local function flatten(source,target)
+ for i=1,#source do
+ local d = source[i]
+ if type(d) == "table" then
+ flatten(d,target)
+ elseif d and d ~= "" then
+ target[#target+1] = d
+ end
+ end
+ return target
+end
+
+local function prepareddata(data)
+ if data and data ~= "" then
+ if type(data) == "table" then
+ data = flatten(data,{ })
+ data = #data > 1 and concat(data,"\n") or data[1]
+ end
+ return data
+ end
+end
+
+local function executempx(mpx,data)
+ local terminal = mpxterminals[mpx]
+ if terminal then
+ terminal.writer(data)
+ data = ""
+ elseif type(data) == "table" then
+ data = prepareddata(data,collapse)
+ end
+ return mpx:execute(data)
+end
directives.register("mplib.texerrors", function(v) metapost.texerrors = v end)
trackers.register ("metapost.showlog", function(v) metapost.showlog = v end)
@@ -77,7 +119,7 @@ local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("bas
-- for some reason mp sometimes calls this function twice which is inefficient
-- but we cannot catch this
-do
+local realtimelogging do
local finders = { }
mplib.finders = finders -- also used in meta-lua.lua
@@ -85,12 +127,10 @@ do
local new_instance = mplib.new
local function validftype(ftype)
- if ftype == "" then
- -- whatever
- elseif ftype == 0 then
- -- mplib bug
+ if ftype == "mp" then
+ return "mp"
else
- return ftype
+ return nil
end
end
@@ -98,6 +138,8 @@ do
return resolvers.findfile(name,validftype(ftype))
end
+ -- this will be redone in lmtx
+
local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi
local specification = url.hashed(name)
local finder = finders[specification.scheme] or finders.file
@@ -115,9 +157,172 @@ do
return (mode == "w" and o_finder or i_finder)(name,mode,validftype(ftype))
end
- function mplib.new(specification)
- specification.find_file = finder -- so we block an overload
- return new_instance(specification)
+ local report_logger = logs.reporter("metapost log")
+ local report_error = logs.reporter("metapost error")
+
+ local l, nl, dl = { }, 0, false
+ local t, nt, dt = { }, 0, false
+ local e, ne, de = { }, 0, false
+
+ local function logger(target,str)
+ if target == 1 then
+ -- log
+ elseif target == 2 or target == 3 then
+ -- term
+ if str == "\n" then
+ realtimelogging = true
+ if nl > 0 then
+ report_logger(concat(l,"",1,nl))
+ nl, dl = 0, false
+ elseif not dl then
+ report_logger("")
+ dl = true
+ end
+ else
+ nl = nl + 1
+ l[nl] = str
+ end
+ elseif target == 4 then
+ report_error(str)
+ end
+ end
+
+ -- experiment, todo: per instance, just a push / pop ?
+
+ local findtexfile = resolvers.findtexfile
+ local opentexfile = resolvers.opentexfile
+ local splitlines = string.splitlines
+
+ local function writetoterminal(terminaldata,maxterm,d)
+ local t = type(d)
+ local n = 0
+ if t == "string" then
+ d = splitlines(d)
+ n = #d
+ for i=1,#d do
+ maxterm = maxterm + 1
+ terminaldata[maxterm] = d[i]
+ end
+ elseif t == "table" then
+ for i=1,#d do
+ local l = d[i]
+ if find(l,"[\n\r]") then
+ local s = splitlines(l)
+ local m = #s
+ for i=1,m do
+ maxterm = maxterm + 1
+ terminaldata[maxterm] = s[i]
+ end
+ n = n + m
+ else
+ maxterm = maxterm + 1
+ terminaldata[maxterm] = d[i]
+ n = 1
+ end
+ end
+ end
+ if trace_terminal then
+ report_metapost("writing %i lines, in cache %s",n,maxterm)
+ end
+ return maxterm
+ end
+
+ local function readfromterminal(terminaldata,maxterm,nowterm)
+ if nowterm >= maxterm then
+ terminaldata[nowterm] = false
+ maxterm = 0
+ nowterm = 0
+ if trace_terminal then
+ report_metapost("resetting, maxcache %i",#terminaldata)
+ end
+ return maxterm, nowterm, nil
+ else
+ if nowterm > 0 then
+ terminaldata[nowterm] = false
+ end
+ nowterm = nowterm + 1
+ local s = terminaldata[nowterm]
+ if trace_terminal then
+ report_metapost("reading line %i: %s",nowterm,s)
+ end
+ return maxterm, nowterm, s
+ end
+ end
+
+ local function fileopener()
+
+ -- these can go into the table itself
+
+ local terminaldata = { }
+ local maxterm = 0
+ local nowterm = 0
+
+ local terminal = {
+ name = "terminal",
+ close = function()
+ -- terminal = { }
+ -- maxterm = 0
+ -- nowterm = 0
+ end,
+ reader = function()
+ local line
+ maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm)
+ return line
+ end,
+ writer = function(d)
+ maxterm = writetoterminal(terminaldata,maxterm,d)
+ end,
+ }
+
+ return function(name,mode,kind)
+ if name == "terminal" then
+ -- report_metapost("opening terminal")
+ return terminal
+ elseif mode == "w" then
+ local f = io.open(name,"wb")
+ if f then
+ -- report_metapost("opening file %a for writing",full)
+ return {
+ name = full,
+ writer = function(s) return f:write(s) end, -- io.write(f,s)
+ close = function() f:close() end,
+ }
+ end
+ else
+ local full = findtexfile(name,validftype(ftype))
+ if full then
+ -- report_metapost("opening file %a for reading",full)
+ return opentexfile(full)
+ end
+ end
+ end
+
+ end
+
+ -- end of experiment
+
+ if CONTEXTLMTXMODE > 0 then
+
+ function mplib.new(specification)
+ local openfile = fileopener()
+ specification.find_file = finder
+ specification.run_logger = logger
+ specification.open_file = openfile
+ specification.interaction = "silent"
+ specification.halt_on_error = true
+ local instance = new_instance(specification)
+ mpxterminals[instance] = openfile("terminal")
+ return instance
+ end
+
+ else
+
+ function mplib.new(specification)
+ specification.find_file = finder
+ specification.run_logger = logger
+ return new_instance(specification)
+ end
+
end
mplib.finder = finder
@@ -130,7 +335,12 @@ local find_file = mplib.finder
function metapost.reporterror(result)
if not result then
report_metapost("error: no result object returned")
- elseif result.status > 0 then
+ return true
+ elseif result.status == 0 then
+ return false
+ elseif realtimelogging then
+ return false -- we already reported
+ else
local t = result.term
local e = result.error
local l = result.log
@@ -150,10 +360,8 @@ function metapost.reporterror(result)
else
report_metapost("error: unknown, no error, terminal or log messages")
end
- else
- return false
+ return true
end
- return true
end
local f_preamble = formatters [ [[
@@ -173,7 +381,7 @@ local methods = {
}
function metapost.runscript(code)
- return code
+ return ""
end
function metapost.scripterror(str)
@@ -210,7 +418,10 @@ function metapost.load(name,method)
if not mpx then
result = { status = 99, error = "out of memory"}
else
- result = mpx:execute(f_preamble(file.addsuffix(name,"mp"),seed)) -- addsuffix is redundant
+ -- pushing permits advanced features
+ metapost.pushscriptrunner(mpx)
+ result = executempx(mpx,f_preamble(file.addsuffix(name,"mp"),seed))
+ metapost.popscriptrunner()
end
stoptiming(mplib)
metapost.reporterror(result)
@@ -254,42 +465,10 @@ function metapost.unload(mpx)
stoptiming(mplib)
end
--- The flatten hack is needed because the library currently barks on \n\n and the
--- collapse because mp cannot handle snippets due to grouping issues.
-
-local function flatten(source,target)
- for i=1,#source do
- local d = source[i]
- if type(d) == "table" then
- flatten(d,target)
- elseif d and d ~= "" then
- target[#target+1] = d
- end
- end
- return target
-end
-
-local function prepareddata(data,collapse)
- if data and data ~= "" then
- if type(data) == "table" then
- data = flatten(data,{ })
- if collapse then
- data = #data > 1 and concat(data,"\n") or data[1]
- end
- end
- return data
- end
-end
-
metapost.defaultformat = "metafun"
metapost.defaultinstance = "metafun"
metapost.defaultmethod = "default"
-local mpxformats = { }
-local nofformats = 0
-local mpxpreambles = { }
-local mpxextradata = { }
-
function metapost.getextradata(mpx)
return mpxextradata[mpx]
end
@@ -332,24 +511,24 @@ function metapost.pushformat(specification,f,m) -- was: instance, name, method
end
nofformats = nofformats + 1
local usedinstance = instance .. ":" .. nofformats
- local mpx = mpxformats[usedinstance]
+ local mpx = mpxformats [usedinstance]
local mpp = mpxpreambles[instance] or ""
if preamble then
- preamble = prepareddata(preamble,true)
+ preamble = prepareddata(preamble)
mpp = mpp .. "\n" .. preamble
mpxpreambles[instance] = mpp
end
if not mpx then
report_metapost("initializing instance %a using format %a and method %a",usedinstance,format,method)
mpx = metapost.checkformat(format,method)
- mpxformats[usedinstance] = mpx
+ mpxformats [usedinstance] = mpx
mpxextradata[mpx] = { }
if mpp ~= "" then
preamble = mpp
end
end
if preamble then
- mpx:execute(preamble)
+ executempx(mpx,preamble)
end
specification.mpx = mpx
return mpx
@@ -370,16 +549,19 @@ function metapost.reset(mpx)
-- nothing
elseif type(mpx) == "string" then
if mpxformats[mpx] then
- mpxextradata[mpx] = nil
- mpxformats[mpx] = nil
- mpxformats[mpx]:finish()
+ local instance = mpxformats[mpx]
+ instance:finish()
+ mpxterminals[instance] = nil
+ mpxextradata[mpx] = nil
+ mpxformats [mpx] = nil
end
else
for name, instance in next, mpxformats do
if instance == mpx then
- mpxextradata[mpx] = nil
- mpxformats[mpx] = nil
mpx:finish()
+ mpxextradata[mpx] = nil
+ mpxformats [mpx] = nil
+ mpxterminals[mpx] = nil
break
end
end
@@ -469,7 +651,7 @@ function metapost.run(specification)
end
if mpx and data then
local tra = nil
- starttiming(metapost)
+ starttiming(metapost) -- why not at the outer level ...
metapost.variables = { } -- todo also push / pop
metapost.pushscriptrunner(mpx)
if trace_graphics then
@@ -487,20 +669,25 @@ function metapost.run(specification)
tra.inp:write(banner)
tra.log:write(banner)
end
- local data = prepareddata(data,metapost.collapse)
local function process(d,i)
if d then
if trace_graphics then
if i then
tra.inp:write(formatters["\n%% begin snippet %s\n"](i))
end
- tra.inp:write(d)
+ if type(d) == "table" then
+ for i=1,#d do
+ tra.inp:write(d[i])
+ end
+ else
+ tra.inp:write(d)
+ end
if i then
tra.inp:write(formatters["\n%% end snippet %s\n"](i))
end
end
starttiming(metapost.exectime)
- result = mpx:execute(d)
+ result = executempx(mpx,d)
stoptiming(metapost.exectime)
if trace_graphics and result then
local str = result.log or result.error
@@ -510,6 +697,7 @@ function metapost.run(specification)
end
if not metapost.reporterror(result) then
if metapost.showlog then
+ -- make function and overload in lmtx
local str = result.term ~= "" and result.term or "no terminal output"
if not emptystring(str) then
metapost.lastlog = metapost.lastlog .. "\n" .. str
@@ -527,14 +715,16 @@ function metapost.run(specification)
end
end
+-- local data = prepareddata(data)
if type(data) == "table" then
if trace_tracingall then
- mpx:execute("tracingall;")
+ executempx(mpx,"tracingall;")
end
- for i=1,#data do
- process(data[i],i)
- end
- else
+ process(data)
+-- for i=1,#data do
+-- process(data[i],i)
+-- end
+ else
if trace_tracingall then
data = "tracingall;" .. data
end
@@ -562,67 +752,71 @@ if not metapost.convert then
end
--- handy
+-- This will be redone as we no longer output svg of ps!
+
+-- function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
+-- local fullname = file.addsuffix(filename,"mp")
+-- local data = mpdata or io.loaddata(fullname)
+-- if outputformat ~= "svg" then
+-- outputformat = "mps"
+-- end
+-- if not data then
+-- report_metapost("unknown file %a",filename)
+-- else
+-- local mpx = metapost.checkformat(formatname)
+-- if not mpx then
+-- report_metapost("unknown format %a",formatname)
+-- else
+-- report_metapost("processing %a",(mpdata and (filename or "data")) or fullname)
+-- local result = executempx(mpx,data)
+-- if not result then
+-- report_metapost("error: no result object returned")
+-- elseif result.status > 0 then
+-- report_metapost("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+-- else
+-- if metapost.showlog then
+-- metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+-- report_metapost("info: %s",result.term or "no-term")
+-- end
+-- local figures = result.fig
+-- if figures then
+-- local sorted = table.sortedkeys(figures)
+-- if astable then
+-- local result = { }
+-- report_metapost("storing %s figures in table",#sorted)
+-- for k=1,#sorted do
+-- local v = sorted[k]
+-- if outputformat == "mps" then
+-- result[v] = figures[v]:postscript()
+-- else
+-- result[v] = figures[v]:svg() -- (3) for prologues
+-- end
+-- end
+-- return result
+-- else
+-- local basename = file.removesuffix(file.basename(filename))
+-- for k=1,#sorted do
+-- local v = sorted[k]
+-- local output
+-- if outputformat == "mps" then
+-- output = figures[v]:postscript()
+-- else
+-- output = figures[v]:svg() -- (3) for prologues
+-- end
+-- local outname = formatters["%s-%s.%s"](basename,v,outputformat)
+-- report_metapost("saving %s bytes in %a",#output,outname)
+-- io.savedata(outname,output)
+-- end
+-- return #sorted
+-- end
+-- end
+-- end
+-- end
+-- end
+-- end
function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
- local fullname = file.addsuffix(filename,"mp")
- local data = mpdata or io.loaddata(fullname)
- if outputformat ~= "svg" then
- outputformat = "mps"
- end
- if not data then
- report_metapost("unknown file %a",filename)
- else
- local mpx = metapost.checkformat(formatname)
- if not mpx then
- report_metapost("unknown format %a",formatname)
- else
- report_metapost("processing %a",(mpdata and (filename or "data")) or fullname)
- local result = mpx:execute(data)
- if not result then
- report_metapost("error: no result object returned")
- elseif result.status > 0 then
- report_metapost("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
- else
- if metapost.showlog then
- metapost.lastlog = metapost.lastlog .. "\n" .. result.term
- report_metapost("info: %s",result.term or "no-term")
- end
- local figures = result.fig
- if figures then
- local sorted = table.sortedkeys(figures)
- if astable then
- local result = { }
- report_metapost("storing %s figures in table",#sorted)
- for k=1,#sorted do
- local v = sorted[k]
- if outputformat == "mps" then
- result[v] = figures[v]:postscript()
- else
- result[v] = figures[v]:svg() -- (3) for prologues
- end
- end
- return result
- else
- local basename = file.removesuffix(file.basename(filename))
- for k=1,#sorted do
- local v = sorted[k]
- local output
- if outputformat == "mps" then
- output = figures[v]:postscript()
- else
- output = figures[v]:svg() -- (3) for prologues
- end
- local outname = formatters["%s-%s.%s"](basename,v,outputformat)
- report_metapost("saving %s bytes in %a",#output,outname)
- io.savedata(outname,output)
- end
- return #sorted
- end
- end
- end
- end
- end
+ report_metapost("producing postscript and svg is no longer supported")
end
-- goodie
diff --git a/tex/context/base/mkiv/mtx-context-listing.tex b/tex/context/base/mkiv/mtx-context-listing.tex
index 285113850..1053e80b9 100644
--- a/tex/context/base/mkiv/mtx-context-listing.tex
+++ b/tex/context/base/mkiv/mtx-context-listing.tex
@@ -116,10 +116,10 @@
-- forced
end
context.page()
--- context.setupfootertexts( -- return true: we need to keep this entry
--- { function() context.detokenize(pattern and filename or file.basename(filename)) return true end },
--- { function() context.pagenumber() return true end }
--- )
+ context.setupfootertexts( -- return true: we need to keep this entry
+ { function() context.detokenize(pattern and filename or file.basename(filename)) return true end },
+ { function() context.pagenumber() return true end }
+ )
if scite then
context.scitefile { filename } -- here { }
elseif pretty then
diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua
index 57cf4778a..eb5cc4f08 100644
--- a/tex/context/base/mkiv/mult-fun.lua
+++ b/tex/context/base/mkiv/mult-fun.lua
@@ -17,6 +17,7 @@ return {
"drawoptionsfactor",
"dq", "sq",
"crossingscale", "crossingoption",
+ "contextlmtxmode",
},
commands = {
"loadfile", "loadimage", "loadmodule",
@@ -174,5 +175,7 @@ return {
"comment", "report", "lua", "mp", "MP", "luacall",
--
"mirrored", "mirroredabout",
+ --
+ "scriptindex",
},
}
diff --git a/tex/context/base/mkiv/mult-mps.lua b/tex/context/base/mkiv/mult-mps.lua
index 1d7252c29..b42beb2b8 100644
--- a/tex/context/base/mkiv/mult-mps.lua
+++ b/tex/context/base/mkiv/mult-mps.lua
@@ -15,7 +15,7 @@ return {
"false", "nullpicture", "pencircle", "penspec", "true",
"and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot",
"char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize",
- "hex", "infont", "intersectiontimes", "known", "length", "llcorner",
+ "hex", "infont", "intersectiontimes", "known", "void", "length", "llcorner",
"lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not",
"numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point",
"postcontrol", "precontrol", "reverse", "rotated", "scaled",
@@ -49,7 +49,7 @@ return {
"extra_beginfig", "extra_endfig", "mpxbreak",
"endinput",
"message", "delimiters", "turningnumber", "errmessage",
- "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom",
+ "scantokens", "end", "outer", "inner", "write", "to", "readfrom", "closefrom",
"withprescript", "withpostscript",
"top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt",
--
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index ebccab04c..b097fb8b1 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -147,8 +147,9 @@ local nuts = nodes.nuts
nuts.check_discretionaries = direct.check_discretionaries
nuts.copy = direct.copy
-nuts.copy_list = direct.copy_list
nuts.copy_node = direct.copy
+nuts.copy_only = direct.copy_only or direct.copy
+nuts.copy_list = direct.copy_list
nuts.count = direct.count
nuts.current_attr = direct.current_attr
nuts.delete = direct.delete
@@ -367,7 +368,7 @@ local d_setlink = direct.setlink
local d_setboth = direct.setboth
local d_getboth = direct.getboth
-local function remove(head,current,free_too)
+local remove = (CONTEXTLMTXMODE > 0 and LUATEXFUNCTIONALITY >= 20190704) and d_remove_node or function(head,current,free_too)
if current then
local h, c = d_remove_node(head,current)
if free_too then
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index 4b8187fa3..5012e771a 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -99,7 +99,7 @@ local setdata = nuts.setdata
local setruledata = nuts.setruledata
local setvalue = nuts.setvalue
-local copy_nut = nuts.copy
+local copy_nut = nuts.copy_only or nuts.copy
local new_nut = nuts.new
local flush_nut = nuts.flush
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index 5a8fdc48a..1b86c9716 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -543,8 +543,8 @@ local function find_attr(head,attr)
end
function linefillers.handler(head)
- for current, subtype, list in nexthlist, head do
- if list and subtype == linelist_code then
+ for current, subtype in nexthlist, head do
+ if current and subtype == linelist_code then
-- why doesn't leftskip take the attributes
-- or list[linefiller] or maybe first match (maybe we need a fast helper for that)
local a = getattr(current,a_linefiller)
@@ -568,6 +568,8 @@ function linefillers.handler(head)
rightlocal = true
end
--
+ local list = getlist(current)
+ --
if location == v_left or location == v_both then
local lskip = nil -- leftskip
local iskip = nil -- indentation
diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua
index bb2eba780..9f333315b 100644
--- a/tex/context/base/mkiv/node-syn.lua
+++ b/tex/context/base/mkiv/node-syn.lua
@@ -168,7 +168,7 @@ local getdimensions = nuts.dimensions
local getrangedimensions = nuts.rangedimensions
local get_synctex_fields = nuts.get_synctex_fields
-local set_synctex_fields = nuts.set_synctex_fields
+----- set_synctex_fields = nuts.set_synctex_fields
local set_synctex_line = tex.set_synctex_line
local set_synctex_tag = tex.set_synctex_tag
local force_synctex_tag = tex.force_synctex_tag
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index c171029ad..472dee79a 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 0f13f1cb4..4b9db0b9a 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-flt.mkvi b/tex/context/base/mkiv/strc-flt.mkvi
index a1289bf1d..5daf2b44d 100644
--- a/tex/context/base/mkiv/strc-flt.mkvi
+++ b/tex/context/base/mkiv/strc-flt.mkvi
@@ -1068,8 +1068,9 @@
\def\floatcaptionattribute
{\iflocation
- %\ifnofloatnumber
- %\else
+ \ifx\currentfloatattribute\empty
+ % safeguard, can be samepage too
+ \else
\ifnofloatcaption
\else
\ifinsidesplitfloat
@@ -1081,7 +1082,7 @@
attr \destinationattribute \currentfloatattribute
\fi
\fi
- %\fi
+ \fi
\fi}
\newconditional\usesamefloatnumber
@@ -1144,7 +1145,7 @@
\glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize
\fi
%
- \global\setfalse\usesamefloatnumber % one shot
+ \iftrialtypesetting\else\global\setfalse\usesamefloatnumber\fi % one shot
% check float box
\strc_floats_set_natural_dimensions\nextbox
\global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}% can be anything so no pack
@@ -1170,6 +1171,7 @@
\strc_floats_get_box
\global\insidefloatfalse}
+
\newdimen\availablefloatwidth
\newdimen\availablefloatheight
diff --git a/tex/context/base/mkiv/tabl-tsp.mkiv b/tex/context/base/mkiv/tabl-tsp.mkiv
index e0ddce38a..9395f4039 100644
--- a/tex/context/base/mkiv/tabl-tsp.mkiv
+++ b/tex/context/base/mkiv/tabl-tsp.mkiv
@@ -187,7 +187,9 @@
\bgroup
\forcelocalfloats
\setuplocalfloats[\c!before=,\c!after=,\c!inbetween=]%
+ \settrialtypesetting % this controls samepage resetting too
\splitfloatcommand{\hbox to #1{\strut}}% dummy line
+ \resettrialtypesetting
\setbox\scratchbox\vbox{\flushlocalfloats}% \vpack ?
\getnoflines{\ht\scratchbox}%
\resetlocalfloats
diff --git a/tex/context/base/mkiv/typo-wrp.lua b/tex/context/base/mkiv/typo-wrp.lua
index 9fb544152..f2ca43b56 100644
--- a/tex/context/base/mkiv/typo-wrp.lua
+++ b/tex/context/base/mkiv/typo-wrp.lua
@@ -32,7 +32,7 @@ local getprev = nuts.getprev
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getpenalty = nuts.getpenalty
-local remove = nuts.remove
+local remove_node = nuts.remove
local enableaction = nodes.tasks.enableaction
@@ -66,7 +66,7 @@ local function remove_dangling_crlf(head,tail)
if trace_wrappers then
report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno)
end
- remove(head,tail,true)
+ remove_node(head,tail,true)
return head, tail
end
end
diff --git a/tex/context/interface/mkii/keys-cs.xml b/tex/context/interface/mkii/keys-cs.xml
index 1b8ce2fa6..bb4800900 100644
--- a/tex/context/interface/mkii/keys-cs.xml
+++ b/tex/context/interface/mkii/keys-cs.xml
@@ -737,6 +737,7 @@
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
+ <cd:constant name='compressdistance' value='compressdistance'/>
<cd:constant name='compressseparator' value='compressseparator'/>
<cd:constant name='concerns' value='concerns'/>
<cd:constant name='connector' value='connector'/>
diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml
index 97a18d711..2ab5c9c12 100644
--- a/tex/context/interface/mkii/keys-de.xml
+++ b/tex/context/interface/mkii/keys-de.xml
@@ -737,6 +737,7 @@
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
+ <cd:constant name='compressdistance' value='compressdistance'/>
<cd:constant name='compressseparator' value='compressseparator'/>
<cd:constant name='concerns' value='concerns'/>
<cd:constant name='connector' value='connector'/>
diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml
index 0c1d450ec..c852ae515 100644
--- a/tex/context/interface/mkii/keys-it.xml
+++ b/tex/context/interface/mkii/keys-it.xml
@@ -573,6 +573,7 @@
<cd:variable name='temporary' value='temporaneo'/>
<cd:variable name='test' value='test'/>
<cd:variable name='text' value='testo'/>
+ <cd:variable name='textnote' value='textnote'/>
<cd:variable name='three' value='tre'/>
<cd:variable name='thursday' value='giovedi'/>
<cd:variable name='tight' value='tight'/>
@@ -736,6 +737,7 @@
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
+ <cd:constant name='compressdistance' value='compressdistance'/>
<cd:constant name='compressseparator' value='compressseparator'/>
<cd:constant name='concerns' value='concerns'/>
<cd:constant name='connector' value='connector'/>
diff --git a/tex/context/interface/mkii/keys-pe.xml b/tex/context/interface/mkii/keys-pe.xml
index 8532d9894..710f9d74b 100644
--- a/tex/context/interface/mkii/keys-pe.xml
+++ b/tex/context/interface/mkii/keys-pe.xml
@@ -737,6 +737,7 @@
<cd:constant name='component' value='مولفه'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='فشردن'/>
+ <cd:constant name='compressdistance' value='compressdistance'/>
<cd:constant name='compressseparator' value='compressseparator'/>
<cd:constant name='concerns' value='concerns'/>
<cd:constant name='connector' value='connector'/>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 51806d7e1..97b13f0d0 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 97206e852..9f90949bb 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/modules/mkiv/m-simulate.mkiv b/tex/context/modules/mkiv/m-simulate.mkiv
new file mode 100644
index 000000000..dc4448903
--- /dev/null
+++ b/tex/context/modules/mkiv/m-simulate.mkiv
@@ -0,0 +1,222 @@
+%D \module
+%D [ file=m-simulate,
+%D version=2016.02.18, % follow up on m-visual of 2000.01.10
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Visualization and Faking Redone,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\definepalet
+ [fakerule]
+ [fr1c=darkred,
+ fr2c=darkgreen,
+ fr3c=darkblue,
+ fr4c=darkyellow,
+ fr5c=darkgray,
+ fr6c=darkred,
+ fr7c=darkgreen,
+ fr8c=darkblue,
+ fr9c=darkyellow,
+ fr0c=darkgray]
+
+\installcorenamespace {simulatewords}
+
+\installcommandhandler \??simulatewords {simulatewords} \??simulatewords
+
+\setupsimulatewords
+ [\c!n =\plusten,
+ \c!m =40,
+ \c!min =\plusone,
+ \c!max =\plusfive,
+ \c!minwidth=0.50\emwidth,
+ \c!maxwidth=1.25\emwidth,
+ \c!color =\empty,
+ \c!hyphen =\v!yes,
+ \c!distance=-.2\onebasepoint]
+
+\unexpanded\def\dosimulatedword
+ {\clf_fakeword
+ factor \exheight
+ name {\p_line}
+ min \scratchdimenone
+ max \scratchdimentwo
+ \relax}
+
+\def\simulatedhyphen
+ {\kern.2\points-\kern.2\points}
+
+\unexpanded\def\simulatewords
+ {\dodoubleempty\dosimulatewords}
+
+\unexpanded\def\dosimulatewords[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \begstrut
+ \ifsecondargument
+ \edef\currentsimulatewords{#1}%
+ \setupcurrentsimulatewords[#2]%
+ \else
+ \doifassignmentelse{#1}
+ {\let\currentsimulatewords\empty
+ \setupcurrentsimulatewords[#1]}
+ {\edef\currentsimulatewords{#1}%
+ \setupcurrentsimulatewords[#2]}%
+ \fi
+ \scratchcounterone\simulatewordsparameter\c!n
+ \scratchcountertwo\simulatewordsparameter\c!m
+ \scratchmin \simulatewordsparameter\c!min
+ \scratchmax \simulatewordsparameter\c!max
+ \scratchdimenone \simulatewordsparameter\c!minwidth
+ \scratchdimentwo \simulatewordsparameter\c!maxwidth
+ \scratchdimenthree\simulatewordsparameter\c!distance
+ \edef\p_random{\simulatewordsparameter\c!random}%
+ \edef\p_color {\simulatewordsparameter\c!color}%
+ \edef\p_line {\simulatewordsparameter\c!line}%
+ \edef\p_hyphen{\simulatewordsparameter\c!hyphen}%
+ \edef\p_line {fake:\ifx\p_line\v!yes word\else rule\fi}%
+ \ifx\p_color\v!text
+ % no need
+ \else
+ \setuppalet[fakerule]%
+ \ifx\p_color\empty
+ \directcolored[fakerulecolor]%
+ \else\ifx\p_color\v!auto
+ % different
+ \else
+ \directcolored[\p_color]%
+ \fi\fi
+ \fi
+ \edef\p_hyphen
+ {\ifx\p_hyphen\v!yes
+ \discretionary{\bf\simulatedhyphen}{}{\kern\scratchdimenthree}%
+ \else\ifx\p_hyphen\v!margin
+ \discretionary{\hpack to \zeropoint{\bf\simulatedhyphen\hss}}{}{\kern\scratchdimenthree}%
+ \else\ifx\p_hyphen\v!none
+ \allowbreak\kern\scratchdimenthree
+ \else\ifx\p_hyphen\v!no
+ \allowbreak\kern\scratchdimenthree
+ \else\ifx\p_hyphen\v!both
+ \discretionary{\bf\simulatedhyphen}{\bf\simulatedhyphen}{\kern\scratchdimenthree}%
+ \else\ifx\p_hyphen\empty
+ \allowbreak\kern\scratchdimenthree
+ \else
+ \discretionary{\p_hyphen}{}{\kern\scratchdimenthree}%
+ \fi\fi\fi\fi\fi\fi}%
+ \edef\truncated##1##2\relax{##1}%
+ % trialtypesetting: tricky
+ \ifx\p_random\empty \else
+ \pushrandomseed
+ \setrandomseed\p_random
+ \fi
+ \dorecurse{\randomnumber\scratchcounterone\scratchcountertwo} {%
+ \let\dosimulatedhyphen\relax
+ \dorecurse{\randomnumber\scratchmin\scratchmax} {%
+ \dosimulatedhyphen
+ \begingroup
+ \ifx\p_color\v!auto
+ \directcolored[fr\truncated####1\relax c]%
+ \fi
+ \dosimulatedword
+ \endgroup
+ \let\dosimulatedhyphen\p_hyphen
+ }%
+ \relax
+ \space
+ }%
+ \ifx\p_random\empty \else
+ \poprandomseed
+ \fi
+ \removeunwantedspaces
+ \endstrut
+ \endgroup}
+
+%D For old times sake:
+
+\unexpanded\def\fakewords#1#2%
+ {\simulatewords[\c!n=#1,\c!m=#2,\c!min=1,\c!max=5,\c!hyphen=\v!none,\c!color=\v!text,\c!line=\v!yes]}
+
+%D Lines
+
+\unexpanded\def\fakeline
+ {\dosingleempty\dofakeline}
+
+\unexpanded\def\dofakeline[#1]%
+ {\par
+ \dontleavehmode
+ \hpack\bgroup
+ \scratchwidth \availablehsize
+ \scratchheight.8\strutht
+ \scratchdepth .8\strutdp
+ \iffirstargument
+ \letsimulatewordsparameter\c!width \scratchwidth
+ \letsimulatewordsparameter\c!height\scratchheight
+ \letsimulatewordsparameter\c!depth \scratchdepth
+ \getcurrentsimulatewords[#1]%
+ \scratchwidth \simulatewordsparameter\c!width
+ \scratchheight\simulatewordsparameter\c!height
+ \scratchdepth \simulatewordsparameter\c!depth
+ \fi
+ \edef\p_color{\simulatewordsparameter\c!color}%
+ \begingroup
+ \ifx\p_color\empty
+ \directcolored[fakerulecolor]%
+ \else\ifx\p_color\v!auto
+ % text color
+ \else
+ \directcolored[\p_color]%
+ \fi\fi
+ \vrule
+ \s!width \scratchwidth
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \endgroup
+ \hskip-\scratchwidth
+ \directcolored[\s!white]%
+ \scratchdimen.5\onepoint
+ \vrule
+ \s!width \scratchwidth
+ \s!height\scratchdimen
+ \s!depth \scratchdimen
+ \egroup
+ \par}
+
+\protect
+
+\continueifinputfile{m-simulate.mkiv}
+
+\starttext
+
+ \simulatewords[n=50,m=100,min=1,max=5,color=auto,hyphen=margin,line=yes]\par
+ \simulatewords[n=50,m=100,min=3,max=9,color=auto,hyphen=margin,line=yes]\par
+ \simulatewords[n=50,m=100,min=3,max=9,color=auto,hyphen=margin,line=yes]\par
+ \page
+ \simulatewords[n=50,m=100,min=2,max=6,hyphen=yes]\par
+ \simulatewords[n=50,m=100,min=2,max=6,hyphen=both]\par
+ \simulatewords[n=50,m=100,min=2,max=6,hyphen=both]\par
+
+ \startcolor[red]
+ \simulatewords[n=50,m=100,min=2,max=6,color=text]\par
+ \stopcolor
+
+ \definesimulatewords[foo][n=50,m=100,min=2,max=6,color=text]
+
+ \startcolor[green]
+ \simulatewords[foo][color=darkyellow,random=1234]
+ \stopcolor
+
+ \page
+
+ \fakeline
+
+ \startnarrower
+ \fakeline
+ \stopnarrower
+
+\stoptext