1if not modules then modules = { } end modules ['mlib-lmp'] = {
2 version = 1.001,
3 comment = "companion to mlib-ctx.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files",
7}
8
9
10
11local type, tonumber, tostring = type, tonumber, tostring
12local find, match = string.find, string.match
13local insert, remove, sort = table.insert, table.remove, table.sort
14
15local aux = mp.aux
16local mpnumeric = aux.numeric
17local mppair = aux.pair
18
19local registerdirect = metapost.registerdirect
20local registerscript = metapost.registerscript
21
22local scan = mp.scan
23local skip = mp.skip
24local get = mp.get
25local inject = mp.inject
26
27local scannumber = scan.number
28local scanstring = scan.string
29local scaninteger = scan.integer
30local scannumeric = scan.numeric
31local scanwhatever = scan.whatever
32local scanpath = scan.path
33local scanproperty = scan.property
34
35local gethashentry = get.hashentry
36
37local bpfactor = number.dimenfactors.bp
38
39local injectwhatever = inject.whatever
40local injectboolean = inject.boolean
41local injectnumeric = inject.numeric
42local injectstring = inject.string
43local injectpair = inject.pair
44local injectpath = inject.path
45
46local injectwhd = inject.whd
47local injectxy = inject.xy
48local injectpt = inject.pt
49
50local report = logs.reporter("metapost", "log")
51local report_message = logs.reporter("metapost")
52
53local codes = metapost.codes
54local types = metapost.types
55local procodes = mplib.propertycodes
56
57local implement = interfaces.implement
58
59do
60
61 local function s(a,b)
62 local aa = a[1]
63 local bb = b[1]
64 if aa == bb then
65 aa = a[2]
66 bb = b[2]
67 end
68 return aa < bb
69 end
70
71 registerscript("sortedpath", function()
72 local p = scanpath()
73 for i=1,#p do
74 local pi = p[i]
75 p[i] = { pi[1], pi[2] }
76 end
77 sort(p,s)
78 injectpath(p)
79 end)
80
81 registerscript("uniquepath", function()
82 local p = scanpath()
83 local u = { }
84 local n = 0
85 local xx = nil
86 local yy = nil
87 sort(p,s)
88 for i=1,#p do
89 local pi = p[i]
90 local x = pi[1]
91 local y = pi[2]
92 if x ~= xx or y ~= yy then
93 n = n + 1
94 u[n] = { x, y }
95 xx = x
96 yy = y
97 end
98 end
99 injectpath(u)
100 end)
101
102end
103
104do
105
106 local p = nil
107 local n = 0
108
109 registerscript("pathreset", function()
110 p = nil
111 n = 0
112 end)
113
114 registerdirect("pathlengthof", function()
115 p = scanpath()
116 n = p and #p or 1
117 return n
118 end)
119
120 registerdirect("pathpointof", function()
121 local i = scaninteger()
122 if i > 0 and i <= n then
123 local pi = p[i]
124 injectpair(pi[1],pi[2])
125 end
126 end)
127
128 registerdirect("pathleftof", function()
129 local i = scaninteger()
130 if i > 0 and i <= n then
131 local pi = p[i]
132 injectpair(pi[5],pi[6])
133 end
134 end)
135
136 registerdirect("pathrightof", function()
137 local i = scaninteger()
138 if i > 0 and i <= n then
139 local pn
140 if i == 1 then
141 pn = p[2] or p[1]
142 else
143 pn = p[i+1] or p[1]
144 end
145 injectpair(pn[3],pn[4])
146 end
147 end)
148
149end
150
151registerscript("showproperty", function()
152 local k, s, p, d = scanproperty()
153 if k then
154 report("name %a, property %a, command %a, detail %a",s,procodes[p] or "-",codes[k] or "-",types[d] or "-")
155 end
156end)
157
158registerscript("showhashentry", function()
159 local s = scanstring()
160 if s then
161 local k, p, d = gethashentry(s)
162 if k then
163 report("name %a, property %a, command %a, detail %a",s,procodes[p] or "-",codes[k] or "-",types[d] or "-")
164 end
165 end
166end)
167
168
169
170
171
172
173
174
175
176
177
178do
179
180 local expandtex = mp.expandtex
181
182 local tokenvalues = tokens.values
183 local dimension_value = tokenvalues.dimension
184 local integer_value = tokenvalues.integer
185 local boolean_value = tokenvalues.boolean
186 local string_value = tokenvalues.string
187 local unknown_value = tokenvalues.none
188
189 registerdirect("mpvard", function()
190 if not expandtex(dimension_value,"mpcategoryparameter",true,scanstring()) then
191 injectnumeric(0)
192 end
193 end)
194
195 registerdirect("mpvarn", function()
196 if not expandtex(integer_value,"mpcategoryparameter",true,scanstring()) then
197 injectnumeric(0)
198 end
199 end)
200
201 registerdirect("mpvars", function()
202 if not expandtex(string_value,"mpcategoryparameter",true,scanstring()) then
203 injectstring("")
204 end
205 end)
206
207 registerdirect("mpvarb", function()
208 if not expandtex(boolean_value,"mpcategoryparameter",true,scanstring()) then
209 injectboolean(false)
210 end
211 end)
212
213 registerdirect("mpvar", function()
214 if not expandtex(unknown_value,"mpcategoryparameter",true,scanstring()) then
215 injectnumeric(0)
216 end
217 end)
218
219
220
221 registerscript("texvar", function()
222 if not expandtex(unknown_value,"mpcategoryparameter",true,scanstring()) then
223 injectnumeric(0)
224 end
225 end)
226
227 registerscript("texstr", function()
228 if not expandtex(string_value,"mpcategoryparameter",true,scanstring()) then
229 injectstring("")
230 end
231 end)
232
233end
234
235do
236
237 registerscript("textextanchor", function()
238 local x, y = match(scanstring(),"tx_anchor=(%S+) (%S+)")
239 if x and y then
240 x = tonumber(x)
241 y = tonumber(y)
242 end
243 injectpair(x or 0,y or 0)
244 end)
245
246end
247
248do
249
250 local mpnamedcolor = attributes.colors.mpnamedcolor
251 local mpprint = mp.aux.print
252
253 mp.mf_named_color = function(str)
254 mpprint(mpnamedcolor(str))
255 end
256
257
258
259
260 registerscript("namedcolor",function() mpprint(mpnamedcolor(scanstring())) end)
261
262end
263
264do
265
266 local hashes = table.setmetatableindex("table")
267
268
269
270
271 local registery = { }
272
273
274
275
276
277
278
279 registerdirect("lmt_hash_new", function()
280 for i=1,#registry + 1 do
281 if not registry[i] then
282 registry[i] = { }
283 injectwhatever(i)
284 end
285 end
286 end)
287
288 registerdirect("lmt_hash_dispose", function()
289
290 local name = scanwhatever()
291 hashes[name] = nil
292
293 if registry[name] then
294 registry[name] = false
295 end
296 end)
297
298 registerdirect("lmt_hash_in", function()
299
300 local name = scanwhatever()
301
302 local key = scanwhatever()
303 local hash = hashes[name]
304 injectwhatever(hash and hash[key] and true or false)
305 end)
306
307 registerdirect("lmt_hash_to", function()
308
309 local name = scanwhatever()
310
311 local key = scanwhatever()
312 local value = scanwhatever()
313 local hash = hashes[name]
314 if hash then
315 hash[key] = value
316 end
317 end)
318
319 registerdirect("lmt_hash_from", function()
320
321 local name = scanwhatever()
322
323 local key = scanwhatever()
324 local hash = hashes[name]
325 injectwhatever(hash and hash[key] or false)
326 end)
327
328 interfaces.implement {
329 name = "MPfromhash",
330 arguments = "2 strings",
331 actions = function(name,key)
332 local hash = hashes[name] or hashes[tonumber(name)] or hashes[tostring(name)]
333 if hash then
334 local v = hash[key]
335 if v then
336 context(v)
337 end
338 end
339 end
340 }
341
342end
343
344do
345
346 local bpfactor = number.dimenfactors.bp
347 local nbdimensions = nodes.boxes.dimensions
348
349 registerdirect("boxdimensions", function()
350 local category = scanstring()
351 local index = scanwhatever()
352 injectwhd(nbdimensions(category,index))
353 end)
354
355end
356
357do
358
359 local skiptoken = skip.token
360
361 local comma_code = codes.comma
362
363 local getmacro = tokens.getters.macro
364 local setmacro = tokens.setters.macro
365
366 local getdimen = tex.getdimen
367 local getcount = tex.getcount
368 local gettoks = tex.gettoks
369 local setdimen = tex.setdimen
370 local setcount = tex.setcount
371 local settoks = tex.settoks
372
373
374
375 registerdirect("getmacro", function() return getmacro(scanstring()) end)
376 registerdirect("getcount", function() return getcount(scanwhatever()) end)
377 registerdirect("gettoks", function() return gettoks (scanwhatever()) end)
378 registerdirect("getdimen", function() return getdimen(scanwhatever()) * bpfactor end)
379
380 registerscript("setmacro", function() setmacro(scanstring(),scanstring()) end)
381 registerscript("setdimen", function() setdimen(scanwhatever(),scannumeric()/bpfactor) end)
382 registerscript("setcount", function() setcount(scanwhatever(),scannumeric()) end)
383 registerscript("settoks", function() settoks (scanwhatever(),scanstring()) end)
384
385 registerscript("setglobalmacro", function() setmacro(scanstring(),scanstring(),"global") end)
386 registerscript("setglobaldimen", function() setdimen("global",scanwhatever(),scannumeric()/bpfactor) end)
387 registerscript("setglobalcount", function() setcount("global",scanwhatever(),scaninteger()) end)
388 registerscript("setglobaltoks", function() settoks ("global",scanwhatever(),scanstring()) end)
389
390 local utfnum = utf.byte
391 local utflen = utf.len
392 local utfsub = utf.sub
393
394 registerdirect("utfnum", function() return utfnum(scanstring()) end)
395 registerdirect("utflen", function() return utflen(scanstring()) end)
396
397 registerdirect("utfsub", function()
398 return utfsub(scanstring(),skiptoken(comma_code) and scannumeric(),skiptoken(comma_code) and scannumeric())
399 end)
400
401 local setlogging = metapost.setlogging
402
403 registerscript("message", function()
404 setlogging(false)
405 local str = scanstring()
406 setlogging(true)
407 report_message("message : %s",str)
408 end)
409
410end
411
412
413
414do
415
416 local getcount = tex.getcount
417
418 local mpprint = mp.print
419 local mpfprint = mp.fprint
420
421 local mpscaninteger = mp.scan.integer
422 local mpscannumber = mp.scan.number
423
424 local jobpositions = job.positions
425 local getwhd = jobpositions.whd
426 local getxy = jobpositions.xy
427 local getx = jobpositions.x
428 local gety = jobpositions.y
429 local getposition = jobpositions.position
430 local getpage = jobpositions.page
431 local getparagraph = jobpositions.paragraph
432 local getregion = jobpositions.region
433 local getcolumn = jobpositions.column
434 local getmacro = tokens.getters.macro
435
436 local columnofpos = jobpositions.columnofpos
437 local getcolumndata = jobpositions.getcolumndata
438
439
440
441
442
443
444 registerscript("positionpath", function()
445 local w, h, d = getwhd(scanstring())
446 if w then
447 mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",0,-d,w,-d,w,h,0,h)
448 else
449 mpprint("(origin--cycle)")
450 end
451 end)
452
453 registerscript("positioncurve", function()
454 local w, h, d = getwhd(scanstring())
455 if w then
456 mpfprint("((%p,%p)..(%p,%p)..(%p,%p)..(%p,%p)..cycle)",0,-d,w,-d,w,h,0,h)
457 else
458 mpprint("(origin--cycle)")
459 end
460 end)
461
462 registerscript("positionbox", function()
463 local p, x, y, w, h, d = getposition(scanstring())
464 if p then
465 mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h)
466 else
467 mpprint("(%p,%p)--cycle",x or 0,y or 0)
468 end
469 end)
470
471 registerscript("positioncolumnbox", function()
472 local column = mpscaninteger()
473 local data = getcolumndata(getcount("realpageno"),column)
474 if data then
475 local x, y, w, h, d = data.x, data.y, data.w, data.h, data.d
476 mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h)
477 else
478 mpprint("(0,0)--cycle")
479 end
480 end)
481
482 registerscript("overlaycolumnbox", function()
483 local column = mpscaninteger()
484 local data = getcolumndata(getcount("realpageno"),column)
485 if data then
486 local w, hd = data.w, data.h + data.d
487 mpfprint("((0,0)--(%p,0)--(%p,%p)--(0,%p)--cycle)",w,w,hd,hd)
488 else
489 mpprint("(0,0)--cycle")
490 end
491 end)
492
493 registerdirect("positionpage", function() return getpage (scanstring()) or 0 end)
494 registerdirect("positioncolumn", function() return getcolumn (scanstring()) or 0 end)
495 registerdirect("positionparagraph", function() return getparagraph(scanstring()) or 0 end)
496 registerdirect("positionregion", function() return getregion (scanstring()) or "unknown" end)
497 registerdirect("positionanchor", function() return getmacro ("MPanchorid") end)
498 registerdirect("positionwhd", function() injectwhd(getwhd(scanstring())) end)
499 registerdirect("positionxy", function() injectxy (getxy (scanstring())) end)
500 registerdirect("positionx", function() injectpt (getx (scanstring())) end)
501 registerdirect("positiony", function() injectpt (gety (scanstring())) end)
502
503 registerdirect("positioncolumnatx", function()
504 local realpage = mpscaninteger()
505 local xposition = mpscannumber()
506 return columnofpos(realpage,xposition)
507 end)
508
509end
510
511do
512
513 local modes = tex.modes
514 local systemmodes = tex.systemmodes
515
516 registerdirect("mode", function() injectboolean(modes [scanstring()] and true or false) end)
517 registerdirect("systemmode", function() injectboolean(systemmodes[scanstring()] and true or false) end)
518
519
520
521 local modes = tex.modes
522 local systemmodes = tex.systemmodes
523
524 function mp.mode(s)
525 injectboolean(modes[s] and true or false)
526 end
527
528 function mp.systemmode(s)
529 injectboolean(systemmodes[s] and true or false)
530 end
531
532 mp.processingmode = mp.mode
533
534end
535
536
537
538do
539
540 local lpegmatch, lpegpatterns, P = lpeg.match, lpeg.patterns, lpeg.P
541
542
543
544 registerdirect("isarray", function()
545 injectboolean(find(scanstring(),"%d") and true or false)
546 end)
547
548 registerdirect("prefix", function()
549 local str = scanstring()
550 return match(str,"^(.-)[%d%[]") or str
551 end)
552
553 local dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer)
554
555 registerdirect("dimension", function() return dimension(scanstring()) end)
556
557
558
559
560
561
562
563 local p1 = P("mf_object=")
564 local p2 = lpegpatterns.eol * p1
565 local pattern = (1-p2)^0 * p2 + p1
566
567 registerdirect("isobject", function()
568 local str = scanstring()
569 injectboolean(pattern and str ~= "" and lpegmatch(pattern,str))
570 end)
571
572end
573
574
575
576do
577
578 local stack, top = { }, nil
579
580 local function setvariable(k,v)
581 if top then
582 top[k] = v
583 else
584 metapost.variables[k] = v
585 end
586 end
587
588 local function pushvariable(k)
589 local t = { }
590 if top then
591 insert(stack,top)
592 top[k] = t
593 else
594 metapost.variables[k] = t
595 end
596 top = t
597 end
598
599 local function popvariable()
600 top = remove(stack)
601 end
602
603 registerscript("passvariable", function() setvariable (scanstring(), scanwhatever()) end)
604 registerscript("pushvariable", function() pushvariable(scanstring()) end)
605 registerscript("popvariable", function() popvariable () end)
606
607 local stack = { }
608
609 local function pushvariables()
610 insert(stack,metapost.variables)
611 metapost.variables = { }
612 end
613
614 local function popvariables()
615 metapost.variables = remove(stack) or metapost.variables
616 end
617
618 metapost.setvariable = setvariable
619 metapost.pushvariable = pushvariable
620 metapost.popvariable = popvariable
621 metapost.pushvariables = pushvariables
622 metapost.popvariables = popvariables
623
624 implement {
625 name = "mppushvariables",
626 actions = pushvariables,
627 }
628
629 implement {
630 name = "mppopvariables",
631 actions = popvariables,
632 }
633
634end
635
636do
637
638 local repeatable = utilities.randomizer.repeatable
639
640 registerdirect("repeatablerandom", function()
641 return repeatable(scanstring())
642 end)
643
644end
645 |