texlive[69109] Master/texmf-dist: context-legacy

commits+siepo at tug.org commits+siepo at tug.org
Wed Dec 13 11:01:49 CET 2023


Revision: 69109
          https://tug.org/svn/texlive?view=revision&revision=69109
Author:   siepo
Date:     2023-12-13 11:01:49 +0100 (Wed, 13 Dec 2023)
Log Message:
-----------
context-legacy

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
    trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
    trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
    trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
    trunk/Master/texmf-dist/doc/man/man1/luatools.1
    trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/texmfstart.1
    trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf
    trunk/Master/texmf-dist/fonts/enc/dvips/context/
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmin.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmit.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmitt.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmrm.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmsc.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/cmtt.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/ec-2004.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/q-8r.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/context/teff-trinite.enc
    trunk/Master/texmf-dist/fonts/map/dvips/context/
    trunk/Master/texmf-dist/fonts/map/dvips/context/contnav.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/
    trunk/Master/texmf-dist/fonts/map/pdftex/context/8r-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-os-public-lm.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-px.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-tx.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-adobe-euro.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-cmr.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-euler.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-context-symbol.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-dummy.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-empty.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-micropress-informal.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-csr.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-lm.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-plr.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-vnr.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-vogel-symbol.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-wasy.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-px.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-tx.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-os-public-lm.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-os-public-lm.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-base.map
    trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-os-public-lm.map
    trunk/Master/texmf-dist/metapost/context/base/mpii/
    trunk/Master/texmf-dist/metapost/context/base/mpii/metafun.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-back.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-base.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-butt.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-char.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-core.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-figs.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-fobg.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-form.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-func.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grid.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grph.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-page.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-shap.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-spec.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-step.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-symb.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-text.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-tool.mpii
    trunk/Master/texmf-dist/metapost/context/base/mpii/mp-txts.mpii
    trunk/Master/texmf-dist/scripts/context/ruby/
    trunk/Master/texmf-dist/scripts/context/ruby/base/
    trunk/Master/texmf-dist/scripts/context/ruby/base/ctx.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/exa.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/file.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/drb.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/soap.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/trees.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpse.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpsedirect.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpsefast.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpseremote.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/kpserunner.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/logger.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/merge.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/mp.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/pdf.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/state.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/switch.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/system.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/tex.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/texutil.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/tool.rb
    trunk/Master/texmf-dist/scripts/context/ruby/base/variables.rb
    trunk/Master/texmf-dist/scripts/context/ruby/concheck.rb
    trunk/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/graphics/
    trunk/Master/texmf-dist/scripts/context/ruby/graphics/gs.rb
    trunk/Master/texmf-dist/scripts/context/ruby/graphics/inkscape.rb
    trunk/Master/texmf-dist/scripts/context/ruby/graphics/magick.rb
    trunk/Master/texmf-dist/scripts/context/ruby/imgtopdf.rb
    trunk/Master/texmf-dist/scripts/context/ruby/pdftools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/pstopdf.rb
    trunk/Master/texmf-dist/scripts/context/ruby/rlxtools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/rscortool.rb
    trunk/Master/texmf-dist/scripts/context/ruby/rsfiltool.rb
    trunk/Master/texmf-dist/scripts/context/ruby/rslb/
    trunk/Master/texmf-dist/scripts/context/ruby/rslb/base.rb
    trunk/Master/texmf-dist/scripts/context/ruby/rslibtool.rb
    trunk/Master/texmf-dist/scripts/context/ruby/runtools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/texexec.rb
    trunk/Master/texmf-dist/scripts/context/ruby/texmfstart.rb
    trunk/Master/texmf-dist/scripts/context/ruby/textools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/texutil.rb
    trunk/Master/texmf-dist/scripts/context/ruby/tmftools.rb
    trunk/Master/texmf-dist/scripts/context/ruby/xmltools.rb
    trunk/Master/texmf-dist/scripts/context/stubs/
    trunk/Master/texmf-dist/scripts/context/stubs/unix/
    trunk/Master/texmf-dist/scripts/context/stubs/unix/ctxtools
    trunk/Master/texmf-dist/scripts/context/stubs/unix/pstopdf
    trunk/Master/texmf-dist/scripts/context/stubs/unix/texexec
    trunk/Master/texmf-dist/scripts/context/stubs/unix/texmfstart
    trunk/Master/texmf-dist/scripts/context/stubs/win64/
    trunk/Master/texmf-dist/scripts/context/stubs/win64/ctxtools.cmd
    trunk/Master/texmf-dist/scripts/context/stubs/win64/pstopdf.cmd
    trunk/Master/texmf-dist/scripts/context/stubs/win64/texexec.cmd
    trunk/Master/texmf-dist/scripts/context/stubs/win64/texmfstart.cmd
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/unix/
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/unix/contextjit
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/unix/luatools
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/unix/mtxrunjit
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/win64/
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/win64/contextjit.cmd
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/win64/luatools.cmd
    trunk/Master/texmf-dist/scripts/context/stubs-mkiv/win64/mtxrunjit.cmd

Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>CtxTools 1.3.5</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">CtxTools 1.3.5 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--touchcontextfile</th><td></td><td>update context version</td></tr>
+        <tr><th>--contextversion</th><td></td><td>report context version</td></tr>
+        <tr><th>--jeditinterface</th><td></td><td>generate jedit syntax files [--pipe]</td></tr>
+        <tr><th>--bbeditinterface</th><td></td><td>generate bbedit syntax files [--pipe]</td></tr>
+        <tr><th>--sciteinterface</th><td></td><td>generate scite syntax files [--pipe]</td></tr>
+        <tr><th>--rawinterface</th><td></td><td>generate raw syntax files [--pipe]</td></tr>
+        <tr><th>--translateinterface</th><td></td><td>generate interface files (xml) [nl de ..]</td></tr>
+        <tr><th>--purgefiles</th><td></td><td>remove temporary files [--all --recurse] [basename]</td></tr>
+        <tr><th>--documentation  generate documentation [--type</th><td>]</td><td>[filename]</td></tr>
+        <tr><th>--filterpages'</th><td></td><td>) # no help, hidden temporary feature</td></tr>
+        <tr><th>--dpxmapfiles</th><td></td><td>convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]</td></tr>
+        <tr><th>--listentities</th><td></td><td>create doctype entity definition from enco-uc.tex</td></tr>
+        <tr><th>--brandfiles</th><td></td><td>add context copyright notice [--force]</td></tr>
+        <tr><th>--platformize</th><td></td><td>replace line-endings [--recurse --force] [pattern]</td></tr>
+        <tr><th>--dependencies  analyze depedencies within context [--save --compact --filter</th><td>[macros|filenames] ]</td><td>[filename]</td></tr>
+        <tr><th>--updatecontext</th><td></td><td>download latest version and remake formats [--proxy]</td></tr>
+        <tr><th>--disarmutfbom</th><td></td><td>remove utf bom [--force]</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,75 @@
+.TH "ctxtools" "1" "01-01-2023" "version 1.3.5" "CtxTools"
+.SH NAME
+ ctxtools - CtxTools
+.SH SYNOPSIS
+.B ctxtools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B CtxTools
+.SH OPTIONS
+.TP
+.B --touchcontextfile
+update context version
+.TP
+.B --contextversion
+report context version
+.TP
+.B --jeditinterface
+generate jedit syntax files [--pipe]
+.TP
+.B --bbeditinterface
+generate bbedit syntax files [--pipe]
+.TP
+.B --sciteinterface
+generate scite syntax files [--pipe]
+.TP
+.B --rawinterface
+generate raw syntax files [--pipe]
+.TP
+.B --translateinterface
+generate interface files (xml) [nl de ..]
+.TP
+.B --purgefiles
+remove temporary files [--all --recurse] [basename]
+.TP
+.B --documentation  generate documentation [--type=]
+[filename]
+.TP
+.B --filterpages'
+) # no help, hidden temporary feature
+.TP
+.B --dpxmapfiles
+convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]
+.TP
+.B --listentities
+create doctype entity definition from enco-uc.tex
+.TP
+.B --brandfiles
+add context copyright notice [--force]
+.TP
+.B --platformize
+replace line-endings [--recurse --force] [pattern]
+.TP
+.B --dependencies  analyze depedencies within context [--save --compact --filter=[macros|filenames] ]
+[filename]
+.TP
+.B --updatecontext
+download latest version and remake formats [--proxy]
+.TP
+.B --disarmutfbom
+remove utf bom [--force]
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">ctxtools</entry>
+  <entry name="detail">CtxTools</entry>
+  <entry name="version">1.3.5</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="touchcontextfile"><short>update context version</short></flag>
+    <flag name="contextversion"><short>report context version</short></flag>
+    <flag name="jeditinterface"><short>generate jedit syntax files [<ref name="pipe]"/></short></flag>
+    <flag name="bbeditinterface"><short>generate bbedit syntax files [<ref name="pipe]"/></short></flag>
+    <flag name="sciteinterface"><short>generate scite syntax files [<ref name="pipe]"/></short></flag>
+    <flag name="rawinterface"><short>generate raw syntax files [<ref name="pipe]"/></short></flag>
+    <flag name="translateinterface"><short>generate interface files (xml) [nl de ..]</short></flag>
+    <flag name="purgefiles"><short>remove temporary files [<ref name="all"/> <ref name="recurse]"/> [basename]</short></flag>
+    <flag name="documentation  generate documentation [--type" value="]"><short>[filename]</short></flag>
+    <flag name="filterpages'"><short>) # no help, hidden temporary feature</short></flag>
+    <flag name="dpxmapfiles"><short>convert pdftex mapfiles to dvipdfmx [<ref name="force]"/> [texmfroot]</short></flag>
+    <flag name="listentities"><short>create doctype entity definition from enco-uc.tex</short></flag>
+    <flag name="brandfiles"><short>add context copyright notice [<ref name="force]"/></short></flag>
+    <flag name="platformize"><short>replace line-endings [<ref name="recurse"/> <ref name="force]"/> [pattern]</short></flag>
+    <flag name="dependencies  analyze depedencies within context [--save --compact --filter" value="[macros|filenames] ]"><short>[filename]</short></flag>
+    <flag name="updatecontext"><short>download latest version and remake formats [<ref name="proxy]"/></short></flag>
+    <flag name="disarmutfbom"><short>remove utf bom [<ref name="force]"/></short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>ImgToPdf 1.1.2</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">ImgToPdf 1.1.2 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--convert</th><td></td><td>convert image into pdf</td></tr>
+        <tr><th>--compression</th><td></td><td>level of compression in percent</td></tr>
+        <tr><th>--depth</th><td></td><td>image depth in bits</td></tr>
+        <tr><th>--colorspace</th><td></td><td> colorspace (rgb,cmyk,gray)</td></tr>
+        <tr><th>--quality</th><td></td><td>quality in percent</td></tr>
+        <tr><th>--inputpath</th><td></td><td>path where files are looked for</td></tr>
+        <tr><th>--outputpath</th><td></td><td>path where files end up</td></tr>
+        <tr><th>--auto</th><td></td><td>determine settings automatically</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,48 @@
+.TH "imgtopdf" "1" "01-01-2023" "version 1.1.2" "ImgToPdf"
+.SH NAME
+ imgtopdf - ImgToPdf
+.SH SYNOPSIS
+.B imgtopdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ImgToPdf
+.SH OPTIONS
+.TP
+.B --convert
+convert image into pdf
+.TP
+.B --compression
+level of compression in percent
+.TP
+.B --depth
+image depth in bits
+.TP
+.B --colorspace
+ colorspace (rgb,cmyk,gray)
+.TP
+.B --quality
+quality in percent
+.TP
+.B --inputpath
+path where files are looked for
+.TP
+.B --outputpath
+path where files end up
+.TP
+.B --auto
+determine settings automatically
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">imgtopdf</entry>
+  <entry name="detail">ImgToPdf</entry>
+  <entry name="version">1.1.2</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="convert"><short>convert image into pdf</short></flag>
+    <flag name="compression"><short>level of compression in percent</short></flag>
+    <flag name="depth"><short>image depth in bits</short></flag>
+    <flag name="colorspace"><short> colorspace (rgb,cmyk,gray)</short></flag>
+    <flag name="quality"><short>quality in percent</short></flag>
+    <flag name="inputpath"><short>path where files are looked for</short></flag>
+    <flag name="outputpath"><short>path where files end up</short></flag>
+    <flag name="auto"><short>determine settings automatically</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>PDFTools 1.2.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">PDFTools 1.2.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--spotimage  filename --colorspec</th><td></td><td>--colorname=  [--retain --invert --subpath=]</td></tr>
+        <tr><th>--colorimage  filename --colorspec</th><td></td><td>[--retain --invert --colorname= ]</td></tr>
+        <tr><th>--convertimage</th><td></td><td>filename [--retain --subpath]</td></tr>
+        <tr><th>--downsampleimage</th><td></td><td>filename [--retain --subpath --lowres --normal]</td></tr>
+        <tr><th>--info</th><td></td><td>filename</td></tr>
+        <tr><th>--countpages</th><td></td><td>[--pattern --threshold]</td></tr>
+        <tr><th>--checkembedded</th><td></td><td>[--pattern]</td></tr>
+        <tr><th>--analyzefile</th><td></td><td>filename</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,48 @@
+.TH "pdftools" "1" "01-01-2023" "version 1.2.1" "PDFTools"
+.SH NAME
+ pdftools - PDFTools
+.SH SYNOPSIS
+.B pdftools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B PDFTools
+.SH OPTIONS
+.TP
+.B --spotimage  filename --colorspec
+--colorname=  [--retain --invert --subpath=]
+.TP
+.B --colorimage  filename --colorspec
+[--retain --invert --colorname= ]
+.TP
+.B --convertimage
+filename [--retain --subpath]
+.TP
+.B --downsampleimage
+filename [--retain --subpath --lowres --normal]
+.TP
+.B --info
+filename
+.TP
+.B --countpages
+[--pattern --threshold]
+.TP
+.B --checkembedded
+[--pattern]
+.TP
+.B --analyzefile
+filename
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">pdftools</entry>
+  <entry name="detail">PDFTools</entry>
+  <entry name="version">1.2.1</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="spotimage  filename --colorspec" value=""><short><ref name="colorname="/>  [<ref name="retain"/> <ref name="invert"/> <ref name="subpath=]"/></short></flag>
+    <flag name="colorimage  filename --colorspec" value=""><short>[<ref name="retain"/> <ref name="invert"/> <ref name="colorname="/> ]</short></flag>
+    <flag name="convertimage"><short>filename [<ref name="retain"/> <ref name="subpath]"/></short></flag>
+    <flag name="downsampleimage"><short>filename [<ref name="retain"/> <ref name="subpath"/> <ref name="lowres"/> <ref name="normal]"/></short></flag>
+    <flag name="info"><short>filename</short></flag>
+    <flag name="countpages"><short>[<ref name="pattern"/> <ref name="threshold]"/></short></flag>
+    <flag name="checkembedded"><short>[<ref name="pattern]"/></short></flag>
+    <flag name="analyzefile"><short>filename</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>PStoPDF 2.0.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">PStoPDF 2.0.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--request</th><td></td><td>handles exa request file</td></tr>
+        <tr><th>--watch</th><td></td><td>watch folders for conversions (untested)</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,30 @@
+.TH "pstopdf" "1" "01-01-2023" "version 2.0.1" "PStoPDF"
+.SH NAME
+ pstopdf - PStoPDF
+.SH SYNOPSIS
+.B pstopdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B PStoPDF
+.SH OPTIONS
+.TP
+.B --request
+handles exa request file
+.TP
+.B --watch
+watch folders for conversions (untested)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">pstopdf</entry>
+  <entry name="detail">PStoPDF</entry>
+  <entry name="version">2.0.1</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="request"><short>handles exa request file</short></flag>
+    <flag name="watch"><short>watch folders for conversions (untested)</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>RlxTools 1.0.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">RlxTools 1.0.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--manipulate</th><td></td><td>[--test] manipulatorfile resourselog</td></tr>
+        <tr><th>--identify</th><td></td><td>[--collect] filename</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,30 @@
+.TH "rlxtools" "1" "01-01-2023" "version 1.0.1" "RlxTools"
+.SH NAME
+ rlxtools - RlxTools
+.SH SYNOPSIS
+.B rlxtools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B RlxTools
+.SH OPTIONS
+.TP
+.B --manipulate
+[--test] manipulatorfile resourselog
+.TP
+.B --identify
+[--collect] filename
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">rlxtools</entry>
+  <entry name="detail">RlxTools</entry>
+  <entry name="version">1.0.1</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="manipulate"><short>[<ref name="test]"/> manipulatorfile resourselog</short></flag>
+    <flag name="identify"><short>[<ref name="collect]"/> filename</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>TeXExec 6.2.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">TeXExec 6.2.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--make</th><td></td><td>make formats</td></tr>
+        <tr><th>--check</th><td></td><td>check versions</td></tr>
+        <tr><th>--process</th><td></td><td>process file</td></tr>
+        <tr><th>--mptex</th><td></td><td>process mp file</td></tr>
+        <tr><th>--mpxtex</th><td></td><td>process mpx file</td></tr>
+        <tr><th>--mpgraphic</th><td></td><td>process mp file to stand-alone graphics</td></tr>
+        <tr><th>--mpstatic</th><td></td><td>process mp/ctx file to stand-alone graphics</td></tr>
+        <tr><th>--listing</th><td></td><td>list of file content</td></tr>
+        <tr><th>--figures</th><td></td><td>generate overview of figures</td></tr>
+        <tr><th>--modules</th><td></td><td>generate module documentation</td></tr>
+        <tr><th>--pdfarrange</th><td></td><td>impose pages (booklets)</td></tr>
+        <tr><th>--pdfselect</th><td></td><td>select pages from file(s)</td></tr>
+        <tr><th>--pdfcopy</th><td></td><td>copy pages from file(s)</td></tr>
+        <tr><th>--pdftrim</th><td></td><td>trim pages from file(s)</td></tr>
+        <tr><th>--pdfcombine</th><td></td><td>combine multiple pages</td></tr>
+        <tr><th>--pdfsplit</th><td></td><td>split file in pages</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,72 @@
+.TH "texexec" "1" "01-01-2023" "version 6.2.1" "TeXExec"
+.SH NAME
+ texexec - TeXExec
+.SH SYNOPSIS
+.B texexec [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXExec
+.SH OPTIONS
+.TP
+.B --make
+make formats
+.TP
+.B --check
+check versions
+.TP
+.B --process
+process file
+.TP
+.B --mptex
+process mp file
+.TP
+.B --mpxtex
+process mpx file
+.TP
+.B --mpgraphic
+process mp file to stand-alone graphics
+.TP
+.B --mpstatic
+process mp/ctx file to stand-alone graphics
+.TP
+.B --listing
+list of file content
+.TP
+.B --figures
+generate overview of figures
+.TP
+.B --modules
+generate module documentation
+.TP
+.B --pdfarrange
+impose pages (booklets)
+.TP
+.B --pdfselect
+select pages from file(s)
+.TP
+.B --pdfcopy
+copy pages from file(s)
+.TP
+.B --pdftrim
+trim pages from file(s)
+.TP
+.B --pdfcombine
+combine multiple pages
+.TP
+.B --pdfsplit
+split file in pages
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">texexec</entry>
+  <entry name="detail">TeXExec</entry>
+  <entry name="version">6.2.1</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="make"><short>make formats</short></flag>
+    <flag name="check"><short>check versions</short></flag>
+    <flag name="process"><short>process file</short></flag>
+    <flag name="mptex"><short>process mp file</short></flag>
+    <flag name="mpxtex"><short>process mpx file</short></flag>
+    <flag name="mpgraphic"><short>process mp file to stand-alone graphics</short></flag>
+    <flag name="mpstatic"><short>process mp/ctx file to stand-alone graphics</short></flag>
+    <flag name="listing"><short>list of file content</short></flag>
+    <flag name="figures"><short>generate overview of figures</short></flag>
+    <flag name="modules"><short>generate module documentation</short></flag>
+    <flag name="pdfarrange"><short>impose pages (booklets)</short></flag>
+    <flag name="pdfselect"><short>select pages from file(s)</short></flag>
+    <flag name="pdfcopy"><short>copy pages from file(s)</short></flag>
+    <flag name="pdftrim"><short>trim pages from file(s)</short></flag>
+    <flag name="pdfcombine"><short>combine multiple pages</short></flag>
+    <flag name="pdfsplit"><short>split file in pages</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>texmfstart 7.0.0</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">texmfstart 7.0.0 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--script</th><td></td><td>run an mtx script (lua prefered method) (--noquotes), no script gives list</td></tr>
+        <tr><th>--evaluate</th><td></td><td>run code passed on the commandline (between quotes) (=loop) (exit|quit aborts)</td></tr>
+        <tr><th>--execute</th><td></td><td>run a script or program (texmfstart method) (--noquotes)</td></tr>
+        <tr><th>--resolve</th><td></td><td>resolve prefixed arguments</td></tr>
+        <tr><th>--ctxlua</th><td></td><td>run internally (using preloaded libs)</td></tr>
+        <tr><th>--internal</th><td></td><td>run script using built in libraries (same as --ctxlua)</td></tr>
+        <tr><th>--locate</th><td></td><td>locate given filename in database (default) or system (--first --all --detail)</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--tree</th><td>pathtotree</td><td>use given texmf tree (default file: setuptex.tmf)</td></tr>
+        <tr><th>--path</th><td>runpath</td><td>go to given path before execution</td></tr>
+        <tr><th>--ifchanged</th><td>filename</td><td>only execute when given file has changed (md checksum)</td></tr>
+        <tr><th>--iftouched</th><td>old,new</td><td>only execute when given file has changed (time stamp)</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--makestubs</th><td></td><td>create stubs for (context related) scripts</td></tr>
+        <tr><th>--removestubs</th><td></td><td>remove stubs (context related) scripts</td></tr>
+        <tr><th>--stubpath</th><td>binpath</td><td>paths where stubs wil be written</td></tr>
+        <tr><th>--windows</th><td></td><td>create windows (mswin) stubs</td></tr>
+        <tr><th>--unix</th><td></td><td>create unix (linux) stubs</td></tr>
+        <tr><th>--addbinarypath</th><td></td><td>prepend the (found) binarypath to runners</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--verbose</th><td></td><td>give a bit more info</td></tr>
+        <tr><th>--trackers</th><td>list</td><td>enable given trackers</td></tr>
+        <tr><th>--progname</th><td>str</td><td>format or backend</td></tr>
+        <tr><th>--systeminfo</th><td>str</td><td>show current operating system, processor, etc</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--edit</th><td></td><td>launch editor with found file</td></tr>
+        <tr><th>--launch</th><td></td><td>launch files like manuals, assumes os support (--all,--list)</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--timedrun</th><td></td><td>run a script and time its run</td></tr>
+        <tr><th>--autogenerate</th><td></td><td>regenerate databases if needed (handy when used to run context in an editor)</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--usekpse</th><td></td><td>use kpse as fallback (when no mkiv and cache installed, often slower)</td></tr>
+        <tr><th>--forcekpse</th><td></td><td>force using kpse (handy when no mkiv and cache installed but less functionality)</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--prefixes</th><td></td><td>show supported prefixes</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--generate</th><td></td><td>generate file database</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--variables</th><td></td><td>show configuration variables</td></tr>
+        <tr><th>--configurations</th><td></td><td>show configuration order</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--directives</th><td></td><td>show (known) directives</td></tr>
+        <tr><th>--trackers</th><td></td><td>show (known) trackers</td></tr>
+        <tr><th>--experiments</th><td></td><td>show (known) experiments</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--expand-braces</th><td></td><td>expand complex variable</td></tr>
+        <tr><th>--resolve-path</th><td></td><td>expand variable (completely resolve paths)</td></tr>
+        <tr><th>--expand-path</th><td></td><td>expand variable (resolve paths)</td></tr>
+        <tr><th>--expand-var</th><td></td><td>expand variable (resolve references)</td></tr>
+        <tr><th>--show-path</th><td></td><td>show path expansion of ...</td></tr>
+        <tr><th>--var-value</th><td></td><td>report value of variable</td></tr>
+        <tr><th>--find-file</th><td></td><td>report file location</td></tr>
+        <tr><th>--find-path</th><td></td><td>report path of file</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--pattern</th><td>string</td><td>filter variables</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,153 @@
+.TH "mtxrun" "1" "01-01-2023" "version 1.33" "ConTeXt TDS Runner Tool"
+.SH NAME
+ mtxrun - ConTeXt TDS Runner Tool
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
+.SH OPTIONS
+.TP
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
+.TP
+.B --evaluate
+run code passed on the commandline (between quotes) (=loop) (exit|quit aborts)
+.TP
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
+.TP
+.B --resolve
+resolve prefixed arguments
+.TP
+.B --ctxlua
+run internally (using preloaded libs)
+.TP
+.B --internal
+run script using built in libraries (same as --ctxlua)
+.TP
+.B --locate
+locate given filename in database (default) or system (--first --all --detail)
+.TP
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
+.TP
+.B --path=runpath
+go to given path before execution
+.TP
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
+.TP
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
+.TP
+.B --makestubs
+create stubs for (context related) scripts
+.TP
+.B --removestubs
+remove stubs (context related) scripts
+.TP
+.B --stubpath=binpath
+paths where stubs wil be written
+.TP
+.B --windows
+create windows (mswin) stubs
+.TP
+.B --unix
+create unix (linux) stubs
+.TP
+.B --addbinarypath
+prepend the (found) binarypath to runners
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
+.TP
+.B --systeminfo=str
+show current operating system, processor, etc
+.TP
+.B --edit
+launch editor with found file
+.TP
+.B --launch
+launch files like manuals, assumes os support (--all,--list)
+.TP
+.B --timedrun
+run a script and time its run
+.TP
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
+.TP
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
+.TP
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
+.TP
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --resolve-path
+expand variable (completely resolve paths)
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,80 @@
+<?xml version="1.0"?><application>
+ <metadata>
+  <entry name="name">mtxrun</entry>
+  <entry name="detail">ConTeXt TDS Runner Tool</entry>
+  <entry name="version">1.33</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="script"><short>run an mtx script (lua prefered method) (<ref name="noquotes"/>), no script gives list</short></flag>
+    <flag name="evaluate"><short>run code passed on the commandline (between quotes) (=loop) (exit|quit aborts)</short></flag>
+    <flag name="execute"><short>run a script or program (texmfstart method) (<ref name="noquotes"/>)</short></flag>
+    <flag name="resolve"><short>resolve prefixed arguments</short></flag>
+    <flag name="ctxlua"><short>run internally (using preloaded libs)</short></flag>
+    <flag name="internal"><short>run script using built in libraries (same as <ref name="ctxlua"/>)</short></flag>
+    <flag name="locate"><short>locate given filename in database (default) or system (<ref name="first"/> <ref name="all"/> <ref name="detail"/>)</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="tree" value="pathtotree"><short>use given texmf tree (default file: setuptex.tmf)</short></flag>
+    <flag name="path" value="runpath"><short>go to given path before execution</short></flag>
+    <flag name="ifchanged" value="filename"><short>only execute when given file has changed (md checksum)</short></flag>
+    <flag name="iftouched" value="old,new"><short>only execute when given file has changed (time stamp)</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="makestubs"><short>create stubs for (context related) scripts</short></flag>
+    <flag name="removestubs"><short>remove stubs (context related) scripts</short></flag>
+    <flag name="stubpath" value="binpath"><short>paths where stubs wil be written</short></flag>
+    <flag name="windows"><short>create windows (mswin) stubs</short></flag>
+    <flag name="unix"><short>create unix (linux) stubs</short></flag>
+    <flag name="addbinarypath"><short>prepend the (found) binarypath to runners</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="verbose"><short>give a bit more info</short></flag>
+    <flag name="trackers" value="list"><short>enable given trackers</short></flag>
+    <flag name="progname" value="str"><short>format or backend</short></flag>
+    <flag name="systeminfo" value="str"><short>show current operating system, processor, etc</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="edit"><short>launch editor with found file</short></flag>
+    <flag name="launch"><short>launch files like manuals, assumes os support (<ref name="all"/>,<ref name="list"/>)</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="timedrun"><short>run a script and time its run</short></flag>
+    <flag name="autogenerate"><short>regenerate databases if needed (handy when used to run context in an editor)</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="usekpse"><short>use kpse as fallback (when no mkiv and cache installed, often slower)</short></flag>
+    <flag name="forcekpse"><short>force using kpse (handy when no mkiv and cache installed but less functionality)</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="prefixes"><short>show supported prefixes</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="generate"><short>generate file database</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="variables"><short>show configuration variables</short></flag>
+    <flag name="configurations"><short>show configuration order</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="directives"><short>show (known) directives</short></flag>
+    <flag name="trackers"><short>show (known) trackers</short></flag>
+    <flag name="experiments"><short>show (known) experiments</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="expand-braces"><short>expand complex variable</short></flag>
+    <flag name="resolve-path"><short>expand variable (completely resolve paths)</short></flag>
+    <flag name="expand-path"><short>expand variable (resolve paths)</short></flag>
+    <flag name="expand-var"><short>expand variable (resolve references)</short></flag>
+    <flag name="show-path"><short>show path expansion of ...</short></flag>
+    <flag name="var-value"><short>report value of variable</short></flag>
+    <flag name="find-file"><short>report file location</short></flag>
+    <flag name="find-path"><short>report path of file</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="pattern" value="string"><short>filter variables</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>TeXTools 1.3.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">TeXTools 1.3.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--removemapnames</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--restoremapnames</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--hidemapnames</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--videmapnames</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--findfile</th><td></td><td>filename    [--recurse]</td></tr>
+        <tr><th>--unzipfiles</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--fixafmfiles</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--mactodos</th><td></td><td>[pattern]   [--recurse]</td></tr>
+        <tr><th>--fixtexmftrees</th><td></td><td>[texmfroot] [--force]</td></tr>
+        <tr><th>--replacefile</th><td></td><td>filename    [--force]</td></tr>
+        <tr><th>--updatetree</th><td></td><td>fromroot toroot [--force --nocheck --merge --delete]</td></tr>
+        <tr><th>--downcasefilenames</th><td></td><td>[--recurse] [--force]</td></tr>
+        <tr><th>--stripformfeeds</th><td></td><td>[--recurse] [--force]</td></tr>
+        <tr><th>--showfont</th><td></td><td>filename</td></tr>
+        <tr><th>--encmake</th><td></td><td>afmfile encodingname</td></tr>
+        <tr><th>--tpmmake</th><td></td><td>tpm file (run in texmf root)</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,72 @@
+.TH "textools" "1" "01-01-2023" "version 1.3.1" "TeXTools"
+.SH NAME
+ textools - TeXTools
+.SH SYNOPSIS
+.B textools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXTools
+.SH OPTIONS
+.TP
+.B --removemapnames
+[pattern]   [--recurse]
+.TP
+.B --restoremapnames
+[pattern]   [--recurse]
+.TP
+.B --hidemapnames
+[pattern]   [--recurse]
+.TP
+.B --videmapnames
+[pattern]   [--recurse]
+.TP
+.B --findfile
+filename    [--recurse]
+.TP
+.B --unzipfiles
+[pattern]   [--recurse]
+.TP
+.B --fixafmfiles
+[pattern]   [--recurse]
+.TP
+.B --mactodos
+[pattern]   [--recurse]
+.TP
+.B --fixtexmftrees
+[texmfroot] [--force]
+.TP
+.B --replacefile
+filename    [--force]
+.TP
+.B --updatetree
+fromroot toroot [--force --nocheck --merge --delete]
+.TP
+.B --downcasefilenames
+[--recurse] [--force]
+.TP
+.B --stripformfeeds
+[--recurse] [--force]
+.TP
+.B --showfont
+filename
+.TP
+.B --encmake
+afmfile encodingname
+.TP
+.B --tpmmake
+tpm file (run in texmf root)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">textools</entry>
+  <entry name="detail">TeXTools</entry>
+  <entry name="version">1.3.1</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="removemapnames"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="restoremapnames"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="hidemapnames"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="videmapnames"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="findfile"><short>filename    [<ref name="recurse]"/></short></flag>
+    <flag name="unzipfiles"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="fixafmfiles"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="mactodos"><short>[pattern]   [<ref name="recurse]"/></short></flag>
+    <flag name="fixtexmftrees"><short>[texmfroot] [<ref name="force]"/></short></flag>
+    <flag name="replacefile"><short>filename    [<ref name="force]"/></short></flag>
+    <flag name="updatetree"><short>fromroot toroot [<ref name="force"/> <ref name="nocheck"/> <ref name="merge"/> <ref name="delete]"/></short></flag>
+    <flag name="downcasefilenames"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag>
+    <flag name="stripformfeeds"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag>
+    <flag name="showfont"><short>filename</short></flag>
+    <flag name="encmake"><short>afmfile encodingname</short></flag>
+    <flag name="tpmmake"><short>tpm file (run in texmf root)</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/textools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>TeXUtil 9.1.0</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">TeXUtil 9.1.0 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--references</th><td></td><td>convert tui file into tuo file</td></tr>
+        <tr><th>--figures</th><td></td><td>generate figure dimensions file</td></tr>
+        <tr><th>--logfile</th><td></td><td>filter essential log messages</td></tr>
+        <tr><th>--purgefiles</th><td></td><td>remove most temporary files</td></tr>
+        <tr><th>--purgeallfiles</th><td></td><td>remove all temporary files</td></tr>
+        <tr><th>--documentation</th><td></td><td>generate documentation file from source</td></tr>
+        <tr><th>--analyzefile</th><td></td><td>analyze pdf file</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,45 @@
+.TH "texutil" "1" "01-01-2023" "version 9.1.0" "TeXUtil"
+.SH NAME
+ texutil - TeXUtil
+.SH SYNOPSIS
+.B texutil [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXUtil
+.SH OPTIONS
+.TP
+.B --references
+convert tui file into tuo file
+.TP
+.B --figures
+generate figure dimensions file
+.TP
+.B --logfile
+filter essential log messages
+.TP
+.B --purgefiles
+remove most temporary files
+.TP
+.B --purgeallfiles
+remove all temporary files
+.TP
+.B --documentation
+generate documentation file from source
+.TP
+.B --analyzefile
+analyze pdf file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">texutil</entry>
+  <entry name="detail">TeXUtil</entry>
+  <entry name="version">9.1.0</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="references"><short>convert tui file into tuo file</short></flag>
+    <flag name="figures"><short>generate figure dimensions file</short></flag>
+    <flag name="logfile"><short>filter essential log messages</short></flag>
+    <flag name="purgefiles"><short>remove most temporary files</short></flag>
+    <flag name="purgeallfiles"><short>remove all temporary files</short></flag>
+    <flag name="documentation"><short>generate documentation file from source</short></flag>
+    <flag name="analyzefile"><short>analyze pdf file</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>TMFTools 1.2.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">TMFTools 1.2.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--analyze</th><td></td><td>[--strict --sort --rootpath --treepath --delete --force] [pattern]</td></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--serve</th><td></td><td>act as kpse server</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,30 @@
+.TH "tmftools" "1" "01-01-2023" "version 1.1.0" "TMFTools"
+.SH NAME
+ tmftools - TMFTools
+.SH SYNOPSIS
+.B tmftools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TMFTools
+.SH OPTIONS
+.TP
+.B --analyze
+[--strict --sort --rootpath --treepath --delete --force] [pattern]
+.TP
+.B --serve
+act as kpse server
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">tmftools</entry>
+  <entry name="detail">TMFTools</entry>
+  <entry name="version">1.1.0</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="analyze"><short>[<ref name="strict"/> <ref name="sort"/> <ref name="rootpath"/> <ref name="treepath"/> <ref name="delete"/> <ref name="force"/>] [pattern]</short></flag>
+   </subcategory>
+   <subcategory>
+    <flag name="serve"><short>act as kpse server</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!-- compare with lmx framework variant -->
+
+<!--
+    filename : context-base.xml
+    comment  : companion to mtx-server-ctx-startup.tex
+    author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
+    copyright: PRAGMA ADE / ConTeXt Development Team
+    license  : see context related readme files
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>XMLTools 1.2.1</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+                <style type="text/css">
+            body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } .invisible { visibility: hidden; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90!
 %; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } 
+        </style>
+        <style type="text/css">
+                    </style>
+                    </head>
+        <body>
+            <div id="top">            <div id="top-one">
+                <div id="top-two">XMLTools 1.2.1 </div>
+            </div>
+        </div>
+        <div id="bottom">            <div id="bottom-one">
+                <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context at ntg.nl | website: http://www.pragma-ade.nl</div>
+            </div>
+        </div>
+        <div id="left"></div>
+        <div id="right"></div>
+        <div id="main">
+            <div id='main-settings'>
+                <h1>Command line options</h1>
+<table>
+    <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr>
+        <tr><th/><td/><td/></tr>
+        <tr><th>--dir</th><td></td><td>generate directory listing</td></tr>
+        <tr><th>--mmlpages</th><td></td><td>generate graphic from mathml</td></tr>
+        <tr><th>--analyze</th><td></td><td>report entities and elements [--utf --process]</td></tr>
+        <tr><th>--cleanup</th><td></td><td>cleanup xml file [--force]</td></tr>
+        <tr><th>--enhance</th><td></td><td>enhance xml file (partial)</td></tr>
+        <tr><th>--filter</th><td></td><td>filter elements from xml file [--element]</td></tr>
+        <tr><th>--dir</th><td></td><td>generate ddirectory listing</td></tr>
+    </table>
+<br/>
+            </div>
+        </div>
+        </body>
+</html>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,45 @@
+.TH "xmltools" "1" "01-01-2023" "version 1.2.2" "XMLTools"
+.SH NAME
+ xmltools - XMLTools
+.SH SYNOPSIS
+.B xmltools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B XMLTools
+.SH OPTIONS
+.TP
+.B --dir
+generate directory listing
+.TP
+.B --mmlpages
+generate graphic from mathml
+.TP
+.B --analyze
+report entities and elements [--utf --process]
+.TP
+.B --cleanup
+cleanup xml file [--force]
+.TP
+.B --enhance
+enhance xml file (partial)
+.TP
+.B --filter
+filter elements from xml file [--element]
+.TP
+.B --dir
+generate ddirectory listing
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
===================================================================
--- trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<application>
+ <metadata>
+  <entry name="name">xmltools</entry>
+  <entry name="detail">XMLTools</entry>
+  <entry name="version">1.2.2</entry>
+ </metadata>
+ <flags>
+  <category name="basic">
+   <subcategory>
+    <flag name="dir"><short>generate directory listing</short></flag>
+    <flag name="mmlpages"><short>generate graphic from mathml</short></flag>
+    <flag name="analyze"><short>report entities and elements [<ref name="utf"/> <ref name="process"/>]</short></flag>
+    <flag name="cleanup"><short>cleanup xml file [<ref name="force"/>]</short></flag>
+    <flag name="enhance"><short>enhance xml file (partial)</short></flag>
+    <flag name="filter"><short>filter elements from xml file [<ref name="element"/>]</short></flag>
+    <flag name="dir"><short>generate ddirectory listing</short></flag>
+   </subcategory>
+  </category>
+ </flags>
+</application>


Property changes on: trunk/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/man/man1/luatools.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/luatools.1	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/man/man1/luatools.1	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,78 @@
+.TH "luatools" "1" "01-01-2023" "version 1.35" "ConTeXt TDS Management Tool (aka luatools)"
+.SH NAME
+ luatools - ConTeXt TDS Management Tool (aka luatools)
+.SH SYNOPSIS
+.B luatools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Management Tool (aka luatools)
+.SH OPTIONS
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --make
+[or --ini] make luatex format
+.TP
+.B --run
+[or --fmt] run luatex format
+.TP
+.B --compile
+assemble and compile lua inifile
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --all
+show all found files
+.TP
+.B --format=str
+filter cf format specification (default 'tex', use 'any' for any match)
+.TP
+.B --pattern=str
+filter variables
+.TP
+.B --trackers=list
+enable given trackers
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/man/man1/luatools.1
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf	2023-12-13 09:58:31 UTC (rev 69108)
+++ trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf	2023-12-13 10:01:49 UTC (rev 69109)

Property changes on: trunk/Master/texmf-dist/doc/man/man1/luatools.man1.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/man/man1/texmfstart.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/texmfstart.1	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/man/man1/texmfstart.1	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,153 @@
+.TH "mtxrun" "1" "01-01-2023" "version 1.33" "ConTeXt TDS Runner Tool"
+.SH NAME
+ mtxrun - ConTeXt TDS Runner Tool
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
+.SH OPTIONS
+.TP
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
+.TP
+.B --evaluate
+run code passed on the commandline (between quotes) (=loop) (exit|quit aborts)
+.TP
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
+.TP
+.B --resolve
+resolve prefixed arguments
+.TP
+.B --ctxlua
+run internally (using preloaded libs)
+.TP
+.B --internal
+run script using built in libraries (same as --ctxlua)
+.TP
+.B --locate
+locate given filename in database (default) or system (--first --all --detail)
+.TP
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
+.TP
+.B --path=runpath
+go to given path before execution
+.TP
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
+.TP
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
+.TP
+.B --makestubs
+create stubs for (context related) scripts
+.TP
+.B --removestubs
+remove stubs (context related) scripts
+.TP
+.B --stubpath=binpath
+paths where stubs wil be written
+.TP
+.B --windows
+create windows (mswin) stubs
+.TP
+.B --unix
+create unix (linux) stubs
+.TP
+.B --addbinarypath
+prepend the (found) binarypath to runners
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
+.TP
+.B --systeminfo=str
+show current operating system, processor, etc
+.TP
+.B --edit
+launch editor with found file
+.TP
+.B --launch
+launch files like manuals, assumes os support (--all,--list)
+.TP
+.B --timedrun
+run a script and time its run
+.TP
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
+.TP
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
+.TP
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
+.TP
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --resolve-path
+expand variable (completely resolve paths)
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context at ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net


Property changes on: trunk/Master/texmf-dist/doc/man/man1/texmfstart.1
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf	2023-12-13 09:58:31 UTC (rev 69108)
+++ trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf	2023-12-13 10:01:49 UTC (rev 69109)

Property changes on: trunk/Master/texmf-dist/doc/man/man1/texmfstart.man1.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmin.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmin.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmin.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmin[
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/space
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmin.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmit.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmit.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmit.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmit[
+/Gamma
+/Delta
+/Theta
+/Lambda
+/Xi
+/Pi
+/Sigma
+/Upsilon
+/Phi
+/Psi
+/Omega
+/ff
+/fi
+/fl
+/ffi
+/ffl
+/dotlessi
+/dotlessj
+/grave
+/acute
+/caron
+/breve
+/macron
+/ring
+/cedilla
+/germandbls
+/ae
+/oe
+/oslash
+/AE
+/OE
+/Oslash
+/suppress
+/exclam
+/quotedblright
+/numbersign
+/sterling
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/exclamdown
+/equal
+/questiondown
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/quotedblleft
+/bracketright
+/circumflex
+/dotaccent
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/endash
+/emdash
+/hungarumlaut
+/tilde
+/dieresis
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmit.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmitt.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmitt.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmitt.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmitt[
+/Gamma
+/Delta
+/Theta
+/Lambda
+/Xi
+/Pi
+/Sigma
+/Upsilon
+/Phi
+/Psi
+/Omega
+/arrowup
+/arrowdown
+/quotesingle
+/exclamdown
+/questiondown
+/dotlessi
+/dotlessj
+/grave
+/acute
+/caron
+/breve
+/macron
+/ring
+/cedilla
+/germandbls
+/ae
+/oe
+/oslash
+/AE
+/OE
+/Oslash
+/visiblespace
+/exclam
+/quotedbl
+/numbersign
+/sterling
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/less
+/equal
+/greater
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/backslash
+/bracketright
+/asciicircum
+/underscore
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/braceleft
+/bar
+/braceright
+/asciitilde
+/dieresis
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmitt.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmrm.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmrm.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmrm.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmrm[
+/Gamma
+/Delta
+/Theta
+/Lambda
+/Xi
+/Pi
+/Sigma
+/Upsilon
+/Phi
+/Psi
+/Omega
+/ff
+/fi
+/fl
+/ffi
+/ffl
+/dotlessi
+/dotlessj
+/grave
+/acute
+/caron
+/breve
+/macron
+/ring
+/cedilla
+/germandbls
+/ae
+/oe
+/oslash
+/AE
+/OE
+/Oslash
+/suppress
+/exclam
+/quotedblright
+/numbersign
+/dollar
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/exclamdown
+/equal
+/questiondown
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/quotedblleft
+/bracketright
+/circumflex
+/dotaccent
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/endash
+/emdash
+/hungarumlaut
+/tilde
+/dieresis
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmrm.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmsc.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmsc.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmsc.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmsc[
+/Gamma
+/Delta
+/Theta
+/Lambda
+/Xi
+/Pi
+/Sigma
+/Upsilon
+/Phi
+/Psi
+/Omega
+/arrowup
+/arrowdown
+/quotesingle
+/exclamdown
+/questiondown
+/dotlessi
+/dotlessj
+/grave
+/acute
+/caron
+/breve
+/macron
+/ring
+/cedilla
+/germandbls
+/ae
+/oe
+/oslash
+/AE
+/OE
+/Oslash
+/suppress
+/exclam
+/quotedblright
+/numbersign
+/dollar
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/less
+/equal
+/greater
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/quotedblleft
+/bracketright
+/circumflex
+/dotaccent
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/endash
+/emdash
+/hungarumlaut
+/tilde
+/dieresis
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmsc.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmtt.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/cmtt.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/cmtt.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,258 @@
+/enccmtt[
+/Gamma
+/Delta
+/Theta
+/Lambda
+/Xi
+/Pi
+/Sigma
+/Upsilon
+/Phi
+/Psi
+/Omega
+/arrowup
+/arrowdown
+/quotesingle
+/exclamdown
+/questiondown
+/dotlessi
+/dotlessj
+/grave
+/acute
+/caron
+/breve
+/macron
+/ring
+/cedilla
+/germandbls
+/ae
+/oe
+/oslash
+/AE
+/OE
+/Oslash
+/visiblespace
+/exclam
+/quotedbl
+/numbersign
+/dollar
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/less
+/equal
+/greater
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/backslash
+/bracketright
+/asciicircum
+/underscore
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/braceleft
+/bar
+/braceright
+/asciitilde
+/dieresis
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/cmtt.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/ec-2004.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/ec-2004.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/ec-2004.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,82 @@
+%
+%   This is the EC encoding.
+%
+%   These are the ligs and kerns in addition to those found in the
+%   AFM file.  (The only ligs in the Times-Roman.afm file are the
+%   fi and fl ligatures.)
+%
+% LIGKERN space l =: lslash ; space L =: Lslash ;
+% LIGKERN question quoteleft =: questiondown ; exclam quoteleft =: exclamdown ;
+% LIGKERN hyphen hyphen =: endash ; endash hyphen =: emdash ;
+% LIGKERN quoteleft quoteleft =: quotedblleft ;
+% LIGKERN quoteright quoteright =: quotedblright ;
+%
+%   We blow away kerns to and from spaces (TeX doesn't have a
+%   space) and also remove any kerns from the numbers (although
+%   the only kern pair that mentions a number in Times-Roman.afm
+%   is one one.)
+%
+% LIGKERN space {} * ; * {} space ; zero {} * ; * {} zero ;
+% LIGKERN one {} * ; * {} one ; two {} * ; * {} two ;
+% LIGKERN three {} * ; * {} three ; four {} * ; * {} four ;
+% LIGKERN five {} * ; * {} five ; six {} * ; * {} six ;
+% LIGKERN seven {} * ; * {} seven ; eight {} * ; * {} eight ;
+% LIGKERN nine {} * ; * {} nine ;
+% LIGKERN comma comma =: quotedblbase ; less less =: guillemotleft ;
+% LIGKERN greater greater =: guillemotright ;
+%
+/ECEncoding [          % now 256 chars follow
+% 0x00
+  /grave /acute /circumflex /tilde /dieresis /hungarumlaut /ring /caron
+  /breve /macron /dotaccent /cedilla
+  /ogonek /quotesinglbase /guilsinglleft /guilsinglright
+% 0x10
+  /quotedblleft /quotedblright /quotedblbase /guillemotleft 
+  /guillemotright /endash /emdash /cwm
+  /zeroinferior /dotlessi /dotlessj /ff /fi /fl /ffi /ffl
+% 0x20
+  /visualspace /exclam /quotedbl /numbersign
+  /dollar /percent /ampersand /quoteright
+  /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash
+% 0x30
+  /zero /one /two /three /four /five /six /seven
+  /eight /nine /colon /semicolon /less /equal /greater /question
+% 0x40
+  /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O
+% 0x50
+  /P /Q /R /S /T /U /V /W
+  /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore
+% 0x60
+  /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o
+% 0x70
+  /p /q /r /s /t /u /v /w
+  /x /y /z /braceleft /bar /braceright /asciitilde /hyphen
+% 0x80
+  /Abreve /Aogonek /Cacute /Ccaron /Dcaron /Ecaron /Eogonek /Gbreve
+  /Lacute /Lcaron /Lslash /Nacute /Ncaron /Ng /Ohungarumlaut /Racute
+% 0x90
+  /Rcaron /Sacute /Scaron /Scedilla
+  /Tcaron /Tcedilla /Uhungarumlaut /Uring
+  /Ydieresis /Zacute /Zcaron /Zdotaccent /IJ /Idotaccent /dbar /section
+% 0xA0
+  /abreve /aogonek /cacute /ccaron /dcaron /ecaron /eogonek /gbreve
+  /lacute /lcaron /lslash /nacute /ncaron /ng /ohungarumlaut /racute
+% 0xB0
+  /rcaron /sacute /scaron /scedilla
+  /tquoteright /tcedilla /uhungarumlaut /uring
+  /ldot /zacute /zcaron /zdotaccent /ij /exclamdown /questiondown /sterling
+% 0xC0
+  /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla
+  /Egrave /Eacute /Ecircumflex /Edieresis
+  /Igrave /Iacute /Icircumflex /Idieresis
+% 0xD0
+  /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /OE
+  /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /Germandbls
+% 0xE0
+  /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla
+  /egrave /eacute /ecircumflex /edieresis
+  /igrave /iacute /icircumflex /idieresis
+% 0xF0
+  /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /oe
+  /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /germandbls
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/ec-2004.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/q-8r.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/q-8r.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/q-8r.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,264 @@
+% This file could belong to the TeX Gyre collection of fonts,
+% but is only needed and thus distributed with ConTeXt macro package.
+%
+% It provides 8r encoding compatible with TeX Gyre fonts and is used to enable
+% substituting Adobe fonts by TeX Gyre in pxfonts & txfonts.
+%
+/encq8r [
+/.notdef
+/dotaccent
+/fi
+/fl
+/fraction
+/hungarumlaut
+/Lslash
+/lslash
+/ogonek
+/ring
+/.notdef
+/breve
+/minus
+/.notdef
+/Zcaron
+/zcaron
+/caron
+/dotlessi
+/dotlessj
+/ff
+/ffi
+/ffl
+/notequal
+/infinity
+/lessequal
+/greaterequal
+/partialdiff
+/summation
+/product
+/pi
+/grave
+/quotesingle
+/space
+/exclam
+/quotedbl
+/numbersign
+/dollar
+/percent
+/ampersand
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+/zero
+/one
+/two
+/three
+/four
+/five
+/six
+/seven
+/eight
+/nine
+/colon
+/semicolon
+/less
+/equal
+/greater
+/question
+/at
+/A
+/B
+/C
+/D
+/E
+/F
+/G
+/H
+/I
+/J
+/K
+/L
+/M
+/N
+/O
+/P
+/Q
+/R
+/S
+/T
+/U
+/V
+/W
+/X
+/Y
+/Z
+/bracketleft
+/backslash
+/bracketright
+/asciicircum
+/underscore
+/quoteleft
+/a
+/b
+/c
+/d
+/e
+/f
+/g
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/braceleft
+/bar
+/braceright
+/asciitilde
+/.notdef
+/Euro
+/integral
+/quotesinglbase
+/florin
+/quotedblbase
+/ellipsis
+/dagger
+/daggerdbl
+/circumflex
+/perthousand
+/Scaron
+/guilsinglleft
+/OE
+/Omega
+/radical
+/approxequal
+/.notdef
+/.notdef
+/.notdef
+/quotedblleft
+/quotedblright
+/bullet
+/endash
+/emdash
+/tilde
+/trademark
+/scaron
+/guilsinglright
+/oe
+/Delta
+/lozenge
+/Ydieresis
+/.notdef
+/exclamdown
+/cent
+/sterling
+/currency
+/yen
+/brokenbar
+/section
+/dieresis
+/copyright
+/ordfeminine
+/guillemotleft
+/logicalnot
+/hyphen
+/registered
+/macron
+/degree
+/plusminus
+/two.superior
+/three.superior
+/acute
+/mu
+/paragraph
+/periodcentered
+/cedilla
+/one.superior
+/ordmasculine
+/guillemotright
+/onequarter
+/onehalf
+/threequarters
+/questiondown
+/Agrave
+/Aacute
+/Acircumflex
+/Atilde
+/Adieresis
+/Aring
+/AE
+/Ccedilla
+/Egrave
+/Eacute
+/Ecircumflex
+/Edieresis
+/Igrave
+/Iacute
+/Icircumflex
+/Idieresis
+/Eth
+/Ntilde
+/Ograve
+/Oacute
+/Ocircumflex
+/Otilde
+/Odieresis
+/multiply
+/Oslash
+/Ugrave
+/Uacute
+/Ucircumflex
+/Udieresis
+/Yacute
+/Thorn
+/germandbls
+/agrave
+/aacute
+/acircumflex
+/atilde
+/adieresis
+/aring
+/ae
+/ccedilla
+/egrave
+/eacute
+/ecircumflex
+/edieresis
+/igrave
+/iacute
+/icircumflex
+/idieresis
+/eth
+/ntilde
+/ograve
+/oacute
+/ocircumflex
+/otilde
+/odieresis
+/divide
+/oslash
+/ugrave
+/uacute
+/ucircumflex
+/udieresis
+/yacute
+/thorn
+/ydieresis
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/q-8r.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/context/teff-trinite.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/context/teff-trinite.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/context/teff-trinite.enc	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,260 @@
+% Encoding file, generated by textools.rb from TriniteNo2RomCon-Regular.afm
+
+/tefftriniteencoding [
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /breve
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /caron
+  /dotlessi
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /fraction
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /space
+  /exclam
+  /quotedbl
+  /numbersign
+  /dollar
+  /percent
+  /ampersand
+  /quotesingle
+  /parenleft
+  /parenright
+  /asterisk
+  /plus
+  /comma
+  /hyphen
+  /period
+  /slash
+  /zero
+  /one
+  /two
+  /three
+  /four
+  /five
+  /six
+  /seven
+  /eight
+  /nine
+  /colon
+  /semicolon
+  /less
+  /equal
+  /greater
+  /question
+  /at
+  /A
+  /B
+  /C
+  /D
+  /E
+  /F
+  /G
+  /H
+  /I
+  /J
+  /K
+  /L
+  /M
+  /N
+  /O
+  /P
+  /Q
+  /R
+  /S
+  /T
+  /U
+  /V
+  /W
+  /X
+  /Y
+  /Z
+  /bracketleft
+  /backslash
+  /bracketright
+  /.notdef
+  /underscore
+  /grave
+  /a
+  /b
+  /c
+  /d
+  /e
+  /f
+  /g
+  /h
+  /i
+  /j
+  /k
+  /l
+  /m
+  /n
+  /o
+  /p
+  /q
+  /r
+  /s
+  /t
+  /u
+  /v
+  /w
+  /x
+  /y
+  /z
+  /braceleft
+  /bar
+  /braceright
+  /.notdef
+  /.notdef
+  /Euro
+  /.notdef
+  /.notdef
+  /florin
+  /quotedblbase
+  /ellipsis
+  /dagger
+  /daggerdbl
+  /circumflex
+  /perthousand
+  /.notdef
+  /guilsinglleft
+  /OE
+  /.notdef
+  /.notdef
+  /.notdef
+  /.notdef
+  /quoteleft
+  /quoteright
+  /quotedblleft
+  /quotedblright
+  /bullet
+  /endash
+  /emdash
+  /tilde
+  /.notdef
+  /.notdef
+  /guilsinglright
+  /oe
+  /.notdef
+  /.notdef
+  /Ydieresis
+  /.notdef
+  /exclamdown
+  /cent
+  /sterling
+  /.notdef
+  /.notdef
+  /.notdef
+  /section
+  /dieresis
+  /copyright
+  /.notdef
+  /guillemotleft
+  /.notdef
+  /.notdef
+  /.notdef
+  /macron
+  /degree
+  /.notdef
+  /.notdef
+  /.notdef
+  /acute
+  /.notdef
+  /paragraph
+  /multiply
+  /cedilla
+  /.notdef
+  /.notdef
+  /guillemotright
+  /.notdef
+  /.notdef
+  /.notdef
+  /questiondown
+  /Agrave
+  /Aacute
+  /Acircumflex
+  /Atilde
+  /Adieresis
+  /Aring
+  /AE
+  /Ccedilla
+  /Egrave
+  /Eacute
+  /Ecircumflex
+  /Edieresis
+  /Igrave
+  /Iacute
+  /Icircumflex
+  /Idieresis
+  /.notdef
+  /Ntilde
+  /Ograve
+  /Oacute
+  /Ocircumflex
+  /Otilde
+  /Odieresis
+  /.notdef
+  /Oslash
+  /Ugrave
+  /Uacute
+  /Ucircumflex
+  /Udieresis
+  /.notdef
+  /.notdef
+  /germandbls
+  /agrave
+  /aacute
+  /acircumflex
+  /atilde
+  /adieresis
+  /aring
+  /ae
+  /ccedilla
+  /egrave
+  /eacute
+  /ecircumflex
+  /edieresis
+  /igrave
+  /iacute
+  /icircumflex
+  /idieresis
+  /.notdef
+  /ntilde
+  /ograve
+  /oacute
+  /ocircumflex
+  /otilde
+  /odieresis
+  /.notdef
+  /oslash
+  /ugrave
+  /uacute
+  /ucircumflex
+  /udieresis
+  /.notdef
+  /.notdef
+  /ydieresis
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/context/teff-trinite.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/dvips/context/contnav.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/dvips/context/contnav.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/dvips/context/contnav.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1 @@
+contnav ContextNavigation <contnav.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/dvips/context/contnav.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/8r-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/8r-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/8r-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,135 @@
+% courier / urw
+
+ucrb8r  NimbusMonL-Bold          <8r.enc <ucrb8a.pfb
+ucrbo8r NimbusMonL-BoldObli      <8r.enc <ucrbo8a.pfb
+ucrr8r  NimbusMonL-Regu          <8r.enc <ucrr8a.pfb
+ucrro8r NimbusMonL-ReguObli      <8r.enc <ucrro8a.pfb
+
+% courier / adobe
+
+pcrb8r  NimbusMonL-Bold          <8r.enc <ucrb8a.pfb
+pcrbo8r NimbusMonL-BoldObli      <8r.enc <ucrbo8a.pfb
+pcrr8r  NimbusMonL-Regu          <8r.enc <ucrr8a.pfb
+pcrro8r NimbusMonL-ReguObli      <8r.enc <ucrro8a.pfb
+
+% helvetica / urw
+
+uhvb8r  NimbusSanL-Bold          <8r.enc <uhvb8a.pfb
+uhvbo8r NimbusSanL-BoldItal      <8r.enc <uhvbo8a.pfb
+uhvr8r  NimbusSanL-Regu          <8r.enc <uhvr8a.pfb
+uhvro8r NimbusSanL-ReguItal      <8r.enc <uhvro8a.pfb
+
+% helvetica / adobe
+
+phvb8r  NimbusSanL-Bold          <8r.enc <uhvb8a.pfb
+phvbo8r NimbusSanL-BoldItal      <8r.enc <uhvbo8a.pfb
+phvr8r  NimbusSanL-Regu          <8r.enc <uhvr8a.pfb
+phvro8r NimbusSanL-ReguItal      <8r.enc <uhvro8a.pfb
+
+% times / urw
+
+utmb8r  NimbusRomNo9L-Medi       <8r.enc <utmb8a.pfb
+utmbi8r NimbusRomNo9L-MediItal   <8r.enc <utmbi8a.pfb
+utmr8r  NimbusRomNo9L-Regu       <8r.enc <utmr8a.pfb
+utmri8r NimbusRomNo9L-ReguItal   <8r.enc <utmri8a.pfb
+
+utmbo8r NimbusRomNo9L-Medi       ".167 SlantFont" <8r.enc <utmb8a.pfb
+utmro8r NimbusRomNo9L-Regu       ".167 SlantFont" <8r.enc <utmr8a.pfb
+
+% times / adobe
+
+ptmb8r  NimbusRomNo9L-Medi       <8r.enc <utmb8a.pfb
+ptmbi8r NimbusRomNo9L-MediItal   <8r.enc <utmbi8a.pfb
+ptmr8r  NimbusRomNo9L-Regu       <8r.enc <utmr8a.pfb
+ptmri8r NimbusRomNo9L-ReguItal   <8r.enc <utmri8a.pfb
+
+ptmbo8r NimbusRomNo9L-Medi       ".167 SlantFont" <8r.enc <utmb8a.pfb
+ptmro8r NimbusRomNo9L-Regu       ".167 SlantFont" <8r.enc <utmr8a.pfb
+
+% palatino / urw
+
+uplb8r  URWPalladioL-Bold        <8r.enc <uplb8a.pfb
+uplbi8r URWPalladioL-BoldItal    <8r.enc <uplbi8a.pfb
+uplr8r  URWPalladioL-Roma        <8r.enc <uplr8a.pfb
+uplri8r URWPalladioL-Ital        <8r.enc <uplri8a.pfb
+
+uplbo8r URWPalladioL-Bold        ".167 SlantFont" <8r.enc <uplb8a.pfb
+uplro8r URWPalladioL-Roma        ".167 SlantFont" <8r.enc <uplr8a.pfb
+
+% palatino / adobe
+
+pplb8r  URWPalladioL-Bold        <8r.enc <uplb8a.pfb
+pplbi8r URWPalladioL-BoldItal    <8r.enc <uplbi8a.pfb
+pplr8r  URWPalladioL-Roma        <8r.enc <uplr8a.pfb
+pplri8r URWPalladioL-Ital        <8r.enc <uplri8a.pfb
+
+pplbo8r URWPalladioL-Bold        ".167 SlantFont" <8r.enc <uplb8a.pfb
+pplro8r URWPalladioL-Roma        ".167 SlantFont" <8r.enc <uplr8a.pfb
+
+% bookman / urw
+
+ubkd8r  URWBookmanL-DemiBold     <8r.enc <ubkd8a.pfb
+ubkdi8r URWBookmanL-DemiBoldItal <8r.enc <ubkdi8a.pfb
+ubkl8r  URWBookmanL-Ligh         <8r.enc <ubkl8a.pfb
+ubkli8r URWBookmanL-LighItal     <8r.enc <ubkli8a.pfb
+
+ubkdo8r URWBookmanL-DemiBold     ".167 SlantFont" <8r.enc <ubkd8a.pfb
+ubklo8r URWBookmanL-Ligh         ".167 SlantFont" <8r.enc <ubkl8a.pfb
+
+% bookman / adobe
+
+pbkd8r  URWBookmanL-DemiBold     <8r.enc <ubkd8a.pfb
+pbkdi8r URWBookmanL-DemiBoldItal <8r.enc <ubkdi8a.pfb
+pbkl8r  URWBookmanL-Ligh         <8r.enc <ubkl8a.pfb
+pbkli8r URWBookmanL-LighItal     <8r.enc <ubkli8a.pfb
+
+pbkdo8r URWBookmanL-DemiBold     ".167 SlantFont" <8r.enc <ubkd8a.pfb
+pbklo8r URWBookmanL-Ligh         ".167 SlantFont" <8r.enc <ubkl8a.pfb
+
+% chancery / urw
+
+uzcmi8r URWChanceryL-MediItal    <8r.enc <uzcmi8a.pfb
+
+% chancery / adobe
+
+pzcmi8r URWChanceryL-MediItal    <8r.enc <uzcmi8a.pfb
+
+% schoolbook / urw
+
+uncb8r  CenturySchL-Bold         <8r.enc <uncb8a.pfb
+uncbi8r CenturySchL-BoldItal     <8r.enc <uncbi8a.pfb
+uncr8r  CenturySchL-Roma         <8r.enc <uncr8a.pfb
+uncri8r CenturySchL-Ital         <8r.enc <uncri8a.pfb
+
+uncbo8r CenturySchL-Bold         ".167 SlantFont" <8r.enc <uncb8a.pfb
+uncro8r CenturySchL-Roma         ".167 SlantFont" <8r.enc <uncr8a.pfb
+
+% schoolbook / adobe
+
+pncb8r  CenturySchL-Bold         <8r.enc <uncb8a.pfb
+pncbi8r CenturySchL-BoldItal     <8r.enc <uncbi8a.pfb
+pncr8r  CenturySchL-Roma         <8r.enc <uncr8a.pfb
+pncri8r CenturySchL-Ital         <8r.enc <uncri8a.pfb
+
+pncbo8r CenturySchL-Bold         ".167 SlantFont" <8r.enc <uncb8a.pfb
+pncro8r CenturySchL-Roma         ".167 SlantFont" <8r.enc <uncr8a.pfb
+
+% utopia
+
+putb8r  Utopia-Bold              <8r.enc <putb8a.pfb
+putbi8r Utopia-BoldItalic        <8r.enc <putbi8a.pfb
+putr8r  Utopia-Regular           <8r.enc <putr8a.pfb
+putri8r Utopia-Italic            <8r.enc <putri8a.pfb
+
+putbo8r Utopia-Bold              ".167 SlantFont" <8r.enc <putb8a.pfb
+putro8r Utopia-Regular           ".167 SlantFont" <8r.enc <putr8a.pfb
+
+% charter
+
+bchb8r  CharterBT-Bold           <8r.enc <bchb8a.pfb
+bchbi8r CharterBT-BoldItalic     <8r.enc <bchbi8a.pfb
+bchr8r  CharterBT-Roman          <8r.enc <bchr8a.pfb
+bchri8r CharterBT-Italic         <8r.enc <bchri8a.pfb
+
+bchbo8r CharterBT-Bold           ".167 SlantFont" <8r.enc <bchb8a.pfb
+bchro8r CharterBT-Roman          ".167 SlantFont" <8r.enc <bchr8a.pfb
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/8r-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,135 @@
+% courier / urw
+
+ucrb8t  NimbusMonL-Bold          <ec.enc <ucrb8a.pfb
+ucrbo8t NimbusMonL-BoldObli      <ec.enc <ucrbo8a.pfb
+ucrr8t  NimbusMonL-Regu          <ec.enc <ucrr8a.pfb
+ucrro8t NimbusMonL-ReguObli      <ec.enc <ucrro8a.pfb
+
+% courier / adobe
+
+pcrb8t  NimbusMonL-Bold          <ec.enc <ucrb8a.pfb
+pcrbo8t NimbusMonL-BoldObli      <ec.enc <ucrbo8a.pfb
+pcrr8t  NimbusMonL-Regu          <ec.enc <ucrr8a.pfb
+pcrro8t NimbusMonL-ReguObli      <ec.enc <ucrro8a.pfb
+
+% helvetica / urw
+
+uhvb8t  NimbusSanL-Bold          <ec.enc <uhvb8a.pfb
+uhvbo8t NimbusSanL-BoldItal      <ec.enc <uhvbo8a.pfb
+uhvr8t  NimbusSanL-Regu          <ec.enc <uhvr8a.pfb
+uhvro8t NimbusSanL-ReguItal      <ec.enc <uhvro8a.pfb
+
+% helvetica / adobe
+
+phvb8t  NimbusSanL-Bold          <ec.enc <uhvb8a.pfb
+phvbo8t NimbusSanL-BoldItal      <ec.enc <uhvbo8a.pfb
+phvr8t  NimbusSanL-Regu          <ec.enc <uhvr8a.pfb
+phvro8t NimbusSanL-ReguItal      <ec.enc <uhvro8a.pfb
+
+% times / urw
+
+utmb8t  NimbusRomNo9L-Medi       <ec.enc <utmb8a.pfb
+utmbi8t NimbusRomNo9L-MediItal   <ec.enc <utmbi8a.pfb
+utmr8t  NimbusRomNo9L-Regu       <ec.enc <utmr8a.pfb
+utmri8t NimbusRomNo9L-ReguItal   <ec.enc <utmri8a.pfb
+
+utmbo8t NimbusRomNo9L-Medi       ".167 SlantFont" <ec.enc <utmb8a.pfb
+utmro8t NimbusRomNo9L-Regu       ".167 SlantFont" <ec.enc <utmr8a.pfb
+
+% times / adobe
+
+ptmb8t  NimbusRomNo9L-Medi       <ec.enc <utmb8a.pfb
+ptmbi8t NimbusRomNo9L-MediItal   <ec.enc <utmbi8a.pfb
+ptmr8t  NimbusRomNo9L-Regu       <ec.enc <utmr8a.pfb
+ptmri8t NimbusRomNo9L-ReguItal   <ec.enc <utmri8a.pfb
+
+ptmbo8t NimbusRomNo9L-Medi       ".167 SlantFont" <ec.enc <utmb8a.pfb
+ptmro8t NimbusRomNo9L-Regu       ".167 SlantFont" <ec.enc <utmr8a.pfb
+
+% palatino / urw
+
+uplb8t  URWPalladioL-Bold        <ec.enc <uplb8a.pfb
+uplbi8t URWPalladioL-BoldItal    <ec.enc <uplbi8a.pfb
+uplr8t  URWPalladioL-Roma        <ec.enc <uplr8a.pfb
+uplri8t URWPalladioL-Ital        <ec.enc <uplri8a.pfb
+
+uplbo8t URWPalladioL-Bold        ".167 SlantFont" <ec.enc <uplb8a.pfb
+uplro8t URWPalladioL-Roma        ".167 SlantFont" <ec.enc <uplr8a.pfb
+
+% palatino / adobe
+
+pplb8t  URWPalladioL-Bold        <ec.enc <uplb8a.pfb
+pplbi8t URWPalladioL-BoldItal    <ec.enc <uplbi8a.pfb
+pplr8t  URWPalladioL-Roma        <ec.enc <uplr8a.pfb
+pplri8t URWPalladioL-Ital        <ec.enc <uplri8a.pfb
+
+pplbo8t URWPalladioL-Bold        ".167 SlantFont" <ec.enc <uplb8a.pfb
+pplro8t URWPalladioL-Roma        ".167 SlantFont" <ec.enc <upplr8a.pfb
+
+% bookman / urw
+
+ubkd8t  URWBookmanL-DemiBold     <ec.enc <ubkd8a.pfb
+ubkdi8t URWBookmanL-DemiBoldItal <ec.enc <ubkdi8a.pfb
+ubkl8t  URWBookmanL-Ligh         <ec.enc <ubkl8a.pfb
+ubkli8t URWBookmanL-LighItal     <ec.enc <ubkli8a.pfb
+
+ubkdo8t URWBookmanL-DemiBold     ".167 SlantFont" <ec.enc <ubkd8a.pfb
+ubklo8t URWBookmanL-Ligh         ".167 SlantFont" <ec.enc <ubkl8a.pfb
+
+% bookman / adobe
+
+pbkd8t  URWBookmanL-DemiBold     <ec.enc <ubkd8a.pfb
+pbkdi8t URWBookmanL-DemiBoldItal <ec.enc <ubkdi8a.pfb
+pbkl8t  URWBookmanL-Ligh         <ec.enc <ubkl8a.pfb
+pbkli8t URWBookmanL-LighItal     <ec.enc <ubkli8a.pfb
+
+pbkdo8t URWBookmanL-DemiBold     ".167 SlantFont" <ec.enc <ubkd8a.pfb
+pbklo8t URWBookmanL-Ligh         ".167 SlantFont" <ec.enc <ubkl8a.pfb
+
+% chancery / urw
+
+uzcmi8t URWChanceryL-MediItal    <ec.enc <uzcmi8a.pfb
+
+% chancery / adobe
+
+pzcmi8t URWChanceryL-MediItal    <ec.enc <uzcmi8a.pfb
+
+% schoolbook / urw
+
+uncb8t  CenturySchL-Bold         <ec.enc <uncb8a.pfb
+uncbi8t CenturySchL-BoldItal     <ec.enc <uncbi8a.pfb
+uncr8t  CenturySchL-Roma         <ec.enc <uncr8a.pfb
+uncri8t CenturySchL-Ital         <ec.enc <uncri8a.pfb
+
+uncbo8t CenturySchL-Bold         ".167 SlantFont" <ec.enc <uncb8a.pfb
+uncro8t CenturySchL-Roma         ".167 SlantFont" <ec.enc <uncr8a.pfb
+
+% schoolbook / adobe
+
+pncb8t  CenturySchL-Bold         <ec.enc <uncb8a.pfb
+pncbi8t CenturySchL-BoldItal     <ec.enc <uncbi8a.pfb
+pncr8t  CenturySchL-Roma         <ec.enc <uncr8a.pfb
+pncri8t CenturySchL-Ital         <ec.enc <uncri8a.pfb
+
+pncbo8t CenturySchL-Bold         ".167 SlantFont" <ec.enc <uncb8a.pfb
+pncro8t CenturySchL-Roma         ".167 SlantFont" <ec.enc <uncr8a.pfb
+
+% utopia
+
+putb8t  Utopia-Bold              <ec.enc <putb8a.pfb
+putbi8t Utopia-BoldItalic        <ec.enc <putbi8a.pfb
+putr8t  Utopia-Regular           <ec.enc <putr8a.pfb
+putri8t Utopia-Italic            <ec.enc <putri8a.pfb
+
+putbo8t Utopia-Bold              ".167 SlantFont" <ec.enc <putb8a.pfb
+putro8t Utopia-Regular           ".167 SlantFont" <ec.enc <putr8a.pfb
+
+% charter
+
+bchb8t  CharterBT-Bold           <ec.enc <bchb8a.pfb
+bchbi8t CharterBT-BoldItalic     <ec.enc <bchbi8a.pfb
+bchr8t  CharterBT-Roman          <ec.enc <bchr8a.pfb
+bchri8t CharterBT-Italic         <ec.enc <bchri8a.pfb
+
+bchbo8t CharterBT-Bold           ".167 SlantFont" <ec.enc <bchb8a.pfb
+bchro8t CharterBT-Roman          ".167 SlantFont" <ec.enc <bchr8a.pfb
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-os-public-lm.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-os-public-lm.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-os-public-lm.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,69 @@
+ec-lmb10 LMRoman10-Demi "enclmecos ReEncodeFont" <lm-ec-os.enc <lmb10.pfb
+ec-lmbo10 LMRoman10-DemiOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbo10.pfb
+ec-lmbx10 LMRoman10-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx10.pfb
+ec-lmbx12 LMRoman12-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx12.pfb
+ec-lmbx5 LMRoman5-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx5.pfb
+ec-lmbx6 LMRoman6-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx6.pfb
+ec-lmbx7 LMRoman7-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx7.pfb
+ec-lmbx8 LMRoman8-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx8.pfb
+ec-lmbx9 LMRoman9-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbx9.pfb
+ec-lmbxi10 LMRoman10-BoldItalic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbxi10.pfb
+ec-lmbxo10 LMRoman10-BoldOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmbxo10.pfb
+ec-lmcsc10 LMRoman10-CapsRegular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmcsc10.pfb
+ec-lmcsco10 LMRoman10-CapsOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmcsco10.pfb
+ec-lmr10 LMRoman10-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr10.pfb
+ec-lmr12 LMRoman12-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr12.pfb
+ec-lmr17 LMRoman17-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr17.pfb
+ec-lmr5 LMRoman5-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr5.pfb
+ec-lmr6 LMRoman6-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr6.pfb
+ec-lmr7 LMRoman7-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr7.pfb
+ec-lmr8 LMRoman8-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr8.pfb
+ec-lmr9 LMRoman9-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmr9.pfb
+ec-lmri10 LMRoman10-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmri10.pfb
+ec-lmri12 LMRoman12-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmri12.pfb
+ec-lmri7 LMRoman7-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmri7.pfb
+ec-lmri8 LMRoman8-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmri8.pfb
+ec-lmri9 LMRoman9-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmri9.pfb
+ec-lmro10 LMRoman10-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmro10.pfb
+ec-lmro12 LMRoman12-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmro12.pfb
+ec-lmro17 LMRoman17-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmro17.pfb
+ec-lmro8 LMRoman8-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmro8.pfb
+ec-lmro9 LMRoman9-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmro9.pfb
+ec-lmss10 LMSans10-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmss10.pfb
+ec-lmss12 LMSans12-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmss12.pfb
+ec-lmss17 LMSans17-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmss17.pfb
+ec-lmss8 LMSans8-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmss8.pfb
+ec-lmss9 LMSans9-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmss9.pfb
+ec-lmssbo10 LMSans10-BoldOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssbo10.pfb
+ec-lmssbx10 LMSans10-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssbx10.pfb
+ec-lmssdc10 LMSans10-DemiCondensed "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssdc10.pfb
+ec-lmssdo10 LMSans10-DemiCondensedOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssdo10.pfb
+ec-lmsso10 LMSans10-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmsso10.pfb
+ec-lmsso12 LMSans12-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmsso12.pfb
+ec-lmsso17 LMSans17-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmsso17.pfb
+ec-lmsso8 LMSans8-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmsso8.pfb
+ec-lmsso9 LMSans9-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmsso9.pfb
+ec-lmssq8 LMSansQuotation8-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssq8.pfb
+ec-lmssqbo8 LMSansQuotation8-BoldOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssqbo8.pfb
+ec-lmssqbx8 LMSansQuotation8-Bold "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssqbx8.pfb
+ec-lmssqo8 LMSansQuotation8-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmssqo8.pfb
+ec-lmtcsc10 LMTypewriter10-CapsRegular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtcsc10.pfb
+ec-lmtcso10 LMTypewriter10-CapsOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtcso10.pfb
+ec-lmtl10 LMTypewriter10-Light "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtl10.pfb
+ec-lmtlo10 LMTypewriter10-LightOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtlo10.pfb
+ec-lmtlc10 LMTypewriter10-LightCondensed "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtlc10.pfb
+ec-lmtlco10 LMTypewriter10-LightCondensedOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtlco10.pfb
+ec-lmtk10 LMTypewriter10-Dark "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtk10.pfb
+ec-lmtko10 LMTypewriter10-DarkOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtko10.pfb
+ec-lmtt10 LMTypewriter10-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtt10.pfb
+ec-lmtt12 LMTypewriter12-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtt12.pfb
+ec-lmtt8 LMTypewriter8-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtt8.pfb
+ec-lmtt9 LMTypewriter9-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtt9.pfb
+ec-lmtti10 LMTypewriter10-Italic "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtti10.pfb
+ec-lmtto10 LMTypewriter10-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmtto10.pfb
+ec-lmvtt10 LMTypewriterVarWd10-Regular "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtt10.pfb
+ec-lmvtto10 LMTypewriterVarWd10-Oblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtto10.pfb
+ec-lmvtl10 LMTypewriterVarWd10-Light "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtl10.pfb
+ec-lmvtlo10 LMTypewriterVarWd10-LightOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtlo10.pfb
+ec-lmvtk10 LMTypewriterVarWd10-Dark "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtk10.pfb
+ec-lmvtko10 LMTypewriterVarWd10-DarkOblique "enclmecos ReEncodeFont" <lm-ec-os.enc <lmvtko10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/ec-os-public-lm.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,224 @@
+% some left-overs
+
+% context
+
+contnav ContextNavigation          <contnav.pfb
+hans    Hans-Regular               <hans.pfb
+hans-sh Hans-sh-Regular            <hans-sh.pfb
+
+% dingbats
+
+uzdr Dingbats                      <uzdr.pfb
+pzdr Dingbats                      <pzdr.pfb
+
+% symbols
+
+usyr StandardSymL                  <usyr.pfb
+
+% ralph
+
+rsfs7  rsfs5                       <rsfs7.pfb
+rsfs5  rsfs7                       <rsfs5.pfb
+rsfs10 rsfs10                      <rsfs10.pfb
+
+% marvosym
+
+fmvr8x  MarVoSym                   <marvosym.pfb
+fmvri8x MarVoSym ".167 SlantFont"  <marvosym.pfb
+
+% xypic
+
+xyatip10 XYATIP10                  <xyatip10.pfb
+xybsql10 XYBSQL10                  <xybsql10.pfb
+xybtip10 XYBTIP10                  <xybtip10.pfb
+xycirc10 XYCIRC10                  <xycirc10.pfb
+xydash10 XYDASH10                  <xydash10.pfb
+
+xycmat10 XYCMAT10                  <xycmat10.pfb
+xycmbt10 XYCMBT10                  <xycmbt10.pfb
+xyeuat10 XYEUAT10                  <xyeuat10.pfb
+xyeubt10 XYEUBT10                  <xyeubt10.pfb
+
+xycmat11 XYCMAT10 "1.1 ExtendFont" <xycmat10.pfb
+xycmbt11 XYCMBT10 "1.1 ExtendFont" <xycmbt10.pfb
+xyeuat11 XYEUAT10 "1.1 ExtendFont" <xyeuat10.pfb
+xyeubt11 XYEUBT10 "1.1 ExtendFont" <xyeubt10.pfb
+
+xycmat12 XYCMAT10 "1.2 ExtendFont" <xycmat10.pfb
+xycmbt12 XYCMBT10 "1.2 ExtendFont" <xycmbt10.pfb
+xyeuat12 XYEUAT10 "1.2 ExtendFont" <xyeuat10.pfb
+xyeubt12 XYEUBT10 "1.2 ExtendFont" <xyeubt10.pfb
+
+% euro
+
+zpeub   EuroSerif-Bold             <zpeub.pfb
+zpeubi  EuroSerif-BoldItalic       <zpeubi.pfb
+zpeubis EuroSans-BoldItalic        <zpeubis.pfb
+zpeubit EuroMono-BoldItalic        <zpeubit.pfb
+zpeubs  EuroSans-Bold              <zpeubs.pfb
+zpeubt  EuroMono-Bold              <zpeubt.pfb
+zpeur   EuroSerif-Regular          <zpeur.pfb
+zpeuri  EuroSerif-Italic           <zpeuri.pfb
+zpeuris EuroSans-Italic            <zpeuris.pfb
+zpeurit EuroMono-Italic            <zpeurit.pfb
+zpeurs  EuroSans-Regular           <zpeurs.pfb
+zpeurt  EuroMono-Regular           <zpeurt.pfb
+
+% not used i think
+
+lasy5      LASY5      <lasy5.pfb
+lasy6      LASY6      <lasy6.pfb
+lasy7      LASY7      <lasy7.pfb
+lasy8      LASY8      <lasy8.pfb
+lasy9      LASY9      <lasy9.pfb
+lasy10     LASY10     <lasy10.pfb
+
+lasyb10    LASYB10    <lasyb10.pfb
+lcircle10  LCIRCLE10  <lcircle1.pfb
+lcirclew10 LCIRCLEW10 <lcirclew.pfb
+lcmss8     LCMSS8     <lcmss8.pfb
+lcmssb8    LCMSSB8    <lcmssb8.pfb
+lcmssi8    LCMSSI8    <lcmssi8.pfb
+line10     LINE10     <line10.pfb
+linew10    LINEW10    <linew10.pfb
+
+wncyb10    WNCYB10    <wncyb10.pfb
+wncyi10    WNCYI10    <wncyi10.pfb
+wncyr10    WNCYR10    <wncyr10.pfb
+wncysc10   WNCYSC10   <wncysc10.pfb
+wncyss10   WNCYSS10   <wncyss10.pfb
+
+manfnt     MANFNT     <manfnt.pfb
+
+% ams
+
+msam5      MSAM5      <msam5.pfb
+msam7      MSAM7      <msam7.pfb
+msam10     MSAM10     <msam10.pfb
+msbm5      MSBM5      <msbm5.pfb
+msbm7      MSBM7      <msbm7.pfb
+msbm10     MSBM10     <msbm10.pfb
+
+% metapost
+
+logo8      LOGO8      <logo8.pfb
+logo9      LOGO9      <logo9.pfb
+logo10     LOGO10     <logo10.pfb
+logobf10   LOGOBF10   <logobf10.pfb
+logosl10   LOGOSL10   <logosl10.pfb
+
+% euler .. used for manuals
+
+euex10 EUEX10 <euex10.pfb
+
+eufb5  EUFB5  <eufb5.pfb
+eufb7  EUFB7  <eufb7.pfb
+eufb10 EUFB10 <eufb10.pfb
+
+eufm5  EUFM5  <eufm5.pfb
+eufm7  EUFM7  <eufm7.pfb
+eufm10 EUFM10 <eufm10.pfb
+
+eurb5  EURB5  <eurb5.pfb
+eurb7  EURB7  <eurb7.pfb
+eurb10 EURB10 <eurb10.pfb
+
+eurm5  EURM5  <eurm5.pfb
+eurm7  EURM7  <eurm7.pfb
+eurm10 EURM10 <eurm10.pfb
+
+eusb5  EUSB5  <eusb5.pfb
+eusb7  EUSB7  <eusb7.pfb
+eusb10 EUSB10 <eusb10.pfb
+
+eusm5  EUSM5  <eusm5.pfb
+eusm7  EUSM7  <eusm7.pfb
+eusm10 EUSM10 <eusm10.pfb
+
+% original
+
+cmtex10   CMTEX10  <cmtex10.pfb
+cmtex8    CMTEX8   <cmtex8.pfb
+cmtex9    CMTEX9   <cmtex9.pfb
+
+cmff10    CMFF10   <cmff10.pfb
+cmfi10    CMFI10   <cmfi10.pfb
+cmfib8    CMFIB8   <cmfib8.pfb
+
+% the latest gust list
+
+cmb10     LMRomanDemi10-Regular     "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmb10.pfb
+cmbx10    LMRoman10-Bold            "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx10.pfb
+cmbx5     LMRoman5-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx5.pfb
+cmbx6     LMRoman6-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx6.pfb
+cmbx7     LMRoman7-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx7.pfb
+cmbx8     LMRoman8-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx8.pfb
+cmbx9     LMRoman9-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbx9.pfb
+cmbxsl10  LMRomanSlant10-Bold       "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmbxo10.pfb
+cmbxti10  LMRoman10-BoldItalic      "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmbxi10.pfb
+cmcsc10   LMRomanCaps10-Regular     "enclmrepcmsc ReEncodeFont"  <lm-rep-cmsc.enc  <lmcsc10.pfb
+cmcscsl10 LMRomanCaps10-Oblique     "enclmrepcmsc ReEncodeFont"  <lm-rep-cmsc.enc  <lmcsco10.pfb
+cmdunh10  LMRomanDunh10-Regular     "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmdunh10.pfb
+cminch    LMSans10-Bold             "enclmrepcmin ReEncodeFont"  <lm-rep-cmin.enc  <lmssbx10.pfb
+cmitt10   LMMono10-Italic           "enclmrepcmitt ReEncodeFont" <lm-rep-cmitt.enc <lmtti10.pfb
+cmr10     LMRoman10-Regular         "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr10.pfb
+cmr12     LMRoman12-Regular         "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr12.pfb
+cmr17     LMRoman17-Regular         "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr17.pfb
+cmr5      LMRoman5-Regular          "enclmrepcmsc ReEncodeFont"  <lm-rep-cmsc.enc  <lmr5.pfb
+cmr6      LMRoman6-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr6.pfb
+cmr7      LMRoman7-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr7.pfb
+cmr8      LMRoman8-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr8.pfb
+cmr9      LMRoman9-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmr9.pfb
+cmsl10    LMRomanSlant10-Regular    "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmro10.pfb
+cmsl12    LMRomanSlant12-Regular    "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmro12.pfb
+cmsl8     LMRomanSlant8-Regular     "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmro8.pfb
+cmsl9     LMRomanSlant9-Regular     "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmro9.pfb
+cmsltt10  LMMonoSlant10-Regular     "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtto10.pfb
+cmss10    LMSans10-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmss10.pfb
+cmss12    LMSans12-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmss12.pfb
+cmss17    LMSans17-Regular          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmss17.pfb
+cmss8     LMSans8-Regular           "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmss8.pfb
+cmss9     LMSans9-Regular           "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmss9.pfb
+cmssbx10  LMSans10-Bold             "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmssbx10.pfb
+cmssbxo10 LMSans10-BoldOblique      "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmssbo10.pfb
+cmssdc10  LMSansDemiCond10-Regular  "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmssdc10.pfb
+cmssi10   LMSans10-Oblique          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmsso10.pfb
+cmssi12   LMSans12-Oblique          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmsso12.pfb
+cmssi17   LMSans17-Oblique          "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmsso17.pfb
+cmssi8    LMSans8-Oblique           "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmsso8.pfb
+cmssi9    LMSans9-Oblique           "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmsso9.pfb
+cmssq8    LMSansQuot8-Regular       "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmssq8.pfb
+cmssqi8   LMSansQuot8-Oblique       "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmssqo8.pfb
+cmtcsc10  LMMonoCaps10-Regular      "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtcsc10.pfb
+cmti10    LMRoman10-Italic          "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmri10.pfb
+cmti12    LMRoman12-Italic          "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmri12.pfb
+cmti7     LMRoman7-Italic           "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmri7.pfb
+cmti8     LMRoman8-Italic           "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmri8.pfb
+cmti9     LMRoman9-Italic           "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmri9.pfb
+cmtt10    LMMono10-Regular          "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtt10.pfb
+cmtt12    LMMono12-Regular          "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtt12.pfb
+cmtt8     LMMono8-Regular           "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtt8.pfb
+cmtt9     LMMono9-Regular           "enclmrepcmtt ReEncodeFont"  <lm-rep-cmtt.enc  <lmtt9.pfb
+cmu10     LMRomanUnsl10-Regular     "enclmrepcmit ReEncodeFont"  <lm-rep-cmit.enc  <lmu10.pfb
+cmvtt10   LMMonoProp10-Regular      "enclmrepcmrm ReEncodeFont"  <lm-rep-cmrm.enc  <lmvtt10.pfb
+
+cmbsy5    LMMathSymbols5-Bold       "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmbsy5.pfb
+cmbsy7    LMMathSymbols7-Bold       "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmbsy7.pfb
+cmbsy10   LMMathSymbols10-Bold      "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmbsy10.pfb
+cmsy5     LMMathSymbols5-Regular    "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy5.pfb
+cmsy6     LMMathSymbols6-Regular    "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy6.pfb
+cmsy7     LMMathSymbols7-Regular    "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy7.pfb
+cmsy8     LMMathSymbols8-Regular    "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy8.pfb
+cmsy9     LMMathSymbols9-Regular    "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy9.pfb
+cmsy10    LMMathSymbols10-Regular   "enclmmathsy ReEncodeFont"   <lm-mathsy.enc    <lmsy10.pfb
+cmex10    LMMathExtension10-Regular "enclmmathex ReEncodeFont"   <lm-mathex.enc    <lmex10.pfb
+cmmi5     LMMathItalic5-Regular     "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi5.pfb
+cmmi6     LMMathItalic6-Regular     "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi6.pfb
+cmmi7     LMMathItalic7-Regular     "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi7.pfb
+cmmi8     LMMathItalic8-Regular     "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi8.pfb
+cmmi9     LMMathItalic9-Regular     "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi9.pfb
+cmmi10    LMMathItalic10-Regular    "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi10.pfb
+cmmi12    LMMathItalic12-Regular    "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmi12.pfb
+cmmib5    LMMathItalic5-Bold        "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmib5.pfb
+cmmib7    LMMathItalic7-Bold        "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmib7.pfb
+cmmib10   LMMathItalic10-Bold       "enclmmathit ReEncodeFont"   <lm-mathit.enc    <lmmib10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-px.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-px.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-px.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,51 @@
+% This file a (slightly adapted) copy of the map file
+% that comes with the PX fonts by Young Ryu.
+
+% URW fonts replaced by TeX Gyre
+
+% TeX Gyre Pagella (Palatino)
+
+% rpxpplr  TeXGyrePagella-Regular     "encq8r ReEncodeFont" <q-8r.enc <qplr.pfb
+% rpxpplb  TeXGyrePagella-Bold        "encq8r ReEncodeFont" <q-8r.enc <qplb.pfb
+% rpxpplri TeXGyrePagella-Italic      "encq8r ReEncodeFont" <q-8r.enc <qplri.pfb
+% rpxpplbi TeXGyrePagella-BoldItalic  "encq8r ReEncodeFont" <q-8r.enc <qplbi.pfb
+% % no idea why these were added
+% rpxpplro TeXGyrePagella-Oblique     ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qplr.pfb
+% rpxpplbo TeXGyrePagella-BoldOblique ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qplb.pfb
+
+% PX Text
+
+rpxr    rpxr                    <rpxr.pfb
+rpxsl   rpxr   ".167 SlantFont" <rpxr.pfb
+rpxi    rpxi                    <rpxi.pfb
+rpxsc   rpxsc                   <rpxsc.pfb
+rpxb    rpxb                    <rpxb.pfb
+rpxbsl  rpxb   ".167 SlantFont" <rpxb.pfb
+rpxbi   rpxbi                   <rpxbi.pfb
+rpxbsc  rpxbsc                  <rpxbsc.pfb
+rpcxb   rpcxb                   <rpcxb.pfb
+rpcxbsl rpcxb  ".167 SlantFont" <rpcxb.pfb
+rpcxbi  rpcxbi                  <rpcxbi.pfb
+rpcxi   rpcxi                   <rpcxi.pfb
+rpcxr   rpcxr                   <rpcxr.pfb
+rpcxsl  rpcxsl ".167 SlantFont" <rpcxr.pfb
+
+% PX Math
+
+rpxbmi  rpxbmi                  <rpxbmi.pfb
+rpxmi   rpxmi                   <rpxmi.pfb
+
+pxbex   pxbex                   <pxbex.pfb
+pxbexa  pxbexa                  <pxbexa.pfb
+pxbmia  pxbmia                  <pxbmia.pfb
+pxbsy   pxbsy                   <pxbsy.pfb
+pxbsya  pxbsya                  <pxbsya.pfb
+pxbsyb  pxbsyb                  <pxbsyb.pfb
+pxbsyc  pxbsyc                  <pxbsyc.pfb
+pxex    pxex                    <pxex.pfb
+pxexa   pxexa                   <pxexa.pfb
+pxmia   pxmia                   <pxmia.pfb
+pxsy    pxsy                    <pxsy.pfb
+pxsya   pxsya                   <pxsya.pfb
+pxsyb   pxsyb                   <pxsyb.pfb
+pxsyc   pxsyc                   <pxsyc.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-px.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-tx.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-tx.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-tx.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,94 @@
+% This file is a (slightly adapted) copy of the map file
+% that comes with the TX fonts by Young Ryu.
+
+% URW fonts replaced by TeX Gyre
+
+% TeX Gyre Termes (Times)
+
+% rtxptmr  TeXGyreTermes-Regular     "encq8r ReEncodeFont" <q-8r.enc <qtmr.pfb
+% rtxptmb  TeXGyreTermes-Bold        "encq8r ReEncodeFont" <q-8r.enc <qtmb.pfb
+% rtxptmri TeXGyreTermes-Italic      "encq8r ReEncodeFont" <q-8r.enc <qtmri.pfb
+% rtxptmbi TeXGyreTermes-BoldItalic  "encq8r ReEncodeFont" <q-8r.enc <qtmbi.pfb
+% % no idea why these were added
+% rtxptmro TeXGyreTermes-Oblique     ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qtmr.pfb
+% rtxptmbo TeXGyreTermes-BoldOblique ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qtmb.pfb
+%
+% % TeX Gyre Heros (Helvetica)
+%
+% rtxphvr  TeXGyreHeros-Regular     "encqrm ReEncodeFont" <q-rm.enc <qtmr.pfb
+% rtxphvb  TeXGyreHeros-Bold        "encqrm ReEncodeFont" <q-rm.enc <qtmb.pfb
+% % probably not used by txfonts
+% % rtxphvri TeXGyreHeros-Italic      "encqrm ReEncodeFont" <q-rm.enc <qtmri.pfb
+% % rtxphvbi TeXGyreHeros-BoldItalic  "encqrm ReEncodeFont" <q-rm.enc <qtmbi.pfb
+% % followed original definitions; one could also use the italic version
+% rtxphvro TeXGyreHeros-Oblique     ".167 SlantFont encqrm ReEncodeFont" <q-rm.enc <qtmr.pfb
+% rtxphvbo TeXGyreHeros-BoldOblique ".167 SlantFont encqrm ReEncodeFont" <q-rm.enc <qtmb.pfb
+
+% TX Text
+
+rtxr     rtxr                      <rtxr.pfb
+rtxsl    rtxr    ".167 SlantFont"  <rtxr.pfb
+rtxi     rtxi                      <rtxi.pfb
+rtxsc    rtxsc                     <rtxsc.pfb
+rtxb     rtxb                      <rtxb.pfb
+rtxbsl   rtxb    ".167 SlantFont"  <rtxb.pfb
+rtxbi    rtxbi                     <rtxbi.pfb
+rtxbsc   rtxbsc                    <rtxbsc.pfb
+rtcxb    rtcxb                     <rtcxb.pfb
+rtcxbsl  rtcxb   ".167 SlantFont"  <rtcxb.pfb
+rtcxbi   rtcxbi                    <rtcxbi.pfb
+rtcxi    rtcxi                     <rtcxi.pfb
+rtcxr    rtcxr                     <rtcxr.pfb
+rtcxsl   rtcx    ".167 SlantFont"  <rtcxr.pfb
+
+% TX Math
+
+rtxbmi   rtxbmi                    <rtxbmi.pfb
+rtxmi    rtxmi                     <rtxmi.pfb
+
+txbex    txbex                     <txbex.pfb
+txbexa   txbexa                    <txbexa.pfb
+txbmia   txbmia                    <txbmia.pfb
+txbsy    txbsy                     <txbsy.pfb
+txbsya   txbsya                    <txbsya.pfb
+txbsyb   txbsyb                    <txbsyb.pfb
+txbsyc   txbsyc                    <txbsyc.pfb
+txex     txex                      <txex.pfb
+txexa    txexa                     <txexa.pfb
+txmia    txmia                     <txmia.pfb
+txsy     txsy                      <txsy.pfb
+txsya    txsya                     <txsya.pfb
+txsyb    txsyb                     <txsyb.pfb
+txsyc    txsyc                     <txsyc.pfb
+
+% TX TT Text
+
+txtt     txtt                      <txtt.pfb
+txttsl   txtt     ".167 SlantFont" <txtt.pfb
+txttsc   txttsc                    <txttsc.pfb
+txbtt    txbtt                     <txbtt.pfb
+txbttsl  txbtt    ".167 SlantFont" <txbtt.pfb
+txbttsc  txbttsc                   <txbttsc.pfb
+t1xtt    t1xtt                     <t1xtt.pfb
+t1xttsl  t1xtt    ".167 SlantFont" <t1xtt.pfb
+t1xttsc  t1xttsc                   <t1xttsc.pfb
+t1xbtt   t1xbtt                    <t1xbtt.pfb
+t1xbttsl t1xbtt   ".167 SlantFont" <t1xbtt.pfb
+t1xbttsc t1xbttsc                  <t1xbttsc.pfb
+tcxtt    tcxtt                     <tcxtt.pfb
+tcxttsl  tcxtt    ".167 SlantFont" <tcxtt.pfb
+tcxbtt   tcxbtt                    <tcxbtt.pfb
+tcxbttsl tcxbtt   ".167 SlantFont" <tcxbtt.pfb
+
+% TX SS Text
+
+rtxss    rtxss                     <rtxss.pfb
+rtxsssl  rtxss    ".167 SlantFont" <rtxss.pfb
+rtxsssc  rtxsssc                   <rtxsssc.pfb
+rtxbss   rtxbss                    <rtxbss.pfb
+rtxbsssl rtxbss   ".167 SlantFont" <rtxbss.pfb
+rtxbsssc rtxbsssc                  <rtxbsssc.pfb
+rtcxss   rtcxss                    <rtcxss.pfb
+rtcxbss  rtcxbss                   <rtcxbss.pfb
+rtcxsssl rtcxss   ".167 SlantFont" <rtcxss.pfb
+rtcxbsso rtcxbss  ".167 SlantFont" <rtcxbss.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/mkiv-tx.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-adobe-euro.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-adobe-euro.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-adobe-euro.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,25 @@
+euromo   EuroMono-Regular      <euromo.pfb
+euromob  EuroMono-Bold         <euromob.pfb
+euromoi  EuroMono-Italic       <euromoi.pfb
+euromobi EuroMono-BoldItalic   <euromobi.pfb
+eurosa   EuroSans-Regular      <eurosa.pfb
+eurosab  EuroSans-Bold         <eurosab.pfb
+eurosai  EuroSans-Italic       <eurosai.pfb
+eurosabi EuroSans-BoldItalic   <eurosebi.pfb
+eurose   EuroSerif-Regular     <eurose.pfb
+euroseb  EuroSerif-Bold        <euroseb.pfb
+eurosei  EuroSerif-Italic      <eurosei.pfb
+eurosebi EuroSerif-BoldItalic  <eurosebi.pfb
+
+% euromo   <_2______.pfb
+% euromob  <_2b_____.pfb
+% euromoi  <_2i_____.pfb
+% euromobi <_2bi____.pfb
+% eurosa   <_1______.pfb
+% eurosab  <_1b_____.pfb
+% eurosai  <_1i_____.pfb
+% eurosabi <_1bi____.pfb
+% eurose   <_3______.pfb
+% euroseb  <_3b_____.pfb
+% eurosei  <_3i_____.pfb
+% eurosebi <_3bi____.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-adobe-euro.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,47 @@
+lasy5      LASY5      <lasy5.pfb
+lasy6      LASY6      <lasy6.pfb
+lasy7      LASY7      <lasy7.pfb
+lasy8      LASY8      <lasy8.pfb
+lasy9      LASY9      <lasy9.pfb
+lasy10     LASY10     <lasy10.pfb
+
+lasyb10    LASYB10    <lasyb10.pfb
+lcircle10  LCIRCLE10  <lcircle1.pfb
+lcirclew10 LCIRCLEW10 <lcirclew.pfb
+lcmss8     LCMSS8     <lcmss8.pfb
+lcmssb8    LCMSSB8    <lcmssb8.pfb
+lcmssi8    LCMSSI8    <lcmssi8.pfb
+line10     LINE10     <line10.pfb
+linew10    LINEW10    <linew10.pfb
+
+logo8      LOGO8      <logo8.pfb
+logo9      LOGO9      <logo9.pfb
+logo10     LOGO10     <logo10.pfb
+logobf10   LOGOBF10   <logobf10.pfb
+logosl10   LOGOSL10   <logosl10.pfb
+
+msam5      MSAM5      <msam5.pfb
+msam7      MSAM7      <msam7.pfb
+msam10     MSAM10     <msam10.pfb
+msbm5      MSBM5      <msbm5.pfb
+msbm7      MSBM7      <msbm7.pfb
+msbm10     MSBM10     <msbm10.pfb
+
+wncyb10    WNCYB10    <wncyb10.pfb
+wncyi10    WNCYI10    <wncyi10.pfb
+wncyr10    WNCYR10    <wncyr10.pfb
+wncysc10   WNCYSC10   <wncysc10.pfb
+wncyss10   WNCYSS10   <wncyss10.pfb
+
+manfnt     MANFNT     <manfnt.pfb
+
+% i dunno what this is
+
+icmex10    <icmex10.pfb
+icmmi8     <icmmi8.pfb
+icmsy8     <icmsy8.pfb
+icmtt8     <icmtt8.pfb
+ilasy8     <ilasy8.pfb
+ilcmss8    <ilcmss8.pfb
+ilcmssb8   <ilcmssb8.pfb
+ilcmssi8   <ilcmssi8.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-cmr.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-cmr.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-cmr.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,97 @@
+cmb10      CMB10     <cmb10.pfb
+
+cmbsy6     CMBSY6    <cmbsy6.pfb
+cmbsy7     CMBSY7    <cmbsy7.pfb
+cmbsy8     CMBSY8    <cmbsy8.pfb
+cmbsy9     CMBSY9    <cmbsy9.pfb
+cmbsy10    CMBSY10   <cmbsy10.pfb
+
+cmbx5      CMBX5     <cmbx5.pfb
+cmbx6      CMBX6     <cmbx6.pfb
+cmbx7      CMBX7     <cmbx7.pfb
+cmbx8      CMBX8     <cmbx8.pfb
+cmbx9      CMBX9     <cmbx9.pfb
+cmbx10     CMBX10    <cmbx10.pfb
+cmbx12     CMBX10    <cmbx12.pfb
+
+cmbxsl10   CMBXSL10  <cmbxsl10.pfb
+cmbxti10   CMBXTI10  <cmbxti10.pfb
+
+cmcsc10    CMCSC10   <cmcsc10.pfb
+cmdunh10   CMDUNH10  <cmdunh10.pfb
+cmex10     CMEX10    <cmex10.pfb
+cmff10     CMFF10    <cmff10.pfb
+cmfi10     CMFI10    <cmfi10.pfb
+cmfib8     CMFIB8    <cmfib8.pfb
+cminch     CMINCH    <cminch.pfb
+cmitt10    CMITT10   <cmitt10.pfb
+cmmib10    CMMIB10   <cmmib10.pfb
+
+cmmi5      CMMI5     <cmmi5.pfb
+cmmi6      CMMI6     <cmmi6.pfb
+cmmi7      CMMI7     <cmmi7.pfb
+cmmi8      CMMI8     <cmmi8.pfb
+cmmi9      CMMI9     <cmmi9.pfb
+cmmi10     CMMI10    <cmmi10.pfb
+cmmi12     CMMI12    <cmmi12.pfb
+
+cmr5       CMR5      <cmr5.pfb
+cmr6       CMR6      <cmr6.pfb
+cmr7       CMR7      <cmr7.pfb
+cmr8       CMR8      <cmr8.pfb
+cmr9       CMR9      <cmr9.pfb
+cmr10      CMR10     <cmr10.pfb
+cmr12      CMR12     <cmr12.pfb
+cmr17      CMR17     <cmr17.pfb
+
+cmsl8      CMSL8     <cmsl8.pfb
+cmsl9      CMSL9     <cmsl9.pfb
+cmsl10     CMSL10    <cmsl10.pfb
+cmsl12     CMSL12    <cmsl12.pfb
+
+cmsltt10   CMSLTT10  <cmsltt10.pfb
+
+cmss8      CMSS8     <cmss8.pfb
+cmss9      CMSS9     <cmss9.pfb
+cmss10     CMSS10    <cmss10.pfb
+cmss12     CMSS12    <cmss12.pfb
+cmss17     CMSS17    <cmss17.pfb
+
+cmssbx10   CMSSBX10  <cmssbx10.pfb
+cmssdc10   CMSSDC10  <cmssdc10.pfb
+
+cmssi8     CMSSI8    <cmssi8.pfb
+cmssi9     CMSSI9    <cmssi9.pfb
+cmssi10    CMSSI10   <cmssi10.pfb
+cmssi12    CMSSI12   <cmssi12.pfb
+cmssi17    CMSSI17   <cmssi17.pfb
+
+cmssq8     CMSSQ8    <cmssq8.pfb
+cmssqi8    CMSSQI8   <cmssqi8.pfb
+
+cmsy5      CMSY5     <cmsy5.pfb
+cmsy6      CMSY6     <cmsy6.pfb
+cmsy7      CMSY7     <cmsy7.pfb
+cmsy8      CMSY8     <cmsy8.pfb
+cmsy9      CMSY9     <cmsy9.pfb
+cmsy10     CMSY10    <cmsy10.pfb
+
+cmtcsc10   CMTCSC10  <cmtcsc10.pfb
+
+cmtex8     CMTEX8    <cmtex8.pfb
+cmtex9     CMTEX9    <cmtex9.pfb
+cmtex10    CMTEX10   <cmtex10.pfb
+
+cmti7      CMTI7     <cmti7.pfb
+cmti8      CMTI8     <cmti8.pfb
+cmti9      CMTI9     <cmti9.pfb
+cmti10     CMTI10    <cmti10.pfb
+cmti12     CMTI12    <cmti12.pfb
+
+cmtt8      CMTT8     <cmtt8.pfb
+cmtt9      CMTT9     <cmtt9.pfb
+cmtt10     CMTT10    <cmtt10.pfb
+cmtt12     CMTT12    <cmtt12.pfb
+
+cmu10      CMU10     <cmu10.pfb
+cmvtt10    CMVTT10   <cmvtt10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-cmr.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-euler.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-euler.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-euler.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,25 @@
+euex10 EUEX10 <euex10.pfb
+
+eufb5  EUFB5  <eufb5.pfb
+eufb7  EUFB7  <eufb7.pfb
+eufb10 EUFB10 <eufb10.pfb
+
+eufm5  EUFM5  <eufm5.pfb
+eufm7  EUFM7  <eufm7.pfb
+eufm10 EUFM10 <eufm10.pfb
+
+eurb5  EURB5  <eurb5.pfb
+eurb7  EURB7  <eurb7.pfb
+eurb10 EURB10 <eurb10.pfb
+
+eurm5  EURM5  <eurm5.pfb
+eurm7  EURM7  <eurm7.pfb
+eurm10 EURM10 <eurm10.pfb
+
+eusb5  EUSB5  <eusb5.pfb
+eusb7  EUSB7  <eusb7.pfb
+eusb10 EUSB10 <eusb10.pfb
+
+eusm5  EUSM5  <eusm5.pfb
+eusm7  EUSM7  <eusm7.pfb
+eusm10 EUSM10 <eusm10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-ams-euler.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,62 @@
+% ralph
+
+rsfs7  rsfs5                       <rsfs7.pfb
+rsfs5  rsfs7                       <rsfs5.pfb
+rsfs10 rsfs10                      <rsfs10.pfb
+
+% marvosym
+
+umvs MarVoSym                      <marvosym.pfb
+
+% context
+
+contnav ContextNavigation          <contnav.pfb
+hans    Hans-Regular               <hans.pfb
+hans-sh Hans-sh-Regular            <hans-sh.pfb
+
+% dingbats
+
+uzdr Dingbats                      <uzdr.pfb
+pzdr Dingbats                      <pzdr.pfb
+
+% symbols
+
+usyr StandardSymL                  <usyr.pfb
+
+% xypic
+
+xyatip10 XYATIP10                  <xyatip10.pfb
+xybsql10 XYBSQL10                  <xybsql10.pfb
+xybtip10 XYBTIP10                  <xybtip10.pfb
+xycirc10 XYCIRC10                  <xycirc10.pfb
+xydash10 XYDASH10                  <xydash10.pfb
+
+xycmat10 XYCMAT10                  <xycmat10.pfb
+xycmbt10 XYCMBT10                  <xycmbt10.pfb
+xyeuat10 XYEUAT10                  <xyeuat10.pfb
+xyeubt10 XYEUBT10                  <xyeubt10.pfb
+
+xycmat11 XYCMAT10 "1.1 ExtendFont" <xycmat10.pfb
+xycmbt11 XYCMBT10 "1.1 ExtendFont" <xycmbt10.pfb
+xyeuat11 XYEUAT10 "1.1 ExtendFont" <xyeuat10.pfb
+xyeubt11 XYEUBT10 "1.1 ExtendFont" <xyeubt10.pfb
+
+xycmat12 XYCMAT10 "1.2 ExtendFont" <xycmat10.pfb
+xycmbt12 XYCMBT10 "1.2 ExtendFont" <xycmbt10.pfb
+xyeuat12 XYEUAT10 "1.2 ExtendFont" <xyeuat10.pfb
+xyeubt12 XYEUBT10 "1.2 ExtendFont" <xyeubt10.pfb
+
+% euro
+
+zpeub   EuroSerif-Bold             <zpeub.pfb
+zpeubi  EuroSerif-BoldItalic       <zpeubi.pfb
+zpeubis EuroSans-BoldItalic        <zpeubis.pfb
+zpeubit EuroMono-BoldItalic        <zpeubit.pfb
+zpeubs  EuroSans-Bold              <zpeubs.pfb
+zpeubt  EuroMono-Bold              <zpeubt.pfb
+zpeur   EuroSerif-Regular          <zpeur.pfb
+zpeuri  EuroSerif-Italic           <zpeuri.pfb
+zpeuris EuroSans-Italic            <zpeuris.pfb
+zpeurit EuroMono-Italic            <zpeurit.pfb
+zpeurs  EuroSans-Regular           <zpeurs.pfb
+zpeurt  EuroMono-Regular           <zpeurt.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-context-symbol.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-context-symbol.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-context-symbol.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,3 @@
+contnav ContextNavigation          <contnav.pfb
+hans    Hans-Regular               <hans.pfb
+hans-sh Hans-sh-Regular            <hans-sh.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-context-symbol.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-dummy.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-dummy.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-dummy.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1 @@
+% no entries in here


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-dummy.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-empty.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-empty.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-empty.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,4 @@
+
+
+% this is an empty map file
+


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-empty.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-micropress-informal.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-micropress-informal.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-micropress-informal.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,7 @@
+ifrm10cm   Informal Regular            <cm.enc <ifrg.pfb
+ifrb10cm   InformalBold                <cm.enc <ifb.pfb
+ifro10cm   InformalOblique             <cm.enc <ifo.pfb
+ifbo10cm   InformalBoldOblique         <cm.enc <ifbo.pfb
+ifex10     InformalExtendedMathSymbols         <ifex10.pfb
+ifmi10     InformalMathItalics                 <ifmi10.pfb
+ifsy10     InformalMathSymbols                 <ifsy10.pfb
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-micropress-informal.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-csr.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-csr.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-csr.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,56 @@
+csr5     CSR5     <csr1.enc <csr5.pfb
+csr6     CSR6     <csr.enc  <csr6.pfb
+csr7     CSR7     <csr.enc  <csr7.pfb
+csr8     CSR8     <csr.enc  <csr8.pfb
+csr9     CSR9     <csr.enc  <csr9.pfb
+csr10    CSR10    <csr.enc  <csr10.pfb
+csr12    CSR12    <csr.enc  <csr12.pfb
+csr17    CSR17    <csr.enc  <csr17.pfb
+csbx5    CSBX5    <csr.enc  <csbx5.pfb
+csbx6    CSBX6    <csr.enc  <csbx6.pfb
+csbx7    CSBX7    <csr.enc  <csbx7.pfb
+csbx8    CSBX8    <csr.enc  <csbx8.pfb
+csbx9    CSBX9    <csr.enc  <csbx9.pfb
+csbx10   CSBX10   <csr.enc  <csbx10.pfb
+csbx12   CSBX12   <csr.enc  <csbx12.pfb
+csb10    CSB10    <csr.enc  <csb10.pfb
+csti7    CSTI7    <csr.enc  <csti7.pfb
+csti8    CSTI8    <csr.enc  <csti8.pfb
+csti9    CSTI9    <csr.enc  <csti9.pfb
+csti10   CSTI10   <csr.enc  <csti10.pfb
+csti12   CSTI12   <csr.enc  <csti12.pfb
+cstt8    CSTT8    <cstt.enc <cstt8.pfb
+cstt9    CSTT9    <cstt.enc <cstt9.pfb
+cstt10   CSTT10   <cstt.enc <cstt10.pfb
+cstt12   CSTT12   <cstt.enc <cstt12.pfb
+cssltt10 CSSLTT10 <cstt.enc <cssltt10.pfb
+csvtt10  CSVTT10  <cstt.enc <csvtt10.pfb
+csss8    CSSS8    <csr.enc  <csss8.pfb
+csss9    CSSS9    <csr.enc  <csss9.pfb
+csss10   CSSS10   <csr.enc  <csss10.pfb
+csss12   CSSS12   <csr.enc  <csss12.pfb
+csss17   CSSS17   <csr.enc  <csss17.pfb
+csssi8   CSSSI8   <csr.enc  <csssi8.pfb
+csssi9   CSSSI9   <csr.enc  <csssi9.pfb
+csssi10  CSSSI10  <csr.enc  <csssi10.pfb
+csssi12  CSSSI12  <csr.enc  <csssi12.pfb
+csssi17  CSSSI17  <csr.enc  <csssi17.pfb
+cssl8    CSSL8    <csr.enc  <cssl8.pfb
+cssl9    CSSL9    <csr.enc  <cssl9.pfb
+cssl10   CSSL10   <csr.enc  <cssl10.pfb
+cssl12   CSSL12   <csr.enc  <cssl12.pfb
+csssq8   CSSSQ8   <csr.enc  <csssq8.pfb
+csssqi8  CSSSQI8  <csr.enc  <csssqi8.pfb
+csssdc10 CSSSDC10 <csr.enc  <csssdc10.pfb
+csssbx10 CSSSBX10 <csr.enc  <csssbx10.pfb
+csinch   CSINCH   <csin.enc <csinch.pfb
+csdunh10 CSDUNH10 <csr.enc  <csdunh10.pfb
+csbxsl10 CSBXSL10 <csr.enc  <csbxsl10.pfb
+csff10   CSFF10   <csr.enc  <csff10.pfb
+csfib8   CSFIB8   <csr.enc  <csfib8.pfb
+csbxti10 CSBXTI10 <csr.enc  <csbxti10.pfb
+csitt10  CSITT10  <cstt.enc <csitt10.pfb
+csu10    CSU10    <csr.enc  <csu10.pfb
+csfi10   CSFI10   <csr.enc  <csfi10.pfb
+cscsc10  CSCSC10  <csr1.enc <cscsc10.pfb
+cstcsc10 CSTCSC10 <cstt.enc <cstcsc10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-csr.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-lm.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-lm.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-lm.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,182 @@
+% LM replacement, thanks to Jacko
+
+% official
+
+% cmb10     LMRomanDemi10-Regular        <lm-rep-cmrm.enc  <lmb10.pfb
+% cmbx10    LMRoman10-Bold               <lm-rep-cmrm.enc  <lmbx10.pfb
+% cmbx12    LMRoman12-Bold               <lm-rep-cmrm.enc  <lmbx12.pfb
+% cmbx5     LMRoman5-Bold                <lm-rep-cmrm.enc  <lmbx5.pfb
+% cmbx6     LMRoman6-Bold                <lm-rep-cmrm.enc  <lmbx6.pfb
+% cmbx7     LMRoman7-Bold                <lm-rep-cmrm.enc  <lmbx7.pfb
+% cmbx8     LMRoman8-Bold                <lm-rep-cmrm.enc  <lmbx8.pfb
+% cmbx9     LMRoman9-Bold                <lm-rep-cmrm.enc  <lmbx9.pfb
+% cmbxsl10  LMSlanted10-BoldItalic       <lm-rep-cmrm.enc  <lmbxo10.pfb
+% cmbxti10  LMRoman10-BoldItalic         <lm-rep-cmit.enc  <lmbxi10.pfb
+% cmbxti12  LMRoman10-BoldItalic         <lm-rep-cmit.enc  <lmbxti10.pfb
+% cmbxti7   LMRoman10-BoldItalic         <lm-rep-cmit.enc  <lmbxti10.pfb
+% cmcsc10   LMCaps10-Regular             <lm-rep-cmsc.enc  <lmcsc10.pfb
+% cmcsc8    LMCaps10-Regular             <lm-rep-cmsc.enc  <lmcsc10.pfb
+% cmcsc9    LMCaps10-Regular             <lm-rep-cmsc.enc  <lmcsc10.pfb
+% cminch    LMSans10-Bold                <lm-rep-cmin.enc  <lmssbx10.pfb
+% cmitt10   LMTypewriter10-Italic        <lm-rep-cmitt.enc <lmtti10.pfb
+% cmitt12   LMTypewriter10-Italic        <lm-rep-cmitt.enc <lmtti10.pfb
+% cmitt9    LMTypewriter10-Italic        <lm-rep-cmitt.enc <lmtti10.pfb
+% cmr10     LMRoman10-Regular            <lm-rep-cmrm.enc  <lmr10.pfb
+% cmr12     LMRoman12-Regular            <lm-rep-cmrm.enc  <lmr12.pfb
+% cmr17     LMRoman17-Regular            <lm-rep-cmrm.enc  <lmr17.pfb
+% cmr5      LMRoman5-Regular             <lm-rep-cmsc.enc  <lmr5.pfb
+% cmr6      LMRoman6-Regular             <lm-rep-cmrm.enc  <lmr6.pfb
+% cmr7      LMRoman7-Regular             <lm-rep-cmrm.enc  <lmr7.pfb
+% cmr8      LMRoman8-Regular             <lm-rep-cmrm.enc  <lmr8.pfb
+% cmr9      LMRoman9-Regular             <lm-rep-cmrm.enc  <lmr9.pfb
+% cmsl10    LMSlanted10-Italic           <lm-rep-cmrm.enc  <lmro10.pfb
+% cmsl12    LMSlanted12-Italic           <lm-rep-cmrm.enc  <lmro12.pfb
+% cmsl6     LMSlanted8-Italic            <lm-rep-cmrm.enc  <lmro8.pfb
+% cmsl8     LMSlanted8-Italic            <lm-rep-cmrm.enc  <lmro8.pfb
+% cmsl9     LMSlanted9-Italic            <lm-rep-cmrm.enc  <lmro9.pfb
+% cmsltt10  LMTypewriterSlanted10-Italic <lm-rep-cmtt.enc  <lmtto10.pfb
+% cmsltt9   LMTypewriterSlanted10-Italic <lm-rep-cmtt.enc  <lmtto10.pfb
+% cmss10    LMSans10-Regular             <lm-rep-cmrm.enc  <lmss10.pfb
+% cmss12    LMSans12-Regular             <lm-rep-cmrm.enc  <lmss12.pfb
+% cmss17    LMSans17-Regular             <lm-rep-cmrm.enc  <lmss17.pfb
+% cmss8     LMSans8-Regular              <lm-rep-cmrm.enc  <lmss8.pfb
+% cmss9     LMSans9-Regular              <lm-rep-cmrm.enc  <lmss9.pfb
+% cmssbx10  LMSans10-Bold                <lm-rep-cmrm.enc  <lmssbx10.pfb
+% cmssbxo10 LMSans10-BoldItalic          <lm-rep-cmrm.enc  <lmssbo10.pfb
+% cmssdc10  LMSansDemiCond10-Regular     <lm-rep-cmrm.enc  <lmssdc10.pfb
+% cmssi10   LMSans10-Italic              <lm-rep-cmrm.enc  <lmsso10.pfb
+% cmssi12   LMSans12-Italic              <lm-rep-cmrm.enc  <lmsso12.pfb
+% cmssi17   LMSans17-Italic              <lm-rep-cmrm.enc  <lmsso17.pfb
+% cmssi8    LMSans8-Italic               <lm-rep-cmrm.enc  <lmsso8.pfb
+% cmssi9    LMSans9-Italic               <lm-rep-cmrm.enc  <lmsso9.pfb
+% cmssq8    LMSansQuotation8-Regular     <lm-rep-cmrm.enc  <lmssq8.pfb
+% cmssqi8   LMSansQuotation8-Italic      <lm-rep-cmrm.enc  <lmssqo8.pfb
+% cmtcsc10  LMTypewriterCaps10-Regular   <lm-rep-cmtt.enc  <lmtcsc10.pfb
+% cmti10    LMRoman10-Italic             <lm-rep-cmit.enc  <lmri10.pfb
+% cmti12    LMRoman12-Italic             <lm-rep-cmit.enc  <lmri12.pfb
+% cmti7     LMRoman7-Italic              <lm-rep-cmit.enc  <lmri7.pfb
+% cmti8     LMRoman8-Italic              <lm-rep-cmit.enc  <lmri8.pfb
+% cmti9     LMRoman9-Italic              <lm-rep-cmit.enc  <lmri9.pfb
+% cmtt10    LMTypewriter10-Regular       <lm-rep-cmtt.enc  <lmtt10.pfb
+% cmtt12    LMTypewriter12-Regular       <lm-rep-cmtt.enc  <lmtt12.pfb
+% cmtt8     LMTypewriter8-Regular        <lm-rep-cmtt.enc  <lmtt8.pfb
+% cmtt9     LMTypewriter9-Regular        <lm-rep-cmtt.enc  <lmtt9.pfb
+% cmvtt10   LMTypewriterVarWd10-Regular  <lm-rep-cmrm.enc  <lmvtt10.pfb
+%
+% but more efficient since to-be-included old files have those names
+
+cmb10     CMB10     <lm-rep-cmrm.enc  <lmb10.pfb
+cmbx10    CMBX10    <lm-rep-cmrm.enc  <lmbx10.pfb
+cmbx12    CMBX12    <lm-rep-cmrm.enc  <lmbx12.pfb
+cmbx5     CMBX5     <lm-rep-cmrm.enc  <lmbx5.pfb
+cmbx6     CMBX6     <lm-rep-cmrm.enc  <lmbx6.pfb
+cmbx7     CMBX7     <lm-rep-cmrm.enc  <lmbx7.pfb
+cmbx8     CMBX8     <lm-rep-cmrm.enc  <lmbx8.pfb
+cmbx9     CMBX9     <lm-rep-cmrm.enc  <lmbx9.pfb
+cmbxsl10  CMBXSL10  <lm-rep-cmrm.enc  <lmbxo10.pfb
+cmbxti10  CMBXTI10  <lm-rep-cmit.enc  <lmbxi10.pfb
+cmbxti12  CMBXTI12  <lm-rep-cmit.enc  <lmbxti10.pfb
+cmbxti7   CMBXTI7   <lm-rep-cmit.enc  <lmbxti10.pfb
+cmcsc10   CMCSC10   <lm-rep-cmsc.enc  <lmcsc10.pfb
+cmcsc8    CMCSC8    <lm-rep-cmsc.enc  <lmcsc10.pfb
+cmcsc9    CMCSC9    <lm-rep-cmsc.enc  <lmcsc10.pfb
+cminch    CMINCH    <lm-rep-cmin.enc  <lmssbx10.pfb
+cmitt10   CMITT10   <lm-rep-cmitt.enc <lmtti10.pfb
+cmitt12   CMITT12   <lm-rep-cmitt.enc <lmtti10.pfb
+cmitt9    CMITT9    <lm-rep-cmitt.enc <lmtti10.pfb
+cmr10     CMR10     <lm-rep-cmrm.enc  <lmr10.pfb
+cmr12     CMR12     <lm-rep-cmrm.enc  <lmr12.pfb
+cmr17     CMR17     <lm-rep-cmrm.enc  <lmr17.pfb
+cmr5      CMR5      <lm-rep-cmsc.enc  <lmr5.pfb
+cmr6      CMR6      <lm-rep-cmrm.enc  <lmr6.pfb
+cmr7      CMR7      <lm-rep-cmrm.enc  <lmr7.pfb
+cmr8      CMR8      <lm-rep-cmrm.enc  <lmr8.pfb
+cmr9      CMR9      <lm-rep-cmrm.enc  <lmr9.pfb
+cmsl10    CMSL10    <lm-rep-cmrm.enc  <lmro10.pfb
+cmsl12    CMSL12    <lm-rep-cmrm.enc  <lmro12.pfb
+cmsl6     CMSL6     <lm-rep-cmrm.enc  <lmro8.pfb
+cmsl8     CMSL8     <lm-rep-cmrm.enc  <lmro8.pfb
+cmsl9     CMSL9     <lm-rep-cmrm.enc  <lmro9.pfb
+cmsltt10  CMSLTT10  <lm-rep-cmtt.enc  <lmtto10.pfb
+cmsltt9   CMSLTT9   <lm-rep-cmtt.enc  <lmtto10.pfb
+cmss10    CMS10     <lm-rep-cmrm.enc  <lmss10.pfb
+cmss12    CMS12     <lm-rep-cmrm.enc  <lmss12.pfb
+cmss17    CMS17     <lm-rep-cmrm.enc  <lmss17.pfb
+cmss8     CMS8      <lm-rep-cmrm.enc  <lmss8.pfb
+cmss9     CMS9      <lm-rep-cmrm.enc  <lmss9.pfb
+cmssbx10  CMSSBX10  <lm-rep-cmrm.enc  <lmssbx10.pfb
+cmssbxo10 CMSSBXO10 <lm-rep-cmrm.enc  <lmssbo10.pfb
+cmssdc10  CMSSDC10  <lm-rep-cmrm.enc  <lmssdc10.pfb
+cmssi10   CMSI10    <lm-rep-cmrm.enc  <lmsso10.pfb
+cmssi12   CMSI12    <lm-rep-cmrm.enc  <lmsso12.pfb
+cmssi17   CMSI17    <lm-rep-cmrm.enc  <lmsso17.pfb
+cmssi8    CMSSI8    <lm-rep-cmrm.enc  <lmsso8.pfb
+cmssi9    CMSSI9    <lm-rep-cmrm.enc  <lmsso9.pfb
+cmssq8    CMSQ8     <lm-rep-cmrm.enc  <lmssq8.pfb
+cmssqi8   CMSSQI8   <lm-rep-cmrm.enc  <lmssqo8.pfb
+cmtcsc10  CMTCSC10  <lm-rep-cmtt.enc  <lmtcsc10.pfb
+cmti10    CMTI10    <lm-rep-cmit.enc  <lmri10.pfb
+cmti12    CMTI12    <lm-rep-cmit.enc  <lmri12.pfb
+cmti7     CMTI7     <lm-rep-cmit.enc  <lmri7.pfb
+cmti8     CMTI8     <lm-rep-cmit.enc  <lmri8.pfb
+cmti9     CMTI9     <lm-rep-cmit.enc  <lmri9.pfb
+cmtt10    CMTT10    <lm-rep-cmtt.enc  <lmtt10.pfb
+cmtt12    CMTT12    <lm-rep-cmtt.enc  <lmtt12.pfb
+cmtt8     CMTT8     <lm-rep-cmtt.enc  <lmtt8.pfb
+cmtt9     CMTT9     <lm-rep-cmtt.enc  <lmtt9.pfb
+cmvtt10   CMVTT10   <lm-rep-cmrm.enc  <lmvtt10.pfb
+
+% Math 
+
+cmex10  LMMathExtension10-Regular  "enclmmathex ReEncodeFont" <lm-mathex.enc  <lmex10.pfb
+cmex9   LMMathExtension10-Regular  "enclmmathex ReEncodeFont" <lm-mathex.enc  <lmex10.pfb
+cmex8   LMMathExtension10-Regular  "enclmmathex ReEncodeFont" <lm-mathex.enc  <lmex10.pfb
+cmex7   LMMathExtension10-Regular  "enclmmathex ReEncodeFont" <lm-mathex.enc  <lmex10.pfb
+
+cmmi5   LMMathItalic5-Italic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi5.pfb
+cmmi6   LMMathItalic6-Italic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi6.pfb
+cmmi7   LMMathItalic7-Italic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi7.pfb
+cmmi8   LMMathItalic8-Italic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi8.pfb
+cmmi9   LMMathItalic9-Italic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi9.pfb
+cmmi10  LMMathItalic10-Italic  "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi10.pfb
+cmmi12  LMMathItalic12-Italic  "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmi12.pfb
+
+cmmib5   LMMathItalic5-BoldItalic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib5.pfb
+cmmib6   LMMathItalic6-BoldItalic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib6.pfb
+cmmib7   LMMathItalic7-BoldItalic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib7.pfb
+cmmib8   LMMathItalic8-BoldItalic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib8.pfb
+cmmib9   LMMathItalic9-BoldItalic   "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib9.pfb
+cmmib10  LMMathItalic10-BoldItalic  "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib10.pfb
+cmmib12  LMMathItalic12-BoldItalic  "enclmmathit ReEncodeFont" <lm-mathit.enc  <lmmib12.pfb
+
+cmsy5   LMMathSymbols5-Italic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy5.pfb
+cmsy6   LMMathSymbols6-Italic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy6.pfb
+cmsy7   LMMathSymbols7-Italic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy7.pfb
+cmsy8   LMMathSymbols8-Italic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy8.pfb
+cmsy9   LMMathSymbols9-Italic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy9.pfb
+cmsy10  LMMathSymbols10-Italic  "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmsy10.pfb
+
+cmbsy5   LMMathSymbols5-BoldItalic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy5.pfb
+cmbsy6   LMMathSymbols6-BoldItalic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy6.pfb
+cmbsy7   LMMathSymbols7-BoldItalic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy7.pfb
+cmbsy8   LMMathSymbols8-BoldItalic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy8.pfb
+cmbsy9   LMMathSymbols9-BoldItalic   "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy9.pfb
+cmbsy10  LMMathSymbols10-BoldItalic  "enclmmathsy ReEncodeFont" <lm-mathsy.enc  <lmbsy10.pfb
+
+
+% original
+
+cmdunh10  CMDUNH10 <cmdunh10.pfb
+
+cmtex10   CMTEX10  <cmtex10.pfb
+cmtex8    CMTEX8   <cmtex8.pfb
+cmtex9    CMTEX9   <cmtex9.pfb
+
+cmff10    CMFF10   <cmff10.pfb
+cmfi10    CMFI10   <cmfi10.pfb
+cmfib8    CMFIB8   <cmfib8.pfb
+
+
+% a weird one, not used in context
+
+cmu10     LMRoman10-Italic "-0.25 SlantFont" <lm-rep-cmit.enc <lmri10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-lm.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-plr.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-plr.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-plr.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,77 @@
+plb10    PLB10     <plrm.enc  <plb10.pfb
+plbsy10  PLBSY10   <plms.enc  <plbsy10.pfb
+plbx5    PLBX5     <plrm.enc  <plbx5.pfb
+plbx6    PLBX6     <plrm.enc  <plbx6.pfb
+plbx7    PLBX7     <plrm.enc  <plbx7.pfb
+plbx8    PLBX8     <plrm.enc  <plbx8.pfb
+plbx9    PLBX9     <plrm.enc  <plbx9.pfb
+plbx10   PLBX10    <plrm.enc  <plbx10.pfb
+plbx12   PLBX12    <plrm.enc  <plbx12.pfb
+plbxsl10 PLBXSL10  <plrm.enc  <plbxsl10.pfb
+plbxti10 PLBXTI10  <plit.enc  <plbxti10.pfb
+plcsc10  PLCSC10   <plsc.enc  <plcsc10.pfb
+pldunh10 PLDUNH10  <plrm.enc  <pldunh10.pfb
+plex9    PLEX9     <plme.enc  <plex9.pfb
+plex10   PLEX10    <plme.enc  <plex10.pfb
+plff10   PLFF10    <plrm.enc  <plff10.pfb
+plfi10   PLFI10    <plit.enc  <plfi10.pfb
+plfib8   PLFIB8    <plrm.enc  <plfib8.pfb
+plinch   PLINCH    <plin.enc  <plinch.pfb
+plitt10  PLITT10   <plitt.enc <plitt10.pfb
+plmi5    PLMI5     <plmi.enc  <plmi5.pfb
+plmi6    PLMI6     <plmi.enc  <plmi6.pfb
+plmi7    PLMI7     <plmi.enc  <plmi7.pfb
+plmi8    PLMI8     <plmi.enc  <plmi8.pfb
+plmi9    PLMI9     <plmi.enc  <plmi9.pfb
+plmi10   PLMI10    <plmi.enc  <plmi10.pfb
+plmi12   PLMI12    <plmi.enc  <plmi12.pfb
+plmib10  PLMIB10   <plmi.enc  <plmib10.pfb
+plr5     PLR5      <plsc.enc  <plr5.pfb
+plr6     PLR6      <plrm.enc  <plr6.pfb
+plr7     PLR7      <plrm.enc  <plr7.pfb
+plr8     PLR8      <plrm.enc  <plr8.pfb
+plr9     PLR9      <plrm.enc  <plr9.pfb
+plr10    PLR10     <plrm.enc  <plr10.pfb
+plr12    PLR12     <plrm.enc  <plr12.pfb
+plr17    PLR17     <plrm.enc  <plr17.pfb
+plsl8    PLSL8     <plrm.enc  <plsl8.pfb
+plsl9    PLSL9     <plrm.enc  <plsl9.pfb
+plsl10   PLSL10    <plrm.enc  <plsl10.pfb
+plsl12   PLSL12    <plrm.enc  <plsl12.pfb
+plsltt10 PLSLTT10  <pltt.enc  <plsltt10.pfb
+plss8    PLSS8     <plrm.enc  <plss8.pfb
+plss9    PLSS9     <plrm.enc  <plss9.pfb
+plss10   PLSS10    <plrm.enc  <plss10.pfb
+plss12   PLSS12    <plrm.enc  <plss12.pfb
+plss17   PLSS17    <plrm.enc  <plss17.pfb
+plssbi10 PLSSBI10  <plrm.enc  <plssbi10.pfb
+plssbx10 PLSSBX10  <plrm.enc  <plssbx10.pfb
+plssdc10 PLSSDC10  <plrm.enc  <plssdc10.pfb
+plssi8   PLSSI8    <plrm.enc  <plssi8.pfb
+plssi9   PLSSI9    <plrm.enc  <plssi9.pfb
+plssi10  PLSSI10   <plrm.enc  <plssi10.pfb
+plssi12  PLSSI12   <plrm.enc  <plssi12.pfb
+plssi17  PLSSI17   <plrm.enc  <plssi17.pfb
+plssq8   PLSSQ8    <plrm.enc  <plssq8.pfb
+plssqi8  PLSSQI8   <plrm.enc  <plssqi8.pfb
+plsy5    PLSY5     <plms.enc  <plsy5.pfb
+plsy6    PLSY6     <plms.enc  <plsy6.pfb
+plsy7    PLSY7     <plms.enc  <plsy7.pfb
+plsy8    PLSY8     <plms.enc  <plsy8.pfb
+plsy9    PLSY9     <plms.enc  <plsy9.pfb
+plsy10   PLSY10    <plms.enc  <plsy10.pfb
+pltcsc10 PLTCSC10  <pltt.enc  <pltcsc10.pfb
+pltex8   PLTEX8    <plte.enc  <pltex8.pfb
+pltex9   PLTEX9    <plte.enc  <pltex9.pfb
+pltex10  PLTEX10   <plte.enc  <pltex10.pfb
+plti7    PLTI7     <plit.enc  <plti7.pfb
+plti8    PLTI8     <plit.enc  <plti8.pfb
+plti9    PLTI9     <plit.enc  <plti9.pfb
+plti10   PLTI10    <plit.enc  <plti10.pfb
+plti12   PLTI12    <plit.enc  <plti12.pfb
+pltt8    PLTT8     <pltt.enc  <pltt8.pfb
+pltt9    PLTT9     <pltt.enc  <pltt9.pfb
+pltt10   PLTT10    <pltt.enc  <pltt10.pfb
+pltt12   PLTT12    <pltt.enc  <pltt12.pfb
+plu10    PLU10     <plit.enc  <plu10.pfb
+plvtt10  PLVTT10   <plrm.enc  <plvtt10.pfb
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-plr.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-vnr.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-vnr.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-vnr.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,59 @@
+% this is the original file, i don't want to be surprised by changes,
+% so we copied it; some day soon we will use pdfmapline instead; well
+% we'll use latin modern in the end
+
+vnb10    VNB10    <vnb10.pfb
+vnbx10   VNBX10   <vnbx10.pfb
+vnbx12   VNBX12   <vnbx12.pfb
+vnbx5    VNBX5    <vnbx5.pfb
+vnbx6    VNBX6    <vnbx6.pfb
+vnbx7    VNBX7    <vnbx7.pfb
+vnbx8    VNBX8    <vnbx8.pfb
+vnbx9    VNBX9    <vnbx9.pfb
+vnbxsl10 VNBXSL10 <vnbxsl10.pfb
+vnbxti10 VNBXTI10 <vnbxti10.pfb
+vncsc10  VNCSC10  <vncsc10.pfb
+vndunh10 VNDUNH10 <vndunh10.pfb
+vnff10   VNFF10   <vnff10.pfb
+vnfi10   VNFI10   <vnfi10.pfb
+vnfib8   VNFIB8   <vnfib8.pfb
+vnitt10  VNITT10  <vnitt10.pfb
+vnr10    VNR10    <vnr10.pfb
+vnr12    VNR12    <vnr12.pfb
+vnr17    VNR17    <vnr17.pfb
+vnr5     VNR5     <vnr5.pfb
+vnr6     VNR6     <vnr6.pfb
+vnr7     VNR7     <vnr7.pfb
+vnr8     VNR8     <vnr8.pfb
+vnr9     VNR9     <vnr9.pfb
+vnsl10   VNSL10   <vnsl10.pfb
+vnsl12   VNSL12   <vnsl12.pfb
+vnsl8    VNSL8    <vnsl8.pfb
+vnsl9    VNSL9    <vnsl9.pfb
+vnsltt10 VNSLTT10 <vnsltt10.pfb
+vnss10   VNSS10   <vnss10.pfb
+vnss12   VNSS12   <vnss12.pfb
+vnss17   VNSS17   <vnss17.pfb
+vnss8    VNSS8    <vnss8.pfb
+vnss9    VNSS9    <vnss9.pfb
+vnssbx10 VNSSBX10 <vnssbx10.pfb
+vnssdc10 VNSSDC10 <vnssdc10.pfb
+vnssi10  VNSSI10  <vnssi10.pfb
+vnssi12  VNSSI12  <vnssi12.pfb
+vnssi17  VNSSI17  <vnssi17.pfb
+vnssi8   VNSSI8   <vnssi8.pfb
+vnssi9   VNSSI9   <vnssi9.pfb
+vnssq8   VNSSQ8   <vnssq8.pfb
+vnssqi8  VNSSQI8  <vnssqi8.pfb
+vntcsc10 VNTCSC10 <vntcsc10.pfb
+vnti10   VNTI10   <vnti10.pfb
+vnti12   VNTI12   <vnti12.pfb
+vnti7    VNTI7    <vnti7.pfb
+vnti8    VNTI8    <vnti8.pfb
+vnti9    VNTI9    <vnti9.pfb
+vntt10   VNTT10   <vntt10.pfb
+vntt12   VNTT12   <vntt12.pfb
+vntt8    VNTT8    <vntt8.pfb
+vntt9    VNTT9    <vntt9.pfb
+vnu10    VNU10    <vnu10.pfb
+vnvtt10  VNVTT10  <vnvtt10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-public-vnr.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-vogel-symbol.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-vogel-symbol.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-vogel-symbol.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,2 @@
+fmvr8x Marvosym < marvosym.pfb
+


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-vogel-symbol.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-wasy.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-wasy.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-wasy.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,7 @@
+wasy5      WASY5      <wasy5.pfb
+wasy6      WASY6      <wasy6.pfb
+wasy7      WASY7      <wasy7.pfb
+wasy8      WASY8      <wasy8.pfb
+wasy9      WASY9      <wasy9.pfb
+wasy10     WASY10     <wasy10.pfb
+wasyb10    WASYB10    <wasyb10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-wasy.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-px.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-px.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-px.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,51 @@
+% This file a (slightly adapted) copy of the map file
+% that comes with the PX fonts by Young Ryu.
+
+% URW fonts replaced by TeX Gyre
+
+% TeX Gyre Pagella (Palatino)
+
+rpxpplr  TeXGyrePagella-Regular     "encq8r ReEncodeFont" <q-8r.enc <qplr.pfb
+rpxpplb  TeXGyrePagella-Bold        "encq8r ReEncodeFont" <q-8r.enc <qplb.pfb
+rpxpplri TeXGyrePagella-Italic      "encq8r ReEncodeFont" <q-8r.enc <qplri.pfb
+rpxpplbi TeXGyrePagella-BoldItalic  "encq8r ReEncodeFont" <q-8r.enc <qplbi.pfb
+% no idea why these were added
+rpxpplro TeXGyrePagella-Oblique     ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qplr.pfb
+rpxpplbo TeXGyrePagella-BoldOblique ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qplb.pfb
+
+% PX Text
+
+rpxr    rpxr                    <rpxr.pfb
+rpxsl   rpxr   ".167 SlantFont" <rpxr.pfb
+rpxi    rpxi                    <rpxi.pfb
+rpxsc   rpxsc                   <rpxsc.pfb
+rpxb    rpxb                    <rpxb.pfb
+rpxbsl  rpxb   ".167 SlantFont" <rpxb.pfb
+rpxbi   rpxbi                   <rpxbi.pfb
+rpxbsc  rpxbsc                  <rpxbsc.pfb
+rpcxb   rpcxb                   <rpcxb.pfb
+rpcxbsl rpcxb  ".167 SlantFont" <rpcxb.pfb
+rpcxbi  rpcxbi                  <rpcxbi.pfb
+rpcxi   rpcxi                   <rpcxi.pfb
+rpcxr   rpcxr                   <rpcxr.pfb
+rpcxsl  rpcxsl ".167 SlantFont" <rpcxr.pfb
+
+% PX Math
+
+rpxbmi  rpxbmi                  <rpxbmi.pfb
+rpxmi   rpxmi                   <rpxmi.pfb
+
+pxbex   pxbex                   <pxbex.pfb
+pxbexa  pxbexa                  <pxbexa.pfb
+pxbmia  pxbmia                  <pxbmia.pfb
+pxbsy   pxbsy                   <pxbsy.pfb
+pxbsya  pxbsya                  <pxbsya.pfb
+pxbsyb  pxbsyb                  <pxbsyb.pfb
+pxbsyc  pxbsyc                  <pxbsyc.pfb
+pxex    pxex                    <pxex.pfb
+pxexa   pxexa                   <pxexa.pfb
+pxmia   pxmia                   <pxmia.pfb
+pxsy    pxsy                    <pxsy.pfb
+pxsya   pxsya                   <pxsya.pfb
+pxsyb   pxsyb                   <pxsyb.pfb
+pxsyc   pxsyc                   <pxsyc.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-px.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-tx.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-tx.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-tx.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,94 @@
+% This file is a (slightly adapted) copy of the map file
+% that comes with the TX fonts by Young Ryu.
+
+% URW fonts replaced by TeX Gyre
+
+% TeX Gyre Termes (Times)
+
+rtxptmr  TeXGyreTermes-Regular     "encq8r ReEncodeFont" <q-8r.enc <qtmr.pfb
+rtxptmb  TeXGyreTermes-Bold        "encq8r ReEncodeFont" <q-8r.enc <qtmb.pfb
+rtxptmri TeXGyreTermes-Italic      "encq8r ReEncodeFont" <q-8r.enc <qtmri.pfb
+rtxptmbi TeXGyreTermes-BoldItalic  "encq8r ReEncodeFont" <q-8r.enc <qtmbi.pfb
+% no idea why these were added
+rtxptmro TeXGyreTermes-Oblique     ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qtmr.pfb
+rtxptmbo TeXGyreTermes-BoldOblique ".167 SlantFont encq8r ReEncodeFont" <q-8r.enc <qtmb.pfb
+
+% TeX Gyre Heros (Helvetica)
+
+rtxphvr  TeXGyreHeros-Regular     "encqrm ReEncodeFont" <q-rm.enc <qtmr.pfb
+rtxphvb  TeXGyreHeros-Bold        "encqrm ReEncodeFont" <q-rm.enc <qtmb.pfb
+% probably not used by txfonts
+% rtxphvri TeXGyreHeros-Italic      "encqrm ReEncodeFont" <q-rm.enc <qtmri.pfb
+% rtxphvbi TeXGyreHeros-BoldItalic  "encqrm ReEncodeFont" <q-rm.enc <qtmbi.pfb
+% followed original definitions; one could also use the italic version
+rtxphvro TeXGyreHeros-Oblique     ".167 SlantFont encqrm ReEncodeFont" <q-rm.enc <qtmr.pfb
+rtxphvbo TeXGyreHeros-BoldOblique ".167 SlantFont encqrm ReEncodeFont" <q-rm.enc <qtmb.pfb
+
+% TX Text
+
+rtxr     rtxr                      <rtxr.pfb
+rtxsl    rtxr    ".167 SlantFont"  <rtxr.pfb
+rtxi     rtxi                      <rtxi.pfb
+rtxsc    rtxsc                     <rtxsc.pfb
+rtxb     rtxb                      <rtxb.pfb
+rtxbsl   rtxb    ".167 SlantFont"  <rtxb.pfb
+rtxbi    rtxbi                     <rtxbi.pfb
+rtxbsc   rtxbsc                    <rtxbsc.pfb
+rtcxb    rtcxb                     <rtcxb.pfb
+rtcxbsl  rtcxb   ".167 SlantFont"  <rtcxb.pfb
+rtcxbi   rtcxbi                    <rtcxbi.pfb
+rtcxi    rtcxi                     <rtcxi.pfb
+rtcxr    rtcxr                     <rtcxr.pfb
+rtcxsl   rtcx    ".167 SlantFont"  <rtcxr.pfb
+
+% TX Math
+
+rtxbmi   rtxbmi                    <rtxbmi.pfb
+rtxmi    rtxmi                     <rtxmi.pfb
+
+txbex    txbex                     <txbex.pfb
+txbexa   txbexa                    <txbexa.pfb
+txbmia   txbmia                    <txbmia.pfb
+txbsy    txbsy                     <txbsy.pfb
+txbsya   txbsya                    <txbsya.pfb
+txbsyb   txbsyb                    <txbsyb.pfb
+txbsyc   txbsyc                    <txbsyc.pfb
+txex     txex                      <txex.pfb
+txexa    txexa                     <txexa.pfb
+txmia    txmia                     <txmia.pfb
+txsy     txsy                      <txsy.pfb
+txsya    txsya                     <txsya.pfb
+txsyb    txsyb                     <txsyb.pfb
+txsyc    txsyc                     <txsyc.pfb
+
+% TX TT Text
+
+txtt     txtt                      <txtt.pfb
+txttsl   txtt     ".167 SlantFont" <txtt.pfb
+txttsc   txttsc                    <txttsc.pfb
+txbtt    txbtt                     <txbtt.pfb
+txbttsl  txbtt    ".167 SlantFont" <txbtt.pfb
+txbttsc  txbttsc                   <txbttsc.pfb
+t1xtt    t1xtt                     <t1xtt.pfb
+t1xttsl  t1xtt    ".167 SlantFont" <t1xtt.pfb
+t1xttsc  t1xttsc                   <t1xttsc.pfb
+t1xbtt   t1xbtt                    <t1xbtt.pfb
+t1xbttsl t1xbtt   ".167 SlantFont" <t1xbtt.pfb
+t1xbttsc t1xbttsc                  <t1xbttsc.pfb
+tcxtt    tcxtt                     <tcxtt.pfb
+tcxttsl  tcxtt    ".167 SlantFont" <tcxtt.pfb
+tcxbtt   tcxbtt                    <tcxbtt.pfb
+tcxbttsl tcxbtt   ".167 SlantFont" <tcxbtt.pfb
+
+% TX SS Text
+
+rtxss    rtxss                     <rtxss.pfb
+rtxsssl  rtxss    ".167 SlantFont" <rtxss.pfb
+rtxsssc  rtxsssc                   <rtxsssc.pfb
+rtxbss   rtxbss                    <rtxbss.pfb
+rtxbsssl rtxbss   ".167 SlantFont" <rtxbss.pfb
+rtxbsssc rtxbsssc                  <rtxbsssc.pfb
+rtcxss   rtcxss                    <rtcxss.pfb
+rtcxbss  rtcxbss                   <rtcxbss.pfb
+rtcxsssl rtcxss   ".167 SlantFont" <rtcxss.pfb
+rtcxbsso rtcxbss  ".167 SlantFont" <rtcxbss.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/original-youngryu-tx.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,55 @@
+% courier / urw
+
+qcrb  <qcr.enc <qcrb.pfb
+qcrbi <qcr.enc <qcrbi.pfb
+qcrr  <qcr.enc <qcrr.pfb
+qcrri <qcr.enc <qcrri.pfb
+
+% helvetica / urw
+
+qhvb   <qhv.enc <qhvb.pfb
+qhvbi  <qhv.enc <qhvbi.pfb
+qhvcb  <qhv.enc <qhvcb.pfb
+qhvcbi <qhv.enc <qhvcbi.pfb
+qhvcr  <qhv.enc <qhvcr.pfb
+qhvcri <qhv.enc <qhvcri.pfb
+qhvr   <qhv.enc <qhvr.pfb
+qhvri  <qhv.enc <qhvri.pfb
+
+% times / urw
+
+qtmb  <qtm.enc <qtmb.pfb
+qtmbi <qtm.enc <qtmbi.pfb
+qtmr  <qtm.enc <qtmr.pfb
+qtmri <qtm.enc <qtmri.pfb
+
+% palatino / urw
+
+qplb  <qpl.enc <qplb.pfb
+qplbi <qpl.enc <qplbi.pfb
+qplr  <qpl.enc <qplr.pfb
+qplri <qpl.enc <qplri.pfb
+
+% bookman / urw
+
+qbkb  <qbk.enc <qbkb.pfb
+qbkbi <qbk.enc <qbkbi.pfb
+qbkr  <qbk.enc <qbkr.pfb
+qbkri <qbk.enc <qbkri.pfb
+
+% chancery / urw
+
+qzcmi <qzc.enc <qzcmi.pfb
+
+% schoolbook / urw
+%
+% not available
+
+% utopia
+%
+% not available
+
+% charter
+%
+% not available
+


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-os-public-lm.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-os-public-lm.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-os-public-lm.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,69 @@
+qx-lmb10 LMRoman10-Demi "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmb10.pfb
+qx-lmbo10 LMRoman10-DemiOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbo10.pfb
+qx-lmbx10 LMRoman10-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx10.pfb
+qx-lmbx12 LMRoman12-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx12.pfb
+qx-lmbx5 LMRoman5-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx5.pfb
+qx-lmbx6 LMRoman6-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx6.pfb
+qx-lmbx7 LMRoman7-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx7.pfb
+qx-lmbx8 LMRoman8-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx8.pfb
+qx-lmbx9 LMRoman9-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbx9.pfb
+qx-lmbxi10 LMRoman10-BoldItalic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbxi10.pfb
+qx-lmbxo10 LMRoman10-BoldOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmbxo10.pfb
+qx-lmcsc10 LMRoman10-CapsRegular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmcsc10.pfb
+qx-lmcsco10 LMRoman10-CapsOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmcsco10.pfb
+qx-lmr10 LMRoman10-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr10.pfb
+qx-lmr12 LMRoman12-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr12.pfb
+qx-lmr17 LMRoman17-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr17.pfb
+qx-lmr5 LMRoman5-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr5.pfb
+qx-lmr6 LMRoman6-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr6.pfb
+qx-lmr7 LMRoman7-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr7.pfb
+qx-lmr8 LMRoman8-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr8.pfb
+qx-lmr9 LMRoman9-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmr9.pfb
+qx-lmri10 LMRoman10-Italic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmri10.pfb
+qx-lmri12 LMRoman12-Italic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmri12.pfb
+qx-lmri7 LMRoman7-Italic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmri7.pfb
+qx-lmri8 LMRoman8-Italic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmri8.pfb
+qx-lmri9 LMRoman9-Italic "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmri9.pfb
+qx-lmro10 LMRoman10-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmro10.pfb
+qx-lmro12 LMRoman12-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmro12.pfb
+qx-lmro17 LMRoman17-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmro17.pfb
+qx-lmro8 LMRoman8-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmro8.pfb
+qx-lmro9 LMRoman9-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmro9.pfb
+qx-lmss10 LMSans10-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmss10.pfb
+qx-lmss12 LMSans12-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmss12.pfb
+qx-lmss17 LMSans17-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmss17.pfb
+qx-lmss8 LMSans8-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmss8.pfb
+qx-lmss9 LMSans9-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmss9.pfb
+qx-lmssbo10 LMSans10-BoldOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssbo10.pfb
+qx-lmssbx10 LMSans10-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssbx10.pfb
+qx-lmssdc10 LMSans10-DemiCondensed "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssdc10.pfb
+qx-lmssdo10 LMSans10-DemiCondensedOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssdo10.pfb
+qx-lmsso10 LMSans10-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmsso10.pfb
+qx-lmsso12 LMSans12-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmsso12.pfb
+qx-lmsso17 LMSans17-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmsso17.pfb
+qx-lmsso8 LMSans8-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmsso8.pfb
+qx-lmsso9 LMSans9-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmsso9.pfb
+qx-lmssq8 LMSansQuotation8-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssq8.pfb
+qx-lmssqbo8 LMSansQuotation8-BoldOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssqbo8.pfb
+qx-lmssqbx8 LMSansQuotation8-Bold "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssqbx8.pfb
+qx-lmssqo8 LMSansQuotation8-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmssqo8.pfb
+qx-lmtcsc10 LMTypewriter10-CapsRegular "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtcsc10.pfb
+qx-lmtcso10 LMTypewriter10-CapsOblique "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtcso10.pfb
+qx-lmtl10 LMTypewriter10-Light "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtl10.pfb
+qx-lmtlo10 LMTypewriter10-LightOblique "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtlo10.pfb
+qx-lmtlc10 LMTypewriter10-LightCondensed "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtlc10.pfb
+qx-lmtlco10 LMTypewriter10-LightCondensedOblique "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtlco10.pfb
+qx-lmtk10 LMTypewriter10-Dark "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtk10.pfb
+qx-lmtko10 LMTypewriter10-DarkOblique "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtko10.pfb
+qx-lmtt10 LMTypewriter10-Regular "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtt10.pfb
+qx-lmtt12 LMTypewriter12-Regular "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtt12.pfb
+qx-lmtt8 LMTypewriter8-Regular "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtt8.pfb
+qx-lmtt9 LMTypewriter9-Regular "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtt9.pfb
+qx-lmtti10 LMTypewriter10-Italic "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtti10.pfb
+qx-lmtto10 LMTypewriter10-Oblique "enclmqxostt ReEncodeFont" <lm-qxtt.enc <lmtto10.pfb
+qx-lmvtt10 LMTypewriterVarWd10-Regular "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtt10.pfb
+qx-lmvtto10 LMTypewriterVarWd10-Oblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtto10.pfb
+qx-lmvtl10 LMTypewriterVarWd10-Light "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtl10.pfb
+qx-lmvtlo10 LMTypewriterVarWd10-LightOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtlo10.pfb
+qx-lmvtk10 LMTypewriterVarWd10-Dark "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtk10.pfb
+qx-lmvtko10 LMTypewriterVarWd10-DarkOblique "enclmqxos ReEncodeFont" <lm-qx-os.enc <lmvtko10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/qx-os-public-lm.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,72 @@
+% courier / urw
+
+ucrr8v  VnNimbusMonL-Regu                          "T5Encoding ReEncodeFont" <t5.enc <ucrr8v.pfb
+ucrro8v VnNimbusMonL-ReguObli                      "T5Encoding ReEncodeFont" <t5.enc <ucrro8v.pfb
+ucrb8v  VnNimbusMonL-Bold                          "T5Encoding ReEncodeFont" <t5.enc <ucrb8v.pfb
+ucrbo8v VnNimbusMonL-BoldObli                      "T5Encoding ReEncodeFont" <t5.enc <ucrbo8v.pfb
+
+% helvetica / urw
+
+uhvr8v  VnNimbusSanL-Regu                          "T5Encoding ReEncodeFont" <t5.enc <uhvr8v.pfb
+uhvro8v VnNimbusSanL-ReguItal                      "T5Encoding ReEncodeFont" <t5.enc <uhvro8v.pfb
+uhvb8v  VnNimbusSanL-Bold                          "T5Encoding ReEncodeFont" <t5.enc <uhvb8v.pfb
+uhvbo8v VnNimbusSanL-BoldItal                      "T5Encoding ReEncodeFont" <t5.enc <uhvbo8v.pfb
+
+% times / urw
+
+utmr8v  VnNimbusRomNo9L-Regu                       "T5Encoding ReEncodeFont" <t5.enc <utmr8v.pfb
+utmri8v VnNimbusRomNo9L-ReguItal                   "T5Encoding ReEncodeFont" <t5.enc <utmri8v.pfb
+utmb8v  VnNimbusRomNo9L-Medi                       "T5Encoding ReEncodeFont" <t5.enc <utmb8v.pfb
+utmbi8v VnNimbusRomNo9L-MediItal                   "T5Encoding ReEncodeFont" <t5.enc <utmbi8v.pfb
+
+utmro8v VnNimbusRomNo9L-Regu       "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <utmr8v.pfb
+utmbo8v VnNimbusRomNo9L-Medi       "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <utmb8v.pfb
+
+% palatino / urw
+
+uplr8v  VnURWPalladioL-Roma                        "T5Encoding ReEncodeFont" <t5.enc <uplr8v.pfb
+uplri8v VnURWPalladioL-Ital                        "T5Encoding ReEncodeFont" <t5.enc <uplri8v.pfb
+uplb8v  VnURWPalladioL-Bold                        "T5Encoding ReEncodeFont" <t5.enc <uplb8v.pfb
+uplbi8v VnURWPalladioL-BoldItal                    "T5Encoding ReEncodeFont" <t5.enc <uplbi8v.pfb
+
+uplro8v VnURWPalladioL-Roma        "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <uplr8v.pfb
+uplbo8v VnURWPalladioL-Bold        "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <uplb8v.pfb
+
+% bookman / urw
+
+ubkl8v  VnURWBookmanL-Ligh                         "T5Encoding ReEncodeFont" <t5.enc <ubkl8v.pfb
+ubkli8v VnURWBookmanL-LighItal                     "T5Encoding ReEncodeFont" <t5.enc <ubkli8v.pfb
+ubkd8v  VnURWBookmanL-DemiBold                     "T5Encoding ReEncodeFont" <t5.enc <ubkd8v.pfb
+ubkdi8v VnURWBookmanL-DemiBoldItal                 "T5Encoding ReEncodeFont" <t5.enc <ubkdi8v.pfb
+
+ubklo8v VnURWBookmanL-Ligh         "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <ubkl8v.pfb
+ubkdo8v VnURWBookmanL-DemiBold     "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <ubkd8v.pfb
+
+% chancery / urw
+
+% not supported
+%
+% schoolbook / urw
+
+uncr8v  VnCenturySchL-Roma                         "T5Encoding ReEncodeFont" <t5.enc <uncr8v.pfb
+uncri8v VnCenturySchL-Ital                         "T5Encoding ReEncodeFont" <t5.enc <uncri8v.pfb
+uncb8v  VnCenturySchL-Bold                         "T5Encoding ReEncodeFont" <t5.enc <uncb8v.pfb
+uncbi8v VnCenturySchL-BoldItal                     "T5Encoding ReEncodeFont" <t5.enc <uncbi8v.pfb
+
+uncro8v VnCenturySchL-Roma         "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <uncr8v.pfb
+uncbo8v VnCenturySchL-Bold         "0.277 SlantFont T5Encoding ReEncodeFont" <t5.enc <uncb8v.pfb
+
+% utopia
+%
+% not supported
+
+% charter
+%
+% not supported
+
+% gothic / urw
+
+uagk8v  VnURWGothicL-Book                          "T5Encoding ReEncodeFont" <t5.enc <uagk8v.pfb
+uagko8v VnURWGothicL-BookObli                      "T5Encoding ReEncodeFont" <t5.enc <uagko8v.pfb
+uagd8v  VnURWGothicL-Demi                          "T5Encoding ReEncodeFont" <t5.enc <uagd8v.pfb
+uagdo8v VnURWGothicL-DemiObli                      "T5Encoding ReEncodeFont" <t5.enc <uagdo8v.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-os-public-lm.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-os-public-lm.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-os-public-lm.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,69 @@
+t5-lmb10 LMRoman10-Demi "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmb10.pfb
+t5-lmbo10 LMRoman10-DemiOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbo10.pfb
+t5-lmbx10 LMRoman10-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx10.pfb
+t5-lmbx12 LMRoman12-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx12.pfb
+t5-lmbx5 LMRoman5-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx5.pfb
+t5-lmbx6 LMRoman6-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx6.pfb
+t5-lmbx7 LMRoman7-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx7.pfb
+t5-lmbx8 LMRoman8-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx8.pfb
+t5-lmbx9 LMRoman9-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbx9.pfb
+t5-lmbxi10 LMRoman10-BoldItalic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbxi10.pfb
+t5-lmbxo10 LMRoman10-BoldOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmbxo10.pfb
+t5-lmcsc10 LMRoman10-CapsRegular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmcsc10.pfb
+t5-lmcsco10 LMRoman10-CapsOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmcsco10.pfb
+t5-lmr10 LMRoman10-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr10.pfb
+t5-lmr12 LMRoman12-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr12.pfb
+t5-lmr17 LMRoman17-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr17.pfb
+t5-lmr5 LMRoman5-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr5.pfb
+t5-lmr6 LMRoman6-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr6.pfb
+t5-lmr7 LMRoman7-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr7.pfb
+t5-lmr8 LMRoman8-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr8.pfb
+t5-lmr9 LMRoman9-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmr9.pfb
+t5-lmri10 LMRoman10-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmri10.pfb
+t5-lmri12 LMRoman12-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmri12.pfb
+t5-lmri7 LMRoman7-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmri7.pfb
+t5-lmri8 LMRoman8-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmri8.pfb
+t5-lmri9 LMRoman9-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmri9.pfb
+t5-lmro10 LMRoman10-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmro10.pfb
+t5-lmro12 LMRoman12-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmro12.pfb
+t5-lmro17 LMRoman17-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmro17.pfb
+t5-lmro8 LMRoman8-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmro8.pfb
+t5-lmro9 LMRoman9-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmro9.pfb
+t5-lmss10 LMSans10-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmss10.pfb
+t5-lmss12 LMSans12-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmss12.pfb
+t5-lmss17 LMSans17-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmss17.pfb
+t5-lmss8 LMSans8-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmss8.pfb
+t5-lmss9 LMSans9-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmss9.pfb
+t5-lmssbo10 LMSans10-BoldOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssbo10.pfb
+t5-lmssbx10 LMSans10-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssbx10.pfb
+t5-lmssdc10 LMSans10-DemiCondensed "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssdc10.pfb
+t5-lmssdo10 LMSans10-DemiCondensedOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssdo10.pfb
+t5-lmsso10 LMSans10-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmsso10.pfb
+t5-lmsso12 LMSans12-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmsso12.pfb
+t5-lmsso17 LMSans17-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmsso17.pfb
+t5-lmsso8 LMSans8-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmsso8.pfb
+t5-lmsso9 LMSans9-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmsso9.pfb
+t5-lmssq8 LMSansQuotation8-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssq8.pfb
+t5-lmssqbo8 LMSansQuotation8-BoldOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssqbo8.pfb
+t5-lmssqbx8 LMSansQuotation8-Bold "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssqbx8.pfb
+t5-lmssqo8 LMSansQuotation8-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmssqo8.pfb
+t5-lmtcsc10 LMTypewriter10-CapsRegular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtcsc10.pfb
+t5-lmtcso10 LMTypewriter10-CapsOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtcso10.pfb
+t5-lmtl10 LMTypewriter10-Light "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtl10.pfb
+t5-lmtlo10 LMTypewriter10-LightOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtlo10.pfb
+t5-lmtlc10 LMTypewriter10-LightCondensed "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtlc10.pfb
+t5-lmtlco10 LMTypewriter10-LightCondensedOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtlco10.pfb
+t5-lmtk10 LMTypewriter10-Dark "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtk10.pfb
+t5-lmtko10 LMTypewriter10-DarkOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtko10.pfb
+t5-lmtt10 LMTypewriter10-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtt10.pfb
+t5-lmtt12 LMTypewriter12-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtt12.pfb
+t5-lmtt8 LMTypewriter8-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtt8.pfb
+t5-lmtt9 LMTypewriter9-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtt9.pfb
+t5-lmtti10 LMTypewriter10-Italic "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtti10.pfb
+t5-lmtto10 LMTypewriter10-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmtto10.pfb
+t5-lmvtt10 LMTypewriterVarWd10-Regular "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtt10.pfb
+t5-lmvtto10 LMTypewriterVarWd10-Oblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtto10.pfb
+t5-lmvtl10 LMTypewriterVarWd10-Light "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtl10.pfb
+t5-lmvtlo10 LMTypewriterVarWd10-LightOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtlo10.pfb
+t5-lmvtk10 LMTypewriterVarWd10-Dark "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtk10.pfb
+t5-lmvtko10 LMTypewriterVarWd10-DarkOblique "enclmt5os ReEncodeFont" <lm-t5-os.enc <lmvtko10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/t5-os-public-lm.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-base.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-base.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-base.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,142 @@
+% author: Hans Hagen
+%
+% This map file defines the texnansi alternatives of the public fonts,
+% beware, these are seldom present on your system. If you really want
+% to use these fonts, uncomment the relevant lines. If no fonts are
+% present, pdftex may get confused.
+
+% courier / urw
+
+% ucrb8y  NimbusMonL-Bold          <texnansi.enc <ucrb8a.pfb
+% ucrbo8y NimbusMonL-BoldObli      <texnansi.enc <ucrbo8a.pfb
+% ucrr8y  NimbusMonL-Regu          <texnansi.enc <ucrr8a.pfb
+% ucrro8y NimbusMonL-ReguObli      <texnansi.enc <ucrro8a.pfb
+
+% courier / adobe
+
+% pcrb8y  NimbusMonL-Bold          <texnansi.enc <ucrb8a.pfb
+% pcrbo8y NimbusMonL-BoldObli      <texnansi.enc <ucrbo8a.pfb
+% pcrr8y  NimbusMonL-Regu          <texnansi.enc <ucrr8a.pfb
+% pcrro8y NimbusMonL-ReguObli      <texnansi.enc <ucrro8a.pfb
+
+% helvetica / urw
+
+% uhvb8y  NimbusSanL-Bold          <texnansi.enc <uhvb8a.pfb
+% uhvbo8y NimbusSanL-BoldItal      <texnansi.enc <uhvbo8a.pfb
+% uhvr8y  NimbusSanL-Regu          <texnansi.enc <uhvr8a.pfb
+% uhvro8y NimbusSanL-ReguItal      <texnansi.enc <uhvro8a.pfb
+
+% helvetica / adobe
+
+% phvb8y  NimbusSanL-Bold          <texnansi.enc <uhvb8a.pfb
+% phvbo8y NimbusSanL-BoldItal      <texnansi.enc <uhvbo8a.pfb
+% phvr8y  NimbusSanL-Regu          <texnansi.enc <uhvr8a.pfb
+% phvro8y NimbusSanL-ReguItal      <texnansi.enc <uhvro8a.pfb
+
+% times / urw
+
+% utmb8y  NimbusRomNo9L-Medi       <texnansi.enc <utmb8a.pfb
+% utmbi8y NimbusRomNo9L-MediItal   <texnansi.enc <utmbi8a.pfb
+% utmr8y  NimbusRomNo9L-Regu       <texnansi.enc <utmr8a.pfb
+% utmri8y NimbusRomNo9L-ReguItal   <texnansi.enc <utmri8a.pfb
+
+% utmbo8y NimbusRomNo9L-Medi       ".167 SlantFont" <texnansi.enc <utmb8a.pfb
+% utmro8y NimbusRomNo9L-Regu       ".167 SlantFont" <texnansi.enc <utmr8a.pfb
+
+% times / adobe
+
+% ptmb8y  NimbusRomNo9L-Medi       <texnansi.enc <utmb8a.pfb
+% ptmbi8y NimbusRomNo9L-MediItal   <texnansi.enc <utmbi8a.pfb
+% ptmr8y  NimbusRomNo9L-Regu       <texnansi.enc <utmr8a.pfb
+% ptmri8y NimbusRomNo9L-ReguItal   <texnansi.enc <utmri8a.pfb
+
+% ptmbo8y NimbusRomNo9L-Medi       ".167 SlantFont" <texnansi.enc <utmb8a.pfb
+% ptmro8y NimbusRomNo9L-Regu       ".167 SlantFont" <texnansi.enc <utmr8a.pfb
+
+% palatino / urw
+
+% uplb8y  URWPalladioL-Bold        <texnansi.enc <uplb8a.pfb
+% uplbi8y URWPalladioL-BoldItal    <texnansi.enc <uplbi8a.pfb
+% uplr8y  URWPalladioL-Roma        <texnansi.enc <uplr8a.pfb
+% uplri8y URWPalladioL-Ital        <texnansi.enc <uplri8a.pfb
+
+% uplbo8y URWPalladioL-Bold        ".167 SlantFont" <texnansi.enc <uplb8a.pfb
+% uplro8y URWPalladioL-Roma        ".167 SlantFont" <texnansi.enc <uplr8a.pfb
+
+% palatino / adobe
+
+% pplb8y  URWPalladioL-Bold        <texnansi.enc <uplb8a.pfb
+% pplbi8y URWPalladioL-BoldItal    <texnansi.enc <uplbi8a.pfb
+% pplr8y  URWPalladioL-Roma        <texnansi.enc <uplr8a.pfb
+% pplri8y URWPalladioL-Ital        <texnansi.enc <uplri8a.pfb
+
+% pplbo8y URWPalladioL-Bold        ".167 SlantFont" <texnansi.enc <uplb8a.pfb
+% pplro8y URWPalladioL-Roma        ".167 SlantFont" <texnansi.enc <uplr8a.pfb
+
+% bookman / urw
+
+% ubkd8y  URWBookmanL-DemiBold     <texnansi.enc <ubkd8a.pfb
+% ubkdi8y URWBookmanL-DemiBoldItal <texnansi.enc <ubkdi8a.pfb
+% ubkl8y  URWBookmanL-Ligh         <texnansi.enc <ubkl8a.pfb
+% vubkli8y URWBookmanL-LighItal     <texnansi.enc <ubkli8a.pfb
+
+% ubkdo8y URWBookmanL-DemiBold     ".167 SlantFont" <texnansi.enc <ubkd8a.pfb
+% ubklo8y URWBookmanL-Ligh         ".167 SlantFont" <texnansi.enc <ubkl8a.pfb
+
+% bookman / adobe
+
+% pbkd8y  URWBookmanL-DemiBold     <texnansi.enc <ubkd8a.pfb
+% pbkdi8y URWBookmanL-DemiBoldItal <texnansi.enc <ubkdi8a.pfb
+% pbkl8y  URWBookmanL-Ligh         <texnansi.enc <ubkl8a.pfb
+% pbkli8y URWBookmanL-LighItal     <texnansi.enc <ubkli8a.pfb
+
+% pbkdo8y URWBookmanL-DemiBold     ".167 SlantFont" <texnansi.enc <ubkd8a.pfb
+% pbklo8y URWBookmanL-Ligh         ".167 SlantFont" <texnansi.enc <ubkl8a.pfb
+
+% chancery / urw
+
+% uzcmi8y URWChanceryL-MediItal    <texnansi.enc <uzcmi8a.pfb
+
+% chancery / adobe
+
+% pzcmi8y URWChanceryL-MediItal    <texnansi.enc <uzcmi8a.pfb
+
+% schoolbook / urw
+
+% uncb8y  CenturySchL-Bold         <texnansi.enc <uncb8a.pfb
+% uncbi8y CenturySchL-BoldItal     <texnansi.enc <uncbi8a.pfb
+% uncr8y  CenturySchL-Roma         <texnansi.enc <uncr8a.pfb
+% uncri8y CenturySchL-Ital         <texnansi.enc <uncri8a.pfb
+
+% uncbo8y CenturySchL-Bold         ".167 SlantFont" <texnansi.enc <uncb8a.pfb
+% uncro8y CenturySchL-Roma         ".167 SlantFont" <texnansi.enc <uncr8a.pfb
+
+% schoolbook / adobe
+
+% pncb8y  CenturySchL-Bold         <texnansi.enc <uncb8a.pfb
+% pncbi8y CenturySchL-BoldItal     <texnansi.enc <uncbi8a.pfb
+% pncr8y  CenturySchL-Roma         <texnansi.enc <uncr8a.pfb
+% pncri8y CenturySchL-Ital         <texnansi.enc <uncri8a.pfb
+
+% pncbo8y CenturySchL-Bold         ".167 SlantFont" <texnansi.enc <uncb8a.pfb
+% pncro8y CenturySchL-Roma         ".167 SlantFont" <texnansi.enc <uncr8a.pfb
+
+% utopia
+
+% putb8y  Utopia-Bold              <texnansi.enc <putb8a.pfb
+% putbi8y Utopia-BoldItalic        <texnansi.enc <putbi8a.pfb
+% putr8y  Utopia-Regular           <texnansi.enc <putr8a.pfb
+% putri8y Utopia-Italic            <texnansi.enc <putri8a.pfb
+
+% putbo8y Utopia-Bold              ".167 SlantFont" <texnansi.enc <putb8a.pfb
+% putro8y Utopia-Regular           ".167 SlantFont" <texnansi.enc <putr8a.pfb
+
+% charter
+
+% bchb8y  CharterBT-Bold           <texnansi.enc <bchb8a.pfb
+% bchbi8y CharterBT-BoldItalic     <texnansi.enc <bchbi8a.pfb
+% bchr8y  CharterBT-Roman          <texnansi.enc <bchr8a.pfb
+% bchri8y CharterBT-Italic         <texnansi.enc <bchri8a.pfb
+
+% bchbo8y CharterBT-Bold           ".167 SlantFont"  <texnansi.enc <bchb8a.pfb
+% bchro8y CharterBT-Roman          ".167 SlantFont " <texnansi.enc <bchr8a.pfb
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-base.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-os-public-lm.map
===================================================================
--- trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-os-public-lm.map	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-os-public-lm.map	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,69 @@
+texnansi-lmb10 LMRoman10-Demi "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmb10.pfb
+texnansi-lmbo10 LMRoman10-DemiOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbo10.pfb
+texnansi-lmbx10 LMRoman10-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx10.pfb
+texnansi-lmbx12 LMRoman12-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx12.pfb
+texnansi-lmbx5 LMRoman5-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx5.pfb
+texnansi-lmbx6 LMRoman6-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx6.pfb
+texnansi-lmbx7 LMRoman7-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx7.pfb
+texnansi-lmbx8 LMRoman8-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx8.pfb
+texnansi-lmbx9 LMRoman9-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbx9.pfb
+texnansi-lmbxi10 LMRoman10-BoldItalic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbxi10.pfb
+texnansi-lmbxo10 LMRoman10-BoldOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmbxo10.pfb
+texnansi-lmcsc10 LMRoman10-CapsRegular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmcsc10.pfb
+texnansi-lmcsco10 LMRoman10-CapsOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmcsco10.pfb
+texnansi-lmr10 LMRoman10-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr10.pfb
+texnansi-lmr12 LMRoman12-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr12.pfb
+texnansi-lmr17 LMRoman17-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr17.pfb
+texnansi-lmr5 LMRoman5-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr5.pfb
+texnansi-lmr6 LMRoman6-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr6.pfb
+texnansi-lmr7 LMRoman7-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr7.pfb
+texnansi-lmr8 LMRoman8-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr8.pfb
+texnansi-lmr9 LMRoman9-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmr9.pfb
+texnansi-lmri10 LMRoman10-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmri10.pfb
+texnansi-lmri12 LMRoman12-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmri12.pfb
+texnansi-lmri7 LMRoman7-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmri7.pfb
+texnansi-lmri8 LMRoman8-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmri8.pfb
+texnansi-lmri9 LMRoman9-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmri9.pfb
+texnansi-lmro10 LMRoman10-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmro10.pfb
+texnansi-lmro12 LMRoman12-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmro12.pfb
+texnansi-lmro17 LMRoman17-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmro17.pfb
+texnansi-lmro8 LMRoman8-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmro8.pfb
+texnansi-lmro9 LMRoman9-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmro9.pfb
+texnansi-lmss10 LMSans10-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmss10.pfb
+texnansi-lmss12 LMSans12-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmss12.pfb
+texnansi-lmss17 LMSans17-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmss17.pfb
+texnansi-lmss8 LMSans8-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmss8.pfb
+texnansi-lmss9 LMSans9-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmss9.pfb
+texnansi-lmssbo10 LMSans10-BoldOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssbo10.pfb
+texnansi-lmssbx10 LMSans10-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssbx10.pfb
+texnansi-lmssdc10 LMSans10-DemiCondensed "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssdc10.pfb
+texnansi-lmssdo10 LMSans10-DemiCondensedOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssdo10.pfb
+texnansi-lmsso10 LMSans10-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmsso10.pfb
+texnansi-lmsso12 LMSans12-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmsso12.pfb
+texnansi-lmsso17 LMSans17-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmsso17.pfb
+texnansi-lmsso8 LMSans8-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmsso8.pfb
+texnansi-lmsso9 LMSans9-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmsso9.pfb
+texnansi-lmssq8 LMSansQuotation8-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssq8.pfb
+texnansi-lmssqbo8 LMSansQuotation8-BoldOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssqbo8.pfb
+texnansi-lmssqbx8 LMSansQuotation8-Bold "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssqbx8.pfb
+texnansi-lmssqo8 LMSansQuotation8-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmssqo8.pfb
+texnansi-lmtcsc10 LMTypewriter10-CapsRegular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtcsc10.pfb
+texnansi-lmtcso10 LMTypewriter10-CapsOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtcso10.pfb
+texnansi-lmtl10 LMTypewriter10-Light "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtl10.pfb
+texnansi-lmtlo10 LMTypewriter10-LightOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtlo10.pfb
+texnansi-lmtlc10 LMTypewriter10-LightCondensed "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtlc10.pfb
+texnansi-lmtlco10 LMTypewriter10-LightCondensedOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtlco10.pfb
+texnansi-lmtk10 LMTypewriter10-Dark "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtk10.pfb
+texnansi-lmtko10 LMTypewriter10-DarkOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtko10.pfb
+texnansi-lmtt10 LMTypewriter10-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtt10.pfb
+texnansi-lmtt12 LMTypewriter12-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtt12.pfb
+texnansi-lmtt8 LMTypewriter8-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtt8.pfb
+texnansi-lmtt9 LMTypewriter9-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtt9.pfb
+texnansi-lmtti10 LMTypewriter10-Italic "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtti10.pfb
+texnansi-lmtto10 LMTypewriter10-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmtto10.pfb
+texnansi-lmvtt10 LMTypewriterVarWd10-Regular "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtt10.pfb
+texnansi-lmvtto10 LMTypewriterVarWd10-Oblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtto10.pfb
+texnansi-lmvtl10 LMTypewriterVarWd10-Light "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtl10.pfb
+texnansi-lmvtlo10 LMTypewriterVarWd10-LightOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtlo10.pfb
+texnansi-lmvtk10 LMTypewriterVarWd10-Dark "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtk10.pfb
+texnansi-lmvtko10 LMTypewriterVarWd10-DarkOblique "enclmtexnansios ReEncodeFont" <lm-texnansi-os.enc <lmvtko10.pfb


Property changes on: trunk/Master/texmf-dist/fonts/map/pdftex/context/texnansi-os-public-lm.map
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/metapost/context/base/mpii/metafun.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/metafun.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/metafun.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,65 @@
+%D \module
+%D   [       file=metafun.mp,
+%D        version=2000.07.15,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=format generation file,
+%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.
+
+%D When generating many graphics at runtime, it can save run
+%D time to use a format file. We could have named this file
+%D \type {context}, but this is error prone, because it forces
+%D to use the progname \type {mpost} or \type {context}
+%D explicitly, depending on the needs. When using the format,
+%D a mismatch in the memory specification of \type {mpost} or
+%D \type {context} (the \TEX\ one) could lead to lost strings
+%D (and as a result in buggy boundingbox and special
+%D handling). By using the name \type {metatex} we make sure
+%D that we use (unless overloaded) the settings of \type
+%D {mpost}.
+
+%D First we input John Hobby's metapost plain file. However,
+%D because we want to prevent dependency problems and in the
+%D end even may use a patched version, we prefer to use a
+%D copy.
+
+input "mp-base.mpii" ;
+input "mp-tool.mpii" ;
+input "mp-spec.mpii" ;
+input "mp-core.mpii" ;
+input "mp-page.mpii" ;
+input "mp-text.mpii" ;
+input "mp-txts.mpii" ;
+input "mp-shap.mpii" ;
+input "mp-butt.mpii" ;
+input "mp-char.mpii" ;
+input "mp-step.mpii" ;
+input "mp-grph.mpii" ;
+input "mp-figs.mpii" ;
+%%%%% "mp-form.mpii" ;
+input "mp-grid.mpii" ;
+input "mp-func.mpii" ;
+
+string metafunversion ;
+
+metafunversion = "metafun ii"                        & " " &
+                 decimal year                        & "-" &
+                 decimal month                       & "-" &
+                 decimal day                         & " " &
+                 if ((time div 60) < 10)           :   "0" & fi
+                 decimal (time div 60)               & ":" &
+                 if ((time-(time div 60)*60) < 10) :   "0" & fi
+                 decimal (time-(time div 60)*60)   ;
+
+let normalend = end ;
+
+def end =
+  ; message "" ; message metafunversion ; message "" ; normalend ;
+enddef ;
+
+% dump ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-back.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-back.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-back.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,205 @@
+%D \module
+%D   [       file=mp-back.mp,
+%D        version=2000.05.31,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=backgrounds,
+%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 licen-en.pdf for
+%C details.
+
+if known context_back : endinput ; fi ;
+
+boolean context_back ; context_back := true ;
+
+def some_hash ( expr hash_width     ,
+                     hash_height    ,
+                     hash_linewidth ,
+                     hash_linecolor ,
+                     hash_angle     ,
+                     hash_gap       ) =
+
+  stripe_gap := hash_gap ;
+  stripe_angle := hash_angle ;
+  drawoptions (withpen pencircle scaled hash_linewidth
+               withcolor hash_linecolor) ;
+  path p ; p := unitsquare xscaled hash_width yscaled hash_height ;
+  stripe_path_a () (draw) p ;  % next we move it all to quadrant 1
+  currentpicture := currentpicture shifted urcorner currentpicture ;
+
+enddef ;
+
+def some_double_back (expr back_type        ,
+                           back_width       ,
+                           back_height      ,
+                           back_delta       ,
+                           back_linewidth   ,
+                           back_linecolor   ,
+                           back_fillcolor   ,
+                           back_topcolor    ,
+                           back_bottomcolor ,
+                           back_leftcolor   ,
+                           back_rightcolor  ) =
+
+  numeric ww ; ww := back_width  ;
+  numeric hh ; hh := back_height ;
+  numeric dd ; dd := back_delta  ;
+
+  color back_nillcolor ; back_nillcolor := back_topcolor ;
+
+  path p ; p := fullsquare xscaled  ww      yscaled  hh      ;
+  path q ; q := fullsquare xscaled (ww-2dd) yscaled (hh-2dd) ;
+  path r ; r := llcorner p --
+                lrcorner p shifted (-3dd,0) .. controls lrcorner p ..
+                lrcorner p shifted (0, 3dd) --
+                urcorner p shifted (0,-3dd) .. controls urcorner p ..
+                urcorner p shifted (-3dd,0) --
+                ulcorner p -- cycle ;
+  path s ; s := r xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+  path t ; t := llcorner p --
+                lrcorner p --
+                urcorner p shifted (0,-3dd) .. controls urcorner p ..
+                urcorner p shifted (-3dd,0) --
+                ulcorner p shifted ( 3dd,0) .. controls ulcorner p ..
+                ulcorner p shifted (0,-3dd) --
+                llcorner p -- cycle ;
+  path u ; u := t xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+  path v ; v := llcorner p shifted ( 3dd,0) --
+                lrcorner p shifted (-3dd,0) .. controls lrcorner p ..
+                lrcorner p shifted (0, 3dd) --
+                urcorner p shifted (0,-3dd) .. controls urcorner p ..
+                urcorner p shifted (-3dd,0) --
+                ulcorner p shifted ( 3dd,0) .. controls ulcorner p ..
+                ulcorner p shifted (0,-3dd) ..
+                llcorner p shifted (0, 3dd) .. controls llcorner p .. cycle ; % {down}  .. cycle ;
+  path w ; w := t xscaled ((ww-2dd)/ww) yscaled ((hh-2dd)/hh) ;
+  path a ; a := llcorner p -- ulcorner p --
+                ulcorner q -- llcorner q -- cycle ;
+  path b ; b := llcorner p -- lrcorner p --
+                lrcorner q -- llcorner q -- cycle ;
+  path c ; c := lrcorner p -- urcorner p --
+                urcorner q -- lrcorner q -- cycle ;
+  path d ; d := ulcorner p -- urcorner p --
+                urcorner q -- ulcorner q -- cycle ;
+  path e ; e := llcorner p -- lrcorner p --
+                urcorner p -- urcorner q --
+                lrcorner q -- llcorner q -- cycle ;
+  path f ; f := llcorner p -- ulcorner p --
+                urcorner p -- urcorner q --
+                ulcorner q -- llcorner q -- cycle ;
+
+  linecap := butt ; pickup pencircle scaled back_linewidth ;
+
+  if back_type=1 :
+
+    fill p withcolor back_fillcolor   ;
+    fill a withcolor back_leftcolor   ;
+    fill b withcolor back_bottomcolor ;
+    fill c withcolor back_rightcolor  ;
+    fill d withcolor back_topcolor    ;
+    draw a withcolor back_linecolor   ;
+    draw d withcolor back_linecolor   ;
+    draw b withcolor back_linecolor   ;
+    draw c withcolor back_linecolor   ;
+
+  elseif back_type=2 :
+
+    fill p withcolor back_fillcolor   ;
+    fill e withcolor back_bottomcolor ;
+    fill f withcolor back_topcolor    ;
+    draw e withcolor back_linecolor   ;
+    draw f withcolor back_linecolor   ;
+
+  elseif back_type=3 :
+
+    fill v withcolor back_nillcolor   ;
+    fill w withcolor back_fillcolor   ;
+    draw v withcolor back_linecolor   ;
+    draw w withcolor back_linecolor   ;
+
+  elseif back_type=4 :
+
+    fill t withcolor back_nillcolor   ;
+    fill u withcolor back_fillcolor   ;
+    draw t withcolor back_linecolor   ;
+    draw u withcolor back_linecolor   ;
+
+  elseif back_type=5 :
+
+    t := t rotatedaround(center t,180) ;
+    u := u rotatedaround(center u,180) ;
+
+    fill t withcolor back_nillcolor   ;
+    fill u withcolor back_fillcolor   ;
+    draw t withcolor back_linecolor   ;
+    draw u withcolor back_linecolor   ;
+
+  elseif back_type=6 :
+
+    r := r rotatedaround(center r,180) ;
+    s := s rotatedaround(center s,180) ;
+
+    fill r withcolor back_nillcolor   ;
+    fill s withcolor back_fillcolor   ;
+    draw r withcolor back_linecolor   ;
+    draw s withcolor back_linecolor   ;
+
+  elseif back_type=7 :
+
+    fill r withcolor back_nillcolor   ;
+    fill s withcolor back_fillcolor   ;
+    draw r withcolor back_linecolor   ;
+    draw s withcolor back_linecolor   ;
+
+fi ;
+
+enddef ;
+
+endinput ;
+
+beginfig (1) ;
+
+some_double_back (1, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, .6white, .7white, .6white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (2, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, .6white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (3, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (4, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (5, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (6, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (7, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+currentpicture := currentpicture shifted (0,-3cm) ;
+
+some_double_back (8, 4.5cm, 1.5cm, .25cm, 1mm,
+           .5white, .8white, .7white, white, white, white)
+
+endfig ;
+
+end .

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-base.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-base.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-base.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,598 @@
+% This is (currently) a copy of the plain.mp file. We use a copy
+% because (1) we want to make sure that there are no unresolved
+% dependencies, and (2) we may patch this file eventually.
+%
+% colorpart will be overloaded later (we already had that one)
+% _findarr now has a filldraw, was fill in 0.63
+
+% This file gives the macros for plain MetaPost
+% It contains all the features of plain METAFONT except those specific to
+% font-making.  (See The METAFONTbook by D.E. Knuth).
+% There are also a number of macros for labeling figures, etc.
+string base_name, base_version; base_name="plain"; base_version="1.004 for metafun ii";
+
+message "Preloading the plain mem file, version "&base_version;
+
+delimiters ();  % this makes parentheses behave like parentheses
+def upto = step 1 until enddef; % syntactic sugar
+def downto = step -1 until enddef;
+def exitunless expr c = exitif not c enddef;
+let relax = \;  % ignore the word `relax', as in TeX
+let \\ = \; % double relaxation is like single
+def ]] = ] ] enddef; % right brackets should be loners
+def -- = {curl 1}..{curl 1} enddef;
+def --- = .. tension infinity .. enddef;
+def ... = .. tension atleast 1 .. enddef;
+
+def gobble primary g = enddef;
+primarydef g gobbled gg = enddef;
+def hide(text t) = exitif numeric begingroup t;endgroup; enddef;
+def ??? = hide(interim showstopping:=1; showdependencies) enddef;
+def stop expr s = message s; gobble readstring enddef;
+
+warningcheck:=1;
+tracinglostchars:=1;
+
+def interact = % sets up to make "show" commands stop
+ hide(showstopping:=1; tracingonline:=1) enddef;
+
+def loggingall =        % puts tracing info into the log
+ tracingcommands:=3; tracingtitles:=1; tracingequations:=1;
+ tracingcapsules:=1; tracingspecs:=2; tracingchoices:=1; tracinglostchars:=1;
+ tracingstats:=1; tracingoutput:=1; tracingmacros:=1; tracingrestores:=1;
+ enddef;
+
+def tracingall =        % turns on every form of tracing
+ tracingonline:=1; showstopping:=1; loggingall enddef;
+
+def tracingnone =       % turns off every form of tracing
+ tracingcommands:=0; tracingtitles:=0; tracingequations:=0;
+ tracingcapsules:=0; tracingspecs:=0; tracingchoices:=0; tracinglostchars:=0;
+ tracingstats:=0; tracingoutput:=0; tracingmacros:=0; tracingrestores:=0;
+ enddef;
+
+
+
+%% dash patterns
+
+vardef dashpattern(text t) =
+  save on, off, w;
+  let on=_on_;
+  let off=_off_;
+  w = 0;
+  nullpicture t
+enddef;
+
+tertiarydef p _on_ d =
+  begingroup save pic;
+  picture pic; pic=p;
+  addto pic doublepath (w,w)..(w+d,w);
+  w := w+d;
+  pic shifted (0,d)
+  endgroup
+enddef;
+
+tertiarydef p _off_ d =
+  begingroup w:=w+d;
+  p shifted (0,d)
+  endgroup
+enddef;
+
+
+
+%% basic constants and mathematical macros
+
+% numeric constants
+newinternal eps,epsilon,infinity,_;
+eps := .00049;    % this is a pretty small positive number
+epsilon := 1/256/256;   % but this is the smallest
+infinity := 4095.99998;    % and this is the largest
+_ := -1; % internal constant to make macros unreadable but shorter
+
+newinternal mitered, rounded, beveled, butt, squared;
+mitered:=0; rounded:=1; beveled:=2; % linejoin types
+butt:=0;    rounded:=1; squared:=2; % linecap types
+
+
+% pair constants
+pair right,left,up,down,origin;
+origin=(0,0); up=-down=(0,1); right=-left=(1,0);
+
+% path constants
+path quartercircle,halfcircle,fullcircle,unitsquare;
+fullcircle = makepath pencircle;
+halfcircle = subpath (0,4) of fullcircle;
+quartercircle = subpath (0,2) of fullcircle;
+unitsquare=(0,0)--(1,0)--(1,1)--(0,1)--cycle;
+
+% transform constants
+transform identity;
+for z=origin,right,up: z transformed identity = z; endfor
+
+% color constants
+color black, white, red, green, blue, cyan, magenta, yellow, background;
+black = (0,0,0);
+white = (1,1,1);
+red = (1,0,0);
+green = (0,1,0);
+blue = (0,0,1);
+cyan = (0,1,1);
+magenta = (1,0,1);
+yellow = (1,1,0);
+background = white;   % The user can reset this
+
+% color part selection for within
+
+newinternal nocolormodel   ; nocolormodel   := 1 ;
+newinternal greycolormodel ; greycolormodel := 3 ;
+newinternal graycolormodel ; graycolormodel := 3 ;
+newinternal rgbcolormodel  ; rgbcolormodel  := 5 ;
+newinternal cmykcolormodel ; cmykcolormodel := 7 ;
+
+def colorpart primary t =
+  if colormodel t=cmykcolormodel:
+    (cyanpart t, magentapart t, yellowpart t, blackpart t)
+  elseif colormodel t=rgbcolormodel:
+    (redpart t, greenpart t, bluepart t)
+  elseif colormodel t=graycolormodel:
+    (greypart t)
+  elseif colormodel t=nocolormodel:
+    false
+  else:
+    %%% For clipping and bounding paths, etc.
+    if defaultcolormodel=cmykcolormodel: (0,0,0,1)
+    elseif defaultcolormodel=rgbcolormodel: black
+    elseif defaultcolormodel=graycolormodel: 0
+    else: false
+    fi
+  fi
+enddef;
+
+% picture constants
+picture blankpicture,evenly,withdots;
+blankpicture=nullpicture; % `display blankpicture...'
+evenly=dashpattern(on 3 off 3); % `dashed evenly'
+withdots=dashpattern(off 2.5 on 0 off 2.5); % `dashed withdots'
+
+% string constants
+string ditto, EOF;
+ditto = char 34; % ASCII double-quote mark
+EOF = char 0;    % end-of-file for readfrom and write..to
+
+% pen constants
+pen pensquare,penrazor,penspeck;
+pensquare = makepen(unitsquare shifted -(.5,.5));
+penrazor = makepen((-.5,0)--(.5,0)--cycle);
+penspeck=pensquare scaled eps;
+
+% nullary operators
+vardef whatever = save ?; ? enddef;
+
+% unary operators
+let abs = length;
+
+vardef round primary u =
+ if numeric u: floor(u+.5)
+ elseif pair u: (round xpart u, round ypart u)
+ else: u fi enddef;
+
+vardef ceiling primary x = -floor(-x) enddef;
+
+vardef byte primary s =
+ if string s: ASCII fi s enddef;
+
+vardef dir primary d = right rotated d enddef;
+
+vardef unitvector primary z = z/abs z enddef;
+
+vardef inverse primary T =
+ transform T_; T_ transformed T = identity; T_ enddef;
+
+vardef counterclockwise primary c =
+ if turningnumber c <= 0: reverse fi c enddef;
+
+vardef tensepath expr r =
+ for k=0 upto length r - 1: point k of r --- endfor
+ if cycle r: cycle else: point infinity of r fi enddef;
+
+vardef center primary p = .5[llcorner p, urcorner p] enddef;
+
+
+
+% binary operators
+
+primarydef x mod y = (x-y*floor(x/y)) enddef;
+primarydef x div y = floor(x/y) enddef;
+primarydef w dotprod z = (xpart w * xpart z + ypart w * ypart z) enddef;
+
+primarydef x**y = if y=2: x*x else: takepower y of x fi enddef;
+def takepower expr y of x =
+ if x>0: mexp(y*mlog x)
+ elseif (x=0) and (y>0): 0
+ else: 1
+  if y=floor y:
+   if y>=0: for n=1 upto y: *x endfor
+   else: for n=_ downto y: /x endfor
+   fi
+  else: hide(errmessage "Undefined power: " & decimal x&"**"&decimal y)
+  fi fi enddef;
+
+vardef direction expr t of p =
+ postcontrol t of p - precontrol t of p enddef;
+
+vardef directionpoint expr z of p =
+ a_:=directiontime z of p;
+ if a_<0: errmessage("The direction doesn't occur"); fi
+ point a_ of p enddef;
+
+secondarydef p intersectionpoint q =
+ begingroup save x_,y_; (x_,y_)=p intersectiontimes q;
+ if x_<0: errmessage("The paths don't intersect"); origin
+ else: .5[point x_ of p, point y_ of q] fi endgroup
+enddef;
+
+tertiarydef p softjoin q =
+ begingroup c_:=fullcircle scaled 2join_radius shifted point 0 of q;
+ a_:=ypart(c_ intersectiontimes p); b_:=ypart(c_ intersectiontimes q);
+ if a_<0:point 0 of p{direction 0 of p} else: subpath(0,a_) of p fi
+  ... if b_<0:{direction infinity of q}point infinity of q
+   else: subpath(b_,infinity) of q fi endgroup enddef;
+newinternal join_radius,a_,b_; path c_;
+
+
+path cuttings;  % what got cut off
+
+tertiarydef a cutbefore b =  % tries to cut as little as possible
+  begingroup save t;
+  (t, whatever) = a intersectiontimes b;
+  if t<0:
+    cuttings:=point 0 of a;
+    a
+  else: cuttings:= subpath (0,t) of a;
+    subpath (t,length a) of a
+  fi
+  endgroup
+enddef;
+
+tertiarydef a cutafter b =
+  reverse (reverse a  cutbefore  b)
+  hide(cuttings:=reverse cuttings)
+enddef;
+
+
+
+% special operators
+vardef incr suffix $ = $:=$+1; $ enddef;
+vardef decr suffix $ = $:=$-1; $ enddef;
+
+def reflectedabout(expr w,z) =    % reflects about the line w..z
+ transformed
+  begingroup transform T_;
+  w transformed T_ = w;  z transformed T_ = z;
+  xxpart T_ = -yypart T_; xypart T_ = yxpart T_; % T_ is a reflection
+  T_ endgroup enddef;
+
+def rotatedaround(expr z, d) =    % rotates d degrees around z
+ shifted -z rotated d shifted z enddef;
+let rotatedabout = rotatedaround;   % for roundabout people
+
+vardef min(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_; setu_ u; for uu = t: if uu<u_: u_:=uu; fi endfor
+ u_ enddef;
+
+vardef max(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_; setu_ u; for uu = t: if uu>u_: u_:=uu; fi endfor
+ u_ enddef;
+
+def setu_ primary u =
+ if pair u: pair u_ elseif string u: string u_ fi;
+ u_=u enddef;
+
+def flex(text t) =           % t is a list of pairs
+ hide(n_:=0; for z=t: z_[incr n_]:=z; endfor
+  dz_:=z_[n_]-z_1)
+ z_1 for k=2 upto n_-1: ...z_[k]{dz_} endfor ...z_[n_] enddef;
+newinternal n_; pair z_[],dz_;
+
+def superellipse(expr r,t,l,b,s)=
+ r{up}...(s[xpart t,xpart r],s[ypart r,ypart t]){t-r}...
+ t{left}...(s[xpart t,xpart l],s[ypart l,ypart t]){l-t}...
+ l{down}...(s[xpart b,xpart l],s[ypart l,ypart b]){b-l}...
+ b{right}...(s[xpart b,xpart r],s[ypart r,ypart b]){r-b}...cycle enddef;
+
+vardef interpath(expr a,p,q) =
+ for t=0 upto length p-1: a[point t of p, point t of q]
+  ..controls a[postcontrol t of p, postcontrol t of q]
+   and a[precontrol t+1 of p, precontrol t+1 of q] .. endfor
+ if cycle p: cycle
+ else: a[point infinity of p, point infinity of q] fi enddef;
+
+vardef solve@#(expr true_x,false_x)= % @#(true_x)=true, @#(false_x)=false
+ tx_:=true_x; fx_:=false_x;
+ forever: x_:=.5[tx_,fx_]; exitif abs(tx_-fx_)<=tolerance;
+ if @#(x_): tx_ else: fx_ fi :=x_; endfor
+ x_ enddef; % now x_ is near where @# changes from true to false
+newinternal tolerance, tx_,fx_,x_; tolerance:=.01;
+
+vardef buildcycle(text ll) =
+  save ta_, tb_, k_, i_, pp_; path pp_[];
+  k_=0;
+  for q=ll: pp_[incr k_]=q; endfor
+  i_=k_;
+  for i=1 upto k_:
+    (ta_[i], length pp_[i_]-tb_[i_]) =
+      pp_[i] intersectiontimes reverse pp_[i_];
+    if ta_[i]<0:
+      errmessage("Paths "& decimal i &" and "& decimal i_ &" don't intersect");
+    fi
+    i_ := i;
+  endfor
+  for i=1 upto k_: subpath (ta_[i],tb_[i]) of pp_[i] .. endfor
+    cycle
+enddef;
+
+
+
+%% units of measure
+
+mm=2.83464;      pt=0.99626;        dd=1.06601;      bp:=1;
+cm=28.34645;     pc=11.95517;       cc=12.79213;     in:=72;
+
+vardef magstep primary m = mexp(46.67432m) enddef;
+
+
+
+%% macros for drawing and filling
+
+def drawoptions(text t) =
+  def _op_ = t enddef
+enddef;
+
+linejoin:=rounded;               % parameters that effect drawing
+linecap:=rounded;
+miterlimit:=10;
+
+drawoptions();
+
+pen currentpen;
+picture currentpicture;
+
+def fill expr c = addto currentpicture contour c _op_ enddef;
+def draw expr p =
+  addto currentpicture
+  if picture p:
+    also p
+  else:
+    doublepath p withpen currentpen
+  fi
+  _op_
+enddef;
+def filldraw expr c =
+  addto currentpicture contour c withpen currentpen
+  _op_ enddef;
+% def drawdot expr z =
+%   addto currentpicture contour makepath currentpen shifted z
+%   _op_ enddef;
+
+def drawdot expr p =
+    if pair p :
+        addto currentpicture doublepath p withpen currentpen _op_
+    else :
+        errmessage("drawdot only accepts a pair expression")
+    fi
+enddef ;
+
+def unfill expr c = fill c withcolor background enddef;
+def undraw expr p = draw p withcolor background enddef;
+def unfilldraw expr c = filldraw c withcolor background enddef;
+def undrawdot expr z = drawdot z withcolor background enddef;
+def erase text t =
+  def _e_ = withcolor background hide(def _e_=enddef;) enddef;
+  t _e_
+enddef;
+def _e_= enddef;
+
+def cutdraw text t =
+  begingroup interim linecap:=butt; draw t _e_; endgroup enddef;
+
+vardef image(text t) =
+  save currentpicture;
+  picture currentpicture;
+  currentpicture := nullpicture;
+  t;
+  currentpicture
+enddef;
+
+def pickup secondary q =
+ if numeric q: numeric_pickup_ else: pen_pickup_ fi q enddef;
+def numeric_pickup_ primary q =
+ if unknown pen_[q]: errmessage "Unknown pen"; clearpen
+ else: currentpen:=pen_[q];
+  pen_lft:=pen_lft_[q];
+  pen_rt:=pen_rt_[q];
+  pen_top:=pen_top_[q];
+  pen_bot:=pen_bot_[q];
+  currentpen_path:=pen_path_[q] fi; enddef;
+def pen_pickup_ primary q =
+  currentpen:=q;
+  pen_lft:=xpart penoffset down of currentpen;
+  pen_rt:=xpart penoffset up of currentpen;
+  pen_top:=ypart penoffset left of currentpen;
+  pen_bot:=ypart penoffset right of currentpen;
+  path currentpen_path; enddef;
+newinternal pen_lft,pen_rt,pen_top,pen_bot,pen_count_;
+
+vardef savepen = pen_[incr pen_count_]=currentpen;
+ pen_lft_[pen_count_]=pen_lft;
+ pen_rt_[pen_count_]=pen_rt;
+ pen_top_[pen_count_]=pen_top;
+ pen_bot_[pen_count_]=pen_bot;
+ pen_path_[pen_count_]=currentpen_path;
+ pen_count_ enddef;
+
+def clearpen = currentpen:=nullpen;
+ pen_lft:=pen_rt:=pen_top:=pen_bot:=0;
+ path currentpen_path;
+ enddef;
+def clear_pen_memory =
+ pen_count_:=0;
+ numeric pen_lft_[],pen_rt_[],pen_top_[],pen_bot_[];
+ pen currentpen,pen_[];
+ path currentpen_path, pen_path_[];
+ enddef;
+
+vardef lft primary x = x + if pair x: (pen_lft,0) else: pen_lft fi enddef;
+vardef rt primary x = x + if pair x: (pen_rt,0) else: pen_rt fi enddef;
+vardef top primary y = y + if pair y: (0,pen_top) else: pen_top fi enddef;
+vardef bot primary y = y + if pair y: (0,pen_bot) else: pen_bot fi enddef;
+
+vardef penpos@#(expr b,d) =
+ (x@#r-x@#l,y@#r-y@#l)=(b,0) rotated d;
+ x@#=.5(x@#l+x@#r); y@#=.5(y@#l+y@#r) enddef;
+
+def penstroke text t =
+ forsuffixes e = l,r: path_.e:=t; endfor
+ fill path_.l -- reverse path_.r -- cycle enddef;
+path path_.l,path_.r;
+
+
+
+%% High level drawing commands
+
+newinternal ahlength, ahangle;
+ahlength := 4;            % default arrowhead length 4bp
+ahangle := 45;           % default head angle 45 degrees
+
+vardef arrowhead expr p =
+  save q,e; path q; pair e;
+  e = point length p of p;
+  q = gobble(p shifted -e cutafter makepath(pencircle scaled 2ahlength))
+    cuttings;
+  (q rotated .5ahangle & reverse q rotated -.5ahangle -- cycle)  shifted e
+enddef;
+
+path _apth;
+def drawarrow expr p = _apth:=p; _finarr enddef;
+def drawdblarrow expr p = _apth:=p; _findarr enddef;
+
+def _finarr text t =
+  draw _apth t;
+  filldraw arrowhead _apth  t
+enddef;
+
+def _findarr text t =
+  draw _apth t;
+  filldraw arrowhead _apth withpen currentpen  t;
+  filldraw arrowhead  reverse _apth  withpen currentpen  t
+enddef;
+
+
+
+%% macros for labels
+
+newinternal bboxmargin; bboxmargin:=2bp;
+
+vardef bbox primary p =
+  llcorner p-(bboxmargin,bboxmargin) -- lrcorner p+(bboxmargin,-bboxmargin)
+  -- urcorner p+(bboxmargin,bboxmargin) -- ulcorner p+(-bboxmargin,bboxmargin)
+  -- cycle
+enddef;
+
+string defaultfont;
+newinternal defaultscale, labeloffset;
+defaultfont = "cmr10";
+defaultscale := 1;
+labeloffset := 3bp;
+
+vardef thelabel@#(expr s,z) =  % Position s near z
+  save p; picture p;
+  if picture s:  p=s
+  else:    p = s infont defaultfont scaled defaultscale
+  fi;
+  p shifted (z + labeloffset*laboff@# -
+     (labxf@#*lrcorner p + labyf@#*ulcorner p
+       + (1-labxf@#-labyf@#)*llcorner p
+     )
+  )
+enddef;
+
+def label = draw thelabel enddef;
+newinternal dotlabeldiam; dotlabeldiam:=3bp;
+vardef dotlabel@#(expr s,z) text t_ =
+  label@#(s,z) t_;
+  interim linecap:=rounded;
+  draw z withpen pencircle scaled dotlabeldiam t_;
+enddef;
+def makelabel = dotlabel enddef;
+
+pair laboff, laboff.lft, laboff.rt, laboff.top, laboff.bot;
+pair laboff.ulft, laboff.llft, laboff.urt, laboff.lrt;
+laboff    =(0,0);    labxf    =.5;  labyf    =.5;
+laboff.lft=(-1,0);   labxf.lft=1;   labyf.lft=.5;
+laboff.rt =(1,0);    labxf.rt =0;   labyf.rt =.5;
+laboff.bot=(0,-1);   labxf.bot=.5;  labyf.bot=1;
+laboff.top=(0,1);    labxf.top=.5;  labyf.top=0;
+laboff.ulft=(-.7,.7);labxf.ulft=1;  labyf.ulft=0;
+laboff.urt=(.7,.7);  labxf.urt=0;   labyf.urt=0;
+laboff.llft=-(.7,.7);labxf.llft=1;  labyf.llft=1;
+laboff.lrt=(.7,-.7); labxf.lrt=0;   labyf.lrt=1;
+
+vardef labels@#(text t) =
+ forsuffixes $=t:
+   label@#(str$,z$); endfor
+ enddef;
+vardef dotlabels@#(text t) =
+ forsuffixes $=t:
+   dotlabel@#(str$,z$); endfor
+ enddef;
+vardef penlabels@#(text t) =
+ forsuffixes $$=l,,r: forsuffixes $=t:
+   makelabel@#(str$.$$,z$.$$); endfor endfor
+ enddef;
+
+
+def range expr x = numtok[x] enddef;
+def numtok suffix x=x enddef;
+tertiarydef m thru n =
+ m for x=m+1 step 1 until n: , numtok[x] endfor enddef;
+
+
+
+%% Overall adminstration
+
+string extra_beginfig, extra_endfig;
+extra_beginfig = extra_endfig = "" ;
+
+def beginfig(expr c) =
+  begingroup
+  charcode:=c;
+  clearxy; clearit; clearpen;
+  pickup defaultpen;
+  drawoptions();
+  scantokens extra_beginfig;
+enddef;
+
+def endfig =
+  ; % added by HH
+  scantokens extra_endfig;
+  shipit ;
+  endgroup
+enddef;
+
+
+%% last-minute items
+
+vardef z@#=(x@#,y@#) enddef;
+
+def clearxy = save x,y enddef;
+def clearit = currentpicture:=nullpicture enddef;
+def shipit = shipout currentpicture enddef;
+
+let bye = end; outer end,bye;
+
+clear_pen_memory;     % initialize the `savepen' mechanism
+clearit;
+
+newinternal defaultpen;
+pickup pencircle scaled .5bp;  % set default line width
+defaultpen := savepen;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-butt.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-butt.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-butt.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,77 @@
+%D \module
+%D   [       file=mp-butt.mpii,
+%D        version=2000.05.31,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=buttons,
+%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 licen-en.pdf for
+%C details.
+
+if known context_butt : endinput ; fi ;
+
+boolean context_butt ; context_butt := true ;
+
+def predefinedbutton (expr button_type, button_size, button_linecolor, button_fillcolor) =
+
+    begingroup ;
+
+    save button_linewidth, p, d, l ;
+
+    numeric button_linewidth ; button_linewidth := button_size/10 ;
+
+    drawoptions (withpen pencircle scaled button_linewidth withcolor button_linecolor) ;
+
+    path    p ; p := unitsquare scaled button_size ;
+    numeric d ; d := button_size ;
+    numeric l ; l := button_linewidth ;
+
+    fill p withcolor button_fillcolor ;
+    draw p ;
+
+    if     button_type = 101 :
+        draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ;
+    elseif button_type = 102 :
+        draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ;
+    elseif button_type = 103 :
+        for i=2l step 2l until d-2l :
+            draw (2l,i)--(2l  ,i) ;
+            draw (4l,i)--(d-2l,i) ;
+        endfor ;
+    elseif button_type = 104 :
+        for i=2l step 2l until d-2l :
+            draw (2l   ,i)--(d/2-l,i) ;
+            draw (d/2+l,i)--(d-2l ,i) ;
+        endfor ;
+    elseif button_type = 105 :
+        fill fullcircle scaled (.2d) shifted (.5d,.7d) ;
+        fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ;
+        clip currentpicture to p ;
+        draw p ;
+    elseif button_type = 106 :
+        draw (2l,2l)--(d-2l,d-2l) ;
+        draw (d-2l,2l)--(2l,d-2l) ;
+    elseif button_type = 107 :
+        p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ;
+        fill p ; draw p ;
+        draw (.5d,2l) ;
+    elseif button_type = 108 :
+        draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ;
+    elseif button_type = 109 :
+        draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ;
+    elseif button_type = 110 :
+        button_linewidth := button_linewidth/2 ;
+        draw p enlarged (-2l,-l) ;
+        for i=2l step l until d-2l :
+            draw (3l,i)--(d-3l,i) ;
+        endfor ;
+    fi ;
+
+    endgroup ;
+
+enddef ;
+
+let some_button = predefinedbutton

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-char.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-char.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-char.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,1006 @@
+% to be cleaned up, namespace needed ! ! ! ! !
+
+%D \module
+%D   [       file=mp-char.mpii,
+%D        version=1998.10.10,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=charts,
+%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 licen-en.pdf for
+%C details.
+
+if unknown context_shap : input "mp-shap.mpii" ; fi ;
+if   known context_flow : endinput ; fi ;
+
+boolean context_char ; context_char := true ;
+
+% kan naar elders
+
+current_position := 0 ;
+
+def save_text_position (expr p) =  % beware: clip shift needed
+  current_position := current_position + 1 ;
+  savedata
+    "\MPposition{" & decimal current_position & "}{"
+                   & decimal xpart p          & "}{"
+                   & decimal ypart p          & "}%" ;
+enddef ;
+
+%D settings
+
+grid_width   := 60pt ; grid_height  := 40pt ;
+shape_width  := 45pt ; shape_height := 30pt ;
+
+chart_offset :=  2pt ;
+color chart_background_color ; chart_background_color := white ;
+
+%D test mode
+
+boolean show_mid_points ; show_mid_points := false ;
+boolean show_con_points ; show_con_points := false ;
+boolean show_all_points ; show_all_points := false ;
+
+%D shapes
+
+color shape_line_color, shape_fill_color ;
+
+shape_line_width := 2pt ;
+shape_line_color := .5white ;
+shape_fill_color := .9white ;
+
+shape_node           :=  0 ;
+shape_action         := 24 ;
+shape_procedure      :=  5 ;
+shape_product        := 12 ;
+shape_decision       := 14 ;
+shape_archive        := 19 ;
+shape_loop           := 35 ;
+shape_wait           :=  6 ;
+shape_subprocedure   := 20 ; shape_sub_procedure   := 20 ;
+shape_singledocument := 32 ; shape_single_document := 32 ;
+shape_multidocument  := 33 ; shape_multi_document  := 33 ;
+shape_right          := 66 ;
+shape_left           := 67 ;
+shape_up             := 68 ;
+shape_down           := 69 ;
+
+% vardef some_shape_path (expr type) == imported from mp-shap
+
+def show_shapes (expr n) =
+
+  begin_chart(n,8,10) ;
+    show_con_points := true ;
+    for i=0 upto 7 :
+      for j=0 upto 9 :
+        new_shape(i+1,j+1,i*10+j);
+      endfor ;
+    endfor ;
+  end_chart ;
+
+enddef ;
+
+%D connections
+
+def new_chart =
+
+  color connection_line_color ;
+
+  connection_line_width  := shape_line_width ;
+  connection_line_color  := .8white ;
+  connection_smooth_size := 5pt ;
+  connection_arrow_size  := 4pt ;
+  connection_dash_size   := 3pt ;
+
+  max_x := 6 ;
+  max_y := 4 ;
+
+  numeric xypoint       ; xypoint := 0 ;
+
+  pair    xypoints []   ;
+
+  boolean xyfree   [][] ;
+  path    xypath   [][] ;
+  numeric xysx     [][] ;
+  numeric xysy     [][] ;
+  color   xyfill   [][] ;
+  color   xydraw   [][] ;
+  numeric xyline   [][] ;
+  boolean xypeep   [][] ;
+  picture xypicture[][] ;
+
+  numeric cpath         ; cpath := 0 ;
+  path    cpaths    []  ;
+  numeric cline     []  ;
+  color   ccolor    []  ;
+  boolean carrow    []  ;
+  boolean cdash     []  ;
+  boolean ccross    []  ;
+
+  boolean smooth        ; smooth       := true  ;
+  boolean peepshape     ; peepshape    := false ;
+  boolean arrowtip      ; arrowtip     := true  ;
+  boolean dashline      ; dashline     := false ;
+  boolean forcevalid    ; forcevalid   := false ;
+  boolean touchshape    ; touchshape   := false ;
+  boolean showcrossing  ; showcrossing := false ;
+
+  picture dash_pattern ;
+
+  boolean reverse_y ; reverse_y := true ;
+
+enddef ;
+
+new_chart ;
+
+def y_pos (expr y) =
+  if reverse_y : max_y + 1 - y else : y fi
+enddef ;
+
+def initialize_grid (expr maxx, maxy) =
+  begingroup ;
+  save i, j ;
+  max_x := maxx ;
+  max_y := maxy ;
+  dsp_x := 0 ;
+  dsp_y := 0 ;
+  for x=1 upto max_x :
+    for y=1 upto max_y :
+      xyfree [x][y] := true ;
+      xyfill [x][y] := shape_fill_color ;
+      xydraw [x][y] := shape_line_color ;
+      xyline [x][y] := shape_line_width ;
+    endfor ;
+  endfor ;
+  endgroup ;
+enddef ;
+
+def scaled_to_grid =
+  xscaled grid_width yscaled grid_height
+enddef ;
+
+def xy_offset (expr x, y) =
+  (x+.5,y+.5)
+enddef ;
+
+def draw_shape (expr x, yy, p, sx, sy) =
+  begingroup ;
+  save y ;
+  y := y_pos(yy) ;
+  xypath [x][y] := (p xscaled sx yscaled sy) shifted xy_offset(x,y) ;
+  xyfree [x][y] := false ;
+  xysx   [x][y] := sx ;
+  xysy   [x][y] := sy ;
+  xyfill [x][y] := shape_fill_color ;
+  xydraw [x][y] := shape_line_color ;
+  xyline [x][y] := shape_line_width ;
+  xypeep [x][y] := peepshape ;
+  endgroup ;
+enddef ;
+
+vardef i_point (expr x, y, p, t) =
+  begingroup ;
+  save q, ok ;
+  pair q ;
+  boolean ok ;
+  q := xypath[x][y] intersection_point ((p) shifted xy_offset(x,y)) ;
+  ok := true ;
+%  if xpart q < -.5 : ok := false ; q := (-.45,ypart q) fi ;
+%  if xpart q >  .5 : ok := false ; q := ( .45,ypart q) fi ;
+%  if ypart q < -.5 : ok := false ; q := (xpart q,-.45) fi ;
+%  if ypart q >  .5 : ok := false ; q := (xpart q, .45) fi ;
+  if not ok :
+    message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ;
+  fi ;
+  q
+  endgroup
+enddef ;
+
+vardef trimmed (expr x, y, z, t) =
+  if touchshape and t : xyline[x][y]/z else : epsilon fi
+enddef ;
+
+zfactor := 1/3 ;
+
+vardef xy_bottom (expr x, y, z, t) =
+  i_point (x, y, ((0,0)--(0,-2)) shifted (zfactor*z*xysx[x][y],0), "bottom")
+  shifted(0,-trimmed(x,y,grid_height,t))
+enddef ;
+
+vardef xy_top (expr x, y, z, t) =
+  i_point (x, y, ((0,0)--(0,2))  shifted (zfactor*z*xysx[x][y],0), "top")
+  shifted(0,trimmed(x,y,grid_height,t))
+enddef ;
+
+vardef xy_left (expr x, y, z, t) =
+  i_point (x, y, ((0,0)--(-2,0)) shifted (0,zfactor*z*xysy[x][y]), "left")
+  shifted(-trimmed(x,y,grid_width,t),0)
+enddef ;
+
+vardef xy_right (expr x, y, z, t) =
+  i_point (x, y, ((0,0)--(2,0))  shifted (0,zfactor*z*xysy[x][y]), "right")
+  shifted(trimmed(x,y,grid_width,t),0)
+enddef ;
+
+def flush_shapes =
+  for x=1 upto max_x :
+    for y=1 upto max_y :
+      flush_shape (x, y) ;
+    endfor ;
+  endfor ;
+enddef ;
+
+def flush_pictures =
+  for x=1 upto max_x :
+    for y=1 upto max_y :
+      flush_picture (x, y) ;
+    endfor ;
+  endfor ;
+enddef ;
+
+
+def draw_connection_point (expr x, y, z) =
+  pickup pencircle scaled if (z=0): 2 fi xyline[x][y] ;
+  drawdot xy_bottom(x,y,z,false) scaled_to_grid withcolor (1,0,0) ;
+  drawdot xy_top   (x,y,z,false) scaled_to_grid withcolor (0,1,0) ;
+  drawdot xy_left  (x,y,z,false) scaled_to_grid withcolor (0,0,1) ;
+  drawdot xy_right (x,y,z,false) scaled_to_grid withcolor (1,1,0) ;
+enddef ;
+
+def flush_shape (expr x, yy) =
+  begingroup ;
+  save y ;
+  y := y_pos(yy) ;
+  if not xyfree[x][y] :
+    pickup pencircle scaled xyline[x][y] ;
+    if xypeep[x][y] :
+      fill (xypath[x][y] peepholed (unitsquare shifted (x,y)))
+        scaled_to_grid withpen pencircle scaled 0
+        withcolor chart_background_color ;
+    else :
+      fill xypath[x][y] scaled_to_grid withcolor xyfill[x][y] ;
+    fi ;
+    draw xypath[x][y] scaled_to_grid withcolor xydraw[x][y] ;
+    if show_con_points or show_all_points :
+      draw_connection_point (x, y, 0) ;
+    fi ;
+    if show_all_points :
+      for i=-1 upto 1 :
+        draw_connection_point (x, y, i) ;
+      endfor ;
+    fi ;
+  fi ;
+  endgroup ;
+enddef ;
+
+vardef points_initialized (expr xfrom, yfrom, xto, yto, n) =
+  if not xyfree[xfrom][yfrom] and not xyfree[xto][yto] :
+    xypoint := n ; true
+  else :
+    xypoint := 0 ; false
+  fi
+enddef ;
+
+def collapse_points =
+  % remove redundant points
+  n := 1 ;
+  for i=2 upto xypoint:
+    if not (xypoints[i]=xypoints[n]) :
+      n := n + 1 ;
+      xypoints[n] := xypoints[i]
+    fi ;
+  endfor ;
+  xypoint := n ;
+  % make straight lines
+  if xypoints[2]=xypoints[xypoint-1] :
+    xypoints[3] := xypoints[xypoint] ;
+    xypoint := 3 ;
+  fi ;
+enddef ;
+
+vardef smooth_connection (expr a,b) =
+  sx := connection_smooth_size/grid_width ;
+  sy := connection_smooth_size/grid_height ;
+  if ypart a = ypart b :
+    a shifted (if xpart a >= xpart b : - fi sx,0)
+% a shifted (sx*xpart unitvector(b-a),0)
+  else :
+    a shifted (0,if ypart a >= ypart b : - fi sy)
+% a shifted (0,sy*ypart unitvector(b-a))
+  fi
+enddef ;
+
+vardef trim_points =
+  begingroup
+  save p, a, b, d, i ; path p ; pair d ;
+  p := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ;
+  if touchshape :
+    a := shape_line_width/grid_width ;
+    b := shape_line_width/grid_height ;
+  else :
+    a := epsilon ;
+    b := epsilon ;
+  fi ;
+  d := direction infinity of p ;
+  xypoints[xypoint] := xypoints[xypoint] shifted
+  if     xpart d < 0 : (+a,0) ;
+  elseif xpart d > 0 : (-a,0) ;
+  elseif ypart d < 0 : (0,+b) ;
+  elseif ypart d > 0 : (0,-b) ;
+  else               : origin ;
+  fi ;
+  d := direction 0 of p ;
+  xypoints[1] := xypoints[1] shifted
+  if     xpart d < 0 : (-a,0) ;
+  elseif xpart d > 0 : (+a,0) ;
+  elseif ypart d < 0 : (0,-b) ;
+  elseif ypart d > 0 : (0,+b) ;
+  else               : origin ;
+  fi ;
+  endgroup
+enddef ;
+
+vardef trim_points = enddef ;
+
+vardef connection_path =
+  if reverse_connection : reverse fi (xypoints[1]--
+  for i=2 upto xypoint-1 :
+    if smooth :
+      smooth_connection(xypoints[i],xypoints[i-1])  ..
+      controls xypoints[i] and xypoints[i] ..
+      smooth_connection(xypoints[i],xypoints[i+1])  --
+    else :
+      xypoints[i]--
+    fi
+  endfor
+  xypoints[xypoint])
+enddef ;
+
+% vardef connection_path =
+%   sx := connection_smooth_size/grid_width ;
+%   sy := connection_smooth_size/grid_height ;
+%   if reverse_connection : reverse fi
+%   (for i=1 upto xypoint-1 : xypoints[i] -- endfor xypoints[xypoint])
+%   if smooth : cornered max(sx,sy) fi
+% enddef ;
+%
+% primarydef p cornered c =
+%   if cycle p :
+%     ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) --
+%      for i=1 upto length(p) :
+%        (point i-1 of p) shifted (c*(unitvector(point i   of p - point i-1 of p))) --
+%        (point i   of p) shifted (c*(unitvector(point i-1 of p - point i   of p))) ..
+%        controls point i of p ..
+%      endfor cycle)
+%   else :
+%     ((point 0 of p) --
+%      for i=1 upto length(p)-1 :
+%        (point i-1 of p) shifted (c*(unitvector(point i   of p - point i-1 of p))) --
+%        (point i   of p) shifted (c*(unitvector(point i-1 of p - point i   of p))) ..
+%        controls point i of p ..
+%      endfor
+%      (point length(p) of p))
+%   fi
+% enddef ;
+
+def draw_connection =
+  if xypoint>0 :
+    collapse_points ;
+    trim_points ;
+    cpath := cpath + 1 ;
+    cpaths[cpath] := connection_path scaled_to_grid ;
+    cline[cpath]  := connection_line_width ;
+    ccolor[cpath] := connection_line_color ;
+    carrow[cpath] := arrowtip ;
+    cdash[cpath]  := dashline ;
+    ccross[cpath] := showcrossing ;
+  else :
+    message("no connection defined") ;
+  fi ;
+  reverse_connection := false ;
+enddef ;
+
+def flush_connections =
+  pair ip ;
+  boolean crossing ;
+  ahlength     := connection_arrow_size ;
+  dash_pattern := dashpattern(on connection_dash_size off connection_dash_size ) ;
+  for i=1 upto cpath :
+    if ccross[i] :
+      crossing := false ;
+      for j=1 upto i :
+       %if not ((point infinity of cpaths[i] = point infinity of cpaths[j]) or
+       %        (point 0        of cpaths[i] = point 0        of cpaths[j])) :
+        if not  (point infinity of cpaths[i] = point infinity of cpaths[j]) :
+          ip := cpaths[i] intersection_point cpaths[j] ;
+          if intersection_found : crossing := true fi ;
+        fi ;
+      endfor ;
+      if crossing :
+        pickup pencircle scaled 2cline[i] ;
+       %draw cpaths[i] withcolor chart_background_color ;
+        path cp ; cp := cpaths[i] ;
+        cp := cp cutbefore point .05 length cp of cp ;
+        cp := cp cutafter  point .95 length cp of cp ;
+        draw cp withcolor chart_background_color ;
+      fi ;
+    fi ;
+    pickup pencircle scaled cline[i] ;
+    if carrow[i] :
+      if cdash[i] :
+        drawarrow cpaths[i] withcolor ccolor[i] dashed dash_pattern ;
+      else :
+        drawarrow cpaths[i] withcolor ccolor[i] ;
+      fi ;
+    else :
+      if cdash[i] :
+        draw cpaths[i] withcolor ccolor[i] dashed dash_pattern ;
+      else :
+        draw cpaths[i] withcolor ccolor[i] ;
+      fi ;
+    fi ;
+    draw_midpoint (i) ;
+  endfor ;
+enddef ;
+
+def draw_midpoint (expr n) =
+  begingroup
+  save p ;
+  pair p ;
+  p := point .5*length(cpaths[n]) of cpaths[n];
+  pickup pencircle scaled 2cline[n] ;
+  save_text_position (p) ;
+  if show_mid_points :
+    drawdot p withcolor .7white ;
+  fi ;
+  endgroup ;
+enddef ;
+
+def flush_picture(expr x, y) =
+    if known xypicture[x][y]:
+        draw xypicture[x][y] shifted xy_offset((x+0.5)*grid_width,(max_y-y+1.5)*grid_height) ;
+    fi ;
+enddef ;
+
+def chart_draw_picture(expr x, y, p) =
+    xypicture[x][y] := p ;
+enddef ;
+
+boolean reverse_connection ; reverse_connection := false ;
+
+vardef up_on_grid (expr n) =
+  (xpart xypoints[n],(ypart xypoints[n]+1) div 1)
+enddef ;
+
+vardef down_on_grid (expr n) =
+  (xpart xypoints[n],(ypart xypoints[n]) div 1)
+enddef ;
+
+vardef left_on_grid (expr n) =
+  ((xpart xypoints[n]) div 1, ypart xypoints[n])
+enddef ;
+
+vardef right_on_grid (expr n) =
+  ((xpart xypoints[n]+1) div 1, ypart xypoints[n])
+enddef ;
+
+vardef x_on_grid (expr n, xfrom, xto, zfrom) =
+  if (xfrom=xto) and not (zfrom=0) :
+    if (zfrom=1) : right_on_grid(2) else : left_on_grid(2) fi
+  elseif xpart xypoints[1] < xpart xypoints[6] :
+    right_on_grid(n)
+  else :
+    left_on_grid(n)
+  fi
+enddef ;
+
+vardef y_on_grid (expr n, yfrom, yto, zfrom) =
+  if (yfrom=yto) and not (zfrom=0) :
+    if (zfrom=1) : up_on_grid(2) else : down_on_grid(2) fi
+  elseif ypart xypoints[1] < ypart xypoints[6] :
+    up_on_grid(n)
+  else :
+    down_on_grid(n)
+  fi
+enddef ;
+
+vardef xy_on_grid (expr n, m) =
+  (xpart xypoints[n], ypart xypoints[m])
+enddef ;
+
+vardef down_to_grid (expr a,b) =
+  (xpart xypoints[a],
+   ypart xypoints[if ypart xypoints[a]<ypart xypoints[b]:a else:b fi])
+enddef ;
+
+vardef up_to_grid (expr a,b) =
+  (xpart xypoints[a],
+   ypart xypoints[if ypart xypoints[a]>ypart xypoints[b]:a else:b fi])
+enddef ;
+
+vardef left_to_grid (expr a,b) =
+  (xpart xypoints[if xpart xypoints[a]<xpart xypoints[b]:a else:b fi],
+   ypart xypoints[a])
+enddef ;
+
+vardef right_to_grid (expr a,b) =
+  (xpart xypoints[if xpart xypoints[a]>xpart xypoints[b]:a else:b fi],
+   ypart xypoints[a])
+enddef ;
+
+% vardef boundingboxfraction(expr p, f) =
+%   ((boundingbox p) enlarged (-f*bbwidth(p),-f*bbheight(p)))
+% enddef ;
+
+vardef valid_connection (expr xfrom, yfrom, xto, yto) =
+  begingroup ;
+  save ok, vc, pp ;
+  boolean ok ;
+  % check for slanted lines
+  ok := true ;
+  for i=1 upto xypoint-1 :
+   if not ((xpart xypoints[i]=xpart xypoints[i+1]) or
+           (ypart xypoints[i]=ypart xypoints[i+1])) : ok := false ;
+   fi ;
+  endfor ;
+  if not ok :
+   %message("slanted");
+    false
+  elseif forcevalid :
+   %message("force");
+    true
+  elseif (xfrom=xto) and (yfrom=yto) :
+   %message("self");
+    false
+  else :
+    % check for crossing shapes
+    pair vc ;
+    path pp ;
+
+    pair xyfirst, xylast ;
+    xyfirst := xypoints[1] ;
+    xylast := xypoints[xypoint] ;
+    trim_points ;
+    pp := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ;
+    xypoints[1] := xyfirst ;
+    xypoints[xypoint] := xylast ;
+
+    for i=1 upto max_x :
+      for j=1 upto max_y :                % was bug: xfrom,yto
+        if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) :
+          if not xyfree[i][j] :
+            vc := pp intersection_point xypath[i][j] ;
+            if intersection_found : ok := false fi ;
+          fi ;
+        fi ;
+      endfor ;
+    endfor ;
+   %if not ok: message("crossing") ; fi ;
+    ok
+  fi
+  endgroup
+enddef ;
+
+def connect_top_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_bottom(xto,yto,zto,true) ;
+    xypoints[2] := up_on_grid(1) ;
+    xypoints[5] := down_on_grid(6) ;
+    xypoints[3] := up_to_grid(2,5) ;
+    xypoints[4] := up_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+      xypoints[4] := xy_on_grid(3,5) ;
+    fi ;
+    %%%% begin experiment
+    xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+    xypoints[4] := xypoints[4] shifted (dsp_x,0) ;
+    if dsp_y>0 :
+      xypoints[2] := xypoints[2] shifted (0,dsp_y) ;
+      xypoints[3] := xypoints[3] shifted (0,dsp_y) ;
+    elseif dsp_y<0 :
+      xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+      xypoints[5] := xypoints[5] shifted (0,dsp_y) ;
+    fi
+    %%%% end experiment
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_left_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_right(xto,yto,zto,true) ;
+    xypoints[2] := left_on_grid(1) ;
+    xypoints[5] := right_on_grid(6) ;
+    xypoints[3] := left_to_grid(2,5) ;
+    xypoints[4] := left_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+      xypoints[4] := xy_on_grid(5,3) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_left_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,5) :
+    xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+    xypoints[5] := xy_top(xto,yto,zto,true) ;
+    xypoints[2] := left_on_grid(1) ;
+    xypoints[4] := up_on_grid(5) ;
+    xypoints[3] := left_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := xy_on_grid(2,4) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_left_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,5) :
+    xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+    xypoints[5] := xy_bottom(xto,yto,zto,true) ;
+    xypoints[2] := left_on_grid(1) ;
+    xypoints[4] := down_on_grid(5) ;
+    xypoints[3] := left_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := xy_on_grid(2,4) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_right_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,5) :
+    xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+    xypoints[5] := xy_top(xto,yto,zto,true) ;
+    xypoints[2] := right_on_grid(1) ;
+    xypoints[4] := up_on_grid(5) ;
+    xypoints[3] := right_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := xy_on_grid(2,4) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_right_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,5) :
+    xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+    xypoints[5] := xy_bottom(xto,yto,zto,true) ;
+    xypoints[2] := right_on_grid(1) ;
+    xypoints[4] := down_on_grid(5) ;
+    xypoints[3] := right_to_grid(2,5) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := xy_on_grid(2,4) ;
+    fi ;
+    %%%% begin experiment
+    xypoints[2] := xypoints[2] shifted (dsp_x,0) ;
+    xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+    if dsp_y>0 :
+      xypoints[3] := xypoints[3] shifted (0,-dsp_y) ;
+      xypoints[4] := xypoints[4] shifted (0,-dsp_y) ;
+    elseif dsp_y<0 :
+      xypoints[3] := xypoints[3] shifted (0,dsp_y) ;
+      xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+    fi
+    %%%% end experiment
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_left_left (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_left(xto,yto,zto,true) ;
+    xypoints[2] := left_on_grid(1) ;
+    xypoints[5] := left_on_grid(6) ;
+    xypoints[3] := left_to_grid(2,5) ;
+    xypoints[4] := left_to_grid(5,2) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+      xypoints[4] := xy_on_grid(5,3) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_right_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_right(xto,yto,zto,true) ;
+    xypoints[2] := right_on_grid(1) ;
+    xypoints[5] := right_on_grid(6) ;
+    xypoints[3] := right_to_grid(2,5) ;
+    xypoints[4] := right_to_grid(5,2) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ;
+      xypoints[4] := xy_on_grid(5,3) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_top_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_top(xto,yto,zto,true) ;
+    xypoints[2] := up_on_grid(1) ;
+    xypoints[5] := up_on_grid(6) ;
+    xypoints[3] := up_to_grid(2,5) ;
+    xypoints[4] := up_to_grid(5,2) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+      xypoints[4] := xy_on_grid(3,5) ;
+    fi ;
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_bottom_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+  yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ;
+  if points_initialized(xfrom,yfrom,xto,yto,6) :
+    xypoints[1] := xy_bottom(xfrom,yfrom,zfrom,true) ;
+    xypoints[6] := xy_bottom(xto,yto,zto,true) ;
+    xypoints[2] := down_on_grid(1) ;
+    xypoints[5] := down_on_grid(6) ;
+    xypoints[3] := down_to_grid(2,5) ;
+    xypoints[4] := down_to_grid(5,2) ;
+    if not valid_connection(xfrom,yfrom,xto,yto) :
+      xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ;
+      xypoints[4] := xy_on_grid(3,5) ;
+    fi ;
+    %%%% begin experiment
+    xypoints[3] := xypoints[3] shifted (dsp_x,0) ;
+    xypoints[4] := xypoints[4] shifted (dsp_x,0) ;
+    if dsp_y<0 :
+      xypoints[2] := xypoints[2] shifted (0,-dsp_y) ;
+      xypoints[3] := xypoints[3] shifted (0,-dsp_y) ;
+    elseif dsp_y>0 :
+      xypoints[4] := xypoints[4] shifted (0,dsp_y) ;
+      xypoints[5] := xypoints[5] shifted (0,dsp_y) ;
+    fi
+    %%%% end experiment
+    draw_connection ;
+  fi ;
+enddef ;
+
+def connect_bottom_top (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_top_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_right_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_left_right (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_top_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_left_top (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_bottom_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_left_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_top_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_right_top (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def connect_bottom_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+  reverse_connection := true ;
+  connect_right_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def draw_test_shape (expr x, y) =
+  draw_shape(x,y,fullcircle, .7, .7) ;
+enddef ;
+
+def draw_test_shapes =
+  for i=1 upto max_x :
+    for j=1 upto max_y :
+      draw_test_shape(i,j) ;
+    endfor ;
+  endfor ;
+enddef;
+
+def draw_test_area =
+  pickup pencircle scaled .5shape_line_width ;
+  draw (unitsquare xscaled max_x yscaled max_y shifted (1,1))
+    scaled_to_grid withcolor blue ;
+enddef ;
+
+def show_connection (expr n, m) =
+
+  begin_chart(100+n,6,6) ;
+
+    draw_test_area ;
+
+    smooth   := true ;
+    arrowtip := true ;
+    dashline := true ;
+
+    draw_test_shape(2,2) ; draw_test_shape(4,5) ;
+    draw_test_shape(3,3) ; draw_test_shape(5,1) ;
+    draw_test_shape(2,5) ; draw_test_shape(1,3) ;
+    draw_test_shape(6,2) ; draw_test_shape(4,6) ;
+
+    if     (m=1) :
+      connect_top_bottom (2,2,0) (4,5,0) ;
+      connect_top_bottom (3,3,0) (5,1,0) ;
+      connect_top_bottom (2,5,0) (1,3,0) ;
+      connect_top_bottom (6,2,0) (4,6,0) ;
+    elseif (m=2) :
+      connect_top_top (2,2,0) (4,5,0) ;
+      connect_top_top (3,3,0) (5,1,0) ;
+      connect_top_top (2,5,0) (1,3,0) ;
+      connect_top_top (6,2,0) (4,6,0) ;
+    elseif (m=3) :
+      connect_bottom_bottom (2,2,0) (4,5,0) ;
+      connect_bottom_bottom (3,3,0) (5,1,0) ;
+      connect_bottom_bottom (2,5,0) (1,3,0) ;
+      connect_bottom_bottom (6,2,0) (4,6,0) ;
+    elseif (m=4) :
+      connect_left_right (2,2,0) (4,5,0) ;
+      connect_left_right (3,3,0) (5,1,0) ;
+      connect_left_right (2,5,0) (1,3,0) ;
+      connect_left_right (6,2,0) (4,6,0) ;
+    elseif (m=5) :
+      connect_left_left (2,2,0) (4,5,0) ;
+      connect_left_left (3,3,0) (5,1,0) ;
+      connect_left_left (2,5,0) (1,3,0) ;
+      connect_left_left (6,2,0) (4,6,0) ;
+    elseif (m=6) :
+      connect_right_right (2,2,0) (4,5,0) ;
+      connect_right_right (3,3,0) (5,1,0) ;
+      connect_right_right (2,5,0) (1,3,0) ;
+      connect_right_right (6,2,0) (4,6,0) ;
+    elseif (m=7) :
+      connect_left_top (2,2,0) (4,5,0) ;
+      connect_left_top (3,3,0) (5,1,0) ;
+      connect_left_top (2,5,0) (1,3,0) ;
+      connect_left_top (6,2,0) (4,6,0) ;
+    elseif (m=8) :
+      connect_left_bottom (2,2,0) (4,5,0) ;
+      connect_left_bottom (3,3,0) (5,1,0) ;
+      connect_left_bottom (2,5,0) (1,3,0) ;
+      connect_left_bottom (6,2,0) (4,6,0) ;
+    elseif (m=9) :
+      connect_right_top (2,2,0) (4,5,0) ;
+      connect_right_top (3,3,0) (5,1,0) ;
+      connect_right_top (2,5,0) (1,3,0) ;
+      connect_right_top (6,2,0) (4,6,0) ;
+    else :
+      connect_right_bottom (2,2,0) (4,5,0) ;
+      connect_right_bottom (3,3,0) (5,1,0) ;
+      connect_right_bottom (2,5,0) (1,3,0) ;
+      connect_right_bottom (6,2,0) (4,6,0) ;
+    fi ;
+
+  end_chart ;
+
+enddef ;
+
+def show_connections =
+  for f=1 upto 10 :
+    show_connection(f,f) ;
+  endfor ;
+enddef ;
+
+%D charts
+
+def clip_chart (expr minx, miny, maxx, maxy) =
+  cmin_x := minx ;
+  cmax_x := maxx ;
+  cmin_y := miny ;
+  cmax_y := maxy ;
+enddef ;
+
+def begin_chart (expr n, maxx, maxy) =
+  new_chart ;
+  chart_figure := n ;
+  chart_scale := 1 ;
+  if chart_figure>0: beginfig(chart_figure) ; fi ;
+  startsavingdata ;
+  initialize_grid (maxx, maxy) ;
+  bboxmargin := 0 ;
+  cmin_x := 1 ;
+  cmax_x := maxx ;
+  cmin_y := 1 ;
+  cmax_y := maxy ;
+enddef ;
+
+def end_chart =
+  flush_shapes ;
+  flush_connections ;
+  flush_pictures ;
+  cmin_x := cmin_x ;
+  cmax_x := cmin_x+cmax_x ;
+  cmin_y := cmin_y-1 ;
+  cmax_y := cmin_y+cmax_y ;
+  if reverse_y :
+   cmin_y := y_pos(cmin_y) ;
+   cmax_y := y_pos(cmax_y) ;
+  fi ;
+  path p ;
+  p := (((cmin_x,cmin_y)--(cmax_x,cmin_y)--
+         (cmax_x,cmax_y)--(cmin_x,cmax_y)--cycle))
+       scaled_to_grid ;
+ %draw p withcolor red ;
+  p := p enlarged chart_offset ;
+  clip currentpicture to p ;
+  setbounds currentpicture to p ;
+  savedata
+    "\MPclippath{" &
+    decimal xpart llcorner p & "}{" &
+    decimal ypart llcorner p & "}{" &
+    decimal xpart urcorner p & "}{" &
+    decimal ypart urcorner p & "}%" ;
+  savedata
+    "\MPareapath{" &
+    decimal (xpart llcorner p + 2chart_offset) & "}{" &
+    decimal (ypart llcorner p + 2chart_offset) & "}{" &
+    decimal (xpart urcorner p - 2chart_offset) & "}{" &
+    decimal (ypart urcorner p - 2chart_offset) & "}%" ;
+  currentpicture := currentpicture scaled chart_scale ;
+  stopsavingdata ;
+  if chart_figure>0: endfig ; fi ;
+enddef ;
+
+def new_shape (expr x, y, n) =
+  if known n :
+    if (x>0) and (x<=max_x) and (y>0) and (y<=max_y) :
+      sx := shape_width/grid_width ;
+      sy := shape_height/grid_height ;
+      draw_shape(x,y,some_shape_path(n), sx, sy) ;
+    else :
+      message ("shape outside grid ignored") ;
+    fi ;
+  else
+    message ("shape not known" ) ;
+  fi ;
+enddef ;
+
+def begin_sub_chart =
+  begingroup ;
+  save    shape_line_width , connection_line_width ;
+  save    shape_line_color, shape_fill_color, connection_line_color ;
+  color   shape_line_color, shape_fill_color, connection_line_color ;
+  save    smooth, arrowtip, dashline, peepshape ;
+  boolean smooth, arrowtip, dashline, peepshape ;
+enddef ;
+
+def end_sub_chart =
+  endgroup ;
+enddef ;
+
+% show_shapes(100) ;
+%
+% show_connections ;
+%
+% begin_chart (1,4,5) ;
+%  %clip_chart(1,1,1,2) ;
+%   new_shape (1,1,31) ;
+%   new_shape (1,2,3) ;
+%   new_shape (4,4,5) ;
+%   connect_top_left   (1,1,0) (4,4,0) ;
+%   connect_bottom_top (1,2,0) (4,4,0) ;
+%   connect_left_right (1,2,0) (1,1,0) ;
+% end_chart ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-core.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-core.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-core.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,1418 @@
+if known context_core : endinput ; fi ;
+
+boolean context_core ; context_core := true ;
+
+pair    lxy[], rxy[], cxy[], llxy[], lrxy[], ulxy[], urxy[] ;
+path    pxy[] ;
+numeric hxy[], wxy[], dxy[], nxy[] ;
+
+def box_found (expr n,x,y,w,h,d) =
+  not ((x=0) and (y=0) and (w=0) and (h=0) and (d=0))
+enddef ;
+
+def initialize_box_pos (expr pos,n,x,y,w,h,d) =
+  pair lxy, rxy, cxy, llxy, lrxy, ulxy, urxy ;
+  path pxy ; numeric hxy, wxy, dxy, nxy;
+  lxy  := (x,y) ;
+  llxy := (x,y-d) ;
+  lrxy := (x+w,y-d) ;
+  urxy := (x+w,y+h) ;
+  ulxy := (x,y+h) ;
+  wxy  := w ;
+  hxy  := h ;
+  dxy  := d ;
+  rxy  := lxy shifted (wxy,0) ;
+  pxy  := llxy--lrxy--urxy--ulxy--cycle ;
+  cxy  := center pxy ;
+  nxy  := n ;
+  freeze_box(pos) ;
+enddef ;
+
+def freeze_box (expr pos) =
+  lxy[pos]  := lxy  ;
+  llxy[pos] := llxy ;
+  lrxy[pos] := lrxy ;
+  urxy[pos] := urxy ;
+  ulxy[pos] := ulxy ;
+  wxy[pos]  := wxy  ;
+  hxy[pos]  := hxy  ;
+  dxy[pos]  := dxy  ;
+  rxy[pos]  := rxy  ;
+  pxy[pos]  := pxy  ;
+  cxy[pos]  := cxy  ;
+  nxy[pos]  := nxy  ;
+enddef ;
+
+def initialize_box (expr n,x,y,w,h,d) =
+
+  numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ;
+
+enddef ;
+
+def initialize_area (expr fn,fx,fy,fw,fh,fd,
+                          tn,tx,ty,tw,th,td) =
+
+  numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+  numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+
+  do_initialize_area (fpos, tpos) ;
+
+enddef ;
+
+def do_initialize_area (expr fpos, tpos) =
+  lxy  := lxy[fpos] ;
+  llxy := (xpart llxy[fpos], ypart llxy[tpos]) ;
+  lrxy := lrxy[tpos] ;
+  urxy := (xpart urxy[tpos], ypart urxy[fpos]) ;
+  ulxy := ulxy[fpos] ;
+  wxy  := xpart lrxy - xpart llxy ;
+  hxy  := hxy[fpos] ;
+  dxy  := dxy[tpos] ;
+  rxy  := lxy shifted (wxy,0) ;
+  pxy  := llxy--lrxy--urxy--ulxy--cycle ;
+  cxy  := center pxy ;
+enddef ;
+
+def set_par_line_height (expr ph, pd) =
+  par_strut_height :=
+    if ph>0 : ph elseif StrutHeight>0 : StrutHeight else : 8pt fi ;
+  par_strut_depth  :=
+    if pd>0 : pd elseif StrutDepth >0 : StrutDepth  else : 3pt fi ;
+  par_line_height  :=
+    par_strut_height + par_strut_depth ;
+enddef ;
+
+def initialize_par (expr fn,fx,fy,fw,fh,fd,
+                         tn,tx,ty,tw,th,td,
+                         mn,mx,my,mw,mh,md,
+                         pn,px,py,pw,ph,pd,
+                         rw,rl,rr,rh,ra,ri) =
+
+  numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+  numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+  numeric mpos ; mpos := 3 ; initialize_box_pos(mpos,mn,mx,my,mw,mh,md) ;
+  numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+  numeric par_strut_height, par_strut_depth, par_line_height ;
+
+  set_par_line_height (ph, pd) ;
+
+  do_initialize_area (fpos, tpos) ;
+  do_initialize_par  (fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) ;
+
+enddef ;
+
+def initialize_area_par (expr fn,fx,fy,fw,fh,fd,
+                              tn,tx,ty,tw,th,td,
+                              wn,wx,wy,ww,wh,wd) =
+
+  numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+  numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+  numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+
+  numeric par_strut_height, par_strut_depth, par_line_height ;
+
+  set_par_line_height (wh, wd) ;
+
+  numeric ffpos ; ffpos := 4 ; initialize_box_pos(ffpos,wn,wx,fy,0,wh,wd) ;
+  numeric ttpos ; ttpos := 5 ; initialize_box_pos(ttpos,wn,wx+ww,ty,0,wh,wd) ;
+
+  do_initialize_area (ffpos, ttpos) ;
+
+  numeric mpos ; mpos := 6 ; freeze_box(mpos) ;
+
+  do_initialize_par  (fpos, tpos, mpos, ffpos, 0,0,0,0,0,0) ;
+
+enddef ;
+
+def do_initialize_par (expr fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) =
+
+  pair lref, rref, pref, lhref, rhref ;
+
+  % clip the page area to the left and right skips
+
+  llxy[mpos] := llxy[mpos] shifted (+rl,0) ;
+  lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ;
+  urxy[mpos] := urxy[mpos] shifted (-rr,0) ;
+  ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ;
+
+  % fixate the leftskip, rightskip and hanging indentation
+
+  lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ;
+  rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ;
+
+  pref := lxy[ppos] ;
+
+  if nxy[tpos] > nxy[fpos] :
+    if nxy[fpos] = nxy[mpos] :
+      % first of multiple pages
+      llxy[tpos] := llxy[mpos] ;
+      lrxy[tpos] := lrxy[mpos] ;
+      urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+      ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+      boxgriddirection := down ;
+    elseif nxy[tpos] = nxy[mpos] :
+      % last of multiple pages
+      llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+      lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+      urxy[fpos] := urxy[mpos] ;
+      ulxy[fpos] := ulxy[mpos] ;
+      boxgriddirection := up ;
+    else :
+      % middle of multiple pages
+      llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+      lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+      urxy[fpos] := urxy[mpos] ;
+      ulxy[fpos] := ulxy[mpos] ;
+      llxy[tpos] := llxy[mpos] ;
+      lrxy[tpos] := lrxy[mpos] ;
+      urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+      ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+      boxgriddirection := up ;
+    fi ;
+  else :
+    % just one page
+    boxgriddirection := up ;
+  fi ;
+
+  path txy, bxy, pxy, mxy ;
+
+  txy := originpath ; % top
+  bxy := originpath ; % bottom
+  pxy := originpath ; % composed
+
+  boolean lefthang, righthang, somehang ;
+
+  % we only hang on the first of a multiple page background
+
+  if nxy[mpos] > nxy[fpos] :
+    lefthang := righthang := somehang := false ;
+  else :
+    lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ;
+  fi ;
+
+  if lefthang :
+    mxy  := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ;
+  elseif righthang :
+    mxy  := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ;
+  else :
+    mxy  := originpath ;
+  fi ;
+
+  if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+    % We have a one-liner. Watch how er use the bottom pos for
+    % determining the height.
+
+    llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ;
+    ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ;
+
+  else :
+
+    % We have a multi-liner. For convenience we now correct the
+    % begin and end points for indentation.
+
+    if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) :
+      llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ;
+      ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ;
+    else :
+      llxy[tpos] := (xpart  lref, ypart llxy[tpos]) ;
+      ulxy[tpos] := (xpart  lref, ypart ulxy[tpos]) ;
+    fi ;
+
+    if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) :
+      lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ;
+      urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ;
+    else :
+      lrxy[fpos] := (xpart  rref, ypart lrxy[fpos]) ;
+      urxy[fpos] := (xpart  rref, ypart urxy[fpos]) ;
+    fi ;
+
+  fi ;
+
+  somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and
+              (ypart llxy[tpos]<ypart llcorner mxy) ;
+
+  if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+    % A (short) one-liner goes into the top box.
+
+    txy := llxy[fpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[fpos] -- cycle ;
+
+  elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) and
+         (round(xpart lrxy[tpos]) < round(xpart llxy[fpos])) :
+
+    % We have a sentence that spans two lines but with only end
+    % of line and begin of line segments. We need to take care of
+    % indentation.
+
+    txy := llxy[fpos] -- lrxy[fpos] -- urxy[fpos] -- ulxy[fpos] -- cycle ;
+    bxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[tpos] -- cycle ;
+
+  elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) :
+
+    % We have a sentence that spans two lines but with overlap.
+
+    pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- lrxy[fpos] --
+           urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- ulxy[tpos] -- cycle ;
+
+  elseif lefthang and somehang :
+
+    % We have a sentence that spans more than two lines with
+    % left hanging indentation.
+
+    pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+           (xpart urxy[fpos],ypart urxy[tpos]) --
+           urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+           if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+             (xpart lrcorner mxy,ypart llxy[fpos]) --
+             lrcorner mxy --
+             (xpart llxy[tpos],ypart llcorner mxy) --
+           else :
+             (xpart llxy[tpos],ypart llxy[fpos]) --
+           fi
+           cycle ;
+
+  elseif righthang and somehang :
+
+    % We have a sentence that spans more than two lines with
+    % right hanging indentation.
+
+    pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+           if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+             (xpart lrcorner mxy,ypart urxy[tpos]) --
+             lrcorner mxy -- llcorner mxy --
+           else :
+             (xpart urxy[fpos],ypart urxy[tpos]) --
+           fi
+           urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+           (xpart llxy[tpos],ypart llxy[fpos]) --
+           cycle ;
+
+  else :
+
+    % We have a sentence that spans more than two lines with
+    % no hanging indentation.
+
+    pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+           (xpart urxy[fpos],ypart urxy[tpos]) --
+           urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+           (xpart llxy[tpos],ypart llxy[fpos]) -- cycle ;
+
+  fi ;
+
+  pxy := simplified pxy ;
+  pxy := unspiked   pxy ;
+
+enddef ;
+
+TopSkip     := 0 ; % will move
+StrutHeight := 0 ; % will move
+
+pair last_multi_par_shift ; last_multi_par_shift := origin ;
+
+def relocate_multipars (expr xy) =
+  last_multi_par_shift := xy ;
+  for i=1 upto nofmultipars :
+    multipars[i] := multipars[i] shifted last_multi_par_shift ;
+  endfor ;
+enddef ;
+
+boolean compensate_multi_par_topskip ;
+boolean span_multi_column_pars ;
+boolean auto_multi_par_hsize ;
+boolean enable_multi_par_fallback ;
+
+compensate_multi_par_topskip := true ;
+span_multi_column_pars       := false ;
+auto_multi_par_hsize         := false ; % true ;
+enable_multi_par_fallback    := true ;
+
+vardef multi_par_at_top (expr i) =
+  (round (ypart ulcorner multipars[i]) = round (ypart ulcorner
+     (TextAreas[multirefs[i]] shifted last_multi_par_shift)))
+enddef ;
+
+numeric nofmultipars ; nofmultipars := 0 ;
+
+boolean obey_multi_par_hang    ; obey_multi_par_hang    := true  ;
+boolean obey_multi_par_more    ; obey_multi_par_more    := true  ;
+boolean snap_multi_par_tops    ; snap_multi_par_tops    := true  ;
+boolean local_multi_par_area   ; local_multi_par_area   := false ;
+boolean ignore_multi_par_page  ; ignore_multi_par_page  := false ;
+boolean force_multi_par_chain  ; force_multi_par_chain  := true  ;
+boolean one_piece_multi_par    ; one_piece_multi_par    := false ;
+boolean check_multi_par_chain  ; check_multi_par_chain  := true  ; % extra page check
+
+boolean multi_column_first_page_hack; multi_column_first_page_hack := true ; % seems to work ok
+
+if unknown NOfTextColumns : numeric NOfTextColumns ; NOfTextColumns := 0 ; fi ;
+if unknown NOfTextAreas   : numeric NOfTextAreas   ; NOfTextAreas   := 0 ; fi ;
+
+def simplify_multi_pars = % boundingbox ipv shape als optie
+  for i := 1 upto nofmultipars :
+    multipars[i] := boundingbox multipars[i] ;
+  endfor ;
+enddef ;
+
+def save_multipar (expr i, l, p) =
+  nofmultipars := nofmultipars + 1 ;
+  multirefs[nofmultipars] := i ;
+  multilocs[nofmultipars] := l ;
+  multipars[nofmultipars] := unspiked (simplified p) ;
+enddef ;
+
+def prepare_multi_pars (expr fn,fx,fy,fw,fh,fd,
+                             tn,tx,ty,tw,th,td,
+                             wn,wx,wy,ww,wh,wd,
+                             pn,px,py,pw,ph,pd,
+                             rw,rl,rr,rh,ra,ri) =
+
+% if span_multi_column_pars :
+%   begingroup ;
+%   save TextAreas ; path TextAreas[] ;
+%   save NOfTextAreas ; numeric NOfTextAreas ;
+%   for i=1 upto NOfTextColumns :
+%     TextAreas[i] := TextColumns[i] ;
+%   endfor ;
+%   NOfTextAreas := NOfTextColumns ;
+% fi ;
+
+  last_multi_par_shift := origin ;
+
+  numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+  numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+  numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+  numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+  if local_multi_par_area :
+    RealPageNumber := fn ;
+    NOfTextAreas := 1 ;
+    NOfSavedTextAreas := 0 ;
+    TextAreas[1] := TextAreas[0] ;
+    TextColumns[1] := TextColumns[0] ;
+    nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+   % draw TextColumns[1] withcolor green ;
+   % draw TextAreas[1] withcolor green ;
+  elseif ignore_multi_par_page :
+    RealPageNumber := fn ;
+    nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+  fi ;
+
+  numeric par_strut_height, par_strut_depth, par_line_height ;
+
+  set_par_line_height (ph, pd) ;
+
+  numeric par_hang_indent, par_hang_after, par_indent, par_left_skip, par_right_skip ;
+
+  par_hang_indent  := rh ;
+  par_hang_after   := ra ;
+  par_indent       := ri ;
+  par_left_skip    := rl ;
+  par_right_skip   := rr ;
+
+  pair par_start_pos ;
+  pair par_stop_pos ;
+
+  par_start_pos := llxy[fpos]
+    if par_indent   <0: shifted (-par_indent,   0) fi
+    if par_left_skip<0: shifted (-par_left_skip,0) fi ;
+  par_stop_pos := lrxy[tpos]
+    if par_right_skip<0: shifted (par_right_skip,0) fi ; % nasty as the endpos can be shifted by rightskip
+
+  if wxy[wpos]>0 :
+    left_skip  := rl + xpart llxy[wpos] - xpart llxy[ppos] ;
+    right_skip := rw - left_skip - ww ;
+  else :
+    left_skip  := rl ;
+    right_skip := rr ;
+  fi ;
+
+  path    multipar, multipars[] ;
+  numeric multiref, multirefs[] ;
+  numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end
+
+  numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ;
+
+  % locals .. why can't i move these outside?
+
+vardef _pmp_set_multipar_ (expr i) =
+  ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip
+    if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) )
+enddef ;
+
+vardef _pmp_snapped_multi_pos_ (expr p) =
+  if snap_multi_par_tops :
+    if abs(ypart p - ypart ulcorner multipar) < par_line_height :
+      (xpart p,ypart ulcorner multipar)
+    else :
+      p
+    fi
+  else :
+    p
+  fi
+enddef ;
+
+vardef _pmp_estimated_par_lines_ (expr h) =
+  round(h/par_line_height)
+enddef ;
+
+vardef _pmp_top_multi_par_(expr p) =
+  (round(_pmp_estimated_par_lines_(bbheight(p)*par_line_height))=round(bbheight(p)))
+enddef ;
+
+vardef _pmp_multi_par_tsc_(expr p) =
+  if _pmp_top_multi_par_(p) : TopSkipCorrection else : 0 fi
+enddef ;
+
+vardef _pmp_estimated_multi_par_height_ (expr n, t) =
+  if round(par_line_height)=0 :
+    0
+  else :
+    save ok, h ; boolean ok ;
+    numeric h ; h := 0 ;
+    ok := false ;
+    if (nxy[fpos]=RealPageNumber-1) :
+      for i := 1 upto NOfSavedTextAreas :
+        if (InsideSavedTextArea(i,par_start_pos)) :
+          ok := true ;
+          h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] -
+                 ypart llcorner SavedTextAreas[i]) ;
+        elseif ok :
+          h := h + _pmp_estimated_par_lines_(bbheight(SavedTextAreas[i])) ;
+        fi ;
+      endfor ;
+    fi ;
+    if ok :
+      for i := 1 upto n-1 :
+        h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ;
+      endfor ;
+    else :
+      % already: ok := false ;
+      for i := 1 upto n-1 :
+        if (InsideTextArea(i,par_start_pos)) :
+          ok := true ;
+          h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ;
+        elseif ok :
+          h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ;
+        fi ;
+      endfor ;
+    fi ;
+    h
+  fi
+enddef ;
+
+vardef _pmp_left_top_hang_ (expr same_area) =
+
+  par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ;
+
+  if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang :
+    pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos]));
+    pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+    if same_area :
+      _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ;
+    fi ;
+    if obey_multi_par_more and (round(par_line_height)>0) :
+      par_hang_after := min(0,round(par_hang_after +
+        (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+    fi ;
+    (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) --
+    (xpart _ul_ + par_hang_indent, ypart _pa_) --
+    (xpart ulcorner multipar, ypart _pa_)
+  else :
+    (xpart ulcorner multipar, ypart lrxy[fpos])
+  fi
+enddef ;
+
+vardef _pmp_right_top_hang_ (expr same_area) =
+
+  par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ;
+
+  if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang :
+    pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ;
+    pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+    if same_area :
+      _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ;
+    fi ;
+    if obey_multi_par_more and (round(par_line_height)>0) :
+      par_hang_after := min(0,round(par_hang_after +
+        (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+    fi ;
+    (xpart urcorner multipar, ypart _pa_) --
+    (xpart _ur_ + par_hang_indent, ypart _pa_) --
+    (xpart _ur_ + par_hang_indent, ypart _pmp_snapped_multi_pos_(urxy[fpos]))
+  else :
+    (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos]))
+  fi
+enddef ;
+
+vardef _pmp_x_left_top_hang_ (expr i, t) =
+  par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ;
+  if (par_hang_indent>0) and (par_hang_after<0) :
+    pair _ul_ ; _ul_ := ulcorner multipar ;
+    pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+    if t :
+      _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos]));
+    fi ;
+    if abs(ypart _pa_-ypart llxy[tpos])<par_line_height :
+      _pa_ := (xpart _pa_,ypart llxy[tpos]);
+    fi ;
+    if abs(ypart _pa_-ypart llcorner multipar)<par_line_height :
+      _pa_ := (xpart _pa_,ypart llcorner multipar);
+    fi ;
+    (xpart _ul_, ypart _pa_) --
+    (xpart _ul_ + par_hang_indent, ypart _pa_) --
+    (xpart _ul_ + par_hang_indent, ypart _ul_)
+  else :
+    ulcorner multipar
+  fi
+enddef ;
+
+vardef _pmp_x_right_top_hang_ (expr i, t) =
+  par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ;
+  if (par_hang_indent<0) and (par_hang_after<0) :
+    pair _ur_ ; _ur_ := urcorner multipar ;
+    pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+    if t :
+      _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(urxy[tpos]))) ;
+    fi ;
+    (xpart _ur_ + par_hang_indent, ypart _ur_) --
+    (xpart _ur_ + par_hang_indent, ypart _pa_) --
+    (xpart _ur_, ypart _pa_)
+  else :
+    urcorner multipar
+  fi
+enddef ;
+
+vardef _pmp_left_bottom_hang_ (expr same_area) =
+  pair _ll_, _sa_, _pa_ ;
+  _sa_ := if same_area : llxy[tpos] else : lrcorner multipar fi ;
+  if (par_hang_indent>0) and (par_hang_after>0) and obey_multi_par_hang :
+    _ll_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])) ;
+    _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+    if same_area :
+      _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+    fi ;
+    if obey_multi_par_more and (round(par_line_height)>0) :
+      par_hang_after := max(0,round(par_hang_after -
+        (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+    fi ;
+    _pa_ --
+    (xpart _pa_ + par_hang_indent,ypart _pa_) --
+    (xpart _pa_ + par_hang_indent,ypart _sa_)
+  else :
+    (xpart llcorner multipar, ypart _sa_)
+  fi
+enddef ;
+
+vardef _pmp_right_bottom_hang_ (expr same_area) =
+  pair _lr_, _sa_, _pa_ ;
+  _sa_ := if same_area : _pmp_snapped_multi_pos_(ulxy[tpos]) else : lrcorner multipar fi ;
+  if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang :
+    _lr_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ;
+    _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+    if same_area :
+      _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ;
+    fi ;
+    if obey_multi_par_more and (round(par_line_height)>0) :
+      par_hang_after := max(0,round(par_hang_after -
+        (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+    fi ;
+    (xpart _pa_ + par_hang_indent,ypart _sa_) --
+    (xpart _pa_ + par_hang_indent,ypart _pa_) --
+    _pa_
+  else :
+   (xpart lrcorner multipar, ypart _sa_)
+  fi
+enddef ;
+
+vardef _pmp_x_left_bottom_hang_ (expr i, t) =
+  pair _ll_, _sa_, _pa_ ;
+  _sa_ := if t : llxy[tpos] else : llcorner multipar fi ;
+  if (par_hang_indent>0) and (ra>0) :
+    par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i,t)) ;
+    _ll_ := ulcorner multipar ;
+    _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+    % we need to compensate for topskip enlarged areas
+    if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+      (xpart _pa_ + par_hang_indent,ypart _sa_) --
+      (xpart _pa_ + par_hang_indent,ypart _pa_) --
+    fi
+    _pa_
+  else :
+    (xpart llcorner multipar, ypart _sa_)
+  fi
+enddef ;
+
+vardef _pmp_x_right_bottom_hang_ (expr i, t) =
+  pair _lr_, _sa_, _pa_ ;
+  _sa_ := if t : _pmp_snapped_multi_pos_(ulxy[tpos]) else : llcorner multipar fi ;
+  if (par_hang_indent<0) and (ra>0) :
+    par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i, t)) ;
+    _lr_ := urcorner multipar ;
+    _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+    _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+    % we need to compensate for topskip enlarged areas
+    _pa_
+    if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+      -- (xpart _pa_ + par_hang_indent,ypart _pa_)
+      -- (xpart _pa_ + par_hang_indent,ypart _sa_)
+    fi
+  else :
+   (xpart lrcorner multipar, ypart _sa_)
+  fi
+enddef ;
+
+% def _pmp_test_multipar_ =
+%   multipar := boundingbox multipar ;
+% enddef ;
+
+  % first loop
+
+  ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ;
+
+  if enable_multi_par_fallback  and
+     (nxy[fpos]=RealPageNumber) and
+     (nxy[tpos]=RealPageNumber) and not
+     (InsideSomeTextArea(lxy[fpos]) and
+      InsideSomeTextArea(rxy[tpos])) :
+
+  % fallback
+
+    % multipar :=
+    %   llxy[fpos] --
+    %   lrxy[tpos] --
+    %   urxy[tpos] --
+    %   ulxy[fpos] -- cycle ;
+    %
+    % save_multipar (1,1,multipar) ;
+
+    % we need to take the boundingbox because there can be
+    % more lines and we want a proper rectange
+
+    multipar :=
+      ulxy[fpos] --
+      urxy[tpos] --
+      lrxy[fpos] --
+      llxy[tpos] -- cycle ;
+
+    save_multipar (1,1,boundingbox(multipar)) ;
+
+  else :
+
+  % normal
+
+  for i=1 upto NOfTextAreas :
+
+    TopSkipCorrection := 0 ;
+
+    multipar := _pmp_set_multipar_(i) ;
+
+    % watch how we compensate for negative indentation
+
+    if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) :
+
+      % first one in chain
+
+      ii := i ;
+
+%       if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) :
+      if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) :
+
+        % in same area
+
+        nn := i ;
+
+        if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) :
+
+          TopSkipCorrection := TopSkip - StrutHeight ;
+
+          if round(ypart ulxy[fpos] + TopSkipCorrection) =
+             round(ypart ulcorner TextAreas[i]) :
+            ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ;
+            urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ;
+          else :
+            TopSkipCorrection := 0 ;
+          fi ;
+
+        fi ;
+
+        if ypart llxy[fpos] = ypart llxy[tpos] :
+
+          multipar :=
+            llxy[fpos] --
+            lrxy[tpos] --
+           %urxy[tpos] --
+            _pmp_snapped_multi_pos_(urxy[tpos]) --
+           %ulxy[fpos] --
+            _pmp_snapped_multi_pos_(ulxy[fpos]) --
+            cycle ;
+
+          save_multipar (i,1,multipar) ;
+
+        elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and
+               (xpart llxy[tpos] < xpart llxy[fpos]) :
+
+          % two loners
+
+          multipar := if obey_multi_par_hang :
+
+            _pmp_right_bottom_hang_(true) --
+            _pmp_right_top_hang_(true) --
+            _pmp_snapped_multi_pos_(urxy[fpos]) --
+            lrxy[fpos] --
+
+          else :
+
+            llxy[fpos] --
+            (xpart urcorner multipar, ypart llxy[fpos]) --
+            (xpart urcorner multipar, ypart ulxy[fpos]) --
+            _pmp_snapped_multi_pos_(ulxy[fpos]) --
+
+          fi cycle ;
+
+          save_multipar (i,1,multipar) ;
+
+          multipar := _pmp_set_multipar_(i) ;
+
+          multipar := if obey_multi_par_hang :
+
+            _pmp_left_bottom_hang_(true) --
+            llxy[tpos] --
+            _pmp_snapped_multi_pos_(ulxy[tpos]) --
+            _pmp_left_top_hang_(true) --
+
+          else :
+
+            (xpart llcorner multipar, ypart llxy[tpos]) --
+            llxy[tpos] --
+            _pmp_snapped_multi_pos_(ulxy[tpos]) --
+            (xpart llcorner multipar, ypart ulxy[tpos]) --
+
+          fi cycle ;
+
+          save_multipar (i,1,multipar) ;
+
+        else :
+
+          multipar := if obey_multi_par_hang :
+
+            _pmp_left_bottom_hang_(true) --
+            llxy[tpos] --
+           %ulxy[tpos] --
+            _pmp_snapped_multi_pos_(ulxy[tpos]) --
+            _pmp_right_bottom_hang_(true) --
+            _pmp_right_top_hang_(true) --
+           %urxy[fpos] --
+            _pmp_snapped_multi_pos_(urxy[fpos]) --
+            lrxy[fpos] --
+            _pmp_left_top_hang_(true) --
+
+          else :
+
+            (xpart llcorner multipar, ypart llxy[tpos]) --
+            llxy[tpos] --
+           %ulxy[tpos] --
+            _pmp_snapped_multi_pos_(ulxy[tpos]) --
+            (xpart lrcorner multipar, ypart ulxy[tpos]) --
+            (xpart urcorner multipar, ypart urxy[fpos]) --
+           %urxy[fpos] --
+            _pmp_snapped_multi_pos_(urxy[fpos]) --
+            lrxy[fpos] --
+            (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+          fi cycle ;
+
+          save_multipar (i,1,multipar) ;
+
+        fi ;
+
+      else :
+
+        multipar := if obey_multi_par_hang :
+
+          _pmp_left_bottom_hang_(false) --
+          _pmp_right_bottom_hang_(false) --
+          _pmp_right_top_hang_(false) --
+         %urxy[fpos] --
+          _pmp_snapped_multi_pos_(urxy[fpos]) --
+          lrxy[fpos] --
+          _pmp_left_top_hang_(false) --
+
+        else :
+
+          llcorner multipar --
+          lrcorner multipar --
+          (xpart urcorner multipar, ypart urxy[fpos]) --
+         %urxy[fpos] --
+          _pmp_snapped_multi_pos_(urxy[fpos]) --
+          lrxy[fpos] --
+          (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+        fi cycle ;
+
+        save_multipar (i,1,multipar) ;
+
+      fi ;
+
+%     elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) :
+    elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) :
+
+      % last one in chain
+
+      nn := i ;
+
+      if obey_multi_par_hang and obey_multi_par_more :
+
+        multipar :=
+          _pmp_x_left_top_hang_(i,true) --
+          _pmp_x_right_top_hang_(i,true) --
+          _pmp_x_right_bottom_hang_(i,true) --
+          _pmp_snapped_multi_pos_(ulxy[tpos]) --
+          llxy[tpos] --
+          _pmp_x_left_bottom_hang_(i,true) --
+          cycle ;
+
+      else :
+
+        multipar :=
+          ulcorner multipar --
+          urcorner multipar --
+          (xpart lrcorner multipar, ypart urxy[tpos]) --
+          _pmp_snapped_multi_pos_(ulxy[tpos]) --
+          llxy[tpos] --
+          (xpart llcorner multipar, ypart llxy[tpos]) --
+          cycle ;
+
+      fi ;
+
+      save_multipar (i,3,multipar) ;
+
+    elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber)) : % and (NOfTextColumns>1)) :
+
+      save_multipar (i,2,multipar) ;
+
+    else :
+      % handled later
+    fi ;
+
+  endfor ;
+
+  % second loop
+
+  if force_multi_par_chain or (ii > 1) :
+
+    for i=ii+1 upto nn-1 :
+
+      % rest of chain / todo : hang
+
+% hm, the second+ column in column sets now gets lost in a NOfTextColumns
+
+    if (not check_multi_par_chain) or
+       ((nxy[fpos]<RealPageNumber) and (nxy[tpos]>RealPageNumber))
+       :
+
+        multipar := _pmp_set_multipar_(i) ;
+
+        if obey_multi_par_hang and obey_multi_par_more :
+
+          multipar :=
+            _pmp_x_left_top_hang_(i,false) --
+            _pmp_x_right_top_hang_(i,false) --
+            _pmp_x_right_bottom_hang_(i,false) --
+            _pmp_x_left_bottom_hang_(i,false) --
+            cycle ;
+
+        fi ;
+
+        save_multipar(i,2,multipar) ;
+
+      fi ;
+
+    endfor ;
+
+  fi ;
+
+  % end of normal/fallback
+
+fi ;
+
+%  if span_multi_column_pars :
+%    endgroup ;
+%  fi ;
+
+  % potential safeguard:
+
+  % for i=1 upto nofmultipars :
+  %   if length p <= 4 :
+  %     multipars[i] := boundingbox(multipars[i]) ;
+  %   fi ;
+  % end ;
+
+  % quick hack for gb:
+
+  one_piece_multi_par := (nofmultipars=1) and (pn=tn) ;
+
+enddef ;
+
+color   boxgridcolor     ; boxgridcolor     := .8red ;
+color   boxlinecolor     ; boxlinecolor     := .8blue ;
+color   boxfillcolor     ; boxfillcolor     := .8white ;
+numeric boxgridtype      ; boxgridtype      := 0 ;
+numeric boxlinetype      ; boxlinetype      := 1 ;
+numeric boxfilltype      ; boxfilltype      := 1 ;
+numeric boxdashtype      ; boxdashtype      := 0 ;
+pair    boxgriddirection ; boxgriddirection := up ;
+numeric boxgridwidth     ; boxgridwidth     := 1pt ;
+numeric boxlinewidth     ; boxlinewidth     := 1pt ;
+numeric boxlineradius    ; boxlineradius    := 0pt ;
+numeric boxfilloffset    ; boxfilloffset    := 0pt ;
+numeric boxgriddistance  ; boxgriddistance  := .5cm ;
+numeric boxgridshift     ; boxgridshift     := 0pt ;
+
+def draw_box =
+  draw pxy withcolor boxlinecolor withpen pencircle scaled boxlinewidth ;
+  draw lxy -- rxy withcolor boxlinecolor withpen pencircle scaled boxgridwidth ;
+enddef ;
+
+def draw_par  = % 1 2 3 11 12
+  do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ;
+  for i = pxy, txy, bxy :
+        if boxgridtype = 1 :
+      boxgriddirection := origin ;
+      draw baseline_grid (i,boxgriddirection,true ) withcolor boxgridcolor ;
+    elseif boxgridtype = 2 :
+      boxgriddirection := origin ;
+      draw baseline_grid (i,boxgriddirection,false) withcolor boxgridcolor ;
+    elseif boxgridtype = 3 :
+      boxgriddirection := origin ;
+      draw baseline_grid (i,boxgriddirection,true ) withcolor boxgridcolor ;
+      draw baseline_grid (i,boxgriddirection,true )
+        shifted (0,ExHeight) withcolor boxgridcolor ;
+    elseif boxgridtype = 4 :
+      boxgriddirection := origin ;
+      draw baseline_grid (i,boxgriddirection,true )
+        shifted (0,ExHeight/2) withcolor boxgridcolor ;
+    elseif boxgridtype = 11 :
+      draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+    elseif boxgridtype = 12 :
+      draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ;
+    fi ;
+  endfor ;
+enddef ;
+
+def do_show_par (expr p, r, c) =
+  if length(p) > 2 : for i=0 upto length(p) :
+    draw fullcircle scaled r shifted point i of p
+      withpen pencircle scaled .5pt withcolor c ;
+  endfor ; fi ;
+  draw p withpen pencircle scaled .5pt withcolor c ;
+enddef ;
+
+def show_par  =
+  if length(mxy) > 2 :
+    draw mxy dashed evenly
+      withpen pencircle scaled .5pt withcolor .5white ;
+  fi ;
+  do_show_par(txy, 4pt, .5green) ;
+  do_show_par(bxy, 6pt, .5blue ) ;
+  do_show_par(pxy, 8pt, .5red  ) ;
+  draw pref withpen pencircle scaled 2pt ;
+enddef ;
+
+def sort_multi_pars =
+  if nofmultipars>1 :
+    begingroup ; save _p_, _n_ ; path _p_ ; numeric _n_ ;
+      for i := 1 upto nofmultipars :
+        if multilocs[i] = 3 :
+          _p_ := multipars[nofmultipars] ;
+          multipars[nofmultipars] := multipars[i] ;
+          multipars[i] := _p_ ;
+          _n_ := multirefs[nofmultipars] ;
+          multirefs[nofmultipars] := multirefs[i] ;
+          multirefs[i] := _n_ ;
+          _n_ := multilocs[nofmultipars] ;
+          multilocs[nofmultipars] := multilocs[i] ;
+          multilocs[i] := _n_ ;
+        fi ;
+      endfor ;
+    endgroup ;
+  fi ;
+enddef ;
+
+
+def collapse_multi_pars =
+  if nofmultipars>1 :
+    begingroup ; save _nofmultipars_ ; numeric _nofmultipars_ ;
+    _nofmultipars_ := 1 ;
+    sort_multi_pars ; % block not in order: 1, 3, 2....
+    for i:=1 upto nofmultipars-1 :
+      if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and
+         (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) :
+multilocs[_nofmultipars_] := multilocs[i+1] ;
+multirefs[_nofmultipars_] := multirefs[i+1] ;
+        multipars[_nofmultipars_] :=
+          ulcorner multipars[_nofmultipars_] --
+          urcorner multipars[_nofmultipars_] --
+          lrcorner multipars[i+1] --
+          llcorner multipars[i+1] -- cycle ;
+      else :
+        _nofmultipars_ := _nofmultipars_ + 1 ;
+        multipars[_nofmultipars_] := multipars[i+1] ;
+        multilocs[_nofmultipars_] := multilocs[i+1] ;
+        multirefs[_nofmultipars_] := multirefs[i+1] ;
+      fi  ;
+    endfor ;
+    nofmultipars := _nofmultipars_ ;
+    endgroup ;
+  fi ;
+enddef ;
+
+% def draw_multi_pars  =
+%   for i=1 upto nofmultipars :
+%     do_draw_par(multipars[i]) ;
+%         if boxgridtype= 1 :
+%       draw baseline_grid (multipars[i],up,true ) ; % withcolor boxgridcolor ;
+%     elseif boxgridtype= 2 :
+%       draw baseline_grid (multipars[i],up,false) ; % withcolor boxgridcolor ;
+%     elseif boxgridtype= 3 :
+%       draw baseline_grid (multipars[i],up,true ) ; % withcolor boxgridcolor ;
+%       draw baseline_grid (multipars[i],up,true )
+%         shifted (0,ExHeight) ; % withcolor boxgridcolor ;
+%     elseif boxgridtype= 4 :
+%       draw baseline_grid (multipars[i],up,true )
+%         shifted (0,ExHeight/2) ; % withcolor boxgridcolor ;
+%     elseif boxgridtype=11 :
+%       draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+%     elseif boxgridtype=12 :
+%       draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+%     fi ;
+%   endfor ;
+% enddef ;
+
+def draw_multi_pars  =
+  for i=1 upto nofmultipars :
+    do_draw_par(multipars[i]) ;
+        if boxgridtype= 1 :
+      draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; % withcolor boxgridcolor ;
+    elseif boxgridtype= 2 :
+      draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ; % withcolor boxgridcolor ;
+    elseif boxgridtype= 3 :
+      draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; % withcolor boxgridcolor ;
+      draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ; % withcolor boxgridcolor ;
+    elseif boxgridtype= 4 :
+      draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ; % withcolor boxgridcolor ;
+    elseif boxgridtype=11 :
+      draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+    elseif boxgridtype=12 :
+      draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+    fi ;
+  endfor ;
+enddef ;
+
+def show_multi_pars  =
+  for i=1 upto nofmultipars :
+    do_show_par(multipars[i], 6pt, .5blue) ;
+  endfor ;
+enddef ;
+
+vardef do_draw_par (expr p) =
+  if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) :
+    save pp ; path pp ;
+    if (boxlineradius>0) and (boxlinetype=2) :
+      pp := p cornered boxlineradius ;
+    else :
+      pp := p ;
+    fi ;
+    if boxfilltype>0 :
+      if boxfilloffset>0 :
+        % temporary hack
+        begingroup ; interim linejoin := mitered ;
+          filldraw pp withcolor boxfillcolor withpen pencircle scaled (2*boxfilloffset) ;
+        endgroup ;
+      else :
+        fill pp withcolor boxfillcolor ;
+      fi ;
+    fi ;
+    if boxlinetype>0 :
+      draw pp withcolor boxlinecolor withpen pencircle scaled boxlinewidth ;
+    fi ;
+  fi ;
+enddef ;
+
+vardef baseline_grid (expr pxy, pdir, at_baseline) =
+  if (par_line_height>0) and (bbheight(pxy)>1) and (bbwidth(pxy)>1) and (boxgridwidth>0) :
+    save i, grid, bb ; picture grid ; pair start ; path bb ;
+    def _do_ (expr start) =
+      % 1 = normal, 2 = with background (i.e. no shine-through)
+      if boxdashtype = 2 :
+        draw start -- start shifted (bbwidth(pxy),0)
+          withpen pencircle scaled boxgridwidth
+          withcolor boxfillcolor ;
+      fi ;
+      draw start -- start shifted (bbwidth(pxy),0)
+        if boxdashtype > 0 : dashed evenly fi
+        withpen pencircle scaled boxgridwidth
+        withcolor boxgridcolor ;
+    enddef ;
+    grid := image
+      ( %fails with inlinespace
+        %
+        if pdir=up :
+          for i = if at_baseline : par_strut_depth else : 0 fi
+                  step  par_line_height
+                  until max(bbheight(pxy),par_line_height) :
+            _do_ (llcorner pxy shifted (0,+i)) ;
+          endfor ;
+        else :
+          for i = if at_baseline : par_strut_height else : 0 fi
+                  step  par_line_height
+                  until bbheight(pxy) :
+            _do_ (ulcorner pxy shifted (0,-i)) ;
+          endfor ;
+        fi ;
+      ) ;
+    clip grid to pxy ;
+    bb := boundingbox grid ;
+    grid := grid shifted (0,boxgridshift) ;
+    setbounds grid to bb ;
+    grid
+  else :
+    nullpicture
+  fi
+enddef ;
+
+vardef graphic_grid (expr pxy, dx, dy, x, y) =
+  if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) :
+    save grid ; picture grid ;
+    grid := image
+      ( for i = xpart llcorner pxy step dx until xpart lrcorner pxy :
+          draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy)
+            withpen pencircle scaled boxgridwidth ;
+        endfor ;
+        for i = ypart llcorner pxy step dy until ypart ulcorner pxy :
+          draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i)
+            withpen pencircle scaled boxgridwidth ;
+        endfor ) shifted (x,y) ;
+    clip grid to pxy ;
+    grid
+  else :
+    nullpicture
+  fi
+enddef ;
+
+def anchor_box (expr n,x,y,w,h,d) =
+  currentpicture := currentpicture shifted (-x,-y) ;
+enddef ;
+
+let draw_area   = draw_box ;
+let anchor_area = anchor_box ;
+let anchor_par  = anchor_box ;
+
+
+numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ;
+pair sync_xy[][] ; color sync_c[][] ;
+
+def ResetSyncTasks =
+  path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ;
+  NOfSyncPaths := CurrentSyncClass := 0 ;
+  if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0          ; fi ;
+  if unknown SyncWidth      : numeric SyncWidth      ; SyncWidth      := 0          ; fi ;
+  if unknown SyncThreshold  : numeric SyncThreshold  ; SyncThreshold  := LineHeight ; fi ;
+  if unknown SyncColor      : color   SyncColor      ; SyncColor      := .5white    ; fi ;
+  if (SyncLeftOffset = 0) and (SyncWidth = 0) :
+    SyncWidth := if known TextWidth : TextWidth else : -1cm fi ;
+  fi ;
+enddef ;
+
+ResetSyncTasks ;
+
+vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) =
+   save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ;
+   o shifted (leftoffset,sync_h[n][i]+topoffset) --
+   o shifted (width+leftoffset,sync_h[n][i]+topoffset) --
+   o shifted (width+leftoffset,bottomoffset) --
+   o shifted (leftoffset,bottomoffset) -- cycle
+enddef ;
+
+def SetSyncColor(expr n, i, c) =
+  sync_c[n][i] := c ;
+enddef ;
+
+def SetSyncThreshold(expr n, i, th) =
+  sync_th[n][i] := th ;
+enddef ;
+
+vardef TheSyncColor(expr n, i) =
+  if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi
+enddef ;
+
+vardef TheSyncThreshold(expr n, i) =
+  if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi
+enddef ;
+
+vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) =
+  ResetSyncTasks ;
+  if known sync_n[n] :
+    CurrentSyncClass := n ;
+    save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ;
+    for i=1 upto sync_n[n] :
+      if RealPageNumber > sync_p[n][i] :
+        l := i ;
+      elseif RealPageNumber = sync_p[n][i] :
+        NOfSyncPaths := NOfSyncPaths + 1 ;
+        if not ok :
+          if i>1 :
+            if sync_t[n][i-1] = sync_t[n][i] :
+              SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+              SyncTasks[NOfSyncPaths] := i ;
+            else :
+              SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+              SyncTasks[NOfSyncPaths] := i-1 ;
+              NOfSyncPaths := NOfSyncPaths + 1 ;
+              SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+              SyncTasks[NOfSyncPaths] := i ;
+            fi ;
+          else :
+            SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+            SyncTasks[NOfSyncPaths] := i ;
+          fi ;
+        else :
+          SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+          SyncTasks[NOfSyncPaths] := i ;
+        fi ;
+        ok := true ;
+      fi ;
+    endfor ;
+    if (NOfSyncPaths = 0) and (l > 0) :
+      NOfSyncPaths := 1 ;
+      SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+      SyncTasks[NOfSyncPaths] := l ;
+    fi ;
+    if NOfSyncPaths > 0 :
+      for i = 1 upto NOfSyncPaths-1 :
+        SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ;
+      endfor ;
+      if unknown SyncThresholdMethod :
+        numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ;
+      fi ;
+      if extendtop :
+        if SyncThresholdMethod = 1 :
+          if NOfSyncPaths>1 :
+            d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ;
+            if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) :
+              SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ;
+            fi ;
+          fi ;
+        else :
+          for i = 1 upto NOfSyncPaths :
+            d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ;
+            if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) :
+              SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ;
+            fi ;
+          endfor ;
+        fi ;
+      fi ;
+      if prestartnext :
+        if NOfSyncPaths>1 :
+          if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one
+            d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ;
+            if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) :
+              SyncPaths[NOfSyncPaths+1] :=
+                (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+                (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+                lrcorner SyncPaths[NOfSyncPaths] --
+                llcorner SyncPaths[NOfSyncPaths] -- cycle ;
+              SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ;
+              NOfSyncPaths := NOfSyncPaths + 1 ;
+            fi ;
+          fi ;
+        fi ;
+      else :
+        if NOfSyncPaths>1 :
+          d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ;
+          if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) :
+            NOfSyncPaths := NOfSyncPaths - 1 ;
+            SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ;
+          fi ;
+        fi ;
+      fi ;
+      if (NOfSyncPaths>1) and collapse :
+        save j ; numeric j ; j := 1 ;
+        for i = 2 upto NOfSyncPaths :
+          if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] :
+            SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ;
+            SyncTasks[j] := SyncTasks[i] ;
+          else :
+            j := j + 1 ;
+            SyncPaths[j] := SyncPaths[i] ;
+            SyncTasks[j] := SyncTasks[i] ;
+          fi ;
+        endfor ;
+        NOfSyncPaths := j ;
+      fi ;
+    fi ;
+  fi ;
+enddef ;
+
+def SyncTask(expr n) =
+  if known SyncTasks[n] : SyncTasks[n] else : 0 fi
+enddef ;
+
+def FlushSyncTasks =
+  for i = 1 upto NOfSyncPaths :
+    ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ;
+  endfor ;
+enddef ;
+
+def ProcessSyncTask(expr p, c) =
+  fill p withcolor c ;
+enddef ;
+
+% for Jelle Huisman
+%
+% \setupcolors[state=start]
+% \dontcomplain
+% \definecolumnset[example][n=3,distance=5mm]
+% \startMPextensions
+%     multi_column_first_page_hack := true ;
+% \stopMPextensions
+% \startuseMPgraphic{mpos:par:trick}
+%     for i=1 upto nofmultipars-1 : draw (rightboundary multipars[i]) shifted (2.5mm, 0) ; endfor ;
+% \stopuseMPgraphic
+% \definetextbackground[test][mp=mpos:par:trick,method=mpos:par:columnset]
+% \starttext
+% \definecolumnsetspan[chapter][n=3]
+% \startcolumnset[example]
+% \startcolumnsetspan[chapter]
+% \chapter{Chapter One}
+% \stopcolumnsetspan
+% \starttextbackground[test] \dorecurse {3}{\input knuth } \stoptextbackground
+% \stopcolumnset
+% \startcolumnset[example]
+% \startcolumnsetspan[chapter]
+% \chapter{Chapter One}
+% \stopcolumnsetspan
+% \starttextbackground[test] \dorecurse {10}{\input knuth } \stoptextbackground
+% \stopcolumnset
+% \stoptext
+%
+% fast variant:
+%
+% \startuseMPgraphic{whatever}
+%     for i=1 upto NOfTextColumns-1 :
+%         draw (rightboundary TextColumns[i]) shifted (2.5mm,0) shifted -\MPxy\textanchor ;
+%     endfor ;
+%     setbounds currentpicture to OverlayBox ;
+% \stopuseMPgraphic
+% \defineoverlay[whatever][\useMPgraphic{whatever}]
+% \setupbackgrounds[text][background=whatever]

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-figs.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-figs.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-figs.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,47 @@
+%D \module
+%D   [       file=mp-figs.mpii,
+%D        version=2003.01.15,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=figures,
+%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 licen-en.pdf for
+%C details.
+
+if known context_figs : endinput ; fi ;
+
+boolean context_figs ; context_figs := true ;
+
+% todo: check defined
+
+def registerfigure(expr name,width,height) =
+    begingroup ;
+    save s ; string s ; s := cleanstring(name) ;
+    scantokens( s & "_width  := " & decimal(width )) ;
+    scantokens( s & "_height := " & decimal(height)) ;
+    endgroup ;
+enddef ;
+
+vardef figuresize(expr name) =
+    save s, p ; string s ; pair p ;
+    s := cleanstring(name) ;
+    scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ;
+    p
+enddef ;
+
+vardef figurewidth(expr name) =
+    xpart figuresize(name)
+enddef ;
+
+vardef figureheight(expr name) =
+    ypart figuresize(name)
+enddef ;
+
+let figuredimensions = figuresize ; % for old times sake
+
+def naturalfigure(expr name) =
+    externalfigure name xyscaled(figuresize(name))
+enddef ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-fobg.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-fobg.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-fobg.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,87 @@
+%D \module
+%D   [       file=mp-fobg.mp,
+%D        version=2004.03.12,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=Formatting Objects,
+%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 licen-en.pdf for
+%C details.
+
+if known context_fobg : endinput ; fi ;
+
+boolean context_fobg ; context_fobg := true ;
+
+FoNone   := 0 ; FoHidden := 1 ; FoDotted := 2 ; FoDashed := 3 ; FoSolid  := 4 ;
+FoDouble := 5 ; FoGroove := 6 ; FoRidge  := 7 ; FoInset  := 8 ; FoOutset := 9 ;
+FoAll    := 0 ; FoTop    := 1 ; FoBottom := 2 ; FoLeft   := 3 ; FoRight  := 4 ;
+FoMedium := .5pt ; FoThin := FoMedium/2 ; FoThick := FoMedium*2 ;
+
+color FoBackgroundColor, FoNoColor, FoLineColor[] ; FoNoColor := (-1,-1,-1) ;
+numeric FoLineWidth[], FoLineStyle[] ;
+boolean FoFrame, FoBackground, FoSplit ;
+
+FoFrame := FoBackground := FoSplit := false ;
+FoBackgroundColor := white ;
+FoDashFactor := .5 ;
+FoDotFactor := .375 ;
+
+for i = FoAll upto FoRight :
+  FoLineColor[i] := black ;
+  FoLineWidth[i] := .5pt ;
+  FoLineStyle[i] := FoNone ;
+endfor ;
+
+def DrawFoFrame(expr n, p) =
+  drawoptions(withcolor FoLineColor[n] withpen pencircle scaled FoLineWidth[n]) ;
+  if     FoLineStyle[n] = FoNone   :
+    % nothing
+  elseif FoLineStyle[n] = FoHidden :
+    % nothing
+  elseif FoLineStyle[n] = FoDotted :
+    draw p dashed (withdots scaled (FoDotFactor*FoLineWidth[n])) ;
+  elseif FoLineStyle[n] = FoDashed :
+    draw p dashed (evenly scaled (FoDashFactor*FoLineWidth[n])) ;
+  elseif FoLineStyle[n] = FoSolid  :
+    draw p ;
+  elseif FoLineStyle[n] = FoDouble :
+    draw p enlarged  FoLineWidth[n] ; draw p enlarged -FoLineWidth[n] ;
+  elseif FoLineStyle[n] = FoGroove :
+    draw p ;
+    draw p withpen pencircle scaled .5FoLineWidth[n] withcolor (inverted FoLineColor[n] softened .5) ;
+  elseif FoLineStyle[n] = FoRidge  :
+    draw p withcolor  (inverted FoLineColor[n] softened .5) ;
+    draw p withpen pencircle scaled .5FoLineWidth[n] ;
+  elseif FoLineStyle[n] = FoInset  :
+    draw p ; draw p inset 2.5FoLineWidth[n] ;
+  elseif FoLineStyle[n] = FoOutset :
+    draw p ; draw p outset 2.5FoLineWidth[n] ;
+ fi ;
+enddef ;
+
+primarydef p outset d =
+  ((lrcorner p -- urcorner p -- ulcorner p -- llcorner p -- cycle)
+      shifted (d*(-1,1)) cutbefore topboundary p) cutafter leftboundary p
+enddef ;
+
+primarydef p inset d =
+  ((ulcorner p -- llcorner p -- lrcorner p -- urcorner p -- cycle)
+      shifted (d*(1,-1)) cutbefore bottomboundary p) cutafter rightboundary p
+enddef ;
+
+vardef equalpaths(expr p, q) =
+  if length(p) = length(q) :
+    save ok ; boolean ok ; ok := true ;
+    for i = 0 upto length(p)-1 :
+      ok := ok and (round(point i of p) = round(point i of q)) ;
+    endfor ;
+    ok
+  else :
+    false
+  fi
+enddef ;
+
+endinput ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-form.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-form.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-form.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,392 @@
+% Hans Hagen / October 2000
+%
+% This file is mostly a copy from the file format.mp, that
+% comes with MetaPost and is written by John Hobby. This file
+% is meant to be compatible, but has a few more features,
+% controlled by the variables:
+%
+% fmt_initialize  when false, initialization is skipped
+% fmt_precision   the default accuracy (default=3)
+% fmt_separator   the pattern separator (default=%)
+% fmt_zerocheck   activate extra sci notation zero check
+%
+% instead of a picture, one can format a number in a for TeX
+% acceptable input string
+
+boolean mant_font ; mant_font := true ; % signals graph not to load form
+
+if known context_form : endinput ; fi ;
+
+boolean context_form ; context_form := true ;
+
+if unknown fmt_metapost   : boolean fmt_metapost   ; fmt_metapost   := true  ; fi ; % == use old method
+if unknown fmt_precision  : numeric fmt_precision  ; fmt_precision  := 3     ; fi ;
+if unknown fmt_initialize : boolean fmt_initialize ; fmt_initialize := true  ; fi ;
+if unknown fmt_separator  : string  fmt_separator  ; fmt_separator  := "%"   ; fi ;
+if unknown fmt_zerocheck  : boolean fmt_zerocheck  ; fmt_zerocheck  := false ; fi ;
+
+% As said, all clever code is from John, the more stupid
+% extensions are mine. The following string variables are
+% responsible for the TeX formatting.
+
+% TeX specs when using TeX instead of pseudo TeX.
+
+string sFebraise_ ; sFebraise_ := "{" ;
+string sFeeraise_ ; sFeeraise_ := "}" ;
+string sFebmath_  ; sFebmath_  := "$" ;
+string sFeemath_  ; sFeemath_  := "$" ;
+
+string sFmneg_    ; sFmneg_    := "-" ;
+string sFemarker_ ; sFemarker_ := "{\times}10^" ;
+string sFeneg_    ; sFeneg_    := "-" ;
+string sFe_plus   ; sFe_plus   := "" ; % "+"
+
+def sFe_base = Fline_up_("1", sFemarker_) enddef ;
+
+% Macros for generating typeset pictures of computed numbers
+%
+% format(f,x)               typeset generalized number x using format string f
+% Mformat(f,x)              like format, but x is in Mlog form (see marith.mp)
+% init_numbers(s,m,x,sn,e)  choose typeset style given sample sign, mantissa,...
+% roundd(x,d)               round numeric x to d places right of decimal point
+% Fe_base                   what precedes the exponent for typeset powers of 10
+% Fe_plus                   plus sign if any for typesetting positive exponents
+% Ten_to[]                  powers of ten for indices 0,1,2,3,4
+%
+% New are:
+%
+% formatstr(f,x)            TeX string representing x using format f
+% Mformatstr(f,x)           like Mformatstr, but x is in Mlog form
+
+% Other than the above-documented user interface, all
+% externally visible names start with F and end with _.
+
+% Allow big numbers in token lists
+
+begingroup interim warningcheck := 0 ;
+
+%%% Load auxiliary macros.
+
+input string ;
+input marith ;
+
+%%% Choosing the Layout %%%
+
+picture Fmneg_, Femarker_, Feneg_, Fe_base, Fe_plus ;
+string  Fmfont_, Fefont_ ;
+numeric Fmscale_, Fescale_, Feraise_ ;
+
+% Argument
+%
+% s   is a leading minus sign
+% m   is a 1-digit mantissa
+% x   is whatever follows the mantissa
+% sn  is a leading minus for the exponent, and
+% e   is a 1-digit exponent.
+%
+% Numbers in scientific notation are constructed by placing
+% these pieces side-by-side; decimal numbers use only m
+% and/or s. To get exponents with leading plus signs, assign
+% to Fe_plus after calling init_numbers. To do something
+% special with a unit mantissa followed by x, assign to
+% Fe_base after calling init_numbers.
+
+vardef init_numbers(expr s, m, x, sn, e) =
+  Fmneg_ := s ;
+  for p within m :
+    Fmfont_ := fontpart p ;
+    Fmscale_ := xxpart p ;
+    exitif true ;
+  endfor
+  Femarker_ := x ;
+  Feneg_ := sn ;
+  for p within e :
+    Fefont_ := fontpart p ;
+    Fescale_ := xxpart p ;
+    Feraise_ := ypart llcorner p ;
+    exitif true ;
+  endfor
+  if fmt_metapost :
+    Fe_base := Fline_up_("1" infont Fmfont_ scaled Fmscale_, Femarker_) ;
+  % else :
+  %   sFe_base := Fline_up_("1", sFemarker_) ;
+  fi ;
+  Fe_plus := nullpicture ;
+enddef ;
+
+%%% Low-Level Typesetting %%%
+
+vardef Fmant_(expr x) = %%% adapted by HH %%%
+  if fmt_metapost :
+    (decimal abs x infont Fmfont_ scaled Fmscale_)
+  else :
+    (decimal abs x)
+  fi
+enddef ;
+
+vardef Fexp_(expr x) = %%% adapted by HH %%%
+  if fmt_metapost :
+    (decimal x infont Fefont_ scaled Fescale_ shifted (0,Feraise_))
+  else :
+    (decimal x)
+  fi
+enddef ;
+
+vardef Fline_up_(text t_) = %%% adapted by HH %%%
+  if fmt_metapost :
+    save p_, c_ ;
+    picture p_ ; p_ = nullpicture ;
+    pair c_ ; c_ = (0,0) ;
+    for q_ = t_ :
+      addto p_ also q_ if string q_ : infont defaultfont scaled defaultscale fi
+          shifted c_ ;
+      c_ := (xpart lrcorner p_, 0) ;
+    endfor
+    p_
+  else :
+    "" for q_ = t_ : & q_ endfor
+  fi
+enddef ;
+
+vardef Fdec_o_(expr x) = %%% adapted by HH %%%
+  if x<0 :
+    Fline_up_(if fmt_metapost : Fmneg_ else : sFmneg_ fi, Fmant_(x))
+  else :
+    Fmant_(x)
+  fi
+enddef ;
+
+vardef Fsci_o_(expr x, e) = %%% adapted by HH %%%
+  if fmt_metapost :
+    Fline_up_
+      (if x < 0 : Fmneg_,fi
+       if abs x = 1 : Fe_base else : Fmant_(x), Femarker_ fi,
+       if e < 0 : Feneg_ else : Fe_plus fi,
+       Fexp_(abs e))
+  else :
+    Fline_up_
+      (if x < 0 : sFmneg_, fi
+       if abs x = 1 : sFe_base else : Fmant_(x), sFemarker_ fi,
+       sFebraise_,
+       if e < 0 : sFeneg_ else : sFe_plus fi,
+       Fexp_(abs e),
+       sFeeraise_)
+   fi
+enddef ;
+
+% Assume prologues=1 implies troff mode. TeX users who want
+% prologues on should use some other positive value. The mpx
+% file mechanism requires separate input files here.
+%
+% if fmt_initialize : %%% adapted by HH
+%   if prologues = 1 : input troffnum else : input texnum fi
+% fi ;
+%
+% wrong assumption, so we need:
+
+if fmt_initialize :
+  input texnum ;
+fi ;
+
+%%% Scaling and Rounding %%%
+
+% Find a pair p where x = xpart p*10**ypart p and either p =
+% (0,0) or xpart p is between 1000 and 9999.99999. This is
+% the `exponent form' of x.
+
+vardef Feform_(expr x) =
+  interim warningcheck := 0 ;
+  if string x :
+    Meform(Mlog_str x)
+  else :
+    save b, e ;
+    b = x ; e = 0 ;
+    if abs b >= 10000 :
+      (b/10, 1)
+    elseif b = 0 :
+      origin
+    else :
+      forever :
+        exitif abs b >= 1000 ;
+        b := b*10 ; e := e-1 ;
+      endfor
+      (b, e)
+    fi
+  fi
+enddef ;
+
+% The marith.mp macros include a similar macro Meform that
+% converts from `Mlog form' to exponent form. In case
+% rounding has made the xpart of an exponent form number too
+% large, fix it.
+
+vardef Feadj_(expr x, y) =
+  if abs x >= 10000 : (x/10, y+1) else : (x,y) fi
+enddef ;
+
+% Round x to d places right of the decimal point. When d<0,
+% round to the nearest multiple of 10 to the -d.
+
+vardef roundd(expr x, d) =
+  if abs d > 4 :
+    if d > 0 : x else : 0 fi
+  elseif d > 0 :
+    save i ; i = floor x ;
+    i + round(Ten_to[d]*(x-i))/Ten_to[d]
+  else :
+    round(x/Ten_to[-d])*Ten_to[-d]
+  fi
+enddef ;
+
+Ten_to0 =     1 ;
+Ten_to1 =    10 ;
+Ten_to2 =   100 ;
+Ten_to3 =  1000 ;
+Ten_to4 = 10000 ;
+
+% Round an exponent form number p to k significant figures.
+
+primarydef p Fprec_ k =
+  Feadj_(roundd(xpart p,k-4), ypart p)
+enddef ;
+
+% Round an exponent form number p to k digits right of the
+% decimal point.
+
+primarydef p Fdigs_ k =
+  Feadj_(roundd(xpart p,k+ypart p), ypart p)
+enddef ;
+
+%%% High-Level Routines %%%
+
+% The following operators convert z from exponent form and
+% produce typeset output: Formsci_ generates scientific
+% notation; Formdec_ generates decimal notation; and
+% Formgen_ generates whatever is likely to be most compact.
+
+vardef Formsci_(expr z) = %%% adapted by HH %%%
+  if fmt_zerocheck and (z = origin) :
+    Fsci_o_(0,0)
+  else :
+    Fsci_o_(xpart z/1000, ypart z + 3)
+  fi
+enddef ;
+
+vardef Formdec_(expr z) =
+  if ypart z > 0 :
+    Formsci_(z)
+  else :
+    Fdec_o_
+      (xpart z if ypart z >= -4 :
+                 /Ten_to[-ypart z]
+               else :
+                 for i = ypart z upto -5 : /(10) endfor /10000
+               fi)
+  fi
+enddef ;
+
+vardef Formgen_(expr q) =
+  clearxy ; (x,y) = q ;
+  if     x  =  0 : Formdec_
+  elseif y >= -6 : Formdec_
+  else           : Formsci_
+  fi (q)
+enddef ;
+
+def Fset_item_(expr s) = %%% adapted by HH %%%
+  if s <> "" :
+    if fmt_metapost :
+      s infont defaultfont scaled defaultscale,
+    else :
+      s,
+    fi
+  fi
+enddef ;
+
+% For each format letter, the table below tells how to
+% round and typeset a quantity z in exponent form.
+%
+% e  scientific, p significant figures
+% f  decimal, p digits right of the point
+% g  decimal or scientific, p sig. figs.
+% G  decimal or scientific, p digits
+
+string fmt_[] ;
+
+fmt_[ASCII "e"] = "Formsci_(z Fprec_ p)" ;
+fmt_[ASCII "f"] = "Formdec_(z Fdigs_ p)" ;
+fmt_[ASCII "g"] = "Formgen_(z Fprec_ p)" ;
+fmt_[ASCII "G"] = "Formgen_(z Fdigs_ p)" ;
+
+% The format and Mformat macros take a format string f and
+% generate typeset output for a numeric quantity x. String f
+% should contain a `%' followed by an optional number and one
+% of the format letters defined above. The number should be
+% an integer giving the precision (default 3).
+
+vardef isfmtseparator primary c = %%% added by HH %%%
+  ((c <> fmt_separator) and (c <> "%"))
+enddef ;
+
+def initialize_form_numbers =
+  initialize_numbers ; % in context: do_initialize_numbers ;
+enddef ;
+
+vardef dofmt_@#(expr f, x) = %%% adapted by HH %%%
+  initialize_form_numbers ;
+  if f = "" :
+    if fmt_metapost : nullpicture else : "" fi
+  else :
+    interim warningcheck := 0 ;
+    save k, l, s, p, z ;
+    pair z ; z = @#(x) ;
+    % the next adaption is okay
+    % k = 1 + cspan(f, fmt_separator <> ) ;
+    % but best is to support both % and fmt_separator
+    k = 1 + cspan(f, isfmtseparator) ;
+    %
+    l-k = cspan(substring(k,infinity) of f, isdigit) ;
+    p = if l > k :
+      scantokens substring(k,l) of f
+    else :
+      fmt_precision
+    fi ;
+    string s ; s = fmt_[ASCII substring (l,l+1) of f] ;
+    if unknown s :
+      if k <= length f :
+        errmessage("No valid format letter found in "&f) ;
+      fi
+      s = if fmt_metapost : "nullpicture" else : "" fi ;
+    fi
+    Fline_up_
+      (Fset_item_(substring (0,k-1) of f)
+       if not fmt_metapost : sFebmath_, fi
+       scantokens s,
+       if not fmt_metapost : sFeemath_, fi
+       Fset_item_(substring (l+1,infinity) of f)
+       if fmt_metapost : nullpicture else : "" fi)
+  fi
+  hide (fmt_metapost := true)
+enddef ;
+
+%%% so far %%%
+
+vardef format (expr f, x) =
+  fmt_metapost := true ; dofmt_.Feform_(f,x)
+enddef ;
+
+vardef Mformat(expr f, x) =
+  fmt_metapost := true ; dofmt_.Meform (f,x)
+enddef ;
+
+vardef formatstr (expr f, x) =
+  fmt_metapost := false ; dofmt_.Feform_(f,x)
+enddef ;
+
+vardef Mformatstr(expr f, x) =
+  fmt_metapost := false ; dofmt_.Meform (f,x)
+enddef ;
+
+% Restore warningcheck to previous value.
+
+endgroup ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-func.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-func.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-func.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,58 @@
+%D \module
+%D   [       file=mp-func.mpii,
+%D        version=2001.12.29,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=function hacks,
+%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 licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_func : endinput ; fi ;
+
+boolean context_func ; context_func := true ;
+
+string pathconnectors[] ;
+
+pathconnectors[0] := ","   ;
+pathconnectors[1] := "--"  ;
+pathconnectors[2] := ".."  ;
+pathconnectors[3] := "..." ;
+
+vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ;
+  for xx := b step s until e :
+    hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi
+    (scantokens(u),scantokens(t))
+  endfor
+enddef ;
+
+def punkedfunction = function (1) enddef ;
+def curvedfunction = function (2) enddef ;
+def tightfunction  = function (3) enddef ;
+
+vardef constructedpath (expr f) (text t) =
+  save ok ; boolean ok ; ok := false ;
+  for i=t :
+    if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i
+  endfor
+enddef ;
+
+def punkedpath = constructedpath (1) enddef ;
+def curvedpath = constructedpath (2) enddef ;
+def tightpath  = constructedpath (3) enddef ;
+
+vardef constructedpairs (expr f) (text p) =
+  save i ; i := -1 ;
+  forever : exitif unknown p[incr(i)] ;
+    if i>0 : scantokens(pathconnectors[f]) fi p[i]
+  endfor
+enddef ;
+
+def punkedpairs = constructedpairs (1) enddef ;
+def curvedpairs = constructedpairs (2) enddef ;
+def tightpairs  = constructedpairs (3) enddef ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grid.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grid.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grid.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,149 @@
+%D \module
+%D   [       file=mp-grid.mpii,
+%D        version=2000.07.10,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=grid support,
+%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 licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_grid : endinput ; fi ;
+
+boolean context_grid ; context_grid := true ;
+
+string  fmt_separator  ; fmt_separator  := "@" ;
+numeric fmt_precision  ; fmt_precision  := 3 ;
+boolean fmt_initialize ; fmt_initialize := false ;
+boolean fmt_zerocheck  ; fmt_zerocheck  := true ;
+
+if unknown fmt_loaded : input "mp-form.mpii" ; fi ;
+
+boolean fmt_pictures ; fmt_pictures := true ;
+
+def  do_format = if fmt_pictures :  format else :  formatstr fi enddef ;
+def do_mformat = if fmt_pictures : Mformat else : Mformatstr fi enddef ;
+
+numeric grid_eps ; grid_eps = eps ;
+
+def hlingrid (expr Min, Max, Step, Length, Width) text t =
+  image ( for i=Min step Step until Max+grid_eps :
+    draw (origin--(Width,0)) shifted (0,i*(Length/Max)) t ;
+  endfor ; ) ;
+enddef ;
+
+def vlingrid (expr Min, Max, Step, Length, Height) text t =
+  image ( for i=Min step Step until Max+grid_eps :
+    draw (origin--(0,Height)) shifted (i*(Length/Max),0) t ;
+  endfor ; ) ;
+enddef ;
+
+def hloggrid (expr Min, Max, Step, Length, Width) text t =
+  image ( for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+    draw (origin--(Width,0)) shifted (0,Length*log(i)) t ;
+  endfor ; ) ;
+enddef ;
+
+def vloggrid (expr Min, Max, Step, Length, Height) text t =
+  image ( for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+    draw (origin--(0,Height)) shifted (Length*log(i),0) t ;
+  endfor ; ) ;
+enddef ;
+
+vardef hlintext@#(expr Min, Max, Step, Length, Format) text t =
+  image ( do_initialize_numbers ;
+  for i=Min step Step until Max+grid_eps :
+    draw textext@#(do_format(Format,i)) shifted (0,i*(Length/Max)) t ;
+  endfor ; )
+enddef ;
+
+vardef vlintext@#(expr Min, Max, Step, Length, Format) text t =
+  image ( do_initialize_numbers ;
+  for i=Min step Step until Max+grid_eps :
+    draw textext@#(do_format(Format,i)) shifted (i*(Length/Max),0) t ;
+  endfor ; )
+enddef ;
+
+vardef hlogtext@#(expr Min, Max, Step, Length, Format) text t =
+  image ( do_initialize_numbers ;
+  for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+    draw textext@#(do_format(Format,i)) shifted (0,Length*log(i)) t ;
+  endfor ; )
+enddef ;
+
+vardef vlogtext@#(expr Min, Max, Step, Length, Format) text t =
+  image ( do_initialize_numbers ;
+  for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+    draw textext@#(do_format(Format,i)) shifted (Length*log(i),0) t ;
+  endfor ; )
+enddef ;
+
+vardef hlinlabel@#(expr Min, Max, Step, Length) text t =
+  image (
+  for i=Min step Step until Max+grid_eps :
+    draw thelabel@#(decimal i,(0,i*(Length/Max))) t ;
+  endfor ; )
+enddef ;
+
+vardef vlinlabel@#(expr Min, Max, Step, Length) text t =
+  image (
+  for i=Min step Step until Max+grid_eps :
+    draw thelabel@#(decimal i,(i*(Length/Max),0)) t ;
+  endfor ; )
+enddef ;
+
+boolean numbers_initialized ; numbers_initialized := false ;
+
+def do_initialize_numbers =
+  if not numbers_initialized :
+    init_numbers ( textext.raw("$-$")          ,
+                   textext.raw("$1$")          ,
+                   textext.raw("${\times}10$") ,
+                   textext.raw("${}^-$")       ,
+                   textext.raw("${}^2$")       ) ;
+    if unknown _trial_run_ :
+      numbers_initialized := true ;
+    else :
+      % no reset, otherwise textexts get out of sync
+      % slows down graphics a bit but not much
+    fi ;
+  fi ;
+enddef ;
+
+def initialize_numbers =
+  numbers_initialized := false ; do_initialize_numbers ;
+enddef ;
+
+vardef linlog(expr xy) = (    xpart xy,  log(ypart xy)) enddef ;
+vardef loglin(expr xy) = (log(xpart xy),     ypart xy)  enddef ;
+vardef loglog(expr xy) = (log(xpart xy), log(ypart xy)) enddef ;
+vardef linlin(expr xy) = (   (xpart xy),    (ypart xy)) enddef ;
+
+vardef loglinpath primary p = processpath (p) (loglin) enddef ;
+vardef linlogpath primary p = processpath (p) (linlog) enddef ;
+vardef loglogpath primary p = processpath (p) (loglog) enddef ;
+vardef linlinpath primary p = processpath (p) (linlin) enddef ;
+
+def processpath (expr p) (text pp) =
+  if path p :
+    for i=0 upto length(p)-1 :
+      (pp(point       i    of p)) .. controls
+      (pp(postcontrol i    of p)) and
+      (pp(precontrol (i+1) of p)) ..
+    endfor
+    if cycle p :
+      cycle
+    else :
+      (pp(point length(p) of p))
+    fi
+  elseif pair p :
+    (pp(p))
+  else :
+    p
+  fi
+enddef ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grph.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grph.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-grph.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,310 @@
+%D \module
+%D   [       file=mp-grph.mpii,
+%D        version=2000.12.14,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=graphic text support,
+%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 licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_grph : endinput ; fi ;
+
+boolean context_grph ; context_grph := true ;
+
+string CRLF ; CRLF := char 10 & char 13 ;
+
+picture _currentpicture_ ;
+
+numeric _fig_nesting_ ; _fig_nesting_ := 0 ;
+
+def beginfig (expr c) =
+    _fig_nesting_ := _fig_nesting_ + 1 ;
+    if _fig_nesting_  = 1 :
+        begingroup
+        charcode := c ;
+        resetfig ;
+        scantokens extra_beginfig ;
+    fi ;
+enddef ;
+
+def endfig =
+    ; % safeguard
+    if _fig_nesting_ = 1 :
+        scantokens extra_endfig;
+        shipit ;
+        endgroup ;
+    fi ;
+    _fig_nesting_ := _fig_nesting_ - 1 ;
+enddef;
+
+
+def resetfig =
+  clearxy ;
+  clearit ;
+  clearpen ;
+  pickup defaultpen ;
+  interim linecap := linecap ;
+  interim linejoin := linejoin ;
+  interim miterlimit := miterlimit ;
+  save _background_ ; color _background_ ; _background_ :=  background  ;
+  save  background  ; color  background  ;  background  := _background_ ;
+  drawoptions () ;
+enddef ;
+
+def protectgraphicmacros =
+  save showtext ;
+  save beginfig ; let beginfig = begingraphictextfig ;
+  save endfig   ; let endfig   = endgraphictextfig ;
+  save end      ; let end      = relax ;
+  interim prologues := prologues ;
+  resetfig ; % resets currentpicture
+enddef ;
+
+numeric currentgraphictext ; currentgraphictext := 0 ;
+string  graphictextformat  ; graphictextformat  := "plain" ;
+string  graphictextstring  ; graphictextstring  := "" ;
+string  graphictextfile    ; graphictextfile    := "dummy.mpo" ;
+
+def data_mpo_file = job_name & "-mpgraph.mpo" enddef ;
+def data_mpy_file = job_name & "-mpgraph.mpy" enddef ;
+
+if unknown mplib :
+
+    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 ;" ;
+
+fi ;
+
+def begingraphictextfig (expr n) =
+  foundpicture := n ; scratchpicture := nullpicture ;
+enddef ;
+
+def endgraphictextfig =
+  if foundpicture = currentgraphictext :
+    expandafter endinput
+  else :
+    scratchpicture := nullpicture ;
+  fi ;
+enddef ;
+
+def loadfigure primary filename =
+  doloadfigure (filename)
+enddef ;
+
+def doloadfigure (expr filename) text figureattributes =
+  begingroup ;
+  save figurenumber, figurepicture, number, fixedplace ;
+  numeric figurenumber  ; figurenumber := 0 ;
+  boolean figureshift ; figureshift := true ;
+  picture figurepicture ; figurepicture := currentpicture ;
+  def number primary n = hide(figurenumber := n) enddef ;
+  def fixedplace = hide(figureshift := false) enddef ;
+  protectgraphicmacros ;
+  % defaults
+  interim linecap    := rounded ;
+  interim linejoin   := rounded ;
+  interim miterlimit := 10 ;
+  %
+  currentpicture := nullpicture ;
+  draw fullcircle figureattributes ; % expand number
+  currentpicture := nullpicture ;
+  def beginfig (expr n) =
+    currentpicture := nullpicture ;
+    if (figurenumber=n) or (figurenumber=0) :
+      let endfig = endinput ;
+    fi ;
+  enddef ;
+  let endfig = relax ;
+  readfile(filename) ;
+  if figureshift :
+    currentpicture := currentpicture shifted -llcorner currentpicture ;
+  fi ;
+  addto figurepicture also currentpicture figureattributes ;
+  currentpicture := figurepicture  ;
+  endgroup ;
+enddef ;
+
+def graphictext primary t =
+  dographictext(t)
+enddef ;
+
+def dographictext (expr t) =
+  begingroup ;
+  save figurepicture ; picture figurepicture ;
+  figurepicture := currentpicture ; currentpicture := nullpicture ;
+  if graphictextformat<>"" :
+    graphictextstring :=
+      "% format=" & graphictextformat & CRLF & graphictextstring ;
+    graphictextformat := "" ;
+  fi ;
+  currentgraphictext := currentgraphictext + 1 ;
+  if unknown mplib :
+    savegraphictext ("\startTEXpage[scale=10000]" & t & "\stopTEXpage") ;
+  fi ;
+  dofinishgraphictext
+enddef ;
+
+def redographictext primary t =
+  regraphictext(t)
+enddef ;
+
+def regraphictext (expr t) =
+  begingroup ;
+  save figurepicture ; picture figurepicture ;
+  figurepicture := currentpicture ; currentpicture := nullpicture ;
+  save currentgraphictext ; numeric currentgraphictext ;
+  currentgraphictext := t ;
+  dofinishgraphictext
+enddef ;
+
+%D Believe it or not, but it took me half a day to uncover
+%D the following neccessity:
+%D
+%D \starttypen
+%D save withfillcolor, withdrawcolor ;
+%D \stoptypen
+%D
+%D When we have more than one graphictext, these will be
+%D defined after the first graphic. For some obscure reason,
+%D this means that in the next graphic they will be called, but
+%D afterwards the data and boolean are not set. Don't ask me
+%D why.
+
+def dofinishgraphictext text x_op_x =
+  protectgraphicmacros ; % resets currentpicture
+  interim linecap    := butt ;     % normally rounded
+  interim linejoin   := mitered ;  % normally rounded
+  interim miterlimit := 10 ;       % todo
+  let normalwithshade = withshade ;
+  save foundpicture, scratchpicture, str ;
+  save fill, draw, withshade, reversefill, outlinefill ;
+  save withfillcolor, withdrawcolor ; % quite important
+  numeric foundpicture ; picture scratchpicture ; string str ;
+  def draw expr p =
+    % the first, naive implementation was:
+    %   addto scratchpicture doublepath p withpen currentpen ;
+    % but it is better to turn lines into fills
+    addto scratchpicture contour boundingbox
+      image (addto currentpicture doublepath p withpen currentpen) ;
+  enddef ;
+  def fill expr p =
+    addto scratchpicture contour p withpen currentpen ;
+  enddef ;
+  def f_op_f = enddef ; boolean f_color ; f_color := false ;
+  def d_op_d = enddef ; boolean d_color ; d_color := false ;
+  def s_op_s = enddef ; boolean s_color ; s_color := false ;
+  boolean reverse_fill ; reverse_fill := false ;
+  boolean outline_fill ; outline_fill := false ;
+  def reversefill =
+    hide(reverse_fill := true )
+  enddef ;
+  def outlinefill =
+    hide(outline_fill := true )
+  enddef ;
+  def withshade primary c =
+    hide(def s_op_s = normalwithshade c enddef ; s_color := true )
+  enddef ;
+  def withfillcolor primary c =
+    hide(def f_op_f = withcolor c enddef ; f_color := true )
+  enddef ;
+  def withdrawcolor primary c =
+    hide(def d_op_d = withcolor c enddef ; d_color := true )
+  enddef ;
+  scratchpicture := nullpicture ;
+  addto scratchpicture doublepath origin x_op_x ; % pre-roll
+  for i within scratchpicture : % Below here is a dirty tricky test!
+    if (urcorner dashpart i) = origin : outline_fill := false ; fi ;
+  endfor ;
+  scratchpicture := nullpicture ;
+  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 ;
+  currentpicture := figurepicture ;
+  if d_color and not reverse_fill :
+    for i within scratchpicture :
+      if f_color and outline_fill :
+        addto currentpicture doublepath pathpart i _op_ x_op_x f_op_f
+          dashed nullpicture ;
+      fi ;
+      if filled i :
+        addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+      fi ;
+    endfor ;
+  fi ;
+  if f_color :
+    for i within scratchpicture :
+      if filled i :
+        addto currentpicture contour pathpart i _op_ x_op_x f_op_f
+          withpen pencircle scaled 0 ;
+      fi ;
+    endfor ;
+  fi ;
+  if d_color and reverse_fill :
+    for i within scratchpicture :
+      if filled i :
+        addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+      fi ;
+    endfor ;
+  fi ;
+  if s_color :
+    for i within scratchpicture :
+      if filled i :
+        addto currentpicture contour pathpart i _op_ x_op_x s_op_s ;
+      fi ;
+    endfor ;
+  else :
+    for i within scratchpicture :
+      if stroked i :
+        addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+      fi ;
+    endfor ;
+  fi ;
+  endgroup ;
+enddef ;
+
+def resetgraphictextdirective =
+  graphictextstring := "" ;
+enddef ;
+
+def graphictextdirective text t =
+  graphictextstring := graphictextstring & t & CRLF ;
+enddef ;
+
+% example
+%
+% % graphictextformat := "context" ;
+% % graphictextformat := "plain" ;
+%
+% beginfig (1) ;
+%   graphictext
+%     "\vbox{\hsize10cm \input tufte }"
+%     scaled 8
+%     withdrawcolor blue
+%     withfillcolor red
+%     withpen pencircle scaled 2pt ;
+% endfig ;
+%
+% beginfig(1) ;
+%   loadfigure "gracht.mp" rotated 20 ;
+%   loadfigure "koe.mp" number 1 scaled 2 ;
+% endfig ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-page.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-page.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-page.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,659 @@
+%D \module
+%D   [       file=mp-page.mpii,
+%D        version=1999.03.10,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=page enhancements,
+%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.
+
+%D This module is rather preliminary and subjected to
+%D changes.
+
+if known context_page : endinput ; fi ;
+
+boolean context_page ; context_page := true ;
+
+if unknown PageStateAvailable :
+  boolean PageStateAvailable ; PageStateAvailable := false ;
+fi ;
+
+if unknown OnRightPage :
+  boolean OnRightPage ; OnRightPage := true ;
+fi ;
+
+if unknown OnOddPage :
+  boolean OnOddPage ; OnOddPage := true ;
+fi ;
+
+if unknown InPageBody :
+  boolean InPageBody ; InPageBody := false ;
+fi ;
+
+def SaveTextAreas =
+  path    SavedTextAreas  []  ;
+  path    SavedTextColumns[]  ;
+  numeric NOfSavedTextAreas   ;
+  numeric NOfSavedTextColumns ;
+  for i=1 upto NOfTextAreas :
+    SavedTextAreas[i] := TextAreas[i] ;
+  endfor ;
+  for i=1 upto NOfTextColumns :
+    SavedTextColumns[i] := TextColumns[i] ;
+  endfor ;
+  NOfSavedTextAreas   := NOfTextAreas ;
+  NOfSavedTextColumns := NOfTextColumns ;
+enddef ;
+
+def ResetTextAreas =
+  path TextAreas[], TextColumns[] ;
+  numeric NOfTextAreas   ; NOfTextAreas   := 0 ;
+  numeric NOfTextColumns ; NOfTextColumns := 0 ;
+  numeric nofmultipars   ; nofmultipars   := 0 ;
+  TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetTextAreas ; SaveTextAreas ; ;
+
+def RegisterTextArea (expr x, y, w, h, d) =
+  begingroup ; save p ; path p ;
+    p := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+    if NOfTextAreas>0 :
+      % if needed, concatenate areas
+      if (round(llcorner TextAreas[NOfTextAreas]) = round(ulcorner p)) and
+         (round(lrcorner TextAreas[NOfTextAreas]) = round(urcorner p)) :
+        p := ulcorner TextAreas[NOfTextAreas] --
+             urcorner TextAreas[NOfTextAreas] --
+             lrcorner p --
+             llcorner p --
+             cycle ;
+      else :
+        NOfTextAreas := NOfTextAreas + 1 ;
+      fi ;
+    else :
+      NOfTextAreas := NOfTextAreas + 1 ;
+    fi ;
+    TextAreas[NOfTextAreas] := p ;
+    if NOfTextColumns>0 :
+      if (round(xpart llcorner TextColumns[NOfTextColumns]) = round(xpart ulcorner p)) and
+         (round(xpart lrcorner TextColumns[NOfTextColumns]) = round(xpart urcorner p)) :
+        p := ulcorner TextColumns[NOfTextColumns] --
+             urcorner TextColumns[NOfTextColumns] --
+             lrcorner p --
+             llcorner p --
+             cycle ;
+      else :
+        NOfTextColumns := NOfTextColumns + 1 ;
+      fi ;
+    else :
+      NOfTextColumns := NOfTextColumns + 1 ;
+    fi ;
+    TextColumns[NOfTextColumns] := p ;
+  endgroup ;
+enddef ;
+
+%D We store a local area in slot zero.
+
+def RegisterLocalTextArea (expr x, y, w, h, d) =
+  TextAreas[0] := TextColumns[0] := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+enddef ;
+
+def ResetLocalTextArea =
+  TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetLocalTextArea ;
+
+vardef InsideTextArea (expr _i_, _xy_) =
+  ( (round(xpart _xy_) >= round(xpart llcorner TextAreas[_i_])) and
+    (round(xpart _xy_) <= round(xpart lrcorner TextAreas[_i_])) and
+    (round(ypart _xy_) >= round(ypart llcorner TextAreas[_i_])) and
+    (round(ypart _xy_) <= round(ypart urcorner TextAreas[_i_])) )
+enddef ;
+
+vardef InsideSavedTextArea (expr _i_, _xy_) =
+  ( (round(xpart _xy_) >= round(xpart llcorner SavedTextAreas[_i_])) and
+    (round(xpart _xy_) <= round(xpart lrcorner SavedTextAreas[_i_])) and
+    (round(ypart _xy_) >= round(ypart llcorner SavedTextAreas[_i_])) and
+    (round(ypart _xy_) <= round(ypart urcorner SavedTextAreas[_i_])) )
+enddef ;
+
+vardef InsideSomeTextArea (expr _xy_) =
+  save ok ; boolean ok ; ok := false ;
+  for i := 1 upto NOfTextAreas :
+    if InsideTextArea(i,_xy_) : ok := true ; fi ;
+    exitif ok ;
+  endfor ;
+  ok
+enddef ;
+
+vardef InsideSomeSavedTextArea (expr _xy_) =
+  save ok ; boolean ok ; ok := false ;
+  for i := 1 upto NOfSavedTextAreas :
+    if InsideSavedTextArea(i,_xy_) : ok := true ; fi ;
+    exitif ok ;
+  endfor ;
+  ok
+enddef ;
+
+vardef TextAreaX (expr x) =
+  numeric _TextAreaX_ ; _TextAreaX_ := 0 ;
+  for i := 1 upto NOfTextAreas :
+    if (round(x) >= round(xpart llcorner TextAreas[i])) and
+       (round(x) <= round(xpart lrcorner TextAreas[i])) :
+      _TextAreaX_ := xpart llcorner TextAreas[i] ;
+    fi ;
+  endfor ;
+  _TextAreaX_
+enddef ;
+
+vardef TextAreaY (expr y) =
+  numeric _TextAreaY_ ; _TextAreaY_ := 0 ;
+  for i := 1 upto NOfTextAreas :
+    if (round(y) >= round(ypart llcorner TextAreas[NOfTextAreas])) and
+       (round(y) <= round(ypart ulcorner TextAreas[NOfTextAreas])) :
+      _TextAreaY_ := ypart llcorner TextAreas[NOfTextAreas] ;
+    fi ;
+  endfor ;
+  _TextAreaY_
+enddef ;
+
+vardef TextAreaXY (expr x, y) =
+  pair _TextAreaXY_ ; _TextAreaXY_ := origin ;
+  for i := 1 upto NOfTextAreas :
+    if (round(x) >= round(xpart llcorner TextAreas[i])) and
+       (round(x) <= round(xpart lrcorner TextAreas[i])) and
+       (round(y) >= round(ypart llcorner TextAreas[i])) and
+       (round(y) <= round(ypart ulcorner TextAreas[i])) :
+      _TextAreaXY_ := llconer TextAreas[i] ;
+    fi ;
+  endfor ;
+  _TextAreaXY_
+enddef ;
+
+vardef TextAreaW (expr x) =
+  numeric _TextAreaW_ ; _TextAreaW_ := 0 ;
+  for i := 1 upto NOfTextAreas :
+    if (round(x) >= round(xpart llcorner TextAreas[i])) and
+       (round(x) <= round(xpart lrcorner TextAreas[i])) :
+      _TextAreaW_ := bbwidth(TextAreas[i]) ;
+    fi ;
+  endfor ;
+  _TextAreaW_
+enddef ;
+
+vardef TextAreaH (expr y) =
+  numeric _TextAreaH_ ; _TextAreaH_ := 0 ;
+  for i := 1 upto NOfTextAreas :
+    if (round(y) >= round(ypart llcorner TextAreas[i])) and
+       (round(y) <= round(ypart ulcorner TextAreas[i])) :
+      _TextAreaH_ := bbheight(TextAreas[i]) ;
+    fi ;
+  endfor ;
+  _TextAreaH_
+enddef ;
+
+vardef TextAreaWH (expr x, y) =
+  pair _TextAreaWH_ ; _TextAreaWH_ := origin ;
+  for i := 1 upto NOfTextAreas :
+    if (round(x) >= round(xpart llcorner TextAreas[i])) and
+       (round(x) <= round(xpart lrcorner TextAreas[i])) and
+       (round(y) >= round(ypart llcorner TextAreas[i])) and
+       (round(y) <= round(ypart ulcorner TextAreas[i])) :
+      _TextAreaWH_ := (bbwidth(TextAreas[i]),bbheight(TextAreas[i])) ;
+    fi ;
+  endfor ;
+  _TextAreaWH_
+enddef ;
+
+string CurrentLayout ;
+
+CurrentLayout       := "default" ;
+
+PageNumber          := 0 ;
+PaperHeight         := 845.04684pt  ;
+PaperWidth          := 597.50787pt  ;
+PrintPaperHeight    := 845.04684pt  ;
+PrintPaperWidth     := 597.50787pt  ;
+TopSpace            :=  71.12546pt  ;
+BottomSpace         :=   0.0pt      ;
+BackSpace           :=  71.13275pt  ;
+CutSpace            :=   0.0pt      ;
+MakeupHeight        := 711.3191pt   ;
+MakeupWidth         := 426.78743pt  ;
+TopHeight           :=   0.0pt      ;
+TopDistance         :=   0.0pt      ;
+HeaderHeight        :=  56.90294pt  ;
+HeaderDistance      :=   0.0pt      ;
+TextHeight          := 597.51323pt  ;
+FooterDistance      :=   0.0pt      ;
+FooterHeight        :=  56.90294pt  ;
+BottomDistance      :=   0.0pt      ;
+BottomHeight        :=   0.0pt      ;
+LeftEdgeWidth       :=   0.0pt      ;
+LeftEdgeDistance    :=   0.0pt      ;
+LeftMarginWidth     :=   75.58197pt ;
+LeftMarginDistance  :=   11.99829pt ;
+TextWidth           :=  426.78743pt ;
+RightMarginDistance :=   11.99829pt ;
+RightMarginWidth    :=   75.58197pt ;
+RightEdgeDistance   :=    0.0pt     ;
+RightEdgeWidth      :=    0.0pt     ;
+
+PageOffset          :=    0.0pt     ;
+PageDepth           :=    0.0pt     ;
+
+LayoutColumns       :=    0         ;
+LayoutColumnDistance:=    0.0pt     ;
+LayoutColumnWidth   :=    0.0pt     ;
+
+LeftEdge             :=  -4 ; Top             := -40 ;
+LeftEdgeSeparator    :=  -3 ; TopSeparator    := -30 ;
+LeftMargin           :=  -2 ; Header          := -20 ;
+LeftMarginSeparator  :=  -1 ; HeaderSeparator := -10 ;
+Text                 :=   0 ; Text            :=   0 ;
+RightMarginSeparator :=  +1 ; FooterSeparator := +10 ;
+RightMargin          :=  +2 ; Footer          := +20 ;
+RightEdgeSeparator   :=  +3 ; BottomSeparator := +30 ;
+RightEdge            :=  +4 ; Bottom          := +40 ;
+
+Margin      := LeftMargin  ; % obsolete
+Edge        := LeftEdge    ; % obsolete
+InnerMargin := RightMargin ; % obsolete
+InnerEdge   := RightEdge   ; % obsolete
+OuterMargin := LeftMargin  ; % obsolete
+OuterEdge   := LeftEdge    ; % obsolete
+
+InnerMarginWidth     := 0pt ;
+OuterMarginWidth     := 0pt ;
+InnerMarginDistance  := 0pt ;
+OuterMarginDistance  := 0pt ;
+
+InnerEdgeWidth     := 0pt ;
+OuterEdgeWidth     := 0pt ;
+InnerEdgeDistance  := 0pt ;
+OuterEdgeDistance  := 0pt ;
+
+path Area [][] ; pair Location [][] ; path Field [][] ;  path Page ;
+numeric HorPos ; numeric Hstep [] ; numeric Hsize [] ;
+numeric VerPos ; numeric Vstep [] ; numeric Vsize [] ;
+
+for VerPos=Top step 10 until Bottom:
+  for HorPos=LeftEdge step 1 until RightEdge:
+    Area[HorPos][VerPos] := origin--cycle ;
+    Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+    Location[HorPos][VerPos] := origin ;
+    Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+    Field[HorPos][VerPos] := origin--cycle ;
+    Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+  endfor ;
+endfor ;
+
+% def LoadPageState =
+%   scantokens "input mp-state.tmp" ;
+% enddef ;
+
+def SwapPageState =
+  if not OnRightPage :
+           BackSpace := PaperWidth-MakeupWidth-BackSpace ;
+            CutSpace := PaperWidth-MakeupWidth-CutSpace ;
+                   i := LeftMarginWidth ;
+     LeftMarginWidth := RightMarginWidth ;
+    RightMarginWidth := i ;
+                   i := LeftMarginDistance ;
+  LeftMarginDistance := RightMarginDistance ;
+ RightMarginDistance := i ;
+                   i := LeftEdgeWidth ;
+       LeftEdgeWidth := RightEdgeWidth ;
+      RightEdgeWidth := i ;
+                   i := LeftEdgeDistance ;
+    LeftEdgeDistance := RightEdgeDistance ;
+   RightEdgeDistance := i ;
+
+% these are now available as ..Width and ..Distance
+
+              Margin := LeftMargin ;
+                Edge := LeftEdge ;
+         InnerMargin := RightMargin ;
+           InnerEdge := RightEdge ;
+         OuterMargin := LeftMargin ;
+           OuterEdge := LeftEdge ;
+  else :
+              Margin := RightMargin ;
+                Edge := RightEdge ;
+         InnerMargin := LeftMargin ;
+           InnerEdge := LeftEdge ;
+         OuterMargin := RightMargin ;
+           OuterEdge := RightEdge ;
+  fi ;
+enddef ;
+
+def SetPageAreas =
+
+  numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
+
+  Vsize[Top]             = TopHeight ;
+  Vsize[TopSeparator]    = TopDistance ;
+  Vsize[Header]          = HeaderHeight ;
+  Vsize[HeaderSeparator] = HeaderDistance ;
+  Vsize[Text]            = TextHeight ;
+  Vsize[FooterSeparator] = FooterDistance ;
+  Vsize[Footer]          = FooterHeight ;
+  Vsize[BottomSeparator] = BottomDistance ;
+  Vsize[Bottom]          = BottomHeight ;
+
+  Vstep[Top]             = Vstep[TopSeparator]   +Vsize[TopSeparator] ;
+  Vstep[TopSeparator]    = PaperHeight-TopSpace ;
+  Vstep[Header]          = Vstep[TopSeparator]   -Vsize[Header] ;
+  Vstep[HeaderSeparator] = Vstep[Header]         -Vsize[HeaderSeparator] ;
+  Vstep[Text]            = Vstep[HeaderSeparator]-Vsize[Text] ;
+  Vstep[FooterSeparator] = Vstep[Text]           -Vsize[FooterSeparator] ;
+  Vstep[Footer]          = Vstep[FooterSeparator]-Vsize[Footer] ;
+  Vstep[BottomSeparator] = Vstep[Footer]         -Vsize[BottomSeparator] ;
+  Vstep[Bottom]          = Vstep[BottomSeparator]-Vsize[Bottom] ;
+
+  Hsize[LeftEdge]             = LeftEdgeWidth ;
+  Hsize[LeftEdgeSeparator]    = LeftEdgeDistance ;
+  Hsize[LeftMargin]           = LeftMarginWidth ;
+  Hsize[LeftMarginSeparator]  = LeftMarginDistance ;
+  Hsize[Text]                 = MakeupWidth ;
+  Hsize[RightMarginSeparator] = RightMarginDistance ;
+  Hsize[RightMargin]          = RightMarginWidth ;
+  Hsize[RightEdgeSeparator]   = RightEdgeDistance ;
+  Hsize[RightEdge]            = RightEdgeWidth ;
+
+  Hstep[LeftEdge]             = Hstep[LeftEdgeSeparator]   -Hsize[LeftEdge] ;
+  Hstep[LeftEdgeSeparator]    = Hstep[LeftMargin]          -Hsize[LeftEdgeSeparator] ;
+  Hstep[LeftMargin]           = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
+  Hstep[LeftMarginSeparator]  = Hstep[Text]                -Hsize[LeftMarginSeparator] ;
+  Hstep[Text]                 = BackSpace ;
+  Hstep[RightMarginSeparator] = Hstep[Text]                +Hsize[Text] ;
+  Hstep[RightMargin]          = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
+  Hstep[RightEdgeSeparator]   = Hstep[RightMargin]         +Hsize[RightMargin] ;
+  Hstep[RightEdge]            = Hstep[RightEdgeSeparator]  +Hsize[RightEdgeSeparator] ;
+
+  for VerPos=Top step 10 until Bottom:
+    for HorPos=LeftEdge step 1 until RightEdge:
+      Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
+      Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+      Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
+      Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+      Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
+      Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+    endfor ;
+  endfor ;
+
+  Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+
+enddef ;
+
+def BoundPageAreas =
+
+ % pickup pencircle scaled 0pt ;
+
+  bboxmargin := 0 ; setbounds currentpicture to Page ;
+
+enddef ;
+
+def StartPage =
+
+  begingroup ;
+
+  if PageStateAvailable :
+    LoadPageState ;
+    SwapPageState ;
+  fi ;
+
+  SetPageAreas ;
+  BoundPageAreas ;
+
+enddef ;
+
+def StopPage =
+
+  BoundPageAreas ;
+
+  endgroup ;
+
+enddef ;
+
+def OverlayBox =
+  (unitsquare xyscaled (OverlayWidth,OverlayHeight))
+enddef ;
+
+% handy
+
+def innerenlarged =
+  hide(LoadPageState)
+  if OnRightPage : leftenlarged  else : rightenlarged fi
+enddef ;
+
+def outerenlarged =
+  hide(LoadPageState)
+  if OnRightPage : rightenlarged else : leftenlarged  fi
+enddef ;
+
+% obsolete
+
+def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ;
+def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ;
+def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ;
+def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ;
+
+def Enlarged (expr p, d) =
+  (llEnlarged (p,d) --
+   lrEnlarged (p,d) --
+   urEnlarged (p,d) --
+   ulEnlarged (p,d) -- cycle)
+enddef ;
+
+% New:
+
+def position_anchor_bar(expr p_b_self, p_e_self, y_b_self, y_e_self, h_b_self, d_e_self,
+        distance, linewidth, linecolor) =
+    StartPage ;
+      path p ; p :=
+      if p_b_self=p_e_self :
+        (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) --
+        (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ;
+      elseif RealPageNumber=p_b_self :
+        (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) --
+        (llcorner Field[Text][Text]) ;
+      elseif RealPageNumber=p_e_self :
+        (ulcorner Field[Text][Text]) --
+        (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ;
+      else :
+        (ulcorner Field[Text][Text]) --
+        (llcorner Field[Text][Text]) ;
+      fi ;
+      p := p shifted (-llcorner Field[Text][Text]-(distance,0)) ;
+      interim linecap := butt ;
+      draw p
+        withpen pencircle scaled linewidth
+        withcolor linecolor ;
+    StopPage ;
+enddef ;
+
+% Crop stuff
+
+vardef crop_marks_lines (expr box, length, offset, nx, ny) =
+    save p ; picture p ; save w, h, x, y ; numeric w, h, x, y  ;
+    p := image (
+        x := if nx = 0 : 1 else : nx - 1 fi ;
+        y := if ny = 0 : 1 else : ny - 1 fi ;
+        w := bbwidth (box) / x ;
+        h := bbheight(box) / y ;
+        for i=0 upto y :
+            draw ((llcorner box) -- (llcorner box) shifted (-length,0)) shifted (-offset,i*h) ;
+            draw ((lrcorner box) -- (lrcorner box) shifted ( length,0)) shifted ( offset,i*h) ;
+        endfor ;
+        for i=0 upto x :
+            draw ((llcorner box) -- (llcorner box) shifted (0,-length)) shifted (i*w,-offset) ;
+            draw ((ulcorner box) -- (ulcorner box) shifted (0, length)) shifted (i*w, offset) ;
+        endfor ;
+    ) ;
+    setbounds p to box ;
+    p
+enddef ;
+
+vardef crop_marks_cmyk =
+    save p ; picture p ; p := image (
+        fill ulcircle   scaled 12.5 withcolor (1,0,0,0) ;
+        fill urcircle   scaled 12.5 withcolor (0,1,0,0) ;
+        fill lrcircle   scaled 12.5 withcolor (0,0,1,0) ;
+        fill llcircle   scaled 12.5 withcolor (0,0,0,1) ;
+        draw (-10,0) -- (10,0) ;
+        draw (0,-10) -- (0,10) ;
+        draw fullcircle scaled 12.5 ;
+    ) ;
+    setbounds p to fullsquare scaled 20 ;
+    p
+enddef ;
+
+vardef crop_marks_gray =
+    save p ; picture p ; p := image (
+        fill ulcircle   scaled 12.5 withcolor (0.00) ;
+        fill urcircle   scaled 12.5 withcolor (0.25) ;
+        fill lrcircle   scaled 12.5 withcolor (0.50) ;
+        fill llcircle   scaled 12.5 withcolor (0.75) ;
+        draw (-10,0) -- (10,0) ;
+        draw (0,-10) -- (0,10) ;
+        draw (-6,0) -- (6,0) withcolor white ;
+        draw (0,-6) -- (0,6) withcolor white  ;
+        draw fullcircle scaled 12.5 ;
+    ) ;
+    setbounds p to fullsquare scaled 20 ;
+    p
+enddef ;
+
+vardef crop_marks_cmykrgb =
+    save p ; picture p ; p := image (
+        fill ulcircle   scaled 15 withcolor (1,0,0) ;
+        fill urcircle   scaled 15 withcolor (0,1,0) ;
+        fill lrcircle   scaled 15 withcolor (0,0,1) ;
+        fill llcircle   scaled 15 withcolor (.5,.5,.5) ;
+        fill ulcircle   scaled 10 withcolor (1,0,0,0) ;
+        fill urcircle   scaled 10 withcolor (0,1,0,0) ;
+        fill lrcircle   scaled 10 withcolor (0,0,1,0) ;
+        fill llcircle   scaled 10 withcolor (0,0,0,1) ;
+        draw (-10,0) -- (10,0) ;
+        draw (0,-10) -- (0,10) ;
+        draw fullcircle scaled 10 ;
+        draw fullcircle scaled 15 ;
+    ) ;
+    setbounds p to fullsquare scaled 20 ;
+    p
+enddef ;
+
+vardef crop_color(expr c, h, w, dx, dy, ts) =
+    image (
+        save p ; path p ;
+        for i=1 upto 6 :
+            p := fullsquare
+                xscaled w
+                yscaled h
+                shifted (dx,dy-i*h) ;
+            fill p
+                withcolor (crop_colors[i]*c) ;
+            draw textext("\format{'@0.2f'," & decimal crop_colors[i] & "}")
+                scaled ts
+                shifted center p withcolor white ;
+        endfor ;
+    )
+enddef ;
+
+vardef crop_gray(expr c, h, w, dx, dy, ts) =
+    image (
+        save p ; path p ;
+        for i=.05 step .05 until 1 :
+                p := fullsquare
+                xscaled w
+                yscaled h
+                shifted (20*(i-1)*w+dx,dy) ;
+            fill p
+                withcolor (i*c) ;
+            draw textext("\format{'@0.2f'," & decimal i & "}")
+                scaled ts
+                shifted center p withcolor white ;
+        endfor ;
+    )
+enddef ;
+
+% draw crop_marks_cmyk shifted llcorner more ;
+% draw crop_marks_cmyk shifted lrcorner more ;
+% draw crop_marks_cmyk shifted ulcorner more ;
+% draw crop_marks_cmyk shifted urcorner more ;
+
+def page_marks_add_color(expr width, height, length, offset) = % todo: namespace
+
+    path page ; page := fullsquare xscaled width yscaled height ;
+    path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+    numeric crop_colors[] ;
+    crop_colors[1] := 1 ;
+    crop_colors[2] := 0.95 ;
+    crop_colors[3] := 0.75 ;
+    crop_colors[4] := 0.50 ;
+    crop_colors[5] := 0.25 ;
+    crop_colors[6] := 0.05 ;
+
+    numeric h ; h := height / 20 ;
+    numeric w ; w := width  / 20 ;
+    numeric d ; d := offset + length/2 ;
+
+    draw crop_color((1,0,0,0),h,length,xpart ulcorner page - d, 10h,length/20) ;
+    draw crop_color((0,1,0,0),h,length,xpart ulcorner page - d,3.5h,length/20) ;
+    draw crop_color((0,0,1,0),h,length,xpart ulcorner page - d, -3h,length/20) ;
+
+    draw crop_color((0,1,1,0),h,length,xpart urcorner page + d, 10h,length/20) ;
+    draw crop_color((1,0,1,0),h,length,xpart urcorner page + d,3.5h,length/20) ;
+    draw crop_color((1,1,0,0),h,length,xpart urcorner page + d, -3h,length/20) ;
+
+    draw crop_gray((0,0,0,1),length,  w,-xpart llcorner page,-ypart llcorner page + d            ,w/20) ;
+    draw crop_gray((1,0,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d + 1length/3,w/20) ;
+    draw crop_gray((0,1,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 0length/3,w/20) ;
+    draw crop_gray((0,0,1,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 1length/3,w/20) ;
+
+    setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_marking(expr width, height, length, offset) = % todo: namespace
+
+    path page ; page := fullsquare xscaled width yscaled height ;
+    path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+    draw crop_marks_gray shifted center(topboundary    more) shifted (0, offset+length);
+    draw crop_marks_cmyk shifted center(bottomboundary more) shifted (0,-offset-length);
+
+    setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_lines(expr width, height, length, offset, nx, ny) = % todo: namespace
+
+    path page ; page := fullsquare xscaled width yscaled height ;
+    path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+    draw crop_marks_lines(page,length,offset,nx,ny) ;
+
+    setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_number(expr width, height, length, offset, n) = % todo: namespace
+
+    path page ; page := fullsquare xscaled width yscaled height ;
+    path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+    for s=llcorner more, lrcorner more, ulcorner more, urcorner more :
+        draw textext(decimal n) shifted s ;
+    endfor ;
+
+    setbounds currentpicture to page ;
+
+enddef ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-shap.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-shap.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-shap.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,206 @@
+%D \module
+%D   [       file=mp-shap.mpii,
+%D        version=2000.05.31,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=shapes,
+%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 licen-en.pdf for
+%C details.
+
+if known context_shap : endinput ; fi ;
+
+boolean context_shap ; context_shap := true ;
+
+path predefined_shapes[] ;
+
+begingroup ;
+
+save xradius, yradius, xxradius, yyradius ;
+save ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+numeric xradius, yradius, xxradius, yyradius ;
+pair ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+xradius  := .15 ;
+yradius  := .15 ;
+xxradius := .10 ;
+yyradius := .10 ;
+
+ll       := llcorner (unitsquare shifted (-.5,-.5)) ;
+lr       := lrcorner (unitsquare shifted (-.5,-.5)) ;
+ur       := urcorner (unitsquare shifted (-.5,-.5)) ;
+ul       := ulcorner (unitsquare shifted (-.5,-.5)) ;
+
+llx      := ll shifted (xradius,0)  ;
+lly      := ll shifted (0,yradius)  ;
+
+lrx      := lr shifted (-xradius,0) ;
+lry      := lr shifted (0,yradius)  ;
+
+urx      := ur shifted (-xradius,0) ;
+ury      := ur shifted (0,-yradius) ;
+
+ulx      := ul shifted (xradius,0)  ;
+uly      := ul shifted (0,-yradius) ;
+
+llxx     := ll shifted (xxradius,0)  ;
+llyy     := ll shifted (0,yyradius)  ;
+
+lrxx     := lr shifted (-xxradius,0) ;
+lryy     := lr shifted (0,yyradius)  ;
+
+urxx     := ur shifted (-xxradius,0) ;
+uryy     := ur shifted (0,-yyradius) ;
+
+ulxx     := ul shifted (xxradius,0)  ;
+ulyy     := ul shifted (0,-yyradius) ;
+
+lc       := ll shifted (0,.5) ;
+rc       := lr shifted (0,.5) ;
+tc       := ul shifted (.5,0) ;
+bc       := ll shifted (.5,0) ;
+
+predefined_shapes[ 0] := (origin--cycle) ;
+predefined_shapes[ 5] := (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ;
+predefined_shapes[ 6] := (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
+predefined_shapes[ 7] := (ll--lrx{right}...rc...{left}urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[ 8] := (lr--ury{up}...tc...{down}uly--ll--cycle) ;
+predefined_shapes[ 9] := (lr--ury{up}...tc...{down}uly--ll--cycle) rotatedaround(origin,180) ;
+predefined_shapes[10] := (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ;
+predefined_shapes[11] := (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ;
+predefined_shapes[12] := (ll--lrx--ur--ulx--cycle) ;
+predefined_shapes[13] := (llx--lr--urx--ul--cycle) ;
+predefined_shapes[14] := (lly--bc--lry--ury--tc--uly--cycle) ;
+predefined_shapes[15] := (llx--lrx--rc--urx--ulx--lc--cycle) ;
+predefined_shapes[16] := (ll--lrx--rc--urx--ul--cycle) ;
+predefined_shapes[17] := (ll--lrx--rc--urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[18] := (lr--ury--tc--uly--ll--cycle) ;
+predefined_shapes[19] := (lr--ury--tc--uly--ll--cycle) rotatedaround(origin,180) ;
+predefined_shapes[20] := (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--lr--ur--urxx--lrxx--cycle) ;
+predefined_shapes[21] := (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--ll--lr--lryy--llyy--cycle) ;
+predefined_shapes[22] := (ll--lrx--lry--ur--ulx--uly--cycle) ;
+predefined_shapes[23] := (llx--lr--ury--urx--ul--lly--cycle) ;
+predefined_shapes[24] := (ll--lr--ur--ul--cycle) ;
+predefined_shapes[25] := (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ;
+predefined_shapes[26] := (ll--lrx--lry--ur--ul--cycle) ;
+predefined_shapes[27] := (ll--lr--ury--urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[28] := (ll--lr--ury--urx--ul--cycle) ;
+predefined_shapes[29] := (ll--lrx--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[30] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) rotated 45;
+predefined_shapes[31] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
+predefined_shapes[32] := (ll{right}...{right}lry--ur--ul--ll--cycle) ;
+predefined_shapes[33] := (ll{right}...{right}lry--ur--ul--ll--cycle--ul--ulx--ulx shifted(0,yyradius)--ur shifted(yyradius,yyradius)--lry shifted(yyradius,yyradius)--lry shifted(0,yyradius)--ur--ul--cycle ) ;
+predefined_shapes[34] := (uly..tc..ury & ury..tc shifted (0,-2yradius)..uly & uly--lly & lly..bc..lry & lry--ury & ury..tc shifted (0,-2yradius)..uly & cycle ) ;
+predefined_shapes[35] := (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ;
+predefined_shapes[36] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) ;
+predefined_shapes[37] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) rotatedaround(origin,180) ;
+predefined_shapes[38] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) ;
+predefined_shapes[39] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) rotatedaround(origin,180) ;
+predefined_shapes[40] := (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ;
+predefined_shapes[41] := (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ;
+predefined_shapes[42] := (ll--lr--origin shifted (+epsilon,0)--ur--ul--origin shifted (-epsilon,0)--cycle) ;
+predefined_shapes[43] := (ll--ul--origin shifted (0,+epsilon)--ur--lr--origin shifted (0,-epsilon)--cycle) ;
+predefined_shapes[45] := (bc--rc--tc--lc--cycle) ;
+predefined_shapes[46] := (ll--ul--rc--cycle) ;
+predefined_shapes[47] := (ll--ul--rc--cycle) rotatedaround(origin,180) ;
+predefined_shapes[48] := (ul--ur--bc--cycle) rotatedaround(origin,180) ;
+predefined_shapes[49] := (ul--ur--bc--cycle) ;
+predefined_shapes[56] := (ll--lry--ury--ul--cycle) ;
+predefined_shapes[57] := (ll--lry--ury--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[58] := (ll--ulx--urx--lr--cycle) ;
+predefined_shapes[59] := (ll--ulx--urx--lr--cycle) rotatedaround(origin,180);
+predefined_shapes[66] := (rc--origin shifted ( epsilon,0) --cycle & rc--origin--cycle ) ;
+predefined_shapes[67] := (lc--origin shifted (-epsilon,0) --cycle & lc--origin--cycle ) ;
+predefined_shapes[68] := (tc--origin shifted (0, epsilon) --cycle & tc--origin--cycle ) ;
+predefined_shapes[69] := (bc--origin shifted (0,-epsilon) --cycle & bc--origin--cycle ) ;
+predefined_shapes[75] := (lly--lry--ury--uly--cycle) rotatedaround(origin,180) ;
+predefined_shapes[76] := (ll--lr--ur--uly--cycle) rotatedaround(origin,180) ;
+predefined_shapes[77] := (ll--lr--ury--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[78] := (lly--lr--ur--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[79] := (ll--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+
+numeric predefined_shapes_xradius  ; predefined_shapes_xradius  := xradius  ;
+numeric predefined_shapes_yradius  ; predefined_shapes_yradius  := yradius  ;
+numeric predefined_shapes_xxradius ; predefined_shapes_xxradius := xxradius ;
+numeric predefined_shapes_yyradius ; predefined_shapes_yyradius := yyradius ;
+
+endgroup ;
+
+vardef some_shape_path (expr type) =
+    if known predefined_shapes[type] : predefined_shapes[type] else : predefined_shapes[0] fi
+enddef ;
+
+def some_shape (expr shape_type, shape_width, shape_height, shape_linewidth, shape_linecolor, shape_fillcolor) =
+    begingroup ;
+        save p ; path p ;
+        p := some_shape_path (shape_type) xscaled shape_width yscaled shape_height ;
+        pickup pencircle scaled shape_linewidth ;
+        fill p withcolor shape_fillcolor ;
+        draw p withcolor shape_linecolor ;
+    endgroup ;
+enddef ;
+
+vardef drawpredefinedshape (expr t, p, lw, lc, fc) =
+    save pp ;
+    if t>1 : % normal shape
+        path pp ;
+        pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+        fill pp withcolor fc ;
+        draw pp withpen pencircle scaled lw withcolor lc ;
+    elseif t=1 : % background only
+        path pp ;
+        pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+        fill pp withcolor fc ;
+    else : % dimensions only
+        picture pp ; pp := nullpicture ;
+        setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+        draw pp ;
+    fi ;
+enddef ;
+
+vardef drawpredefinedline (expr t, p, lw, lc) =
+    if (t>0) and (length(p)>1) :
+        saveoptions ;
+        drawoptions(withpen pencircle scaled lw withcolor lc) ;
+        draw p ;
+        if     t =  1 :
+            draw arrowheadonpath(p,1) ;
+        elseif t =  2 :
+            draw arrowheadonpath(reverse p,1) ;
+        elseif t =  3 :
+            for $ = p,reverse p :
+                draw arrowheadonpath($,1) ;
+            endfor ;
+        elseif t = 11 :
+            draw arrowheadonpath(p,1/2) ;
+        elseif t = 12 :
+            draw arrowheadonpath(reverse p,1/2) ;
+        elseif t = 13 :
+            for $=p,reverse p :
+                draw arrowheadonpath($,1) ;
+            endfor ;
+            for $=p,reverse p :
+                draw arrowheadonpath($,3/4) ;
+            endfor ;
+        elseif t = 21 :
+            for $=1/5,1/2,4/5 :
+                draw arrowheadonpath(p,$) ;
+            endfor ;
+        elseif t = 22 :
+            for $=1/5,1/2,4/5 :
+                draw arrowheadonpath(reverse p,$) ;
+            endfor ;
+        elseif t = 23 :
+            for $=p,reverse p :
+                draw arrowheadonpath($,1/4) ;
+            endfor ;
+        fi ;
+    fi ;
+enddef ;
+
+let drawshape = drawpredefinedshape ;
+let drawline  = drawpredefinedline  ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-spec.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-spec.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-spec.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,782 @@
+%D \module
+%D   [       file=mp-spec.mpii,
+%D        version=1999.6.26,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=special extensions,
+%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 licen-en.pdf for
+%C details.
+
+% Spot colors are not handled by mptopdf !
+
+% let graycolor    = numeric ;
+% let greycolor    = numeric ;
+% let withanycolor = withcolor ;
+
+% rgbcolor  red     ; red        := (1,0,0) ;
+% rgbcolor  green   ; green      := (0,1,0) ;
+% rgbcolor  blue    ; blue       := (0,0,1) ;
+% cmykcolor cyan    ; cyan       := (1,0,0,0) ;
+% cmykcolor magenta ; magenta    := (0,1,0,0) ;
+% cmykcolor yellow  ; yellow     := (0,0,1,0) ;
+% graycolor black   ; black      := 0 ; % (0) ;
+% graycolor white   ; white      := 1 ; % (1) ;
+
+% primarydef p withcolor c =
+%     p withanycolor (c)
+% enddef ;
+
+% fill fullcircle scaled 10cm withcolor  cyan ;
+% fill fullcircle scaled  7cm withcolor   red ;
+% fill fullcircle scaled  4cm withcolor white ;
+
+% (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
+
+%D This module is rather preliminary and subjected to
+%D changes. Here we closely cooperates with the \METAPOST\
+%D to \PDF\ converter module built in \CONTEXT\ and provides
+%D for instance shading. More information can be found in
+%D type {supp-mpe.tex}.
+
+if known context_spec : endinput ; fi ;
+
+boolean context_spec ; context_spec := true ;
+
+numeric _special_counter_ ; _special_counter_ :=   0 ;
+numeric _color_counter_   ; _color_counter_   :=  11 ; % < 10 reserved
+numeric _special_signal_  ; _special_signal_  := 123 ;
+
+numeric _special_div_ ; _special_div_ := 1000 ;
+
+%D When set to \type {true}, shading will be supported. Some
+%D day I will also write an additional directive.
+
+boolean _inline_specials_ ; _inline_specials_ := false ;
+
+%D Because we want to output only those specials that are
+%D actually used in a figure, we need a bit complicated
+%D bookkeeping and collection of specials. At the cost of some
+%D obscurity, we now have rather efficient resources.
+
+string _global_specials_ ; _global_specials_ := "" ;
+string _local_specials_  ; _local_specials_  := "" ;
+
+% vardef add_special_signal = % write the version number
+%   if (length _global_specials_>0) or (length _local_specials_ >0) :
+%     special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ;
+%   fi ;
+% enddef ;
+%
+% After some reported problems at the \CONTEXT\ mailing list,
+% Taco's came up with:
+
+% TH: \quotation {Ok, got it. There is a bug in mp-spec.mp (inside metafun).
+% Because of a wrapping number, it fails to recognize the fact that there
+% are embedded specials at all.} The corrected definition is:
+
+vardef add_special_signal = % write the version number
+  if (length _global_specials_ <> 0) or (length _local_specials_ <> 0) :
+    special ("%%MetaPostSpecials: 2.0 " & decimal _special_signal_ & " " & decimal _special_div_) ;
+  fi ;
+enddef ;
+
+% \quotation {It now tests for \quote {not equal to zero} instead of
+% \quote {larger than zero}: because of all the included files, the
+% string \type {_local_specials_} becomes longer than the maximum number
+% \quote {length} can return, so it returns -32768 instead, and that is
+% of course less than zero.}
+
+vardef add_extra_specials =
+  scantokens _global_specials_ ;
+  scantokens _local_specials_ ;
+enddef ;
+
+vardef reset_extra_specials =
+  % only local ones
+  _local_specials_ := "" ;
+enddef ;
+
+boolean insidefigure ; insidefigure := false ;
+
+% todo: alleen als special gebruikt flush
+
+extra_beginfig :=
+  " insidefigure := true ; " &
+  " reset_extra_specials ; " &
+    extra_beginfig           &
+  " ; "                      ;
+
+extra_endfig :=
+  " ; "                       &
+  " add_special_signal ; "    &
+    extra_endfig              &
+  " add_extra_specials ; "    &
+  " reset_extra_specials ; "  &
+  " insidefigure := false ; " ;
+
+def set_extra_special (expr s) =
+  if insidefigure :
+    _local_specials_  := _local_specials_  & s ;
+  else :
+    _global_specials_ := _global_specials_ & s ;
+  fi
+enddef ;
+
+def flush_special (expr typ, siz, dat) =
+  _special_counter_ := _special_counter_ + 1 ;
+  if _inline_specials_ :
+    set_extra_special
+      ( "special "
+      & "(" & ditto
+      & dat & " "
+      & decimal _special_counter_ & " "
+      & decimal typ & " "
+      & decimal siz
+      & " special"
+      & ditto & ");" ) ;
+  else :
+    set_extra_special
+      ( "special "
+      & "(" & ditto
+      & "%%MetaPostSpecial: "
+      & decimal siz & " "
+      & dat & " "
+      & decimal _special_counter_ & " "
+      & decimal typ
+      & ditto & ");" ) ;
+  fi ;
+enddef ;
+
+%D The next hack is needed in case you use a version of
+%D \METAPOST\ that does not provide you the means to configure
+%D the buffer size. Patrick Gundlach suggested to use arrays
+%D in this case.
+
+boolean bufferhack ; bufferhack := false ; % true ;
+
+if bufferhack :
+
+  string _global_specials_[] ; numeric _nof_global_specials_ ;
+  string _local_specials_[]  ; numeric _nof_local_specials_ ;
+
+  _nof_global_specials_ := _nof_local_specials_ := 0 ;
+
+  vardef add_special_signal = % write the version number
+    if (_nof_global_specials_>0) or (_nof_local_specials_>0) :
+      special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ;
+    fi ;
+  enddef ;
+
+  vardef add_extra_specials =
+    for i=1 upto _nof_global_specials_ :
+      scantokens _global_specials_[i] ;
+    endfor;
+    for i=1 upto _nof_local_specials_ :
+      scantokens _local_specials_[i] ;
+    endfor;
+  enddef ;
+
+  vardef reset_extra_specials =
+    string _local_specials_[]  ; _nof_local_specials_ := 0 ;
+  enddef ;
+
+  def set_extra_special (expr s) =
+    if insidefigure :
+      _local_specials_[incr(_nof_local_specials_)]   := s ;
+    else :
+      _global_specials_[incr(_nof_global_specials_)] := s ;
+    fi
+  enddef ;
+
+fi ;
+
+%D So far for this hack.
+
+%D Shade allocation.
+
+newinternal shadefactor ; shadefactor := 1 ;
+
+pair shadeoffset ; shadeoffset := origin ;
+
+% vardef define_linear_shade (expr a, b, ca, cb) =
+%   flush_special(30, 15, "0 1 " & decimal shadefactor & " " &
+%     dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " &
+%     dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ;
+%   _special_counter_
+% enddef ;
+
+% vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+%   flush_special(31, 17, "0 1 " & decimal shadefactor & " " &
+%     dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+%     dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+%   _special_counter_
+% enddef ;
+
+% these tests are not yet robust for new gray/cmyk features;
+%
+% - we need to get rid of cmykcolor() and
+
+vardef _is_cmyk_(expr c) =
+    (redpart c = _special_signal_/_special_div_) and (greenpart c = 1/_special_div_)
+enddef ;
+vardef _is_spot_(expr c) =
+    (redpart c = _special_signal_/_special_div_) and (greenpart c = 2/_special_div_)
+enddef ;
+vardef _is_gray_(expr c) =
+    (redpart c = greenpart c) and (greenpart c = bluepart c)
+enddef ;
+
+numeric mp_shade_version ; mp_shade_version := 2 ; % more colors, needs new backend
+
+vardef define_linear_shade (expr a, b, ca, cb) =
+    save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ;
+    save gray_a, gray_b ; boolean gray_a, gray_b ;
+    cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ;
+    cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ;
+    if (mp_shade_version > 1) and cmyk_a and cmyk_b :
+        flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+            cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+    elseif (mp_shade_version > 1) and cmyk_a and gray_b :
+        save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ;
+        flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+            cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) ) ;
+    elseif (mp_shade_version > 1) and gray_a and cmyk_b :
+        save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ;
+        flush_special(32, 17, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " &
+            cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+    elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) :
+        flush_special(34, 17, "0 1 " & decimal shadefactor & " " &
+            spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " &
+            spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ;
+    else :
+        flush_special(30, 15, "0 1 " & decimal shadefactor & " " &
+            dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " &
+            dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ;
+    fi ;
+    _special_counter_
+enddef ;
+
+vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+    save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ;
+    save gray_a, gray_b ; boolean gray_a, gray_b ;
+    cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ;
+    cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ;
+    if (mp_shade_version > 1) and cmyk_a and cmyk_b :
+        flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+            cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+    elseif (mp_shade_version > 1) and cmyk_a and gray_b :
+        save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ;
+        flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+            cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+    elseif (mp_shade_version > 1) and gray_a and cmyk_b :
+        save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ;
+        flush_special(33, 19, "0 1 " & decimal shadefactor & " " &
+            cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+            cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+    elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) :
+        flush_special(35, 19, "0 1 " & decimal shadefactor & " " &
+            spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+            spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+    else :
+        flush_special(31, 17, "0 1 " & decimal shadefactor & " " &
+            dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " &
+            dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ;
+    fi ;
+  _special_counter_
+enddef ;
+
+%D A few predefined shading macros.
+
+boolean trace_shades ; trace_shades := false ;
+
+%  if     (n=1) : a := llcorner p ; b := urcorner p ;
+%  elseif (n=2) : a := llcorner p ; b := ulcorner p ;
+%  elseif (n=3) : a := lrcorner p ; b := ulcorner p ;
+%  else         : a := llcorner p ; b := lrcorner p ;
+%  fi ;
+
+def set_linear_vector (suffix a,b)(expr p,n) =
+  if     (n=1) : a := llcorner p ;
+                 b := urcorner p ;
+  elseif (n=2) : a := lrcorner p ;
+                 b := ulcorner p ;
+  elseif (n=3) : a := urcorner p ;
+                 b := llcorner p ;
+  elseif (n=4) : a := ulcorner p ;
+                 b := lrcorner p ;
+  elseif (n=5) : a := .5[ulcorner p,llcorner p] ;
+                 b := .5[urcorner p,lrcorner p] ;
+  elseif (n=6) : a := .5[llcorner p,lrcorner p] ;
+                 b := .5[ulcorner p,urcorner p] ;
+  elseif (n=7) : a := .5[lrcorner p,urcorner p] ;
+                 b := .5[llcorner p,ulcorner p] ;
+  elseif (n=8) : a := .5[urcorner p,ulcorner p] ;
+                 b := .5[lrcorner p,llcorner p] ;
+  else         : a := .5[ulcorner p,llcorner p] ;
+                 b := .5[urcorner p,lrcorner p] ;
+  fi ;
+enddef ;
+
+def set_circular_vector (suffix ab, r)(expr p,n) =
+  if     (n=1) : ab := llcorner p ;
+  elseif (n=2) : ab := lrcorner p ;
+  elseif (n=3) : ab := urcorner p ;
+  elseif (n=4) : ab := ulcorner p ;
+  else         : ab := center   p ; r := .5r ;
+  fi ;
+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 withshade define_linear_shade (a,b,ca,cb) ;
+  if trace_shades :
+    drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
+  fi ;
+  endgroup ;
+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 withshade define_circular_shade(ab,ab,0,r,ca,cb) ;
+  if trace_shades :
+    drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
+  fi ;
+  endgroup ;
+enddef ;
+
+vardef predefined_linear_shade (expr p, n, ca, cb) =
+    save a, b, sh ; pair a, b ;
+    set_linear_vector(a,b)(p,n) ;
+    define_linear_shade (a,b,ca,cb)
+enddef ;
+
+vardef predefined_circular_shade (expr p, n, ca, cb) =
+    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) ;
+    define_circular_shade(ab,ab,0,r,ca,cb)
+enddef ;
+
+%D Since a \type {fill p withshade s} syntax looks better
+%D than some macro, we implement a new primary.
+
+primarydef p withshade sc = % == p withcolor shadecolor(sh)
+  hide (_color_counter_ := _color_counter_ + 1)
+  p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_)
+enddef ;
+
+vardef shadecolor(expr sc) =
+  hide (_color_counter_ := _color_counter_ + 1)
+  (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_)
+enddef ;
+
+%D Figure inclusion.
+
+%numeric cef ; cef := 0 ;
+
+def externalfigure primary filename =
+  doexternalfigure (filename)
+enddef ;
+
+def doexternalfigure (expr filename) text transformation =
+  begingroup ; save p, t ; picture p ; transform t ;
+  p := nullpicture ; t := identity transformation ;
+  flush_special(10, 9,
+    dddecimal (xxpart t, yxpart t, xypart t) & " " &
+    dddecimal (yypart t,  xpart t,  ypart t) & " " & filename) ;
+  addto p contour unitsquare scaled 0 ;
+  setbounds p to unitsquare transformed t ;
+  _color_counter_ := _color_counter_ + 1 ;
+  draw p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ;
+  endgroup ;
+enddef ;
+
+%D Experimental:
+
+%numeric currenthyperlink ; currenthyperlink := 0 ;
+
+def hyperlink primary t = dohyperlink(t) enddef ;
+def hyperpath primary t = dohyperpath(t) enddef ;
+
+def dohyperlink (expr destination) text transformation  =
+  begingroup ; save somepath ; path somepath ;
+  somepath := fullsquare transformation ;
+  dohyperpath(destination) somepath ;
+  endgroup ;
+enddef ;
+
+def dohyperpath (expr destination) expr somepath =
+  begingroup ;
+  flush_special(20, 7,
+    ddecimal (xpart llcorner somepath, ypart llcorner somepath) & " " &
+    ddecimal (xpart urcorner somepath, ypart urcorner somepath) & " " & destination) ;
+  _color_counter_ := _color_counter_ + 1 ;
+  fill boundingbox unitsquare scaled 0 withcolor
+    (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ;
+  endgroup ;
+enddef ;
+
+% \setupinteraction[state=start]
+% \setupcolors     [state=start]
+%
+% Hello There! \blank
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 4cm withcolor red ;
+% hyperpath "nextpage" boundingbox currentpicture ;
+% draw origin withcolor blue ;
+% \stopMPcode
+%
+% \blank Does it work or not?
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 4cm withcolor red ;
+% hyperpath "nextpage" fullcircle scaled 4cm ;
+% draw origin withcolor blue ;
+% draw fullcircle scaled 4cm shifted (1cm,1cm);
+% \stopMPcode
+%
+% \blank Does it work or not? \page Hello There! \blank
+%
+% \startMPcode
+% pickup pencircle scaled 5 ;
+% draw fullcircle scaled 2cm shifted (-2cm,-1cm) ;
+% draw fullcircle scaled 3cm shifted (2cm,1cm) withcolor red ;
+% draw fullcircle scaled 1cm ;
+% hyperlink "previouspage" scaled 3cm shifted (2cm,1cm) ;
+% draw origin withcolor blue ;
+% \stopMPcode
+%
+% \blank Does it work or not?
+
+_cmyk_counter_ := 0 ;
+
+extra_endfig := " ; resetcmykcolors ; " & extra_endfig ;
+
+def resetcmykcolors =
+  numeric cmykcolorhash[][][][] ;
+enddef ;
+
+resetcmykcolors ; boolean cmykcolors ; cmykcolors := false ; % true
+
+string cmykcolorpattern[] ; % needed for transparancies
+
+vardef cmyk(expr c,m,y,k) =
+  if cmykcolors :
+    save ok ; boolean ok ;
+    if unknown cmykcolorhash[c][m][y][k] :
+      ok := false ; % not yet defined
+    elseif cmykcolorhash[c][m][y][k] = -1 :
+      ok := false ; % locally defined and undefined
+    else :
+      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 := ddddecimal (c,m,y,k) ;
+      _cmyk_counter_ := _cmyk_counter_ + 1 ;
+      cmykcolorpattern[_cmyk_counter_/_special_div_] := s ;
+      cmykcolorhash[c][m][y][k] := _cmyk_counter_ ;
+      flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ;
+      _local_specials_ := _local_specials_ &
+        " cmykcolorhash[" & decimal c & "][" & decimal m &
+        "][" & decimal y & "][" & decimal k & "] := -1 ; " ;
+    fi ;
+    (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_)
+  else :
+    (1-c-k,1-m-k,1-y-k)
+  fi
+enddef ;
+
+% newcolor truecyan, truemagenta, trueyellow ;
+%
+% truecyan    = (1,0,0,0) ;
+% truemagenta = (0,1,0,0) ;
+% trueyellow  = (0,0,1,0) ;
+
+%D Spot colors
+
+_spotcolor_counter_ := 0 ;
+_spotcolor_number_ := 0 ;
+
+extra_endfig := " ; resetspotcolors ; " & extra_endfig ;
+
+def resetspotcolors =
+  numeric spotcolorhash[][] ;
+enddef ;
+
+resetspotcolors ; boolean spotcolors ; spotcolors := false ; % true
+
+string spotcolorpattern[] ; % needed for transparancies
+
+vardef spotcolor(expr p, s) =
+  multitonecolor(p, 1, "", decimal s)
+enddef ;
+
+vardef multitonecolor(expr n, f, d, p) = % name fractions names factors
+  if spotcolors :
+    save ok, pc_tag ; boolean ok ; string pc_tag ;
+    pc_tag := "_pct_" & n ;
+    if not unstringed(pc_tag) :
+      _spotcolor_number_ := _spotcolor_number_ + 1 ;
+      setunstringed(pc_tag,_spotcolor_number_) ;
+    fi ;
+    pp := getunstringed(pc_tag) ;
+    pc_tag := "_pct_"& decimal f & "_" & if d = "" : n else : d fi & "_" & p ; % check for d empty
+    if not unstringed(pc_tag) :
+      _spotcolor_number_ := _spotcolor_number_ + 1 ;
+      setunstringed(pc_tag,_spotcolor_number_) ;
+    fi ;
+    ps := getunstringed(pc_tag) ;
+    if unknown spotcolorhash[pp][ps] :
+      ok := false ; % not yet defined
+    elseif spotcolorhash[pp][ps] = -1 :
+      ok := false ; % locally defined and undefined
+    else :
+      ok := true ;  % globally already defined
+    fi ;
+    if not ok :
+      save ss ; string ss ; ss := n & " " & decimal f & " " & if d = "" : n else : d fi & " " & p ;
+      _spotcolor_counter_ := _spotcolor_counter_ + 1 ;
+      spotcolorpattern[_spotcolor_counter_/_special_div_] := ss ;
+      spotcolorhash[pp][ps] := _spotcolor_counter_ ;
+      flush_special(2, 7, decimal _spotcolor_counter_ & " " & ss) ;
+      _local_specials_ := _local_specials_ &
+        "spotcolorhash["&decimal pp&"]["&decimal ps&"]:=-1;" ;
+    fi ;
+    (_special_signal_/_special_div_,2/_special_div_,spotcolorhash[pp][ps]/_special_div_)
+  else :
+   .5white
+  fi
+enddef ;
+
+%D Transparency
+
+normaltransparent     :=  1 ; multiplytransparent   :=  2 ;
+screentransparent     :=  3 ; overlaytransparent    :=  4 ;
+softlighttransparent  :=  5 ; hardlighttransparent  :=  6 ;
+colordodgetransparent :=  7 ; colorburntransparent  :=  8 ;
+darkentransparent     :=  9 ; lightentransparent    := 10 ;
+differencetransparent := 11 ; exclusiontransparent  := 12 ;
+
+% nottransparent        :=  0 ;
+% compatibletransparent := 99 ;
+
+% fill fullcircle scaled 10cm withcolor transparant(8,.3,red) ;
+
+vardef transparent(expr n, t, c) =
+  save s, ss, nn, cc, is_cmyk, is_spot, ok ;
+  string s, ss ; numeric nn ; color cc ; boolean is_cmyk, is_spot, ok ;
+  % transparancy type
+  if string n :
+    if expandafter known scantokens(n&"transparent") :
+      nn := scantokens(n&"transparent") ;
+    else :
+      nn := 0 ;
+    fi
+  else : % nn := min(n,13)
+    nn := if n<13 : n else : nn := 0 fi ;
+  fi ;
+  % we need to expand the color (can be cmyk(..) or predefined)
+  cc := c ; % expand color
+  % check for cmyk special
+  is_cmyk := (redpart   cc = _special_signal_/_special_div_)
+         and (greenpart cc = 1/_special_div_) ;
+  is_spot := (redpart   cc = _special_signal_/_special_div_)
+         and (greenpart cc = 2/_special_div_) ;
+  % build special string, fetch cmyk components
+  s := decimal nn & " " & decimal t & " " &
+       if     is_cmyk : cmykcolorpattern[bluepart cc]
+       elseif is_spot : spotcolorpattern[bluepart cc]
+       else           : dddecimal cc fi ;
+  % check if this one is already used
+  ss := cleanstring("tr_" & s) ;
+  % we now have rather unique names, i.e. a color spec of .234 becomes
+  % tr..._234.... and metapost gives a number overflow (parse error)
+  % for variables like tr_12345678 which may result from many decimal
+  % positions (imo mp bug)
+  ss := asciistring(ss) ;
+  % efficiency hack
+  if expandafter unknown scantokens(ss) :
+    ok := false ; % not yet defined
+  elseif scantokens(ss) < 0  :
+    ok := false ; % locally defined and undefined
+  else :
+    ok := true ;  % globally already defined
+  fi ;
+  if not ok :
+    if is_spot  :
+      flush_special(5, 8, s) ;
+    elseif is_cmyk :
+      flush_special(4, 8, s) ;
+    else :
+      flush_special(3, 7, s) ;
+    fi ;
+    scantokens(ss) := _special_counter_ ;
+    _local_specials_ := _local_specials_ & "scantokens(" & ditto & ss & ditto & ") := -1 ;" ;
+  fi ;
+  % go ahead
+  if is_spot :
+    (_special_signal_/_special_div_,5/_special_div_,scantokens(ss)/_special_div_)
+  elseif is_cmyk :
+    (_special_signal_/_special_div_,4/_special_div_,scantokens(ss)/_special_div_)
+  else :
+    (_special_signal_/_special_div_,3/_special_div_,scantokens(ss)/_special_div_)
+  fi
+enddef ;
+
+%D This function returns true of false, dependent on transparency.
+
+vardef is_transparent(text t) =
+  begingroup ; save transparent ; save _c_, _b_ ;
+    vardef transparent(expr nn, tt, cc) = _b_ := true ; cc enddef ;
+    boolean _b_ ; _b_ := false ;
+    color _c_ ; _c_ := t ; _b_
+  endgroup
+enddef ;
+
+% boolean _b_ ; better namespacing
+% color   _c_ ;
+% vardef _transparent_(expr nn, tt, cc) = _b_ := true ; cc enddef ;
+% vardef is_transparent(text t) =
+%   begingroup ;
+%     save transparent ;
+%     transparent := _transparent_ ;
+%     _b_ := false ;
+%     _c_ := t ; _b_
+%   endgroup
+% enddef ;
+
+%D This function returns the not transparent color.
+
+vardef not_transparent(text t) =
+  begingroup ; save transparent ;
+  vardef transparent(expr nn, tt, cc) = cc enddef ;
+  t endgroup
+enddef ;
+
+%D Basic position tracking:
+
+def register (expr label, width, height, offset) =
+  begingroup ;
+  flush_special(50, 7,
+    ddecimal offset & " " &
+    decimal  width  & " " &
+    decimal  height & " " & label) ;
+  endgroup ;
+enddef ;
+
+%D We cannot scale cmyk colors directly since this spoils
+%D the trigger signal (such colors are no real colors).
+
+vardef scaledcmyk(expr c,m,y,k,sf) =
+  cmyk(sf*c,sf*m,sf*y,sf*k)
+enddef ;
+
+vardef scaledcmykasrgb(expr c,m,y,k,sf) =
+  (sf*(1-c-k,1-m-k,1-y-k))
+enddef ;
+
+vardef scaledrgbascmyk(expr c,m,y,k,sf) =
+  scaledcmyk(1-c,1-m,1-y,0,sf)
+enddef ;
+
+vardef scaledrgb(expr r,g,b,sf) =
+  (sf*(r,g,b))
+enddef ;
+
+vardef scaledgray(expr s,sf) =
+  (sf*(s,s,s))
+enddef ;
+
+% spotcolor is already scaled
+
+% just an exercise (due to a question by Chof on the context mailing list); scaling of
+% 'special' colors is not possible and the next solution is incomplete (spot colors,
+% transparency, etc); watch the the tricky chained macro construction
+
+% vardef normalgray(expr s      ) = (s,s,s) enddef ;
+% vardef normalrgb (expr r,g,b  ) = (r,g,b) enddef ;
+% vardef normalcmyk(expr c,m,y,k) = if cmykcolors : save ok ; boolean ok ; if unknown cmykcolorhash[c][m][y][k] : ok := false ; elseif cmykcolorhash[c][m][y][k] = -1 : ok := false ; else : ok := true ; fi ; if not ok : save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ; _cmyk_counter_ := _cmyk_counter_ + 1 ; cmykcolorpattern[_cmyk_counter_/_special_div_] := s ; cmykcolorhash[c][m][y][k] := _cmyk_counter_ ; flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ; _local_specials_ := _local_specials_ & " cmykcolorhash[" & decimal c & "][" & decimal m & "][" & decimal y & "][" & decimal k & "] := -1 ; " ; fi ; (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_) else : (1-c-k,1-m-k,1-y-k) fi enddef ;
+
+% vardef gray(expr s)       = normalgray(s      ) enddef ;
+% vardef rgb (expr r,g,b)   = normalrgb (r,g,b  ) enddef ;
+% vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ;
+
+% numeric _scaled_color_t_ ;
+% color   _scaled_color_c_ ;
+
+% def withscaledcolor =
+%     hide (
+%         _scaled_color_t_ := 0 ; % direct
+%         def gray(expr s) =
+%             hide (
+%                 _gray_s_ := s ;
+%                 _scaled_color_t_ := 1; % gray
+%             )
+%             0
+%         enddef ;
+%         def rgb (expr r,g,b) =
+%             hide (
+%                 _rgb_r_ := r ; _rgb_g_ := g ; _rgb_b_ := b ;
+%                 _scaled_color_t_ := 2 ; % rgb
+%             )
+%             0
+%         enddef ;
+%         def cmyk (expr c,m,y,k) =
+%             hide (
+%                 _cmyk_c_ := c ; _cmyk_m_ := m ; _cmyk_y_ := y ; _cmyk_k_ := k ;
+%                 _scaled_color_t_ := 3 ; % cmyk
+%             )
+%             0
+%         enddef ; )
+%     dowithscaledcolor
+% enddef ;
+
+% def dowithscaledcolor expr t =
+%     hide (
+%         if color t : _scaled_color_c_ := t fi ;
+%         vardef gray(expr s)       = normalgray(s)       enddef ;
+%         vardef rgb (expr r,g,b)   = normalrgb (r,g,b)   enddef ;
+%         vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ;
+%     )
+% enddef ;
+
+% def by expr s =
+%     if     _scaled_color_t_ = 0 :
+%         withcolor s*_scaled_color_c_
+%     elseif _scaled_color_t_ = 1 :
+%         withcolor gray(s*_gray_s_)
+%     elseif _scaled_color_t_ = 2 :
+%         withcolor rgb (s*_rgb_r_, s*_rgb_g_, s*_rgb_b_)
+%     elseif _scaled_color_t_ = 3 :
+%         withcolor cmyk(s*_cmyk_c_, s*_cmyk_m_, s*_cmyk_y_, s*_cmyk_k_)
+%     fi
+% enddef ;
+
+% fill fullcircle scaled 10cm withscaledcolor cmyk(0,0,1,0) by .5 ;
+% fill fullcircle scaled  8cm withscaledcolor rgb (0,0,1)   by .5 ;
+% fill fullcircle scaled  6cm withscaledcolor gray(1)       by .5 ;
+% fill fullcircle scaled  4cm withscaledcolor     (0,1,0)   by .5 ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-step.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-step.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-step.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,317 @@
+%D \module
+%D   [       file=mp-step.mpii,
+%D        version=2001.05.22,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=steps,
+%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 licen-en.pdf for
+%C details.
+
+if known context_step : endinput ; fi ;
+
+boolean context_step ; context_step := true ;
+
+%D In the associated \TEX\ module \type {m-steps}, we describe
+%D three methods. The first method uses a different kind of
+%D code than the other two. The method we decided to use,
+%D is based on positional information (paths) provided by
+%D \CONTEXT.
+
+def initialize_step_variables =
+  save line_method, line_h_offset, line_v_offset ;
+  numeric line_method   ; line_method   := 1 ;
+  numeric line_h_offset ; line_h_offset := 3pt ;
+  numeric line_v_offset ; line_v_offset := 3pt ;
+enddef ;
+
+def begin_step_chart =
+  initialize_step_variables ;
+  save steps, texts, t, b, tb, nofcells ;
+  picture cells[][], texts[][][], lines[][][] ;
+  numeric t, b ; t := 1 ; b := 2 ;
+  numeric nofcells ; nofcells := 0 ;
+enddef ;
+
+def analyze_step_chart =
+  numeric n[], l[][], r[][] ; pair p[] ;
+  n[t] := n[b] := 0 ; numeric tb ;
+  for i=1 upto nofcells : for nn = t, b :
+    if bbwidth(cells[nn][i])>0 : n[nn] := n[nn] + 1 ; fi ;
+    l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ;
+  endfor ; endfor ;
+  % count left and right points
+  for i=1 upto nofcells-1 : for j=i upto nofcells-1 : for nn = t, b :
+    if bbwidth(texts[nn][i][j])>0 :
+      l[nn][i] := l[nn][i] + 1 ;
+      r[nn][j+1] := r[nn][j+1] + 1 ;
+    fi ;
+  endfor ; endfor ; endfor ;
+  % calculate left and right points
+  vardef do (expr nn, mm, ii, ss) =
+    if (l[nn][ii] + r[nn][ii]) > 1 : ss else : .5 fi
+      [ ulcorner cells[mm][ii], urcorner cells[mm][ii] ]
+  enddef ;
+  % combined rows
+  tb := if n[t]>0 : t else : b fi ;
+enddef ;
+
+vardef get_step_chart_top_line (expr i, j) =
+  if bbwidth(cells[tb][i])>0 :
+    if bbwidth(texts[t][i][j])>0 :
+      if bbwidth(cells[tb][j+1])>0 :
+        p[1] := top do(t, tb,   i, .6) ;
+        p[3] := top do(t, tb, j+1, .4) ;
+        p[2] := .5[p[1],p[3]] ;
+        if line_method = 1 :
+          p[2] := p[2] shifted (0, ypart
+            (llcorner texts[t][i][j] - ulcorner cells[tb][j+1])) ;
+        elseif line_method = 2 :
+          p[2] := center texts[t][i][j] ;
+        else :
+          % nothing
+        fi ;
+        p[1] := p[1] shifted (0,+line_v_offset) ;
+        p[2] := p[2] shifted (0,-line_v_offset) ;
+        p[3] := p[3] shifted (0,+line_v_offset) ;
+        (p[1] {up} ... p[2] ... {down} p[3])
+      else :
+        origin
+      fi
+    else :
+      origin
+    fi
+  else :
+    origin
+  fi
+enddef ;
+
+vardef get_step_chart_bot_line (expr i, j) =
+  if bbwidth(cells[b][i])>0 :
+    if bbwidth(texts[b][i][j])>0 :
+      if bbwidth(cells[b][j+1])>0 :
+        p[1] := (bot do(b, b,   i, .6)) shifted (0,-bbheight(cells[b][i])) ;
+        p[3] := (bot do(b, b, j+1, .4)) shifted (0,-bbheight(cells[b][j+1])) ;
+        p[2] := .5[p[1],p[3]] ;
+        if line_method = 1 :
+          p[2] := p[2] shifted (0, -ypart
+            (llcorner cells[b][j+1] - ulcorner texts[b][i][j])) ;
+        elseif line_method = 2 :
+          p[2] := center texts[b][i][j] ;
+        fi ;
+        p[1] := p[1] shifted (0,-line_v_offset) ;
+        p[2] := p[2] shifted (0,+line_v_offset) ;
+        p[3] := p[3] shifted (0,-line_v_offset) ;
+        (p[1] {down} ... p[2] ... {up} p[3])
+      else :
+        origin
+      fi
+    else :
+      origin
+    fi
+  else :
+    origin
+  fi
+enddef ;
+
+def end_step_chart =
+  for i=1 upto nofcells :                         for nn = t, b :
+      if bbwidth(cells[nn][i])   >0 : draw cells[nn][i]    ; fi ;
+  endfor ;          endfor ;
+  for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
+    if known lines[nn][i][j] :
+      if bbwidth(lines[nn][i][j])>0 : draw lines[nn][i][j] ; fi ;
+    fi ;
+  endfor ; endfor ; endfor ;
+  for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
+      if bbwidth(texts[nn][i][j])>0 : draw texts[nn][i][j] ; fi ;
+  endfor ; endfor ; endfor ;
+enddef ;
+

+%D Step tables.
+
+def begin_step_table =
+  initialize_step_variables ;
+  picture cells[], texts[], lines[] ;
+  numeric nofcells ; nofcells := 0 ;
+enddef ;
+
+def end_step_table =
+  for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 :
+    draw cells[i] ;
+  fi ; fi ; endfor ;
+  for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 :
+    draw lines[i] ;
+  fi ; fi ; endfor ;
+  for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 :
+    draw texts[i] ;
+  fi ; fi ; endfor ;
+enddef ;
+
+vardef get_step_table_line (expr i) =
+  pair prev, self, next ;
+  if known texts[i] :
+    self := lft .5[llcorner texts[i], ulcorner texts[i] ] ;
+    prev := rt if known texts[i-1] : .3 else : .5 fi [lrcorner cells[i]  , urcorner cells[i]  ] ;
+    next := rt if known texts[i+1] : .7 else : .5 fi [lrcorner cells[i+1], urcorner cells[i+1]] ;
+    self := self shifted (-line_h_offset,0) ;
+    prev := prev shifted (+line_h_offset,0) ;
+    next := next shifted (+line_h_offset,0) ;
+    prev {right} ... self ... {left} next
+  else :
+    origin
+  fi
+enddef ;
+
+%D The older method let \METAPOST\ do the typesetting. The
+%D macros needed for that are included here for educational
+%D purposes.
+%D
+%D \starttypen
+%D def initialize_step_variables =
+%D   save line_color, line_width, arrow_alternative,
+%D     text_fill_color, text_line_color, text_line_width, text_offset,
+%D     cell_fill_color, cell_line_color, cell_line_width, cell_offset,
+%D     line_h_offset, line_v_offset ;
+%D   color   line_color       ; line_color       := .4white ;
+%D   numeric line_width       ; line_width       := 1.5pt ;
+%D   color   text_fill_color  ; text_fill_color  := white ;
+%D   color   text_line_color  ; text_line_color  := red ;
+%D   numeric text_line_width  ; text_line_width  := 1pt ;
+%D   numeric text_offset      ; text_offset      := 2pt ;
+%D   color   cell_fill_color  ; cell_fill_color  := white ;
+%D   color   cell_line_color  ; cell_line_color  := blue ;
+%D   numeric cell_line_width  ; cell_line_width  := 1pt ;
+%D   numeric cell_offset      ; cell_offset      := 2pt ;
+%D   numeric line_alternative ; line_alternative := 1 ;
+%D   numeric line_h_offset    ; line_h_offset    := 3pt ;
+%D   numeric line_v_offset    ; line_v_offset    := 3pt ;
+%D enddef ;
+%D
+%D def begin_step_chart =
+%D   begingroup ;
+%D   initialize_step_variables ;
+%D   save steps, texts, t, b ;
+%D   picture cells[][]   ; numeric nofcells ; nofcells := 0 ;
+%D   picture texts[][][] ; numeric noftexts ; noftexts := 0 ;
+%D   numeric t, b ; t := 1 ; b := 2 ;
+%D enddef ;
+%D \stoptypen
+%D
+%D We use a couple of macros to store the content. In the
+%D second (third) alternative we will directly fill the
+%D cells.
+%D
+%D \starttypen
+%D def set_step_chart_cells (expr one, two) =
+%D   nofcells := nofcells + 1 ; noftexts := 0 ;
+%D   cells[t][nofcells] := textext.rt(one) ;
+%D   cells[b][nofcells] := textext.rt(two) ;
+%D enddef ;
+%D
+%D def set_step_chart_texts (expr one, two) =
+%D   noftexts := noftexts + 1 ;
+%D   texts[t][nofcells][noftexts] := textext.rt(one) ;
+%D   texts[b][nofcells][noftexts] := textext.rt(two) ;
+%D enddef ;
+%D \stoptypen
+%D
+%D If you compare the building macro with the later
+%D alternative, you will notice that here we explicitly
+%D have to calculate the distances and positions.
+%D
+%D \starttypen
+%D def end_step_chart =
+%D   numeric dx ; dx :=  0 ; path p ;
+%D   numeric n[] ; n[t] := n[b] := 0 ;
+%D   numeric stepsvdistance[] ;
+%D   vardef bbwidth  (expr p) = (xpart (lrcorner p - llcorner p)) enddef ;
+%D   vardef bbheight (expr p) = (ypart (urcorner p - lrcorner p)) enddef ;
+%D   stepsvdistance[t] := stepsvdistance[b] := 0 ;
+%D   for i=1 upto nofcells :
+%D     % find largest bbox
+%D     p := boundingbox steps
+%D       [if bbwidth(cells[t][i])>bbwidth(cells[b][i]): t else: b fi][i] ;
+%D     % assign largest bbox
+%D     for nn = t, b :
+%D       if bbwidth(cells[nn][i])>0 :
+%D         setbounds cells[nn][i] to p enlarged cell_offset ;
+%D         n[nn] := n[nn] + 1 ;
+%D       fi ;
+%D     endfor ;
+%D     % determine height
+%D     if n[t]>0 :
+%D       stepsvdistance[t] := bbheight(cells[t][1]) + intertextdistance ;
+%D     fi ;
+%D     % add to row
+%D     for nn = t, b :
+%D       cells[nn][i] := cells[nn][i] shifted (dx,stepsvdistance[nn]) ;
+%D       if bbwidth(cells[nn][i])>0 :
+%D         dowithpath (boundingbox cells[nn][i],
+%D           cell_line_width, cell_line_color, cell_background_color) ;
+%D       fi ;
+%D     endfor ;
+%D     % calculate position
+%D     dx := dx + interstepdistance + bbwidth(cells[b][i]) ;
+%D   endfor ;
+%D   boolean stacked ; stacked := false ;
+%D   numeric l[][], r[][], l[][], r[][] ;
+%D   pair pa, pb, pc ; path p[] ;
+%D   for i=1 upto nofcells :
+%D     l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ;
+%D   endfor ;
+%D   % count left and right points
+%D   for i=1 upto nofcells : for j=1 upto nofcells : for nn = t, b :
+%D     if known texts[nn][i][j] : if bbwidth(texts[nn][i][j])>0 :
+%D       l[nn][i]   := l[nn][i]   + 1 ;
+%D         r[nn][j+i] := r[nn][j+i] + 1 ;
+%D         stacked := (stacked or (j>1)) ;
+%D         setbounds texts[nn][i][j] to boundingbox texts[nn][i][j] enlarged cell_offset ;
+%D     fi fi ;
+%D     endfor ; endfor ; endfor ;
+%D     % calculate left and right points
+%D     vardef do (expr nn, mm, ii, ss) =
+%D       if (l[nn][ii] > 0) and (r[nn][ii] > 0) : ss else : .5 fi
+%D         [ ulcorner cells[mm][ii],urcorner cells[mm][ii] ]
+%D     enddef ;
+%D     % draw arrow from left to right point
+%D     def dodo (expr nn, ii, jj, dd) =
+%D       drawarrow p[nn]
+%D         withpen pencircle scaled arrow_line_width
+%D         withcolor arrow_line_color ;
+%D       transform tr ; tr := identity
+%D         shifted point .5 along p[nn]
+%D         shifted -center texts[nn][ii][jj]
+%D         if not stacked : shifted (0,dd) fi ;
+%D         dowithpath ((boundingbox texts[nn][ii][jj]) transformed tr,
+%D           text_line_width, text_line_color, text_fill_color) ;
+%D     enddef ;
+%D     % draw top and bottom text boxes
+%D     for i=1 upto nofcells : for j=1 upto nofcells :
+%D       pickup pencircle scaled arrow_line_width ;
+%D       if known texts[t][i][j] : if bbwidth(texts[t][i][j]) > 0 :
+%D         pa := top do(t, if n[t]>0 : t else : b fi,   i, .6) ;
+%D         pb := top do(t, if n[t]>0 : t else : b fi, j+i, .4) ;
+%D         pc := .5[pa,pb] shifted (0,+step_arrow_depth) ;
+%D         p[t] := pa {up} .. if not stacked : pc .. fi {down} pb ;
+%D         dodo(t, i, j, +intertextdistance) ;
+%D       fi fi ;
+%D       if known texts[b][i][j] : if bbwidth(texts[b][i][j]) > 0 :
+%D         pa := (bot do(b, b,   i, .6)) shifted (0,-bbheight(cells[b][i])) ;
+%D         pb := (bot do(b, b, j+i, .4)) shifted (0,-bbheight(cells[b][j+i])) ;
+%D         pc := .5[pa,pb] shifted (0,-step_arrow_depth) ;
+%D         p[b] := pa {down} .. if not stacked : pc .. fi {up} pb ;
+%D         dodo(b, i, j, -intertextdistance) ;
+%D       fi fi ;
+%D     endfor ; endfor ;
+%D   endgroup ;
+%D enddef ;
+%D \stoptypen
+%D
+%D If you compare both methods, you will notice that the
+%D first method is the cleanest, but not the most efficient
+%D (since it needs \TEX\ runs within \METAPOST\ runs within
+%D \TEX\ runs).

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-symb.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-symb.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-symb.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,351 @@
+%D \module
+%D   [       file=mp-symb.mp,
+%D        version=very old,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=navigation symbol macros,
+%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.
+
+%D Instead of these symbols, you can use the \type {contnav}
+%D font by Taco Hoekwater that is derived form this file.
+
+u  := 3;
+h  := 5u;
+wt := 5u;
+wb := .25wt;
+o  := .1u;
+pw := .5u;
+
+drawoptions (withpen pencircle scaled pw);
+
+path lefttriangle, righttriangle, sublefttriangle, subrighttriangle;
+
+pair s ; s = (2wb,0) ;
+
+x1t = x2t = 0;
+x3t = wt;
+y3t = .5h;
+z1t-z2t = (z3t-z2t) rotated 60;
+
+z4t = (z2t--z3t) intersectionpoint ((z1t--z2t) shifted s) ;
+z5t = (z3t--z1t) intersectionpoint ((z1t--z2t) shifted s) ;
+
+righttriangle = z1t--z2t--z3t--cycle;
+lefttriangle = righttriangle rotatedaround((0,.5h), 180) shifted (wt,0);
+
+subrighttriangle = z4t--((z2t--z3t--z1t) shifted s)--z5t ;
+sublefttriangle  = subrighttriangle rotatedaround((0,.5h), 180) shifted (wt,0);
+
+path sidebar;
+
+x1b = x4b = 0;
+x2b = x3b = wb;
+y1b = y2b = y1t;
+y3b = y4b = y2t;
+
+sidebar = z1b--z2b--z3b--z4b--cycle;
+
+path midbar, onebar, twobar;
+
+hh = abs(y1t-y2t);
+
+%midbar := unitsquare scaled 2hh/3;
+midbar := unitsquare scaled hh;
+onebar := unitsquare xscaled (hh/3) yscaled hh;
+twobar := onebar;
+
+def prepareglyph =
+  drawoptions (withpen pencircle scaled .5u);
+enddef;
+
+def finishglyph =
+  set_outer_boundingbox currentpicture;
+  bboxmargin := o;
+  setbounds currentpicture to bbox currentpicture;
+%  draw boundingbox currentpicture withcolor red withpen pencircle scaled 1;
+enddef;
+
+beginfig  (1);
+  prepareglyph;
+  fill lefttriangle;
+  draw lefttriangle;  % draw gets the bbox right, filldraw doesn't
+  finishglyph;
+endfig;
+
+beginfig  (2);
+  prepareglyph;
+  fill righttriangle;
+  draw righttriangle;
+  finishglyph;
+endfig;
+
+beginfig  (3);
+  prepareglyph;
+  fill sidebar;
+  draw sidebar;
+  fill lefttriangle shifted (.5s);
+  draw lefttriangle shifted (.5s);
+  finishglyph;
+endfig;
+
+beginfig  (4);
+  prepareglyph;
+  fill righttriangle;
+  draw righttriangle;
+  fill sidebar shifted (wt,0);
+  draw sidebar shifted (wt,0);
+  finishglyph;
+endfig;
+
+beginfig  (5);
+  prepareglyph;
+  fill lefttriangle;
+  draw lefttriangle;
+  fill lefttriangle shifted s;
+  draw lefttriangle shifted s;
+  finishglyph;
+endfig;
+
+beginfig  (6);
+  prepareglyph;
+  fill righttriangle;
+  draw righttriangle;
+  fill righttriangle shifted s;
+  draw righttriangle shifted s;
+  finishglyph;
+endfig;
+
+beginfig  (7);
+  prepareglyph;
+  fill midbar;
+  draw midbar;
+  finishglyph;
+endfig;
+
+beginfig  (8);
+  prepareglyph;
+  fill onebar;
+  draw onebar;
+  finishglyph;
+endfig;
+
+beginfig  (9);
+  prepareglyph;
+  fill twobar;
+  draw twobar;
+  fill twobar shifted (pw+hh/2,0);
+  draw twobar shifted (pw+hh/2,0);
+  finishglyph;
+endfig;
+
+beginfig(101);
+  prepareglyph;
+  draw lefttriangle;
+  finishglyph;
+endfig;
+
+beginfig(102);
+  prepareglyph;
+  draw righttriangle;
+  finishglyph;
+endfig;
+
+beginfig(103);
+  prepareglyph;
+  draw sidebar;
+  draw lefttriangle shifted (.5s);
+  finishglyph;
+endfig;
+
+beginfig(104);
+  prepareglyph;
+  draw righttriangle;
+  draw sidebar shifted (wt,0);
+  finishglyph;
+endfig;
+
+beginfig(105);
+  prepareglyph;
+  draw lefttriangle;
+  draw lefttriangle shifted s;
+  finishglyph;
+endfig;
+
+beginfig(106);
+  prepareglyph;
+  draw righttriangle;
+  draw righttriangle shifted s;
+  finishglyph;
+endfig;
+
+beginfig(107);
+  prepareglyph;
+  draw midbar;
+  finishglyph;
+endfig;
+
+beginfig(108);
+  prepareglyph;
+  draw onebar;
+  finishglyph;
+endfig;
+
+beginfig(109);
+  prepareglyph;
+  draw twobar;
+  draw twobar shifted (pw+hh/2,0);
+  finishglyph;
+endfig;
+
+beginfig(201);
+  prepareglyph;
+  draw lefttriangle;
+  finishglyph;
+endfig;
+
+beginfig(202);
+  prepareglyph;
+  draw righttriangle;
+  finishglyph;
+endfig;
+
+beginfig(203);
+  prepareglyph;
+  draw sidebar;
+  draw lefttriangle shifted (.5s);
+  finishglyph;
+endfig;
+
+beginfig(204);
+  prepareglyph;
+  draw righttriangle;
+  draw sidebar shifted (wt,0);
+  finishglyph;
+endfig;
+
+beginfig(205);
+  prepareglyph;
+  draw sublefttriangle shifted s;
+  draw lefttriangle shifted s;
+  finishglyph;
+endfig;
+
+beginfig(206);
+  prepareglyph;
+  draw subrighttriangle;
+  draw righttriangle;
+  finishglyph;
+endfig;
+
+beginfig(207);
+  prepareglyph;
+  draw midbar;
+  finishglyph;
+endfig;
+
+beginfig(208);
+  prepareglyph;
+  draw onebar;
+  finishglyph;
+endfig;
+
+beginfig(209);
+  prepareglyph;
+  draw twobar;
+  draw twobar shifted (pw+hh/2,0);
+  finishglyph;
+endfig;
+
+
+beginfig(999);
+
+picture collection []  ;
+
+prepareglyph ;
+draw lefttriangle ;
+finishglyph ;
+collection[201] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw righttriangle ;
+finishglyph ;
+collection[202] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw sidebar ;
+draw lefttriangle shifted (.5s) ;
+finishglyph ;
+collection[203] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw righttriangle ;
+draw sidebar shifted (wt,0) ;
+finishglyph ;
+collection[204] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw sublefttriangle shifted s ;
+draw lefttriangle shifted s ;
+finishglyph ;
+collection[205] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw subrighttriangle ;
+draw righttriangle ;
+finishglyph ;
+collection[206] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw midbar ;
+finishglyph ;
+collection[207] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw onebar ;
+finishglyph ;
+collection[208] := currentpicture ;
+currentpicture := nullpicture ;
+
+prepareglyph ;
+draw twobar ;
+draw twobar shifted (pw+hh/2,0) ;
+finishglyph ;
+collection[209] := currentpicture ;
+currentpicture := nullpicture ;
+
+for i=201 upto 209 :
+  collection[i] := collection[i] shifted - center collection[i] ;
+endfor ;
+
+addto currentpicture also collection[205] shifted (   0,   0)
+  withcolor (.3,.4,.5) ;
+addto currentpicture also collection[202] shifted (   0,1.5h)
+  withcolor (.5,.6,.7) ;
+addto currentpicture also collection[201] shifted (1.5h,   0)
+  withcolor (.6,.7,.8) ;
+addto currentpicture also collection[206] shifted (1.5h,1.5h)
+  withcolor (.4,.5,.6) ;
+
+collection[210] := currentpicture ;
+currentpicture := nullpicture ;
+
+bboxmargin := .25u;
+
+fill bbox collection[210] withcolor .95(1,1,0);
+addto currentpicture also collection[210] ;
+
+endfig ;
+
+end

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-text.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-text.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-text.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,274 @@
+%D \module
+%D   [       file=mp-text.mpii,
+%D        version=2000.07.10,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=text support,
+%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 licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_text : endinput ; fi ;
+
+boolean context_text ; context_text := true ;
+
+if unknown noftexpictures :
+  numeric noftexpictures ; noftexpictures := 0 ;
+fi ;
+
+if unknown texpictures[1] :
+  picture texpictures[] ;
+fi ;
+
+numeric textextoffset ; textextoffset := 0 ;
+
+% vardef textext@#(expr txt) =
+%   interim labeloffset := textextoffset ;
+%   noftexpictures := noftexpictures + 1 ;
+%   if string txt :
+%     write "% figure " & decimal charcode & " : " &
+%       "texpictures[" & decimal noftexpictures & "] := btex " &
+%       txt & " etex ;" to jobname & ".mpt" ;
+%     if unknown texpictures[noftexpictures] :
+%       thelabel@#("unknown",origin)
+%     else :
+%       thelabel@#(texpictures[noftexpictures],origin)
+%     fi
+%   else :
+%     thelabel@#(txt,origin)
+%   fi
+% enddef ;
+
+boolean hobbiestextext ; hobbiestextext := false ;
+% string  textextstring  ; textextstring  := "" ;
+
+% def resettextextdirective =
+%   textextstring := "" ;
+% enddef ;
+
+% def textextdirective text t =
+%   textextstring := textextstring & t ;
+% enddef ;
+
+vardef textext@#(expr txt) =
+  interim labeloffset := textextoffset ;
+  noftexpictures := noftexpictures + 1 ;
+  if string txt :
+    if hobbiestextext : % the tex.mp method as fallback (see tex.mp)
+      write "btex " & txt & " etex" to "mptextmp.mp" ;
+      write EOF to "mptextmp.mp" ;
+      scantokens "input mptextmp"
+    else :
+      write "% figure " & decimal charcode & " : " &
+        "texpictures[" & decimal noftexpictures & "] := btex " &
+        txt & " etex ;" to jobname & ".mpt" ;
+      if unknown texpictures[noftexpictures] :
+        thelabel@#("unknown",origin)
+      else :
+        thelabel@#(texpictures[noftexpictures],origin)
+      fi
+    fi
+  else :
+    thelabel@#(txt,origin)
+  fi
+enddef ;
+
+string laboff_   ; laboff_   := ""      ;
+string laboff_c  ; laboff_c  := ""      ;
+string laboff_l  ; laboff_l  := ".lft"  ;
+string laboff_r  ; laboff_r  := ".rt"   ;
+string laboff_b  ; laboff_b  := ".bot"  ;
+string laboff_t  ; laboff_t  := ".top"  ;
+
+string laboff_lt ; laboff_lt := ".ulft" ;
+string laboff_rt ; laboff_rt := ".urt"  ; % bugged, conflict with r
+string laboff_lb ; laboff_lb := ".llft" ;
+string laboff_rb ; laboff_rb := ".lrt"  ;
+string laboff_tl ; laboff_tl := ".ulft" ;
+string laboff_tr ; laboff_tr := ".urt"  ;
+string laboff_bl ; laboff_bl := ".llft" ;
+string laboff_br ; laboff_br := ".lrt"  ;
+
+vardef textextstr(expr s, a) =
+  save ss ; string ss ;
+  ss := "laboff_" & a  ;
+  ss := scantokens ss ;
+  ss := "textext" & ss & "(" & ditto & s & ditto & ")" ;
+  scantokens ss
+enddef ;
+
+pair laboff.origin ; laboff.origin = (0,0) ; % (infinity,infinity) ;
+pair laboff.raw    ; laboff.raw    = (0,0) ; % (infinity,infinity) ;
+
+laboff.origin = (0,0) ; labxf.origin := 0 ; labyf.origin := 0 ;
+laboff.raw    = (0,0) ; labxf.raw    := 0 ; labyf.raw    := 0 ;
+
+vardef installlabel@# (expr type, x, y, offset) =
+    numeric labtype@# ; labtype@# := type ;
+    pair    laboff @# ; laboff @# := offset ;
+    numeric labxf  @# ; labxf  @# := x ;
+    numeric labyf  @# ; labyf  @# := y ;
+enddef ;
+
+vardef thelabel@#(expr s, z) =
+  save p ; picture p ;
+  p = s if not picture s : infont defaultfont scaled defaultscale fi ;
+%   wrong, see myway textext
+%   if laboff@#<>laboff.origin :
+    (p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p +
+         labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)))
+%   else :
+%     (p shifted z)
+%   fi
+enddef;
+
+def build_parshape (expr p, offset_or_path, dx, dy,
+  baselineskip, strutheight, strutdepth, topskip) =
+
+  if unknown trace_parshape :
+    boolean trace_parshape ; trace_parshape := false ;
+  fi ;
+
+  begingroup ;
+
+  save    q, l, r, line, tt, bb,
+          n, hsize, vsize, vvsize, voffset, hoffset, width, indent,
+          ll, lll, rr, rrr, cp, cq, t, b ;
+
+  path    q, l, r, line, tt, bb ;
+  numeric n, hsize, vsize, vvsize, voffset, hoffset, width[], indent[] ;
+  pair    ll, lll, rr, rrr, cp, cq, t, b ;
+
+  n := 0 ; cp := center p ;
+
+  if path offset_or_path :
+    q := offset_or_path ; cq := center q ;
+    voffset := dy ;
+    hoffset := dx ;
+  else :
+    q := p ; cq := center q ;
+    hoffset := offset_or_path + dx ;
+    voffset := offset_or_path + dy ;
+  fi ;
+
+  hsize := xpart lrcorner q - xpart llcorner q ;
+  vsize := ypart urcorner q - ypart lrcorner q ;
+
+  q := p shifted - cp ;
+
+  startsavingdata ;
+
+  savedata "\global\parvoffset " & decimal voffset&"bp " ;
+  savedata "\global\parhoffset " & decimal hoffset&"bp " ;
+  savedata "\global\parwidth   " & decimal   hsize&"bp " ;
+  savedata "\global\parheight  " & decimal   vsize&"bp " ;
+
+  if not path offset_or_path :
+    q := q xscaled ((hsize-2hoffset)/hsize)
+           yscaled ((vsize-2voffset)/vsize) ;
+  fi ;
+
+  hsize := xpart lrcorner q - xpart llcorner q ;
+  vsize := ypart urcorner q - ypart lrcorner q ;
+
+  t := (ulcorner q -- urcorner q) intersection_point q ;
+  b := (llcorner q -- lrcorner q) intersection_point q ;
+
+  if xpart directionpoint t of q < 0 :
+    q := reverse q ;
+  fi ;
+
+  l := q cutbefore t ;
+  l := l if xpart point 0 of q < 0 : & q fi cutafter b ;
+
+  r := q cutbefore b ;
+  r := r if xpart point 0 of q > 0 : & q fi cutafter t ;
+
+%  tt := (ulcorner q -- urcorner q) shifted (0,-topskip) ;
+%  bb := (llcorner q -- lrcorner q) shifted (0,strutdepth) ;
+%
+%  l := l cutbefore (l intersection_point tt) ;
+%  l := l cutafter  (l intersection_point bb) ;
+%  r := r cutbefore (r intersection_point bb) ;
+%  r := r cutafter  (r intersection_point tt) ;
+
+  if trace_parshape :
+    drawarrow p            withpen pencircle scaled 2pt withcolor red ;
+    drawarrow l shifted cp withpen pencircle scaled 1pt withcolor green ;
+    drawarrow r shifted cp withpen pencircle scaled 1pt withcolor blue ;
+  fi ;
+
+  vardef found_point (expr lin, pat, sig) =
+    pair a, b ;
+    a := pat intersection_point (lin shifted (0,strutheight)) ;
+    if intersection_found :
+      a := a shifted (0,-strutheight) ;
+    else :
+      a := pat intersection_point lin ;
+    fi ;
+    b := pat intersection_point (lin shifted (0,-strutdepth)) ;
+    if intersection_found :
+      if sig :
+        if xpart b > xpart a : a := b shifted (0,strutdepth) fi ;
+      else :
+        if xpart b < xpart a : a := b shifted (0,strutdepth) fi ;
+      fi ;
+    fi ;
+    a
+  enddef ;
+
+  if (strutheight+strutdepth<baselineskip) :
+    vvsize := vsize ;
+  else :
+    vvsize := (vsize div baselineskip) * baselineskip ;
+  fi ;
+
+  for i=topskip step baselineskip until vvsize :
+
+    line := (ulcorner q -- urcorner q) shifted (0,-i-eps) ;
+
+    ll := found_point(line,l,true ) ;
+    rr := found_point(line,r,false) ;
+
+    if trace_parshape :
+      fill (ll--rr--rr shifted (0,strutheight)--ll
+        shifted (0,strutheight)--cycle) shifted cp withcolor .5white ;
+      fill (ll--rr--rr shifted (0,-strutdepth)--ll
+        shifted (0,-strutdepth)--cycle) shifted cp withcolor .7white ;
+      draw ll shifted cp withpen pencircle scaled 2pt ;
+      draw rr shifted cp withpen pencircle scaled 2pt ;
+      draw (ll--rr) shifted cp  withpen pencircle scaled .5pt ;
+    fi ;
+
+    n := n + 1 ;
+    indent[n] := abs(xpart ll - xpart llcorner q) ;
+    width[n]  := abs(xpart rr - xpart ll) ;
+
+    if (i=strutheight) and (width[n]<baselineskip) :
+      n := n - 1 ;
+      savedata "\global\chardef\parfirst=1 " ;
+    fi ;
+
+  endfor ;
+
+  savedata "\global\parlines  " & decimal n ;
+  savedata "\global\partoks{  " ;
+  for i=1 upto n:
+    savedata decimal indent[i]&"bp " & decimal width[i]&"bp " ;
+  endfor ;
+  savedata "}" ;
+
+  stopsavingdata ;
+
+  endgroup ;
+
+enddef ;
+
+vardef verbatim(expr str) =
+    ditto & "\detokenize{" & str & "}" & ditto
+enddef ;

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-tool.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-tool.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-tool.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,2819 @@
+%D \module
+%D   [       file=mp-tool.mpii,
+%D        version=1998.02.15,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=auxiliary macros,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% def loadfile(expr name) = scantokens("input " & name & ";") enddef ;
+
+if known context_tool : endinput ; fi ;
+
+boolean context_tool ; context_tool := true ;
+
+let @## = @# ;
+
+%D New, version number testing:
+%D
+%D \starttyping
+%D fill fullcircle scaled 2cm withcolor if mpversiongt("0.6") : red  else : green fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversionlt(0.6)   : blue else : white fi ;
+%D \stoptyping
+
+if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ;
+
+% newinternal metapostversion ; metapostversion := scantokens(mpversion) ;
+
+newinternal metapostversion ; metapostversion := 2.0 ;
+
+% vardef mpversiongt(expr s) =
+%     scantokens (mpversion & " > " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversionlt(expr s) =
+%     scantokens (mpversion & " < " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversioneq(expr s) =
+%     scantokens (mpversion & " = " & if numeric s : decimal s else : s fi)
+% enddef ;
+
+%D More interesting:
+%D
+%D \starttyping
+%D fill fullcircle scaled 4cm withcolor if mpversiongt("0.6")     : red    else : green fi ;
+%D fill fullcircle scaled 2cm withcolor if mpversionlt(0.6)       : blue   else : white fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversioncmp(0.6,">=") : yellow else : black fi ;
+%D \stoptyping
+
+vardef mpversioncmp(expr s, c) =
+    scantokens (mpversion & c & if numeric s : decimal s else : s fi)
+enddef ;
+
+vardef mpversionlt (expr s) = mpversioncmp(s, "<") enddef ;
+vardef mpversioneq (expr s) = mpversioncmp(s, "=") enddef ;
+vardef mpversiongt (expr s) = mpversioncmp(s, ">") enddef ;
+
+%D We always want \EPS\ conforming output, so we say:
+
+prologues    := 1 ;
+warningcheck := 0 ;
+mpprocset    := 1 ;
+
+%D Namespace handling:
+
+% let exclamationmark = ! ;
+% let questionmark    = ? ;
+%
+% def unprotect =
+%   let ! = relax ;
+%   let ? = relax ;
+% enddef ;
+%
+% def protect =
+%   let ! = exclamationmark ;
+%   let ? = questionmark ;
+% enddef ;
+%
+% unprotect ;
+%
+% mp!some!module = 10 ; show mp!some!module ; show somemodule ;
+%
+% protect ;
+
+string space ; space := char 32 ;
+string CRLF  ; CRLF  := char 10 & char 13 ;
+
+vardef ddecimal primary p =
+    decimal xpart p & " " & decimal ypart p
+enddef ;
+
+%D Plain compatibility:
+
+string plain_compatibility_data ; plain_compatibility_data := "" ;
+
+def startplaincompatibility =
+    begingroup ;
+    scantokens plain_compatibility_data ;
+enddef ;
+
+def stopplaincompatibility =
+    endgroup ;
+enddef ;
+
+% is now built in
+%
+% extra_endfig := extra_endfig
+%   & "special "
+%        & "("
+%        & ditto
+%        & "%%HiResBoundingBox: "
+%        & ditto
+%        & "&ddecimal llcorner currentpicture"
+%        & "&space"
+%        & "&ddecimal urcorner currentpicture"
+%        & ");";
+
+%D More neutral:
+
+let triplet    = rgbcolor ;
+let quadruplet = cmykcolor ;
+
+%D Crap (experimental, not used):
+
+def forcemultipass =
+    % extra_endfig := extra_endfig & "special(" & ditto  & "%%MetaPostOption: multipass" & ditto & ");" ;
+enddef ;
+
+%D Colors:
+
+let grayscale = numeric ;
+let greyscale = numeric ;
+
+vardef colorpart expr c =
+    if not picture c :
+        0
+    elseif colormodel c = greycolormodel :
+        greypart c
+    elseif colormodel c = rgbcolormodel  :
+        (redpart c,greenpart c,bluepart c)
+    elseif colormodel c = cmykcolormodel :
+        (cyanpart c,magentapart c,yellowpart c,blackpart c)
+    else :
+        0 % black
+    fi
+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 :
+            greycolor i ;
+        fi ;
+    endfor ;
+enddef ;
+
+%D Also handy (when we flush colors):
+
+vardef dddecimal primary c =
+    decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c
+enddef ;
+
+vardef ddddecimal primary c =
+    decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c
+enddef ;
+
+vardef colordecimals primary 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
+    else :
+        decimal c
+    fi
+enddef ;
+
+%D We have standardized data file names:
+
+def job_name =
+    jobname
+enddef ;
+
+def data_mpd_file =
+    job_name & "-mp.mpd"
+enddef ;
+
+%D Because \METAPOST\ has a hard coded limit of 4~datafiles,
+%D we need some trickery when we have multiple files.
+
+if unknown collapse_data :
+    boolean collapse_data ;
+    collapse_data := false ;
+fi ;
+
+boolean savingdata     ; savingdata     := false ;
+boolean savingdatadone ; savingdatadone := false ;
+
+def savedata expr txt =
+    write if collapse_data :
+        txt
+    else :
+        if savingdata : txt else : "\MPdata{" & decimal charcode & "}{" & txt & "}" fi & "%"
+    fi to data_mpd_file ;
+enddef ;
+
+def startsavingdata =
+    savingdata := true ;
+    savingdatadone := true ;
+    if collapse_data :
+        write "\MPdata{" & decimal charcode & "}{%" to data_mpd_file ;
+    fi ;
+enddef ;
+
+def stopsavingdata =
+    if collapse_data :
+        write "}%" to data_mpd_file ;
+    fi ;
+    savingdata := false ;
+enddef ;
+
+def finishsavingdata =
+    if savingdatadone :
+        write EOF to data_mpd_file ;
+        savingdatadone := false ;
+    fi ;
+enddef ;
+
+%D Instead of a keystroke eating save and allocation
+%D sequence, you can use the \citeer {new} alternatives to
+%D save and allocate in one command.
+
+def newcolor     text v = forsuffixes i=v : save i ; color     i ; endfor ; enddef ;
+def newnumeric   text v = forsuffixes i=v : save i ; numeric   i ; endfor ; enddef ;
+def newboolean   text v = forsuffixes i=v : save i ; boolean   i ; endfor ; enddef ;
+def newtransform text v = forsuffixes i=v : save i ; transform i ; endfor ; enddef ;
+def newpath      text v = forsuffixes i=v : save i ; path      i ; endfor ; enddef ;
+def newpicture   text v = forsuffixes i=v : save i ; picture   i ; endfor ; enddef ;
+def newstring    text v = forsuffixes i=v : save i ; string    i ; endfor ; enddef ;
+def newpair      text v = forsuffixes i=v : save i ; pair      i ; endfor ; enddef ;
+
+%D Sometimes we don't want parts of the graphics add to the
+%D bounding box. One way of doing this is to save the bounding
+%D box, draw the graphics that may not count, and restore the
+%D bounding box.
+%D
+%D \starttyping
+%D push_boundingbox currentpicture;
+%D pop_boundingbox currentpicture;
+%D \stoptyping
+%D
+%D The bounding box can be called with:
+%D
+%D \starttyping
+%D boundingbox currentpicture
+%D inner_boundingbox currentpicture
+%D outer_boundingbox currentpicture
+%D \stoptyping
+%D
+%D Especially the latter one can be of use when we include
+%D the graphic in a document that is clipped to the bounding
+%D box. In such occasions one can use:
+%D
+%D \starttyping
+%D set_outer_boundingbox currentpicture;
+%D \stoptyping
+%D
+%D Its counterpart is:
+%D
+%D \starttyping
+%D set_inner_boundingbox p
+%D \stoptyping
+
+path    mfun_boundingbox_stack ;
+numeric mfun_boundingbox_stack_depth ;
+
+mfun_boundingbox_stack_depth := 0 ;
+
+def pushboundingbox text p =
+    mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth + 1 ;
+    mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := boundingbox p ;
+enddef ;
+
+def popboundingbox text p =
+    setbounds p to mfun_boundingbox_stack[mfun_boundingbox_stack_depth] ;
+    mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := origin ;
+    mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth - 1 ;
+enddef ;
+
+let push_boundingbox = pushboundingbox ; % downward compatible
+let pop_boundingbox  = popboundingbox  ; % downward compatible
+
+vardef boundingbox primary p =
+    if (path p) or (picture p) :
+        llcorner p -- lrcorner p -- urcorner p -- ulcorner  p
+    else :
+        origin
+    fi -- cycle
+enddef;
+
+vardef innerboundingbox primary p =
+    top  rt llcorner p --
+    top lft lrcorner p --
+    bot lft urcorner p --
+    bot  rt ulcorner p -- cycle
+enddef;
+
+vardef outerboundingbox primary p =
+    bot lft llcorner p --
+    bot  rt lrcorner p --
+    top  rt urcorner p --
+    top lft ulcorner p -- cycle
+enddef;
+
+def inner_boundingbox = innerboundingbox enddef ;
+def outer_boundingbox = outerboundingbox enddef ;
+
+vardef set_inner_boundingbox text q = % obsolete
+    setbounds q to innerboundingbox q;
+enddef;
+
+vardef set_outer_boundingbox text q = % obsolete
+    setbounds q to outerboundingbox q;
+enddef;
+
+%D Some missing functions can be implemented rather straightforward (thanks to
+%D Taco and others):
+
+pi := 3.14159265358979323846 ; radian := 180/pi ; % 2pi*radian = 360 ;
+
+% let +++ = ++ ;
+
+numeric Pi ; Pi := pi ; % for some old compatibility reasons i guess
+
+vardef sqr  primary x = x*x                                 enddef ;
+vardef log  primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ;
+vardef ln   primary x = if x=0: 0 else: mlog(x)/256 fi      enddef ;
+vardef exp  primary x = (mexp 256)**x                       enddef ;
+vardef inv  primary x = if x=0: 0 else: x**-1 fi            enddef ;
+
+vardef pow (expr x,p) = x**p                                enddef ;
+
+vardef tand   primary x = sind(x)/cosd(x)  enddef ;
+vardef cotd   primary x = cosd(x)/sind(x)  enddef ;
+
+vardef sin    primary x = sind(x*radian)   enddef ;
+vardef cos    primary x = cosd(x*radian)   enddef ;
+vardef tan    primary x = sin(x)/cos(x)    enddef ;
+vardef cot    primary x = cos(x)/sin(x)    enddef ;
+
+vardef asin   primary x = angle((1+-+x,x)) enddef ;
+vardef acos   primary x = angle((x,1+-+x)) enddef ;
+vardef atan   primary x = angle(1,x)       enddef ;
+
+vardef invsin primary x = (asin(x))/radian enddef ;
+vardef invcos primary x = (acos(x))/radian enddef ;
+vardef invtan primary x = (atan(x))/radian enddef ;
+
+vardef acosh  primary x = ln(x+(x+-+1))    enddef ;
+vardef asinh  primary x = ln(x+(x++1))     enddef ;
+
+vardef sinh   primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ;
+vardef cosh   primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ;
+
+%D Sometimes this is handy:
+
+def undashed =
+    dashed nullpicture
+enddef ;
+
+%D We provide two macros for drawing stripes across a shape.
+%D The first method (with the n suffix) uses another method,
+%D slower in calculation, but more efficient when drawn. The
+%D first macro divides the sides into n equal parts. The
+%D first argument specifies the way the lines are drawn, while
+%D the second argument identifier the way the shape is to be
+%D drawn.
+%D
+%D \starttyping
+%D stripe_path_n
+%D   (dashed evenly withcolor blue)
+%D   (filldraw)
+%D   fullcircle xscaled 100 yscaled 40 shifted (50,50) withpen pencircle scaled 4;
+%D \stoptyping
+%D
+%D The a (or angle) alternative supports arbitrary angles and
+%D is therefore more versatile.
+%D
+%D \starttyping
+%D stripe_path_a
+%D   (withpen pencircle scaled 2 withcolor red)
+%D   (draw)
+%D   fullcircle xscaled 100 yscaled 40 withcolor blue;
+%D \stoptyping
+%D
+%D We have two alternatives, controlled by arguments or defaults (when arguments
+%D are zero).
+%D
+%D The newer and nicer interface is used as follows (triggered by a question by Mari):
+%D
+%D \starttyping
+%D draw image (draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green) numberstriped (1,10,3) withcolor red ;
+%D draw image (draw fullcircle scaled 3cm shifted (3cm,0cm) withcolor green) numberstriped (2,20,3) withcolor green ;
+%D draw image (draw fullcircle scaled 3cm shifted (3cm,3cm) withcolor green) numberstriped (3,10,5) withcolor blue ;
+%D draw image (draw fullcircle scaled 3cm shifted (0cm,3cm) withcolor green) numberstriped (4,20,5) withcolor yellow ;
+%D
+%D draw image (draw fullcircle scaled 3cm shifted (6cm,0cm) withcolor green) anglestriped (1,20,2) withcolor red ;
+%D draw image (draw fullcircle scaled 3cm shifted (9cm,0cm) withcolor green) anglestriped (2,40,2) withcolor green ;
+%D draw image (draw fullcircle scaled 3cm shifted (9cm,3cm) withcolor green) anglestriped (3,60,2) withcolor blue ;
+%D draw image (draw fullcircle scaled 3cm shifted (6cm,3cm) withcolor green) anglestriped (4,80,2) withcolor yellow ;
+%D
+%D draw image (
+%D     draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ;
+%D     draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue  withpen pencircle scaled 3mm ;
+%D ) shifted (9cm,0cm) numberstriped (1,10,3) withcolor red ;
+%D
+%D draw image (
+%D     draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green  withpen pencircle scaled 2mm ;
+%D     draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue   withpen pencircle scaled 3mm ;
+%D ) shifted (12cm,0cm) numberstriped (2,10,3) withcolor red ;
+%D
+%D draw image (
+%D     draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green  withpen pencircle scaled 2mm ;
+%D     draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue   withpen pencircle scaled 3mm ;
+%D ) shifted (9cm,5cm) numberstriped (3,10,3) withcolor red ;
+%D
+%D draw image (
+%D     draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green  withpen pencircle scaled 2mm ;
+%D     draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue   withpen pencircle scaled 3mm ;
+%D ) shifted (12cm,5cm) numberstriped (4,10,3) withcolor red ;
+%D \stoptyping
+
+stripe_n     := 10;
+stripe_slot  :=  3;
+stripe_gap   :=  5;
+stripe_angle := 45;
+
+def mfun_tool_striped_number_action text extra =
+    for i = 1/used_n step 1/used_n until 1 :
+        draw point (1+i) of bounds -- point (3-i) of bounds withpen pencircle scaled penwidth extra ;
+    endfor ;
+    for i = 0 step 1/used_n until 1 :
+        draw point (3+i) of bounds -- point (1-i) of bounds withpen pencircle scaled penwidth extra ;
+    endfor ;
+enddef ;
+
+def mfun_tool_striped_set_options(expr option) =
+    save isinner, swapped ;
+    boolean isinner, swapped ;
+    if option = 1 :
+        isinner := false ;
+        swapped := false ;
+    elseif option = 2 :
+        isinner := true ;
+        swapped := false ;
+    elseif option = 3 :
+        isinner := false ;
+        swapped := true ;
+    elseif option = 4 :
+        isinner := true ;
+        swapped := true ;
+    else :
+        isinner := false ;
+        swapped := false ;
+    fi ;
+enddef ;
+
+vardef mfun_tool_striped_number(expr option, p, s_n, s_slot) text extra =
+    image (
+        begingroup ;
+        save pattern, shape, bounds, penwidth, used_n, used_slot ;
+        picture pattern, shape ; path bounds ; numeric used_s, used_slot ;
+        mfun_tool_striped_set_options(option) ;
+        used_slot := if s_slot = 0 : stripe_slot else : s_slot fi ;
+        used_n := if s_n = 0 : stripe_n else : s_n fi ;
+        shape := image(draw p) ;
+        bounds := boundingbox shape ;
+        penwidth := min(ypart urcorner shape - ypart llcorner shape, xpart urcorner shape - xpart llcorner shape) / (used_slot * used_n) ;
+        pattern := image (
+            if isinner :
+                mfun_tool_striped_number_action extra ;
+                for s within shape :
+                    if stroked s or filled s :
+                        clip currentpicture to pathpart s ;
+                    fi
+                endfor ;
+            else :
+                for s within shape :
+                    if stroked s or filled s :
+                        draw image (
+                            mfun_tool_striped_number_action extra ;
+                            clip currentpicture to pathpart s ;
+                        ) ;
+                    fi ;
+                endfor ;
+            fi ;
+        ) ;
+        if swapped :
+            addto currentpicture also shape ;
+            addto currentpicture also pattern ;
+        else :
+            addto currentpicture also pattern ;
+            addto currentpicture also shape ;
+        fi ;
+        endgroup ;
+    )
+enddef ;
+
+def mfun_tool_striped_angle_action text extra =
+    for i = minimum -.5used_gap step used_gap until maximum :
+        draw (minimum,i) -- (maximum,i) extra ;
+    endfor ;
+    currentpicture := currentpicture rotated used_angle ;
+enddef ;
+
+vardef mfun_tool_striped_angle(expr option, p, s_angle, s_gap) text extra =
+    image (
+        begingroup ;
+        save pattern, shape, mask, maximum, minimum, centrum, used_angle, used_gap ;
+        picture pattern, shape, mask ; numeric maximum, minimum ; pair centrum ; numeric used_angle, used_gap ;
+        mfun_tool_striped_set_options(option) ;
+        used_angle := if s_angle = 0 : stripe_angle else : s_angle fi ;
+        used_gap := if s_gap = 0 : stripe_gap else : s_gap fi ;
+        shape := image(draw p) ;
+        centrum := center shape ;
+        shape := shape shifted - centrum ;
+        mask := shape rotated used_angle ;
+        maximum := max (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ;
+        minimum := min (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ;
+        pattern := image (
+            if isinner :
+                mfun_tool_striped_angle_action extra ;
+                for s within shape :
+                    if stroked s or filled s :
+                        clip currentpicture to pathpart s ;
+                    fi
+                endfor ;
+            else :
+                for s within shape :
+                    if stroked s or filled s :
+                        draw image (
+                            mfun_tool_striped_angle_action extra ;
+                            clip currentpicture to pathpart s ;
+                        ) ;
+                    fi ;
+                endfor ;
+            fi ;
+        ) ;
+        if swapped :
+            addto currentpicture also shape ;
+            addto currentpicture also pattern ;
+        else :
+            addto currentpicture also pattern ;
+            addto currentpicture also shape ;
+        fi ;
+        currentpicture := currentpicture shifted centrum ;
+        endgroup ;
+    )
+enddef;
+
+newinternal striped_normal_inner  ; striped_normal_inner  := 1 ;
+newinternal striped_reverse_inner ; striped_reverse_inner := 2 ;
+newinternal striped_normal_outer  ; striped_normal_outer  := 3 ;
+newinternal striped_reverse_outer ; striped_reverse_outer := 4 ;
+
+secondarydef p anglestriped s =
+    mfun_tool_striped_angle(redpart s,p,greenpart s,bluepart s)
+enddef ;
+
+secondarydef p numberstriped s =
+    mfun_tool_striped_number(redpart s,p,greenpart s,bluepart s)
+enddef ;
+
+% for old times sake:
+
+def stripe_path_n (text s_spec) (text s_draw) expr s_path =
+    do_stripe_path_n (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_n (text s_spec) (text s_draw) (expr s_path) text s_text =
+    draw image(s_draw s_path s_text) numberstriped(3,0,0) s_spec ;
+enddef ;
+
+def stripe_path_a (text s_spec) (text s_draw) expr s_path =
+    do_stripe_path_a (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_a (text s_spec) (text s_draw) (expr s_path) text s_text =
+    draw image(s_draw s_path s_text) anglestriped(3,0,0) s_spec ;
+enddef ;
+
+%D A few normalizing macros:
+%D
+%D \starttypen
+%D xscale_currentpicture  ( width )
+%D yscale_currentpicture  ( height )
+%D xyscale_currentpicture ( width, height )
+%D scale_currentpicture   ( width, height )
+%D \stoptypen
+
+% def xscale_currentpicture(expr the_width) =
+%   natural_width  := xpart urcorner currentpicture - xpart llcorner currentpicture;
+%   currentpicture := currentpicture scaled (the_width/natural_width) ;
+% enddef;
+%
+% def yscale_currentpicture(expr the_height ) =
+%   natural_height := ypart urcorner currentpicture - ypart llcorner currentpicture;
+%   currentpicture := currentpicture scaled (the_height/natural_height) ;
+% enddef;
+%
+% def xyscale_currentpicture(expr the_width, the_height) =
+%   natural_width  := xpart urcorner currentpicture - xpart llcorner currentpicture;
+%   natural_height := ypart urcorner currentpicture - ypart llcorner currentpicture;
+%   currentpicture := currentpicture
+%     xscaled (the_width/natural_width)
+%     yscaled (the_height/natural_height) ;
+% enddef;
+%
+% def scale_currentpicture(expr the_width, the_height) =
+%   xscale_currentpicture(the_width) ;
+%   yscale_currentpicture(the_height) ;
+% enddef;
+
+% nog eens uitbreiden zodat path en pic worden afgehandeld.
+
+%   natural_width  := xpart urcorner currentpicture - xpart llcorner currentpicture;
+%   currentpicture := currentpicture scaled (the_width/natural_width) ;
+
+primarydef p xsized w =
+    (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi)
+enddef ;
+
+primarydef p ysized h =
+    (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi)
+enddef ;
+
+primarydef p xysized s =
+    begingroup
+    save wh, w, h ; pair wh ; numeric w, h ;
+    wh := paired (s) ; w := bbwidth(p) ; h := bbheight(p) ;
+    p
+        if (w>0) and (h>0) :
+            if xpart wh > 0 : xscaled (xpart wh/w) fi
+            if ypart wh > 0 : yscaled (ypart wh/h) fi
+        fi
+    endgroup
+enddef ;
+
+let sized = xysized ;
+
+def xscale_currentpicture(expr w) = % obsolete
+    currentpicture := currentpicture xsized w ;
+enddef;
+
+def yscale_currentpicture(expr h) = % obsolete
+    currentpicture := currentpicture ysized h ;
+enddef;
+
+def xyscale_currentpicture(expr w, h) = % obsolete
+    currentpicture := currentpicture xysized (w,h) ;
+enddef;
+
+def scale_currentpicture(expr w, h) = % obsolete
+    currentpicture := currentpicture xsized w ;
+    currentpicture := currentpicture ysized h ;
+enddef;
+
+%D A full circle is centered at the origin, while a unitsquare
+%D is located in the first quadrant. Now guess what kind of
+%D path fullsquare and unitcircle do return.
+
+path fullsquare, unitcircle ;
+
+fullsquare := unitsquare shifted - center unitsquare ;
+unitcircle := fullcircle shifted urcorner fullcircle ;
+
+%D Some more paths:
+
+path urcircle, ulcircle, llcircle, lrcircle ;
+
+urcircle := origin -- (+.5,0) & (+.5,0){up}    .. (0,+.5) & (0,+.5) -- cycle ;
+ulcircle := origin -- (0,+.5) & (0,+.5){left}  .. (-.5,0) & (-.5,0) -- cycle ;
+llcircle := origin -- (-.5,0) & (-.5,0){down}  .. (0,-.5) & (0,-.5) -- cycle ;
+lrcircle := origin -- (0,-.5) & (0,-.5){right} .. (+.5,0) & (+.5,0) -- cycle ;
+
+path tcircle, bcircle, lcircle, rcircle ;
+
+tcircle = origin -- (+.5,0) & (+.5,0) {up}    .. (0,+.5) .. {down}  (-.5,0) -- cycle ;
+bcircle = origin -- (-.5,0) & (-.5,0) {down}  .. (0,-.5) .. {up}    (+.5,0) -- cycle ;
+lcircle = origin -- (0,+.5) & (0,+.5) {left}  .. (-.5,0) .. {right} (0,-.5) -- cycle ;
+rcircle = origin -- (0,-.5) & (0,-.5) {right} .. (+.5,0) .. {left}  (0,+.5) -- cycle ;
+
+path urtriangle, ultriangle, lltriangle, lrtriangle ; % watch out: it's contrary to what you expect and starts in the origin
+
+urtriangle := origin -- (+.5,0) -- (0,+.5) -- cycle ;
+ultriangle := origin -- (0,+.5) -- (-.5,0) -- cycle ;
+lltriangle := origin -- (-.5,0) -- (0,-.5) -- cycle ;
+lrtriangle := origin -- (0,-.5) -- (+.5,0) -- cycle ;
+
+path unitdiamond, fulldiamond ;
+
+unitdiamond := (.5,0) -- (1,.5) -- (.5,1) -- (0,.5) -- cycle ;
+fulldiamond := unitdiamond shifted - center unitdiamond ;
+
+%D More robust:
+
+% let  normalscaled =  scaled ;
+% let normalxscaled = xscaled ;
+% let normalyscaled = yscaled ;
+%
+% def  scaled expr s =  normalscaled (s) enddef ;
+% def xscaled expr s = normalxscaled (s) enddef ;
+% def yscaled expr s = normalyscaled (s) enddef ;
+
+%D Shorter
+
+primarydef p xyscaled q = % secundarydef does not work out well
+    begingroup
+    save qq ; pair qq ;
+    qq = paired(q) ;
+    p
+        if xpart qq <> 0 : xscaled (xpart qq) fi
+        if ypart qq <> 0 : yscaled (ypart qq) fi
+    endgroup
+enddef ;
+
+%D Some personal code that might move to another module
+
+def set_grid(expr w, h, nx, ny) =
+    boolean grid[][] ; boolean grid_full ;
+    numeric grid_w, grid_h, grid_nx, grid_ny, grid_x, grid_y, grid_left ;
+    grid_w := w ;
+    grid_h := h ;
+    grid_nx := nx ;
+    grid_ny := ny ;
+    grid_x := round(w/grid_nx) ; % +.5) ;
+    grid_y := round(h/grid_ny) ; % +.5) ;
+    grid_left := (1+grid_x)*(1+grid_y) ;
+    grid_full := false ;
+    for i=0 upto grid_x :
+        for j=0 upto grid_y :
+            grid[i][j] := false ;
+        endfor ;
+    endfor ;
+enddef ;
+
+vardef new_on_grid(expr _dx_, _dy_) =
+    dx := _dx_ ;
+    dy := _dy_ ;
+    ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ;
+    ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ;
+    if not grid_full and not grid[ddx][ddy] :
+        grid[ddx][ddy] := true ;
+        grid_left := grid_left-1 ;
+        grid_full := (grid_left=0) ;
+        true
+    else :
+        false
+    fi
+enddef ;
+
+%D usage: \type{innerpath peepholed outerpath}.
+%D
+%D beginfig(1);
+%D   def fullsquare = (unitsquare shifted -center unitsquare) enddef ;
+%D   fill (fullsquare scaled 200) withcolor red ;
+%D   path p ; p := (fullcircle scaled 100) ; bboxmargin := 0 ;
+%D   fill p peepholed bbox p ;
+%D endfig;
+
+secondarydef p peepholed q =
+    begingroup
+    save start ; pair start ;
+    start := point 0 of p ;
+    if xpart start >= xpart center p :
+        if ypart start >= ypart center p :
+            urcorner q -- ulcorner q -- llcorner q -- lrcorner q --
+            reverse  p -- lrcorner q -- cycle
+        else :
+            lrcorner q -- urcorner q -- ulcorner q -- llcorner q --
+            reverse  p -- llcorner q -- cycle
+        fi
+    else :
+        if ypart start > ypart center p :
+            ulcorner q -- llcorner q -- lrcorner q -- urcorner q --
+            reverse  p -- urcorner q -- cycle
+        else :
+            llcorner q -- lrcorner q -- urcorner q -- ulcorner q --
+            reverse  p -- ulcorner q -- cycle
+        fi
+    fi
+    endgroup
+enddef ;
+
+boolean intersection_found ;
+
+secondarydef p intersection_point q =
+    begingroup
+    save x_, y_ ;
+    (x_,y_) = p intersectiontimes q ;
+    if x_<0 :
+        intersection_found := false ;
+        center p % origin
+    else :
+        intersection_found := true ;
+        .5[point x_ of p, point y_ of q]
+    fi
+    endgroup
+enddef ;
+
+%D New, undocumented, experimental:
+
+vardef tensecircle (expr width, height, offset) =
+    (-width/2,-height/2) ... (0,-height/2-offset) ...
+    (+width/2,-height/2) ... (+width/2+offset,0)  ...
+    (+width/2,+height/2) ... (0,+height/2+offset) ...
+    (-width/2,+height/2) ... (-width/2-offset,0)  ... cycle
+enddef ;
+
+vardef roundedsquare (expr width, height, offset) =
+    (offset,0)            -- (width-offset,0)      {right} ..
+    (width,offset)        -- (width,height-offset) {up}    ..
+    (width-offset,height) -- (offset,height)       {left}  ..
+    (0,height-offset)     -- (0,offset)            {down}  .. cycle
+enddef ;
+
+%D Some colors.
+
+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 =
+    fill t ;
+    draw t ;
+enddef;
+
+%D This two step approach saves the path first, since it can
+%D be a function. Attributes must not be randomized.
+
+def drawfill expr c =
+    path _c_ ; _c_ := c ;
+    mfun_do_drawfill
+enddef ;
+
+def mfun_do_drawfill text t =
+    draw _c_ t ;
+    fill _c_ t ;
+enddef;
+
+def undrawfill expr c =
+    drawfill c withcolor background % rather useless
+enddef ;
+
+%D Moved from mp-char.mp
+
+vardef paired primary d =
+    if pair d : d else : (d,d) fi
+enddef ;
+
+vardef tripled primary d =
+    if color d : d else : (d,d,d) fi
+enddef ;
+
+% maybe secondaries:
+
+primarydef p enlarged       d = ( p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle ) enddef ;
+primarydef p llenlarged     d = ( p llmoved d -- lrcorner p  -- urcorner p  -- ulcorner p  -- cycle ) enddef ;
+primarydef p lrenlarged     d = ( llcorner p  -- p lrmoved d -- urcorner p  -- ulcorner p  -- cycle ) enddef ;
+primarydef p urenlarged     d = ( llcorner p  -- lrcorner p  -- p urmoved d -- ulcorner p  -- cycle ) enddef ;
+primarydef p ulenlarged     d = ( llcorner p  -- lrcorner p  -- urcorner p  -- p ulmoved d -- cycle ) enddef ;
+
+primarydef p llmoved        d = ( (llcorner p) shifted (-xpart paired(d),-ypart paired(d)) ) enddef ;
+primarydef p lrmoved        d = ( (lrcorner p) shifted (+xpart paired(d),-ypart paired(d)) ) enddef ;
+primarydef p urmoved        d = ( (urcorner p) shifted (+xpart paired(d),+ypart paired(d)) ) enddef ;
+primarydef p ulmoved        d = ( (ulcorner p) shifted (-xpart paired(d),+ypart paired(d)) ) enddef ;
+
+primarydef p leftenlarged   d = ( (llcorner p) shifted (-d,0) -- lrcorner p -- urcorner p -- (ulcorner p) shifted (-d,0) -- cycle ) enddef ;
+primarydef p rightenlarged  d = ( llcorner p -- (lrcorner p) shifted (d,0) -- (urcorner p) shifted (d,0) -- ulcorner p -- cycle   ) enddef ;
+primarydef p topenlarged    d = ( llcorner p -- lrcorner p -- (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle   ) enddef ;
+primarydef p bottomenlarged d = ( llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- urcorner p -- ulcorner p -- cycle     ) enddef ;
+
+%D Handy for testing/debugging:
+
+primarydef p crossed d = (
+    if pair p :
+        p shifted (-d, 0) -- p --
+        p shifted ( 0,-d) -- p --
+        p shifted (+d, 0) -- p --
+        p shifted ( 0,+d) -- p -- cycle
+    else :
+        center p shifted (-d, 0) -- llcorner p --
+        center p shifted ( 0,-d) -- lrcorner p --
+        center p shifted (+d, 0) -- urcorner p --
+        center p shifted ( 0,+d) -- ulcorner p -- cycle
+    fi
+) enddef ;
+
+%D Also handy (math ladders):
+
+vardef laddered primary p = % was expr
+    point 0 of p
+    for i=1 upto length(p) :
+        -- (xpart (point i of p), ypart (point (i-1) of p)) -- (point i of p)
+    endfor
+enddef ;
+
+%D Saves typing:
+
+% vardef bottomboundary primary p = (llcorner p -- lrcorner p) enddef ;
+% vardef rightboundary  primary p = (lrcorner p -- urcorner p) enddef ;
+% vardef topboundary    primary p = (urcorner p -- ulcorner p) enddef ;
+% vardef leftboundary   primary p = (ulcorner p -- llcorner p) enddef ;
+
+vardef bottomboundary primary p = if pair p : p else : (llcorner p -- lrcorner p) fi enddef ;
+vardef rightboundary  primary p = if pair p : p else : (lrcorner p -- urcorner p) fi enddef ;
+vardef topboundary    primary p = if pair p : p else : (urcorner p -- ulcorner p) fi enddef ;
+vardef leftboundary   primary p = if pair p : p else : (ulcorner p -- llcorner p) fi enddef ;
+
+%D Nice too:
+
+primarydef p superellipsed s =
+    superellipse (
+        .5[lrcorner p,urcorner p],
+        .5[urcorner p,ulcorner p],
+        .5[ulcorner p,llcorner p],
+        .5[llcorner p,lrcorner p],
+        s
+    )
+enddef ;
+
+primarydef p squeezed s = (
+    (llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) &
+    (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) &
+    (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) &
+    (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle
+) enddef ;
+
+primarydef p randomshifted s =
+    begingroup ;
+    save ss ; pair ss ;
+    ss := paired(s) ;
+    p shifted (-.5xpart ss + uniformdeviate xpart ss,-.5ypart ss + uniformdeviate ypart ss)
+    endgroup
+enddef ;
+
+primarydef p randomized s = (
+    if path p :
+        for i=0 upto length(p)-1 :
+            ((point       i    of p) randomshifted s) .. controls
+            ((postcontrol i    of p) randomshifted s) and
+            ((precontrol (i+1) of p) randomshifted s) ..
+        endfor
+        if cycle p :
+            cycle
+        else :
+            ((point length(p) of p) randomshifted s)
+        fi
+    elseif pair p :
+        p randomshifted s
+    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,
+            (uniformdeviate bluepart  s) * bluepart  p)
+        elseif pair s :
+           ((xpart s + (uniformdeviate (ypart s - xpart s))) * p)
+        else :
+           ((uniformdeviate s) * p)
+        fi
+    elseif color p :
+        if color s :
+            ((uniformdeviate greypart s) * greypart p)
+        elseif pair s :
+            ((xpart s + (uniformdeviate (ypart s - xpart s))) * p)
+        else :
+            ((uniformdeviate s) * p)
+        fi
+    else :
+        p + uniformdeviate s
+    fi
+) enddef ;
+
+%D Not perfect (alternative for interpath)
+
+vardef interpolated(expr s, p, q) =
+    save m ; numeric m ;
+    m := max(length(p),length(q)) ;
+    if path p :
+        for i=0 upto m-1 :
+            s[point       (i   /m) along p,point       (i   /m) along q] .. controls
+            s[postcontrol (i   /m) along p,postcontrol (i   /m) along q] and
+            s[precontrol ((i+1)/m) along p,precontrol ((i+1)/m) along q] ..
+        endfor
+        if cycle p :
+            cycle
+        else :
+            s[point infinity of p,point infinity of q]
+        fi
+    else :
+        a[p,q]
+    fi
+enddef ;
+
+%D Interesting too:
+
+primarydef p paralleled d = (
+    p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p)
+) enddef ;
+
+vardef punked primary p =
+    point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor
+    if cycle p : -- cycle else : -- point length(p) of p fi
+enddef ;
+
+vardef curved primary p =
+    point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor
+    if cycle p : .. cycle else : .. point length(p) of p fi
+enddef ;
+
+primarydef p blownup s =
+    begingroup
+        save _p_ ; path _p_ ;
+        _p_ := p xysized (bbwidth(p)+2(xpart paired(s)),bbheight(p)+2(ypart paired(s))) ;
+        (_p_ shifted (center p - center _p_))
+    endgroup
+enddef ;
+
+%D Rather fundamental.
+
+% not yet ok
+
+vardef leftrightpath(expr p, l) = % used in s-pre-19
+    save q, r, t, b ; path q, r ; pair t, b ;
+    t := (ulcorner p -- urcorner p) intersection_point p ;
+    b := (llcorner p -- lrcorner p) intersection_point p ;
+    r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed
+    q := r cutbefore if l: t else: b fi ;
+    q := q if xpart point 0 of r > 0 : & r fi cutafter  if l: b else: t fi ;
+    q
+enddef ;
+
+vardef  leftpath expr p = leftrightpath(p,true ) enddef ;
+vardef rightpath expr p = leftrightpath(p,false) enddef ;
+
+%D Drawoptions
+
+def saveoptions =
+    save _op_ ; def _op_ = enddef ;
+enddef ;
+
+%D Tracing. (not yet in lexer)
+
+let normaldraw = draw ;
+let normalfill = fill ;
+
+% bugged in mplib so ...
+
+def normalfill expr c = addto currentpicture contour c _op_ enddef ;
+def normaldraw expr p = addto currentpicture if picture p: also p else: doublepath p withpen currentpen fi _op_ enddef ;
+
+def drawlineoptions   (text t) = def _lin_opt_ = t enddef ; enddef ;
+def drawpointoptions  (text t) = def _pnt_opt_ = t enddef ; enddef ;
+def drawcontroloptions(text t) = def _ctr_opt_ = t enddef ; enddef ;
+def drawlabeloptions  (text t) = def _lab_opt_ = t enddef ; enddef ;
+def draworiginoptions (text t) = def _ori_opt_ = t enddef ; enddef ;
+def drawboundoptions  (text t) = def _bnd_opt_ = t enddef ; enddef ;
+def drawpathoptions   (text t) = def _pth_opt_ = t enddef ; enddef ;
+
+def resetdrawoptions =
+    drawlineoptions   (withpen pencircle scaled 1pt   withcolor .5white) ;
+    drawpointoptions  (withpen pencircle scaled 4pt   withcolor   black) ;
+    drawcontroloptions(withpen pencircle scaled 2.5pt withcolor   black) ;
+    drawlabeloptions  () ;
+    draworiginoptions (withpen pencircle scaled 1pt   withcolor .5white) ;
+    drawboundoptions  (dashed evenly _ori_opt_) ;
+    drawpathoptions   (withpen pencircle scaled 5pt   withcolor .8white) ;
+enddef ;
+
+resetdrawoptions ;
+
+%D Path.
+
+def drawpath expr p =
+    normaldraw p _pth_opt_
+enddef ;
+
+%D Arrow.
+
+vardef drawarrowpath expr p =
+    save autoarrows ; boolean autoarrows ; autoarrows := true ;
+    drawarrow p _pth_opt_
+enddef ;
+
+% def drawarrowpath expr p =
+%   begingroup ;
+%   save autoarrows ; boolean autoarrows ; autoarrows := true ;
+%   save arrowpath ; path arrowpath ; arrowpath := p ;
+%   _drawarrowpath_
+% enddef ;
+%
+% def _drawarrowpath_ text t =
+%   drawarrow arrowpath _pth_opt_ t ;
+%   endgroup ;
+% enddef ;
+
+def midarrowhead expr p =
+    arrowhead p cutafter (point length(p cutafter point .5 along p)+ahlength on p)
+enddef ;
+
+vardef arrowheadonpath (expr p, s) =
+    save autoarrows ; boolean autoarrows ;
+    autoarrows := true ;
+    set_ahlength(scaled ahfactor) ; % added
+    arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi
+enddef ;
+
+%D Points.
+
+def drawpoint expr c =
+    if string c :
+        string _c_ ;
+        _c_ := "(" & c & ")" ;
+        dotlabel.urt(_c_, scantokens _c_) ;
+        drawdot scantokens _c_
+    else :
+        dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ;
+        drawdot c
+    fi _pnt_opt_
+enddef ;
+
+%D PathPoints.
+
+def drawpoints        expr c = path _c_ ; _c_ := c ; mfun_draw_points        enddef ;
+def drawcontrolpoints expr c = path _c_ ; _c_ := c ; mfun_draw_controlpoints enddef ;
+def drawcontrollines  expr c = path _c_ ; _c_ := c ; mfun_draw_controllines  enddef ;
+def drawpointlabels   expr c = path _c_ ; _c_ := c ; mfun_draw_pointlabels   enddef ;
+
+def mfun_draw_points text t =
+    for _i_=0 upto length(_c_) :
+        normaldraw point _i_ of _c_ _pnt_opt_ t ;
+    endfor ;
+enddef;
+
+def mfun_draw_controlpoints text t =
+    for _i_=0 upto length(_c_) :
+        normaldraw precontrol  _i_ of _c_ _ctr_opt_ t ;
+        normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ;
+    endfor ;
+enddef;
+
+def mfun_draw_controllines text t =
+    for _i_=0 upto length(_c_) :
+        normaldraw point _i_ of _c_ -- precontrol  _i_ of _c_ _lin_opt_ t ;
+        normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ;
+    endfor ;
+enddef;
+
+boolean swappointlabels ; swappointlabels := false ;
+
+def mfun_draw_pointlabels text t =
+    for _i_=0 upto length(_c_) :
+        pair _u_ ; _u_ := unitvector(direction _i_ of _c_) rotated if swappointlabels : - fi 90 ;
+        pair _p_ ; _p_ := (point _i_ of _c_) ;
+        _u_ := 12 * defaultscale * _u_ ;
+        normaldraw thelabel ( decimal _i_, _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ;
+    endfor ;
+enddef;
+
+%D Bounding box.
+
+def drawboundingbox expr p =
+    normaldraw boundingbox p _bnd_opt_
+enddef ;
+
+%D Origin.
+
+numeric originlength ; originlength := .5cm ;
+
+def draworigin text t =
+    normaldraw (origin shifted (0, originlength) -- origin shifted (0,-originlength)) _ori_opt_ t ;
+    normaldraw (origin shifted ( originlength,0) -- origin shifted (-originlength,0)) _ori_opt_ t ;
+enddef;
+
+%D Axis.
+
+numeric tickstep   ; tickstep   := 5mm ;
+numeric ticklength ; ticklength := 2mm ;
+
+def drawxticks expr c = path _c_ ; _c_ := c ; mfun_draw_xticks enddef ;
+def drawyticks expr c = path _c_ ; _c_ := c ; mfun_draw_yticks enddef ;
+def drawticks  expr c = path _c_ ; _c_ := c ; mfun_draw_ticks  enddef ;
+
+% Adding eps prevents disappearance due to rounding errors.
+
+def mfun_draw_xticks text t =
+    for i=0 step -tickstep until xpart llcorner _c_ - eps :
+        if (i<=xpart lrcorner _c_) :
+        normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+        fi ;
+    endfor ;
+    for i=0 step  tickstep until xpart lrcorner _c_ + eps :
+        if (i>=xpart llcorner _c_) :
+            normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+        fi ;
+    endfor ;
+    normaldraw (llcorner _c_ -- ulcorner _c_) shifted (-xpart llcorner _c_,0) _ori_opt_ t ;
+enddef ;
+
+def mfun_draw_yticks text t =
+    for i=0 step -tickstep until ypart llcorner _c_ - eps :
+        if (i<=ypart ulcorner _c_) :
+            normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+        fi ;
+    endfor ;
+    for i=0 step  tickstep until ypart ulcorner _c_ + eps :
+        if (i>=ypart llcorner _c_) :
+            normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+        fi ;
+    endfor ;
+    normaldraw (llcorner _c_ -- lrcorner _c_) shifted (0,-ypart llcorner _c_) _ori_opt_ t ;
+enddef ;
+
+def mfun_draw_ticks text t =
+    drawxticks _c_ t ;
+    drawyticks _c_ t ;
+enddef ;
+
+%D All of it except axis.
+
+def drawwholepath expr p =
+    draworigin          ;
+    drawpath          p ;
+    drawcontrollines  p ;
+    drawcontrolpoints p ;
+    drawpoints        p ;
+    drawboundingbox   p ;
+    drawpointlabels   p ;
+enddef ;
+
+%D Tracing.
+
+def visualizeddraw expr c =
+    if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi
+enddef ;
+
+def visualizedfill expr c =
+    if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi
+enddef ;
+
+def do_visualizeddraw text t =
+    draworigin            ;
+    drawpath          _c_ t ;
+    drawcontrollines  _c_ ;
+    drawcontrolpoints _c_ ;
+    drawpoints        _c_ ;
+    drawboundingbox   _c_ ;
+    drawpointlabels   _c_ ;
+enddef ;
+
+def do_visualizedfill text t =
+    if cycle _c_ : normalfill _c_ t fi ;
+    draworigin            ;
+    drawcontrollines  _c_ ;
+    drawcontrolpoints _c_ ;
+    drawpoints        _c_ ;
+    drawboundingbox   _c_ ;
+    drawpointlabels   _c_ ;
+enddef ;
+
+def visualizepaths =
+    let fill = visualizedfill ;
+    let draw = visualizeddraw ;
+enddef ;
+
+def naturalizepaths =
+    let fill = normalfill ;
+    let draw = normaldraw ;
+enddef ;
+
+extra_endfig := extra_endfig & " naturalizepaths ; " ;
+
+%D Nice tracer:
+
+def drawboundary primary p =
+    draw p dashed evenly withcolor white ;
+    draw p dashed oddly  withcolor black ;
+    draw (- llcorner p) withpen pencircle scaled 3   withcolor white ;
+    draw (- llcorner p) withpen pencircle scaled 1.5 withcolor black ;
+enddef ;
+
+%D Also handy:
+
+extra_beginfig := extra_beginfig & " truecorners :=  0 ; "   ; % restores
+extra_beginfig := extra_beginfig & " miterlimit  := 10 ; "   ; % restores
+extra_beginfig := extra_beginfig & " linejoin := rounded ; " ; % restores
+extra_beginfig := extra_beginfig & " linecap  := rounded ; " ; % restores
+
+%D Normally, arrowheads don't scale well. So we provide a
+%D hack.
+
+boolean autoarrows ; autoarrows := false ;
+numeric ahfactor   ; ahfactor   := 2.5 ;
+
+def set_ahlength (text t) =
+  % ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added
+  % problem: _op_ can contain color so a no-go, we could apply the transform
+  % but i need to figure out the best way (fakepicture and take components).
+    ahlength := (ahfactor*pen_size(t)) ;
+enddef ;
+
+vardef pen_size (text t) =
+    save p ; picture p ; p := nullpicture ;
+    addto p doublepath (top origin -- bot origin) t ;
+    (ypart urcorner p - ypart lrcorner p)
+enddef ;
+
+%D The next two macros are adapted versions of plain
+%D \METAPOST\ definitions.
+
+vardef arrowpath expr p = % patch by Peter Rolf: supports squared pen and shifting (hh: maybe just use center of head as first)
+    (p cutafter makepath(pencircle scaled 2(ahlength*cosd(.5ahangle)) shifted point length p of p))
+enddef;
+
+% def _finarr text t =
+%     if autoarrows : set_ahlength (t) fi ;
+%     draw     arrowpath _apth t ; % arrowpath added
+%     filldraw arrowhead _apth t ;
+% enddef;
+
+def _finarr text t =
+    if autoarrows : set_ahlength (t) fi ;
+    draw arrowpath _apth t ; % arrowpath added
+    fill arrowhead _apth t ;
+    draw arrowhead _apth t ;
+enddef;
+
+def _finarr text t =
+    if autoarrows : set_ahlength (t) fi ;
+    draw arrowpath _apth t ; % arrowpath added
+    fill arrowhead _apth t ;
+    draw arrowhead _apth t undashed ;
+enddef;
+
+%D Handy too ......
+
+vardef pointarrow (expr pat, loc, len, off) =
+    save l, r, s, t ; path l, r ; numeric s ; pair t ;
+    t := if pair loc : loc else : point loc along pat fi ;
+    s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+    r := pat cutbefore t ;
+    r := (r cutafter point (arctime s of r) of r) ;
+    s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+    l := reverse (pat cutafter t) ;
+    l := (reverse (l cutafter point (arctime s of l) of l)) ;
+    (l..r)
+enddef ;
+
+def rightarrow  (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ;
+def leftarrow   (expr pat,tim,len) = pointarrow(pat,tim,len,+len) enddef ;
+def centerarrow (expr pat,tim,len) = pointarrow(pat,tim,len,   0) enddef ;
+
+%D The \type {along} and \type {on} operators can be used
+%D as follows:
+%D
+%D \starttyping
+%D drawdot point .5  along somepath ;
+%D drawdot point 3cm on    somepath ;
+%D \stoptyping
+%D
+%D The number denotes a percentage (fraction).
+
+primarydef pct along pat = % also negative
+    (arctime (pct * (arclength pat)) of pat) of pat
+enddef ;
+
+primarydef len on pat = % no outer ( ) .. somehow fails
+    (arctime if len>=0 : len else : (arclength(pat)+len) fi of pat) of pat
+enddef ;
+
+% this cuts of a piece from both ends
+
+% tertiarydef pat cutends len =
+%   begingroup ; save tap ; path tap ;
+%   tap := pat cutbefore (point len on pat) ;
+%   (tap cutafter (point -len on tap))
+%   endgroup
+% enddef ;
+
+tertiarydef pat cutends len =
+    begingroup
+    save tap ; path tap ;
+    tap := pat cutbefore (point (xpart paired(len)) on pat) ;
+    (tap cutafter (point -(ypart paired(len)) on tap))
+    endgroup
+enddef ;
+
+%D To be documented.
+
+path freesquare ;
+
+freesquare := (
+    (-1,0) -- (-1,-1) -- (0,-1) -- (+1,-1) --
+    (+1,0) -- (+1,+1) -- (0,+1) -- (-1,+1) -- cycle
+) scaled .5 ;
+
+numeric freelabeloffset  ; freelabeloffset  := 3pt ;
+numeric freedotlabelsize ; freedotlabelsize := 3pt ;
+
+vardef thefreelabel (expr str, loc, ori) =
+    save s, p, q, l ; picture s ; path p, q ; pair l ;
+    interim labeloffset := freelabeloffset ;
+    s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ;
+    setbounds s to boundingbox s enlarged freelabeloffset ;
+    p := fullcircle scaled (2*length(loc-ori)) shifted ori ;
+    q := freesquare xyscaled (urcorner s - llcorner s) ;
+    l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ;
+    setbounds s to boundingbox s enlarged -freelabeloffset ; % new
+  % draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ;
+    (s shifted -l)
+enddef ;
+
+vardef freelabel (expr str, loc, ori) =
+    draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+vardef freedotlabel (expr str, loc, ori) =
+    interim linecap := rounded ;
+    draw loc withpen pencircle scaled freedotlabelsize ;
+    draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+%D \starttyping
+%D drawarrow anglebetween(line_a,line_b,somelabel) ;
+%D \stoptyping
+
+newinternal angleoffset ; angleoffset :=  0pt ;
+newinternal anglelength ; anglelength := 20pt ;
+newinternal anglemethod ; anglemethod :=    1 ;
+
+% vardef anglebetween (expr a, b, str) = % path path string
+%   save pointa, pointb, common, middle, offset ;
+%   pair pointa, pointb, common, middle, offset ;
+%   save curve ; path curve ;
+%   save where ; numeric where ;
+%   if round point 0 of a = round point 0 of b :
+%     common := point 0 of a ;
+%   else :
+%     common := a intersectionpoint b ;
+%   fi ;
+%   pointa := point anglelength on a ;
+%   pointb := point anglelength on b ;
+%   where  := turningnumber (common--pointa--pointb--cycle) ;
+%   middle := ((common--pointa) rotatedaround (pointa,-where*90))
+%                             intersectionpoint
+%             ((common--pointb) rotatedaround (pointb, where*90)) ;
+%   if     anglemethod = 0 :
+%     curve  := pointa{unitvector(middle-pointa)}.. pointb;
+%     middle := point .5 along curve ;
+%     curve  := common ;
+%   elseif anglemethod = 1 :
+%     curve  := pointa{unitvector(middle-pointa)}.. pointb;
+%     middle := point .5 along curve ;
+%   elseif anglemethod = 2 :
+%     middle := common rotatedaround(.5[pointa,pointb],180) ;
+%     curve  := pointa--middle--pointb ;
+%   elseif anglemethod = 3 :
+%     curve  := pointa--middle--pointb ;
+%   elseif anglemethod = 4 :
+%     curve  := pointa..controls middle..pointb ;
+%     middle := point .5 along curve ;
+%   fi ;
+%   draw thefreelabel(str, middle, common) withcolor black ;
+%   curve
+% enddef ;
+
+vardef anglebetween (expr a, b, str) = % path path string
+    save pointa, pointb, common, middle, offset ;
+    pair pointa, pointb, common, middle, offset ;
+    save curve ; path curve ;
+    save where ; numeric where ;
+    if round point 0 of a = round point 0 of b :
+        common := point 0 of a ;
+    else :
+        common := a intersectionpoint b ;
+    fi ;
+    pointa := point anglelength on a ;
+    pointb := point anglelength on b ;
+    where  := turningnumber (common--pointa--pointb--cycle) ;
+    middle := (reverse(common--pointa) rotatedaround (pointa,-where*90))
+        intersection_point
+        (reverse(common--pointb) rotatedaround (pointb, where*90)) ;
+    if not intersection_found :
+        middle := point .5 along
+        ((reverse(common--pointa) rotatedaround (pointa,-where*90)) --
+        (       (common--pointb) rotatedaround (pointb, where*90))) ;
+    fi ;
+    if     anglemethod = 0 :
+        curve  := pointa{unitvector(middle-pointa)}.. pointb;
+        middle := point .5 along curve ;
+        curve  := common ;
+    elseif anglemethod = 1 :
+        curve  := pointa{unitvector(middle-pointa)}.. pointb;
+        middle := point .5 along curve ;
+    elseif anglemethod = 2 :
+        middle := common rotatedaround(.5[pointa,pointb],180) ;
+        curve  := pointa--middle--pointb ;
+    elseif anglemethod = 3 :
+        curve  := pointa--middle--pointb ;
+    elseif anglemethod = 4 :
+        curve  := pointa..controls middle..pointb ;
+        middle := point .5 along curve ;
+    fi ;
+    draw thefreelabel(str, middle, common) ; % withcolor black ;
+    curve
+enddef ;
+
+% Stack
+
+picture mfun_current_picture_stack[] ;
+numeric mfun_current_picture_depth   ;
+
+mfun_current_picture_depth := 0 ;
+
+def pushcurrentpicture =
+    mfun_current_picture_depth := mfun_current_picture_depth + 1 ;
+    mfun_current_picture_stack[mfun_current_picture_depth] := currentpicture ;
+    currentpicture := nullpicture ;
+enddef ;
+
+def popcurrentpicture text t = % optional text
+    if mfun_current_picture_depth > 0 :
+        addto mfun_current_picture_stack[mfun_current_picture_depth] also currentpicture t ;
+        currentpicture := mfun_current_picture_stack[mfun_current_picture_depth] ;
+        mfun_current_picture_stack[mfun_current_picture_depth] := nullpicture ;
+        mfun_current_picture_depth := mfun_current_picture_depth - 1 ;
+    fi ;
+enddef ;
+
+%D colorcircle(size, red, green, blue) ;
+
+% vardef colorcircle (expr size, red, green, blue) =
+%   save r, g, b, rr, gg, bb, cc, mm, yy ; save radius ;
+%   path r, g, b, rr, bb, gg, cc, mm, yy ; numeric radius ;
+%
+%   radius := 5cm ; pickup pencircle scaled (radius/25) ;
+%
+%   r := g := b := fullcircle scaled radius shifted (0,radius/4) ;
+%
+%   r := r rotatedaround (origin, 15) ;
+%   g := g rotatedaround (origin,135) ;
+%   b := b rotatedaround (origin,255) ;
+%
+%   r := r rotatedaround(center r,-90) ;
+%   g := g rotatedaround(center g, 90) ;
+%
+%   gg := buildcycle(buildcycle(reverse r,b),g) ;
+%   cc := buildcycle(buildcycle(b,reverse g),r) ;
+%
+%   rr := gg rotatedaround(origin,120) ;
+%   bb := gg rotatedaround(origin,240) ;
+%
+%   yy := cc rotatedaround(origin,120) ;
+%   mm := cc rotatedaround(origin,240) ;
+%
+%   pushcurrentpicture ;
+%
+%   fill fullcircle scaled radius withcolor white ;
+%
+%   fill rr withcolor red   ; fill cc withcolor white-red   ;
+%   fill gg withcolor green ; fill mm withcolor white-green ;
+%   fill bb withcolor blue  ; fill yy withcolor white-blue  ;
+%
+%   for i = rr,gg,bb,cc,mm,yy : draw i withcolor .5white ; endfor ;
+%
+%   currentpicture := currentpicture xsized size ;
+%
+%   popcurrentpicture ;
+% enddef ;
+
+% vardef colorcircle (expr size, red, green, blue) =
+%   save r, g, b, rr, gg, bb, cc, mm, yy ; save radius ;
+%   path r, g, b, rr, bb, gg, cc, mm, yy ; numeric radius ;
+%
+%   radius := 5cm ; pickup pencircle scaled (radius/25) ;
+%
+%   transform t ; t := identity rotatedaround(origin,120) ;
+%
+%   r := fullcircle scaled radius
+%    shifted (0,radius/4) rotatedaround(origin,15) ;
+%
+%   g := r transformed t ; b := g transformed t ;
+%
+%   r := r rotatedaround(center r,-90) ;
+%   g := g rotatedaround(center g, 90) ;
+%
+%   gg := buildcycle(buildcycle(reverse r,b),g) ;
+%   cc := buildcycle(buildcycle(b,reverse g),r) ;
+%
+%   rr := gg transformed t ; bb := rr transformed t ;
+%   yy := cc transformed t ; mm := yy transformed t ;
+%
+%   pushcurrentpicture ;
+%
+%   fill fullcircle scaled radius withcolor white ;
+%
+%   fill rr withcolor red   ; fill cc withcolor white-red   ;
+%   fill gg withcolor green ; fill mm withcolor white-green ;
+%   fill bb withcolor blue  ; fill yy withcolor white-blue  ;
+%
+%   for i = rr,gg,bb,cc,mm,yy : draw i withcolor .5white ; endfor ;
+%
+%   currentpicture := currentpicture xsized size ;
+%
+%   popcurrentpicture ;
+% enddef ;
+
+vardef colorcircle (expr size, red, green, blue) = % might move
+    save r, g, b, c, m, y, w ; save radius ;
+    path r, g, b, c, m, y, w ; numeric radius ;
+
+    radius := 5cm ; pickup pencircle scaled (radius/25) ;
+
+    transform t ; t := identity rotatedaround(origin,120) ;
+
+    r := fullcircle rotated 90 scaled radius shifted (0,radius/4) rotatedaround(origin,135) ;
+
+    b := r transformed t ; g := b transformed t ;
+
+    c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ;
+    y := c transformed t ; m := y transformed t ;
+
+    w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ;
+
+    pushcurrentpicture ;
+
+    fill r withcolor         red   ;
+    fill g withcolor         green ;
+    fill b withcolor         blue  ;
+    fill c withcolor white - red   ;
+    fill m withcolor white - green ;
+    fill y withcolor white - blue  ;
+    fill w withcolor white         ;
+
+    for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ;
+
+    currentpicture := currentpicture xsized size ;
+
+    popcurrentpicture ;
+enddef ;
+
+% penpoint (i,2) of somepath -> inner / outer point
+
+vardef penpoint expr pnt of p =
+    save n, d ; numeric n, d ;
+    (n,d) = if pair pnt : pnt else : (pnt,1) fi ;
+    (point n of p shifted ((penoffset direction n of p of currentpen) scaled d))
+enddef ;
+
+% nice: currentpicture := inverted currentpicture ;
+
+primarydef p uncolored c =
+    if color p :
+        c - p
+    else :
+        image (
+            for i within p :
+                addto currentpicture
+                    if stroked i or filled i :
+                        if filled i :
+                            contour
+                        else :
+                            doublepath
+                        fi
+                        pathpart i
+                        dashed dashpart i withpen penpart i
+                    else :
+                        also i
+                    fi
+                    withcolor c-(redpart i, greenpart i, bluepart i) ;
+            endfor ;
+        )
+  fi
+enddef ;
+
+vardef inverted primary p =
+    p uncolored white
+enddef ;
+
+% primarydef p softened c =
+%   if color p :
+%     tripled(c) * p
+%   else :
+%     image
+%       (save cc ; color cc ; cc := tripled(c) ;
+%        for i within p :
+%          addto currentpicture
+%          if stroked i or filled i :
+%            if filled i : contour else : doublepath fi pathpart i
+%            dashed dashpart i withpen penpart i
+%          else :
+%           also i
+%          fi
+%          withcolor (redpart   cc * redpart   i,
+%                     greenpart cc * greenpart i,
+%                     bluepart  cc * bluepart  i) ;
+%        endfor ;)
+%   fi
+% enddef ;
+
+primarydef p softened c =
+    begingroup
+    save cc ; color cc ; cc := tripled(c) ;
+    if color p :
+        (redpart cc * redpart p,greenpart cc * greenpart p, bluepart cc * bluepart p)
+    else :
+        image (
+            for i within p :
+                addto currentpicture
+                    if stroked i or filled i :
+                        if filled i :
+                            contour
+                        else :
+                            doublepath
+                        fi
+                        pathpart i
+                        dashed dashpart i withpen penpart i
+                    else :
+                        also i
+                    fi
+                    withcolor (redpart cc * redpart i, greenpart cc * greenpart i, bluepart cc * bluepart i) ;
+            endfor ;
+        )
+    fi
+    endgroup
+enddef ;
+
+vardef grayed primary p =
+    if color p :
+        tripled(.30redpart p+.59greenpart p+.11bluepart p)
+    else :
+        image (
+            for i within p :
+                addto currentpicture
+                    if stroked i or filled i :
+                        if filled i :
+                            contour
+                        else :
+                            doublepath
+                        fi
+                        pathpart i
+                        dashed dashpart i
+                        withpen penpart i
+                    else :
+                        also i
+                    fi
+                withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ;
+            endfor ;
+        )
+  fi
+enddef ;
+
+% yes or no: "text" infont "cmr12" at 24pt ;
+
+% let normalinfont = infont ;
+%
+% numeric lastfontsize ; lastfontsize = fontsize defaultfont ;
+%
+% def infont primary name =  % no vardef, no expr
+%   hide(lastfontsize := fontsize name) % no ;
+%   normalinfont name
+% enddef ;
+%
+% def scaledat expr size =
+%   scaled (size/lastfontsize)
+% enddef ;
+%
+% let at = scaledat ;
+
+% like decimal
+
+def condition primary b = if b : "true" else : "false" fi enddef ;
+
+% undocumented
+
+primarydef p stretched s =
+    begingroup
+    save pp ; path pp ; pp := p xyscaled s ;
+    (pp shifted ((point 0 of p) - (point 0 of pp)))
+    endgroup
+enddef ;
+
+% primarydef p enlonged len =
+%     begingroup
+%     save al ; al := arclength(p) ;
+%     if al > 0 :
+%         if pair p :
+%             point 1 of ((origin -- p) stretched ((al+len)/al))
+%         else :
+%             p stretched ((al+len)/al)
+%         fi
+%     else :
+%         p
+%     fi
+%     endgroup
+% enddef ;
+
+primarydef p enlonged len =
+    begingroup
+    if len == 0 :
+        p
+    elseif pair p :
+        save q ; path q ; q := origin -- p ;
+        save al ; al := arclength(q) ;
+        if al > 0 :
+            point 1 of (q stretched ((al+len)/al))
+        else :
+            p
+        fi
+    else :
+        save al ; al := arclength(p) ;
+        if al > 0 :
+            p stretched ((al+len)/al)
+        else :
+            p
+        fi
+    fi
+    endgroup
+enddef ;
+
+% path p ; p := (0,0) -- (10cm,5cm) ;
+% drawarrow p withcolor red ;
+% drawarrow p shortened 1cm withcolor green ;
+
+% primarydef p shortened d =
+%     reverse ( ( reverse (p enlonged -d) ) enlonged -d )
+% enddef ;
+
+primarydef p shortened d =
+    reverse ( ( reverse (p enlonged -xpart paired(d)) ) enlonged -ypart paired(d) )
+enddef ;
+
+% yes or no, untested -)
+
+def xshifted expr dx = shifted(dx,0) enddef ;
+def yshifted expr dy = shifted(0,dy) enddef ;
+
+% also handy
+
+% right: str = readfrom ("abc" & ".def" ) ;
+% wrong: str = readfrom  "abc" & ".def"   ;
+
+% Every 62th read fails so we need to try again!
+
+% def readfile (expr name) =
+%   if (readfrom (name) <> EOF) :
+%     scantokens("input " & name & ";") ;
+%   elseif (readfrom (name) <> EOF) :
+%     scantokens("input " & name & ";") ;
+%   fi ;
+%   closefrom (name) ;
+% enddef ;
+%
+% this sometimes fails on the elseif, so :
+%
+
+def readfile (expr name) =
+    begingroup ; save ok ; boolean ok ;
+    if (readfrom (name) <> EOF) :
+        ok := false ;
+    elseif (readfrom (name) <> EOF) :
+        ok := false ;
+    else :
+        ok := true ;
+    fi ;
+    if not ok :
+        scantokens("input " & name & " ") ;
+    fi ;
+    closefrom (name) ;
+    endgroup ;
+enddef ;
+
+% permits redefinition of end in macro
+
+inner end ;
+
+% this will be redone (when needed) using scripts and backend handling
+
+let normalwithcolor = withcolor ;
+
+def remapcolors =
+    def withcolor primary c = normalwithcolor remappedcolor(c) enddef ;
+enddef ;
+
+def normalcolors =
+    let withcolor = normalwithcolor ;
+enddef ;
+
+def resetcolormap =
+    color color_map[][][] ;
+    normalcolors ;
+enddef ;
+
+resetcolormap ;
+
+% color_map_resolution := 1000 ;
+%
+% def r_color primary c = round(color_map_resolution*redpart   c) enddef ;
+% def g_color primary c = round(color_map_resolution*greenpart c) enddef ;
+% def b_color primary c = round(color_map_resolution*bluepart  c) enddef ;
+
+def r_color primary c = redpart   c enddef ;
+def g_color primary c = greenpart c enddef ;
+def b_color primary c = bluepart  c enddef ;
+
+def remapcolor(expr old, new) =
+    color_map[redpart old][greenpart old][bluepart old] := new ;
+enddef ;
+
+def remappedcolor(expr c) =
+    if known color_map[redpart c][greenpart c][bluepart c] :
+        color_map[redpart c][greenpart c][bluepart c]
+    else :
+        c
+    fi
+enddef ;
+
+% def refill  suffix c = do_repath (1) (c) enddef ;
+% def redraw  suffix c = do_repath (2) (c) enddef ;
+% def recolor suffix c = do_repath (0) (c) enddef ;
+%
+% color refillbackground ; refillbackground := (1,1,1) ;
+%
+% def do_repath (expr mode) (suffix c) text t = % can it be stroked and filled at the same time ?
+%   begingroup ;
+%   if mode=0 : save withcolor ; remapcolors ; fi ;
+%   save _c_, _cc_, _f_, _b_ ; picture _c_, _cc_ ; color _f_ ; path _b_ ;
+%   _c_ := c ; _b_ := boundingbox c ; c := nullpicture ;
+%   for i within _c_ :
+%     _f_ := (redpart i, greenpart i, bluepart i) ;
+%     if     bounded i :
+%       setbounds c to pathpart i ;
+%     elseif clipped i :
+%       clip c to pathpart i ;
+%     elseif stroked i :
+%       addto c doublepath pathpart i
+%         dashed dashpart i withpen penpart i
+%         withcolor _f_ % (redpart i, greenpart i, bluepart i)
+%         if mode=2 : t fi ;
+%     elseif filled  i :
+%       addto c contour pathpart i
+%         withcolor _f_
+%         if (mode=1) and (_f_<>refillbackground) : t fi ;
+%     else :
+%       addto c also i ;
+%     fi ;
+%   endfor ;
+%   setbounds c to _b_ ;
+%   endgroup ;
+% enddef ;
+
+% Thanks to Jens-Uwe Morawski for pointing out that we need
+% to treat bounded and clipped components as local pictures.
+
+def recolor suffix p = p := repathed (0,p) enddef ;
+def refill  suffix p = p := repathed (1,p) enddef ;
+def redraw  suffix p = p := repathed (2,p) enddef ;
+def retext  suffix p = p := repathed (3,p) enddef ;
+def untext  suffix p = p := repathed (4,p) enddef ;
+
+% primarydef p recolored t = repathed(0,p) t enddef ;
+% primarydef p refilled  t = repathed(1,p) t enddef ;
+% primarydef p redrawn   t = repathed(2,p) t enddef ;
+% primarydef p retexted  t = repathed(3,p) t enddef ;
+% primarydef p untexted  t = repathed(4,p) t enddef ;
+
+color refillbackground ; refillbackground := (1,1,1) ;
+
+% vardef repathed (expr mode, p) text t =
+%   begingroup ;
+%   if mode=0 : save withcolor ; remapcolors ; fi ;
+%   save _p_, _pp_, _f_, _b_, _t_ ;
+%   picture _p_, _pp_ ; color _f_ ; path _b_ ; transform _t_ ;
+%   _b_ := boundingbox p ; _p_ := nullpicture ;
+%   for i within p :
+%     _f_ := (redpart i, greenpart i, bluepart i) ;
+%     if     bounded i :
+%       _pp_ := repathed(mode,i) t ;
+%       setbounds _pp_ to pathpart i ;
+%       addto _p_ also _pp_ ;
+%     elseif clipped i :
+%       _pp_ := repathed(mode,i) t ;
+%       clip _pp_ to pathpart i ;
+%       addto _p_ also _pp_ ;
+%     elseif stroked i :
+%       addto _p_ doublepath pathpart i
+%         dashed dashpart i withpen penpart i
+%         withcolor _f_ % (redpart i, greenpart i, bluepart i)
+%         if mode=2 : t fi ;
+%     elseif filled  i :
+%       addto _p_ contour pathpart i
+%         withcolor _f_
+%         if (mode=1) and (_f_<>refillbackground) : t fi ;
+%     elseif textual i : % textpart i <> "" :
+%       if mode <> 4 :
+%         % transform _t_ ;
+%         % (xpart _t_, xxpart _t_, xypart _t_)  = (xpart  i, xxpart i, xypart i) ;
+%         % (ypart _t_, yypart _t_, yxpart _t_)  = (ypart  i, yypart i, yxpart i) ;
+%         % addto _p_ also
+%         %   textpart i infont fontpart i % todo : other font
+%         %   transformed _t_
+%         %   withpen penpart i
+%         %   withcolor _f_
+%         %   if mode=3 : t fi ;
+%         addto _p_ also i if mode=3 : t fi ;
+%       fi ;
+%     else :
+%       addto _p_ also i ;
+%     fi ;
+%   endfor ;
+%   setbounds _p_ to _b_ ;
+%   _p_
+%   endgroup
+% enddef ;
+
+def restroke  suffix p = p := repathed (21,p) enddef ; % keep attributes
+def reprocess suffix p = p := repathed (22,p) enddef ; % no attributes
+
+% also 11 and 12
+
+vardef repathed (expr mode, p) text t =
+    begingroup ;
+    if mode = 0 :
+        save withcolor ;
+        remapcolors ;
+    fi ;
+    save _p_, _pp_, _ppp_, _f_, _b_, _t_ ;
+    picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ;
+    _b_ := boundingbox p ;
+    _p_ := nullpicture ;
+    for i within p :
+        _f_ := (redpart i, greenpart i, bluepart i) ;
+        if bounded i :
+            _pp_ := repathed(mode,i) t ;
+            setbounds _pp_ to pathpart i ;
+            addto _p_ also _pp_ ;
+        elseif clipped i :
+            _pp_ := repathed(mode,i) t ;
+            clip _pp_ to pathpart i ;
+            addto _p_ also _pp_ ;
+        elseif stroked i :
+            if mode=21 :
+                _ppp_ := i ; % indirectness is needed
+                addto _p_ also image(scantokens(t & " pathpart _ppp_")
+                    dashed dashpart i withpen penpart i
+                    withcolor _f_ ; ) ;
+            elseif mode=22 :
+                _ppp_ := i ; % indirectness is needed
+                addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+            else :
+                addto _p_ doublepath pathpart i
+                    dashed dashpart i withpen penpart i
+                    withcolor _f_ % (redpart i, greenpart i, bluepart i)
+                    if mode = 2 :
+                        t
+                    fi ;
+            fi ;
+        elseif filled  i :
+            if mode=11 :
+                _ppp_ := i ; % indirectness is needed
+                addto _p_ also image(scantokens(t & " pathpart _ppp_")
+                    withcolor _f_ ; ) ;
+            elseif mode=12 :
+                _ppp_ := i ; % indirectness is needed
+                addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+            else :
+                addto _p_ contour pathpart i
+                    withcolor _f_
+                    if (mode=1) and (_f_<>refillbackground) :
+                        t
+                    fi ;
+            fi ;
+        elseif textual i : % textpart i <> "" :
+            if mode <> 4 :
+                % transform _t_ ;
+                % (xpart _t_, xxpart _t_, xypart _t_)  = (xpart  i, xxpart i, xypart i) ;
+                % (ypart _t_, yypart _t_, yxpart _t_)  = (ypart  i, yypart i, yxpart i) ;
+                % addto _p_ also
+                %     textpart i infont fontpart i % todo : other font
+                %     transformed _t_
+                %     withpen penpart i
+                %     withcolor _f_
+                %     if mode=3 : t fi ;
+                addto _p_ also i
+                    if mode=3 :
+                        t
+                    fi ;
+            fi ;
+        else :
+            addto _p_ also i ;
+        fi ;
+    endfor ;
+    setbounds _p_ to _b_ ;
+    _p_
+    endgroup
+enddef ;
+
+% After a question of Denis on how to erase a z variable, Jacko
+% suggested to assign whatever to x and y. So a clearz
+% variable can be defined as:
+%
+% vardef clearz@# =
+%   x@# := whatever ;
+%   y@# := whatever ;
+% enddef ;
+%
+% but Jacko suggested a redefinition of clearxy:
+%
+% def clearxy text s =
+%  clearxy_index_:=0;
+%  for $:=s:
+%    clearxy_index_:=clearxy_index_+1; endfor;
+%  if clearxy_index_=0:
+%    save x,y;
+%  else:
+%    forsuffixes $:=s: x$:=whatever; y$:=whatever; endfor;
+%  fi
+% enddef;
+%
+% which i decided to simplify to:
+
+def clearxy text s =
+    if false for $ := s : or true endfor :
+        forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ;
+    else :
+        save x, y ;
+    fi
+enddef ;
+
+% so now we can say: clearxy ; as well as clearxy 1, 2, 3 ;
+
+% show x0 ; z0 = (10,10) ;
+% show x0 ; x0 := whatever ; y0 := whatever ;
+% show x0 ; z0 = (20,20) ;
+% show x0 ; clearxy 0 ;
+% show x0 ; z0 = (30,30) ;
+
+primarydef p smoothed d =
+   (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} ..
+    p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up}    ..
+    p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left}  ..
+    p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down}  .. cycle)
+enddef ;
+
+primarydef p cornered c =
+    ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) --
+    for i=1 upto length(p) :
+        (point i-1 of p) shifted (c*(unitvector(point i   of p - point i-1 of p))) --
+        (point i   of p) shifted (c*(unitvector(point i-1 of p - point i   of p))) ..
+        controls point i of p ..
+    endfor cycle)
+enddef ;
+
+% cmyk color support
+
+vardef cmyk(expr c,m,y,k) =
+    (1-c-k,1-m-k,1-y-k)
+enddef ;
+
+% handy
+
+% vardef bbwidth (expr p) = % vardef width_of primary p =
+%     if known p :
+%         if path p or picture p :
+%             xpart (lrcorner p - llcorner p)
+%         else :
+%             0
+%         fi
+%     else :
+%         0
+%     fi
+% enddef ;
+
+vardef bbwidth primary p =
+    if unknown p :
+        0
+    elseif path p or picture p :
+        xpart (lrcorner p - llcorner p)
+    else :
+        0
+    fi
+enddef ;
+
+% vardef bbheight (expr p) = % vardef heigth_of primary p =
+%     if known p :
+%         if path p or picture p :
+%             ypart (urcorner p - lrcorner p)
+%         else :
+%             0
+%         fi
+%     else :
+%         0
+%     fi
+% enddef ;
+
+vardef bbheight primary p =
+    if unknown p :
+        0
+    elseif path p or picture p :
+        ypart (urcorner p - lrcorner p)
+    else :
+        0
+    fi
+enddef ;
+
+color nocolor ; numeric noline ; % both unknown signals
+
+def dowithpath (expr p, lw, lc, bc) =
+    if known p :
+        if known bc :
+            fill p withcolor bc ;
+        fi ;
+        if known lw and known lc :
+            draw p withpen pencircle scaled lw withcolor lc ;
+        elseif known lw :
+            draw p withpen pencircle scaled lw ;
+        elseif known lc :
+            draw p withcolor lc ;
+        fi ;
+    fi ;
+enddef ;
+
+% result from metafont discussion list (denisr/boguslawj)
+
+def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ;
+def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ;
+
+let == = = ;
+
+% added
+
+picture oddly ; % evenly already defined
+
+evenly := dashpattern(on  3 off 3) ;
+oddly  := dashpattern(off 3 on  3) ;
+
+% not perfect, but useful since it removes redundant points.
+
+vardef mfun_straightened(expr sign, p) =
+    save _p_, _q_ ; path _p_, _q_ ;
+    _p_ := p ;
+    forever :
+        _q_ := mfun_do_straightened(sign, _p_) ;
+        exitif length(_p_) = length(_q_) ;
+        _p_ := _q_ ;
+    endfor ;
+    _q_
+enddef ;
+
+vardef mfun_do_straightened(expr sign, p) =
+    if length(p)>2 : % was 1, but straight lines are ok
+        save pp ; path pp ;
+        pp := point 0 of p ;
+        for i=1 upto length(p)-1 :
+            if round(point i of p) <> round(point length(pp) of pp) :
+                pp := pp -- point i of p ;
+            fi ;
+        endfor ;
+        save n, ok ; numeric n ; boolean ok ;
+        n := length(pp) ; ok := false ;
+        if n>2 :
+            for i=0 upto n : % evt hier ook round
+                if unitvector(round(point i of pp - point if i=0 : n else : i-1 fi of pp)) <>
+                        sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - point i of pp)) :
+                    if ok :
+                        --
+                    else :
+                        ok := true ;
+                    fi point i of pp
+                fi
+            endfor
+            if ok and (cycle p) :
+                -- cycle
+            fi
+        else :
+            pp
+        fi
+    else :
+        p
+    fi
+enddef ;
+
+vardef simplified expr p = (
+    reverse mfun_straightened(+1,mfun_straightened(+1,reverse p))
+) enddef ;
+
+vardef unspiked expr p = (
+    reverse mfun_straightened(-1,mfun_straightened(-1,reverse p))
+) enddef ;
+
+% path p ;
+% p := (2cm,1cm) -- (2cm,1cm) -- (2cm,1cm) -- (3cm,1cm) --
+%      (4cm,1cm) -- (4cm,2cm) -- (4cm,2.5cm) -- (4cm,3cm) --
+%      (3cm,3cm) -- (2cm,3cm) -- (1cm,3cm) -- (-1cm,3cm) --
+%      .5[(-1cm,3cm),(1cm,1cm)] -- (1cm,1cm) -- cycle ;
+%
+% p := unitcircle scaled 4cm ;
+%
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+
+% new
+
+path originpath ; originpath := origin -- cycle ;
+
+vardef unitvector primary z =
+    if abs z = abs origin : z else : z/abs z fi
+enddef;
+
+% also new
+
+% vardef anchored@#(expr p, z) = % maybe use the textext variant
+%     p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
+% enddef ;
+
+% epsed(1.2345)
+
+vardef epsed (expr e) =
+    e if e>0 : + eps elseif e<0 : - eps fi
+enddef ;
+
+% handy
+
+def withgray primary g =
+    withcolor (g,g,g)
+enddef ;
+
+% for metafun
+
+if unknown darkred     : color darkred     ; darkred     := .625(1,0,0) fi ;
+if unknown darkgreen   : color darkgreen   ; darkgreen   := .625(0,1,0) fi ;
+if unknown darkblue    : color darkblue    ; darkblue    := .625(0,0,1) fi ;
+if unknown darkcyan    : color darkcyan    ; darkcyan    := .625(0,1,1) fi ;
+if unknown darkmagenta : color darkmagenta ; darkmagenta := .625(1,0,1) fi ;
+if unknown darkyellow  : color darkyellow  ; darkyellow  := .625(1,1,0) fi ;
+if unknown darkgray    : color darkgray    ; darkgray    := .625(1,1,1) fi ;
+if unknown lightgray   : color lightgray   ; lightgray   := .850(1,1,1) fi ;
+
+% an improved plain mp macro
+
+vardef center primary p =
+    if pair p :
+        p
+    else :
+        .5[llcorner p, urcorner p]
+    fi
+enddef;
+
+% new, yet undocumented
+
+vardef rangepath (expr p, d, a) =
+    if length p>0 :
+        (d*unitvector(direction 0 of p) rotated a) shifted point 0 of p
+        -- p --
+        (d*unitvector(direction length(p) of p) rotated a) shifted point length(p) of p
+    else :
+        p
+    fi
+enddef ;
+
+% under construction
+
+vardef straightpath (expr a, b, method) =
+    if (method<1) or (method>6)  :
+        (a--b)
+    elseif method = 1 :
+        (a --
+            if xpart a > xpart b :
+                if ypart a > ypart b :
+                    (xpart b,ypart a) --
+                elseif ypart a < ypart b :
+                    (xpart a,ypart b) --
+                fi
+            elseif xpart a < xpart b :
+                if ypart a > ypart b :
+                    (xpart a,ypart b) --
+                elseif ypart a < ypart b :
+                    (xpart b,ypart a) --
+                fi
+            fi
+        b)
+    elseif method = 3 :
+        (a --
+            if xpart a > xpart b :
+                (xpart b,ypart a) --
+            elseif xpart a < xpart b :
+                (xpart a,ypart b) --
+            fi
+        b)
+    elseif method = 5 :
+        (a --
+            if ypart a > ypart b :
+                (xpart b,ypart a) --
+            elseif ypart a < ypart b :
+                (xpart a,ypart b) --
+            fi
+        b)
+    else :
+        (reverse straightpath(b,a,method-1))
+    fi
+enddef ;
+
+% handy for myself
+
+def addbackground text t =
+    begingroup ;
+    save p, b ; picture p ; path b ;
+    b := boundingbox currentpicture ;
+    p := currentpicture ; currentpicture := nullpicture ;
+    fill b t ;
+    setbounds currentpicture to b ;
+    addto currentpicture also p ;
+    endgroup ;
+enddef ;
+
+% makes a (line) into an infinite one (handy for calculating
+% intersection points
+
+vardef infinite expr p =
+    (-infinity*unitvector(direction 0 of p)
+    shifted point 0 of p
+    -- p --
+    +infinity*unitvector(direction length(p) of p)
+        shifted point length(p) of p)
+enddef ;
+
+% obscure macros: create var from string and replace - and :
+% (needed for process color id's) .. will go away
+
+string mfun_clean_ascii[] ;
+
+def register_dirty_chars(expr str) =
+    for i = 0 upto length(str)-1 :
+        mfun_clean_ascii[ASCII substring(i,i+1) of str] := "_" ;
+    endfor ;
+enddef ;
+
+register_dirty_chars("+-*/:;., ") ;
+
+vardef cleanstring (expr s) =
+    save ss ; string ss, si ; ss = "" ; save i ;
+    for i=0 upto length(s) :
+        si := substring(i,i+1) of s ;
+        ss := ss & if known mfun_clean_ascii[ASCII si] : mfun_clean_ascii[ASCII si] else : si fi ;
+    endfor ;
+    ss
+enddef ;
+
+vardef asciistring (expr s) =
+    save ss ; string ss, si ; ss = "" ; save i ;
+    for i=0 upto length(s) :
+        si := substring(i,i+1) of s ;
+        if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") :
+            ss := ss & char(scantokens(si) + ASCII "A") ;
+        else :
+            ss := ss & si ;
+        fi ;
+    endfor ;
+    ss
+enddef ;
+
+vardef setunstringed (expr s, v) =
+    scantokens(cleanstring(s)) := v ;
+enddef ;
+
+vardef getunstringed (expr s) =
+    scantokens(cleanstring(s))
+enddef ;
+
+vardef unstringed (expr s) =
+    expandafter known scantokens(cleanstring(s))
+enddef ;
+
+% for david arnold:
+
+% showgrid(-5,10,1cm,-10,10,1cm);
+
+def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY) = % will move
+    begingroup
+    save size ; numeric size ; size := 2pt ;
+    for x=MinX upto MaxX :
+        for y=MinY upto MaxY :
+            draw (x*DeltaX, y*DeltaY) withpen pencircle scaled
+                if (x mod 5 = 0) and (y mod 5 = 0) :
+                    1.5size withcolor .50white
+                else :
+                       size withcolor .75white
+                fi ;
+        endfor ;
+    endfor ;
+    for x=MinX upto MaxX:
+        label.bot(textext("\infofont " & decimal x), (x*DeltaX,-size)) ;
+    endfor ;
+    for y=MinY upto MaxY:
+        label.lft(textext("\infofont " & decimal y), (-size,y*DeltaY)) ;
+    endfor ;
+    endgroup
+enddef;
+
+% new, handy for:
+%
+% \startuseMPgraphic{map}{n}
+%   \includeMPgraphic{map:germany} ;
+%   c_phantom (\MPvar{n}<1) (
+%     fill map_germany withcolor \MPcolor{lightgray} ;
+%     draw map_germany withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+%   ) ;
+%   \includeMPgraphic{map:austria} ;
+%   c_phantom (\MPvar{n}<2) (
+%     fill map_austria withcolor \MPcolor{lightgray} ;
+%     draw map_austria withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+%   ) ;
+%   c_phantom (\MPvar{n}<3) (
+%   \includeMPgraphic{map:swiss} ;
+%     fill map_swiss withcolor \MPcolor{lightgray} ;
+%     draw map_swiss withpen pencircle scaled 1pt withcolor \MPcolor{darkgray}  ;
+%   ) ;
+%   c_phantom (\MPvar{n}<4) (
+%   \includeMPgraphic{map:luxembourg} ;
+%     fill map_luxembourg withcolor \MPcolor{lightgray} ;
+%     draw map_luxembourg withpen pencircle scaled 1pt withcolor \MPcolor{darkgray}  ;
+%   ) ;
+% \stopuseMPgraphic
+%
+% \useMPgraphic{map}{n=3}
+
+vardef phantom (text t) = % to be checked
+    picture _p_ ;
+    _p_ := image(t) ;
+    addto _p_ also currentpicture ;
+    setbounds currentpicture to boundingbox _p_ ;
+enddef ;
+
+vardef c_phantom (expr b) (text t) =
+    if b :
+        picture _p_ ;
+        _p_ := image(t) ;
+        addto _p_ also currentpicture ;
+        setbounds currentpicture to boundingbox _p_ ;
+    else :
+        t ;
+    fi ;
+enddef ;
+
+%D Handy:
+
+def break =
+    exitif true fi ;
+enddef ;
+
+%D New too:
+
+primarydef p xstretched w = (
+    p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi
+) enddef ;
+
+primarydef p ystretched h = (
+    p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi
+) enddef ;
+
+primarydef p snapped s =
+    hide (
+        if path p :
+            forever :
+                exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ;
+                p := p scaled (1/2) ;
+            endfor ;
+        elseif numeric p :
+            forever :
+                exitif p <= s ;
+                p := p scaled (1/2) ;
+            endfor ;
+        fi ;
+    )
+    p
+enddef ;
+
+% vardef somecolor = (1,1,0,0) enddef ;
+
+% fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ;
+% fill OverlayBox withcolor (ccomponent somecolor,mcomponent somecolor,ycomponent somecolor,bcomponent somecolor) ;
+
+% This could be standard mplib 2 behaviour:
+
+vardef rcomponent expr p = if rgbcolor  p : redpart     p elseif cmykcolor p : 1 - cyanpart    p else : p fi enddef ;
+vardef gcomponent expr p = if rgbcolor  p : greenpart   p elseif cmykcolor p : 1 - magentapart p else : p fi enddef ;
+vardef bcomponent expr p = if rgbcolor  p : bluepart    p elseif cmykcolor p : 1 - yellowpart  p else : p fi enddef ;
+vardef ccomponent expr p = if cmykcolor p : cyanpart    p elseif rgbcolor  p : 1 - redpart     p else : p fi enddef ;
+vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor  p : 1 - greenpart   p else : p fi enddef ;
+vardef ycomponent expr p = if cmykcolor p : yellowpart  p elseif rgbcolor  p : 1 - bluepart    p else : p fi enddef ;
+vardef bcomponent expr p = if cmykcolor p : blackpart   p elseif rgbcolor  p :                 0 else : p fi enddef ;
+
+% draw image       (...) ... ; % prescripts prepended to first, postscripts appended to last
+% draw decorated   (...) ... ; % prescripts prepended to each,  postscripts appended to each
+% draw redecorated (...) ... ; % prescripts assigned  to each,  postscripts assigned to each
+% draw undecorated (...) ... ; % following properties are ignored, existing properties are kept
+%
+% draw decorated (
+%     draw fullcircle scaled 20cm withpen pencircle scaled 20mm withcolor red   withtransparency (1,.40) ;
+%     draw fullcircle scaled 15cm withpen pencircle scaled 15mm withcolor green withtransparency (1,.30) ;
+%     draw fullcircle scaled 10cm withpen pencircle scaled 10mm withcolor blue  withtransparency (1,.20) ;
+% )
+%     withcolor blue
+%     withtransparency (1,.125) % selectively applied
+%     withpen pencircle scaled 10mm
+% ;
+
+% vardef image (text imagedata) = % already defined
+%     save currentpicture ;
+%     picture currentpicture ;
+%     currentpicture := nullpicture ;
+%     imagedata ;
+%     currentpicture
+% enddef ;
+
+vardef undecorated (text imagedata) text decoration =
+    save currentpicture ;
+    picture currentpicture ;
+    currentpicture := nullpicture ;
+    imagedata ;
+    currentpicture
+enddef ;
+
+
+% if metapostversion < 1.770  :
+%
+%     vardef decorated (text imagedata) text decoration =
+%         save mfun_decorated_path, currentpicture ;
+%         picture mfun_decorated_path, currentpicture ;
+%         currentpicture := nullpicture ;
+%         imagedata ;
+%         mfun_decorated_path := currentpicture ;
+%         currentpicture := nullpicture ;
+%         for i within mfun_decorated_path :
+%             addto currentpicture
+%                 if stroked i :
+%                     doublepath pathpart i
+%                     dashed dashpart i
+%                     withpen penpart i
+%                     withcolor colorpart i
+%                     decoration
+%                 elseif filled i :
+%                     contour pathpart i
+%                     withpen penpart i
+%                     withcolor colorpart i
+%                     decoration
+%                 elseif textual i :
+%                     also i
+%                     withcolor colorpart i
+%                     decoration
+%                 else :
+%                     also i
+%                 fi
+%             ;
+%         endfor ;
+%         currentpicture
+%     enddef ;
+%
+% else:
+
+    vardef decorated (text imagedata) text decoration =
+        save mfun_decorated_path, currentpicture ;
+        picture mfun_decorated_path, currentpicture ;
+        currentpicture := nullpicture ;
+        imagedata ;
+        mfun_decorated_path := currentpicture ;
+        currentpicture := nullpicture ;
+        for i within mfun_decorated_path :
+            addto currentpicture
+                if stroked i :
+                    doublepath pathpart i
+                    dashed dashpart i
+                    withpen penpart i
+                    withcolor colorpart i
+                    withprescript prescriptpart i
+                    withpostscript postscriptpart i
+                    decoration
+                elseif filled i :
+                    contour pathpart i
+                    withpen penpart i
+                    withcolor colorpart i
+                    withprescript prescriptpart i
+                    withpostscript postscriptpart i
+                    decoration
+                elseif textual i :
+                    also i
+                    withcolor colorpart i
+                    withprescript prescriptpart i
+                    withpostscript postscriptpart i
+                    decoration
+                else :
+                    also i
+                fi
+            ;
+        endfor ;
+        currentpicture
+    enddef ;
+
+% fi ;
+
+vardef redecorated (text imagedata) text decoration =
+    save mfun_decorated_path, currentpicture ;
+    picture mfun_decorated_path, currentpicture ;
+    currentpicture := nullpicture ;
+    imagedata ;
+    mfun_decorated_path := currentpicture ;
+    currentpicture := nullpicture ;
+    for i within mfun_decorated_path :
+        addto currentpicture
+            if stroked i :
+                doublepath pathpart i
+                dashed dashpart i
+                withpen penpart i
+                decoration
+            elseif filled i :
+                contour pathpart i
+                withpen penpart i
+                decoration
+            elseif textual i :
+                also i
+                decoration
+            else :
+                also i
+            fi
+        ;
+    endfor ;
+    currentpicture
+enddef ;
+
+% path mfun_bleed_box ;
+
+% primarydef p bleeded d =
+%     image (
+%         mfun_bleed_box := boundingbox p ;
+%         if pair d :
+%             draw p xysized (bbwidth(p)+2*xpart d,bbheight(p)+2*ypart d) shifted -d ;
+%         else :
+%             draw p xysized (bbwidth(p)+2d,bbheight(p)+2d) shifted (-d,-d) ;
+%         fi ;
+%         setbounds currentpicture to mfun_bleed_box ;
+%     )
+% enddef ;
+
+%D New helpers:
+
+def beginglyph(expr unicode, width, height, depth) =
+    beginfig(unicode) ; % the number is irrelevant
+    charcode := unicode ;
+    charwd   := width ;
+    charht   := height ;
+    chardp   := depth ;
+enddef ;
+
+def endglyph =
+    setbounds currentpicture to (boundingbox unitsquare xscaled charwd yscaled (charht + chardp) shifted (0,-chardp)) ;
+    if known charscale :
+        currentpicture := currentpicture scaled charscale ;
+    fi ;
+    endfig ;
+enddef ;
+
+%D Dimensions have bever been an issue as traditional MP can't make that large
+%D pictures, but with double mode we need a catch:
+
+newinternal maxdimensions ; maxdimensions := 14000 ;
+
+def mfun_apply_max_dimensions = % not a generic helper, we want to protect this one
+    if bbwidth currentpicture > maxdimensions :
+        currentpicture := currentpicture if bbheight currentpicture  > bbwidth currentpicture : ysized else : xsized fi maxdimensions ;
+    elseif bbheight currentpicture  > maxdimensions :
+        currentpicture := currentpicture ysized maxdimensions ;
+    fi ;
+enddef;
+
+extra_endfig := extra_endfig & "mfun_apply_max_dimensions ;" ;
+
+let dump = relax ;
+

Added: trunk/Master/texmf-dist/metapost/context/base/mpii/mp-txts.mpii
===================================================================
--- trunk/Master/texmf-dist/metapost/context/base/mpii/mp-txts.mpii	                        (rev 0)
+++ trunk/Master/texmf-dist/metapost/context/base/mpii/mp-txts.mpii	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,66 @@
+%D \module
+%D   [       file=mp-txts.mpii,
+%D        version=2006.06.08,
+%D          title=\CONTEXT\ \METAPOST\ graphics,
+%D       subtitle=more text support,
+%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 licen-en.pdf for
+%C details.
+
+if known context_txts : endinput ; fi ;
+
+boolean context_txts ; context_txts := true ;
+
+%D The real code:
+
+string  txtfile  ; txtfile  := "" ;
+string  txtfont  ; txtfont  := defaultfont ;
+string  txtpref  ; txtpref  := "00001::::" ;
+numeric txtnext  ; txtnext  := 0 ;
+numeric txtdepth ; txtdepth := 0 ;
+
+vardef nexttxt =
+   txtnext := txtnext + 1 ;
+   txtnext
+enddef ;
+
+picture savedtxts[] ;
+numeric depthtxts[] ;
+
+vardef zerofilled(expr fd) =
+    if fd<10: "0000" else :
+    if fd<100: "000" else :
+    if fd<1000: "00" else :
+    if fd<10000: "0" else :
+    fi fi fi fi & decimal fd
+enddef;
+
+vardef savetxt(expr n,w,h,d) text t =
+    depthtxts[n] := d ;
+    savedtxts[n] := ((txtpref & zerofilled(n)) infont txtfont) xysized(w,h+d) t
+enddef ;
+
+vardef sometxt(expr n) =
+    if known savedtxts[n] :
+        txtdepth := depthtxts[n] ; savedtxts[n]
+    else :
+        txtdepth := 0 ; nullpicture
+    fi
+enddef ;
+
+def loadtxts =
+    if txtfile <> "" :
+        readfile(txtfile) ;
+    fi ;
+enddef ;
+
+def StartTexts =
+    loadtxts ;
+enddef ;
+
+def StopTexts =
+enddef ;

Added: trunk/Master/texmf-dist/scripts/context/ruby/base/ctx.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/ctx.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/ctx.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,462 @@
+# module    : base/ctx
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# todo: write systemcall for mpost to file so that it can be run
+# faster
+
+# report ?
+
+require 'base/system'
+require 'base/file'
+require 'base/switch' # has needsupdate, bad place
+
+require 'rexml/document'
+
+class CtxRunner
+
+    attr_reader :environments, :modules, :filters, :flags, :modes
+
+    @@suffix = 'prep'
+
+    def initialize(jobname=nil,logger=nil)
+        if @logger = logger then
+            def report(str='')
+                @logger.report(str)
+            end
+        else
+            def report(str='')
+                puts(str)
+            end
+        end
+        @jobname = jobname
+        @ctxname = nil
+        @xmldata = nil
+        @prepfiles = Hash.new
+        @environments = Array.new
+        @modules = Array.new
+        @filters = Array.new
+        @flags = Array.new
+        @modes = Array.new
+        @local = false
+        @paths = Array.new
+    end
+
+    def register_path(str)
+        @paths << str
+    end
+
+    def manipulate(ctxname=nil,defaultname=nil)
+
+        if ctxname then
+            @ctxname = ctxname
+            @jobname = File.suffixed(@ctxname,'tex') unless @jobname
+        else
+            @ctxname = File.suffixed(@jobname,'ctx') if @jobname
+        end
+
+        if not @ctxname then
+            report('no ctx file specified')
+            return
+        end
+
+        if @ctxname !~ /\.[a-z]+$/ then
+            @ctxname += ".ctx"
+        end
+
+        # name can be kpse:res-make.ctx
+        if not FileTest.file?(@ctxname) then
+            fullname, done = '', false
+            if @ctxname =~ /^kpse:/ then
+                begin
+                    if fullname = Kpse.found(@ctxname.sub(/^kpse:/,'')) then
+                        @ctxname, done = fullname, true
+                    end
+                rescue
+                    # should not happen
+                end
+            else
+                ['..','../..'].each do |path|
+                    begin
+                        fullname = File.join(path, at ctxname)
+                        if FileTest.file?(fullname) then
+                            @ctxname, done = fullname, true
+                        end
+                    rescue
+                        # probably strange join
+                    end
+                    break if done
+                end
+                if ! done then
+                    fullname = Kpse.found(@ctxname)
+                    if FileTest.file?(fullname) then
+                        @ctxname, done = fullname, true
+                    end
+                end
+            end
+            if ! done && defaultname && FileTest.file?(defaultname) then
+                report("using default ctxfile #{defaultname}")
+                @ctxname, done = defaultname, true
+            end
+            if not done then
+                report('no ctx file found')
+                return false
+            end
+        end
+
+        if FileTest.file?(@ctxname) then
+            @xmldata = IO.read(@ctxname)
+        else
+            report('no ctx file found')
+            return false
+        end
+
+        unless @xmldata =~ /^.*<\?xml.*?\?>/moi then
+            report("ctx file #{@ctxname} is no xml file, skipping")
+            return
+        else
+            report("loading ctx file #{@ctxname}")
+        end
+
+        if @xmldata then
+            # out if a sudden rexml started to be picky about namespaces
+            @xmldata.gsub!(/<ctx:job>/,"<ctx:job xmlns:ctx='http://www.pragma-ade.com/rng/ctx.rng'>")
+        end
+
+        begin
+            @xmldata = REXML::Document.new(@xmldata)
+        rescue
+            report('provide valid ctx file (xml error)')
+            return
+        else
+            include(@xmldata,'ctx:include','name')
+        end
+
+        begin
+            variables = Hash.new
+            if @jobname then
+                variables['job'] = @jobname
+            end
+            root = @xmldata.root
+            REXML::XPath.each(root,"/ctx:job//ctx:flags/ctx:flag") do |flg|
+                @flags << justtext(flg)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:resources/ctx:environment") do |sty|
+                @environments << justtext(sty)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:resources/ctx:module") do |mod|
+                @modules << justtext(mod)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:resources/ctx:filter") do |fil|
+                @filters << justtext(fil)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:resources/ctx:mode") do |fil|
+                @modes << justtext(fil)
+            end
+            begin
+                REXML::XPath.each(root,"//ctx:block") do |blk|
+                    if @jobname && blk.attributes['pattern'] then
+                        root.delete(blk) unless @jobname =~ /#{blk.attributes['pattern']}/
+                    else
+                        root.delete(blk)
+                    end
+                end
+            rescue
+            end
+            REXML::XPath.each(root,"//ctx:value[@name='job']") do |val|
+                substititute(val,variables['job'])
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:message") do |mes|
+                report("preprocessing: #{justtext(mes)}")
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:environment") do |sty|
+                @environments << justtext(sty)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:module") do |mod|
+                @modules << justtext(mod)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:filter") do |fil|
+                @filters << justtext(fil)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:mode") do |fil|
+                @modes << justtext(fil)
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:flags/ctx:flag") do |flg|
+                @flags << justtext(flg)
+            end
+            commands = Hash.new
+            REXML::XPath.each(root,"/ctx:job//ctx:preprocess/ctx:processors/ctx:processor") do |pre|
+                begin
+                    commands[pre.attributes['name']] = pre
+                rescue
+                end
+            end
+            suffix = @@suffix
+            begin
+                suffix = REXML::XPath.match(root,"/ctx:job//ctx:preprocess/@suffix").to_s
+            rescue
+                suffix = @@suffix
+            else
+                if suffix && suffix.empty? then suffix = @@suffix end
+            end
+            if (REXML::XPath.first(root,"/ctx:job//ctx:preprocess/ctx:processors/@local").to_s =~ /(yes|true)/io rescue false) then
+                @local = true
+            else
+                @local = false
+            end
+            REXML::XPath.each(root,"/ctx:job//ctx:preprocess/ctx:files") do |files|
+                REXML::XPath.each(files,"ctx:file") do |pattern|
+                    suffix = @@suffix
+                    begin
+                        suffix = REXML::XPath.match(root,"/ctx:job//ctx:preprocess/@suffix").to_s
+                    rescue
+                        suffix = @@suffix
+                    else
+                        if suffix && suffix.empty? then suffix = @@suffix end
+                    end
+                    preprocessor = pattern.attributes['processor']
+                    if preprocessor and not preprocessor.empty? then
+                        begin
+                            variables['old'] = @jobname
+                            variables['new'] = ""
+                            REXML::XPath.each(pattern,"ctx:value") do |value|
+                                if name = value.attributes['name'] then
+                                    substititute(value,variables[name.to_s])
+                                end
+                            end
+                        rescue
+                            report('unable to resolve file pattern')
+                            return
+                        end
+                        pattern = justtext(pattern)
+                        oldfiles = Dir.glob(pattern)
+                        pluspath = false
+                        if oldfiles.length == 0 then
+                            report("no files match #{pattern}")
+                            if @paths.length > 0 then
+                                @paths.each do |p|
+                                    oldfiles = Dir.glob("#{p}/#{pattern}")
+                                    if oldfiles.length > 0 then
+                                        pluspath = true
+                                        break
+                                    end
+                                end
+                                if oldfiles.length == 0 then
+                                    report("no files match #{pattern} on path")
+                                end
+                            end
+                        end
+                        oldfiles.each do |oldfile|
+                            newfile = "#{oldfile}.#{suffix}"
+                            newfile = File.basename(newfile) if @local # or pluspath
+                            if File.expand_path(oldfile) != File.expand_path(newfile) && File.needsupdate(oldfile,newfile) then
+                                report("#{oldfile} needs preprocessing")
+                                begin
+                                    File.delete(newfile)
+                                rescue
+                                    # hope for the best
+                                end
+                                # there can be a sequence of processors
+                                preprocessor.split(',').each do |pp|
+                                    if command = commands[pp] then
+                                        # a lie: no <?xml ...?>
+                                        command = REXML::Document.new(command.to_s) # don't infect original
+                                        # command = command.deep_clone() # don't infect original
+                                        command = command.elements["ctx:processor"]
+                                        if suf = command.attributes['suffix'] then
+                                            newfile = "#{oldfile}.#{suf}"
+                                        end
+                                        begin
+                                            newfile = File.basename(newfile) if @local
+                                        rescue
+                                        end
+                                        REXML::XPath.each(command,"ctx:old") do |value| replace(value,oldfile) end
+                                        REXML::XPath.each(command,"ctx:new") do |value| replace(value,newfile) end
+                                        report("preprocessing #{oldfile} into #{newfile} using #{pp}")
+                                        variables['old'] = oldfile
+                                        variables['new'] = newfile
+                                        REXML::XPath.each(command,"ctx:value") do |value|
+                                            if name = value.attributes['name'] then
+                                                substititute(value,variables[name.to_s])
+                                            end
+                                        end
+                                        command = justtext(command)
+                                        report(command)
+                                        unless ok = System.run(command) then
+                                            report("error in preprocessing file #{oldfile}")
+                                        end
+                                        begin
+                                            oldfile = File.basename(oldfile) if @local
+                                        rescue
+                                        end
+                                    end
+                                end
+                                if FileTest.file?(newfile) then
+                                    File.syncmtimes(oldfile,newfile)
+                                else
+                                    report("check target location of #{newfile}")
+                                end
+                            else
+                                report("#{oldfile} needs no preprocessing (same file)")
+                            end
+                            @prepfiles[oldfile] = FileTest.file?(newfile)
+                        end
+                    end
+                end
+            end
+        rescue
+            report("fatal error in preprocessing #{@ctxname}: #{$!}")
+        end
+    end
+
+    def savelog(ctlname=nil)
+        unless ctlname then
+            if @jobname then
+                ctlname = File.suffixed(@jobname,'ctl')
+            elsif @ctxname then
+                ctlname = File.suffixed(@ctxname,'ctl')
+            else
+                return
+            end
+        end
+        if @prepfiles.length > 0 then
+            if log = File.open(ctlname,'w') then
+                log << "<?xml version='1.0' standalone='yes'?>\n\n"
+                if @local then
+                    log << "<ctx:preplist local='yes'>\n"
+                else
+                    log << "<ctx:preplist local='no'>\n"
+                end
+                @prepfiles.keys.sort.each do |prep|
+                    # log << "\t<ctx:prepfile done='#{yes_or_no(@prepfiles[prep])}'>#{File.basename(prep)}</ctx:prepfile>\n"
+                    log << "\t<ctx:prepfile done='#{yes_or_no(@prepfiles[prep])}'>#{prep}</ctx:prepfile>\n"
+                end
+                log << "</ctx:preplist>\n"
+                log.close
+            end
+        else
+            begin
+                File.delete(ctlname)
+            rescue
+            end
+        end
+    end
+
+    private
+
+    def include(xmldata,element='ctx:include',attribute='name')
+        loop do
+            begin
+                more = false
+                REXML::XPath.each(xmldata.root,element) do |e|
+                    begin
+                        name = e.attributes.get_attribute(attribute).to_s
+                        name = e.text.to_s if name.empty?
+                        name.strip! if name
+                        done = false
+                        if name and not name.empty? then
+                            ['.',File.dirname(@ctxname),'..','../..'].each do |path|
+                                begin
+                                    fullname = if path == '.' then name else File.join(path,name) end
+                                    if FileTest.file?(fullname) then
+                                        if f = File.open(fullname,'r') and i = REXML::Document.new(f) then
+                                            report("including ctx file #{name}")
+                                            REXML::XPath.each(i.root,"*") do |ii|
+                                                xmldata.root.insert_before(e,ii)
+                                                more = true
+                                            end
+                                        end
+                                        done = true
+                                    end
+                                rescue
+                                end
+                                break if done
+                            end
+                        end
+                        report("no valid ctx inclusion file #{name}") unless done
+                    rescue Exception
+                        # skip this file
+                    ensure
+                        xmldata.root.delete(e)
+                    end
+                end
+                break unless more
+            rescue Exception
+                break # forget about inclusion
+            end
+        end
+    end
+
+    private
+
+    def yes_or_no(b)
+        if b then 'yes' else 'no' end
+    end
+
+    private # copied from rlxtools.rb
+
+    def justtext(str)
+        str = str.to_s
+        str.gsub!(/<[^>]*?>/o, '')
+        str.gsub!(/\s+/o, ' ')
+        str.gsub!(/</o, '<')
+        str.gsub!(/>/o, '>')
+        str.gsub!(/&/o, '&')
+        str.gsub!(/"/o, '"')
+        str.gsub!(/[\/\\]+/o, '/')
+        return str.strip
+    end
+
+    def substititute(value,str)
+        if str then
+            begin
+                if value.attributes.key?('method') then
+                    str = filtered(str.to_s,value.attributes['method'].to_s)
+                end
+                if str.empty? && value.attributes.key?('default') then
+                    str = value.attributes['default'].to_s
+                end
+                value.insert_after(value,REXML::Text.new(str.to_s))
+            rescue Exception
+            end
+        end
+    end
+
+    def replace(value,str)
+        if str then
+            begin
+                value.insert_after(value,REXML::Text.new(str.to_s))
+            rescue Exception
+            end
+        end
+    end
+
+    def filtered(str,method)
+        str = str.to_s # to be sure
+        case method
+            when 'name' then # no path, no suffix
+                case str
+                    when /^.*[\\\/](.+?)\..*?$/o then $1
+                    when /^.*[\\\/](.+?)$/o      then $1
+                    when /^(.*)\..*?$/o          then $1
+                    else                              str
+                end
+            when 'path'     then if str =~ /^(.+)([\\\/])(.*?)$/o then $1 else ''  end
+            when 'suffix'   then if str =~ /^.*\.(.*?)$/o         then $1 else ''  end
+            when 'nosuffix' then if str =~ /^(.*)\..*?$/o         then $1 else str end
+            when 'nopath'   then if str =~ /^.*[\\\/](.*?)$/o     then $1 else str end
+            when 'base'     then if str =~ /^.*[\\\/](.*?)$/o     then $1 else str end
+            when 'full'     then str
+            when 'complete' then str
+            when 'expand'   then File.expand_path(str).gsub(/\\/,"/")
+            else                 str
+        end
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/ctx.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/exa.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/exa.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/exa.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,407 @@
+# \setuplayout[width=3cm]
+#
+# tex.setup.setuplayout.width.[integer|real|dimension|string|key]
+# tex.[mp]var.whatever.width.[integer|real|dimension|string|key]
+
+require 'fileutils'
+# require 'ftools'
+require 'digest/md5'
+
+# this can become a lua thing
+
+# no .*? but 0-9a-z\:\. because other too slow (and greedy)
+
+class Hash
+
+    def subset(pattern)
+        h = Hash.new
+        r = /^#{pattern.gsub('.','\.')}/
+        self.keys.each do |k|
+            h[k] = self[k].dup if k =~ r
+        end
+        return h
+    end
+
+end
+
+module ExaEncrypt
+
+    def ExaEncrypt.encrypt_base(logger, oldfilename, newfilename)
+        if FileTest.file?(oldfilename) then
+            logger.report("checking #{oldfilename}") if logger
+            if data = IO.read(oldfilename) then
+                done = false
+                # cfg file:
+                #
+                # banner : exa configuration file
+                # user   : domain, name = password, projectlist
+                #
+                if data =~ /^\s*banner\s*\:\s*exa\s*configuration\s*file/ then
+                    data.gsub!(/^(\s*user\s*\:\s*.+?\s*\,\s*.+?\s*\=\s*)(.+?)(\s*\,\s*.+\s*)$/) do
+                        pre, password, post = $1, $2, $3
+                        unless password =~ /MD5:/i then
+                            done = true
+                            password = "MD5:" + Digest::MD5.hexdigest(password).upcase
+                        end
+                        "#{pre}#{password}#{post}"
+                    end
+                else
+                    data.gsub!(/<exa:password([^>]*?)>(.*?)<\/exa:password>/moi) do
+                        attributes, password = $1, $2
+                        unless password =~ /^([0-9A-F][0-9A-F])+$/ then
+                            done = true
+                            password = Digest::MD5.hexdigest(password).upcase
+                            attributes = " encryption='md5'#{attributes}"
+                        end
+                        "<exa:password#{attributes}>#{password}</exa:password>"
+                    end
+                end
+                begin
+                    File.open(newfilename,'w') do |f|
+                        f.puts(data)
+                    end
+                rescue
+                    logger.report("#{newfilename} cannot be written") if logger
+                else
+                    logger.report("#{oldfilename} encrypted into #{newfilename}") if done and logger
+                end
+            end
+        end
+    end
+
+end
+
+module ExaModes
+
+    @@modefile = 'examodes.tex'
+
+    @@request = /(<exa:request.*?)(>.*?<\/exa:request>)/mo
+    @@redone  = /<exa:request[^>]*?texified=([\'\"])yes\1.*?>/mo
+    @@reload  = /<(exa:variable)([^>]+?label\=)([\"\'])([0-9A-Za-z\-\.\:]+?)(\3[^\/]*?)>(.*?)<(\/exa:variable)>/mo
+    @@recalc  = /<(exa:variable)([^>]+?label\=)([\"\'])([0-9A-Za-z\-\.\:]+?)([\.\:]calcmath)(\3[^\/]*?)>(.*?)<(\/exa:variable)>/mo
+    @@rename  = /<(exa:variable)([^>]+?label\=)([\"\'])([0-9A-Za-z\-\.\:]+?)(\3[^\/]*?)>(.*?)<(\/exa:variable)>/mo
+    @@refile  = /<(exa:filename|exa:filelist)>(.*?)<(\/\1)>/mo
+
+    def ExaModes.cleanup_request(logger,filename='request.exa',modefile=@@modefile)
+        begin File.delete(filename+'.raw') ; rescue ; end
+        begin File.delete(modefile)        ; rescue ; end
+        if FileTest.file?(filename) then
+            data, done = nil, false
+            begin
+                data = IO.read(filename)
+            rescue
+                data = nil
+            end
+            if data =~ @@request and data !~ @@redone then
+                data.gsub!(@@rename) do
+                    done = true
+                    '<' + $1 + $2 + $3 + $4 + $5 + '>' +
+                    texifiedstr($4,$6) +
+                    '<' + $7 + '>'
+                end
+                data.gsub!(@@refile) do
+                    done = true
+                    '<' + $1 + '>' +
+                    cleanpath($2) +
+                    '<' + $3 + '>'
+                end
+                data.gsub!(@@recalc) do
+                    done = true
+                    '<' + $1 + $2 + $3 + $4 + ":raw" + $6 + '>' + $7 + '<' + $8 + '>' +
+                    '<' + $1 + $2 + $3 + $4 + $6 + '>' +
+                    calculatortexmath($7,false) +
+                    '<' + $8 + '>'
+                end
+                if done then
+                    data.gsub!(@@request) do
+                        $1 + " texified='yes'" + $2
+                    end
+                    begin File.copy(filename, filename+'.raw') ; rescue ; end
+                    begin
+                        logger.report("rewriting #{filename}") if logger
+                        File.open(filename,'w') do |f|
+                            f.puts(data)
+                        end
+                    rescue
+                        logger.report("#{filename} cannot be rewritten") if logger
+                    end
+                end
+            else
+                logger.report("#{filename} is already ok") if logger
+            end
+            @variables = Hash.new
+            data.scan(@@reload) do
+                @variables[$4] = $5
+            end
+            vars   = @variables.subset('data.tex.var')
+            mpvars = @variables.subset('data.tex.mpvar')
+            modes  = @variables.subset('data.tex.mode')
+            setups = @variables.subset('data.tex.setup')
+            if not (modes.empty? and setups.empty? and vars.empty? and mpvars.empty?) then
+                begin
+                    File.open(modefile,'w') do |mod|
+                        logger.report("saving modes and setups in #{modefile}") if logger
+                        if not modes.empty? then
+                            for key in modes.keys do
+                                k = key.dup
+                                k.gsub!(/\./,'-')
+                                mod.puts("\\enablemode[#{k}-#{modes[key]}]\n")
+                                if modes[key] =~ /(on|yes|start)/o then # ! ! ! ! !
+                                    mod.puts("\\enablemode[#{k}]\n")
+                                end
+                            end
+                            mod.puts("\n\\readfile{cont-mod}{}{}\n")
+                        end
+                        if not setups.empty? then
+                            for key in setups.keys
+                                if key =~ /^(.+?)\.(.+?)\.(.+?)$/o then
+                                    command, key, type, value = $1, $2, $3, setups[key]
+                                    value = cleanedup(key,type,value)
+                                    mod.puts("\\#{$1}[#{key}=#{value}]\n")
+                                elsif key =~ /^(.+?)\.(.+?)$/o then
+                                    command, type, value = $1, $2, setups[key]
+                                    mod.puts("\\#{$1}[#{value}]\n")
+                                end
+                            end
+                        end
+                        savevaroptions(vars,  'setvariables',  mod)
+                        savevaroptions(mpvars,'setMPvariables',mod)
+                    end
+                rescue
+                    logger.report("#{modefile} cannot be saved") if logger
+                end
+            else
+                logger.report("#{modefile} is not created") if logger
+            end
+        end
+    end
+
+    private
+
+    def ExaModes.autoparenthesis(str)
+        if str =~ /[\+\-]/o then '[1]' + str + '[1]' else str end
+    end
+
+    def ExaModes.cleanedup(key,type,value)
+        if type == 'dimension' then
+            unless value =~ /(cm|mm|in|bp|sp|pt|dd|em|ex)/o
+                value + 'pt'
+            else
+                value
+            end
+        elsif type == 'calcmath' then
+            '{' + calculatortexmath(value,true) + '}'
+        elsif type =~ /^filename|filelist$/ or key =~ /^filename|filelist$/ then
+            cleanpath(value)
+        else
+            value
+        end
+    end
+
+    def ExaModes.cleanpath(str)
+        (str ||'').gsub(/\\/o,'/')
+    end
+
+    def ExaModes.texifiedstr(key,val)
+        case key
+            when 'filename' then
+                cleanpath(val)
+            when 'filelist' then
+                cleanpath(val)
+            else
+                val
+        end
+    end
+
+    def ExaModes.savevaroptions(vars,setvariables,mod)
+        if not vars.empty? then
+            for key in vars.keys do
+                # var.whatever.width.dimension.value
+                if key =~ /^(.+?)\.(.+?)\.(.+?)$/o then
+                    tag, key, type, value = $1, $2, $3, vars[key]
+                    value = cleanedup(key,type,value)
+                    mod.puts("\\#{setvariables}[#{tag}][#{key}=#{value}]\n")
+                elsif key =~ /^(.+?)\.(.+?)$/o then
+                    tag, key, value = $1, $2, vars[key]
+                    mod.puts("\\#{setvariables}[#{tag}][#{key}=#{value}]\n")
+                end
+            end
+        end
+    end
+
+    def ExaModes.calculatortexmath(str,tx=true)
+        if tx then
+            bdisp, edisp = "\\displaymath\{", "\}"
+            binln, einln = "\\inlinemath\{" , "\}"
+            egraf        = "\\endgraf"
+        else
+            bdisp, edisp = "<displaytexmath>", "</displaytexmath>"
+            binln, einln = "<inlinetexmath>" , "</inlinetexmath>"
+            egraf        = "<p/>"
+        end
+        str.gsub!(/\n\s*\n+/moi, "\\ENDGRAF ")
+        str.gsub!(/(\[\[)\s*(.*?)\s*(\]\])/mos) do
+            $1 + docalculatortexmath($2) + $3
+        end
+        str.gsub!(/(\\ENDGRAF)+\s*(\[\[)\s*(.*?)\s*(\]\])/moi) do
+            $1 + bdisp + $3 + edisp
+        end
+        str.gsub!(/(\[\[)\s*(.*?)\s*(\]\])/o) do
+            binln + $2 + einln
+        end
+        str.gsub!(/\\ENDGRAF/mos, egraf)
+        str
+    end
+
+    def ExaModes.docalculatortexmath(str)
+        str.gsub!(/\n/o) { ' ' }
+        str.gsub!(/\s+/o) { ' ' }
+        str.gsub!(/>/o) { '>' }
+        str.gsub!(/</o) { '<' }
+        str.gsub!(/&.*?;/o) { }
+        level = 0
+        str.gsub!(/([\(\)])/o) do |chr|
+            if    chr == '(' then
+                level = level + 1
+                chr = '[' + level.to_s + ']'
+            elsif chr == ')' then
+                chr = '[' + level.to_s + ']'
+                level = level - 1
+            end
+            chr
+        end
+        # ...E...
+        loop do
+            break unless str.gsub!(/([\d\.]+)E([\-\+]{0,1}[\d\.]+)/o) do
+                "\{\\SCINOT\{#{$1}\}\{#{$2}\}\}"
+            end
+        end
+        # ^-..
+        loop do
+            break unless str.gsub!(/\^([\-\+]*\d+)/o) do
+                "\^\{#{$1}\}"
+            end
+        end
+        # ^(...)
+        loop do
+            break unless str.gsub!(/\^(\[\d+\])(.*?)\1/o) do
+                "\^\{#{$2}\}"
+            end
+        end
+        # 1/x^2
+        loop do
+            break unless str.gsub!(/([\d\w\.]+)\/([\d\w\.]+)\^([\d\w\.]+)/o) do
+                "@\{#{$1}\}\{#{$2}\^\{#{$3}\}\}"
+            end
+        end
+        # int(a,b,c)
+        loop do
+            break unless str.gsub!(/(int|sum|prod)(\[\d+\])(.*?),(.*?),(.*?)\2/o) do
+                "\\#{$1.upcase}\^\{#{$4}\}\_\{#{$5}\}\{#{autoparenthesis($3)}\}"
+            end
+        end
+        # int(a,b)
+        loop do
+            break unless str.gsub!(/(int|sum|prod)(\[\d+\])(.*?),(.*?)\2/o) do
+                "\\#{$1.upcase}\_\{#{$4}\}\{#{autoparenthesis($3)}\}"
+            end
+        end
+        # int(a)
+        loop do
+            break unless str.gsub!(/(int|sum|prod)(\[\d+\])(.*?)\2/o) do
+                "\\#{$1.upcase}\{#{autoparenthesis($3)}\}"
+            end
+        end
+        # sin(x) => {\sin(x)}
+        loop do
+            break unless str.gsub!(/(median|min|max|round|sqrt|sin|cos|tan|sinh|cosh|tanh|ln|log)\s*(\[\d+\])(.*?)\2/o) do
+                "\{\\#{$1.upcase}\{#{$2}#{$3}#{$2}\}\}"
+            end
+        end
+        # mean
+        str.gsub!(/(mean)(\[\d+\])(.*?)\2/o) do
+            "\{\\OVERLINE\{#{$3}\}\}"
+        end
+        # sin x  => {\sin(x)}
+        # ...
+        # (1+x)/(1+x) => \frac{1+x}{1+x}
+        loop do
+            break unless str.gsub!(/(\[\d+\])(.*?)\1\/(\[\d+\])(.*?)\3/o) do
+                "@\{#{$2}\}\{#{$4}\}"
+            end
+        end
+        # (1+x)/x => \frac{1+x}{x}
+        loop do
+            break unless str.gsub!(/(\[\d+\])(.*?)\1\/([a-zA-Z0-9]+)/o) do
+                "@\{#{$2}\}\{#{$3}\}"
+            end
+        end
+        # 1/(1+x) => \frac{1}{1+x}
+        loop do
+            break unless str.gsub!(/([a-zA-Z0-9]+)\/(\[\d+\])(.*?)\2/o) do
+                "@\{#{$1}\}\{#{$3}\}"
+            end
+        end
+        # 1/x => \frac{1}{x}
+        loop do
+            break unless str.gsub!(/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)/o) do
+                "@\{#{$1}\}\{#{$2}\}"
+            end
+        end
+        #
+        str.gsub!(/\@/o) do
+            "\\FRAC "
+        end
+        str.gsub!(/\*/o) do
+            " "
+        end
+        str.gsub!(/\<\=/o) do
+            "\\LE "
+        end
+        str.gsub!(/\>\=/o) do
+            "\\GE "
+        end
+        str.gsub!(/\=/o) do
+            "\\EQ "
+        end
+        str.gsub!(/\</o) do
+            "\\LT "
+        end
+        str.gsub!(/\>/) do
+            "\\GT "
+        end
+        str.gsub!(/(D)(\[\d+\])(.*?)\2/o) do
+            "\{\\FRAC\{\\MBOX{d}\}\{\\MBOX{d}x\}\{#{$2}#{$3}#{$2}\}\}"
+        end
+        str.gsub!(/(exp)(\[\d+\])(.*?)\2/o) do
+            "\{e^\{#{$3}\}\}"
+        end
+        str.gsub!(/(abs)(\[\d+\])(.*?)\2/o) do
+            "\{\\left\|#{$3}\\right\|\}"
+        end
+        str.gsub!(/D([x|y])/o) do
+            "\\FRAC\{\{\\rm d\}#{$1}\}\{\{\\rm d\}x\}"
+        end
+        str.gsub!(/D([f|g])(\[\d+\])(.*?)\2/o) do
+            "\{\\rm #{$1}\}'#{$2}#{$3}#{$2}"
+        end
+        str.gsub!(/([f|g])(\[\d+\])(.*?)\2/o) do
+            "\{\\rm #{$1}\}#{$2}#{$3}#{$2}"
+        end
+        str.gsub!(/(pi|inf)/io) do
+            "\\#{$1} "
+        end
+        loop do
+            break unless str.gsub!(/(\[\d+?\])(.*?)\1/o) do
+                "\\left(#{$2}\\right)"
+            end
+        end
+        str.gsub!(/\\([A-Z]+?)([\s\{\^\_\\])/io) do
+            "\\#{$1.downcase}#{$2}"
+        end
+        str
+    end
+
+end
+
+# ExaModes.cleanup_request()


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/exa.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/file.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/file.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/file.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,150 @@
+# module    : base/file
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+require 'fileutils'
+# require 'ftools'
+
+class File
+
+    def File.suffixed(name,sufa,sufb=nil)
+        if sufb then
+            if sufa.empty? then
+                unsuffixed(name) + ".#{sufb}"
+            else
+                unsuffixed(name) + "-#{sufa}.#{sufb}"
+            end
+        else
+            unsuffixed(name) + ".#{sufa}"
+        end
+    end
+
+    def File.unsuffixed(name)
+        name.sub(/\.[^\.]*?$/o, '')
+    end
+
+    def File.suffix(name,default='')
+        if name =~ /\.([^\.]*?)$/o then
+            $1
+        else
+            default
+        end
+    end
+
+    def File.splitname(name,suffix='')
+        if name =~ /^(.*)\.([^\.]*?)$/o then
+            [$1, $2]
+        else
+            [name, suffix]
+        end
+    end
+
+end
+
+class File
+
+    def File.silentopen(name,method='r')
+        begin
+            f = File.open(name,method)
+        rescue
+            return nil
+        else
+            return f
+        end
+    end
+
+    def File.silentread(name)
+        begin
+            data = IO.read(name)
+        rescue
+            return nil
+        else
+            return data
+        end
+    end
+
+    def File.atleast?(name,n=0)
+        begin
+            size = FileTest.size(name)
+        rescue
+            return false
+        else
+            return size > n
+        end
+    end
+
+    def File.appended(name,str='')
+        if FileTest.file?(name) then
+            begin
+                if f = File.open(name,'a') then
+                    f << str
+                    f.close
+                    return true
+                end
+            rescue
+            end
+        end
+        return false
+    end
+
+    def File.written(name,str='')
+        begin
+            if f = File.open(name,'w') then
+                f << str
+                f.close
+                return true
+            end
+        rescue
+        end
+        return false
+    end
+
+    def File.silentdelete(filename)
+        File.delete(filename) rescue false
+    end
+
+    def File.silentcopy(oldname,newname)
+        return if File.expand_path(oldname) == File.expand_path(newname)
+        FileUtils.makedirs(File.dirname(newname)) rescue false
+        File.copy(oldname,newname) rescue false
+    end
+
+    def File.silentrename(oldname,newname)
+        # in case of troubles, we just copy the file; we
+        # maybe working over multiple file systems or
+        # apps may have mildly locked files (like gs does)
+        return if File.expand_path(oldname) == File.expand_path(newname)
+        File.delete(newname) rescue false
+        begin
+            File.rename(oldname,newname)
+        rescue
+            FileUtils.makedirs(File.dirname(newname)) rescue false
+            File.copy(oldname,newname) rescue false
+        end
+    end
+
+end
+
+class File
+
+    # handles "c:\tmp\test.tex" as well as "/${TEMP}/test.tex")
+
+    def File.unixfied(filename)
+        begin
+            str = filename.gsub(/\$\{*([a-z0-9\_]+)\}*/oi) do
+                if ENV.key?($1) then ENV[$1] else $1 end
+            end
+            str.gsub(/[\/\\]+/o, '/')
+        rescue
+            filename
+        end
+    end
+
+end
+


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/file.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/drb.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/drb.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/drb.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,57 @@
+require 'drb'
+require 'base/kpse/trees'
+
+class KpseServer
+
+    attr_accessor :port
+
+    def initialize(port=7000)
+        @port = port
+    end
+
+    def start
+        puts "starting drb service at port #{@port}"
+        DRb.start_service("druby://localhost:#{@port}", KpseTrees.new)
+        trap(:INT) do
+            DRb.stop_service
+        end
+        DRb.thread.join
+    end
+
+    def stop
+        # todo
+    end
+
+end
+
+class KpseClient
+
+    attr_accessor :port
+
+    def initialize(port=7000)
+        @port = port
+        @kpse = nil
+    end
+
+    def start
+        # only needed when callbacks are used / slow, due to Socket::getaddrinfo
+        # DRb.start_service
+    end
+
+    def object
+        @kpse = DRbObject.new(nil,"druby://localhost:#{@port}")
+    end
+
+end
+
+
+# SERVER_URI="druby://localhost:8787"
+#
+#   # Start a local DRbServer to handle callbacks.
+#   #
+#   # Not necessary for this small example, but will be required
+#   # as soon as we pass a non-marshallable object as an argument
+#   # to a dRuby call.
+#   DRb.start_service
+#
+#   timeserver = DRbObject.new_with_uri(SERVER_URI)


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/drb.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/soap.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/soap.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/soap.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,79 @@
+require 'soap/rpc/standaloneServer'
+require 'soap/rpc/driver'
+
+require 'base/kpse/trees'
+
+class KpseService < SOAP::RPC::StandaloneServer
+
+    def on_init
+        kpse = KpseTrees.new
+        add_method(kpse, 'choose', 'files', 'environment')
+        add_method(kpse, 'load', 'files', 'environment')
+        add_method(kpse, 'expand_variables', 'tree')
+        add_method(kpse, 'expand_braces', 'tree', 'str')
+        add_method(kpse, 'expand_path', 'tree', 'str')
+        add_method(kpse, 'expand_var', 'tree', 'str')
+        add_method(kpse, 'show_path', 'tree', 'str')
+        add_method(kpse, 'var_value', 'tree', 'str')
+        add_method(kpse, 'find_file', 'tree', 'filename')
+        add_method(kpse, 'find_files', 'tree', 'filename', 'first')
+    end
+
+end
+
+class KpseServer
+
+    @@url = 'http://kpse.thismachine.org/KpseService'
+
+    attr_accessor :port
+
+    def initialize(port=7000)
+        @port = port
+        @server = nil
+    end
+
+    def start
+        puts "starting soap service at port #{@port}"
+        @server = KpseService.new('KpseServer', @@url, '0.0.0.0', @port.to_i)
+        trap(:INT) do
+            @server.shutdown
+        end
+        status = @server.start
+    end
+
+    def stop
+        @server.shutdown rescue false
+    end
+
+end
+
+class KpseClient
+
+    @@url = 'http://kpse.thismachine.org/KpseService'
+
+    attr_accessor :port
+
+    def initialize(port=7000)
+        @port = port
+        @kpse = nil
+    end
+
+    def start
+        @kpse = SOAP::RPC::Driver.new("http://localhost:#{port}/", @@url)
+        @kpse.add_method('choose','files', 'environment')
+        @kpse.add_method('load','files', 'environment')
+        @kpse.add_method('expand_variables', 'tree')
+        @kpse.add_method('expand_braces', 'tree', 'str')
+        @kpse.add_method('expand_path', 'tree', 'str')
+        @kpse.add_method('expand_var', 'tree', 'str')
+        @kpse.add_method('show_path', 'tree', 'str')
+        @kpse.add_method('var_value', 'tree', 'str')
+        @kpse.add_method('find_file', 'tree', 'filename')
+        @kpse.add_method('find_files', 'tree', 'filename', 'first')
+    end
+
+    def object
+        @kpse
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/soap.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/trees.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/trees.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/trees.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,84 @@
+require 'monitor'
+require 'base/kpsefast'
+
+class KpseTrees < Monitor
+
+    def initialize
+        @trees = Hash.new
+    end
+
+    def pattern(filenames)
+        filenames.join('|').gsub(/\\+/o,'/').downcase
+    end
+
+    def choose(filenames,environment)
+        current = pattern(filenames)
+        load(filenames,environment) unless @trees[current]
+        puts "enabling tree #{current}"
+        current
+    end
+
+    def fetch(filenames,environment) # will send whole object !
+        current = pattern(filenames)
+        load(filenames,environment) unless @trees[current]
+        puts "fetching tree #{current}"
+        @trees[current]
+    end
+
+    def load(filenames,environment)
+        current = pattern(filenames)
+        puts "loading tree #{current}"
+        @trees[current] = KpseFast.new
+        @trees[current].push_environment(environment)
+        @trees[current].load_cnf(filenames)
+        @trees[current].expand_variables
+        @trees[current].load_lsr
+    end
+
+    def set(tree,key,value)
+        case key
+            when 'progname' then @trees[tree].progname = value
+            when 'engine'   then @trees[tree].engine   = value
+            when 'format'   then @trees[tree].format   = value
+        end
+    end
+    def get(tree,key)
+        case key
+            when 'progname' then @trees[tree].progname
+            when 'engine'   then @trees[tree].engine
+            when 'format'   then @trees[tree].format
+        end
+    end
+
+    def load_cnf(tree)
+        @trees[tree].load_cnf
+    end
+    def load_lsr(tree)
+        @trees[tree].load_lsr
+    end
+    def expand_variables(tree)
+        @trees[tree].expand_variables
+    end
+    def expand_braces(tree,str)
+        @trees[tree].expand_braces(str)
+    end
+    def expand_path(tree,str)
+        @trees[tree].expand_path(str)
+    end
+    def expand_var(tree,str)
+        @trees[tree].expand_var(str)
+    end
+    def show_path(tree,str)
+        @trees[tree].show_path(str)
+    end
+    def var_value(tree,str)
+        @trees[tree].var_value(str)
+    end
+    def find_file(tree,filename)
+        @trees[tree].find_file(filename)
+    end
+    def find_files(tree,filename,first)
+        @trees[tree].find_files(filename,first)
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse/trees.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpse.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpse.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,399 @@
+# module    : base/kpse
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# rename this one to environment
+#
+# todo: web2c vs miktex module and include in kpse
+
+require 'rbconfig'
+require 'fileutils'
+
+# beware $engine is lowercase in kpse
+#
+# miktex has mem|fmt|base paths
+
+class String
+
+    def split_path
+        if self =~ /\;/o || self =~ /^[a-z]\:/io then
+            self.split(";")
+        else
+            self.split(":")
+        end
+    end
+
+    def sane_path
+        self.gsub(/\\/,'/')
+    end
+
+end
+
+class Array
+
+    def join_path
+        self.join(File::PATH_SEPARATOR)
+    end
+
+    def non_empty
+        self.delete_if do |i|
+            (i == nil || i.empty?) rescue false
+        end
+    end
+
+end
+
+module Kpse
+
+    @@located       = Hash.new
+    @@paths         = Hash.new
+    @@scripts       = Hash.new
+    @@formats       = ['tex','texmfscripts','other text files']
+    @@progname      = 'context'
+    @@ownpath       = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
+    @@problems      = false
+    @@tracing       = false
+    @@distribution  = 'web2c'
+    @@crossover     = true
+    @@mswindows     = RbConfig::CONFIG['host_os'] =~ /mswin/
+
+    # @@distribution  = 'miktex' if ENV['PATH'] =~ /miktex[\\\/]bin/o
+
+    # if ENV['PATH'] =~ /(.*?)miktex[\\\/]bin/i then
+        # @@distribution = 'miktex' unless $1 =~ /(texmf\-mswin[\/\\]bin|bin[\/\\]win32)/i
+    # end
+
+    if @@mswindows && (ENV['PATH'] =~ /(.*?)miktex[\\\/]bin/i) then
+         @@distribution = 'miktex' unless $1 =~ /(texmf\-mswin[\/\\]bin|bin[\/\\]win32)/i
+    end
+
+    @@re_true = /yes|on|true|1/i
+
+    if (ENV['KPSEFAST'] =~ @@re_true) || (ENV['CTXMINIMAL'] =~ @@re_true) then
+        @@usekpserunner = true
+        require 'base/kpsefast'
+        require 'base/kpserunner'
+    else
+        @@usekpserunner = false
+    end
+
+    if @@crossover then
+        ENV.keys.each do |k|
+            case k
+                when /\_CTX\_KPSE\_V\_(.*?)\_/io then @@located[$1] = ENV[k].dup
+                when /\_CTX\_KPSE\_P\_(.*?)\_/io then @@paths  [$1] = ENV[k].dup.split(';')
+                when /\_CTX\_KPSE\_S\_(.*?)\_/io then @@scripts[$1] = ENV[k].dup
+            end
+        end
+    end
+
+    def Kpse.distribution
+        @@distribution
+    end
+
+    def Kpse.miktex?
+        @@distribution == 'miktex'
+    end
+
+    def Kpse.web2c?
+        @@distribution == 'web2c'
+    end
+
+    def Kpse.inspect
+        @@located.keys.sort.each do |k| puts("located : #{k} -> #{@@located[k]}\n") end
+        @@paths  .keys.sort.each do |k| puts("paths   : #{k} -> #{@@paths  [k]}\n") end
+        @@scripts.keys.sort.each do |k| puts("scripts : #{k} -> #{@@scripts[k]}\n") end
+    end
+
+    def Kpse.used_path(varname)
+        begin
+            if @@mswindows then
+                path = run("--expand-path=\$#{varname}") rescue ''
+            else
+                path = run("--expand-path='$#{varname}'") rescue ''
+            end
+        rescue
+            path = ''
+        end
+        return path.sane_path
+    end
+
+    def Kpse.found(filename, progname=nil, format=nil)
+        begin
+            tag = Kpse.key(filename) # all
+            if @@located.key?(tag) then
+                return @@located[tag].sane_path
+            elsif FileTest.file?(filename) then
+                setvariable(tag,filename)
+                return filename
+            elsif FileTest.file?(File.join(@@ownpath,filename)) then
+                setvariable(tag,File.join(@@ownpath,filename))
+                return @@located[tag].sane_path
+            else
+                [progname,@@progname].flatten.compact.uniq.each do |prg|
+                    [format,@@formats].flatten.compact.uniq.each do |fmt|
+                        begin
+                            tag = Kpse.key(filename,prg,fmt)
+                            if @@located.key?(tag) then
+                                return @@located[tag].sane_path
+                            elsif p = Kpse.kpsewhich(filename,prg,fmt) then
+                                setvariable(tag,p.chomp)
+                                return @@located[tag].sane_path
+                            end
+                        rescue
+                        end
+                    end
+                end
+                setvariable(tag,filename)
+                return filename.sane_path
+            end
+        rescue
+            filename.sane_path
+        end
+    end
+
+    def Kpse.kpsewhich(filename,progname,format)
+        p = if progname && ! progname.empty? then "-progname=#{progname}" else '' end
+        f = if format   && ! format.empty?   then "-format=\"#{format}\"" else '' end
+        Kpse.run("#{p} #{f} #{filename}")
+    end
+
+    def Kpse.which
+        Kpse.kpsewhich
+    end
+
+    def Kpse.run(arguments)
+        puts arguments if @@tracing
+        begin
+            if @@problems then
+                results = ''
+            elsif @@usekpserunner then
+                results = KpseRunner.kpsewhich(arguments).chomp
+            else
+                results = `kpsewhich #{arguments}`.chomp
+            end
+        rescue
+            puts "unable to run kpsewhich" if @@tracing
+            @@problems, results = true, ''
+        end
+        puts results if @@tracing
+        return results
+    end
+
+
+    def Kpse.formatpaths
+        # maybe we should check for writeability
+        unless @@paths.key?('formatpaths') then
+            begin
+                setpath('formatpaths',run("--show-path=fmt").sane_path.split_path)
+            rescue
+                setpath('formatpaths',[])
+            end
+        end
+        return @@paths['formatpaths']
+    end
+
+    def Kpse.key(filename='',progname='all',format='all')
+        [progname,format,filename].join('-')
+    end
+
+    def Kpse.formatpath(engine='pdftex',enginepath=true)
+
+        # because engine support in distributions is not always
+        # as we expect, we need to check for it;
+
+        # todo: miktex
+
+        if miktex? then
+            return '.'
+        else
+            unless @@paths.key?(engine) then
+                # savedengine = ENV['engine']
+                if ENV['TEXFORMATS'] && ! ENV['TEXFORMATS'].empty? then
+                    # make sure that we have a lowercase entry
+                    ENV['TEXFORMATS'] = ENV['TEXFORMATS'].sub(/\$engine/io,"\$engine")
+                    # well, we will append anyway, so we could also strip it
+                    # ENV['TEXFORMATS'] = ENV['TEXFORMATS'].sub(/\$engine/io,"")
+                end
+                # use modern method
+                if enginepath then
+                    formatpath = run("--engine=#{engine} --show-path=fmt")
+                else
+                    # ENV['engine'] = engine if engine
+                    formatpath = run("--show-path=fmt")
+                end
+                # use ancient method
+                if formatpath.empty? then
+                    if enginepath then
+                        if @@mswindows then
+                            formatpath = run("--engine=#{engine} --expand-path=\$TEXFORMATS")
+                        else
+                            formatpath = run("--engine=#{engine} --expand-path=\\\$TEXFORMATS")
+                        end
+                    end
+                    # either no enginepath or failed run
+                    if formatpath.empty? then
+                        if @@mswindows then
+                            formatpath = run("--expand-path=\$TEXFORMATS")
+                        else
+                            formatpath = run("--expand-path=\\\$TEXFORMATS")
+                        end
+                    end
+                end
+                # locate writable path
+                if ! formatpath.empty? then
+                    formatpaths, done = formatpath.split_path, false
+                    formatpaths.collect! do |fp|
+                        fp.gsub!(/\\/o,'/')
+                        fp.gsub!(/\/\/$/o,'/')
+                        # remove funny patterns
+                        fp.sub!(/^!!/o,'')
+                        fp.sub!(/\/+$/o,'')
+                        fp.sub!(/(unsetengine|unset)/o,if enginepath then engine else '' end)
+                        fp
+                    end
+                    formatpaths.delete_if do |fp|
+                        fp.empty? || fp == '.'
+                    end
+                    # the engine path may not yet be present, find first writable
+                    formatpaths.each do |fp|
+                        # strip (possible engine) and test for writeability
+                        fpp = fp.sub(/#{engine}\/*$/o,'')
+                        if FileTest.directory?(fpp) && FileTest.writable?(fpp) then
+                            # use this path
+                            formatpath, done = fp.dup, true
+                            break
+                        end
+                    end
+                    unless done then
+                        formatpaths.each do |fp|
+                            fpp = fp.sub(/#{engine}\/*$/o,'')
+                            FileUtils.makedirs(fpp) rescue false # maybe we don't have an path yet
+                            if FileTest.directory?(fpp) && FileTest.writable?(fpp) then
+                                # use this path
+                                formatpath, done = fp.dup, true
+                                break
+                            end
+                        end
+                    end
+                    unless done then
+                        formatpath = '.'
+                    end
+                end
+                # needed !
+                FileUtils.makedirs(formatpath) rescue false
+                # fall back to current path
+                formatpath = '.' if formatpath.empty? || ! FileTest.writable?(formatpath)
+                # append engine but prevent duplicates
+                formatpath = File.join(formatpath.sub(/\/*#{engine}\/*$/,''), engine) if enginepath
+                FileUtils.makedirs(formatpath) rescue false
+                setpath(engine,formatpath)
+                # ENV['engine'] = savedengine
+            end
+            return @@paths[engine].first
+        end
+    end
+
+    def Kpse.update
+        system('initexmf -u') if Kpse.miktex?
+        system('mktexlsr')
+    end
+
+    # engine support is either broken of not implemented in some
+    # distributions, so we need to take care of it ourselves (without
+    # delays due to kpse calls); there can be many paths in the string
+    #
+    # in a year or so, i will drop this check
+
+    def Kpse.fixtexmfvars(engine=nil)
+        ENV['ENGINE'] = engine if engine
+        texformats = if ENV['TEXFORMATS'] then ENV['TEXFORMATS'].dup else '' end
+        if texformats.empty? then
+            if engine then
+                if @@mswindows then
+                    texformats = `kpsewhich --engine=#{engine} --expand-var=\$TEXFORMATS`.chomp
+                else
+                    texformats = `kpsewhich --engine=#{engine} --expand-var=\\\$TEXFORMATS`.chomp
+                end
+            else
+                if @@mswindows then
+                    texformats = `kpsewhich --expand-var=\$TEXFORMATS`.chomp
+                else
+                    texformats = `kpsewhich --expand-var=\\\$TEXFORMATS`.chomp
+                end
+            end
+        end
+        if engine then
+            texformats.sub!(/unsetengine/,engine)
+        else
+            texformats.sub!(/unsetengine/,"\$engine")
+        end
+        if engine && (texformats =~ /web2c[\/\\].*#{engine}/o) then
+            # ok, engine is seen
+            return false
+        elsif texformats =~ /web2c[\/\\].*\$engine/io then
+            # shouldn't happen
+            return false
+        else
+            ENV['TEXFORMATS'] = texformats.gsub(/(web2c\/\{)(,\})/o) do
+                "#{$1}\$engine#{$2}"
+            end
+            if texformats !~ /web2c[\/\\].*\$engine/io then
+                ENV['TEXFORMATS'] = texformats.gsub(/web2c\/*/, "web2c/{\$engine,}")
+            end
+            return true
+        end
+    end
+
+    # def Kpse.runscript(name,filename=[],options=[])
+        # setscript(name,`texmfstart --locate #{name}`) unless @@scripts.key?(name)
+        # cmd = "#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}"
+        # system(cmd)
+    # end
+
+    # def Kpse.pipescript(name,filename=[],options=[])
+        # setscript(name,`texmfstart --locate #{name}`) unless @@scripts.key?(name)
+        # cmd = "#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}"
+        # `#{cmd}`
+    # end
+
+    def Kpse.runscript(name,filename=[],options=[])
+        cmd = "mtxrun --script #{name} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}"
+        system(cmd)
+    end
+
+    def Kpse.pipescript(name,filename=[],options=[])
+        cmd = "mtxrun --script #{name} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}"
+        `#{cmd}`
+    end
+
+    def Kpse.searchmethod
+        if @@usekpserunner then 'kpsefast' else 'kpsewhich' end
+    end
+
+    private
+
+    def Kpse.setvariable(key,value)
+        @@located[key] = value
+        ENV["_CTX_K_V_#{key}_"] = @@located[key] if @@crossover
+    end
+
+    def Kpse.setscript(key,value)
+        @@scripts[key] = value
+        ENV["_CTX_K_S_#{key}_"] = @@scripts[key] if @@crossover
+    end
+
+    def Kpse.setpath(key,value)
+        @@paths[key] = [value].flatten.uniq.collect do |p|
+            p.sub(/^!!/,'').sub(/\/*$/,'')
+        end
+        ENV["_CTX_K_P_#{key}_"] = @@paths[key].join(';') if @@crossover
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpse.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpsedirect.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpsedirect.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpsedirect.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,34 @@
+class KpseDirect
+
+    attr_accessor :progname, :format, :engine
+
+    def initialize
+        @progname, @format, @engine = '', '', ''
+    end
+
+    def expand_path(str)
+        clean_name(`kpsewhich -expand-path=#{str}`.chomp)
+    end
+
+    def expand_var(str)
+        clean_name(`kpsewhich -expand-var=#{str}`.chomp)
+    end
+
+    def find_file(str)
+        clean_name(`kpsewhich #{_progname_} #{_format_} #{str}`.chomp)
+    end
+
+    def _progname_
+        if @progname.empty? then '' else "-progname=#{@progname}" end
+    end
+    def _format_
+        if @format.empty?   then '' else "-format=\"#{@format}\"" end
+    end
+
+    private
+
+    def clean_name(str)
+        str.gsub(/\\/,'/')
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpsedirect.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpsefast.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpsefast.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpsefast.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,934 @@
+# module    : base/kpsefast
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# todo: multiple cnf files
+#
+# todo: cleanup, string or table store (as in lua variant)
+
+class String
+
+    def split_path
+        if self =~ /\;/o || self =~ /^[a-z]\:/io then
+            self.split(";")
+        else
+            self.split(":")
+        end
+    end
+
+end
+
+class Array
+
+    def join_path
+        self.join(File::PATH_SEPARATOR)
+    end
+
+end
+
+class File
+
+    def File.locate_file(path,name)
+        begin
+            files = Dir.entries(path)
+            if files.include?(name) then
+                fullname = File.join(path,name)
+                return fullname if FileTest.file?(fullname)
+            end
+            files.each do |p|
+                fullname = File.join(path,p)
+                if p != '.' and p != '..' and FileTest.directory?(fullname) and result = locate_file(fullname,name) then
+                    return result
+                end
+            end
+        rescue
+            # bad path
+        end
+        return nil
+    end
+
+    def File.glob_file(pattern)
+        return Dir.glob(pattern).first
+    end
+
+end
+
+module KpseUtil
+
+    # to be adapted, see loading cnf file
+
+    @@texmftrees = ['texmf-local','texmf.local','../..','texmf'] # '../..' is for gwtex
+    @@texmfcnf   = 'texmf.cnf'
+
+    def KpseUtil::identify
+        # we mainly need to identify the local tex stuff and wse assume that
+        # the texmfcnf variable is set; otherwise we need to expand the
+        # TEXMF variable and that takes time since it may involve more
+        ownpath = File.expand_path($0)
+        if ownpath.gsub!(/texmf.*?$/o, '') then
+            ENV['SELFAUTOPARENT'] = ownpath
+        else
+            ENV['SELFAUTOPARENT'] = '.' # fall back
+            # may be too tricky:
+            #
+            # (ENV['PATH'] ||'').split_path.each do |p|
+                # if p.gsub!(/texmf.*?$/o, '') then
+                    # ENV['SELFAUTOPARENT'] = p
+                    # break
+                # end
+            # end
+        end
+        filenames = Array.new
+        if ENV['TEXMFCNF'] && ! ENV['TEXMFCNF'].empty? then
+            ENV['TEXMFCNF'].to_s.split_path.each do |path|
+                filenames << File.join(path,@@texmfcnf)
+            end
+        elsif ENV['SELFAUTOPARENT'] == '.' then
+            filenames << File.join('.',@@texmfcnf)
+        else
+            @@texmftrees.each do |tree|
+                filenames << File.join(ENV['SELFAUTOPARENT'],tree,'web2c',@@texmfcnf)
+            end
+        end
+        loop do
+            busy = false
+            filenames.collect! do |f|
+                f.gsub(/\$([a-zA-Z0-9\_\-]+)/o) do
+                    if (! ENV[$1]) || (ENV[$1] == $1) then
+                        "$#{$1}"
+                    else
+                        busy = true
+                        ENV[$1]
+                    end
+                end
+            end
+            break unless busy
+        end
+        filenames.delete_if do |f|
+            ! FileTest.file?(f)
+        end
+        return filenames
+    end
+
+    def KpseUtil::environment
+        Hash.new.merge(ENV)
+    end
+
+end
+
+class KpseFast
+
+    # formats are an incredible inconsistent mess
+
+    @@suffixes  = Hash.new
+    @@formats   = Hash.new
+    @@suffixmap = Hash.new
+
+    @@texmfcnf  = 'texmf.cnf'
+
+    @@suffixes['gf']                       = ['.<resolution>gf'] # todo
+    @@suffixes['pk']                       = ['.<resolution>pk'] # todo
+    @@suffixes['tfm']                      = ['.tfm']
+    @@suffixes['afm']                      = ['.afm']
+    @@suffixes['base']                     = ['.base']
+    @@suffixes['bib']                      = ['.bib']
+    @@suffixes['bst']                      = ['.bst']
+    @@suffixes['cnf']                      = ['.cnf']
+    @@suffixes['ls-R']                     = ['ls-R', 'ls-r']
+    @@suffixes['fmt']                      = ['.fmt', '.efmt', '.efm', '.ofmt', '.ofm', '.oft', '.eofmt', '.eoft', '.eof', '.pfmt', '.pfm', '.epfmt', '.epf', '.xpfmt', '.xpf', '.afmt', '.afm']
+    @@suffixes['map']                      = ['.map']
+    @@suffixes['mem']                      = ['.mem']
+    @@suffixes['mf']                       = ['.mf']
+    @@suffixes['mfpool']                   = ['.pool']
+    @@suffixes['mft']                      = ['.mft']
+    @@suffixes['mp']                       = ['.mp']
+    @@suffixes['mppool']                   = ['.pool']
+    @@suffixes['ocp']                      = ['.ocp']
+    @@suffixes['ofm']                      = ['.ofm', '.tfm']
+    @@suffixes['opl']                      = ['.opl']
+    @@suffixes['otp']                      = ['.otp']
+    @@suffixes['ovf']                      = ['.ovf']
+    @@suffixes['ovp']                      = ['.ovp']
+    @@suffixes['graphic/figure']           = ['.eps', '.epsi']
+    @@suffixes['tex']                      = ['.tex']
+    @@suffixes['texpool']                  = ['.pool']
+    @@suffixes['PostScript header']        = ['.pro']
+    @@suffixes['type1 fonts']              = ['.pfa', '.pfb']
+    @@suffixes['vf']                       = ['.vf']
+    @@suffixes['ist']                      = ['.ist']
+    @@suffixes['truetype fonts']           = ['.ttf', '.ttc']
+    @@suffixes['web']                      = ['.web', '.ch']
+    @@suffixes['cweb']                     = ['.w', '.web', '.ch']
+    @@suffixes['enc files']                = ['.enc']
+    @@suffixes['cmap files']               = ['.cmap']
+    @@suffixes['subfont definition files'] = ['.sfd']
+    @@suffixes['lig files']                = ['.lig']
+    @@suffixes['bitmap font']              = []
+    @@suffixes['MetaPost support']         = []
+    @@suffixes['TeX system documentation'] = []
+    @@suffixes['TeX system sources']       = []
+    @@suffixes['Troff fonts']              = []
+    @@suffixes['dvips config']             = []
+    @@suffixes['type42 fonts']             = []
+    @@suffixes['web2c files']              = []
+    @@suffixes['other text files']         = []
+    @@suffixes['other binary files']       = []
+    @@suffixes['misc fonts']               = []
+    @@suffixes['opentype fonts']           = []
+    @@suffixes['pdftex config']            = []
+    @@suffixes['texmfscripts']             = []
+
+    # replacements
+
+    @@suffixes['fmt']                      = ['.fmt']
+    @@suffixes['type1 fonts']              = ['.pfa', '.pfb', '.pfm']
+    @@suffixes['tex']                      = ['.tex', '.xml']
+    @@suffixes['texmfscripts']             = ['rb','lua','py','pl']
+
+    @@suffixes.keys.each do |k| @@suffixes[k].each do |s| @@suffixmap[s] = k end end
+
+    # TTF2TFMINPUTS
+    # MISCFONTS
+    # TEXCONFIG
+    # DVIPDFMINPUTS
+    # OTFFONTS
+
+    @@formats['gf']                       = ''
+    @@formats['pk']                       = ''
+    @@formats['tfm']                      = 'TFMFONTS'
+    @@formats['afm']                      = 'AFMFONTS'
+    @@formats['base']                     = 'MFBASES'
+    @@formats['bib']                      = ''
+    @@formats['bst']                      = ''
+    @@formats['cnf']                      = ''
+    @@formats['ls-R']                     = ''
+    @@formats['fmt']                      = 'TEXFORMATS'
+    @@formats['map']                      = 'TEXFONTMAPS'
+    @@formats['mem']                      = 'MPMEMS'
+    @@formats['mf']                       = 'MFINPUTS'
+    @@formats['mfpool']                   = 'MFPOOL'
+    @@formats['mft']                      = ''
+    @@formats['mp']                       = 'MPINPUTS'
+    @@formats['mppool']                   = 'MPPOOL'
+    @@formats['ocp']                      = 'OCPINPUTS'
+    @@formats['ofm']                      = 'OFMFONTS'
+    @@formats['opl']                      = 'OPLFONTS'
+    @@formats['otp']                      = 'OTPINPUTS'
+    @@formats['ovf']                      = 'OVFFONTS'
+    @@formats['ovp']                      = 'OVPFONTS'
+    @@formats['graphic/figure']           = ''
+    @@formats['tex']                      = 'TEXINPUTS'
+    @@formats['texpool']                  = 'TEXPOOL'
+    @@formats['PostScript header']        = 'TEXPSHEADERS'
+    @@formats['type1 fonts']              = 'T1FONTS'
+    @@formats['vf']                       = 'VFFONTS'
+    @@formats['ist']                      = ''
+    @@formats['truetype fonts']           = 'TTFONTS'
+    @@formats['web']                      = ''
+    @@formats['cweb']                     = ''
+    @@formats['enc files']                = 'ENCFONTS'
+    @@formats['cmap files']               = 'CMAPFONTS'
+    @@formats['subfont definition files'] = 'SFDFONTS'
+    @@formats['lig files']                = 'LIGFONTS'
+    @@formats['bitmap font']              = ''
+    @@formats['MetaPost support']         = ''
+    @@formats['TeX system documentation'] = ''
+    @@formats['TeX system sources']       = ''
+    @@formats['Troff fonts']              = ''
+    @@formats['dvips config']             = ''
+    @@formats['type42 fonts']             = 'T42FONTS'
+    @@formats['web2c files']              = 'WEB2C'
+    @@formats['other text files']         = ''
+    @@formats['other binary files']       = ''
+    @@formats['misc fonts']               = ''
+    @@formats['opentype fonts']           = 'OPENTYPEFONTS'
+    @@formats['pdftex config']            = 'PDFTEXCONFIG'
+    @@formats['texmfscripts']             = 'TEXMFSCRIPTS'
+
+    attr_accessor :progname, :engine, :format, :rootpath, :treepath,
+        :verbose, :remember, :scandisk, :diskcache, :renewcache
+
+    @@cacheversion = '1'
+
+    def initialize
+        @rootpath    = ''
+        @treepath    = ''
+        @progname    = 'kpsewhich'
+        @engine      = 'pdftex'
+        @variables   = Hash.new
+        @expansions  = Hash.new
+        @files       = Hash.new
+        @found       = Hash.new
+        @kpsevars    = Hash.new
+        @lsrfiles    = Array.new
+        @cnffiles    = Array.new
+        @verbose     = true
+        @remember    = true
+        @scandisk    = true
+        @diskcache   = true
+        @renewcache  = false
+        @isolate     = false
+
+        @diskcache   = false
+        @cachepath   = nil
+        @cachefile   = 'tmftools.log'
+
+        @environment = ENV
+    end
+
+    def set(key,value)
+        case key
+            when 'progname' then @progname = value
+            when 'engine'   then @engine   = value
+            when 'format'   then @format   = value
+        end
+    end
+
+    def push_environment(env)
+        @environment = env
+    end
+
+    # {$SELFAUTOLOC,$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}
+    #
+    # $SELFAUTOLOC    : /usr/tex/bin/platform
+    # $SELFAUTODIR    : /usr/tex/bin
+    # $SELFAUTOPARENT : /usr/tex
+    #
+    # since we live in scriptpath we need a slightly different method
+
+    def load_cnf(filenames=nil)
+        unless filenames then
+            ownpath = File.expand_path($0)
+            if ownpath.gsub!(/texmf.*?$/o, '') then
+                @environment['SELFAUTOPARENT'] = ownpath
+            else
+                @environment['SELFAUTOPARENT'] = '.'
+            end
+            unless @treepath.empty? then
+                unless @rootpath.empty? then
+                    @treepath = @treepath.split(',').collect do |p| File.join(@rootpath,p) end.join(',')
+                end
+                @environment['TEXMF'] = @treepath
+                # only the first one
+                @environment['TEXMFCNF'] = File.join(@treepath.split(',').first,'texmf/web2c')
+            end
+            unless @rootpath.empty? then
+                @environment['TEXMFCNF'] = File.join(@rootpath,'texmf/web2c')
+                @environment['SELFAUTOPARENT'] = @rootpath
+                @isolate = true
+            end
+            filenames = Array.new
+            if @environment['TEXMFCNF'] and not @environment['TEXMFCNF'].empty? then
+                @environment['TEXMFCNF'].to_s.split_path.each do |path|
+                    filenames << File.join(path,@@texmfcnf)
+                end
+            elsif @environment['SELFAUTOPARENT'] == '.' then
+                filenames << File.join('.',@@texmfcnf)
+            else
+                ['texmf-local','texmf'].each do |tree|
+                    filenames << File.join(@environment['SELFAUTOPARENT'],tree,'web2c',@@texmfcnf)
+                end
+            end
+        end
+        # <root>/texmf/web2c/texmf.cnf
+        filenames = _expanded_path_(filenames)
+        @rootpath = filenames.first
+        3.times do
+            @rootpath = File.dirname(@rootpath)
+        end
+        filenames.collect! do |f|
+            f.gsub("\\", '/')
+        end
+        filenames.each do |fname|
+            if FileTest.file?(fname) and f = File.open(fname) then
+                @cnffiles << fname
+                while line = f.gets do
+                    loop do
+                        # concatenate lines ending with \
+                        break unless line.sub!(/\\\s*$/o) do
+                            f.gets || ''
+                        end
+                    end
+                    case line
+                        when /^[\%\#]/o then
+                            # comment
+                        when /^\s*(.*?)\s*\=\s*(.*?)\s*$/o then
+                            key, value = $1, $2
+                            unless @variables.key?(key) then
+                                value.sub!(/\%.*$/,'')
+                                value.sub!(/\~/, "$HOME")
+                                @variables[key] = value
+                            end
+                            @kpsevars[key] = true
+                    end
+                end
+                f.close
+            end
+        end
+    end
+
+    def load_lsr
+        @lsrfiles = []
+        simplified_list(expansion('TEXMF')).each do |p|
+            ['ls-R','ls-r'].each do |f|
+                filename = File.join(p,f)
+                if FileTest.file?(filename) then
+                    @lsrfiles << [filename,File.size(filename)]
+                    break
+                end
+            end
+        end
+        @files = Hash.new
+        if @diskcache then
+            ['HOME','TEMP','TMP','TMPDIR'].each do |key|
+                if @environment[key] then
+                    if FileTest.directory?(@environment[key]) then
+                        @cachepath = @environment[key]
+                        @cachefile = [@rootpath.gsub(/[^A-Z0-9]/io, '-').gsub(/\-+/,'-'),File.basename(@cachefile)].join('-')
+                        break
+                    end
+                end
+            end
+            if @cachepath and not @renewcache and FileTest.file?(File.join(@cachepath, at cachefile)) then
+                begin
+                    if f = File.open(File.join(@cachepath, at cachefile)) then
+                        cacheversion = Marshal.load(f)
+                        if cacheversion == @@cacheversion then
+                            lsrfiles = Marshal.load(f)
+                            if lsrfiles == @lsrfiles then
+                                @files = Marshal.load(f)
+                            end
+                        end
+                        f.close
+                    end
+                rescue
+                   @files = Hash.new
+               end
+            end
+        end
+        return if @files.size > 0
+        @lsrfiles.each do |filedata|
+            filename, filesize = filedata
+            filepath = File.dirname(filename)
+            begin
+                path = '.'
+                data = IO.readlines(filename)
+                if data[0].chomp =~ /% ls\-R \-\- filename database for kpathsea\; do not change this line\./io then
+                    data.each do |line|
+                        case line
+                            when /^[a-zA-Z0-9]/o then
+                                line.chomp!
+                                if @files[line] then
+                                    @files[line] << path
+                                else
+                                    @files[line] = [path]
+                                end
+                            when /^\.\/(.*?)\:$/o then
+                                path = File.join(filepath,$1)
+                        end
+                    end
+                end
+            rescue
+                # sorry
+            end
+        end
+        if @diskcache and @cachepath and f = File.open(File.join(@cachepath, at cachefile),'wb') then
+            f << Marshal.dump(@@cacheversion)
+            f << Marshal.dump(@lsrfiles)
+            f << Marshal.dump(@files)
+            f.close
+        end
+    end
+
+    def expand_variables
+        @expansions = Hash.new
+        if @isolate then
+            @variables['TEXMFCNF'] = @environment['TEXMFCNF'].dup
+            @variables['SELFAUTOPARENT'] = @environment['SELFAUTOPARENT'].dup
+        else
+            @environment.keys.each do |e|
+                if e =~ /^([a-zA-Z]+)\_(.*)\s*$/o then
+                    @expansions["#{$1}.#{$2}"] = (@environment[e] ||'').dup
+                else
+                    @expansions[e] = (@environment[e] ||'').dup
+                end
+            end
+        end
+        @variables.keys.each do |k|
+            @expansions[k] = @variables[k].dup unless @expansions[k]
+        end
+        loop do
+            busy = false
+            @expansions.keys.each do |k|
+                @expansions[k].gsub!(/\$([a-zA-Z0-9\_\-]*)/o) do
+                    busy = true
+                    @expansions[$1] || ''
+                end
+                @expansions[k].gsub!(/\$\{([a-zA-Z0-9\_\-]*)\}/o) do
+                    busy = true
+                    @expansions[$1] || ''
+                end
+            end
+            break unless busy
+        end
+        @expansions.keys.each do |k|
+            @expansions[k] = @expansions[k].gsub("\\", '/')
+        end
+    end
+
+    def variable(name='')
+        (name and not name.empty? and @variables[name.sub('$','')]) or  ''
+    end
+
+    def expansion(name='')
+        (name and not name.empty? and @expansions[name.sub('$','')]) or ''
+    end
+
+    def variable?(name='')
+        name and not name.empty? and @variables.key?(name.sub('$',''))
+    end
+
+    def expansion?(name='')
+        name and not name.empty? and @expansions.key?(name.sub('$',''))
+    end
+
+    def simplified_list(str)
+        lst = str.gsub(/^\{/o,'').gsub(/\}$/o,'').split(",")
+        lst.collect do |l|
+            l.sub(/^[\!]*/,'').sub(/[\/\\]*$/o,'')
+        end
+    end
+
+    def original_variable(variable)
+        if variable?("#{@progname}.#{variable}") then
+            variable("#{@progname}.#{variable}")
+        elsif variable?(variable) then
+            variable(variable)
+        else
+            ''
+        end
+    end
+
+    def expanded_variable(variable)
+        if expansion?("#{variable}.#{@progname}") then
+            expansion("#{variable}.#{@progname}")
+        elsif expansion?(variable) then
+            expansion(variable)
+        else
+            ''
+        end
+    end
+
+    def original_path(filename='')
+        _expanded_path_(original_variable(var_of_format_or_suffix(filename)).split(";"))
+    end
+
+    def expanded_path(filename='')
+        _expanded_path_(expanded_variable(var_of_format_or_suffix(filename)).split(";"))
+    end
+
+    def _expanded_path_(pathlist)
+        i, n = 0, 0
+        pathlist.collect! do |mainpath|
+            mainpath.gsub(/([\{\}])/o) do
+                if $1 == "{" then
+                    i += 1 ; n = i if i > n ; "<#{i}>"
+                else
+                    i -= 1 ; "</#{i+1}>"
+                end
+            end
+        end
+        n.times do |i|
+            loop do
+                more = false
+                newlist = []
+                pathlist.each do |path|
+                    unless path.sub!(/^(.*?)<(#{n-i})>(.*?)<\/\2>(.*?)$/) do
+                        pre, mid, post = $1, $3, $4
+                        mid.gsub!(/\,$/,',.')
+                        mid.split(',').each do |m|
+                            more = true
+                            if m == '.' then
+                                newlist << "#{pre}#{post}"
+                            else
+                                newlist << "#{pre}#{m}#{post}"
+                            end
+                        end
+                    end then
+                        newlist << path
+                    end
+                end
+                if more then
+                    pathlist = [newlist].flatten # copy -)
+                else
+                    break
+                end
+            end
+        end
+        pathlist = pathlist.uniq.collect do |path|
+            p = path
+            # p.gsub(/^\/+/o) do '' end
+            # p.gsub!(/(.)\/\/(.)/o) do "#{$1}/#{$2}" end
+            # p.gsub!(/\/\/+$/o) do '//' end
+            p.gsub!(/\/\/+/o) do '//' end
+            p
+        end
+        pathlist
+    end
+
+    # todo: ignore case
+
+    def var_of_format(str)
+        @@formats[str] || ''
+    end
+
+    def var_of_suffix(str) # includes .
+        if @@suffixmap.key?(str) then @@formats[@@suffixmap[str]] else '' end
+    end
+
+    def var_of_format_or_suffix(str)
+        if @@formats.key?(str) then
+            @@formats[str]
+        elsif @@suffixmap.key?(File.extname(str)) then # extname includes .
+            @@formats[@@suffixmap[File.extname(str)]]  # extname includes .
+        else
+            ''
+        end
+    end
+
+end
+
+class KpseFast
+
+    # test things
+
+    def list_variables(kpseonly=true)
+        @variables.keys.sort.each do |k|
+            if kpseonly then
+                puts("#{k} = #{@variables[k]}") if @kpsevars[k]
+            else
+                puts("#{if @kpsevars[k] then 'K' else 'E' end} #{k} = #{@variables[k]}")
+            end
+        end
+    end
+
+    def list_expansions(kpseonly=true)
+        @expansions.keys.sort.each do |k|
+            if kpseonly then
+                puts("#{k} = #{@expansions[k]}") if @kpsevars[k]
+            else
+                puts("#{if @kpsevars[k] then 'K' else 'E' end} #{k} = #{@expansions[k]}")
+            end
+        end
+    end
+
+    def list_lsr
+        puts("files = #{@files.size}")
+    end
+
+    def set_test_patterns
+        @variables["KPSE_TEST_PATTERN_A"] = "foo/{1,2}/bar//"
+        @variables["KPSE_TEST_PATTERN_B"] = "!!x{A,B{1,2}}y"
+        @variables["KPSE_TEST_PATTERN_C"] = "x{A,B//{1,2}}y"
+        @variables["KPSE_TEST_PATTERN_D"] = "x{A,B//{1,2,}}//y"
+    end
+
+    def show_test_patterns
+        ['A','B','D'].each do |i|
+            puts ""
+            puts @variables ["KPSE_TEST_PATTERN_#{i}"]
+            puts ""
+            puts expand_path("KPSE_TEST_PATTERN_#{i}").split_path
+            puts ""
+        end
+    end
+
+end
+
+class KpseFast
+
+    # kpse stuff
+
+    def expand_braces(str) # output variable and brace expansion of STRING.
+        _expanded_path_(original_variable(str).split_path).join_path
+    end
+
+    def expand_path(str)   # output complete path expansion of STRING.
+        _expanded_path_(expanded_variable(str).split_path).join_path
+    end
+
+    def expand_var(str)    # output variable expansion of STRING.
+        expanded_variable(str)
+    end
+
+    def show_path(str)     # output search path for file type NAME
+        expanded_path(str).join_path
+    end
+
+    def var_value(str)     # output the value of variable $STRING.
+        original_variable(str)
+    end
+
+end
+
+class KpseFast
+
+    def _is_cnf_?(filename)
+        filename == File.basename((@cnffiles.first rescue @@texmfcnf) || @@texmfcnf)
+    end
+
+    def find_file(filename)
+        if _is_cnf_?(filename) then
+            @cnffiles.first rescue ''
+        else
+            [find_files(filename,true)].flatten.first || ''
+        end
+    end
+
+    def find_files(filename,first=false)
+        if _is_cnf_?(filename) then
+            result = @cnffiles.dup
+        else
+            if @remember then
+                # stamp = "#{filename}--#{@format}--#{@engine}--#{@progname}"
+                stamp = "#{filename}--#{@engine}--#{@progname}"
+                return @found[stamp] if @found.key?(stamp)
+            end
+            pathlist = expanded_path(filename)
+            result = []
+            filelist = if @files.key?(filename) then @files[filename].uniq else nil end
+            done = false
+            if pathlist.size == 0 then
+                if FileTest.file?(filename) then
+                    done = true
+                    result << '.'
+                end
+            else
+                pathlist.each do |path|
+                    doscan = if path =~ /^\!\!/o then false else true end
+                    recurse = if path =~ /\/\/$/o then true else false end
+                    pathname = path.dup
+                    pathname.gsub!(/^\!+/o, '')
+                    done = false
+                    if not done and filelist then
+                        # checking for exact match
+                        if filelist.include?(pathname) then
+                            result << pathname
+                            done = true
+                        end
+                        if not done and recurse then
+                            # checking for fuzzy //
+                            pathname.gsub!(/\/+$/o, '/.*')
+                            # pathname.gsub!(/\/\//o,'/[\/]*/')
+                            pathname.gsub!(/\/\//o,'/.*?/')
+                            re = /^#{pathname}/
+                            filelist.each do |f|
+                                if re =~ f then
+                                    result << f # duplicates will be filtered later
+                                    done = true
+                                end
+                                break if done
+                            end
+                        end
+                    end
+                    if not done and doscan then
+                        # checking for path itself
+                        pname = pathname.sub(/\.\*$/,'')
+                        if not pname =~ /\*/o and FileTest.file?(File.join(pname,filename)) then
+                            result << pname
+                            done = true
+                        end
+                    end
+                    break if done and first
+                end
+            end
+            if not done and @scandisk then
+                pathlist.each do |path|
+                    pathname = path.dup
+                    unless pathname.gsub!(/^\!+/o, '') then # !! prevents scan
+                        recurse = pathname.gsub!(/\/+$/o, '')
+                        complex = pathname.gsub!(/\/\//o,'/*/')
+                        if recurse then
+                            if complex then
+                                if ok = File.glob_file("#{pathname}/**/#{filename}") then
+                                    result << File.dirname(ok)
+                                    done = true
+                                end
+                            elsif ok = File.locate_file(pathname,filename) then
+                                result << File.dirname(ok)
+                                done = true
+                            end
+                        elsif complex then
+                            if ok = File.glob_file("#{pathname}/#{filename}") then
+                                result << File.dirname(ok)
+                                done = true
+                            end
+                        elsif FileTest.file?(File.join(pathname,filename)) then
+                            result << pathname
+                            done = true
+                        end
+                        break if done and first
+                    end
+                end
+            end
+            result = result.uniq.collect do |pathname|
+                File.join(pathname,filename)
+            end
+            @found[stamp] = result if @remember
+        end
+        return result # redundant
+    end
+
+end
+
+class KpseFast
+
+    class FileData
+        attr_accessor :tag, :name, :size, :date
+        def initialize(tag=0,name=nil,size=nil,date=nil)
+            @tag, @name, @size, @date = tag, name, size, date
+        end
+        def FileData.sizes(a)
+            a.collect do |aa|
+                aa.size
+            end
+        end
+        def report
+            case @tag
+                when 1 then "deleted  | #{@size.to_s.rjust(8)} | #{@date.strftime('%m/%d/%Y %I:%M')} | #{@name}"
+                when 2 then "present  | #{@size.to_s.rjust(8)} | #{@date.strftime('%m/%d/%Y %I:%M')} | #{@name}"
+                when 3 then "obsolete | #{' '*8} | #{' '*16} | #{@name}"
+            end
+        end
+    end
+
+    def analyze_files(filter='',strict=false,sort='',delete=false)
+        puts("command line     = #{ARGV.join(' ')}")
+        puts("number of files  = #{@files.size}")
+        puts("filter pattern   = #{filter}")
+        puts("loaded cnf files = #{@cnffiles.join(' ')}")
+        puts('')
+        if filter.gsub!(/^not:/,'') then
+            def the_same(filter,filename)
+                not filter or filter.empty? or /#{filter}/ !~ filename
+            end
+        else
+            def the_same(filter,filename)
+                not filter or filter.empty? or /#{filter}/ =~ filename
+            end
+        end
+        @files.keys.each do |name|
+            if @files[name].size > 1 then
+                data = Array.new
+                @files[name].each do |path|
+                    filename = File.join(path,name)
+                    # if not filter or filter.empty? or /#{filter}/ =~ filename then
+                    if the_same(filter,filename) then
+                        if FileTest.file?(filename) then
+                            if delete then
+                                data << FileData.new(1,filename,File.size(filename),File.mtime(filename))
+                                begin
+                                    File.delete(filename) if delete
+                                rescue
+                                end
+                            else
+                                data << FileData.new(2,filename,File.size(filename),File.mtime(filename))
+                            end
+                        else
+                            # data << FileData.new(3,filename)
+                        end
+                    end
+                end
+                if data.length > 1 then
+                    if strict then
+                        # if data.collect do |d| d.size end.uniq! then
+                            # data.sort! do |a,b| b.size <=> a.size end
+                            # data.each do |d| puts d.report end
+                            # puts ''
+                        # end
+                        data.sort! do |a,b|
+                            if a.size and b.size then
+                                b.size <=> a.size
+                            else
+                                0
+                            end
+                        end
+                        bunch = Array.new
+                        done = false
+                        data.each do |d|
+                            if bunch.size == 0 then
+                                bunch << d
+                            elsif bunch[0].size == d.size then
+                                bunch << d
+                            else
+                                if bunch.size > 1 then
+                                    bunch.each do |b|
+                                        puts b.report
+                                    end
+                                    done = true
+                                end
+                                bunch = [d]
+                            end
+                        end
+                        puts '' if done
+                    else
+                        case sort
+                            when 'size'    then data.sort! do |a,b| a.size <=> b.size end
+                            when 'revsize' then data.sort! do |a,b| b.size <=> a.size end
+                            when 'date'    then data.sort! do |a,b| a.date <=> b.date end
+                            when 'revdate' then data.sort! do |a,b| b.date <=> a.date end
+                        end
+                        data.each do |d| puts d.report end
+                        puts ''
+                    end
+                end
+            end
+        end
+    end
+
+end
+
+# if false then
+
+    # k = KpseFast.new # (root)
+    # k.set_test_patterns
+    # k.load_cnf
+    # k.expand_variables
+    # k.load_lsr
+
+    # k.show_test_patterns
+
+    # puts k.list_variables
+    # puts k.list_expansions
+    # k.list_lsr
+    # puts k.expansion("$TEXMF")
+    # puts k.expanded_path("TEXINPUTS","context")
+
+    # k.progname, k.engine, k.format = 'context', 'pdftex', 'tfm'
+    # k.scandisk = false # == must_exist
+    # k.expand_variables
+
+    # 10.times do |i| puts k.find_file('texnansi-lmr10.tfm') end
+
+    # puts "expand braces $TEXMF"
+    # puts k.expand_braces("$TEXMF")
+    # puts "expand path $TEXMF"
+    # puts k.expand_path("$TEXMF")
+    # puts "expand var $TEXMF"
+    # puts k.expand_var("$TEXMF")
+    # puts "expand path $TEXMF"
+    # puts k.show_path('tfm')
+    # puts "expand value $TEXINPUTS"
+    # puts k.var_value("$TEXINPUTS")
+    # puts "expand value $TEXINPUTS.context"
+    # puts k.var_value("$TEXINPUTS.context")
+
+    # exit
+
+# end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpsefast.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpseremote.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpseremote.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpseremote.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,116 @@
+require 'base/kpsefast'
+
+case ENV['KPSEMETHOD']
+    when /soap/o then require 'base/kpse/soap'
+    when /drb/o  then require 'base/kpse/drb'
+    else              require 'base/kpse/drb'
+end
+
+class KpseRemote
+
+    @@port   = ENV['KPSEPORT']   || 7000
+    @@method = ENV['KPSEMETHOD'] || 'drb'
+
+    def KpseRemote::available?
+        @@method && @@port
+    end
+
+    def KpseRemote::start_server(port=nil)
+        kpse = KpseServer.new(port || @@port)
+        kpse.start
+    end
+
+    def KpseRemote::start_client(port=nil) # keeps object in server
+        kpseclient = KpseClient.new(port || @@port)
+        kpseclient.start
+        kpse = kpseclient.object
+        tree = kpse.choose(KpseUtil::identify, KpseUtil::environment)
+        [kpse, tree]
+    end
+
+    def KpseRemote::fetch(port=nil) # no need for defining methods but slower, send whole object
+        kpseclient = KpseClient.new(port || @@port)
+        kpseclient.start
+        kpseclient.object.fetch(KpseUtil::identify, KpseUtil::environment) rescue nil
+    end
+
+    def initialize(port=nil)
+        if KpseRemote::available? then
+            begin
+                @kpse, @tree = KpseRemote::start_client(port)
+            rescue
+                @kpse, @tree = nil, nil
+            end
+        else
+            @kpse, @tree = nil, nil
+        end
+    end
+
+    def progname=(value)
+        @kpse.set(@tree,'progname',value)
+    end
+    def format=(value)
+        @kpse.set(@tree,'format',value)
+    end
+    def engine=(value)
+        @kpse.set(@tree,'engine',value)
+    end
+
+    def progname
+        @kpse.get(@tree,'progname')
+    end
+    def format
+        @kpse.get(@tree,'format')
+    end
+    def engine
+        @kpse.get(@tree,'engine')
+    end
+
+    def load
+        @kpse.load(KpseUtil::identify, KpseUtil::environment)
+    end
+    def okay?
+        @kpse && @tree
+    end
+    def set(key,value)
+        @kpse.set(@tree,key,value)
+    end
+    def load_cnf
+        @kpse.load_cnf(@tree)
+    end
+    def load_lsr
+        @kpse.load_lsr(@tree)
+    end
+    def expand_variables
+        @kpse.expand_variables(@tree)
+    end
+    def expand_braces(str)
+        clean_name(@kpse.expand_braces(@tree,str))
+    end
+    def expand_path(str)
+        clean_name(@kpse.expand_path(@tree,str))
+    end
+    def expand_var(str)
+        clean_name(@kpse.expand_var(@tree,str))
+    end
+    def show_path(str)
+        clean_name(@kpse.show_path(@tree,str))
+    end
+    def var_value(str)
+        clean_name(@kpse.var_value(@tree,str))
+    end
+    def find_file(filename)
+        clean_name(@kpse.find_file(@tree,filename))
+    end
+    def find_files(filename,first=false)
+        # dodo: each filename
+        @kpse.find_files(@tree,filename,first)
+    end
+
+    private
+
+    def clean_name(str)
+        str.gsub(/\\/,'/')
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpseremote.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/kpserunner.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/kpserunner.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/kpserunner.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,87 @@
+require 'base/kpsefast'
+
+module KpseRunner
+
+    @@kpse = nil
+
+    def KpseRunner.kpsewhich(arg='')
+        options, arguments = split_args(arg)
+        unless @@kpse then
+            if ENV['KPSEMETHOD'] && ENV['KPSEPORT'] then
+                require 'base/kpseremote'
+                @@kpse = KpseRemote.new
+            else
+                @@kpse = nil
+            end
+            if @@kpse && @@kpse.okay? then
+                @@kpse.progname = options['progname'] || ''
+                @@kpse.engine   = options['engine']   || ''
+                @@kpse.format   = options['format']   || ''
+            else
+                require 'base/kpsefast'
+                @@kpse = KpseFast.new
+                @@kpse.load_cnf
+                @@kpse.progname = options['progname'] || ''
+                @@kpse.engine   = options['engine']   || ''
+                @@kpse.format   = options['format']   || ''
+                @@kpse.expand_variables
+                @@kpse.load_lsr
+            end
+        else
+            @@kpse.progname = options['progname'] || ''
+            @@kpse.engine   = options['engine']   || ''
+            @@kpse.format   = options['format']   || ''
+            @@kpse.expand_variables
+        end
+        if    option = options['expand-braces'] and not option.empty? then
+            @@kpse.expand_braces(option)
+        elsif option = options['expand-path']   and not option.empty? then
+            @@kpse.expand_path(option)
+        elsif option = options['expand-var']    and not option.empty? then
+            @@kpse.expand_var(option)
+        elsif option = options['show-path']     and not option.empty? then
+            @@kpse.show_path(option)
+        elsif option = options['var-value']     and not option.empty? then
+            @@kpse.expand_var(option)
+        elsif arguments.size > 0 then
+            files = Array.new
+            arguments.each do |option|
+                if file = @@kpse.find_file(option) and not file.empty? then
+                    files << file
+                end
+            end
+            files.join("\n")
+        else
+            ''
+        end
+    end
+
+    def KpseRunner.kpsereset
+        @@kpse = nil
+    end
+
+    private
+
+    def KpseRunner.split_args(arg)
+        vars, args = Hash.new, Array.new
+        arg.gsub!(/([\"\'])(.*?)\1/o) do
+            $2.gsub(' ','<space/>')
+        end
+        arg = arg.split(/\s+/o)
+        arg.collect! do |a|
+            a.gsub('<space/>',' ')
+        end
+        arg.each do |a|
+            if a =~ /^(.*?)\=(.*?)$/o then
+                k, v = $1, $2
+                vars[k.sub(/^\-+/,'')] = v
+            else
+                args << a
+            end
+        end
+        # puts vars.inspect
+        # puts args.inspect
+        return vars, args
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/kpserunner.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/logger.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/logger.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/logger.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,105 @@
+# module    : base/logger
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+require 'thread'
+
+# The next calls are valid:
+
+# @log.report('a','b','c', 'd')
+# @log.report('a','b',"c #{d}")
+# @log.report("a b c #{d}")
+
+# Keep in mind that "whatever #{something}" is two times faster than
+# 'whatever ' + something or ['whatever',something].join and that
+# when verbosity is not needed the following is much faster too:
+
+# @log.report('a','b','c', 'd') if @log.verbose?
+# @log.report('a','b',"c #{d}") if @log.verbose?
+# @log.report("a b c #{d}")     if @log.verbose?
+
+# The last three cases are equally fast when verbosity is turned off.
+
+# Under consideration: verbose per instance
+
+class Logger
+
+    @@length  = 0
+    @@verbose = false
+
+    def initialize(tag=nil,length=0,verbose=false)
+        @tag = tag || ''
+        @@verbose = @@verbose || verbose
+        @@length = @tag.length if @tag.length > @@length
+        @@length =      length if      length > @@length
+    end
+
+    def report(*str)
+        begin
+            case str.length
+                when 0
+                    print("\n")
+                    return true
+                when 1
+                  # message = str.first
+                    message = str.first.join(' ')
+                else
+                    message = [str].flatten.collect{|s| s.to_s}.join(' ').chomp
+            end
+            if @tag.empty? then
+                print("#{message}\n")
+            else
+                # try to avoid too many adjustments
+                @tag = @tag.ljust(@@length) unless @tag.length == @@length
+                print("#{@tag} | #{message}\n")
+            end
+        rescue
+        end
+        return true
+    end
+
+    def reportlines(*str)
+        unless @tag.empty? then
+            @tag = @tag.ljust(@@length) unless @tag.length == @@length
+        end
+        report([str].flatten.collect{|s| s.gsub(/\n/,"\n#{@tag} | ")}.join(' '))
+    end
+
+    def debug(*str)
+        report(str) if @@verbose
+    end
+
+    def error(*str)
+        if ! $! || $!.to_s.empty? then
+            report(str)
+        else
+            report(str,$!)
+        end
+    end
+
+    def verbose
+        @@verbose = true
+    end
+
+    def silent
+        @@verbose = false
+    end
+
+    def verbose?
+        @@verbose
+    end
+
+    # attr_reader :tag
+
+    # alias fatal  error
+    # alias info   debug
+    # alias warn   debug
+    # alias debug? :verbose?
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/logger.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/merge.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/merge.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/merge.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,139 @@
+# module    : base/merge
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2006
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# --selfmerg ewill create stand alone script (--selfcleanup does the opposite)
+
+# this module will package all the used modules in the file itself
+# so that we can relocate the file at wish, usage:
+#
+# merge:
+#
+# unless SelfMerge::ok? && SelfMerge::merge then
+#     puts("merging should happen on the path were the base inserts reside")
+# end
+#
+# cleanup:
+#
+# unless SelfMerge::cleanup then
+#     puts("merging should happen on the path were the base inserts reside")
+# end
+
+module SelfMerge
+
+    @@kpsemergestart = "\# kpse_merge_start"
+    @@kpsemergestop  = "\# kpse_merge_stop"
+    @@kpsemergefile  = "\# kpse_merge_file: "
+    @@kpsemergedone  = "\# kpse_merge_done: "
+
+    @@filename = File.basename($0)
+    @@ownpath  = File.expand_path(File.dirname($0))
+    @@modroot  = '(base|graphics|rslb|www)' # needed in regex in order not to mess up SelfMerge
+    @@modules  = $".collect do |file| File.expand_path(file) end
+
+    @@modules.delete_if do |file|
+        file !~ /^#{@@ownpath}\/#{@@modroot}.*$/i
+    end
+
+    def SelfMerge::ok?
+        begin
+            @@modules.each do |file|
+                return false unless FileTest.file?(file)
+            end
+        rescue
+            return false
+        else
+            return true
+        end
+    end
+
+    def SelfMerge::merge
+        begin
+            if SelfMerge::ok? && rbfile = IO.read(@@filename) then
+                begin
+                    inserts = "#{@@kpsemergestart}\n\n"
+                    @@modules.each do |file|
+                        inserts << "#{@@kpsemergefile}'#{file}'\n\n"
+                        inserts << IO.read(file).gsub(/^#.*?\n$/,'')
+                        inserts << "\n\n"
+                    end
+                    inserts << "#{@@kpsemergestop}\n\n"
+                    # no gsub! else we end up in SelfMerge
+                    rbfile.sub!(/#{@@kpsemergestart}\s*#{@@kpsemergestop}/moi) do
+                        inserts
+                    end
+                    rbfile.gsub!(/^(.*)(require [\"\'].*?#{@@modroot}.*)$/) do
+                        pre, post = $1, $2
+                        if pre =~ /#{@@kpsemergedone}/ then
+                            "#{pre}#{post}"
+                        else
+                            "#{pre}#{@@kpsemergedone}#{post}"
+                        end
+                    end
+                rescue
+                    return false
+                else
+                    begin
+                        File.open(@@filename,'w') do |f|
+                            f << rbfile
+                        end
+                    rescue
+                        return false
+                    end
+                end
+            end
+        rescue
+            return false
+        else
+            return true
+        end
+    end
+
+    def SelfMerge::cleanup
+        begin
+            if rbfile = IO.read(@@filename) then
+                begin
+                    rbfile.sub!(/#{@@kpsemergestart}(.*)#{@@kpsemergestop}\s*/moi) do
+                        "#{@@kpsemergestart}\n\n#{@@kpsemergestop}\n\n"
+                    end
+                    rbfile.gsub!(/^(.*#{@@kpsemergedone}.*)$/) do
+                        str = $1
+                        if str =~ /require [\"\']/ then
+                            str.gsub(/#{@@kpsemergedone}/, '')
+                        else
+                            str
+                        end
+                    end
+                rescue
+                    return false
+                else
+                    begin
+                        File.open(@@filename,'w') do |f|
+                            f << rbfile
+                        end
+                    rescue
+                        return false
+                    end
+                end
+            end
+        rescue
+            return false
+        else
+            return true
+        end
+    end
+
+    def SelfMerge::replace
+        if SelfMerge::ok? then
+            SelfMerge::cleanup
+            SelfMerge::merge
+        end
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/merge.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/mp.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/mp.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/mp.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,167 @@
+# module    : base/mp
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2005-2006
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+module MPTools
+
+    @@definitions, @@start, @@stop, @@before, @@after = Hash.new, Hash.new, Hash.new, Hash.new, Hash.new
+
+
+    @@definitions['plain'] = <<EOT
+\\gdef\\mpxshipout{\\shipout\\hbox\\bgroup
+  \\setbox0=\\hbox\\bgroup}
+
+\\gdef\\stopmpxshipout{\\egroup  \\dimen0=\\ht0 \\advance\\dimen0\\dp0
+  \\dimen1=\\ht0 \\dimen2=\\dp0
+  \\setbox0=\\hbox\\bgroup
+    \\box0
+    \\ifnum\\dimen0>0 \\vrule width1sp height\\dimen1 depth\\dimen2
+    \\else \\vrule width1sp height1sp depth0sp\\relax
+    \\fi\\egroup
+  \\ht0=0pt \\dp0=0pt \\box0 \\egroup}
+EOT
+
+    @@start ['plain'] = ""
+    @@before['plain'] = "\\mpxshipout"
+    @@after ['plain'] = "\\stopmpxshipout"
+    @@stop  ['plain'] = "\\end{document}"
+
+    @@definitions['context'] = <<EOT
+\\ifx\\startMPXpage\\undefined
+
+  \\ifx\\loadallfontmapfiles\\undefined \\let\\loadallfontmapfiles\\relax \\fi
+
+  \\gdef\\startMPXpage
+    {\\shipout\\hbox
+     \\bgroup
+     \\setbox0=\\hbox
+     \\bgroup}
+
+  \\gdef\\stopMPXpage
+    {\\egroup
+     \\dimen0=\\ht0
+     \\advance\\dimen0\\dp0
+     \\dimen1=\\ht0
+     \\dimen2=\\dp0
+     \\setbox0=\\hbox\\bgroup
+       \\box0
+       \\ifnum\\dimen0>0
+         \\vrule width 1sp height \\dimen1 depth \\dimen2
+       \\else
+         \\vrule width 1sp height 1sp depth 0sp \\relax
+       \\fi
+    \\egroup
+    \\ht0=0pt
+    \\dp0=0pt
+    \\loadallfontmapfiles
+    \\box0
+    \\egroup}
+
+\\fi
+
+\\ifx\\starttext\\undefined
+
+  \\let\\starttext\\relax
+  \\def\\stoptext{\\end{document}}
+
+\\fi
+EOT
+
+    @@start ['context'] = "\\starttext"
+    @@before['context'] = "\\startMPXpage"
+    @@after ['context'] = "\\stopMPXpage"
+    @@stop  ['context'] = "\\stoptext"
+
+    # todo: \usemodule[m-mpx ] and test fo defined
+
+    def MPTools::mptotex(from,to=nil,method='plain')
+        begin
+            if from && data = IO.read(from) then
+                f = if to then File.open(to,'w') else $stdout end
+                f.puts("% file: #{from}")
+                f.puts("")
+                f.puts(@@definitions[method])
+                unless @@start[method].empty? then
+                    f.puts("")
+                    f.puts(@@start[method])
+                end
+                data.gsub!(/([^\\])%.*?$/mo) do
+                    $1
+                end
+                data.scan(/(verbatim|b)tex\s*(.*?)\s*etex/mo) do
+                    tag, text = $1, $2
+                    f.puts("")
+                    if tag == 'b' then
+                        f.puts(@@before[method])
+                        f.puts("#{text}%")
+                        f.puts(@@after [method])
+                    else
+                        f.puts("#{text}")
+                    end
+                    f.puts("")
+                end
+                f.puts("")
+                f.puts(@@stop[method])
+                f.close
+            else
+                return false
+            end
+        rescue
+            File.delete(to) rescue false
+            return false
+        else
+            return true
+        end
+    end
+
+    @@splitMPlines = false
+
+    def MPTools::splitmplines(str)
+        if @@splitMPlines then
+            btex, verbatimtex, strings, result = Array.new, Array.new, Array.new, str.dup
+            # protect texts
+            result.gsub!(/btex\s*(.*?)\s*etex/) do
+                btex << $1
+                "btex(#{btex.length-1})"
+            end
+            result.gsub!(/verbatimtex\s*(.*?)\s*etex/) do
+                verbatimtex << $1
+                "verbatimtex(#{verbatimtex.length-1})"
+            end
+            result.gsub!(/\"(.*?)\"/) do
+                strings << $1
+                "\"#{strings.length-1}\""
+            end
+            result.gsub!(/\;/) do
+                ";\n"
+            end
+            result.gsub!(/(.{80,})(\-\-\-|\-\-|\.\.\.|\.\.)/) do
+                "#{$1}#{$2}\n"
+            end
+            result.gsub!(/\n[\s\n]+/moi) do
+                "\n"
+            end
+            result.gsub!(/btex\((\d+)\)/) do
+                "btex #{btex[$1.to_i]} etex"
+            end
+            result.gsub!(/verbatimtex\((\d+)\)/) do
+                "verbatimtex #{verbatimtex[$1.to_i]} etex"
+            end
+            result.gsub!(/\"(\d+)\"/) do
+                "\"#{strings[$1.to_i]}\""
+            end
+            # return result # let's catch xetex bug
+            return result.gsub(/\^\^(M|J)/o, "\n")
+        else
+            # return str # let's catch xetex bug
+            return str.gsub(/\^\^(M|J)/o, "\n")
+        end
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/mp.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/pdf.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/pdf.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/pdf.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,83 @@
+module PDFview
+
+    @files      = Hash.new
+    @opencalls  = Hash.new
+    @closecalls = Hash.new
+    @allcalls   = Hash.new
+
+    # acrobat no longer is a valid default as (1) it keeps crashing with pdfopen due to a dual acrobat/reader install (a side effect
+    # of the api changing every version, and (2) because there are all these anyoing popups with respect to signed, review, online
+    # this and that stuff ... hardly useable as fast previewer, and (3) sumatra is faster and nicer and doesn't block (okay, we have to
+    # get rid of this horrible yellow bg-coloring buts that is doable
+
+    @method     = 'sumatra' # 'default' # 'xpdf'
+
+    @opencalls['default']  = "pdfopen  --file" # "pdfopen --back --file"
+    @opencalls['xpdf']     = "xpdfopen"
+    @opencalls['sumatra']  = 'start "test" sumatrapdf.exe -reuse-instance -bg-color 0xCCCCCC'
+
+    @closecalls['default'] = "pdfclose --file"
+    @closecalls['xpdf']    = nil
+    @closecalls['sumatra'] = nil
+
+    @allcalls['default']   = "pdfclose --all"
+    @allcalls['xpdf']      = nil
+    @allcalls['sumatra']   = nil
+
+    def PDFview.setmethod(method)
+        @method = method
+    end
+
+    def PDFview.open(*list)
+        begin
+            [*list].flatten.each do |file|
+                filename = fullname(file)
+                if FileTest.file?(filename) then
+                    if @opencalls[@method] then
+                        result = `#{@opencalls[@method]} #{filename} 2>&1`
+                        @files[filename] = true
+                    end
+                end
+            end
+        rescue
+        end
+    end
+
+    def PDFview.close(*list)
+        [*list].flatten.each do |file|
+            filename = fullname(file)
+            begin
+                if @files.key?(filename) then
+                    if @closecalls[@method] then
+                        result = `#{@closecalls[@method]} #{filename} 2>&1`
+                    end
+                else
+                    closeall
+                    return
+                end
+            rescue
+            end
+            @files.delete(filename)
+        end
+    end
+
+    def PDFview.closeall
+        begin
+            if @allcalls[@method] then
+                result = `#{@allcalls[@method]} 2>&1`
+            end
+        rescue
+        end
+        @files.clear
+    end
+
+    def PDFview.fullname(name)
+        name + if name =~ /\.pdf$/ then '' else '.pdf' end
+    end
+
+end
+
+# PDFview.open("t:/document/show-exa.pdf")
+# PDFview.open("t:/document/show-gra.pdf")
+# PDFview.close("t:/document/show-exa.pdf")
+# PDFview.close("t:/document/show-gra.pdf")


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/pdf.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/state.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/state.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/state.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,75 @@
+require 'digest/md5'
+
+# todo: register omissions per file
+
+class FileState
+
+    def initialize
+        @states = Hash.new
+        @omiter = Hash.new
+    end
+
+    def reset
+        @states.clear
+        @omiter.clear
+    end
+
+    def register(filename,omit=nil)
+        unless @states.key?(filename) then
+            @states[filename] = Array.new
+            @omiter[filename] = omit
+        end
+        @states[filename] << checksum(filename, at omiter[filename])
+    end
+
+    def update(filename=nil)
+        [filename, at states.keys].flatten.compact.uniq.each do |fn|
+            register(fn)
+        end
+    end
+
+    def inspect(filename=nil)
+        result = ''
+        [filename, at states.keys].flatten.compact.uniq.sort.each do |fn|
+            if @states.key?(fn) then
+                result += "#{fn}: #{@states[fn].inspect}\n"
+            end
+        end
+        result
+    end
+
+    def changed?(filename)
+        if @states.key?(filename) then
+            n = @states[filename].length
+            if n>1 then
+                changed = @states[filename][n-1] != @states[filename][n-2]
+            else
+                changed = true
+            end
+        else
+            changed = true
+        end
+        return changed
+    end
+
+    def checksum(filename,omit=nil)
+        sum = ''
+        begin
+            if FileTest.file?(filename) && (data = IO.read(filename)) then
+                data.gsub!(/\n.*?(#{[omit].flatten.join('|')}).*?\n/) do "\n" end if omit
+                sum = Digest::MD5.hexdigest(data).upcase
+            end
+        rescue
+            sum = ''
+        end
+        return sum
+    end
+
+    def stable?
+        @states.keys.each do |s|
+            return false if changed?(s)
+        end
+        return true
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/state.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/switch.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/switch.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/switch.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,637 @@
+#encoding: ASCII-8BIT
+
+# module    : base/switch
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# we cannot use getoptlong because we want to be more
+# tolerant; also we want to be case insensitive (2002).
+
+# we could make each option a class itself, but this is
+# simpler; also we can put more in the array
+
+# beware: regexps/o in methods are optimized globally
+
+require "rbconfig"
+
+$mswindows = RbConfig::CONFIG['host_os'] =~ /mswin/
+$separator = File::PATH_SEPARATOR
+
+class String
+
+    def has_suffix?(suffix)
+        self =~ /\.#{suffix}$/i
+    end
+
+end
+
+# may move to another module
+
+class File
+
+    @@update_eps = 1
+
+    def File.needsupdate(oldname,newname)
+        begin
+            oldtime = File.stat(oldname).mtime.to_i
+            newtime = File.stat(newname).mtime.to_i
+            if newtime >= oldtime then
+                return false
+            elsif oldtime-newtime < @@update_eps then
+                return false
+            else
+                return true
+            end
+        rescue
+            return true
+        end
+    end
+
+    def File.syncmtimes(oldname,newname)
+        return
+        begin
+            if $mswindows then
+                # does not work (yet) / gives future timestamp
+                # t = File.mtime(oldname) # i'm not sure if the time is frozen, so we do it here
+                # File.utime(0,t,oldname,newname)
+            else
+                t = File.mtime(oldname) # i'm not sure if the time is frozen, so we do it here
+                File.utime(0,t,oldname,newname)
+            end
+        rescue
+        end
+    end
+
+    def File.timestamp(name)
+        begin
+            "#{File.stat(name).mtime}"
+        rescue
+            return 'unknown'
+        end
+    end
+
+end
+
+# main thing
+
+module CommandBase
+
+    # this module can be used as a mixin in a command handler
+
+    $stdout.sync = true
+
+    def initialize(commandline,logger,banner)
+        @commandline, @logger, @banner = commandline, logger, banner
+        @forcenewline, @versiondone, @error = false, false, false
+        version if @commandline.option('version')
+    end
+
+    def reportlines(*str)
+        @logger.reportlines(str)
+    end
+
+    # only works in 1.8
+    #
+    # def report(*str)
+    #     @logger.report(str)
+    # end
+    #
+    # def version # just a bit of playing with defs
+    #    report(@banner.join(' - '))
+    #    def report(*str)
+    #        @logger.report
+    #        @logger.report(str)
+    #        def report(*str)
+    #            @logger.report(str)
+    #        end
+    #    end
+    #    def version
+    #    end
+    # end
+
+    def report(*str)
+        initlogger ; @logger.report(str)
+    end
+
+    def seterror
+        @error = true
+    end
+
+    def error?
+        return @error
+    end
+
+    def exit
+        if @error then Kernel.exit(1) else Kernel.exit(0) end
+    end
+
+    def execute(str=nil)
+        send(str || action || 'main')
+        exit
+    end
+
+    def debug(*str)
+        initlogger ; @logger.debug(str)
+    end
+
+    def error(*str)
+        initlogger ; @logger.error(str)
+    end
+
+    def initlogger
+        if @forcenewline then
+            @logger.report
+            @forcenewline = false
+        end
+    end
+
+    def logger
+        @logger
+    end
+
+    def version # just a bit of playing with defs
+        unless @versiondone then
+            report(@banner.join(' - '))
+            @forcenewline = true
+            @versiondone = true
+        end
+    end
+
+    def help
+        version # is nilled when already given
+        @commandline.helpkeys.each do |k|
+            if @commandline.help?(k) then
+                kstr = ('--'+k).ljust(@commandline.helplength+2)
+                message = @commandline.helptext(k)
+                message = '' if message == CommandLine::NOHELP
+                message = message.split(/\s*\n\s*/)
+                loop do
+                    report("#{kstr} #{message.shift}")
+                    kstr = ' '*kstr.length
+                    break if message.length == 0
+                end
+            end
+        end
+    end
+
+    def option(key)
+        @commandline.option(key)
+    end
+    def oneof(*key)
+        @commandline.oneof(*key)
+    end
+
+    def globfiles(pattern='*',suffix=nil)
+        @commandline.setarguments([pattern].flatten)
+        if files = findfiles(suffix) then
+            @commandline.setarguments(files)
+        else
+            @commandline.setarguments
+        end
+    end
+
+    private
+
+    def findfiles(suffix=nil)
+
+        if @commandline.arguments.length>1 then
+            return @commandline.arguments
+        else
+            pattern  = @commandline.argument('first')
+            pattern  = '*' if pattern.empty?
+            if suffix && ! pattern.match(/\..+$/o) then
+                suffix   = '.' + suffix
+                pattern += suffix unless pattern =~ /#{suffix}$/
+            end
+            # not {} safe
+            pattern = '**/' + pattern if @commandline.option('recurse')
+            files = Dir[pattern]
+            if files && files.length>0 then
+                return files
+            else
+                pattern = @commandline.argument('first')
+                if FileTest.file?(pattern) then
+                    return [pattern]
+                else
+                    report("no files match pattern #{pattern}")
+                    return nil
+                end
+            end
+        end
+
+    end
+
+    def globbed(pattern,recurse=false)
+
+        files = Array.new
+        pattern.split(' ').each do |p|
+            if recurse then
+                if p =~ /^(.*)(\/.*?)$/i then
+                    p = $1 + '/**' + $2
+                else
+                    p = '**/' + p
+                end
+                p.gsub!(/[\\\/]+/, '/')
+            end
+            files.push(Dir.glob(p))
+        end
+        files.flatten.sort do |a,b|
+            pathcompare(a,b)
+        end
+    end
+
+    def pathcompare(a,b)
+
+        aa, bb = a.split('/'), b.split('/')
+        if aa.length == bb.length then
+            aa.each_index do |i|
+                if aa[i]<bb[i] then
+                    return -1
+                elsif aa[i]>bb[i] then
+                    return +1
+                end
+            end
+            return 0
+        else
+            return aa.length <=> bb.length
+        end
+
+    end
+
+end
+
+class CommandLine
+
+    VALUE, FLAG = 1, 2
+    NOHELP = 'no arguments'
+
+    def initialize(prefix='-')
+
+        @registered = Array.new
+        @options    = Hash.new
+        @unchecked  = Hash.new
+        @arguments  = Array.new
+        @original   = ARGV.join(' ')
+        @helptext   = Hash.new
+        @mandated   = Hash.new
+        @provided   = Hash.new
+        @prefix     = prefix
+        @actions    = Array.new
+
+        # The quotes in --switch="some value" get lost in ARGV, so we need to do some trickery here.
+
+        @original = ''
+        ARGV.each do |a|
+            aa = a.strip.gsub(/^([#{@prefix}]+\w+\=)([^\"].*?\s+.*[^\"])$/) do
+                $1 + "\"" + $2 + "\""
+            end
+            @original += if @original.empty? then '' else ' ' end + aa
+        end
+
+    end
+
+    def setarguments(args=[])
+        @arguments = if args then args else [] end
+    end
+
+    def register(option,shortcut,kind,default=false,action=false,helptext='')
+        if kind == FLAG then
+            @options[option] = default
+        elsif not default then
+            @options[option] = ''
+        else
+            @options[option] = default
+        end
+        @registered.push([option,shortcut,kind])
+        @mandated[option] = false
+      # @provided[option] = false
+        @helptext[option] = helptext
+        @actions.push(option) if action
+    end
+
+    def registerflag(option,default=false,helptext='')
+        if default.class == String then
+            register(option,'',FLAG,false,false,default)
+        else
+            register(option,'',FLAG,false,false,helptext)
+        end
+    end
+
+    def registervalue(option,default='',helptext='')
+        register(option,'',VALUE,default,false,helptext)
+    end
+
+    def registeraction(option,helptext='')
+        register(option,'',FLAG,false,true,helptext)
+    end
+
+    def registermandate(*option)
+        [*option].each do |o|
+            [o].each do |oo|
+                @mandated[oo] = true
+            end
+        end
+    end
+
+    def actions
+        a = @actions.delete_if do |t|
+            ! option(t)
+        end
+        if a && a.length>0 then
+            return a
+        else
+            return nil
+        end
+    end
+
+    def action
+        @actions.each do |t|
+            return t if option(t)
+        end
+        return nil
+    end
+
+    def forgotten
+        @mandated.keys.sort - @provided.keys.sort
+    end
+
+    def registerhelp(option,text='')
+        @helptext['unknown'] = if text.empty? then option else text end
+    end
+
+    def helpkeys(option='.*')
+        @helptext.keys.sort.grep(/#{option}/)
+    end
+
+    def helptext(option)
+        @helptext.fetch(option,'')
+    end
+
+    def help?(option)
+        @helptext[option] && ! @helptext[option].empty?
+    end
+
+    def helplength
+        n = 0
+        @helptext.keys.each do |h|
+            n = h.length if h.length>n
+        end
+        return n
+    end
+
+    def expand
+
+        # todo : '' or false, depending on type
+        # @options.clear
+        # @arguments.clear
+
+        dirtyvalue(@original).split(' ').each do |arg|
+            case arg
+                when /^[#{@prefix}][#{@prefix}](.+?)\=(.*?)$/ then locatedouble($1,$2)
+                when /^[#{@prefix}][#{@prefix}](.+?)$/        then locatedouble($1,false)
+                when /^[#{@prefix}](.)\=(.)$/                 then locatesingle($1,$2)
+                when /^[#{@prefix}](.+?)$/                    then locateseries($1,false)
+                when /^[\+\-]+/o                              then # do nothing
+            else
+                arguments.push(arg)
+            end
+        end
+
+        @options or @unchecked or @arguments
+
+    end
+
+    def extend (str)
+        @original = @original + ' ' + str
+    end
+
+    def replace (str)
+        @original = str
+    end
+
+    def show
+      # print "-- options --\n"
+        @options.keys.sort.each do |key|
+            print "option: #{key} -> #{@options[key]}\n"
+        end
+      # print "-- arguments --\n"
+        @arguments.each_index do |key|
+            print "argument: #{key} -> #{@arguments[key]}\n"
+        end
+    end
+
+    def option(str,default=nil)
+        if @options.key?(str) then
+            @options[str]
+        elsif default then
+            default
+        else
+            @options[str]
+        end
+    end
+
+    def checkedoption(str,default='')
+        if @options.key?(str) then
+            if @options[str].empty? then default else @options[str] end
+        else
+            default
+        end
+    end
+
+    def foundoption(str,default='')
+        str = str.split(',') if str.class == String
+        str.each do |s|
+            return str if @options.key?(str)
+        end
+        return default
+    end
+
+    def oneof(*key)
+        [*key].flatten.compact.each do |k|
+           return true if @options.key?(k) && @options[k]
+        end
+        return false
+    end
+
+    def setoption(str,value)
+        @options[str] = value
+    end
+
+    def getoption(str,value='') # value ?
+        @options[str]
+    end
+
+    def argument(n=0)
+        if n.class == String then
+            case n
+                when 'first'  then argument(0)
+                when 'second' then argument(1)
+                when 'third'  then argument(2)
+            else
+                argument(0)
+            end
+        elsif @arguments[n] then
+            @arguments[n]
+        else
+            ''
+        end
+    end
+
+    # a few local methods, cannot be defined nested (yet)
+
+    private
+
+    def dirtyvalue(value) # \xFF suddenly doesn't work any longer
+        if value then
+            value.gsub(/([\"\'])(.*?)\1/) do
+                $2.gsub(/\s+/o, "\0xFF")
+            end
+        else
+            ''
+        end
+    end
+
+    def cleanvalue(value) # \xFF suddenly doesn't work any longer
+        if value then
+            # value.sub(/^([\"\'])(.*?)\1$/) { $2.gsub(/\xFF/o, ' ') }
+            value.gsub(/\0xFF/o, ' ')
+        else
+            ''
+        end
+    end
+
+    def locatedouble(key, value)
+
+        foundkey, foundkind = nil, nil
+
+        @registered.each do |option, shortcut, kind|
+            if option == key then
+                foundkey, foundkind = option, kind
+                break
+            end
+        end
+        unless foundkey then
+            @registered.each do |option, shortcut, kind|
+                n = 0
+                begin
+                    re = /^#{key}/i
+                rescue
+                    key = key.inspect.sub(/^\"(.*)\"$/) do $1 end
+                    re = /^#{key}/i
+                ensure
+                    if option =~ re then
+                        case n
+                            when 0
+                                foundkey, foundkind, n = option, kind, 1
+                            when 1
+                                # ambiguous matches, like --fix => --fixme --fixyou
+                                foundkey, foundkind = nil, nil
+                                break
+                        end
+                    end
+                end
+            end
+        end
+        if foundkey then
+            @provided[foundkey] = true
+            if foundkind == VALUE then
+                @options[foundkey] = cleanvalue(value)
+            else
+                @options[foundkey] = true
+            end
+        else
+            if value.class == FalseClass then
+                @unchecked[key] = true
+            else
+                @unchecked[key] = cleanvalue(value)
+            end
+        end
+
+    end
+
+    def locatesingle(key, value)
+
+        @registered.each do |option, shortcut, kind|
+            if shortcut == key then
+                @provided[option] = true
+                @options[option] = if kind == VALUE then '' else cleanvalue(value) end
+                break
+            end
+        end
+
+    end
+
+    def locateseries(series, value)
+
+        series.each_char do |key| # was .each but there is no alias to each_char any longer
+            locatesingle(key,cleanvalue(value))
+        end
+
+    end
+
+    public
+
+    attr_reader :arguments, :options, :original, :unchecked
+
+end
+
+# options = CommandLine.new
+#
+# options.register("filename", "f", CommandLine::VALUE)
+# options.register("request" , "r", CommandLine::VALUE)
+# options.register("verbose" , "v", CommandLine::FLAG)
+#
+# options.expand
+# options.extend(str)
+# options.show
+#
+# c = CommandLine.new
+#
+# c.registervalue('aaaa')
+# c.registervalue('test')
+# c.registervalue('zzzz')
+#
+# c.registerhelp('aaaa','some aaaa to enter')
+# c.registerhelp('test','some text to enter')
+# c.registerhelp('zzzz','some zzzz to enter')
+#
+# c.registermandate('test')
+#
+# c.expand
+#
+# class CommandLine
+#
+# def showhelp (banner,*str)
+#   if helpkeys(*str).length>0
+#     print banner
+#     helpkeys(*str).each do |h|
+#       print helptext(h) + "\n"
+#     end
+#     true
+#   else
+#     false
+#   end
+# end
+#
+# def showmandate(banner)
+#   if forgotten.length>0
+#     print banner
+#     forgotten.each do |f|
+#       print helptext(f) + "\n"
+#     end
+#     true
+#   else
+#     false
+#   end
+# end
+#
+# end
+#
+# c.showhelp("you can provide:\n\n")
+# c.showmandate("you also need to provide:\n\n")


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/switch.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/system.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/system.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/system.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,121 @@
+# module    : base/system
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+require "rbconfig"
+
+module System
+
+    @@mswindows   = RbConfig::CONFIG['host_os'] =~ /mswin/
+    @@binpaths    = ENV['PATH'].split(File::PATH_SEPARATOR)
+    @@binsuffixes = if $mswindows then ['.exe','.com','.bat'] else ['','.sh','.csh'] end
+    @@located     = Hash.new
+    @@binnames    = Hash.new
+
+    if @@mswindows then
+        @@binnames['ghostscript'] = ['gswin32c.exe','gs.cmd','gs.bat']
+        @@binnames['imagemagick'] = ['imagemagick.exe','convert.exe']
+        @@binnames['inkscape']    = ['inkscape.exe']
+    else
+        @@binnames['ghostscript'] = ['gs']
+        @@binnames['imagemagick'] = ['convert']
+        @@binnames['inkscape']    = ['inkscape']
+    end
+
+
+    def System.null
+        if @@mswindows then 'nul' else '/dev/null' end
+    end
+
+    def System.unix?
+        not @@mswindows
+    end
+    def System.mswin?
+        @@mswindows
+    end
+
+    def System.binnames(str)
+        if @@binnames.key?(str) then
+            @@binnames[str]
+        else
+            [str]
+        end
+    end
+
+    def System.prependengine(str)
+        if str =~ /^\S+\.(pl|rb|lua|py)/io then
+            case $1
+                when 'pl'  then return "perl #{str}"
+                when 'rb'  then return "ruby #{str}"
+                when 'lua' then return "lua #{str}"
+                when 'py'  then return "python #{str}"
+            end
+        end
+        return str
+    end
+
+    def System.locatedprogram(program)
+        if @@located.key?(program) then
+            return @@located[program]
+        else
+            System.binnames(program).each do |binname|
+                if binname =~ /\..*$/io then
+                    @@binpaths.each do |path|
+                        if FileTest.file?(str = File.join(path,binname)) then
+                            return @@located[program] = System.prependengine(str)
+                        end
+                    end
+                end
+                binname.gsub!(/\..*$/io, '')
+                @@binpaths.each do |path|
+                    @@binsuffixes.each do |suffix|
+                        if FileTest.file?(str = File.join(path,"#{binname}#{suffix}")) then
+                            return @@located[program] = System.prependengine(str)
+                        end
+                    end
+                end
+            end
+        end
+        return @@located[program] = "texmfstart #{program}"
+    end
+
+    def System.command(program,arguments='')
+        if program =~ /^(.*?) (.*)$/ then
+            program = System.locatedprogram($1) + ' ' + $2
+        else
+            program = System.locatedprogram(program)
+        end
+        program = program + ' ' + arguments if ! arguments.empty?
+        program.gsub!(/\s+/io, ' ')
+        #program.gsub!(/(\/\.\/)+/io, '/')
+        program.gsub!(/\\/io, '/')
+        return program
+    end
+
+    def System.run(program,arguments='',pipe=false,collect=false)
+        if pipe then
+            if collect then
+                `#{System.command(program,arguments)} 2>&1`
+            else
+                `#{System.command(program,arguments)}`
+            end
+        else
+            system(System.command(program,arguments))
+        end
+    end
+
+    def System.pipe(program,arguments='',collect=false)
+        System.run(program,arguments,true)
+    end
+
+    def System.safepath(path)
+        if path.match(/ /o) then "\"#{path}\"" else path end
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/system.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/tex.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/tex.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/tex.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,2182 @@
+#encoding: ASCII-8BIT
+
+# module    : base/tex
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# todo:
+#
+# - write systemcall for mpost to file so that it can be run faster
+# - use -8bit and -progname
+#
+
+# report ?
+
+require 'fileutils'
+
+require 'base/variables'
+require 'base/kpse'
+require 'base/system'
+require 'base/state'
+require 'base/pdf'
+require 'base/file'
+require 'base/ctx'
+require 'base/mp'
+
+class String
+
+    def standard?
+        begin
+            self == 'standard'
+        rescue
+            false
+        end
+    end
+
+end
+
+# class String
+    # def utf_bom?
+        # self.match(/^\357\273\277/o).length>0 rescue false
+    # end
+# end
+
+class Array
+
+    def standard?
+        begin
+            self.include?('standard')
+        rescue
+            false
+        end
+    end
+
+    def join_path
+        self.join(File::PATH_SEPARATOR)
+    end
+
+end
+
+class TEX
+
+    # The make-part of this class was made on a rainy day while listening
+    # to "10.000 clowns on a rainy day" by Jan Akkerman. Unfortunately the
+    # make method is not as swinging as this live cd.
+
+    include Variables
+
+    @@texengines      = Hash.new
+    @@mpsengines      = Hash.new
+    @@backends        = Hash.new
+    @@mappaths        = Hash.new
+    @@runoptions      = Hash.new
+    @@draftoptions    = Hash.new
+    @@synctexcoptions = Hash.new
+    @@texformats      = Hash.new
+    @@mpsformats      = Hash.new
+    @@prognames       = Hash.new
+    @@texmakestr      = Hash.new
+    @@texprocstr      = Hash.new
+    @@mpsmakestr      = Hash.new
+    @@mpsprocstr      = Hash.new
+    @@texmethods      = Hash.new
+    @@mpsmethods      = Hash.new
+    @@pdftex          = 'pdftex'
+
+    @@platformslash = if System.unix? then "\\\\" else "\\" end
+
+    ['tex','etex','pdftex','standard']             .each do |e| @@texengines[e] = 'pdftex'    end
+    ['aleph','omega']                              .each do |e| @@texengines[e] = 'aleph'     end
+    ['xetex']                                      .each do |e| @@texengines[e] = 'xetex'     end
+    ['petex']                                      .each do |e| @@texengines[e] = 'petex'     end
+
+    ['metapost','mpost', 'standard']               .each do |e| @@mpsengines[e] = 'mpost'     end
+
+    ['pdftex','pdf','pdftex','standard']           .each do |b| @@backends[b]   = 'pdftex'    end
+    ['dvipdfmx','dvipdfm','dpx','dpm']             .each do |b| @@backends[b]   = 'dvipdfmx'  end
+    ['xetex','xtx']                                .each do |b| @@backends[b]   = 'xetex'     end
+    ['petex']                                      .each do |b| @@backends[b]   = 'dvipdfmx'  end
+    ['aleph']                                      .each do |b| @@backends[b]   = 'dvipdfmx'  end
+    ['dvips','ps','dvi']                           .each do |b| @@backends[b]   = 'dvips'     end
+    ['dvipsone']                                   .each do |b| @@backends[b]   = 'dvipsone'  end
+    ['acrobat','adobe','distiller']                .each do |b| @@backends[b]   = 'acrobat'   end
+    ['xdv','xdv2pdf']                              .each do |b| @@backends[b]   = 'xdv2pdf'   end
+
+    ['tex','standard']                             .each do |b| @@mappaths[b]   = 'dvips'     end
+    ['pdftex']                                     .each do |b| @@mappaths[b]   = 'pdftex'    end
+    ['aleph','omega','xetex','petex']              .each do |b| @@mappaths[b]   = 'dvipdfmx'  end
+    ['dvipdfm', 'dvipdfmx', 'xdvipdfmx']           .each do |b| @@mappaths[b]   = 'dvipdfmx'  end
+    ['xdv','xdv2pdf']                              .each do |b| @@mappaths[b]   = 'dvips'     end
+
+    # todo norwegian (no)
+
+    ['plain']                                      .each do |f| @@texformats[f] = 'plain'        end
+    ['cont-en','en','english','context','standard'].each do |f| @@texformats[f] = 'cont-en.mkii' end
+    ['cont-nl','nl','dutch']                       .each do |f| @@texformats[f] = 'cont-nl.mkii' end
+    ['cont-de','de','german']                      .each do |f| @@texformats[f] = 'cont-de.mkii' end
+    ['cont-it','it','italian']                     .each do |f| @@texformats[f] = 'cont-it.mkii' end
+    ['cont-fr','fr','french']                      .each do |f| @@texformats[f] = 'cont-fr.mkii' end
+    ['cont-cs','cs','cont-cz','cz','czech']        .each do |f| @@texformats[f] = 'cont-cs.mkii' end
+    ['cont-ro','ro','romanian']                    .each do |f| @@texformats[f] = 'cont-ro.mkii' end
+    ['cont-gb','gb','cont-uk','uk','british']      .each do |f| @@texformats[f] = 'cont-gb.mkii' end
+    ['mptopdf']                                    .each do |f| @@texformats[f] = 'mptopdf'      end
+
+    ['latex']                                      .each do |f| @@texformats[f] = 'latex.ltx' end
+
+    ['plain','mpost']                              .each do |f| @@mpsformats[f] = 'mpost'     end
+    ['metafun','context','standard']               .each do |f| @@mpsformats[f] = 'metafun'   end
+
+    ['pdftex','aleph','omega','petex','xetex']     .each do |p| @@prognames[p]  = 'context'   end
+    ['mpost']                                      .each do |p| @@prognames[p]  = 'metafun'   end
+    ['latex','pdflatex']                           .each do |p| @@prognames[p]  = 'latex'     end
+
+    ['plain','default','standard','mptopdf']       .each do |f| @@texmethods[f] = 'plain'     end
+    ['cont-en','cont-en.mkii',
+     'cont-nl','cont-nl.mkii',
+     'cont-de','cont-de.mkii',
+     'cont-it','cont-it.mkii',
+     'cont-fr','cont-fr.mkii',
+     'cont-cs','cont-cs.mkii',
+     'cont-ro','cont-ro.mkii',
+     'cont-gb','cont-gb.mkii']                     .each do |f| @@texmethods[f] = 'context'   end
+    ['latex','latex.ltx','pdflatex']               .each do |f| @@texmethods[f] = 'latex'     end # untested
+
+    ['plain','default','standard']                 .each do |f| @@mpsmethods[f] = 'plain'     end
+    ['metafun']                                    .each do |f| @@mpsmethods[f] = 'metafun'   end
+
+    @@texmakestr['plain'] = @@platformslash + "dump"
+    @@mpsmakestr['plain'] = @@platformslash + "dump"
+
+    ['cont-en','cont-nl','cont-de','cont-it',
+     'cont-fr','cont-cs','cont-ro','cont-gb',
+     'cont-pe','cont-xp']                         .each do |f| @@texprocstr[f] = @@platformslash + "emergencyend"  end
+
+    @@runoptions['aleph']      = ['--8bit']
+    @@runoptions['mpost']      = ['--8bit']
+    @@runoptions['pdftex']     = ['--8bit']
+  # @@runoptions['petex']      = []
+    @@runoptions['xetex']      = ['--8bit','-output-driver="xdvipdfmx -E -d 4 -V 5"']
+    @@draftoptions['pdftex']   = ['--draftmode']
+    @@synctexcoptions['pdftex'] = ['--synctex=1']
+    @@synctexcoptions['xetex']  = ['--synctex=1']
+
+    @@mainbooleanvars = [
+        'batchmode', 'nonstopmode', 'fast', 'final',
+        'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterns', 'draft',
+        'nompmode', 'nomprun', 'automprun', 'combine',
+        'nomapfiles', 'local',
+        'arrange', 'noarrange',
+        'forcexml', 'foxet',
+        'alpha', 'beta',
+        'mpyforce', 'forcempy',
+        'forcetexutil', 'texutil',
+        'globalfile', 'autopath',
+        'purge', 'purgeall', 'keep', 'autopdf', 'xpdf', 'simplerun', 'verbose',
+        'nooptionfile', 'nobackend', 'noctx', 'utfbom',
+        'mkii','mkiv',
+        'synctex',
+    ]
+    @@mainstringvars = [
+        'modefile', 'result', 'suffix', 'response', 'path',
+        'filters', 'usemodules', 'environments', 'separation', 'setuppath',
+        'arguments', 'input', 'output', 'randomseed', 'modes', 'mode', 'filename',
+        'ctxfile', 'printformat', 'paperformat', 'paperoffset',
+        'timeout', 'passon', 'pdftitle'
+    ]
+    @@mainstandardvars = [
+        'mainlanguage', 'bodyfont', 'language'
+    ]
+    @@mainknownvars = [
+        'engine', 'distribution', 'texformats', 'mpsformats', 'progname', 'interface',
+        'runs', 'backend'
+    ]
+
+    @@extrabooleanvars = []
+    @@extrastringvars = []
+
+    def booleanvars
+        [@@mainbooleanvars,@@extrabooleanvars].flatten.uniq
+    end
+    def stringvars
+        [@@mainstringvars,@@extrastringvars].flatten.uniq
+    end
+    def standardvars
+        [@@mainstandardvars].flatten.uniq
+    end
+    def knownvars
+        [@@mainknownvars].flatten.uniq
+    end
+    def allbooleanvars
+        [@@mainbooleanvars,@@extrabooleanvars].flatten.uniq
+    end
+    def allstringvars
+        [@@mainstringvars,@@extrastringvars,@@mainstandardvars,@@mainknownvars].flatten.uniq
+    end
+
+    def setextrastringvars(vars)
+        # @@extrastringvars << vars -- problems in 1.9
+        @@extrastringvars = [@@extrastringvars,vars].flatten
+    end
+    def setextrabooleanvars(vars)
+        # @@extrabooleanvars << vars -- problems in 1.9
+        @@extrabooleanvars = [@@extrabooleanvars,vars].flatten
+    end
+
+    # def jobvariables(names=nil)
+        # if [names ||[]].flatten.size == 0 then
+            # names = [allbooleanvars,allstringvars].flatten
+        # end
+        # data = Hash.new
+        # names.each do |name|
+            # if allbooleanvars.include?(name) then
+                # data[name] = if getvariable(name) then "yes" else "no" end
+            # else
+                # data[name] = getvariable(name)
+            # end
+        # end
+        # data
+    # end
+
+    # def setjobvariables(names=nil)
+        # assignments = Array.new
+        # jobvariables(names).each do |k,v|
+            # assignments << "#{k}=\{#{v}\}"
+        # end
+        # "\setvariables[exe][#{assignments.join(", ")}]"
+    # end
+
+    @@temprunfile = 'texexec'
+    @@temptexfile = 'texexec.tex'
+
+    def initialize(logger=nil)
+        if @logger = logger then
+            def report(str='')
+                @logger.report(str)
+            end
+        else
+            def report(str='')
+                puts(str)
+            end
+        end
+        @cleanups    = Array.new
+        @variables   = Hash.new
+        @startuptime = Time.now
+        # options
+        booleanvars.each do |k|
+            setvariable(k,false)
+        end
+        stringvars.each do |k|
+            setvariable(k,'')
+        end
+        standardvars.each do |k|
+            setvariable(k,'standard')
+        end
+        setvariable('distribution', Kpse.distribution)
+        setvariable('texformats',   defaulttexformats)
+        setvariable('mpsformats',   defaultmpsformats)
+        setvariable('progname',     'standard') # or ''
+        setvariable('interface',    'standard')
+        setvariable('engine',       'standard') # replaced by tex/mpsengine
+        setvariable('backend',      'pdftex')
+        setvariable('runs',         '8')
+        setvariable('randomseed',   rand(1440).to_s) # we want the same seed for one run
+        # files
+        setvariable('files',        [])
+        # defaults
+        setvariable('texengine',    'standard')
+        setvariable('mpsengine',    'standard')
+        setvariable('backend',      'standard')
+        setvariable('error',        '')
+    end
+
+    def error?
+        not getvariable('error').empty?
+    end
+
+    def runtime
+        Time.now - @startuptime
+    end
+
+    def reportruntime
+        report("runtime: #{runtime}")
+    end
+
+    def runcommand(something)
+        command = [something].flatten.join(' ')
+        report("running: #{command}") if getvariable('verbose')
+        system(command)
+    end
+
+    def inspect(name=nil)
+        if ! name || name.empty? then
+            name = [booleanvars,stringvars,standardvars,knownvars]
+        end
+        str = '' # allocate
+        [name].flatten.each do |n|
+            if str = getvariable(n) then
+                str = str.join(" ") if str.class == Array
+                unless (str.class == String) && str.empty? then
+                    report("option '#{n}' is set to '#{str}'")
+                end
+            end
+        end
+    end
+
+    def tempfilename(suffix='')
+        @@temprunfile + if suffix.empty? then '' else ".#{suffix}" end
+    end
+
+    def cleanup
+        @cleanups.each do |name|
+            begin
+                File.delete(name) if FileTest.file?(name)
+            rescue
+                report("unable to delete #{name}")
+            end
+        end
+    end
+
+    def cleanuptemprunfiles
+        begin
+            Dir.glob("#{@@temprunfile}*").each do |name|
+                if File.file?(name) && (File.splitname(name)[1] !~ /(pdf|dvi)/o) then
+                    File.delete(name) rescue false
+                end
+            end
+        rescue
+        end
+        # ['mpgraph.mp'].each do |file|
+            # (File.delete(file) if (FileTest.size?(file) rescue 10) < 10) rescue false
+        # end
+    end
+
+    def backends() @@backends.keys.sort end
+
+    def texengines() @@texengines.keys.sort end
+    def mpsengines() @@mpsengines.keys.sort end
+    def texformats() @@texformats.keys.sort end
+    def mpsformats() @@mpsformats.keys.sort end
+
+    def defaulttexformats() ['en','nl','mptopdf'] end
+    def defaultmpsformats() ['metafun']           end # no longer formats
+
+    def texmakeextras(format) @@texmakestr[format] || '' end
+    def mpsmakeextras(format) @@mpsmakestr[format] || '' end
+    def texprocextras(format) @@texprocstr[format] || '' end
+    def mpsprocextras(format) @@mpsprocstr[format] || '' end
+
+    def texmethod(format) @@texmethods[str] || @@texmethods['standard'] end
+    def mpsmethod(format) @@mpsmethods[str] || @@mpsmethods['standard'] end
+
+    def runoptions(engine)
+        options = if getvariable('draft') then @@draftoptions[engine] else [] end
+        options = if getvariable('synctex') then @@synctexcoptions[engine] else [] end
+        begin
+            if str = getvariable('passon') then
+                options = [options,str.split(' ')].flatten
+            end
+        rescue
+        end
+        if @@runoptions.key?(engine) then
+            [options,@@runoptions[engine]].flatten.join(' ')
+        else
+            options.join(' ')
+        end
+    end
+
+    # private
+
+    def cleanuplater(name)
+        begin
+            @cleanups.push(File.expand_path(name))
+        rescue
+            @cleanups.push(name)
+        end
+    end
+
+    def openedfile(name)
+        begin
+            f = File.open(name,'w')
+        rescue
+            report("file '#{File.expand_path(name)}' cannot be opened for writing")
+            return nil
+        else
+            cleanuplater(name) if f
+            return f
+        end
+    end
+
+    def prefixed(format,engine)
+        # format
+        case engine
+           when /etex|pdftex|aleph|xetex/io then
+               "*#{format}"
+           else
+               format
+        end
+    end
+
+    def quoted(str)
+        if str =~ /^[^\"].* / then "\"#{str}\"" else str end
+    end
+
+    def getarrayvariable(str='')
+        str = getvariable(str)
+        if str.class == String then str.split(',') else str.flatten end
+    end
+
+    def validsomething(str,something,type=nil)
+        if str then
+            list = [str].flatten.collect do |s|
+                if something[s] then
+                    something[s]
+                elsif type && s =~ /\.#{type}$/ then
+                    s
+                else
+                    nil
+                end
+            end .compact.uniq
+            if list.length>0 then
+                if str.class == String then list.first else list end
+            else
+                false
+            end
+        else
+            false
+        end
+    end
+
+    def validtexformat(str) validsomething(str,@@texformats,'tex')    ||
+                            validsomething(str,@@texformats,'mkii')   end
+    def validmpsformat(str) validsomething(str,@@mpsformats,'mp' )    end
+    def validtexengine(str) validsomething(str,@@texengines,'pdftex') end
+    def validmpsengine(str) validsomething(str,@@mpsengines,'mpost' ) end
+
+    def validtexmethod(str) [validsomething(str,@@texmethods)].flatten.first end
+    def validmpsmethod(str) [validsomething(str,@@mpsmethods)].flatten.first end
+
+    def validbackend(str)
+        if str && @@backends.key?(str) then
+            @@backends[str]
+        else
+            @@backends['standard']
+        end
+    end
+
+    def validprogname(str)
+        if str then
+            [str].flatten.each do |s|
+                s = s.sub(/\.\S*/,"")
+                return @@prognames[s] if @@prognames.key?(s)
+            end
+            return str[0].sub(/\.\S*/,"")
+        else
+            return nil
+        end
+    end
+
+    # we no longer support the & syntax
+
+    def formatflag(engine=nil,format=nil)
+        case getvariable('distribution')
+            when 'standard' then prefix = "--fmt"
+            when /web2c/io  then prefix = web2cformatflag(engine)
+            when /miktex/io then prefix = "--undump"
+                            else return ""
+        end
+        if format then
+            "#{prefix}=#{format.sub(/\.\S+$/,"")}"
+        else
+            prefix
+        end
+    end
+
+    def web2cformatflag(engine=nil)
+        # funny that we've standardized on the fmt suffix (at the cost of
+        # upward compatibility problems) but stuck to the bas/mem/fmt flags
+        if engine then
+            case validmpsengine(engine)
+                when /mpost/ then "-mem"
+                when /mfont/ then "-bas"
+                else              "-fmt"
+            end
+        else
+            "-fmt"
+        end
+    end
+
+    def prognameflag(progname=nil)
+        case getvariable('distribution')
+            when 'standard' then prefix = "-progname"
+            when /web2c/io  then prefix = "-progname"
+            when /miktex/io then prefix = "-alias"
+                            else return ""
+        end
+        if progname and not progname.empty? then
+            "#{prefix}=#{progname}"
+        else
+            prefix
+        end
+    end
+
+    def iniflag() # should go to kpse and kpse should become texenv
+        if Kpse.miktex? then
+            "-initialize"
+        else
+            "--ini"
+        end
+    end
+
+  # # obsolete
+  #
+  # def tcxflag(engine)
+  #     if @@tcxflag[engine] then
+  #         file = "natural.tcx"
+  #         if Kpse.miktex? then
+  #             "-tcx=#{file}"
+  #         else
+  #             "-translate-file=#{file}"
+  #         end
+  #     else
+  #         ""
+  #     end
+  # end
+
+    def filestate(file)
+        File.mtime(file).strftime("%d/%m/%Y %H:%M:%S")
+    end
+
+    # will go to context/process context/listing etc
+
+    def contextversion # ook elders gebruiken
+        filename = Kpse.found('context.mkii')
+        version = 'unknown'
+        begin
+            if FileTest.file?(filename) && IO.read(filename).match(/\\contextversion\{(\d+\.\d+\.\d+.*?)\}/) then
+                version = $1
+            end
+        rescue
+        end
+        return version
+    end
+
+    # we need engine methods
+
+    def makeformats
+
+        checktestversion
+
+        report("using search method '#{Kpse.searchmethod}'")
+        if getvariable('fast') then
+            report('using existing database')
+        else
+            report('updating file database')
+            Kpse.update # obsolete here
+        end
+        # goody
+        if getvariable('texformats') == 'standard' then
+            setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
+        end
+        # prepare
+        texformats = validtexformat(getarrayvariable('texformats'))
+        mpsformats = validmpsformat(getarrayvariable('mpsformats'))
+        texengine  = validtexengine(getvariable('texengine'))
+        mpsengine  = validmpsengine(getvariable('mpsengine'))
+        # save current path
+        savedpath = Dir.getwd
+        # generate tex formats
+        unless texformats || mpsformats then
+            report('provide valid format (name.tex, name.mp, ...) or format id (metafun, en, nl, ...)')
+            setvariable('error','no format specified')
+        end
+        if texformats && texengine then
+            report("using tex engine #{texengine}")
+            texformatpath = if getvariable('local') then '.' else Kpse.formatpath(texengine,true) end
+            # can be empty, to do
+            report("using tex format path #{texformatpath}")
+            Dir.chdir(texformatpath) rescue false
+            if FileTest.writable?(texformatpath) then
+            # from now on we no longer support this; we load
+            # all patterns and if someone wants another
+            # interface language ... cook up a fmt or usr file
+            #
+            #   if texformats.length > 0 then
+            #       makeuserfile
+            #       makeresponsefile
+            #   end
+                texformats.each do |texformat|
+                    report("generating tex format #{texformat}")
+                    progname = validprogname([getvariable('progname'),texformat,texengine])
+                    runcommand([quoted(texengine),prognameflag(progname),iniflag,prefixed(texformat,texengine),texmakeextras(texformat)])
+                end
+            else
+                report("unable to make format due to lack of permissions")
+                texformatpath = ''
+                setvariable('error','no permissions to write')
+            end
+            if not mpsformats then
+                # we want metafun to be in sync
+                setvariable('mpsformats',defaultmpsformats)
+                mpsformats = validmpsformat(getarrayvariable('mpsformats'))
+            end
+        else
+            texformatpath = ''
+        end
+        # generate mps formats
+     #  if mpsformats && mpsengine then
+     #      report("using mp engine #{mpsengine}")
+     #      mpsformatpath = if getvariable('local') then '.' else Kpse.formatpath(mpsengine,false) end
+     #      report("using mps format path #{mpsformatpath}")
+     #      Dir.chdir(mpsformatpath) rescue false
+     #      if FileTest.writable?(mpsformatpath) then
+     #          mpsformats.each do |mpsformat|
+     #              report("generating mps format #{mpsformat}")
+     #              progname = validprogname([getvariable('progname'),mpsformat,mpsengine])
+     #              if not runcommand([quoted(mpsengine),prognameflag(progname),iniflag,runoptions(mpsengine),mpsformat,mpsmakeextras(mpsformat)]) then
+     #                  setvariable('error','no format made')
+     #              end
+     #          end
+     #      else
+     #          report("unable to make format due to lack of permissions")
+     #          mpsformatpath = ''
+     #          setvariable('error','file permission problem')
+     #      end
+     #   else
+     #      mpsformatpath = ''
+     #  end
+        # check for problems
+        report("")
+        report("tex engine path: #{texformatpath}") unless texformatpath.empty?
+     #  report("mps engine path: #{mpsformatpath}") unless mpsformatpath.empty?
+        report("")
+     #  [['fmt','tex'],['mem','mps']].each do |f|
+     #      [[texformatpath,'global'],[mpsformatpath,'global'],[savedpath,'current']].each do |p|
+        [['fmt','tex']].each do |f|
+            [[texformatpath,'global'],[savedpath,'current']].each do |p|
+                begin
+                    Dir.chdir(p[0])
+                rescue
+                else
+                    Dir.glob("*.#{f[0]}").each do |file|
+                        report("#{f[1]}: #{filestate(file)} > #{File.expand_path(file)} (#{File.size(file)})")
+                    end
+                end
+            end
+        end
+        # to be sure, go back to current path
+        begin
+            Dir.chdir(savedpath)
+        rescue
+        end
+        # finalize
+        cleanup
+        report("")
+        reportruntime
+    end
+
+    def checkcontext
+
+        # todo : report texmf.cnf en problems
+
+        # basics
+        report("current distribution: #{Kpse.distribution}")
+        report("context source date: #{contextversion}")
+        formatpaths = Kpse.formatpaths
+        globpattern = "**/{#{formatpaths.join(',')}}/*/*.{fmt,efmt,ofmt,xfmt,mem}"
+        report("format path: #{formatpaths.join(' ')}")
+        # utilities
+        report('start of analysis')
+        results = Array.new
+        # ['texexec','texutil','ctxtools'].each do |program|
+        ['texexec'].each do |program|
+            result = `texmfstart #{program} --help`
+            result.sub!(/.*?(#{program}[^\n]+)\n.*/mi) do $1 end
+            results.push("#{result}")
+        end
+        # formats
+        cleanuptemprunfiles
+        if formats = Dir.glob(globpattern) then
+            formats.sort.each do |name|
+                cleanuptemprunfiles
+                if f = open(tempfilename('tex'),'w') then
+                    # kind of aleph-run-out-of-par safe
+                    f << "\\starttext\n"
+                    f << "  \\relax test \\relax\n"
+                    f << "\\stoptext\n"
+                    f << "\\endinput\n"
+                    f.close
+                    if FileTest.file?(tempfilename('tex')) then
+                        format = File.basename(name)
+                        engine = if name =~ /(pdftex|aleph|xetex)[\/\\]#{format}/ then $1 else '' end
+                        if engine.empty? then
+                            engineflag = ""
+                        else
+                            engineflag = "--engine=#{$1}"
+                        end
+                        case format
+                            when /cont\-([a-z]+)/ then
+                                interface = $1.sub(/cont\-/,'')
+                                results.push('')
+                                results.push("testing interface #{interface}")
+                                flags = ['--noctx','--process','--batch','--once',"--interface=#{interface}",engineflag]
+                                # result = Kpse.pipescript('texexec',tempfilename,flags)
+                                result = runtexexec([tempfilename], flags, 1)
+                                if FileTest.file?("#{@@temprunfile}.log") then
+                                    logdata = IO.read("#{@@temprunfile}.log")
+                                    if logdata =~ /^\s*This is (.*?)[\s\,]+(.*?)$/moi then
+                                        if validtexengine($1.downcase) then
+                                            results.push("#{$1} #{$2.gsub(/\(format.*$/,'')}".strip)
+                                        end
+                                    end
+                                    if logdata =~ /^\s*(ConTeXt)\s+(.*int:\s+[a-z]+.*?)\s*$/moi then
+                                        results.push("#{$1} #{$2}".gsub(/\s+/,' ').strip)
+                                    end
+                                else
+                                    results.push("format #{format} does not work")
+                                end
+                            when /metafun/ then
+                                # todo
+                            when /mptopdf/ then
+                                # todo
+                        end
+                    else
+                        results.push("error in creating #{tempfilename('tex')}")
+                    end
+                end
+                cleanuptemprunfiles
+            end
+        end
+        report('end of analysis')
+        report
+        results.each do |line|
+            report(line)
+        end
+        cleanuptemprunfiles
+
+    end
+
+    private
+
+    def makeuserfile
+        language = getvariable('language')
+        mainlanguage = getvariable('mainlanguage')
+        bodyfont = getvariable('bodyfont')
+        if f = openedfile("cont-fmt.tex") then
+            f << "\\unprotect\n"
+            case language
+                when 'all' then
+                    f << "\\preloadallpatterns\n"
+                when '' then
+                    f << "% no language presets\n"
+                when 'standard'
+                    f << "% using defaults\n"
+                else
+                    languages = language.split(',')
+                    languages.each do |l|
+                        f << "\\installlanguage[\\s!#{l}][\\c!state=\\v!start]\n"
+                    end
+                    mainlanguage = languages.first
+            end
+            unless mainlanguage == 'standard' then
+                f << "\\setupcurrentlanguage[\\s!#{mainlanguage}]\n";
+            end
+            unless bodyfont == 'standard' then
+                # ~ will become obsolete when lmr is used
+                f << "\\definetypescriptsynonym[cmr][#{bodyfont}]"
+                # ~ is already obsolete for some years now
+                f << "\\definefilesynonym[font-cmr][font-#{bodyfont}]\n"
+            end
+            f << "\\protect\n"
+            f << "\\endinput\n"
+            f.close
+        end
+    end
+
+    def makeresponsefile
+        interface = getvariable('interface')
+        if f = openedfile("mult-def.tex") then
+            case interface
+                when 'standard' then
+                    f << "% using default response interface"
+                else
+                    f << "\\def\\currentresponses\{#{interface}\}\n"
+            end
+            f << "\\endinput\n"
+            f.close
+        end
+    end
+
+    private  # will become base/context
+
+    @@preamblekeys = [
+        ['tex','texengine'],
+        ['engine','texengine'],
+        ['program','texengine'],
+      # ['translate','tcxfilter'],
+      # ['tcx','tcxfilter'],
+        ['output','backend'],
+        ['mode','mode'],
+        ['ctx','ctxfile'],
+        ['version','contextversion'],
+        ['format','texformats'],
+        ['interface','texformats'],
+    ]
+
+    @@re_utf_bom = /^\357\273\277/o
+
+    def scantexpreamble(filename)
+        begin
+            if FileTest.file?(filename) and tex = File.open(filename,'rb') then
+                bomdone = false
+                while str = tex.gets and str.chomp! do
+                    unless bomdone then
+                        if str.sub!(@@re_utf_bom, '')
+                            report("utf mode forced (bom found)")
+                            setvariable('utfbom',true)
+                        end
+                        bomdone = true
+                    end
+                    if str =~ /^\%\s*(.*)/o then
+                        # we only accept lines with key=value pairs
+                        vars, ok = Hash.new, true
+                        $1.split(/\s+/o).each do |s|
+                            k, v = s.split('=')
+                            if k && v then
+                                vars[k] = v
+                            else
+                                ok = false
+                                break
+                            end
+                        end
+                        if ok then
+                            # we have a valid line
+
+                            @@preamblekeys.each do |v|
+                                setvariable(v[1],vars[v[0]]) if vars.key?(v[0]) && vars[v[0]]
+                            end
+
+if getvariable('given.backend') == "standard" or getvariable('given.backend') == "" then
+    setvariable('backend',@@backends[getvariable('texengine')] || 'standard')
+end
+                            break
+                        end
+                    else
+                        break
+                    end
+                end
+                tex.close
+            end
+        rescue
+            # well, let's not worry too much
+        end
+    end
+
+    def scantexcontent(filename)
+        if FileTest.file?(filename) and tex = File.open(filename,'rb') then
+            while str = tex.gets do
+                case str.chomp
+                    when /^\%/o then
+                        # next
+                #   when /\\(starttekst|stoptekst|startonderdeel|startdocument|startoverzicht)/o then
+                    when /\\(starttekst|stoptekst|startonderdeel|startoverzicht)/o then
+                        setvariable('texformats','nl') ; break
+                    when /\\(stelle|verwende|umgebung|benutze)/o then
+                        setvariable('texformats','de') ; break
+                    when /\\(stel|gebruik|omgeving)/o then
+                        setvariable('texformats','nl') ; break
+                    when /\\(use|setup|environment)/o then
+                        setvariable('texformats','en') ; break
+                    when /\\(usa|imposta|ambiente)/o then
+                        setvariable('texformats','it') ; break
+                    when /(height|width|style)=/o then
+                        setvariable('texformats','en') ; break
+                    when /(hoehe|breite|schrift)=/o then
+                        setvariable('texformats','de') ; break
+                    when /(hoogte|breedte|letter)=/o then
+                        setvariable('texformats','nl') ; break
+                    when /(altezza|ampiezza|stile)=/o then
+                        setvariable('texformats','it') ; break
+                    when /externfiguur/o then
+                        setvariable('texformats','nl') ; break
+                    when /externalfigure/o then
+                        setvariable('texformats','en') ; break
+                    when /externeabbildung/o then
+                        setvariable('texformats','de') ; break
+                    when /figuraesterna/o then
+                        setvariable('texformats','it') ; break
+                end
+            end
+            tex.close
+        end
+
+    end
+
+    private # will become base/context
+
+    def pushresult(filename,resultname)
+        fname = File.unsuffixed(filename)
+        rname = File.unsuffixed(resultname)
+        if ! rname.empty? && (rname != fname) then
+            report("outputfile #{rname}")
+            ['tuo','tuc','log','dvi','pdf'].each do |s|
+                File.silentrename(File.suffixed(fname,s),File.suffixed('texexec',s))
+            end
+            ['tuo','tuc'].each do |s|
+                File.silentrename(File.suffixed(rname,s),File.suffixed(fname,s)) if FileTest.file?(File.suffixed(rname,s))
+            end
+        end
+    end
+
+    def popresult(filename,resultname)
+        fname = File.unsuffixed(filename)
+        rname = File.unsuffixed(resultname)
+        if ! rname.empty? && (rname != fname) then
+            report("renaming #{fname} to #{rname}")
+            ['tuo','tuc','log','dvi','pdf'].each do |s|
+                File.silentrename(File.suffixed(fname,s),File.suffixed(rname,s))
+            end
+            report("restoring #{fname}")
+            unless $fname == 'texexec' then
+                ['tuo','tuc','log','dvi','pdf'].each do |s|
+                    File.silentrename(File.suffixed('texexec',s),File.suffixed(fname,s))
+                end
+            end
+        end
+    end
+
+    def makestubfile(rawname,rawbase,forcexml=false)
+        if tmp = openedfile(File.suffixed(rawbase,'run')) then
+            tmp << "\\starttext\n"
+            if forcexml then
+                # tmp << checkxmlfile(rawname)
+                if getvariable('mkiv') then
+                    tmp << "\\xmlprocess{\\xmldocument}{#{rawname}}{}\n"
+                else
+                    tmp << "\\processXMLfilegrouped{#{rawname}}\n"
+                end
+            else
+                tmp << "\\processfile{#{rawname}}\n"
+            end
+            tmp << "\\stoptext\n"
+            tmp.close
+            return "run"
+        else
+            return File.splitname(rawname)[1]
+        end
+    end
+
+    # def checkxmlfile(rawname)
+        # tmp = ''
+        # if FileTest.file?(rawname) && (xml = File.open(rawname)) then
+            # xml.each do |line|
+                # case line
+                    # when /<\?context\-directive\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*?)\s*\?>/o then
+                        # category, key, value, rest = $1, $2, $3, $4
+                        # case category
+                            # when 'job' then
+                                # case key
+                                    # when 'control' then
+                                        # setvariable(value,if rest.empty? then true else rest end)
+                                    # when 'mode', 'modes' then
+                                        # tmp << "\\enablemode[#{value}]\n"
+                                    # when 'stylefile', 'environment' then
+                                        # tmp << "\\environment #{value}\n"
+                                    # when 'module' then
+                                        # tmp << "\\usemodule[#{value}]\n"
+                                    # when 'interface' then
+                                        # contextinterface = value
+                                    # when 'ctxfile' then
+                                        # setvariable('ctxfile', value)
+                                        # report("using source driven ctxfile #{value}")
+                                # end
+                        # end
+                    # when /<[a-z]+/io then # beware of order, first pi test
+                        # break
+                # end
+            # end
+            # xml.close
+        # end
+        # return tmp
+    # end
+
+    def extendvariable(name,value)
+        set = getvariable(name).split(',')
+        set << value
+        str = set.uniq.join(',')
+        setvariable(name,str)
+    end
+
+    def checkxmlfile(rawname)
+        if FileTest.file?(rawname) && (xml = File.open(rawname,'rb')) then
+            xml.each do |line|
+                case line
+                    when /<\?context\-directive\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*?)\s*\?>/o then
+                        category, key, value, rest = $1, $2, $3, $4
+                        case category
+                            when 'job' then
+                                case key
+                                    when 'control' then
+                                        setvariable(value,if rest.empty? then true else rest end)
+                                    when /^(mode)(s|)$/ then
+                                        extendvariable('modes',value)
+                                    when /^(stylefile|environment)(s|)$/ then
+                                        extendvariable('environments',value)
+                                    when /^(use|)(module)(s|)$/ then
+                                        extendvariable('usemodules',value)
+                                    when /^(filter)(s|)$/ then
+                                        extendvariable('filters',value)
+                                    when 'interface' then
+                                        contextinterface = value
+                                    when 'ctxfile' then
+                                        setvariable('ctxfile', value)
+                                        report("using source driven ctxfile #{value}")
+                                end
+                        end
+                    when /<[a-z]+/io then # beware of order, first pi test
+                        break
+                end
+            end
+            xml.close
+        end
+    end
+
+end
+
+class TEX
+
+    def timedrun(delay, &block)
+        delay = delay.to_i rescue 0
+        if delay > 0 then
+            begin
+                report("job started with timeout '#{delay}'")
+                timeout(delay) do
+                    yield block
+                end
+            rescue TimeoutError
+                report("job aborted due to timeout '#{delay}'")
+                setvariable('error','timeout')
+            rescue
+                report("job aborted due to error")
+                setvariable('error','fatal error')
+            else
+                report("job finished within timeout '#{delay}'")
+            end
+        else
+            yield block
+        end
+    end
+
+    def processtex # much to do: mp, xml, runs etc
+        setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
+        getarrayvariable('files').each do |filename|
+            setvariable('filename',filename)
+            report("processing document '#{filename}'")
+            timedrun(getvariable('timeout')) do
+                processfile
+            end
+        end
+        reportruntime
+    end
+
+    def processmptex
+        getarrayvariable('files').each do |filename|
+            setvariable('filename',filename)
+            report("processing graphic '#{filename}'")
+            runtexmp(filename)
+        end
+        reportruntime
+    end
+
+    private
+
+    def load_map_files(filename) # tui basename
+        # c \usedmapfile{=}{lm-texnansi}
+        begin
+            str = ""
+            IO.read(filename).scan(/^c\s+\\usedmapfile\{(.*?)\}\{(.*?)\}\s*$/o) do
+                str << "\\loadmapfile[#{$2}.map]\n"
+            end
+        rescue
+            return ""
+        else
+            return str
+        end
+    end
+
+    public
+
+    def processmpgraphic
+        getarrayvariable('files').each do |filename|
+            setvariable('filename',filename)
+            report("processing graphic '#{filename}'")
+            runtexmp(filename,'',false) # no purge
+            mapspecs = load_map_files(File.suffixed(filename,'temp','tui'))
+            unless getvariable('keep') then
+                # not enough: purge_mpx_files(filename)
+                Dir.glob(File.suffixed(filename,'temp*','*')).each do |fname|
+                    File.delete(fname) unless File.basename(filename) == File.basename(fname)
+                end
+            end
+            begin
+                data = IO.read(File.suffixed(filename,'log'))
+                basename = filename.sub(/\.mp$/, '')
+                if data =~ /output files* written\:\s*(.*)$/moi then
+                    files, number, range, list = $1.split(/\s+/), 0, false, []
+                    files.each do |fname|
+                        if fname =~ /^.*\.(\d+)$/ then
+                            if range then
+                                (number+1 .. $1.to_i).each do |i|
+                                    list << i
+                                end
+                                range = false
+                            else
+                                number = $1.to_i
+                                list << number
+                            end
+                        elsif fname =~ /\.\./ then
+                            range = true
+                        else
+                            range = false
+                            next
+                        end
+                    end
+                    begin
+                        if getvariable('combine') then
+                            fullname = "#{basename}.#{number}"
+                            File.open("texexec.tex",'w') do |f|
+                                f << "\\setupoutput[pdftex]\n"
+                                f << "\\setupcolors[state=start]\n"
+                                f << mapspecs
+                                f << "\\starttext\n"
+                                list.each do |number|
+                                    f << "\\startTEXpage\n"
+                                    f << "\\convertMPtoPDF{#{fullname}}{1}{1}"
+                                    f << "\\stopTEXpage\n"
+                                end
+                                f << "\\stoptext\n"
+                            end
+                            report("converting graphic '#{fullname}'")
+                            runtex("texexec.tex")
+                            pdffile = File.suffixed(basename,'pdf')
+                            File.silentrename("texexec.pdf",pdffile)
+                            report ("#{basename}.* converted to #{pdffile}")
+                        else
+                            list.each do |number|
+                                begin
+                                    fullname = "#{basename}.#{number}"
+                                    File.open("texexec.tex",'w') do |f|
+                                        f << "\\setupoutput[pdftex]\n"
+                                        f << "\\setupcolors[state=start]\n"
+                                        f << mapspecs
+                                        f << "\\starttext\n"
+                                        f << "\\startTEXpage\n"
+                                        f << "\\convertMPtoPDF{#{fullname}}{1}{1}"
+                                        f << "\\stopTEXpage\n"
+                                        f << "\\stoptext\n"
+                                    end
+                                    report("converting graphic '#{fullname}'")
+                                    runtex("texexec.tex")
+                                    if files.length>1 then
+                                        pdffile = File.suffixed(basename,number.to_s,'pdf')
+                                    else
+                                        pdffile = File.suffixed(basename,'pdf')
+                                    end
+                                    File.silentrename("texexec.pdf",pdffile)
+                                    report ("#{fullname} converted to #{pdffile}")
+                                end
+                            end
+                        end
+                    rescue
+                        report ("error when converting #{fullname} (#{$!})")
+                    end
+                end
+            rescue
+                report("error in converting #{filename}")
+            end
+        end
+        reportruntime
+    end
+
+    def processmpstatic
+        if filename = getvariable('filename') then
+            filename += ".mp" unless filename =~ /\..+?$/
+            if FileTest.file?(filename) then
+                begin
+                    data = IO.read(filename)
+                    File.open("texexec.tex",'w') do |f|
+                        f << "\\setupoutput[pdftex]\n"
+                        f << "\\setupcolors[state=start]\n"
+                        data.sub!(/^%mpenvironment\:\s*(.*?)$/moi) do
+                            f << $1
+                            "\n"
+                        end
+                        f << "\\starttext\n"
+                        f << "\\startMPpage\n"
+                        f << data.gsub(/end\.*\s*$/m, '') # a bit of a hack
+                        f << "\\stopMPpage\n"
+                        f << "\\stoptext\n"
+                    end
+                    report("converting static '#{filename}'")
+                    runtex("texexec.tex")
+                    pdffile = File.suffixed(filename,'pdf')
+                    File.silentrename("texexec.pdf",pdffile)
+                    report ("#{filename} converted to #{pdffile}")
+                rescue
+                    report("error in converting #{filename} (#{$!}")
+                end
+            end
+        end
+        reportruntime
+    end
+
+    def processmpxtex
+        getarrayvariable('files').each do |filename|
+            setvariable('filename',filename)
+            report("processing text of graphic '#{filename}'")
+            processmpx(filename,false,true,true)
+        end
+        reportruntime
+    end
+
+    def deleteoptionfile(rawname)
+        ['top','top.keep'].each do |suffix|
+            begin
+                File.delete(File.suffixed(rawname,suffix))
+            rescue
+            end
+        end
+    end
+
+    def makeoptionfile(rawname, jobname, jobsuffix, finalrun, fastdisabled, kindofrun, currentrun=1)
+        begin
+            # jobsuffix = orisuffix
+            if topname = File.suffixed(rawname,'top') and opt = File.open(topname,'w') then
+                report("writing option file #{topname}")
+                # local handies
+                opt << "\% #{topname}\n"
+                opt << "\\unprotect\n"
+                #
+                # feedback and basic control
+                #
+                if getvariable('batchmode') then
+                    opt << "\\batchmode\n"
+                end
+                if getvariable('nonstopmode') then
+                    opt << "\\nonstopmode\n"
+                end
+                if getvariable('paranoid') then
+                    opt << "\\def\\maxreadlevel{1}\n"
+                end
+                if getvariable('nomapfiles') then
+                    opt << "\\disablemapfiles\n"
+                end
+                if getvariable('nompmode') || getvariable('nomprun') || getvariable('automprun') then
+                    opt << "\\runMPgraphicsfalse\n"
+                end
+                if getvariable('utfbom') then
+                    opt << "\\enableregime[utf]"
+                end
+                progname = validprogname(['metafun']) # [getvariable('progname'),mpsformat,mpsengine]
+                opt << "\\def\\MPOSTformatswitch\{#{prognameflag(progname)} #{formatflag('mpost')}=\}\n"
+                #
+                # process info
+                #
+                opt << "\\setupsystem[\\c!n=#{kindofrun},\\c!m=#{currentrun}]\n"
+                if (str = File.unixfied(getvariable('modefile'))) && ! str.empty? then
+                    opt << "\\readlocfile{#{str}}{}{}\n"
+                end
+                if (str = File.unixfied(getvariable('result'))) && ! str.empty? then
+                    opt << "\\setupsystem[file=#{str}]\n"
+                elsif (str = getvariable('suffix')) && ! str.empty? then
+                    opt << "\\setupsystem[file=#{jobname}.#{str}]\n"
+                end
+                opt << "\\setupsystem[\\c!method=2]\n" # 1=oldtexexec 2=newtexexec (obsolete)
+                opt << "\\setupsystem[\\c!type=#{Tool.ruby_platform()}]\n"
+                if (str = File.unixfied(getvariable('path'))) && ! str.empty? then
+                    opt << "\\usepath[#{str}]\n" unless str.empty?
+                end
+                if (str = getvariable('mainlanguage').downcase) && ! str.empty? && ! str.standard? then
+                    opt << "\\setuplanguage[#{str}]\n"
+                end
+                if (str = getvariable('arguments')) && ! str.empty? then
+                    opt << "\\setupenv[#{str}]\n"
+                end
+                if (str = getvariable('setuppath')) && ! str.empty? then
+                    opt << "\\setupsystem[\\c!directory=\{#{str}\}]\n"
+                end
+                if (str = getvariable('randomseed')) && ! str.empty? then
+                    report("using randomseed #{str}")
+                    opt << "\\setupsystem[\\c!random=#{str}]\n"
+                end
+                if (str = getvariable('input')) && ! str.empty? then
+                    opt << "\\setupsystem[inputfile=#{str}]\n"
+                else
+                    opt << "\\setupsystem[inputfile=#{rawname}]\n"
+                end
+                #
+                # modes
+                #
+                # we handle both "--mode" and "--modes", else "--mode" is mapped onto "--modefile"
+                if (str = getvariable('modes')) && ! str.empty? then
+                    opt << "\\enablemode[#{str}]\n"
+                end
+                if (str = getvariable('mode')) && ! str.empty? then
+                    opt << "\\enablemode[#{str}]\n"
+                end
+                #
+                # options
+                #
+                opt << "\\startsetups *runtime:options\n"
+                if str = validbackend(getvariable('backend')) then
+                    opt << "\\setupoutput[#{str}]\n"
+                elsif str = validbackend(getvariable('output')) then
+                    opt << "\\setupoutput[#{str}]\n"
+                end
+                if getvariable('color') then
+                    opt << "\\setupcolors[\\c!state=\\v!start]\n"
+                end
+                if (str = getvariable('separation')) && ! str.empty? then
+                    opt << "\\setupcolors[\\c!split=#{str}]\n"
+                end
+                if (str = getvariable('paperformat')) && ! str.empty? && ! str.standard? then
+                    if str =~ /^([a-z]+\d+)([a-z]+\d+)$/io then # A5A4 A4A3 A2A1 ...
+                        opt << "\\setuppapersize[#{$1.upcase}][#{$2.upcase}]\n"
+                    else # ...*...
+                        pf = str.upcase.split(/[x\*]/o)
+                        pf << pf[0] if pf.size == 1
+                        opt << "\\setuppapersize[#{pf[0]}][#{pf[1]}]\n"
+                    end
+                end
+                if (str = getvariable('background')) && ! str.empty? then
+                    opt << "\\defineoverlay[whatever][{\\externalfigure[#{str}][\\c!factor=\\v!max]}]\n"
+                    opt << "\\setupbackgrounds[\\v!page][\\c!background=whatever]\n"
+                end
+                if getvariable('centerpage') then
+                    opt << "\\setuplayout[\\c!location=\\v!middle,\\c!marking=\\v!on]\n"
+                end
+                if getvariable('noarrange') then
+                    opt << "\\setuparranging[\\v!disable]\n"
+                elsif getvariable('arrange') then
+                    arrangement = Array.new
+                    if finalrun then
+                        arrangement << "\\v!doublesided" unless getvariable('noduplex')
+                        case getvariable('printformat')
+                            when ''         then arrangement << "\\v!normal"
+                            when /.*up/oi   then arrangement << ["2UP","\\v!rotated"]
+                            when /.*down/oi then arrangement << ["2DOWN","\\v!rotated"]
+                            when /.*side/oi then arrangement << ["2SIDE","\\v!rotated"]
+                        end
+                    else
+                        arrangement << "\\v!disable"
+                    end
+                    opt << "\\setuparranging[#{arrangement.flatten.join(',')}]\n" if arrangement.size > 0
+                end
+                if (str = getvariable('pages')) && ! str.empty? then
+                    if str.downcase == 'odd' then
+                        opt << "\\chardef\\whichpagetoshipout=1\n"
+                    elsif str.downcase == 'even' then
+                        opt << "\\chardef\\whichpagetoshipout=2\n"
+                    else
+                        pagelist = Array.new
+                        str.split(/\,/).each do |page|
+                            pagerange = page.split(/\D+/o)
+                            if pagerange.size > 1 then
+                                pagerange.first.to_i.upto(pagerange.last.to_i) do |p|
+                                    pagelist << p.to_s
+                                end
+                            else
+                                pagelist << page
+                            end
+                        end
+                        opt << "\\def\\pagestoshipout\{#{pagelist.join(',')}\}\n";
+                    end
+                end
+                opt << "\\stopsetups\n"
+                #
+                # styles and modules
+                #
+                opt << "\\startsetups *runtime:modules\n"
+                begin getvariable('filters'     ).split(',').uniq.each do |f| opt << "\\useXMLfilter[#{f}]\n" end ; rescue ; end
+                begin getvariable('usemodules'  ).split(',').uniq.each do |m| opt << "\\usemodule   [#{m}]\n" end ; rescue ; end
+                begin getvariable('environments').split(',').uniq.each do |e| opt << "\\environment  #{e} \n" end ; rescue ; end
+                opt << "\\stopsetups\n"
+                #
+                opt << "\\protect \\endinput\n"
+                #
+                opt.close
+           else
+                report("unable to write option file #{topname}")
+            end
+        rescue
+            report("fatal error in writing option file #{topname} (#{$!})")
+        end
+    end
+
+    def takeprecautions
+        ENV['MPXCOMAND'] = '0' # else loop
+        if getvariable('paranoid') then
+            ENV['SHELL_ESCAPE'] = ENV['SHELL_ESCAPE'] || 'f'
+            ENV['OPENOUT_ANY']  = ENV['OPENOUT_ANY']  || 'p'
+            ENV['OPENIN_ANY']   = ENV['OPENIN_ANY']   || 'p'
+        elsif getvariable('notparanoid') then
+            ENV['SHELL_ESCAPE'] = ENV['SHELL_ESCAPE'] || 't'
+            ENV['OPENOUT_ANY']  = ENV['OPENOUT_ANY']  || 'a'
+            ENV['OPENIN_ANY']   = ENV['OPENIN_ANY']   || 'a'
+        end
+        if ENV['OPENIN_ANY'] && (ENV['OPENIN_ANY'] == 'p') then # first test redundant
+            setvariable('paranoid', true)
+        end
+        if ENV.key?('SHELL_ESCAPE') && (ENV['SHELL_ESCAPE'] == 'f') then
+            setvariable('automprun',true)
+        end
+        done = false
+        ['TXRESOURCES','MPRESOURCES','MFRESOURCES'].each do |res|
+            [getvariable('runpath'),getvariable('path')].each do |pat|
+                unless pat.empty? then
+                    if ENV.key?(res) then
+                        # ENV[res] = if ENV[res].empty? then pat else pat + ":" + ENV[res] end
+if ENV[res].empty? then
+    ENV[res] = pat
+elsif ENV[res] == pat || ENV[res] =~ /^#{pat}\:/ || ENV[res] =~ /\:#{pat}\:/ then
+    # skip
+else
+    ENV[res] = pat + ":" + ENV[res]
+end
+                    else
+                        ENV[res] = pat
+                    end
+                    report("setting #{res} to #{ENV[res]}") unless done
+                end
+            end
+            done = true
+        end
+    end
+
+    def checktestversion
+        #
+        # one can set TEXMFALPHA and TEXMFBETA for test versions
+        # but keep in mind that the format as well as the test files
+        # then need the --alpha or --beta flag
+        #
+        done, tree = false, ''
+        ['alpha', 'beta'].each do |what|
+            if getvariable(what) then
+                if ENV["TEXMF#{what.upcase}"] then
+                    done, tree = true, ENV["TEXMF#{what.upcase}"]
+                elsif ENV["TEXMFLOCAL"] then
+                    done, tree = true, File.join(File.dirname(ENV['TEXMFLOCAL']), "texmf-#{what}")
+                end
+            end
+            break if done
+        end
+        if done then
+            tree = tree.strip
+            ENV['TEXMFPROJECT'] = tree
+            report("using test tree '#{tree}'")
+            ['MP', 'MF', 'TX'].each do |ctx|
+                ENV['CTXDEV#{ctx}PATH'] = ''
+            end
+            unless (FileTest.file?(File.join(tree,'ls-r')) || FileTest.file?(File.join(tree,'ls-R'))) then
+                report("no ls-r/ls-R file for tree '#{tree}' (run: mktexlsr #{tree})")
+            end
+        end
+        # puts `kpsewhich --expand-path=$TEXMF`
+        # exit
+    end
+
+    def runtex(filename)
+        checktestversion
+        texengine = validtexengine(getvariable('texengine'))
+        texformat = validtexformat(getarrayvariable('texformats').first)
+        report("tex engine: #{texengine}")
+        report("tex format: #{texformat}")
+        if texengine && texformat then
+            fixbackendvars(@@mappaths[texengine])
+            progname = validprogname([getvariable('progname'),texformat,texengine])
+            runcommand([quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),runoptions(texengine),filename,texprocextras(texformat)])
+        else
+            false
+        end
+    end
+
+    def runmp(mpname,mpx=false)
+        checktestversion
+        mpsengine = validmpsengine(getvariable('mpsengine'))
+        mpsformat = validmpsformat(getarrayvariable('mpsformats').first)
+        if mpsengine && mpsformat then
+            ENV["MPXCOMMAND"] = "0" unless mpx
+            progname = validprogname([getvariable('progname'),mpsformat,mpsengine])
+            mpname.gsub!(/\.mp$/,"") # temp bug in mp
+            runcommand([quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),runoptions(mpsengine),mpname,mpsprocextras(mpsformat)])
+            true
+        else
+            false
+        end
+    end
+
+    def runtexmp(filename,filetype='',purge=true)
+        checktestversion
+        mpname = File.suffixed(filename,filetype,'mp')
+        if File.atleast?(mpname,10) then
+            # first run needed
+            File.silentdelete(File.suffixed(mpname,'mpt'))
+            doruntexmp(mpname,nil,true,purge)
+            mpgraphics = checkmpgraphics(mpname)
+            mplabels = checkmplabels(mpname)
+            if mpgraphics || mplabels then
+                # second run needed
+                doruntexmp(mpname,mplabels,true,purge)
+            else
+                # no labels
+            end
+        end
+    end
+
+    def runtexmpjob(filename,filetype='')
+        checktestversion
+        mpname = File.suffixed(filename,filetype,'mp')
+        if File.atleast?(mpname,25) && (data = File.silentread(mpname)) then
+            textranslation = if data =~ /^\%\s+translate.*?\=([\w\d\-]+)/io then $1 else '' end
+            mpjobname = if data =~ /collected graphics of job \"(.+?)\"/io then $1 else '' end
+            if ! mpjobname.empty? and File.unsuffixed(filename) =~ /#{mpjobname}/ then # don't optimize
+                options = Array.new
+                options.push("--mptex")
+                options.push("--nomp")
+                options.push("--mpyforce") if getvariable('forcempy') || getvariable('mpyforce')
+                options.push("--translate=#{textranslation}") unless textranslation.empty?
+                options.push("--batch") if getvariable('batchmode')
+                options.push("--nonstop") if getvariable('nonstopmode')
+                options.push("--output=ps") # options.push("--dvi")
+                options.push("--nobackend")
+                return runtexexec(mpname,options,2)
+            end
+        end
+        return false
+    end
+
+    def runtexutil(filename=[], options=['--ref','--ij','--high'], old=false)
+        [filename].flatten.each do |fname|
+            if old then
+                Kpse.runscript('texutil',fname,options)
+            else
+                begin
+                    logger = Logger.new('TeXUtil')
+                    if tu = TeXUtil::Converter.new(logger) and tu.loaded(fname) then
+                        ok = tu.processed && tu.saved && tu.finalized
+                    end
+                rescue
+                    Kpse.runscript('texutil',fname,options)
+                end
+            end
+        end
+    end
+
+    # 1=tex 2=mptex 3=mpxtex 4=mpgraphic 5=mpstatic
+
+    def runtexexec(filename=[], options=[], mode=nil)
+        begin
+            if mode and job = TEX.new(@logger) then
+                options.each do |option|
+                    case option
+                        when /^\-*(.*?)\=(.*)$/o then
+                            job.setvariable($1,$2)
+                        when /^\-*(.*?)$/o then
+                            job.setvariable($1,true)
+                    end
+                end
+                job.setvariable("files",filename)
+                case mode
+                    when 1 then job.processtex
+                    when 2 then job.processmptex
+                    when 3 then job.processmpxtex
+                    when 4 then job.processmpgraphic
+                    when 5 then job.processmpstatic
+                end
+                job.inspect && Kpse.inspect if getvariable('verbose')
+                return true
+            else
+                Kpse.runscript('texexec',filename,options)
+            end
+        rescue
+            Kpse.runscript('texexec',filename,options)
+        end
+    end
+
+    def fixbackendvars(backend)
+        if backend then
+            ENV['backend']     = backend ;
+            ENV['progname']    = backend unless validtexengine(backend)
+            ENV['TEXFONTMAPS'] = ['.',"\$TEXMF/fonts/{data,map}/{#{backend},pdftex,dvips,}//",'./fonts//'].join_path
+            report("fixing backend map path for #{backend}: #{ENV['TEXFONTMAPS']}") if getvariable('verbose')
+        else
+            report("unable to fix backend map path") if getvariable('verbose')
+        end
+    end
+
+    def runbackend(rawname)
+        unless getvariable('nobackend') then
+            case validbackend(getvariable('backend'))
+                when 'dvipdfmx' then
+                    fixbackendvars('dvipdfm')
+                    runcommand("dvipdfmx -d 4 -V 5 #{File.unsuffixed(rawname)}")
+                when 'xetex'    then
+                    # xetex now runs its own backend
+                    xdvfile = File.suffixed(rawname,'xdv')
+                    if FileTest.file?(xdvfile) then
+                        fixbackendvars('dvipdfm')
+                        runcommand("xdvipdfmx -q -d 4 -V 5 -E #{xdvfile}")
+                    end
+                when 'xdv2pdf' then
+                    xdvfile = File.suffixed(rawname,'xdv')
+                    if FileTest.file?(xdvfile) then
+                        fixbackendvars('xdv2pdf')
+                        runcommand("xdv2pdf #{xdvfile}")
+                    end
+                when 'dvips' then
+                    fixbackendvars('dvips')
+                    mapfiles = ''
+                    begin
+                        if tuifile = File.suffixed(rawname,'tui') and FileTest.file?(tuifile) then
+                            IO.read(tuifile).scan(/^c \\usedmapfile\{.\}\{(.*?)\}\s*$/o) do
+                                mapfiles += "-u +#{$1} " ;
+                            end
+                        end
+                    rescue
+                        mapfiles = ''
+                    end
+                    runcommand("dvips #{mapfiles} #{File.unsuffixed(rawname)}")
+                when 'pdftex'   then
+                    # no need for postprocessing
+                else
+                    report("no postprocessing needed")
+            end
+        end
+    end
+
+    def processfile
+
+        takeprecautions
+        report("using search method '#{Kpse.searchmethod}'") if getvariable('verbose')
+
+        rawname    = getvariable('filename')
+        jobname    = getvariable('filename')
+
+        if getvariable('autopath') then
+            jobname = File.basename(jobname)
+            inppath = File.dirname(jobname)
+        else
+            inppath = ''
+        end
+
+        jobname, jobsuffix = File.splitname(jobname,'tex')
+
+        jobname = File.unixfied(jobname)
+        inppath = File.unixfied(inppath)
+
+        orisuffix = jobsuffix # still needed ?
+
+        if jobsuffix =~ /^(htm|html|xhtml|xml|fo|fox|rlg|exa)$/io then
+            setvariable('forcexml',true)
+        end
+
+        dummyfile = false
+
+        # fuzzy code snippet: (we kunnen kpse: prefix gebruiken)
+
+        unless FileTest.file?(File.suffixed(jobname,jobsuffix)) then
+            if FileTest.file?(rawname + '.tex') then
+                jobname = rawname.dup
+                jobsuffix  = 'tex'
+            end
+        end
+
+        # we can have funny names, like 2005.10.10 (given without suffix)
+
+        rawname = jobname + '.' + jobsuffix
+        rawpath = File.dirname(rawname)
+        rawbase = File.basename(rawname)
+
+        unless FileTest.file?(rawname) then
+            inppath.split(',').each do |ip|
+                break if dummyfile = FileTest.file?(File.join(ip,rawname))
+            end
+        end
+
+        forcexml   = getvariable('forcexml')
+
+        if dummyfile || forcexml then # after ctx?
+            jobsuffix = makestubfile(rawname,rawbase,forcexml)
+            checkxmlfile(rawname)
+        end
+
+        # preprocess files
+
+        unless getvariable('noctx') then
+            ctx = CtxRunner.new(rawname, at logger)
+            if pth = getvariable('path') then
+                pth.split(',').each do |p|
+                    ctx.register_path(p)
+                end
+            end
+            if getvariable('ctxfile').empty? then
+                if rawname == rawbase then
+                    ctx.manipulate(File.suffixed(rawname,'ctx'),'jobname.ctx')
+                else
+                    ctx.manipulate(File.suffixed(rawname,'ctx'),File.join(rawpath,'jobname.ctx'))
+                end
+            else
+                ctx.manipulate(File.suffixed(getvariable('ctxfile'),'ctx'))
+            end
+            ctx.savelog(File.suffixed(rawbase,'ctl'))
+
+            envs  = ctx.environments
+            mods  = ctx.modules
+            flags = ctx.flags
+            mdes  = ctx.modes
+
+            flags.each do |f|
+                f.sub!(/^\-+/,'')
+                if f =~ /^(.*?)=(.*)$/ then
+                    setvariable($1,$2)
+                else
+                    setvariable(f,true)
+                end
+            end
+
+            report("using flags #{flags.join(' ')}") if flags.size > 0
+
+            # merge environment and module specs
+
+            envs << getvariable('environments') unless getvariable('environments').empty?
+            mods << getvariable('usemodules')   unless getvariable('usemodules')  .empty?
+            mdes << getvariable('modes')        unless getvariable('modes')       .empty?
+
+            envs = envs.uniq.join(',')
+            mods = mods.uniq.join(',')
+            mdes = mdes.uniq.join(',')
+
+            report("using search method '#{Kpse.searchmethod}'") if getvariable('verbose')
+
+            report("using environments #{envs}") if envs.length > 0
+            report("using modules #{mods}")      if mods.length > 0
+            report("using modes #{mdes}")        if mdes.length > 0
+
+            setvariable('environments', envs)
+            setvariable('usemodules',   mods)
+            setvariable('modes',        mdes)
+        end
+
+        # end of preprocessing and merging
+
+        setvariable('nomprun',true) if orisuffix == 'mpx' # else cylic run
+        PDFview.setmethod('xpdf') if getvariable('xpdf')
+        PDFview.closeall if getvariable('autopdf')
+
+        runonce    = getvariable('once')
+        finalrun   = getvariable('final') || (getvariable('arrange') && ! getvariable('noarrange'))
+        suffix     = getvariable('suffix')
+        result     = getvariable('result')
+        globalfile = getvariable('globalfile')
+        forcexml   = getvariable('forcexml') # can be set in ctx file
+
+if dummyfile || forcexml then # after ctx?
+    jobsuffix = makestubfile(rawname,rawbase,forcexml)
+    checkxmlfile(rawname)
+end
+
+        result     = File.unixfied(result)
+
+        if globalfile || FileTest.file?(rawname) then
+
+            if not dummyfile and not globalfile and not forcexml then
+                scantexpreamble(rawname)
+                scantexcontent(rawname) if getvariable('texformats').standard?
+            end
+            result = File.suffixed(rawname,suffix) unless suffix.empty?
+
+            pushresult(rawbase,result)
+
+            method = validtexmethod(validtexformat(getvariable('texformats')))
+
+            report("tex processing method: #{method}")
+
+            case method
+
+                when 'context' then
+                    if getvariable('simplerun') || runonce then
+                        makeoptionfile(rawbase,jobname,orisuffix,true,true,3,1) unless getvariable('nooptionfile')
+                        ok = runtex(if dummyfile || forcexml then rawbase else rawname end)
+                        if ok then
+                            ok = runtexutil(rawbase) if getvariable('texutil') || getvariable('forcetexutil')
+                            runbackend(rawbase)
+                            popresult(rawbase,result)
+                        end
+                        if getvariable('keep') then
+                            ['top','log','run'].each do |suffix|
+                                File.silentrename(File.suffixed(rawbase,suffix),File.suffixed(rawbase,suffix+'.keep'))
+                            end
+                        end
+                    else
+# goto tmp/jobname when present
+                        mprundone, ok, stoprunning = false, true, false
+                        texruns, nofruns = 0, getvariable('runs').to_i
+                        state = FileState.new
+                        ['tub','tuo','tuc'].each do |s|
+                            state.register(File.suffixed(rawbase,s))
+                        end
+                        if getvariable('automprun') then # check this
+                            ['mprun','mpgraph'].each do |s|
+                                state.register(File.suffixed(rawbase,s,'mp'),'randomseed')
+                            end
+                        end
+                        while ! stoprunning && (texruns < nofruns) && ok do
+                            texruns += 1
+                            report("TeX run #{texruns}")
+                            unless getvariable('nooptionfile') then
+                                if texruns == nofruns then
+                                    makeoptionfile(rawbase,jobname,orisuffix,false,false,4,texruns) # last
+                                elsif texruns == 1 then
+                                    makeoptionfile(rawbase,jobname,orisuffix,false,false,1,texruns) # first
+                                else
+                                    makeoptionfile(rawbase,jobname,orisuffix,false,false,2,texruns) # unknown
+                                end
+                            end
+# goto .
+
+                            ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
+
+if getvariable('texengine') == "xetex" then
+    ok = true
+end
+
+############################
+
+# goto tmp/jobname when present
+                            if ok && (nofruns > 1) then
+                                unless getvariable('nompmode') then
+                                    mprundone = runtexmpjob(rawbase, "mpgraph")
+                                    mprundone = runtexmpjob(rawbase, "mprun")
+                                end
+                                ok = runtexutil(rawbase)
+                                state.update
+                                stoprunning = state.stable?
+                            end
+                        end
+                        if not ok then
+                            setvariable('error','error in tex file')
+                        end
+                        if (nofruns == 1) && getvariable('texutil') then
+                            ok = runtexutil(rawbase)
+                        end
+                        if ok && finalrun && (nofruns > 1) then
+                            makeoptionfile(rawbase,jobname,orisuffix,true,finalrun,4,texruns) unless getvariable('nooptionfile')
+                            report("final TeX run #{texruns}")
+# goto .
+                            ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
+# goto tmp/jobname when present
+                        end
+                        if getvariable('keep') then
+                            ['top','log','run'].each do |suffix|
+                                File.silentrename(File.suffixed(rawbase,suffix),File.suffixed(rawbase,suffix+'.keep'))
+                            end
+                        else
+                            File.silentrename(File.suffixed(rawbase,'top'),File.suffixed(rawbase,'tmp'))
+                        end
+                        # ['tmp','top','log'].each do |s| # previous tuo file / runtime option file / log file
+                             # File.silentdelete(File.suffixed(rawbase,s))
+                        # end
+                        if ok then
+# goto .
+                            runbackend(rawbase)
+                            popresult(rawbase,result)
+# goto tmp/jobname when present
+# skip next
+                        end
+                        if true then # autopurge
+                            begin
+                                File.open(File.suffixed(rawbase, 'tuo'),'rb') do |f|
+                                    ok = 0
+                                    f.each do |line|
+                                        case ok
+                                            when 1 then
+                                                # next line is empty
+                                                ok = 2
+                                            when 2 then
+                                                if line =~ /^\%\s+\>\s+(.*?)\s+(\d+)/moi then
+                                                    filename, n = $1, $2
+                                                    done = File.delete(filename) rescue false
+                                                    if done && getvariable('verbose') then
+                                                        report("deleting #{filename} (#{n} times used)")
+                                                    end
+                                                else
+                                                    break
+                                                end
+                                            else
+                                                if line =~ /^\%\s+temporary files\:\s+(\d+)/moi then
+                                                    if $1.to_i == 0 then
+                                                        break
+                                                    else
+                                                        ok = 1
+                                                    end
+                                                end
+                                        end
+                                    end
+                                end
+                            rescue
+                                # report("fatal error #{$!}")
+                            end
+                        end
+                    end
+
+                    Kpse.runscript('ctxtools',rawbase,'--purge')       if getvariable('purge')
+                    Kpse.runscript('ctxtools',rawbase,'--purge --all') if getvariable('purgeall')
+
+                    # runcommand('mtxrun','--script','ctxtools',rawbase,'--purge')       if getvariable('purge')
+                    # runcommand('mtxrun','--script','ctxtools',rawbase,'--purge --all') if getvariable('purgeall')
+
+                when 'latex' then
+
+                    ok = runtex(rawname)
+
+                else
+
+                    ok = runtex(rawname)
+
+            end
+
+            if (dummyfile or forcexml) and FileTest.file?(rawbase) then
+                begin
+                    File.delete(File.suffixed(rawbase,'run'))
+                rescue
+                    report("unable to delete stub file")
+                end
+            end
+
+            if ok and getvariable('autopdf') then
+                PDFview.open(File.suffixed(if result.empty? then rawbase else result end,'pdf'))
+            end
+
+        else
+            report("nothing to process")
+        end
+
+    end
+
+    # The labels are collected in the mergebe hash. Here we merge the relevant labels
+    # into beginfig/endfig. We could as well do this in metafun itself. Maybe some
+    # day ... (it may cost a bit of string space but that is cheap nowadays).
+
+    def doruntexmp(mpname,mergebe=nil,context=true,purge=true)
+        texfound = false
+        mpname = File.suffixed(mpname,'mp')
+        mpcopy = File.suffixed(mpname,'mp.copy')
+        mpkeep = File.suffixed(mpname,'mp.keep')
+        setvariable('mp.file',mpname)
+        setvariable('mp.line','')
+        setvariable('mp.error','')
+        if mpdata = File.silentread(mpname) then
+        #   mpdata.gsub!(/^\%.*\n/o,'')
+            File.silentrename(mpname,mpcopy)
+            texfound = mergebe || (mpdata =~ /btex .*? etex/mo)
+            if mp = openedfile(mpname) then
+                if mergebe then
+                    mpdata.gsub!(/beginfig\s*\((\d+)\)\s*\;(.+?)endfig\s*\;/mo) do
+                        n, str = $1, $2
+                        if str =~ /^(.*?)(verbatimtex.*?etex)\s*\;(.*)$/mo then
+                            "beginfig(#{n})\;\n#{$1}#{$2}\;\n#{mergebe[n]}\n#{$3}\;endfig\;\n"
+                        else
+                            "beginfig(#{n})\;\n#{mergebe[n]}\n#{str}\;endfig\;\n"
+                        end
+                    end
+                    unless mpdata =~ /beginfig\s*\(\s*0\s*\)/o then
+                        mp << mergebe['0'] if mergebe.key?('0')
+                    end
+                end
+        #       mp << MPTools::splitmplines(mpdata)
+                mp << mpdata
+                mp << "\n"
+        #        mp << "end"
+        #        mp << "\n"
+                mp.close
+            end
+            processmpx(mpname,true,true,purge) if texfound
+            if getvariable('batchmode') then
+                options = ' --interaction=batch'
+            elsif getvariable('nonstopmode') then
+                options = ' --interaction=nonstop'
+            else
+                options = ''
+            end
+            # todo plain|mpost|metafun
+            begin
+                ok = runmp(mpname)
+            rescue
+            end
+            if f = File.silentopen(File.suffixed(mpname,'log')) then
+                while str = f.gets do
+                    if str =~ /^l\.(\d+)\s(.*?)\n/o then
+                        setvariable('mp.line',$1)
+                        setvariable('mp.error',$2)
+                        break
+                    end
+                end
+                f.close
+            end
+            File.silentrename(mpname, mpkeep)
+            File.silentrename(mpcopy, mpname)
+        end
+    end
+
+    # todo: use internal mptotext function and/or turn all btex/etex into textexts
+
+    def processmpx(mpname,force=false,context=true,purge=true)
+        unless force then
+            mpname = File.suffixed(mpname,'mp')
+            if File.atleast?(mpname,10) && (data = File.silentread(mpname)) then
+                if data =~ /(btex|etex|verbatimtex|textext)/o then
+                    force = true
+                end
+            end
+        end
+        if force then
+            begin
+                mptex = File.suffixed(mpname,'temp','tex')
+                mpdvi = File.suffixed(mpname,'temp','dvi')
+                mplog = File.suffixed(mpname,'temp','log')
+                mpmpx = File.suffixed(mpname,'mpx')
+                File.silentdelete(mptex)
+                if true then
+                    report("using internal mptotex converter")
+                    ok = MPTools::mptotex(mpname,mptex,'context')
+                else
+                    command = "mpto #{mpname} > #{mptex}"
+                    report(command) if getvariable('verbose')
+                    ok = system(command)
+                end
+                # not "ok && ..." because of potential problem with return code and redirect (>)
+                if FileTest.file?(mptex) && File.appended(mptex, "\\end\n") then
+                    # to be replaced by runtexexec([filenames],options,1)
+                    if localjob = TEX.new(@logger) then
+                        localjob.setvariable('files',mptex)
+                        localjob.setvariable('backend','dvips')
+                        localjob.setvariable('engine',getvariable('engine')) unless getvariable('engine').empty?
+                        localjob.setvariable('once',true)
+                        localjob.setvariable('nobackend',true)
+                        if context then
+                            localjob.setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
+                        elsif getvariable('interface').empty? then
+                            localjob.setvariable('texformats',['plain'])
+                        else
+                            localjob.setvariable('texformats',[getvariable('interface')])
+                        end
+                        localjob.processtex
+                        ok = true # todo
+                    else
+                        ok = false
+                    end
+                    # so far
+                    command = "dvitomp #{mpdvi} #{mpmpx}"
+                    report(command) if getvariable('verbose')
+                    ok = ok && FileTest.file?(mpdvi) && system(command)
+                    purge_mpx_files(mpname) if purge
+                end
+            rescue
+                # error in processing mpx file
+            end
+        end
+    end
+
+    def purge_mpx_files(mpname)
+        unless getvariable('keep') then
+            ['tex', 'log', 'tui', 'tuo', 'tuc', 'top'].each do |suffix|
+                File.silentdelete(File.suffixed(mpname,'temp',suffix))
+            end
+        end
+    end
+
+    def checkmpgraphics(mpname)
+        # in practice the checksums will differ because of multiple instances
+        # ok, we could save the mpy/mpo files by number, but not now
+        mpoptions = ''
+        if getvariable('makempy') then
+            mpoptions += " --makempy "
+        end
+        mponame = File.suffixed(mpname,'mpo')
+        mpyname = File.suffixed(mpname,'mpy')
+        pdfname = File.suffixed(mpname,'pdf')
+        tmpname = File.suffixed(mpname,'tmp')
+        if getvariable('mpyforce') || getvariable('forcempy') then
+            mpoptions += " --force "
+        else
+            return false unless File.atleast?(mponame,32)
+            mpochecksum = FileState.new.checksum(mponame)
+            return false if mpochecksum.empty?
+            # where does the checksum get into the file?
+            # maybe let texexec do it?
+            # solution: add one if not present or update when different
+            begin
+                mpydata = IO.read(mpyname)
+                if mpydata then
+                    if mpydata =~ /^\%\s*mpochecksum\s*\:\s*([A-Z0-9]+)$/mo then
+                        checksum = $1
+                        if mpochecksum == checksum then
+                            return false
+                        end
+                    end
+                end
+            rescue
+                # no file
+            end
+        end
+        # return Kpse.runscript('makempy',mpname)
+        # only pdftex
+        flags = ['--noctx','--process','--batch','--once']
+        result = runtexexec([mponame], flags, 1)
+        runcommand(["pstoedit","-ssp -dt -f mpost", pdfname,tmpname])
+        tmpdata = IO.read(tmpname)
+        if tmpdata then
+            if mpy = openedfile(mpyname) then
+                mpy << "% mpochecksum: #{mpochecksum}\n"
+                tmpdata.scan(/beginfig(.*?)endfig/mo) do |s|
+                    mpy << "begingraphictextfig#{s}endgraphictextfig\n"
+                end
+                mpy.close()
+            end
+        end
+        File.silentdelete(tmpname)
+        File.silentdelete(pdfname)
+        return true
+    end
+
+    def checkmplabels(mpname)
+        mpname = File.suffixed(mpname,'mpt')
+        if File.atleast?(mpname,10) && (mp = File.silentopen(mpname)) then
+            labels = Hash.new
+            while str = mp.gets do
+                t = if str =~ /^%\s*setup\s*:\s*(.*)$/o then $1 else '' end
+                if str =~ /^%\s*figure\s*(\d+)\s*:\s*(.*)$/o then
+                    labels[$1] = labels[$1] || ''
+                    unless t.empty? then
+                        labels[$1] += "#{t}\n"
+                        t = ''
+                    end
+                    labels[$1] += "#{$2}\n"
+                end
+            end
+            mp.close
+            if labels.size>0 then
+                return labels
+            else
+                return nil
+            end
+        end
+        return nil
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/tex.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/texutil.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/texutil.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/texutil.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,1097 @@
+require "base/file"
+require "base/logger"
+
+class String
+
+    # real dirty, but inspect does a pretty good escaping but
+    # unfortunately puts quotes around the string so we need
+    # to strip these
+
+    # def escaped
+    #     self.inspect[1,self.inspect.size-2]
+    # end
+
+    def escaped
+        str = self.inspect ; str[1,str.size-2]
+    end
+
+    def splitdata
+        if self =~ /^\s*(.*?)\s*\{(.*)\}\s*$/o then
+            first, second = $1, $2
+            if first.empty? then
+                [second.split(/\} \{/o)].flatten
+            else
+                [first.split(/\s+/o)] + [second.split(/\} \{/o)]
+            end
+        else
+            []
+        end
+    end
+
+end
+
+class Logger
+    def banner(str)
+        report(str)
+        return "%\n% #{str}\n%\n"
+    end
+end
+
+class TeXUtil
+
+    class Plugin
+
+        # we need to reset module data for each run; persistent data is
+        # possible, just don't reinitialize the data structures that need
+        # to be persistent; we reset afterwards becausethen we know what
+        # plugins are defined
+
+        def initialize(logger)
+            @plugins = Array.new
+            @logger = logger
+        end
+
+        def report(str)
+            @logger.report("fatal error in plugin (#{str}): #{$!}")
+            puts("\n")
+            $@.each do |line|
+                puts("  #{line}")
+            end
+            puts("\n")
+        end
+
+        def reset(name)
+            if @plugins.include?(name) then
+                begin
+                    eval("#{name}").reset(@logger)
+                rescue Exception
+                    report("resetting")
+                end
+            else
+               @logger.report("no plugin #{name}")
+            end
+        end
+
+        def resets
+            @plugins.each do |p|
+                reset(p)
+            end
+        end
+
+        def register(name, file=nil) # maybe also priority
+            if file then
+                begin
+                    require("#{file.downcase.sub(/\.rb$/,'')}.rb")
+                rescue Exception
+                    @logger.report("no plugin file #{file} for #{name}")
+                else
+                    @plugins.push(name)
+                end
+            else
+                @plugins.push(name)
+            end
+            return self
+        end
+
+        def reader(name, data=[])
+            if @plugins.include?(name) then
+                begin
+                    eval("#{name}").reader(@logger,data.flatten)
+                rescue Exception
+                    report("reading")
+                end
+            else
+               @logger.report("no plugin #{name}")
+            end
+        end
+
+        def readers(data=[])
+            @plugins.each do |p|
+                reader(p,data.flatten)
+            end
+        end
+
+        def writers(handle)
+            @plugins.each do |p|
+                begin
+                    eval("#{p}").writer(@logger,handle)
+                rescue Exception
+                    report("writing")
+                end
+            end
+        end
+
+        def processors
+            @plugins.each do |p|
+                begin
+                    eval("#{p}").processor(@logger)
+                rescue Exception
+                    report("processing")
+                end
+            end
+        end
+
+        def finalizers
+            @plugins.each do |p|
+                begin
+                    eval("#{p}").finalizer(@logger)
+                rescue Exception
+                    report("finalizing")
+                end
+            end
+        end
+
+    end
+
+    class Sorter
+
+        @@downcase = true
+
+        def initialize(max=12)
+            @rep, @map, @exp, @div = Hash.new, Hash.new, Hash.new, Hash.new
+            @max = max
+            @rexa, @rexb = nil, nil
+        end
+
+        def replacer(from,to='') # and expand
+            @max = [@max,to.length+1].max if to
+            @rep[from.escaped] = to || ''
+        end
+
+        # sorter.reducer('ch', 'c')
+        # sorter.reducer('ij', 'y')
+
+        def reducer(from,to='')
+            @max = [@max,to.length+1].max if to
+            @map[from] = to || ''
+        end
+
+        # sorter.expander('aeligature', 'ae')
+        # sorter.expander('ijligature', 'y')
+
+        def expander(from,to=nil)
+            to = converted(to) # not from !!!
+            @max = [@max,to.length+1].max if to
+            @exp[from] = to || from || ''
+        end
+
+        def division(from,to=nil)
+            from, to = converted(from), converted(to)
+            @max = [@max,to.length+1].max if to
+            @div[from] = to || from || ''
+        end
+
+        # shortcut("\\ab\\cd\\e\\f", 'iacute')
+        # shortcut("\\\'\\i", 'iacute')
+        # shortcut("\\\'i", 'iacute')
+        # shortcut("\\\"e", 'ediaeresis')
+        # shortcut("\\\'o", 'oacute')
+
+        def hextoutf(str)
+            str.gsub(/^(0x[A-F\d]+)$/) do
+                [$1.hex()].pack("U")
+            end
+        end
+
+        def shortcut(from,to)
+            from = hextoutf(from)
+            replacer(from,to)
+            expander(to)
+        end
+
+        def prepare
+            if @rep.size > 0 then
+                @rexa = /(#{@rep.keys.join('|')})/ # o
+            else
+                @rexa = nil
+            end
+            if @map.size > 0 then
+                # watch out, order of match matters
+                if @@downcase then
+                    @rexb = /(\\[a-zA-Z]+|#{@map.keys.join('|')}|.)\s*/i # o
+                else
+                    @rexb = /(\\[a-zA-Z]+|#{@map.keys.join('|')}|.)\s*/ # o
+                end
+            else
+                if @@downcase then
+                    @rexb = /(\\[a-zA-Z]+|.)\s*/io
+                else
+                    @rexb = /(\\[a-zA-Z]+|.)\s*/o
+                end
+            end
+            if false then
+                @exp.keys.each do |e|
+                    @exp[e].downcase!
+                end
+            end
+        end
+
+        def replace(str)
+            if @rexa then
+                str.gsub(@rexa) do
+                    @rep[$1.escaped]
+                end
+            else
+                str
+            end
+        end
+
+        def normalize(str)
+            # replace(str).gsub(/ +/,' ')
+            replace(str).gsub(/\s\s+/," \\space")
+        end
+
+        def tokenize(str)
+            if str then
+                str.gsub(/\\strchr\{(.*?)\}/o) do "\\#{$1}" end
+            else
+                ""
+            end
+        end
+
+        def remap(str)
+            s = str.dup
+            if true then # numbers are treated special
+                s.gsub!(/(\d+)/o) do
+                    $1.rjust(10,'a') # rest is b .. k
+                end
+            end
+            if @rexa then
+                s.gsub!(@rexa) do
+                    @rep[$1.escaped]
+                end
+            end
+            if @rexb then
+                s.gsub!(@rexb) do
+                    token = $1.sub(/\\/o, '')
+                    if @@downcase then
+                        token.downcase!
+                    end
+                    if @exp.key?(token) then
+                        @exp[token].ljust(@max,' ')
+                    elsif @map.key?(token) then
+                        @map[token].ljust(@max,' ')
+                    else
+                        ''
+                    end
+                end
+            end
+            s
+        end
+
+        def preset(shortcuts=[],expansions=[],reductions=[],divisions=[],language='')
+            'a'.upto('z') do |c| expander(c) ; division(c) end
+            'A'.upto('Z') do |c| expander(c) ; division(c) end
+            expander('1','b') ; expander('2','c') ; expander('3','e') ; expander('4','f')
+            expander('5','g') ; expander('6','h') ; expander('7','i') ; expander('8','i')
+            expander('9','j') ; expander('0','a') ; expander('-','-') ;
+            shortcuts.each  do |s| shortcut(s[1],s[2]) if s[0] == '' || s[0] == language end
+            expansions.each do |e| expander(e[1],e[2]) if e[0] == '' || e[0] == language end
+            reductions.each do |r|  reducer(r[1],r[2]) if r[0] == '' || r[0] == language end
+            divisions.each  do |d| division(d[1],d[2]) if d[0] == '' || d[0] == language end
+        end
+
+        def simplify(str)
+            s = str.dup
+            # ^^
+            # s.gsub!(/\^\^([a-f0-9][a-f0-9])/o, $1.hex.chr)
+            # \- ||
+            s.gsub!(/(\\\-|\|\|)/o) do '-' end
+            # {}
+            s.gsub!(/\{\}/o) do '' end
+            # <*..> (internal xml entity)
+            s.gsub!(/<\*(.*?)>/o) do $1 end
+            # entities
+            s.gsub!(/\\getXMLentity\s*\{(.*?)\}/o) do $1 end
+            # elements
+            s.gsub!(/\<.*?>/o) do '' end
+            # what to do with xml and utf-8
+            # \"e etc
+            # unknown \cs
+            s.gsub!(/\\[a-zA-Z][a-zA-Z]+\s*\{(.*?)\}/o) do $1 end
+            return s
+        end
+
+        def getdivision(str)
+            @div[str] || str
+        end
+
+        def division?(str)
+            @div.key?(str)
+        end
+
+        private
+
+        def converted(str)
+            if str then
+                # puts str
+                str.gsub(/([\+\-]*\d+)/o) do
+                    n = $1.to_i
+                    if n > 0 then
+                        'z'*n
+                    elsif n < 0 then
+                        '-'*(-n) # '-' precedes 'a'
+                    else
+                        ''
+                    end
+                end
+            else
+                nil
+            end
+        end
+
+    end
+
+    class Plugin
+
+        module MyFiles
+
+            @@files, @@temps = Hash.new, Hash.new
+
+            def MyFiles::reset(logger)
+                @@files, @@temps = Hash.new, Hash.new
+            end
+
+            def MyFiles::reader(logger,data)
+                case data[0]
+                    when 'b', 'e' then
+                        @@files[data[1]] = (@@files[data[1]] ||0) + 1
+                    when 't' then # temporary file
+                        @@temps[data[1]] = (@@temps[data[1]] ||0) + 1
+                end
+            end
+
+            def MyFiles::writer(logger,handle)
+                handle << logger.banner("loaded files: #{@@files.size}")
+                @@files.keys.sort.each do |k|
+                    handle << "% > #{k} #{@@files[k]/2}\n"
+                end
+                handle << logger.banner("temporary files: #{@@temps.size}")
+                @@temps.keys.sort.each do |k|
+                    handle << "% > #{k} #{@@temps[k]}\n"
+                end
+            end
+
+            def MyFiles::processor(logger)
+                @@files.keys.sort.each do |k|
+                    unless (@@files[k] % 2) == 0 then
+                        logger.report("check loading of file '#{k}', begin/end problem")
+                    end
+                end
+                @@temps.keys.sort.each do |k|
+                    # logger.report("temporary file '#{k}' can be deleted")
+                end
+            end
+
+            def MyFiles::finalizer(logger)
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MyCommands
+
+            @@commands = []
+
+            def MyCommands::reset(logger)
+                @@commands = []
+            end
+
+            def MyCommands::reader(logger,data)
+                @@commands.push(data.shift+data.collect do |d| "\{#{d}\}" end.join)
+            end
+
+            def MyCommands::writer(logger,handle)
+                handle << logger.banner("commands: #{@@commands.size}")
+                @@commands.each do |c|
+                    handle << "#{c}%\n"
+                end
+            end
+
+            def MyCommands::processor(logger)
+            end
+
+            def MyCommands::finalizer(logger)
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MyExtras
+
+            @@programs = []
+
+            def MyExtras::reset(logger)
+                @@programs = []
+            end
+
+            def MyExtras::reader(logger,data)
+                case data[0]
+                    when 'p' then
+                        @@programs.push(data[1]) if data[0]
+                end
+            end
+
+            def MyExtras::writer(logger,handle)
+                handle << logger.banner("programs: #{@@programs.size}")
+                @@programs.each_with_index do |cmd, p|
+                    handle << "% #{p+1} (#{cmd})\n"
+                end
+            end
+
+            def MyExtras::processor(logger)
+                @@programs.each do |p|
+                    # cmd = @@programs[p.to_i]
+                    # logger.report("running #{cmd}")
+                    # system(cmd)
+                end
+            end
+
+            def MyExtras::finalizer(logger)
+                unless (ENV["CTX.TEXUTIL.EXTRAS"] =~ /^(no|off|false|0)$/io) || (ENV["CTX_TEXUTIL_EXTRAS"] =~ /^(no|off|false|0)$/io) then
+                    @@programs.each do |cmd|
+                        logger.report("running #{cmd}")
+                        system(cmd)
+                    end
+                end
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MySynonyms
+
+            class Synonym
+
+                @@debug = false
+
+                def initialize(t, c, k, d)
+                    @type, @command, @key, @sortkey, @data = t, c, k, c, d
+                end
+
+                attr_reader :type, :command, :key, :data
+                attr_reader :sortkey
+                attr_writer :sortkey
+
+                # def build(sorter)
+                    # if @key then
+                        # @sortkey = sorter.normalize(sorter.tokenize(@sortkey))
+                        # @sortkey = sorter.remap(sorter.simplify(@key.downcase)) # ??
+                        # if @sortkey.empty? then
+                            # @sortkey = sorter.remap(@command.downcase)
+                        # end
+                    # else
+                        # @key = ""
+                        # @sortkey = ""
+                    # end
+                # end
+
+                def build(sorter)
+                    if @sortkey and not @sortkey.empty? then
+                        @sortkey = sorter.normalize(sorter.tokenize(@sortkey))
+                        @sortkey = sorter.remap(sorter.simplify(@sortkey.downcase)) # ??
+                    end
+                    if not @sortkey or @sortkey.empty? then
+                        @sortkey = sorter.normalize(sorter.tokenize(@key))
+                        @sortkey = sorter.remap(sorter.simplify(@sortkey.downcase)) # ??
+                    end
+                    if not @sortkey or @sortkey.empty? then
+                        @sortkey = @key.dup
+                    end
+                end
+
+                def <=> (other)
+                    @sortkey <=> other.sortkey
+                end
+
+                def Synonym.flush(list,handle)
+                    if @@debug then
+                        list.each do |entry|
+                            handle << "% [#{entry.sortkey}]\n"
+                        end
+                    end
+                    list.each do |entry|
+                        handle << "\\synonymentry{#{entry.type}}{#{entry.command}}{#{entry.key}}{#{entry.data}}%\n"
+                    end
+                end
+
+            end
+
+            @@synonyms  = Hash.new
+            @@sorter    = Hash.new
+            @@languages = Hash.new
+
+            def MySynonyms::reset(logger)
+                @@synonyms  = Hash.new
+                @@sorter    = Hash.new
+                @@languages = Hash.new
+            end
+
+            def MySynonyms::reader(logger,data)
+                case data[0]
+                    when 'e' then
+                        @@synonyms[data[1]] = Array.new unless @@synonyms.key?(data[1])
+                        @@synonyms[data[1]].push(Synonym.new(data[1],data[2],data[3],data[4]))
+                    when 'l' then
+                        @@languages[data[1]] = data[2] || ''
+                end
+            end
+
+            def MySynonyms::writer(logger,handle)
+                if @@synonyms.size > 0 then
+                    @@synonyms.keys.sort.each do |s|
+                        handle << logger.banner("synonyms: #{s} #{@@synonyms[s].size}")
+                        Synonym.flush(@@synonyms[s],handle)
+                    end
+                end
+            end
+
+            def MySynonyms::processor(logger)
+                @@synonyms.keys.each do |s|
+                    @@sorter[s] = Sorter.new
+                    @@sorter[s].preset(
+                        eval("MyKeys").shortcuts,
+                        eval("MyKeys").expansions,
+                        eval("MyKeys").reductions,
+                        eval("MyKeys").divisions,
+                        @@languages[s] || '')
+                    @@sorter[s].prepare
+                    @@synonyms[s].each_index do |i|
+                        @@synonyms[s][i].build(@@sorter[s])
+                    end
+                    @@synonyms[s] = @@synonyms[s].sort
+                end
+            end
+
+            def MySynonyms::finalizer(logger)
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MyRegisters
+
+            class Register
+
+                @@specialsymbol = "\000"
+                @@specialbanner = "" # \\relax"
+
+                @@debug = false
+
+                @@howto = /^(.*?)\:\:(.*)$/o
+                @@split = ' && '
+
+                def initialize(state, t, l, k, e, s, p, r)
+                    @state, @type, @location, @key, @entry, @seetoo, @page, @realpage = state, t, l, k, e, s, p, r
+                    if @key   =~ @@howto then @pagehowto, @key   = $1, $2 else @pagehowto = '' end
+                    if @entry =~ @@howto then @texthowto, @entry = $1, $2 else @texthowto = '' end
+                    @key = @entry.dup if @key.empty?
+                    @sortkey = @key.dup
+                    @nofentries, @nofpages = 0, 0
+                    @normalizeentry = false
+                end
+
+                attr_reader :state, :type, :location, :key, :entry, :seetoo, :page, :realpage, :texthowto, :pagehowto
+                attr_reader :sortkey
+                attr_writer :sortkey
+
+                def build(sorter)
+                    # @entry, @key = sorter.normalize(@entry), sorter.normalize(sorter.tokenize(@key))
+                    @entry = sorter.normalize(sorter.tokenize(@entry)) if @normalizeentry
+                    @key   = sorter.normalize(sorter.tokenize(@key))
+                    if false then
+                        @entry, @key = [@entry, @key].collect do |target|
+                            # +a+b+c &a&b&c a+b+c a&b&c
+                            case target[0,1]
+                                when '&' then target = target.sub(/^./o,'').gsub(/([^\\])\&/o)     do "#{$1}#{@@split}" end
+                                when '+' then target = target.sub(/^./o,'').gsub(/([^\\])\+/o)     do "#{$1}#{@@split}" end
+                                else          target = target              .gsub(/([^\\])[\&\+]/o) do "#{$1}#{@@split}" end
+                            end
+                            # {a}{b}{c}
+                            # if target =~ /^\{(.*)\}$/o then
+                                # $1.split(/\} \{/o).join(@@split) # space between } { is mandate
+                            # else
+                                target
+                            # end
+                        end
+                    else
+                        # @entry, @key = cleanupsplit(@entry), cleanupsplit(@key)
+                        @entry, @key = cleanupsplit(@entry), xcleanupsplit(@key)
+                    end
+                    @sortkey = sorter.simplify(@key)
+                    # special = @sortkey =~ /^([^a-zA-Z\\])/o
+                    special = @sortkey =~ /^([\`\~\!\@\#\$\%\^\&\*\(\)\_\-\+\=\{\}\[\]\:\;\"\'\|\<\,\>\.\?\/\d])/o
+                    @sortkey = @sortkey.split(@@split).collect do |c| sorter.remap(c) end.join(@@split)
+                    if special then
+                        @sortkey = "#{@@specialsymbol}#{@sortkey}"
+                    end
+                    if @realpage == 0 then
+                        @realpage = 999999
+                    end
+                    @sortkey = [
+                        @sortkey.downcase,
+                        @sortkey,
+                        @entry,
+                        @texthowto.ljust(10,' '),
+                        # @state, # no, messes up things
+                        (@realpage.to_s || '').rjust(6,' ').gsub(/0/,' '),
+                        # (@realpage ||'').rjust(6,' '),
+                        @pagehowto
+                    ].join(@@split)
+                end
+
+                def cleanupsplit(target)
+                    # +a+b+c &a&b&c a+b+c a&b&c
+                    case target[0,1]
+                        when '&' then target.sub(/^./o,'').gsub(/([^\\])\&/o)     do "#{$1}#{@@split}" end
+                        when '+' then target.sub(/^./o,'').gsub(/([^\\])\+/o)     do "#{$1}#{@@split}" end
+                        else          target              .gsub(/([^\\])[\&\+]/o) do "#{$1}#{@@split}" end
+                    end
+                end
+
+                def xcleanupsplit(target) # +a+b+c &a&b&c a+b+c a&b&c
+                    t = Array.new
+                    case target[0,1]
+                        when '&' then
+                            t = target.sub(/^./o,'').split(/([^\\])\&/o)
+                        when '+' then
+                            t = target.sub(/^./o,'').split(/([^\\])\+/o)
+                        else
+                            # t = target.split(/([^\\])[\&\+]/o)
+                            # t = target.split(/[\&\+]/o)
+                            t = target.split(/(?!\\)[\&\+]/o) # lookahead
+                    end
+                    if not t[1] then t[1] = " " end # we need some entry else we get subentries first
+                    if not t[2] then t[2] = " " end # we need some entry else we get subentries first
+                    if not t[3] then t[3] = " " end # we need some entry else we get subentries first
+                    return t.join(@@split)
+                end
+                def <=> (other)
+                    @sortkey <=> other.sortkey
+                end
+
+                # more module like
+
+                @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '', ''
+                @@collapse = false
+
+                def Register.flushsavedline(handle)
+                    if @@collapse && ! @@savedfrom.empty? then
+                        if ! @@savedto.empty? then
+                            handle << "\\registerfrom#{@@savedfrom}%"
+                            handle << "\\registerto#{@@savedto}%"
+                        else
+                            handle << "\\registerpage#{@@savedfrom}%"
+                        end
+                    end
+                    @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', ''
+                end
+
+                def Register.flush(list,handle,sorter)
+                    # a bit messy, quite old mechanism, maybe some day ...
+                    # alphaclass can go, now flushed per class
+                    if list.size > 0 then
+                        @nofentries, @nofpages = 0, 0
+                        current, previous, howto  = Array.new, Array.new, Array.new
+                        lastpage, lastrealpage = '', ''
+                        alphaclass, alpha = '', ''
+                        @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', ''
+                        if @@debug then
+                            list.each do |entry|
+                                handle << "% [#{entry.sortkey.gsub(/#{@@split}/o,'] [')}]\n"
+                            end
+                        end
+                        list.each do |entry|
+# puts(entry.sortkey.gsub(/\s+/,""))
+                            if entry.sortkey =~ /^(\S+)/o then
+                                if sorter.division?($1) then
+                                    testalpha = sorter.getdivision($1)
+                                else
+                                    testalpha = entry.sortkey[0,1].downcase
+                                end
+                            else
+                                testalpha = entry.sortkey[0,1].downcase
+                            end
+                            if (testalpha != alpha.downcase) || (alphaclass != entry.class) then
+                                alpha = testalpha
+                                alphaclass = entry.class
+                                if alpha != ' ' then
+                                    flushsavedline(handle)
+                                    if alpha =~ /^[a-zA-Z]$/o then
+                                        character = alpha.dup
+                                    elsif alpha == @@specialsymbol then
+                                        character = @@specialbanner
+                                    elsif alpha.length > 1 then
+                                        # character = "\\getvalue\{#{alpha}\}"
+                                        character = "\\#{alpha}"
+                                    else
+                                        character = "\\unknown"
+                                    end
+                                    handle << "\\registerentry{#{entry.type}}{#{character}}%\n"
+                                end
+                            end
+                            current = [entry.entry.split(@@split),'','','',''].flatten
+                            howto = current.collect do |e|
+                                e + '::' + entry.texthowto
+                            end
+                            if howto[0] == previous[0] then
+                                current[0] = ''
+                            else
+                                previous[0] = howto[0].dup
+                                previous[1] = ''
+                                previous[2] = ''
+                                previous[3] = ''
+                            end
+                            if howto[1] == previous[1] then
+                                current[1] = ''
+                            else
+                                previous[1] = howto[1].dup
+                                previous[2] = ''
+                                previous[3] = ''
+                            end
+                            if howto[2] == previous[2] then
+                                current[2] = ''
+                            else
+                                previous[2] = howto[2].dup
+                                previous[3] = ''
+                            end
+                            if howto[3] == previous[3] then
+                                current[3] = ''
+                            else
+                                previous[3] = howto[3].dup
+                            end
+                            copied = false
+                            unless current[0].empty? then
+                                Register.flushsavedline(handle)
+                                handle << "\\registerentrya{#{entry.type}}{#{current[0]}}%\n"
+                                copied = true
+                            end
+                            unless current[1].empty? then
+                                Register.flushsavedline(handle)
+                                handle << "\\registerentryb{#{entry.type}}{#{current[1]}}%\n"
+                                copied = true
+                            end
+                            unless current[2].empty? then
+                                Register.flushsavedline(handle)
+                                handle << "\\registerentryc{#{entry.type}}{#{current[2]}}%\n"
+                                copied = true
+                            end
+                            unless current[3].empty? then
+                                Register.flushsavedline(handle)
+                                handle << "\\registerentryd{#{entry.type}}{#{current[3]}}%\n"
+                                copied = true
+                            end
+                            @nofentries += 1 if copied
+                            # if entry.realpage.to_i == 0 then
+                            if entry.realpage.to_i == 999999 then
+                                Register.flushsavedline(handle)
+                                handle << "\\registersee{#{entry.type}}{#{entry.pagehowto},#{entry.texthowto}}{#{entry.seetoo}}{#{entry.page}}%\n" ;
+                                lastpage, lastrealpage = entry.page, entry.realpage
+                                copied = false # no page !
+                            elsif @@savedhowto != entry.pagehowto and ! entry.pagehowto.empty? then
+                                @@savedhowto = entry.pagehowto
+                            end
+                            # beware, we keep multiple page entries per realpage because of possible prefix usage
+                            if copied || ! ((lastpage == entry.page) && (lastrealpage == entry.realpage)) then
+                                nextentry = "{#{entry.type}}{#{previous[0]}}{#{previous[1]}}{#{previous[2]}}{#{previous[3]}}{#{entry.pagehowto},#{entry.texthowto}}"
+                                savedline = "{#{entry.type}}{#{@@savedhowto},#{entry.texthowto}}{#{entry.location}}{#{entry.page}}{#{entry.realpage}}"
+                                if entry.state == 1 then # from
+                                    Register.flushsavedline(handle)
+                                    handle << "\\registerfrom#{savedline}%\n"
+                                elsif entry.state == 3 then # to
+                                    Register.flushsavedline(handle)
+                                    handle << "\\registerto#{savedline}%\n"
+                                    @@savedhowto = '' # test
+                                elsif @@collapse then
+                                    if savedentry != nextentry then
+                                        savedFrom = savedline
+                                    else
+                                        savedTo, savedentry = savedline, nextentry
+                                    end
+                                else
+                                    handle << "\\registerpage#{savedline}%\n"
+                                    @@savedhowto = '' # test
+                                end
+                                @nofpages += 1
+                                lastpage, lastrealpage = entry.page, entry.realpage
+                            end
+                        end
+                        Register.flushsavedline(handle)
+                    end
+                end
+
+            end
+
+            @@registers = Hash.new
+            @@sorter    = Hash.new
+            @@languages = Hash.new
+
+            def MyRegisters::reset(logger)
+                @@registers = Hash.new
+                @@sorter    = Hash.new
+                @@languages = Hash.new
+            end
+
+            def MyRegisters::reader(logger,data)
+                case data[0]
+                    when 'f' then
+                        @@registers[data[1]] = Array.new unless @@registers.key?(data[1])
+                        @@registers[data[1]].push(Register.new(1,data[1],data[2],data[3],data[4],nil,data[5],data[6]))
+                    when 'e' then
+                        @@registers[data[1]] = Array.new unless @@registers.key?(data[1])
+                        @@registers[data[1]].push(Register.new(2,data[1],data[2],data[3],data[4],nil,data[5],data[6]))
+                    when 't' then
+                        @@registers[data[1]] = Array.new unless @@registers.key?(data[1])
+                        @@registers[data[1]].push(Register.new(3,data[1],data[2],data[3],data[4],nil,data[5],data[6]))
+                    when 's' then
+                        @@registers[data[1]] = Array.new unless @@registers.key?(data[1])
+                        # was this but wrong sort order       (4,data[1],data[2],data[3],data[4],data[5],data[6],nil))
+                        @@registers[data[1]].push(Register.new(4,data[1],data[2],data[3],data[4],data[5],data[6],0))
+                    when 'l' then
+                        @@languages[data[1]] = data[2] || ''
+                end
+            end
+
+            def MyRegisters::writer(logger,handle)
+                if @@registers.size > 0 then
+                    @@registers.keys.sort.each do |s|
+                        handle << logger.banner("registers: #{s} #{@@registers[s].size}")
+                        Register.flush(@@registers[s],handle,@@sorter[s])
+                        # report("register #{@@registers[s].class}: #{@@registers[s]. at nofentries} entries and #{@@registers[s]. at nofpages} pages")
+                    end
+                end
+            end
+
+            def MyRegisters::processor(logger)
+                @@registers.keys.each do |s|
+                    @@sorter[s] = Sorter.new
+                    @@sorter[s].preset(
+                        eval("MyKeys").shortcuts,
+                        eval("MyKeys").expansions,
+                        eval("MyKeys").reductions,
+                        eval("MyKeys").divisions,
+                        @@languages[s] || '')
+                    @@sorter[s].prepare
+                    @@registers[s].each_index do |i|
+                        @@registers[s][i].build(@@sorter[s])
+                    end
+                    # @@registers[s].uniq!
+                    @@registers[s] = @@registers[s].sort
+                end
+            end
+
+            def MyRegisters::finalizer(logger)
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MyPlugins
+
+            @@plugins = nil
+
+            def MyPlugins::reset(logger)
+                @@plugins = nil
+            end
+
+            def MyPlugins::reader(logger,data)
+                @@plugins = Plugin.new(logger) unless @@plugins
+                case data[0]
+                    when 'r' then
+                        logger.report("registering plugin #{data[1]}")
+                        @@plugins.register(data[1],data[2])
+                    when 'd' then
+                        begin
+                            @@plugins.reader(data[1],data[2,data.length-1])
+                        rescue
+                            @@plugins.reader(data[1],['error'])
+                        end
+                end
+            end
+
+            def MyPlugins::writer(logger,handle)
+                @@plugins.writers(handle) if @@plugins
+            end
+
+            def MyPlugins::processor(logger)
+                @@plugins.processors if @@plugins
+            end
+
+            def MyPlugins::finalizer(logger)
+                @@plugins.finalizers if @@plugins
+            end
+
+        end
+
+    end
+
+    class Plugin
+
+        module MyKeys
+
+            @@shortcuts  = Array.new
+            @@expansions = Array.new
+            @@reductions = Array.new
+            @@divisions  = Array.new
+
+            def MyKeys::shortcuts
+                @@shortcuts
+            end
+            def MyKeys::expansions
+                @@expansions
+            end
+            def MyKeys::reductions
+                @@reductions
+            end
+            def MyKeys::divisions
+                @@divisions
+            end
+
+            def MyKeys::reset(logger)
+                @@shortcuts  = Array.new
+                @@expansions = Array.new
+                @@reductions = Array.new
+            end
+
+            def MyKeys::reader(logger,data)
+                key = data.shift
+                # grp = data.shift # language code, todo
+                case key
+                    when 's' then @@shortcuts.push(data)
+                    when 'e' then @@expansions.push(data)
+                    when 'r' then @@reductions.push(data)
+                    when 'd' then @@divisions.push(data)
+                end
+            end
+
+            def MyKeys::writer(logger,handle)
+            end
+
+            def MyKeys::processor(logger)
+                logger.report("shortcuts : #{@@shortcuts.size}")  # logger.report(@@shortcuts.inspect)
+                logger.report("expansions: #{@@expansions.size}") # logger.report(@@expansions.inspect)
+                logger.report("reductions: #{@@reductions.size}") # logger.report(@@reductions.inspect)
+                logger.report("divisions : #{@@divisions.size}")  # logger.report(@@divisions.inspect)
+            end
+
+            def MyKeys::finalizer(logger)
+            end
+
+        end
+
+    end
+
+    class Converter
+
+        def initialize(logger=nil)
+            if @logger = logger then
+                def report(str)
+                    @logger.report(str)
+                end
+                def banner(str)
+                    @logger.banner(str)
+                end
+            else
+                @logger = self
+                def report(str)
+                    puts(str)
+                end
+                def banner(str)
+                    puts(str)
+                end
+            end
+            @filename = 'texutil'
+            @fatalerror = false
+            @plugins = Plugin.new(@logger)
+            ['MyFiles', 'MyCommands', 'MySynonyms', 'MyRegisters', 'MyExtras', 'MyPlugins', 'MyKeys'].each do |p|
+                @plugins.register(p)
+            end
+        end
+
+        def loaded(filename)
+            begin
+                tuifile = File.suffixed(filename,'tui')
+                if FileTest.file?(tuifile) then
+                    report("parsing file #{tuifile}")
+                    if f = File.open(tuifile,'rb') then
+                        f.each do |line|
+                            case line.chomp
+                                when /^f (.*)$/o then @plugins.reader('MyFiles',    $1.splitdata)
+                                when /^c (.*)$/o then @plugins.reader('MyCommands', [$1])
+                                when /^e (.*)$/o then @plugins.reader('MyExtras',   $1.splitdata)
+                                when /^s (.*)$/o then @plugins.reader('MySynonyms', $1.splitdata)
+                                when /^r (.*)$/o then @plugins.reader('MyRegisters',$1.splitdata)
+                                when /^p (.*)$/o then @plugins.reader('MyPlugins',  $1.splitdata)
+                                when /^x (.*)$/o then @plugins.reader('MyKeys',     $1.splitdata)
+                                when /^r (.*)$/o then # nothing, not handled here
+                            else
+                                # report("unknown entry #{line[0,1]} in line #{line.chomp}")
+                            end
+                        end
+                        f.close
+                    end
+                else
+                    report("unable to locate #{tuifile}")
+                end
+            rescue
+                report("fatal error in parsing #{tuifile}")
+                @filename = 'texutil'
+            else
+                @filename = filename
+            end
+        end
+
+        def processed
+            @plugins.processors
+            return true # for the moment
+        end
+
+        def saved(filename=@filename)
+            if @fatalerror then
+                report("fatal error, no tuo file saved")
+                return false
+            else
+                begin
+                    if f = File.open(File.suffixed(filename,'tuo'),'w') then
+                        @plugins.writers(f)
+                        f << "\\endinput\n"
+                        f.close
+                    end
+                rescue
+                    report("fatal error when saving file (#{$!})")
+                    return false
+                else
+                    report("tuo file saved")
+                    return true
+                end
+            end
+        end
+
+        def finalized
+            @plugins.finalizers
+            @plugins.resets
+            return true # for the moment
+        end
+
+        def reset
+            @plugins.resets
+        end
+
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/texutil.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/tool.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/tool.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/tool.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,291 @@
+# module    : base/tool
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+require 'timeout'
+require 'socket'
+require 'rbconfig'
+
+module Tool
+
+    $constructedtempdir = ''
+
+    def Tool.constructtempdir(create,mainpath='',fallback='')
+        begin
+            mainpath += '/' unless mainpath.empty?
+            timeout(5) do
+                begin
+                    t = Time.now
+                    u = t.usec.to_s % [1..2] [0..3]
+                    pth = t.strftime("#{mainpath}%Y%m%d-%H%M%S-#{u}-#{Process.pid}")
+                #
+                #    problems with 1.9
+                #
+                #    if pth == $constructedtempdir
+                #        # sleep(0.01)
+                #        retry
+                #    end
+                    pth == $constructedtempdir
+                #
+                    Dir.mkdir(pth) if create
+                    $constructedtempdir = pth
+                    return pth
+                rescue
+                    # sleep(0.01)
+                    retry
+                end
+            end
+        rescue TimeoutError
+            # ok
+        rescue
+            # ok
+        end
+        unless fallback.empty?
+            begin
+                pth = "#{mainpath}#{fallback}"
+                mkdir(pth) if create
+                $constructedtempdir = path
+                return pth
+            rescue
+                return '.'
+            end
+        else
+            return '.'
+        end
+
+    end
+
+    def Tool.findtempdir(*vars)
+        constructtempdir(false,*vars)
+    end
+
+    def Tool.maketempdir(*vars)
+        constructtempdir(true,*vars)
+    end
+
+    # print maketempdir + "\n"
+    # print maketempdir + "\n"
+    # print maketempdir + "\n"
+    # print maketempdir + "\n"
+    # print maketempdir + "\n"
+
+
+    def Tool.ruby_platform
+        case RUBY_PLATFORM
+            when /(mswin|bccwin|mingw|cygwin)/i then 'mswin'
+            when /(linux)/i                     then 'linux'
+            when /(netbsd|unix)/i               then 'unix'
+            when /(darwin|rhapsody|nextstep)/i  then 'macosx'
+            else                                     'unix'
+        end
+    end
+
+    $defaultlineseparator = $/ # $RS in require 'English'
+
+    def Tool.file_platform(filename)
+
+        begin
+            if f = open(filename,'rb') then
+                str = f.read(4000)
+                str.gsub!(/(.*?)\%\!PS/mo, "%!PS") # don't look into preamble crap
+                f.close
+                nn = str.count("\n")
+                nr = str.count("\r")
+                if nn>nr then
+                    return 2
+                elsif nn<nr then
+                    return 3
+                else
+                    return 1
+                end
+            else
+                return 0
+            end
+        rescue
+            return 0
+        end
+
+    end
+
+    def Tool.path_separator
+        return File::PATH_SEPARATOR
+    end
+
+    def Tool.line_separator(filename)
+
+        case file_platform(filename)
+            when 1 then return $defaultlineseparator
+            when 2 then return "\n"
+            when 3 then return "\r"
+            else        return $defaultlineseparator
+        end
+
+    end
+
+    def Tool.default_line_separator
+        $defaultlineseparator
+    end
+
+    def Tool.simplefilename(old)
+
+        return old # too fragile
+
+        return old if not FileTest.file?(old)
+
+        new = old.downcase
+        new.gsub!(/[^A-Za-z0-9\_\-\.\\\/]/o) do # funny chars
+            '-'
+        end
+        if old =~ /[a-zA-Z]\:/o
+            # seems like we have a dos/windows drive prefix, so roll back
+            new.sub!(/^(.)\-/) do
+                $1 + ':'
+            end
+        end
+        # fragile for a.b.c.d.bla-bla.e.eps
+        # new.gsub!(/(.+?)\.(.+?)(\..+)$/o)  do # duplicate .
+            # $1 + '-' + $2 + $3
+        # end
+        new.gsub!(/\-+/o)                  do # duplicate -
+            '-'
+        end
+        new
+
+    end
+
+    if RbConfig::CONFIG['host_os'] =~ /mswin/ then
+
+        require 'Win32API'
+
+        GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', ['P','P','N'], 'N')
+        GetLongPathName = Win32API.new('kernel32', 'GetLongPathName', ['P','P','N'], 'N')
+
+        def Tool.dowith_pathname (filename,filemethod)
+            filename.gsub!(/\\/o,'/')
+            case filename
+                when /\;/o then
+                    # could be a path spec
+                    return filename
+                when /\s+/o then
+                    # danger lurking
+                    buffer = ' ' * 260
+                    length = filemethod.call(filename,buffer,buffer.size)
+                    if length>0 then
+                        return buffer.slice(0..length-1)
+                    else
+                        # when the path or file does not exist, nothing is returned
+                        # so we try to handle the path separately from the basename
+                        basename = File.basename(filename)
+                        pathname = File.dirname(filename)
+                        length = filemethod.call(pathname,buffer,260)
+                        if length>0 then
+                            return buffer.slice(0..length-1) + '/' + basename
+                        else
+                            return filename
+                        end
+                    end
+                else
+                    # no danger
+                    return filename
+            end
+        end
+
+        def Tool.shortpathname(filename)
+            dowith_pathname(filename,GetShortPathName)
+        end
+
+        def Tool.longpathname(filename)
+            dowith_pathname(filename,GetLongPathName)
+        end
+
+    else
+
+        def Tool.shortpathname(filename)
+            filename
+        end
+
+        def Tool.longpathname(filename)
+            filename
+        end
+
+    end
+
+    # print shortpathname("C:/Program Files/ABBYY FineReader 6.0/matrix.str")+ "!\n"
+    # print shortpathname("C:/Program Files/ABBYY FineReader 6.0/matrix.strx")+ "!\n"
+
+    def Tool.checksuffix(old)
+
+        return old unless FileTest.file?(old)
+
+        new = old
+
+        unless new =~ /\./io # no suffix
+            f = open(filename,'rb')
+            if str = f.gets
+                case str
+                    when /^\%\!PS/io
+                        # logging.report(filename, 'analyzed as EPS')
+                        new = new + '.eps'
+                    when /^\%PDF/io
+                        # logging.report(filename, 'analyzed as PDF')
+                        new = new + '.pdf'
+                    else
+                        # logging.report(filename, 'fallback as TIF')
+                        new = new + '.tif'
+                end
+            end
+            f.close
+        end
+
+        new.sub!(/\.jpeg$/io) do
+            '.jpg'
+        end
+        new.sub!(/\.tiff$/io) do
+            '.tif'
+        end
+        new.sub!(/\.ai$/io) do
+            '.eps'
+        end
+        new.sub!(/\.ai([a-z0-9]*)$/io) do
+            '-' + $1 + '.eps'
+        end
+        new
+
+    end
+
+    def Tool.cleanfilename(old,logging=nil)
+
+        return old if not FileTest.file?(old)
+
+        new = checksuffix(simplefilename(old))
+        unless new == old
+            begin # bugged, should only be name, not path
+                File.rename(old,new)
+                logging.report("renaming fuzzy name #{old} to #{new}") unless logging
+                return old
+            rescue
+                logging.report("unable to rename fuzzy name #{old} to #{new}") unless logging
+            end
+        end
+        return new
+
+    end
+
+    def Tool.servername
+        host = Socket::gethostname
+        begin
+            Socket::gethostbyname(host)[0]
+        rescue
+            host
+        end
+    end
+
+    # print file_platform(ARGV[0])
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/tool.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/base/variables.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/base/variables.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/base/variables.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,132 @@
+# module    : base/variables
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# ['base/tool','tool'].each do |r| begin require r ; rescue Exception ; else break ; end ; end
+
+require 'base/tool'
+
+class Hash
+
+    def nothing?(id)
+        ! self[id] || self[id].empty?
+    end
+
+    def subset(pattern)
+        h = Hash.new
+        p = pattern.gsub(/([\.\:\-])/) do "\\#{$1}" end
+        r = /^#{p}/
+        self.keys.each do |k|
+            h[k] = self[k].dup if k =~ r
+        end
+        return h
+    end
+
+end
+
+class ExtendedHash < Hash
+
+    @@re_var_a = /\%(.*?)\%/
+    @@re_var_b = /\$\((.*?)\)/
+
+    def set(key,value='',resolve=true)
+        if value then
+            self[key] = if resolve then resolved(value.to_s) else value.to_s end
+        else
+            self[key] = ''
+        end
+    end
+
+    def replace(key,value='')
+        self[key] = value if self?(key)
+    end
+
+    def get(key,default='')
+        if self.key?(key) then self[key] else default end
+    end
+
+    def true?(key)
+        self[key] =~ /^(yes|on|true|enable|enabled|y|start)$/io rescue false
+    end
+
+    def resolved(str)
+        begin
+            str.to_s.gsub(@@re_var_a) do
+                self[$1] || ''
+            end.gsub(@@re_var_b) do
+                self[$1] || ''
+            end
+        rescue
+            str.to_s rescue ''
+        end
+    end
+
+    def check(key,default='')
+        if self.key?(key) then
+            if self[key].empty? then self[key] = (default || '') end
+        else
+            self[key] = (default || '')
+        end
+    end
+
+    def checked(key,default='')
+        if self.key?(key) then
+            if self[key].empty? then default else self[key] end
+        else
+            default
+        end
+    end
+
+    def empty?(key)
+        self[key].empty?
+    end
+
+    # def downcase(key)
+        # self[key].downcase!
+    # end
+
+end
+
+# the next one is obsolete so we need to replace things
+
+module Variables
+
+    def setvariable(key,value='')
+        @variables[key] = value
+    end
+
+    def replacevariable(key,value='')
+        @variables[key] = value if @variables.key?(key)
+    end
+
+    def getvariable(key,default='')
+        if @variables.key?(key) then @variables[key] else default end
+    end
+
+    def truevariable(key)
+        @variables[key] =~ /^(yes|on|true)$/io rescue false
+    end
+
+    def checkedvariable(str,default='')
+        if @variables.key?(key) then
+            if @variables[key].empty? then default else @variables[key] end
+        else
+            default
+        end
+    end
+
+    def report(*str)
+        @logger.report(*str)
+    end
+
+    def debug(*str)
+        @logger.debug(str)
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/base/variables.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/concheck.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/concheck.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/concheck.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,471 @@
+# Program   : concheck (tex & context syntax checker)
+# Copyright : PRAGMA ADE / Hasselt NL / www.pragma-ade.com
+# Author    : Hans Hagen
+# Version   : 1.1 / 2003.08.18
+
+# remarks:
+#
+# - the error messages are formatted like tex's messages so that scite can see them
+# - begin and end tags are only tested on a per line basis because we assume clean sources
+# - maybe i'll add begin{something} ... end{something} checking
+
+# # example validation file
+#
+# begin interface en
+#
+# 1 text
+# 4 Question
+# 0 endinput
+# 0 setupsomething
+# 0 chapter
+#
+# end interface en
+
+# nicer
+
+# class Interface
+
+    # def initialize (language = 'unknown')
+        # @valid = Array.new
+        # @language = language
+    # end
+
+    # def register (left, right)
+        # @valid.push([left,right])
+    # end
+
+# end
+
+# $interfaces = Hash.new
+
+# $interfaces['en'] = Interface.new('english')
+# $interfaces['nl'] = Interface.new('dutch')
+
+# $interfaces['en'].add('\\\\start','\\\\stop')
+# $interfaces['en'].add('\\\\begin','\\\\end')
+# $interfaces['en'].add('\\\\Start','\\\\Stop')
+# $interfaces['en'].add('\\\\Begin','\\\\End')
+
+# $interfaces['nl'].add('\\\\start','\\\\stop')
+# $interfaces['nl'].add('\\\\beginvan','\\\\eindvan')
+# $interfaces['nl'].add('\\\\Start','\\\\Stop')
+# $interfaces['nl'].add('\\\\BeginVan','\\\\Eindvan')
+
+# rest todo
+
+$valid = Hash.new
+
+$valid['en'] = Array.new
+$valid['nl'] = Array.new
+
+#$valid['en'].push(['',''])
+$valid['en'].push(['\\\\start','\\\\stop'])
+$valid['en'].push(['\\\\begin','\\\\end'])
+$valid['en'].push(['\\\\Start','\\\\Stop'])
+$valid['en'].push(['\\\\Begin','\\\\End'])
+
+#$valid['nl'].push(['',''])
+$valid['nl'].push(['\\\\start','\\\\stop'])
+$valid['nl'].push(['\\\\beginvan','\\\\eindvan'])
+$valid['nl'].push(['\\\\Start','\\\\Stop'])
+$valid['nl'].push(['\\\\BeginVan','\\\\Eindvan'])
+
+$valid_tex = "\\\\end\(input|insert|csname|linechar|graf|buffer|strut\)"
+$valid_mp  = "(enddef||end||endinput)"
+
+$start_verbatim = Hash.new
+$stop_verbatim  = Hash.new
+
+$start_verbatim['en'] = '\\\\starttyping'
+$start_verbatim['nl'] = '\\\\starttypen'
+
+$stop_verbatim['en'] = '\\\\stoptyping'
+$stop_verbatim['nl'] = '\\\\stoptypen'
+
+def message(str, filename=nil, line=nil, column=nil)
+    if filename then
+        if line then
+            if column then
+                puts("error in file #{filename} at line #{line} in column #{column}: #{str}\n")
+            else
+                puts("error in file #{filename} at line #{line}: #{str}\n")
+            end
+        else
+            puts("file #{filename}: #{str}\n")
+        end
+    else
+        puts(str+"\n")
+    end
+end
+
+def load_file (filename='')
+    begin
+        data = IO.readlines(filename)
+        data.collect! do |d|
+            if d =~ /^\s*%/o then
+                ''
+            elsif d =~ /(.*?[^\\])%.*$/o then
+                $1
+            else
+                d
+            end
+        end
+    rescue
+        message("provide proper filename")
+        return nil
+    end
+    # print data.to_s + "\n"
+    return data
+end
+
+def guess_interface(data)
+    if data.first =~ /^%.*interface\=(.*)\s*/ then
+        return $1
+    else
+        data.each do |line|
+            case line
+                when /\\(starttekst|stoptekst|startonderdeel|startdocument|startoverzicht)/o then return 'nl'
+                when /\\(stelle|verwende|umgebung|benutze)/o                                 then return 'de'
+                when /\\(stel|gebruik|omgeving)/                                             then return 'nl'
+                when /\\(use|setup|environment)/                                             then return 'en'
+                when /\\(usa|imposta|ambiente)/                                              then return 'it'
+                when /(height|width|style)=/                                                 then return 'en'
+                when /(hoehe|breite|schrift)=/                                               then return 'de'
+                when /(hoogte|breedte|letter)=/                                              then return 'nl'
+                when /(altezza|ampiezza|stile)=/                                             then return 'it'
+                when /externfiguur/                                                          then return 'nl'
+                when /externalfigure/                                                        then return 'en'
+                when /externeabbildung/                                                      then return 'de'
+                when /figuraesterna/                                                         then return 'it'
+            end
+        end
+        return 'en'
+    end
+end
+
+def cleanup_data(data, interface='en')
+    verbatim = 0
+    re_start = /^\s*#{$start_verbatim[interface]}/
+    re_stop = /^\s*#{$stop_verbatim[interface]}/
+    data.collect! do |d|
+        if d =~ re_start then
+            verbatim += 1
+            if verbatim>1 then
+                ''
+            else
+                d
+            end
+        elsif d =~ re_stop then
+            verbatim -= 1
+            if verbatim>0 then
+                ''
+            else
+                d
+            end
+        elsif verbatim > 0 then
+            ''
+        else
+            d
+        end
+    end
+    return data
+end
+
+def load_valid(data, interface=nil)
+    if data && (data.first =~ /^%.*valid\=(.*)\s*/)
+        filename = $1
+        filename = '../' + filename unless test(?f,filename)
+        filename = '../' + filename unless test(?f,filename)
+        if test(?f,filename) then
+            interface = guess_interface(data) unless interface
+            if $valid.has_key?(interface) then
+                interface = $valid[interface]
+            else
+                interface = $valid['en']
+            end
+            begin
+                message("loading validation file",filename)
+                validkeys = Hash.new
+                line = 1
+                IO.readlines(filename).each do |l|
+                    if l =~ /\s+[\#\%]/io then
+                        # ignore line
+                    elsif l =~ /^\s*(begin|end)\s+interface\s+([a-z][a-z])/o then
+                        # not yet supported
+                    elsif l =~ /^\s*(\d+)\s+([a-zA-Z]*)$/o then
+                        type, key = $1.to_i, $2.strip
+                        if interface[type] then
+                            validkeys[interface[type].first+key] = true
+                            validkeys[interface[type].last+key]  = true
+                        else
+                            error_message(filename,line,nil,'wrong definition')
+                        end
+                    end
+                    line += 1
+                end
+                if validkeys then
+                    message("#{validkeys.length} validation keys loaded",filename)
+                end
+                return validkeys
+            rescue
+                message("invalid validation file",filename)
+            end
+        else
+            message("unknown validation file", filename)
+        end
+    else
+        message("no extra validation file specified")
+    end
+    return nil
+end
+
+def some_chr_error(data, filename, left, right)
+    levels = Array.new
+    for line in 0..data.length-1 do
+         str = data[line]
+         # str = data[line].gsub(/\\[\#{left}\#{right}]/,'')
+         column = 0
+         while column<str.length do
+            case str[column].chr
+                when "\%" then
+                    break
+                when "\\" then
+                    column += 2
+                when left then
+                    levels.push([line,column])
+                    column += 1
+                when right then
+                    if levels.pop
+                        column += 1
+                    else
+                        message("missing #{left} for #{right}",filename,line+1,column+1)
+                        return true
+                    end
+                else
+                    column += 1
+            end
+        end
+    end
+    if levels && levels.length>0 then
+        levels.each do |l|
+            column = l.pop
+            line = l.pop
+            message("missing #{right} for #{left}",filename,line+1,column+1)
+        end
+        return true
+    else
+        return false
+    end
+end
+
+def some_wrd_error(data, filename, start, stop, ignore)
+    levels = Array.new
+    len = 0
+    re_start = /[^\%]*(#{start})([a-zA-Z]*)/
+    re_stop = /[^\%]*(#{stop})([a-zA-Z]*)/
+    re_ignore = /#{ignore}.*/
+    str_start = start.gsub(/\\+/,'\\')
+    str_stop = stop.gsub(/\\+/,'\\')
+    line = 0
+    while line<data.length do
+        dataline = data[line].split(/[^\\A-Za-z]/)
+        if dataline.length>0 then
+            # todo: more on one line
+            dataline.each do |dataword|
+                case dataword
+                    when re_ignore then
+                        # just go on
+                    when re_start then
+                        levels.push([line,$2])
+                        # print ' '*levels.length + '>' + $2 + "\n"
+                    when re_stop then
+                        # print ' '*levels.length + '<' + $2 + "\n"
+                        if levels && levels.last && (levels.last[1] == $2) then
+                            levels.pop
+                        elsif levels && levels.last then
+                            message("#{str_stop}#{levels.last[1]} expected instead of #{str_stop}#{$2}",filename,line+1)
+                            return true
+                        else
+                            message("missing #{str_start}#{$2} for #{str_stop}#{$2}",filename,line+1)
+                            return true
+                        end
+                    else
+                        # just go on
+                end
+            end
+        end
+        line += 1
+    end
+    if levels && levels.length>0 then
+        levels.each do |l|
+            text = l.pop
+            line = l.pop
+            message("missing #{str_stop}#{text} for #{str_start}#{text}",filename,line+1)
+        end
+        return true
+    else
+        return false
+    end
+end
+
+def some_sym_error (data, filename, symbol, template=false)
+    saved = Array.new
+    inside = false
+    level = 0
+    for line in 0..data.length-1 do
+         str = data[line]
+         column = 0
+         while column<str.length do
+            case str[column].chr
+                when "[" then
+                    level += 1 if template
+                when "]" then
+                    level -= 1 if template && level > 0
+                when "\%" then
+                    break
+                when "\\" then
+                    column += 1
+                when symbol then
+                    if level == 0 then
+                        inside = ! inside
+                        saved = [line,column]
+                    else
+                        # we're in some kind of template or so
+                    end
+                else
+                    # go on
+            end
+            column += 1
+        end
+    end
+    if inside && saved && level == 0 then
+        column = saved.pop
+        line = saved.pop
+        message("missing #{symbol} for #{symbol}",filename,line+1)
+        return true
+    else
+        return false
+    end
+end
+
+def some_key_error(data, filename, valid)
+    return if (! valid) || (valid.length == 0)
+    error = false
+    # data.foreach do |line| ... end
+    for line in 0..data.length-1 do
+        data[line].scan(/\\([a-zA-Z]+)/io) do
+            unless valid.has_key?($1) then
+                message("unknown command \\#{$1}",filename,line+1)
+                error = true
+            end
+        end
+    end
+    return error
+end
+
+# todo : language dependent
+
+def check_file_tex (filename)
+    error = false
+    if data = load_file(filename) then
+        message("checking tex file", filename)
+        interface = guess_interface(data)
+        valid = load_valid(data,interface)
+        data = cleanup_data(data,interface)
+        # data.each do |d| print d  end
+        $valid[interface].each do |v|
+            if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex) then
+                error = true
+                break
+            end
+        end
+        # return false if some_wrd_error(data, filename, '\\\\start'   , '\\\\stop'   , $valid_tex)
+        # return false if some_wrd_error(data, filename, '\\\\Start'   , '\\\\Stop'   , $valid_tex)
+        # return false if some_wrd_error(data, filename, '\\\\beginvan', '\\\\eindvan', $valid_tex)
+        # return false if some_wrd_error(data, filename, '\\\\begin'   , '\\\\end|\\\\eind', $valid_tex)
+        error = true if some_sym_error(data, filename, '$', false)
+        error = true if some_sym_error(data, filename, '|', true)
+        error = true if some_chr_error(data, filename, '{', '}')
+        error = true if some_chr_error(data, filename, '[', ']')
+        error = true if some_chr_error(data, filename, '(', ')')
+        error = true if some_key_error(data, filename, valid)
+        message("no errors in tex code", filename) unless error
+        return error
+    else
+        return false
+    end
+end
+
+def check_file_mp (filename)
+    error = false
+    if data = load_file(filename) then
+        message("checking metapost file", filename)
+        interface = guess_interface(data)
+        valid = load_valid(data,interface)
+        $valid[interface].each do |v|
+            if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex) then
+                error = true
+                break
+            end
+        end
+        # return false if some_wrd_error(data, filename, '', 'begin', 'end', $valid_mp)
+        error = true if some_chr_error(data, filename, '{', '}')
+        error = true if some_chr_error(data, filename, '[', ']')
+        error = true if some_chr_error(data, filename, '(', ')')
+        error = true if some_key_error(data, filename, valid)
+        message("no errors in metapost code", filename) unless error
+        return error
+    else
+        return false
+    end
+end
+
+def check_file_text(filename='')
+    if data = load_file(filename) then
+        for line in 0..data.length-1 do
+            # case data[line]
+                # when /\s([\:\;\,\.\?\!])/ then
+                    # message("space before #{$1}",filename,line+1)
+                # when /\D([\:\;\,\.\?\!])\S/ then
+                    # message("no space after #{$1}",filename,line+1)
+            # end
+            if data[line] =~ /\s([\:\;\,\.\?\!])/ then
+                message("space before #{$1}",filename,line+1)
+            else
+                data[line].gsub!(/\[.*?\]/o, '')
+                data[line].gsub!(/\(.*?\)/o, '')
+                data[line].gsub!(/\[.*?$/o, '')
+                data[line].gsub!(/^.*?\]/o, '')
+                if data[line] =~ /\D([\:\;\,\.\?\!])\S/ then
+                    message("no space after #{$1}",filename,line+1)
+                end
+            end
+        end
+    end
+end
+
+def check_file(filename='')
+    case filename
+        when '' then
+            message("provide filename")
+            return false
+        when /\.(tex|mk.+)$/i then
+            return check_file_tex(filename) # && check_file_text(filename)
+        when /\.mp$/i then
+            return check_file_mp(filename)
+        else
+            message("only tex and metapost files are checked")
+            return false
+    end
+end
+
+if ARGV.size > 0 then
+    someerror = false
+    ARGV.each do |filename|
+         somerror = true if check_file(filename)
+    end
+    exit (if someerror then 1 else 0 end)
+else
+    exit 1
+end
+


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/concheck.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/ctxtools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/ctxtools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,2779 @@
+#!/usr/bin/env ruby
+#encoding: ASCII-8BIT
+
+# program   : ctxtools
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2004-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# This script will harbor some handy manipulations on context
+# related files.
+
+# todo: move scite here
+#
+# todo: move kpse call to kpse class/module, faster and better
+
+# Taco Hoekwater on patterns and lig building (see 'agr'):
+#
+# Any direct use of a ligature (as accessed by \char or through active
+# characters) is wrong and will create faulty hyphenation. Normally,
+# when TeX sees "office", it has six tokens, and it knows from the
+# patterns that it can hyphenate between the "ff". It will build an
+# internal list of four nodes, like this:
+#
+# [char, o  , ffi ]
+# [lig , ffi, c   ,[f,f,i]]
+# [char, c  , e   ]
+# [char, e  , NULL]
+#
+# as you can see from the ffi line, it has remembered the original
+# characters. While hyphenating, it temporarily changes back to
+# that, then re-instates the ligature afterwards.
+#
+# If you feed it the ligature directly, like so:
+#
+# [char, o   , ffi ]
+# [char, ffi , c   ]
+# [char, c   , e   ]
+# [char, e   , NULL]
+#
+# it cannot do that (it tries to hyphenate as if the "ffi" was a
+# character), and the result is wrong hyphenation.
+
+banner = ['CtxTools', 'version 1.3.5', '2004/2008', 'PRAGMA ADE']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'base/switch'
+require 'base/logger'
+require 'base/system'
+require 'base/kpse'
+require 'base/file'
+
+require 'rexml/document'
+require 'net/http'
+require 'fileutils'
+# require 'ftools'
+require 'kconv'
+
+exit if defined?(REQUIRE2LIB)
+
+class String
+
+    def i_translate(element, attribute, category)
+        self.gsub!(/(<#{element}.*?#{attribute}=)([\"\'])(.*?)\2/) do
+            if category.key?($3) then
+                # puts "#{element} #{$3} -> #{category[$3]}\n" if element == 'cd:inherit'
+                # puts "#{element} #{$3} => #{category[$3]}\n" if element == 'cd:command'
+                "#{$1}#{$2}#{category[$3]}#{$2}"
+            else
+                # puts "#{element} #{$3} -> ?\n" if element == 'cd:inherit'
+                # puts "#{element} #{$3} => ?\n" if element == 'cd:command'
+                "#{$1}#{$2}#{$3}#{$2}" # unchanged
+            end
+        end
+    end
+
+    def i_load(element, category)
+        self.scan(/<#{element}.*?name=([\"\'])(.*?)\1.*?value=\1(.*?)\1/) do
+            category[$2] = $3
+        end
+    end
+
+    def nosuffix(suffix)
+        self.sub(/\.#{suffix}/,'') # no /o
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    def touchcontextfile
+        dowithcontextfile(1)
+    end
+
+    def contextversion
+        dowithcontextfile(2)
+    end
+
+    private
+
+    def dowithcontextfile(action)
+        maincontextfile = 'context.tex'
+        unless FileTest.file?(maincontextfile) then
+            begin
+                maincontextfile = Kpse.found(maincontextfile,'context')
+            rescue
+                maincontextfile = ''
+            end
+        end
+        unless maincontextfile.empty? then
+            nextcontextfile = maincontextfile.sub(/context\.tex$/,"cont-new.tex")
+            case action
+                when 1 then
+                    touchfile(maincontextfile)
+                    touchfile(nextcontextfile,@@newcontextversion)
+                when 2 then
+                    reportversion(maincontextfile)
+                    reportversion(nextcontextfile,@@newcontextversion)
+            end
+        end
+
+    end
+
+    @@contextversion    = "\\\\contextversion"
+    @@newcontextversion = "\\\\newcontextversion"
+
+    def touchfile(filename,command=@@contextversion)
+
+        if FileTest.file?(filename) then
+            if data = IO.read(filename) then
+                timestamp = Time.now.strftime('%Y.%m.%d %H:%M')
+                prevstamp = ''
+                begin
+                    data.gsub!(/#{command}\{(\d+\.\d+\.\d+.*?)\}/) do
+                        prevstamp = $1
+                        "#{command.sub(/(\\)+/,"\\")}{#{timestamp}}"
+                    end
+                rescue
+                else
+                    begin
+                        File.delete(filename+'.old')
+                    rescue
+                    end
+                    begin
+                        File.copy(filename,filename+'.old')
+                    rescue
+                    end
+                    begin
+                        if f = File.open(filename,'w') then
+                            f.puts(data)
+                            f.close
+                        end
+                    rescue
+                    end
+                end
+                if prevstamp.empty? then
+                    report("#{filename} is not updated, no timestamp found")
+                else
+                    report("#{filename} is updated from #{prevstamp} to #{timestamp}")
+                end
+            end
+        else
+            report("#{filename} is not found")
+        end
+
+    end
+
+    def reportversion(filename,command=@@contextversion)
+
+        version = 'unknown'
+        begin
+            if FileTest.file?(filename) && IO.read(filename).match(/#{command}\{(\d+\.\d+\.\d+.*?)\}/) then
+                version = $1
+            end
+        rescue
+        end
+        if @commandline.option("pipe") then
+            print version
+        else
+            report("context version: #{version} (#{filename})")
+        end
+
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    def jeditinterface
+        editinterface('jedit')
+    end
+
+    def bbeditinterface
+        editinterface('bbedit')
+    end
+
+    def sciteinterface
+        editinterface('scite')
+    end
+
+    def rawinterface
+        editinterface('raw')
+    end
+
+    private
+
+    def editinterface(type='raw')
+
+        return unless FileTest.file?("cont-en.xml")
+
+        interfaces = @commandline.arguments
+
+        if interfaces.empty? then
+            interfaces = ['en','cs','de','it','nl','ro','fr']
+        end
+
+        interfaces.each do |interface|
+            begin
+                collection = Hash.new
+                mappings   = Hash.new
+                if f = open("keys-#{interface}.xml") then
+                    while str = f.gets do
+                        if str =~ /\<cd\:command\s+name=\"(.*?)\"\s+value=\"(.*?)\".*?\>/o then
+                            mappings[$1] = $2
+                        end
+                    end
+                    f.close
+                    if f = open("cont-en.xml") then
+                        while str = f.gets do
+                            if str =~ /\<cd\:command\s+name=\"(.*?)\"\s+type=\"environment\".*?\>/o then
+                                collection["start#{mappings[$1]}"] = ''
+                                collection["stop#{mappings[$1]}"]  = ''
+                            elsif str =~ /\<cd\:command\s+name=\"(.*?)\".*?\>/o then
+                                collection["#{mappings[$1]}"] = ''
+                            end
+                        end
+                        f.close
+                        case type
+                            when 'jedit' then
+                                if f = open("context-jedit-#{interface}.xml", 'w') then
+                                    f.puts("<?xml version='1.0'?>\n\n")
+                                    f.puts("<!DOCTYPE MODE SYSTEM 'xmode.dtd'>\n\n")
+                                    f.puts("<MODE>\n")
+                                    f.puts("  <RULES>\n")
+                                    f.puts("    <KEYWORDS>\n")
+                                    collection.keys.sort.each do |name|
+                                        f.puts("      <KEYWORD2>\\#{name}</KEYWORD2>\n") unless name.empty?
+                                    end
+                                    f.puts("    </KEYWORDS>\n")
+                                    f.puts("  </RULES>\n")
+                                    f.puts("</MODE>\n")
+                                    f.close
+                                end
+                            when 'bbedit' then
+                                if f = open("context-bbedit-#{interface}.xml", 'w') then
+                                    f.puts("<?xml version='1.0'?>\n\n")
+                                    f.puts("<key>BBLMKeywordList</key>\n")
+                                    f.puts("<array>\n")
+                                    collection.keys.sort.each do |name|
+                                        f.puts("    <string>\\#{name}</string>\n") unless name.empty?
+                                    end
+                                    f.puts("</array>\n")
+                                    f.close
+                                end
+                            when 'scite' then
+                                if f = open("cont-#{interface}-scite.properties", 'w') then
+                                    i = 0
+                                    f.write("keywordclass.macros.context.#{interface}=")
+                                    collection.keys.sort.each do |name|
+                                        unless name.empty? then
+                                            if i==0 then
+                                                f.write("\\\n    ")
+                                                i = 5
+                                            else
+                                                i = i - 1
+                                            end
+                                            f.write("#{name} ")
+                                        end
+                                    end
+                                    f.write("\n")
+                                    f.close
+                                end
+                            else # raw
+                                collection.keys.sort.each do |name|
+                                    puts("\\#{name}\n") unless name.empty?
+                                end
+                        end
+                    end
+                end
+            end
+        end
+
+    end
+
+end
+
+# class Commands
+#
+#     include CommandBase
+#
+#     public
+#
+#     def translateinterface
+#
+#         # since we know what kind of file we're dealing with,
+#         # we do it quick and dirty instead of using rexml or
+#         # xslt
+#
+#         interfaces = @commandline.arguments
+#
+#         if interfaces.empty? then
+#             interfaces = ['cs','de','it','nl','ro','fr']
+#         else
+#             interfaces.delete('en')
+#         end
+#
+#         interfaces.flatten.each do |interface|
+#
+#             variables, constants, strings, list, data = Hash.new, Hash.new, Hash.new, '', ''
+#
+#             keyfile, intfile, outfile = "keys-#{interface}.xml", "cont-en.xml", "cont-#{interface}.xml"
+#
+#             report("generating #{keyfile}")
+#
+#             begin
+#                 one = "texexec --make --all #{interface}"
+#                 two = "texexec --batch --silent --interface=#{interface} x-set-01"
+#                 if @commandline.option("force") then
+#                     system(one)
+#                     system(two)
+#                 elsif not system(two) then
+#                     system(one)
+#                     system(two)
+#                 end
+#             rescue
+#             end
+#
+#             unless File.file?(keyfile) then
+#                 report("no #{keyfile} generated")
+#                 next
+#             end
+#
+#             report("loading #{keyfile}")
+#
+#             begin
+#                 list = IO.read(keyfile)
+#             rescue
+#                 list = empty
+#             end
+#
+#             if list.empty? then
+#                 report("error in loading #{keyfile}")
+#                 next
+#             end
+#
+#             list.i_load('cd:variable', variables)
+#             list.i_load('cd:constant', constants)
+#             list.i_load('cd:command' , strings)
+#             # list.i_load('cd:element' , strings)
+#
+#             report("loading #{intfile}")
+#
+#             begin
+#                 data = IO.read(intfile)
+#             rescue
+#                 data = empty
+#             end
+#
+#             if data.empty? then
+#                 report("error in loading #{intfile}")
+#                 next
+#             end
+#
+#             report("translating interface en to #{interface}")
+#
+#             data.i_translate('cd:string'   , 'value', strings)
+#             data.i_translate('cd:variable' , 'value', variables)
+#             data.i_translate('cd:parameter', 'name' , constants)
+#             data.i_translate('cd:constant' , 'type' , variables)
+#             data.i_translate('cd:variable' , 'type' , variables)
+#             data.i_translate('cd:inherit'  , 'name' , strings)
+#             # data.i_translate('cd:command'  , 'name' , strings)
+#
+#             data.gsub!(/(\<cd\:interface[^\>]*?language=")en(")/) do
+#                 $1 + interface + $2
+#             end
+#
+#             report("saving #{outfile}")
+#
+#             begin
+#                 if f = File.open(outfile, 'w') then
+#                     f.write(data)
+#                     f.close
+#                 end
+#             rescue
+#             end
+#
+#         end
+#
+#     end
+#
+# end
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    # faster is to glob the whole dir and regexp over that list
+
+    def purgefiles
+
+        pattern  = @commandline.arguments
+        purgeall = @commandline.option("all")
+        recurse  = @commandline.option("recurse")
+
+        $dontaskprefixes.push(Dir.glob("mpx-*"))
+
+        if purgeall then
+            $dontaskprefixes.push(Dir.glob("*.tex.prep"))
+            $dontaskprefixes.push(Dir.glob("*.xml.prep"))
+        end
+
+        $dontaskprefixes.flatten!
+        $dontaskprefixes.sort!
+
+        if purgeall then
+          $forsuresuffixes.push($texnonesuffixes)
+          $texnonesuffixes = []
+          $forsuresuffixes.flatten!
+        end
+
+        if ! pattern || pattern.empty? then
+            globbed = if recurse then "**/*.*" else "*.*" end
+            files = Dir.glob(globbed)
+            report("purging#{if purgeall then ' all' end} temporary files : #{globbed}")
+        else
+            report("purging#{if purgeall then ' all' end} temporary files : #{pattern.join(' ')}")
+            pattern.each do |pat|
+                nosuf = File.unsuffixed(pat)
+                globbed = if recurse then "**/#{nosuf}-*.*" else "#{nosuf}-*.*" end
+                report("checking files that match '#{globbed}'")
+                files = Dir.glob(globbed)
+                globbed = if recurse then "**/#{nosuf}.*" else "#{nosuf}.*" end
+                report("checking files that match '#{globbed}'")
+                files.push(Dir.glob(globbed))
+            end
+        end
+        files.flatten!
+        files.sort!
+
+        $dontaskprefixes.each do |file|
+            removecontextfile(file)
+        end
+        $dontasksuffixes.each do |suffix|
+            files.each do |file|
+                removecontextfile(file) if file =~ /#{suffix}$/i
+            end
+        end
+        $forsuresuffixes.each do |suffix|
+            files.each do |file|
+                removecontextfile(file) if file =~ /\.#{suffix}$/i
+            end
+        end
+        files.each do |file|
+            if file =~ /(.*?)\.\d+$/o then
+                basename = $1
+                if file =~ /mp(graph|run)/o || FileTest.file?("#{basename}.mp") then
+                    removecontextfile($file)
+                end
+            end
+        end
+        $dummyfiles.each do |file|
+            (File.delete(file) if (FileTest.size?(file) rescue 10) < 10) rescue false
+        end
+        $texnonesuffixes.each do |suffix|
+            files.each do |file|
+                if file =~ /(.*)\.#{suffix}$/i then
+                    if FileTest.file?("#{$1}.tex") || FileTest.file?("#{$1}.xml") || FileTest.file?("#{$1}.fo") then
+                        keepcontextfile(file)
+                    else
+                        strippedname = $1.gsub(/\-[a-z]$/io, '')
+                        if FileTest.file?("#{strippedname}.tex") || FileTest.file?("#{strippedname}.xml") then
+                            keepcontextfile("#{file} (potential result file)")
+                        else
+                            removecontextfile(file)
+                        end
+                    end
+                end
+            end
+        end
+
+        files = Dir.glob("*.*")
+        $dontasksuffixes.each do |suffix|
+            files.each do |file|
+                removecontextfile(file) if file =~ /^#{suffix}$/i
+            end
+        end
+
+        if $removedfiles || $keptfiles || $persistentfiles then
+            report("removed files : #{$removedfiles}")
+            report("kept files : #{$keptfiles}")
+            report("persistent files : #{$persistentfiles}")
+            report("reclaimed bytes : #{$reclaimedbytes}")
+        end
+
+    end
+
+    private
+
+    $removedfiles    = 0
+    $keptfiles       = 0
+    $persistentfiles = 0
+    $reclaimedbytes  = 0
+
+    $dontaskprefixes = [
+        # "tex-form.tex", "tex-edit.tex", "tex-temp.tex",
+        "texexec.tex", "texexec.tui", "texexec.tuo",
+        "texexec.tuc", "texexec.tua",
+        "texexec.ps", "texexec.pdf", "texexec.dvi",
+        "cont-opt.tex", "cont-opt.bak"
+    ]
+    $dontasksuffixes = [
+        "mp(graph|run)\\.mp", "mp(graph|run)\\.mpd", "mp(graph|run)\\.mpo", "mp(graph|run)\\.mpy",
+        "mp(graph|run)\\.\\d+", "mp(graph|run)\\.mp.keep",
+        "xlscript\\.xsl"
+    ]
+    $forsuresuffixes = [
+        "tui", "tua", "tup", "ted", "tes", "top",
+        "log", "tmp", "run", "bck", "rlg",
+        "mpt", "mpx", "mpd", "mpo", "mpb",
+        "ctl",
+        "pgf", "synctex.gz",
+        "tmp.md5", "tmp.out"
+    ]
+    $texonlysuffixes = [
+        "dvi", "ps", "pdf"
+    ]
+    $texnonesuffixes = [
+        "tuo", "tub", "top", "tuc"
+    ]
+    $dummyfiles = [
+        # "mpgraph"
+    ]
+
+    def removecontextfile (filename)
+        if filename && FileTest.file?(filename) then
+            begin
+                filesize = FileTest.size(filename)
+                File.delete(filename)
+            rescue
+                report("problematic : #{filename}")
+            else
+                if FileTest.file?(filename) then
+                    $persistentfiles += 1
+                    report("persistent : #{filename}")
+                else
+                    $removedfiles += 1
+                    $reclaimedbytes += filesize
+                    report("removed : #{filename}")
+                end
+            end
+        end
+    end
+
+    def keepcontextfile (filename)
+        if filename && FileTest.file?(filename)  then
+            $keptfiles += 1
+            report("not removed : #{filename}")
+        end
+    end
+
+end
+
+#D Documentation can be woven into a source file. The next
+#D routine generates a new, \TEX\ ready file with the
+#D documentation and source fragments properly tagged. The
+#D documentation is included as comment:
+#D
+#D \starttypen
+#D %D ......  some kind of documentation
+#D %M ......  macros needed for documenation
+#D %S B       begin skipping
+#D %S E       end skipping
+#D \stoptypen
+#D
+#D The most important tag is \type {%D}. Both \TEX\ and \METAPOST\
+#D files use \type{%} as a comment chacacter, while \PERL, \RUBY\
+#D and alike use \type{#}. Therefore \type{#D} is also handled.
+#D
+#D The generated file gets the suffix \type{ted} and is
+#D structured as:
+#D
+#D \starttypen
+#D \startmoduledocumentation[type=suffix]
+#D \startdocumentation
+#D \stopdocumentation
+#D \startdefinition
+#D \stopdefinition
+#D \stopmoduledocumentation
+#D \stoptypen
+#D
+#D Macro definitions specific to the documentation are not
+#D surrounded by start||stop commands. The suffix specifaction
+#D can be overruled at runtime, but defaults to the file
+#D extension. This specification can be used for language
+#D depended verbatim typesetting.
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    def documentation
+        files = @commandline.arguments
+        processtype = @commandline.option("type")
+        files.each do |fullname|
+            if fullname =~ /(.*)\.(.+?)$/o then
+                filename, filesuffix = $1, $2
+            else
+                filename, filesuffix = fullname, 'tex'
+            end
+            filesuffix = 'tex' if filesuffix.empty?
+            fullname, resultname = "#{filename}.#{filesuffix}", "#{filename}.ted"
+            if ! FileTest.file?(fullname)
+                report("empty input file #{fullname}")
+            elsif ! tex = File.open(fullname)
+                report("invalid input file #{fullname}")
+            elsif ! ted = File.open(resultname,'w') then
+                report("unable to openresult file #{resultname}")
+            else
+                report("input file : #{fullname}")
+                report("output file : #{resultname}")
+                nofdocuments, nofdefinitions, nofskips = 0, 0, 0
+                skiplevel, indocument, indefinition, skippingbang = 0, false, false, false
+                if processtype.empty? then
+                  filetype = filesuffix.downcase.sub(/^mk.+$/,'tex') # make sure that mkii and mkiv files are handled
+                else
+                  filetype = processtype.downcase
+                end
+                report("filetype : #{filetype}")
+                # we need to signal to texexec what interface to use
+                firstline = tex.gets
+                if firstline =~ /^\%.*interface\=/ then
+                  ted.puts(firstline)
+                else
+                  tex.rewind # seek(0)
+                end
+                ted.puts("\\startmoduledocumentation[type=#{filetype}]\n")
+                while str = tex.gets do
+                    if skippingbang then
+                        skippingbang = false
+                    else
+                        str.chomp!
+                        str.sub!(/\s*$/o, '')
+                        case str
+                            when /^[%\#]D($| )/io then
+                                if skiplevel == 0 then
+                                    someline = if str.length < 3 then "" else str[3,str.length-1] end
+                                    if indocument then
+                                        ted.puts("#{someline}\n")
+                                    else
+                                        if indefinition then
+                                            ted.puts("\\stopdefinition\n")
+                                            indefinition = false
+                                        end
+                                        unless indocument then
+                                            ted.puts("\n\\startdocumentation\n")
+                                        end
+                                        ted.puts("#{someline}\n")
+                                        indocument = true
+                                        nofdocuments += 1
+                                    end
+                                end
+                            when /^[%\#]M($| )/io then
+                                if skiplevel == 0 then
+                                    someline = if str.length < 3 then "" else str[3,str.length-1] end
+                                    ted.puts("#{someline}\n")
+                                end
+                            when /^[%\%]S B/io then
+                                skiplevel += 1
+                                nofskips += 1
+                            when /^[%\%]S E/io then
+                                  skiplevel -= 1
+                            when /^[%\#]/io then
+                                  #nothing
+                            when /^eval \'\(exit \$\?0\)\' \&\& eval \'exec perl/o then
+                                skippingbang = true
+                            else
+                                if skiplevel == 0 then
+                                    inlocaldocument = indocument
+                                    inlocaldocument = false # else first line skipped when not empty
+                                    someline = str
+                                    if indocument then
+                                        ted.puts("\\stopdocumentation\n")
+                                        indocument = false
+                                    end
+                                    if indefinition then
+                                        if someline.empty? then
+                                            ted.puts("\\stopdefinition\n")
+                                            indefinition = false
+                                        else
+                                            ted.puts("#{someline}\n")
+                                        end
+                                    elsif ! someline.empty? then
+                                        ted.puts("\n\\startdefinition\n")
+                                        indefinition = true
+                                        if inlocaldocument then
+                                            # nothing
+                                        else
+                                            nofdefinitions += 1
+                                            ted.puts("#{someline}\n")
+                                        end
+                                    end
+                                end
+                        end
+                    end
+                end
+                if indocument then
+                    ted.puts("\\stopdocumentation\n")
+                end
+                if indefinition then
+                    ted.puts("\\stopdefinition\n")
+                end
+                ted.puts("\\stopmoduledocumentation\n")
+                ted.close
+
+                if nofdocuments == 0 && nofdefinitions == 0 then
+                    begin
+                        File.delete(resultname)
+                    rescue
+                    end
+                end
+                report("documentation sections : #{nofdocuments}")
+                report("definition sections : #{nofdefinitions}")
+                report("skipped sections : #{nofskips}")
+            end
+        end
+    end
+
+end
+
+#D This feature was needed when \PDFTEX\ could not yet access page object
+#D numbers (versions prior to 1.11).
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    def filterpages # temp feature / no reporting
+        filename = @commandline.argument('first')
+        filename.sub!(/\.([a-z]+?)$/io,'')
+        pdffile = "#{filename}.pdf"
+        tuofile = "#{filename}.tuo"
+        if FileTest.file?(pdffile) then
+            begin
+                prevline, n = '', 0
+                if (pdf = File.open(pdffile)) && (tuo = File.open(tuofile,'a')) then
+                    report('filtering page object numbers')
+                    pdf.binmode
+                    while line = pdf.gets do
+                        line.chomp
+                        # typical pdftex search
+                        if (line =~ /\/Type \/Page/o) && (prevline =~ /^(\d+)\s+0\s+obj/o) then
+                            p = $1
+                            n += 1
+                            tuo.puts("\\objectreference{PDFP}{#{n}}{#{p}}{#{n}}\n")
+                        else
+                            prevline = line
+                        end
+                    end
+                end
+                pdf.close
+                tuo.close
+                report("number of pages : #{n}")
+            rescue
+                report("fatal error in filtering pages")
+            end
+        end
+    end
+
+end
+
+# This script is used to generate hyphenation pattern files
+# that suit ConTeXt. One reason for independent files is that
+# over the years too many uncommunicated changes took place
+# as well that inconsistency in content, naming, and location
+# in the texmf tree takes more time than I'm willing to spend
+# on it. Pattern files are normally shipped for LaTeX (and
+# partially plain). A side effect of independent files is that
+# we can make them encoding independent.
+#
+# Maybe I'll make this hyptools.tex
+
+class String
+
+    def markbraces
+        level = 0
+        self.gsub(/([\{\}])/o) do |chr|
+            if    chr == '{' then
+                level = level + 1
+                chr = "((+#{level}))"
+            elsif chr == '}' then
+                chr = "((-#{level}))"
+                level = level - 1
+            end
+            chr
+        end
+    end
+
+    def unmarkbraces
+        self.gsub(/\(\(\+\d+?\)\)/o) do
+            "{"
+        end .gsub(/\(\(\-\d+?\)\)/o) do
+            "}"
+        end
+    end
+
+    def getargument(pattern)
+        if self =~ /(#{pattern})\s*\(\(\+(\d+)\)\)(.*?)\(\(\-\2\)\)/m then # no /o
+            return $3
+        else
+            return ""
+        end
+    end
+
+    def withargument(pattern, &block)
+        if self.markbraces =~ /^(.*)(#{pattern}\s*)\(\(\+(\d+)\)\)(.*?)\(\(\-\3\)\)(.*)$/m then # no /o
+            "#{$1.unmarkbraces}#{$2}{#{yield($4.unmarkbraces)}}#{$5.unmarkbraces}"
+        else
+            self
+        end
+    end
+
+    def filterargument(pattern, &block)
+        if self.markbraces =~ /^(.*)(#{pattern}\s*)\(\(\+(\d+)\)\)(.*?)\(\(\-\3\)\)(.*)$/m then # no /o
+            yield($4.unmarkbraces)
+        else
+            self
+        end
+    end
+
+end
+
+class Language
+
+    include CommandBase
+
+    def initialize(commandline=nil, language='en', filenames=nil, encoding='ec')
+        @commandline= commandline
+        @language = language
+        @filenames = filenames
+        @remapping = Array.new
+        @demapping = Array.new
+        @cloning = Array.new
+        @unicode = Hash.new
+        @encoding = encoding
+        @data = ''
+        @read = ''
+        preload_accents()
+        preload_unicode() if @commandline.option('utf8')
+        case @encoding.downcase
+            when 't1', 'ec', 'cork' then preload_vector('ec',       'enco-ec.tex')
+            when 'y', 'texnansi'    then preload_vector('texnansi', 'enco-ans.tex')
+            when 'agr', 'agreek'    then preload_vector('agr',      'enco-agr.tex')
+            when 't2a'              then preload_vector('t2a',      'enco-cyr.tex')
+            when 'cyr'              then preload_vector() # somehow loading t2a does not work out well
+        end
+    end
+
+    def report(str)
+        if @commandline then
+            @commandline.report(str)
+        else
+            puts("#{str}\n")
+        end
+    end
+
+    def remap(from, to)
+        @remapping.push([from,to])
+    end
+    def demap(from, to)
+        @demapping.push([from,to])
+    end
+    def clone(from, to)
+        @cloning.push([from,to])
+    end
+
+    def load(filenames=@filenames)
+        found = false
+        begin
+            if filenames then
+                @filenames.each do |fileset|
+                    [fileset].flatten.each do |filename|
+                        begin
+                            if fname = located(filename) then
+                                data = IO.read(fname)
+                                @data += data.gsub(/\%.*$/, '').gsub(/\\message\{.*?\}/, '')
+                                data.gsub!(/(\\patterns|\\hyphenation)\s*\{.*/mo) do '' end
+                                @read += "\n% preamble of file #{fname}\n\n#{data}\n"
+                                @data.gsub!(/^[\s\n]+$/moi, '')
+                                report("file #{fname} is loaded")
+                                found = true
+                                break # next fileset
+                            end
+                        rescue
+                            report("file #{filename} is not readable")
+                        end
+                    end
+                end
+            end
+        rescue
+        end
+        return found
+    end
+
+    def valid?
+        ! @data.empty?
+    end
+
+    def convert
+        if @data then
+            n = 0
+            if true then
+                report("")
+                ["\\patterns","\\hyphenation"].each do |what|
+                    @data = @data.withargument(what) do |content|
+                        report("converting #{what}")
+                        report("")
+                        @demapping.each_index do |i|
+                            content.gsub!(@demapping[i][0], @demapping[i][1])
+                        end
+                        content.gsub!(/\\delete\{.*?\}/o) do '' end
+                        content.gsub!(/\\keep\{(.*?)\}/o) do $1 end
+                        done = false
+                        @remapping.each_index do |i|
+                            from, to, m = @remapping[i][0], @remapping[i][1], 0
+                            content.gsub!(from) do
+                                done = true
+                                m += 1
+                                "[#{i}]"
+                            end
+                            report("#{m.to_s.rjust(5)} entries remapped to #{to}") unless m == 0
+                            n += m
+                        end
+                        content.gsub!(/\[(\d+)\]/o) do
+                            @remapping[$1.to_i][1]
+                        end
+                        report("      nothing remapped") unless done
+                        @cloning.each_index do |i|
+                            c = 0
+                            f, s = @cloning[i][0], @cloning[i][1]
+                            str = "#{f}|#{s}"
+                            str.gsub!(/([\[\]])/) do "\\" + "#{$1}" end
+                            reg = /(#{str})/
+                            content.gsub!(/(\S*(#{str})\S*)/) do
+                                a, b = $1, $1
+                                a.gsub!(reg, f)
+                                b.gsub!(reg, s)
+                                c = c + 1
+                                "#{a} #{b}"
+                            end
+                            report("#{c.to_s.rjust(5)} times #{f} cloned to #{s}")
+                            n += c
+                        end
+                        report("")
+                        content.to_s
+                    end
+                end
+            else
+                @remapping.each do |k|
+                    from, to, m = k[0], k[1], 0
+                    @data.gsub!(from) do
+                        m += 1
+                        to
+                    end
+                    report("#{m.to_s.rjust(5)} entries remapped to #{to}") unless m == 0
+                    n += m
+                end
+            end
+            report("#{n} changes in patterns and exceptions")
+            if @commandline.option('utf8') then
+                n = 0
+                @data.gsub!(/\[(.*?)\]/o) do
+                    n += 1
+                    @unicode[$1] || $1
+                end
+                report("#{n} unicode utf8 entries")
+            end
+            return true
+        else
+            return false
+        end
+    end
+
+    def comment(str)
+        str.gsub!(/^\n/o, '')
+        str.chomp!
+        if @commandline.option('xml') then
+            "<!-- #{str.strip} -->\n\n"
+        else
+            "% #{str.strip}\n\n"
+        end
+    end
+
+    def content(tag, str)
+        lst = str.split(/\s+/)
+        lst.collect! do |l|
+            l.strip
+        end
+        if lst.length>0 then
+            lst = "\n#{lst.join("\n")}\n"
+        else
+            lst = ""
+        end
+        if @commandline.option('xml') then
+            lst.gsub!(/\[(.*?)\]/o) do
+                "&#{$1};"
+            end
+            "<#{tag}>#{lst}</#{tag}>\n\n"
+        else
+            "\\#{tag} \{#{lst}\}\n\n"
+        end
+    end
+
+    def banner
+        if @commandline.option('xml') then
+            "<?xml version='1.0' standalone='yes' ?>\n\n"
+        end
+    end
+
+    def triggerunicode
+        return
+        if @commandline.option('utf8') then
+            "% xetex needs utf8 encoded patterns and for patterns\n" +
+            "% coded as such we need to enable this regime when\n" +
+            "% not in xetex; this code will be moved into context\n" +
+            "% as soon as we've spread the generic patterns\n" +
+            "\n" +
+            "\\ifx\\XeTeXversion\\undefined \\else\n" +
+            "  \\ifx\\enableregime\\undefined \\else\n" +
+            "    \\enableregime[utf]\n" +
+            "  \\fi\n" +
+            "\\fi\n" +
+            "\n"
+        end
+    end
+
+    def save
+        xml = @commandline.option("xml")
+
+        patname = "lang-#{@language}.pat"
+        hypname = "lang-#{@language}.hyp"
+        rmename = "lang-#{@language}.rme"
+        logname = "lang-#{@language}.log"
+
+        desname = "lang-all.xml"
+
+        @data.gsub!(/\\[nc]\{(.+?)\}/)  do $1    end
+        @data.gsub!(/\{\}/)             do ''    end
+        @data.gsub!(/\n+/mo)            do "\n"  end
+        @read.gsub!(/\n+/mo)            do "\n"  end
+
+        description = ''
+        commentfile = rmename.dup
+
+        begin
+            desfile = Kpse.found(desname,'context')
+            if f = File.new(desfile) then
+                if doc = REXML::Document.new(f) then
+                    if e = REXML::XPath.first(doc.root,"/descriptions/description[@language='#{@language}']") then
+                        description = e.to_s
+                    end
+                end
+            end
+        rescue
+            description = ''
+        else
+            unless description.empty? then
+                commentfile = desname.dup
+                str  = "<!-- copied from lang-all.xml\n\n"
+                str << "<?xml version='1.0' standalone='yes'?>\n\n"
+                str << description.chomp
+                str << "\n\nend of copy -->\n"
+                str.gsub!(/^/io, "% ") unless @commandline.option('xml')
+                description =  comment("begin description data")
+                description << str + "\n"
+                description << comment("end description data")
+                report("description found for language #{@language}")
+            end
+        end
+
+        begin
+            if description.empty? || @commandline.option('log') then
+                if f = File.open(logname,'w') then
+                    report("saving #{@remapping.length} remap patterns in #{logname}")
+                    @remapping.each do |m|
+                        f.puts("#{m[0].inspect} => #{m[1]}\n")
+                    end
+                    f.close
+                end
+            else
+                File.delete(logname) if FileTest.file?(logname)
+            end
+        rescue
+        end
+
+        begin
+            if description.empty? || @commandline.option('log') then
+                if f = File.open(rmename,'w') then
+                    data = @read.dup
+                    data.gsub!(/(\s*\n\s*)+/mo, "\n")
+                    f << comment("comment copied from public hyphenation files}")
+                    f << comment("source of data: #{@filenames.join(' ')}")
+                    f << comment("begin original comment")
+                    f << "#{data}\n"
+                    f << comment("end original comment")
+                    f.close
+                    report("comment saved in file #{rmename}")
+                else
+                    report("file #{rmename} is not writable")
+                end
+            else
+                File.delete(rmename) if FileTest.file?(rmename)
+            end
+        rescue
+        end
+
+        begin
+            if f = File.open(patname,'w') then
+                data = ''
+                @data.filterargument('\\patterns') do |content|
+                    report("merging patterns")
+                    data += content.strip
+                end
+                data.gsub!(/(\s*\n\s*)+/mo, "\n")
+
+                f << banner
+                f << comment("context pattern file, see #{commentfile} for original comment")
+                f << comment("source of data: #{@filenames.join(' ')}")
+                f << description
+                f << comment("begin pattern data")
+                f << triggerunicode
+                f << content('patterns', data)
+                f << comment("end pattern data")
+                f.close
+                report("patterns saved in file #{patname}")
+            else
+                report("file #{patname} is not writable")
+            end
+        rescue
+            report("problems with file #{patname}")
+        end
+
+        begin
+            if f = File.open(hypname,'w') then
+                data = ''
+                @data.filterargument('\\hyphenation') do |content|
+                    report("merging exceptions")
+                    data += content.strip
+                end
+                data.gsub!(/(\s*\n\s*)+/mo, "\n")
+                f << banner
+                f << comment("context hyphenation file, see #{commentfile} for original comment")
+                f << comment("source of data: #{@filenames.join(' ')}")
+                f << description
+                f << comment("begin hyphenation data")
+                f << triggerunicode
+                f << content('hyphenation', data)
+                f << comment("end hyphenation data")
+                f.close
+                report("exceptions saved in file #{hypname}")
+            else
+                report("file #{hypname} is not writable")
+            end
+        rescue
+            report("problems with file #{hypname}")
+        end
+    end
+
+    def process
+        load
+        if valid? then
+            convert
+            save
+        else
+            report("aborted due to missing files")
+        end
+    end
+
+    def Language::generate(commandline, language='', filenames='', encoding='ec')
+        if ! language.empty? && ! filenames.empty? then
+            commandline.report("processing language #{language}")
+            commandline.report("")
+            language = Language.new(commandline,language,filenames,encoding)
+            if language.load then
+                language.convert
+                language.save
+                commandline.report("")
+            end
+        end
+    end
+
+    private
+
+    def located(filename)
+        begin
+            ["context","plain","latex"].each do |name| # fallbacks needed for czech patterns
+                fname = Kpse.found(filename, name)
+                if FileTest.file?(fname) then
+                    report("using file #{fname}")
+                    return fname
+                end
+            end
+            report("file #{filename} is not present")
+            return nil
+        rescue
+            report("file #{filename} cannot be located using kpsewhich")
+            return nil
+        end
+    end
+
+    def preload_accents
+
+        begin
+            if filename = located("enco-acc.tex") then
+                if data = IO.read(filename) then
+                    report("preloading accent conversions")
+                    data.scan(/\\defineaccent\s*\\*(.+?)\s*\{*(.+?)\}*\s*\{\\(.+?)\}/o) do
+                        one, two, three = $1, $2, $3
+                        one.gsub!(/[\`\~\!\^\*\_\-\+\=\:\;\"\'\,\.\?]/o) do
+                            "\\#{one}"
+                        end
+                        remap(/\\#{one} #{two}/, "[#{three}]")
+                        remap(/\\#{one}#{two}/, "[#{three}]")  unless one =~ /[a-zA-Z]/o
+                        remap(/\\#{one}\{#{two}\}/, "[#{three}]")
+                    end
+                end
+            end
+        rescue
+        end
+
+    end
+
+    def preload_unicode
+
+        # \definecharacter Agrave {\uchar0{192}}
+
+        begin
+            if filename = located("enco-uc.tex") then
+                if data = IO.read(filename) then
+                    report("preloading unicode conversions")
+                    data.scan(/\\definecharacter\s*(.+?)\s*\{\\uchar\{*(\d+)\}*\s*\{(\d+)\}/o) do
+                        one, two, three = $1, $2.to_i, $3.to_i
+                        @unicode[one] = [(two*256 + three)].pack("U")
+                    end
+                end
+            end
+        rescue
+            report("error in loading unicode mapping (#{$!})")
+        end
+
+    end
+
+    def preload_vector(encoding='', filename='')
+
+        # funny polish
+
+        case @language
+            when 'pl' then
+                remap(/\/a/, "[aogonek]")    ; remap(/\/A/, "[Aogonek]")
+                remap(/\/c/, "[cacute]")     ; remap(/\/C/, "[Cacute]")
+                remap(/\/e/, "[eogonek]")    ; remap(/\/E/, "[Eogonek]")
+                remap(/\/l/, "[lstroke]")    ; remap(/\/L/, "[Lstroke]")
+                remap(/\/n/, "[nacute]")     ; remap(/\/N/, "[Nacute]")
+                remap(/\/o/, "[oacute]")     ; remap(/\/O/, "[Oacute]")
+                remap(/\/s/, "[sacute]")     ; remap(/\/S/, "[Sacute]")
+                remap(/\/x/, "[zacute]")     ; remap(/\/X/, "[Zacute]")
+                remap(/\/z/, "[zdotaccent]") ; remap(/\/Z/, "[Zdotaccent]")
+            when 'sl' then
+                remap(/\"c/,"[ccaron]")  ; remap(/\"C/,"[Ccaron]")
+                remap(/\"s/,"[scaron]")  ; remap(/\"S/,"[Scaron]")
+                remap(/\"z/,"[zcaron]")  ; remap(/\"Z/,"[Zcaron]")
+            when 'da' then
+                remap(/X/, "[aeligature]")
+                remap(/Y/, "[ostroke]")
+                remap(/Z/, "[aring]")
+            when 'hu' then
+                # nothing
+            when 'ca' then
+                demap(/\\c\{/, "\\delete{")
+            when 'de', 'deo' then
+                demap(/\\c\{/, "\\delete{")
+                demap(/\\n\{/, "\\keep{")
+                remap(/\\3/, "[ssharp]")
+                remap(/\\9/, "[ssharp]")
+                remap(/\"a/, "[adiaeresis]")
+                remap(/\"o/, "[odiaeresis]")
+                remap(/\"u/, "[udiaeresis]")
+            when 'fr' then
+                demap(/\\n\{/, "\\delete{")
+                remap(/\\ae/, "[aeligature]")
+                remap(/\\oe/, "[oeligature]")
+            when 'la' then
+                # \lccode`'=`' somewhere else, todo
+                demap(/\\c\{/, "\\delete{")
+                remap(/\\a\s*/, "[aeligature]")
+                remap(/\\o\s*/, "[oeligature]")
+            when 'agr' then
+                # bug fix
+                remap("a2|", "[greekalphaiotasub]")
+                remap("h2|", "[greeketaiotasub]")
+                remap("w2|", "[greekomegaiotasub]")
+         		remap(">2r1<2r", "[2ῤ1ῥ]")
+                remap(">a2n1wdu'", "[ἀ2ν1ωδύ]")
+                remap(">e3s2ou'", "[ἐ3σ2ού]")
+                # main conversion
+                remap(/\<\'a\|/, "[greekalphaiotasubdasiatonos]")
+                # remap(/\<\'a\|/, "[greekdasiatonos][greekAlpha][greekiota]")
+                remap(/\>\'a\|/, "[greekalphaiotasubpsilitonos]")
+                remap(/\<\`a\|/, "[greekalphaiotasubdasiavaria]")
+                remap(/\>\`a\|/, "[greekalphaiotasubpsilivaria]")
+                remap(/\<\~a\|/, "[greekalphaiotasubdasiaperispomeni]")
+                remap(/\>\~a\|/, "[greekalphaiotasubpsiliperispomeni]")
+                remap(/\'a\|/,   "[greekalphaiotasubtonos]")
+                remap(/\`a\|/,   "[greekalphaiotasubvaria]")
+                remap(/\~a\|/,   "[greekalphaiotasubperispomeni]")
+                remap(/\<a\|/,   "[greekalphaiotasubdasia]")
+                remap(/\>a\|/,   "[greekalphaiotasubpsili]")
+                remap(/a\|/,     "[greekalphaiotasub]")
+                remap(/\<\'h\|/, "[greeketaiotasubdasiatonos]")
+                remap(/\>\'h\|/, "[greeketaiotasubpsilitonos]")
+                remap(/\<\`h\|/, "[greeketaiotasubdasiavaria]")
+                remap(/\>\`h\|/, "[greeketaiotasubpsilivaria]")
+                remap(/\<\~h\|/, "[greeketaiotasubdasiaperispomeni]")
+                remap(/\>\~h\|/, "[greeketaiotasubpsiliperispomeni]")
+                remap(/\'h\|/,   "[greeketaiotasubtonos]")
+                remap(/\`h\|/,   "[greeketaiotasubvaria]")
+                remap(/\~h\|/,   "[greeketaiotasubperispomeni]")
+                remap(/\<h\|/,   "[greeketaiotasubdasia]")
+                remap(/\>h\|/,   "[greeketaiotasubpsili]")
+                remap(/h\|/,     "[greeketaiotasub]")
+                remap(/\<'w\|/,  "[greekomegaiotasubdasiatonos]")
+                remap(/\>'w\|/,  "[greekomegaiotasubpsilitonos]")
+                remap(/\<`w\|/,  "[greekomegaiotasubdasiavaria]")
+                remap(/\>`w\|/,  "[greekomegaiotasubpsilivaria]")
+                remap(/\<~w\|/,  "[greekomegaiotasubdasiaperispomeni]")
+                remap(/\>~w\|/,  "[greekomegaiotasubpsiliperispomeni]")
+                remap(/\<w\|/,   "[greekomegaiotasubdasia]")
+                remap(/\>w\|/,   "[greekomegaiotasubpsili]")
+                remap(/\'w\|/,   "[greekomegaiotasubtonos]")
+                remap(/\`w\|/,   "[greekomegaiotasubvaria]")
+                remap(/\~w\|/,   "[greekomegaiotasubperispomeni]")
+                remap(/w\|/,     "[greekomegaiotasub]")
+                remap(/\<\'i/,   "[greekiotadasiatonos]")
+                remap(/\>\'i/,   "[greekiotapsilitonos]")
+                remap(/\<\`i/,   "[greekiotadasiavaria]")
+                remap(/\>\`i/,   "[greekiotapsilivaria]")
+                remap(/\<\~i/,   "[greekiotadasiaperispomeni]")
+                remap(/\>\~i/,   "[greekiotapsiliperispomeni]")
+                remap(/\"\'i/,   "[greekiotadialytikatonos]")
+                remap(/\"\`i/,   "[greekiotadialytikavaria]")
+                remap(/\"\~i/,   "[greekiotadialytikaperispomeni]")
+                remap(/\<i/,     "[greekiotadasia]")
+                remap(/\>i/,     "[greekiotapsili]")
+                remap(/\'i/,     "[greekiotaoxia]")
+                remap(/\`i/,     "[greekiotavaria]")
+                remap(/\~i/,     "[greekiotaperispomeni]")
+                remap(/\"i/,     "[greekiotadialytika]")
+                remap(/\>\~e/,   "[greekepsilonpsiliperispomeni]")
+                remap(/\<\~e/,   "[greekepsilondasiaperispomeni]")
+                remap(/\<\'e/,   "[greekepsilondasiatonos]")
+                remap(/\>\'e/,   "[greekepsilonpsilitonos]")
+                remap(/\<\`e/,   "[greekepsilondasiavaria]")
+                remap(/\>\`e/,   "[greekepsilonpsilivaria]")
+                remap(/\<e/,     "[greekepsilondasia]")
+                remap(/\>e/,     "[greekepsilonpsili]")
+                remap(/\'e/,     "[greekepsilonoxia]")
+                remap(/\`e/,     "[greekepsilonvaria]")
+                remap(/\~e/,     "[greekepsilonperispomeni]")
+                remap(/\<\'a/,   "[greekalphadasiatonos]")
+                remap(/\>\'a/,   "[greekalphapsilitonos]")
+                remap(/\<\`a/,   "[greekalphadasiavaria]")
+                remap(/\>\`a/,   "[greekalphapsilivaria]")
+                remap(/\<\~a/,   "[greekalphadasiaperispomeni]")
+                remap(/\>\~a/,   "[greekalphapsiliperispomeni]")
+                remap(/\<a/,     "[greekalphadasia]")
+                remap(/\>a/,     "[greekalphapsili]")
+                remap(/\'a/,     "[greekalphaoxia]")
+                remap(/\`a/,     "[greekalphavaria]")
+                remap(/\~a/,     "[greekalphaperispomeni]")
+                remap(/\<\'h/,   "[greeketadasiatonos]")
+                remap(/\>\'h/,   "[greeketapsilitonos]")
+                remap(/\<\`h/,   "[greeketadasiavaria]")
+                remap(/\>\`h/,   "[greeketapsilivaria]")
+                remap(/\<\~h/,   "[greeketadasiaperispomeni]")
+                remap(/\>\~h/,   "[greeketapsiliperispomeni]")
+                remap(/\<h/,     "[greeketadasia]")
+                remap(/\>h/,     "[greeketapsili]")
+                remap(/\'h/,     "[greeketaoxia]")
+                remap(/\`h/,     "[greeketavaria]")
+                remap(/\~h/,     "[greeketaperispomeni]")
+                remap(/\<\~o/,   "[greekomicrondasiaperispomeni]")
+                remap(/\>\~o/,   "[greekomicronpsiliperispomeni]")
+                remap(/\<\'o/,   "[greekomicrondasiatonos]")
+                remap(/\>\'o/,   "[greekomicronpsilitonos]")
+                remap(/\<\`o/,   "[greekomicrondasiavaria]")
+                remap(/\>\`o/,   "[greekomicronpsilivaria]")
+                remap(/\<o/,     "[greekomicrondasia]")
+                remap(/\>o/,     "[greekomicronpsili]")
+                remap(/\'o/,     "[greekomicronoxia]")
+                remap(/\`o/,     "[greekomicronvaria]")
+                remap(/\~o/,     "[greekomicronperispomeni]")
+                remap(/\<\'u/,   "[greekupsilondasiatonos]")
+                remap(/\>\'u/,   "[greekupsilonpsilitonos]")
+                remap(/\<\`u/,   "[greekupsilondasiavaria]")
+                remap(/\>\`u/,   "[greekupsilonpsilivaria]")
+                remap(/\<\~u/,   "[greekupsilondasiaperispomeni]")
+                remap(/\>\~u/,   "[greekupsilonpsiliperispomeni]")
+                remap(/\"\'u/,   "[greekupsilondialytikatonos]")
+                remap(/\"\`u/,   "[greekupsilondialytikavaria]")
+                remap(/\"\~u/,   "[greekupsilondialytikaperispomeni]")
+                remap(/\<u/,     "[greekupsilondasia]")
+                remap(/\>u/,     "[greekupsilonpsili]")
+                remap(/\'u/,     "[greekupsilonoxia]")
+                remap(/\`u/,     "[greekupsilonvaria]")
+                remap(/\~u/,     "[greekupsilonperispomeni]")
+                remap(/\"u/,     "[greekupsilondiaeresis]")
+                remap(/\<\'w/,   "[greekomegadasiatonos]")
+                remap(/\>\'w/,   "[greekomegapsilitonos]")
+                remap(/\<\`w/,   "[greekomegadasiavaria]")
+                remap(/\>\`w/,   "[greekomegapsilivaria]")
+                remap(/\<\~w/,   "[greekomegadasiaperispomeni]")
+                remap(/\>\~w/,   "[greekomegapsiliperispomeni]")
+                remap(/\<w/,     "[greekomegadasia]")
+                remap(/\>w/,     "[greekomegapsili]")
+                remap(/\'w/,     "[greekomegaoxia]")
+                remap(/\`w/,     "[greekomegavaria]")
+                remap(/\~w/,     "[greekomegaperispomeni]")
+                remap(/\<r/,     "[greekrhodasia]")
+                remap(/\>r/,     "[greekrhopsili]")
+                remap(/\<\~/,    "[greekdasiaperispomeni]")
+                remap(/\>\~/,    "[greekpsiliperispomeni]")
+                remap(/\<\'/,    "[greekdasiatonos]")
+                remap(/\>\'/,    "[greekpsilitonos]")
+                remap(/\<\`/,    "[greekdasiavaria]")
+                remap(/\>\`/,    "[greekpsilivaria]")
+                remap(/\"\'/,    "[greekdialytikatonos]")
+                remap(/\"\`/,    "[greekdialytikavaria]")
+                remap(/\"\~/,    "[greekdialytikaperispomeni]")
+                remap(/\</,      "[greekdasia]")
+                remap(/\>/,      "[greekpsili]")
+                remap(/\d.{0,2}''/, "")
+                remap(/\'/,      "[greekoxia]")
+                remap(/\`/,      "[greekvaria]")
+                remap(/\~/,      "[perispomeni]")
+                remap(/\"/,      "[greekdialytika]")
+                # unknown
+                # remap(/\|/,      "[greekIotadialytika]")
+                # next
+                remap(/A/, "[greekAlpha]")
+                remap(/B/, "[greekBeta]")
+                remap(/D/, "[greekDelta]")
+                remap(/E/, "[greekEpsilon]")
+                remap(/F/, "[greekPhi]")
+                remap(/G/, "[greekGamma]")
+                remap(/H/, "[greekEta]")
+                remap(/I/, "[greekIota]")
+                remap(/J/, "[greekTheta]")
+                remap(/K/, "[greekKappa]")
+                remap(/L/, "[greekLambda]")
+                remap(/M/, "[greekMu]")
+                remap(/N/, "[greekNu]")
+                remap(/O/, "[greekOmicron]")
+                remap(/P/, "[greekPi]")
+                remap(/Q/, "[greekChi]")
+                remap(/R/, "[greekRho]")
+                remap(/S/, "[greekSigma]")
+                remap(/T/, "[greekTau]")
+                remap(/U/, "[greekUpsilon]")
+                remap(/W/, "[greekOmega]")
+                remap(/X/, "[greekXi]")
+                remap(/Y/, "[greekPsi]")
+                remap(/Z/, "[greekZeta]")
+                remap(/a/, "[greekalpha]")
+                remap(/b/, "[greekbeta]")
+                remap(/c/, "[greekfinalsigma]")
+                remap(/d/, "[greekdelta]")
+                remap(/e/, "[greekepsilon]")
+                remap(/f/, "[greekphi]")
+                remap(/g/, "[greekgamma]")
+                remap(/h/, "[greeketa]")
+                remap(/i/, "[greekiota]")
+                remap(/j/, "[greektheta]")
+                remap(/k/, "[greekkappa]")
+                remap(/l/, "[greeklambda]")
+                remap(/m/, "[greekmu]")
+                remap(/n/, "[greeknu]")
+                remap(/o/, "[greekomicron]")
+                remap(/p/, "[greekpi]")
+                remap(/q/, "[greekchi]")
+                remap(/r/, "[greekrho]")
+                remap(/s/, "[greeksigma]")
+                remap(/t/, "[greektau]")
+                remap(/u/, "[greekupsilon]")
+                remap(/w/, "[greekomega]")
+                remap(/x/, "[greekxi]")
+                remap(/y/, "[greekpsi]")
+                remap(/z/, "[greekzeta]")
+                clone("[greekalphatonos]", "[greekalphaoxia]")
+                clone("[greekepsilontonos]", "[greekepsilonoxia]")
+                clone("[greeketatonos]", "[greeketaoxia]")
+                clone("[greekiotatonos]", "[greekiotaoxia]")
+                clone("[greekomicrontonos]", "[greekomicronoxia]")
+                clone("[greekupsilontonos]", "[greekupsilonoxia]")
+                clone("[greekomegatonos]", "[greekomegaoxia]")
+            when 'ru' then
+                remap(/\xC1/, "[cyrillica]")
+                remap(/\xC2/, "[cyrillicb]")
+                remap(/\xD7/, "[cyrillicv]")
+                remap(/\xC7/, "[cyrillicg]")
+                remap(/\xC4/, "[cyrillicd]")
+                remap(/\xC5/, "[cyrillice]")
+                remap(/\xD6/, "[cyrilliczh]")
+                remap(/\xDA/, "[cyrillicz]")
+                remap(/\xC9/, "[cyrillici]")
+                remap(/\xCA/, "[cyrillicishrt]")
+                remap(/\xCB/, "[cyrillick]")
+                remap(/\xCC/, "[cyrillicl]")
+                remap(/\xCD/, "[cyrillicm]")
+                remap(/\xCE/, "[cyrillicn]")
+                remap(/\xCF/, "[cyrillico]")
+                remap(/\xD0/, "[cyrillicp]")
+                remap(/\xD2/, "[cyrillicr]")
+                remap(/\xD3/, "[cyrillics]")
+                remap(/\xD4/, "[cyrillict]")
+                remap(/\xD5/, "[cyrillicu]")
+                remap(/\xC6/, "[cyrillicf]")
+                remap(/\xC8/, "[cyrillich]")
+                remap(/\xC3/, "[cyrillicc]")
+                remap(/\xDE/, "[cyrillicch]")
+                remap(/\xDB/, "[cyrillicsh]")
+                remap(/\xDD/, "[cyrillicshch]")
+                remap(/\xDF/, "[cyrillichrdsn]")
+                remap(/\xD9/, "[cyrillicery]")
+                remap(/\xD8/, "[cyrillicsftsn]")
+                remap(/\xDC/, "[cyrillicerev]")
+                remap(/\xC0/, "[cyrillicyu]")
+                remap(/\xD1/, "[cyrillicya]")
+                remap(/\xA3/, "[cyrillicyo]")
+            when 'tr' then
+                remap(/\^\^11/, "[dotlessi]")
+            else
+        end
+
+        if ! encoding.empty? then
+            begin
+                filename = Kpse.found(filename, 'context')
+                if data = IO.readlines(filename.chomp) then
+                    report("preloading #{encoding} character mappings")
+                    accept = false
+                    data.each do |line|
+                        case line.chomp
+                            when /\\start(en|)coding\s*\[(.*?)\]/io then
+                                enc = $2
+                                if accept = (enc == encoding) then
+                                    report("accepting vector #{enc}")
+                                else
+                                    report("skipping vector #{enc}")
+                                end
+                            when /\\stop(en|)coding/io then
+                                accept = false
+                            when accept && /\\definecharacter\s*([a-zA-Z]+)\s*(\d+)\s*/o then
+                                name, number = $1, $2
+                                remap(/\^\^#{sprintf("%02x",number)}/, "[#{name}]")
+                                if number.to_i > 127 then
+                                    remap(/#{sprintf("\\%03o",number)}/, "[#{name}]")
+                                end
+                        end
+                    end
+                end
+            rescue
+            end
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    public
+
+    @@languagedata = Hash.new
+
+    def patternfiles
+        language = @commandline.argument('first')
+        if (language == 'all') || language.empty? then
+            languages = @@languagedata.keys.sort
+        elsif @@languagedata.key?(language) then
+            languages = [language]
+        else
+            languages = []
+        end
+        languages.each do |language|
+            encoding = @@languagedata[language][0] || ''
+            files    = @@languagedata[language][1] || []
+            Language::generate(self,language,files,encoding)
+        end
+    end
+
+    private
+
+    # todo: filter the fallback list from context
+
+    # The first entry in the array is the encoding which will be used
+    # when interpreting the raw patterns. The second entry is a list of
+    # filesets (string|aray), each first match of a set is taken.
+
+    @@languagedata['ba' ] = [ 'ec'      , ['bahyph.tex'] ]
+    @@languagedata['ca' ] = [ 'ec'      , ['cahyph.tex'] ]
+    @@languagedata['cy' ] = [ 'ec'      , ['cyhyph.tex'] ]
+    @@languagedata['cs' ] = [ 'ec'      , ['czhyphen.tex','czhyphen.ex'] ]
+    @@languagedata['de' ] = [ 'ec'      , ['dehyphn.tex'] ]
+    @@languagedata['deo'] = [ 'ec'      , ['dehypht.tex'] ]
+    @@languagedata['da' ] = [ 'ec'      , ['dkspecial.tex','dkcommon.tex'] ]
+    # elhyph.tex
+    @@languagedata['es' ] = [ 'ec'      , ['eshyph.tex'] ]
+    @@languagedata['et' ] = [ 'ec'      , ['ethyph.tex'] ]
+    @@languagedata['fi' ] = [ 'ec'      , ['fihyph.tex'] ]
+    @@languagedata['fr' ] = [ 'ec'      , ['frhyph.tex'] ]
+    # ghyphen.readme ghyph31.readme grphyph
+    @@languagedata['hr' ] = [ 'ec'      , ['hrhyph.tex'] ]
+    @@languagedata['hu' ] = [ 'ec'      , ['huhyphn.tex'] ]
+    @@languagedata['us' ] = [ 'default' , [['ushyphmax.tex'],['ushyph.tex'],['hyphen.tex']] ]
+    @@languagedata['us' ] = [ 'default' , [['ushyphmax.tex'],['ushyph.tex'],['hyphen.tex']] ]
+    # inhyph.tex
+    @@languagedata['is' ] = [ 'ec'      , ['ishyph.tex'] ]
+    @@languagedata['it' ] = [ 'ec'      , ['ithyph.tex'] ]
+    @@languagedata['la' ] = [ 'ec'      , ['lahyph.tex'] ]
+    # mnhyph
+    @@languagedata['nl' ] = [ 'ec'      , ['nehyph96.tex'] ]
+    # @@languagedata['no' ] = [ 'ec'      , ['nohyphbx.tex'],['nohyphb.tex'],['nohyph2.tex'],['nohyph1.tex'],['nohyph.tex'] ]
+    @@languagedata['no' ] = [ 'ec'      , [['asxsx.tex','nohyphbx.tex'],['nohyphb.tex'],['nohyph2.tex'],['nohyph1.tex'],['nohyph.tex']] ]
+    @@languagedata['agr'] = [ 'agr'     , [['grahyph4.tex'], ['oldgrhyph.tex']] ] # new, todo
+    @@languagedata['pl' ] = [ 'ec'      , ['plhyph.tex'] ]
+    @@languagedata['pt' ] = [ 'ec'      , ['pthyph.tex'] ]
+    @@languagedata['ro' ] = [ 'ec'      , ['rohyph.tex'] ]
+    @@languagedata['sl' ] = [ 'ec'      , [['slhyph.tex'], ['sihyph.tex']] ]
+    @@languagedata['sk' ] = [ 'ec'      , ['skhyphen.tex','skhyphen.ex'] ]
+    # sorhyph.tex / upper sorbian
+    # srhyphc.tex / cyrillic
+    @@languagedata['sv' ] = [ 'ec'      , ['svhyph.tex'] ]
+    @@languagedata['tr' ] = [ 'ec'      , ['tkhyph.tex'] ]
+    @@languagedata['gb' ] = [ 'default' , [['ukhyphen.tex'],['ukhyph.tex']] ]
+  # @@languagedata['ru' ] = [ 't2a'     , ['ruhyphal.tex'] ] # t2a does not work
+    @@languagedata['ru' ] = [ 'cyr'     , ['ruhyphal.tex'] ]
+end
+
+class Commands
+
+    include CommandBase
+
+    def dpxmapfiles
+
+        force = @commandline.option("force")
+
+        texmfroot = @commandline.argument('first')
+        texmfroot = '.' if texmfroot.empty?
+        if @commandline.option('maproot') != "" then
+            maproot = @commandline.option('maproot')
+        else
+            maproot = "#{texmfroot.gsub(/\\/,'/')}/fonts/map/pdftex/context"
+        end
+        if File.directory?(maproot) then
+            files = Dir.glob("#{maproot}/*.map")
+            if files.size > 0 then
+                files.each do |pdffile|
+                    next if File.basename(pdffile) == 'pdftex.map'
+                    pdffile = File.expand_path(pdffile)
+                    dpxfile = File.expand_path(pdffile.sub(/(dvips|pdftex)/i,'dvipdfm'))
+                    unless pdffile == dpxfile then
+                        begin
+                            if data = File.read(pdffile) then
+                                report("< #{File.basename(pdffile)} - pdf(e)tex")
+                                n = 0
+                                data = data.collect do |line|
+                                    if line =~ /^[\%\#]+/mo then
+                                        ''
+                                    else
+                                        encoding = if line =~ /([a-z0-9\-]+)\.enc/io        then $1 else ''  end
+                                        fontfile = if line =~ /([a-z0-9\-]+)\.(pfb|ttf)/io  then $1 else nil end
+                                        metrics  = if line =~ /^([a-z0-9\-]+)[\s\<]+/io     then $1 else nil end
+                                        slant    = if line =~ /\"([\d\.]+)\s+SlantFont\"/io then "-s #{$1}" else '' end
+                                        if metrics && encoding && fontfile then
+                                            n += 1
+                                            "#{metrics} #{encoding} #{fontfile} #{slant}"
+                                        else
+                                            ''
+                                        end
+                                    end
+                                end
+                                data.delete_if do |line|
+                                    line.gsub(/\s+/,'').empty?
+                                end
+                                data.collect! do |line|
+                                    # remove line with "name name" lines
+                                    line.gsub(/^(\S+)\s+\1\s*$/) do
+                                        $1
+                                    end
+                                end
+                                begin
+                                    if force then
+                                        if n > 0 then
+                                            File.makedirs(File.dirname(dpxfile))
+                                            if f = File.open(dpxfile,'w') then
+                                                report("> #{File.basename(dpxfile)} - dvipdfm(x) - #{n}")
+                                                f.puts(data)
+                                                f.close
+                                            else
+                                                report("? #{File.basename(dpxfile)} - dvipdfm(x)")
+                                            end
+                                        else
+                                            report("- #{File.basename(dpxfile)} - dvipdfm(x) - no entries")
+                                            # begin File.delete(dpxname) ; rescue ; end
+                                            if f = File.open(dpxfile,'w') then
+                                                f.puts("% no map entries")
+                                                f.close
+                                            end
+                                        end
+                                    else
+                                        report(". #{File.basename(dpxfile)} - dvipdfm(x) - #{n}")
+                                    end
+                                rescue
+                                    report("error in saving dvipdfm file")
+                                end
+                            else
+                                report("error in loading pdftex file")
+                            end
+                        rescue
+                            report("error in processing pdftex file")
+                        end
+                    end
+                end
+                if force then
+                    begin
+                        report("regenerating database for #{texmfroot}")
+                        system("mktexlsr #{texmfroot}")
+                    rescue
+                    end
+                end
+            else
+                report("no mapfiles found in #{maproot}")
+            end
+        else
+            report("provide proper texmfroot")
+        end
+
+    end
+
+end
+
+class Array
+
+    def add_shebang(filename,program)
+        unless self[0] =~ /^\#/ then
+            self.insert(0,"\#!/usr/bin/env #{program}")
+        end
+        unless self[2] =~ /^\#.*?copyright\=/ then
+            self.insert(1,"\#")
+            self.insert(2,"\# copyright=pragma-ade readme=readme.pdf licence=cc-gpl")
+            self.insert(3,"") unless self[3].chomp.strip.empty?
+            self[2].gsub!(/ +/, ' ')
+            return true
+        else
+            return false
+        end
+    end
+
+    def add_directive(filename,program)
+        unless self[0] =~ /^\%/ then
+            self.insert(0,"\% content=#{program}")
+        end
+        unless self[2] =~ /^\%.*?copyright\=/ then
+            self.insert(1,"\%")
+            if File.expand_path(filename) =~ /[\\\/](doc|manuals)[\\\/]/ then
+                self.insert(2,"\% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa")
+            else
+                self.insert(2,"\% copyright=pragma-ade readme=readme.pdf licence=cc-gpl")
+            end
+            self.insert(3,"") unless self[3].chomp.strip.empty?
+            self[0].gsub!(/ +/, ' ')
+            return true
+        else
+            return false
+        end
+    end
+
+    def add_comment(filename)
+        if self[0] =~ /<\?xml.*?\?>/ && self[2] !~ /^<\!\-\-.*?copyright\=.*?\-\->/ then
+            self.insert(1,"")
+            if File.expand_path(filename) =~ /[\\\/](doc|manuals)[\\\/]/ then
+                self.insert(2,"<!-- copyright='pragma-ade' readme='readme.pdf' licence='cc-by-nc-sa' -->")
+            else
+                self.insert(2,"<!-- copyright='pragma-ade' readme='readme.pdf' licence='cc-gpl' -->")
+            end
+            self.insert(3,"") unless self[3].chomp.strip.empty?
+            return true
+        else
+            return false
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    def brandfiles
+
+        force = @commandline.option("force")
+        files = @commandline.arguments # Dir.glob("**/*.*")
+        done  = false
+
+        files.each do |filename|
+            if FileTest.file?(filename) then
+                ok = false
+                begin
+                    data = IO.readlines(filename)
+                    case filename
+                        when /\.rb$/ then
+                            ok = data.add_shebang(filename,'ruby')
+                        when /\.pl$/ then
+                            ok = data.add_shebang(filename,'perl')
+                        when /\.py$/ then
+                            ok = data.add_shebang(filename,'python')
+                        when /\.tex$/ then
+                            ok = data.add_directive(filename,'tex')
+                        when /\.mp$/ then
+                            ok = data.add_directive(filename,'metapost')
+                        when /\.mf$/ then
+                            ok = data.add_directive(filename,'metafont')
+                        when /\.(xml|xsl|fo|fx|rlx|rng|exa)$/ then
+                            ok = data.add_comment(filename)
+                    end
+                rescue
+                    report("fatal error in processing #{filename}") # maybe this catches the mac problem taco reported
+                else
+                    if ok then
+                        report()
+                        report(filename)
+                        report()
+                        for i in 0..4 do
+                           report('  ' + data[i].chomp)
+                        end
+                        if force && f = File.open(filename,'w') then
+                            f.puts data
+                            f.close
+                        end
+                        done = true
+                    end
+                end
+            else
+                report("no file named #{filename}")
+            end
+        end
+        report() if done
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    # usage   : ctxtools --listentities entities.xml
+    # document: <!DOCTYPE something SYSTEM "entities.xml">
+
+    def flushentities(handle,entities,doctype=nil) # 'stylesheet'
+        if doctype then
+            tab = "\t"
+            handle << "<?xml version='1.0' encoding='utf-8'?>\n\n"
+            handle << "<!-- !DOCTYPE entities SYSTEM 'entities.xml' -->\n\n"
+            handle << "<!DOCTYPE #{doctype} [\n"
+        else
+            tab = ""
+        end
+        entities.keys.sort.each do |k|
+            handle << "#{tab}<!ENTITY #{k} \"\&\#x#{entities[k]};\">\n"
+        end
+        if doctype then
+            handle << "]>\n"
+        end
+    end
+
+    def listentities
+
+        filenames  = ['enco-uc.tex','contextnames.txt']
+        outputname = @commandline.argument('first')
+        doctype    = @commandline.option('doctype')
+        entities   = Hash.new
+
+        filenames.each do |filename|
+            filename = Kpse.found(filename, 'context')
+            if filename and not filename.empty? and FileTest.file?(filename) then
+                report("loading #{filename.gsub(/\\/,'/')}") unless outputname.empty?
+                IO.readlines(filename).each do |line|
+                    case line
+                        when /^[\#\%]/io then
+                            # skip comment line
+                        when /\\definecharacter\s+([a-z]+)\s+\{\\uchar\{*(\d+)\}*\{(\d+)\}\}/io then
+                            name, code = $1, sprintf("%04X",$2.to_i*256 + $3.to_i)
+                            entities[name] = code.rjust(4,'0') unless entities.key?(name)
+                        when /^([A-F0-9]+)\;([a-z][a-z]+)\;(.*?)\;(.*?)\s*$/io then
+                            code, name, adobe, comment = $1, $2, $3, $4
+                            entities[name] = code.rjust(4,'0') unless entities.key?(name)
+                    end
+                end
+            end
+        end
+        if outputname and not outputname.empty? then
+            if f = File.open(outputname,'w') then
+                report("saving #{entities.size} entities in #{outputname}")
+                flushentities(f,entities,doctype)
+                f.close
+            else
+                flushentities($stdout,entities,doctype)
+            end
+        else
+            flushentities($stdout,entities,doctype)
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    def platformize
+
+        pattern = if @commandline.arguments.empty? then "*.{rb,pl,py}" else @commandline.arguments end
+        recurse = @commandline.option("recurse")
+        force = @commandline.option("force")
+        pattern = "#{if recurse then '**/' else '' end}#{pattern}"
+        Dir.glob(pattern).each do |file|
+            if File.file?(file) then
+                size = File.size(file)
+                data = IO.readlines(file)
+                if force then
+                    if f = File.open(file,'w')
+                        data.each do |line|
+                            f.puts(line.chomp)
+                        end
+                        f.close
+                    end
+                    if File.size(file) == size then # not robust
+                        report("file '#{file}' is unchanged")
+                    else
+                        report("file '#{file}' is platformized")
+                    end
+                else
+                    report("file '#{file}' is a candidate")
+                end
+            end
+        end
+    end
+
+end
+
+class TexDeps
+
+    @@cs_tex = %q/
+        above abovedisplayshortskip abovedisplayskip
+        abovewithdelims accent adjdemerits advance afterassignment
+        aftergroup atop atopwithdelims
+        badness baselineskip batchmode begingroup
+        belowdisplayshortskip belowdisplayskip binoppenalty botmark
+        box boxmaxdepth brokenpenalty
+        catcode char chardef cleaders closein closeout clubpenalty
+        copy count countdef cr crcr csname
+        day deadcycles def defaulthyphenchar defaultskewchar
+        delcode delimiter delimiterfactor delimeters
+        delimitershortfall delimeters dimen dimendef discretionary
+        displayindent displaylimits displaystyle
+        displaywidowpenalty displaywidth divide
+        doublehyphendemerits dp dump
+        edef else emergencystretch end endcsname endgroup endinput
+        endlinechar eqno errhelp errmessage errorcontextlines
+        errorstopmode escapechar everycr everydisplay everyhbox
+        everyjob everymath everypar everyvbox exhyphenpenalty
+        expandafter
+        fam fi finalhyphendemerits firstmark floatingpenalty font
+        fontdimen fontname futurelet
+        gdef global group globaldefs
+        halign hangafter hangindent hbadness hbox hfil horizontal
+        hfill horizontal hfilneg hfuzz hoffset holdinginserts hrule
+        hsize hskip hss horizontal ht hyphenation hyphenchar
+        hyphenpenalty hyphen
+        if ifcase ifcat ifdim ifeof iffalse ifhbox ifhmode ifinner
+        ifmmode ifnum ifodd iftrue ifvbox ifvmode ifvoid ifx
+        ignorespaces immediate indent input inputlineno input
+        insert insertpenalties interlinepenalty
+        jobname
+        kern
+        language lastbox lastkern lastpenalty lastskip lccode
+        leaders left lefthyphenmin leftskip leqno let limits
+        linepenalty line lineskip lineskiplimit long looseness
+        lower lowercase
+        mag mark mathaccent mathbin mathchar mathchardef mathchoice
+        mathclose mathcode mathinner mathop mathopen mathord
+        mathpunct mathrel mathsurround maxdeadcycles maxdepth
+        meaning medmuskip message mkern month moveleft moveright
+        mskip multiply muskip muskipdef
+        newlinechar noalign noboundary noexpand noindent nolimits
+        nonscript scriptscript nonstopmode nulldelimiterspace
+        nullfont number
+        omit openin openout or outer output outputpenalty over
+        overfullrule overline overwithdelims
+        pagedepth pagefilllstretch pagefillstretch pagefilstretch
+        pagegoal pageshrink pagestretch pagetotal par parfillskip
+        parindent parshape parskip patterns pausing penalty
+        postdisplaypenalty predisplaypenalty predisplaysize
+        pretolerance prevdepth prevgraf
+        radical raise read relax relpenalty right righthyphenmin
+        rightskip romannumeral
+        scriptfont scriptscriptfont scriptscriptstyle scriptspace
+        scriptstyle scrollmode setbox setlanguage sfcode shipout
+        show showbox showboxbreadth showboxdepth showlists showthe
+        skewchar skip skipdef spacefactor spaceskip span special
+        splitbotmark splitfirstmark splitmaxdepth splittopskip
+        string
+        tabskip textfont textstyle the thickmuskip thinmuskip time
+        toks toksdef tolerance topmark topskip tracingcommands
+        tracinglostchars tracingmacros tracingonline tracingoutput
+        tracingpages tracingparagraphs tracingrestores tracingstats
+        uccode uchyph underline unhbox unhcopy unkern unpenalty
+        unskip unvbox unvcopy uppercase
+        vadjust valign vbadness vbox vcenter vfil vfill vfilneg
+        vfuzz voffset vrule vsize vskip vsplit vss vtop
+        wd widowpenalty write
+        xdef xleaders xspaceskip
+        year
+    /.split
+
+    @@cs_etex = %q/
+        beginL beginR botmarks
+        clubpenalties currentgrouplevel currentgrouptype
+        currentifbranch currentiflevel currentiftype
+        detokenize dimexpr displaywidowpenalties
+        endL endR eTeXrevision eTeXversion everyeof
+        firstmarks fontchardp fontcharht fontcharic fontcharwd
+        glueexpr glueshrink glueshrinkorder gluestretch
+        gluestretchorder gluetomu
+        ifcsname ifdefined iffontchar interactionmode
+        interactionmode interlinepenalties
+        lastlinefit lastnodetype
+        marks topmarks middle muexpr mutoglue
+        numexpr
+        pagediscards parshapedimen parshapeindent parshapelength
+        predisplaydirection
+        savinghyphcodes savingvdiscards scantokens showgroups
+        showifs showtokens splitdiscards splitfirstmarks
+        TeXXeTstate tracingassigns tracinggroups tracingifs
+        tracingnesting tracingscantokens
+        unexpanded unless
+        widowpenalties
+    /.split
+
+    @@cs_pdftex = %q/
+        pdfadjustspacing pdfannot pdfavoidoverfull
+        pdfcatalog pdfcompresslevel
+        pdfdecimaldigits pdfdest pdfdestmargin
+        pdfendlink pdfendthread
+        pdffontattr pdffontexpand pdffontname pdffontobjnum pdffontsize
+        pdfhorigin
+        pdfimageresolution pdfincludechars pdfinfo
+        pdflastannot pdflastdemerits pdflastobj
+        pdflastvbreakpenalty pdflastxform pdflastximage
+        pdflastximagepages pdflastxpos pdflastypos
+        pdflinesnapx pdflinesnapy pdflinkmargin pdfliteral
+        pdfmapfile pdfmaxpenalty pdfminpenalty pdfmovechars
+        pdfnames
+        pdfobj pdfoptionpdfminorversion pdfoutline pdfoutput
+        pdfpageattr pdfpageheight pdfpageresources pdfpagesattr
+        pdfpagewidth pdfpkresolution pdfprotrudechars
+        pdfrefobj pdfrefxform pdfrefximage
+        pdfsavepos pdfsnaprefpoint pdfsnapx pdfsnapy pdfstartlink
+        pdfstartthread
+        pdftexrevision pdftexversion pdfthread pdfthreadmargin
+        pdfuniqueresname
+        pdfvorigin
+        pdfxform pdfximage
+    /.split
+
+    @@cs_omega = %q/
+        odelimiter omathaccent omathchar oradical omathchardef omathcode odelcode
+        leftghost rightghost
+        charwd charht chardp charit
+        localleftbox localrightbox
+        localinterlinepenalty localbrokenpenalty
+        pagedir bodydir pardir textdir mathdir
+        boxdir nextfakemath
+        pagewidth pageheight pagerightoffset pagebottomoffset
+        nullocp nullocplist ocp externalocp ocplist pushocplist popocplist clearocplists ocptracelevel
+        addbeforeocplist addafterocplist removebeforeocplist removeafterocplist
+        OmegaVersion
+        InputTranslation OutputTranslation DefaultInputTranslation DefaultOutputTranslation
+        noInputTranslation noOutputTranslation
+        InputMode OutputMode DefaultInputMode DefaultOutputMode
+        noInputMode noOutputMode noDefaultInputMode noDefaultOutputMode
+    /.split
+
+    @@cs_metatex = %q/
+    /.split
+
+    @@cs_xetex = %q/
+    /.split
+
+    @@cs_skip = %q/
+        v\! c\! s\! e\! m\! f\!
+        \!tf \!tt \!tq \!ta \?\?
+        csname endcsname relax
+        \!\!string[a-f] \!\!dimen[a-k] \!\!count[a-f] \!\!toks[a-e] \!\!box[a-e]
+        \!\!width[a-c] \!\!height[a-c] \!\!depth[a-c]
+        \!\!done[a-f] if\!\!done[a-f] if\:\!\!done[a-f]
+        scratch globalscratch
+        ascii[a-d] globalascii
+        @@expanded @@globalexpanded @EA @EAEA @EAEAEA
+        bgroup egroup par next nextnext docommand dodocommand dododocommand
+        \!\!width \!\!height \!\!depth \!\!plus \!\!minus \!\!to
+    /.split
+
+    @@cs_skip = %q/
+        [vcsemf]\! \?\?
+        \!t[ftqa]
+        csname endcsname relax
+        \!\!string[a-f] \!\!dimen[a-k] \!\!count[a-f] \!\!toks[a-e] \!\!box[a-e]
+        \!\!width[a-c] \!\!height[a-c] \!\!depth[a-c]
+        \!\!done[a-f] if\!\!done[a-f] if\:\!\!done[a-f]
+        scratch globalscratch
+        ascii[a-d] globalascii
+        @@expanded @@globalexpanded @(EA)+
+        [be]group par next nextnext (do)+command
+        \!\!(width|height|depth|plus|minus|to)
+    /.split
+
+    # let's ignore \dimendef etc
+
+    @@primitives_def = %q/
+         def edef xdef gdef let
+         newcount newdimen newskip newbox newtoks newmarks newif newinsert newmuskip
+         chardef mathchardef dimendef countdef toksdef
+         newconditional definecomplexorsimple definecomplexorsimpleempty
+         newcounter newpersistentmark
+         installinsertion installspecial\s*\\[* installoutput\s*\\[*
+    /.split
+
+    @@types = [['invalid','*'],['okay','='],['forward','>'],['backward','<'],['unknown','?']]
+
+    @@skips = /^(#{@@cs_skip.join('|')})/o
+
+    def initialize(logger=nil,compact=false)
+        @defined      = Hash.new
+        @definitive   = Hash.new
+        @used_before  = Hash.new
+        @used_after   = Hash.new
+        @dependencies = Hash.new
+        @fineorder    = Hash.new
+        @forward      = Hash.new
+        @backward     = Hash.new
+        @disorder     = Hash.new
+        @disordercs   = Hash.new
+        @type         = Hash.new
+        @filename     = 'context.tex'
+        @files        = Array.new # keep load order !
+        @order        = Hash.new
+        @logger       = logger
+        @filefilter   = nil
+        @namefilter   = nil
+        @compact      = compact
+        #
+        @@cs_tex.each     do |cs| @defined[cs] = ['-tex--------'] end
+        @@cs_etex.each    do |cs| @defined[cs] = ['-etex-------'] end
+        @@cs_pdftex.each  do |cs| @defined[cs] = ['-pdftex-----'] end
+        @@cs_omega.each   do |cs| @defined[cs] = ['-omega------'] end
+        @@cs_xetex.each   do |cs| @defined[cs] = ['-xetex------'] end
+        @@cs_metatex.each do |cs| @defined[cs] = ['-metatex----'] end
+    end
+
+    def report(str)
+        @logger.report(str) rescue false
+    end
+
+    def setfilter(data)
+        data.split(/\s*\,\s*/).each do |d|
+            if d =~ /\.tex$/ then
+                @filefilter = Array.new unless @filefilter
+                @filefilter << d
+            else
+                @namefilter = Array.new unless @namefilter
+                @namefilter << d
+            end
+        end
+    end
+
+    def load(filename='context.tex')
+        begin
+            @filename = filename
+            n = 0
+            File.open(filename) do |f|
+                f.each do |line|
+                    if line =~ /^(\\input\s+|\\load[a-z]+\{)([a-z\-\.]+)(\}*)/ then
+                        ante, name, post = $1, $2, $3
+                        @files.push(name)
+                        @order[name] = n += 1
+                    end
+                end
+            end
+        rescue
+            @files = Array.new
+            @order = Hash.new
+        end
+    end
+
+    def save(filename='context.tex')
+        unless @filefilter || @namefilter then
+            begin
+                data = IO.readlines(filename).each do |line|
+                    line.gsub!(/^(\\input\s+|\\load[a-z]+\{)([a-z\-\.]+)(\}*)\s*$/) do
+                        ante, name, post = $1, $2, $3
+                        fin = (@fineorder[name]    || [])-[name]
+                        dep = (@dependencies[name] || [])-[name]
+                        dis = (@disorder[name]     || [])-[name]
+                        fin = if fin.size > 0 then " B[#{fin.join(' ')}]" else "" end
+                        dep = if dep.size > 0 then " A[#{dep.join(' ')}]" else "" end
+                        dis = if dis.size > 0 then " D[#{dis.join(' ')}]" else "" end
+                        "#{ante}#{name}#{post} %#{fin}#{dep}#{dis}\n"
+                    end
+                end
+            rescue
+                report("error: #{$!}")
+            else
+                begin
+                    newname = filename.sub(/\..*$/,'.log')
+                    report("")
+                    report("writing to #{newname}")
+                    report("")
+                    File.open(newname,'w') do |f|
+                        f << data
+                    end
+                rescue
+                    report("error: #{$!}")
+                end
+            end
+        end
+    end
+
+    def analyze
+        report('')
+        report("loading files")
+        report('')
+        n = 0
+# try tex and mkiv
+        @files.each do |filename|
+            if File.file?(filename) and f = File.open(filename) then
+                defs, uses, l = 0, 0, 0
+                n += 1
+                report("#{n.to_s.rjust(5,' ')} #{filename}")
+                f.each do |line|
+                    l += 1
+                    line.chomp!
+
+
+                    line.sub!(/\%.*$/, '')
+                    line.gsub!(/\\(unexpanded|unprotected|global|protected|long)\s*(\\)/, "\\")
+                    # the superseded, overloaded, forwarded, and predefined macros
+                    # are at the outer level anyway, so there we may ignore leading
+                    # spaces (could be inside an \if); other definitions are only
+                    # accepted when they start at the beginning of a line
+                    case line
+                        when /^\\ifx\s*\\[a-zA-Z\@\!\?]+\s*\\undefined\s*(\\else)*(.*?)$/ then
+                            if $2 =~ /^\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})/o then
+                                pushdef(filename,l,$2,5) # kind of auto-predefined
+                            end
+                        when /^\s*\\superseded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,1)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\overloaded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,2)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\forwarded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,3)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\predefined\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,4)
+                            moreuse(filename,l,rest)
+                        when /^\\(#{@@primitives_def.join('|')})[\=\s]*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3 # \=* catches the \let \a = \b
+                            pushdef(filename,l,name,0)
+                            moreuse(filename,l,rest)
+                        when /\\newevery\s*\\([a-zA-Z\@\?\!]+)\s*\\([a-zA-Z\@\?\!]+)/ then
+                            a, b = $1, $2
+                            pushdef(filename,l,a,0)
+                            pushdef(filename,l,b,0)
+                        else
+                            moreuse(filename,l,line)
+                    end
+                end
+                f.close
+            end
+        end
+        @used_after.each do |cs,files|
+            (@defined[cs] || []).each do |name|
+                @dependencies[name] = Array.new unless @dependencies[name]
+                files.each do |file|
+                    @dependencies[name] << file unless @dependencies[name].include?(file)
+                end
+            end
+        end
+        @used_before.each do |cs,files|
+            (@defined[cs] || []).each do |name|
+                @disorder[name]   = Array.new unless @disorder[name]
+                @disordercs[name] = Array.new unless @disordercs[name]
+                @fineorder[name]  = Array.new unless @fineorder[name]
+                files.each do |file|
+                    unless @disorder[name].include?(file) || name == file then
+                        unless @defined[cs].include?(file) then
+                            if @order[name] > @order[file] then
+                                @disorder[name]   << file
+                                @disordercs[name] << "#{file}:#{cs}"
+                            end
+                        end
+                    end
+                    @fineorder[name] << file unless @fineorder[name].include?(file) || name == file
+                end
+            end
+        end
+    end
+
+    def moreuse(filename,l,line)
+        line.scan(/\\if([a-zA-Z@\?\!]{3,})/) do |name, rest| # rest, else array
+            pushuse(filename,l,"if#{name}") unless name =~ /^(true|false)$/
+        end
+        line.scan(/\\([a-zA-Z@\?\!]{3,})/) do |name, rest| # rest, else array
+            if name =~ /(true|false)$/ then
+                pushuse(filename,l,"if#{name}") unless name =~ /^(if|set)$/
+            else
+                pushuse(filename,l,name)
+            end
+        end
+    end
+
+    def feedback
+        begin
+            # get max length
+            l = 0
+            list = @defined.keys.sort
+            list.each do |cs|
+                l = cs.length if cs.length > l
+            end
+            if ! @compact then
+                n = 0
+                report('')
+                report("defined: #{@defined.size}")
+                report('')
+                @defined.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter && ! @defined[cs].include?(cs)
+                    if @defined[cs].size > 1 then
+                        dlist = @defined[cs].collect do |d|
+                            if d == @definitive[cs] then d else "[#{d}]" end
+                        end
+                    else
+                        dlist = @defined[cs]
+                    end
+                    report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{dlist.join(' ')}")
+                end
+            end
+            if true then
+                n = 0
+                report('')
+                report("used before defined: #{@used_before.size}")
+                report('')
+                @used_before.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter && (@used_before[cs] & @filefilter).size == 0
+                    used = @used_before[cs] - (@defined[cs] || [])
+                    defined = (@defined[cs] || []).join(' ')
+                    defined = "[ ? ]" if defined.empty?
+                    if used.size > 0 then
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined} -> #{used.join(' ')}")
+                    else
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined}")
+                    end
+                end
+                report('      none') if n == 0
+            end
+            if ! @compact then
+                n = 0
+                report('')
+                report("used after defined: #{@used_after.size}")
+                report('')
+                @used_after.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter &&  (@used_after[cs] & @filefilter).size == 0
+                    used = @used_after[cs] - (@defined[cs] || [])
+                    defined = (@defined[cs] || []).join(' ')
+                    if used.size > 0 then
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined} <- #{used.join(' ')}")
+                    else
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined}")
+                    end
+                end
+                report('      none') if n == 0
+            end
+            if ! @compact then
+                unless @filefilter || @namefilter then
+                    [false,true].each do |mode|
+                        n = 0
+                        report("")
+                        report("file dependecies #{if mode then '(critical)' end}")
+                        [@dependencies].each do |dependencies|
+                            report("")
+                            dependencies.keys.sort.each do |f|
+                                if dependencies[f].size > 0 then
+                                    dependencies[f].delete(f)
+                                end
+                                if mode then
+                                    dep = dependencies[f].delete_if do |d|
+                                        f[0..3] == d[0..3] # same xxxx- prefix
+                                    end
+                                else
+                                    dep = dependencies[f]
+                                end
+                                if dep.size > 0 then
+                                    name = f.nosuffix('tex').ljust(8,' ')
+                                    list = dep.sort.collect do |k| k.nosuffix('tex') end
+                                    report("#{(n += 1).to_s.rjust(5,' ')} #{name} !! #{list.join(' ')}")
+                                end
+                            end
+                        end
+                        report('      none') if n == 0
+                    end
+                end
+            end
+            if true then
+                unless @filefilter || @namefilter then
+                    [false,true].each do |mode|
+                        [@disorder, at disordercs].each do |disorder|
+                            n = 0
+                            report("")
+                            report("file disorder #{if mode then '(critical)' end}")
+                            report("")
+                            disorder.keys.sort.each do |f|
+                                if disorder[f].size > 0 then
+                                    disorder[f].delete(f)
+                                end
+                                if mode then
+                                    dis = disorder[f].delete_if do |d|
+                                        f[0..3] == d[0..3] # same xxxx- prefix
+                                    end
+                                else
+                                    dis = disorder[f]
+                                end
+                                if dis.size > 0 then
+                                    name = f.nosuffix('tex').ljust(8,' ')
+                                    list = dis.sort.collect do |k| k.nosuffix('tex') end
+                                    report("#{(n += 1).to_s.rjust(3,' ')} #{name} ?? #{list.join(' ')}")
+                                end
+                            end
+                        end
+                        report('      none') if n == 0
+                    end
+                end
+            end
+        rescue
+            puts("fatal error: #{$!} #{$@.join("\n")}")
+        end
+    end
+
+    private
+
+    def csdefined?(cs,filename)
+        @defined[cs] && @defined[cs].include?(filename)
+    end
+    def csbefore?(cs,filename)
+        @used_before[cs] && @used_before[cs].include?(filename)
+    end
+    def csafter?(cs,filename)
+        @used_after[cs] && @used_after[cs].include?(filename)
+    end
+
+    def csignored?(cs)
+        cs.to_s =~ @@skips
+    end
+
+    def pushdef(filename,n,cs,type)
+        if csignored?(cs) then
+            # nothing
+        elsif @defined[cs] then
+            case type
+                when 5 then
+                    # if test, no definition done
+                else
+                    @definitive[cs] = filename
+                    unless @filefilter || @namefilter then
+                        report("#{cs} is redefined") unless csdefined?(cs,filename) || @compact
+                    end
+            end
+            @defined[cs] << filename unless @defined[cs].include?(filename)
+        else
+            @defined[cs] = Array.new
+            @defined[cs] << filename
+            @definitive[cs] = filename
+            @type[cs] = type
+        end
+    end
+
+    def pushuse(filename,n,cs)
+        if csignored?(cs) then
+            # nothing
+        elsif @defined[cs] then
+            @used_after[cs] = Array.new unless @used_after[cs]
+            @used_after[cs] << filename unless csafter?(cs,filename)
+        else
+            @used_before[cs] = Array.new unless @used_before[cs]
+            @used_before[cs] << filename unless csbefore?(cs,filename)
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    def dependencies
+
+        filename = if @commandline.arguments.empty? then 'context.tex' else @commandline.arguments.first end
+        compact  = @commandline.option('compact')
+
+        ['context',''].each do |progname|
+            unless FileTest.file?(filename) then
+                name = Kpse.found(filename, progname)
+                if FileTest.file?(name) then
+                    filename = name
+                    break
+                end
+            end
+        end
+
+        if FileTest.file?(filename) && deps = TexDeps.new(logger,compact) then
+            deps.setfilter(@commandline.option('filter'))
+            deps.load
+            deps.analyze
+            deps.feedback
+            deps.save if @commandline.option('save')
+        else
+            report("unknown file #{filename}")
+        end
+
+    end
+
+end
+
+class Commands
+
+    @@re_utf_bom = /^\357\273\277/o # just utf-8
+
+    def disarmutfbom
+
+        if @commandline.arguments.empty? then
+            report("provide filename")
+        else
+            @commandline.arguments.each do |filename|
+                report("checking '#{filename}'")
+                if FileTest.file?(filename) then
+                    begin
+                        data = IO.read(filename)
+                        if data.sub!(@@re_utf_bom,'') then
+                            if @commandline.option('force') then
+                                if f = File.open(filename,'wb') then
+                                    f << data
+                                    f.close
+                                    report("bom found and removed")
+                                else
+                                    report("bom found and removed, but saving file fails")
+                                end
+                            else
+                                report("bom found, use '--force' to remove it")
+                            end
+                        else
+                            report("no bom found")
+                        end
+                    rescue
+                        report("bom found, but removing it fails")
+                    end
+                else
+                    report("provide valid filename")
+                end
+            end
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    def updatecontext
+
+        def fetchfile(site, name, target=nil)
+            begin
+                proxy = @commandline.option('proxy')
+                if proxy && ! proxy.empty? then
+                    address, port = proxy.split(":")
+                    if address && port then
+                        http = Net::HTTP::Proxy(address, port).new(site)
+                    else
+                        http = Net::HTTP::Proxy(proxy, 80).new(site)
+                    end
+                else
+                    http = Net::HTTP.new(site)
+                end
+                resp, data = http.get(name.gsub(/^\/*/, '/'))
+            rescue
+                return false
+            else
+                begin
+                    if data then
+                        name = File.basename(name)
+                        File.open(target || name, 'wb') do |f|
+                            f << data
+                        end
+                    else
+                        return false
+                    end
+                rescue
+                    return false
+                else
+                    return true
+                end
+            end
+        end
+
+        def locatedlocaltree
+            tree = Kpse.used_path('TEXMFLOCAL')
+            unless tree && FileTest.directory?(tree) then
+                tree = Kpse.used_path('TEXMF')
+            end
+            return tree
+        end
+
+        def extractarchive(archive)
+            unless FileTest.file?(archive) then
+                 report("fatal error, '#{archive}' has not been downloaded")
+                 return false
+            end
+            # unless system("unzip -uo #{archive}") then
+            unless system("unzip -o #{archive}") then
+                report("fatal error, make sure that you have 'unzip' in your path")
+                return false
+            end
+            stubs = "scripts/context/stubs/unix/*"
+            if System.unix? and not system("chmod +x #{stubs}") then
+                report("change x-permissions of '#{stubs}' manually")
+            end
+            return true
+         end
+
+        def remakeformats
+            system("mktexlsr")
+            system("texmfstart texexec --make --all  --fast --pdftex")
+            system("texmfstart texexec --make --all  --fast --xetex")
+            return true
+        end
+
+        if localtree = locatedlocaltree then
+            report("updating #{localtree}")
+            begin
+                Dir.chdir(localtree)
+            rescue
+                report("unable to change to #{localtree}")
+            else
+                archive = 'cont-tmf.zip'
+                report("fetching #{archive}")
+                unless fetchfile("www.pragma-ade.com","/context/latest/#{archive}") then
+                    report("unable to fetch #{archive}")
+                    return
+                end
+                report("extracting #{archive}")
+                unless extractarchive(archive) then
+                    report("unable to extract #{archive}")
+                    return
+                end
+                report("remaking formats")
+                unless remakeformats then
+                    report("unable to remak formats")
+                end
+            end
+        else
+            report("unable to locate local tree")
+        end
+
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registeraction('touchcontextfile'  , 'update context version')
+commandline.registeraction('contextversion'    , 'report context version')
+commandline.registeraction('jeditinterface'    , 'generate jedit syntax files [--pipe]')
+commandline.registeraction('bbeditinterface'   , 'generate bbedit syntax files [--pipe]')
+commandline.registeraction('sciteinterface'    , 'generate scite syntax files [--pipe]')
+commandline.registeraction('rawinterface'      , 'generate raw syntax files [--pipe]')
+# commandline.registeraction('translateinterface', 'generate interface files (xml) [nl de ..]')
+commandline.registeraction('purgefiles'        , 'remove temporary files [--all --recurse] [basename]')
+commandline.registeraction('documentation'     , 'generate documentation [--type=] [filename]')
+commandline.registeraction('filterpages'       ) # no help, hidden temporary feature
+commandline.registeraction('patternfiles'      , 'generate pattern files [--all --xml --utf8] [languagecode]')
+commandline.registeraction('dpxmapfiles'       , 'convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]')
+commandline.registeraction('listentities'      , 'create doctype entity definition from enco-uc.tex')
+commandline.registeraction('brandfiles'        , 'add context copyright notice [--force]')
+commandline.registeraction('platformize'       , 'replace line-endings [--recurse --force] [pattern]')
+commandline.registeraction('dependencies'      , 'analyze depedencies within context [--save --compact --filter=[macros|filenames]] [filename]')
+commandline.registeraction('updatecontext'     , 'download latest version and remake formats [--proxy]')
+commandline.registeraction('disarmutfbom'      , 'remove utf bom [--force]')
+
+commandline.registervalue('type','')
+commandline.registervalue('filter','')
+commandline.registervalue('maproot','')
+commandline.registervalue('proxy','')
+
+commandline.registerflag('recurse')
+commandline.registerflag('force')
+commandline.registerflag('compact')
+commandline.registerflag('pipe')
+commandline.registerflag('save')
+commandline.registerflag('all')
+commandline.registerflag('xml')
+commandline.registerflag('log')
+commandline.registerflag('utf8')
+commandline.registerflag('doctype')
+
+# general
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'help')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/graphics/gs.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/graphics/gs.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/graphics/gs.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,684 @@
+# module    : graphics/gs
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# ['base/variables','../variables','variables'].each do |r| begin require r ; rescue Exception ; else break ; end ; end
+# ['base/system',   '../system',   'system'   ].each do |r| begin require r ; rescue Exception ; else break ; end ; end
+
+require 'base/variables'
+require 'base/system'
+require 'fileutils'
+# Require 'ftools'
+
+class GhostScript
+
+    include Variables
+
+    @@pdftrimwhite = 'pdftrimwhite.pl'
+
+    @@pstopdfoptions = [
+        'AntiAliasColorImages',
+        'AntiAliasGrayImages',
+        'AntiAliasMonoImages',
+        'ASCII85EncodePages',
+        'AutoFilterColorImages',
+        'AutoFilterGrayImages',
+        'AutoPositionEPSFiles',
+        'AutoRotatePages',
+        'Binding',
+        'ColorConversionStrategy',
+        'ColorImageDepth',
+        'ColorImageDownsampleThreshold',
+        'ColorImageDownsampleType',
+        'ColorImageFilter',
+        'ColorImageResolution',
+        'CompatibilityLevel',
+        'CompressPages',
+        #'ConvertCMYKImagesToRGB', # buggy
+        #'ConvertImagesToIndexed', # buggy
+        'CreateJobTicket',
+        'DetectBlends',
+        'DoThumbnails',
+        'DownsampleColorImages',
+        'DownsampleGrayImages',
+        'DownsampleMonoImages',
+        'EmbedAllFonts',
+        'EncodeColorImages',
+        'EncodeGrayImages',
+        'EncodeMonoImages',
+        'EndPage',
+        'FirstPage',
+        'GrayImageDepth',
+        'GrayImageDownsampleThreshold',
+        'GrayImageDownsampleType',
+        'GrayImageFilter',
+        'GrayImageResolution',
+        'MaxSubsetPct',
+        'MonoImageDepth',
+        'MonoImageDownsampleThreshold',
+        'MonoImageDownsampleType',
+        'MonoImageFilter',
+        'MonoImageResolution',
+        'Optimize',
+        'ParseDCSComments',
+        'ParseDCSCommentsForDocInfo',
+        'PreserveCopyPage',
+        'PreserveEPSInfo',
+        'PreserveHalftoneInfo',
+        'PreserveOPIComments',
+        'PreserveOverprintSettings',
+        'SubsetFonts',
+        'UseFlateCompression'
+    ]
+
+    @@methods = Hash.new
+
+    @@methods['raw']         = '1'
+    @@methods['bound']       = '2'
+    @@methods['bounded']     = '2'
+    @@methods['crop']        = '3'
+    @@methods['cropped']     = '3'
+    @@methods['down']        = '4'
+    @@methods['downsample']  = '4'
+    @@methods['downsampled'] = '4'
+    @@methods['simplify']    = '5'
+    @@methods['simplified']  = '5'
+
+    @@tempfile    = 'gstemp'
+    @@pstempfile  = @@tempfile + '.ps'
+    @@pdftempfile = @@tempfile + '.pdf'
+
+    @@bboxspec = '\s*([\-\d\.]+)' + '\s+([\-\d\.]+)'*3
+
+    def initialize(logger=nil)
+
+        unless logger then
+            puts('gs class needs a logger')
+            exit
+        end
+
+        @variables = Hash.new
+        @psoptions = Hash.new
+        @logger    = logger
+
+        setvariable('profile',    'gsprofile.ini')
+        setvariable('pipe',       true)
+        setvariable('method',     2)
+        setvariable('force',      false)
+        setvariable('colormodel', 'cmyk')
+        setvariable('inputfile',  '')
+        setvariable('outputfile', '')
+
+        @@pstopdfoptions.each do |key|
+            @psoptions[key] = ''
+        end
+
+        reset
+
+    end
+
+    def reset
+        @llx = @lly = @ulx = @uly = 0
+        @oldbbox = [@llx, at lly, at urx, at ury]
+        @width = @height = @xoffset = @yoffset = @offset = 0
+        @rs = Tool.default_line_separator
+    end
+
+    def supported?(filename)
+        psfile?(filename) || pdffile?(filename)
+    end
+
+    def psfile?(filename)
+        filename =~ /\.(eps|epsf|ps|ai\d*)$/io
+    end
+
+    def pdffile?(filename)
+        filename =~ /\.(pdf)$/io
+    end
+
+    def setpsoption(key,value)
+        @psoptions[key] = value unless value.empty?
+    end
+
+    def setdimensions (llx,lly,urx,ury)
+        @oldbbox = [llx,lly,urx,ury]
+        @llx, @lly = llx.to_f- at offset, lly.to_f- at offset
+        @urx, @ury = urx.to_f+ at offset, ury.to_f+ at offset
+        @width,   @height  = @urx - @llx, @ury - @lly
+        @xoffset, @yoffset =    0 - @llx,    0 - @lly
+    end
+
+    def setoffset (offset=0)
+        @offset = offset.to_f
+        setdimensions(@llx, at lly, at urx, at ury) if dimensions?
+    end
+
+    def resetdimensions
+        setdimensions(0,0,0,0)
+    end
+
+    def dimensions?
+        (@width>0) && (@height>0)
+    end
+
+    def convert
+
+        inpfile = getvariable('inputfile')
+
+        if inpfile.empty? then
+            report('no inputfile specified')
+            return false
+        end
+
+        unless FileTest.file?(inpfile) then
+            report("unknown input file #{inpfile}")
+            return false
+        end
+
+        outfile = getvariable('outputfile')
+
+        if outfile.empty? then
+            outfile = inpfile
+            outfile = outfile.sub(/^.*[\\\/]/,'')
+        end
+
+        outfile = outfile.sub(/\.(pdf|eps|ps|ai)/i, "")
+        resultfile = outfile + '.pdf'
+        setvariable('outputfile', resultfile)
+
+        # flags
+
+        saveprofile(getvariable('profile'))
+
+        begin
+            gsmethod = method(getvariable('method')).to_i
+            report("conversion method #{gsmethod}")
+        rescue
+            gsmethod = 1
+            report("fallback conversion method #{gsmethod}")
+        end
+
+        debug('piping data') if getvariable('pipe')
+
+        ok = false
+        begin
+            case gsmethod
+                when 0, 1 then ok = convertasis(inpfile,resultfile)
+                when 2    then ok = convertbounded(inpfile,resultfile)
+                when 3    then ok = convertcropped(inpfile,resultfile)
+                when 4    then ok = downsample(inpfile,resultfile,'screen')
+                when 5    then ok = downsample(inpfile,resultfile,'prepress')
+                else report("invalid conversion method #{gsmethod}")
+            end
+        rescue
+            report("job aborted due to some error: #{$!}")
+            begin
+                File.delete(resultfile) if FileTest.file?(resultfile)
+            rescue
+                report("unable to delete faulty #{resultfile}")
+            end
+            ok = false
+        ensure
+            deleteprofile(getvariable('profile'))
+            File.delete(@@pstempfile)  if FileTest.file?(@@pstempfile)
+            File.delete(@@pdftempfile) if FileTest.file?(@@pdftempfile)
+        end
+        return ok
+    end
+
+    # private
+
+    def method (str)
+        if @@methods.key?(str) then
+            @@methods[str]
+        else
+            str
+        end
+    end
+
+    def pdfmethod? (str)
+        case method(str).to_i
+            when 1, 3, 4, 5 then return true
+        end
+        return false
+    end
+
+    def pdfprefix (str)
+        case method(str).to_i
+            when 1 then return 'raw-'
+            when 4 then return 'lowres-'
+            when 5 then return 'normal-'
+        end
+        return ''
+    end
+
+    def psmethod? (str)
+        ! pdfmethod?(str)
+    end
+
+    def insertprofile (flags)
+        for key in flags.keys do
+            replacevariable("flag.#{key}", flags[key])
+        end
+    end
+
+    def deleteprofile (filename)
+        begin
+            File.delete(filename) if FileTest.file?(filename)
+        rescue
+        end
+    end
+
+    def saveprofile (filename)
+        return if filename.empty? || ! (ini = open(filename,"w"))
+        @@pstopdfoptions.each do |k|
+            str = @psoptions[k]
+            # beware, booleans are translated, but so are yes/no which is dangerous
+            if str.class == String then
+                if ! str.empty? && (str != 'empty') then
+                    str.sub!(/(.+)\-/io, '')
+                    str = "/" + str unless str =~ /^(true|false|none|[\d\.\-\+]+)$/
+                    ini.puts("-d#{k}=#{str}\n")
+                end
+            end
+        end
+        ini.close
+        debug("gs profile #{filename} saved")
+    end
+
+    def gsstream # private
+        if getvariable('pipe') then '-' else @@pstempfile end
+    end
+
+    def gscolorswitch
+        case getvariable('colormodel')
+            when 'cmyk' then '-dProcessColorModel=/DeviceCMYK -dColorConversionStrategy=/CMYK '
+            when 'rgb'  then '-dProcessColorModel=/DeviceRGB  -dColorConversionStrategy=/RGB '
+            when 'gray' then '-dProcessColorModel=/DeviceGRAY -dColorConversionStrategy=/GRAY '
+        else
+            ''
+        end
+    end
+
+    def gsdefaults
+        defaults = ''
+        begin
+            defaults << '-dAutoRotatePages=/None ' if @psoptions['AutoRotatePages'].empty?
+        rescue
+            defaults << '-dAutoRotatePages=/None '
+        end
+        return defaults
+    end
+
+    def convertasis (inpfile, outfile)
+
+        report("converting #{inpfile} as-is")
+
+        @rs = Tool.line_separator(inpfile)
+        debug("platform mac") if @rs == "\r"
+
+        arguments = ''
+        arguments << "\@gsprofile.ini "
+        arguments << "-q -sDEVICE=pdfwrite -dNOPAUSE -dNOCACHE -dBATCH "
+        arguments << "#{gsdefaults} "
+        arguments << "#{gscolorswitch} "
+        arguments << "-sOutputFile=#{outfile} #{inpfile} -c quit "
+
+        debug("ghostscript: #{arguments}")
+        unless ok = System.run('ghostscript',arguments) then
+            begin
+                report("removing file #{outfile}")
+                File.delete(outfile) if FileTest.file?(outfile)
+            rescue
+                debug("file #{outfile} may be invalid")
+            end
+        end
+        return ok
+
+    end
+
+    def convertbounded(inpfile, outfile)
+        report("converting #{inpfile} bounded")
+        do_convertbounded(inpfile, outfile)
+    end
+
+    def do_convertbounded(inpfile, outfile)
+
+        begin
+            return false if FileTest.file?(outfile) && (! File.delete(outfile))
+        rescue
+            return false
+        end
+
+        arguments = ''
+        arguments << "\@gsprofile.ini "
+        arguments << "-q -sDEVICE=pdfwrite -dNOPAUSE -dNOCACHE -dBATCH -dSAFER "
+        arguments << "#{gscolorswitch} "
+        arguments << "#{gsdefaults} "
+        arguments << "-sOutputFile=#{outfile} #{gsstream} -c quit "
+
+        debug("ghostscript: #{arguments}")
+        debug('opening input file')
+
+        @rs = Tool.line_separator(inpfile)
+        debug("platform mac") if @rs == "\r"
+
+        if FileTest.file?(outfile) and not File.writable?(outfile) then
+            report("output file cannot be written")
+            return false
+        elsif not tmp = open(inpfile, 'rb') then
+            report("input file cannot be opened")
+            return false
+        end
+
+        debug('opening pipe/file')
+
+        if getvariable('pipe') then
+
+            return false unless eps = IO.popen(System.command('ghostscript',arguments),'wb')
+            debug('piping data')
+            unless pipebounded(tmp,eps) then
+                debug('something went wrong in the pipe')
+                File.delete(outfile) if FileTest.file?(outfile)
+            end
+            debug('closing pipe')
+            eps.close_write
+
+        else
+
+            return false unless eps = File.open(@@pstempfile, 'wb')
+
+            debug('copying data')
+
+            if pipebounded(tmp,eps) then
+                eps.close
+                debug('processing temp file')
+                begin
+                    ok = System.run('ghostscript',arguments)
+                rescue
+                    ok = false
+                    # debug("fatal error: #{$!}")
+                ensure
+                end
+            else
+                eps.close
+                ok = false
+            end
+
+            unless ok then
+                begin
+                    report('no output file due to error')
+                    File.delete(outfile) if FileTest.file?(outfile)
+                rescue
+                    # debug("fatal error: #{$!}")
+                    debug('file',outfile,'may be invalid')
+                end
+            end
+
+            debug('deleting temp file')
+            begin
+                File.delete(@@pstempfile) if FileTest.file?(@@pstempfile)
+            rescue
+            end
+
+        end
+
+        tmp.close
+        return FileTest.file?(outfile)
+
+    end
+
+    # hm, strange, no execute here, todo ! ! !
+
+    def getdimensions (inpfile)
+
+        # -dEPSFitPage and -dEPSCrop behave weird (don't work)
+
+        arguments = "-sDEVICE=bbox -dSAFER -dNOPAUSE -dBATCH #{inpfile} "
+
+        debug("ghostscript: #{arguments}")
+
+        begin
+            bbox = System.run('ghostscript',arguments,true,true)
+        rescue
+            bbox = ''
+        end
+
+        resetdimensions
+
+        debug('bbox spec', bbox)
+
+        if bbox =~ /(Exact|HiRes)BoundingBox:#{@@bboxspec}/moi then
+            debug("high res bbox #{$2} #{$3} #{$4} #{$5}")
+            setdimensions($2,$3,$4,$5)
+        elsif bbox =~ /BoundingBox:#{@@bboxspec}/moi
+            debug("low res bbox #{$1} #{$2} #{$3} #{$4}")
+            setdimensions($1,$2,$3,$4)
+        end
+
+        return dimensions?
+
+    end
+
+    # def convertcropped (inpfile, outfile)
+        # report("converting #{inpfile} cropped")
+        # do_convertbounded(inpfile, @@pdftempfile)
+        # return unless FileTest.file?(@@pdftempfile)
+        # arguments = " --offset=#{@offset} #{@@pdftempfile} #{outfile}"
+        # report("calling #{@@pdftrimwhite}")
+        # unless ok = System.run(@@pdftrimwhite,arguments) then
+            # report('cropping failed')
+            # begin
+                # File.delete(outfile)
+            # rescue
+            # end
+            # begin
+                # File.move(@@pdftempfile,outfile)
+            # rescue
+                # File.copy(@@pdftempfile,outfile)
+                # File.delete(@@pdftempfile)
+            # end
+        # end
+        # return ok
+    # end
+
+    def convertcropped (inpfile, outfile)
+        report("converting #{inpfile} cropped")
+        if File.expand_path(inpfile) == File.expand_path(outfile) then
+            report("output filename must be different")
+        elsif inpfile =~ /\.pdf$/io then
+            System.run("pdftops -eps #{inpfile} #{@@pstempfile}")
+            if getdimensions(@@pstempfile) then
+                report("tight boundingbox found")
+            end
+            do_convertbounded(@@pstempfile, outfile)
+            File.delete(@@pstempfile) if FileTest.file?(@@pstempfile)
+        else
+            if getdimensions(inpfile) then
+                report("tight boundingbox found")
+            end
+            do_convertbounded(inpfile, outfile)
+        end
+        resetdimensions
+        return true
+    end
+
+
+    def pipebounded (eps, out)
+
+        epsbbox, skip, buffer = false, false, ''
+
+        while str = eps.gets(rs=@rs) do
+            if str =~ /^%!PS/oi then
+                debug("looks like a valid ps file")
+                break
+            elsif str =~ /%PDF\-\d+\.\d+/oi then
+                debug("looks like a pdf file, so let\'s quit")
+                return false
+            end
+        end
+
+        # why no BeginData check
+
+        eps.rewind
+
+if dimensions? then
+
+        debug('using found boundingbox')
+
+else
+
+        debug('locating boundingbox')
+        while str = eps.gets(rs=@rs) do
+            case str
+                when /^%%Page:/io then
+                    break
+                when /^%%(Crop|HiResBounding|ExactBounding)Box:#{@@bboxspec}/moi then
+                    debug('high res boundingbox found')
+                    setdimensions($2,$3,$4,$5)
+                    break
+                when /^%%BoundingBox:#{@@bboxspec}/moi then
+                    debug('low res boundingbox found')
+                    setdimensions($1,$2,$3,$4)
+            end
+        end
+        debug('no boundingbox found') if @width == 0
+
+end
+
+        eps.rewind
+
+        while str = eps.gets(rs=@rs) do
+            if str.sub!(/^(.*)%!PS/moi, "%!PS") then
+                debug("removing pre banner data")
+                out.puts(str)
+                break
+            end
+        end
+
+        while str = eps.gets(rs=@rs) do
+            if skip then
+                skip = false if str =~ /^%+(EndData|EndPhotoshop|BeginProlog).*$/o
+                out.puts(str) if $1 == "BeginProlog"
+            elsif str =~ /^%(BeginPhotoshop)\:\s*\d+.*$/o then
+                skip = true
+            elsif str =~ /^%%/mos then
+                if ! epsbbox && str =~ /^%%(Page:|EndProlog)/io then
+                    out.puts(str) if $1 == "EndProlog"
+                    debug('faking papersize')
+                    # out.puts("<< /PageSize [#{@width} #{@height}] >> setpagedevice\n")
+                    if ! dimensions? then
+                        out.puts("<< /PageSize [1 1] >> setpagedevice\n")
+                    else
+                        out.puts("<< /PageSize [#{@width} #{@height}] >> setpagedevice\n")
+                    end
+                    out.puts("gsave #{@xoffset} #{@yoffset} translate\n")
+                    epsbbox = true
+                elsif str =~ /^%%BeginBinary\:\s*\d+\s*$/o then
+                    debug('copying binary data')
+                    out.puts(str)
+                    while str = eps.gets(rs=@rs)
+                        if str =~ /^%%EndBinary\s*$/o then
+                            out.puts(str)
+                        else
+                            out.write(str)
+                        end
+                    end
+                elsif str =~ /^%AI9\_PrivateDataBegin/o then
+                    debug('ignore private ai crap')
+                    break
+                elsif str =~ /^%%EOF/o then
+                    debug('ignore post eof crap')
+                    break
+                # elsif str =~ /^%%PageTrailer/o then
+                    # debug('ignoring post page trailer crap')
+                    # break
+                elsif str =~ /^%%Trailer/o then
+                    debug('ignoring post trailer crap')
+                    break
+                elsif str =~ /^%%Creator.*Illustrator.*$/io then
+                    debug('getting rid of problematic creator spec')
+                    str = "% Creator: Adobe Illustrator ..."
+                    out.puts(str)
+                elsif str =~ /^%%AI.*(PaperRect|Margin)/io then
+                    debug('removing AI paper crap')
+                elsif str =~ /^%%AI.*Version.*$/io then
+                    debug('removing dangerous version info')
+                elsif str =~ /^(%+AI.*Thumbnail.*)$/o then
+                    debug('skipping AI thumbnail')
+                    skip = true
+                else
+                    out.puts(str)
+                end
+            else
+                out.puts(str)
+            end
+        end
+
+        debug('done, sending EOF')
+
+        out.puts "grestore\n%%EOF\n"
+
+        # ok = $? == 0
+        # report('process aborted, broken pipe, fatal error') unless ok
+        # return ok
+
+resetdimensions
+
+        return true
+
+    end
+
+    def downsample (inpfile, outfile, method='screen')
+
+        # gs <= 8.50
+
+        report("downsampling #{inpfile}")
+
+        doit = true
+        unless getvariable('force') then
+            begin
+                if f = File.open(inpfile) then
+                    f.binmode
+                    while doit && (data = f.gets) do
+                        if data =~ /\/ArtBox\s*\[\s*[\d\.]+\s+[\d\.]+\s+[\d\.]+\s+[\d\.]+\s*\]/io then
+                            doit = false
+                        end
+                    end
+                    f.close
+                end
+            rescue
+            end
+        end
+
+        if doit then
+            arguments = ''
+            arguments << "-dPDFSETTINGS=/#{method} -dEmbedAllFonts=true "
+            arguments << "#{gscolorswitch} "
+            arguments << "#{gsdefaults} "
+            arguments << "-q -sDEVICE=pdfwrite -dNOPAUSE -dNOCACHE -dBATCH -dSAFER "
+            arguments << "-sOutputFile=#{outfile} #{inpfile} -c quit "
+            unless ok = System.run('ghostscript',arguments) then
+                begin
+                    File.delete(outfile) if FileTest.file?(outfile)
+                    report("removing file #{outfile}")
+                rescue
+                    debug("file #{outfile} may be invalid")
+                end
+            end
+            return ok
+        else
+            report("crop problem, straight copying #{inpfile}")
+            File.copy(inpfile,outfile)
+            return false
+        end
+
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/graphics/gs.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/graphics/inkscape.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/graphics/inkscape.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/graphics/inkscape.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,113 @@
+# module    : graphics/inkscape
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# ['base/variables','variables'].each do |r| begin require r ; rescue Exception ; else break ; end ; end
+# ['graphics/gs','gs'].each   do |r| begin require r ; rescue Exception ; else break ; end ; end
+
+require 'base/variables'
+require 'base/system'
+require 'graphics/gs'
+
+class InkScape
+
+    include Variables
+
+    def initialize(logger=nil)
+
+        unless logger then
+            puts('inkscape class needs a logger')
+            exit
+        end
+
+        @variables = Hash.new
+        @logger    = logger
+
+        reset
+
+    end
+
+    def reset
+        # nothing yet
+    end
+
+    def supported?(filename)
+        filename =~ /.*\.(svg|svgz)/io
+    end
+
+    def convert(logfile=System.null)
+
+        directpdf = false
+
+        logfile = logfile.gsub(/\/+$/,"")
+
+        inpfilename = getvariable('inputfile').dup
+        outfilename = getvariable('outputfile').dup
+        outfilename = inpfilename.dup if outfilename.empty?
+        outfilename.gsub!(/(\.[^\.]*?)$/, ".pdf")
+        tmpfilename = outfilename.gsub(/(\.[^\.]*?)$/, ".ps")
+
+        if inpfilename.empty? || outfilename.empty? then
+            report("no filenames given")
+            return false
+        end
+        if inpfilename == outfilename then
+            report("filenames must differ (#{inpfilename} #{outfilename})")
+            return false
+        end
+        unless FileTest.file?(inpfilename) then
+            report("unknown file #{inpfilename}")
+            return false
+        end
+
+        # we need to redirect the error info else we get a pop up console
+
+        if directpdf then
+            report("converting #{inpfilename} to #{outfilename}")
+          # resultpipe = "--without-gui --export-pdf=\"#{outfilename}\" 2>#{logfile}"
+            resultpipe = "--without-gui --export-filename=\"#{outfilename}\" 2>#{logfile}"
+        else
+            report("converting #{inpfilename} to #{tmpfilename}")
+            resultpipe = "--without-gui --print=\">#{tmpfilename}\" 2>#{logfile}"
+        end
+
+        arguments = [resultpipe,inpfilename].join(' ').gsub(/\s+/,' ')
+
+        ok = true
+        begin
+            debug("inkscape: #{arguments}")
+            # should work
+            # ok = System.run('inkscape',arguments) # does not work here
+            # but 0.40 only works with this:
+            command = "inkscape #{arguments}"
+            report(command)
+            ok = system(command)
+            # and 0.41 fails with everything
+            # and 0.45 is better
+        rescue
+            report("aborted due to error")
+            return false
+        else
+            return false unless ok
+        end
+
+        if not directpdf then
+            ghostscript = GhostScript.new(@logger)
+            ghostscript.setvariable('inputfile',tmpfilename)
+            ghostscript.setvariable('outputfile',outfilename)
+            report("converting #{tmpfilename} to #{outfilename}")
+            ghostscript.convert
+            begin
+                File.delete(tmpfilename)
+            rescue
+            end
+        end
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/graphics/inkscape.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/graphics/magick.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/graphics/magick.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/graphics/magick.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,161 @@
+# module    : graphics/inkscape
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# ['base/variables','variables'].each do |r| begin require r ; rescue Exception ; else break ; end ; end
+
+require 'base/variables'
+
+class ImageMagick
+
+    include Variables
+
+    def initialize(logger=nil)
+
+        unless logger then
+            puts('magick class needs a logger')
+            exit
+        end
+
+        @variables = Hash.new
+        @logger    = logger
+
+        reset
+
+    end
+
+    def reset
+        ['compression','depth','colorspace','quality'].each do |key|
+            setvariable(key)
+        end
+    end
+
+    def supported?(filename) # ? pdf
+        filename =~ /.*\.(png|gif|tif|tiff|jpg|jpeg|eps|ai\d*)/io
+    end
+
+    def convert(suffix='pdf')
+
+        inpfilename = getvariable('inputfile').dup
+        outfilename = getvariable('outputfile').dup
+        outfilename = inpfilename.dup if outfilename.empty?
+        outfilename.gsub!(/(\.[^\.]*?)$/, ".#{suffix}")
+
+        if inpfilename.empty? || outfilename.empty? then
+            report("no filenames given")
+            return false
+        end
+        if inpfilename == outfilename then
+            report("filenames must differ (#{inpfilename} #{outfilename})")
+            return false
+        end
+        unless FileTest.file?(inpfilename) then
+            report("unknown file #{inpfilename}")
+            return false
+        end
+
+        if inpfilename =~ /\.tif+$/io then
+            tmpfilename = 'temp.png'
+            arguments = "#{inpfilename} #{tmpfilename}"
+            begin
+                debug("imagemagick: #{arguments}")
+                ok = System.run('imagemagick',arguments)
+            rescue
+                report("aborted due to error")
+                return false
+            else
+                return false unless ok
+            end
+            inpfilename = tmpfilename
+        end
+
+        compression = depth = colorspace = quality = ''
+
+        if getvariable('compression') =~ /(zip|jpeg)/o then
+            compression = " -compress #{$1}"
+        end
+        if getvariable('depth') =~ /(8|16)/o then
+            depth = "-depth #{$1}"
+        end
+        if getvariable('colorspace') =~ /(gray|rgb|cmyk)/o then
+            colorspace = "-colorspace #{$1}"
+        end
+        case getvariable('quality')
+            when 'low'    then quality = '-quality 0'
+            when 'medium' then quality = '-quality 75'
+            when 'high'   then quality = '-quality 100'
+        end
+
+        report("converting #{inpfilename} to #{outfilename}")
+
+        arguments = [compression,depth,colorspace,quality,inpfilename,outfilename].join(' ').gsub(/\s+/,' ')
+
+        begin
+            debug("imagemagick: #{arguments}")
+            ok = System.run('imagemagick',arguments)
+        rescue
+            report("aborted due to error")
+            return false
+        else
+            return ok
+        end
+
+    end
+
+    def autoconvert
+
+        inpfilename = getvariable('inputfile')
+        outfilename = getvariable('outputfile')
+
+        if inpfilename.empty? || ! FileTest.file?(inpfilename) then
+            report("missing file #{inpfilename}")
+            return
+        end
+
+        outfilename = inpfilename.dup if outfilename.empty?
+        tmpfilename = 'temp.jpg'
+
+        reset
+
+        megabyte = 1024*1024
+
+        ok = false
+
+        if FileTest.size(inpfilename)>2*megabyte
+            setvariable('compression','zip')
+            ok = convert
+        else
+            setvariable('compression','jpeg')
+            if FileTest.size(inpfilename)>10*megabyte then
+                setvariable('quality',85)
+            elsif FileTest.size(inpfilename)>5*megabyte then
+                setvariable('quality',90)
+            else
+                setvariable('quality',95)
+            end
+            report("auto quality #{getvariable('quality')}")
+            setvariable('outputfile', tmpfilename)
+            ok = convert('jpg')
+            setvariable('inputfile', tmpfilename)
+            setvariable('outputfile', outfilename)
+            ok = convert
+            begin
+                File.delete(tmpfilename)
+            rescue
+                report("#{tmpfilename} cannot be deleted")
+            end
+        end
+
+        reset
+
+        return ok
+
+ end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/graphics/magick.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/imgtopdf.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/imgtopdf.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/imgtopdf.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,86 @@
+#!/usr/bin/env ruby
+
+# program   : newimgtopdf
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2006
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+unless defined? ownpath
+  ownpath = $0.sub(/[\\\/]\w*?\.rb/i,'')
+  $: << ownpath
+end
+
+require 'base/switch'
+require 'base/logger'
+
+require 'graphics/magick'
+
+banner = ['ImgToPdf', 'version 1.1.2', '2002-2006', 'PRAGMA ADE/POD']
+
+class Commands
+
+    include CommandBase
+
+    # nowadays we would force a directive, but
+    # for old times sake we handle default usage
+
+    def main
+        filename = @commandline.argument('first')
+
+        if filename.empty? then
+            help
+        else
+            convert
+        end
+    end
+
+    # actions
+
+    def convert
+
+        magick = Magick.new(session)
+
+        ['compression','depth','colorspace','quality','inputpath','outputpath'].each do |v|
+            magick.setvariable(v, at commandline.option(v))
+        end
+
+        @commandline.arguments.each do |fullname|
+            magick.setvariable('inputfile',fullname)
+            magick.setvariable('outputfile',fullname.gsub(/(\..*?$)/io, '.pdf'))
+            if @commandline.option('auto') then
+                magick.autoconvert
+            else
+                magick.convert
+            end
+        end
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registerflag('auto')
+
+commandline.registervalue('compression')
+commandline.registervalue('depth')
+commandline.registervalue('colorspace')
+commandline.registervalue('quality')
+
+commandline.registervalue('inputpath')
+commandline.registervalue('outputpath')
+
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registeraction('convert', 'convert image into pdf')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'main')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/imgtopdf.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/pdftools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/pdftools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/pdftools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,861 @@
+#!/usr/bin/env ruby
+
+# program   : pdftools
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2003-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# This script will harbor some handy manipulations on tex
+# related files.
+
+banner = ['PDFTools', 'version 1.2.1', '2003/2005', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'base/switch'
+require 'base/logger'
+
+require 'fileutils'
+# require 'ftools'
+
+class File
+
+    def File.deletefiles(*filenames)
+        filenames.flatten.each do |filename|
+            begin
+                delete(filename) if FileTest.file?(filename)
+            rescue
+            end
+        end
+    end
+
+    def File.needsupdate(oldname,newname)
+        begin
+            return File.stat(oldname).mtime != File.stat(newname).mtime
+        rescue
+            return true
+        end
+    end
+
+    def File.syncmtimes(oldname,newname)
+        begin
+            t = Time.now # i'm not sure if the time is frozen, so we do it here
+            File.utime(0,t,oldname,newname)
+        rescue
+        end
+    end
+
+    def File.replacesuffix(oldname,subpath='')
+        newname = File.expand_path(oldname.sub(/\.\w+?$/,'.pdf'))
+        File.join(File.dirname(newname),subpath,File.basename(newname))
+    end
+
+end
+
+class ImageMagick
+
+    def initialize
+
+        begin
+            version = `convert -version`
+        rescue
+            @binary = nil
+        ensure
+            if (version) && (! version.empty?) && (version =~ /ImageMagick/mo) && (version =~ /version/mio) then
+                @binary = 'convert'
+            else
+                @binary = 'imagemagick'
+            end
+        end
+
+    end
+
+    def process(arguments)
+        begin
+            @binary && system("#{@binary} #{arguments}")
+        rescue
+            false
+        end
+    end
+
+end
+
+class TexExec
+
+    def initialize
+        @binary = 'texmfstart texexec.pl --pdf --batch --silent --purge'
+    end
+
+    def process(arguments,once=true)
+       begin
+            if once then
+                @binary && system("#{@binary} --once #{arguments}")
+            else
+                @binary && system("#{@binary} #{arguments}")
+            end
+       rescue
+            false
+       end
+    end
+
+end
+
+class PdfImages
+
+    def initialize
+        @binary = "pdfimages"
+    end
+
+    def process(arguments)
+       begin
+            @binary && system("#{@binary} #{arguments}")
+       rescue
+            false
+       end
+    end
+
+end
+
+class ConvertImage
+
+    def initialize(command=nil)
+        @command = command
+    end
+
+    def convertimage(filename)
+
+        return if filename =~ /\.(pdf)$/io
+
+        retain = @command.option('retain')
+        subpath = @command.option('subpath')
+
+        if filename =~ /\s/ then
+            @command.report("skipping strange filename '#{filename}'")
+        else
+            newname = File.replacesuffix(filename,subpath)
+            # newname.gsub!(s/[^a-zA-Z0-9\_-\.]/o, '-')
+            begin
+                File.makedirs(File.dirname(newname))
+            rescue
+            end
+            if ! retain || File.needsupdate(filename,newname) then
+                imagemagick = ImageMagick.new
+                if imagemagick then
+                    ok = imagemagick.process("-compress zip -quality 99 #{filename} #{newname}")
+                    File.syncmtimes(oldname,newname) if retain
+                end
+            end
+        end
+    end
+
+end
+
+class DownsampleImage
+
+    def initialize(command=nil)
+        @command = command
+    end
+
+    def convertimage(filename)
+
+        return if filename =~ /\.(pdf)$/io
+
+        retain  = @command.option('retain')
+        subpath = @command.option('subpath')
+
+        if @command.option('lowres') then
+            method = '4'
+        elsif @command.option('medres') || @command.option('normal') then
+            method = '5'
+        else
+            method = '4'
+        end
+
+        if filename =~ /\s/ then
+            @command.report("skipping strange filename '#{filename}'")
+        else
+            newname = File.replacesuffix(filename,subpath)
+            begin
+                File.makedirs(File.dirname(newname))
+            rescue
+            end
+            if ! retain || File.needsupdate(filename,newname) then
+                ok = system("texmfstart pstopdf.rb --method=#{method} #{filename} #{newname}")
+                File.syncmtimes(oldname,newname) if retain
+            end
+        end
+    end
+
+end
+
+class ColorImage
+
+    def initialize(command=nil,tmpname='pdftools')
+        @command    = command
+        @tmpname    = tmpname
+        @colorname  = nil
+        @colorspec  = nil
+        @colorspace = nil
+    end
+
+    def registercolor(spec='.5',name='c')
+        name = name || 'c'
+        spec = spec.split(',')
+        case spec.length
+            when 4
+                @colorname, @colorspec, @colorspace = name, spec.join('/'), 'cmyk'
+            when 3
+                @colorname, @colorspec, @colorspace = name, spec.join('/'), 'rgb'
+            when 1
+                @colorname, @colorspec, @colorspace = name, spec.join('/'), 'gray'
+            else
+                @colorname, @colorspec, @colorspace = nil, nil, nil
+        end
+    end
+
+    def convertimage(filename)
+
+        invert = @command.option('invert')
+        retain = @command.option('retain')
+        subpath = @command.option('subpath')
+
+        subpath += '/' unless subpath.empty?
+
+        if @colorname && ! @colorname.empty? && @colorspec && ! @colorspec.empty? then
+            basename = filename.sub(/\.\w+?$/,'')
+            oldname = filename
+            ppmname = @tmpname + '-000.ppm'
+            jpgname = @tmpname + '-000.jpg'
+            newname = File.expand_path(oldname)
+            newname = File.dirname(newname) + '/' + subpath + @colorname + '-' + File.basename(newname)
+            newname.sub!(/\.\w+?$/, '.pdf')
+            begin
+                File.makedirs(File.dirname(newname))
+            rescue
+            end
+            if ! retain || File.needsupdate(filename,newname) then
+                pdfimages = PdfImages.new
+                imagemagick = ImageMagick.new
+                if pdfimages && imagemagick then
+                    File.deletefiles(ppmname,jpgname,newname)
+                    if filename =~ /\.(pdf)$/io then
+                        ok = pdfimages.process("-j -f 1 -l 1 #{filename} #{@tmpname}")
+                        if ok then
+                            if FileTest.file?(ppmname) then
+                                inpname = ppmname
+                            elsif FileTest.file?(jpgname) then
+                                inpname = jpgname
+                            else
+                                ok = false
+                            end
+                            if ok then
+                                switch = if ! invert then '-negate' else '' end
+                                # make sure that we keep the format
+                                tmpname = File.basename(inpname)
+                                tmpname = tmpname.sub(/(.*)\..*?$/, at tmpname) # somehow sub! fails here
+                                ok = imagemagick.process("-colorspace gray #{switch} #{inpname} #{tmpname}")
+                                if ! ok || ! FileTest.file?(tmpname) then
+                                    # problems
+                                else
+                                    ok = imagemagick.process("-colorspace #{switch} #{@colorspace} -colorize #{@colorspec} -compress zip #{tmpname} #{newname}")
+                                    if ! ok || ! FileTest.file?(newname) then
+                                        # unable to colorize image
+                                    else
+                                        # conversion done
+                                    end
+                                end
+                            end
+                        end
+                    else
+                        # make sure that we keep the format
+                        tmpname = File.basename(basename)
+                        tmpname = tmpname.sub(/(.*)\..*?$/, at tmpname) # somehow sub! fails here
+                        ok = imagemagick.process("-colorspace gray #{oldname} #{tmpname}")
+                        if ! ok || ! FileTest.file?(tmpname) then
+                            # unable to convert color to gray
+                        else
+                            ok = imagemagick.process("-colorspace #{@colorspace} -colorize #{@colorspec} -compress zip #{tmpname} #{newname}")
+                            if ! ok || ! FileTest.file?(newname) then
+                                # unable to colorize image
+                            else
+                                # conversion done
+                            end
+                        end
+                    end
+                    File.deletefiles(ppmname,jpgname,tmpname)
+                    File.syncmtimes(filename,newname) if retain
+                end
+            end
+        end
+    end
+
+end
+
+class SpotColorImage
+
+    def initialize(command=nil, tmpname='pdftools')
+        @command    = command
+        @tmpname    = tmpname
+        @colorname  = nil
+        @colorspec  = nil
+        @colorspace = nil
+        @colorfile  = nil
+    end
+
+    def registercolor(spec='.5',name='unknown')
+        name = name || 'unknown'
+        if spec =~ /^[\d\.\,]+$/ then
+            spec = spec.split(',')
+            case spec.length
+                when 4
+                    @colorname, @colorspec, @colorspace = name, ["c=#{spec[0]}","m=#{spec[1]}","y=#{spec[2]}","k=#{spec[3]}"].join(','), 'cmyk'
+                when 3
+                    @colorname, @colorspec, @colorspace = name, ["r=#{spec[0]}","g=#{spec[1]}","b=#{spec[2]}"].join(','), 'rgb'
+                when 1
+                    @colorname, @colorspec, @colorspace = name, ["s=#{spec[0]}"].join(','), 'gray'
+                else
+                    @colorname, @colorspec, @colorspace = nil, nil, nil
+            end
+        else
+            @colorname, @colorfile = name, spec
+        end
+    end
+
+    def convertgrayimage(filename)
+
+        invert  = @command.option('invert')
+        retain  = @command.option('retain')
+        subpath = @command.option('subpath')
+
+        subpath += '/' unless subpath.empty?
+
+        if @colorname && ! @colorname.empty? && ((@colorspec && ! @colorspec.empty?) || (@colorfile && ! @colorfile.empty?))  then
+            basename = filename.sub(/\.\w+?$/,'')
+            oldname  = filename # png jpg pdf
+            newname  = File.expand_path(oldname)
+            ppmname  = @tmpname + '-000.ppm'
+            jpgname  = @tmpname + '-000.jpg'
+            outname  = @tmpname + '-000.pdf'
+            texname  = @tmpname + '-temp.tex'
+            pdfname  = @tmpname + '-temp.pdf'
+            newname  = File.dirname(newname) + '/' + subpath + @colorname + '-' + File.basename(newname)
+            newname.sub!(/\.\w+?$/, '.pdf')
+            begin
+                File.makedirs(File.dirname(newname))
+            rescue
+            end
+            if ! retain || File.needsupdate(filename,newname) then
+                pdfimages = PdfImages.new
+                imagemagick = ImageMagick.new
+                texexec  = TexExec.new
+                if pdfimages && imagemagick && texexec then
+                    if filename =~ /\.(jpg|png|pdf)$/io then
+                        @command.report("processing #{basename}")
+                        File.deletefiles(ppmname,jpgname,newname)
+                        switch = if ! invert then '-negate' else '' end
+                        if filename =~ /\.(pdf)$/io then
+                            ok = pdfimages.process("-j -f 1 -l 1 #{oldname} #{@tmpname}")
+                            if ok then
+                                if FileTest.file?(ppmname) then
+                                    inpname = ppmname
+                                elsif FileTest.file?(jpgname) then
+                                    inpname = jpgname
+                                else
+                                    ok = false
+                                end
+                                if ok then
+                                    ok = imagemagick.process("-colorspace gray #{switch} -compress zip #{inpname} #{outname}")
+                                end
+                            end
+                        else
+                            ok = imagemagick.process("-colorspace gray #{switch} -compress zip #{oldname} #{outname}")
+                        end
+                        if ok then
+                            ok = false unless FileTest.file?(outname)
+                        end
+                        if ok then
+                            if f = File.open(texname, 'w') then
+                                f.puts(conversionfile(filename,outname,newname))
+                                f.close
+                                ok = texexec.process(texname)
+                            else
+                                ok = false
+                            end
+                            @command.report("error in processing #{newname}") unless ok
+                            if FileTest.file?(pdfname) then
+                                if f = File.open(pdfname,'r') then
+                                    f.binmode
+                                    begin
+                                        if g = File.open(newname,'w') then
+                                            g.binmode
+                                            data = f.read
+                                            # pdftex (direct) & imagemagick (indirect)
+                                            if data =~ /(\d+)\s+0\s+obj\s+\[\/Separation\s+\/#{@colorname}/mos then
+                                                @command.report("replacing separation color")
+                                                object = $1
+                                                data.gsub!(/(\/Type\s+\/XObject.*?)(\/ColorSpace\s*(\/DeviceGray|\/DeviceCMYK|\/DeviceRGB|\d+\s+\d+\s+R))/moi) do
+                                                    $1 + "/ColorSpace #{object} 0 R".ljust($2.length)
+                                                end
+                                            elsif data =~ /(\d+)\s+0\s+obj\s+\[\/Indexed\s*\[/mos then
+                                                @command.report("replacing indexed color")
+                                                # todo: more precise check on color
+                                                object = $1
+                                                data.gsub!(/(\/Type\s+\/XObject.*?)(\/ColorSpace\s*(\/DeviceGray|\/DeviceCMYK|\/DeviceRGB|\d+\s+\d+\s+R))/moi) do
+                                                    $1 + "/ColorSpace #{object} 0 R".ljust($2.length)
+                                                end
+                                            elsif data =~ /(\d+)\s+0\s+obj\s+\[\/Separation/mos then
+                                                @command.report("replacing separation color")
+                                                object = $1
+                                                data.gsub!(/(\/Type\s+\/XObject.*?)(\/ColorSpace\s*(\/DeviceGray|\/DeviceCMYK|\/DeviceRGB|\d+\s+\d+\s+R))/moi) do
+                                                    $1 + "/ColorSpace #{object} 0 R".ljust($2.length)
+                                                end
+                                            end
+                                            g.write(data)
+                                            g.close
+                                        end
+                                    rescue
+                                        @command.report("error in converting #{newname}")
+                                    else
+                                        @command.report("#{newname} is converted")
+                                    end
+                                    f.close
+                                end
+                            else
+                                @command.report("error in writing #{newname}")
+                            end
+                        else
+                            @command.report("error in producing #{newname}")
+                        end
+                        File.deletefiles(ppmname,jpgname,outname)
+                        # File.deletefiles(texname,pdfname)
+                        File.syncmtimes(filename,newname) if retain
+                    end
+                else
+                    @command.report("error in locating binaries")
+                end
+            else
+                @command.report("#{newname} is not changed")
+            end
+        end
+    end
+
+    private
+
+    # % example colorfile:
+    #
+    # \definecolor [darkblue]   [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
+    # \definecolor [darkyellow] [c=0,m=.28,y=1,k=.06] % pantone pms  124 uncoated m
+    #
+    # % \definecolor [darkblue-100]    [darkblue]   [p=1]
+    # % \definecolor [darkyellow-100]  [darkyellow] [p=1]
+    #
+    # \definecolorcombination [pdftoolscolor] [darkblue=.12,darkyellow=.28] [c=.1,m=.1,y=.3,k=.1]
+
+    def conversionfile(originalname,filename,finalname)
+        tex = "\\setupcolors[state=start]\n"
+        if @colorfile then
+            tex += "\\readfile{#{@colorfile}}{}{}\n"
+            tex += "\\starttext\n"
+            # tex += "\\predefineindexcolor[pdftoolscolor]\n"
+            tex += "\\startTEXpage\n"
+            tex += "\\pdfimage{#{filename}}\n"
+            tex += "\\stopTEXpage\n"
+            tex += "\\stoptext\n"
+        else
+            tex += "\\definecolor[#{@colorname}][#{@colorspec}]\n"
+            tex += "\\definecolor[pdftoolscolor][#{@colorname}][p=1]\n"
+            tex += "\\starttext\n"
+            tex += "\\startTEXpage\n"
+            tex += "\\hbox{\\color[pdftoolscolor]{\\pdfimage{#{filename}}}}\n"
+            tex += "\\stopTEXpage\n"
+            tex += "\\stoptext\n"
+        end
+        tex += "\n"
+        tex += "% old: #{originalname}\n"
+        tex += "% new: #{finalname}\n"
+        return tex
+    end
+
+end
+
+module XML
+
+    def XML::version
+        "<?xml version='1.0'?>"
+    end
+
+    def XML::start(element, attributes='')
+        if attributes.empty? then
+            "<#{element}>"
+        else
+            "<#{element} #{attributes}>"
+        end
+    end
+
+    def XML::end(element)
+        "</#{element}>"
+    end
+
+    def XML::empty(element, attributes='')
+        if attributes && attributes.empty? then
+            "<#{element}/>"
+        else
+            "<#{element} #{attributes}/>"
+        end
+    end
+
+    def XML::element(element, attributes='', content='')
+        if content && ! content.empty? then
+            XML::start(element,attributes) + content + XML::end(element)
+        else
+            XML::empty(element,attributes)
+        end
+    end
+
+    def XML::box(tag, rect, type=1)
+        case type
+            when 1
+                if rect && ! rect.empty? then
+                    rect = rect.split(' ')
+                    XML::element("#{tag}box", '',
+                        XML::element("llx", '', rect[0]) +
+                        XML::element("lly", '', rect[1]) +
+                        XML::element("ulx", '', rect[2]) +
+                        XML::element("uly", '', rect[3]) )
+                else
+                    XML::empty("#{tag}box")
+                end
+            when 2
+                if rect && ! rect.empty? then
+                    rect = rect.split(' ')
+                    XML::element("box", "type='#{tag}'",
+                        XML::element("llx", '', rect[0]) +
+                        XML::element("lly", '', rect[1]) +
+                        XML::element("ulx", '', rect[2]) +
+                        XML::element("uly", '', rect[3]) )
+                else
+                    XML::empty("box", "type='#{tag}'")
+                end
+            when 3
+                if rect && ! rect.empty? then
+                    rect = rect.split(' ')
+                    XML::element("box", "type='#{tag}' llx='#{rect[0]}' lly='#{rect[1]}' ulx='#{rect[2]}' uly='#{rect[3]}'")
+                else
+                    XML::empty("box", "type='#{tag}'")
+                end
+            else
+                ''
+        end
+    end
+
+    def XML::crlf
+        "\n"
+    end
+
+    def XML::skip(n=1)
+        '  '*n
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    # alias savedhelp :help
+
+    # def help
+        # savedhelp
+        # report("under construction (still separate tools)")
+    # end
+
+    # filename.pdf --spotimage --colorname=darkblue --colorspec=1,0.38,0,0.64
+
+    def spotimage
+
+        if ! @commandline.argument('first').empty? && files = findfiles() then
+            colorname = @commandline.option('colorname')
+            colorspec = @commandline.option('colorspec')
+            if colorname && ! colorname.empty? && colorspec && ! colorspec.empty? then
+                files.each do |filename|
+                    s = SpotColorImage.new(self)
+                    s.registercolor(colorspec,colorname)
+                    s.convertgrayimage(filename)
+                end
+            else
+                report("provide --colorname=somename --colorspec=c,m,y,k")
+            end
+        else
+            report("provide filename (png, jpg, pdf)")
+        end
+
+    end
+
+    def colorimage
+
+        if ! @commandline.argument('first').empty? && files = findfiles() then
+            colorname = @commandline.option('colorname')
+            colorspec = @commandline.option('colorspec')
+            if colorspec && ! colorspec.empty? then
+                files.each do |filename|
+                    s = ColorImage.new(self)
+                    s.registercolor(colorspec,colorname) # name optional
+                    s.convertimage(filename)
+                end
+            else
+                report("provide --colorspec=c,m,y,k")
+            end
+        else
+            report("provide filename")
+        end
+
+    end
+
+    def convertimage
+
+        if ! @commandline.argument('first').empty? && files = findfiles() then
+            files.each do |filename|
+                s = ConvertImage.new(self)
+                s.convertimage(filename)
+            end
+        else
+            report("provide filename")
+        end
+
+    end
+
+    def downsampleimage
+
+        if ! @commandline.argument('first').empty? && files = findfiles() then
+            files.each do |filename|
+                s = DownsampleImage.new(self)
+                s.convertimage(filename)
+            end
+        else
+            report("provide filename")
+        end
+
+    end
+
+    def info
+
+        if files = findfiles() then
+
+            print(XML.version + XML.crlf)
+            print(XML.start('pdfinfo', "xmlns='http://www.pragma-ade.com/schemas/pdfinfo.rng'") + XML.crlf)
+
+            files.each do |filename|
+
+                if filename =~ /\.pdf$/io then
+
+                    begin
+                        data = `pdfinfo -box #{filename}`.chomp.split("\n")
+                    rescue
+                        data = nil
+                    end
+
+                    if data then
+
+                        pairs = Hash.new
+
+                        data.each do |d|
+                            if (d =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/moi) then
+                                key, val = $1, $2
+                                pairs[key.downcase.sub(/ /,'')] = val
+                            end
+                        end
+
+                        print(XML.skip(1) + XML.start('pdffile', "filename='#{filename}'") + XML.crlf)
+
+                        print(XML.skip(2) + XML.element('path', '', File.expand_path(filename)) + XML.crlf)
+
+                        if pairs.key?('error') then
+
+                            print(XML.skip(2) + XML.element('comment', '', pairs['error']) + XML.crlf)
+
+                        else
+
+                            print(XML.skip(2) + XML.element('version',  '', pairs['pdfversion']) + XML.crlf)
+                            print(XML.skip(2) + XML.element('pages',    '', pairs['pages'     ]) + XML.crlf)
+                            print(XML.skip(2) + XML.element('title',    '', pairs['title'     ]) + XML.crlf)
+                            print(XML.skip(2) + XML.element('subject',  '', pairs['subject'   ]) + XML.crlf)
+                            print(XML.skip(2) + XML.element('author',   '', pairs['author'    ]) + XML.crlf)
+                            print(XML.skip(2) + XML.element('producer', '', pairs['producer'  ]) + XML.crlf)
+
+                            if pairs.key?('creationdate') then
+                                pairs['creationdate'].sub!(/(\d\d)\/(\d\d)\/(\d\d)/) do
+                                    '20' + $3 + '-' + $1 + '-' +$2
+                                end
+                                pairs['creationdate'].sub!(/(\d\d)\/(\d\d)\/(\d\d\d\d)/) do
+                                    $3 + '-' + $1 + '-' + $2
+                                end
+                                print(XML.skip(2) + XML.element('creationdate', '', pairs['creationdate']) + XML.crlf)
+                            end
+
+                            if pairs.key?('moddate') then
+                                if pairs['moddate'] =~ /(\d\d\d\d)(\d\d)(\d\d)/ then
+                                    pairs['moddate'] = "#{$1}-#{$2}-#{$3}"
+                                end
+                                print(XML.skip(2) + XML.element('modificationdate', '', pairs['moddate']) + XML.crlf)
+                            end
+
+                            print(XML.skip(2) + XML.element('tagged',    '', pairs['tagged'   ]) + XML.crlf)
+                            print(XML.skip(2) + XML.element('encrypted', '', pairs['encrypted']) + XML.crlf)
+                            print(XML.skip(2) + XML.element('optimized', '', pairs['optimized']) + XML.crlf)
+
+                            if pairs.key?('PageSize') then
+                                print(XML.skip(2) + XML.element('width',  '', pairs['pagesize'].sub(/\s*(.*?)\s+(.*?)\s+.*/, $1)) + XML.crlf)
+                                print(XML.skip(2) + XML.element('height', '', pairs['pagesize'].sub(/\s*(.*?)\s+(.*?)\s+.*/, $2)) + XML.crlf)
+                            end
+
+                            if pairs.key?('FileSize') then
+                                print(XML.skip(2) + XML.element('size', '', pairs['filesize'].sub(/\s*(.*?)\s+.*/, $1)) + XML.crlf)
+                            end
+
+                            print(XML.skip(2) + XML.box('media', pairs['mediabox']) + XML.crlf)
+                            print(XML.skip(2) + XML.box('crop' , pairs['cropbox' ]) + XML.crlf)
+                            print(XML.skip(2) + XML.box('bleed', pairs['bleedbox']) + XML.crlf)
+                            print(XML.skip(2) + XML.box('trim' , pairs['trimBox' ]) + XML.crlf)
+                            print(XML.skip(2) + XML.box('art'  , pairs['artbox'  ]) + XML.crlf)
+
+                        end
+
+                        print(XML.skip(1) + XML.end('pdffile') + XML.crlf)
+
+                    end
+
+                end
+
+            end
+
+            print(XML.end('pdfinfo') + XML.crlf)
+
+        end
+
+    end
+
+    # name                                 type         emb sub uni object ID
+    # ------------------------------------ ------------ --- --- --- ---------
+    # EOPLBP+TimesNewRomanPSMT             TrueType     yes yes no     167  0
+    # Times-Roman                          TrueType     no  no  no      95  0
+    # EPBAAB+Helvetica                     Type 1C      yes yes yes    108  0
+    # EPBMLE+Helvetica-Oblique             Type 1C      yes yes yes    111  0
+    # Helvetica                            TrueType     no  no  no     112  0
+
+    def checkembedded
+        $stderr = $stdout
+        $stdout.flush
+        if @commandline.option('pattern') then
+            # **/*.pdf
+            filenames, n = globfiles(@commandline.option('pattern'),'pdf'), 0
+        else
+            filenames, n = findfiles('pdf'), 0
+        end
+        filenames.sort.each do |file|
+            report("= checking #{File.expand_path(file)}")
+            result = `pdffonts #{file}`.chomp
+            lines = result.split(/\n/)
+            if result =~ /emb\s+sub\s+uni/io then
+                lines.each do |line|
+                    report("! #{line}") if line =~ /no\s+(no|yes)\s+(no|yes)/io
+                end
+            else
+                lines.each do |line|
+                    report("? #{line}")
+                end
+            end
+            report("")
+        end
+    end
+
+    def countpages
+        if @commandline.option('pattern') then
+            filenames, n = globfiles(@commandline.option('pattern'),'pdf'), 0
+        else
+            filenames, n = findfiles('pdf'), 0
+        end
+        threshold = @commandline.option('threshold').to_i rescue 0
+        filenames.each do |filename|
+            if `pdfinfo #{filename}`.chomp =~ /^pages\s*\:\s*(\d+)/moi then
+                p = $1
+                m = p.to_i rescue 0
+                if threshold == 0 or m > threshold then
+                    report("#{p.rjust(4)} pages found in #{filename}")
+                    n += m
+                end
+           end
+        end
+        report("")
+        report("#{n.to_s.rjust(4)} pages in total")
+    end
+
+    def analyzefile
+        # needs an update
+        filenames = @commandline.arguments
+        filenames.each do |filename|
+            if filename && FileTest.file?(filename) && filename =~ /\.pdf/io then
+                filesize = FileTest.size(filename)
+                report("analyzing file : #{filename}")
+                report("file size : #{filesize}")
+                if pdf = File.open(filename) then
+                    pdf.binmode
+                    nofobject, nofxform, nofannot, noflink, nofwidget, nofnamed, nofscript, nofcross = 0, 0, 0, 0, 0, 0, 0, 0
+                    while data = pdf.gets do
+                        data.scan(/\d+\s+\d+\s+obj/o)      do nofobject += 1 end
+                        data.scan(/\/Type\s*\/XObject/o)   do nofxform  += 1 end
+                        data.scan(/\/Type\s*\/Annot/o)     do nofannot  += 1 end
+                        data.scan(/\/GoToR\s*\/F/o)        do nofcross  += 1 end
+                        data.scan(/\/Subtype\s*\/Link/o)   do noflink   += 1 end
+                        data.scan(/\/Subtype\s*\/Widget/o) do nofwidget += 1 end
+                        data.scan(/\/S\s*\/Named/o)        do nofnamed  += 1 end
+                        data.scan(/\/S\s*\/JavaScript/o)   do nofscript += 1 end
+                    end
+                    pdf.close
+                    report("objects : #{nofobject}")
+                    report("xforms : #{nofxform}")
+                    report("annotations : #{nofannot}")
+                    report("links : #{noflink} (#{nofnamed} named / #{nofscript} scripts / #{nofcross} files)")
+                    report("widgets : #{nofwidget}")
+                end
+            end
+        end
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registeraction('spotimage' ,      'filename --colorspec=  --colorname=  [--retain --invert --subpath=]')
+commandline.registeraction('colorimage',      'filename --colorspec= [--retain --invert --colorname= ]')
+commandline.registeraction('convertimage',    'filename [--retain --subpath]')
+commandline.registeraction('downsampleimage', 'filename [--retain --subpath --lowres --normal]')
+commandline.registeraction('info',            'filename')
+commandline.registeraction('countpages',      '[--pattern --threshold]')
+commandline.registeraction('checkembedded',   '[--pattern]')
+
+commandline.registeraction('analyzefile' ,    'filename')
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registervalue('colorname')
+commandline.registervalue('colorspec')
+commandline.registervalue('subpath')
+commandline.registervalue('pattern')
+commandline.registervalue('threshold',0)
+
+commandline.registerflag('lowres')
+commandline.registerflag('medres')
+commandline.registerflag('normal')
+commandline.registerflag('invert')
+commandline.registerflag('retain')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'help')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/pdftools.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/pstopdf.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/pstopdf.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/pstopdf.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,533 @@
+#!/usr/bin/env ruby
+
+# program   : pstopdf
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+banner = ['PsToPdf', 'version 2.0.1', '2002-2006', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+# todo: paden/prefix in magick and inkscape
+# todo: clean up method handling (pass strings, no numbers)
+# --method=crop|bounded|raw|...
+# --resolution=low|normal|medium|high|printer|print|screen|ebook|default
+# + downward compatible flag handling
+
+require 'base/switch'
+require 'base/tool'
+require 'base/logger'
+
+require 'graphics/gs'
+require 'graphics/magick'
+require 'graphics/inkscape'
+
+require 'rexml/document'
+
+exit if defined?(REQUIRE2LIB)
+
+class Commands
+
+    include CommandBase
+
+    # nowadays we would force a directive, but
+    # for old times sake we handle default usage
+
+    def main
+        filename = @commandline.argument('first')
+        pattern  = @commandline.option('pattern')
+        if filename.empty? && ! pattern.empty? then
+            pattern = "**/#{pattern}" if @commandline.option('recurse')
+            globfiles(pattern)
+        end
+        filename = @commandline.argument('first')
+        if filename.empty? then
+            help
+        elsif filename =~ /\.exa$/ then
+            request
+        else
+            convert
+        end
+    end
+
+    # actions
+
+    def convert
+
+        ghostscript = GhostScript.new(logger)
+        magick      = ImageMagick.new(logger)
+        inkscape    = InkScape.new(logger)
+
+        outpath = @commandline.option('outputpath')
+        unless outpath.empty? then
+            begin
+                File.expand_path(outpath)
+                outpath = File.makedirs(outpath) unless FileTest.directory?(outpath)
+            rescue
+                # sorry
+            end
+        end
+
+        @commandline.arguments.each do |filename|
+
+            filename = Tool.cleanfilename(filename, at commandline) # brrrr
+            inppath = @commandline.option('inputpath')
+            if inppath.empty? then
+               inppath = '.'
+               fullname = filename # avoid duplicate './'
+            else
+               fullname = File.join(inppath,filename)
+            end
+            if FileTest.file?(fullname) then
+                handle_whatever(ghostscript,inkscape,magick,filename)
+            else
+                report("file #{fullname} does not exist")
+            end
+
+        end
+
+    end
+
+    def request
+
+        # <exa:request>
+        #   <exa:application>
+        #     <exa:command>pstopdf</exa:command>
+        #     <exa:filename>E:/tmp/demo.ps</exa:filename>
+        #   </exa:application>
+        #   <exa:data>
+        #     <exa:variable label='gs:DoThumbnails'>false</exa:variable>
+        #     <exa:variable label='gs:ColorImageDepth'>-1</exa:variable>
+        #   </exa:data>
+        # </exa:request>
+
+        ghostscript = GhostScript.new(logger)
+        magick      = ImageMagick.new(logger)
+        inkscape    = InkScape.new(logger)
+
+        dataname = @commandline.argument('first')  || ''
+        filename = @commandline.argument('second') || ''
+
+        if dataname.empty? || ! FileTest.file?(dataname) then
+            report('provide valid exa file')
+            return
+        else
+            begin
+                request = REXML::Document.new(File.new(dataname))
+            rescue
+                report('provide valid exa file (xml error)')
+                return
+            end
+        end
+        if filename.empty? then
+            begin
+                if filename = REXML::XPath.first(request.root,"exa:request/exa:application/exa:filename/text()") then
+                    filename = filename.to_s
+                else
+                    report('no filename found in exa file')
+                    return
+                end
+            rescue
+                filename = ''
+            end
+        end
+        if filename.empty? then
+            report('provide valid filename')
+            return
+        elsif ! FileTest.file?(filename) then
+            report("invalid filename #{filename}")
+            return
+        end
+
+        [ghostscript,inkscape,magick].each do |i|
+            i.setvariable('inputfile',filename)
+        end
+
+        # set ghostscript variables
+        REXML::XPath.each(request.root,"/exa:request/exa:data/exa:variable") do |v|
+            begin
+                if (key = v.attributes['label']) and (value = v.text.to_s) then
+                    case key
+                        when /gs[\:\.](var[\:\.])*(offset)/io then ghostscript.setoffset(value)
+                        when /gs[\:\.](var[\:\.])*(method)/io then ghostscript.setvariable('method',value)
+                        when /gs[\:\.](var[\:\.])*(.*)/io     then ghostscript.setpsoption($2,value)
+                    end
+                end
+            rescue
+            end
+        end
+
+        # no inkscape and magick variables (yet)
+
+        handle_whatever(ghostscript,inkscape,magick,filename)
+
+    end
+
+    def watch
+
+        ghostscript = GhostScript.new(logger)
+        magick      = ImageMagick.new(logger)
+        inkscape    = InkScape.new(logger)
+
+        pathname = commandline.option('watch')
+
+        unless pathname and not pathname.empty? then
+            report('empty watchpath is not supported')
+            exit
+        end
+
+        if pathname == '.' then
+            report("watchpath #{pathname} is not supported")
+            exit
+        end
+
+        if FileTest.directory?(pathname) then
+            if Dir.chdir(pathname) then
+                report("watching path #{pathname}")
+            else
+                report("unable to change to path #{pathname}")
+                exit
+            end
+        else
+            report("invalid path #{pathname}")
+            exit
+        end
+
+        waiting = false
+
+        loop do
+
+            if waiting then
+                report("waiting #{getvariable('delay')}")
+                waiting = false
+                sleep(getvariable('delay').to_i)
+            end
+
+            files = Dir.glob("**/*.*")
+
+            if files and files.length > 0 then
+
+                files.each do |fullname|
+
+                    next unless fullname
+
+                    if FileTest.directory?(fullname) then
+                        debug('skipping path', fullname)
+                        next
+                    end
+
+                    unless magick.supported(fullname) then
+                        debug('not supported', fullname)
+                        next
+                    end
+
+                    if (! FileTest.file?(fullname)) || (FileTest.size(fullname) < 100) then
+                        debug("skipping small crap file #{fullname}")
+                        next
+                    end
+
+                    debug("handling file #{fullname}")
+
+                    begin
+                        next unless File.rename(fullname,fullname) # access trick
+                    rescue
+                        next                                       # being written
+                    end
+
+                    fullname = Tool.cleanfilename(fullname, at commandline)
+
+                    fullname.gsub!(/\\/io, '/')
+
+                    filename = File.basename(fullname)
+                    filepath = File.dirname(fullname)
+
+                    next if filename =~ /gstemp.*/io
+
+                    if filepath !~ /(result|done|raw|crop|bound|bitmap)/io then
+                        begin
+                            File.makedirs(filepath+'/raw')
+                            File.makedirs(filepath+'/bound')
+                            File.makedirs(filepath+'/crop')
+                            File.makedirs(filepath+'/bitmap')
+                            debug("creating prefered input paths on #{filepath}")
+                        rescue
+                            debug("creating input paths on #{filepath} failed")
+                        end
+                    end
+
+                    if filepath =~ /^(.*\/|)(done|result)$/io then
+                        debug("skipping file #{fullname}")
+                    else
+                        report("start processing file #{fullname}")
+                        if filepath =~ /^(.*\/*)(raw|crop|bound)$/io then
+                            donepath = $1 + 'done'
+                            resultpath = $1 + 'result'
+                            case $2
+                                when 'raw'   then method = 1
+                                when 'bound' then method = 2
+                                when 'crop'  then method = 3
+                                else              method = 2
+                            end
+                            report("forcing method #{method}")
+                        else
+                            method = 2
+                            donepath = filepath + '/done'
+                            resultpath = filepath + '/result'
+                            report("default method #{method}")
+                        end
+
+                        begin
+                            File.makedirs(donepath)
+                            File.makedirs(resultpath)
+                        rescue
+                            report('result path creation fails')
+                        end
+
+                        if FileTest.directory?(donepath) && FileTest.directory?(resultpath) then
+
+                            resultname = resultpath + '/' + filename.sub(/\.[^\.]*$/,'') + '.pdf'
+
+                            @commandline.setoption('inputpath',  filepath)
+                            @commandline.setoption('outputpath', resultpath)
+                            @commandline.setoption('method',     method)
+
+                            if ghostscript.psfile?(fullname) then
+                                handle_ghostscript(ghostscript,filename)
+                            else
+                                handle_magick(magick,filename)
+                            end
+
+                            sleep(1) # calm down
+
+                            if FileTest.file?(fullname) then
+                                begin
+                                    File.copy(fullname,donepath + '/' + filename)
+                                    File.delete(fullname)
+                                rescue
+                                    report('cleanup fails')
+                                end
+                            end
+
+                        end
+
+                    end
+
+                end
+
+            end
+
+            waiting = true
+        end
+
+    end
+
+    private
+
+    def handle_whatever(ghostscript,inkscape,magick,filename)
+        if ghostscript.psfile?(filename) then
+            # report("processing ps file #{filename}")
+            ghostscript.setvariable('pipe',false) if @commandline.option('nopipe')
+            # ghostscript.setvariable('pipe',not @commandline.option('nopipe'))
+            ghostscript.setvariable('colormodel', at commandline.option('colormodel'))
+            ghostscript.setvariable('offset', at commandline.option('offset'))
+            handle_ghostscript(ghostscript,filename)
+        elsif ghostscript.pdffile?(filename) && ghostscript.pdfmethod?(@commandline.option('method')) then
+            # report("processing pdf file #{filename}")
+            handle_ghostscript(ghostscript,filename)
+        elsif inkscape.supported?(filename) then
+            # report("processing non ps/pdf file #{filename}")
+            handle_inkscape(inkscape,filename)
+        elsif magick.supported?(filename) then
+            # report("processing non ps/pdf file #{filename}")
+            handle_magick(magick,filename)
+        else
+            report("option not supported for #{filename}")
+        end
+    end
+
+    def handle_magick(magick,filename)
+
+        report("converting non-ps file #{filename} into pdf")
+
+        inppath = @commandline.option('inputpath')
+        outpath = @commandline.option('outputpath')
+
+        inppath = inppath + '/' if not inppath.empty?
+        outpath = outpath + '/' if not outpath.empty?
+
+        prefix = @commandline.option('prefix')
+        suffix = @commandline.option('suffix')
+
+        inpfilename = "#{inppath}#{filename}"
+        outfilename = "#{outpath}#{prefix}#{filename.sub(/\.([^\.]*?)$/, '')}#{suffix}.pdf"
+
+        magick.setvariable('inputfile' , inpfilename)
+        magick.setvariable('outputfile', outfilename)
+
+        magick.autoconvert
+
+    end
+
+    def handle_inkscape(inkscape,filename)
+
+        report("converting svg(z) file #{filename} into pdf")
+
+        inppath = @commandline.option('inputpath')
+        outpath = @commandline.option('outputpath')
+
+        inppath = inppath + '/' if not inppath.empty?
+        outpath = outpath + '/' if not outpath.empty?
+
+        prefix = @commandline.option('prefix')
+        suffix = @commandline.option('suffix')
+
+        inpfilename = "#{inppath}#{filename}"
+        outfilename = "#{outpath}#{prefix}#{filename.sub(/\.([^\.]*?)$/, '')}#{suffix}.pdf"
+
+        inkscape.setvariable('inputfile' , inpfilename)
+        inkscape.setvariable('outputfile', outfilename)
+
+        if @commandline.option('verbose') || @commandline.option('debug') then
+            logname = filename.gsub(/\.[^\.]*?$/, '.log')
+            report("log info saved in #{logname}")
+            inkscape.convert(logname) # logname ook doorgeven
+        else
+            inkscape.convert
+        end
+
+    end
+
+    def handle_ghostscript(ghostscript,filename)
+
+        ghostscript.reset
+
+        method = ghostscript.method(@commandline.option('method'))
+        force = ghostscript.method(@commandline.option('force'))
+
+        ghostscript.setvariable('method', method)
+        ghostscript.setvariable('force', force)
+
+        # report("conversion method #{method}")
+
+        inppath = @commandline.option('inputpath')
+        outpath = @commandline.option('outputpath')
+
+        inppath = inppath + '/' if not inppath.empty?
+        outpath = outpath + '/' if not outpath.empty?
+
+        prefix = @commandline.option('prefix')
+        suffix = @commandline.option('suffix')
+
+        ok = false
+
+        if ghostscript.pdfmethod?(method) then
+
+            report("converting pdf file #{filename} into pdf")
+
+            if prefix.empty? && suffix.empty? && inppath.empty? && outpath.empty? then
+                prefix = ghostscript.pdfprefix(method)
+            end
+
+            if ghostscript.pdffile?(filename) then
+
+                filename = filename.sub(/\.pdf$/, '')
+
+                inpfilename = "#{inppath}#{filename}.pdf"
+                outfilename = "#{outpath}#{prefix}#{filename}#{suffix}.pdf"
+
+                ghostscript.setvariable('inputfile' ,inpfilename)
+                ghostscript.setvariable('outputfile',outfilename)
+
+                if FileTest.file?(inpfilename) then
+                    ok = ghostscript.convert
+                else
+                    report("no file found #{filename}")
+                end
+
+            else
+                report("no pdf file #{filename}")
+            end
+
+        elsif ghostscript.psfile?(filename) then
+
+            if filename =~ /(.*)\.([^\.]*?)$/io then
+                filename, filesuffix = $1, $2
+            else
+                filesuffix = 'eps'
+            end
+
+            report("converting #{filesuffix} (ps) into pdf")
+
+            inpfilename = "#{inppath}#{filename}.#{filesuffix}"
+            outfilename = "#{outpath}#{prefix}#{filename}#{suffix}.pdf"
+
+            ghostscript.setvariable('inputfile' , inpfilename)
+            ghostscript.setvariable('outputfile', outfilename)
+
+            if FileTest.file?(inpfilename) then
+                ok = ghostscript.convert
+                if ! ok && FileTest.file?(outfilename) then
+                    begin
+                        File.delete(outfilename)
+                    rescue
+                    end
+                end
+            else
+                report("no file with name #{filename} found")
+            end
+
+        else
+            report('file must be of type eps/ps/ai/pdf')
+        end
+
+        return ok
+
+    end
+
+end
+
+# ook pdf -> pdf onder optie 0, andere kleurruimte
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registerflag('debug')
+commandline.registerflag('verbose')
+commandline.registerflag('nopipe')
+
+commandline.registervalue('method',2)
+commandline.registervalue('offset',0)
+
+commandline.registervalue('prefix')
+commandline.registervalue('suffix')
+
+commandline.registervalue('inputpath')
+commandline.registervalue('outputpath')
+
+commandline.registerflag('watch')
+commandline.registerflag('force')
+commandline.registerflag('recurse')
+
+commandline.registervalue('delay',2)
+
+commandline.registervalue('colormodel','cmyk')
+commandline.registervalue('pattern','')
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registeraction('convert', 'convert ps into pdf')
+commandline.registeraction('request', 'handles exa request file')
+commandline.registeraction('watch',   'watch folders for conversions (untested)')
+
+commandline.expand
+
+logger.verbose if (commandline.option('verbose') || commandline.option('debug'))
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'main')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/pstopdf.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/rlxtools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/rlxtools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/rlxtools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,368 @@
+#!/usr/bin/env ruby
+
+# program   : rlxtools
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2004-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+banner = ['RlxTools', 'version 1.0.1', '2004/2005', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'base/switch'
+require 'base/logger'
+require 'base/system'
+require 'base/kpse'
+
+require 'fileutils'
+# require 'ftools'
+require 'rexml/document'
+
+class Commands
+
+    include CommandBase
+
+    # <?xml version='1.0 standalone='yes'?>
+    # <rl:manipulators>
+    #    <rl:manipulator name='lowres' suffix='pdf'>
+    #         <rl:step>
+    #             texmfstart
+    #             --verbose
+    #             --iftouched=<rl:value name='path'/>/<rl:value name='file'/>,<rl:value name='path'/>/<rl:value name='prefix'/><rl:value name='file'/>
+    #             pstopdf
+    #             --method=5
+    #             --inputpath=<rl:value name='path'/>
+    #             --outputpath=<rl:value name='path'/>/<rl:value name='prefix'/>
+    #             <rl:value name='file'/>
+    #         </rl:step>
+    #     </rl:manipulator>
+    # </rl:manipulators>
+    #
+    # <?xml version='1.0' standalone='yes'?>
+    # <rl:library>
+    #     <rl:usage>
+    #         <rl:type>figure</rl:type>
+    #         <rl:state>found</rl:state>
+    #         <rl:file>cow.pdf</rl:file>
+    #         <rl:suffix>pdf</rl:suffix>
+    #         <rl:path>.</rl:path>
+    #         <rl:conversion>lowres</rl:conversion>
+    #         <rl:prefix>lowres/</rl:prefix>
+    #         <rl:width>276.03125pt</rl:width>
+    #         <rl:height>200.75pt</rl:height>
+    #     </rl:usage>
+    # </r:library>
+
+    def manipulate
+
+        procname = @commandline.argument('first')  || ''
+        filename = @commandline.argument('second') || ''
+
+        procname = Kpse.found(procname)
+
+        if procname.empty? || ! FileTest.file?(procname) then
+            report('provide valid manipulator file')
+        elsif filename.empty? || ! FileTest.file?(filename) then
+            report('provide valid resource log file')
+        else
+            begin
+                data = REXML::Document.new(File.new(filename))
+            rescue
+                report('provide valid resource log file (xml error)')
+                return
+            end
+            begin
+                proc = REXML::Document.new(File.new(procname))
+            rescue
+                report('provide valid manipulator file (xml error)')
+                return
+            end
+            report("manipulator file: #{procname}")
+            report("resourcelog file: #{filename}")
+            begin
+                nofrecords, nofdone = 0, 0
+                REXML::XPath.each(data.root,"/rl:library/rl:usage") do |usage|
+                    nofrecords += 1
+                    variables = Hash.new
+                    usage.elements.each do |e|
+                        variables[e.name] = e.text.to_s
+                    end
+                    report("processing record #{nofrecords} (#{variables['file'] || 'noname'}: #{variables.size} entries)")
+                    if conversion = variables['conversion'] then
+                        report("testing for conversion #{conversion}")
+                        if suffix = variables['suffix'] then
+                            suffix.downcase!
+                            if ! suffix.empty? && variables['file'] && variables['file'] !~ /\.([a-z]+)$/i then
+                                variables['file'] += ".#{suffix}"
+                            end
+                            if file = variables['file'] then
+                                report("conversion #{conversion} for suffix #{suffix} for file #{file}")
+                            else
+                                report("conversion #{conversion} for suffix #{suffix}")
+                            end
+                            pattern = "@name='#{conversion}' and @suffix='#{suffix}'"
+                            if steps = REXML::XPath.first(proc.root,"/rl:manipulators/rl:manipulator[#{pattern}]") then
+                                localsteps = steps.deep_clone
+                                ['rl:old','rl:new'].each do |tag|
+                                    REXML::XPath.each(localsteps,tag) do |extras|
+                                        REXML::XPath.each(extras,"rl:value") do |value|
+                                            if name = value.attributes['name'] then
+                                                substitute(value,variables[name.to_s] || '')
+                                            end
+                                        end
+                                    end
+                                end
+                                old = REXML::XPath.first(localsteps,"rl:old")
+                                new = REXML::XPath.first(localsteps,"rl:new")
+                                if old && new then
+                                    old, new = justtext(old.to_s), justtext(new.to_s)
+                                    variables['old'], variables['new'] = old, new
+                                    begin
+                                        [old,new].each do |d|
+                                            File.makedirs(File.dirname(d))
+                                        end
+                                    rescue
+                                        report("error during path creation")
+                                    end
+                                    report("old file #{old}")
+                                    report("new file #{new}")
+                                    level = if File.needsupdate(old,new) then 2 else 0 end
+                                else
+                                    level = 1
+                                end
+                                if level>0 then
+                                    REXML::XPath.each(localsteps,"rl:step") do |command|
+                                        REXML::XPath.each(command,"rl:old") do |value|
+                                            replace(value,old)
+                                        end
+                                        REXML::XPath.each(command,"rl:new") do |value|
+                                            replace(value,new)
+                                        end
+                                        REXML::XPath.each(command,"rl:value") do |value|
+                                            if name = value.attributes['name'] then
+                                                substitute(value,variables[name.to_s])
+                                            end
+                                        end
+                                        str = justtext(command.to_s)
+                                        # str.gsub!(/(\.\/)+/io, '')
+                                        report("command #{str}")
+                                        System.run(str) unless @commandline.option('test')
+                                        report("synchronizing #{old} and #{new}")
+                                        File.syncmtimes(old,new) if level > 1
+                                        nofdone += 1
+                                    end
+                                else
+                                    report("no need for a manipulation")
+                                end
+                            else
+                                report("no manipulator found")
+                            end
+                        else
+                            report("no suffix specified")
+                        end
+                    else
+                        report("no conversion needed")
+                    end
+                end
+                if nofdone > 0 then
+                    jobname = filename.gsub(/\.(.*?)$/,'') # not 'tuo' here
+                    tuoname = jobname + '.tuo'
+                    if FileTest.file?(tuoname) && (f = File.open(tuoname,'a')) then
+                        f.puts("%\n% number of rlx manipulations: #{nofdone}\n")
+                        f.close
+                    end
+                end
+            rescue
+                report("error in manipulating files: #{$!}")
+            end
+            begin
+                logname = "#{filename}.log"
+                File.delete(logname) if FileTest.file?(logname)
+                File.copy(filename,logname)
+            rescue
+            end
+        end
+
+    end
+
+    private
+
+    def justtext(str)
+        str = str.to_s
+        str.gsub!(/<[^>]*?>/o, '')
+        str.gsub!(/\s+/o, ' ')
+        str.gsub!(/</o, '<')
+        str.gsub!(/>/o, '>')
+        str.gsub!(/&/o, '&')
+        str.gsub!(/"/o, '"')
+        str.gsub!(/[\/\\]+/o, '/')
+        return str.strip
+    end
+
+    def substitute(value,str='')
+        if str then
+            begin
+                if value.attributes.key?('method') then
+                    str = filtered(str.to_s,value.attributes['method'].to_s)
+                end
+                if str.empty? && value.attributes.key?('default') then
+                    str = value.attributes['default'].to_s
+                end
+                value.insert_after(value,REXML::Text.new(str.to_s))
+            rescue Exception
+            end
+        end
+    end
+
+    def replace(value,str)
+        if str then
+            begin
+                value.insert_after(value,REXML::Text.new(str.to_s))
+            rescue Exception
+            end
+        end
+    end
+
+    def filtered(str,method)
+
+        str = str.to_s # to be sure
+        case method
+            when 'name' then # no path, no suffix
+                case str
+                    when /^.*[\\\/](.+?)\..*?$/o then $1
+                    when /^.*[\\\/](.+?)$/o      then $1
+                    when /^(.*)\..*?$/o          then $1
+                    else                              str
+                end
+            when 'path'     then if str =~ /^(.+)([\\\/])(.*?)$/o then $1 else ''  end
+            when 'suffix'   then if str =~ /^.*\.(.*?)$/o         then $1 else ''  end
+            when 'nosuffix' then if str =~ /^(.*)\..*?$/o         then $1 else str end
+            when 'nopath'   then if str =~ /^.*[\\\/](.*?)$/o     then $1 else str end
+            else                                                               str
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    @@xmlbanner = "<?xml version='1.0' standalone='yes'?>"
+
+    def identify(resultfile='rlxtools.rli')
+        if @commandline.option('collect') then
+            begin
+                File.open(resultfile,'w') do |f|
+                    f << "#{@@xmlbanner}\n"
+                    f << "<rl:identification>\n"
+                    @commandline.arguments.each do |filename|
+                        if state = do_identify(filename) then
+                            report("#{filename} is identified")
+                            f << state
+                        else
+                            report("unable to identify #{filename}")
+                        end
+                    end
+                    f << "</rl:identification>\n"
+                    report("result saved in #{resultfile}")
+                end
+            rescue
+                report("error in writing result")
+            end
+        else
+            @commandline.arguments.each do |filename|
+                if state = do_identify(filename) then
+                    begin
+                        File.open(filename+'.rli','w') do |f|
+                            f << "#{@@xmlbanner}\n"
+                            f << state
+                        end
+                    rescue
+                        report("error in identifying #{filename}")
+                    else
+                        report("#{filename} is identified")
+                    end
+                else
+                    report("unable to identify #{filename}")
+                end
+            end
+        end
+    end
+
+    private
+
+    def do_identify(filename,centimeters=false)
+        begin
+            str = nil
+            if FileTest.file?(filename) then
+                # todo: use pdfinto for pdf files, identify is bugged
+                if centimeters then
+                    result = `identify -units PixelsPerCentimeter -format \"x=%x,y=%y,w=%w,h=%h,b=%b\" #{filename}`.chomp.split(',')
+                else
+                    result = `identify -units PixelsPerInch       -format \"x=%x,y=%y,w=%w,h=%h,b=%b\" #{filename}`.chomp.split(',')
+                end
+                tags = Hash.new
+                result.each do |r|
+                    if rr = r.split("=") then
+                        tags[rr[0]] = rr[1]
+                    end
+                end
+                size   = (tags['b']||0).to_i
+                width  = unified(tags['w']||0,tags['x']||'1')
+                height = unified(tags['h']||0,tags['y']||'1')
+                if size > 0 then
+                    str = ''
+                    str << "<rl:identify name='#{File.basename(filename)}'>\n"
+                    str << "  <rl:size>#{size}</rl:size>\n"
+                    str << "  <rl:path>#{File.dirname(filename).sub(/\\/o,'/')}</rl:path>\n"
+                    str << "  <rl:width>#{width}</rl:width>\n"
+                    str << "  <rl:height>#{height}</rl:height>\n"
+                    str << "</rl:identify>\n"
+                end
+            else
+                str = nil
+            end
+        rescue
+            str = nil
+        end
+        return str
+    end
+
+    def unified(dim,res)
+        case res
+            when /([\d\.]+)\s*PixelsPerInch/io then
+                sprintf("%.4fin",dim.to_f/$1.to_f)
+            when /([\d\.]+)\s*PixelsPerCentimeter/io then
+                sprintf("%.4fcm",dim.to_f/$1.to_f)
+            when /([\d\.]+)\s*PixelsPerMillimeter/io then
+                sprintf("%.4fmm",dim.to_f/$1.to_f)
+            when /([\d\.]+)\s*PixelsPerPoint/io then
+                sprintf("%.4fbp",dim.to_f/$1.to_f)
+            else
+                sprintf("%.4fbp",dim.to_f)
+        end
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registeraction('manipulate', '[--test] manipulatorfile resourselog')
+commandline.registeraction('identify'  , '[--collect] filename')
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registerflag('test')
+commandline.registerflag('collect')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'help')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/rlxtools.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/rscortool.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/rscortool.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/rscortool.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,63 @@
+# program   : rscortool
+# copyright : PRAGMA Publishing On Demand
+# version   : 1.00 - 2002
+# author    : Hans Hagen
+#
+# project   : eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-pod.com / www.pragma-ade.com
+
+require 'rexml/document.rb'
+
+class Array
+
+    def downcase
+        self.collect { |l| l.to_s.downcase }
+    end
+
+end
+
+class SortedXML
+
+    def initialize (filename)
+        return nil if not filename or filename.empty? or not test(?e,filename)
+        @data = REXML::Document.new(File.new(filename),
+            {:ignore_whitespace_nodes => :all,
+             :compress_whitespace     => :all})
+    end
+
+    def save (filename)
+        # filename += '.xml' unless filename.match(/\..*?$/)
+        filename += '.xml' unless filename =~ /\..*?$/
+        if not filename.empty? and f = open(filename,'w')
+            @data.write(f,0)
+            f.close
+        end
+    end
+
+    def sort
+        keys = REXML::XPath.match(@data.root,"/contacts/contact/@label")
+        return unless keys
+        keys = keys.downcase
+        records = @data.elements.to_a("/contacts/contact")
+        @data.elements.delete_all("/contacts/contact")
+        keys = keys.collect do |l| # prepare numbers
+            l.gsub(/(\d+)/) do |d| sprintf('%05d', d) end
+        end
+        keys.sort.each do |s|
+            @data.root.add_element(records[keys.index(s)])
+        end
+    end
+
+end
+
+def sortfile (filename)
+    c = SortedXML.new(filename)
+    c.sort
+    c.save('test.xml')
+end
+
+exit if ARGV[0] == nil or ARGV[0].empty?
+
+sortfile(ARGV[0])


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/rscortool.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/rsfiltool.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/rsfiltool.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/rsfiltool.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,341 @@
+# program   : rsfiltool
+# copyright : PRAGMA Publishing On Demand
+# version   : 1.01 - 2002
+# author    : Hans Hagen
+#
+# project   : eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-pod.com / www.pragma-ade.com
+
+unless defined? ownpath
+    ownpath = $0.sub(/[\\\/]\w*?\.rb/i,'')
+    $: << ownpath
+end
+
+# --name=a,b,c.xml wordt names [a.xml, b.xml, c.xml]
+# --path=x/y/z/a,b,c.xml wordt [x/y/z/a.xml, x/y/z/b.xml, x/y/z/c.xml]
+
+# todo : split session stuff from xmpl/base into an xmpl/session module and "include xmpl/session" into base and here and ...
+
+require 'fileutils'
+# require 'ftools'
+require 'xmpl/base'
+require 'xmpl/switch'
+require 'xmpl/request'
+
+session = Example.new('rsfiltool', '1.01', 'PRAGMA POD')
+
+filterprefix = 'rsfil-'
+
+commandline = CommandLine.new
+
+commandline.registerflag('submit')
+commandline.registerflag('fetch')
+commandline.registerflag('report')
+#commandline.registerflag('split')
+commandline.registerflag('stamp')
+commandline.registerflag('silent')
+commandline.registerflag('request')
+commandline.registerflag('nobackup')
+
+commandline.registervalue('filter')
+
+commandline.registervalue('root')
+commandline.registervalue('path')
+commandline.registervalue('name')
+
+commandline.expand
+
+session.set('log.silent',true) if commandline.option('silent')
+
+session.inherit(commandline)
+
+session.identify
+
+# session.exit unless session.loadenvironment
+
+def prepare (session)
+
+    # Normally the system provides the file, but a user can provide the rest; in
+    # order to prevent problems with keying in names, we force lowercase names.
+
+    session.set('option.file',session.get('argument.first')) if session.get('option.file').empty?
+
+    root = session.get('option.root').downcase
+    path = session.get('option.path').downcase
+    name = session.get('option.name').downcase
+    file = session.get('option.file').downcase
+
+    session.error('provide file') if file.empty?
+    session.error('provide root') if root.empty?
+
+    filter = session.get('option.filter').downcase
+    trash  = session.get('option.trash').downcase
+
+    trash = '' unless FileTest.directory?(trash)
+
+    if not filter.empty? then
+        begin
+            require filter
+        rescue Exception
+            begin
+                require filterprefix + filter
+            rescue Exception
+                session.error('invalid filter')
+            end
+        end
+        begin
+            if RSFIL::valid?(file) then
+                split = RSFIL::split(file,name)
+                path = if split[0].downcase then split[0] else '' end
+                file = if split[1].downcase then split[1] else '' end
+                name = if split[2].downcase then split[2] else '' end
+                session.report('split result',split.inspect)
+                session.error('unable to split off path') if path.empty?
+                session.error('unable to split off file') if file.empty?
+                session.error('unable to split off name') if name.empty?
+                session.set('option.path',path) if path
+                session.set('option.file',file) if file
+                session.set('option.name',name) if name
+            else
+                session.error('invalid filename', file)
+                unless trash.empty? then
+                    File.copy(file,trash + '/' + file)
+                end
+            end
+        rescue
+            session.error('unable to split',file,'with filter',filter)
+        end
+    end
+
+    session.error('provide path') if path.empty?
+
+    session.error('invalid root') unless test(?d,root)
+
+    exit if session.error?
+
+    session.set('fb.filename',file)
+
+    path.gsub!(/\\/o, '/')
+    path.gsub!(/\s/o, '')
+
+    path = root + '/' + path
+
+    # multiple paths
+
+    if path =~ /^(.*)\/(.*?)$/o then
+        prepath = $1
+        postpath = $2
+        paths = postpath.split(/\,/)
+        paths.collect! do |p|
+            prepath + '/' + p
+        end
+    else
+        paths = Array.new
+        paths.push(path)
+    end
+
+    paths.collect! do |p|
+        p.gsub(/[^a-zA-Z0-9\s\-\_\/\.\:]/o, '-')
+    end
+
+    file.gsub!(/\\/o, '/')
+    file.gsub!(/[^a-zA-Z0-9\s\-\_\/\.\:]/o, '-')
+
+#    if session.get('option.split')
+#        if file =~ /(.*)\.(.*?)$/o
+#            path = path + '/' + $1
+#        else
+#            session.error('nothing to split in filename')
+#        end
+#    end
+
+    paths.each do |p|
+        begin
+            session.report('creating path', p)
+            File.makedirs(p)
+        rescue
+            session.error('unable to create path', p)
+        end
+    end
+
+    name.gsub!(/\s+/,'')
+
+    # can be a,b,c.exa.saved => a.exa.saved,b.exa.saved,c.exa.saved
+
+    if name =~ /(.*?)\.(.*)$/
+        name = $1
+        suffix = $2
+        names = name.split(/\,/)
+        names.collect! do |n|
+            n + '.' + suffix
+        end
+        name = names.join(',')
+    else
+        names = name.split(/\,/)
+    end
+
+    session.set('fb.path',path)
+    session.set('fb.paths',paths)
+    session.set('fb.name',name)
+    session.set('fb.names',names)
+
+end
+
+def thefullname(path,file,name='')
+
+    filename = file.gsub(/.*?\//, '')
+
+    if name.empty?
+        path + '/' + filename
+    else
+        unless name =~ /\..+$/o  # unless name.match(/\..+$/o)
+            if filename =~ /(\..+)$/o  # if file.match(/(\..+)$/o)
+                name = name + $1
+            end
+        end
+        path + '/' + name
+    end
+
+end
+
+def submitfile (session)
+
+    filename = session.get('fb.filename')
+    paths = session.get('fb.paths')
+    names = session.get('fb.names')
+
+    paths.each do |path|
+        session.report('submitting path',path)
+        names.each do |name|
+            session.report('submitting file',filename,'to',name)
+            submit(session,path,filename,name)
+        end
+    end
+
+end
+
+def submitlist (session)
+
+    requestname = session.get('fb.filename')
+    paths = session.get('fb.paths')
+
+    if test(?e,requestname)
+        session.report('loading request file', requestname)
+        if request = ExaRequest.new(requestname)
+            filelist = request.files
+            if filelist && (filelist.size > 0)
+                filelist.each do |filename|
+                    paths.each do |path|
+                        session.report('submitting file from list', filename)
+                        submit(session,path,filename,request.naturalname(filename))
+                    end
+                end
+            else
+                session.warning('no filelist in', requestname)
+            end
+        else
+            session.warning('unable to load', requestname)
+        end
+    else
+        session.warning('no file', requestname)
+    end
+
+end
+
+def submit (session, path, filename, newname)
+
+    fullname = thefullname(path,newname)
+
+    unless test(?e,filename)
+        session.warning('no file to submit', filename)
+        return
+    end
+
+    begin
+        File.copy(fullname,fullname+'.old') if ! session.get('nobackup') && test(?e,fullname)
+        if test(?e,filename)
+            File.copy(filename,fullname)
+            session.report('submit', filename, 'in', fullname)
+            if session.get('option.stamp')
+                f = open(fullname+'.tim','w')
+                f.puts(Time.now.gmtime.strftime("%a %b %d %H:%M:%S %Y"))
+                f.close
+            end
+        else
+            session.error('unable to locate', filename)
+        end
+    rescue
+        session.error('unable to move', filename, 'to', fullname)
+    end
+
+end
+
+def fetch (session)
+
+    filename = session.get('fb.filename')
+    paths = session.get('fb.paths')
+    name = session.get('fb.name')
+
+    begin
+        File.copy(filename,filename+'.old') if ! session.get('nobackup') && test(?e,filename)
+        paths.each do |path|
+            #  fullname = thefullname(path,request.naturalname(filename))
+            # fullname = thefullname(path,filename)
+            fullname = thefullname(path,name)
+            if test(?e,fullname)
+                File.copy(fullname,filename)
+                session.report('fetch', filename, 'from', fullname)
+                return
+            else
+                session.report('file',fullname, 'is not present')
+            end
+        end
+    rescue
+        session.error('unable to fetch file from path')
+    end
+    session.error('no file',filename, 'fetched') unless test(?e,filename)
+
+end
+
+def report (session)
+
+    filename = session.get('fb.filename')
+    paths = session.get('fb.paths')
+
+    paths.each do |path|
+        fullname = thefullname(path,request.naturalname(filename))
+        if test(?e,fullname)
+            begin
+                session.report('file', fullname)
+                session.report('size', test(?s,fullname))
+                if test(?e,fullname+'.tim')
+                    str = IO.readlines(fullname+'.tim')
+                    # str = IO.read(fullname+'.tim')
+                    session.report('time', str)
+                end
+            rescue
+                session.error('unable to report about', fullname)
+            end
+        end
+    end
+
+end
+
+if session.get('option.submit')
+    prepare(session)
+    if session.get('option.request')
+        submitlist(session)
+    else
+        submitfile(session)
+    end
+elsif session.get('option.fetch')
+    prepare(session)
+    fetch(session)
+elsif session.get('option.report')
+    prepare(session)
+    report(session)
+else
+    session.report('provide action')
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/rsfiltool.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/rslb/base.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/rslb/base.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/rslb/base.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,270 @@
+# hans hagen, pragma-ade, hasselt nl
+# experimental code, don't touch it
+
+require 'rexml/document.rb'
+
+class Array
+
+  def downcase
+    self.collect do |l|
+        l.to_s.downcase
+    end
+  end
+
+end
+
+class Resource
+
+  @@rslburl = 'http://www.pragma-ade.com/rng/rslb.rng'
+  @@rslbns = 'rl'
+  @@rslbtmp = 'rslbtool-tmp.xml'
+
+  def initialize (filename='',namespace=@@rslbns)
+    @ns = if namespace then @@rslbns + ':' else '' end
+    set_filename(filename)
+    @library = REXML::Document.new(skeleton,
+      {:ignore_whitespace_nodes => :all,
+       :compress_whitespace     => :all})
+    @lastindex = 0
+    @texexec = 'texexec'
+    @downcaselabels = true
+    @downcasefilenames = true
+  end
+
+  def keeplabelcase
+    @downcaselabels = false
+  end
+
+  def keepfilenamecase
+    @downcasefilenames = false
+  end
+
+  def outer_skeleton (str)
+    tmp = if @ns.empty? then '' else " xmlns:#{@ns.sub(':','')}='#{@@rslburl}'" end
+    "<?xml version='1.0'?>\n" + "<#{@ns}library#{tmp}>\n" + str + "\n</#{@ns}library>"
+  end
+
+  def skeleton
+    outer_skeleton("<#{@ns}description>" +
+          "<#{@ns}organization>unknown</#{@ns}organization>" +
+          "<#{@ns}project>unknown</#{@ns}project>" +
+          "<#{@ns}product>unknown</#{@ns}product>" +
+          "<#{@ns}comment>unknown</#{@ns}comment>" +
+       "</#{@ns}description>")
+  end
+
+  def set_filename (filename)
+    @filename = if filename.empty? then 'unknown' else filename end
+    @fullname = @filename
+    @filename = File.basename(@filename).sub(/\..*$/,'')
+  end
+
+  def set_texexec (filename)
+    print "setting texexec binary to: #{filename}\n"
+    @texexec = filename
+  end
+
+  def load (filename='')
+    set_filename(filename)
+    if not filename.empty? and FileTest.file?(filename) # todo: test op valide fig base
+      @library = REXML::Document.new(File.new(filename),
+        {:ignore_whitespace_nodes => :all,
+         :compress_whitespace     => :all})
+      unless @library.root.prefix.empty?
+        @ns = @library.root.prefix + ':'
+      end
+    else
+      initialize(filename,!@ns.empty?)
+    end
+  end
+
+  def save (filename)
+    filename += '.xml' unless filename =~ /\..*?$/
+    if not filename.empty? and f = open(filename,'w')
+      @library.write(f,0)
+      f.close
+    end
+  end
+
+  def figure_labels
+    REXML::XPath.match(@library.root,"/#{@ns}library/#{@ns}figure/#{@ns}label/text()")
+  end
+
+  def figure_records
+    @library.elements.to_a("/#{@ns}library/#{@ns}figure")
+  end
+
+  def figure_files
+    REXML::XPath.match(@library.root,"/#{@ns}library/#{@ns}figure/#{@ns}file/text()")
+  end
+
+  def delete_figure (label='')
+    return if label.empty?
+    labels = figure_labels
+    labels.each_index do |i|
+      if labels[i].to_s.downcase == label.downcase
+        @library.elements.delete_all("/#{@ns}library/#{@ns}figure[#{i+1}]")
+      end
+    end
+  end
+
+  def add_figure (file='',label='',prefix='')
+    return if file.empty? or file.match(/^#{@filename}\..*$/i)
+    labels = figure_labels
+    prefix = @filename if prefix.empty?
+    if label.empty?
+      i = @lastindex
+      loop do
+        i += 1
+        label = prefix + ' ' + i.to_s
+        break unless labels.include?(label)
+      end
+    else
+      delete_figure(label) unless label.empty?
+    end
+    e = REXML::Element.new("#{@ns}figure")
+    l = REXML::Element.new("#{@ns}label")
+    f = REXML::Element.new("#{@ns}file")
+    l.text, f.text = label, file
+    e.add_element(l)
+    e.add_element(f)
+    @library.root.add_element(e)
+  end
+
+  def add_figures (list='',prefix='')
+    if @downcasefilenames then
+        files = figure_files.downcase
+        [list].flatten.downcase.each do |f|
+          next unless FileTest.file?(f)
+          add_figure(f,'',prefix) unless files.include?(f)
+        end
+    else
+        files = figure_files
+        [list].flatten.each do |f|
+          next unless FileTest.file?(f)
+          add_figure(f,'',prefix) unless files.include?(f)
+        end
+    end
+  end
+
+  def delete_figures (list='')
+    [list].flatten.downcase.each do |l|
+      delete_figure(l)
+    end
+  end
+
+  def sort_figures
+    if @downcaselabels then
+        labels = figure_labels.downcase
+    else
+        labels = figure_labels
+    end
+    return unless labels
+    figures = figure_records
+    @library.elements.delete_all("/#{@ns}library/#{@ns}figure")
+    labels = labels.collect do |l| # prepare numbers
+      l.gsub(/(\d+)/) do |d| sprintf('%05d', d) end
+    end
+    labels.sort.each do |s|
+      @library.root.add_element(figures[labels.index(s)])
+    end
+  end
+
+  def purge_figures
+    REXML::XPath.each(@library.root,"/#{@ns}library/#{@ns}figure") do |e|
+      filename = REXML::XPath.match(e,"#{@ns}file/text()").to_s
+      e.parent.delete(e) unless FileTest.file?(filename)
+    end
+  end
+
+  def run_command(command)
+    print "calling #{command}\n"
+    print "\n"
+    begin
+      system(command)
+    rescue
+      # sorry again
+    end
+    print "\n"
+  end
+
+  def create_dummies(process=false,result='',zipalso='')
+    result = @filename if result.empty?
+    list = REXML::XPath.match(@library.root,"/#{@ns}library/#{@ns}usage")
+    begin
+      File.delete(result+'.pdf')
+    rescue
+      # no way
+    end
+    return unless list && list.length>0
+    done = Array.new
+    list.each do |e|
+      t = REXML::XPath.match(e,"#{@ns}type/text()")
+      s = REXML::XPath.match(e,"#{@ns}state/text()")
+      if t && (t.to_s == 'figure') && s && (s.to_s == 'missing')
+        begin
+          f = REXML::XPath.match(e,"#{@ns}file/text()").to_s
+          if done.index(f)
+            print "skipping dummy figure: " + f + "\n"
+          elsif f =~ /\s/o
+            print "skipping crappy fname: " + f + "\n"
+          elsif f == 'dummy'
+            print "skipping dummy figure: " + f + "\n"
+          else
+            print "creating dummy figure: " + f + "\n"
+            if process && (x = open(@@rslbtmp,'w'))
+              x.puts(outer_skeleton(e.to_s))
+              x.close
+              run_command ("#{@texexec} --pdf --once --batch --silent --random --use=res-10 --xml --result=#{f} #{@@rslbtmp}")
+            end
+            done.push(f+'.pdf')
+            begin
+              File.delete(@@rslbtmp)
+            rescue
+              # sorry once more
+            end
+          end
+        rescue
+          # sorry, skip 'm
+        end
+      end
+    end
+    if process && (done.length>0)
+      begin
+        File.delete(result + '.zip')
+      rescue
+         # ok
+      end
+      run_command("zip #{result+'.zip'} #{@fullname}")
+      unless zipalso.empty?
+        begin
+            zipalso.split(',').each do |name|
+                run_command("zip #{result+'.zip'} #{name}")
+            end
+        end
+      end
+      done.each do |name|
+        run_command("zip #{result+'.zip'} #{name}")
+      end
+      run_command("#{@texexec} --pdf --batch --silent --use=res-11 --xml --result=#{result} #{@fullname}")
+      done.each do |name|
+        begin
+          File.delete(name)
+        rescue
+          # sorry
+        end
+      end
+    end
+  end
+
+end
+
+# reslib = Resource.new
+# reslib.load('f.xml')  # reslib.load('figbase.xml')
+# reslib.delete_figure('figbase 5')
+# reslib.delete_figure('figbase 5')
+# reslib.add_figure('a.pdf')
+# reslib.add_figure('b.pdf','something')
+# reslib.add_figure('c.pdf')
+# reslib.add_files('x.pdf')
+# reslib.save('figbase.tmp')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/rslb/base.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/rslibtool.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/rslibtool.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/rslibtool.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,114 @@
+# program   : rslibtool
+# copyright : PRAGMA Publishing On Demand
+# version   : 1.00 - 2002
+# author    : Hans Hagen
+#
+# project   : eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-pod.com / www.pragma-ade.com
+
+# --add      --base=filename --path=directory pattern
+# --remove   --base=filename --path=directory label
+# --sort     --base=filename --path=directory
+# --purge    --base=filename --path=directory
+# --dummy    --base=filename
+# --namespace
+
+# rewrite
+
+unless defined? ownpath
+    ownpath = $0.sub(/[\\\/]\w*?\.rb/i,'')
+    $: << ownpath
+end
+
+require 'rslb/base'
+require 'xmpl/base'
+require 'xmpl/switch'
+
+session = Example.new('rslbtool', '1.0', 'PRAGMA POD')
+
+session.identify
+
+commandline = CommandLine.new
+
+commandline.registerflag('add')
+commandline.registerflag('remove')
+commandline.registerflag('delete')
+commandline.registerflag('sort')
+commandline.registerflag('purge')
+commandline.registerflag('dummy')
+commandline.registerflag('process')
+commandline.registerflag('namespace')
+
+commandline.registervalue('prefix')
+commandline.registervalue('base')
+commandline.registervalue('path')
+commandline.registervalue('result')
+commandline.registervalue('texexec')
+commandline.registervalue('zipalso')
+
+commandline.expand
+
+session.inherit(commandline)
+
+base = session.get('option.base')
+path = session.get('option.path')
+
+base = 'rslbtool.xml' if base.empty?
+
+# when path is given, assume that arg list is list of
+# suffixes, else assume it is a list of globbed filespec
+
+if path.empty?
+	base += '.xml' unless base =~ /\..+$/
+	list = commandline.arguments
+else
+	Dir.chdir(File.dirname(path))
+	list = Dir.glob("*.{#{commandline.arguments.join(',')}}")
+end
+
+begin
+	reslib = Resource.new(base,session.get('option.namespace'))
+	reslib.load(base)
+rescue
+	session.error('problems with loading base')
+	exit
+end
+
+unless session.get('option.texexec').empty?
+    reslib.set_texexec(session.get('option.texexec'))
+end
+
+if session.get('option.add')
+
+	session.report('adding records', list)
+	reslib.add_figures(list,session.get('option.prefix'))
+
+elsif session.get('option.remove') or session.get('option.delete')
+
+	session.report('removing records')
+	reslib.delete_figures(list)
+
+elsif session.get('option.sort')
+
+	session.report('sorting records')
+	reslib.sort_figures()
+
+elsif session.get('option.purge')
+
+	session.report('purging records')
+	reslib.purge_figures()
+
+elsif session.get('option.dummy')
+
+	session.report('creating dummy records')
+    reslib.create_dummies(session.get('option.process'),session.get('option.result'),session.get('option.zipalso'))
+
+else
+
+	session.warning('provide action')
+
+end
+
+reslib.save(base)


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/rslibtool.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/runtools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/runtools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/runtools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,506 @@
+require 'timeout'
+require 'fileutils'
+# require 'ftools'
+require 'rbconfig'
+
+class File
+
+    # we don't want a/b//c
+    #
+    # puts File.join('a','b','c')
+    # puts File.join('/a','b','c')
+    # puts File.join('a:','b','c')
+    # puts File.join('a/','/b/','c')
+    # puts File.join('/a','/b/','c')
+    # puts File.join('//a/','/b/','c')
+
+    def File.join(*list)
+        path, prefix = [*list].flatten.join(File::SEPARATOR), ''
+        path.sub!(/^([\/]+)/) do
+            prefix = $1
+            ''
+        end
+        path.gsub!(/([\\\/]+)/) do
+            File::SEPARATOR
+        end
+        prefix + path
+    end
+
+end
+
+
+class Job
+
+    $ownfile, $ownpath = '', ''
+
+    def Job::set_own_path(file)
+        $ownfile, $ownpath = File.basename(file), File.expand_path(File.dirname(file))
+        $: << $ownpath
+    end
+
+    def Job::ownfile
+        $ownfile
+    end
+
+    def Job::ownpath
+        $ownpath
+    end
+
+end
+
+class Job
+
+    def initialize
+        @startuppath = Dir.getwd
+        @log = Array.new
+        @testmode = false
+        @ownpath = $ownpath
+        @paths = Array.new
+    end
+
+    def exit(showlog=false)
+        Dir.chdir(@startuppath)
+        show_log if showlog
+        Kernel::exit
+    end
+
+    def platform
+        case RbConfig::CONFIG['host_os']
+            when /mswin/ then :windows
+                         else :unix
+        end
+    end
+
+    def path(*components)
+        File.join([*components].flatten)
+    end
+
+    def found(name)
+        FileTest.file?(path(name)) || FileTest.directory?(path(name))
+    end
+
+    def binary(name)
+        if platform == :windows then
+            name.sub(/\.[^\/]+$/o,'') + '.exe'
+        else
+            name
+        end
+    end
+
+    def suffixed(name,suffix)
+        if name =~ /\.[^\/]+$/o then
+            name
+        else
+            name + '.' + suffix
+        end
+    end
+
+    def expanded(*name)
+        File.expand_path(File.join(*name))
+    end
+
+    def argument(n,default=nil)
+        ARGV[n] || default
+    end
+
+    def variable(name,default='')
+        ENV[name] || default
+    end
+
+    def change_dir(*dir)
+        dir, old = expanded(path(*dir)), expanded(Dir.getwd)
+        unless old == dir then
+            begin
+                Dir.chdir(dir)
+            rescue
+                error("unable to change to path #{dir}")
+            else
+                if old == dir then
+                    error("error in changing to path #{dir}")
+                else
+                    message("changed to path #{dir}")
+                end
+            end
+        end
+        # return File.expand_path(Dir.getwd)
+    end
+
+    def delete_dir(*dir)
+        begin
+            dir = path(*dir)
+            pattern = "#{dir}/**/*"
+            puts("analyzing dir #{pattern}")
+            files = Dir.glob(pattern).sort.reverse
+            files.each do |f|
+                begin
+                    # FileTest.file?(f) fails on .whatever files
+                    File.delete(f)
+                rescue
+                    # probably directory
+                else
+                    puts("deleting file #{f}")
+                end
+            end
+            files.each do |f|
+                begin
+                    Dir.rmdir(f)
+                rescue
+                    # strange
+                else
+                    message("deleting path #{f}")
+                end
+            end
+            begin
+                Dir.rmdir(dir)
+            rescue
+                # strange
+            else
+                message("deleting parent #{dir}")
+            end
+            Dir.glob(pattern).sort.each do |f|
+                warning("unable to delete #{f}")
+            end
+        rescue
+            warning("unable to delete path #{File.expand_path(dir)} (#{$!})")
+        else
+            message("path #{File.expand_path(dir)} removed")
+        end
+    end
+
+
+    def create_dir(*dir)
+        begin
+            dir = path(*dir)
+            unless FileTest.directory?(dir) then
+                File.makedirs(dir)
+            else
+                return
+            end
+        rescue
+            error("unable to create path #{File.expand_path(dir)}")
+        else
+            message("path #{File.expand_path(dir)} created")
+        end
+    end
+
+    def show_dir(delay=0)
+        _puts_("\n")
+        print Dir.getwd + ' '
+        begin
+            timeout(delay) do
+                loop do
+                    print '.'
+                    sleep(1)
+                end
+            end
+        rescue TimeoutError
+            # ok
+        end
+        _puts_("\n\n")
+    end
+
+    def copy_file(from,to='.',exclude=[])
+        to, ex = path(to), [exclude].flatten
+        Dir.glob(path(from)).each do |file|
+            tofile = to.sub(/[\.\*]$/o) do File.basename(file) end
+            _do_copy_(file,tofile) unless ex.include?(File.extname(file))
+        end
+    end
+
+    def clone_file(from,to)
+        if from and to then
+            to = File.join(File.basename(from),to) if File.basename(to).empty?
+            _do_copy_(from,to)
+        end
+    end
+
+    def copy_dir(from,to,pattern='*',exclude=[]) # recursive
+        pattern = '*' if ! pattern or pattern.empty?
+        if from and to and File.expand_path(from) != File.expand_path(to) then
+            ex = [exclude].flatten
+            Dir.glob("#{from}/**/#{pattern}").each do |file|
+                unless ex.include?(File.extname(file)) then
+                    _do_copy_(file,File.join(to,file.sub(/^#{from}/, '')))
+                end
+            end
+        end
+    end
+
+    def copy_path(from,to,pattern='*',exclude=[]) # non-recursive
+        pattern = '*' if ! pattern or pattern.empty?
+        if from and to and File.expand_path(from) != File.expand_path(to) then
+            ex = [exclude].flatten
+            Dir.glob("#{from}/#{pattern}").each do |file|
+                unless ex.include?(File.extname(file)) then
+                    _do_copy_(file,File.join(to,file.sub(/^#{from}/, '')))
+                end
+            end
+        end
+    end
+
+    def _do_copy_(file,tofile)
+        if FileTest.file?(file) and File.expand_path(file) != File.expand_path(tofile) then
+            begin
+                create_dir(File.dirname(tofile))
+                File.copy(file,tofile)
+            rescue
+                error("unable to copy #{file} to #{tofile}")
+            else
+                message("file #{file} copied to #{tofile}")
+            end
+        else
+            puts("file #{file} is not copied")
+        end
+    end
+
+    def rename_file(from,to)
+        from, to = path(from), path(to)
+        begin
+            File.move(from,to)
+        rescue
+            error("unable to rename #{from} to #{to}")
+        else
+            message("#{from} renamed to #{to}")
+        end
+    end
+
+    def delete_file(pattern)
+        Dir.glob(path(pattern)).each do |file|
+            _do_delete_(file)
+        end
+    end
+
+    def delete_files(*files)
+        [*files].flatten.each do |file|
+            _do_delete_(file)
+        end
+    end
+
+    def _do_delete_(file)
+        if FileTest.file?(file) then
+            begin
+                File.delete(file)
+            rescue
+                error("unable to delete file #{file}")
+            else
+                message("file #{file} deleted")
+            end
+        else
+            message("no file #{File.expand_path(file)}")
+        end
+    end
+
+    def show_log(filename=nil)
+        if filename then
+            begin
+                if f = File.open(filename,'w') then
+                    @log.each do |line|
+                        f.puts(line)
+                    end
+                    f.close
+                end
+                message("log data written to #{filename}")
+            rescue
+                error("unable to write log to #{filename}")
+            end
+        else
+            @log.each do |line|
+                _puts_(line)
+            end
+        end
+    end
+
+    def _puts_(str)
+        begin
+            STDOUT.puts(    str)
+        rescue
+            STDERR.puts("error while writing '#{str}' to terminal")
+        end
+    end
+
+    def puts(message)
+        @log << message
+        _puts_(message)
+    end
+
+    def error(message)
+        puts("! #{message}")
+        exit
+    end
+
+    def warning(message)
+        puts("- #{message}")
+    end
+
+    def message(message)
+        puts("+ #{message}")
+    end
+
+    def export_variable(variable,value)
+        value = path(value) if value.class == Array
+        ENV[variable] = value
+        message("environment variable #{variable} set to #{value}")
+        return value
+    end
+
+    def execute_command(*command)
+        begin
+            command = [*command].flatten.join(' ')
+            message("running '#{command}'")
+            _puts_("\n")
+            ok = system(command)
+            _puts_("\n")
+            if true then # ok then
+                message("finished '#{command}'")
+            else
+                error("error in running #{command}")
+            end
+        rescue
+            error("unable to run #{command}")
+        end
+    end
+
+    def pipe_command(*command)
+        begin
+            command = [*command].flatten.join(' ')
+            message("running '#{command}'")
+            result = `#{command}`
+            _puts_("\n")
+            _puts_(result)
+            _puts_("\n")
+        rescue
+            error("unable to run #{command}")
+        end
+    end
+
+    def execute_script(script)
+        script = suffixed(script,'rb')
+        script = path(script_path,File.basename(script)) unless found(script)
+        if found(script) then
+            begin
+                message("loading script #{script}")
+                load(script)
+            rescue
+                error("error in loading script #{script} (#{$!})")
+            else
+                message("script #{script} finished")
+            end
+        else
+            warning("no script #{script}")
+        end
+    end
+
+    def execute_binary(*command)
+        command = [*command].flatten.join(' ').split(' ')
+        command[0] = binary(command[0])
+        execute_command(command)
+    end
+
+    def extend_path(pth)
+        export_variable('PATH',"#{path(pth)}#{File::PATH_SEPARATOR}#{ENV['PATH']}")
+    end
+
+    def startup_path
+        @startuppath
+    end
+
+    def current_path
+        Dir.getwd
+    end
+
+    def script_path
+        @ownpath
+    end
+
+    def push_path(newpath)
+        newpath = File.expand_path(newpath)
+        @paths.push(newpath)
+        change_dir(newpath)
+    end
+
+    def pop_path
+        change_dir(if @paths.length > 0 then @paths.pop else @startuppath end)
+    end
+
+    # runner = Runner.new
+    # runner.texmfstart('texexec','--help')
+
+    def texmfstart(name,args,verbose=false)
+        command = ['texmfstart',"#{'--verbose' if verbose}",name,args].flatten.join(' ')
+        system(command)
+    end
+
+end
+
+class Job
+
+    # copied from texmfstart and patched (message/error), different name
+
+    def use_tree(tree)
+        unless tree.empty? then
+            begin
+                setuptex = File.join(tree,'setuptex.tmf')
+                if FileTest.file?(setuptex) then
+                    message("tex tree : #{setuptex}")
+                    ENV['TEXPATH'] = tree.sub(/\/+$/,'') #  + '/'
+                    ENV['TMP'] = ENV['TMP'] || ENV['TEMP'] || ENV['TMPDIR'] || ENV['HOME']
+                    case RUBY_PLATFORM
+                        when /(mswin|bccwin|mingw|cygwin)/i then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-mswin'
+                        when /(linux)/i                     then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-linux'
+                        when /(darwin|rhapsody|nextstep)/i  then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-macosx'
+                    #   when /(netbsd|unix)/i               then # todo
+                        else                                     # todo
+                    end
+                    ENV['TEXMFOS'] = "#{ENV['TEXPATH']}/#{ENV['TEXOS']}"
+                    message("preset   : TEXPATH => #{ENV['TEXPATH']}")
+                    message("preset   : TEXOS   => #{ENV['TEXOS']}")
+                    message("preset   : TEXMFOS => #{ENV['TEXMFOS']}")
+                    message("preset   : TMP => #{ENV['TMP']}")
+                    IO.readlines(File.join(tree,'setuptex.tmf')).each do |line|
+                        case line
+                            when /^[\#\%]/ then
+                                # comment
+                            when /^(.*?)\s+\=\s+(.*)\s*$/ then
+                                k, v = $1, $2
+                                ENV[k] = v.gsub(/\%(.*?)\%/) do
+                                    ENV[$1] || ''
+                                end
+                                message("user set : #{k} => #{ENV[k]}")
+                        end
+                    end
+                else
+                    warning("no setup file '#{setuptex}', tree not initialized") # no error
+                end
+            rescue
+                warning("error in setup: #{$!}")
+            end
+        end
+    end
+
+end
+
+Job::set_own_path($0)
+
+if Job::ownfile == 'runtools.rb' then
+
+    begin
+        script = ARGV.shift
+        if script then
+            script += '.rb' if File.extname(script).empty?
+            fullname = File.expand_path(script)
+            fullname = File.join(Job::ownpath,script) unless FileTest.file?(fullname)
+            if FileTest.file?(fullname) then
+                puts("loading script #{fullname}")
+                Job::set_own_path(fullname)
+                load(fullname)
+            else
+                puts("unknown script #{fullname}")
+            end
+        else
+            puts("provide script name")
+        end
+    rescue
+        puts("fatal error: #{$!}")
+    end
+
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/runtools.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/texexec.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/texexec.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/texexec.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,791 @@
+#!/usr/bin/env ruby
+#encoding: ASCII-8BIT
+
+banner = ['TeXExec', 'version 6.2.1', '1997-2009', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'fileutils'
+# require 'ftools'     # needed ?
+
+require 'base/switch'
+require 'base/logger'
+require 'base/variables'
+require 'base/system'
+
+require 'base/state' # needed ?
+require 'base/file'  # needed ?
+
+require 'base/tex'
+require 'base/texutil'
+require 'base/kpse'
+
+class Commands
+
+    include CommandBase
+
+    def make
+        if job = TEX.new(logger) then
+            prepare(job)
+            # bonus, overloads language switch !
+            job.setvariable('language','all') if @commandline.option('all')
+            if @commandline.arguments.length > 0 then
+                if @commandline.arguments.first == 'all' then
+                    job.setvariable('texformats',job.defaulttexformats)
+                    job.setvariable('mpsformats',job.defaultmpsformats)
+                else
+                    job.setvariable('texformats', at commandline.arguments)
+                    job.setvariable('mpsformats', at commandline.arguments)
+                end
+            end
+            job.makeformats
+            job.inspect && Kpse.inspect if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    def check
+        if job = TEX.new(logger) then
+            job.checkcontext
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+        end
+    end
+
+    def main
+        if @commandline.arguments.length>0 then
+            process
+        else
+            help
+        end
+    end
+
+    def process
+        if job = TEX.new(logger) then
+            job.setvariable('files', at commandline.arguments)
+            prepare(job)
+            job.processtex
+            job.inspect && Kpse.inspect if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    def mptex
+        if job = TEX.new(logger) then
+            job.setvariable('files', at commandline.arguments)
+            prepare(job)
+            job.processmptex
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    def mpxtex
+        if job = TEX.new(logger) then
+            job.setvariable('files', at commandline.arguments)
+            prepare(job)
+            job.processmpxtex
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    def mpgraphic
+        if job = TEX.new(logger) then
+            job.setvariable('files', at commandline.arguments)
+            prepare(job)
+            job.processmpgraphic
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    def mpstatic
+        if job = TEX.new(logger) then
+            job.setvariable('filename', at commandline.arguments.first)
+            prepare(job)
+            job.processmpstatic
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+            seterror if job.error?
+        end
+    end
+
+    # hard coded goodies # to be redone as s-ctx-.. with vars passed as such
+
+    def listing
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if files.length > 0 then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    backspace = @commandline.checkedoption('backspace', '1.5cm')
+                    topspace  = @commandline.checkedoption('topspace', '1.5cm')
+                    pretty    = @commandline.option('pretty')
+                    f << "% interface=english\n"
+                    f << "\\setupbodyfont[11pt,tt]\n"
+                    f << "\\setuplayout\n"
+                    f << "  [topspace=#{topspace},backspace=#{backspace},\n"
+                    f << "   header=0cm,footer=1.5cm,\n"
+                    f << "   width=middle,height=middle]\n"
+                    f << "\\setuptyping[lines=yes]\n"
+                    f << "\\setuptyping[option=color]\n" if pretty
+                    f << "\\starttext\n";
+                    files.each do |filename|
+                        report("list file: #{filename}")
+                        cleanname = cleantexfilename(filename).downcase
+                        f << "\\page\n"
+                        f << "\\setupfootertexts[\\tttf #{cleanname}][\\tttf \\pagenumber]\n"
+                        f << "\\typefile{#{filename}}\n"
+                    end
+                    f << "\\stoptext\n"
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    # job.setvariable('nooptionfile',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                else
+                    report('no files to list')
+                end
+            else
+                report('no files to list')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def figures
+        # we replaced "texutil --figures ..."
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            fast = @commandline.option('fast')
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if fast or (files.length > 0) then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    files.delete("texexec.pdf")
+                    # Kpse.runscript('rlxtools', ['--identify','--collect'], files.join(' ')) unless fast
+                    system("texmfstart rlxtools --identify --collect #{files.join(' ')}")
+                    figures     = @commandline.checkedoption('method', 'a').downcase
+                    paperoffset = @commandline.checkedoption('paperoffset', '0pt')
+                    backspace   = @commandline.checkedoption('backspace', '1.5cm')
+                    topspace    = @commandline.checkedoption('topspace', '1.5cm')
+                    boxtype     = @commandline.checkedoption('boxtype','')
+                    f << "% format=english\n";
+                    f << "\\usemodule[res-20]\n"
+                    f << "\\setuplayout\n";
+                    f << "  [topspace=#{topspace},backspace=#{backspace},\n"
+                    f << "   header=1.5cm,footer=0pt,\n";
+                    f << "   width=middle,height=middle]\n";
+                    if @commandline.option('fullscreen') then
+                        f << "\\setupinteraction\n";
+                        f << "  [state=start]\n";
+                        f << "\\setupinteractionscreen\n";
+                        f << "  [option=max]\n";
+                    end
+                    boxtype += "box" unless boxtype.empty? || (boxtype =~ /box$/io)
+                    f << "\\starttext\n";
+                    f << "\\showexternalfigures[alternative=#{figures},offset=#{paperoffset},size=#{boxtype}]\n";
+                    f << "\\stoptext\n";
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                    # File.silentdelete('rlxtools.rli') unless job.getvariable('keep')
+                else
+                    report('no figures to show')
+                end
+            else
+                report('no figures to show')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def modules
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            msuffixes = ['tex','mkii','mkiv','mp','pl','pm','rb']
+            if files.length > 0 then
+                files.each do |fname|
+                    fnames = Array.new
+                    if FileTest.file?(fname) then
+                        fnames << fname
+                    else
+                        msuffixes.each do |fsuffix|
+                            fnames << File.suffixed(fname,fsuffix)
+                        end
+                    end
+                    fnames.each do |ffname|
+                        if msuffixes.include?(File.splitname(ffname)[1]) && FileTest.file?(ffname) then
+                            if mod = File.open(job.tempfilename('tex'),'w') then
+                                if File.suffix(ffname) =~ /^(mkii|mkiv)$/o then
+                                    markfile = $1
+                                else
+                                    markfile = nil
+                                end
+                                # Kpse.runscript('ctxtools',['--document'],ffname)
+                                system("texmfstart ctxtools --document #{ffname}")
+                                if ted = File.silentopen(File.suffixed(ffname,'ted')) then
+                                    firstline = ted.gets
+                                    if firstline =~ /interface=/o then
+                                        mod << firstline
+                                    else
+                                        mod << "% interface=en\n"
+                                    end
+                                    ted.close
+                                else
+                                    mod << "% interface=en\n"
+                                end
+                                mod << "\\usemodule[mod-01]\n"
+                                mod << "\\def\\ModuleNumber{1}\n"
+                                mod << "\\starttext\n"
+                                # todo: global file too
+                                mod << "\\readlocfile{#{File.suffixed(ffname,'ted')}}{}{}\n"
+                                mod << "\\stoptext\n"
+                                mod.close
+                                job.setvariable('interface','english') # redundant
+                                # job.setvariable('simplerun',true)
+                                # job.setvariable('nooptionfile',true)
+                                job.setvariable('files',[job.tempfilename])
+                                result = File.unsuffixed(File.basename(ffname))
+                                if markfile then
+                                    result = result+'-'+markfile
+                                end
+                                job.setvariable('result',result)
+                                job.processtex
+                                # ["dvi", "pdf","ps"].each do |s|
+                                    # File.silentrename(job.tempfilename(s),File.suffixed(ffname,s));
+                                # end
+                            end
+                        end
+                    end
+                end
+            else
+                report('no modules to process')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def pdfsplit
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            filename = File.expand_path(@commandline.arguments.first)
+            if FileTest.file?(filename) then
+                basename = filename.sub(/\..*?$/,'')
+                tempfile = File.suffixed(job.tempfilename,'tex')
+                if basename != filename then
+                    info = `pdfinfo #{filename}`
+                    if info =~ /Pages:\s*(\d+)/ then
+                        nofpages = $1.to_i
+                        result = @commandline.checkedoption('result','texexec')
+                        nofpages.times do |i|
+                            if f = File.open(tempfile,"w") then
+                                n = i + 1
+                                report("extracting page #{n}")
+                                f << "\\starttext\\startTEXpage\n"
+                                f << "\\externalfigure[#{filename}][object=no,page=#{n}]\n"
+                                f << "\\stopTEXpage\\stoptext\n"
+                                f.close
+                                job.setvariable('result',"#{result}-#{n}")
+                                job.setvariable('interface','english') # redundant
+                                job.setvariable('simplerun',true)
+                                job.setvariable('purge',true)
+                                job.setvariable('files',[tempfile])
+                                job.processtex
+                            end
+                        end
+                    end
+                end
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def arrangeoutput
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if files.length > 0 then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    emptypages  = @commandline.checkedoption('addempty', '')
+                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+                    textwidth   = @commandline.checkedoption('textwidth', '0cm')
+                    backspace   = @commandline.checkedoption('backspace', '0cm')
+                    topspace    = @commandline.checkedoption('topspace', '0cm')
+                    f << "\\definepapersize\n"
+                    f << "  [offset=#{paperoffset}]\n"
+                    f << "\\setuplayout\n"
+                    f << "  [backspace=#{backspace},\n"
+                    f << "    topspace=#{topspace},\n"
+                    f << "     marking=on,\n" if @commandline.option('marking')
+                    f << "       width=middle,\n"
+                    f << "      height=middle,\n"
+                    f << "    location=middle,\n"
+                    f << "      header=0pt,\n"
+                    f << "      footer=0pt]\n"
+                    unless @commandline.option('noduplex') then
+                        f << "\\setuppagenumbering\n"
+                        f << "  [alternative=doublesided]\n"
+                    end
+                    f << "\\starttext\n"
+                    files.each do |filename|
+                        report("arranging file #{filename}")
+                        f << "\\insertpages\n"
+                        f << "  [#{filename}]\n"
+                        f << "  [#{emptypages}]\n" unless emptypages.empty?
+                        f << "  [width=#{textwidth}]\n"
+                    end
+                    f << "\\stoptext\n"
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    job.setvariable('arrange',true)
+                    # job.setvariable('nooptionfile',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                else
+                    report('no files to arrange')
+                end
+            else
+                report('no files to arrange')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def selectoutput
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if files.length > 0 then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    selection   = @commandline.checkedoption('selection', '')
+                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+                    textwidth   = @commandline.checkedoption('textwidth', '0cm')
+                    backspace   = @commandline.checkedoption('backspace', '0cm')
+                    topspace    = @commandline.checkedoption('topspace', '0cm')
+                    paperformat = @commandline.checkedoption('paperformat', 'A4*A4').split(/[\*x]/o)
+                    from, to = paperformat[0] || 'A4', paperformat[1] || paperformat[0] || 'A4'
+                    if from == 'fit' or to == 'fit' then
+                        f << "\\getfiguredimensions[#{files.first}]\n"
+                        if from == 'fit' then
+                            f << "\\expanded{\\definepapersize[from-fit][width=\\figurewidth,height=\\figureheight]}\n"
+                            from = 'from-fit'
+                        end
+                        if to == 'fit' then
+                            f << "\\expanded{\\definepapersize[to-fit][width=\\figurewidth,height=\\figureheight]}\n"
+                            to = 'to-fit'
+                        end
+                    end
+                    job.setvariable('paperformat','') # else overloaded later on
+                    f << "\\setuppapersize[#{from}][#{to}]\n"
+                    f << "\\definepapersize\n";
+                    f << "  [offset=#{paperoffset}]\n";
+                    f << "\\setuplayout\n";
+                    f << "  [backspace=#{backspace},\n";
+                    f << "    topspace=#{topspace},\n";
+                    f << "     marking=on,\n" if @commandline.option('marking')
+                    f << "       width=middle,\n";
+                    f << "      height=middle,\n";
+                    f << "    location=middle,\n";
+                    f << "      header=0pt,\n";
+                    f << "      footer=0pt]\n";
+                    f << "\\setupexternalfigures\n";
+                    f << "  [directory=]\n";
+                    f << "\\starttext\n";
+                    unless selection.empty? then
+                        f << "\\filterpages\n"
+                        f << "  [#{files.first}][#{selection}][width=#{textwidth}]\n"
+                    end
+                    f << "\\stoptext\n"
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    # job.setvariable('nooptionfile',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                else
+                    report('no files to selectt')
+                end
+            else
+                report('no files to select')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    def copyoutput
+        copyortrim(false,'copy')
+    end
+
+    def trimoutput
+        copyortrim(true,'trim')
+    end
+
+    def copyortrim(trim=false,what='unknown')
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if files.length > 0 then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    scale = @commandline.checkedoption('scale')
+                    begin
+                        scale = (scale.to_f * 1000.0).to_i if scale.to_i < 10
+                    rescue
+                        scale = 1000
+                    end
+                    scale = scale.to_i
+                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+                    f << "\\starttext\n"
+                    files.each do |filename|
+                        result = @commandline.checkedoption('result','texexec')
+                        begin
+                            if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
+                                report("copying file: #{filename}")
+                                f <<  "\\getfiguredimensions\n"
+                                f <<  "  [#{filename}]\n"
+                                f <<  "  [scale=#{scale},\n"
+                                f <<  "   page=1,\n"
+                                f <<  "   size=trimbox\n" if trim
+                                f <<  "]\n"
+                                f <<  "\\definepapersize\n"
+                                f <<  "  [copy]\n"
+                                f <<  "  [width=\\figurewidth,\n"
+                                f <<  "   height=\\figureheight]\n"
+                                f <<  "\\setuppapersize\n"
+                                f <<  "  [copy][copy]\n"
+                                f <<  "\\setuplayout\n"
+                                f <<  "  [page]\n"
+                                f <<  "\\setupexternalfigures\n"
+                                f <<  "  [directory=]\n"
+                                f <<  "\\copypages\n"
+                                f <<  "  [#{filename}]\n"
+                                f <<  "  [scale=#{scale},\n"
+                                f <<  "   marking=on,\n" if @commandline.option('markings')
+                                f <<  "   size=trimbox,\n" if trim
+                                f <<  "   offset=#{paperoffset}]\n"
+                            end
+                        rescue
+                            report("wrong specification")
+                        end
+                    end
+                    f << "\\stoptext\n"
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    # job.setvariable('nooptionfile',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                else
+                    report("no files to #{what}")
+                end
+            else
+                report("no files to #{what}")
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    # todo: make this styles
+
+    def combineoutput
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            files =  if @commandline.option('sort') then @commandline.arguments.sort else @commandline.arguments end
+            if files.length > 0 then
+                if f = File.open(job.tempfilename('tex'),'w') then
+                    paperoffset = @commandline.checkedoption('paperoffset', '0cm')
+                    combination = @commandline.checkedoption('combination','2*2').split(/[\*x]/o)
+                    paperformat = @commandline.checkedoption('paperformat', 'A4*A4').split(/[\*x]/o)
+                    bannerheight = @commandline.checkedoption('bannerheight', '')
+                    pdftitle = @commandline.checkedoption('pdftitle', '')
+                    nx, ny = combination[0] || '2', combination[1] || combination[0] || '2'
+                    from, to = paperformat[0] || 'A4', paperformat[1] || paperformat[0] || 'A4'
+                    f << "\\setuppapersize[#{from}][#{to}]\n"
+                    f << "\\setuplayout\n"
+                    f << "  [topspace=#{paperoffset},backspace=#{paperoffset},\n"
+                    f << "   header=0pt,footer=0pt,\n"
+                    f << "   width=middle,height=middle]\n"
+                    if bannerheight.empty? then
+                        f << "\\setuplayout[footer=1cm]\n"
+                    else
+                        f << "\\definelayer[page][width=\\paperwidth,height=\\paperheight]\n"
+                        f << "\\setupbackgrounds[page][background=page]\n"
+                    end
+                    if @commandline.option('nobanner') then
+                        f << "\\setuplayout[footer=0cm]\n"
+                        f << "\\setupbackgrounds[page][background=]\n"
+                    end
+                    f << "\\setupexternalfigures[directory=]\n"
+                    if not pdftitle.empty? then
+                        f << "\\setupinteraction[state=start,title={#{pdftitle}}]\n"
+                    end
+                    f << "\\starttext\n"
+                    files.each do |filename|
+                        result = @commandline.checkedoption('result','texexec')
+                        if (filename !~ /^texexec/io) && (filename !~ /^#{result}/) then
+                            report("combination file: #{filename}")
+                            cleanname = cleantexfilename(filename).downcase
+                            bannerstring = "\\tttf #{cleanname}\\quad\\quad\\currentdate\\quad\\quad\\pagenumber"
+                            if bannerheight.empty? then
+                                f << "\\setupfootertexts\n"
+                                f << "  [#{bannerstring}]\n"
+                            else
+                                # for the moment we lack a better hook
+                                f << "\\setuptexttexts\n"
+                                f << "  [{\\setlayerframed[page][preset=middlebottom][frame=off,height=#{bannerheight}]{#{bannerstring}}}]\n"
+                            end
+                            f << "\\combinepages[#{filename}][nx=#{nx},ny=#{ny}]\n"
+                            f << "\\page\n"
+                        end
+                    end
+                    f << "\\stoptext\n"
+                    f.close
+                    job.setvariable('interface','english')
+                    job.setvariable('simplerun',true)
+                    # job.setvariable('nooptionfile',true)
+                    job.setvariable('files',[job.tempfilename])
+                    job.processtex
+                else
+                    report('no files to list')
+                end
+            else
+                report('no files to list')
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
+    private
+
+    def prepare(job)
+
+        job.booleanvars.each do |k|
+            job.setvariable(k, at commandline.option(k))
+        end
+        job.stringvars.each do |k|
+            job.setvariable(k, at commandline.option(k)) unless @commandline.option(k).empty?
+        end
+        job.standardvars.each do |k|
+            job.setvariable(k, at commandline.option(k)) unless @commandline.option(k).empty?
+        end
+        job.knownvars.each do |k|
+            job.setvariable(k, at commandline.option(k)) unless @commandline.option(k).empty?
+        end
+
+job.setvariable('given.backend',job.getvariable('backend'))
+
+        if (str = @commandline.option('engine')) && ! str.standard? && ! str.empty? then
+            job.setvariable('texengine',str)
+        elsif @commandline.oneof('pdfetex','pdftex','pdf') then
+            job.setvariable('texengine','pdftex')
+        elsif @commandline.oneof('xetex','xtx') then
+            job.setvariable('texengine','xetex')
+        elsif @commandline.oneof('aleph') then
+            job.setvariable('texengine','aleph')
+        elsif @commandline.oneof('petex') then
+            job.setvariable('texengine','petex')
+        else
+            job.setvariable('texengine','standard')
+        end
+
+        if (str = @commandline.option('backend')) && ! str.standard? && ! str.empty? then
+            job.setvariable('backend',str)
+        elsif @commandline.oneof('pdfetex','pdftex','pdf') then
+            job.setvariable('backend','pdftex')
+        elsif @commandline.oneof('dvipdfmx','dvipdfm','dpx','dpm') then
+            job.setvariable('backend','dvipdfmx')
+        elsif @commandline.oneof('xetex','xtx') then
+            job.setvariable('backend','xetex')
+        elsif @commandline.oneof('aleph') then
+            job.setvariable('backend','dvipdfmx')
+        elsif @commandline.oneof('petex') then
+            job.setvariable('backend','dvipdfmx')
+        elsif @commandline.oneof('dvips','ps') then
+            job.setvariable('backend','dvips')
+        elsif @commandline.oneof('xdv') then
+            job.setvariable('backend','xdv')
+        else
+            case job.getvariable('texengine')
+                when 'pdfetex'  then job.setvariable('backend','pdftex')
+                when 'pdftex'   then job.setvariable('backend','pdftex')
+                when 'xetex'    then job.setvariable('backend','xetex')
+                when 'petex'    then job.setvariable('backend','dvipdfmx')
+                when 'aleph'    then job.setvariable('backend','dvipdfmx')
+            else
+                job.setvariable('backend','standard')
+            end
+        end
+
+        if (str = @commandline.option('engine')) && ! str.standard? && ! str.empty? then
+            job.setvariable('mpsengine', at commandline.option('engine'))
+        else
+            job.setvariable('mpsengine','standard')
+        end
+
+    end
+
+    def cleantexfilename(filename)
+        filename.gsub(/([\$\_\#])/) do "\\$1" end.gsub(/([\~])/) do "\\string$1" end
+    end
+
+end
+
+# we will make this pluggable, i.e. load plugins from base/tex that
+# extend the class and may even add switches
+#
+# commandline.load_plugins('base/tex')
+#
+# maybe it's too slow so for a while keep the --pdf* in here
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registeraction('make',      'make formats')
+commandline.registeraction('check',     'check versions')
+commandline.registeraction('process',   'process file')
+commandline.registeraction('mptex',     'process mp file')
+commandline.registeraction('mpxtex',    'process mpx file')
+commandline.registeraction('mpgraphic', 'process mp file to stand-alone graphics')
+commandline.registeraction('mpstatic',  'process mp/ctx file to stand-alone graphics')
+
+commandline.registeraction('listing',    'list of file content')
+commandline.registeraction('figures',    'generate overview of figures')
+commandline.registeraction('modules',    'generate module documentation')
+commandline.registeraction('pdfarrange', 'impose pages (booklets)')
+commandline.registeraction('pdfselect',  'select pages from file(s)')
+commandline.registeraction('pdfcopy',    'copy pages from file(s)')
+commandline.registeraction('pdftrim',    'trim pages from file(s)')
+commandline.registeraction('pdfcombine', 'combine multiple pages')
+commandline.registeraction('pdfsplit',   'split file in pages')
+
+# compatibility switch
+
+class Commands
+
+    include CommandBase
+
+    alias pdfarrange :arrangeoutput
+    alias pdfselect  :selectoutput
+    alias pdfcopy    :copyoutput
+    alias pdftrim    :trimoutput
+    alias pdfcombine :combineoutput
+
+end
+
+# so far for compatibility, will move to tex
+
+extrastringvars = [
+    'pages', 'background', 'backspace', 'topspace', 'boxtype', 'tempdir','bannerheight',
+    'printformat', 'method', 'scale', 'selection',
+    'combination', 'textwidth', 'addempty', 'logfile',
+    'startline', 'endline', 'startcolumn', 'endcolumn', 'scale'
+]
+
+extrabooleanvars = [
+    'centerpage', 'noduplex', 'color', 'pretty',
+    'fullscreen', 'screensaver', 'markings'
+]
+
+if job = TEX.new(logger) then
+
+    job.setextrastringvars(extrastringvars)
+    job.setextrabooleanvars(extrabooleanvars)
+
+    job.booleanvars.each do |k|
+        commandline.registerflag(k)
+    end
+    job.stringvars.each do |k|
+        commandline.registervalue(k,'')
+    end
+    job.standardvars.each do |k|
+        commandline.registervalue(k,'standard')
+    end
+    job.knownvars.each do |k|
+        commandline.registervalue(k,'')
+    end
+
+end
+
+class Commands
+
+    alias saved_help help
+
+    def wrap_help(title, vars)
+        report("")
+        report(title)
+        report("")
+        r, n = '', 0
+        vars.sort.each do |s|
+            if n == 5 then
+                report(r)
+                r, n = '', 1
+            else
+                n += 1
+            end
+            r << '  ' + s.to_s
+        end
+        report(r) unless r.empty?
+    end
+
+    def help
+        saved_help
+        if @commandline.option('all') then
+            if job = TEX.new(logger) then
+                wrap_help("boolean switches:", job.allbooleanvars)
+                wrap_help("string switches:", job.allstringvars)
+            end
+        else
+            report('')
+            report('--help --all   shows all switches')
+        end
+    end
+
+end
+
+# todo: register flags -> first one true
+
+commandline.registerflag('pdf')
+commandline.registerflag('pdftex')
+commandline.registerflag('pdfetex')
+
+commandline.registerflag('dvipdfmx')
+commandline.registerflag('dvipdfm')
+commandline.registerflag('dpx')
+commandline.registerflag('dpm')
+
+commandline.registerflag('dvips')
+commandline.registerflag('ps')
+
+commandline.registerflag('xetex')
+commandline.registerflag('xtx')
+commandline.registerflag('xdv')
+
+commandline.registerflag('aleph')
+
+commandline.registerflag('petex')
+
+commandline.registerflag('all')
+commandline.registerflag('fast')
+commandline.registerflag('sort')
+
+# generic
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registerflag('verbose')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).execute(commandline.action || 'main') # or just execute()


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/texexec.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/texmfstart.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/texmfstart.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/texmfstart.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,1271 @@
+#!/usr/bin/env ruby
+#encoding: ASCII-8BIT
+
+# We have removed the fast, server and client variants and no longer
+# provide the distributed 'serve trees' option. After all, we're now
+# using luatex.
+
+# program   : texmfstart
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 1.9.0 - 2003/2006
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-pod.com / www.pragma-ade.com
+
+# no special requirements, i.e. no exa modules/classes used
+
+# texmfstart [switches] filename [optional arguments]
+#
+# ruby2exe texmfstart --help -> avoids stub test
+#
+# Of couse I can make this into a nice class, which i'll undoubtely will
+# do when I feel the need. In that case it will be part of a bigger game.
+
+# --locate        => provides location
+# --exec          => exec instead of system
+# --iftouched=a,b => only if timestamp a<>b
+# --ifchanged=a,b => only if checksum changed
+#
+# file: path: bin:
+
+# texmfstart --exec bin:scite *.tex
+
+# we don't depend on other libs
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require "rbconfig"
+require "fileutils"
+
+require "digest/md5"
+
+# kpse_merge_start
+
+class File
+    def File::makedirs(*x)
+        FileUtils.makedirs(x)
+    end
+end
+
+class String
+
+    def split_path
+        if self =~ /\;/o || self =~ /^[a-z]\:/io then
+            self.split(";")
+        else
+            self.split(":")
+        end
+    end
+
+end
+
+class Array
+
+    def join_path
+        self.join(File::PATH_SEPARATOR)
+    end
+
+end
+
+class File
+
+    def File.locate_file(path,name)
+        begin
+            files = Dir.entries(path)
+            if files.include?(name) then
+                fullname = File.join(path,name)
+                return fullname if FileTest.file?(fullname)
+            end
+            files.each do |p|
+                fullname = File.join(path,p)
+                if p != '.' and p != '..' and FileTest.directory?(fullname) and result = locate_file(fullname,name) then
+                    return result
+                end
+            end
+        rescue
+            # bad path
+        end
+        return nil
+    end
+
+    def File.glob_file(pattern)
+        return Dir.glob(pattern).first
+    end
+
+end
+
+# kpse_merge_file: 't:/ruby/base/kpsedirect.rb'
+
+class KpseDirect
+
+    attr_accessor :progname, :format, :engine
+
+    def initialize
+        @progname, @format, @engine = '', '', ''
+    end
+
+    def expand_path(str)
+        clean_name(`kpsewhich -expand-path=#{str}`.chomp)
+    end
+
+    def expand_var(str)
+        clean_name(`kpsewhich -expand-var=#{str}`.chomp)
+    end
+
+    def find_file(str)
+        clean_name(`kpsewhich #{_progname_} #{_format_} #{str}`.chomp)
+    end
+
+    def _progname_
+        if @progname.empty? then '' else "-progname=#{@progname}" end
+    end
+    def _format_
+        if @format.empty?   then '' else "-format=\"#{@format}\"" end
+    end
+
+    private
+
+    def clean_name(str)
+        str.gsub(/\\/,'/')
+    end
+
+end
+
+# kpse_merge_stop
+
+$mswindows = RbConfig::CONFIG['host_os'] =~ /mswin/
+$separator = File::PATH_SEPARATOR
+$version   = "2.1.0"
+$ownpath   = File.dirname($0)
+
+if $mswindows then
+    require "win32ole"
+    require "Win32API"
+end
+
+# exit if defined?(REQUIRE2LIB)
+
+$stdout.sync = true
+$stderr.sync = true
+
+$applications = Hash.new
+$suffixinputs = Hash.new
+$predefined   = Hash.new
+$runners      = Hash.new
+
+$suffixinputs['pl']  = 'PERLINPUTS'
+$suffixinputs['rb']  = 'RUBYINPUTS'
+$suffixinputs['py']  = 'PYTHONINPUTS'
+$suffixinputs['jar'] = 'JAVAINPUTS'
+$suffixinputs['pdf'] = 'PDFINPUTS'
+
+$predefined['texexec']  = 'texexec.rb'
+$predefined['texutil']  = 'texutil.rb'
+$predefined['texfont']  = 'texfont.pl'
+$predefined['texshow']  = 'texshow.pl'
+
+$predefined['makempy']  = 'makempy.pl'
+$predefined['mptopdf']  = 'mptopdf.pl'
+$predefined['pstopdf']  = 'pstopdf.rb'
+
+$predefined['examplex'] = 'examplex.rb'
+$predefined['concheck'] = 'concheck.rb'
+
+$predefined['runtools'] = 'runtools.rb'
+$predefined['textools'] = 'textools.rb'
+$predefined['tmftools'] = 'tmftools.rb'
+$predefined['ctxtools'] = 'ctxtools.rb'
+$predefined['rlxtools'] = 'rlxtools.rb'
+$predefined['pdftools'] = 'pdftools.rb'
+$predefined['mpstools'] = 'mpstools.rb'
+# $predefined['exatools'] = 'exatools.rb'
+$predefined['xmltools'] = 'xmltools.rb'
+# $predefined['mtxtools'] = 'mtxtools.rb'
+
+$predefined['newpstopdf']   = 'pstopdf.rb'
+$predefined['newtexexec']   = 'texexec.rb'
+$predefined['pdftrimwhite'] = 'pdftrimwhite.pl'
+
+$makelist = [
+    # context
+    'texexec',
+    'texutil',
+    'texfont',
+    # mp/ps
+    'pstopdf',
+    'mptopdf',
+    'makempy',
+    # misc
+    'ctxtools',
+    'pdftools',
+    'xmltools',
+    'textools',
+    'mpstools',
+    'tmftools',
+    'exatools',
+    'runtools',
+    'rlxtools',
+    'pdftrimwhite',
+    'texfind',
+    'texshow'
+    #
+    # no 'mtxtools',
+    # no, 'texmfstart'
+]
+
+$scriptlist   = 'rb|pl|py|jar'
+$documentlist = 'pdf|ps|eps|htm|html'
+
+$editor       = ENV['TEXMFSTART_EDITOR'] || ENV['EDITOR'] || ENV['editor'] || 'scite'
+
+$crossover    = true # to other tex tools, else only local
+$kpse         = nil
+
+def set_applications(page=1)
+
+    $applications['unknown']  = ''
+    $applications['ruby']     = $applications['rb']  = 'ruby'
+    $applications['perl']     = $applications['pl']  = 'perl'
+    $applications['python']   = $applications['py']  = 'python'
+    $applications['java']     = $applications['jar'] = 'java'
+
+    if $mswindows then
+        $applications['pdf']  = ['',"pdfopen --page #{page} --file",'acroread']
+        $applications['html'] = ['','netscape','mozilla','opera','iexplore']
+        $applications['ps']   = ['','gview32','gv','gswin32','gs']
+    else
+        $applications['pdf']  = ["pdfopen --page #{page} --file",'acroread']
+        $applications['html'] = ['netscape','mozilla','opera']
+        $applications['ps']   = ['gview','gv','gs']
+    end
+
+    $applications['htm']      = $applications['html']
+    $applications['eps']      = $applications['ps']
+
+end
+
+set_applications()
+
+def check_kpse
+    if $kpse then
+        # already done
+    else
+        $kpse = KpseDirect.new
+    end
+end
+
+if $mswindows then
+
+    GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', ['P','P','N'], 'N')
+    GetLongPathName  = Win32API.new('kernel32', 'GetLongPathName',  ['P','P','N'], 'N')
+
+    def dowith_pathname (filename,filemethod)
+        filename = filename.gsub(/\\/o,'/') # no gsub! because filename can be frozen
+        case filename
+            when /\;/o then
+                # could be a path spec
+                return filename
+            when /\s+/o then
+                # danger lurking
+                buffer = ' ' * 260
+                length = filemethod.call(filename,buffer,buffer.size)
+                if length>0 then
+                    return buffer.slice(0..length-1)
+                else
+                    # when the path or file does not exist, nothing is returned
+                    # so we try to handle the path separately from the basename
+                    basename = File.basename(filename)
+                    pathname = File.dirname(filename)
+                    length = filemethod.call(pathname,buffer,260)
+                    if length>0 then
+                        return buffer.slice(0..length-1) + '/' + basename
+                    else
+                        return filename
+                    end
+                end
+            else
+                # no danger
+                return filename
+        end
+    end
+
+    def longpathname (filename)
+        dowith_pathname(filename,GetLongPathName)
+    end
+
+    def shortpathname (filename)
+        dowith_pathname(filename,GetShortPathName)
+    end
+
+else
+
+    def longpathname (filename)
+        filename
+    end
+
+    def shortpathname (filename)
+        filename
+    end
+
+end
+
+class File
+
+    @@update_eps = 1
+
+    def File.needsupdate(oldname,newname)
+        begin
+            oldtime = File.stat(oldname).mtime.to_i
+            newtime = File.stat(newname).mtime.to_i
+            if newtime >= oldtime then
+                return false
+            elsif oldtime-newtime < @@update_eps then
+                return false
+            else
+                return true
+            end
+        rescue
+            return true
+        end
+    end
+
+    def File.syncmtimes(oldname,newname)
+        return
+        begin
+            if $mswindows then
+                # does not work (yet) / gives future timestamp
+                # t = File.mtime(oldname) # i'm not sure if the time is frozen, so we do it here
+                # File.utime(0,t,oldname,newname)
+            else
+                t = File.mtime(oldname) # i'm not sure if the time is frozen, so we do it here
+                File.utime(0,t,oldname,newname)
+            end
+        rescue
+        end
+    end
+
+    def File.timestamp(name)
+        begin
+            "#{File.stat(name).mtime}"
+        rescue
+            return 'unknown'
+        end
+    end
+
+end
+
+def hashed (arr=[])
+    arg = if arr.class == String then arr.split(' ') else arr.dup end
+    hsh = Hash.new
+    if arg.length > 0
+        hsh['arguments'] = ''
+        done = false
+        arg.each do |s|
+            if done then
+                if s =~ /\s/ then
+                    kvl = s.split('=')
+                    if kvl[1] and kvl[1] !~ /^[\"\']/ then
+                        hsh['arguments'] += ' ' + kvl[0] + "=" + '"' + kvl[1] + '"'
+                    elsif s =~ /\s/ then
+                        hsh['arguments'] += ' "' + s + '"'
+                    else
+                        hsh['arguments'] += ' ' + s
+                    end
+                else
+                    hsh['arguments'] += ' ' + s
+                end
+            else
+                kvl = s.split('=')
+                if kvl[0].sub!(/^\-+/,'') then
+                    hsh[kvl[0]] = if kvl.length > 1 then kvl[1] else true end
+                else
+                    hsh['file'] = s
+                    done = true
+                end
+            end
+        end
+    end
+    return hsh
+end
+
+
+def launch(filename)
+    if $browser && $mswindows then
+        filename = filename.gsub(/\.[\/\\]/) do
+            Dir.getwd + '/'
+        end
+        report("launching #{filename}")
+        ie = WIN32OLE.new("InternetExplorer.Application")
+        ie.visible = true
+        ie.navigate(filename)
+        return true
+    else
+        return false
+    end
+end
+
+# env|environment
+# rel|relative
+# loc|locate|kpse|path|file
+
+def quoted(str)
+    if str =~ /^\"/ then
+        return str
+    elsif str =~ / / then
+        return "\"#{str}\""
+    else
+        return str
+    end
+end
+
+def expanded(arg) # no "other text files", too restricted
+    arg.gsub(/(env|environment)\:([a-zA-Z\-\_\.0-9]+)/o) do
+        method, original, resolved = $1, $2, ''
+        if resolved = ENV[original] then
+            report("environment variable #{original} expands to #{resolved}") unless $report
+            quoted(resolved)
+        else
+            report("environment variable #{original} cannot be resolved") unless $report
+            quoted(original)
+        end
+    end . gsub(/(rel|relative)\:([a-zA-Z\-\_\.0-9]+)/o) do
+        method, original, resolved = $1, $2, ''
+        ['.','..','../..'].each do |r|
+            if FileTest.file?(File.join(r,original)) then
+                resolved = File.join(r,original)
+                break
+            end
+        end
+        if resolved.empty? then
+            quoted(original)
+        else
+            quoted(resolved)
+        end
+    end . gsub(/(kpse|loc|locate|file|path)\:([a-zA-Z\-\_\.0-9]+)/o) do
+        method, original, resolved = $1, $2, ''
+        if $program && ! $program.empty? then
+            # pstrings = ["-progname=#{$program}"]
+            pstrings = [$program]
+        else
+            # pstrings = ['','-progname=context']
+            pstrings = ['','context']
+        end
+        # auto suffix with texinputs as fall back
+        if ENV["_CTX_K_V_#{original}_"] then
+            resolved = ENV["_CTX_K_V_#{original}_"]
+            report("environment provides #{original} as #{resolved}") unless $report
+            quoted(resolved)
+        else
+            check_kpse
+            pstrings.each do |pstr|
+                if resolved.empty? then
+                    # command = "kpsewhich #{pstr} #{original}"
+                    # report("running #{command}")
+                    report("locating '#{original}' in program space '#{pstr}'")
+                    begin
+                        # resolved = `#{command}`.chomp
+                        $kpse.progname = pstr
+                        $kpse.format = ''
+                        resolved = $kpse.find_file(original).gsub(/\\/,'/')
+                    rescue
+                        resolved = ''
+                    end
+                end
+                # elsewhere in the tree
+                if resolved.empty? then
+                    # command = "kpsewhich #{pstr} -format=\"other text files\" #{original}"
+                    # report("running #{command}")
+                    report("locating '#{original}' in program space '#{pstr}' using format 'other text files'")
+                    begin
+                        # resolved = `#{command}`.chomp
+                        $kpse.progname = pstr
+                        $kpse.format = 'other text files'
+                        resolved = $kpse.find_file(original).gsub(/\\/,'/')
+                    rescue
+                        resolved = ''
+                    end
+                end
+            end
+            if resolved.empty? then
+                original = File.dirname(original) if method =~ /path/
+                report("#{original} is not resolved") unless $report
+                ENV["_CTX_K_V_#{original}_"] = original if $crossover
+                quoted(original)
+            else
+                resolved = File.dirname(resolved) if method =~ /path/
+                report("#{original} is resolved to #{resolved}") unless $report
+                ENV["_CTX_K_V_#{original}_"] = resolved if $crossover
+                quoted(resolved)
+            end
+        end
+    end
+end
+
+def changeddir?(path)
+    if path.empty? then
+        return true
+    else
+        oldpath = File.expand_path(path)
+        begin
+            Dir.chdir(path) if not path.empty?
+        rescue
+            report("unable to change to directory: #{path}")
+        else
+            report("changed to directory: #{path}")
+        end
+        newpath = File.expand_path(Dir.getwd)
+        return oldpath == newpath
+    end
+end
+
+def runcommand(command)
+    if $locate then
+        command = command.split(' ').collect do |c|
+            if c =~ /\//o then
+                begin
+                    cc = File.expand_path(c)
+                    c = cc if FileTest.file?(cc)
+                rescue
+                end
+            end
+            c
+        end . join(' ')
+        print command # to stdout and no newline
+    elsif $execute then
+        report("using 'exec' instead of 'system' call: #{command}")
+        exec(command) if changeddir?($path)
+    else
+        report("using 'system' call: #{command}")
+        system(command) if changeddir?($path)
+    end
+end
+
+def join_command(args)
+    args[0] = $runners[args[0]] || args[0]
+    [args].join(' ')
+end
+
+def runoneof(application,fullname,browserpermitted)
+    if browserpermitted && launch(fullname) then
+        return true
+    else
+        fullname = quoted(fullname) # added because MM ran into problems
+        report("starting #{$filename}") unless $report
+        output("\n") if $report && $verbose
+        applications = $applications[application.downcase]
+        if ! applications then
+            output("problems with determining application type")
+            return true
+        elsif applications.class == Array then
+            if $report then
+                output(join_command([fullname,expanded($arguments)]))
+                return true
+            else
+                applications.each do |a|
+                    return true if runcommand(join_command([a,fullname,expanded($arguments)]))
+                end
+            end
+        elsif applications.empty? then
+            if $report then
+                output(join_command([fullname,expanded($arguments)]))
+                return true
+            else
+                return runcommand(join_command([fullname,expanded($arguments)]))
+            end
+        else
+            if $report then
+                output(join_command([applications,fullname,expanded($arguments)]))
+                return true
+            else
+                return runcommand(join_command([applications,fullname,expanded($arguments)]))
+            end
+        end
+        return false
+    end
+end
+
+def report(str)
+    $stdout.puts(str) if $verbose
+end
+
+def output(str)
+    $stdout.puts(str)
+end
+
+def usage
+    print "version  : #{$version} - 2003/2006 - www.pragma-ade.com\n"
+    print("\n")
+    print("usage    : texmfstart [switches] filename [optional arguments]\n")
+    print("\n")
+    print("switches : --verbose --report --browser --direct --execute --locate --iftouched --ifchanged\n")
+    print("           --program --file --page --arguments --batch --edit --report --clear\n")
+    print("           --make --lmake --wmake --path --stubpath --indirect --before --after\n")
+    print("           --tree --autotree --environment --showenv\n")
+    print("\n")
+    print("example  : texmfstart pstopdf.rb cow.eps\n")
+    print("           texmfstart --locate examplex.rb\n")
+    print("           texmfstart --execute examplex.rb\n")
+    print("           texmfstart --browser examplap.pdf\n")
+    print("           texmfstart showcase.pdf\n")
+    print("           texmfstart --page=2 --file=showcase.pdf\n")
+    print("           texmfstart --program=yourtex yourscript.rb arg-1 arg-2\n")
+    print("           texmfstart --direct xsltproc kpse:somefile.xsl somefile.xml\n")
+    print("           texmfstart --direct ruby rel:wn-cleanup-1.rb oldfile.xml newfile.xml\n")
+    print("           texmfstart bin:xsltproc env:somepreset path:somefile.xsl somefile.xml\n")
+    print("           texmfstart --iftouched=normal,lowres downsample.rb normal lowres\n")
+    print("           texmfstart --ifchanged=somefile.dat --direct processit somefile.dat\n")
+    print("           texmfstart bin:scite kpse:texmf.cnf\n")
+    print("           texmfstart --exec bin:scite *.tex\n")
+    print("           texmfstart --edit texmf.cnf\n")
+    print("           texmfstart --edit kpse:texmf.cnf\n")
+    print("           texmfstart --serve\n")
+    print("\n")
+    print("           texmfstart --stubpath=/usr/local/bin [--make --remove] --verbose all\n")
+    print("           texmfstart --stubpath=auto [--make --remove] all\n")
+    print("\n")
+    check_kpse
+end
+
+# somehow registration does not work out (at least not under windows)
+# the . is also not accepted by unix as seperator
+
+def tag(name)
+    if $crossover then "_CTX_K_S_#{name}_" else "TEXMFSTART.#{name}" end
+end
+
+def registered?(filename)
+    return ENV[tag(filename)] != nil
+end
+
+def registered(filename)
+    return ENV[tag(filename)] || 'unknown'
+end
+
+def register(filename,fullname)
+    if fullname && ! fullname.empty? then # && FileTest.file?(fullname)
+        ENV[tag(filename)] = fullname
+        report("registering '#{filename}' as '#{fullname}'")
+        return true
+    else
+        return false
+    end
+end
+
+def find(filename,program)
+    begin
+        filename = filename.sub(/script:/o, '') # so we have bin: and script: and nothing
+        if $predefined.key?(filename) then
+            report("expanding '#{filename}' to '#{$predefined[filename]}'")
+            filename = $predefined[filename]
+        end
+        if registered?(filename) then
+            report("already located '#{filename}'")
+            return registered(filename)
+        end
+        # create suffix list
+        if filename =~ /^(.*)\.(.+)$/ then
+            filename = $1
+            suffixlist = [$2]
+        else
+            suffixlist = [$scriptlist.split('|'),$documentlist.split('|')].flatten
+        end
+        # first we honor a given path
+        if filename =~ /[\\\/]/ then
+            report("trying to honor '#{filename}'")
+            suffixlist.each do |suffix|
+                fullname = filename+'.'+suffix
+                if FileTest.file?(fullname) && register(filename,fullname)
+                    return shortpathname(fullname)
+                end
+            end
+        end
+        filename.sub!(/^.*[\\\/]/, '')
+        # next we look at the current path and the callerpath
+        pathlist = [ ]
+        progpath = $applications[suffixlist[0]]
+        threadok = registered("THREAD") !~ /unknown/
+        pathlist << ['.','current']
+        pathlist << [$ownpath,'caller']                                 if $ownpath != '.'
+        pathlist << ["#{$ownpath}/../#{progpath}",'caller']             if progpath
+        pathlist << [registered("THREAD"),'thread']                     if threadok
+        pathlist << ["#{registered("THREAD")}/../#{progpath}",'thread'] if progpath && threadok
+        pathlist.each do |p|
+            if p && ! p.empty? && ! (p[0] == 'unknown') then
+                suffixlist.each do |suffix|
+                    fname = "#{filename}.#{suffix}"
+                    fullname = File.expand_path(File.join(p[0],fname))
+                    report("locating '#{fname}' in #{p[1]} path '#{p[0]}'")
+                    if FileTest.file?(fullname) && register(filename,fullname) then
+                        report("'#{fname}' located in #{p[1]} path")
+                        return shortpathname(fullname)
+                    end
+                end
+            end
+        end
+        # now we consult environment settings
+        fullname = nil
+        check_kpse
+        $kpse.progname = program
+        suffixlist.each do |suffix|
+            begin
+                break unless $suffixinputs[suffix]
+                environment = ENV[$suffixinputs[suffix]] || ENV[$suffixinputs[suffix]+".#{$program}"]
+                if ! environment || environment.empty? then
+                    begin
+                        # environment = `kpsewhich -expand-path=\$#{$suffixinputs[suffix]}`.chomp
+                        environment = $kpse.expand_path("\$#{$suffixinputs[suffix]}")
+                    rescue
+                        environment = nil
+                    else
+                        if environment && ! environment.empty? then
+                            report("using kpsewhich variable #{$suffixinputs[suffix]}")
+                        end
+                    end
+                elsif environment && ! environment.empty? then
+                    report("using environment variable #{$suffixinputs[suffix]}")
+                end
+                if environment && ! environment.empty? then
+                    environment.split($separator).each do |e|
+                        e.strip!
+                        e = '.' if e == '\.' # somehow . gets escaped
+                        e += '/' unless e =~ /[\\\/]$/
+                        fullname = e + filename + '.' + suffix
+                        report("testing '#{fullname}'")
+                        if FileTest.file?(fullname) then
+                            break
+                        else
+                            fullname = nil
+                        end
+                    end
+                end
+            rescue
+                report("environment string '#{$suffixinputs[suffix]}' cannot be used to locate '#{filename}'")
+                fullname = nil
+            else
+                return shortpathname(fullname) if register(filename,fullname)
+            end
+        end
+        return shortpathname(fullname) if register(filename,fullname)
+        # then we fall back on kpsewhich
+        suffixlist.each do |suffix|
+            # TDS script scripts location as per 2004
+            if suffix =~ /(#{$scriptlist})/ then
+                begin
+                    report("using 'kpsewhich' to locate '#{filename}' in suffix space '#{suffix}' (1)")
+                    # fullname = `kpsewhich -progname=#{program} -format=texmfscripts #{filename}.#{suffix}`.chomp
+                    $kpse.format = 'texmfscripts'
+                    fullname = $kpse.find_file("#{filename}.#{suffix}").gsub(/\\/,'/')
+                rescue
+                    report("kpsewhich cannot locate '#{filename}' in suffix space '#{suffix}' (1)")
+                    fullname = nil
+                else
+                    return shortpathname(fullname) if register(filename,fullname)
+                end
+            end
+            # old TDS location: .../texmf/context/...
+            begin
+                report("using 'kpsewhich' to locate '#{filename}' in suffix space '#{suffix}' (2)")
+                # fullname = `kpsewhich -progname=#{program} -format="other text files" #{filename}.#{suffix}`.chomp
+                $kpse.format = 'other text files'
+                fullname = $kpse.find_file("#{filename}.#{suffix}").gsub(/\\/,'/')
+            rescue
+                report("kpsewhich cannot locate '#{filename}' in suffix space '#{suffix}' (2)")
+                fullname = nil
+            else
+                return shortpathname(fullname) if register(filename,fullname)
+            end
+        end
+        return shortpathname(fullname) if register(filename,fullname)
+        # let's take a look at the path
+        paths = ENV['PATH'].split($separator)
+        suffixlist.each do |s|
+            paths.each do |p|
+                suffixedname = "#{filename}.#{s}"
+                report("checking #{p} for #{filename}")
+                if FileTest.file?(File.join(p,suffixedname)) then
+                    fullname = File.join(p,suffixedname)
+                    return  shortpathname(fullname) if register(filename,fullname)
+                end
+            end
+        end
+        # bad luck, we need to search the tree ourselves
+        if (suffixlist.length == 1) && (suffixlist.first =~ /(#{$documentlist})/) then
+            report("aggressively locating '#{filename}' in document trees")
+            begin
+                # texroot = `kpsewhich -expand-var=$SELFAUTOPARENT`.chomp
+                texroot = $kpse.expand_var("$SELFAUTOPARENT")
+            rescue
+                texroot = ''
+            else
+                texroot.sub!(/[\\\/][^\\\/]*?$/, '')
+            end
+            if not texroot.empty? then
+                sffxlst = suffixlist.join(',')
+                begin
+                    report("locating '#{filename}' in document tree '#{texroot}/doc*'")
+                    if (result = Dir.glob("#{texroot}/doc*/**/#{filename}.{#{sffxlst}}")) && result && result[0] && FileTest.file?(result[0]) then
+                        fullname = result[0]
+                    end
+                rescue
+                    report("locating '#{filename}.#{suffixlist.join('|')}' in tree '#{texroot}' aborted")
+                end
+            end
+            return shortpathname(fullname) if register(filename,fullname)
+        end
+        report("aggressively locating '#{filename}' in tex trees")
+        begin
+            # textrees = `kpsewhich -expand-var=$TEXMF`.chomp
+            textrees = $kpse.expand_var("$TEXMF")
+        rescue
+            textrees = ''
+        end
+        if not textrees.empty? then
+            textrees.gsub!(/[\{\}\!]/, '')
+            textrees = textrees.split(',')
+            if (suffixlist.length == 1) && (suffixlist.first =~ /(#{$documentlist})/) then
+                speedup = ['doc**','**']
+            else
+                speedup = ['**']
+            end
+            sffxlst = suffixlist.join(',')
+            speedup.each do |speed|
+                textrees.each do |tt|
+                    tt.gsub!(/[\\\/]$/, '')
+                    if FileTest.directory?(tt) then
+                        begin
+                            report("locating '#{filename}' in tree '#{tt}/#{speed}/#{filename}.{#{sffxlst}}'")
+                            if (result = Dir.glob("#{tt}/#{speed}/#{filename}.{#{sffxlst}}")) && result && result[0] && FileTest.file?(result[0]) then
+                                fullname = result[0]
+                                break
+                            end
+                        rescue
+                            report("locating '#{filename}' in tree '#{tt}' aborted")
+                            next
+                        end
+                    end
+                end
+                break if fullname && ! fullname.empty?
+            end
+        end
+        if register(filename,fullname) then
+            return shortpathname(fullname)
+        else
+            return ''
+        end
+    rescue
+        error, trace = $!, $@.join("\n")
+        report("fatal error: #{error}\n#{trace}")
+        # report("fatal error")
+    end
+end
+
+def run(fullname)
+    if ! fullname || fullname.empty? then
+        output("the file '#{$filename}' is not found")
+    elsif FileTest.file?(fullname) then
+        begin
+            case fullname
+                when /\.(#{$scriptlist})$/i then
+                    return runoneof($1,fullname,false)
+                when /\.(#{$documentlist})$/i then
+                    return runoneof($1,fullname,true)
+                else
+                    return runoneof('unknown',fullname,false)
+            end
+        rescue
+            report("starting '#{$filename}' in program space '#{$program}' fails (#{$!})")
+        end
+    else
+        report("the file '#{$filename}' in program space '#{$program}' is not accessible")
+    end
+    return false
+end
+
+def direct(fullname)
+    begin
+        return runcommand([fullname.sub(/^(bin|binary)\:/, ''),expanded($arguments)].join(' '))
+    rescue
+        return false
+    end
+end
+
+def edit(filename)
+    begin
+        return runcommand([$editor,expanded(filename),expanded($arguments)].join(' '))
+    rescue
+        return false
+    end
+end
+
+def make(filename,windows=false,linux=false,remove=false)
+    basename = File.basename(filename).gsub(/\.[^.]+?$/, '')
+    if $stubpath == 'auto' then
+        basename = File.dirname($0) + '/' + basename
+    else
+        basename = $stubpath + '/' + basename unless $stubpath.empty?
+    end
+    if filename == 'texmfstart' then
+        program = 'ruby'
+        command = 'kpsewhich --format=texmfscripts --progname=context texmfstart.rb'
+        filename = `#{command}`.chomp.gsub(/\\/, '/')
+        if filename.empty? then
+            report("failure: #{command}")
+            return
+        elsif not remove then
+            if windows then
+                ['bat','cmd','exe'].each do |suffix|
+                    if FileTest.file?("#{basename}.#{suffix}") then
+                        report("windows stub '#{basename}.#{suffix}' skipped (already present)")
+                        return
+                    end
+                end
+            elsif linux && FileTest.file?(basename) then
+                report("unix stub '#{basename}' skipped (already present)")
+                return
+            end
+        end
+    else
+        program = nil
+        if filename =~ /[\\\/]/ && filename =~ /\.(#{$scriptlist})$/ then
+            program = $applications[$1]
+        end
+        filename = "\"#{filename}\"" if filename =~ /\s/
+        program = 'texmfstart' if $indirect || ! program || program.empty?
+    end
+    begin
+        callname = $predefined[filename.sub(/\.*?$/,'')] || filename
+        if remove then
+            if windows && (File.delete(basename+'.bat') rescue false) then
+                report("windows stub '#{basename}.bat' removed (calls #{callname})")
+            elsif linux && (File.delete(basename) rescue false) then
+                report("unix stub '#{basename}' removed (calls #{callname})")
+            end
+        else
+            if windows && f = open(basename+'.bat','w') then
+                f.binmode
+                f.write("@echo off\015\012")
+                f.write("#{program} #{callname} %*\015\012")
+                f.close
+                report("windows stub '#{basename}.bat' made (calls #{callname})")
+            elsif linux && f = open(basename,'w') then
+                f.binmode
+                f.write("#!/bin/sh\012")
+                f.write("#{program} #{callname} \"$@\"\012")
+                f.close
+                report("unix stub '#{basename}' made (calls #{callname})")
+            end
+        end
+    rescue
+        report("failed to make stub '#{basename}' #{$!}")
+        return false
+    else
+        return true
+    end
+end
+
+def process(&block)
+    if $iftouched then
+        files = $directives['iftouched'].split(',')
+        oldname, newname = files[0], files[1]
+        if oldname && newname && File.needsupdate(oldname,newname) then
+            report("file #{oldname}: #{File.timestamp(oldname)}")
+            report("file #{newname}: #{File.timestamp(newname)}")
+            report("file is touched, processing started")
+            yield
+            File.syncmtimes(oldname,newname)
+        else
+            report("file #{oldname} is untouched")
+        end
+    elsif $ifchanged then
+        filename = $directives['ifchanged']
+        checkname = filename + ".md5"
+        oldchecksum, newchecksum = "old", "new"
+        begin
+            newchecksum = Digest::MD5.hexdigest(IO.read(filename)).upcase
+        rescue
+            newchecksum = "new"
+        else
+            begin
+                oldchecksum = IO.read(checkname).chomp
+            rescue
+                oldchecksum = "old"
+            end
+        end
+        if $verbose then
+            report("old checksum #{filename}: #{oldchecksum}")
+            report("new checksum #{filename}: #{newchecksum}")
+        end
+        if oldchecksum != newchecksum then
+            report("file is changed, processing started")
+            begin
+                File.open(checkname,'w') do |f|
+                    f << newchecksum
+                end
+            rescue
+            end
+            yield
+        else
+            report("file #{filename} is unchanged")
+        end
+    else
+        yield
+    end
+end
+
+def checkenvironment(tree)
+    report('')
+    ENV['TMP'] = ENV['TMP'] || ENV['TEMP'] || ENV['TMPDIR'] || ENV['HOME']
+    case RUBY_PLATFORM
+        when /(mswin|bccwin|mingw|cygwin)/i then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-mswin'
+        when /(linux)/i                     then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-linux'
+        when /(darwin|rhapsody|nextstep)/i  then ENV['TEXOS'] = ENV['TEXOS'] || 'texmf-macosx'
+    #   when /(netbsd|unix)/i               then # todo
+        else                                     # todo
+    end
+    ENV['TEXOS']   = "#{ENV['TEXOS'].sub(/^[\\\/]*/, '').sub(/[\\\/]*$/, '')}"
+    ENV['TEXPATH'] = tree.sub(/\/+$/,'') # + '/'
+    ENV['TEXMFOS'] = "#{ENV['TEXPATH']}/#{ENV['TEXOS']}"
+    report('')
+    report("preset : TEXPATH => #{ENV['TEXPATH']}")
+    report("preset : TEXOS   => #{ENV['TEXOS']}")
+    report("preset : TEXMFOS => #{ENV['TEXMFOS']}")
+    report("preset : TMP => #{ENV['TMP']}")
+    report('')
+end
+
+def loadfile(filename)
+    begin
+        IO.readlines(filename).each do |line|
+            case line.chomp
+                when /^[\#\%]/ then
+                    # comment
+                when /^(.*?)\s*(\>|\=|\<)\s*(.*)\s*$/ then
+                    # = assign | > prepend | < append
+                    key, how, value = $1, $2, $3
+                    begin
+                        # $SAFE = 0
+                        value.gsub!(/\%(.*?)\%/) do
+                            ENV[$1] || ''
+                        end
+                        # value.gsub!(/\;/,$separator) if key =~ /PATH/i then
+                        case how
+                            when '=', '<<' then ENV[key] = value
+                            when '?', '??' then ENV[key] = ENV[key] || value
+                            when '<', '+=' then ENV[key] = (ENV[key] || '') + $separator + value
+                            when '>', '=+' then ENV[key] = value + $separator + (ENV[key] ||'')
+                        end
+                    rescue
+                        report("user set failed : #{key} (#{$!})")
+                    else
+                        report("user set : #{key} => #{ENV[key]}")
+                    end
+            end
+        end
+    rescue
+        report("error in reading file '#{filename}'")
+    end
+end
+
+def loadtree(tree)
+    begin
+        unless tree.empty? then
+            if File.directory?(tree) then
+                setuptex = File.join(tree,'setuptex.tmf')
+            else
+                setuptex = tree.dup
+            end
+            if FileTest.file?(setuptex) then
+                report("tex tree definition: #{setuptex}")
+                checkenvironment(File.dirname(setuptex))
+                loadfile(setuptex)
+            else
+                report("no setup file '#{setuptex}'")
+            end
+        end
+    rescue
+        # maybe tree is empty or boolean (no arg given)
+    end
+end
+
+def loadenvironment(environment)
+    begin
+        unless environment.empty? then
+            filename = if $path.empty? then environment else File.expand_path(File.join($path,environment)) end
+            if FileTest.file?(filename) then
+                report("environment : #{environment}")
+                loadfile(filename)
+            else
+                report("no environment file '#{environment}'")
+            end
+        end
+    rescue
+        report("problem while loading '#{environment}'")
+    end
+end
+
+def show_environment
+    if $showenv then
+        keys = ENV.keys.sort
+        size = 0
+        keys.each do |k|
+            size = k.size if k.size > size
+        end
+        report('')
+        keys.each do |k|
+            report("#{k.rjust(size)} => #{ENV[k]}")
+        end
+        report('')
+    end
+end
+
+def execute(arguments) # br global
+
+    arguments = arguments.split(/\s+/) if arguments.class == String
+    $directives = hashed(arguments)
+
+    $help        = $directives['help']        || false
+    $batch       = $directives['batch']       || false
+    $filename    = $directives['file']        || ''
+    $program     = $directives['program']     || 'context'
+    $direct      = $directives['direct']      || false
+    $edit        = $directives['edit']        || false
+    $page        = $directives['page']        || 1
+    $browser     = $directives['browser']     || false
+    $report      = $directives['report']      || false
+    $verbose     = $directives['verbose']     || false
+    $arguments   = $directives['arguments']   || ''
+    $execute     = $directives['execute']     || $directives['exec'] || false
+    $locate      = $directives['locate']      || false
+
+    $autotree    = if $directives['autotree'] then (ENV['TEXMFSTART_TREE'] || ENV['TEXMFSTARTTREE'] || '') else '' end
+
+    $path        = $directives['path']        || ''
+    $tree        = $directives['tree']        || $autotree || ''
+    $environment = $directives['environment'] || ''
+
+    $make        = $directives['make']        || false
+    $remove      = $directives['remove']      || $directives['delete'] || false
+    $unix        = $directives['unix']        || false
+    $windows     = $directives['windows']     || $directives['mswin'] || false
+    $stubpath    = $directives['stubpath']    || ''
+    $indirect    = $directives['indirect']    || false
+
+    $before      = $directives['before']      || ''
+    $after       = $directives['after']       || ''
+
+    $iftouched   = $directives['iftouched']   || false
+    $ifchanged   = $directives['ifchanged']   || false
+
+    $openoffice  = $directives['oo']          || false
+
+    $crossover   = false if $directives['clear']
+
+    $showenv     = $directives['showenv']     || false
+    $verbose     = true if $showenv
+
+    $serve       = $directives['serve']       || false
+
+    $verbose = true if (ENV['_CTX_VERBOSE_'] =~ /(y|yes|t|true|on)/io) && ! $locate && ! $report
+
+    set_applications($page)
+
+    # private:
+
+    $selfmerge   = $directives['selfmerge'] || false
+    $selfcleanup = $directives['selfclean'] || $directives['selfcleanup'] || false
+
+    ENV['_CTX_VERBOSE_'] = 'yes' if $verbose
+
+    if $openoffice then
+        if ENV['OOPATH'] then
+            if FileTest.directory?(ENV['OOPATH']) then
+                report("using open office python")
+                if $mswindows then
+                    $applications['python'] = $applications['py']  = "\"#{File.join(ENV['OOPATH'],'program','python.bat')}\""
+                else
+                    $applications['python'] = $applications['py']  = File.join(ENV['OOPATH'],'python')
+                end
+                report("python path #{$applications['python']}")
+            else
+                report("environment variable 'OOPATH' does not exist")
+            end
+        else
+            report("environment variable 'OOPATH' is not set")
+        end
+    end
+
+    if $selfmerge then
+        output("ruby libraries are cleaned up") if SelfMerge::cleanup
+        output("ruby libraries are merged")     if SelfMerge::merge
+        return true
+    elsif $selfcleanup then
+        output("ruby libraries are cleaned up") if SelfMerge::cleanup
+        return true
+    elsif $help || ! $filename || $filename.empty? then
+        usage
+        loadtree($tree)
+        loadenvironment($environment)
+        show_environment()
+        return true
+    elsif $batch && $filename && ! $filename.empty? then
+        # todo, take commands from file and avoid multiple starts and checks
+        return false
+    else
+        report("texmfstart version #{$version}")
+        loadtree($tree)
+        loadenvironment($environment)
+        show_environment()
+        if $make || $remove then
+            if $filename == 'all' then
+                makelist = $makelist
+            else
+                makelist = [$filename]
+            end
+            makelist.each do |filename|
+                if $windows then
+                    make(filename,true,false,$remove)
+                elsif $unix then
+                    make(filename,false,true,$remove)
+                else
+                    make(filename,$mswindows,!$mswindows,$remove)
+                end
+            end
+            return true # guess
+        elsif $browser && $filename =~ /^http\:\/\// then
+            return launch($filename)
+        else
+            begin
+                process do
+                    if $direct || $filename =~ /^bin\:/ then
+                        return direct($filename)
+                    elsif $edit && ! $editor.empty? then
+                        return edit($filename)
+                    else # script: or no prefix
+                        command = find(shortpathname($filename),$program)
+                        if command then
+                            register("THREAD",File.dirname(File.expand_path(command)))
+                            return run(command)
+                        else
+                            report('unable to locate program')
+                            return false
+                        end
+                    end
+                end
+            rescue
+                report('fatal error in starting process')
+                return false
+            end
+        end
+    end
+
+end
+
+if execute(ARGV) then
+    report("\nexecution was successful") if $verbose
+    exit(0)
+else
+    report("\nexecution failed") if $verbose
+    exit(1)
+end


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/texmfstart.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/textools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/textools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/textools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,1033 @@
+#!/usr/bin/env ruby
+
+# program   : textools
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2002-2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt / eXaMpLe
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+
+# This script will harbor some handy manipulations on tex
+# related files.
+
+banner = ['TeXTools', 'version 1.3.1', '2002/2006', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'base/switch'
+require 'base/logger'
+
+require 'fileutils'
+# require 'ftools'
+
+# Remark
+#
+# The fixtexmftrees feature does not realy belong in textools, but
+# since it looks like no measures will be taken to make texlive (and
+# tetex) downward compatible with respect to fonts installed by
+# users, we provide this fixer. This option also moves script files
+# to their new location (only for context) in the TDS. Beware: when
+# locating  scripts, the --format switch in kpsewhich should now use
+# 'texmfscripts' instead of  'other text files' (texmfstart is already
+# aware of this). Files will only be moved when --force is given. Let
+# me know if more fixes need to be made.
+
+class Commands
+
+    include CommandBase
+
+    def tpmmake
+        if filename = @commandline.argument('first') then
+            filename = File.join('tpm',filename) unless filename =~ /^tpm[\/\\]/
+            filename += '.tpm' unless filename =~ /\.tpm$/
+            if FileTest.file?(filename) then
+                data = IO.read(filename) rescue ''
+                data, fn, n = calculate_tpm(data,"TPM:RunFiles")
+                data, fm, m = calculate_tpm(data,"TPM:DocFiles")
+                data = replace_tpm(data,"TPM:Size",n+m)
+                report("total size #{n+m}")
+                begin
+                    File.open(filename, 'w') do |f|
+                        f << data
+                    end
+                rescue
+                    report("unable to save '#{filename}'")
+                else
+                    report("file '#{filename}' is updated")
+                    filename = File.basename(filename).sub(/\..*$/,'')
+                    zipname = sprintf("%s-%04i.%02i.%02i%s",filename,Time.now.year,Time.now.month,Time.now.day,'.zip')
+                    File.delete(zipname) rescue true
+                    report("zipping file '#{zipname}'")
+                    system("zip -r -9 -q #{zipname} #{[fn,fm].flatten.join(' ')}")
+                end
+            else
+                report("no file '#{filename}'")
+            end
+        end
+    end
+
+    def calculate_tpm(data, tag='')
+        size, ok = 0, Array.new
+        data.gsub!(/<#{tag}.*>(.*?)<\/#{tag}>/m) do
+            content = $1
+            files = content.split(/\s+/)
+            files.each do |file|
+                unless file =~ /^\s*$/ then
+                    if FileTest.file?(file) then
+                        report("found file #{file}")
+                        size += FileTest.size(file) rescue 0
+                        ok << file
+                    else
+                        report("missing file #{file}")
+                    end
+                end
+            end
+            "<#{tag} size=\"#{size}\">#{content}</#{tag}>"
+        end
+        [data, ok, size]
+    end
+
+    def replace_tpm(data, tag='', txt='')
+        data.gsub(/(<#{tag}.*>)(.*?)(<\/#{tag}>)/m) do
+            $1 + txt.to_s + $3
+        end
+    end
+
+end
+
+class Commands
+
+    include CommandBase
+
+    def hidemapnames
+        report('hiding FontNames in map files')
+        xidemapnames(true)
+    end
+
+    def videmapnames
+        report('unhiding FontNames in map files')
+        xidemapnames(false)
+    end
+
+    def removemapnames
+
+        report('removing FontNames from map files')
+
+        if files = findfiles('map') then
+            report
+            files.sort.each do |fn|
+                gn = fn # + '.nonames'
+                hn = fn + '.original'
+                begin
+                    if FileTest.file?(fn) && ! FileTest.file?(hn) then
+                        if File.rename(fn,hn) then
+                            if (fh = File.open(hn,'r')) && (gh = File.open(gn,'w')) then
+                                report("processing #{fn}")
+                                while str = fh.gets do
+                                    str.sub!(/^([^\%]+?)(\s+)([^\"\<\s]*?)(\s)/) do
+                                        $1 + $2 + " "*$3.length + $4
+                                    end
+                                    gh.puts(str)
+                                end
+                                fh.close
+                                gh.close
+                            else
+                                report("no permissions to handle #{fn}")
+                            end
+                        else
+                            report("unable to rename #{fn} to #{hn}")
+                        end
+                    else
+                        report("not processing #{fn} due to presence of #{hn}")
+                    end
+                rescue
+                    report("error in handling #{fn}")
+                end
+            end
+        end
+
+    end
+
+    def restoremapnames
+
+        report('restoring FontNames in map files')
+
+        if files = findfiles('map') then
+            report
+            files.sort.each do |fn|
+                hn = fn + '.original'
+                begin
+                    if FileTest.file?(hn) then
+                        File.delete(fn) if FileTest.file?(fn)
+                        report("#{fn} restored") if File.rename(hn,fn)
+                    else
+                        report("no original found for #{fn}")
+                    end
+                rescue
+                    report("error in restoring #{fn}")
+                end
+            end
+        end
+
+    end
+
+    def findfile
+
+        report('locating file in texmf tree')
+
+        # ! not in tree
+        # ? fuzzy
+        # . in tree
+        # > in tree and used
+
+        if filename = @commandline.argument('first') then
+            if filename && ! filename.empty? then
+                report
+                used = kpsefile(filename) || pathfile(filename)
+                if paths = texmfroots then
+                    found, prefered = false, false
+                    paths.each do |p|
+                        if files = texmffiles(p,filename) then
+                            found = true
+                            files.each do |f|
+                                # unreadable: report("#{if f == used then '>' else '.' end} #{f}")
+                                if f == used then
+                                    prefered = true
+                                    report("> #{f}")
+                                else
+                                    report(". #{f}")
+                                end
+                            end
+                        end
+                    end
+                    if prefered then
+                        report("! #{used}") unless found
+                    else
+                        report("> #{used}")
+                    end
+                elsif used then
+                    report("? #{used}")
+                else
+                    report('no file found')
+                end
+            else
+                report('no file specified')
+            end
+        else
+            report('no file specified')
+        end
+
+    end
+
+    def unzipfiles
+
+        report('g-unzipping files')
+
+        if files = findfiles('gz') then
+            report
+            files.each do |f|
+                begin
+                    system("gunzip -d #{f}")
+                rescue
+                    report("unable to unzip file #{f}")
+                else
+                    report("file #{f} is unzipped")
+                end
+            end
+        end
+
+    end
+
+    def fixafmfiles
+
+        report('fixing afm files')
+
+        if files = findfiles('afm') then
+            report
+            ok = false
+            files.each do |filename|
+                if filename =~ /\.afm$/io then
+                    if f = File.open(filename) then
+                        result = ''
+                        done = false
+                        while str = f.gets do
+                            str.chomp!
+                            str.strip!
+                            if str.empty? then
+                                # skip
+                            elsif (str.length > 200) && (str =~ /^(comment|notice)\s(.*)\s*$/io) then
+                                done = true
+                                tag, words, len = $1, $2.split(' '), 0
+                                result += tag
+                                while words.size > 0 do
+                                    str = words.shift
+                                    len += str.length + 1
+                                    result += ' ' + str
+                                    if len > (70 - tag.length) then
+                                        result += "\n"
+                                        result += tag if words.size > 0
+                                        len = 0
+                                    end
+                                end
+                                result += "\n" if len>0
+                            else
+                                result += str + "\n"
+                            end
+                        end
+                        f.close
+                        if done then
+                            ok = true
+                            begin
+                                if File.rename(filename,filename+'.original') then
+                                    if FileTest.file?(filename) then
+                                        report("something to fix in #{filename} but error in renaming (3)")
+                                    elsif f = File.open(filename,'w') then
+                                        f.puts(result)
+                                        f.close
+                                        report('file', filename, 'has been fixed')
+                                    else
+                                        report("something to fix in #{filename} but error in opening (4)")
+                                        File.rename(filename+'.original',filename) # gamble
+                                    end
+                                else
+                                    report("something to fix in #{filename} but error in renaming (2)")
+                                end
+                            rescue
+                                report("something to fix in #{filename} but error in renaming (1)")
+                            end
+                        else
+                            report("nothing to fix in #{filename}")
+                        end
+                    else
+                        report("error in opening #{filename}")
+                    end
+                end
+            end
+            report('no files match the pattern') unless ok
+        end
+
+    end
+
+    def mactodos
+
+        report('fixing mac newlines')
+
+        if files = findfiles('tex') then
+            report
+            files.each do |filename|
+                begin
+                    report("converting file #{filename}")
+                    tmpfilename = filename + '.tmp'
+                    if f = File.open(filename) then
+                        if g = File.open(tmpfilename, 'w')
+                            while str = f.gets do
+                                g.puts(str.gsub(/\r/,"\n"))
+                            end
+                            if f.close && g.close && FileTest.file?(tmpfilename) then
+                                File.delete(filename)
+                                File.rename(tmpfilename,filename)
+                            end
+                        else
+                            report("unable to open temporary file #{tmpfilename}")
+                        end
+                    else
+                        report("unable to open #{filename}")
+                    end
+                rescue
+                    report("problems with fixing #{filename}")
+                end
+            end
+        end
+
+    end
+
+    def fixtexmftrees
+
+        if paths = @commandline.argument('first') then
+            paths = [paths] if ! paths.empty?
+        end
+        paths = texmfroots if paths.empty?
+
+        if paths then
+
+            moved = 0
+            force = @commandline.option('force')
+
+            report
+            report("checking TDS 2003 => TDS 2004 : map files")
+            # report
+
+            # move [map,enc]  files from /texmf/[dvips,pdftex,dvipdfmx] -> /texmf/fonts/[*]
+
+            ['map','enc'].each do |suffix|
+                paths.each do |path|
+                    ['dvips','pdftex','dvipdfmx'].each do |program|
+                        report
+                        report("checking #{suffix} files for #{program} on #{path}")
+                        report
+                        moved += movefiles("#{path}/#{program}","#{path}/fonts/#{suffix}/#{program}",suffix) do
+                            # nothing
+                        end
+                    end
+                end
+            end
+
+            report
+            report("checking TDS 2003 => TDS 2004 : scripts")
+            # report
+
+            # move [rb,pl,py] files from /texmf/someplace -> /texmf/scripts/someplace
+
+            ['rb','pl','py'].each do |suffix|
+                paths.each do |path|
+                    ['context'].each do |program|
+                        report
+                        report("checking #{suffix} files for #{program} on #{path}")
+                        report
+                        moved += movefiles("#{path}/#{program}","#{path}/scripts/#{program}",suffix) do |f|
+                            f.gsub!(/\/(perl|ruby|python)tk\//o) do
+                                "/#{$1}/"
+                            end
+                        end
+                    end
+                end
+            end
+
+            begin
+                if moved>0 then
+                    report
+                    if force then
+                        system('mktexlsr')
+                        report
+                        report("#{moved} files moved")
+                    else
+                        report("#{moved} files will be moved")
+                    end
+                else
+                    report('no files need to be moved')
+                end
+            rescue
+                report('you need to run mktexlsr')
+            end
+
+        end
+
+    end
+
+    def replacefile
+
+        report('replace file')
+
+        if newname = @commandline.argument('first') then
+            if newname && ! newname.empty? then
+                report
+                report("replacing #{newname}")
+                report
+                oldname = kpsefile(File.basename(newname))
+                force = @commandline.option('force')
+                if oldname && ! oldname.empty? then
+                    oldname = File.expand_path(oldname)
+                    newname = File.expand_path(newname)
+                    report("old: #{oldname}")
+                    report("new: #{newname}")
+                    report
+                    if newname == oldname then
+                        report('unable to replace itself')
+                    elsif force then
+                        begin
+                            File.copy(newname,oldname)
+                        rescue
+                            report('error in replacing the old file')
+                        end
+                    else
+                        report('the old file will be replaced (use --force)')
+                    end
+                else
+                    report('nothing to replace')
+                end
+            else
+                report('no file specified')
+            end
+        else
+            report('no file specified')
+        end
+
+    end
+
+    private # general
+
+    def texmfroots
+        begin
+            paths = `kpsewhich -expand-path=\$TEXMF`.chomp
+        rescue
+        else
+            return paths.split(/#{File::PATH_SEPARATOR}/) if paths && ! paths.empty?
+        end
+        return nil
+    end
+
+    def texmffiles(root, filename)
+        begin
+            files = Dir.glob("#{root}/**/#{filename}")
+        rescue
+        else
+            return files if files && files.length>0
+        end
+        return nil
+    end
+
+    def pathfile(filename)
+        used = nil
+        begin
+            if ! filename || filename.empty? then
+                return nil
+            else
+                ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
+                    if FileTest.file?(File.join(path,filename)) then
+                        used = File.join(path,filename)
+                        break
+                    end
+                end
+            end
+        rescue
+            used = nil
+        else
+            used = nil if used && used.empty?
+        end
+        return used
+    end
+
+    def kpsefile(filename)
+        used = nil
+        begin
+            if ! filename || filename.empty? then
+                return nil
+            else
+                used = `kpsewhich #{filename}`.chomp
+            end
+            if used && used.empty? then
+                used = `kpsewhich -progname=context #{filename}`.chomp
+            end
+            if used && used.empty? then
+                used = `kpsewhich -format=texmfscripts #{filename}`.chomp
+            end
+            if used && used.empty? then
+                used = `kpsewhich -progname=context -format=texmfscripts #{filename}`.chomp
+            end
+            if used && used.empty? then
+                used = `kpsewhich -format="other text files" #{filename}`.chomp
+            end
+            if used && used.empty? then
+                used = `kpsewhich -progname=context -format="other text files" #{filename}`.chomp
+            end
+        rescue
+            used = nil
+        else
+            used = nil if used && used.empty?
+        end
+        return used
+    end
+
+    def downcasefilenames
+
+        report('downcase filenames')
+
+        force = @commandline.option('force')
+
+        # if @commandline.option('recurse') then
+            # files = Dir.glob('**/*')
+        # else
+            # files = Dir.glob('*')
+        # end
+        # if files && files.length>0 then
+
+        if files = findfiles() then
+            files.each do |oldname|
+                if FileTest.file?(oldname) then
+                    newname = oldname.downcase
+                    if oldname != newname then
+                        if force then
+                            begin
+                                File.rename(oldname,newname)
+                            rescue
+                                report("#{oldname} == #{oldname}\n")
+                            else
+                                report("#{oldname} => #{newname}\n")
+                            end
+                        else
+                            report("(#{oldname} => #{newname})\n")
+                        end
+                    end
+                end
+            end
+        end
+    end
+
+    def stripformfeeds
+
+        report('strip formfeeds')
+
+        force = @commandline.option('force')
+
+        if files = findfiles() then
+            files.each do |filename|
+                if FileTest.file?(filename) then
+                    begin
+                        data = IO.readlines(filename).join('')
+                    rescue
+                    else
+                        if data.gsub!(/\n*\f\n*/io,"\n\n") then
+                            if force then
+                                if f = open(filename,'w') then
+                                    report("#{filename} is stripped\n")
+                                    f.puts(data)
+                                    f.close
+                                else
+                                    report("#{filename} cannot be stripped\n")
+                                end
+                            else
+                                report("#{filename} will be stripped\n")
+                            end
+                        end
+                    end
+                end
+            end
+        end
+    end
+
+    public
+
+    def showfont
+
+        file = @commandline.argument('first')
+
+        if file.empty? then
+            report('provide filename')
+        else
+            file.sub!(/\.afm$/,'')
+            begin
+                report("analyzing afm file #{file}.afm")
+                file = `kpsewhich #{file}.afm`.chomp
+            rescue
+                report('unable to run kpsewhich')
+                return
+            end
+
+            names = Array.new
+
+            if FileTest.file?(file) then
+                File.new(file).each do |line|
+                    if line.match(/^C\s*([\-\d]+)\s*\;.*?\s*N\s*(.+?)\s*\;/o) then
+                        names.push($2)
+                    end
+                end
+                ranges = names.size
+                report("number of glyphs: #{ranges}")
+                ranges = ranges/256 + 1
+                report("number of subsets: #{ranges}")
+                file = File.basename(file).sub(/\.afm$/,'')
+                tex = File.open("textools.tex",'w')
+                map = File.open("textools.map",'w')
+                tex.puts("\\starttext\n")
+                tex.puts("\\loadmapfile[textools.map]\n")
+                for i in 1..ranges do
+                    rfile = "#{file}-range-#{i}"
+                    report("generating enc file #{rfile}.enc")
+                    flushencoding("#{rfile}", (i-1)*256, i*256-1, names)
+                    # catch console output
+                    report("generating tfm file #{rfile}.tfm")
+                    mapline = `afm2tfm #{file}.afm -T #{rfile}.enc #{rfile}.tfm`
+                    # more robust replacement
+                    mapline = "#{rfile} <#{rfile}.enc <#{file}.pfb"
+                    # final entry in map file
+                    mapline = "#{mapline} <#{file}.pfb"
+                    map.puts("#{mapline}\n")
+                    tex.puts("\\showfont[#{rfile}][unknown]\n")
+                end
+                tex.puts("\\stoptext\n")
+                report("generating map file textools.map")
+                report("generating tex file textools.tex")
+                map.close
+                tex.close
+            else
+                report("invalid file #{file}")
+            end
+        end
+
+    end
+
+    @@knownchars = Hash.new
+
+    @@knownchars['ae'] = 'aeligature' ; @@knownchars['oe'] = 'oeligature'
+    @@knownchars['AE'] = 'AEligature' ; @@knownchars['OE'] = 'OEligature'
+
+    @@knownchars['acute'       ] = 'textacute'
+    @@knownchars['breve'       ] = 'textbreve'
+    @@knownchars['caron'       ] = 'textcaron'
+    @@knownchars['cedilla'     ] = 'textcedilla'
+    @@knownchars['circumflex'  ] = 'textcircumflex'
+    @@knownchars['diaeresis'   ] = 'textdiaeresis'
+    @@knownchars['dotaccent'   ] = 'textdotaccent'
+    @@knownchars['grave'       ] = 'textgrave'
+    @@knownchars['hungarumlaut'] = 'texthungarumlaut'
+    @@knownchars['macron'      ] = 'textmacron'
+    @@knownchars['ogonek'      ] = 'textogonek'
+    @@knownchars['ring'        ] = 'textring'
+    @@knownchars['tilde'       ] = 'texttilde'
+
+    @@knownchars['cent'    ] = 'textcent'
+    @@knownchars['currency'] = 'textcurrency'
+    @@knownchars['euro'    ] = 'texteuro'
+    @@knownchars['florin'  ] = 'textflorin'
+    @@knownchars['sterling'] = 'textsterling'
+    @@knownchars['yen'     ] = 'textyen'
+
+    @@knownchars['brokenbar'] = 'textbrokenbar'
+    @@knownchars['bullet'   ] = 'textbullet'
+    @@knownchars['dag'      ] = 'textdag'
+    @@knownchars['ddag'     ] = 'textddag'
+    @@knownchars['degree'   ] = 'textdegree'
+    @@knownchars['div'      ] = 'textdiv'
+    @@knownchars['ellipsis' ] = 'textellipsis'
+    @@knownchars['fraction' ] = 'textfraction'
+    @@knownchars['lognot'   ] = 'textlognot'
+    @@knownchars['minus'    ] = 'textminus'
+    @@knownchars['mu'       ] = 'textmu'
+    @@knownchars['multiply' ] = 'textmultiply'
+    @@knownchars['pm'       ] = 'textpm'
+
+    def encmake
+        afmfile  = @commandline.argument('first')
+        encoding = @commandline.argument('second') || 'dummy'
+        if afmfile && FileTest.file?(afmfile) then
+            chars = Array.new
+            IO.readlines(afmfile).each do |line|
+                if line =~ /C\s+(\d+).*?N\s+([a-zA-Z\-\.]+?)\s*;/ then
+                    chars[$1.to_i] = $2
+                end
+            end
+            if f = File.open(encoding+'.enc','w') then
+                f << "% Encoding file, generated by textools.rb from #{afmfile}\n"
+                f << "\n"
+                f << "/#{encoding.gsub(/[^a-zA-Z]/,'')}encoding [\n"
+                256.times do |i|
+                    f << "  /#{chars[i] || '.notdef'} % #{i}\n"
+                end
+                f << "] def\n"
+                f.close
+            end
+            if f = File.open('enco-'+encoding+'.tex','w') then
+                f << "% ConTeXt file, generated by textools.rb from #{afmfile}\n"
+                f << "\n"
+                f << "\\startencoding[#{encoding}]\n\n"
+                256.times do |i|
+                    if str = chars[i] then
+                        tmp = str.gsub(/dieresis/,'diaeresis')
+                        if chr = @@knownchars[tmp] then
+                            f << "  \\definecharacter #{chr} #{i}\n"
+                        elsif tmp.length > 5 then
+                            f << "  \\definecharacter #{tmp} #{i}\n"
+                        end
+                    end
+                end
+                f << "\n\\stopencoding\n"
+                f << "\n\\endinput\n"
+                f.close
+            end
+        end
+    end
+
+    private
+
+    def flushencoding (file, from, to, names)
+        n = 0
+        out = File.open("#{file}.enc",'w')
+        out.puts("/#{file.gsub(/\-/,'')} [\n")
+        for i in from..to do
+            if names[i] then
+                n += 1
+                out.puts("/#{names[i]}\n")
+            else
+                out.puts("/.notdef\n")
+            end
+        end
+        out.puts("] def\n")
+        out.close
+        return n
+    end
+
+    private # specific
+
+    def movefiles(from_path,to_path,suffix,&block)
+        obsolete = 'obsolete'
+        force = @commandline.option('force')
+        moved = 0
+        if files = texmffiles(from_path, "*.#{suffix}") then
+            files.each do |filename|
+                newfilename = filename.sub(/^#{from_path}/, to_path)
+                yield(newfilename) if block
+                if FileTest.file?(newfilename) then
+                    begin
+                        File.rename(filename,filename+'.obsolete') if force
+                    rescue
+                        report("#{filename} cannot be made obsolete") if force
+                    else
+                        if force then
+                            report("#{filename} is made obsolete")
+                        else
+                            report("#{filename} will become obsolete")
+                        end
+                    end
+                else
+                    begin
+                        File.makedirs(File.dirname(newfilename)) if force
+                    rescue
+                    end
+                    begin
+                        File.copy(filename,newfilename) if force
+                    rescue
+                        report("#{filename} cannot be copied to #{newfilename}")
+                    else
+                        begin
+                            File.delete(filename) if force
+                        rescue
+                            report("#{filename} cannot be deleted") if force
+                        else
+                            if force then
+                                report("#{filename} is moved to #{newfilename}")
+                                moved += 1
+                            else
+                                report("#{filename} will be moved to #{newfilename}")
+                            end
+                        end
+                    end
+                end
+            end
+        else
+            report('no matches found')
+        end
+        return moved
+    end
+
+    def xidemapnames(hide)
+
+        filter  = /^([^\%]+?)(\s+)([^\"\<\s]*?)(\s)/
+        banner  = '% textools:nn '
+
+        if files = findfiles('map') then
+            report
+            files.sort.each do |fn|
+                if fn.has_suffix?('map') then
+                    begin
+                        lines = IO.read(fn)
+                        report("processing #{fn}")
+                        if f = File.open(fn,'w') then
+                            skip = false
+                            if hide then
+                                lines.each do |str|
+                                    if skip then
+                                        skip = false
+                                    elsif str =~ /#{banner}/ then
+                                        skip = true
+                                    elsif str =~ filter then
+                                        f.puts(banner+str)
+                                        str.sub!(filter) do
+                                            $1 + $2 + " "*$3.length + $4
+                                        end
+                                    end
+                                    f.puts(str)
+                                end
+                            else
+                                lines.each do |str|
+                                    if skip then
+                                        skip = false
+                                    elsif str.sub!(/#{banner}/, '') then
+                                        f.puts(str)
+                                        skip = true
+                                    else
+                                        f.puts(str)
+                                    end
+                                end
+                            end
+                            f.close
+                        end
+                    rescue
+                        report("error in handling #{fn}")
+                    end
+                end
+            end
+        end
+
+    end
+
+    public
+
+    def updatetree
+
+        nocheck  = @commandline.option('nocheck')
+        merge    = @commandline.option('merge')
+        delete   = @commandline.option('delete')
+        force    = @commandline.option('force')
+        root     = @commandline.argument('first').gsub(/\\/,'/')
+        path     = @commandline.argument('second').gsub(/\\/,'/')
+
+        if FileTest.directory?(root) then
+            report("scanning #{root}")
+            rootfiles = Dir.glob("#{root}/**/*")
+        else
+            report("provide source root")
+            return
+        end
+        if rootfiles.size > 0 then
+            report("#{rootfiles.size} files")
+        else
+            report("no files")
+            return
+        end
+        rootfiles.collect! do |rf|
+            rf.gsub(/\\/o, '/').sub(/#{root}\//o, '')
+        end
+        rootfiles = rootfiles.delete_if do |rf|
+            FileTest.directory?(File.join(root,rf))
+        end
+
+        if FileTest.directory?(path) then
+            report("scanning #{path}")
+            pathfiles = Dir.glob("#{path}/**/*")
+        else
+            report("provide destination root")
+            return
+        end
+        if pathfiles.size > 0 then
+            report("#{pathfiles.size} files")
+        else
+            report("no files")
+            return
+        end
+        pathfiles.collect! do |pf|
+            pf.gsub(/\\/o, '/').sub(/#{path}\//o, '')
+        end
+        pathfiles = pathfiles.delete_if do |pf|
+            FileTest.directory?(File.join(path,pf))
+        end
+
+        root = File.expand_path(root)
+        path = File.expand_path(path)
+
+        donepaths   = Hash.new
+        copiedfiles = Hash.new
+
+        # update existing files, assume similar paths
+
+        report("")
+        pathfiles.each do |f| # destination
+            p = File.join(path,f)
+            if rootfiles.include?(f) then
+                r = File.join(root,f)
+                if p != r then
+                    if nocheck or File.mtime(p) < File.mtime(r) then
+                        copiedfiles[File.expand_path(p)] = true
+                        report("updating '#{r}' to '#{p}'")
+                        begin
+                            begin File.makedirs(File.dirname(p)) if force ; rescue ; end
+                            File.copy(r,p) if force
+                        rescue
+                            report("updating failed")
+                        end
+                    else
+                        report("not updating '#{r}'")
+                    end
+                end
+            end
+        end
+
+        # merging non existing files
+
+        report("")
+        rootfiles.each do |f|
+            donepaths[File.dirname(f)] = true
+            r = File.join(root,f)
+            if not pathfiles.include?(f) then
+                p = File.join(path,f)
+                if p != r then
+                    if merge then
+                        copiedfiles[File.expand_path(p)] = true
+                        report("merging '#{r}' to '#{p}'")
+                        begin
+                            begin File.makedirs(File.dirname(p)) if force ; rescue ; end
+                            File.copy(r,p) if force
+                        rescue
+                            report("merging failed")
+                        end
+                    else
+                        report("not merging '#{r}'")
+                    end
+                end
+            end
+        end
+
+        # deleting obsolete files
+
+        report("")
+        donepaths.keys.sort.each do |d|
+            pathfiles = Dir.glob("#{path}/#{d}/**/*")
+            pathfiles.each do |p|
+# puts(File.dirname(p))
+# if donepaths[File.dirname(p)] then
+                r = File.join(root,d,File.basename(p))
+                if FileTest.file?(p) and not FileTest.file?(r) and not copiedfiles.key?(File.expand_path(p)) then
+                    if delete then
+                        report("deleting '#{p}'")
+                        begin
+                            File.delete(p) if force
+                        rescue
+                            report("deleting failed")
+                        end
+                    else
+                        report("not deleting '#{p}'")
+                    end
+                end
+            end
+# end
+        end
+
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+commandline.registeraction('removemapnames'   , '[pattern]   [--recurse]')
+commandline.registeraction('restoremapnames'  , '[pattern]   [--recurse]')
+commandline.registeraction('hidemapnames'     , '[pattern]   [--recurse]')
+commandline.registeraction('videmapnames'     , '[pattern]   [--recurse]')
+commandline.registeraction('findfile'         , 'filename    [--recurse]')
+commandline.registeraction('unzipfiles'       , '[pattern]   [--recurse]')
+commandline.registeraction('fixafmfiles'      , '[pattern]   [--recurse]')
+commandline.registeraction('mactodos'         , '[pattern]   [--recurse]')
+commandline.registeraction('fixtexmftrees'    , '[texmfroot] [--force]')
+commandline.registeraction('replacefile'      , 'filename    [--force]')
+commandline.registeraction('updatetree'       , 'fromroot toroot [--force --nocheck --merge --delete]')
+commandline.registeraction('downcasefilenames', '[--recurse] [--force]') # not yet documented
+commandline.registeraction('stripformfeeds'   , '[--recurse] [--force]') # not yet documented
+commandline.registeraction('showfont'         , 'filename')
+commandline.registeraction('encmake'          , 'afmfile encodingname')
+
+commandline.registeraction('tpmmake'          , 'tpm file (run in texmf root)')
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registerflag('recurse')
+commandline.registerflag('force')
+commandline.registerflag('merge')
+commandline.registerflag('delete')
+commandline.registerflag('nocheck')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'help')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/textools.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/texutil.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/texutil.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/texutil.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,93 @@
+banner = ['TeXUtil  ', 'version 9.1.0', '1997-2005', 'PRAGMA ADE/POD']
+
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
+
+require 'base/switch'
+require 'base/logger'
+require 'base/file'
+require 'base/texutil'
+
+class Commands
+
+    include CommandBase
+
+    def references
+        filename = @commandline.argument('first')
+        if not filename.empty? and FileTest.file?(File.suffixed(filename,'tuo')) then
+            if tu = TeXUtil::Converter.new(logger) and tu.loaded(filename) then
+                tu.saved if tu.processed
+            end
+        end
+    end
+
+    def main
+        if @commandline.arguments.length>0 then
+            references
+        else
+            help
+        end
+    end
+
+    def purgefiles
+        system("texmfstart ctxtools --purge #{@commandline.arguments.join(' ')}")
+    end
+
+    def purgeallfiles
+        system("texmfstart ctxtools --purge --all #{@commandline.arguments.join(' ')}")
+    end
+
+    def documentation
+        system("texmfstart ctxtools --document #{@commandline.arguments.join(' ')}")
+    end
+
+    def analyzefile
+        system("texmfstart pdftools --analyze #{@commandline.arguments.join(' ')}")
+    end
+
+    def filterpages # obsolete
+        system("texmfstart ctxtools --purge #{@commandline.arguments.join(' ')}")
+    end
+
+    def figures
+        report("this code is not yet converted from perl to ruby")
+    end
+
+    def logfile
+        report("this code is not yet converted from perl to ruby")
+    end
+
+end
+
+logger      = Logger.new(banner.shift)
+commandline = CommandLine.new
+
+# main feature
+
+commandline.registeraction('references', 'convert tui file into tuo file')
+
+# todo features
+
+commandline.registeraction('figures', 'generate figure dimensions file')
+commandline.registeraction('logfile', 'filter essential log messages')
+
+# backward compatibility features
+
+commandline.registeraction('purgefiles', 'remove most temporary files')
+commandline.registeraction('purgeallfiles', 'remove all temporary files')
+commandline.registeraction('documentation', 'generate documentation file from source')
+commandline.registeraction('analyzefile', 'analyze pdf file')
+
+# old feature, not needed any longer due to extension of pdftex
+
+commandline.registeraction('filterpages')
+
+# generic features
+
+commandline.registeraction('help')
+commandline.registeraction('version')
+
+commandline.registerflag('verbose')
+
+commandline.expand
+
+Commands.new(commandline,logger,banner).send(commandline.action || 'main')


Property changes on: trunk/Master/texmf-dist/scripts/context/ruby/texutil.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/context/ruby/tmftools.rb
===================================================================
--- trunk/Master/texmf-dist/scripts/context/ruby/tmftools.rb	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/context/ruby/tmftools.rb	2023-12-13 10:01:49 UTC (rev 69109)
@@ -0,0 +1,165 @@
+#!/usr/bin/env ruby
+
+# program   : tmftools
+# copyright : PRAGMA Advanced Document Engineering
+# version   : 2005
+# author    : Hans Hagen
+#
+# project   : ConTeXt
+# concept   : Hans Hagen
+# info      : j.hagen at xs4all.nl
+# www       : www.pragma-ade.com
+

@@ Diff output truncated at 1234567 characters. @@


More information about the tex-live-commits mailing list.