summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fonts/fea/context/greek-babel-extended.fea297
-rw-r--r--fonts/fea/verbose-digits.fea36
-rw-r--r--scripts/context/lua/luatools.lua79
-rw-r--r--scripts/context/lua/mtx-babel.lua368
-rw-r--r--scripts/context/lua/mtx-chars.lua81
-rw-r--r--scripts/context/lua/mtxrun.lua2348
-rw-r--r--scripts/context/ruby/base/pdf.rb2
-rw-r--r--scripts/context/ruby/base/tex.rb55
-rw-r--r--scripts/context/ruby/base/texutil.rb84
-rw-r--r--scripts/context/ruby/www/dir.rb6
-rw-r--r--tex/context/base/attr-ini.lua3
-rw-r--r--tex/context/base/char-ini.lua19
-rw-r--r--tex/context/base/colo-ini.tex6
-rw-r--r--tex/context/base/colo-new.lua14
-rw-r--r--tex/context/base/cont-new.mkiv1
-rw-r--r--tex/context/base/cont-new.tex2
-rw-r--r--tex/context/base/context.tex2
-rw-r--r--tex/context/base/core-def.tex13
-rw-r--r--tex/context/base/core-fig.tex43
-rw-r--r--tex/context/base/core-reg.lua14
-rw-r--r--tex/context/base/core-reg.tex37
-rw-r--r--tex/context/base/core-rul.tex142
-rw-r--r--tex/context/base/core-spa.mkiv6
-rw-r--r--tex/context/base/core-trf.tex18
-rw-r--r--tex/context/base/enco-ini.mkii16
-rw-r--r--tex/context/base/enco-ini.tex22
-rw-r--r--tex/context/base/enco-pfr.mkiv12
-rw-r--r--tex/context/base/enco-pfr.tex36
-rw-r--r--tex/context/base/enco-utf.tex1130
-rw-r--r--tex/context/base/font-afm.lua4
-rw-r--r--tex/context/base/font-ini.tex158
-rw-r--r--tex/context/base/font-otf.lua14
-rw-r--r--tex/context/base/font-syn.lua28
-rw-r--r--tex/context/base/font-tfm.lua2
-rw-r--r--tex/context/base/l-boolean.lua20
-rw-r--r--tex/context/base/l-string.lua15
-rw-r--r--tex/context/base/l-table.lua21
-rw-r--r--tex/context/base/l-xml-edu.lua381
-rw-r--r--tex/context/base/l-xml.lua2356
-rw-r--r--tex/context/base/lang-ini.lua203
-rw-r--r--tex/context/base/lang-ini.mkiv5
-rw-r--r--tex/context/base/luat-env.lua28
-rw-r--r--tex/context/base/lxml-ini.lua254
-rw-r--r--tex/context/base/lxml-ini.tex41
-rw-r--r--tex/context/base/meta-ini.tex4
-rw-r--r--tex/context/base/meta-tex.tex5
-rw-r--r--tex/context/base/mult-sys.tex1
-rw-r--r--tex/context/base/regi-ini.mkii51
-rw-r--r--tex/context/base/s-abr-01.tex2
-rw-r--r--tex/context/base/s-pre-64.tex201
-rw-r--r--tex/context/base/spec-mis.tex2
-rw-r--r--tex/context/base/spec-tpd.tex3
-rw-r--r--tex/context/base/toks-ini.lua97
-rw-r--r--tex/context/base/toks-ini.tex53
-rw-r--r--tex/context/base/type-one.tex217
-rw-r--r--tex/context/base/type-otf.tex362
-rw-r--r--tex/context/base/type-tmf.tex180
-rw-r--r--tex/context/base/unic-ini.tex70
-rw-r--r--tex/context/base/x-cals.mkiv4
-rw-r--r--tex/context/base/x-ct.mkiv202
-rw-r--r--tex/context/interface/cont-cz.xml1
-rw-r--r--tex/context/interface/cont-de.xml1
-rw-r--r--tex/context/interface/cont-en.xml1
-rw-r--r--tex/context/interface/cont-fr.xml1
-rw-r--r--tex/context/interface/cont-it.xml1
-rw-r--r--tex/context/interface/cont-nl.xml1
-rw-r--r--tex/context/interface/cont-ro.xml1
-rw-r--r--tex/context/interface/keys-cz.xml2
-rw-r--r--tex/context/interface/keys-de.xml2
-rw-r--r--tex/context/interface/keys-en.xml2
-rw-r--r--tex/context/interface/keys-fr.xml2
-rw-r--r--tex/context/interface/keys-it.xml2
-rw-r--r--tex/context/interface/keys-nl.xml2
-rw-r--r--tex/context/interface/keys-ro.xml2
-rw-r--r--tex/context/test/x-cals-test.cdx31
-rw-r--r--tex/context/test/x-cals-test.tex32
-rw-r--r--tex/context/test/x-cals-test.xml78
-rw-r--r--tex/context/test/x-ct-test.tex7
-rw-r--r--tex/context/test/x-ct-test.xml149
79 files changed, 6894 insertions, 3300 deletions
diff --git a/fonts/fea/context/greek-babel-extended.fea b/fonts/fea/context/greek-babel-extended.fea
new file mode 100644
index 000000000..69d8b5d76
--- /dev/null
+++ b/fonts/fea/context/greek-babel-extended.fea
@@ -0,0 +1,297 @@
+# An Opentype feature to replace the Babel input scheme
+
+# Not quite complete; some rhos with breathings and accents are missing (where
+# are they?) and the final sigma isn't accounted for.
+
+lookup GreekBabelLookupSimple {
+ lookupflag 0 ;
+ sub a by alpha ;
+ sub b by beta ;
+ sub g by gamma ;
+ sub d by delta ;
+ sub e by epsilon ;
+ sub z by zeta ;
+ sub h by eta ;
+ sub j by theta ;
+ sub i by iota ;
+ sub k by kappa ;
+ sub l by lambda ;
+ sub m by mu ;
+ sub n by nu ;
+ sub x by xi ;
+ sub o by omicron ;
+ sub p by pi ;
+ sub r by rho ;
+ sub c by sigmafinal ;
+ sub s by sigma ;
+ sub t by tau ;
+ sub u by upsilon ;
+ sub f by phi ;
+ sub q by chi ;
+ sub y by psi ;
+ sub w by omega ;
+ sub A by Alpha ;
+ sub B by Beta ;
+ sub G by Gamma ;
+ sub D by Delta ;
+ sub E by Epsilon ;
+ sub Z by Zeta ;
+ sub H by Eta ;
+ sub J by Theta ;
+ sub I by Iota ;
+ sub K by Kappa ;
+ sub L by Lambda ;
+ sub M by Mu ;
+ sub N by Nu ;
+ sub X by Xi ;
+ sub O by Omicron ;
+ sub P by Pi ;
+ sub R by Rho ;
+ sub C by Uni03C2 ;
+ sub S by Sigma ;
+ sub T by Tau ;
+ sub U by Upsilon ;
+ sub F by Phi ;
+ sub Q by Chi ;
+ sub Y by Psi ;
+ sub W by Omega ;
+ sub semicolon by periodcentered ;
+} GreekBabelLookupSimple ;
+
+lookup GreekBabelLookupMultiple {
+ lookupflag 1 ;
+ # sub s 'space by sigmafinal ;
+ sub greater a by uni1F00 ;
+ sub greater A by uni1F08 ;
+ sub greater e by uni1F10 ;
+ sub greater E by uni1F18 ;
+ sub greater h by uni1F20 ;
+ sub greater H by uni1F28 ;
+ sub greater i by uni1F30 ;
+ sub greater I by uni1F38 ;
+ sub greater o by uni1F40 ;
+ sub greater O by uni1F48 ;
+ sub greater u by uni1F50 ;
+ # sub greater U by uni1F58 ;
+ sub greater w by uni1F60 ;
+ sub greater W by uni1F68 ;
+ sub greater grave a by uni1F02 ;
+ sub greater grave A by uni1F0A ;
+ sub greater grave e by uni1F12 ;
+ sub greater grave E by uni1F1A ;
+ sub greater grave h by uni1F22 ;
+ sub greater grave H by uni1F2A ;
+ sub greater grave i by uni1F32 ;
+ sub greater grave I by uni1F3A ;
+ sub greater grave o by uni1F42 ;
+ sub greater grave O by uni1F4A ;
+ sub greater grave u by uni1F52 ;
+ # sub greater grave U by uni1F5A ;
+ sub greater grave w by uni1F62 ;
+ sub greater grave W by uni1F6A ;
+ sub greater quotesingle a by uni1F04 ;
+ sub greater quotesingle A by uni1F0C ;
+ sub greater quotesingle e by uni1F14 ;
+ sub greater quotesingle E by uni1F1C ;
+ sub greater quotesingle h by uni1F24 ;
+ sub greater quotesingle H by uni1F2C ;
+ sub greater quotesingle i by uni1F34 ;
+ sub greater quotesingle I by uni1F3C ;
+ sub greater quotesingle o by uni1F44 ;
+ sub greater quotesingle O by uni1F4C ;
+ sub greater quotesingle u by uni1F54 ;
+ sub greater quotesingle U by uni1F5C ;
+ sub greater quotesingle w by uni1F64 ;
+ sub greater quotesingle W by uni1F6C ;
+ sub greater asciitilde a by uni1F06 ;
+ sub greater asciitilde A by uni1F0E ;
+ sub greater asciitilde e by uni1F16 ;
+ sub greater asciitilde E by uni1F1E ;
+ sub greater asciitilde h by uni1F26 ;
+ sub greater asciitilde H by uni1F2E ;
+ sub greater asciitilde i by uni1F36 ;
+ sub greater asciitilde I by uni1F3E ;
+ sub greater asciitilde o by uni1F46 ;
+ sub greater asciitilde O by uni1F4E ;
+ sub greater asciitilde u by uni1F56 ;
+ sub greater asciitilde U by uni1F5E ;
+ sub greater asciitilde w by uni1F66 ;
+ sub greater asciitilde W by uni1F6E ;
+ sub less a by uni1F01 ;
+ sub less A by uni1F09 ;
+ sub less e by uni1F11 ;
+ sub less E by uni1F19 ;
+ sub less h by uni1F21 ;
+ sub less H by uni1F29 ;
+ sub less i by uni1F31 ;
+ sub less I by uni1F39 ;
+ sub less o by uni1F41 ;
+ sub less O by uni1F49 ;
+ sub less u by uni1F51 ;
+ sub less U by uni1F59 ;
+ sub less w by uni1F61 ;
+ sub less W by uni1F69 ;
+ sub less grave a by uni1F03 ;
+ sub less grave A by uni1F0B ;
+ sub less grave e by uni1F13 ;
+ sub less grave E by uni1F1B ;
+ sub less grave h by uni1F23 ;
+ sub less grave H by uni1F2B ;
+ sub less grave i by uni1F33 ;
+ sub less grave I by uni1F3B ;
+ sub less grave o by uni1F43 ;
+ sub less grave O by uni1F4B ;
+ sub less grave u by uni1F53 ;
+ sub less grave U by uni1F5B ;
+ sub less grave w by uni1F63 ;
+ sub less grave W by uni1F6B ;
+ sub less quotesingle a by uni1F05 ;
+ sub less quotesingle A by uni1F0D ;
+ sub less quotesingle e by uni1F15 ;
+ sub less quotesingle E by uni1F1D ;
+ sub less quotesingle h by uni1F25 ;
+ sub less quotesingle H by uni1F2D ;
+ sub less quotesingle i by uni1F35 ;
+ sub less quotesingle I by uni1F3D ;
+ sub less quotesingle o by uni1F45 ;
+ sub less quotesingle O by uni1F4D ;
+ sub less quotesingle u by uni1F55 ;
+ sub less quotesingle U by uni1F5D ;
+ sub less quotesingle w by uni1F65 ;
+ sub less quotesingle W by uni1F6D ;
+ sub less asciitilde a by uni1F07 ;
+ sub less asciitilde A by uni1F0F ;
+ sub less asciitilde e by uni1F17 ;
+ sub less asciitilde E by uni1F1F ;
+ sub less asciitilde h by uni1F27 ;
+ sub less asciitilde H by uni1F2F ;
+ sub less asciitilde i by uni1F37 ;
+ sub less asciitilde I by uni1F3F ;
+ sub less asciitilde o by uni1F47 ;
+ sub less asciitilde O by uni1F4F ;
+ sub less asciitilde u by uni1F57 ;
+ sub less asciitilde U by uni1F5F ;
+ sub less asciitilde w by uni1F67 ;
+ sub less asciitilde W by uni1F6F ;
+ sub grave a by uni1F70 ;
+ sub quotesingle a by uni1F71 ;
+ sub grave e by uni1F72 ;
+ sub quotesingle e by uni1F73 ;
+ sub grave h by uni1F74 ;
+ sub quotesingle h by uni1F75 ;
+ sub grave i by uni1F76 ;
+ sub quotesingle i by uni1F77 ;
+ sub grave o by uni1F78 ;
+ sub quotesingle o by uni1F79 ;
+ sub grave u by uni1F7A ;
+ sub quotesingle u by uni1F7B ;
+ sub grave w by uni1F7C ;
+ sub quotesingle w by uni1F7D ;
+ sub grave A by uni1FBA ;
+ sub quotesingle A by uni1FBB ;
+ sub grave E by uni1FC8 ;
+ sub quotesingle E by uni1FC9 ;
+ sub grave H by uni1FCA ;
+ sub quotesingle H by uni1FCB ;
+ sub grave I by uni1FDA ;
+ sub quotesingle I by uni1FDB ;
+ sub grave U by uni1FEA ;
+ sub quotesingle U by uni1FEB ;
+ sub grave W by uni1FFA ;
+ sub quotesingle W by uni1FFB ;
+ sub greater a bar by uni1F80 ;
+ sub greater A bar by uni1F88 ;
+ sub greater h bar by uni1F90 ;
+ sub greater H bar by uni1F98 ;
+ sub greater w bar by uni1FA0 ;
+ sub greater W bar by uni1FA8 ;
+ sub greater grave a bar by uni1F82 ;
+ sub greater grave A bar by uni1F8A ;
+ sub greater grave h bar by uni1F92 ;
+ sub greater grave H bar by uni1F9A ;
+ sub greater grave w bar by uni1FA2 ;
+ sub greater grave W bar by uni1FAA ;
+ sub greater quotesingle a bar by uni1F84 ;
+ sub greater quotesingle A bar by uni1F8C ;
+ sub greater quotesingle h bar by uni1F94 ;
+ sub greater quotesingle H bar by uni1F9C ;
+ sub greater quotesingle w bar by uni1FA4 ;
+ sub greater quotesingle W bar by uni1FAC ;
+ sub greater asciitilde a bar by uni1F86 ;
+ sub greater asciitilde A bar by uni1F8E ;
+ sub greater asciitilde h bar by uni1F96 ;
+ sub greater asciitilde H bar by uni1F9E ;
+ sub greater asciitilde w bar by uni1FA6 ;
+ sub greater asciitilde W bar by uni1FAE ;
+ sub less a bar by uni1F81 ;
+ sub less A bar by uni1F89 ;
+ sub less h bar by uni1F91 ;
+ sub less H bar by uni1F99 ;
+ sub less w bar by uni1FA1 ;
+ sub less W bar by uni1FA9 ;
+ sub less grave a bar by uni1F83 ;
+ sub less grave A bar by uni1F8B ;
+ sub less grave h bar by uni1F93 ;
+ sub less grave H bar by uni1F9B ;
+ sub less grave w bar by uni1FA3 ;
+ sub less grave W bar by uni1FAB ;
+ sub less quotesingle a bar by uni1F85 ;
+ sub less quotesingle A bar by uni1F8D ;
+ sub less quotesingle h bar by uni1F95 ;
+ sub less quotesingle H bar by uni1F9D ;
+ sub less quotesingle w bar by uni1FA5 ;
+ sub less quotesingle W bar by uni1FAD ;
+ sub less asciitilde a bar by uni1F87 ;
+ sub less asciitilde A bar by uni1F8F ;
+ sub less asciitilde h bar by uni1F97 ;
+ sub less asciitilde H bar by uni1F9F ;
+ sub less asciitilde w bar by uni1FA7 ;
+ sub less asciitilde W bar by uni1FAF ;
+ sub grave a bar by uni1FB2 ;
+ sub quotesingle a bar by uni1FB4 ;
+ sub grave h bar by uni1FC2 ;
+ sub quotesingle h bar by uni1FC4 ;
+ sub grave w bar by uni1FD2 ;
+ sub quotesingle w bar by uni1FD4 ;
+ sub asciitilde a by uni1FB6 ;
+ sub asciitilde a bar by uni1FB7 ;
+ sub asciitilde h by uni1FC6 ;
+ sub asciitilde h bar by uni1FC7 ;
+ sub asciitilde w by uni1FD6 ;
+ sub asciitilde w bar by uni1FD7 ;
+ sub greater r by uni1FE4 ;
+ sub less r by uni1FE5 ;
+ sub less R by uni1FEC ;
+} GreekBabelLookupMultiple ;
+
+lookup GreekBabel2LookupMultiple {
+ lookupflag 1 ;
+ sub alpha bar by uni1FB3 ;
+ sub eta bar by uni1FC3 ;
+ sub omega bar by uni1FF3 ;
+} GreekBabel2LookupMultiple ;
+
+feature grbl {
+
+ script DFLT ;
+ language dflt ;
+ lookup GreekBabelLookupMultiple ;
+ lookup GreekBabelLookupSimple ;
+
+ script latn;
+ language dflt ;
+ lookup GreekBabelLookupMultiple ;
+ lookup GreekBabelLookupSimple ;
+} grbl ;
+
+feature grb2 {
+
+ script DFLT ;
+ language dflt ;
+ lookup GreekBabel2LookupMultiple ;
+
+ script latn;
+ language dflt ;
+ lookup GreekBabel2LookupMultiple ;
+} grb2 ;
+
diff --git a/fonts/fea/verbose-digits.fea b/fonts/fea/verbose-digits.fea
deleted file mode 100644
index 7fd1fcf85..000000000
--- a/fonts/fea/verbose-digits.fea
+++ /dev/null
@@ -1,36 +0,0 @@
-lookup NumericLookupDFLT {
- lookupflag 0 ;
- sub zero by z e r o ;
- sub one by o n e ;
- sub two by t w o ;
- sub three by t h r e e ;
- sub four by f o u r ;
- sub five by f i v e ;
- sub six by s i x ;
- sub seven by s e v e n ;
- sub eight by e i g h t ;
- sub nine by n i n e ;
-} NumericLookupDFLT ;
-
-feature verb {
-
- script DFLT ;
- language dflt ;
- lookup NumericLookupDFLT ;
-
- script latn;
- language dflt ;
- lookup NumericLookupDFLT ;
- language AZE exclude_dflt ;
- lookup NumericLookupDFLT ;
- language CRT exclude_dflt ;
- lookup NumericLookupDFLT ;
- language MOL exclude_dflt ;
- lookup NumericLookupDFLT ;
- language ROM exclude_dflt ;
- lookup NumericLookupDFLT ;
- language TRK exclude_dflt ;
- lookup NumericLookupDFLT ;
-
-} verb ;
-
diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua
index 84899275c..d53180cfa 100644
--- a/scripts/context/lua/luatools.lua
+++ b/scripts/context/lua/luatools.lua
@@ -5056,6 +5056,7 @@ messages.help = [[
--show-path show path expansion of ...
--var-value report value of variable
--find-file report file location
+--find-path report path of file
--make or --ini make luatex format
--run or --fmt= run luatex format
--luafile=str lua inifile (default is <progname>.lua)
@@ -5203,22 +5204,26 @@ input.report(banner,"\n")
local ok = true
-if environment.arguments["selfmerge"] then
- utils.merger.selfmerge(own.name,own.libs,own.list)
-elseif environment.arguments["selfclean"] then
- utils.merger.selfclean(own.name)
-elseif environment.arguments["selfupdate"] then
- input.my_prepare_b(instance)
- input.verbose = true
- input.update_script(instance,own.name,"luatools")
-elseif environment.arguments["generate"] then
- instance.renewcache = true
- input.verbose = true
+if environment.arguments["find-file"] then
input.my_prepare_b(instance)
-elseif environment.arguments["make"] or environment.arguments["ini"] or environment.arguments["compile"] then
+ instance.format = environment.arguments["format"] or instance.format
+ if instance.pattern then
+ instance.allresults = true
+ input.for_files(instance, input.find_files, { instance.pattern }, instance.my_format)
+ else
+ input.for_files(instance, input.find_files, environment.files, instance.my_format)
+ end
+elseif environment.arguments["find-path"] then
input.my_prepare_b(instance)
- input.verbose = true
- input.my_make_format(instance,environment.files[1] or "")
+ local path = input.find_file(instance, environment.files[1], instance.my_format)
+ if input.verbose then
+ input.report(file.dirname(path))
+ else
+ print(file.dirname(path))
+ end
+--~ elseif environment.arguments["first-writable-path"] then
+--~ input.my_prepare_b(instance)
+--~ input.report(input.first_writable_path(instance,environment.files[1] or "."))
elseif environment.arguments["run"] then
input.my_prepare_a(instance) -- ! no need for loading databases
input.verbose = true
@@ -5227,15 +5232,6 @@ elseif environment.arguments["fmt"] then
input.my_prepare_a(instance) -- ! no need for loading databases
input.verbose = true
input.my_run_format(instance,environment.arguments["fmt"], environment.files[1] or "")
-elseif environment.arguments["variables"] or environment.arguments["show-variables"] then
- input.my_prepare_a(instance)
- input.list_variables(instance)
-elseif environment.arguments["expansions"] or environment.arguments["show-expansions"] then
- input.my_prepare_a(instance)
- input.list_expansions(instance)
-elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then
- input.my_prepare_a(instance)
- input.list_configurations(instance)
elseif environment.arguments["expand-braces"] then
input.my_prepare_a(instance)
input.for_files(instance, input.expand_braces, environment.files)
@@ -5251,18 +5247,6 @@ elseif environment.arguments["show-path"] or environment.arguments["path-value"]
elseif environment.arguments["var-value"] or environment.arguments["show-value"] then
input.my_prepare_a(instance)
input.for_files(instance, input.var_value, environment.files)
-elseif environment.arguments["find-file"] then
- input.my_prepare_b(instance)
- instance.format = environment.arguments["format"] or instance.format
- if instance.pattern then
- instance.allresults = true
- input.for_files(instance, input.find_files, { instance.pattern }, instance.my_format)
- else
- input.for_files(instance, input.find_files, environment.files, instance.my_format)
- end
---~ elseif environment.arguments["first-writable-path"] then
---~ input.my_prepare_b(instance)
---~ input.report(input.first_writable_path(instance,environment.files[1] or "."))
elseif environment.arguments["format-path"] then
input.my_prepare_b(instance)
input.report(caches.setpath(instance,"format"))
@@ -5271,6 +5255,31 @@ elseif instance.pattern then -- brrr
instance.format = environment.arguments["format"] or instance.format
instance.allresults = true
input.for_files(instance, input.find_files, { instance.pattern }, instance.my_format)
+elseif environment.arguments["generate"] then
+ instance.renewcache = true
+ input.verbose = true
+ input.my_prepare_b(instance)
+elseif environment.arguments["make"] or environment.arguments["ini"] or environment.arguments["compile"] then
+ input.my_prepare_b(instance)
+ input.verbose = true
+ input.my_make_format(instance,environment.files[1] or "")
+elseif environment.arguments["selfmerge"] then
+ utils.merger.selfmerge(own.name,own.libs,own.list)
+elseif environment.arguments["selfclean"] then
+ utils.merger.selfclean(own.name)
+elseif environment.arguments["selfupdate"] then
+ input.my_prepare_b(instance)
+ input.verbose = true
+ input.update_script(instance,own.name,"luatools")
+elseif environment.arguments["variables"] or environment.arguments["show-variables"] then
+ input.my_prepare_a(instance)
+ input.list_variables(instance)
+elseif environment.arguments["expansions"] or environment.arguments["show-expansions"] then
+ input.my_prepare_a(instance)
+ input.list_expansions(instance)
+elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then
+ input.my_prepare_a(instance)
+ input.list_configurations(instance)
elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then
if not input.verbose then
input.verbose = true
diff --git a/scripts/context/lua/mtx-babel.lua b/scripts/context/lua/mtx-babel.lua
new file mode 100644
index 000000000..5ef9ae934
--- /dev/null
+++ b/scripts/context/lua/mtx-babel.lua
@@ -0,0 +1,368 @@
+-- data tables by Thomas A. Schmitz
+
+dofile(input.find_file(instance,"luat-log.lua"))
+
+texmf.instance = instance -- we need to get rid of this / maybe current instance in global table
+
+scripts = scripts or { }
+scripts.babel = scripts.babel or { }
+
+do
+
+ local replace_01 = { -- <' * |
+ a = "ᾅ",
+ h = "ᾕ",
+ w = "ᾥ",
+ }
+
+ local replace_02 = { -- >' * |
+ a = "ᾄ",
+ h = "ᾔ",
+ w = "ᾤ",
+ }
+
+ local replace_03 = { -- <` * |
+ a = "ᾃ",
+ h = "ᾓ",
+ w = "ᾣ",
+ }
+
+ local replace_04 = { -- >` * |
+ a = "ᾂ",
+ h = "ᾒ",
+ w = "ᾢ",
+ }
+
+ local replace_05 = { -- <~ * |
+ a = "ᾇ",
+ h = "ᾗ",
+ w = "ᾧ",
+ }
+
+ local replace_06 = { -- >~ * |
+ a = "ᾆ",
+ h = "ᾖ",
+ w = "ᾦ"
+ }
+
+ local replace_07 = { -- "' *
+ i = "ΐ",
+ u = "ΰ",
+ }
+
+ local replace_08 = { -- "` *
+ i = "ῒ",
+ u = "ῢ",
+ }
+
+ local replace_09 = { -- "~ *
+ i = "ῗ",
+ u = "ῧ",
+ }
+
+ local replace_10 = { -- <' *
+ a = "ἅ",
+ e = "ἕ",
+ h = "ἥ",
+ i = "ἵ",
+ o = "ὅ",
+ u = "ὕ",
+ w = "ὥ",
+ A = "Ἅ",
+ E = "Ἕ",
+ H = "Ἥ",
+ I = "Ἵ",
+ O = "Ὅ",
+ U = "Ὕ",
+ W = "Ὥ",
+ }
+
+ local replace_11 = { -- >' *
+ a = "ἄ",
+ e = "ἔ",
+ h = "ἤ",
+ i = "ἴ",
+ o = "ὄ",
+ u = "ὔ",
+ w = "ὤ",
+ A = "Ἄ",
+ E = "Ἔ",
+ H = "Ἤ",
+ I = "Ἴ",
+ O = "Ὄ",
+ U = "῎Υ",
+ W = "Ὤ",
+ }
+
+ local replace_12 = { -- <` *
+ a = "ἃ",
+ e = "ἓ",
+ h = "ἣ",
+ i = "ἳ",
+ o = "ὃ",
+ u = "ὓ",
+ w = "ὣ",
+ A = "Ἃ",
+ E = "Ἒ",
+ H = "Ἣ",
+ I = "Ἳ",
+ O = "Ὃ",
+ U = "Ὓ",
+ W = "Ὣ",
+ }
+
+ local replace_13 = { -- >` *
+ a = "ἂ",
+ e = "ἒ",
+ h = "ἢ",
+ i = "ἲ",
+ o = "ὂ",
+ u = "ὒ",
+ w = "ὢ",
+ A = "Ἂ",
+ E = "Ἒ",
+ H = "Ἢ",
+ I = "Ἲ",
+ O = "Ὂ",
+ U = "῍Υ",
+ W = "Ὢ",
+ }
+
+ local replace_14 = { -- <~ *
+ a = "ἇ",
+ h = "ἧ",
+ i = "ἷ",
+ u = "ὗ",
+ w = "ὧ",
+ A = "Ἇ",
+ H = "Ἧ",
+ I = "Ἷ",
+ U = "Ὗ",
+ W = "Ὧ",
+ }
+
+ local replace_15 = { -- >~ *
+ a = "ἆ",
+ h = "ἦ",
+ i = "ἶ",
+ u = "ὖ",
+ w = "ὦ",
+ A = "Ἆ",
+ H = "Ἦ",
+ I = "Ἶ",
+ U = "῏Υ",
+ W = "Ὦ",
+ }
+
+ local replace_16 = { -- ' * |
+ a = "ᾴ",
+ h = "ῄ",
+ w = "ῴ",
+ }
+
+ local replace_17 = { -- ` * |
+ a = "ᾲ",
+ h = "ῂ",
+ w = "ῲ",
+ }
+
+ local replace_18 = { -- ~ * |
+ a = "ᾷ",
+ h = "ῇ",
+ w = "ῷ"
+ }
+
+ local replace_19 = { -- ' *
+ a = "ά",
+ e = "έ",
+ h = "ή",
+ i = "ί",
+ o = "ό",
+ u = "ύ",
+ w = "ώ",
+ }
+
+ local replace_20 = { -- ` *
+ a = "ὰ",
+ e = "ὲ",
+ h = "ὴ",
+ i = "ὶ",
+ o = "ὸ",
+ u = "ὺ",
+ w = "ὼ",
+ }
+
+ local replace_21 = { -- ~ *
+ a = "ᾶ",
+ h = "ῆ",
+ i = "ῖ",
+ u = "ῦ",
+ w = "ῶ",
+ }
+
+ local replace_22 = { -- < *
+ a = "ἁ",
+ e = "ἑ",
+ h = "ἡ",
+ i = "ἱ",
+ o = "ὁ",
+ u = "ὑ",
+ w = "ὡ",
+ r = "ῥ",
+ A = "Ἁ",
+ E = "Ἑ",
+ H = "Ἡ",
+ I = "Ἱ",
+ O = "Ὁ",
+ U = "Ὑ",
+ W = "Ὡ",
+ }
+
+ local replace_23 = { -- > *
+ a = "ἀ",
+ e = "ἐ",
+ h = "ἠ",
+ i = "ἰ",
+ o = "ὀ",
+ u = "ὐ",
+ w = "ὠ",
+ A = "Ἀ",
+ E = "Ἐ",
+ H = "Ἠ",
+ I = "Ἰ",
+ O = "Ὀ",
+ U = "᾿Υ",
+ W = "Ὠ",
+ }
+
+ local replace_24 = { -- * |
+ a = "ᾳ",
+ h = "ῃ",
+ w = "ῳ",
+ }
+
+ local replace_25 = { -- " *
+ i = "ϊ",
+ u = "ϋ",
+ }
+
+ local replace_26 = { -- *
+ a = "α",
+ b = "β",
+ g = "γ",
+ d = "δ",
+ e = "ε",
+ z = "ζ",
+ h = "η",
+ j = "θ",
+ i = "ι",
+ k = "κ",
+ l = "λ",
+ m = "μ",
+ n = "ν",
+ x = "ξ",
+ o = "ο",
+ p = "π",
+ r = "ρ",
+ s = "σ",
+ c = "ς",
+ t = "τ",
+ u = "υ",
+ f = "φ",
+ q = "χ",
+ y = "ψ",
+ w = "ω",
+ A = "Α",
+ B = "Β",
+ G = "Γ",
+ D = "Δ",
+ E = "Ε",
+ Z = "Ζ",
+ H = "Η",
+ J = "Θ",
+ I = "Ι",
+ K = "Κ",
+ L = "Λ",
+ M = "Μ",
+ N = "Ν",
+ X = "Ξ",
+ O = "Ο",
+ P = "Π",
+ R = "Ρ",
+ S = "Σ",
+ T = "Τ",
+ U = "Υ",
+ F = "Φ",
+ Q = "Χ",
+ Y = "Ψ",
+ W = "Ω"
+ }
+
+ local skips_01 = lpeg.P("\\") * lpeg.R("az", "AZ")^1
+ local skips_02 = lpeg.P("[") * (1- lpeg.S("[]"))^1 * lpeg.P("]")
+
+ local stage_01 = (lpeg.P("<'") * lpeg.Cs(1) * lpeg.P('|')) / replace_01
+ local stage_02 = (lpeg.P(">'") * lpeg.Cs(1) * lpeg.P('|')) / replace_02
+ local stage_03 = (lpeg.P("<`") * lpeg.Cs(1) * lpeg.P('|')) / replace_03
+ local stage_04 = (lpeg.P(">`") * lpeg.Cs(1) * lpeg.P('|')) / replace_04
+ local stage_05 = (lpeg.P("<~") * lpeg.Cs(1) * lpeg.P('|')) / replace_05
+ local stage_06 = (lpeg.P(">~") * lpeg.Cs(1) * lpeg.P('|')) / replace_06
+ local stage_07 = (lpeg.P('"\'') * lpeg.Cs(1) ) / replace_07
+ local stage_08 = (lpeg.P('"`') * lpeg.Cs(1) ) / replace_08
+ local stage_09 = (lpeg.P('"~') * lpeg.Cs(1) ) / replace_09
+ local stage_10 = (lpeg.P("<'") * lpeg.Cs(1) ) / replace_10
+ local stage_11 = (lpeg.P(">'") * lpeg.Cs(1) ) / replace_11
+ local stage_12 = (lpeg.P("<`") * lpeg.Cs(1) ) / replace_12
+ local stage_13 = (lpeg.P(">`") * lpeg.Cs(1) ) / replace_13
+ local stage_14 = (lpeg.P(">~") * lpeg.Cs(1) ) / replace_14
+ local stage_15 = (lpeg.P(">~") * lpeg.Cs(1) ) / replace_15
+ local stage_16 = (lpeg.P("'") * lpeg.Cs(1) * lpeg.P('|')) / replace_16
+ local stage_17 = (lpeg.P("`") * lpeg.Cs(1) * lpeg.P('|')) / replace_17
+ local stage_18 = (lpeg.P("~") * lpeg.Cs(1) * lpeg.P('|')) / replace_18
+ local stage_19 = (lpeg.P("'") * lpeg.Cs(1) ) / replace_19
+ local stage_20 = (lpeg.P("`") * lpeg.Cs(1) ) / replace_20
+ local stage_21 = (lpeg.P("~") * lpeg.Cs(1) ) / replace_21
+ local stage_22 = (lpeg.P("<") * lpeg.Cs(1) ) / replace_22
+ local stage_23 = (lpeg.P(">") * lpeg.Cs(1) ) / replace_23
+ local stage_24 = (lpeg.Cs(1) * lpeg.P('|') ) / replace_24
+ local stage_25 = (lpeg.P('"') * lpeg.Cs(1) ) / replace_25
+ local stage_26 = (lpeg.Cs(1) ) / replace_26
+
+ local stages =
+ skips_01 + skips_02 +
+ stage_01 + stage_02 + stage_03 + stage_04 + stage_05 +
+ stage_06 + stage_07 + stage_08 + stage_09 + stage_10 +
+ stage_11 + stage_12 + stage_13 + stage_14 + stage_15 +
+ stage_16 + stage_17 + stage_18 + stage_19 + stage_20 +
+ stage_21 + stage_22 + stage_23 + stage_24 + stage_25 +
+ stage_26
+
+ local parser = lpeg.Cs((stages + 1)^0)
+
+ -- lpeg.print(parser): 254 lines
+
+ function scripts.babel.convert(filename)
+ if filename and filename ~= empty then
+ local data = io.loaddata(filename)
+ if data then
+ data = parser:match(data)
+ io.savedata(filename .. ".utf", data)
+ end
+ end
+ end
+
+end
+
+banner = banner .. " | conversion tools "
+
+messages.help = [[
+--convert convert babel codes into utf
+]]
+
+input.verbose = true
+
+if environment.argument("convert") then
+ scripts.babel.convert(environment.files[1] or "")
+else
+ input.help(banner,messages.help)
+end
diff --git a/scripts/context/lua/mtx-chars.lua b/scripts/context/lua/mtx-chars.lua
index 28d7b4a40..470846419 100644
--- a/scripts/context/lua/mtx-chars.lua
+++ b/scripts/context/lua/mtx-chars.lua
@@ -75,16 +75,97 @@ if not characters then characters = { } end
end
end
+scripts.chars.banner_utf_1 = [[
+% filename : enco-utf.tex
+% comment : generated by mtxrun --script chars --utf
+% author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+% copyright: PRAGMA ADE / ConTeXt Development Team
+% license : see context related readme files
+
+\ifx\setcclcucx\undefined
+
+ \def\setcclcucx #1 #2 #3 %
+ {\global\catcode"#1=11
+ \global\lccode "#1="#2
+ \global\uccode "#1="#3 }
+
+\fi
+]]
+
+scripts.chars.banner_utf_2 = [[
+
+% lc/uc/catcode mappings
+
+]]
+
+scripts.chars.banner_utf_3 = [[
+
+% named characters mapped onto utf
+
+]]
+
+scripts.chars.banner_utf_4 = [[
+
+\endinput
+]]
+
+function scripts.chars.makeencoutf()
+ local chartable = input.find_file(instance,"char-def.lua") or ""
+ if chartable ~= "" then
+ dofile(chartable)
+ if characters and characters.data then
+ local f = io.open("enco-utf.tex", 'w')
+ if f then
+ local char, format = unicode.utf8.char, string.format
+ f:write(scripts.chars.banner_utf_1)
+ f:write(scripts.chars.banner_utf_2)
+ local list = table.sortedkeys(characters.data)
+ local length = 0
+ for i=1,#list do
+ local code = list[i]
+ if code <= 0xFFFF then
+ local chr = characters.data[code]
+ local cc = chr.category
+ if cc == 'll' or cc == 'lu' or cc == 'lt' then
+ if not chr.lccode then chr.lccode = code end
+ if not chr.uccode then chr.uccode = code end
+ f:write(format("\\setcclcucx %04X %04X %04X %% %s\n",code,chr.lccode,chr.uccode,chr.description))
+ end
+ if #(chr.contextname or "") > length then
+ length = #chr.contextname
+ end
+ end
+ end
+ f:write(scripts.chars.banner_utf_3)
+ for i=1,#list do
+ local code = list[i]
+ if code > 0x7F and code <= 0xFFFF then
+ local chr = characters.data[code]
+ if chr.contextname then
+ f:write(format("\\def\\%s{%s} %% %s\n", chr.contextname:rpadd(length," "), char(code),chr.description))
+ end
+ end
+ end
+ f:write(scripts.chars.banner_utf_4)
+ f:close()
+ end
+ end
+ end
+end
+
banner = banner .. " | character tools "
messages.help = [[
--stix convert stix table to math table
+--utf generate enco-utf.tex (used by xetex)
]]
if environment.argument("stix") then
local inname = environment.files[1] or ""
local outname = environment.files[2] or ""
scripts.chars.stixtomkiv(inname,outname)
+elseif environment.argument("utf") then
+ scripts.chars.makeencoutf()
else
input.help(banner,messages.help)
end
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 2a3a496a3..baad28e84 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -168,7 +168,7 @@ end
--~ split = lpeg.Ct(c*(p*c)^0)
--~ splitters[separator] = split
--~ end
---~ return lpeg.match(split,self)
+--~ return lpeg.match(split,self) -- split:match(self)
--~ else
--~ return { }
--~ end
@@ -325,7 +325,7 @@ end
--~ return self .. self.rep(chr or " ",n-#self)
--~ end
-function string:padd(n,chr)
+function string:rpadd(n,chr)
local m = n-#self
if m > 0 then
return self .. self.rep(chr or " ",m)
@@ -334,6 +334,17 @@ function string:padd(n,chr)
end
end
+function string:lpadd(n,chr)
+ local m = n-#self
+ if m > 0 then
+ return self.rep(chr or " ",m) .. self
+ else
+ return self
+ end
+end
+
+string.padd = string.rpadd
+
function is_number(str)
return str:find("^[%-%+]?[%d]-%.?[%d+]$") == 1
end
@@ -530,6 +541,8 @@ end
do
+ -- one of my first exercises in lua ...
+
-- 34.055.092 32.403.326 arabtype.tma
-- 1.620.614 1.513.863 lmroman10-italic.tma
-- 1.325.585 1.233.044 lmroman10-regular.tma
@@ -889,6 +902,25 @@ function table.tohash(t)
return h
end
+function table.contains(t, v)
+ if t then
+ for i=1, #t do
+ if t[i] == v then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function table.count(t)
+ local n, e = 0, next(t)
+ while e do
+ n, e = n + 1, next(t,e)
+ end
+ return n
+end
+
--~ function table.are_equal(a,b)
--~ return table.serialize(a) == table.serialize(b)
--~ end
@@ -1387,12 +1419,20 @@ function boolean.tonumber(b)
if b then return 1 else return 0 end
end
-function toboolean(str)
- if type(str) == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1"
- elseif type(str) == "number" then
- return tonumber(str) ~= 0
- elseif type(str) == "nil" then
+function toboolean(str,tolerant)
+ if tolerant then
+ if type(str) == "string" then
+ return str == "true" or str == "yes" or str == "on" or str == "1"
+ elseif type(str) == "number" then
+ return tonumber(str) ~= 0
+ elseif type(str) == "nil" then
+ return false
+ else
+ return str
+ end
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
return false
else
return str
@@ -1427,13 +1467,14 @@ if not modules then modules = { } end modules ['l-xml'] = {
license = "see context related readme files"
}
--- todo: ns, tg = s:match("^(.-):?([^:]+)$")
+-- RJ: key=value ... lpeg.Ca(lpeg.Cc({}) * (pattern-producing-key-and-value / rawset)^0)
--[[ldx--
<p>The parser used here is inspired by the variant discussed in the lua book, but
handles comment and processing instructions, has a different structure, provides
parent access; a first version used different tricky but was less optimized to we
-went this route.</p>
+went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
+The find based parser can be found in l-xml-edu.lua along with other older code.</p>
<p>Expecially the lpath code is experimental, we will support some of xpath, but
only things that make sense for us; as compensation it is possible to hook in your
@@ -1442,7 +1483,7 @@ this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
files.</p>
<typing>
-a/b/c /*/c (todo: a/b/(pattern)/d)
+a/b/c /*/c
a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
</typing>
@@ -1457,48 +1498,86 @@ tex = tex or { }
xml.trace_lpath = false
xml.trace_print = false
+xml.trace_remap = false
--[[ldx--
-<p>First a hack to enable namespace resolving.</p>
+<p>First a hack to enable namespace resolving. A namespace is characterized by
+a <l n='url'/>. The following function associates a namespace prefix with a
+pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
+find based solution where we loop over an array of patterns. Less code and
+much cleaner.</p>
--ldx]]--
+xml.xmlns = { }
+
do
- xml.xmlns = { }
+ local parser = lpeg.P(false) -- printing shows that this has no side effects
+
+ --[[ldx--
+ <p>The next function associates a namespace prefix with an <l n='url'/>. This
+ normally happens independent of parsing.</p>
- local data = { }
+ <typing>
+ xml.registerns("mml","mathml")
+ </typing>
+ --ldx]]--
- function xml.registerns(namespace,pattern)
- data[#data+1] = { namespace:lower(), pattern:lower() }
+ function xml.registerns(namespace, pattern) -- pattern can be an lpeg
+ parser = parser + lpeg.C(lpeg.P(pattern:lower())) / namespace
end
+ --[[ldx--
+ <p>The next function also registers a namespace, but this time we map a
+ given namespace prefix onto a registered one, using the given
+ <l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
+
+ <typing>
+ xml.checkns("m","http://www.w3.org/mathml")
+ </typing>
+ --ldx]]--
+
function xml.checkns(namespace,url)
- url = url:lower()
- for i=1,#data do
- local d = data[i]
- if url:find(d[2]) then
- if namespace ~= d[1] then
- xml.xmlns[namespace] = d[1]
- end
- end
+ local ns = parser:match(url:lower())
+ if ns and namespace ~= ns then
+ xml.xmlns[namespace] = ns
end
end
+ --[[ldx--
+ <p>Next we provide a way to turn an <l n='url'/> into a registered
+ namespace. This used for the <t>xmlns</t> attribute.</p>
+
+ <typing>
+ resolvedns = xml.resolvens("http://www.w3.org/mathml")
+ </typing>
+
+ This returns <t>mml</t>.
+ --ldx]]--
+
function xml.resolvens(url)
- url = url:lower()
- for i=1,#data do
- local d = data[i]
- if url:find(d[2]) then
- return d[1]
- end
- end
- return ""
+ return parser:match(url:lower()) or ""
end
+ --[[ldx--
+ <p>A namespace in an element can be remapped onto the registered
+ one efficiently by using the <t>xml.xmlns</t> table.</p>
+ --ldx]]--
+
end
--[[ldx--
-<p>Next comes the loader. The dreadful doctype comes in many disguises:</p>
+<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
+such. This version is about twice as fast which is mostly due to the fact that
+we don't have to prepare the stream for cdata, doctype etc etc. This variant is
+is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
+took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
+the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
+<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
+
+<p>Next comes the parser. The rather messy doctype definition comes in many
+disguises so it is no surprice that later on have to dedicate quite some
+<l n='lpeg'/> code to it.</p>
<typing>
<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
@@ -1508,320 +1587,466 @@ end
<!DOCTYPE Something [ ... ] >
<!DOCTYPE Something >
</typing>
+
+<p>The code may look a bit complex but this is mostly due to the fact that we
+resolve namespaces and attach metatables. There is only one public function:</p>
+
+<typing>
+local x = xml.convert(somestring)
+</typing>
+
+<p>An optional second boolean argument tells this function not to create a root
+element.</p>
--ldx]]--
do
- -- Loading 12 cont-*.xml and keys-*.xml files totaling to 2.62 MBytes takes 1.1 sec
- -- on a windows vista laptop with dual core 7600 (2.3 Ghz), which is not that bad.
- -- Of this half time is spent on doctype etc parsing.
-
- local doctype_patterns = {
- "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\"%s+%b[])%s*>",
- "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\")%s*>",
- "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\"%s+%b[])%s*>",
- "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\")%s*>",
- "<!DOCTYPE%s+(.-%s%b[])%s*>",
- "<!DOCTYPE%s+(.-)%s*>"
- }
+ local remove, nsremap = table.remove, xml.xmlns
- -- We assume no "<" which is the lunatic part of the xml spec
- -- especially since ">" is permitted; otherwise we need a char
- -- by char parser ... more something for later ... normally
- -- entities will be used anyway.
+ local stack, top, dt, at, xmlns, errorstr = {}, {}, {}, {}, {}, nil
- -- data = data:gsub(nothing done) is still a copy so we find first
+ local mt = { __tostring = xml.text }
- local function prepare(data,text)
- -- pack (for backward compatibility)
- if type(data) == "table" then
- data = table.concat(data,"")
- end
- -- CDATA
- if data:find("<%!%[CDATA%[") then
- data = data:gsub("<%!%[CDATA%[(.-)%]%]>", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@cd@>%s</@cd@>",#text)
- end)
- end
- -- DOCTYPE
- if data:find("<!DOCTYPE ") then
- data = data:gsub("^(.-)(<[^%!%?])", function(a,b)
- if a:find("<!DOCTYPE ") then
- for _,v in ipairs(doctype_patterns) do
- a = a:gsub(v, function(d)
- text[#text+1] = d or ""
- return string.format("<@dd@>%s</@dd@>",#text)
- end)
- end
- end
- return a .. b
- end,1)
+ local function add_attribute(namespace,tag,value)
+ if tag == "xmlns" then
+ xmlns[#xmlns+1] = xml.resolvens(value)
+ at[tag] = value
+ elseif ns == "xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:" .. tag] = value
+ else
+ at[tag] = value
end
- -- comment / does not catch doctype
- data = data:gsub("<%!%-%-(.-)%-%->", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@cm@>%s</@cm@>",#text)
- end)
- -- processing instructions / altijd 1
- data = data:gsub("<%?(.-)%?>", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@pi@>%s</@pi@>",#text)
- end)
- return data, text
end
+ local function add_begin(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = { ns=namespace or "", nr=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
+ setmetatable(top, mt)
+ dt = top.dt
+ stack[#stack+1] = top
+ at = { }
+ end
+ local function add_end(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local toclose = remove(stack)
+ top = stack[#stack]
+ if #stack < 1 then
+ errorstr = string.format("nothing to close with %s", tag)
+ elseif toclose.tg ~= tag then -- no namespace check
+ errorstr = string.format("unable to close %s with %s", toclose.tg, tag)
+ end
+ dt = top.dt
+ dt[#dt+1] = toclose
+ if at.xmlns then
+ remove(xmlns)
+ end
+ end
+ local function add_empty(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = stack[#stack]
+ setmetatable(top, mt)
+ dt = top.dt
+ dt[#dt+1] = { ns=namespace or "", nr=resolved, tg=tag, at=at, dt={}, __p__ = top }
+ at = { }
+ if at.xmlns then
+ remove(xmlns)
+ end
+ end
+ local function add_text(text)
+ dt[#dt+1] = text
+ end
+ local function add_special(what, spacing, text)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ top = stack[#stack]
+ setmetatable(top, mt)
+ dt[#dt+1] = { special=true, ns="", tg=what, dt={text} }
+ end
+ local function set_message(txt)
+ errorstr = "garbage at the end of the file: " .. txt:gsub("([ \n\r\t]*)","")
+ end
+
+ local space = lpeg.S(' \r\n\t')
+ local open = lpeg.P('<')
+ local close = lpeg.P('>')
+ local squote = lpeg.S("'")
+ local dquote = lpeg.S('"')
+ local equal = lpeg.P('=')
+ local slash = lpeg.P('/')
+ local colon = lpeg.P(':')
+ local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-.')
+ local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1)
+ local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local name = name_yes + name_nop
+
+ local utfbom = lpeg.P('\000\000\254\255') + lpeg.P('\255\254\000\000') +
+ lpeg.P('\255\254') + lpeg.P('\254\255') + lpeg.P('\239\187\191') -- no capture
+
+ local spacing = lpeg.C(space^0)
+ local justtext = lpeg.C((1-open)^1)
+ local somespace = space^1
+ local optionalspace = space^0
+
+ local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local attribute = (somespace * name * optionalspace * equal * optionalspace * value) / add_attribute
+ local attributes = attribute^0
+
+ local text = justtext / add_text
+ local balanced = lpeg.P { "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" } -- taken from lpeg manual, () example
+
+ local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
+ local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
+ local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
+
+ local begincomment = open * lpeg.P("!--")
+ local endcomment = lpeg.P("--") * close
+ local begininstruction = open * lpeg.P("?")
+ local endinstruction = lpeg.P("?") * close
+ local begincdata = open * lpeg.P("![CDATA[")
+ local endcdata = lpeg.P("]]") * close
+
+ local someinstruction = lpeg.C((1 - endinstruction)^0)
+ local somecomment = lpeg.C((1 - endcomment )^0)
+ local somecdata = lpeg.C((1 - endcdata )^0)
+
+ local begindoctype = open * lpeg.P("!DOCTYPE")
+ local enddoctype = close
+ local publicdoctype = lpeg.P("PUBLIC") * somespace * value * somespace * value * somespace * balanced^0
+ local systemdoctype = lpeg.P("SYSTEM") * somespace * value * somespace * balanced^0
+ local simpledoctype = (1-close)^1 * balanced^0
+ local somedoctype = lpeg.C((somespace * lpeg.P(publicdoctype + systemdoctype + simpledoctype) * optionalspace)^0)
+
+ local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
+ local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
+ local cdata = (spacing * begincdata * somecdata * endcdata ) / function(...) add_special("@cd@",...) end
+ local doctype = (spacing * begindoctype * somedoctype * enddoctype ) / function(...) add_special("@dd@",...) end
+
+ -- nicer but slower:
+ --
+ -- local instruction = (lpeg.Cc("@pi@") * spacing * begininstruction * someinstruction * endinstruction) / add_special
+ -- local comment = (lpeg.Cc("@cm@") * spacing * begincomment * somecomment * endcomment ) / add_special
+ -- local cdata = (lpeg.Cc("@cd@") * spacing * begincdata * somecdata * endcdata ) / add_special
+ -- local doctype = (lpeg.Cc("@dd@") * spacing * begindoctype * somedoctype * enddoctype ) / add_special
+
+ local trailer = space^0 * (justtext/set_message)^0
- -- maybe we will move the @tg@ stuff to a dedicated key, say 'st'; this will speed up
- -- serializing and testing
+ -- comment + emptyelement + text + cdata + instruction + lpeg.V("parent"), -- 6.5 seconds on 40 MB database file
+ -- text + comment + emptyelement + cdata + instruction + lpeg.V("parent"), -- 5.8
+ -- text + lpeg.V("parent") + emptyelement + comment + cdata + instruction, -- 5.5
- function xml.convert(data,no_root,collapse)
- local crap = { }
- data, crap = prepare(data, crap)
- local nsremap = xml.xmlns
- local remove = table.remove
- local stack, top = {}, {}
- local i, j, errorstr = 1, 1, nil
+
+ local grammar = lpeg.P { "preamble",
+ preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * lpeg.V("parent") * trailer,
+ parent = beginelement * lpeg.V("children")^0 * endelement,
+ children = text + lpeg.V("parent") + emptyelement + comment + cdata + instruction,
+ }
+
+ function xml.convert(data, no_root) -- no collapse any more
+ stack, top, at, xmlns, errorstr, result = {}, {}, {}, {}, nil, nil
stack[#stack+1] = top
top.dt = { }
- local dt = top.dt
- local id = 0
- local namespaces = { }
- local mt = { __tostring = xml.text }
- while true do
- local ni, first, attributes, last, fulltag
- ni, j, first, fulltag, attributes, last = data:find("<(/-)([^%s%>/]+)%s*([^>]-)%s*(/-)>", j)
- if not ni then break end
- local namespace, tag = fulltag:match("^(.-):(.+)$")
- if attributes ~= "" then
- local t = {}
- for ns, tag, _, value in attributes:gmatch("(%w-):?(%w+)=([\"\'])(.-)%3") do
- if tag == "xmlns" then -- not ok yet
- namespaces[#stack] = xml.resolvens(value)
- elseif ns == "" then
- t[tag] = value
- elseif ns == "xmlns" then
- xml.checkns(tag,value)
- else
- t[tag] = value
- end
- end
- attributes = t
- else
- attributes = { }
- end
- if namespace then -- realtime remapping
- namespace = nsremap[namespace] or namespace
- else
- namespace, tag = namespaces[#stack] or "", fulltag
- end
- local text = data:sub(i, ni-1)
- if text == "" or (collapse and text:find("^%s*$")) then
- -- no need for empty text nodes, beware, also packs <a>x y z</a>
- -- so is not that useful unless used with empty elements
- else
- dt[#dt+1] = text
- end
- if first == "/" then
- -- end tag
- local toclose = remove(stack) -- remove top
- top = stack[#stack]
- namespaces[#stack] = nil
- if #stack < 1 then
- errorstr = string.format("nothing to close with %s", tag)
- break
- elseif toclose.tg ~= tag then -- no namespace check
- errorstr = string.format("unable to close %s with %s", toclose.tg, tag)
- break
- end
- if tag:find("^@..@$") then
- dt[1] = crap[tonumber(dt[1])] or ""
- end
- dt = top.dt
- dt[#dt+1] = toclose
- elseif last == "/" then
- -- empty element tag
- dt[#dt+1] = { ns = namespace, tg = tag, dt = { }, at = attributes, __p__ = top }
- -- setmetatable(top, { __tostring = xml.text })
- setmetatable(top, mt)
- else
- -- begin tag
- top = { ns = namespace, tg = tag, dt = { }, at = attributes, __p__ = stack[#stack] }
- -- setmetatable(top, { __tostring = xml.text })
- setmetatable(top, mt)
- dt = top.dt
- stack[#stack+1] = top
- end
- i = j + 1
- end
- if not errorstr then
- local text = data:sub(i)
- if dt and not text:find("^%s*$") then
- dt[#dt+1] = text
- end
- if #stack > 1 then
- errorstr = string.format("unclosed %s", stack[#stack].tg)
- end
+ dt = top.dt
+ if not data or data == "" then
+ errorstr = "empty xml file"
+ elseif not grammar:match(data) then
+ errorstr = "invalid xml file"
end
if errorstr then
- stack = { { tg = "error", dt = { errorstr } } }
- -- setmetatable(stack, { __tostring = xml.text })
+ result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={} } } }
setmetatable(stack, mt)
- end
- if no_root then
- return stack[1]
+ if xml.error_handler then xml.error_handler("load",errorstr) end
else
- local t = { ns = "", tg = '@rt@', dt = stack[1].dt }
- -- setmetatable(t, { __tostring = xml.text })
- setmetatable(t, mt)
- for k,v in ipairs(t.dt) do
- if type(v) == "table" and v.tg ~= "@pi@" and v.tg ~= "@dd@" and v.tg ~= "@cm@" then
- t.ri = k -- rootindex
+ result = stack[1]
+ end
+ if not no_root then
+ result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={} }
+ setmetatable(result, mt)
+ for k,v in ipairs(result.dt) do
+ if type(v) == "table" and not v.special then -- always table -)
+ result.ri = k -- rootindex
break
end
end
- return t
end
+ return result
end
- function xml.copy(old,tables,parent) -- fast one
- tables = tables or { }
- if old then
- local new = { }
- if not table[old] then
- table[old] = new
- end
- for i,v in pairs(old) do
- -- new[i] = (type(v) == "table" and (table[v] or xml.copy(v, tables, table))) or v
- if type(v) == "table" then
- new[i] = table[v] or xml.copy(v, tables, table)
- else
- new[i] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- return new
- else
- return { }
- end
+ --[[ldx--
+ <p>Packaging data in an xml like table is done with the following
+ function. Maybe it will go away (when not used).</p>
+ --ldx]]--
+
+ function xml.package(tag,attributes,data)
+ local ns, tg = tag:match("^(.-):?([^:]+)$")
+ local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
+ setmetatable(t, mt)
+ return t
end
+ xml.error_handler = (logs and logs.report) or print
+
end
-function xml.load(filename,collapse)
+--[[ldx--
+<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
+the whole file first. The function accepts a string representing
+a filename or a file handle.</p>
+--ldx]]--
+
+function xml.load(filename)
if type(filename) == "string" then
- local root, f = { }, io.open(filename,'r') -- no longer 'rb'
+ local root, f = { }, io.open(filename,'r')
if f then
- root = xml.convert(f:read("*all"),false,collapse)
+ root = xml.convert(f:read("*all"))
f:close()
+ else
+ -- if we want an error: root = xml.convert("")
end
- return root
+ return root -- no nil but an empty table if it fails
else
- return xml.convert(filename:read("*all"),false,collapse)
+ return xml.convert(filename:read("*all"))
end
end
-function xml.root(root)
- return (root.ri and root.dt[root.ri]) or root
+--[[ldx--
+<p>When we inject new elements, we need to convert strings to
+valid trees, which is what the next function does.</p>
+--ldx]]--
+
+function xml.toxml(data)
+ if type(data) == "string" then
+ local root = { xml.convert(data,true) }
+ return (#root > 1 and root) or root[1]
+ else
+ return data
+ end
end
-function xml.toxml(data,collapse)
- local t = { xml.convert(data,true,collapse) }
- if #t > 1 then
- return t
+--[[ldx--
+<p>For copying a tree we use a dedicated function instead of the
+generic table copier. Since we know what we're dealing with we
+can speed up things a bit. The second argument is not to be used!</p>
+--ldx]]--
+
+function xml.copy(old,tables)
+ if old then
+ tables = tables or { }
+ local new = { }
+ if not tables[old] then
+ tables[old] = new
+ end
+ for k,v in pairs(old) do
+ new[k] = (type(v) == "table" and (tables[v] or xml.copy(v, tables))) or v
+ end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
else
- return t[1]
+ return { }
end
end
-function xml.serialize(e, handle, textconverter, attributeconverter)
- handle = handle or (tex and tex.sprint) or io.write
- if not e then
- -- quit
- elseif e.command and xml.command then -- test for command == "" ?
- xml.command(e)
- elseif e.tg then
- local format, serialize = string.format, xml.serialize
- local ens, etg, eat, edt = e.ns, e.tg, e.at, e.dt
- -- no spaces, so no flush needed (check)
- if etg == "@pi@" then
- handle(format("<?%s?>",edt[1]))
- elseif etg == "@cm@" then
- handle(format("<!--%s-->",edt[1]))
- elseif etg == "@cd@" then
- handle(format("<![CDATA[%s]]>",edt[1]))
- elseif etg == "@dd@" then
- handle(format("<!DOCTYPE %s>",edt[1]))
- elseif etg == "@rt@" then
- serialize(edt,handle,textconverter,attributeconverter)
+--[[ldx--
+<p>In <l n='context'/> serializing the tree or parts of the tree is a major
+actitivity which is why the following function is pretty optimized resulting
+in a few more lines of code than needed. The variant that uses the formatting
+function for all components is about 15% slower than the concatinating
+alternative.</p>
+--ldx]]--
+
+do
+
+ -- todo: add <?xml version='1.0' standalone='yes'?> when not present
+
+ local fallbackhandle = (tex and tex.sprint) or io.write
+
+ function xml.serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
+ if not e then
+ -- quit
+ elseif not nocommands and e.command and xml.command then
+ xml.command(e)
else
- local ats = eat and next(eat) and { }
- if ats then
- if attributeconverter then
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ handle = handle or fallbackhandle
+ local etg = e.tg
+ if etg then
+ -- local format = string.format
+ if e.special then
+ local edt = e.dt
+ local spc = specialconverter and specialconverter[etg]
+ if spc then
+ local result = spc(edt[1])
+ if result then
+ handle(result)
+ else
+ -- no need to handle any further
+ end
+ elseif etg == "@pi@" then
+ -- handle(format("<?%s?>",edt[1]))
+ handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt)
+ elseif etg == "@cm@" then
+ -- handle(format("<!--%s-->",edt[1]))
+ handle("<!--" .. edt[1] .. "-->")
+ elseif etg == "@cd@" then
+ -- handle(format("<![CDATA[%s]]>",edt[1]))
+ handle("<![CDATA[" .. edt[1] .. "]]>")
+ elseif etg == "@dd@" then
+ -- handle(format("<!DOCTYPE %s>",edt[1]))
+ handle("<!DOCTYPE " .. edt[1] .. ">")
+ elseif etg == "@rt@" then
+ xml.serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
else
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,v)
- end
- end
- end
- if ens ~= "" then
- if edt and #edt > 0 then
+ local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { }
if ats then
- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
- else
- handle(format("<%s:%s>",ens,etg))
+ local format = string.format
+ if attributeconverter then
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ end
+ else
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,v)
+ end
+ end
end
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter)
+ if ern and xml.trace_remap then
+ if ats then
+ ats[#ats+1] = string.format("xmlns:remapped='%s'",ern)
+ else
+ ats = { string.format("xmlns:remapped='%s'",ern) }
+ end
end
- handle(format("</%s:%s>",ens,etg))
- else
- if ats then
- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
+ if ens ~= "" then
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s:%s>",ens,etg))
+ handle("<" .. ens .. ":" .. etg .. ">")
+ end
+ local serialize = xml.serialize
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
+ else
+ handle(e)
+ end
+ else
+ serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ end
+ -- handle(format("</%s:%s>",ens,etg))
+ handle("</" .. ens .. ":" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
+ handle("<%" .. ens .. ":" .. etg .. table.concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s:%s/>",ens,etg))
+ handle("<%" .. ens .. ":" .. "/>")
+ end
+ end
else
- handle(format("<%s:%s/>",ens,etg))
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s %s>",etg,table.concat(ats," ")))
+ handle("<" .. etg .. " " .. table.concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s>",etg))
+ handle("<" .. etg .. ">")
+ end
+ local serialize = xml.serialize
+ for i=1,#edt do
+ serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ -- handle(format("</%s>",etg))
+ handle("</" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s %s/>",etg,table.concat(ats," ")))
+ handle("<" .. etg .. table.concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s/>",etg))
+ handle("<" .. etg .. "/>")
+ end
+ end
end
end
- else
- if edt and #edt > 0 then
- if ats then
- handle(format("<%s %s>",etg,table.concat(ats," ")))
- else
- handle(format("<%s>",etg))
- end
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter)
- end
- handle(format("</%s>",etg))
+ elseif type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- if ats then
- handle(format("<%s %s/>",etg,table.concat(ats," ")))
- else
- handle(format("<%s/>",etg))
- end
+ handle(e)
+ end
+ else
+ local serialize = xml.serialize
+ for i=1,#e do
+ serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
end
- elseif type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
- else
- handle(e)
- end
- else
- for i=1,#e do
- xml.serialize(e[i],handle,textconverter,attributeconverter)
+ end
+
+ function xml.checkbom(root)
+ if root.ri then
+ local dt, found = root.dt, false
+ for k,v in ipairs(dt) do
+ if type(v) == "table" and v.special and v.tg == "@pi" and v.dt:find("xml.*version=") then
+ found = true
+ break
+ end
+ end
+ if not found then
+ table.insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ table.insert(dt, 2, "\n" )
+ end
end
end
+
end
-function xml.string(e,handle) -- weird one that may become obsolete
- if e.tg then
+--[[ldx--
+<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
+and then handle the lot.</p>
+--ldx]]--
+
+function xml.tostring(root) -- 25% overhead due to collecting
+ if root then
+ if type(root) == 'string' then
+ return root
+ elseif next(root) then
+ local result = { }
+ xml.serialize(root,function(s) result[#result+1] = s end)
+ return table.concat(result,"")
+ end
+end
+ return ""
+end
+
+--[[ldx--
+<p>The next function operated on the content only and needs a handle function
+that accepts a string.</p>
+--ldx]]--
+
+function xml.string(e,handle)
+ if not handle or (e.special and e.tg ~= "@rt@") then
+ -- nothing
+ elseif e.tg then
local edt = e.dt
if edt then
for i=1,#edt do
@@ -1833,6 +2058,21 @@ function xml.string(e,handle) -- weird one that may become obsolete
end
end
+--[[ldx--
+<p>How you deal with saving data depends on your preferences. For a 40 MB database
+file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
+
+<lines>
+1.3 : load data from file to string
+6.1 : convert string into tree
+5.3 : saving in file using xmlsave
+6.8 : converting to string using xml.tostring
+3.6 : saving converted string in file
+</lines>
+
+<p>The save function is given below.</p>
+--ldx]]--
+
function xml.save(root,name)
local f = io.open(name,"w")
if f then
@@ -1841,535 +2081,67 @@ function xml.save(root,name)
end
end
-function xml.stringify(root)
- if root then
- if type(root) == 'string' then
- return root
- elseif next(root) then
- local result = { }
- xml.serialize(root,function(s) result[#result+1] = s end)
- return table.concat(result,"")
- end
- end
- return ""
-end
-
-xml.tostring = xml.stringify
-
-do
-
- -- print
-
- local newline = lpeg.P("\n")
- local space = lpeg.P(" ")
- local content = lpeg.C((1-newline)^1)
-
- if tex then
-
- -- taco: we need a kind of raw print into tex, i.e. embedded \n's become lineendings
- -- for tex and an empty line a par; could be a c-wrapper around existing stuff; i
- -- played a lot with tex.print but that does not work ok (should be obeylines save)
-
- local buffer = {}
-
- local function cprint(s)
- buffer[#buffer+1] = s
- end
- local function nprint( )
- if #buffer > 0 then
- if xml.trace_print then
- texio.write_nl(string.format("tex.print : [[[%s]]]", table.join(buffer)))
- end
- tex.print(table.join(buffer))
- buffer = {}
- else
- if xml.trace_print then
- texio.write_nl(string.format("tex.print : [[[%s]]]", ""))
- end
- tex.print("")
- end
- end
- local function fprint()
- if #buffer > 0 then
- if xml.trace_print then
- texio.write_nl(string.format("tex.sprint: [[[%s]]]", table.join(buffer)))
- end
- tex.sprint(table.join(buffer))
- buffer = { }
- end
- end
-
- local line_n = newline / nprint
- local line_c = content / cprint
- local capture = (line_n + line_c)^0
-
- local function sprint(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root, sprint, nil, nil, true)
- end
- end
-
- function xml.sprint(root)
- buffer = {}
- sprint(root)
- if #buffer > 0 then
- nprint()
- end
- end
-
- xml.sflush = fprint
-
- else
-
- function xml.sprint(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- print(root)
- elseif next(root) then
- xml.serialize(root, xml.sprint, nil, nil, true)
- end
- end
-
- end
-
- function xml.tprint(root)
- if type(root) == "table" then
- for i=1,#root do
- xml.sprint(root[i])
- end
- elseif type(root) == "string" then
- xml.sprint(root)
- end
- end
-
- -- lines (looks hackery, but we cannot pass variables in capture functions)
-
- local buffer, flush = {}, nil
-
- local function cprint(s)
- buffer[#buffer+1] = s
- end
- local function nprint()
- flush()
- end
-
- local line_n = newline / nprint
- local line_c = content / cprint
- local capture = (line_n + line_c)^0
-
- function lines(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root, lines)
- end
- end
-
- function xml.lines(root)
- local result = { }
- flush = function()
- result[#result+1] = table.join(buffer)
- buffer = { }
- end
- buffer = {}
- lines(root)
- if #buffer > 0 then
- result[#result+1] = table.join(buffer)
- end
- return result
- end
+--[[ldx--
+<p>A few helpers:</p>
+--ldx]]--
+function xml.body(root)
+ return (root.ri and root.dt[root.ri]) or root
end
function xml.text(root)
- return (root and xml.stringify(root)) or ""
+ return (root and xml.tostring(root)) or ""
end
function xml.content(root)
return (root and root.dt and xml.tostring(root.dt)) or ""
end
-function xml.body(t) -- removes initial pi
- if t and t.dt and t.tg == "@rt@" then
- for k,v in ipairs(t.dt) do
- if type(v) == "table" and v.tg ~= "@pi@" then
- return v
- end
- end
- end
- return t
-end
+--[[ldx--
+<p>The next helper erases an element but keeps the table as it is,
+and since empty strings are not serialized (effectively) it does
+not harm. Copying the table would take more time. Usage:</p>
--- call: e[k] = xml.empty() or xml.empty(e,k)
+<typing>
+dt[k] = xml.empty() or xml.empty(dt,k)
+</typing>
+--ldx]]--
-function xml.empty(e,k) -- erases an element but keeps the table intact
- if e and k then
- e[k] = ""
- return e[k]
+function xml.empty(dt,k)
+ if dt and k then
+ dt[k] = ""
+ return dt[k]
else
return ""
end
end
--- call: e[k] = xml.assign(t) or xml.assign(e,k,t)
+--[[ldx--
+<p>The next helper assigns a tree (or string). Usage:</p>
+
+<typing>
+dt[k] = xml.assign(root) or xml.assign(dt,k,root)
+</typing>
+--ldx]]--
-function xml.assign(e,k,t) -- assigns xml tree / more testing will be done
- if e and k then
- if type(t) == "table" then
- e[k] = xml.body(t)
- else
- e[k] = t -- no parsing
- end
- return e[k]
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k] = (type(root) == "table" and xml.body(root)) or root
+ return dt[k]
else
- return xml.body(t)
+ return xml.body(root)
end
end
--- 0=nomatch 1=match 2=wildcard 3=ancestor
-
--- "tag"
--- "tag1/tag2/tag3"
--- "*/tag1/tag2/tag3"
--- "/tag1/tag2/tag3"
--- "/tag1/tag2|tag3"
--- "tag[@att='value']
--- "tag1|tag2[@att='value']
-
-function xml.tag(e)
- return e.tg or ""
-end
-
-function xml.att(e,a)
- return (e.at and e.at[a]) or ""
-end
-
-xml.attribute = xml.att
-
---~ local cache = { }
-
---~ local function f_fault ( ) return 0 end
---~ local function f_wildcard( ) return 2 end
---~ local function f_result (b) if b then return 1 else return 0 end end
-
---~ function xml.lpath(str) --maybe @rt@ special
---~ if not str or str == "" then
---~ str = "*"
---~ end
---~ local m = cache[str]
---~ if not m then
---~ -- todo: text()
---~ if type(str) == "table" then
---~ if xml.trace_lpath then print("lpath", "table" , "inherit") end
---~ m = str
---~ elseif str == "/" then
---~ if xml.trace_lpath then print("lpath", "/", "root") end
---~ m = false
---~ elseif str == "*" then
---~ if xml.trace_lpath then print("lpath", "no string or *", "wildcard") end
---~ m = true
---~ else
---~ str = str:gsub("^//","") -- any
---~ if str == "" then
---~ if xml.trace_lpath then print("lpath", "//", "wildcard") end
---~ m = true
---~ else
---~ m = { }
---~ if not str:find("^/") then
---~ m[1] = 2
---~ end
---~ for v in str:gmatch("([^/]+)") do
---~ if v == "" or v == "*" then
---~ if #m > 0 then -- when not, then we get problems with root being second (after <?xml ...?> (we could start at dt[2])
---~ if xml.trace_lpath then print("lpath", "empty or *", "wildcard") end
---~ m[#m+1] = 2
---~ end
---~ elseif v == ".." then
---~ if xml.trace_lpath then print("lpath", "..", "ancestor") end
---~ m[#m+1] = 3
---~ else
---~ local a, b = v:match("^(.+)::(.-)$")
---~ if a and b then
---~ if a == "ancestor" then
---~ if xml.trace_lpath then print("lpath", a, "ancestor") end
---~ m[#m+1] = 3
---~ -- todo: b
---~ elseif a == "pi" then
---~ if xml.trace_lpath then print("lpath", a, "processing instruction") end
---~ local expr = "^" .. b .. " "
---~ m[#m+1] = function(e)
---~ if e.tg == '@pi@' and e.dt[1]:find(expr) then
---~ return 6
---~ else
---~ return 0
---~ end
---~ end
---~ end
---~ else
---~ local n, a, t = v:match("^(.-)%[@(.-)=(.-)%]$")
---~ if n and a and t then
---~ -- todo: namespace, negate
---~ -- t = t:gsub("^\'(.*)\'$", "%1")
---~ -- t = t:gsub("^\"(.*)\"$", "%1")
---~ -- t = t:sub(2,-2) -- "" or '' mandate
---~ t = t:gsub("^([\'\"])(.-)%1$", "%2")
---~ if n:find("|") then
---~ local tt = n:split("|")
---~ if xml.trace_lpath then print("lpath", "match", t, n) end
---~ m[#m+1] = function(e,i)
---~ for i=1,#tt do
---~ if e.at and e.tg == tt[i] and e.at[a] == t then return 1 end
---~ end
---~ return 0
---~ end
---~ else
---~ if xml.trace_lpath then print("lpath", "match", t, n) end
---~ m[#m+1] = function(e)
---~ if e.at and e.ns == s and e.tg == n and e.at[a] == t then
---~ return 1
---~ else
---~ return 0
---~ end
---~ end
---~ end
---~ else -- todo, better tracing (string.format, ook negate etc)
---~ local negate = v:sub(1,1) == '^'
---~ if negate then v = v:sub(2) end
---~ if v:find("|") then
---~ local t = { }
---~ for s in v:gmatch("([^|]+)") do
---~ local ns, tg = s:match("^(.-):(.+)$")
---~ if tg == "*" then
---~ if xml.trace_lpath then print("lpath", "or wildcard", ns, tg) end
---~ t[#t+1] = function(e) return e.ns == ns end
---~ elseif tg then
---~ if xml.trace_lpath then print("lpath", "or match", ns, tg) end
---~ t[#t+1] = function(e) return e.ns == ns and e.tg == tg end
---~ else
---~ if xml.trace_lpath then print("lpath", "or match", s) end
---~ t[#t+1] = function(e) return e.ns == "" and e.tg == s end
---~ end
---~ end
---~ if negate then
---~ m[#m+1] = function(e)
---~ for i=1,#t do if t[i](e) then return 0 end end return 1
---~ end
---~ else
---~ m[#m+1] = function(e)
---~ for i=1,#t do if t[i](e) then return 1 end end return 0
---~ end
---~ end
---~ else
---~ if xml.trace_lpath then print("lpath", "match", v) end
---~ local ns, tg = v:match("^(.-):(.+)$")
---~ if not tg then ns, tg = "", v end
---~ if tg == "*" then
---~ if ns ~= "" then
---~ m[#m+1] = function(e)
---~ if ns == e.ns then return 1 else return 0 end
---~ end
---~ end
---~ elseif negate then
---~ m[#m+1] = function(e)
---~ if ns == e.ns and tg == e.tg then return 0 else return 1 end
---~ end
---~ else
---~ m[#m+1] = function(e)
---~ if ns == e.ns and tg == e.tg then return 1 else return 0 end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ if xml.trace_lpath then
---~ print("# lpath criteria:", (type(m) == "table" and #m) or "none")
---~ end
---~ cache[str] = m
---~ end
---~ return m
---~ end
-
---~ -- if handle returns true, then quit
-
---~ function xml.traverse(root,pattern,handle,reverse,index,wildcard)
---~ if not root then -- error
---~ return false
---~ elseif pattern == false then -- root
---~ handle(root,root.dt,root.ri)
---~ return false
---~ elseif pattern == true then -- wildcard
---~ local traverse = xml.traverse
---~ local rootdt = root.dt
---~ if rootdt then
---~ local start, stop, step = 1, #rootdt, 1
---~ if reverse then
---~ start, stop, step = stop, start, -1
---~ end
---~ for k=start,stop,step do
---~ if handle(root,rootdt,root.ri or k) then return false end
---~ if not traverse(rootdt[k],true,handle,reverse) then return false end
---~ end
---~ end
---~ return false
---~ elseif root and root.dt then
---~ index = index or 1
---~ local match = pattern[index] or f_wildcard
---~ local traverse = xml.traverse
---~ local rootdt = root.dt
---~ local start, stop, step = 1, #rootdt, 1
---~ if reverse and index == #pattern then -- maybe no index test here / error?
---~ start, stop, step = stop, start, -1
---~ end
---~ for k=start,stop,step do
---~ local e = rootdt[k]
---~ if e.tg then
---~ local m = (type(match) == "function" and match(e,root)) or match
---~ if m == 1 then -- match
---~ if index < #pattern then
---~ if not traverse(e,pattern,handle,reverse,index+1) then return false end
---~ else
---~ if handle(root,rootdt,root.ri or k) then
---~ return false
---~ end
---~ -- tricky, where do we pick up, is this ok now
---~ if pattern[1] == 2 then -- start again with new root (we need a way to inhibit this)
---~ if not traverse(e,pattern,handle,reverse,1) then return false end
---~ end
---~ end
---~ elseif m == 2 then -- wildcard
---~ if index < #pattern then
---~ -- <parent><a><b></b><c></c></a></parent> : "a" (true) "/a" (true) "b" (true) "/b" (false)
---~ -- not good yet, we need to pick up any prev level which is 2
---~ local p = pattern[2]
---~ if index == 1 and p then
---~ local mm = (type(p) == "function" and p(e,root)) or p -- pattern[2](e,root)
---~ if mm == 1 then
---~ if #pattern == 2 then
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ -- hack
---~ if pattern[1] == 2 then -- start again with new root (we need a way to inhibit this)
---~ if not traverse(e,pattern,handle,reverse,1) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,3) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
---~ end
---~ elseif handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 3 then -- ancestor
---~ local ep = e.__p__
---~ if index < #pattern then
---~ if not traverse(ep,pattern,handle,reverse,index+1) then return false end
---~ elseif handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 4 then -- just root
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 6 then -- pi
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif wildcard then -- maybe two kind of wildcards: * ** //
---~ if not traverse(e,pattern,handle,reverse,index,wildcard) then return false end
---~ end
---~ end
---~ end
---~ end
---~ return true
---~ end
-
---~ Y a/b
---~ Y /a/b
---~ Y a/*/b
---~ Y a//b
---~ Y child::
---~ Y .//
---~ Y ..
---~ N id("tag")
---~ Y parent::
---~ Y child::
---~ N preceding-sibling:: (same name)
---~ N following-sibling:: (same name)
---~ N preceding-sibling-of-self:: (same name)
---~ N following-sibling-or-self:: (same name)
---~ Y ancestor::
---~ N descendent::
---~ N preceding::
---~ N following::
---~ N self::node()
---~ N node() == alles
---~ N a[position()=5]
---~ Y a[5]
---~ Y a[-5]
---~ N a[first()]
---~ N a[last()]
---~ Y a/(b|c|d)/e/f
---~ N (c/d|e)
---~ Y a/b[@bla]
---~ Y a/b[@bla='oeps']
---~ Y a/b[@bla=='oeps']
---~ Y a/b[@bla<>'oeps']
---~ Y a/b[@bla!='oeps']
---~ Y a/b/@bla
-
---~ Y ^/a/c (root)
---~ Y ^^/a/c (docroot)
---~ Y root::a/c (docroot)
-
---~ no wild card functions (yet)
-
---~ s = "/a//b/*/(c|d|e)/(f|g)/h[4]/h/child::i/j/(a/b)/p[-1]/q[4]/ancestor::q/r/../s/./t[@bla='true']/k"
-
--- // == /**/
--- / = ^ (root)
+--[[ldx--
+<p>We've now arrived at an intersting part: accessing the tree using a subset
+of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
+will explain more about its usage in other documents.</p>
+--ldx]]--
do
- function analyze(str)
- if not str then
- return ""
- else
- local tmp, result, map, key = { }, { }, { }, str
- str = str:gsub("(%b[])", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
- str = str:gsub("(%b())", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
- str = str:gsub("(%^+)([^/])", "%1/%2")
- str = str:gsub("//+", "/**/")
- str = str:gsub(".*root::", "^/")
- str = str:gsub("child::", "")
- str = str:gsub("ancestor::", "../")
- str = str:gsub("self::", "./")
- str = str:gsub("^/", "^/")
- for s in str:gmatch("([^/]+)") do
- s = s:gsub("%[%[(%d+)%]%]",function(n) return tmp[tonumber(n)] end)
- result[#result+1] = s
- end
- cache[key] = result
- return result
- end
- end
-
- actions = {
+ local actions = {
[10] = "stay",
[11] = "parent",
[12] = "subtree root",
@@ -2381,112 +2153,168 @@ do
[21] = "match one of",
[22] = "match and attribute eq",
[23] = "match and attribute ne",
- [23] = "match and attribute present",
+ [24] = "match one of and attribute eq",
+ [25] = "match one of and attribute ne",
+ [27] = "has attribute",
+ [28] = "has value",
+ [29] = "fast match",
[30] = "select",
[40] = "processing instruction",
}
- function compose(result)
- if not result or #result == 0 then
+ local map = { }
+
+ local space = lpeg.S(' \r\n\t')
+ local squote = lpeg.S("'")
+ local dquote = lpeg.S('"')
+ local lparent = lpeg.P('(')
+ local rparent = lpeg.P(')')
+ local atsign = lpeg.P('@')
+ local lbracket = lpeg.P('[')
+ local rbracket = lpeg.P(']')
+ local exclam = lpeg.P('!')
+ local period = lpeg.P('.')
+ local eq = lpeg.P('==') + lpeg.P('=')
+ local ne = lpeg.P('<>') + lpeg.P('!=')
+ local star = lpeg.P('*')
+ local slash = lpeg.P('/')
+ local colon = lpeg.P(':')
+ local bar = lpeg.P('|')
+ local hat = lpeg.P('^')
+ local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-')
+ local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1)
+ local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local name = name_yes + name_nop
+ local number = lpeg.C((lpeg.S('+-')^0 * lpeg.R('09')^1)) / tonumber
+ local names = (bar^0 * name)^1
+ local morenames = name * (bar^0 * name)^1
+ local instructiontag = lpeg.P('pi::')
+ local spacing = lpeg.C(space^0)
+ local somespace = space^1
+ local optionalspace = space^0
+ local text = lpeg.C(valid^0)
+ local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local empty = 1-slash
+
+ local is_eq = lbracket * atsign * name * eq * value * rbracket
+ local is_ne = lbracket * atsign * name * ne * value * rbracket
+ local is_attribute = lbracket * atsign * name * rbracket
+ local is_value = lbracket * value * rbracket
+ local is_number = lbracket * number * rbracket
+
+ local is_one = name
+ local is_none = exclam * name
+ local is_one_of = ((lparent * names * rparent) + morenames)
+ local is_none_of = exclam * ((lparent * names * rparent) + morenames)
+
+ local stay = (period )
+ local parent = (period * period ) / function( ) map[#map+1] = { 11 } end
+ local subtreeroot = (slash + hat ) / function( ) map[#map+1] = { 12 } end
+ local documentroot = (hat * hat ) / function( ) map[#map+1] = { 13 } end
+ local any = (star ) / function( ) map[#map+1] = { 14 } end
+ local many = (star * star ) / function( ) map[#map+1] = { 15 } end
+ local initial = (hat * hat * hat ) / function( ) map[#map+1] = { 16 } end
+
+ local match = (is_one ) / function(...) map[#map+1] = { 20, true , ... } end
+ local match_one_of = (is_one_of ) / function(...) map[#map+1] = { 21, true , ... } end
+ local dont_match = (is_none ) / function(...) map[#map+1] = { 20, false, ... } end
+ local dont_match_one_of = (is_none_of ) / function(...) map[#map+1] = { 21, false, ... } end
+
+ local match_and_eq = (is_one * is_eq ) / function(...) map[#map+1] = { 22, true , ... } end
+ local match_and_ne = (is_one * is_ne ) / function(...) map[#map+1] = { 23, true , ... } end
+ local dont_match_and_eq = (is_none * is_eq ) / function(...) map[#map+1] = { 22, false, ... } end
+ local dont_match_and_ne = (is_none * is_ne ) / function(...) map[#map+1] = { 23, false, ... } end
+
+ local match_one_of_and_eq = (is_one_of * is_eq ) / function(...) map[#map+1] = { 24, true , ... } end
+ local match_one_of_and_ne = (is_one_of * is_ne ) / function(...) map[#map+1] = { 25, true , ... } end
+ local dont_match_one_of_and_eq = (is_none_of * is_eq ) / function(...) map[#map+1] = { 24, false, ... } end
+ local dont_match_one_of_and_ne = (is_none_of * is_ne ) / function(...) map[#map+1] = { 25, false, ... } end
+
+ local has_attribute = (is_one * is_attribute) / function(...) map[#map+1] = { 27, true , ... } end
+ local has_value = (is_one * is_value ) / function(...) map[#map+1] = { 28, true , ... } end
+ local dont_has_attribute = (is_none * is_attribute) / function(...) map[#map+1] = { 27, false, ... } end
+ local dont_has_value = (is_none * is_value ) / function(...) map[#map+1] = { 28, false, ... } end
+ local position = (is_one * is_number ) / function(...) map[#map+1] = { 30, true, ... } end
+ local dont_position = (is_none * is_number ) / function(...) map[#map+1] = { 30, false, ... } end
+
+ local instruction = (instructiontag * text ) / function(...) map[#map+1] = { 40, ... } end
+ local nothing = (empty ) / function( ) map[#map+1] = { 15 } end -- 15 ?
+ local crap = (1-slash)^1
+
+ -- a few ugly goodies:
+
+ local docroottag = lpeg.P('^^') / function( ) map[#map+1] = { 12 } end
+ local subroottag = lpeg.P('^') / function( ) map[#map+1] = { 13 } end
+ local roottag = lpeg.P('root::') / function( ) map[#map+1] = { 12 } end
+ local parenttag = lpeg.P('parent::') / function( ) map[#map+1] = { 11 } end
+ local childtag = lpeg.P('child::')
+ local selftag = lpeg.P('self::')
+
+ -- there will be more and order will be optimized
+
+ local selector = (
+ instruction +
+ many + any +
+ parent + stay +
+ dont_position + position +
+ dont_match_one_of_and_eq + dont_match_one_of_and_ne +
+ match_one_of_and_eq + match_one_of_and_ne +
+ dont_match_and_eq + dont_match_and_ne +
+ match_and_eq + match_and_ne +
+ has_attribute + has_value +
+ dont_match_one_of + match_one_of +
+ dont_match + match +
+ crap + empty
+ )
+
+ local grammar = lpeg.P { "startup",
+ startup = (initial + documentroot + subtreeroot + roottag + docroottag + subroottag)^0 * lpeg.V("followup"),
+ followup = ((slash + parenttag + childtag + selftag)^0 * selector)^1,
+ }
+
+ function compose(str)
+ if not str or str == "" then
-- wildcard
return true
- elseif #result == 1 then
- local r = result[1][1]
- if r == "14" or r == "15" then
- -- wildcard
+ elseif str == '/' then
+ -- root
+ return false
+ else
+ map = { }
+ grammar:match(str)
+ if #map == 0 then
return true
- elseif r == "12" then
- -- root
- return false
- end
- end
- local map = { }
- for r=1,#result do
- local ri = result[r]
- if ri == "." then
- -- skip
- elseif ri == ".." then
- map[#map+1] = { 11 }
- elseif ri == "^" then
- map[#map+1] = { 12 }
- elseif ri == "^^" then
- map[#map+1] = { 13 }
- elseif ri == "*" then
- map[#map+1] = { 14 }
- elseif ri == "**" then
- map[#map+1] = { 15 }
else
- local m = ri:match("^%((.*)%)$") -- (a|b|c)
- if m or ri:find('|') then
- m = m or ri
- if m:find("[%[%]%(%)%/]") then -- []()/
- -- error
- else
- local t = { 21 }
- for s in m:gmatch("([^|])") do
- local ns, tg = s:match("^(.-):?([^:]+)$")
- t[#t+1] = ns
- t[#t+1] = tg
- end
- map[#map+1] = t
- end
- else
- local s, f = ri:match("^(.-)%[%s*(.+)%s*%]$") --aaa[bbb]
- if s and f then
- local ns, tg = s:match("^(.-):?([^:]+)$")
- local at, op, vl = f:match("^@(.-)([!=<>]?)([^!=<>]+)$") -- [@a=='b']
- if op and op ~= "" then
- if op == '=' or op == '==' then
- map[#map+1] = { 22, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$", "%2")) }
- elseif op == '<>' or op == '!=' then
- map[#map+1] = { 23, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$", "%2")) }
- else
- -- error
- end
- elseif f:find("^([%-%+%d]+)$")then
- map[#map+1] = { 30, ns, tg, tonumber(f) }
- elseif vl ~= "" then
- map[#map+1] = { 24, ns, tg, vl }
- end
- else
- local pi = ri:match("^pi::(.-)$")
- if pi then
- map[#map+1] = { 40, pi }
- else
- map[#map+1] = { 20, ri:match("^(.-):?([^:]+)$") }
- end
+ local m = map[1][1]
+ if #map == 1 then
+ if m == 14 or m == 15 then
+ -- wildcard
+ return true
+ elseif m == 12 then
+ -- root
+ return false
end
+ elseif #map == 2 and m == 12 and map[2][1] == 20 then
+ return { { 29, map[2][2], map[2][3] } }
end
+ if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
+ table.insert(map, 1, { 16 })
+ end
+ return map
end
end
- -- if we have a symbol, we can prepend that to the string, which is faster
- local mm = map[1] or { }
- local r = mm[1] or 0
- if #map == 1 then
- if r == 14 or r == 15 then
- -- wildcard
- return true
- elseif r == 12 then
- -- root
- return false
- end
- end
- if r ~= 11 and r ~= 12 and r ~= 13 and r ~= 14 and r ~= 15 then
- table.insert(map, 1, { 16 })
- end
- return map
end
- cache = { }
+ local cache = { }
- function xml.lpath(pattern)
+ function xml.lpath(pattern,trace)
if type(pattern) == "string" then
local result = cache[pattern]
if not result then
- result = compose(analyze(pattern))
+ result = compose(pattern)
cache[pattern] = result
end
- if xml.trace_lpath then
+ if trace or xml.trace_lpath then
xml.lshow(result)
end
return result
@@ -2495,23 +2323,58 @@ do
end
end
- function xml.lshow(pattern)
+ local fallbackreport = (texio and texio.write) or io.write
+
+ function xml.lshow(pattern,report)
+ report = report or fallbackreport
local lp = xml.lpath(pattern)
if lp == false then
- print("root")
+ report(" -: root\n")
elseif lp == true then
- print("wildcard")
+ report(" -: wildcard\n")
else
- if type(pattern) ~= "table" then
- print("pattern: " .. tostring(pattern))
+ if type(pattern) == "string" then
+ report(string.format("pattern: %s\n",pattern))
end
for k,v in ipairs(lp) do
- print(k,actions[v[1]],table.join(v," ",2))
+ if #v > 1 then
+ local t = { }
+ for i=2,#v do
+ local vv = v[i]
+ if type(vv) == "string" then
+ t[#t+1] = (vv ~= "" and vv) or "#"
+ elseif type(vv) == "boolean" then
+ t[#t+1] = (vv and "==") or "<>"
+ end
+ end
+ report(string.format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," ")))
+ else
+ report(string.format("%2i: %s %s\n", k,v[1],actions[v[1]]))
+ end
end
end
end
- function xml.traverse(root,pattern,handle,reverse,index,wildcard)
+end
+
+--[[ldx--
+<p>An <l n='lpath'/> is converted to a table with instructions for traversing the
+tree. Hoever, simple cases are signaled by booleans. Because we don't know in
+advance what we want to do with the found element the handle gets three arguments:</p>
+
+<lines>
+<t>r</t> : the root element of the data table
+<t>d</t> : the data table of the result
+<t>t</t> : the index in the data table of the result
+</lines>
+
+<p> Access to the root and data table makes it possible to construct insert and delete
+functions.</p>
+--ldx]]--
+
+do
+
+ function xml.traverse(root,pattern,handle,reverse,index,parent,wildcard)
if not root then -- error
return false
elseif pattern == false then -- root
@@ -2531,103 +2394,172 @@ do
end
end
return false
- elseif root and root.dt then
+ elseif root.dt then
index = index or 1
local action = pattern[index]
local command = action[1]
- if (command == 16 or command == 12) and index == 1 then -- initial
- wildcard = true
- index = index + 1
- action = pattern[index]
- command = action[1]
- end
- local traverse = xml.traverse
- local rootdt = root.dt
- local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1
- if command == 30 then
- if action[4] < 0 then
- start, stop, step = stop, start, -1
- dn = -1
+ if command == 29 then -- fast case /oeps
+ local rootdt = root.dt
+ for k=1,#rootdt do
+ local e = rootdt[k]
+ local ns, tg = e.rn or e.ns, e.tg
+ if ns == action[2] and tg == action[3] then
+ if handle(root,rootdt,k) then return false end
+ end
end
- elseif reverse and index == #pattern then
- start, stop, step = stop, start, -1
- end
- for k=start,stop,step do
- local e = rootdt[k]
- local ns, tg = e.ns, e.tg
- if tg then
+ elseif command == 11 then -- parent
+ local ep = root.__p__ or parent
+ if index < #pattern then
+ if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ else
+ if (command == 16 or command == 12) and index == 1 then -- initial
+ wildcard = true
+ index = index + 1
+ action = pattern[index]
+ command = action and action[1] or 0 -- something is wrong
+ end
+ if command == 11 then -- parent
+ local ep = root.__p__ or parent
+ if index < #pattern then
+ if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ else
+ local traverse = xml.traverse
+ local rootdt = root.dt
+ local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1
if command == 30 then
- if ns == action[2] and tg == action[3] then
- n = n + dn
- if n == action[4] then
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- break
- end
- elseif wildcard then
- if not traverse(e,pattern,handle,reverse,index,true) then return false end
+ if action[5] < 0 then
+ start, stop, step = stop, start, -1
+ dn = -1
end
- else
- local matched = false
- if command == 20 then -- match
- matched = ns == action[2] and tg == action[3]
- elseif command == 21 then -- match one of
- for i=2,#action,2 do
- if ns == action[i] and tg == action[i+1] then
- matched = true
- break
+ elseif reverse and index == #pattern then
+ start, stop, step = stop, start, -1
+ end
+ for k=start,stop,step do
+ local e = rootdt[k]
+ local ns, tg = e.rn or e.ns, e.tg
+ if tg then
+ if command == 30 then
+ local matched = ns == action[3] and tg == action[4]
+ if action[2] then matched = not matched end
+ if matched then
+ n = n + dn
+ if n == action[5] then
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ break
+ end
+ elseif wildcard then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
end
- end
- elseif command == 22 then -- eq
- matched = ns == action[2] and tg == action[3] and e.at[action[4]] == action[5]
- elseif command == 23 then -- ne
- matched = ns == action[2] and tg == action[3] and e.at[action[4]] ~= action[5]
- elseif command == 24 then -- present
- matched = ns == action[2] and tg == action[3] and e.at[action[4]]
- end
- if matched then -- combine tg test and at test
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- elseif command == 14 then -- any
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- elseif command == 15 then -- many
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
else
- if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
- end
- elseif command == 11 then -- parent
- local ep = e.__p__
- if index < #pattern then
- if not traverse(ep,pattern,handle,reverse,index+1) then return false end
- elseif handle(root,rootdt,k) then
- return false
- end
- break
- elseif command == 40 and tg == "@pi@" then -- pi
- local pi = action[2]
- if pi ~= "" then
- local pt = e.dt[1]
- if pt and pt:find(pi) then
- if handle(root,rootdt,k) then
+ local matched, multiple = false, false
+ if command == 20 then -- match
+ matched = ns == action[2] and tg == action[3]
+ if action[2] then matched = not matched end
+ elseif command == 21 then -- match one of
+ multiple = true
+ for i=2,#action,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if action[2] then matched = not matched end
+ elseif command == 22 then -- eq
+ matched = ns == action[3] and tg == action[4]
+ if action[2] then matched = not matched end
+ matched = matched and e.at[action[6]] == action[7]
+ elseif command == 23 then -- ne
+ matched = ns == action[3] and tg == action[4]
+ if action[2] then matched = not matched end
+ matched = mached and e.at[action[6]] ~= action[7]
+ elseif command == 24 then -- one of eq
+ multiple = true
+ for i=3,#action-2,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if action[2] then matched = not matched end
+ matched = matched and e.at[action[#action-1]] == action[#action]
+ elseif command == 25 then -- one of ne
+ multiple = true
+ for i=3,#action-2,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if action[2] then matched = not matched end
+ matched = matched and e.at[action[#action-1]] ~= action[#action]
+ elseif command == 27 then -- has attribute
+ local ans = action[3]
+ matched = ns == action[3] and tg == action[4]
+ if action[2] then matched = not matched end
+ matched = matched and e.at[action[5]]
+ elseif command == 28 then -- has value
+ local edt = e.dt
+ matched = ns == action[3] and tg == action[4]
+ if action[2] then matched = not matched end
+ matched = matched and edt and edt[1] == action[5]
+ end
+ if matched then -- combine tg test and at test
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ if wildcard and multiple then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
+ end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ elseif command == 14 then -- any
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ elseif command == 15 then -- many
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root,true) then return false end
+ end
+ -- not here : 11
+ elseif command == 11 then -- parent
+ local ep = e.__p__ or parent
+ if index < #pattern then
+ if not traverse(ep,pattern,handle,reverse,root,index+1) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ elseif command == 40 and e.special and tg == "@pi@" then -- pi
+ local pi = action[2]
+ if pi ~= "" then
+ local pt = e.dt[1]
+ if pt and pt:find(pi) then
+ if handle(root,rootdt,k) then
+ return false
+ end
+ end
+ elseif handle(root,rootdt,k) then
return false
end
+ elseif wildcard then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
end
- elseif handle(root,rootdt,k) then
- return false
end
- elseif wildcard then
- if not traverse(e,pattern,handle,reverse,index,true) then return false end
+ else
+ -- not here : 11
+ if command == 11 then -- parent
+ local ep = e.__p__ or parent
+ if index < #pattern then
+ if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ break -- else loop
+ end
end
end
end
@@ -2636,15 +2568,71 @@ do
return true
end
+end
+
+--[[ldx--
+<p>Next come all kind of locators and manipulators. The most generic function here
+is <t>xml.filter(root,pattern)</t>. All registers functions in the filters namespace
+can be path of a search path, as in:</p>
+
+<typing>
+local r, d, k = xml.filter(root,"/a/b/c/position(4)"
+</typing>
+--ldx]]--
+
+do
+
local traverse, lpath, convert = xml.traverse, xml.lpath, xml.convert
xml.filters = { }
+ --[[ldx--
+ <p>For splitting the filter function from the path specification, we can
+ use string matching or lpeg matching. Here the difference in speed is
+ neglectable but the lpeg variant is more robust.</p>
+ --ldx]]--
+
+ -- function xml.filter(root,pattern)
+ -- local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$")
+ -- if fun then
+ -- return (xml.filters[fun] or xml.filters.default)(root,pat,arg)
+ -- else
+ -- pat, arg = pattern:match("^(.+)/@(.-)$")
+ -- if arg then
+ -- return xml.filters.attributes(root,pat,arg)
+ -- else
+ -- return xml.filters.default(root,pattern)
+ -- end
+ -- end
+ -- end
+
+ -- not faster but hipper ... although ... i can't get rid of the trailing / in the path
+
+ local name = (lpeg.R("az","AZ")+lpeg.R("_-"))^1
+ local path = lpeg.C(((1-lpeg.P('/'))^0 * lpeg.P('/'))^1)
+ local argument = lpeg.P { "(" * lpeg.C(((1 - lpeg.S("()")) + lpeg.V(1))^0) * ")" }
+ local action = lpeg.Cc(1) * path * lpeg.C(name) * argument
+ local attribute = lpeg.Cc(2) * path * lpeg.P('@') * lpeg.C(name)
+
+ local parser = action + attribute
+
+ function xml.filter(root,pattern)
+ local kind, a, b, c = parser:match(pattern)
+ if kind == 1 then
+ return (xml.filters[b] or xml.filters.default)(root,a,c)
+ elseif kind == 2 then
+ return xml.filters.attributes(root,a,b)
+ else
+ return xml.filters.default(root,pattern)
+ end
+ end
+
function xml.filters.default(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end)
return dt and dt[dk], rt, dt, dk
end
+
function xml.filters.reverse(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse')
@@ -2698,17 +2686,14 @@ do
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk, i = r, d, k, i-1 return i == 0 end, reverse)
if i == 0 then
return dt and dt[dk], rt, dt, dk
- else
- return nil, nil, nil, nil
end
- else
- return nil, nil, nil, nil
end
+ return nil, nil, nil, nil
end
function xml.filters.attributes(root,pattern,arguments)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
- local ekat = dt and dt[dk] and dt[dk].at
+ local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
if ekat then
if arguments then
return ekat[arguments] or "", rt, dt, dk
@@ -2722,69 +2707,33 @@ do
function xml.filters.attribute(root,pattern,arguments)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
- local ekat = dt and dt[dk] and dt[dk].at
+ local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
return (ekat and ekat[arguments]) or ""
end
function xml.filters.text(root,pattern,arguments)
- local ek, dt, dk, rt = xml.filters.index(root,pattern,arguments)
- return (ek and ek.dt) or "", rt, dt, dk
- end
-
- function xml.filter(root,pattern)
- local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$")
- if fun then
- return (xml.filters[fun] or xml.filters.default)(root,pat,arg)
- else
- pat, arg = pattern:match("^(.+)/@(.-)$")
- if arg then
- return xml.filters.attributes(root,pat,arg)
+ local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments)
+ if dtk then
+ local dtkdt = dtk.dt
+ if #dtkdt == 1 and type(dtkdt[1]) == "string" then
+ return dtkdt[1], rt, dt, dk
else
- return xml.filters.default(root,pattern)
+ return xml.tostring(dtkdt), rt, dt, dk
end
+ else
+ return "", rt, dt, dk
end
end
- xml.filters.position = xml.filters.index
-
- -- these may go away
-
- xml.index_element = xml.filters.index
- xml.count_elements = xml.filters.count
- xml.first_element = xml.filters.first
- xml.last_element = xml.filters.last
- xml.index_text = xml.filters.text
- xml.first_text = function (root,pattern) return xml.filters.text(root,pattern, 1) end
- xml.last_text = function (root,pattern) return xml.filters.text(root,pattern,-1) end
-
- -- so far
-
- function xml.get_text(root,pattern,reverse)
- local rt, dt, dk
- traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end, reverse)
- local ek = dt and dt[dk]
- return (ek and ek.dt) or "", rt, dt, dk
- end
-
- function xml.each_element(root, pattern, handle, reverse)
- local ok
- traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse)
- return ok
- end
-
- function xml.get_element(root,pattern,reverse)
- local rt, dt, dk
- traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end, reverse)
- return dt and dt[dk], rt, dt, dk
- end
+ --[[ldx--
+ <p>The following functions collect elements and texts.</p>
+ --ldx]]--
- -- these may change
-
- function xml.all_elements(root, pattern, ignorespaces) -- ok?
+ function xml.collect_elements(root, pattern, ignorespaces)
local rr, dd = { }, { }
traverse(root, lpath(pattern), function(r,d,k)
local dk = d and d[k]
if dk then
- if ignorespaces and type(dk) == "string" and dk:find("^[\s\n]*$") then
+ if ignorespaces and type(dk) == "string" and dk:find("^%s*$") then
-- ignore
else
local n = #rr+1
@@ -2795,8 +2744,8 @@ do
return dd, rr
end
- function xml.all_texts(root, pattern, flatten) -- crap
- local t, r = { }, { }
+ function xml.collect_texts(root, pattern, flatten)
+ local t = { } -- no r collector
traverse(root, lpath(pattern), function(r,d,k)
if d then
local ek = d[k]
@@ -2813,10 +2762,76 @@ do
else
t[#t+1] = ""
end
- r[#r+1] = r
end)
- return t, r
+ return t
+ end
+
+ --[[ldx--
+ <p>Often using an iterators looks nicer in the code than passing handler
+ functions. The <l n='lua'/> book describes how to use coroutines for that
+ purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
+ code like:</p>
+
+ <typing>
+ for r, d, k in xml.elements(xml.load('text.xml'),"title") do
+ print(d[k])
end
+ </typing>
+
+ <p>Which will print all the titles in the document. The iterator variant takes
+ 1.5 times the runtime of the function variant which si due to the overhead in
+ creating the wrapper. So, instead of:</p>
+
+ <typing>
+ function xml.filters.first(root,pattern)
+ for rt,dt,dk in xml.elements(root,pattern)
+ return dt and dt[dk], rt, dt, dk
+ end
+ return nil, nil, nil, nil
+ end
+ </typing>
+
+ <p>We use the function variants in the filters.</p>
+ --ldx]]--
+
+ function xml.elements(root,pattern,reverse)
+ return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
+ end
+
+ function xml.each_element(root, pattern, handle, reverse)
+ local ok
+ traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse)
+ return ok
+ end
+
+ function xml.process_elements(root, pattern, handle)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local dkdt = d[k].dt
+ if dkdt then
+ for i=1,#dkdt do
+ local v = dkdt[i]
+ if v.tg then handle(v) end
+ end
+ end
+ end)
+ end
+
+ function xml.process_attributes(root, pattern, handle)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local ek = d[k]
+ local a = ek.at or { }
+ handle(a)
+ if next(a) then
+ ek.at = a
+ else
+ ek.at = nil
+ end
+ end)
+ end
+
+ --[[ldx--
+ <p>We've now arrives at the functions that manipulate the tree.</p>
+ --ldx]]--
function xml.inject_element(root, pattern, element, prepend)
if root and element then
@@ -2868,7 +2883,7 @@ do
function xml.insert_element(root, pattern, element, before) -- todo: element als functie
if root and element then
if pattern == "/" then
- xml.inject_element(root, pattern, element, before) -- todo: element als functie
+ xml.inject_element(root, pattern, element, before)
else
local matches, collect = { }, nil
if type(element) == "string" then
@@ -2898,8 +2913,6 @@ do
end
end
- -- first, last, each
-
xml.insert_element_after = xml.insert_element
xml.insert_element_before = function(r,p,e) xml.insert_element(r,p,e,true) end
xml.inject_element_after = xml.inject_element
@@ -2930,24 +2943,47 @@ do
end
end
- function xml.process(root, pattern, handle)
- traverse(root, lpath(pattern), function(r,d,k)
- if d[k].dt then
- for k,v in ipairs(d[k].dt) do
- if v.tg then handle(v) end
+ function xml.include(xmldata,element,attribute,pathlist,collapse)
+ element = element or 'ctx:include'
+ attribute = attribute or 'name'
+ pathlist = pathlist or { '.' }
+ -- todo, check op ri
+ local function include(r,d,k)
+ local ek = d[k]
+ local name = (ek.at and ek.at[attribute]) or ""
+ if name ~= "" then
+ -- maybe file lookup in tree
+ local fullname
+ for _, path in ipairs(pathlist) do
+ if path == '.' then
+ fullname = name
+ else
+ fullname = file.join(path,name)
+ end
+ local f = io.open(fullname)
+ if f then
+ xml.assign(d,k,xml.load(f,collapse))
+ f:close()
+ break
+ else
+ xml.empty(d,k)
+ end
end
+ else
+ xml.empty(d,k)
end
- end)
+ end
+ while xml.each_element(xmldata, element, include) do end
end
- function xml.strip(root, pattern)
+ function xml.strip_whitespace(root, pattern)
traverse(root, lpath(pattern), function(r,d,k)
local dkdt = d[k].dt
- if dkdt then
+ if dkdt then -- can be optimized
local t = { }
for i=1,#dkdt do
local str = dkdt[i]
- if type(str) == "string" and str:find("^[\032\010\012\013]*$") then
+ if type(str) == "string" and str:find("^[ \n\r\t]*$") then
-- stripped
else
t[#t+1] = str
@@ -2958,8 +2994,6 @@ do
end)
end
- --
-
function xml.rename_space(root, oldspace, newspace) -- fast variant
local ndt = #root.dt
local rename = xml.rename_space
@@ -2968,6 +3002,9 @@ do
if type(e) == "table" then
if e.ns == oldspace then
e.ns = newspace
+ if e.rn then
+ e.rn = newspace
+ end
end
local edt = e.dt
if edt then
@@ -2987,83 +3024,30 @@ do
d[k].ns = newns
end)
end
-
- -- function xml.process_attributes(root, pattern, handle)
- -- traverse(root, lpath(pattern), function(e,k) handle(e[k].at) end)
- -- end
-
- function xml.process_attributes(root, pattern, handle)
+ function xml.check_namespace(root, pattern, newns)
traverse(root, lpath(pattern), function(r,d,k)
- local ek = d[k]
- local a = ek.at or { }
- handle(a)
- if next(a) then
- ek.at = a
- else
- ek.at = nil
+ local dk = d[k]
+ if (not dk.rn or dk.rn == "") and dk.ns == "" then
+ dk.rn = newns
end
end)
end
-
- function xml.package(tag,attributes,data)
- local n, t = tag:match("^(.-):(.+)$")
- if attributes then
- return { ns = n or "", tg = t or tag, dt = data or "", at = attributes }
- else
- return { ns = n or "", tg = t or tag, dt = data or "" }
- end
- end
-
- -- some special functions, handy for the manual:
-
- function xml.gsub(t,old,new)
- if t.dt then
- for k,v in ipairs(t.dt) do
- if type(v) == "string" then
- t.dt[k] = v:gsub(old,new)
- else
- xml.gsub(v,old,new)
- end
- end
- end
- end
-
- function xml.strip_leading_spaces(ek, e, k) -- cosmetic, for manual
- if e and k and e[k-1] and type(e[k-1]) == "string" then
- local s = e[k-1]:match("\n(%s+)")
- xml.gsub(ek,"\n"..string.rep(" ",#s),"\n")
- end
- end
-
- function xml.serialize_path(root,lpath,handle)
- local ek, e, k = xml.first_element(root,lpath)
- ek = xml.copy(ek)
- xml.strip_leading_spaces(ek,e,k)
- xml.serialize(ek,handle)
- end
-
- -- http://www.lua.org/pil/9.3.html (or of course the book)
- --
- -- it's nice to have an iterator but it comes with some extra overhead
- --
- -- for r, d, k in xml.elements(xml.load('text.xml'),"title") do print(d[k]) end
-
- function xml.elements(root,pattern,reverse)
- return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
+ function xml.remap_name(root, pattern, newtg, newns, newrn)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local dk = d[k]
+ dk.tg = newtg
+ dk.ns = newns
+ dk.rn = newrn
+ end)
end
- -- the iterator variant needs 1.5 times the runtime of the function variant
- --
- -- function xml.filters.first(root,pattern)
- -- for rt,dt,dk in xml.elements(root,pattern)
- -- return dt and dt[dk], rt, dt, dk
- -- end
- -- return nil, nil, nil, nil
- -- end
+end
- -- todo xml.gmatch for text
+--[[ldx--
+<p>Here are a few synonyms.</p>
+--ldx]]--
-end
+xml.filters.position = xml.filters.index
xml.count = xml.filters.count
xml.index = xml.filters.index
@@ -3072,7 +3056,10 @@ xml.first = xml.filters.first
xml.last = xml.filters.last
xml.each = xml.each_element
-xml.all = xml.all_elements
+xml.process = xml.process_element
+xml.strip = xml.strip_whitespace
+xml.collect = xml.collect_elements
+xml.all = xml.collect_elements
xml.insert = xml.insert_element_after
xml.inject = xml.inject_element_after
@@ -3081,39 +3068,38 @@ xml.before = xml.insert_element_before
xml.delete = xml.delete_element
xml.replace = xml.replace_element
--- a few helpers, the may move to lxml modules
+--[[ldx--
+<p>The following helper functions best belong to the <t>lmxl-ini</t>
+module. Some are here because we need then in the <t>mk</t>
+document and other manuals, others came up when playing with
+this module. Since this module is also used in <l n='mtxrun'/> we've
+put them here instead of loading mode modules there then needed.</p>
+--ldx]]--
-function xml.include(xmldata,element,attribute,pathlist,collapse)
- element = element or 'ctx:include'
- attribute = attribute or 'name'
- pathlist = pathlist or { '.' }
- -- todo, check op ri
- local function include(r,d,k)
- local ek = d[k]
- local name = (ek.at and ek.at[attribute]) or ""
- if name ~= "" then
- -- maybe file lookup in tree
- local fullname
- for _, path in ipairs(pathlist) do
- if path == '.' then
- fullname = name
- else
- fullname = file.join(path,name)
- end
- local f = io.open(fullname)
- if f then
- xml.assign(d,k,xml.load(f,collapse))
- f:close()
- break
- else
- xml.empty(d,k)
- end
+function xml.gsub(t,old,new)
+ if t.dt then
+ for k,v in ipairs(t.dt) do
+ if type(v) == "string" then
+ t.dt[k] = v:gsub(old,new)
+ else
+ xml.gsub(v,old,new)
end
- else
- xml.empty(d,k)
end
end
- while xml.each(xmldata, element, include) do end
+end
+
+function xml.strip_leading_spaces(dk,d,k) -- cosmetic, for manual
+ if d and k and d[k-1] and type(d[k-1]) == "string" then
+ local s = d[k-1]:match("\n(%s+)")
+ xml.gsub(dk,"\n"..string.rep(" ",#s),"\n")
+ end
+end
+
+function xml.serialize_path(root,lpath,handle)
+ local dk, r, d, k = xml.first(root,lpath)
+ dk = xml.copy(dk)
+ xml.strip_leading_spaces(dk,d,k)
+ xml.serialize(dk,handle)
end
xml.escapes = { ['&'] = '&amp;', ['<'] = '&lt;', ['>'] = '&gt;', ['"'] = '&quot;' }
@@ -3124,22 +3110,37 @@ function xml.unescaped(str) return str:gsub("(&.-;)", xml.unescapes) end
function xml.cleansed (str) return str:gsub("<.->" , '' ) end -- "%b<>"
function xml.join(t,separator,lastseparator)
- local result = { }
- for k,v in pairs(t) do
- result[k] = xml.tostring(v)
- end
- if lastseparator then
- return table.join(result,separator,1,#result-1) .. lastseparator .. result[#result]
+ if #t > 0 then
+ local result = { }
+ for k,v in pairs(t) do
+ result[k] = xml.tostring(v)
+ end
+ if lastseparator then
+ return table.join(result,separator or "",1,#result-1) .. (lastseparator or "") .. result[#result]
+ else
+ return table.join(result,separator)
+ end
else
- return table.join(result,separator)
+ return ""
end
end
-do if utf then
+--[[ldx--
+<p>We provide (at least here) two entity handlers. The more extensive
+resolver consults a hash first, tries to convert to <l n='utf'/> next,
+and finaly calls a handler when defines. When this all fails, the
+original entity is returned.</p>
+--ldx]]--
+
+do if unicode and unicode.utf8 then
+
+ xml.entities = xml.entities or { } -- xml.entities.handler == function
+
+ local char = unicode.utf8.char
local function toutf(s)
- return utf.char(tonumber(s,16))
+ return char(tonumber(s,16))
end
function xml.utfize(root)
@@ -3147,25 +3148,50 @@ do if utf then
for k=1,#d do
local dk = d[k]
if type(dk) == "string" then
- d[k] = dk:gsub("&#x(.-);",toutf)
+ -- test prevents copying if no match
+ if dk:find("&#x.-;") then
+ d[k] = dk:gsub("&#x(.-);",toutf)
+ end
else
xml.utfize(dk)
end
end
end
-else
- function xml.utfize()
- print("entity to utf conversion is not available")
+
+ local entities = xml.entities
+
+ local function resolve(e)
+ local e = entities[e]
+ if e then
+ return e
+ elseif e:find("#x") then
+ return char(tonumber(s:sub(3),16))
+ else
+ local h = entities.handler
+ return (h and h(e)) or "&" .. e .. ";"
+ end
end
-end end
+ function xml.resolve_entities(root)
+ local d = root.dt
+ for k=1,#d do
+ local dk = d[k]
+ if type(dk) == "string" then
+ if dk:find("&.-;") then
+ d[k] = dk:gsub("&(.-);",resolve)
+ end
+ else
+ xml.utfize(dk)
+ end
+ end
+ end
---- examples
+end end
---~ for _, e in ipairs(xml.filters.elements(ctxrunner.xmldata,"ctx:message")) do
---~ print(">>>",xml.tostring(e.dt))
---~ end
+--~ xml.lshow("/../../../a/(b|c)[@d='e']/f")
+--~ xml.lshow("/../../../a/!(b|c)[@d='e']/f")
+--~ xml.lshow("/../../../a/!b[@d!='e']/f")
-- filename : l-utils.lua
diff --git a/scripts/context/ruby/base/pdf.rb b/scripts/context/ruby/base/pdf.rb
index 9f4e9a6c3..5aec06fc5 100644
--- a/scripts/context/ruby/base/pdf.rb
+++ b/scripts/context/ruby/base/pdf.rb
@@ -7,7 +7,7 @@ module PDFview
@method = 'default' # 'xpdf'
- @opencalls['default'] = "pdfopen --file"
+ @opencalls['default'] = "pdfopen --file" # "pdfopen --back --file"
@opencalls['xpdf'] = "xpdfopen"
@closecalls['default'] = "pdfclose --file"
diff --git a/scripts/context/ruby/base/tex.rb b/scripts/context/ruby/base/tex.rb
index ceb9473c0..73b382af9 100644
--- a/scripts/context/ruby/base/tex.rb
+++ b/scripts/context/ruby/base/tex.rb
@@ -72,6 +72,7 @@ class TEX
@@backends = Hash.new
@@mappaths = Hash.new
@@runoptions = Hash.new
+ @@tcxflag = Hash.new
@@draftoptions = Hash.new
@@texformats = Hash.new
@@mpsformats = Hash.new
@@ -169,13 +170,19 @@ class TEX
['cont-en','cont-nl','cont-de','cont-it',
'cont-fr','cont-cz','cont-ro','cont-uk'] .each do |f| @@texprocstr[f] = "\\emergencyend" end
- # @@runoptions['xetex'] = ['--8bit','-output-driver="xdvipdfmx -E -d 4 -V 5 -q"']
- @@runoptions['xetex'] = ['--8bit','-output-driver="xdvipdfmx -E -d 4 -V 5"']
- @@runoptions['pdfetex'] = ['--8bit'] # obsolete
- @@runoptions['pdftex'] = ['--8bit'] # pdftex is now pdfetex
- @@runoptions['luatex'] = ['--file-line-error']
@@runoptions['aleph'] = ['--8bit']
+ @@runoptions['luatex'] = ['--file-line-error']
@@runoptions['mpost'] = ['--8bit']
+ @@runoptions['pdfetex'] = ['--8bit'] # obsolete
+ @@runoptions['pdftex'] = ['--8bit'] # pdftex is now pdfetex
+ @@runoptions['xetex'] = ['--8bit','-output-driver="xdvipdfmx -E -d 4 -V 5"']
+
+ @@tcxflag['aleph'] = true
+ @@tcxflag['luatex'] = false
+ @@tcxflag['mpost'] = true
+ @@tcxflag['pdfetex'] = true
+ @@tcxflag['pdftex'] = true
+ @@tcxflag['xetex'] = false
@@draftoptions['pdftex'] = ['--draftmode']
@@ -540,11 +547,16 @@ class TEX
"--ini"
end
end
- def tcxflag(file="natural.tcx")
- if Kpse.miktex? then
- "-tcx=#{file}"
+ def tcxflag(engine)
+ if @@tcxflag[engine] then
+ file = "natural.tcx"
+ if Kpse.miktex? then
+ "-tcx=#{file}"
+ else
+ "-translate-file=#{file}"
+ end
else
- "-translate-file=#{file}"
+ ""
end
end
@@ -661,7 +673,7 @@ class TEX
texformats.each do |texformat|
report("generating tex format #{texformat}")
progname = validprogname([getvariable('progname'),texformat,texengine])
- runcommand([quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine),texmakeextras(texformat)])
+ runcommand([quoted(texengine),prognameflag(progname),iniflag,tcxflag(texengine),prefixed(texformat,texengine),texmakeextras(texformat)])
end
end
else
@@ -682,7 +694,7 @@ class TEX
mpsformats.each do |mpsformat|
report("generating mps format #{mpsformat}")
progname = validprogname([getvariable('progname'),mpsformat,mpsengine])
- if not runcommand([quoted(mpsengine),prognameflag(progname),iniflag,tcxflag,runoptions(mpsengine),mpsformat,mpsmakeextras(mpsformat)]) then
+ if not runcommand([quoted(mpsengine),prognameflag(progname),iniflag,tcxflag(mpsengine),runoptions(mpsengine),mpsformat,mpsmakeextras(mpsformat)]) then
setvariable('error','no format made')
end
end
@@ -1559,7 +1571,7 @@ end
run_luatools("--fmt=#{texformat} #{filename}")
else
progname = validprogname([getvariable('progname'),texformat,texengine])
- runcommand([quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),tcxflag,runoptions(texengine),filename,texprocextras(texformat)])
+ runcommand([quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),tcxflag(texengine),runoptions(texengine),filename,texprocextras(texformat)])
end
# true
else
@@ -1574,8 +1586,7 @@ end
if mpsengine && mpsformat then
ENV["MPXCOMMAND"] = "0" unless mpx
progname = validprogname([getvariable('progname'),mpsformat,mpsengine])
- runcommand([quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),tcxflag,runoptions(mpsengine),mpname,mpsprocextras(mpsformat)])
- # runcommand([quoted(mpsengine),formatflag(mpsengine,mpsformat),tcxflag,runoptions(mpsengine),mpname,mpsprocextras(mpsformat)])
+ runcommand([quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),tcxflag(mpsengine),runoptions(mpsengine),mpname,mpsprocextras(mpsformat)])
true
else
false
@@ -1790,10 +1801,10 @@ end
forcexml = getvariable('forcexml')
-if dummyfile || forcexml then # after ctx?
- jobsuffix = makestubfile(rawname,rawbase,forcexml)
- checkxmlfile(rawname)
-end
+ if dummyfile || forcexml then # after ctx?
+ jobsuffix = makestubfile(rawname,rawbase,forcexml)
+ checkxmlfile(rawname)
+ end
# preprocess files
@@ -1929,7 +1940,15 @@ end
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
diff --git a/scripts/context/ruby/base/texutil.rb b/scripts/context/ruby/base/texutil.rb
index 726e31381..9c43f00e9 100644
--- a/scripts/context/ruby/base/texutil.rb
+++ b/scripts/context/ruby/base/texutil.rb
@@ -400,7 +400,7 @@ class TeXUtil
def MyCommands::writer(logger,handle)
handle << logger.banner("commands: #{@@commands.size}")
@@commands.each do |c|
- handle << "#{c}\n"
+ handle << "#{c}%\n"
end
end
@@ -494,7 +494,7 @@ class TeXUtil
end
end
list.each do |entry|
- handle << "\\synonymentry{#{entry.type}}{#{entry.command}}{#{entry.key}}{#{entry.data}}\n"
+ handle << "\\synonymentry{#{entry.type}}{#{entry.command}}{#{entry.key}}{#{entry.data}}%\n"
end
end
@@ -602,7 +602,7 @@ class TeXUtil
end
else
# @entry, @key = cleanupsplit(@entry), cleanupsplit(@key)
-@entry, @key = cleanupsplit(@entry), xcleanupsplit(@key)
+ @entry, @key = cleanupsplit(@entry), xcleanupsplit(@key)
end
@sortkey = sorter.simplify(@key)
# special = @sortkey =~ /^([^a-zA-Z\\])/o
@@ -632,23 +632,23 @@ class TeXUtil
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
- return t.join(@@split)
-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
@@ -661,10 +661,10 @@ end
def Register.flushsavedline(handle)
if @@collapse && ! @@savedfrom.empty? then
if ! @@savedto.empty? then
- handle << "\\registerfrom#{@@savedfrom}"
- handle << "\\registerto#{@@savedto}"
+ handle << "\\registerfrom#{@@savedfrom}%"
+ handle << "\\registerto#{@@savedto}%"
else
- handle << "\\registerpage#{@@savedfrom}"
+ handle << "\\registerpage#{@@savedfrom}%"
end
end
@@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', ''
@@ -706,15 +706,15 @@ end
elsif alpha == @@specialsymbol then
character = @@specialbanner
elsif alpha.length > 1 then
- # character = "\\getvalue\{#{alpha}\}"
- character = "\\#{alpha}"
+ # character = "\\getvalue\{#{alpha}\}%"
+ character = "\\#{alpha}%"
else
character = "\\unknown"
end
- handle << "\\registerentry{#{entry.type}}{#{character}}\n"
+ handle << "\\registerentry{#{entry.type}}{#{character}}%\n"
end
end
- current = [entry.entry.split(@@split),'','',''].flatten
+ current = [entry.entry.split(@@split),'','','',''].flatten
howto = current.collect do |e|
e + '::' + entry.texthowto
end
@@ -724,38 +724,51 @@ end
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"
+ 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"
+ 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"
+ 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
Register.flushsavedline(handle)
- handle << "\\registersee{#{entry.type}}{#{entry.pagehowto},#{entry.texthowto}}{#{entry.seetoo}}{#{entry.page}}\n" ;
+ 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
@@ -763,14 +776,14 @@ end
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]}}{#{entry.pagehowto},#{entry.texthowto}}"
+ 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"
+ handle << "\\registerfrom#{savedline}%\n"
elsif entry.state == 3 then # to
Register.flushsavedline(handle)
- handle << "\\registerto#{savedline}\n"
+ handle << "\\registerto#{savedline}%\n"
@@savedhowto = '' # test
elsif @@collapse then
if savedentry != nextentry then
@@ -779,7 +792,7 @@ end
savedTo, savedentry = savedline, nextentry
end
else
- handle << "\\registerpage#{savedline}\n"
+ handle << "\\registerpage#{savedline}%\n"
@@savedhowto = '' # test
end
@nofpages += 1
@@ -1027,6 +1040,7 @@ end
begin
if f = File.open(File.suffixed(filename,'tuo'),'w') then
@plugins.writers(f)
+ f << "\\endinput\n"
f.close
end
rescue
diff --git a/scripts/context/ruby/www/dir.rb b/scripts/context/ruby/www/dir.rb
index 09e088d77..115fd8911 100644
--- a/scripts/context/ruby/www/dir.rb
+++ b/scripts/context/ruby/www/dir.rb
@@ -62,9 +62,9 @@ class WWW
end
u = dir_uri(@variables.get('path') || '.')
str << "<div class='dir-view'>\n<pre>\n"
- str << "<a href=\"#{u}&n=#{d1}\">name</A>".ljust(49+u.length)
- str << "<a href=\"#{u}&m=#{d1}\">last modified</A>".ljust(41+u.length)
- str << "<a href=\"#{u}&s=#{d1}\">size</A>".rjust(31+u.length) << "\n" << "\n"
+ str << "<a href=\"#{u}&n=#{d1}\">name</a>".ljust(49+u.length)
+ str << "<a href=\"#{u}&m=#{d1}\">last modified</a>".ljust(41+u.length)
+ str << "<a href=\"#{u}&s=#{d1}\">size</a>".rjust(31+u.length) << "\n" << "\n"
# parent path
if showdirs && ! hidden.include?('..') then
dname = "parent directory"
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index 2acbc02e4..3a5ca3933 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -429,8 +429,7 @@ do
-- default color space
function colors.gray(s)
- local n = 1-s
- return { 2, s, n, n, n, 0, 0, 0, s }
+ return { 2, s, s, s, s, 0, 0, 0, s }
end
function colors.rgb(r,g,b)
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index d7a2044a2..95030da86 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -90,24 +90,29 @@ use the table. After all, we have this information available anyway.</p>
function characters.context.define()
local unicodes, utfcodes = characters.context.unicodes, characters.context.utfcodes
local flush, tc = tex.sprint, tex.ctxcatcodes
- for _, chr in pairs(characters.data) do
+ for u, chr in pairs(characters.data) do
local contextname = chr.contextname
if contextname then
-- by this time, we're still in normal catcode mode
- if chr.unicodeslot < 128 then
- flush(tc, "\\chardef\\" .. contextname .. "=" .. unicodes[contextname])
- else
- flush(tc, "\\let\\" .. contextname .. "=" .. utfcodes[contextname])
- end
+ if chr.unicodeslot < 128 then
+ flush(tc, "\\chardef\\" .. contextname .. "=" .. u) -- unicodes[contextname])
+ else
+ flush(tc, "\\let\\" .. contextname .. "=" .. utf.char(u)) -- utfcodes[contextname])
+ end
end
end
end
+function characters.charcode(box)
+ local b = tex.box[box]
+ local l = b.list
+ tex.sprint((l and l.id == node.id('glyph') and l.char) or 0)
+end
+
--[[ldx--
<p>Setting the lccodes is also done in a loop over the data table.</p>
--ldx]]--
-
function characters.setcodes()
local flush, tc = tex.sprint, tex.ctxcatcodes
for code, chr in pairs(characters.data) do
diff --git a/tex/context/base/colo-ini.tex b/tex/context/base/colo-ini.tex
index 8cd8331c5..0b43ca3dd 100644
--- a/tex/context/base/colo-ini.tex
+++ b/tex/context/base/colo-ini.tex
@@ -323,7 +323,7 @@
\def\dodefineglobalcolor{\dododefinecolor\doglobal\setgvalue\setxvalue1}
\def\dodefinenamedcolor {\dododefinecolor\doglobal\setvalue \setevalue0}
-\def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value
+\def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value -- maybe add fake [#7] here
{#1\addtocommalist{#5}\colorlist % optional
\doifassignmentelse{#6}
{\@@resetcolorparameters
@@ -529,9 +529,7 @@
\def\dodefinewhatevercolor[#1][#2][#3]%
{\ifthirdargument
- \doifassignmentelse{#2}
- {\dododefinecolor[#1][#2,#3]}% actually this is an error
- {\dodefinespotcolor[#1][#2][#3]}% and this the prefered method
+ \dodefinespotcolor[#1][#2][#3]% this is the prefered method !
\else
\dodefinecolor[#1][#2]%
\fi}
diff --git a/tex/context/base/colo-new.lua b/tex/context/base/colo-new.lua
index 9976708c6..842e9c15a 100644
--- a/tex/context/base/colo-new.lua
+++ b/tex/context/base/colo-new.lua
@@ -248,7 +248,7 @@ do
if t and t.a and t.t then
ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
elseif ctx.couplecolors then
---~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ -- ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
end
@@ -257,36 +257,34 @@ do
function ctx.mpcolor(model,ca,ta,default)
local cv = colors.value(ca) -- faster when direct colors.values[ca]
- local tv = transparencies.value(ta)
if cv then
+ local tv = transparencies.value(ta)
if model == 1 then
model = cv[1]
end
if tv then
if model == 2 then
- return string.format("transparent(%s,%s,(%s,%s,%s))",1-tv[1],1-tv[2],1-cv[2])
+ return string.format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 3 then
return string.format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 4 then
---~ return string.format("transparent(%s,%s,(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
return string.format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
else
return string.format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
end
else
if model == 2 then
- return string.format("(%s,%s,%s)",1-cv[2],1-cv[2],1-cv[2]) -- cv[3],cv[4],cv[5]
+ return string.format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 3 then
return string.format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 4 then
---~ return string.format("(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
return string.format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
else
return string.format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
end
end
else
- default = default or 1 -- rgb !
+ default = default or 0 -- rgb !
return string.format("(%s,%s,%s)",default,default,default)
end
end
@@ -347,7 +345,7 @@ do
end
end
- function ctx.pdfcolor(model,ca,default)
+ function ctx.pdfcolor(model,ca,default) -- todo: use gray when no color
local cv = colors.value(ca)
if cv then
if model == 1 then
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index c7dd11b64..c97575baa 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -38,6 +38,7 @@
\writestatus\m!lua{used cache path - \ctxlua{tex.print(caches.path)}}%
\writestatus\m!lua{modules/dumps/instances - \ctxlua{tex.print((status.luabytecodes-500).."/"..input.storage.done.."/"..status.luastates)}}%
\writestatus\m!lua{current memory usage - \ctxlua{tex.print(status.luastate_bytes)} bytes}%
+ \writestatus\m!lua{language load time - \ctxlua{input.loadtime(languages)} seconds (n=\ctxlua{tex.print(languages.n())})}%
\writestatus\m!lua{loaded fonts - \ctxlua{tex.print(fonts.logger.report())}}%
\to \everybye
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index 51dbd578c..03b7ed27c 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2007.09.10 21:31}
+\newcontextversion{2007.09.28 11:58}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
index 22d75719d..2c807f93c 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -42,7 +42,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2007.09.10 21:31}
+\edef\contextversion{2007.09.28 11:58}
%D For those who want to use this:
diff --git a/tex/context/base/core-def.tex b/tex/context/base/core-def.tex
index 3e7a3585d..c7c49858e 100644
--- a/tex/context/base/core-def.tex
+++ b/tex/context/base/core-def.tex
@@ -13,22 +13,15 @@
\writestatus{loading}{Context Core Macros / Defaults}
-%D Here we collect default settings. More code will moved to
-%D this module later.
+%D Here we collect settings that cannot be done earlier due to
+%D depedencies. More code will moved to this module later.
\unprotect
-%D We preload a couple of symbol|(|sets): a few defaults,
-%D the marvo symbols and a few guillemot replacements.
-
-\usesymbols[mis,mvs,glm]
-
-%D We also choose a navigation symbol set:
+\usesymbols[mis,mvs] % 'glm' no longer needed due to lm
\usesymbols[nav] \setupsymbolset[navigation 1]
\setupinteraction[\c!symbolset=navigation 1]
-%D In \type {core-nav}, we choose this set as well.
-
\protect \endinput
diff --git a/tex/context/base/core-fig.tex b/tex/context/base/core-fig.tex
index 3464b80fe..104b753ec 100644
--- a/tex/context/base/core-fig.tex
+++ b/tex/context/base/core-fig.tex
@@ -565,12 +565,6 @@
\fi
\fi}
-% \def\externalfigurestamp
-% {\wantedfigurename
-% -\ifx\wantedfiguretype\empty\wantedfiguretypespec\else\wantedfiguretype\fi
-% -\wantedfiguretypespec
-% -\wantedfigurepage}
-
\def\externalfigurestamp % needs \edef'd macros!
{\wantedfigurename
\ifx\wantedfiguretype\empty\else
@@ -601,17 +595,6 @@
\newtoks\externalfigurepostprocessors
-% \def\resetfigureusersettings
-% {\getparameters % % % hm, can be faster, like the reset
-% [\??ef]
-% [\c!type=\s!unknown,\c!method=,\c!label=,\c!symbol=\v!no,%\c!foregroundcolor=,
-% \c!object=\@@exobject,\c!preset=\v!yes,\c!split=,\c!size=,
-% \c!page=0,\c!controls=\v!no,\c!preview=\v!no,\c!repeat=\v!no,
-% \c!maxwidth=\@@exmaxwidth,\c!maxheight=\@@exmaxheight,\c!sx=1,\c!sy=1,
-% \c!scale=,\c!xscale=,\c!yscale=,\c!width=,\c!height=,\c!display=,\c!lines=,\c!grid=,
-% \c!color=,\c!conversion=\@@exconversion,\c!prefix=\@@exprefix,\c!cache=\@@excache,
-% \c!factor=,\c!hfactor=,\c!wfactor=]}
-
\def\resetfigureusersettings
{\let\@@eftype \s!unknown \let\@@efmethod \empty \let\@@efpreset\v!yes
\let\@@eflabel \empty \let\@@efsize \empty \let\@@efpage \!!zerocount
@@ -838,13 +821,15 @@
\fi}}
\def\insertfiguredriverdata#1#2%
- {\edef\@@DriverImageWidth {\the\dimexpr#1\relax}%
+ {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \lowercasestring\wantedfiguremethod \to\lcwantedfiguremethod
+ \edef\@@DriverImageWidth {\the\dimexpr#1\relax}%
\edef\@@DriverImageHeight{\the\dimexpr#2\relax}%
- \let \@@DriverImageFile \wantedfigurefullname
- \let \@@DriverImageType \wantedfiguretypespec
- \let \@@DriverImageMethod \wantedfiguremethod
- \let \@@DriverImageLabel \wantedfigurelabel
- \let \@@DriverImagePage \wantedfigurepage
+ \let \@@DriverImageFile \wantedfigurefullname
+ \let \@@DriverImageType \lcwantedfiguretypespec
+ \let \@@DriverImageMethod \lcwantedfiguremethod
+ \let \@@DriverImageLabel \wantedfigurelabel
+ \let \@@DriverImagePage \wantedfigurepage
\doinsertfile}
\def\insertunscaledfiguredriverdata
@@ -1047,7 +1032,8 @@
\let\doanalyzefiguredimensionsfallback\relax
\def\doanalyzefiguredimensions
- {\doiffileinsertionsupportedelse\wantedfiguretypespec
+ {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \doiffileinsertionsupportedelse\lcwantedfiguretypespec
{\doiffileelse\wantedfigurefullname
{\doshowfigurestate{analyzing : \wantedfigurefullname}%
\doanalyzefiguredimensionsinternal
@@ -1104,11 +1090,12 @@
\def\doanalyzefiguredimensionsinternal
{\ifcase\figurestatus
- \let\@@DriverImageFile\wantedfigurefullname
- \let\@@DriverImagePage\wantedfigurepage
- \let\@@DriverImageType\wantedfiguretypespec
+ \lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \let\@@DriverImageFile \wantedfigurefullname
+ \let\@@DriverImagePage \wantedfigurepage
+ \let\@@DriverImageType\lcwantedfiguretypespec
% use internal when available, otherwise try driver (\dogetfiguresize)
- \executeifdefined{dogetfiguresize\wantedfiguretypespec}\dogetfiguresize
+ \executeifdefined{dogetfiguresize\@@DriverImageType}\dogetfiguresize
\setanalyzedfiguredimensions\!!ten
\fi}
diff --git a/tex/context/base/core-reg.lua b/tex/context/base/core-reg.lua
index b5ca260f8..22a75945b 100644
--- a/tex/context/base/core-reg.lua
+++ b/tex/context/base/core-reg.lua
@@ -29,7 +29,7 @@ do
function sorters.index.compare(a,b)
local result = 0
- for i=1,3 do
+ for i=1,4 do
if result == 0 then
result = sorters.comparers.basic(a,b,i)
else
@@ -48,7 +48,7 @@ do
end
function sorters.index.prepare(data)
- sorters.prepare(data,sorters.splitters.utf,3)
+ sorters.prepare(data,sorters.splitters.utf,4)
end
function sorters.index.sort(data)
@@ -152,6 +152,7 @@ do
"\\registerentrya{%s}{%s}",
"\\registerentryb{%s}{%s}",
"\\registerentryc{%s}{%s}",
+ "\\registerentryd{%s}{%s}",
},
}
@@ -164,8 +165,8 @@ do
local done = { false, false, false }
for kk,vv in ipairs(s.data) do
if vv[2][1] then
- local e = { false, false, false }
- for i=1,3,1 do
+ local e = { false, false, false, false }
+ for i=1,4,1 do
if vv[2][i] then
e[i] = vv[2][i][1]
end
@@ -193,7 +194,7 @@ do
end
--- { { entry, key }, { entry, key }, { entry, key } }, kind, realpage|see, reference, pagespec
+-- { { entry, key }, { entry, key }, { entry, key }, { entry, key } }, kind, realpage|see, reference, pagespec
function job.loadregister(class)
if job.registers[class] then
@@ -222,7 +223,8 @@ function job.loadregister(class)
{
{ entry[1] or "", key[1] or "" },
{ entry[2] or "", key[2] or "" },
- { entry[3] or "", key[3] or "" }
+ { entry[3] or "", key[3] or "" },
+ { entry[4] or "", key[4] or "" }
},
v[6], -- realpage or seeword (check see)
v[2], -- reference
diff --git a/tex/context/base/core-reg.tex b/tex/context/base/core-reg.tex
index 77bb6b8f7..d03e788f2 100644
--- a/tex/context/base/core-reg.tex
+++ b/tex/context/base/core-reg.tex
@@ -229,6 +229,7 @@
\let\c!entrya\empty
\let\c!entryb\empty
\let\c!entryc\empty
+\let\c!entryd\empty
\def\nextregisterpage
{\iffirstregisterpage
@@ -306,6 +307,7 @@
\def\registerentrya#1{\executeifdefined{#1\s!entrya}\gobbleoneargument }
\def\registerentryb#1{\executeifdefined{#1\s!entryb}\gobbleoneargument }
\def\registerentryc#1{\executeifdefined{#1\s!entryc}\gobbleoneargument }
+\def\registerentryd#1{\executeifdefined{#1\s!entryd}\gobbleoneargument }
\def\registersee #1{\executeifdefined{#1\s!see }\gobblethreearguments}
\def\registerpage #1{\executeifdefined{#1\s!page }\gobblefourarguments }
\def\registerfrom #1{\executeifdefined{#1\s!from }\gobblefourarguments }
@@ -315,6 +317,7 @@
{\letvalue{#1\s!entrya}\gobbleoneargument
\letvalue{#1\s!entryb}\gobbleoneargument
\letvalue{#1\s!entryc}\gobbleoneargument
+ \letvalue{#1\s!entryd}\gobbleoneargument
\letvalue{#1\s!see }\gobblethreearguments
\letvalue{#1\s!page }\gobblefourarguments
\letvalue{#1\s!from }\gobblefourarguments
@@ -331,6 +334,7 @@
\let\c!entrya =\relax
\let\c!entryb =\relax
\let\c!entryc =\relax
+\let\c!entryd =\relax
\def\limitedregisterentry#1#2%
{\getvalue{\??id#1\c!textcommand}%
@@ -359,13 +363,15 @@
\!!doneafalse
\doifelsevalue{\??id#2\c!interaction}\v!text
{\ifcase\currententrylevel \or
- \!!doneatrue\c!entrya\c!entryb\c!entryc \or
- \c!entrya\!!doneatrue\c!entryb\c!entryc \or
- \c!entrya\c!entryb\!!doneatrue\c!entryc \fi}
- {\c!entrya\c!entryb\c!entryc}%
+ \!!doneatrue\c!entrya\c!entryb\c!entryc\c!entryd \or
+ \c!entrya\!!doneatrue\c!entryb\c!entryc\c!entryd \or
+ \c!entrya\c!entryb\!!doneatrue\c!entryc\c!entryd \or
+ \c!entrya\c!entryb\c!entryc\!!doneatrue\c!entryd \fi}
+ {\c!entrya\c!entryb\c!entryc\c!entryd}%
\global\let\c!entrya\relax
\global\let\c!entryb\relax
\global\let\c!entryc\relax
+ \global\let\c!entryd\relax
\global\let\c!entryletter\relax
\global\let\c!entryreference\relax}
@@ -529,12 +535,13 @@
\def\dohandleregisterentry##1% dubbelop | \strut nieuw
{\doregistertexthowto{#1}{\strut\limitedregisterentry{#1}{##1}}}%
\getvalue
- {#1\ifcase\currententrylevel\s!entrya\or\s!entryb\else\s!entryc\fi}%
+ {#1\ifcase\currententrylevel\s!entrya\or\s!entryb\else\s!entryc\else\s!entryd\fi}%
{\doregisterpagehowto{#1}{\labeltexts\v!see{#3}}}%
- \c!entryletter\c!entrya\c!entryb\c!entryc
+ \c!entryletter\c!entrya\c!entryb\c!entryc\c!entryd
\global\let\c!entrya\relax
\global\let\c!entryb\relax
\global\let\c!entryc\relax
+ \global\let\c!entryd\relax
\global\let\c!entryletter\relax
\global\let\c!entryreference\relax
% \global\firstregisterentrytrue
@@ -627,6 +634,7 @@
\edef\currententrylevel{1}%
\global\let\c!entryb\relax
\global\let\c!entryc\relax
+ \global\let\c!entryd\relax
\gdef\c!entrya
{\iffirstregisterentry\else\endgraf\fi % new
\global\firstregisterpagetrue
@@ -639,6 +647,7 @@
\def\dosetpageregisterentryb#1#2%
{\flushseenregisterpage % redundant
\edef\currententrylevel{2}%
+ \global\let\c!entryd\relax
\global\let\c!entryc\relax
\global\def\c!entryb
{\iffirstregisterentry\else\endgraf\fi % new
@@ -665,6 +674,21 @@
\global\firstregisterentryfalse
\global\firstsubsubentryfalse}}
+\def\dosetpageregisterentryd#1#2%
+ {\flushseenregisterpage % redundant
+ \edef\currententrylevel{4}%
+ \gdef\c!entryd
+ {\iffirstregisterentry\else\endgraf\fi % new
+ \global\firstregisterpagetrue
+ \global\let\c!entrya\relax
+ \global\let\c!entryb\relax
+ \global\let\c!entryc\relax
+ \iffirstsubsubentry\nobreak\fi
+ \hangindent4em\noindent\c!entryreference\hskip3em\relax
+ \dohandlepageregisterentry{#1}{#2}%
+ \global\firstregisterentryfalse
+ \global\firstsubsubentryfalse}}
+
\def\dosetpageregister#1% \currentregister gebruiken
{\dosetreglevel{#1}%
\global\let\currentregisterentry\empty
@@ -674,6 +698,7 @@
\setvalue{#1\s!entrya}{\dosetpageregisterentrya {#1}}%
\setvalue{#1\s!entryb}{\dosetpageregisterentryb {#1}}%
\setvalue{#1\s!entryc}{\dosetpageregisterentryc {#1}}%
+ \setvalue{#1\s!entryd}{\dosetpageregisterentryd {#1}}%
\setvalue{#1\s!page }{\dosetpageregisterpage{1}{#1}}%
\setvalue{#1\s!from }{\dosetpageregisterpage{2}{#1}}%
\setvalue{#1\s!to }{\dosetpageregisterpage{3}{#1}}%
diff --git a/tex/context/base/core-rul.tex b/tex/context/base/core-rul.tex
index ea6ff441c..b481ab49c 100644
--- a/tex/context/base/core-rul.tex
+++ b/tex/context/base/core-rul.tex
@@ -482,33 +482,6 @@
%D by \TEX\ itself, the latter one depends on the driver. This
%D macro also support a negative offset.
-% \def\dooutlinebox
-% {\setbox\framebox\vbox % rules on top of box
-% {\scratchdimen \framedparameter\c!frameoffset\relax
-% \frameddimenwd\dimexpr\wd\framebox+2\scratchdimen\relax
-% \frameddimenht\dimexpr\ht\framebox+ \scratchdimen\relax
-% \frameddimendp\dimexpr\dp\framebox+ \scratchdimen+\framedparameter\c!framedepth\relax
-% \ifdim\frameddimendp<\zeropoint
-% \advance\frameddimenht \frameddimendp
-% \scratchdimen-\frameddimendp
-% \frameddimendp\zeropoint
-% \else
-% \scratchdimen\zeropoint
-% \fi
-% \setbox\extraframebox\hbox
-% {\dostrokedbox}%
-% \setbox\extraframebox\hbox
-% {\raise\scratchdimen\vbox
-% {\moveleft\framedparameter\c!frameoffset\box\extraframebox}}%
-% \wd\extraframebox\wd\framebox
-% \ht\extraframebox\ht\framebox
-% \dp\extraframebox\dp\framebox
-% \hbox
-% {\box\framebox\hskip-\wd\extraframebox
-% \doifsomething{\framedparameter\c!framecolor}% no else needed,
-% {\color[\framedparameter\c!framecolor]}% %
-% {\box\extraframebox}}}} % but {} here
-
\def\dooutlinebox % we needed to move the color command in order to apply attributes properly
{\setbox\framebox\vbox % rules on top of box
{\scratchdimen \framedparameter\c!frameoffset\relax
@@ -563,23 +536,78 @@
\def\@@frame@@{@@frame@@}
-\setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-\setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-\setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-\setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-\setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-\setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-\setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+
+\def\@@frame@@trule{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+\def\@@frame@@brule{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+\def\@@frame@@rrule{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+\def\@@frame@@lrule{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+\letvalue{t\@@frame@@\v!on \v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!off\v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!on }\@@frame@@trule
+
+\letvalue{b\@@frame@@\v!on \v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!off\v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!on }\@@frame@@brule
+
+\letvalue{l\@@frame@@\v!on \v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!off\v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!on }\@@frame@@lrule
+
+\letvalue{r\@@frame@@\v!on \v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!off\v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!on }\@@frame@@rrule
+
+\def\@@frame@@trules{\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}\nointerlineskip\kern-\ruledlinewidth}
+\def\@@frame@@brules{\kern-\ruledlinewidth\nointerlineskip\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}}
+\def\@@frame@@rrules{\kern-\ruledlinewidth\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth}
+\def\@@frame@@lrules{\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+\letvalue{t\@@frame@@\v!small\v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!off \v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!small }\@@frame@@trules
+
+\letvalue{b\@@frame@@\v!small\v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!off \v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!small }\@@frame@@brules
+
+\letvalue{l\@@frame@@\v!small\v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!off \v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!small }\@@frame@@lrules
+
+\letvalue{r\@@frame@@\v!small\v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!off \v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!small }\@@frame@@rrules
%D I condidered using the low level support command
%D \type{\ruledhbox}, but this would slow down processing by a
%D factor~3.
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=on,leftframe=on,topframe=on,bottomframe=on]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=small]
+% {}
+% \framed
+% [width=4cm,height=3cm,rulethickness=3mm,
+% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on]
+% {}
+
%D Before we come to using these macros we yet have to define
%D the rounded corner alternative, which after all is not that
%D hard because it uses the previously defined macro \type
@@ -1736,42 +1764,6 @@
% otherwise we get problems with framed display math and auto
% width.
-% \def\doreshapeframedbox % frozen
-% {\beginofshapebox
-% \unvcopy\framebox
-% \endofshapebox
-% \global\@@globalwidth\zeropoint
-% \resetshapeframebox
-% \reshapebox
-% {\setbox0\hbox
-% {\strut\ifhbox\shapebox\unhbox\else\box\fi\shapebox}%
-% \global\advance\framednoflines \plusone
-% \ifdim\framedlastlength>\zeropoint\else
-% \global\framedlastlength\wd0
-% \fi
-% \ifdim\wd0>\@@globalwidth
-% \global\@@globalwidth\wd0
-% \fi}%
-% \dosetraggedcommand\localformat
-% \raggedcommand
-% \ifboxhasheight
-% \setbox\framebox\vbox to \localheight
-% {\hsize\@@globalwidth
-% \reshapebox{\hbox to \hsize{\ifhbox\shapebox\unhbox\else\box\fi\shapebox}}%
-% \dobeforeframedbox
-% \innerflushshapebox
-% \doafterframedbox}%
-% \else
-% \scratchdimen\dp\framebox
-% \setbox\framebox\vbox to \ht\framebox
-% {\hsize\@@globalwidth
-% \reshapebox{\hbox to \hsize{\ifhbox\shapebox\unhbox\else\box\fi\shapebox}}%
-% \innerflushshapebox}%
-% \dp\framebox\scratchdimen % \strutdp otherwise problem with math
-% \fi
-% \ifdim\framedlastlength=\zeropoint\global\framednoflines\wd\framebox\fi
-% \ifcase\framednoflines\global\framednoflines\plusone\fi}
-
\chardef\reshapeframeboxmethod\plusone % 0=no flush, 1=old method 2=no depth messing
\let\framedboxwidth \!!zeropoint
diff --git a/tex/context/base/core-spa.mkiv b/tex/context/base/core-spa.mkiv
index 0d166078a..780fbe3dc 100644
--- a/tex/context/base/core-spa.mkiv
+++ b/tex/context/base/core-spa.mkiv
@@ -96,6 +96,8 @@
\def\setcharacterspacing[#1]%
{\dosetattribute{spacing}{\csname\??ch:#1\endcsname}}
+\setvalue{\??ch:\s!reset}{\doresetattribute{spacing}}
+
\definecharacterspacing [frenchpunctuation] % name may change / unit is em
\setupcharacterspacing [frenchpunctuation] ["003A] [\c!left =.25] % :
@@ -136,6 +138,8 @@
\def\setcharacterkerning[#1]%
{\dosetattribute{kern}{\csname\??ck:#1\endcsname}}
+\setvalue{\??ck:\s!reset}{\doresetattribute{kern}}
+
\definecharacterkerning[extrakerning]
\setupcharacterkerning[extrakerning][\c!factor=.125]
@@ -199,6 +203,8 @@
\def\setbreakpoints[#1]%
{\dosetattribute{breakpoint}{\csname\??bp:#1\endcsname}}
+\setvalue{\??bp:\s!reset}{\doresetattribute{breakpoint}}
+
\definebreakpoints[compound]
\installbreakpoint [compound] [\number`+] [\c!left=3,\c!right=3,\c!type=1]
diff --git a/tex/context/base/core-trf.tex b/tex/context/base/core-trf.tex
index ab5dfd17a..315f4e474 100644
--- a/tex/context/base/core-trf.tex
+++ b/tex/context/base/core-trf.tex
@@ -115,9 +115,15 @@
\edef\scaleboxstampb % fast way [just sx/sy]
{\scaleparameter\c!sx
\scaleparameter\c!sy}%
+ \edef\scaleboxstampc
+ {11}%
\ifx\scaleboxstampa\empty
- \ifx\scaleboxstampb\empty
- % no scaling
+ \ifx\scaleboxstampb\scaleboxstampc
+ % no scaling, but still check; new
+ \doifsomething{\scaleparameter\c!maxwidth }{\letvalue{\currentscaletag\c!factor}\v!fit}%
+ \doifsomething{\scaleparameter\c!maxheight}{\letvalue{\currentscaletag\c!factor}\v!fit}%
+ \insidefloattrue % trick
+ \dodoscaleboxcalculations
\else
\dosetscalboxsxsy
\nodoscaleboxcalculations
@@ -221,21 +227,21 @@
{\doapplyscaleboxsize
\ifdim\scaleboxsizex>\scaleboxsizey
\docalculatescaleboxnorm \scaleboxdimx\c!factor\c!maxwidth\hsize\scaleboxhsize
-% not here: \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
\else
\docalculatescaleboxnorm \scaleboxdimy\c!factor\c!maxheight\scaleboxoutervsize\scaleboxvsize
-% not here: \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
\fi
\donetrue}
{\doifinsetelse{\scaleparameter\c!hfactor}{\v!max,\v!fit,\v!broad}
{\doapplyscaleboxsize
\docalculatescaleboxnorm \scaleboxdimy\c!hfactor\c!maxheight\scaleboxoutervsize\scaleboxvsize
-% not here: \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
\donetrue}
{\doifinsetelse{\scaleparameter\c!wfactor}{\v!max,\v!fit,\v!broad}
{\doapplyscaleboxsize
\docalculatescaleboxnorm \scaleboxdimx\c!wfactor\c!maxwidth\hsize\scaleboxhsize
-% not here: \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
\donetrue}
{\docalculatescaleboxnorm\scaleboxdimy\c!factor \c!height \textheight\scaleboxvsize
\docalculatescaleboxnorm\scaleboxdimy\c!hfactor\c!height \textheight\scaleboxvsize
diff --git a/tex/context/base/enco-ini.mkii b/tex/context/base/enco-ini.mkii
index 1daeda5d2..d39a64fca 100644
--- a/tex/context/base/enco-ini.mkii
+++ b/tex/context/base/enco-ini.mkii
@@ -15,10 +15,20 @@
\unprotect
-\useencoding[ans,il2,ec,tbo,pdf,uc,pol,qx,t5,cyr,agr] % pol and il2 will go away, not needed in mkiv
+\beginOLDTEX
-\useencoding[032,033,037] % fallbacks for some unicode chars
+ \useencoding[ans,il2,ec,tbo,pdf,pol,qx,t5,cyr,agr] % pol and il2 will go away, not needed in mkiv, uc removed
-\setupencoding[\s!default=ec] % was: [\s!default=\s!default]
+ \useencoding[032,033,037] % fallbacks for some unicode chars
+
+ \setupencoding[\s!default=ec] % was: [\s!default=\s!default]
+
+\endOLDTEX
+
+\beginXETEX
+
+ \setupencoding[\s!default=\s!default]
+
+\endXETEX
\protect \endinput
diff --git a/tex/context/base/enco-ini.tex b/tex/context/base/enco-ini.tex
index e6a27998f..202fa38ef 100644
--- a/tex/context/base/enco-ini.tex
+++ b/tex/context/base/enco-ini.tex
@@ -980,6 +980,9 @@
% "\dobuildtextaccent \char 18 a" but "\dobuildtextaccent {\char 18}{a}"
% instead
+\def\buildmathaccent#1%
+ {\mathaccent#1 }
+
\def\buildtextaccent#1#2% **
{\ifignoreaccent
\expandafter\nobuildtextaccent
@@ -987,14 +990,25 @@
\expandafter\dobuildtextaccent
\fi{#1}{#2}}
+\unexpanded\def\nobuildtextaccent#1#2%
+ {#2}
+
\unexpanded\def\dobuildtextaccent#1#2%
{{\let\char\normalaccent#1\let\char\normalchar#2}}
-\unexpanded\def\nobuildtextaccent#1#2%
- {#2}
+% EVENTUALLY THIS CODE WILL MOVE TO AN mkiv module
-\def\buildmathaccent#1%
- {\mathaccent#1 }
+\beginLUATEX
+
+\newbox\accenttestbox
+
+\unexpanded\def\dobuildtextaccent#1#2%
+ {{\global\setbox\accenttestbox\hbox{#1}%
+ \scratchcounter\ctxlua{characters.charcode(\number\accenttestbox)}%
+ \ifcase\scratchcounter\or\accent\scratchcounter\fi
+ \relax#2}}
+
+\endLUATEX
% will be overloaded later
diff --git a/tex/context/base/enco-pfr.mkiv b/tex/context/base/enco-pfr.mkiv
index 2db8670f0..52ef0cc3b 100644
--- a/tex/context/base/enco-pfr.mkiv
+++ b/tex/context/base/enco-pfr.mkiv
@@ -11,10 +11,12 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\ifx\pdfglyphtounicode\undefined \else
- \appendtoks
- \doif\jobsuffix{pdf}{\ctxlua{characters.setpdfunicodes()}}% pdftounicode mappings can only be done runtime
- \to \everystarttext
-\fi
+% obsolete, at least for wide fonts, we may need to support it otherwise
+%
+% \ifx\pdfglyphtounicode\undefined \else
+% \appendtoks
+% \doif\jobsuffix{pdf}{\ctxlua{characters.setpdfunicodes()}}% pdftounicode mappings can only be done runtime
+% \to \everystarttext
+% \fi
\endinput
diff --git a/tex/context/base/enco-pfr.tex b/tex/context/base/enco-pfr.tex
index 00d0192d3..902eb7bcd 100644
--- a/tex/context/base/enco-pfr.tex
+++ b/tex/context/base/enco-pfr.tex
@@ -15,6 +15,10 @@
\endinput
\endXETEX
+\beginLUATEX
+ \endinput
+\endLUATEX
+
\ifx\pdffontresource\undefined\else\endinput\fi
\writestatus{loading}{Context Encoding Macros (pdf)}
@@ -252,8 +256,6 @@
\letgvalue\pdffontfileresource\empty}%
\egroup}
-\beginETEX
-
\def\doincludepdffontresource
{\ifcsname\s!ucmap\fontfile\endcsname\else
\dodoincludepdffontresource
@@ -281,36 +283,6 @@
\letgvalue{\s!ucmap\fontfile}\empty
\fi}}
-\endETEX
-
-\beginTEX
-
-\def\doincludepdffontresource
- {\expandafter\ifcsname\s!ucmap\fontfile\endcsname\relax
- \dodoincludepdffontresource
- \fi}
-
-\def\dodoincludepdffontresource
- {\doifsomething\currentencoding % no \ifx
- {\expandafter\ifx\csname\pdffontresource\endcsname\relax
- \expandafter\ifx\csname\pdffontfileresource\endcsname\relax\else
- \doifsomething\pdffontfileresource
- {\pdfobj reserveobjnum {}%
- \setxvalue\pdffontresource{\the\pdflastobj}%
- \flushatshipout{\dododoincludepdffontresource{\currentencoding}}}%
-% \doglobal\appendetoks
-% \noexpand\dododoincludepdffontresource{\currentencoding}%
-% \to \everybeforeshipout}% prevent multiple loading
- \fi
- \fi
- \expandafter\ifx\csname\pdffontresource\endcsname\relax\else
- \expanded{\pdffontattr\font{/ToUnicode \csname\pdffontresource\endcsname\space0 R}}%
- % do it only once for each font
- \letgvalue{\s!ucmap\fontfile}\empty
- \fi}}
-
-\endTEX
-
%D For the moment, we keep this definition here, if only
%D because \type {\usepdffontencoding} is not defined in the
%D core. In the end, this will go to \type {enco-*.tex}.
diff --git a/tex/context/base/enco-utf.tex b/tex/context/base/enco-utf.tex
index 6855374a7..eac1b78b0 100644
--- a/tex/context/base/enco-utf.tex
+++ b/tex/context/base/enco-utf.tex
@@ -1,5 +1,5 @@
% filename : enco-utf.tex
-% comment : poor man's alternative for a proper enco file
+% comment : generated by mtxrun --script chars --utf
% author : Hans Hagen, PRAGMA-ADE, Hasselt NL
% copyright: PRAGMA ADE / ConTeXt Development Team
% license : see context related readme files
@@ -13,6 +13,8 @@
\fi
+% lc/uc/catcode mappings
+
\setcclcucx 0041 0061 0041 % LATIN CAPITAL LETTER A
\setcclcucx 0042 0062 0042 % LATIN CAPITAL LETTER B
\setcclcucx 0043 0063 0043 % LATIN CAPITAL LETTER C
@@ -1983,4 +1985,1130 @@
\setcclcucx FF59 FF59 FF39 % FULLWIDTH LATIN SMALL LETTER Y
\setcclcucx FF5A FF5A FF3A % FULLWIDTH LATIN SMALL LETTER Z
+% named characters mapped onto utf
+
+\def\nonbreakablespace { } % NO-BREAK SPACE
+\def\exclamdown {¡} % INVERTED EXCLAMATION MARK
+\def\textcent {¢} % CENT SIGN
+\def\textsterling {£} % POUND SIGN
+\def\textcurrency {¤} % CURRENCY SIGN
+\def\textyen {¥} % YEN SIGN
+\def\textbrokenbar {¦} % BROKEN BAR
+\def\sectionmark {§} % SECTION SIGN
+\def\textdiaeresis {¨} % DIAERESIS
+\def\copyright {©} % COPYRIGHT SIGN
+\def\ordfeminine {ª} % FEMININE ORDINAL INDICATOR
+\def\leftguillemot {«} % LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+\def\textlognot {¬} % NOT SIGN
+\def\softhyphen {­} % SOFT HYPHEN
+\def\registered {®} % REGISTERED SIGN
+\def\textmacron {¯} % MACRON
+\def\textdegree {°} % DEGREE SIGN
+\def\textpm {±} % PLUS-MINUS SIGN
+\def\twosuperior {²} % SUPERSCRIPT TWO
+\def\threesuperior {³} % SUPERSCRIPT THREE
+\def\textacute {´} % ACUTE ACCENT
+\def\textmu {µ} % MICRO SIGN
+\def\paragraphmark {¶} % PILCROW SIGN
+\def\periodcentered {·} % MIDDLE DOT
+\def\textcedilla {¸} % CEDILLA
+\def\onesuperior {¹} % SUPERSCRIPT ONE
+\def\ordmasculine {º} % MASCULINE ORDINAL INDICATOR
+\def\rightguillemot {»} % RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+\def\onequarter {¼} % VULGAR FRACTION ONE QUARTER
+\def\onehalf {½} % VULGAR FRACTION ONE HALF
+\def\threequarter {¾} % VULGAR FRACTION THREE QUARTERS
+\def\questiondown {¿} % INVERTED QUESTION MARK
+\def\Agrave {À} % LATIN CAPITAL LETTER A WITH GRAVE
+\def\Aacute {Á} % LATIN CAPITAL LETTER A WITH ACUTE
+\def\Acircumflex {Â} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+\def\Atilde {Ã} % LATIN CAPITAL LETTER A WITH TILDE
+\def\Adiaeresis {Ä} % LATIN CAPITAL LETTER A WITH DIAERESIS
+\def\Aring {Å} % LATIN CAPITAL LETTER A WITH RING ABOVE
+\def\AEligature {Æ} % LATIN CAPITAL LETTER AE
+\def\Ccedilla {Ç} % LATIN CAPITAL LETTER C WITH CEDILLA
+\def\Egrave {È} % LATIN CAPITAL LETTER E WITH GRAVE
+\def\Eacute {É} % LATIN CAPITAL LETTER E WITH ACUTE
+\def\Ecircumflex {Ê} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+\def\Ediaeresis {Ë} % LATIN CAPITAL LETTER E WITH DIAERESIS
+\def\Igrave {Ì} % LATIN CAPITAL LETTER I WITH GRAVE
+\def\Iacute {Í} % LATIN CAPITAL LETTER I WITH ACUTE
+\def\Icircumflex {Î} % LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+\def\Idiaeresis {Ï} % LATIN CAPITAL LETTER I WITH DIAERESIS
+\def\Eth {Ð} % LATIN CAPITAL LETTER ETH
+\def\Ntilde {Ñ} % LATIN CAPITAL LETTER N WITH TILDE
+\def\Ograve {Ò} % LATIN CAPITAL LETTER O WITH GRAVE
+\def\Oacute {Ó} % LATIN CAPITAL LETTER O WITH ACUTE
+\def\Ocircumflex {Ô} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+\def\Otilde {Õ} % LATIN CAPITAL LETTER O WITH TILDE
+\def\Odiaeresis {Ö} % LATIN CAPITAL LETTER O WITH DIAERESIS
+\def\textmultiply {×} % MULTIPLICATION SIGN
+\def\Ostroke {Ø} % LATIN CAPITAL LETTER O WITH STROKE
+\def\Ugrave {Ù} % LATIN CAPITAL LETTER U WITH GRAVE
+\def\Uacute {Ú} % LATIN CAPITAL LETTER U WITH ACUTE
+\def\Ucircumflex {Û} % LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+\def\Udiaeresis {Ü} % LATIN CAPITAL LETTER U WITH DIAERESIS
+\def\Yacute {Ý} % LATIN CAPITAL LETTER Y WITH ACUTE
+\def\Thorn {Þ} % LATIN CAPITAL LETTER THORN
+\def\ssharp {ß} % LATIN SMALL LETTER SHARP S
+\def\agrave {à} % LATIN SMALL LETTER A WITH GRAVE
+\def\aacute {á} % LATIN SMALL LETTER A WITH ACUTE
+\def\acircumflex {â} % LATIN SMALL LETTER A WITH CIRCUMFLEX
+\def\atilde {ã} % LATIN SMALL LETTER A WITH TILDE
+\def\adiaeresis {ä} % LATIN SMALL LETTER A WITH DIAERESIS
+\def\aring {å} % LATIN SMALL LETTER A WITH RING ABOVE
+\def\aeligature {æ} % LATIN SMALL LETTER AE
+\def\ccedilla {ç} % LATIN SMALL LETTER C WITH CEDILLA
+\def\egrave {è} % LATIN SMALL LETTER E WITH GRAVE
+\def\eacute {é} % LATIN SMALL LETTER E WITH ACUTE
+\def\ecircumflex {ê} % LATIN SMALL LETTER E WITH CIRCUMFLEX
+\def\ediaeresis {ë} % LATIN SMALL LETTER E WITH DIAERESIS
+\def\igrave {ì} % LATIN SMALL LETTER I WITH GRAVE
+\def\iacute {í} % LATIN SMALL LETTER I WITH ACUTE
+\def\icircumflex {î} % LATIN SMALL LETTER I WITH CIRCUMFLEX
+\def\idiaeresis {ï} % LATIN SMALL LETTER I WITH DIAERESIS
+\def\eth {ð} % LATIN SMALL LETTER ETH
+\def\ntilde {ñ} % LATIN SMALL LETTER N WITH TILDE
+\def\ograve {ò} % LATIN SMALL LETTER O WITH GRAVE
+\def\oacute {ó} % LATIN SMALL LETTER O WITH ACUTE
+\def\ocircumflex {ô} % LATIN SMALL LETTER O WITH CIRCUMFLEX
+\def\otilde {õ} % LATIN SMALL LETTER O WITH TILDE
+\def\odiaeresis {ö} % LATIN SMALL LETTER O WITH DIAERESIS
+\def\textdiv {÷} % DIVISION SIGN
+\def\ostroke {ø} % LATIN SMALL LETTER O WITH STROKE
+\def\ugrave {ù} % LATIN SMALL LETTER U WITH GRAVE
+\def\uacute {ú} % LATIN SMALL LETTER U WITH ACUTE
+\def\ucircumflex {û} % LATIN SMALL LETTER U WITH CIRCUMFLEX
+\def\udiaeresis {ü} % LATIN SMALL LETTER U WITH DIAERESIS
+\def\yacute {ý} % LATIN SMALL LETTER Y WITH ACUTE
+\def\thorn {þ} % LATIN SMALL LETTER THORN
+\def\ydiaeresis {ÿ} % LATIN SMALL LETTER Y WITH DIAERESIS
+\def\Amacron {Ā} % LATIN CAPITAL LETTER A WITH MACRON
+\def\amacron {ā} % LATIN SMALL LETTER A WITH MACRON
+\def\Abreve {Ă} % LATIN CAPITAL LETTER A WITH BREVE
+\def\abreve {ă} % LATIN SMALL LETTER A WITH BREVE
+\def\Aogonek {Ą} % LATIN CAPITAL LETTER A WITH OGONEK
+\def\aogonek {ą} % LATIN SMALL LETTER A WITH OGONEK
+\def\Cacute {Ć} % LATIN CAPITAL LETTER C WITH ACUTE
+\def\cacute {ć} % LATIN SMALL LETTER C WITH ACUTE
+\def\Ccircumflex {Ĉ} % LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+\def\ccircumflex {ĉ} % LATIN SMALL LETTER C WITH CIRCUMFLEX
+\def\Cdotaccent {Ċ} % LATIN CAPITAL LETTER C WITH DOT ABOVE
+\def\cdotaccent {ċ} % LATIN SMALL LETTER C WITH DOT ABOVE
+\def\Ccaron {Č} % LATIN CAPITAL LETTER C WITH CARON
+\def\ccaron {č} % LATIN SMALL LETTER C WITH CARON
+\def\Dcaron {Ď} % LATIN CAPITAL LETTER D WITH CARON
+\def\dcaron {ď} % LATIN SMALL LETTER D WITH CARON
+\def\Dstroke {Đ} % LATIN CAPITAL LETTER D WITH STROKE
+\def\dstroke {đ} % LATIN SMALL LETTER D WITH STROKE
+\def\Emacron {Ē} % LATIN CAPITAL LETTER E WITH MACRON
+\def\emacron {ē} % LATIN SMALL LETTER E WITH MACRON
+\def\Ebreve {Ĕ} % LATIN CAPITAL LETTER E WITH BREVE
+\def\ebreve {ĕ} % LATIN SMALL LETTER E WITH BREVE
+\def\Edotaccent {Ė} % LATIN CAPITAL LETTER E WITH DOT ABOVE
+\def\edotaccent {ė} % LATIN SMALL LETTER E WITH DOT ABOVE
+\def\Eogonek {Ę} % LATIN CAPITAL LETTER E WITH OGONEK
+\def\eogonek {ę} % LATIN SMALL LETTER E WITH OGONEK
+\def\Ecaron {Ě} % LATIN CAPITAL LETTER E WITH CARON
+\def\ecaron {ě} % LATIN SMALL LETTER E WITH CARON
+\def\Gcircumflex {Ĝ} % LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+\def\gcircumflex {ĝ} % LATIN SMALL LETTER G WITH CIRCUMFLEX
+\def\Gbreve {Ğ} % LATIN CAPITAL LETTER G WITH BREVE
+\def\gbreve {ğ} % LATIN SMALL LETTER G WITH BREVE
+\def\Gdotaccent {Ġ} % LATIN CAPITAL LETTER G WITH DOT ABOVE
+\def\gdotaccent {ġ} % LATIN SMALL LETTER G WITH DOT ABOVE
+\def\Gcommaaccent {Ģ} % LATIN CAPITAL LETTER G WITH CEDILLA
+\def\gcommaaccent {ģ} % LATIN SMALL LETTER G WITH CEDILLA
+\def\Hcircumflex {Ĥ} % LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+\def\hcircumflex {ĥ} % LATIN SMALL LETTER H WITH CIRCUMFLEX
+\def\Hstroke {Ħ} % LATIN CAPITAL LETTER H WITH STROKE
+\def\hstroke {ħ} % LATIN SMALL LETTER H WITH STROKE
+\def\Itilde {Ĩ} % LATIN CAPITAL LETTER I WITH TILDE
+\def\itilde {ĩ} % LATIN SMALL LETTER I WITH TILDE
+\def\Imacron {Ī} % LATIN CAPITAL LETTER I WITH MACRON
+\def\imacron {ī} % LATIN SMALL LETTER I WITH MACRON
+\def\Ibreve {Ĭ} % LATIN CAPITAL LETTER I WITH BREVE
+\def\ibreve {ĭ} % LATIN SMALL LETTER I WITH BREVE
+\def\Iogonek {Į} % LATIN CAPITAL LETTER I WITH OGONEK
+\def\iogonek {į} % LATIN SMALL LETTER I WITH OGONEK
+\def\Idotaccent {İ} % LATIN CAPITAL LETTER I WITH DOT ABOVE
+\def\dotlessi {ı} % LATIN SMALL LETTER DOTLESS I
+\def\IJligature {IJ} % LATIN CAPITAL LIGATURE IJ
+\def\ijligature {ij} % LATIN SMALL LIGATURE IJ
+\def\Jcircumflex {Ĵ} % LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+\def\jcircumflex {ĵ} % LATIN SMALL LETTER J WITH CIRCUMFLEX
+\def\Kcommaaccent {Ķ} % LATIN CAPITAL LETTER K WITH CEDILLA
+\def\kcommaaccent {ķ} % LATIN SMALL LETTER K WITH CEDILLA
+\def\kkra {ĸ} % LATIN SMALL LETTER KRA
+\def\Lacute {Ĺ} % LATIN CAPITAL LETTER L WITH ACUTE
+\def\lacute {ĺ} % LATIN SMALL LETTER L WITH ACUTE
+\def\Lcommaaccent {Ļ} % LATIN CAPITAL LETTER L WITH CEDILLA
+\def\lcommaaccent {ļ} % LATIN SMALL LETTER L WITH CEDILLA
+\def\Lcaron {Ľ} % LATIN CAPITAL LETTER L WITH CARON
+\def\lcaron {ľ} % LATIN SMALL LETTER L WITH CARON
+\def\Ldotmiddle {Ŀ} % LATIN CAPITAL LETTER L WITH MIDDLE DOT
+\def\ldotmiddle {ŀ} % LATIN SMALL LETTER L WITH MIDDLE DOT
+\def\Lstroke {Ł} % LATIN CAPITAL LETTER L WITH STROKE
+\def\lstroke {ł} % LATIN SMALL LETTER L WITH STROKE
+\def\Nacute {Ń} % LATIN CAPITAL LETTER N WITH ACUTE
+\def\nacute {ń} % LATIN SMALL LETTER N WITH ACUTE
+\def\Ncommaaccent {Ņ} % LATIN CAPITAL LETTER N WITH CEDILLA
+\def\ncommaaccent {ņ} % LATIN SMALL LETTER N WITH CEDILLA
+\def\Ncaron {Ň} % LATIN CAPITAL LETTER N WITH CARON
+\def\ncaron {ň} % LATIN SMALL LETTER N WITH CARON
+\def\napostrophe {ʼn} % LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+\def\Neng {Ŋ} % LATIN CAPITAL LETTER ENG
+\def\neng {ŋ} % LATIN SMALL LETTER ENG
+\def\Omacron {Ō} % LATIN CAPITAL LETTER O WITH MACRON
+\def\omacron {ō} % LATIN SMALL LETTER O WITH MACRON
+\def\Obreve {Ŏ} % LATIN CAPITAL LETTER O WITH BREVE
+\def\obreve {ŏ} % LATIN SMALL LETTER O WITH BREVE
+\def\Ohungarumlaut {Ő} % LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+\def\ohungarumlaut {ő} % LATIN SMALL LETTER O WITH DOUBLE ACUTE
+\def\OEligature {Œ} % LATIN CAPITAL LIGATURE OE
+\def\oeligature {œ} % LATIN SMALL LIGATURE OE
+\def\Racute {Ŕ} % LATIN CAPITAL LETTER R WITH ACUTE
+\def\racute {ŕ} % LATIN SMALL LETTER R WITH ACUTE
+\def\Rcommaaccent {Ŗ} % LATIN CAPITAL LETTER R WITH CEDILLA
+\def\rcommaaccent {ŗ} % LATIN SMALL LETTER R WITH CEDILLA
+\def\Rcaron {Ř} % LATIN CAPITAL LETTER R WITH CARON
+\def\rcaron {ř} % LATIN SMALL LETTER R WITH CARON
+\def\Sacute {Ś} % LATIN CAPITAL LETTER S WITH ACUTE
+\def\sacute {ś} % LATIN SMALL LETTER S WITH ACUTE
+\def\Scircumflex {Ŝ} % LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+\def\scircumflex {ŝ} % LATIN SMALL LETTER S WITH CIRCUMFLEX
+\def\Scedilla {Ş} % LATIN CAPITAL LETTER S WITH CEDILLA
+\def\scedilla {ş} % LATIN SMALL LETTER S WITH CEDILLA
+\def\Scaron {Š} % LATIN CAPITAL LETTER S WITH CARON
+\def\scaron {š} % LATIN SMALL LETTER S WITH CARON
+\def\Tcedilla {Ţ} % LATIN CAPITAL LETTER T WITH CEDILLA
+\def\tcedilla {ţ} % LATIN SMALL LETTER T WITH CEDILLA
+\def\Tcaron {Ť} % LATIN CAPITAL LETTER T WITH CARON
+\def\tcaron {ť} % LATIN SMALL LETTER T WITH CARON
+\def\Tstroke {Ŧ} % LATIN CAPITAL LETTER T WITH STROKE
+\def\tstroke {ŧ} % LATIN SMALL LETTER T WITH STROKE
+\def\Utilde {Ũ} % LATIN CAPITAL LETTER U WITH TILDE
+\def\utilde {ũ} % LATIN SMALL LETTER U WITH TILDE
+\def\Umacron {Ū} % LATIN CAPITAL LETTER U WITH MACRON
+\def\umacron {ū} % LATIN SMALL LETTER U WITH MACRON
+\def\Ubreve {Ŭ} % LATIN CAPITAL LETTER U WITH BREVE
+\def\ubreve {ŭ} % LATIN SMALL LETTER U WITH BREVE
+\def\Uring {Ů} % LATIN CAPITAL LETTER U WITH RING ABOVE
+\def\uring {ů} % LATIN SMALL LETTER U WITH RING ABOVE
+\def\Uhungarumlaut {Ű} % LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+\def\uhungarumlaut {ű} % LATIN SMALL LETTER U WITH DOUBLE ACUTE
+\def\Uogonek {Ų} % LATIN CAPITAL LETTER U WITH OGONEK
+\def\uogonek {ų} % LATIN SMALL LETTER U WITH OGONEK
+\def\Wcircumflex {Ŵ} % LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+\def\wcircumflex {ŵ} % LATIN SMALL LETTER W WITH CIRCUMFLEX
+\def\Ycircumflex {Ŷ} % LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+\def\ycircumflex {ŷ} % LATIN SMALL LETTER Y WITH CIRCUMFLEX
+\def\Ydiaeresis {Ÿ} % LATIN CAPITAL LETTER Y WITH DIAERESIS
+\def\Zacute {Ź} % LATIN CAPITAL LETTER Z WITH ACUTE
+\def\zacute {ź} % LATIN SMALL LETTER Z WITH ACUTE
+\def\Zdotaccent {Ż} % LATIN CAPITAL LETTER Z WITH DOT ABOVE
+\def\zdotaccent {ż} % LATIN SMALL LETTER Z WITH DOT ABOVE
+\def\Zcaron {Ž} % LATIN CAPITAL LETTER Z WITH CARON
+\def\zcaron {ž} % LATIN SMALL LETTER Z WITH CARON
+\def\slong {ſ} % LATIN SMALL LETTER LONG S
+\def\bstroke {ƀ} % LATIN SMALL LETTER B WITH STROKE
+\def\Bhook {Ɓ} % LATIN CAPITAL LETTER B WITH HOOK
+\def\Chook {Ƈ} % LATIN CAPITAL LETTER C WITH HOOK
+\def\chook {ƈ} % LATIN SMALL LETTER C WITH HOOK
+\def\Dafrican {Ɖ} % LATIN CAPITAL LETTER AFRICAN D
+\def\Dhook {Ɗ} % LATIN CAPITAL LETTER D WITH HOOK
+\def\Schwa {Ə} % LATIN CAPITAL LETTER SCHWA
+\def\Fhook {Ƒ} % LATIN CAPITAL LETTER F WITH HOOK
+\def\fhook {ƒ} % LATIN SMALL LETTER F WITH HOOK
+\def\Ghook {Ɠ} % LATIN CAPITAL LETTER G WITH HOOK
+\def\Istroke {Ɨ} % LATIN CAPITAL LETTER I WITH STROKE
+\def\Khook {Ƙ} % LATIN CAPITAL LETTER K WITH HOOK
+\def\khook {ƙ} % LATIN SMALL LETTER K WITH HOOK
+\def\lbar {ƚ} % LATIN SMALL LETTER L WITH BAR
+\def\Ohorn {Ơ} % LATIN CAPITAL LETTER O WITH HORN
+\def\ohorn {ơ} % LATIN SMALL LETTER O WITH HORN
+\def\Phook {Ƥ} % LATIN CAPITAL LETTER P WITH HOOK
+\def\phook {ƥ} % LATIN SMALL LETTER P WITH HOOK
+\def\Thook {Ƭ} % LATIN CAPITAL LETTER T WITH HOOK
+\def\thook {ƭ} % LATIN SMALL LETTER T WITH HOOK
+\def\Uhorn {Ư} % LATIN CAPITAL LETTER U WITH HORN
+\def\uhorn {ư} % LATIN SMALL LETTER U WITH HORN
+\def\Uhook {Ʋ} % LATIN CAPITAL LETTER V WITH HOOK
+\def\Yhook {Ƴ} % LATIN CAPITAL LETTER Y WITH HOOK
+\def\yhook {ƴ} % LATIN SMALL LETTER Y WITH HOOK
+\def\Zstroke {Ƶ} % LATIN CAPITAL LETTER Z WITH STROKE
+\def\zstroke {ƶ} % LATIN SMALL LETTER Z WITH STROKE
+\def\DZcaronligature {DŽ} % LATIN CAPITAL LETTER DZ WITH CARON
+\def\Dzcaronligature {Dž} % LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+\def\dzcaronligature {dž} % LATIN SMALL LETTER DZ WITH CARON
+\def\LJligature {LJ} % LATIN CAPITAL LETTER LJ
+\def\Ljligature {Lj} % LATIN CAPITAL LETTER L WITH SMALL LETTER J
+\def\ljligature {lj} % LATIN SMALL LETTER LJ
+\def\NJligature {NJ} % LATIN CAPITAL LETTER NJ
+\def\Njligature {Nj} % LATIN CAPITAL LETTER N WITH SMALL LETTER J
+\def\njligature {nj} % LATIN SMALL LETTER NJ
+\def\Acaron {Ǎ} % LATIN CAPITAL LETTER A WITH CARON
+\def\acaron {ǎ} % LATIN SMALL LETTER A WITH CARON
+\def\Icaron {Ǐ} % LATIN CAPITAL LETTER I WITH CARON
+\def\icaron {ǐ} % LATIN SMALL LETTER I WITH CARON
+\def\Ocaron {Ǒ} % LATIN CAPITAL LETTER O WITH CARON
+\def\ocaron {ǒ} % LATIN SMALL LETTER O WITH CARON
+\def\Ucaron {Ǔ} % LATIN CAPITAL LETTER U WITH CARON
+\def\ucaron {ǔ} % LATIN SMALL LETTER U WITH CARON
+\def\Udiaeresismacron {Ǖ} % LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+\def\udiaeresismacron {ǖ} % LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+\def\Udiaeresisacute {Ǘ} % LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+\def\udiaeresisacute {ǘ} % LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+\def\Udiaeresiscaron {Ǚ} % LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+\def\udiaeresiscaron {ǚ} % LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+\def\Udiaeresisgrave {Ǜ} % LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+\def\udiaeresisgrave {ǜ} % LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
+\def\Adiaeresismacron {Ǟ} % LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+\def\adiaeresismacron {ǟ} % LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+\def\Adotaccentmacron {Ǡ} % LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+\def\adotaccentmacron {ǡ} % LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+\def\AEmacron {Ǣ} % LATIN CAPITAL LETTER AE WITH MACRON
+\def\aemacron {ǣ} % LATIN SMALL LETTER AE WITH MACRON
+\def\Gstroke {Ǥ} % LATIN CAPITAL LETTER G WITH STROKE
+\def\gstroke {ǥ} % LATIN SMALL LETTER G WITH STROKE
+\def\Gcaron {Ǧ} % LATIN CAPITAL LETTER G WITH CARON
+\def\gcaron {ǧ} % LATIN SMALL LETTER G WITH CARON
+\def\Kcaron {Ǩ} % LATIN CAPITAL LETTER K WITH CARON
+\def\kcaron {ǩ} % LATIN SMALL LETTER K WITH CARON
+\def\Oogonek {Ǫ} % LATIN CAPITAL LETTER O WITH OGONEK
+\def\oogonek {ǫ} % LATIN SMALL LETTER O WITH OGONEK
+\def\Oogonekmacron {Ǭ} % LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+\def\oogonekmacron {ǭ} % LATIN SMALL LETTER O WITH OGONEK AND MACRON
+\def\jcaron {ǰ} % LATIN SMALL LETTER J WITH CARON
+\def\DZligature {DZ} % LATIN CAPITAL LETTER DZ
+\def\Dzligature {Dz} % LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+\def\dzligature {dz} % LATIN SMALL LETTER DZ
+\def\Gacute {Ǵ} % LATIN CAPITAL LETTER G WITH ACUTE
+\def\gacute {ǵ} % LATIN SMALL LETTER G WITH ACUTE
+\def\Ngrave {Ǹ} % LATIN CAPITAL LETTER N WITH GRAVE
+\def\ngrave {ǹ} % LATIN SMALL LETTER N WITH GRAVE
+\def\Aringacute {Ǻ} % LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+\def\aringacute {ǻ} % LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+\def\AEacute {Ǽ} % LATIN CAPITAL LETTER AE WITH ACUTE
+\def\aeacute {ǽ} % LATIN SMALL LETTER AE WITH ACUTE
+\def\Ostrokeacute {Ǿ} % LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+\def\ostrokeacute {ǿ} % LATIN SMALL LETTER O WITH STROKE AND ACUTE
+\def\Adoublegrave {Ȁ} % LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+\def\adoublegrave {ȁ} % LATIN SMALL LETTER A WITH DOUBLE GRAVE
+\def\Ainvertedbreve {Ȃ} % LATIN CAPITAL LETTER A WITH INVERTED BREVE
+\def\ainvertedbreve {ȃ} % LATIN SMALL LETTER A WITH INVERTED BREVE
+\def\Edoublegrave {Ȅ} % LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+\def\edoublegrave {ȅ} % LATIN SMALL LETTER E WITH DOUBLE GRAVE
+\def\Einvertedbreve {Ȇ} % LATIN CAPITAL LETTER E WITH INVERTED BREVE
+\def\einvertedbreve {ȇ} % LATIN SMALL LETTER E WITH INVERTED BREVE
+\def\Idoublegrave {Ȉ} % LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+\def\idoublegrave {ȉ} % LATIN SMALL LETTER I WITH DOUBLE GRAVE
+\def\Iinvertedbreve {Ȋ} % LATIN CAPITAL LETTER I WITH INVERTED BREVE
+\def\iinvertedbreve {ȋ} % LATIN SMALL LETTER I WITH INVERTED BREVE
+\def\Odoublegrave {Ȍ} % LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+\def\odoublegrave {ȍ} % LATIN SMALL LETTER O WITH DOUBLE GRAVE
+\def\Oinvertedbreve {Ȏ} % LATIN CAPITAL LETTER O WITH INVERTED BREVE
+\def\oinvertedbreve {ȏ} % LATIN SMALL LETTER O WITH INVERTED BREVE
+\def\Rdoublegrave {Ȑ} % LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+\def\rdoublegrave {ȑ} % LATIN SMALL LETTER R WITH DOUBLE GRAVE
+\def\Rinvertedbreve {Ȓ} % LATIN CAPITAL LETTER R WITH INVERTED BREVE
+\def\rinvertedbreve {ȓ} % LATIN SMALL LETTER R WITH INVERTED BREVE
+\def\Udoublegrave {Ȕ} % LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+\def\udoublegrave {ȕ} % LATIN SMALL LETTER U WITH DOUBLE GRAVE
+\def\Uinvertedbreve {Ȗ} % LATIN CAPITAL LETTER U WITH INVERTED BREVE
+\def\uinvertedbreve {ȗ} % LATIN SMALL LETTER U WITH INVERTED BREVE
+\def\Scommaaccent {Ș} % LATIN CAPITAL LETTER S WITH COMMA BELOW
+\def\scommaaccent {ș} % LATIN SMALL LETTER S WITH COMMA BELOW
+\def\Tcommaaccent {Ț} % LATIN CAPITAL LETTER T WITH COMMA BELOW
+\def\tcommaaccent {ț} % LATIN SMALL LETTER T WITH COMMA BELOW
+\def\Hcaron {Ȟ} % LATIN CAPITAL LETTER H WITH CARON
+\def\hcaron {ȟ} % LATIN SMALL LETTER H WITH CARON
+\def\dcurl {ȡ} % LATIN SMALL LETTER D WITH CURL
+\def\Zhook {Ȥ} % LATIN CAPITAL LETTER Z WITH HOOK
+\def\zhook {ȥ} % LATIN SMALL LETTER Z WITH HOOK
+\def\Adotaccent {Ȧ} % LATIN CAPITAL LETTER A WITH DOT ABOVE
+\def\adotaccent {ȧ} % LATIN SMALL LETTER A WITH DOT ABOVE
+\def\Ecedilla {Ȩ} % LATIN CAPITAL LETTER E WITH CEDILLA
+\def\ecedilla {ȩ} % LATIN SMALL LETTER E WITH CEDILLA
+\def\Odiaeresismacron {Ȫ} % LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+\def\odiaeresismacron {ȫ} % LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
+\def\Otildemacron {Ȭ} % LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+\def\otildemacron {ȭ} % LATIN SMALL LETTER O WITH TILDE AND MACRON
+\def\Odotaccent {Ȯ} % LATIN CAPITAL LETTER O WITH DOT ABOVE
+\def\odotaccent {ȯ} % LATIN SMALL LETTER O WITH DOT ABOVE
+\def\Odotaccentmacron {Ȱ} % LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+\def\odotaccentmacron {ȱ} % LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
+\def\Ymacron {Ȳ} % LATIN CAPITAL LETTER Y WITH MACRON
+\def\ymacron {ȳ} % LATIN SMALL LETTER Y WITH MACRON
+\def\lcurl {ȴ} % LATIN SMALL LETTER L WITH CURL
+\def\ncurl {ȵ} % LATIN SMALL LETTER N WITH CURL
+\def\tcurl {ȶ} % LATIN SMALL LETTER T WITH CURL
+\def\dotlessj {ȷ} % LATIN SMALL LETTER DOTLESS J
+\def\Astroke {Ⱥ} % LATIN CAPITAL LETTER A WITH STROKE
+\def\Cstroke {Ȼ} % LATIN CAPITAL LETTER C WITH STROKE
+\def\cstroke {ȼ} % LATIN SMALL LETTER C WITH STROKE
+\def\Lbar {Ƚ} % LATIN CAPITAL LETTER L WITH BAR
+\def\bhook {ɓ} % LATIN SMALL LETTER B WITH HOOK
+\def\ccurl {ɕ} % LATIN SMALL LETTER C WITH CURL
+\def\dtail {ɖ} % LATIN SMALL LETTER D WITH TAIL
+\def\dhook {ɗ} % LATIN SMALL LETTER D WITH HOOK
+\def\schwa {ə} % LATIN SMALL LETTER SCHWA
+\def\schwahook {ɚ} % LATIN SMALL LETTER SCHWA WITH HOOK
+\def\dotlessjstroke {ɟ} % LATIN SMALL LETTER DOTLESS J WITH STROKE
+\def\textcircumflex {ˆ} % MODIFIER LETTER CIRCUMFLEX ACCENT
+\def\textcaron {ˇ} % CARON
+\def\textbreve {˘} % BREVE
+\def\textdotaccent {˙} % DOT ABOVE
+\def\textring {˚} % RING ABOVE
+\def\textogonek {˛} % OGONEK
+\def\texttilde {˜} % SMALL TILDE
+\def\texthungarumlaut {˝} % DOUBLE ACUTE ACCENT
+\def\greektonos {΄} % GREEK TONOS
+\def\greekdialytikatonos {΅} % GREEK DIALYTIKA TONOS
+\def\greekAlphatonos {Ά} % GREEK CAPITAL LETTER ALPHA WITH TONOS
+\def\greekEpsilontonos {Έ} % GREEK CAPITAL LETTER EPSILON WITH TONOS
+\def\greekEtatonos {Ή} % GREEK CAPITAL LETTER ETA WITH TONOS
+\def\greekIotatonos {Ί} % GREEK CAPITAL LETTER IOTA WITH TONOS
+\def\greekOmicrontonos {Ό} % GREEK CAPITAL LETTER OMICRON WITH TONOS
+\def\greekUpsilontonos {Ύ} % GREEK CAPITAL LETTER UPSILON WITH TONOS
+\def\greekOmegatonos {Ώ} % GREEK CAPITAL LETTER OMEGA WITH TONOS
+\def\greekiotadialytikatonos {ΐ} % GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+\def\greekAlpha {Α} % GREEK CAPITAL LETTER ALPHA
+\def\greekBeta {Β} % GREEK CAPITAL LETTER BETA
+\def\greekGamma {Γ} % GREEK CAPITAL LETTER GAMMA
+\def\greekDelta {Δ} % GREEK CAPITAL LETTER DELTA
+\def\greekEpsilon {Ε} % GREEK CAPITAL LETTER EPSILON
+\def\greekZeta {Ζ} % GREEK CAPITAL LETTER ZETA
+\def\greekEta {Η} % GREEK CAPITAL LETTER ETA
+\def\greekTheta {Θ} % GREEK CAPITAL LETTER THETA
+\def\greekIota {Ι} % GREEK CAPITAL LETTER IOTA
+\def\greekKappa {Κ} % GREEK CAPITAL LETTER KAPPA
+\def\greekLambda {Λ} % GREEK CAPITAL LETTER LAMDA
+\def\greekMu {Μ} % GREEK CAPITAL LETTER MU
+\def\greekNu {Ν} % GREEK CAPITAL LETTER NU
+\def\greekXi {Ξ} % GREEK CAPITAL LETTER XI
+\def\greekOmicron {Ο} % GREEK CAPITAL LETTER OMICRON
+\def\greekPi {Π} % GREEK CAPITAL LETTER PI
+\def\greekRho {Ρ} % GREEK CAPITAL LETTER RHO
+\def\greekSigma {Σ} % GREEK CAPITAL LETTER SIGMA
+\def\greekTau {Τ} % GREEK CAPITAL LETTER TAU
+\def\greekUpsilon {Υ} % GREEK CAPITAL LETTER UPSILON
+\def\greekPhi {Φ} % GREEK CAPITAL LETTER PHI
+\def\greekChi {Χ} % GREEK CAPITAL LETTER CHI
+\def\greekPsi {Ψ} % GREEK CAPITAL LETTER PSI
+\def\greekOmega {Ω} % GREEK CAPITAL LETTER OMEGA
+\def\greekIotadialytika {Ϊ} % GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+\def\greekUpsilondialytika {Ϋ} % GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+\def\greekalphatonos {ά} % GREEK SMALL LETTER ALPHA WITH TONOS
+\def\greekepsilontonos {έ} % GREEK SMALL LETTER EPSILON WITH TONOS
+\def\greeketatonos {ή} % GREEK SMALL LETTER ETA WITH TONOS
+\def\greekiotatonos {ί} % GREEK SMALL LETTER IOTA WITH TONOS
+\def\greekupsilondialytikatonos {ΰ} % GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+\def\greekalpha {α} % GREEK SMALL LETTER ALPHA
+\def\greekbeta {β} % GREEK SMALL LETTER BETA
+\def\greekgamma {γ} % GREEK SMALL LETTER GAMMA
+\def\greekdelta {δ} % GREEK SMALL LETTER DELTA
+\def\greekepsilon {ε} % GREEK SMALL LETTER EPSILON
+\def\greekzeta {ζ} % GREEK SMALL LETTER ZETA
+\def\greeketa {η} % GREEK SMALL LETTER ETA
+\def\greektheta {θ} % GREEK SMALL LETTER THETA
+\def\greekiota {ι} % GREEK SMALL LETTER IOTA
+\def\greekkappa {κ} % GREEK SMALL LETTER KAPPA
+\def\greeklambda {λ} % GREEK SMALL LETTER LAMDA
+\def\greekmu {μ} % GREEK SMALL LETTER MU
+\def\greeknu {ν} % GREEK SMALL LETTER NU
+\def\greekxi {ξ} % GREEK SMALL LETTER XI
+\def\greekomicron {ο} % GREEK SMALL LETTER OMICRON
+\def\greekpi {π} % GREEK SMALL LETTER PI
+\def\greekrho {ρ} % GREEK SMALL LETTER RHO
+\def\greekfinalsigma {ς} % GREEK SMALL LETTER FINAL SIGMA
+\def\greeksigma {σ} % GREEK SMALL LETTER SIGMA
+\def\greektau {τ} % GREEK SMALL LETTER TAU
+\def\greekupsilon {υ} % GREEK SMALL LETTER UPSILON
+\def\greekphi {φ} % GREEK SMALL LETTER PHI
+\def\greekchi {χ} % GREEK SMALL LETTER CHI
+\def\greekpsi {ψ} % GREEK SMALL LETTER PSI
+\def\greekomega {ω} % GREEK SMALL LETTER OMEGA
+\def\greekiotadialytika {ϊ} % GREEK SMALL LETTER IOTA WITH DIALYTIKA
+\def\greekupsilondiaeresis {ϋ} % GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+\def\greekomicrontonos {ό} % GREEK SMALL LETTER OMICRON WITH TONOS
+\def\greekupsilontonos {ύ} % GREEK SMALL LETTER UPSILON WITH TONOS
+\def\greekomegatonos {ώ} % GREEK SMALL LETTER OMEGA WITH TONOS
+\def\greekthetaalt {ϑ} % GREEK THETA SYMBOL
+\def\greekphialt {ϕ} % GREEK PHI SYMBOL
+\def\greekpialt {ϖ} % GREEK PI SYMBOL
+\def\greekkoppa {ϙ} % GREEK SMALL LETTER ARCHAIC KOPPA
+\def\greekstigma {ϛ} % GREEK SMALL LETTER STIGMA
+\def\greekdigamma {ϝ} % GREEK SMALL LETTER DIGAMMA
+\def\greeknumkoppa {ϟ} % GREEK SMALL LETTER KOPPA
+\def\greeksampi {ϡ} % GREEK SMALL LETTER SAMPI
+\def\greekrhoalt {ϱ} % GREEK RHO SYMBOL
+\def\greeksigmalunate {ϲ} % GREEK LUNATE SIGMA SYMBOL
+\def\greekepsilonalt {ϵ} % GREEK LUNATE EPSILON SYMBOL
+\def\greekSigmalunate {Ϲ} % GREEK CAPITAL LUNATE SIGMA SYMBOL
+\def\cyrillicEgrave {Ѐ} % CYRILLIC CAPITAL LETTER IE WITH GRAVE
+\def\cyrillicYO {Ё} % CYRILLIC CAPITAL LETTER IO
+\def\cyrillicDJE {Ђ} % CYRILLIC CAPITAL LETTER DJE
+\def\cyrillicGJE {Ѓ} % CYRILLIC CAPITAL LETTER GJE
+\def\cyrillicIE {Є} % CYRILLIC CAPITAL LETTER UKRAINIAN IE
+\def\cyrillicDZE {Ѕ} % CYRILLIC CAPITAL LETTER DZE
+\def\cyrillicII {І} % CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+\def\cyrillicYI {Ї} % CYRILLIC CAPITAL LETTER YI
+\def\cyrillicJE {Ј} % CYRILLIC CAPITAL LETTER JE
+\def\cyrillicLJE {Љ} % CYRILLIC CAPITAL LETTER LJE
+\def\cyrillicNJE {Њ} % CYRILLIC CAPITAL LETTER NJE
+\def\cyrillicTSHE {Ћ} % CYRILLIC CAPITAL LETTER TSHE
+\def\cyrillicKJE {Ќ} % CYRILLIC CAPITAL LETTER KJE
+\def\cyrillicIgrave {Ѝ} % CYRILLIC CAPITAL LETTER I WITH GRAVE
+\def\cyrillicUSHRT {Ў} % CYRILLIC CAPITAL LETTER SHORT U
+\def\cyrillicDZHE {Џ} % CYRILLIC CAPITAL LETTER DZHE
+\def\cyrillicA {А} % CYRILLIC CAPITAL LETTER A
+\def\cyrillicB {Б} % CYRILLIC CAPITAL LETTER BE
+\def\cyrillicV {В} % CYRILLIC CAPITAL LETTER VE
+\def\cyrillicG {Г} % CYRILLIC CAPITAL LETTER GHE
+\def\cyrillicD {Д} % CYRILLIC CAPITAL LETTER DE
+\def\cyrillicE {Е} % CYRILLIC CAPITAL LETTER IE
+\def\cyrillicZH {Ж} % CYRILLIC CAPITAL LETTER ZHE
+\def\cyrillicZ {З} % CYRILLIC CAPITAL LETTER ZE
+\def\cyrillicI {И} % CYRILLIC CAPITAL LETTER I
+\def\cyrillicISHRT {Й} % CYRILLIC CAPITAL LETTER SHORT I
+\def\cyrillicK {К} % CYRILLIC CAPITAL LETTER KA
+\def\cyrillicL {Л} % CYRILLIC CAPITAL LETTER EL
+\def\cyrillicM {М} % CYRILLIC CAPITAL LETTER EM
+\def\cyrillicN {Н} % CYRILLIC CAPITAL LETTER EN
+\def\cyrillicO {О} % CYRILLIC CAPITAL LETTER O
+\def\cyrillicP {П} % CYRILLIC CAPITAL LETTER PE
+\def\cyrillicR {Р} % CYRILLIC CAPITAL LETTER ER
+\def\cyrillicS {С} % CYRILLIC CAPITAL LETTER ES
+\def\cyrillicT {Т} % CYRILLIC CAPITAL LETTER TE
+\def\cyrillicU {У} % CYRILLIC CAPITAL LETTER U
+\def\cyrillicF {Ф} % CYRILLIC CAPITAL LETTER EF
+\def\cyrillicH {Х} % CYRILLIC CAPITAL LETTER HA
+\def\cyrillicC {Ц} % CYRILLIC CAPITAL LETTER TSE
+\def\cyrillicCH {Ч} % CYRILLIC CAPITAL LETTER CHE
+\def\cyrillicSH {Ш} % CYRILLIC CAPITAL LETTER SHA
+\def\cyrillicSHCH {Щ} % CYRILLIC CAPITAL LETTER SHCHA
+\def\cyrillicHRDSN {Ъ} % CYRILLIC CAPITAL LETTER HARD SIGN
+\def\cyrillicERY {Ы} % CYRILLIC CAPITAL LETTER YERU
+\def\cyrillicSFTSN {Ь} % CYRILLIC CAPITAL LETTER SOFT SIGN
+\def\cyrillicEREV {Э} % CYRILLIC CAPITAL LETTER E
+\def\cyrillicYU {Ю} % CYRILLIC CAPITAL LETTER YU
+\def\cyrillicYA {Я} % CYRILLIC CAPITAL LETTER YA
+\def\cyrillica {а} % CYRILLIC SMALL LETTER A
+\def\cyrillicb {б} % CYRILLIC SMALL LETTER BE
+\def\cyrillicv {в} % CYRILLIC SMALL LETTER VE
+\def\cyrillicg {г} % CYRILLIC SMALL LETTER GHE
+\def\cyrillicd {д} % CYRILLIC SMALL LETTER DE
+\def\cyrillice {е} % CYRILLIC SMALL LETTER IE
+\def\cyrilliczh {ж} % CYRILLIC SMALL LETTER ZHE
+\def\cyrillicz {з} % CYRILLIC SMALL LETTER ZE
+\def\cyrillici {и} % CYRILLIC SMALL LETTER I
+\def\cyrillicishrt {й} % CYRILLIC SMALL LETTER SHORT I
+\def\cyrillick {к} % CYRILLIC SMALL LETTER KA
+\def\cyrillicl {л} % CYRILLIC SMALL LETTER EL
+\def\cyrillicm {м} % CYRILLIC SMALL LETTER EM
+\def\cyrillicn {н} % CYRILLIC SMALL LETTER EN
+\def\cyrillico {о} % CYRILLIC SMALL LETTER O
+\def\cyrillicp {п} % CYRILLIC SMALL LETTER PE
+\def\cyrillicr {р} % CYRILLIC SMALL LETTER ER
+\def\cyrillics {с} % CYRILLIC SMALL LETTER ES
+\def\cyrillict {т} % CYRILLIC SMALL LETTER TE
+\def\cyrillicu {у} % CYRILLIC SMALL LETTER U
+\def\cyrillicf {ф} % CYRILLIC SMALL LETTER EF
+\def\cyrillich {х} % CYRILLIC SMALL LETTER HA
+\def\cyrillicc {ц} % CYRILLIC SMALL LETTER TSE
+\def\cyrillicch {ч} % CYRILLIC SMALL LETTER CHE
+\def\cyrillicsh {ш} % CYRILLIC SMALL LETTER SHA
+\def\cyrillicshch {щ} % CYRILLIC SMALL LETTER SHCHA
+\def\cyrillichrdsn {ъ} % CYRILLIC SMALL LETTER HARD SIGN
+\def\cyrillicery {ы} % CYRILLIC SMALL LETTER YERU
+\def\cyrillicsftsn {ь} % CYRILLIC SMALL LETTER SOFT SIGN
+\def\cyrillicerev {э} % CYRILLIC SMALL LETTER E
+\def\cyrillicyu {ю} % CYRILLIC SMALL LETTER YU
+\def\cyrillicya {я} % CYRILLIC SMALL LETTER YA
+\def\cyrillicegrave {ѐ} % CYRILLIC SMALL LETTER IE WITH GRAVE
+\def\cyrillicyo {ё} % CYRILLIC SMALL LETTER IO
+\def\cyrillicdje {ђ} % CYRILLIC SMALL LETTER DJE
+\def\cyrillicgje {ѓ} % CYRILLIC SMALL LETTER GJE
+\def\cyrillicie {є} % CYRILLIC SMALL LETTER UKRAINIAN IE
+\def\cyrillicdze {ѕ} % CYRILLIC SMALL LETTER DZE
+\def\cyrillicii {і} % CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+\def\cyrillicyi {ї} % CYRILLIC SMALL LETTER YI
+\def\cyrillicje {ј} % CYRILLIC SMALL LETTER JE
+\def\cyrilliclje {љ} % CYRILLIC SMALL LETTER LJE
+\def\cyrillicnje {њ} % CYRILLIC SMALL LETTER NJE
+\def\cyrillictshe {ћ} % CYRILLIC SMALL LETTER TSHE
+\def\cyrillickje {ќ} % CYRILLIC SMALL LETTER KJE
+\def\cyrillicigrave {ѝ} % CYRILLIC SMALL LETTER I WITH GRAVE
+\def\cyrillicushrt {ў} % CYRILLIC SMALL LETTER SHORT U
+\def\cyrillicdzhe {џ} % CYRILLIC SMALL LETTER DZHE
+\def\cyrillicOMEGA {Ѡ} % CYRILLIC CAPITAL LETTER OMEGA
+\def\cyrillicomega {ѡ} % CYRILLIC SMALL LETTER OMEGA
+\def\cyrillicYAT {Ѣ} % CYRILLIC CAPITAL LETTER YAT
+\def\cyrillicyat {ѣ} % CYRILLIC SMALL LETTER YAT
+\def\cyrillicEiotified {Ѥ} % CYRILLIC CAPITAL LETTER IOTIFIED E
+\def\cyrilliceiotified {ѥ} % CYRILLIC SMALL LETTER IOTIFIED E
+\def\cyrillicLITTLEYUS {Ѧ} % CYRILLIC CAPITAL LETTER LITTLE YUS
+\def\cyrilliclittleyus {ѧ} % CYRILLIC SMALL LETTER LITTLE YUS
+\def\cyrillicLITTLEYUSiotified {Ѩ} % CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+\def\cyrilliclittleyusiotified {ѩ} % CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
+\def\cyrillicBIGYUS {Ѫ} % CYRILLIC CAPITAL LETTER BIG YUS
+\def\cyrillicbigyus {ѫ} % CYRILLIC SMALL LETTER BIG YUS
+\def\cyrillicBIGYUSiotified {Ѭ} % CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+\def\cyrillicbigyusiotified {ѭ} % CYRILLIC SMALL LETTER IOTIFIED BIG YUS
+\def\cyrillicKSI {Ѯ} % CYRILLIC CAPITAL LETTER KSI
+\def\cyrillicksi {ѯ} % CYRILLIC SMALL LETTER KSI
+\def\cyrillicPSI {Ѱ} % CYRILLIC CAPITAL LETTER PSI
+\def\cyrillicpsi {ѱ} % CYRILLIC SMALL LETTER PSI
+\def\cyrillicFITA {Ѳ} % CYRILLIC CAPITAL LETTER FITA
+\def\cyrillicfita {ѳ} % CYRILLIC SMALL LETTER FITA
+\def\cyrillicIZHITSA {Ѵ} % CYRILLIC CAPITAL LETTER IZHITSA
+\def\cyrillicizhitsa {ѵ} % CYRILLIC SMALL LETTER IZHITSA
+\def\cyrillicIZHITSAdoublegrave {Ѷ} % CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+\def\cyrillicizhitsadoublegrave {ѷ} % CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+\def\cyrillicUK {Ѹ} % CYRILLIC CAPITAL LETTER UK
+\def\cyrillicuk {ѹ} % CYRILLIC SMALL LETTER UK
+\def\cyrillicOMEGAround {Ѻ} % CYRILLIC CAPITAL LETTER ROUND OMEGA
+\def\cyrillicomegaround {ѻ} % CYRILLIC SMALL LETTER ROUND OMEGA
+\def\cyrillicOMEGAtitlo {Ѽ} % CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+\def\cyrillicomegatitlo {ѽ} % CYRILLIC SMALL LETTER OMEGA WITH TITLO
+\def\cyrillicOT {Ѿ} % CYRILLIC CAPITAL LETTER OT
+\def\cyrillicot {ѿ} % CYRILLIC SMALL LETTER OT
+\def\cyrillicKOPPA {Ҁ} % CYRILLIC CAPITAL LETTER KOPPA
+\def\cyrillickoppa {ҁ} % CYRILLIC SMALL LETTER KOPPA
+\def\cyrillicTITLO {҃} % COMBINING CYRILLIC TITLO
+\def\cyrillicPALATALIZATION {҄} % COMBINING CYRILLIC PALATALIZATION
+\def\cyrillicDASIAPNEUMATA {҅} % COMBINING CYRILLIC DASIA PNEUMATA
+\def\cyrillicPSILIPNEUMATA {҆} % COMBINING CYRILLIC PSILI PNEUMATA
+\def\cyrillicISHRTtail {Ҋ} % CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
+\def\cyrillicishrttail {ҋ} % CYRILLIC SMALL LETTER SHORT I WITH TAIL
+\def\cyrillicSEMISOFT {Ҍ} % CYRILLIC CAPITAL LETTER SEMISOFT SIGN
+\def\cyrillicsemisoft {ҍ} % CYRILLIC SMALL LETTER SEMISOFT SIGN
+\def\cyrillicERtick {Ҏ} % CYRILLIC CAPITAL LETTER ER WITH TICK
+\def\cyrillicertick {ҏ} % CYRILLIC SMALL LETTER ER WITH TICK
+\def\cyrillicGHEupturn {Ґ} % CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+\def\cyrillicgheupturn {ґ} % CYRILLIC SMALL LETTER GHE WITH UPTURN
+\def\cyrillicGHEstroke {Ғ} % CYRILLIC CAPITAL LETTER GHE WITH STROKE
+\def\cyrillicghestroke {ғ} % CYRILLIC SMALL LETTER GHE WITH STROKE
+\def\cyrillicGHEmidhook {Ҕ} % CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+\def\cyrillicghemidhook {ҕ} % CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
+\def\cyrillicZHEdescender {Җ} % CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+\def\cyrilliczhedescender {җ} % CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+\def\cyrillicZDSC {Ҙ} % CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+\def\cyrilliczdsc {ҙ} % CYRILLIC SMALL LETTER ZE WITH DESCENDER
+\def\cyrillicKADC {Қ} % CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+\def\cyrillickadc {қ} % CYRILLIC SMALL LETTER KA WITH DESCENDER
+\def\cyrillicKAvertstroke {Ҝ} % CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+\def\cyrillickavertstroke {ҝ} % CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+\def\cyrillicKAstroke {Ҟ} % CYRILLIC CAPITAL LETTER KA WITH STROKE
+\def\cyrillickastroke {ҟ} % CYRILLIC SMALL LETTER KA WITH STROKE
+\def\cyrillicKAbashkir {Ҡ} % CYRILLIC CAPITAL LETTER BASHKIR KA
+\def\cyrillickabashkir {ҡ} % CYRILLIC SMALL LETTER BASHKIR KA
+\def\cyrillicENDC {Ң} % CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+\def\cyrillicendc {ң} % CYRILLIC SMALL LETTER EN WITH DESCENDER
+\def\cyrillicENGHE {Ҥ} % CYRILLIC CAPITAL LIGATURE EN GHE
+\def\cyrillicenghe {ҥ} % CYRILLIC SMALL LIGATURE EN GHE
+\def\cyrillicPEmidhook {Ҧ} % CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+\def\cyrillicpemidhook {ҧ} % CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
+\def\cyrillicHA {Ҩ} % CYRILLIC CAPITAL LETTER ABKHASIAN HA
+\def\cyrillicha {ҩ} % CYRILLIC SMALL LETTER ABKHASIAN HA
+\def\cyrillicSDSC {Ҫ} % CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+\def\cyrillicsdsc {ҫ} % CYRILLIC SMALL LETTER ES WITH DESCENDER
+\def\cyrillicTEDC {Ҭ} % CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+\def\cyrillictedc {ҭ} % CYRILLIC SMALL LETTER TE WITH DESCENDER
+\def\cyrillicYstr {Ү} % CYRILLIC CAPITAL LETTER STRAIGHT U
+\def\cyrillicystr {ү} % CYRILLIC SMALL LETTER STRAIGHT U
+\def\cyrillicYstrstroke {Ұ} % CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+\def\cyrillicystrstroke {ұ} % CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+\def\cyrillicHADC {Ҳ} % CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+\def\cyrillichadc {ҳ} % CYRILLIC SMALL LETTER HA WITH DESCENDER
+\def\cyrillicTETSE {Ҵ} % CYRILLIC CAPITAL LIGATURE TE TSE
+\def\cyrillictetse {ҵ} % CYRILLIC SMALL LIGATURE TE TSE
+\def\cyrillicCHEDC {Ҷ} % CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+\def\cyrillicchedc {ҷ} % CYRILLIC SMALL LETTER CHE WITH DESCENDER
+\def\cyrillicCHEvertstroke {Ҹ} % CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+\def\cyrillicchevertstroke {ҹ} % CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+\def\cyrillicSHHA {Һ} % CYRILLIC CAPITAL LETTER SHHA
+\def\cyrillicshha {һ} % CYRILLIC SMALL LETTER SHHA
+\def\cyrillicCHEabkhasian {Ҽ} % CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+\def\cyrilliccheabkhasian {ҽ} % CYRILLIC SMALL LETTER ABKHASIAN CHE
+\def\cyrillicCHEDCabkhasian {Ҿ} % CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+\def\cyrillicchedcabkhasian {ҿ} % CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
+\def\cyrillicPALOCHKA {Ӏ} % CYRILLIC LETTER PALOCHKA
+\def\cyrillicZHEbreve {Ӂ} % CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+\def\cyrilliczhebreve {ӂ} % CYRILLIC SMALL LETTER ZHE WITH BREVE
+\def\cyrillicKAhook {Ӄ} % CYRILLIC CAPITAL LETTER KA WITH HOOK
+\def\cyrillickahook {ӄ} % CYRILLIC SMALL LETTER KA WITH HOOK
+\def\cyrillicELtail {Ӆ} % CYRILLIC CAPITAL LETTER EL WITH TAIL
+\def\cyrilliceltail {ӆ} % CYRILLIC SMALL LETTER EL WITH TAIL
+\def\cyrillicENhook {Ӈ} % CYRILLIC CAPITAL LETTER EN WITH HOOK
+\def\cyrillicenhook {ӈ} % CYRILLIC SMALL LETTER EN WITH HOOK
+\def\cyrillicENtail {Ӊ} % CYRILLIC CAPITAL LETTER EN WITH TAIL
+\def\cyrillicentail {ӊ} % CYRILLIC SMALL LETTER EN WITH TAIL
+\def\cyrillicCHEkhakassian {Ӌ} % CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+\def\cyrillicchekhakassian {ӌ} % CYRILLIC SMALL LETTER KHAKASSIAN CHE
+\def\cyrillicEMtail {Ӎ} % CYRILLIC CAPITAL LETTER EM WITH TAIL
+\def\cyrillicemtail {ӎ} % CYRILLIC SMALL LETTER EM WITH TAIL
+\def\cyrillicAbreve {Ӑ} % CYRILLIC CAPITAL LETTER A WITH BREVE
+\def\cyrillicabreve {ӑ} % CYRILLIC SMALL LETTER A WITH BREVE
+\def\cyrillicAdiaeresis {Ӓ} % CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+\def\cyrillicadiaeresis {ӓ} % CYRILLIC SMALL LETTER A WITH DIAERESIS
+\def\cyrillicAE {Ӕ} % CYRILLIC CAPITAL LIGATURE A IE
+\def\cyrillicae {ӕ} % CYRILLIC SMALL LIGATURE A IE
+\def\cyrillicEbreve {Ӗ} % CYRILLIC CAPITAL LETTER IE WITH BREVE
+\def\cyrillicebreve {ӗ} % CYRILLIC SMALL LETTER IE WITH BREVE
+\def\cyrillicSCHWA {Ә} % CYRILLIC CAPITAL LETTER SCHWA
+\def\cyrillicschwa {ә} % CYRILLIC SMALL LETTER SCHWA
+\def\cyrillicSCHWAdiaeresis {Ӛ} % CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+\def\cyrillicschwadiaeresis {ӛ} % CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+\def\cyrillicZHEdiaeresis {Ӝ} % CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+\def\cyrilliczhediaeresis {ӝ} % CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+\def\cyrillicZEdiaeresis {Ӟ} % CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+\def\cyrilliczediaeresis {ӟ} % CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+\def\cyrillicDZEabkhasian {Ӡ} % CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+\def\cyrillicdzeabkhasian {ӡ} % CYRILLIC SMALL LETTER ABKHASIAN DZE
+\def\cyrillicImacron {Ӣ} % CYRILLIC CAPITAL LETTER I WITH MACRON
+\def\cyrillicimacron {ӣ} % CYRILLIC SMALL LETTER I WITH MACRON
+\def\cyrillicIdiaeresis {Ӥ} % CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+\def\cyrillicidiaeresis {ӥ} % CYRILLIC SMALL LETTER I WITH DIAERESIS
+\def\cyrillicOdiaeresis {Ӧ} % CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+\def\cyrillicodiaeresis {ӧ} % CYRILLIC SMALL LETTER O WITH DIAERESIS
+\def\cyrillicObarred {Ө} % CYRILLIC CAPITAL LETTER BARRED O
+\def\cyrillicobarred {ө} % CYRILLIC SMALL LETTER BARRED O
+\def\cyrillicObarreddiaeresis {Ӫ} % CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+\def\cyrillicobarreddiaeresis {ӫ} % CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+\def\cyrillicEdiaeresis {Ӭ} % CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+\def\cyrillicediaeresis {ӭ} % CYRILLIC SMALL LETTER E WITH DIAERESIS
+\def\cyrillicUmacron {Ӯ} % CYRILLIC CAPITAL LETTER U WITH MACRON
+\def\cyrillicumacron {ӯ} % CYRILLIC SMALL LETTER U WITH MACRON
+\def\cyrillicUdiaeresis {Ӱ} % CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+\def\cyrillicudiaeresis {ӱ} % CYRILLIC SMALL LETTER U WITH DIAERESIS
+\def\cyrillicUdoubleacute {Ӳ} % CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+\def\cyrillicudoubleacute {ӳ} % CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+\def\cyrillicCHEdiaeresis {Ӵ} % CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+\def\cyrillicchediaeresis {ӵ} % CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+\def\cyrillicYERUdiaeresis {Ӹ} % CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+\def\cyrillicyerudiaeresis {ӹ} % CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+\def\hebrewAlef {א} % HEBREW LETTER ALEF
+\def\hebrewBet {ב} % HEBREW LETTER BET
+\def\hebrewGimel {ג} % HEBREW LETTER GIMEL
+\def\hebrewDalet {ד} % HEBREW LETTER DALET
+\def\hebrewHe {ה} % HEBREW LETTER HE
+\def\hebrewVav {ו} % HEBREW LETTER VAV
+\def\hebrewZayin {ז} % HEBREW LETTER ZAYIN
+\def\hebrewHet {ח} % HEBREW LETTER HET
+\def\hebrewTet {ט} % HEBREW LETTER TET
+\def\hebrewYod {י} % HEBREW LETTER YOD
+\def\hebrewKaffinal {ך} % HEBREW LETTER FINAL KAF
+\def\hebrewKaf {כ} % HEBREW LETTER KAF
+\def\hebrewLamed {ל} % HEBREW LETTER LAMED
+\def\hebrewMemfinal {ם} % HEBREW LETTER FINAL MEM
+\def\hebrewMem {מ} % HEBREW LETTER MEM
+\def\hebrewNunfinal {ן} % HEBREW LETTER FINAL NUN
+\def\hebrewNun {נ} % HEBREW LETTER NUN
+\def\hebrewSamekh {ס} % HEBREW LETTER SAMEKH
+\def\hebrewAyin {ע} % HEBREW LETTER AYIN
+\def\hebrewPefinal {ף} % HEBREW LETTER FINAL PE
+\def\hebrewPe {פ} % HEBREW LETTER PE
+\def\hebrewTsadifinal {ץ} % HEBREW LETTER FINAL TSADI
+\def\hebrewTsadi {צ} % HEBREW LETTER TSADI
+\def\hebrewQof {ק} % HEBREW LETTER QOF
+\def\hebrewResh {ר} % HEBREW LETTER RESH
+\def\hebrewShin {ש} % HEBREW LETTER SHIN
+\def\hebrewTav {ת} % HEBREW LETTER TAV
+\def\Adotbelow {Ạ} % LATIN CAPITAL LETTER A WITH DOT BELOW
+\def\adotbelow {ạ} % LATIN SMALL LETTER A WITH DOT BELOW
+\def\Ahook {Ả} % LATIN CAPITAL LETTER A WITH HOOK ABOVE
+\def\ahook {ả} % LATIN SMALL LETTER A WITH HOOK ABOVE
+\def\Acircumflexacute {Ấ} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+\def\acircumflexacute {ấ} % LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+\def\Acircumflexgrave {Ầ} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+\def\acircumflexgrave {ầ} % LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+\def\Acircumflexhook {Ẩ} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+\def\acircumflexhook {ẩ} % LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+\def\Acircumflextilde {Ẫ} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+\def\acircumflextilde {ẫ} % LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+\def\Acircumflexdotbelow {Ậ} % LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+\def\acircumflexdotbelow {ậ} % LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+\def\Abreveacute {Ắ} % LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+\def\abreveacute {ắ} % LATIN SMALL LETTER A WITH BREVE AND ACUTE
+\def\Abrevegrave {Ằ} % LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+\def\abrevegrave {ằ} % LATIN SMALL LETTER A WITH BREVE AND GRAVE
+\def\Abrevehook {Ẳ} % LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+\def\abrevehook {ẳ} % LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+\def\Abrevetilde {Ẵ} % LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+\def\abrevetilde {ẵ} % LATIN SMALL LETTER A WITH BREVE AND TILDE
+\def\Abrevedotbelow {Ặ} % LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+\def\abrevedotbelow {ặ} % LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+\def\Edotbelow {Ẹ} % LATIN CAPITAL LETTER E WITH DOT BELOW
+\def\edotbelow {ẹ} % LATIN SMALL LETTER E WITH DOT BELOW
+\def\Ehook {Ẻ} % LATIN CAPITAL LETTER E WITH HOOK ABOVE
+\def\ehook {ẻ} % LATIN SMALL LETTER E WITH HOOK ABOVE
+\def\Etilde {Ẽ} % LATIN CAPITAL LETTER E WITH TILDE
+\def\etilde {ẽ} % LATIN SMALL LETTER E WITH TILDE
+\def\Ecircumflexacute {Ế} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+\def\ecircumflexacute {ế} % LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+\def\Ecircumflexgrave {Ề} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+\def\ecircumflexgrave {ề} % LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+\def\Ecircumflexhook {Ể} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+\def\ecircumflexhook {ể} % LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+\def\Ecircumflextilde {Ễ} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+\def\ecircumflextilde {ễ} % LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+\def\Ecircumflexdotbelow {Ệ} % LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+\def\ecircumflexdotbelow {ệ} % LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+\def\Ihook {Ỉ} % LATIN CAPITAL LETTER I WITH HOOK ABOVE
+\def\ihook {ỉ} % LATIN SMALL LETTER I WITH HOOK ABOVE
+\def\Idotbelow {Ị} % LATIN CAPITAL LETTER I WITH DOT BELOW
+\def\idotbelow {ị} % LATIN SMALL LETTER I WITH DOT BELOW
+\def\Odotbelow {Ọ} % LATIN CAPITAL LETTER O WITH DOT BELOW
+\def\odotbelow {ọ} % LATIN SMALL LETTER O WITH DOT BELOW
+\def\Ohook {Ỏ} % LATIN CAPITAL LETTER O WITH HOOK ABOVE
+\def\ohook {ỏ} % LATIN SMALL LETTER O WITH HOOK ABOVE
+\def\Ocircumflexacute {Ố} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+\def\ocircumflexacute {ố} % LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+\def\Ocircumflexgrave {Ồ} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+\def\ocircumflexgrave {ồ} % LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+\def\Ocircumflexhook {Ổ} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+\def\ocircumflexhook {ổ} % LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+\def\Ocircumflextilde {Ỗ} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+\def\ocircumflextilde {ỗ} % LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+\def\Ocircumflexdotbelow {Ộ} % LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+\def\ocircumflexdotbelow {ộ} % LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+\def\Ohornacute {Ớ} % LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+\def\ohornacute {ớ} % LATIN SMALL LETTER O WITH HORN AND ACUTE
+\def\Ohorngrave {Ờ} % LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+\def\ohorngrave {ờ} % LATIN SMALL LETTER O WITH HORN AND GRAVE
+\def\Ohornhook {Ở} % LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+\def\ohornhook {ở} % LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+\def\Ohorntilde {Ỡ} % LATIN CAPITAL LETTER O WITH HORN AND TILDE
+\def\ohorntilde {ỡ} % LATIN SMALL LETTER O WITH HORN AND TILDE
+\def\Ohorndotbelow {Ợ} % LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+\def\ohorndotbelow {ợ} % LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+\def\Udotbelow {Ụ} % LATIN CAPITAL LETTER U WITH DOT BELOW
+\def\udotbelow {ụ} % LATIN SMALL LETTER U WITH DOT BELOW
+\def\Uhook {Ủ} % LATIN CAPITAL LETTER U WITH HOOK ABOVE
+\def\uhook {ủ} % LATIN SMALL LETTER U WITH HOOK ABOVE
+\def\Uhornacute {Ứ} % LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+\def\uhornacute {ứ} % LATIN SMALL LETTER U WITH HORN AND ACUTE
+\def\Uhorngrave {Ừ} % LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+\def\uhorngrave {ừ} % LATIN SMALL LETTER U WITH HORN AND GRAVE
+\def\Uhornhook {Ử} % LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+\def\uhornhook {ử} % LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+\def\Uhorntilde {Ữ} % LATIN CAPITAL LETTER U WITH HORN AND TILDE
+\def\uhorntilde {ữ} % LATIN SMALL LETTER U WITH HORN AND TILDE
+\def\Uhorndotbelow {Ự} % LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+\def\uhorndotbelow {ự} % LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+\def\Ygrave {Ỳ} % LATIN CAPITAL LETTER Y WITH GRAVE
+\def\ygrave {ỳ} % LATIN SMALL LETTER Y WITH GRAVE
+\def\Ydotbelow {Ỵ} % LATIN CAPITAL LETTER Y WITH DOT BELOW
+\def\ydotbelow {ỵ} % LATIN SMALL LETTER Y WITH DOT BELOW
+\def\Yhook {Ỷ} % LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+\def\yhook {ỷ} % LATIN SMALL LETTER Y WITH HOOK ABOVE
+\def\Ytilde {Ỹ} % LATIN CAPITAL LETTER Y WITH TILDE
+\def\ytilde {ỹ} % LATIN SMALL LETTER Y WITH TILDE
+\def\greekalphapsili {ἀ} % GREEK SMALL LETTER ALPHA WITH PSILI
+\def\greekalphadasia {ἁ} % GREEK SMALL LETTER ALPHA WITH DASIA
+\def\greekalphapsilivaria {ἂ} % GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA
+\def\greekalphadasiavaria {ἃ} % GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA
+\def\greekalphapsilitonos {ἄ} % GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA
+\def\greekalphadasiatonos {ἅ} % GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA
+\def\greekalphapsiliperispomeni {ἆ} % GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI
+\def\greekalphadasiaperispomeni {ἇ} % GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
+\def\greekAlphapsili {Ἀ} % GREEK CAPITAL LETTER ALPHA WITH PSILI
+\def\greekAlphadasia {Ἁ} % GREEK CAPITAL LETTER ALPHA WITH DASIA
+\def\greekAlphapsilivaria {Ἂ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
+\def\greekAlphadasiavaria {Ἃ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
+\def\greekAlphapsilitonos {Ἄ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
+\def\greekAlphadasiatonos {Ἅ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
+\def\greekAlphapsiliperispomeni {Ἆ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
+\def\greekAlphadasiaperispomeni {Ἇ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+\def\greekepsilonpsili {ἐ} % GREEK SMALL LETTER EPSILON WITH PSILI
+\def\greekepsilondasia {ἑ} % GREEK SMALL LETTER EPSILON WITH DASIA
+\def\greekepsilonpsilivaria {ἒ} % GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA
+\def\greekepsilondasiavaria {ἓ} % GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA
+\def\greekepsilonpsilitonos {ἔ} % GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA
+\def\greekepsilondasiatonos {ἕ} % GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+\def\greekEpsilonpsili {Ἐ} % GREEK CAPITAL LETTER EPSILON WITH PSILI
+\def\greekEpsilondasia {Ἑ} % GREEK CAPITAL LETTER EPSILON WITH DASIA
+\def\greekEpsilonpsilivaria {Ἒ} % GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
+\def\greekEpsilondasiavaria {Ἓ} % GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
+\def\greekEpsilonpsilitonos {Ἔ} % GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
+\def\greekEpsilondasiatonos {Ἕ} % GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+\def\greeketapsili {ἠ} % GREEK SMALL LETTER ETA WITH PSILI
+\def\greeketadasia {ἡ} % GREEK SMALL LETTER ETA WITH DASIA
+\def\greeketapsilivaria {ἢ} % GREEK SMALL LETTER ETA WITH PSILI AND VARIA
+\def\greeketadasiavaria {ἣ} % GREEK SMALL LETTER ETA WITH DASIA AND VARIA
+\def\greeketapsilitonos {ἤ} % GREEK SMALL LETTER ETA WITH PSILI AND OXIA
+\def\greeketadasiatonos {ἥ} % GREEK SMALL LETTER ETA WITH DASIA AND OXIA
+\def\greeketapsiliperispomeni {ἦ} % GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI
+\def\greeketadasiaperispomeni {ἧ} % GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
+\def\greekEtapsili {Ἠ} % GREEK CAPITAL LETTER ETA WITH PSILI
+\def\greekEtadasia {Ἡ} % GREEK CAPITAL LETTER ETA WITH DASIA
+\def\greekEtapsilivaria {Ἢ} % GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
+\def\greekEtadasiavaria {Ἣ} % GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
+\def\greekEtapsilitonos {Ἤ} % GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
+\def\greekEtadasiatonos {Ἥ} % GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
+\def\greekEtapsiliperispomeni {Ἦ} % GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
+\def\greekEtadasiaperispomeni {Ἧ} % GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+\def\greekiotapsili {ἰ} % GREEK SMALL LETTER IOTA WITH PSILI
+\def\greekiotadasia {ἱ} % GREEK SMALL LETTER IOTA WITH DASIA
+\def\greekiotapsilivaria {ἲ} % GREEK SMALL LETTER IOTA WITH PSILI AND VARIA
+\def\greekiotadasiavaria {ἳ} % GREEK SMALL LETTER IOTA WITH DASIA AND VARIA
+\def\greekiotapsilitonos {ἴ} % GREEK SMALL LETTER IOTA WITH PSILI AND OXIA
+\def\greekiotadasiatonos {ἵ} % GREEK SMALL LETTER IOTA WITH DASIA AND OXIA
+\def\greekiotapsiliperispomeni {ἶ} % GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI
+\def\greekiotadasiaperispomeni {ἷ} % GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
+\def\greekIotapsili {Ἰ} % GREEK CAPITAL LETTER IOTA WITH PSILI
+\def\greekIotadasia {Ἱ} % GREEK CAPITAL LETTER IOTA WITH DASIA
+\def\greekIotapsilivaria {Ἲ} % GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
+\def\greekIotadasiavaria {Ἳ} % GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
+\def\greekIotapsilitonos {Ἴ} % GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
+\def\greekIotadasiatonos {Ἵ} % GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
+\def\greekIotapsiliperispomeni {Ἶ} % GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
+\def\greekIotadasiaperispomeni {Ἷ} % GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+\def\greekomicronpsili {ὀ} % GREEK SMALL LETTER OMICRON WITH PSILI
+\def\greekomicrondasia {ὁ} % GREEK SMALL LETTER OMICRON WITH DASIA
+\def\greekomicronpsilivaria {ὂ} % GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA
+\def\greekomicrondasiavaria {ὃ} % GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA
+\def\greekomicronpsilitonos {ὄ} % GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA
+\def\greekomicrondasiatonos {ὅ} % GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+\def\greekOmicronpsili {Ὀ} % GREEK CAPITAL LETTER OMICRON WITH PSILI
+\def\greekOmicrondasia {Ὁ} % GREEK CAPITAL LETTER OMICRON WITH DASIA
+\def\greekOmicronpsilivaria {Ὂ} % GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
+\def\greekOmicrondasiavaria {Ὃ} % GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
+\def\greekOmicronpsilitonos {Ὄ} % GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
+\def\greekOmicrondasiatonos {Ὅ} % GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+\def\greekupsilonpsili {ὐ} % GREEK SMALL LETTER UPSILON WITH PSILI
+\def\greekupsilondasia {ὑ} % GREEK SMALL LETTER UPSILON WITH DASIA
+\def\greekupsilonpsilivaria {ὒ} % GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA
+\def\greekupsilondasiavaria {ὓ} % GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA
+\def\greekupsilonpsilitonos {ὔ} % GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA
+\def\greekupsilondasiatonos {ὕ} % GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA
+\def\greekupsilonpsiliperispomeni {ὖ} % GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI
+\def\greekupsilondasiaperispomeni {ὗ} % GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+\def\greekUpsilondasia {Ὑ} % GREEK CAPITAL LETTER UPSILON WITH DASIA
+\def\greekUpsilondasiavaria {Ὓ} % GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+\def\greekUpsilondasiatonos {Ὕ} % GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+\def\greekUpsilondasiaperispomeni {Ὗ} % GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+\def\greekomegapsili {ὠ} % GREEK SMALL LETTER OMEGA WITH PSILI
+\def\greekomegadasia {ὡ} % GREEK SMALL LETTER OMEGA WITH DASIA
+\def\greekomegapsilivaria {ὢ} % GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA
+\def\greekomegadasiavaria {ὣ} % GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA
+\def\greekomegapsilitonos {ὤ} % GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA
+\def\greekomegadasiatonos {ὥ} % GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA
+\def\greekomegapsiliperispomeni {ὦ} % GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI
+\def\greekomegadasiaperispomeni {ὧ} % GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
+\def\greekOmegapsili {Ὠ} % GREEK CAPITAL LETTER OMEGA WITH PSILI
+\def\greekOmegadasia {Ὡ} % GREEK CAPITAL LETTER OMEGA WITH DASIA
+\def\greekOmegapsilivaria {Ὢ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
+\def\greekOmegadasiavaria {Ὣ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
+\def\greekOmegapsilitonos {Ὤ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
+\def\greekOmegadasiatonos {Ὥ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
+\def\greekOmegapsiliperispomeni {Ὦ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
+\def\greekOmegadasiaperispomeni {Ὧ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+\def\greekalphavaria {ὰ} % GREEK SMALL LETTER ALPHA WITH VARIA
+\def\greekalphaoxia {ά} % GREEK SMALL LETTER ALPHA WITH OXIA
+\def\greekepsilonvaria {ὲ} % GREEK SMALL LETTER EPSILON WITH VARIA
+\def\greekepsilonoxia {έ} % GREEK SMALL LETTER EPSILON WITH OXIA
+\def\greeketavaria {ὴ} % GREEK SMALL LETTER ETA WITH VARIA
+\def\greeketaoxia {ή} % GREEK SMALL LETTER ETA WITH OXIA
+\def\greekiotavaria {ὶ} % GREEK SMALL LETTER IOTA WITH VARIA
+\def\greekiotaoxia {ί} % GREEK SMALL LETTER IOTA WITH OXIA
+\def\greekomicronvaria {ὸ} % GREEK SMALL LETTER OMICRON WITH VARIA
+\def\greekomicronoxia {ό} % GREEK SMALL LETTER OMICRON WITH OXIA
+\def\greekupsilonvaria {ὺ} % GREEK SMALL LETTER UPSILON WITH VARIA
+\def\greekupsilonoxia {ύ} % GREEK SMALL LETTER UPSILON WITH OXIA
+\def\greekomegavaria {ὼ} % GREEK SMALL LETTER OMEGA WITH VARIA
+\def\greekomegaoxia {ώ} % GREEK SMALL LETTER OMEGA WITH OXIA
+\def\greekalphaiotasubpsili {ᾀ} % GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
+\def\greekalphaiotasubdasia {ᾁ} % GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
+\def\greekalphaiotasubpsilivaria {ᾂ} % GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+\def\greekalphaiotasubdasiavaria {ᾃ} % GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+\def\greekalphaiotasubpsilitonos {ᾄ} % GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+\def\greekalphaiotasubdasiatonos {ᾅ} % GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+\def\greekalphaiotasubpsiliperispomeni{ᾆ} % GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greekalphaiotasubdasiaperispomeni{ᾇ} % GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greekAlphaiotasubpsili {ᾈ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+\def\greekAlphaiotasubdasia {ᾉ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+\def\greekAlphaiotasubpsilivaria {ᾊ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+\def\greekAlphaiotasubdasiavaria {ᾋ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+\def\greekAlphaiotasubpsilitonos {ᾌ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+\def\greekAlphaiotasubdasiatonos {ᾍ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+\def\greekAlphaiotasubpsiliperispomeni{ᾎ} % GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greekAlphaiotasubdasiaperispomeni{ᾏ} % GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greeketaiotasubpsili {ᾐ} % GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
+\def\greeketaiotasubdasia {ᾑ} % GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
+\def\greeketaiotasubpsilivaria {ᾒ} % GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+\def\greeketaiotasubdasiavaria {ᾓ} % GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+\def\greeketaiotasubpsilitonos {ᾔ} % GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+\def\greeketaiotasubdasiatonos {ᾕ} % GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+\def\greeketaiotasubpsiliperispomeni {ᾖ} % GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greeketaiotasubdasiaperispomeni {ᾗ} % GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greekEtaiotasubpsili {ᾘ} % GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+\def\greekEtaiotasubdasia {ᾙ} % GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+\def\greekEtaiotasubpsilivaria {ᾚ} % GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+\def\greekEtaiotasubdasiavaria {ᾛ} % GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+\def\greekEtaiotasubpsilitonos {ᾜ} % GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+\def\greekEtaiotasubdasiatonos {ᾝ} % GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+\def\greekEtaiotasubpsiliperispomeni {ᾞ} % GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greekEtaiotasubdasiaperispomeni {ᾟ} % GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greekomegaiotasubpsili {ᾠ} % GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
+\def\greekomegaiotasubdasia {ᾡ} % GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
+\def\greekomegaiotasubpsilivaria {ᾢ} % GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+\def\greekomegaiotasubdasiavaria {ᾣ} % GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+\def\greekomegaiotasubpsilitonos {ᾤ} % GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+\def\greekomegaiotasubdasiatonos {ᾥ} % GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+\def\greekomegaiotasubpsiliperispomeni{ᾦ} % GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greekomegaiotasubdasiaperispomeni{ᾧ} % GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+\def\greekOmegaiotasubpsili {ᾨ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+\def\greekOmegaiotasubdasia {ᾩ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+\def\greekOmegaiotasubpsilivaria {ᾪ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+\def\greekOmegaiotasubdasiavaria {ᾫ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+\def\greekOmegaiotasubpsilitonos {ᾬ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+\def\greekOmegaiotasubdasiatonos {ᾭ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+\def\greekOmegaiotasubpsiliperispomeni{ᾮ} % GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greekOmegaiotasubdasiaperispomeni{ᾯ} % GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+\def\greekalphavrachy {ᾰ} % GREEK SMALL LETTER ALPHA WITH VRACHY
+\def\greekalphamacron {ᾱ} % GREEK SMALL LETTER ALPHA WITH MACRON
+\def\greekalphaiotasubvaria {ᾲ} % GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
+\def\greekalphaiotasub {ᾳ} % GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
+\def\greekalphaiotasubtonos {ᾴ} % GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+\def\greekalphaperispomeni {ᾶ} % GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+\def\greekalphaiotasubperispomeni {ᾷ} % GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
+\def\greekAlphavrachy {Ᾰ} % GREEK CAPITAL LETTER ALPHA WITH VRACHY
+\def\greekAlphamacron {Ᾱ} % GREEK CAPITAL LETTER ALPHA WITH MACRON
+\def\greekAlphavaria {Ὰ} % GREEK CAPITAL LETTER ALPHA WITH VARIA
+\def\greekAlphatonos {Ά} % GREEK CAPITAL LETTER ALPHA WITH OXIA
+\def\greekAlphaiotasub {ᾼ} % GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+\def\greekCoronis {᾽} % GREEK KORONIS
+\def\greekprosgegrammeni {ι} % GREEK PROSGEGRAMMENI
+\def\greekpsili {᾿} % GREEK PSILI
+\def\greekperispomeni {῀} % GREEK PERISPOMENI
+\def\greekdialytikaperispomeni {῁} % GREEK DIALYTIKA AND PERISPOMENI
+\def\greeketaiotasubvaria {ῂ} % GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
+\def\greeketaiotasub {ῃ} % GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
+\def\greeketaiotasubtonos {ῄ} % GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+\def\greeketaperispomeni {ῆ} % GREEK SMALL LETTER ETA WITH PERISPOMENI
+\def\greeketaiotasubperispomeni {ῇ} % GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
+\def\greekEpsilonvaria {Ὲ} % GREEK CAPITAL LETTER EPSILON WITH VARIA
+\def\greekEpsilontonos {Έ} % GREEK CAPITAL LETTER EPSILON WITH OXIA
+\def\greekEtavaria {Ὴ} % GREEK CAPITAL LETTER ETA WITH VARIA
+\def\greekEtatonos {Ή} % GREEK CAPITAL LETTER ETA WITH OXIA
+\def\greekEtaiotasub {ῌ} % GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+\def\greekpsilivaria {῍} % GREEK PSILI AND VARIA
+\def\greekpsilitonos {῎} % GREEK PSILI AND OXIA
+\def\greekpsiliperispomeni {῏} % GREEK PSILI AND PERISPOMENI
+\def\greekiotavrachy {ῐ} % GREEK SMALL LETTER IOTA WITH VRACHY
+\def\greekiotamacron {ῑ} % GREEK SMALL LETTER IOTA WITH MACRON
+\def\greekiotadialytikavaria {ῒ} % GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+\def\greekiotadialytikatonos {ΐ} % GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+\def\greekiotaperispomeni {ῖ} % GREEK SMALL LETTER IOTA WITH PERISPOMENI
+\def\greekiotadialytikaperispomeni {ῗ} % GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+\def\greekIotavrachy {Ῐ} % GREEK CAPITAL LETTER IOTA WITH VRACHY
+\def\greekIotamacron {Ῑ} % GREEK CAPITAL LETTER IOTA WITH MACRON
+\def\greekIotavaria {Ὶ} % GREEK CAPITAL LETTER IOTA WITH VARIA
+\def\greekIotatonos {Ί} % GREEK CAPITAL LETTER IOTA WITH OXIA
+\def\greekdasiavaria {῝} % GREEK DASIA AND VARIA
+\def\greekdasiatonos {῞} % GREEK DASIA AND OXIA
+\def\greekdasiaperispomeni {῟} % GREEK DASIA AND PERISPOMENI
+\def\greekupsilonvrachy {ῠ} % GREEK SMALL LETTER UPSILON WITH VRACHY
+\def\greekupsilonmacron {ῡ} % GREEK SMALL LETTER UPSILON WITH MACRON
+\def\greekupsilondialytikavaria {ῢ} % GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+\def\greekupsilondialytikatonos {ΰ} % GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+\def\greekrhopsili {ῤ} % GREEK SMALL LETTER RHO WITH PSILI
+\def\greekrhodasia {ῥ} % GREEK SMALL LETTER RHO WITH DASIA
+\def\greekupsilonperispomeni {ῦ} % GREEK SMALL LETTER UPSILON WITH PERISPOMENI
+\def\greekupsilondialytikaperispomeni {ῧ} % GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+\def\greekUpsilonvrachy {Ῠ} % GREEK CAPITAL LETTER UPSILON WITH VRACHY
+\def\greekUpsilonmacron {Ῡ} % GREEK CAPITAL LETTER UPSILON WITH MACRON
+\def\greekUpsilonvaria {Ὺ} % GREEK CAPITAL LETTER UPSILON WITH VARIA
+\def\greekUpsilontonos {Ύ} % GREEK CAPITAL LETTER UPSILON WITH OXIA
+\def\greekRhodasia {Ῥ} % GREEK CAPITAL LETTER RHO WITH DASIA
+\def\greekdialytikavaria {῭} % GREEK DIALYTIKA AND VARIA
+\def\greekdialytikatonos {΅} % GREEK DIALYTIKA AND OXIA
+\def\greekvaria {`} % GREEK VARIA
+\def\greekomegaiotasubvaria {ῲ} % GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
+\def\greekomegaiotasub {ῳ} % GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
+\def\greekomegaiotasubtonos {ῴ} % GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+\def\greekomegaperispomeni {ῶ} % GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+\def\greekomegaiotasubperispomeni {ῷ} % GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
+\def\greekOmicronvaria {Ὸ} % GREEK CAPITAL LETTER OMICRON WITH VARIA
+\def\greekOmicrontonos {Ό} % GREEK CAPITAL LETTER OMICRON WITH OXIA
+\def\greekOmegavaria {Ὼ} % GREEK CAPITAL LETTER OMEGA WITH VARIA
+\def\greekOmegatonos {Ώ} % GREEK CAPITAL LETTER OMEGA WITH OXIA
+\def\greekOmegaiotasub {ῼ} % GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+\def\greekoxia {´} % GREEK OXIA
+\def\greekdasia {῾} % GREEK DASIA
+\def\textminus {‒} % FIGURE DASH
+\def\endash {–} % EN DASH
+\def\emdash {—} % EM DASH
+\def\texthorizontalbar {―} % HORIZONTAL BAR
+\def\quoteleft {‘} % LEFT SINGLE QUOTATION MARK
+\def\quoteright {’} % RIGHT SINGLE QUOTATION MARK
+\def\quotesinglebase {‚} % SINGLE LOW-9 QUOTATION MARK
+\def\quotedblleft {“} % LEFT DOUBLE QUOTATION MARK
+\def\quotedblright {”} % RIGHT DOUBLE QUOTATION MARK
+\def\quotedblbase {„} % DOUBLE LOW-9 QUOTATION MARK
+\def\textdag {†} % DAGGER
+\def\textddag {‡} % DOUBLE DAGGER
+\def\textbullet {•} % BULLET
+\def\textellipsis {…} % HORIZONTAL ELLIPSIS
+\def\perthousand {‰} % PER MILLE SIGN
+\def\guilsingleleft {‹} % SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+\def\guilsingleright {›} % SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+\def\textdong {₫} % DONG SIGN
+\def\texteuro {€} % EURO SIGN
+\def\textnumero {№} % NUMERO SIGN
+\def\trademark {™} % TRADE MARK SIGN
+\def\onethird {⅓} % VULGAR FRACTION ONE THIRD
+\def\twothirds {⅔} % VULGAR FRACTION TWO THIRDS
+\def\onefifth {⅕} % VULGAR FRACTION ONE FIFTH
+\def\twofifths {⅖} % VULGAR FRACTION TWO FIFTHS
+\def\threefifths {⅗} % VULGAR FRACTION THREE FIFTHS
+\def\fourfifths {⅘} % VULGAR FRACTION FOUR FIFTHS
+\def\onesixth {⅙} % VULGAR FRACTION ONE SIXTH
+\def\fivesixths {⅚} % VULGAR FRACTION FIVE SIXTHS
+\def\oneeighth {⅛} % VULGAR FRACTION ONE EIGHTH
+\def\threeeighths {⅜} % VULGAR FRACTION THREE EIGHTHS
+\def\fiveeighths {⅝} % VULGAR FRACTION FIVE EIGHTHS
+\def\seveneighths {⅞} % VULGAR FRACTION SEVEN EIGHTHS
+\def\romanI {Ⅰ} % ROMAN NUMERAL ONE
+\def\romanII {Ⅱ} % ROMAN NUMERAL TWO
+\def\romanIII {Ⅲ} % ROMAN NUMERAL THREE
+\def\romanIV {Ⅳ} % ROMAN NUMERAL FOUR
+\def\romanV {Ⅴ} % ROMAN NUMERAL FIVE
+\def\romanVI {Ⅵ} % ROMAN NUMERAL SIX
+\def\romanVII {Ⅶ} % ROMAN NUMERAL SEVEN
+\def\romanVIII {Ⅷ} % ROMAN NUMERAL EIGHT
+\def\romanIX {Ⅸ} % ROMAN NUMERAL NINE
+\def\romanX {Ⅹ} % ROMAN NUMERAL TEN
+\def\romanXI {Ⅺ} % ROMAN NUMERAL ELEVEN
+\def\romanXII {Ⅻ} % ROMAN NUMERAL TWELVE
+\def\romanL {Ⅼ} % ROMAN NUMERAL FIFTY
+\def\romanC {Ⅽ} % ROMAN NUMERAL ONE HUNDRED
+\def\romanD {Ⅾ} % ROMAN NUMERAL FIVE HUNDRED
+\def\romanM {Ⅿ} % ROMAN NUMERAL ONE THOUSAND
+\def\romani {ⅰ} % SMALL ROMAN NUMERAL ONE
+\def\romanii {ⅱ} % SMALL ROMAN NUMERAL TWO
+\def\romaniii {ⅲ} % SMALL ROMAN NUMERAL THREE
+\def\romaniv {ⅳ} % SMALL ROMAN NUMERAL FOUR
+\def\romanv {ⅴ} % SMALL ROMAN NUMERAL FIVE
+\def\romanvi {ⅵ} % SMALL ROMAN NUMERAL SIX
+\def\romanvii {ⅶ} % SMALL ROMAN NUMERAL SEVEN
+\def\romanviii {ⅷ} % SMALL ROMAN NUMERAL EIGHT
+\def\romanix {ⅸ} % SMALL ROMAN NUMERAL NINE
+\def\romanx {ⅹ} % SMALL ROMAN NUMERAL TEN
+\def\romanxi {ⅺ} % SMALL ROMAN NUMERAL ELEVEN
+\def\romanxii {ⅻ} % SMALL ROMAN NUMERAL TWELVE
+\def\romanl {ⅼ} % SMALL ROMAN NUMERAL FIFTY
+\def\romanc {ⅽ} % SMALL ROMAN NUMERAL ONE HUNDRED
+\def\romand {ⅾ} % SMALL ROMAN NUMERAL FIVE HUNDRED
+\def\romanm {ⅿ} % SMALL ROMAN NUMERAL ONE THOUSAND
+\def\ffligature {ff} % LATIN SMALL LIGATURE FF
+\def\filigature {fi} % LATIN SMALL LIGATURE FI
+\def\flligature {fl} % LATIN SMALL LIGATURE FL
+\def\ffiligature {ffi} % LATIN SMALL LIGATURE FFI
+\def\fflligature {ffl} % LATIN SMALL LIGATURE FFL
+\def\stligature {st} % LATIN SMALL LIGATURE ST
+
\endinput
diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua
index 4fcd713a0..e6cb9fcd6 100644
--- a/tex/context/base/font-afm.lua
+++ b/tex/context/base/font-afm.lua
@@ -39,9 +39,9 @@ do
local keys = { }
- function keys.FontName (data,line) data.fullname = line:strip() end
+ function keys.FontName (data,line) data.fullname = line:strip() end
function keys.ItalicAngle (data,line) data.italicangle = tonumber (line) end
- function keys.IsFixedPitch(data,line) data.isfixedpitch = toboolean(line) end
+ function keys.IsFixedPitch(data,line) data.isfixedpitch = toboolean(line,true) end
function keys.CharWidth (data,line) data.charwidth = tonumber (line) end
function keys.XHeight (data,line) data.xheight = tonumber (line) end
function keys.Descender (data,line) data.descender = tonumber (line) end
diff --git a/tex/context/base/font-ini.tex b/tex/context/base/font-ini.tex
index 2de37cd37..0b8da7756 100644
--- a/tex/context/base/font-ini.tex
+++ b/tex/context/base/font-ini.tex
@@ -1188,81 +1188,6 @@
\def\setforcedfontspec#1 #2\relax]%
{\csname\@fs@#1\endcsname#2\relax}
-%D For \XETEX\ we need to support a bit more:
-%D
-%D \starttyping
-%D \definedfont[{cmr10} at 40pt] test
-%D \definedfont['cmss10' at 40pt] test
-%D \definedfont["cmtt10" at 40pt] test
-%D
-%D \definedfont[{cmr10} at 40pt] test
-%D \definedfont['cmss10' at 40pt] test
-%D \definedfont["cmtt10" at 40pt] test
-%D
-%D \definedfont["Gentium" at 40pt] test
-%D \stoptyping
-
-% \beginXETEX \font
-
-% % actually, we can use "" in pdftex> 1.20 as well
-
-% \def\parsefontspec#1%
-% {\xdef\somefontspec{#1\space}%
-% \@EA\doparsefontspec\somefontspec\relax]% =>#1 \empty]
-% \donoparsefontspec}
-
-% \def\doparsefontspec#1%
-% {\ifx"#1%
-% \@EA\dodqparsefontspec
-% \else\ifx'#1%
-% \@EAEAEA\dosqparsefontspec
-% \else
-% \@EAEAEA\dodoparsefontspec
-% \fi\fi#1}
-
-% \def\dqfontquote{"}
-% \def\sqfontquote{'}
-
-% \def\dodqparsefontspec"#1"#2%
-% {\def\somefontname{#1}%
-% \let\somefontquote\dqfontquote
-% \ifx#2\relax\@EA\setnaturalfontspec\else\@EA\setforcedfontspec\fi#2}
-
-% \def\dosqparsefontspec'#1'#2%
-% {\def\somefontname{#1}%
-% \let\somefontquote\sqfontquote
-% \ifx#2\relax\@EA\setnaturalfontspec\else\@EA\setforcedfontspec\fi#2}
-
-% \def\dodoparsefontspec#1 #2%
-% {\def\somefontname{#1}%
-% \let\somefontquote\empty
-% \ifx\somefontname\empty % space before fontname
-% \@EA\doparsefontspec
-% \else\ifx#2\relax
-% \@EAEAEA\setnaturalfontspec
-% \else
-% \@EAEAEA\setforcedfontspec
-% \fi\fi
-% #2}
-
-% \def\setnaturalfontspec#1]%
-% {\@fs@scaled\plusthousand\relax}
-
-% \def\setforcedfontspec#1 #2\relax]%
-% {\csname\@fs@#1\endcsname#2\relax}
-
-% \def\donoparsefontspec % #1 == \cs
-% {\edef\fontfile{\somefontquote\truefontname\somefontname\somefontquote}%
-% \ifx\fontfile\s!unknown \let\fontfile\defaultfontfile \fi
-% \edef\lastfontname{\fontfile\somefontspec}%
-% \ifx\fontclass\empty
-% \expandafter\definefontlocal
-% \else
-% \expandafter\definefontglobal
-% \fi} % #1 == \cs
-
-% \endXETEX
-
\def\@fs@scaled
{\afterassignment\do@fs@scaled\scratchcounter}
@@ -1487,7 +1412,7 @@
\endLUATEX
-% xetex / todo: disable default features !
+% xetex / todo: disable default features ! file:, name:, [], "" etc etc
\beginXETEX
@@ -1500,24 +1425,43 @@
% \font\myfont = "msam7" % also ok
% \font\myfont = "msam7" at 8pt % error
- \newcount\xetexsavedinteractionmode
- \newbox \xetexcrappyhackbox
-
- \def\doiffoundxetexfontelse#1#2%
- {\xetexsavedinteractionmode\interactionmode
- \batchmode
- \setbox\xetexcrappyhackbox\vbox{\par}% resets error count
- \font\xetextempfont=#2\somefontspec\relax
- \edef\xetextempfont{\fontname\xetextempfont}%
- \ifx\xetextempfont\nullfontname
- \interactionmode\xetexsavedinteractionmode
- %\writestatus\m!fonts{fails #1: #2 (\xetextempfont)}%
- \expandafter\secondoftwoarguments
- \else
- \interactionmode\xetexsavedinteractionmode
- %\writestatus\m!fonts{succeeds #1: #2 (\xetextempfont)}%
- \expandafter\firstoftwoarguments
- \fi}
+ \ifx\suppressfontnotfounderror\undefined
+
+ \newcount\xetexsavedinteractionmode
+ \newbox \xetexcrappyhackbox
+
+ \def\doiffoundxetexfontelse#1#2%
+ {\xetexsavedinteractionmode\interactionmode
+ \batchmode
+ \setbox\xetexcrappyhackbox\vbox{\par}% resets error count
+ \font\xetextempfont=#2\somefontspec\relax
+ \edef\xetextempfont{\fontname\xetextempfont}%
+ \ifx\xetextempfont\nullfontname
+ \interactionmode\xetexsavedinteractionmode
+ %\writestatus\m!fonts{fails #1: #2 (\xetextempfont)}%
+ \expandafter\secondoftwoarguments
+ \else
+ \interactionmode\xetexsavedinteractionmode
+ %\writestatus\m!fonts{succeeds #1: #2 (\xetextempfont)}%
+ \expandafter\firstoftwoarguments
+ \fi}
+
+ \else
+
+ \def\doiffoundxetexfontelse#1#2%
+ {\suppressfontnotfounderror\plusone
+ \font\xetextempfont=#2\somefontspec\relax
+ \suppressfontnotfounderror\zerocount
+ \edef\xetextempfont{\fontname\xetextempfont}%
+ \ifx\xetextempfont\nullfontname
+ %\writestatus\m!fonts{fails #1: #2 (\xetextempfont)}%
+ \expandafter\secondoftwoarguments
+ \else
+ %\writestatus\m!fonts{succeeds #1: #2 (\xetextempfont)}%
+ \expandafter\firstoftwoarguments
+ \fi}
+
+ \fi
\def\docheckfontfilenameprefix#1:#2:#3#4\relax
{\edef\!!stringa{#1}%
@@ -1525,17 +1469,19 @@
\ifx\!!stringb\empty
% no prefix
\edef\checkedfontfile{\ifx\@@fontresource\empty\!!stringa\else\@@fontresource\fi}%
- \doiffoundxetexfontelse{1a}{"\checkedfontfile\checkedfontfeatures"}
- {\edef\checkedfontfile{"\checkedfontfile\checkedfontfeatures"}}
- {\doiffoundxetexfontelse{1b}{"[\checkedfontfile]\checkedfontfeatures"}
- {\edef\checkedfontfile{"[\checkedfontfile]\checkedfontfeatures"}}
- {\edef\checkedfontfile{\checkedfontfile}}}%
+ \doiffoundxetexfontelse{1a}{\checkedfontfile\checkedfontfeatures}
+ {\edef\checkedfontfile{\checkedfontfile\checkedfontfeatures}}
+ {\doiffoundxetexfontelse{1b}{"\checkedfontfile\checkedfontfeatures"}
+ {\edef\checkedfontfile{"\checkedfontfile\checkedfontfeatures"}}
+ {\doiffoundxetexfontelse{1c}{"[\checkedfontfile]\checkedfontfeatures"}
+ {\edef\checkedfontfile{"[\checkedfontfile]\checkedfontfeatures"}}
+ {\edef\checkedfontfile{\checkedfontfile}}}}%
\else\ifx\!!stringa\v!file
% force file, only file check when no spaces
\edef\checkedfontfile{\ifx\@@fontresource\empty\!!stringb\else\@@fontresource\fi}%
- \doiffoundxetexfontelse{2a}{"[\checkedfontfile]\checkedfontfeatures"}
+ \doiffoundxetexfontelse{2b}{"[\checkedfontfile]\checkedfontfeatures"}
{\edef\checkedfontfile{"[\checkedfontfile]\checkedfontfeatures"}}
- {\doiffoundxetexfontelse{2b}{"\checkedfontfile\checkedfontfeatures"}
+ {\doiffoundxetexfontelse{2c}{"\checkedfontfile\checkedfontfeatures"}
{\edef\checkedfontfile{"\checkedfontfile\checkedfontfeatures"}}
{\edef\checkedfontfile{\checkedfontfile}}}%
\else\ifx\!!stringa\v!name
@@ -1671,9 +1617,13 @@
%D but somehow they changed \TEX\ so that it does not matter
%D any more.
-\def\defaultfontfile{cmtt10}
-\edef\nullfontname {\fontname\nullfont}
-\edef\dummyfontname {font\strippedcsname\\}
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+\edef\dummyfontname {font\strippedcsname\\}
+
+\beginXETEX
+ \def\defaultfontfile{lmtypewriter10-regular}
+\endXETEX
%D \macros
%D {everyfont,everyfontswitch}
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 205305ea6..46ec72aa0 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -716,11 +716,16 @@ function fonts.otf.load(filename,format,sub,featurefile)
end
local data = containers.read(fonts.otf.cache, hash)
if not data then
- local ff
+ local ff, messages
if sub then
- ff = fontforge.open(filename,sub)
+ ff, messages = fontforge.open(filename,sub)
else
- ff = fontforge.open(filename)
+ ff, messages = fontforge.open(filename)
+ end
+ if messages and #messages > 0 then
+ for _, m in ipairs(messages) do
+ logs.report("load otf","warning: " .. m)
+ end
end
if ff then
logs.report("load otf","loading: " .. filename)
@@ -2316,6 +2321,9 @@ do
local function toligature(start,stop,char,markflag)
if start ~= stop then
local deletemarks = markflag ~= "mark"
+ start.components = node.copy_list(start,stop)
+ node.slide(start.components)
+ -- todo: components
start.subtype = 1
start.char = char
local marknum = 1
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index fdd99e6f2..16910a8fd 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -75,6 +75,30 @@ fonts.names.filters.fixes = {
{ "cond$", "condensed", },
}
+--~ todo
+--~
+--~ function getosfontdirs()
+--~ local hash, result = { }, { }
+--~ local function collect(t)
+--~ for _, v in ipairs(t) do
+--~ v = input.clean_path(v)
+--~ v = v:gsub("/+$","")
+--~ local key = v:lower()
+--~ if not hash[key] then
+--~ hash[key], result[#result+1] = true, v
+--~ end
+--~ end
+--~ end
+--~ collect(input.expanded_path_list(instance,"osfontdir"))
+--~ local name = input.find_file(instance,"fonts.conf","other")
+--~ if name ~= "" then
+--~ local root = xml.load(name)
+--~ collect(xml.all_texts(root,"dir",true))
+--~ end
+--~ return result
+--~ end
+
+
function fonts.names.identify()
fonts.names.data = {
mapping = { },
@@ -122,7 +146,7 @@ function fonts.names.identify()
local function traverse(what, method)
for n, suffix in pairs(fonts.names.filters.list) do
nofread, nofok = 0, 0
- local t = os.clock()
+ local t = os.clock() -- use elapser
logs.report("fontnames", string.format("identifying %s font files with suffix %s",what,suffix))
method(suffix)
logs.report("fontnames", string.format("%s %s files identified, %s hash entries added, runtime %s seconds", nofread, what,nofok, os.clock()-t))
@@ -145,7 +169,7 @@ function fonts.names.identify()
local pattern = path .. "*." .. suffix
logs.info("fontnames", "globbing path " .. pattern)
local t = dir.glob(pattern)
- for _, name in pairs(t) do
+ for _, name in pairs(t) do -- ipairs
local mode = lfs.attributes(name,'mode')
if mode == "file" then
identify(name,file.basename(name),suffix)
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
index 4352122aa..67a7866c5 100644
--- a/tex/context/base/font-tfm.lua
+++ b/tex/context/base/font-tfm.lua
@@ -150,6 +150,8 @@ function fonts.tfm.check_virtual_id(tfmdata, id)
end
end
+-- if t.tounicode = 1 then also characters[n].tounicode = "string"
+
function fonts.tfm.scale(tfmtable, scaledpoints)
-- 65536 = 1pt
-- 1000 units per designsize (not always)
diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua
index e1efa4ad4..098f0b3a1 100644
--- a/tex/context/base/l-boolean.lua
+++ b/tex/context/base/l-boolean.lua
@@ -11,12 +11,20 @@ function boolean.tonumber(b)
if b then return 1 else return 0 end
end
-function toboolean(str)
- if type(str) == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1"
- elseif type(str) == "number" then
- return tonumber(str) ~= 0
- elseif type(str) == "nil" then
+function toboolean(str,tolerant)
+ if tolerant then
+ if type(str) == "string" then
+ return str == "true" or str == "yes" or str == "on" or str == "1"
+ elseif type(str) == "number" then
+ return tonumber(str) ~= 0
+ elseif type(str) == "nil" then
+ return false
+ else
+ return str
+ end
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
return false
else
return str
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index 073f39b5a..b0344c002 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -132,7 +132,7 @@ end
--~ split = lpeg.Ct(c*(p*c)^0)
--~ splitters[separator] = split
--~ end
---~ return lpeg.match(split,self)
+--~ return lpeg.match(split,self) -- split:match(self)
--~ else
--~ return { }
--~ end
@@ -289,7 +289,7 @@ end
--~ return self .. self.rep(chr or " ",n-#self)
--~ end
-function string:padd(n,chr)
+function string:rpadd(n,chr)
local m = n-#self
if m > 0 then
return self .. self.rep(chr or " ",m)
@@ -298,6 +298,17 @@ function string:padd(n,chr)
end
end
+function string:lpadd(n,chr)
+ local m = n-#self
+ if m > 0 then
+ return self.rep(chr or " ",m) .. self
+ else
+ return self
+ end
+end
+
+string.padd = string.rpadd
+
function is_number(str)
return str:find("^[%-%+]?[%d]-%.?[%d+]$") == 1
end
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index e8f56ca09..14fad31d7 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -169,6 +169,8 @@ end
do
+ -- one of my first exercises in lua ...
+
-- 34.055.092 32.403.326 arabtype.tma
-- 1.620.614 1.513.863 lmroman10-italic.tma
-- 1.325.585 1.233.044 lmroman10-regular.tma
@@ -528,6 +530,25 @@ function table.tohash(t)
return h
end
+function table.contains(t, v)
+ if t then
+ for i=1, #t do
+ if t[i] == v then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function table.count(t)
+ local n, e = 0, next(t)
+ while e do
+ n, e = n + 1, next(t,e)
+ end
+ return n
+end
+
--~ function table.are_equal(a,b)
--~ return table.serialize(a) == table.serialize(b)
--~ end
diff --git a/tex/context/base/l-xml-edu.lua b/tex/context/base/l-xml-edu.lua
new file mode 100644
index 000000000..adfc55e68
--- /dev/null
+++ b/tex/context/base/l-xml-edu.lua
@@ -0,0 +1,381 @@
+if not modules then modules = { } end modules ['l-xml-edu'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>This module contains older code thatwe keep around for educational
+purposes. Here you find the find based xml and lpath parsers.</p>
+--ldx]]--
+
+if false then
+
+ do
+
+ -- Loading 12 cont-*.xml and keys-*.xml files totaling to 2.62 MBytes takes 1.1 sec
+ -- on a windows vista laptop with dual core 7600 (2.3 Ghz), which is not that bad.
+ -- Of this half time is spent on doctype etc parsing.
+
+ local doctype_patterns = {
+ "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\"%s+%b[])%s*>",
+ "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\")%s*>",
+ "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\"%s+%b[])%s*>",
+ "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\")%s*>",
+ "<!DOCTYPE%s+(.-%s%b[])%s*>",
+ "<!DOCTYPE%s+(.-)%s*>"
+ }
+
+ -- We assume no "<" which is the lunatic part of the xml spec
+ -- especially since ">" is permitted; otherwise we need a char
+ -- by char parser ... more something for later ... normally
+ -- entities will be used anyway.
+
+ -- data = data:gsub(nothing done) is still a copy so we find first
+
+ local function prepare(data,text)
+ -- pack (for backward compatibility)
+ if type(data) == "table" then
+ data = table.concat(data,"")
+ end
+ -- CDATA
+ if data:find("<!%[CDATA%[") then
+ data = data:gsub("<!%[CDATA%[(.-)%]%]>", function(txt)
+ text[#text+1] = txt or ""
+ return string.format("<@cd@>%s</@cd@>",#text)
+ end)
+ end
+ -- DOCTYPE
+ if data:find("<!DOCTYPE ") then
+ data = data:gsub("^(.-)(<[^!?])", function(a,b)
+ if a:find("<!DOCTYPE ") then -- ?
+ for _,v in ipairs(doctype_patterns) do
+ a = a:gsub(v, function(d)
+ text[#text+1] = d or ""
+ return string.format("<@dd@>%s</@dd@>",#text)
+ end)
+ end
+ end
+ return a .. b
+ end,1)
+ end
+ -- comment / does not catch doctype
+ if data:find("<!%-%-") then
+ data = data:gsub("<!%-%-(.-)%-%->", function(txt)
+ text[#text+1] = txt or ""
+ return string.format("<@cm@>%s</@cm@>",#text)
+ end)
+ end
+ -- processing instructions / altijd 1
+ if data:find("<%?") then
+ data = data:gsub("<%?(.-)%?>", function(txt)
+ text[#text+1] = txt or ""
+ return string.format("<@pi@>%s</@pi@>",#text)
+ end)
+ end
+ return data, text
+ end
+
+ -- maybe we will move the @tg@ stuff to a dedicated key, say 'st'; this will speed up
+ -- serializing and testing
+
+ function xml.convert(data,no_root,collapse)
+ local crap = { }
+ data, crap = prepare(data, crap)
+ local nsremap = xml.xmlns
+ local remove = table.remove
+ local stack, top = {}, {}
+ local i, j, errorstr = 1, 1, nil
+ stack[#stack+1] = top
+ top.dt = { }
+ local dt = top.dt
+ local mt = { __tostring = xml.text }
+ local xmlns = { }
+ while true do
+ local ni, first, attributes, last, fulltag, resolved
+ ni, j, first, fulltag, attributes, last = data:find("<(/-)([^%s>/]+)%s*([^>]-)%s*(/-)>", j)
+ if not ni then break end
+ local namespace, tag = fulltag:match("^(.-):(.+)$")
+ if attributes ~= "" then
+ local t = {}
+ for ns, tag, _, value in attributes:gmatch("(.-):?(.+)=([\"\'])(.-)%3") do -- . was %w
+ if tag == "xmlns" then -- not ok yet
+ xmlns[#xmlns+1] = xml.resolvens(value)
+ t[tag] = value
+ elseif ns == "xmlns" then
+ xml.checkns(tag,value)
+ t["xmlns:" .. tag] = value
+ else
+ t[tag] = value
+ end
+ end
+ attributes = t
+ else
+ attributes = { }
+ end
+ if namespace then -- realtime remapping
+ resolved = nsremap[namespace] or namespace
+ else
+ namespace, tag = "", fulltag
+ resolved = xmlns[#xmlns]
+ end
+ local text = data:sub(i, ni-1)
+ if text == "" or (collapse and text:find("^%s*$")) then
+ -- no need for empty text nodes, beware, also packs <a>x y z</a>
+ -- so is not that useful unless used with empty elements
+ else
+ dt[#dt+1] = text
+ end
+ if first == "/" then
+ -- end tag
+ local toclose = remove(stack) -- remove top
+ top = stack[#stack]
+ if #stack < 1 then
+ errorstr = string.format("nothing to close with %s", tag)
+ break
+ elseif toclose.tg ~= tag then -- no namespace check
+ errorstr = string.format("unable to close %s with %s", toclose.tg, tag)
+ break
+ end
+ if tag:find("^@..@$") then
+ dt[1] = crap[tonumber(dt[1])] or ""
+ end
+ dt = top.dt
+ dt[#dt+1] = toclose
+ if attributes.xmlns then
+ remove(xmlns) -- ?
+ end
+ elseif last == "/" then
+ -- empty element tag
+ dt[#dt+1] = { ns = namespace, rn = resolved, tg = tag, dt = { }, at = attributes, __p__ = top }
+ setmetatable(top, mt)
+ else
+ -- begin tag
+ top = { ns = namespace, rn = resolved, tg = tag, dt = { }, at = attributes, __p__ = stack[#stack] }
+ setmetatable(top, mt)
+ dt = top.dt
+ stack[#stack+1] = top
+ end
+ i = j + 1
+ end
+ if not errorstr then
+ local text = data:sub(i)
+ if dt and not text:find("^%s*$") then
+ dt[#dt+1] = text
+ end
+ if #stack > 1 then
+ errorstr = string.format("unclosed %s", stack[#stack].tg)
+ end
+ end
+ if errorstr then
+ stack = { { tg = "error", dt = { errorstr } } }
+ setmetatable(stack, mt)
+ end
+ if no_root then
+ return stack[1]
+ else
+ local t = { ns = "", tg = '@rt@', dt = stack[1].dt }
+ setmetatable(t, mt)
+ for k,v in ipairs(t.dt) do
+ if type(v) == "table" and v.tg ~= "@pi@" and v.tg ~= "@dd@" and v.tg ~= "@cm@" then
+ t.ri = k -- rootindex
+ break
+ end
+ end
+ return t
+ end
+ end
+
+ end
+
+ --~ Y a/b
+ --~ Y /a/b
+ --~ Y a/*/b
+ --~ Y a//b
+ --~ Y child::
+ --~ Y .//
+ --~ Y ..
+ --~ N id("tag")
+ --~ Y parent::
+ --~ Y child::
+ --~ N preceding-sibling:: (same name)
+ --~ N following-sibling:: (same name)
+ --~ N preceding-sibling-of-self:: (same name)
+ --~ N following-sibling-or-self:: (same name)
+ --~ N ancestor::
+ --~ N descendent::
+ --~ N preceding::
+ --~ N following::
+ --~ N self::node()
+ --~ N node() == alles
+ --~ N a[position()=5]
+ --~ Y a[5]
+ --~ Y a[-5]
+ --~ N a[first()]
+ --~ N a[last()]
+ --~ Y a/(b|c|d)/e/f
+ --~ Y a/!(b|c|d)/e/f
+ --~ N (c/d|e)
+ --~ Y a/b[@bla]
+ --~ Y a/b[@bla='oeps']
+ --~ Y a/b[@bla=='oeps']
+ --~ Y a/b[@bla<>'oeps']
+ --~ Y a/b[@bla!='oeps']
+ --~ Y a/b/@bla
+ --~ Y a['string']
+ --~ Y ^/a/c (root)
+ --~ Y ^^/a/c (docroot)
+ --~ Y root::a/c (docroot)
+ --~ no wild card functions (yet)
+ --~ s = "/a//b/*/(c|d|e)/(f|g)/h[4]/h/child::i/j/(a/b)/p[-1]/q[4]/ancestor::q/r/../s/./t[@bla='true']/k"
+ -- // == /**/
+ -- / = ^ (root)
+
+ do
+
+ function analyze(str)
+ if not str then
+ return ""
+ else
+ local tmp, result, map, key = { }, { }, { }, str
+ str = str:gsub("(%b[])", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
+ str = str:gsub("(%b())", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
+ str = str:gsub("(%^+)([^/])", "%1/%2")
+ str = str:gsub("//+", "/**/")
+ str = str:gsub(".*root::", "^/")
+ str = str:gsub("child::", "")
+ str = str:gsub("parent::", "../")
+ str = str:gsub("self::", "./")
+ str = str:gsub("^/", "^/")
+ for s in str:gmatch("([^/]+)") do
+ s = s:gsub("%[%[(%d+)%]%]",function(n) return tmp[tonumber(n)] end)
+ result[#result+1] = s
+ end
+ return result
+ end
+ end
+
+ function compose(result)
+ if not result or #result == 0 then
+ -- wildcard
+ return true
+ elseif #result == 1 then
+ local r = result[1][1]
+ if r == "14" or r == "15" then
+ -- wildcard
+ return true
+ elseif r == "12" then
+ -- root
+ return false
+ end
+ end
+ local map = { }
+ for r=1,#result do
+ local ri = result[r]
+ if ri == "." then
+ -- skip
+ elseif ri == ".." then
+ map[#map+1] = { 11 }
+ elseif ri == "^" then
+ map[#map+1] = { 12 }
+ elseif ri == "^^" then
+ map[#map+1] = { 13 }
+ elseif ri == "*" then
+ map[#map+1] = { 14 }
+ elseif ri == "**" then
+ map[#map+1] = { 15 }
+ else
+ local negate, m = ri:match("^(!*)%((.*)%)$") -- (a|b|c)
+ if m or ri:find('|') then
+ m = m or ri
+ if m:find("[%[%]%(%)/]") then -- []()/
+ -- error
+ else
+ local t = { (negate and #negate>0 and 25) or 21 }
+ for s in m:gmatch("([^|]+)") do
+ local ns, tg = s:match("^(.-):?([^:]+)$")
+ if ns == "*" then ns = true end
+ t[#t+1] = ns
+ t[#t+1] = tg
+ end
+ map[#map+1] = t
+ end
+ else
+ local s, f = ri:match("^(.-)%[%s*(.+)%s*%]$") --aaa[bbb]
+ if s and f then
+ local ns, tg = s:match("^(.-):?([^:]+)$")
+ local at, op, vl = f:match("^@(.-)([!=<>]?)([^!=<>]+)$") -- [@a=='b']
+ if ns == "*" then ns = true end
+ if vl then
+ if op and op ~= "" then
+ if op == '=' or op == '==' then
+ map[#map+1] = { 22, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$","%2")) }
+ elseif op == '<>' or op == '!=' then
+ map[#map+1] = { 23, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$","%2")) }
+ else
+ -- error
+ end
+ elseif vl ~= "" then -- [@whatever]
+ map[#map+1] = { 26, ns, tg, vl }
+ else
+ -- error
+ end
+ -- elseif f:find("^([%-%+%d]+)$") then -- [123]
+ elseif f:find("^([-+%d]+)$") then -- [123]
+ map[#map+1] = { 30, ns, tg, tonumber(f) }
+ else -- [whatever]
+ map[#map+1] = { 27, ns, tg, (f:gsub("^([\'\"])(.*)%1$","%2")) }
+ end
+ else
+ local pi = ri:match("^pi::(.-)$")
+ if pi then
+ map[#map+1] = { 40, pi }
+ else
+ local negate, ns, tg = ri:match("^(!-)(.-):?([^:]+)$")
+ map[#map+1] = { (negate and #negate>0 and 24) or 20, ns, tg }
+ end
+ end
+ end
+ end
+ end
+ -- if we have a symbol, we can prepend that to the string, which is faster
+ local mm = map[1] or { }
+ local r = mm[1] or 0
+ if #map == 1 then
+ if r == 14 or r == 15 then
+ -- wildcard
+ return true
+ elseif r == 12 then
+ -- root
+ return false
+ end
+ end
+ if r ~= 11 and r ~= 12 and r ~= 13 and r ~= 14 and r ~= 15 then
+ table.insert(map, 1, { 16 })
+ end
+ return map
+ end
+
+ cache = { }
+
+ function xml.lpath(pattern)
+ if type(pattern) == "string" then
+ local result = cache[pattern]
+ if not result then
+ result = compose(analyze(pattern))
+ cache[pattern] = result
+ end
+ if xml.trace_lpath then
+ xml.lshow(result)
+ end
+ return result
+ else
+ return pattern
+ end
+ end
+
+ end
+
+end
diff --git a/tex/context/base/l-xml.lua b/tex/context/base/l-xml.lua
index 7395c9e73..9236411f7 100644
--- a/tex/context/base/l-xml.lua
+++ b/tex/context/base/l-xml.lua
@@ -6,13 +6,14 @@ if not modules then modules = { } end modules ['l-xml'] = {
license = "see context related readme files"
}
--- todo: ns, tg = s:match("^(.-):?([^:]+)$")
+-- RJ: key=value ... lpeg.Ca(lpeg.Cc({}) * (pattern-producing-key-and-value / rawset)^0)
--[[ldx--
<p>The parser used here is inspired by the variant discussed in the lua book, but
handles comment and processing instructions, has a different structure, provides
parent access; a first version used different tricky but was less optimized to we
-went this route.</p>
+went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
+The find based parser can be found in l-xml-edu.lua along with other older code.</p>
<p>Expecially the lpath code is experimental, we will support some of xpath, but
only things that make sense for us; as compensation it is possible to hook in your
@@ -21,7 +22,7 @@ this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
files.</p>
<typing>
-a/b/c /*/c (todo: a/b/(pattern)/d)
+a/b/c /*/c
a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
</typing>
@@ -36,48 +37,86 @@ tex = tex or { }
xml.trace_lpath = false
xml.trace_print = false
+xml.trace_remap = false
--[[ldx--
-<p>First a hack to enable namespace resolving.</p>
+<p>First a hack to enable namespace resolving. A namespace is characterized by
+a <l n='url'/>. The following function associates a namespace prefix with a
+pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
+find based solution where we loop over an array of patterns. Less code and
+much cleaner.</p>
--ldx]]--
+xml.xmlns = { }
+
do
- xml.xmlns = { }
+ local parser = lpeg.P(false) -- printing shows that this has no side effects
+
+ --[[ldx--
+ <p>The next function associates a namespace prefix with an <l n='url'/>. This
+ normally happens independent of parsing.</p>
- local data = { }
+ <typing>
+ xml.registerns("mml","mathml")
+ </typing>
+ --ldx]]--
- function xml.registerns(namespace,pattern)
- data[#data+1] = { namespace:lower(), pattern:lower() }
+ function xml.registerns(namespace, pattern) -- pattern can be an lpeg
+ parser = parser + lpeg.C(lpeg.P(pattern:lower())) / namespace
end
+ --[[ldx--
+ <p>The next function also registers a namespace, but this time we map a
+ given namespace prefix onto a registered one, using the given
+ <l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
+
+ <typing>
+ xml.checkns("m","http://www.w3.org/mathml")
+ </typing>
+ --ldx]]--
+
function xml.checkns(namespace,url)
- url = url:lower()
- for i=1,#data do
- local d = data[i]
- if url:find(d[2]) then
- if namespace ~= d[1] then
- xml.xmlns[namespace] = d[1]
- end
- end
+ local ns = parser:match(url:lower())
+ if ns and namespace ~= ns then
+ xml.xmlns[namespace] = ns
end
end
+ --[[ldx--
+ <p>Next we provide a way to turn an <l n='url'/> into a registered
+ namespace. This used for the <t>xmlns</t> attribute.</p>
+
+ <typing>
+ resolvedns = xml.resolvens("http://www.w3.org/mathml")
+ </typing>
+
+ This returns <t>mml</t>.
+ --ldx]]--
+
function xml.resolvens(url)
- url = url:lower()
- for i=1,#data do
- local d = data[i]
- if url:find(d[2]) then
- return d[1]
- end
- end
- return ""
+ return parser:match(url:lower()) or ""
end
+ --[[ldx--
+ <p>A namespace in an element can be remapped onto the registered
+ one efficiently by using the <t>xml.xmlns</t> table.</p>
+ --ldx]]--
+
end
--[[ldx--
-<p>Next comes the loader. The dreadful doctype comes in many disguises:</p>
+<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
+such. This version is about twice as fast which is mostly due to the fact that
+we don't have to prepare the stream for cdata, doctype etc etc. This variant is
+is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
+took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
+the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
+<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
+
+<p>Next comes the parser. The rather messy doctype definition comes in many
+disguises so it is no surprice that later on have to dedicate quite some
+<l n='lpeg'/> code to it.</p>
<typing>
<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
@@ -87,320 +126,466 @@ end
<!DOCTYPE Something [ ... ] >
<!DOCTYPE Something >
</typing>
+
+<p>The code may look a bit complex but this is mostly due to the fact that we
+resolve namespaces and attach metatables. There is only one public function:</p>
+
+<typing>
+local x = xml.convert(somestring)
+</typing>
+
+<p>An optional second boolean argument tells this function not to create a root
+element.</p>
--ldx]]--
do
- -- Loading 12 cont-*.xml and keys-*.xml files totaling to 2.62 MBytes takes 1.1 sec
- -- on a windows vista laptop with dual core 7600 (2.3 Ghz), which is not that bad.
- -- Of this half time is spent on doctype etc parsing.
-
- local doctype_patterns = {
- "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\"%s+%b[])%s*>",
- "<!DOCTYPE%s+(.-%s+PUBLIC%s+%b\"\"%s+%b\"\")%s*>",
- "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\"%s+%b[])%s*>",
- "<!DOCTYPE%s+(.-%s+SYSTEM%s+%b\"\")%s*>",
- "<!DOCTYPE%s+(.-%s%b[])%s*>",
- "<!DOCTYPE%s+(.-)%s*>"
- }
+ local remove, nsremap = table.remove, xml.xmlns
- -- We assume no "<" which is the lunatic part of the xml spec
- -- especially since ">" is permitted; otherwise we need a char
- -- by char parser ... more something for later ... normally
- -- entities will be used anyway.
+ local stack, top, dt, at, xmlns, errorstr = {}, {}, {}, {}, {}, nil
- -- data = data:gsub(nothing done) is still a copy so we find first
+ local mt = { __tostring = xml.text }
- local function prepare(data,text)
- -- pack (for backward compatibility)
- if type(data) == "table" then
- data = table.concat(data,"")
+ local function add_attribute(namespace,tag,value)
+ if tag == "xmlns" then
+ xmlns[#xmlns+1] = xml.resolvens(value)
+ at[tag] = value
+ elseif ns == "xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:" .. tag] = value
+ else
+ at[tag] = value
end
- -- CDATA
- if data:find("<%!%[CDATA%[") then
- data = data:gsub("<%!%[CDATA%[(.-)%]%]>", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@cd@>%s</@cd@>",#text)
- end)
+ end
+ local function add_begin(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
end
- -- DOCTYPE
- if data:find("<!DOCTYPE ") then
- data = data:gsub("^(.-)(<[^%!%?])", function(a,b)
- if a:find("<!DOCTYPE ") then
- for _,v in ipairs(doctype_patterns) do
- a = a:gsub(v, function(d)
- text[#text+1] = d or ""
- return string.format("<@dd@>%s</@dd@>",#text)
- end)
- end
- end
- return a .. b
- end,1)
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = { ns=namespace or "", nr=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
+ setmetatable(top, mt)
+ dt = top.dt
+ stack[#stack+1] = top
+ at = { }
+ end
+ local function add_end(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local toclose = remove(stack)
+ top = stack[#stack]
+ if #stack < 1 then
+ errorstr = string.format("nothing to close with %s", tag)
+ elseif toclose.tg ~= tag then -- no namespace check
+ errorstr = string.format("unable to close %s with %s", toclose.tg, tag)
+ end
+ dt = top.dt
+ dt[#dt+1] = toclose
+ if at.xmlns then
+ remove(xmlns)
+ end
+ end
+ local function add_empty(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = stack[#stack]
+ setmetatable(top, mt)
+ dt = top.dt
+ dt[#dt+1] = { ns=namespace or "", nr=resolved, tg=tag, at=at, dt={}, __p__ = top }
+ at = { }
+ if at.xmlns then
+ remove(xmlns)
end
- -- comment / does not catch doctype
- data = data:gsub("<%!%-%-(.-)%-%->", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@cm@>%s</@cm@>",#text)
- end)
- -- processing instructions / altijd 1
- data = data:gsub("<%?(.-)%?>", function(txt)
- text[#text+1] = txt or ""
- return string.format("<@pi@>%s</@pi@>",#text)
- end)
- return data, text
+ end
+ local function add_text(text)
+ dt[#dt+1] = text
+ end
+ local function add_special(what, spacing, text)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ top = stack[#stack]
+ setmetatable(top, mt)
+ dt[#dt+1] = { special=true, ns="", tg=what, dt={text} }
+ end
+ local function set_message(txt)
+ errorstr = "garbage at the end of the file: " .. txt:gsub("([ \n\r\t]*)","")
end
- -- maybe we will move the @tg@ stuff to a dedicated key, say 'st'; this will speed up
- -- serializing and testing
+ local space = lpeg.S(' \r\n\t')
+ local open = lpeg.P('<')
+ local close = lpeg.P('>')
+ local squote = lpeg.S("'")
+ local dquote = lpeg.S('"')
+ local equal = lpeg.P('=')
+ local slash = lpeg.P('/')
+ local colon = lpeg.P(':')
+ local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-.')
+ local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1)
+ local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local name = name_yes + name_nop
+
+ local utfbom = lpeg.P('\000\000\254\255') + lpeg.P('\255\254\000\000') +
+ lpeg.P('\255\254') + lpeg.P('\254\255') + lpeg.P('\239\187\191') -- no capture
+
+ local spacing = lpeg.C(space^0)
+ local justtext = lpeg.C((1-open)^1)
+ local somespace = space^1
+ local optionalspace = space^0
+
+ local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local attribute = (somespace * name * optionalspace * equal * optionalspace * value) / add_attribute
+ local attributes = attribute^0
+
+ local text = justtext / add_text
+ local balanced = lpeg.P { "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" } -- taken from lpeg manual, () example
+
+ local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
+ local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
+ local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
+
+ local begincomment = open * lpeg.P("!--")
+ local endcomment = lpeg.P("--") * close
+ local begininstruction = open * lpeg.P("?")
+ local endinstruction = lpeg.P("?") * close
+ local begincdata = open * lpeg.P("![CDATA[")
+ local endcdata = lpeg.P("]]") * close
+
+ local someinstruction = lpeg.C((1 - endinstruction)^0)
+ local somecomment = lpeg.C((1 - endcomment )^0)
+ local somecdata = lpeg.C((1 - endcdata )^0)
+
+ local begindoctype = open * lpeg.P("!DOCTYPE")
+ local enddoctype = close
+ local publicdoctype = lpeg.P("PUBLIC") * somespace * value * somespace * value * somespace * balanced^0
+ local systemdoctype = lpeg.P("SYSTEM") * somespace * value * somespace * balanced^0
+ local simpledoctype = (1-close)^1 * balanced^0
+ local somedoctype = lpeg.C((somespace * lpeg.P(publicdoctype + systemdoctype + simpledoctype) * optionalspace)^0)
+
+ local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
+ local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
+ local cdata = (spacing * begincdata * somecdata * endcdata ) / function(...) add_special("@cd@",...) end
+ local doctype = (spacing * begindoctype * somedoctype * enddoctype ) / function(...) add_special("@dd@",...) end
+
+ -- nicer but slower:
+ --
+ -- local instruction = (lpeg.Cc("@pi@") * spacing * begininstruction * someinstruction * endinstruction) / add_special
+ -- local comment = (lpeg.Cc("@cm@") * spacing * begincomment * somecomment * endcomment ) / add_special
+ -- local cdata = (lpeg.Cc("@cd@") * spacing * begincdata * somecdata * endcdata ) / add_special
+ -- local doctype = (lpeg.Cc("@dd@") * spacing * begindoctype * somedoctype * enddoctype ) / add_special
- function xml.convert(data,no_root,collapse)
- local crap = { }
- data, crap = prepare(data, crap)
- local nsremap = xml.xmlns
- local remove = table.remove
- local stack, top = {}, {}
- local i, j, errorstr = 1, 1, nil
+ local trailer = space^0 * (justtext/set_message)^0
+
+ -- comment + emptyelement + text + cdata + instruction + lpeg.V("parent"), -- 6.5 seconds on 40 MB database file
+ -- text + comment + emptyelement + cdata + instruction + lpeg.V("parent"), -- 5.8
+ -- text + lpeg.V("parent") + emptyelement + comment + cdata + instruction, -- 5.5
+
+
+ local grammar = lpeg.P { "preamble",
+ preamble = utfbom^0 * instruction^0 * (doctype + comment + instruction)^0 * lpeg.V("parent") * trailer,
+ parent = beginelement * lpeg.V("children")^0 * endelement,
+ children = text + lpeg.V("parent") + emptyelement + comment + cdata + instruction,
+ }
+
+ function xml.convert(data, no_root) -- no collapse any more
+ stack, top, at, xmlns, errorstr, result = {}, {}, {}, {}, nil, nil
stack[#stack+1] = top
top.dt = { }
- local dt = top.dt
- local id = 0
- local namespaces = { }
- local mt = { __tostring = xml.text }
- while true do
- local ni, first, attributes, last, fulltag
- ni, j, first, fulltag, attributes, last = data:find("<(/-)([^%s%>/]+)%s*([^>]-)%s*(/-)>", j)
- if not ni then break end
- local namespace, tag = fulltag:match("^(.-):(.+)$")
- if attributes ~= "" then
- local t = {}
- for ns, tag, _, value in attributes:gmatch("(%w-):?(%w+)=([\"\'])(.-)%3") do
- if tag == "xmlns" then -- not ok yet
- namespaces[#stack] = xml.resolvens(value)
- elseif ns == "" then
- t[tag] = value
- elseif ns == "xmlns" then
- xml.checkns(tag,value)
- else
- t[tag] = value
- end
- end
- attributes = t
- else
- attributes = { }
- end
- if namespace then -- realtime remapping
- namespace = nsremap[namespace] or namespace
- else
- namespace, tag = namespaces[#stack] or "", fulltag
- end
- local text = data:sub(i, ni-1)
- if text == "" or (collapse and text:find("^%s*$")) then
- -- no need for empty text nodes, beware, also packs <a>x y z</a>
- -- so is not that useful unless used with empty elements
- else
- dt[#dt+1] = text
- end
- if first == "/" then
- -- end tag
- local toclose = remove(stack) -- remove top
- top = stack[#stack]
- namespaces[#stack] = nil
- if #stack < 1 then
- errorstr = string.format("nothing to close with %s", tag)
- break
- elseif toclose.tg ~= tag then -- no namespace check
- errorstr = string.format("unable to close %s with %s", toclose.tg, tag)
- break
- end
- if tag:find("^@..@$") then
- dt[1] = crap[tonumber(dt[1])] or ""
- end
- dt = top.dt
- dt[#dt+1] = toclose
- elseif last == "/" then
- -- empty element tag
- dt[#dt+1] = { ns = namespace, tg = tag, dt = { }, at = attributes, __p__ = top }
- -- setmetatable(top, { __tostring = xml.text })
- setmetatable(top, mt)
- else
- -- begin tag
- top = { ns = namespace, tg = tag, dt = { }, at = attributes, __p__ = stack[#stack] }
- -- setmetatable(top, { __tostring = xml.text })
- setmetatable(top, mt)
- dt = top.dt
- stack[#stack+1] = top
- end
- i = j + 1
- end
- if not errorstr then
- local text = data:sub(i)
- if dt and not text:find("^%s*$") then
- dt[#dt+1] = text
- end
- if #stack > 1 then
- errorstr = string.format("unclosed %s", stack[#stack].tg)
- end
+ dt = top.dt
+ if not data or data == "" then
+ errorstr = "empty xml file"
+ elseif not grammar:match(data) then
+ errorstr = "invalid xml file"
end
if errorstr then
- stack = { { tg = "error", dt = { errorstr } } }
- -- setmetatable(stack, { __tostring = xml.text })
+ result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={} } } }
setmetatable(stack, mt)
- end
- if no_root then
- return stack[1]
+ if xml.error_handler then xml.error_handler("load",errorstr) end
else
- local t = { ns = "", tg = '@rt@', dt = stack[1].dt }
- -- setmetatable(t, { __tostring = xml.text })
- setmetatable(t, mt)
- for k,v in ipairs(t.dt) do
- if type(v) == "table" and v.tg ~= "@pi@" and v.tg ~= "@dd@" and v.tg ~= "@cm@" then
- t.ri = k -- rootindex
+ result = stack[1]
+ end
+ if not no_root then
+ result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={} }
+ setmetatable(result, mt)
+ for k,v in ipairs(result.dt) do
+ if type(v) == "table" and not v.special then -- always table -)
+ result.ri = k -- rootindex
break
end
end
- return t
end
+ return result
end
- function xml.copy(old,tables,parent) -- fast one
- tables = tables or { }
- if old then
- local new = { }
- if not table[old] then
- table[old] = new
- end
- for i,v in pairs(old) do
- -- new[i] = (type(v) == "table" and (table[v] or xml.copy(v, tables, table))) or v
- if type(v) == "table" then
- new[i] = table[v] or xml.copy(v, tables, table)
- else
- new[i] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- return new
- else
- return { }
- end
+ --[[ldx--
+ <p>Packaging data in an xml like table is done with the following
+ function. Maybe it will go away (when not used).</p>
+ --ldx]]--
+
+ function xml.package(tag,attributes,data)
+ local ns, tg = tag:match("^(.-):?([^:]+)$")
+ local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
+ setmetatable(t, mt)
+ return t
end
+ xml.error_handler = (logs and logs.report) or print
+
end
-function xml.load(filename,collapse)
+--[[ldx--
+<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
+the whole file first. The function accepts a string representing
+a filename or a file handle.</p>
+--ldx]]--
+
+function xml.load(filename)
if type(filename) == "string" then
- local root, f = { }, io.open(filename,'r') -- no longer 'rb'
+ local root, f = { }, io.open(filename,'r')
if f then
- root = xml.convert(f:read("*all"),false,collapse)
+ root = xml.convert(f:read("*all"))
f:close()
+ else
+ -- if we want an error: root = xml.convert("")
end
- return root
+ return root -- no nil but an empty table if it fails
else
- return xml.convert(filename:read("*all"),false,collapse)
+ return xml.convert(filename:read("*all"))
end
end
-function xml.root(root)
- return (root.ri and root.dt[root.ri]) or root
+--[[ldx--
+<p>When we inject new elements, we need to convert strings to
+valid trees, which is what the next function does.</p>
+--ldx]]--
+
+function xml.toxml(data)
+ if type(data) == "string" then
+ local root = { xml.convert(data,true) }
+ return (#root > 1 and root) or root[1]
+ else
+ return data
+ end
end
-function xml.toxml(data,collapse)
- local t = { xml.convert(data,true,collapse) }
- if #t > 1 then
- return t
+--[[ldx--
+<p>For copying a tree we use a dedicated function instead of the
+generic table copier. Since we know what we're dealing with we
+can speed up things a bit. The second argument is not to be used!</p>
+--ldx]]--
+
+function xml.copy(old,tables)
+ if old then
+ tables = tables or { }
+ local new = { }
+ if not tables[old] then
+ tables[old] = new
+ end
+ for k,v in pairs(old) do
+ new[k] = (type(v) == "table" and (tables[v] or xml.copy(v, tables))) or v
+ end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
else
- return t[1]
+ return { }
end
end
-function xml.serialize(e, handle, textconverter, attributeconverter)
- handle = handle or (tex and tex.sprint) or io.write
- if not e then
- -- quit
- elseif e.command and xml.command then -- test for command == "" ?
- xml.command(e)
- elseif e.tg then
- local format, serialize = string.format, xml.serialize
- local ens, etg, eat, edt = e.ns, e.tg, e.at, e.dt
- -- no spaces, so no flush needed (check)
- if etg == "@pi@" then
- handle(format("<?%s?>",edt[1]))
- elseif etg == "@cm@" then
- handle(format("<!--%s-->",edt[1]))
- elseif etg == "@cd@" then
- handle(format("<![CDATA[%s]]>",edt[1]))
- elseif etg == "@dd@" then
- handle(format("<!DOCTYPE %s>",edt[1]))
- elseif etg == "@rt@" then
- serialize(edt,handle,textconverter,attributeconverter)
+--[[ldx--
+<p>In <l n='context'/> serializing the tree or parts of the tree is a major
+actitivity which is why the following function is pretty optimized resulting
+in a few more lines of code than needed. The variant that uses the formatting
+function for all components is about 15% slower than the concatinating
+alternative.</p>
+--ldx]]--
+
+do
+
+ -- todo: add <?xml version='1.0' standalone='yes'?> when not present
+
+ local fallbackhandle = (tex and tex.sprint) or io.write
+
+ function xml.serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands)
+ if not e then
+ -- quit
+ elseif not nocommands and e.command and xml.command then
+ xml.command(e)
else
- local ats = eat and next(eat) and { }
- if ats then
- if attributeconverter then
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ handle = handle or fallbackhandle
+ local etg = e.tg
+ if etg then
+ -- local format = string.format
+ if e.special then
+ local edt = e.dt
+ local spc = specialconverter and specialconverter[etg]
+ if spc then
+ local result = spc(edt[1])
+ if result then
+ handle(result)
+ else
+ -- no need to handle any further
+ end
+ elseif etg == "@pi@" then
+ -- handle(format("<?%s?>",edt[1]))
+ handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt)
+ elseif etg == "@cm@" then
+ -- handle(format("<!--%s-->",edt[1]))
+ handle("<!--" .. edt[1] .. "-->")
+ elseif etg == "@cd@" then
+ -- handle(format("<![CDATA[%s]]>",edt[1]))
+ handle("<![CDATA[" .. edt[1] .. "]]>")
+ elseif etg == "@dd@" then
+ -- handle(format("<!DOCTYPE %s>",edt[1]))
+ handle("<!DOCTYPE " .. edt[1] .. ">")
+ elseif etg == "@rt@" then
+ xml.serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands)
end
else
- for k,v in pairs(eat) do
- ats[#ats+1] = format('%s=%q',k,v)
- end
- end
- end
- if ens ~= "" then
- if edt and #edt > 0 then
+ local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { }
if ats then
- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
- else
- handle(format("<%s:%s>",ens,etg))
+ local format = string.format
+ if attributeconverter then
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,attributeconverter(v))
+ end
+ else
+ for k,v in pairs(eat) do
+ ats[#ats+1] = format('%s=%q',k,v)
+ end
+ end
end
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter)
+ if ern and xml.trace_remap then
+ if ats then
+ ats[#ats+1] = string.format("xmlns:remapped='%s'",ern)
+ else
+ ats = { string.format("xmlns:remapped='%s'",ern) }
+ end
end
- handle(format("</%s:%s>",ens,etg))
- else
- if ats then
- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
+ if ens ~= "" then
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," ")))
+ handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s:%s>",ens,etg))
+ handle("<" .. ens .. ":" .. etg .. ">")
+ end
+ local serialize = xml.serialize
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
+ else
+ handle(e)
+ end
+ else
+ serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ end
+ -- handle(format("</%s:%s>",ens,etg))
+ handle("</" .. ens .. ":" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," ")))
+ handle("<%" .. ens .. ":" .. etg .. table.concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s:%s/>",ens,etg))
+ handle("<%" .. ens .. ":" .. "/>")
+ end
+ end
else
- handle(format("<%s:%s/>",ens,etg))
+ if edt and #edt > 0 then
+ if ats then
+ -- handle(format("<%s %s>",etg,table.concat(ats," ")))
+ handle("<" .. etg .. " " .. table.concat(ats," ") .. ">")
+ else
+ -- handle(format("<%s>",etg))
+ handle("<" .. etg .. ">")
+ end
+ local serialize = xml.serialize
+ for i=1,#edt do
+ serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
+ -- handle(format("</%s>",etg))
+ handle("</" .. etg .. ">")
+ else
+ if ats then
+ -- handle(format("<%s %s/>",etg,table.concat(ats," ")))
+ handle("<" .. etg .. table.concat(ats," ") .. "/>")
+ else
+ -- handle(format("<%s/>",etg))
+ handle("<" .. etg .. "/>")
+ end
+ end
end
end
- else
- if edt and #edt > 0 then
- if ats then
- handle(format("<%s %s>",etg,table.concat(ats," ")))
- else
- handle(format("<%s>",etg))
- end
- for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter)
- end
- handle(format("</%s>",etg))
+ elseif type(e) == "string" then
+ if textconverter then
+ handle(textconverter(e))
else
- if ats then
- handle(format("<%s %s/>",etg,table.concat(ats," ")))
- else
- handle(format("<%s/>",etg))
- end
+ handle(e)
+ end
+ else
+ local serialize = xml.serialize
+ for i=1,#e do
+ serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
end
end
end
- elseif type(e) == "string" then
- if textconverter then
- handle(textconverter(e))
- else
- handle(e)
- end
- else
- for i=1,#e do
- xml.serialize(e[i],handle,textconverter,attributeconverter)
+ end
+
+ function xml.checkbom(root)
+ if root.ri then
+ local dt, found = root.dt, false
+ for k,v in ipairs(dt) do
+ if type(v) == "table" and v.special and v.tg == "@pi" and v.dt:find("xml.*version=") then
+ found = true
+ break
+ end
+ end
+ if not found then
+ table.insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ table.insert(dt, 2, "\n" )
+ end
end
end
+
+end
+
+--[[ldx--
+<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
+and then handle the lot.</p>
+--ldx]]--
+
+function xml.tostring(root) -- 25% overhead due to collecting
+ if root then
+ if type(root) == 'string' then
+ return root
+ elseif next(root) then
+ local result = { }
+ xml.serialize(root,function(s) result[#result+1] = s end)
+ return table.concat(result,"")
+ end
end
+ return ""
+end
+
+--[[ldx--
+<p>The next function operated on the content only and needs a handle function
+that accepts a string.</p>
+--ldx]]--
-function xml.string(e,handle) -- weird one that may become obsolete
- if e.tg then
+function xml.string(e,handle)
+ if not handle or (e.special and e.tg ~= "@rt@") then
+ -- nothing
+ elseif e.tg then
local edt = e.dt
if edt then
for i=1,#edt do
@@ -412,6 +597,21 @@ function xml.string(e,handle) -- weird one that may become obsolete
end
end
+--[[ldx--
+<p>How you deal with saving data depends on your preferences. For a 40 MB database
+file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
+
+<lines>
+1.3 : load data from file to string
+6.1 : convert string into tree
+5.3 : saving in file using xmlsave
+6.8 : converting to string using xml.tostring
+3.6 : saving converted string in file
+</lines>
+
+<p>The save function is given below.</p>
+--ldx]]--
+
function xml.save(root,name)
local f = io.open(name,"w")
if f then
@@ -420,535 +620,67 @@ function xml.save(root,name)
end
end
-function xml.stringify(root)
- if root then
- if type(root) == 'string' then
- return root
- elseif next(root) then
- local result = { }
- xml.serialize(root,function(s) result[#result+1] = s end)
- return table.concat(result,"")
- end
- end
- return ""
-end
-
-xml.tostring = xml.stringify
-
-do
-
- -- print
-
- local newline = lpeg.P("\n")
- local space = lpeg.P(" ")
- local content = lpeg.C((1-newline)^1)
-
- if tex then
-
- -- taco: we need a kind of raw print into tex, i.e. embedded \n's become lineendings
- -- for tex and an empty line a par; could be a c-wrapper around existing stuff; i
- -- played a lot with tex.print but that does not work ok (should be obeylines save)
-
- local buffer = {}
-
- local function cprint(s)
- buffer[#buffer+1] = s
- end
- local function nprint( )
- if #buffer > 0 then
- if xml.trace_print then
- texio.write_nl(string.format("tex.print : [[[%s]]]", table.join(buffer)))
- end
- tex.print(table.join(buffer))
- buffer = {}
- else
- if xml.trace_print then
- texio.write_nl(string.format("tex.print : [[[%s]]]", ""))
- end
- tex.print("")
- end
- end
- local function fprint()
- if #buffer > 0 then
- if xml.trace_print then
- texio.write_nl(string.format("tex.sprint: [[[%s]]]", table.join(buffer)))
- end
- tex.sprint(table.join(buffer))
- buffer = { }
- end
- end
-
- local line_n = newline / nprint
- local line_c = content / cprint
- local capture = (line_n + line_c)^0
-
- local function sprint(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root, sprint, nil, nil, true)
- end
- end
-
- function xml.sprint(root)
- buffer = {}
- sprint(root)
- if #buffer > 0 then
- nprint()
- end
- end
-
- xml.sflush = fprint
-
- else
-
- function xml.sprint(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- print(root)
- elseif next(root) then
- xml.serialize(root, xml.sprint, nil, nil, true)
- end
- end
-
- end
-
- function xml.tprint(root)
- if type(root) == "table" then
- for i=1,#root do
- xml.sprint(root[i])
- end
- elseif type(root) == "string" then
- xml.sprint(root)
- end
- end
-
- -- lines (looks hackery, but we cannot pass variables in capture functions)
-
- local buffer, flush = {}, nil
-
- local function cprint(s)
- buffer[#buffer+1] = s
- end
- local function nprint()
- flush()
- end
-
- local line_n = newline / nprint
- local line_c = content / cprint
- local capture = (line_n + line_c)^0
-
- function lines(root)
- if not root then
- -- quit
- elseif type(root) == 'string' then
- lpeg.match(capture,root)
- elseif next(root) then
- xml.serialize(root, lines)
- end
- end
-
- function xml.lines(root)
- local result = { }
- flush = function()
- result[#result+1] = table.join(buffer)
- buffer = { }
- end
- buffer = {}
- lines(root)
- if #buffer > 0 then
- result[#result+1] = table.join(buffer)
- end
- return result
- end
+--[[ldx--
+<p>A few helpers:</p>
+--ldx]]--
+function xml.body(root)
+ return (root.ri and root.dt[root.ri]) or root
end
function xml.text(root)
- return (root and xml.stringify(root)) or ""
+ return (root and xml.tostring(root)) or ""
end
function xml.content(root)
return (root and root.dt and xml.tostring(root.dt)) or ""
end
-function xml.body(t) -- removes initial pi
- if t and t.dt and t.tg == "@rt@" then
- for k,v in ipairs(t.dt) do
- if type(v) == "table" and v.tg ~= "@pi@" then
- return v
- end
- end
- end
- return t
-end
+--[[ldx--
+<p>The next helper erases an element but keeps the table as it is,
+and since empty strings are not serialized (effectively) it does
+not harm. Copying the table would take more time. Usage:</p>
--- call: e[k] = xml.empty() or xml.empty(e,k)
+<typing>
+dt[k] = xml.empty() or xml.empty(dt,k)
+</typing>
+--ldx]]--
-function xml.empty(e,k) -- erases an element but keeps the table intact
- if e and k then
- e[k] = ""
- return e[k]
+function xml.empty(dt,k)
+ if dt and k then
+ dt[k] = ""
+ return dt[k]
else
return ""
end
end
--- call: e[k] = xml.assign(t) or xml.assign(e,k,t)
+--[[ldx--
+<p>The next helper assigns a tree (or string). Usage:</p>
-function xml.assign(e,k,t) -- assigns xml tree / more testing will be done
- if e and k then
- if type(t) == "table" then
- e[k] = xml.body(t)
- else
- e[k] = t -- no parsing
- end
- return e[k]
+<typing>
+dt[k] = xml.assign(root) or xml.assign(dt,k,root)
+</typing>
+--ldx]]--
+
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k] = (type(root) == "table" and xml.body(root)) or root
+ return dt[k]
else
- return xml.body(t)
+ return xml.body(root)
end
end
--- 0=nomatch 1=match 2=wildcard 3=ancestor
-
--- "tag"
--- "tag1/tag2/tag3"
--- "*/tag1/tag2/tag3"
--- "/tag1/tag2/tag3"
--- "/tag1/tag2|tag3"
--- "tag[@att='value']
--- "tag1|tag2[@att='value']
-
-function xml.tag(e)
- return e.tg or ""
-end
-
-function xml.att(e,a)
- return (e.at and e.at[a]) or ""
-end
-
-xml.attribute = xml.att
-
---~ local cache = { }
-
---~ local function f_fault ( ) return 0 end
---~ local function f_wildcard( ) return 2 end
---~ local function f_result (b) if b then return 1 else return 0 end end
-
---~ function xml.lpath(str) --maybe @rt@ special
---~ if not str or str == "" then
---~ str = "*"
---~ end
---~ local m = cache[str]
---~ if not m then
---~ -- todo: text()
---~ if type(str) == "table" then
---~ if xml.trace_lpath then print("lpath", "table" , "inherit") end
---~ m = str
---~ elseif str == "/" then
---~ if xml.trace_lpath then print("lpath", "/", "root") end
---~ m = false
---~ elseif str == "*" then
---~ if xml.trace_lpath then print("lpath", "no string or *", "wildcard") end
---~ m = true
---~ else
---~ str = str:gsub("^//","") -- any
---~ if str == "" then
---~ if xml.trace_lpath then print("lpath", "//", "wildcard") end
---~ m = true
---~ else
---~ m = { }
---~ if not str:find("^/") then
---~ m[1] = 2
---~ end
---~ for v in str:gmatch("([^/]+)") do
---~ if v == "" or v == "*" then
---~ if #m > 0 then -- when not, then we get problems with root being second (after <?xml ...?> (we could start at dt[2])
---~ if xml.trace_lpath then print("lpath", "empty or *", "wildcard") end
---~ m[#m+1] = 2
---~ end
---~ elseif v == ".." then
---~ if xml.trace_lpath then print("lpath", "..", "ancestor") end
---~ m[#m+1] = 3
---~ else
---~ local a, b = v:match("^(.+)::(.-)$")
---~ if a and b then
---~ if a == "ancestor" then
---~ if xml.trace_lpath then print("lpath", a, "ancestor") end
---~ m[#m+1] = 3
---~ -- todo: b
---~ elseif a == "pi" then
---~ if xml.trace_lpath then print("lpath", a, "processing instruction") end
---~ local expr = "^" .. b .. " "
---~ m[#m+1] = function(e)
---~ if e.tg == '@pi@' and e.dt[1]:find(expr) then
---~ return 6
---~ else
---~ return 0
---~ end
---~ end
---~ end
---~ else
---~ local n, a, t = v:match("^(.-)%[@(.-)=(.-)%]$")
---~ if n and a and t then
---~ -- todo: namespace, negate
---~ -- t = t:gsub("^\'(.*)\'$", "%1")
---~ -- t = t:gsub("^\"(.*)\"$", "%1")
---~ -- t = t:sub(2,-2) -- "" or '' mandate
---~ t = t:gsub("^([\'\"])(.-)%1$", "%2")
---~ if n:find("|") then
---~ local tt = n:split("|")
---~ if xml.trace_lpath then print("lpath", "match", t, n) end
---~ m[#m+1] = function(e,i)
---~ for i=1,#tt do
---~ if e.at and e.tg == tt[i] and e.at[a] == t then return 1 end
---~ end
---~ return 0
---~ end
---~ else
---~ if xml.trace_lpath then print("lpath", "match", t, n) end
---~ m[#m+1] = function(e)
---~ if e.at and e.ns == s and e.tg == n and e.at[a] == t then
---~ return 1
---~ else
---~ return 0
---~ end
---~ end
---~ end
---~ else -- todo, better tracing (string.format, ook negate etc)
---~ local negate = v:sub(1,1) == '^'
---~ if negate then v = v:sub(2) end
---~ if v:find("|") then
---~ local t = { }
---~ for s in v:gmatch("([^|]+)") do
---~ local ns, tg = s:match("^(.-):(.+)$")
---~ if tg == "*" then
---~ if xml.trace_lpath then print("lpath", "or wildcard", ns, tg) end
---~ t[#t+1] = function(e) return e.ns == ns end
---~ elseif tg then
---~ if xml.trace_lpath then print("lpath", "or match", ns, tg) end
---~ t[#t+1] = function(e) return e.ns == ns and e.tg == tg end
---~ else
---~ if xml.trace_lpath then print("lpath", "or match", s) end
---~ t[#t+1] = function(e) return e.ns == "" and e.tg == s end
---~ end
---~ end
---~ if negate then
---~ m[#m+1] = function(e)
---~ for i=1,#t do if t[i](e) then return 0 end end return 1
---~ end
---~ else
---~ m[#m+1] = function(e)
---~ for i=1,#t do if t[i](e) then return 1 end end return 0
---~ end
---~ end
---~ else
---~ if xml.trace_lpath then print("lpath", "match", v) end
---~ local ns, tg = v:match("^(.-):(.+)$")
---~ if not tg then ns, tg = "", v end
---~ if tg == "*" then
---~ if ns ~= "" then
---~ m[#m+1] = function(e)
---~ if ns == e.ns then return 1 else return 0 end
---~ end
---~ end
---~ elseif negate then
---~ m[#m+1] = function(e)
---~ if ns == e.ns and tg == e.tg then return 0 else return 1 end
---~ end
---~ else
---~ m[#m+1] = function(e)
---~ if ns == e.ns and tg == e.tg then return 1 else return 0 end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ if xml.trace_lpath then
---~ print("# lpath criteria:", (type(m) == "table" and #m) or "none")
---~ end
---~ cache[str] = m
---~ end
---~ return m
---~ end
-
---~ -- if handle returns true, then quit
-
---~ function xml.traverse(root,pattern,handle,reverse,index,wildcard)
---~ if not root then -- error
---~ return false
---~ elseif pattern == false then -- root
---~ handle(root,root.dt,root.ri)
---~ return false
---~ elseif pattern == true then -- wildcard
---~ local traverse = xml.traverse
---~ local rootdt = root.dt
---~ if rootdt then
---~ local start, stop, step = 1, #rootdt, 1
---~ if reverse then
---~ start, stop, step = stop, start, -1
---~ end
---~ for k=start,stop,step do
---~ if handle(root,rootdt,root.ri or k) then return false end
---~ if not traverse(rootdt[k],true,handle,reverse) then return false end
---~ end
---~ end
---~ return false
---~ elseif root and root.dt then
---~ index = index or 1
---~ local match = pattern[index] or f_wildcard
---~ local traverse = xml.traverse
---~ local rootdt = root.dt
---~ local start, stop, step = 1, #rootdt, 1
---~ if reverse and index == #pattern then -- maybe no index test here / error?
---~ start, stop, step = stop, start, -1
---~ end
---~ for k=start,stop,step do
---~ local e = rootdt[k]
---~ if e.tg then
---~ local m = (type(match) == "function" and match(e,root)) or match
---~ if m == 1 then -- match
---~ if index < #pattern then
---~ if not traverse(e,pattern,handle,reverse,index+1) then return false end
---~ else
---~ if handle(root,rootdt,root.ri or k) then
---~ return false
---~ end
---~ -- tricky, where do we pick up, is this ok now
---~ if pattern[1] == 2 then -- start again with new root (we need a way to inhibit this)
---~ if not traverse(e,pattern,handle,reverse,1) then return false end
---~ end
---~ end
---~ elseif m == 2 then -- wildcard
---~ if index < #pattern then
---~ -- <parent><a><b></b><c></c></a></parent> : "a" (true) "/a" (true) "b" (true) "/b" (false)
---~ -- not good yet, we need to pick up any prev level which is 2
---~ local p = pattern[2]
---~ if index == 1 and p then
---~ local mm = (type(p) == "function" and p(e,root)) or p -- pattern[2](e,root)
---~ if mm == 1 then
---~ if #pattern == 2 then
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ -- hack
---~ if pattern[1] == 2 then -- start again with new root (we need a way to inhibit this)
---~ if not traverse(e,pattern,handle,reverse,1) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,3) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
---~ end
---~ else
---~ if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
---~ end
---~ elseif handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 3 then -- ancestor
---~ local ep = e.__p__
---~ if index < #pattern then
---~ if not traverse(ep,pattern,handle,reverse,index+1) then return false end
---~ elseif handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 4 then -- just root
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif m == 6 then -- pi
---~ if handle(root,rootdt,k) then
---~ return false
---~ end
---~ elseif wildcard then -- maybe two kind of wildcards: * ** //
---~ if not traverse(e,pattern,handle,reverse,index,wildcard) then return false end
---~ end
---~ end
---~ end
---~ end
---~ return true
---~ end
-
---~ Y a/b
---~ Y /a/b
---~ Y a/*/b
---~ Y a//b
---~ Y child::
---~ Y .//
---~ Y ..
---~ N id("tag")
---~ Y parent::
---~ Y child::
---~ N preceding-sibling:: (same name)
---~ N following-sibling:: (same name)
---~ N preceding-sibling-of-self:: (same name)
---~ N following-sibling-or-self:: (same name)
---~ Y ancestor::
---~ N descendent::
---~ N preceding::
---~ N following::
---~ N self::node()
---~ N node() == alles
---~ N a[position()=5]
---~ Y a[5]
---~ Y a[-5]
---~ N a[first()]
---~ N a[last()]
---~ Y a/(b|c|d)/e/f
---~ N (c/d|e)
---~ Y a/b[@bla]
---~ Y a/b[@bla='oeps']
---~ Y a/b[@bla=='oeps']
---~ Y a/b[@bla<>'oeps']
---~ Y a/b[@bla!='oeps']
---~ Y a/b/@bla
-
---~ Y ^/a/c (root)
---~ Y ^^/a/c (docroot)
---~ Y root::a/c (docroot)
-
---~ no wild card functions (yet)
-
---~ s = "/a//b/*/(c|d|e)/(f|g)/h[4]/h/child::i/j/(a/b)/p[-1]/q[4]/ancestor::q/r/../s/./t[@bla='true']/k"
-
--- // == /**/
--- / = ^ (root)
+--[[ldx--
+<p>We've now arrived at an intersting part: accessing the tree using a subset
+of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
+will explain more about its usage in other documents.</p>
+--ldx]]--
do
- function analyze(str)
- if not str then
- return ""
- else
- local tmp, result, map, key = { }, { }, { }, str
- str = str:gsub("(%b[])", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
- str = str:gsub("(%b())", function(s) tmp[#tmp+1] = s return '[['..#tmp..']]' end)
- str = str:gsub("(%^+)([^/])", "%1/%2")
- str = str:gsub("//+", "/**/")
- str = str:gsub(".*root::", "^/")
- str = str:gsub("child::", "")
- str = str:gsub("ancestor::", "../")
- str = str:gsub("self::", "./")
- str = str:gsub("^/", "^/")
- for s in str:gmatch("([^/]+)") do
- s = s:gsub("%[%[(%d+)%]%]",function(n) return tmp[tonumber(n)] end)
- result[#result+1] = s
- end
- cache[key] = result
- return result
- end
- end
-
- actions = {
+ local actions = {
[10] = "stay",
[11] = "parent",
[12] = "subtree root",
@@ -960,112 +692,186 @@ do
[21] = "match one of",
[22] = "match and attribute eq",
[23] = "match and attribute ne",
- [23] = "match and attribute present",
+ [24] = "match one of and attribute eq",
+ [25] = "match one of and attribute ne",
+ [27] = "has attribute",
+ [28] = "has value",
+ [29] = "fast match",
[30] = "select",
+ [31] = "expression",
[40] = "processing instruction",
}
- function compose(result)
- if not result or #result == 0 then
+ local function make_expression(str)
+ str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')")
+ str = str:gsub("position%(%)", "i")
+ str = str:gsub("text%(%)", "t")
+ str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(")
+ return str, loadstring(string.format("return function(functions,i,a,t) return %s end", str))()
+ end
+
+ local map = { }
+
+ local space = lpeg.S(' \r\n\t')
+ local squote = lpeg.S("'")
+ local dquote = lpeg.S('"')
+ local lparent = lpeg.P('(')
+ local rparent = lpeg.P(')')
+ local atsign = lpeg.P('@')
+ local lbracket = lpeg.P('[')
+ local rbracket = lpeg.P(']')
+ local exclam = lpeg.P('!')
+ local period = lpeg.P('.')
+ local eq = lpeg.P('==') + lpeg.P('=')
+ local ne = lpeg.P('<>') + lpeg.P('!=')
+ local star = lpeg.P('*')
+ local slash = lpeg.P('/')
+ local colon = lpeg.P(':')
+ local bar = lpeg.P('|')
+ local hat = lpeg.P('^')
+ local valid = lpeg.R('az', 'AZ', '09') + lpeg.S('_-')
+ local name_yes = lpeg.C(valid^1) * colon * lpeg.C(valid^1)
+ local name_nop = lpeg.C(lpeg.P(true)) * lpeg.C(valid^1)
+ local name = name_yes + name_nop
+ local number = lpeg.C((lpeg.S('+-')^0 * lpeg.R('09')^1)) / tonumber
+ local names = (bar^0 * name)^1
+ local morenames = name * (bar^0 * name)^1
+ local instructiontag = lpeg.P('pi::')
+ local spacing = lpeg.C(space^0)
+ local somespace = space^1
+ local optionalspace = space^0
+ local text = lpeg.C(valid^0)
+ local value = (squote * lpeg.C((1 - squote)^0) * squote) + (dquote * lpeg.C((1 - dquote)^0) * dquote)
+ local empty = 1-slash
+
+ local is_eq = lbracket * atsign * name * eq * value * rbracket
+ local is_ne = lbracket * atsign * name * ne * value * rbracket
+ local is_attribute = lbracket * atsign * name * rbracket
+ local is_value = lbracket * value * rbracket
+ local is_number = lbracket * number * rbracket
+
+ local nobracket = 1-(lbracket+rbracket) -- must be improved
+ local is_expression = lbracket * lpeg.C(((lpeg.C(nobracket^1))/make_expression)) * rbracket
+
+ local is_expression = lbracket * (lpeg.C(nobracket^1))/make_expression * rbracket
+
+ local is_one = name
+ local is_none = exclam * name
+ local is_one_of = ((lparent * names * rparent) + morenames)
+ local is_none_of = exclam * ((lparent * names * rparent) + morenames)
+
+ local stay = (period )
+ local parent = (period * period ) / function( ) map[#map+1] = { 11 } end
+ local subtreeroot = (slash + hat ) / function( ) map[#map+1] = { 12 } end
+ local documentroot = (hat * hat ) / function( ) map[#map+1] = { 13 } end
+ local any = (star ) / function( ) map[#map+1] = { 14 } end
+ local many = (star * star ) / function( ) map[#map+1] = { 15 } end
+ local initial = (hat * hat * hat ) / function( ) map[#map+1] = { 16 } end
+
+ local match = (is_one ) / function(...) map[#map+1] = { 20, true , ... } end
+ local match_one_of = (is_one_of ) / function(...) map[#map+1] = { 21, true , ... } end
+ local dont_match = (is_none ) / function(...) map[#map+1] = { 20, false, ... } end
+ local dont_match_one_of = (is_none_of ) / function(...) map[#map+1] = { 21, false, ... } end
+
+ local match_and_eq = (is_one * is_eq ) / function(...) map[#map+1] = { 22, true , ... } end
+ local match_and_ne = (is_one * is_ne ) / function(...) map[#map+1] = { 23, true , ... } end
+ local dont_match_and_eq = (is_none * is_eq ) / function(...) map[#map+1] = { 22, false, ... } end
+ local dont_match_and_ne = (is_none * is_ne ) / function(...) map[#map+1] = { 23, false, ... } end
+
+ local match_one_of_and_eq = (is_one_of * is_eq ) / function(...) map[#map+1] = { 24, true , ... } end
+ local match_one_of_and_ne = (is_one_of * is_ne ) / function(...) map[#map+1] = { 25, true , ... } end
+ local dont_match_one_of_and_eq = (is_none_of * is_eq ) / function(...) map[#map+1] = { 24, false, ... } end
+ local dont_match_one_of_and_ne = (is_none_of * is_ne ) / function(...) map[#map+1] = { 25, false, ... } end
+
+ local has_attribute = (is_one * is_attribute) / function(...) map[#map+1] = { 27, true , ... } end
+ local has_value = (is_one * is_value ) / function(...) map[#map+1] = { 28, true , ... } end
+ local dont_has_attribute = (is_none * is_attribute) / function(...) map[#map+1] = { 27, false, ... } end
+ local dont_has_value = (is_none * is_value ) / function(...) map[#map+1] = { 28, false, ... } end
+ local position = (is_one * is_number ) / function(...) map[#map+1] = { 30, true, ... } end
+ local dont_position = (is_none * is_number ) / function(...) map[#map+1] = { 30, false, ... } end
+
+ local expression = (is_one * is_expression)/ function(...) map[#map+1] = { 31, true, ... } end
+ local dont_expression = (is_none * is_expression)/ function(...) map[#map+1] = { 31, false, ... } end
+
+ local instruction = (instructiontag * text ) / function(...) map[#map+1] = { 40, ... } end
+ local nothing = (empty ) / function( ) map[#map+1] = { 15 } end -- 15 ?
+ local crap = (1-slash)^1
+
+ -- a few ugly goodies:
+
+ local docroottag = lpeg.P('^^') / function( ) map[#map+1] = { 12 } end
+ local subroottag = lpeg.P('^') / function( ) map[#map+1] = { 13 } end
+ local roottag = lpeg.P('root::') / function( ) map[#map+1] = { 12 } end
+ local parenttag = lpeg.P('parent::') / function( ) map[#map+1] = { 11 } end
+ local childtag = lpeg.P('child::')
+ local selftag = lpeg.P('self::')
+
+ -- there will be more and order will be optimized
+
+ local selector = (
+ instruction +
+ many + any +
+ parent + stay +
+ dont_position + position +
+ dont_match_one_of_and_eq + dont_match_one_of_and_ne +
+ match_one_of_and_eq + match_one_of_and_ne +
+ dont_match_and_eq + dont_match_and_ne +
+ match_and_eq + match_and_ne +
+ dont_expression + expression +
+ has_attribute + has_value +
+ dont_match_one_of + match_one_of +
+ dont_match + match +
+ crap + empty
+ )
+
+ local grammar = lpeg.P { "startup",
+ startup = (initial + documentroot + subtreeroot + roottag + docroottag + subroottag)^0 * lpeg.V("followup"),
+ followup = ((slash + parenttag + childtag + selftag)^0 * selector)^1,
+ }
+
+ function compose(str)
+ if not str or str == "" then
-- wildcard
return true
- elseif #result == 1 then
- local r = result[1][1]
- if r == "14" or r == "15" then
- -- wildcard
+ elseif str == '/' then
+ -- root
+ return false
+ else
+ map = { }
+ grammar:match(str)
+ if #map == 0 then
return true
- elseif r == "12" then
- -- root
- return false
- end
- end
- local map = { }
- for r=1,#result do
- local ri = result[r]
- if ri == "." then
- -- skip
- elseif ri == ".." then
- map[#map+1] = { 11 }
- elseif ri == "^" then
- map[#map+1] = { 12 }
- elseif ri == "^^" then
- map[#map+1] = { 13 }
- elseif ri == "*" then
- map[#map+1] = { 14 }
- elseif ri == "**" then
- map[#map+1] = { 15 }
else
- local m = ri:match("^%((.*)%)$") -- (a|b|c)
- if m or ri:find('|') then
- m = m or ri
- if m:find("[%[%]%(%)%/]") then -- []()/
- -- error
- else
- local t = { 21 }
- for s in m:gmatch("([^|]+)") do
- local ns, tg = s:match("^(.-):?([^:]+)$")
- t[#t+1] = ns
- t[#t+1] = tg
- end
- map[#map+1] = t
- end
- else
- local s, f = ri:match("^(.-)%[%s*(.+)%s*%]$") --aaa[bbb]
- if s and f then
- local ns, tg = s:match("^(.-):?([^:]+)$")
- local at, op, vl = f:match("^@(.-)([!=<>]?)([^!=<>]+)$") -- [@a=='b']
- if op and op ~= "" then
- if op == '=' or op == '==' then
- map[#map+1] = { 22, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$", "%2")) }
- elseif op == '<>' or op == '!=' then
- map[#map+1] = { 23, ns, tg, at, (vl:gsub("^([\'\"])(.*)%1$", "%2")) }
- else
- -- error
- end
- elseif f:find("^([%-%+%d]+)$")then
- map[#map+1] = { 30, ns, tg, tonumber(f) }
- elseif vl ~= "" then
- map[#map+1] = { 24, ns, tg, vl }
- end
- else
- local pi = ri:match("^pi::(.-)$")
- if pi then
- map[#map+1] = { 40, pi }
- else
- map[#map+1] = { 20, ri:match("^(.-):?([^:]+)$") }
- end
+ local m = map[1][1]
+ if #map == 1 then
+ if m == 14 or m == 15 then
+ -- wildcard
+ return true
+ elseif m == 12 then
+ -- root
+ return false
end
+ elseif #map == 2 and m == 12 and map[2][1] == 20 then
+ return { { 29, map[2][2], map[2][3] } }
end
+ if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
+ table.insert(map, 1, { 16 })
+ end
+ return map
end
end
- -- if we have a symbol, we can prepend that to the string, which is faster
- local mm = map[1] or { }
- local r = mm[1] or 0
- if #map == 1 then
- if r == 14 or r == 15 then
- -- wildcard
- return true
- elseif r == 12 then
- -- root
- return false
- end
- end
- if r ~= 11 and r ~= 12 and r ~= 13 and r ~= 14 and r ~= 15 then
- table.insert(map, 1, { 16 })
- end
- return map
end
- cache = { }
+ local cache = { }
- function xml.lpath(pattern)
+ function xml.lpath(pattern,trace)
if type(pattern) == "string" then
local result = cache[pattern]
if not result then
- result = compose(analyze(pattern))
+ result = compose(pattern)
cache[pattern] = result
end
- if xml.trace_lpath then
+ if trace or xml.trace_lpath then
xml.lshow(result)
end
return result
@@ -1074,23 +880,86 @@ do
end
end
- function xml.lshow(pattern)
+ local fallbackreport = (texio and texio.write) or io.write
+
+ function xml.lshow(pattern,report)
+ report = report or fallbackreport
local lp = xml.lpath(pattern)
if lp == false then
- print("root")
+ report(" -: root\n")
elseif lp == true then
- print("wildcard")
+ report(" -: wildcard\n")
else
- if type(pattern) ~= "table" then
- print("pattern: " .. tostring(pattern))
+ if type(pattern) == "string" then
+ report(string.format("pattern: %s\n",pattern))
end
for k,v in ipairs(lp) do
- print(k,actions[v[1]],table.join(v," ",2))
+ if #v > 1 then
+ local t = { }
+ for i=2,#v do
+ local vv = v[i]
+ if type(vv) == "string" then
+ t[#t+1] = (vv ~= "" and vv) or "#"
+ elseif type(vv) == "boolean" then
+ t[#t+1] = (vv and "==") or "<>"
+ end
+ end
+ report(string.format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," ")))
+ else
+ report(string.format("%2i: %s %s\n", k,v[1],actions[v[1]]))
+ end
+ end
+ end
+ end
+
+ function xml.xshow(e,...) -- also handy when report is given, use () to isolate first e
+ local t = { ... }
+ local report = (type(t[#t]) == "function" and t[#t]) or fallbackreport
+ if not e then
+ report("<!-- no element -->\n")
+ elseif e.tg then
+ report(tostring(e) .. "\n")
+ else
+ for i=1,#e do
+ report(tostring(e[i]) .. "\n")
end
end
end
- function xml.traverse(root,pattern,handle,reverse,index,wildcard)
+end
+
+--[[ldx--
+<p>An <l n='lpath'/> is converted to a table with instructions for traversing the
+tree. Hoever, simple cases are signaled by booleans. Because we don't know in
+advance what we want to do with the found element the handle gets three arguments:</p>
+
+<lines>
+<t>r</t> : the root element of the data table
+<t>d</t> : the data table of the result
+<t>t</t> : the index in the data table of the result
+</lines>
+
+<p> Access to the root and data table makes it possible to construct insert and delete
+functions.</p>
+--ldx]]--
+
+xml.functions = { }
+
+do
+
+ local functions = xml.functions
+
+ functions.contains = string.find
+ functions.find = string.find
+ functions.upper = string.upper
+ functions.lower = string.lower
+ functions.number = tonumber
+ functions.boolean = toboolean
+ functions.oneof = function(s,...) -- slow
+ local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+ end
+
+ function xml.traverse(root,pattern,handle,reverse,index,parent,wildcard)
if not root then -- error
return false
elseif pattern == false then -- root
@@ -1110,103 +979,181 @@ do
end
end
return false
- elseif root and root.dt then
+ elseif root.dt then
index = index or 1
local action = pattern[index]
local command = action[1]
- if (command == 16 or command == 12) and index == 1 then -- initial
- wildcard = true
- index = index + 1
- action = pattern[index]
- command = action[1]
- end
- local traverse = xml.traverse
- local rootdt = root.dt
- local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1
- if command == 30 then
- if action[4] < 0 then
- start, stop, step = stop, start, -1
- dn = -1
+ if command == 29 then -- fast case /oeps
+ local rootdt = root.dt
+ for k=1,#rootdt do
+ local e = rootdt[k]
+ local ns, tg = e.rn or e.ns, e.tg
+ if ns == action[2] and tg == action[3] then
+ if handle(root,rootdt,k) then return false end
+ end
end
- elseif reverse and index == #pattern then
- start, stop, step = stop, start, -1
- end
- for k=start,stop,step do
- local e = rootdt[k]
- local ns, tg = e.ns, e.tg
- if tg then
+ elseif command == 11 then -- parent
+ local ep = root.__p__ or parent
+ if index < #pattern then
+ if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ else
+ if (command == 16 or command == 12) and index == 1 then -- initial
+ wildcard = true
+ index = index + 1
+ action = pattern[index]
+ command = action and action[1] or 0 -- something is wrong
+ end
+ if command == 11 then -- parent
+ local ep = root.__p__ or parent
+ if index < #pattern then
+ if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ else
+ local traverse = xml.traverse
+ local rootdt = root.dt
+ local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1
if command == 30 then
- if ns == action[2] and tg == action[3] then
- n = n + dn
- if n == action[4] then
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- break
- end
- elseif wildcard then
- if not traverse(e,pattern,handle,reverse,index,true) then return false end
+ if action[5] < 0 then
+ start, stop, step = stop, start, -1
+ dn = -1
end
- else
- local matched = false
- if command == 20 then -- match
- matched = ns == action[2] and tg == action[3]
- elseif command == 21 then -- match one of
- for i=2,#action,2 do
- if ns == action[i] and tg == action[i+1] then
- matched = true
- break
+ elseif reverse and index == #pattern then
+ start, stop, step = stop, start, -1
+ end
+ local idx = 0
+ for k=start,stop,step do
+ local e = rootdt[k]
+ local ns, tg = e.rn or e.ns, e.tg
+ if tg then
+ idx = idx + 1
+ if command == 30 then
+ local matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ if matched then
+ n = n + dn
+ if n == action[5] then
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ break
+ end
+ elseif wildcard then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
end
- end
- elseif command == 22 then -- eq
- matched = ns == action[2] and tg == action[3] and e.at[action[4]] == action[5]
- elseif command == 23 then -- ne
- matched = ns == action[2] and tg == action[3] and e.at[action[4]] ~= action[5]
- elseif command == 24 then -- present
- matched = ns == action[2] and tg == action[3] and e.at[action[4]]
- end
- if matched then -- combine tg test and at test
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- elseif command == 14 then -- any
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
else
- if not traverse(e,pattern,handle,reverse,index+1) then return false end
- end
- elseif command == 15 then -- many
- if index == #pattern then
- if handle(root,rootdt,root.ri or k) then return false end
- else
- if not traverse(e,pattern,handle,reverse,index+1,true) then return false end
- end
- elseif command == 11 then -- parent
- local ep = e.__p__
- if index < #pattern then
- if not traverse(ep,pattern,handle,reverse,index+1) then return false end
- elseif handle(root,rootdt,k) then
- return false
- end
- break
- elseif command == 40 and tg == "@pi@" then -- pi
- local pi = action[2]
- if pi ~= "" then
- local pt = e.dt[1]
- if pt and pt:find(pi) then
- if handle(root,rootdt,k) then
+ local matched, multiple = false, false
+ if command == 20 then -- match
+ matched = ns == action[2] and tg == action[3]
+ if not action[2] then matched = not matched end
+ elseif command == 21 then -- match one of
+ multiple = true
+ for i=2,#action,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if not action[2] then matched = not matched end
+ elseif command == 22 then -- eq
+ matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ matched = matched and e.at[action[6]] == action[7]
+ elseif command == 23 then -- ne
+ matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ matched = mached and e.at[action[6]] ~= action[7]
+ elseif command == 24 then -- one of eq
+ multiple = true
+ for i=3,#action-2,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if not action[2] then matched = not matched end
+ matched = matched and e.at[action[#action-1]] == action[#action]
+ elseif command == 25 then -- one of ne
+ multiple = true
+ for i=3,#action-2,2 do
+ if ns == action[i] and tg == action[i+1] then matched = true break end
+ end
+ if not action[2] then matched = not matched end
+ matched = matched and e.at[action[#action-1]] ~= action[#action]
+ elseif command == 27 then -- has attribute
+ local ans = action[3]
+ matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ matched = matched and e.at[action[5]]
+ elseif command == 28 then -- has value
+ local edt = e.dt
+ matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ matched = matched and edt and edt[1] == action[5]
+ elseif command == 31 then
+ local edt = e.dt
+ matched = ns == action[3] and tg == action[4]
+ if not action[2] then matched = not matched end
+ if matched then
+ matched = action[6](functions,idx,e.at,edt[1])
+ end
+ end
+ if matched then -- combine tg test and at test
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ if wildcard and multiple then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
+ end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ elseif command == 14 then -- any
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root) then return false end
+ end
+ elseif command == 15 then -- many
+ if index == #pattern then
+ if handle(root,rootdt,root.ri or k) then return false end
+ else
+ if not traverse(e,pattern,handle,reverse,index+1,root,true) then return false end
+ end
+ -- not here : 11
+ elseif command == 11 then -- parent
+ local ep = e.__p__ or parent
+ if index < #pattern then
+ if not traverse(ep,pattern,handle,reverse,root,index+1) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
+ end
+ elseif command == 40 and e.special and tg == "@pi@" then -- pi
+ local pi = action[2]
+ if pi ~= "" then
+ local pt = e.dt[1]
+ if pt and pt:find(pi) then
+ if handle(root,rootdt,k) then
+ return false
+ end
+ end
+ elseif handle(root,rootdt,k) then
return false
end
+ elseif wildcard then
+ if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
+ end
+ end
+ else
+ -- not here : 11
+ if command == 11 then -- parent
+ local ep = e.__p__ or parent
+ if index < #pattern then
+ if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ elseif handle(root,rootdt,k) then
+ return false
end
- elseif handle(root,rootdt,k) then
- return false
+ break -- else loop
end
- elseif wildcard then
- if not traverse(e,pattern,handle,reverse,index,true) then return false end
end
end
end
@@ -1215,15 +1162,71 @@ do
return true
end
+end
+
+--[[ldx--
+<p>Next come all kind of locators and manipulators. The most generic function here
+is <t>xml.filter(root,pattern)</t>. All registers functions in the filters namespace
+can be path of a search path, as in:</p>
+
+<typing>
+local r, d, k = xml.filter(root,"/a/b/c/position(4)"
+</typing>
+--ldx]]--
+
+do
+
local traverse, lpath, convert = xml.traverse, xml.lpath, xml.convert
xml.filters = { }
+ --[[ldx--
+ <p>For splitting the filter function from the path specification, we can
+ use string matching or lpeg matching. Here the difference in speed is
+ neglectable but the lpeg variant is more robust.</p>
+ --ldx]]--
+
+ -- function xml.filter(root,pattern)
+ -- local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$")
+ -- if fun then
+ -- return (xml.filters[fun] or xml.filters.default)(root,pat,arg)
+ -- else
+ -- pat, arg = pattern:match("^(.+)/@(.-)$")
+ -- if arg then
+ -- return xml.filters.attributes(root,pat,arg)
+ -- else
+ -- return xml.filters.default(root,pattern)
+ -- end
+ -- end
+ -- end
+
+ -- not faster but hipper ... although ... i can't get rid of the trailing / in the path
+
+ local name = (lpeg.R("az","AZ")+lpeg.R("_-"))^1
+ local path = lpeg.C(((1-lpeg.P('/'))^0 * lpeg.P('/'))^1)
+ local argument = lpeg.P { "(" * lpeg.C(((1 - lpeg.S("()")) + lpeg.V(1))^0) * ")" }
+ local action = lpeg.Cc(1) * path * lpeg.C(name) * argument
+ local attribute = lpeg.Cc(2) * path * lpeg.P('@') * lpeg.C(name)
+
+ local parser = action + attribute
+
+ function xml.filter(root,pattern)
+ local kind, a, b, c = parser:match(pattern)
+ if kind == 1 then
+ return (xml.filters[b] or xml.filters.default)(root,a,c)
+ elseif kind == 2 then
+ return xml.filters.attributes(root,a,b)
+ else
+ return xml.filters.default(root,pattern)
+ end
+ end
+
function xml.filters.default(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end)
return dt and dt[dk], rt, dt, dk
end
+
function xml.filters.reverse(root,pattern)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse')
@@ -1277,17 +1280,14 @@ do
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk, i = r, d, k, i-1 return i == 0 end, reverse)
if i == 0 then
return dt and dt[dk], rt, dt, dk
- else
- return nil, nil, nil, nil
end
- else
- return nil, nil, nil, nil
end
+ return nil, nil, nil, nil
end
function xml.filters.attributes(root,pattern,arguments)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
- local ekat = dt and dt[dk] and dt[dk].at
+ local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
if ekat then
if arguments then
return ekat[arguments] or "", rt, dt, dk
@@ -1301,69 +1301,33 @@ do
function xml.filters.attribute(root,pattern,arguments)
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
- local ekat = dt and dt[dk] and dt[dk].at
+ local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
return (ekat and ekat[arguments]) or ""
end
function xml.filters.text(root,pattern,arguments)
- local ek, dt, dk, rt = xml.filters.index(root,pattern,arguments)
- return (ek and ek.dt) or "", rt, dt, dk
- end
-
- function xml.filter(root,pattern)
- local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$")
- if fun then
- return (xml.filters[fun] or xml.filters.default)(root,pat,arg)
- else
- pat, arg = pattern:match("^(.+)/@(.-)$")
- if arg then
- return xml.filters.attributes(root,pat,arg)
+ local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments)
+ if dtk then
+ local dtkdt = dtk.dt
+ if #dtkdt == 1 and type(dtkdt[1]) == "string" then
+ return dtkdt[1], rt, dt, dk
else
- return xml.filters.default(root,pattern)
+ return xml.tostring(dtkdt), rt, dt, dk
end
+ else
+ return "", rt, dt, dk
end
end
- xml.filters.position = xml.filters.index
-
- -- these may go away
-
- xml.index_element = xml.filters.index
- xml.count_elements = xml.filters.count
- xml.first_element = xml.filters.first
- xml.last_element = xml.filters.last
- xml.index_text = xml.filters.text
- xml.first_text = function (root,pattern) return xml.filters.text(root,pattern, 1) end
- xml.last_text = function (root,pattern) return xml.filters.text(root,pattern,-1) end
-
- -- so far
-
- function xml.get_text(root,pattern,reverse)
- local rt, dt, dk
- traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end, reverse)
- local ek = dt and dt[dk]
- return (ek and ek.dt) or "", rt, dt, dk
- end
-
- function xml.each_element(root, pattern, handle, reverse)
- local ok
- traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse)
- return ok
- end
-
- function xml.get_element(root,pattern,reverse)
- local rt, dt, dk
- traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end, reverse)
- return dt and dt[dk], rt, dt, dk
- end
-
- -- these may change
+ --[[ldx--
+ <p>The following functions collect elements and texts.</p>
+ --ldx]]--
- function xml.all_elements(root, pattern, ignorespaces) -- ok?
+ function xml.collect_elements(root, pattern, ignorespaces)
local rr, dd = { }, { }
traverse(root, lpath(pattern), function(r,d,k)
local dk = d and d[k]
if dk then
- if ignorespaces and type(dk) == "string" and dk:find("^[\s\n]*$") then
+ if ignorespaces and type(dk) == "string" and dk:find("^%s*$") then
-- ignore
else
local n = #rr+1
@@ -1374,7 +1338,7 @@ do
return dd, rr
end
- function xml.all_texts(root, pattern, flatten) -- crap
+ function xml.collect_texts(root, pattern, flatten)
local t = { } -- no r collector
traverse(root, lpath(pattern), function(r,d,k)
if d then
@@ -1396,6 +1360,73 @@ do
return t
end
+ --[[ldx--
+ <p>Often using an iterators looks nicer in the code than passing handler
+ functions. The <l n='lua'/> book describes how to use coroutines for that
+ purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
+ code like:</p>
+
+ <typing>
+ for r, d, k in xml.elements(xml.load('text.xml'),"title") do
+ print(d[k])
+ end
+ </typing>
+
+ <p>Which will print all the titles in the document. The iterator variant takes
+ 1.5 times the runtime of the function variant which si due to the overhead in
+ creating the wrapper. So, instead of:</p>
+
+ <typing>
+ function xml.filters.first(root,pattern)
+ for rt,dt,dk in xml.elements(root,pattern)
+ return dt and dt[dk], rt, dt, dk
+ end
+ return nil, nil, nil, nil
+ end
+ </typing>
+
+ <p>We use the function variants in the filters.</p>
+ --ldx]]--
+
+ function xml.elements(root,pattern,reverse)
+ return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
+ end
+
+ function xml.each_element(root, pattern, handle, reverse)
+ local ok
+ traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse)
+ return ok
+ end
+
+ function xml.process_elements(root, pattern, handle)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local dkdt = d[k].dt
+ if dkdt then
+ for i=1,#dkdt do
+ local v = dkdt[i]
+ if v.tg then handle(v) end
+ end
+ end
+ end)
+ end
+
+ function xml.process_attributes(root, pattern, handle)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local ek = d[k]
+ local a = ek.at or { }
+ handle(a)
+ if next(a) then
+ ek.at = a
+ else
+ ek.at = nil
+ end
+ end)
+ end
+
+ --[[ldx--
+ <p>We've now arrives at the functions that manipulate the tree.</p>
+ --ldx]]--
+
function xml.inject_element(root, pattern, element, prepend)
if root and element then
local matches, collect = { }, nil
@@ -1446,7 +1477,7 @@ do
function xml.insert_element(root, pattern, element, before) -- todo: element als functie
if root and element then
if pattern == "/" then
- xml.inject_element(root, pattern, element, before) -- todo: element als functie
+ xml.inject_element(root, pattern, element, before)
else
local matches, collect = { }, nil
if type(element) == "string" then
@@ -1476,8 +1507,6 @@ do
end
end
- -- first, last, each
-
xml.insert_element_after = xml.insert_element
xml.insert_element_before = function(r,p,e) xml.insert_element(r,p,e,true) end
xml.inject_element_after = xml.inject_element
@@ -1508,24 +1537,47 @@ do
end
end
- function xml.process(root, pattern, handle)
- traverse(root, lpath(pattern), function(r,d,k)
- if d[k].dt then
- for k,v in ipairs(d[k].dt) do
- if v.tg then handle(v) end
+ function xml.include(xmldata,element,attribute,pathlist,collapse)
+ element = element or 'ctx:include'
+ attribute = attribute or 'name'
+ pathlist = pathlist or { '.' }
+ -- todo, check op ri
+ local function include(r,d,k)
+ local ek = d[k]
+ local name = (ek.at and ek.at[attribute]) or ""
+ if name ~= "" then
+ -- maybe file lookup in tree
+ local fullname
+ for _, path in ipairs(pathlist) do
+ if path == '.' then
+ fullname = name
+ else
+ fullname = file.join(path,name)
+ end
+ local f = io.open(fullname)
+ if f then
+ xml.assign(d,k,xml.load(f,collapse))
+ f:close()
+ break
+ else
+ xml.empty(d,k)
+ end
end
+ else
+ xml.empty(d,k)
end
- end)
+ end
+ while xml.each_element(xmldata, element, include) do end
end
- function xml.strip(root, pattern)
+ function xml.strip_whitespace(root, pattern)
traverse(root, lpath(pattern), function(r,d,k)
local dkdt = d[k].dt
- if dkdt then
+ if dkdt then -- can be optimized
local t = { }
for i=1,#dkdt do
local str = dkdt[i]
- if type(str) == "string" and str:find("^[\032\010\012\013]*$") then
+ if type(str) == "string" and str:find("^[ \n\r\t]*$") then
-- stripped
else
t[#t+1] = str
@@ -1536,8 +1588,6 @@ do
end)
end
- --
-
function xml.rename_space(root, oldspace, newspace) -- fast variant
local ndt = #root.dt
local rename = xml.rename_space
@@ -1546,6 +1596,9 @@ do
if type(e) == "table" then
if e.ns == oldspace then
e.ns = newspace
+ if e.rn then
+ e.rn = newspace
+ end
end
local edt = e.dt
if edt then
@@ -1565,97 +1618,30 @@ do
d[k].ns = newns
end)
end
-
- -- function xml.process_attributes(root, pattern, handle)
- -- traverse(root, lpath(pattern), function(e,k) handle(e[k].at) end)
- -- end
-
- function xml.process_attributes(root, pattern, handle)
+ function xml.check_namespace(root, pattern, newns)
traverse(root, lpath(pattern), function(r,d,k)
- local ek = d[k]
- local a = ek.at or { }
- handle(a)
- if next(a) then
- ek.at = a
- else
- ek.at = nil
+ local dk = d[k]
+ if (not dk.rn or dk.rn == "") and dk.ns == "" then
+ dk.rn = newns
end
end)
end
-
- function xml.package(tag,attributes,data)
- local n, t = tag:match("^(.-):(.+)$")
- if attributes then
- return { ns = n or "", tg = t or tag, dt = data or "", at = attributes }
- else
- return { ns = n or "", tg = t or tag, dt = data or "" }
- end
- end
-
- -- some special functions, handy for the manual:
-
- function xml.gsub(t,old,new)
- if t.dt then
- for k,v in ipairs(t.dt) do
- if type(v) == "string" then
- t.dt[k] = v:gsub(old,new)
- else
- xml.gsub(v,old,new)
- end
- end
- end
- end
-
---~ function xml.strip_leading_spaces(ek, e, k) -- cosmetic, for manual
---~ if e and k and e[k-1] and type(e[k-1]) == "string" then
---~ local s = e[k-1]:match("\n(%s+)")
---~ xml.gsub(ek,"\n"..string.rep(" ",#s),"\n")
---~ end
---~ end
-
---~ function xml.serialize_path(root,lpath,handle)
---~ local ek, e, k = xml.first_element(root,lpath)
---~ ek = xml.copy(ek)
---~ xml.strip_leading_spaces(ek,e,k)
---~ xml.serialize(ek,handle)
---~ end
-
- function xml.strip_leading_spaces(dk,d,k) -- cosmetic, for manual
- if d and k and d[k-1] and type(d[k-1]) == "string" then
- local s = d[k-1]:match("\n(%s+)")
- xml.gsub(dk,"\n"..string.rep(" ",#s),"\n")
- end
- end
-
- function xml.serialize_path(root,lpath,handle)
- local dk, r, d, k = xml.first(root,lpath)
- dK = xml.copy(dK)
- xml.strip_leading_spaces(dk,d,k)
- xml.serialize(dk,handle)
- end
-
- -- http://www.lua.org/pil/9.3.html (or of course the book)
- --
- -- it's nice to have an iterator but it comes with some extra overhead
- --
- -- for r, d, k in xml.elements(xml.load('text.xml'),"title") do print(d[k]) end
-
- function xml.elements(root,pattern,reverse)
- return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
+ function xml.remap_name(root, pattern, newtg, newns, newrn)
+ traverse(root, lpath(pattern), function(r,d,k)
+ local dk = d[k]
+ dk.tg = newtg
+ dk.ns = newns
+ dk.rn = newrn
+ end)
end
- -- the iterator variant needs 1.5 times the runtime of the function variant
- --
- -- function xml.filters.first(root,pattern)
- -- for rt,dt,dk in xml.elements(root,pattern)
- -- return dt and dt[dk], rt, dt, dk
- -- end
- -- return nil, nil, nil, nil
- -- end
+end
- -- todo xml.gmatch for text
+--[[ldx--
+<p>Here are a few synonyms.</p>
+--ldx]]--
-end
+xml.filters.position = xml.filters.index
xml.count = xml.filters.count
xml.index = xml.filters.index
@@ -1664,7 +1650,10 @@ xml.first = xml.filters.first
xml.last = xml.filters.last
xml.each = xml.each_element
-xml.all = xml.all_elements
+xml.process = xml.process_element
+xml.strip = xml.strip_whitespace
+xml.collect = xml.collect_elements
+xml.all = xml.collect_elements
xml.insert = xml.insert_element_after
xml.inject = xml.inject_element_after
@@ -1673,39 +1662,38 @@ xml.before = xml.insert_element_before
xml.delete = xml.delete_element
xml.replace = xml.replace_element
--- a few helpers, the may move to lxml modules
-
-function xml.include(xmldata,element,attribute,pathlist,collapse)
- element = element or 'ctx:include'
- attribute = attribute or 'name'
- pathlist = pathlist or { '.' }
- -- todo, check op ri
- local function include(r,d,k)
- local ek = d[k]
- local name = (ek.at and ek.at[attribute]) or ""
- if name ~= "" then
- -- maybe file lookup in tree
- local fullname
- for _, path in ipairs(pathlist) do
- if path == '.' then
- fullname = name
- else
- fullname = file.join(path,name)
- end
- local f = io.open(fullname)
- if f then
- xml.assign(d,k,xml.load(f,collapse))
- f:close()
- break
- else
- xml.empty(d,k)
- end
+--[[ldx--
+<p>The following helper functions best belong to the <t>lmxl-ini</t>
+module. Some are here because we need then in the <t>mk</t>
+document and other manuals, others came up when playing with
+this module. Since this module is also used in <l n='mtxrun'/> we've
+put them here instead of loading mode modules there then needed.</p>
+--ldx]]--
+
+function xml.gsub(t,old,new)
+ if t.dt then
+ for k,v in ipairs(t.dt) do
+ if type(v) == "string" then
+ t.dt[k] = v:gsub(old,new)
+ else
+ xml.gsub(v,old,new)
end
- else
- xml.empty(d,k)
end
end
- while xml.each(xmldata, element, include) do end
+end
+
+function xml.strip_leading_spaces(dk,d,k) -- cosmetic, for manual
+ if d and k and d[k-1] and type(d[k-1]) == "string" then
+ local s = d[k-1]:match("\n(%s+)")
+ xml.gsub(dk,"\n"..string.rep(" ",#s),"\n")
+ end
+end
+
+function xml.serialize_path(root,lpath,handle)
+ local dk, r, d, k = xml.first(root,lpath)
+ dk = xml.copy(dk)
+ xml.strip_leading_spaces(dk,d,k)
+ xml.serialize(dk,handle)
end
xml.escapes = { ['&'] = '&amp;', ['<'] = '&lt;', ['>'] = '&gt;', ['"'] = '&quot;' }
@@ -1732,10 +1720,21 @@ function xml.join(t,separator,lastseparator)
end
-do if utf then
+--[[ldx--
+<p>We provide (at least here) two entity handlers. The more extensive
+resolver consults a hash first, tries to convert to <l n='utf'/> next,
+and finaly calls a handler when defines. When this all fails, the
+original entity is returned.</p>
+--ldx]]--
+
+do if unicode and unicode.utf8 then
+
+ xml.entities = xml.entities or { } -- xml.entities.handler == function
+
+ local char = unicode.utf8.char
local function toutf(s)
- return utf.char(tonumber(s,16))
+ return char(tonumber(s,16))
end
function xml.utfize(root)
@@ -1743,22 +1742,67 @@ do if utf then
for k=1,#d do
local dk = d[k]
if type(dk) == "string" then
- d[k] = dk:gsub("&#x(.-);",toutf)
+ -- test prevents copying if no match
+ if dk:find("&#x.-;") then
+ d[k] = dk:gsub("&#x(.-);",toutf)
+ end
else
xml.utfize(dk)
end
end
end
-else
- function xml.utfize()
- print("entity to utf conversion is not available")
+
+ local entities = xml.entities
+
+ local function resolve(e)
+ local e = entities[e]
+ if e then
+ return e
+ elseif e:find("#x") then
+ return char(tonumber(s:sub(3),16))
+ else
+ local h = entities.handler
+ return (h and h(e)) or "&" .. e .. ";"
+ end
end
-end end
+ function xml.resolve_entities(root)
+ local d = root.dt
+ for k=1,#d do
+ local dk = d[k]
+ if type(dk) == "string" then
+ if dk:find("&.-;") then
+ d[k] = dk:gsub("&(.-);",resolve)
+ end
+ else
+ xml.utfize(dk)
+ end
+ end
+ end
---- examples
+end end
---~ for _, e in ipairs(xml.filters.elements(ctxrunner.xmldata,"ctx:message")) do
---~ print(">>>",xml.tostring(e.dt))
---~ end
+--~ xml.lshow("/../../../a/(b|c)[@d='e']/f")
+--~ xml.lshow("/../../../a/!(b|c)[@d='e']/f")
+--~ xml.lshow("/../../../a/!b[@d!='e']/f")
+
+--~ x = xml.convert([[
+--~ <a>
+--~ <b n='01'>01</b>
+--~ <b n='02'>02</b>
+--~ <b n='03'>03</b>
+--~ <b n='04'>OK</b>
+--~ <b n='05'>05</b>
+--~ <b n='06'>06</b>
+--~ <b n='07'>ALSO OK</b>
+--~ </a>
+--~ ]])
+
+--~ xml.trace_lpath = true
+
+--~ xml.xshow(xml.first(x,"b[position() > 2 and position() < 5 and text() == 'ok']"))
+--~ xml.xshow(xml.first(x,"b[position() > 2 and position() < 5 and text() == upper('ok')]"))
+--~ xml.xshow(xml.first(x,"b[@n=='03' or @n=='08']"))
+--~ xml.xshow(xml.all (x,"b[number(@n)>2 and number(@n)<6]"))
+--~ xml.xshow(xml.first(x,"b[find(text(),'ALSO')]"))
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index aa00a8fd1..fad3b22ec 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -6,80 +6,134 @@ if not modules then modules = { } end modules ['lang-ini'] = {
license = "see context related readme files"
}
-languages = languages or { }
-languages.patterns = languages.patterns or { }
-languages.version = 1.009
-languages.template = "words-%s.txt"
-languages.number = nil
-languages.current = nil
-languages.attribute = nil
-
--- We used to have one list: data[word] = pattern but that overflowed lua's function
--- mechanism. Then we split the lists and again we had oveflows. So eventually we
--- ended up with a dedicated reader.
---
--- function languages.set(attribute,number,name)
--- if not languages.patterns[number] then
--- languages.patterns[number] = containers.define("languages","patterns", languages.version, true)
--- end
--- input.start_timing(languages)
--- local data = containers.read(languages.patterns[number],name)
--- if not data then
--- data = { }
--- local fullname = string.format(languages.template,name)
--- local foundname = input.find_file(texmf.instance,fullname,'other text file')
--- if foundname and foundname ~= "" then
--- local ok, blob, size = input.loadbinfile(texmf.instance,foundname)
--- for word in utf.gfind(blob,"(.-)[%s]+") do
--- local key = word:gsub("-","")
--- if key == word then
--- -- skip
--- else
--- data[word:gsub("-","")] = word
--- end
--- end
--- end
--- data = containers.write(languages.patterns[number],name,data)
--- end
--- input.stop_timing(languages)
--- languages.attribute = attribute
--- languages.number = number
--- languages.current = data
--- end
-
-function languages.set(attribute,number,name)
- if not languages.patterns[number] then
+languages = languages or {}
+languages.version = 1.009
+
+languages.hyphenation = languages.hyphenation or {}
+languages.hyphenation.data = languages.hyphenation.data or { }
+
+do
+ -- we can consider hiding data (faster access too)
+
+ local function filter(filename,what)
+ local data = io.loaddata(input.find_file(texmf.instance,filename))
+ local start, stop = data:find(string.format("\\%s%%s*(%%b{})",what or "patterns"))
+ return (start and stop and data:sub(start+1,stop-1)) or ""
+ end
+
+ local function record(tag)
+ local data = languages.hyphenation.data[tag]
+ if not data then
+ data = lang.new()
+ languages.hyphenation.data[tag] = data
+ end
+ return data
+ end
+
+ languages.hyphenation.record = record
+
+ function languages.hyphenation.number(tag)
+ local data = record(tag)
+ return data:id()
+ end
+
+ function languages.hyphenation.load(tag, patterns, exceptions)
+ input.starttiming(languages)
+ local data = record(tag)
+ patterns = (patterns and input.find_file(texmf.instance,patterns )) or ""
+ exceptions = (exceptions and input.find_file(texmf.instance,exceptions)) or ""
+ if patterns ~= "" then
+ data:patterns(filter(patterns,"patterns"))
+ end
+ if exceptions ~= "" then
+ data:exceptions(string.split(filter(exceptions,"hyphenation"),"%s+"))
+ -- local t = { }
+ -- for s in string.gmatch(filter(exceptions,"hyphenation"), "(%S+)") do
+ -- t[#t+1] = s
+ -- end
+ -- print(tag,#t)
+ -- data:exceptions(t)
+ end
+ languages.hyphenation.data[tag] = data
+ input.stoptiming(languages)
+ end
+
+ function languages.hyphenation.exceptions(tag, ...)
+ local data = record(tag)
+ data:exceptions(...)
+ end
+
+ function languages.hyphenation.hyphenate(tag, str)
+ local data = record(tag)
+ return data:hyphenate(str)
+ end
+
+ function languages.hyphenation.lefthyphenmin(tag, value)
+ local data = record(tag)
+ if value then data:lefthyphenmin(value) end
+ return data:lefthyphenmin()
+ end
+ function languages.hyphenation.righthyphenmin(tag, value)
+ local data = record(tag)
+ if value then data:righthyphenmin(value) end
+ return data:righthyphenmin()
+ end
+
+ function languages.n()
+ return table.count(languages.hyphenation.data)
+ end
+
+end
+
+-- beware, the collowing code has to be adapted, and was used in
+-- experiments with loading lists of words; if we keep supporting
+-- this, i will add a namespace; this will happen when the hyphenation
+-- code is in place
+
+languages.dictionary = languages.dictionary or {}
+languages.dictionary.data = languages.dictionary.data or { }
+languages.dictionary.template = "words-%s.txt"
+languages.dictionary.patterns = languages.dictionary.patterns or { }
+
+-- maybe not in dictionary namespace
+
+languages.dictionary.current = nil
+languages.dictionary.number = nil
+languages.dictionary.attribute = nil
+
+function languages.dictionary.set(attribute,number,name)
+ if not languages.dictionary.patterns[number] then
input.start_timing(languages)
- local fullname = string.format(languages.template,name)
+ local fullname = string.format(languages.dictionary.template,name)
local foundname = input.find_file(texmf.instance,fullname,'other text file')
if foundname and foundname ~= "" then
-- texio.write_nl(string.format("loading patterns for language %s as %s from %s",name,number,foundname))
- languages.patterns[number] = tex.load_dict(foundname) or { }
+ languages.dictionary.patterns[number] = tex.load_dict(foundname) or { }
else
- languages.patterns[number] = { }
+ languages.dictionary.patterns[number] = { }
end
input.stop_timing(languages)
end
- languages.attribute = attribute
- languages.number = number
- languages.current = languages.patterns[number]
+ languages.dictionary.attribute = attribute
+ languages.dictionary.number = number
+ languages.dictionary.current = languages.dictionary.patterns[number]
end
-function languages.add(word,pattern)
- if languages.current and word and pattern then
- languages.current[word] = pattern
+function languages.dictionary.add(word,pattern)
+ if languages.dictionary.current and word and pattern then
+ languages.dictionary.current[word] = pattern
end
end
-function languages.remove(word)
- if languages.current and word then
- languages.current[word] = nil
+function languages.dictionary.remove(word)
+ if languages.dictionary.current and word then
+ languages.dictionary.current[word] = nil
end
end
-function languages.hyphenate(str)
- if languages.current then
- local result = languages.current[str]
+function languages.dictionary.hyphenate(str)
+ if languages.dictionary.current then
+ local result = languages.dictionary.current[str]
if result then
return result
else
@@ -89,8 +143,8 @@ function languages.hyphenate(str)
return str
end
-function languages.found(number, str)
- local patterns = languages.patterns[number]
+function languages.dictionary.found(number, str)
+ local patterns = languages.dictionary.patterns[number]
return patterns and patterns[str]
end
@@ -113,7 +167,7 @@ do
if #str < 4 then
-- too short
else
- local wrd = languages.hyphenate(str)
+ local wrd = languages.dictionary.hyphenate(str)
if wrd == str then
-- not found
else
@@ -182,8 +236,8 @@ do
local uc = utf.char
local n, p = head, nil
local done, prev, str, fnt, lan = false, false, "", nil, nil
- local currentlanguage = languages.current
- local att = languages.attribute
+ local currentlanguage = languages.dictionary.current
+ local att, patterns = languages.dictionary.attribute, languages.dictionary.patterns
local function action() -- maybe inline
if reconstruct(prev,str,fnt) then
done = true
@@ -198,12 +252,12 @@ do
if l ~= lan then
if prev then action() end
lan = l
- languages.current = languages.patterns[lan]
+ languages.dictionary.current = patterns[lan]
end
elseif prev then
action()
end
- if not languages.current then
+ if not languages.dictionary.current then
-- skip
elseif n.subtype > 0 then
if not prev then
@@ -236,7 +290,7 @@ do
if prev then
action()
end
- languages.current = currentlanguage
+ languages.dictionary.current = currentlanguage
return head
end
@@ -254,10 +308,11 @@ do
end
str, start, n = "", nil, 0
end
+ local has_attribute = node.has_attribute
while current do
local id = current.id
if id == glyph then
- local a = node.has_attribute(current,attribute)
+ local a = has_attribute(current,attribute)
if a then
if a ~= att then
if start then
@@ -302,7 +357,7 @@ do
return head
end
- function languages.check(head, attribute, yes, nop)
+ function languages.dictionary.check(head, attribute, yes, nop)
local set = node.set_attribute
local unset = node.unset_attribute
local wrong, right = false, false
@@ -311,10 +366,11 @@ do
for n in node.traverse(head) do
unset(n,attribute)
end
- nodes.mark_words(head, languages.attribute, function(att,str)
+ local found = languages.dictionary.found
+ nodes.mark_words(head, languages.dictionary.attribute, function(att,str)
if #str < 4 then
return false
- elseif languages.found(att,str) then
+ elseif found(att,str) then
return right
else
return wrong
@@ -325,3 +381,10 @@ do
end
end
+
+languages.set = languages.dictionary.set
+languages.add = languages.dictionary.add
+languages.remove = languages.dictionary.remove
+languages.hyphenate = languages.dictionary.hyphenate
+languages.found = languages.dictionary.found
+languages.check = languages.dictionary.check
diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv
index e62166966..ac87d85e7 100644
--- a/tex/context/base/lang-ini.mkiv
+++ b/tex/context/base/lang-ini.mkiv
@@ -20,4 +20,9 @@
\def\setnormallanguage #1{\dosetnormallanguage{:\s!default:\s!default:}#1\empty}
\def\setuphyppatencoding {\pathypsettings}
+% temporarily here, awaiting new mechanisms
+
+\def\loadpatternfiles#1{\ctxlua{languages.hyphenation.load('#1', 'lang-#1.pat', 'lang-#1.hyp')}}
+\def\hyphenateword #1{\ctxlua{tex.sprint(languages.hyphenation.hyphenate("\currentlanguage",[[#1]]))}}
+
\protect \endinput
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
index a3bf6cd11..85dbd7033 100644
--- a/tex/context/base/luat-env.lua
+++ b/tex/context/base/luat-env.lua
@@ -4,6 +4,34 @@
-- copyright: PRAGMA ADE / ConTeXt Development Team
-- license : see context related readme files
+--~ do
+--~ local normal_require = require
+--~ local find_lua_file = find_lua_file or kpse.find_file -- you can predefine one
+
+--~ function require(modname,luctoo)
+--~ local file, longfile
+--~ if luctoo then
+--~ file = modname .. '.luc';
+--~ longfile = find_lua_file(file)
+--~ end
+--~ if not longfile then
+--~ file = modname .. '.lua';
+--~ longfile = find_lua_file(file)
+--~ end
+--~ if longfile then
+--~ local dir = longfile:match("^(.+[/\\]).-$")
+--~ local pth = package.path:gsub("\\","/")
+--~ dir = dir:gsub("\\","/")
+--~ if pth:find(dir) then
+--~ package.path = pth -- nicely sanitized
+--~ else
+--~ package.path = pth .. ';' .. dir .. '?.lua' -- dir has trailing /
+--~ end
+--~ normal_require(modname)
+--~ end
+--~ end
+--~ end
+
-- here we don't assume any extra libraries
if not versions then versions = { } end versions['luat-env'] = 1.001
diff --git a/tex/context/base/lxml-ini.lua b/tex/context/base/lxml-ini.lua
index 75ad74ab9..67e1bc75b 100644
--- a/tex/context/base/lxml-ini.lua
+++ b/tex/context/base/lxml-ini.lua
@@ -13,6 +13,121 @@ lxml = { }
lxml.loaded = { }
lxml.self = { }
+do
+
+ local crlf = lpeg.P("\r\n")
+ local cr = lpeg.P("\r")
+ local lf = lpeg.P("\n")
+ local space = lpeg.S(" \t\f\v")
+ local newline = crlf + cr + lf
+ local spacing = space^0 * newline * space^0
+ local content = lpeg.C((1-spacing)^1)
+ local verbose = lpeg.C((1-(space+newline))^1)
+
+ local capture = (
+ newline^2 * lpeg.Cc("") / tex.print +
+ newline * lpeg.Cc(" ") / tex.sprint +
+ content / tex.sprint
+ )^0
+
+ xml.specialhandler = { }
+
+ local function sprint(root)
+ if not root then
+ -- quit
+ elseif type(root) == 'string' then
+ lpeg.match(capture,root)
+ elseif next(root) then
+ xml.serialize(root,sprint,nil,nil,xml.specialhandler)
+ end
+ end
+
+ xml.sprint = sprint
+
+ function xml.tprint(root)
+ if type(root) == "table" then
+ for i=1,#root do
+ sprint(root[i])
+ end
+ elseif type(root) == "string" then
+ sprint(root)
+ end
+ end
+
+ -- lines (untested)
+
+ local buffer = { }
+
+ local capture = (
+ newline^2 / function() buffer[#buffer+1] = "" end +
+ newline / function() buffer[#buffer] = buffer[#buffer] .. " " end +
+ content / function(s) buffer[#buffer] = buffer[#buffer] .. s end
+ )^0
+
+ function lines(root)
+ if not root then
+ -- quit
+ elseif type(root) == 'string' then
+ lpeg.match(capture,root)
+ elseif next(root) then
+ xml.serialize(root, lines)
+ end
+ end
+
+ function xml.lines(root)
+ buffer = { "" }
+ lines(root)
+ return result
+ end
+
+ -- cdata
+
+ local linecommand = "\\obeyedline"
+ local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace"
+ local beforecommand = ""
+ local aftercommand = ""
+
+ local capture = (
+ newline / function( ) tex.sprint(tex.texcatcodes,linecommand .. "{}") end +
+ verbose / function(s) tex.sprint(tex.vrbcatcodes,s) end +
+ space / function( ) tex.sprint(tex.texcatcodes,spacecommand .. "{}") end
+ )^0
+
+ function toverbatim(str)
+ if beforecommand then tex.sprint(tex.texcatcodes,beforecommand .. "{}") end
+ lpeg.match(capture,str)
+ if aftercommand then tex.sprint(tex.texcatcodes,aftercommand .. "{}") end
+ end
+
+ function lxml.set_verbatim(before,after,obeyedline,obeyedspace)
+ beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace
+ end
+
+ function lxml.set_cdata()
+ xml.specialhandler['@cd@'] = toverbatim
+ end
+
+ function lxml.reset_cdata()
+ xml.specialhandler['@cd@'] = nil
+ end
+
+ function lxml.verbatim(id,before,after)
+ local root = lxml.id(id)
+ if before then tex.sprint(tex.ctxcatcodes,string.format("%s[%s]",before,id.tg)) end
+ xml.serialize(root,toverbatim,nil,nil,nil,true)
+ if after then tex.sprint(tex.ctxcatcodes,after) end
+ end
+ function lxml.inlineverbatim(id)
+ lxml.verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
+ end
+ function lxml.displayverbatim(id)
+ lxml.verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
+ end
+
+end
+
+-- now comes the lxml one
+
function lxml.id(id)
return (type(id) == "table" and id) or lxml.loaded[id] or lxml.self[tonumber(id)]
end
@@ -51,11 +166,11 @@ function lxml.last(id,pattern)
end
function lxml.all(id,pattern)
- xml.tprint(xml.all(lxml.id(id),pattern))
+ xml.tprint(xml.collect(lxml.id(id),pattern))
end
function lxml.nonspace(id,pattern)
- xml.tprint(xml.all(lxml.id(id),pattern,true))
+ xml.tprint(xml.collect(lxml.id(id),pattern,true))
end
function lxml.strip(id,pattern)
@@ -63,7 +178,7 @@ function lxml.strip(id,pattern)
end
function lxml.text(id,pattern)
- xml.tprint(xml.all_texts(lxml.id(id),pattern) or {})
+ xml.tprint(xml.collect_texts(lxml.id(id),pattern) or {})
end
function lxml.content(id,pattern)
@@ -90,7 +205,7 @@ end
function lxml.count(id,pattern)
tex.sprint(xml.count(lxml.id(id),pattern) or 0)
end
-function lxml.name(id)
+function lxml.name(id) -- or remapped name?
local r = lxml.id(id)
if r.ns then
tex.sprint(r.ns .. ":" .. r.tg)
@@ -101,23 +216,40 @@ end
function lxml.tag(id)
tex.sprint(lxml.id(id).tg or "")
end
-function lxml.namespace(id)
+function lxml.namespace(id) -- or remapped name?
tex.sprint(lxml.id(id).ns or "")
end
-function lxml.concat(id,what,separator)
- tex.sprint(table.concat(xml.all_texts(lxml.id(id),what,true),separator or ""))
+--~ function lxml.concat(id,what,separator,lastseparator)
+--~ tex.sprint(table.concat(xml.collect_texts(lxml.id(id),what,true),separator or ""))
+--~ end
+
+function lxml.concat(id,what,separator,lastseparator)
+ local t = xml.collect_texts(lxml.id(id),what,true)
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ for i=1,#t do
+ tex.sprint(t[i])
+ if i == #t then
+ -- nothing
+ elseif i == #t-1 and lastseparator ~= "" then
+ tex.sprint(tex.ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ tex.sprint(tex.ctxcatcodes,separator)
+ end
+ end
end
function xml.command(root) -- todo: free self after usage, so maybe hash after all
- xml.sflush()
+ -- no longer needed: xml.sflush()
if type(root.command) == "string" then
local n = #lxml.self + 1
lxml.self[n] = root
if xml.trace_print then
texio.write_nl(string.format("tex.sprint: (((%s:%s)))",n,root.command))
end
- tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,root.command))
+ -- problems with empty elements
+ tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,root.command)) -- no sprint, else spaces go wrong
else
root.command(root)
end
@@ -129,19 +261,25 @@ function lxml.setaction(id,pattern,action)
end
end
+lxml.trace_setups = false
+
function lxml.setsetup(id,pattern,setup)
if not setup or setup == "" or setup == "*" then
for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
- local dtdk = dt[dk]
- if dtdk.ns == "" then
- dtdk.command = dtdk.tg
+ local dtdk = dt and dt[dk] or rt
+ local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg
+ if ns == "" then
+ dtdk.command = tg
else
- dtdk.command = dtdk.ns .. ":" .. dtdk.tg
+ dtdk.command = ns .. ":" .. tg
+ end
+ if lxml.trace_setups then
+ texio.write_nl(string.format("xml setup: namespace=%s, tag=%s, setup=%s",ns, tg, dtdk.command))
end
end
else
for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
- dt[dk].command = setup
+ ((dt and dt[dk]) or rt).command = setup
end
end
end
@@ -155,7 +293,7 @@ function lxml.idx(id,pattern,i)
r.patterns = rp
end
if not rp[pattern] then
- rp[pattern] = xml.all_elements(r,pattern) -- dd, rr
+ rp[pattern] = xml.collect_elements(r,pattern) -- dd, rr
end
local rpi = rp[pattern] and rp[pattern][i]
if rpi then
@@ -166,7 +304,7 @@ end
do
- local traverse = xml.traverse_tree
+ local traverse = xml.traverse
local lpath = xml.lpath
function xml.filters.command(root,pattern,command) -- met zonder ''
@@ -187,9 +325,28 @@ end
do
+ --~ <?xml version="1.0" standalone="yes"?>
+ --~ <!-- demo.cdx -->
+ --~ <directives>
+ --~ <!--
+ --~ <directive attribute='id' value="100" setup="cdx:100"/>
+ --~ <directive attribute='id' value="101" setup="cdx:101"/>
+ --~ -->
+ --~ <!--
+ --~ <directive attribute='cdx' value="colors" element="cals:table" setup="cdx:cals:table:colors"/>
+ --~ <directive attribute='cdx' value="vertical" element="cals:table" setup="cdx:cals:table:vertical"/>
+ --~ <directive attribute='cdx' value="noframe" element="cals:table" setup="cdx:cals:table:noframe"/>
+ --~ -->
+ --~ <directive attribute='cdx' value="*" element="cals:table" setup="cdx:cals:table:*"/>
+ --~ </directives>
+
lxml.directives = { }
- local data = { }
+ local data = {
+ setup = { },
+ before = { },
+ after = { }
+ }
function lxml.directives.load(filename)
if texmf then
@@ -199,23 +356,63 @@ do
end
end
local root = xml.load(filename)
+ local format = string.format
for r, d, k in xml.elements(root,"directive") do
local dk = d[k]
local at = dk.at
- local id, setup = at.id, at.setup
- if id and setup then
- data[id] = setup
+ local attribute, value, element = at.attribute or "", at.value or "", at.element or '*'
+ local setup, before, after = at.setup or "", at.before or "", at.after or ""
+ if attribute ~= "" and value ~= "" then
+ local key = format("%s::%s::%s",element,attribute,value)
+ local t = data[key] or { }
+ if setup ~= "" then t.setup = setup end
+ if before ~= "" then t.before = before end
+ if after ~= "" then t.after = after end
+ data[key] = t
end
end
end
- function lxml.directives.setups(root)
+ function lxml.directives.setup(root,attribute,element)
+ lxml.directives.handle_setup('setup',root,attribute,element)
+ end
+ function lxml.directives.before(root,attribute,element)
+ lxml.directives.handle_setup('before',root,attribute,element)
+ end
+ function lxml.directives.after(root,attribute,element)
+ lxml.directives.handle_setup('after',root,attribute,element)
+ end
+
+ function lxml.directives.handle_setup(category,root,attribute,element)
root = lxml.id(root)
- local id = root.at.id
- if id then
- local setup = data[id]
- if setup then
- tex.sprint(tex.ctxcatcodes,string.format("\\directsetup{%s}",setup))
+ attribute = attribute
+ if attribute then
+ local value = root.at[attribute]
+ if value then
+ if not element then
+ local ns, tg = root.rn or root.ns, root.tg
+ if ns == "" then
+ element = tg
+ else
+ element = ns .. ':' .. tg
+ end
+ end
+ local format = string.format
+ local setup = data[format("%s::%s::%s",element,attribute,value)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup))
+ else
+ setup = data[format("%s::%s::*",element,attribute)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup:gsub('%*',value)))
+ end
+ end
end
end
end
@@ -232,3 +429,8 @@ function lxml.loadbuffer(id,name)
input.stop_timing(lxml)
return lxml.loaded[id], name or id
end
+
+-- for the moment here:
+
+lxml.set_verbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
+lxml.set_cdata()
diff --git a/tex/context/base/lxml-ini.tex b/tex/context/base/lxml-ini.tex
index c9d79060f..0df2d302f 100644
--- a/tex/context/base/lxml-ini.tex
+++ b/tex/context/base/lxml-ini.tex
@@ -40,13 +40,15 @@
\def\xmlattribute #1#2#3{\ctxlua{lxml.attribute("#1","#2","#3")}}
\def\xmlatt #1#2{\ctxlua{lxml.attribute("#1","/","#2")}}
\def\xmlattdef #1#2#3{\ctxlua{lxml.attribute("#1","/","#2","#3")}}
-\def\xmlconcat #1#2#3{\ctxlua{lxml.concat("#1","#2","#3")}}
+\def\xmlconcat #1#2#3{\ctxlua{lxml.concat("#1","#2",[[\detokenize{#3}]])}}
\def\xmlsetsetup #1#2#3{\ctxlua{lxml.setsetup("#1","#2","#3")}}
\def\xmlsetfunction#1#2#3{\ctxlua{lxml.setaction("#1","#2",#3)}}
\def\xmlloaddirectives #1{\ctxlua{lxml.directives.load("#1")}}
\def\xmldirectives #1{\ctxlua{lxml.directives.setups("#1")}}
-\def\xmlregisterns #1#2{\ctxlua{xml.registerns("#1","#2")}}
+\def\xmlregisterns #1#2{\ctxlua{xml.registerns("#1","#2")}} % document
+\def\xmlchecknamespace#1#2#3{\ctxlua{xml.check_namespace(lxml.id("#1"),"#2","#3")}} % element
+\def\xmlremapname #1#2#3#4{\ctxlua{xml.remapname(lxml.id("#1"),"#2","#3","#4")}} % element
\let\xmlgrab\xmlsetsetup
@@ -57,7 +59,7 @@
\newtoks \registeredxmlsetups
\def\xmlregistersetup#1%
- {\appendtoks\directsetup{#1}\to\registeredxmlsetups}
+ {\appendtoksonce\directsetup{#1}\to\registeredxmlsetups}
\def\xmlregisteredsetups
{\the\registeredxmlsetups}
@@ -98,6 +100,39 @@
}
\fi}
+\def\xmlcdataobeyedline {\obeyedline}
+\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\def\xmlcdatabefore {\bgroup\tt}
+\def\xmlcdataafter {\egroup x}
+
+% verbatim (dodo:pre/post whitespace, maybe splot verbatim and
+% cdata commands), experimental:
+%
+% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim}
+% \xmlsetfunction{main}{verb} {lxml.inlineverbatim}
+
+% \def\startxmldisplayverbatim[#1]{}
+% \def\stopxmldisplayverbatim {}
+% \def\startxmlinlineverbatim [#1]{}
+% \def\stopxmlinlineverbatim {}
+
+\def\startxmldisplayverbatim[#1]%
+ {\begingroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{#1}%
+ \def\stopxmldisplayverbatim
+ {\endofverbatimlines
+ \endgroup}%
+ \mkinitializeverbatim
+ \beginofverbatimlines}
+
+\def\startxmlinlineverbatim[#1]%
+ {\begingroup
+ \let\currenttypingclass\??ty
+ \edef\currenttyping{#1}%
+ \let\stopxmldisplayverbatim\endgroup
+ \mkinitializeverbatim}
+
% will move but is developed for xml
\newtoks \collectingtoks
diff --git a/tex/context/base/meta-ini.tex b/tex/context/base/meta-ini.tex
index ad2037b9e..4831967ef 100644
--- a/tex/context/base/meta-ini.tex
+++ b/tex/context/base/meta-ini.tex
@@ -83,11 +83,11 @@
defaultscale:=\the\bodyfontsize/10pt;
\stopMPinitializations
-\beginLUATEX
+\beginNEWTEX
\startMPinitializations % scale is not yet ok
defaultfont:="rm-lmtt10";
\stopMPinitializations
-\endLUATEX
+\endNEWTEX
%D In order to support fancy text features (like outline
%D fonts), we set:
diff --git a/tex/context/base/meta-tex.tex b/tex/context/base/meta-tex.tex
index 75aeb54c7..616a2513c 100644
--- a/tex/context/base/meta-tex.tex
+++ b/tex/context/base/meta-tex.tex
@@ -130,9 +130,8 @@
\newbox\mptextbox
-%definefontsynonym[MPtxtfont][texnansi-lmtt10] \loadmapfile[texnansi-public-lm.map]
-\definefontsynonym[MPtxtfont][texnansi-lmtt10] \loadmapfile[lm-texnansi.map]
-
+% \loadmapfile[lm-texnansi.map] % the font is not really used, i.e. nothing ends up in the file
+\definefontsynonym[MPtxtfont][texnansi-lmtt10]
\definefont[localMPtxtfont][MPtxtfont at 10bp]
\ifx\getTeXtext\undefined
diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex
index 744858eea..f4f8aa5a7 100644
--- a/tex/context/base/mult-sys.tex
+++ b/tex/context/base/mult-sys.tex
@@ -204,6 +204,7 @@
\definesystemconstant {entrya}
\definesystemconstant {entryb}
\definesystemconstant {entryc}
+\definesystemconstant {entryd}
\definesystemconstant {entry}
\definesystemconstant {see}
\definesystemconstant {from}
diff --git a/tex/context/base/regi-ini.mkii b/tex/context/base/regi-ini.mkii
index 7c0850b90..e7c2a6792 100644
--- a/tex/context/base/regi-ini.mkii
+++ b/tex/context/base/regi-ini.mkii
@@ -15,24 +15,39 @@
%D Plugs into the common interface.
-\def\mkloadregime#1%
- {\makeshortfilename[\truefilename{\f!regimeprefix#1}]%
- \startreadingfile
- \readsysfile\shortfilename
- {\showmessage\m!regimes2{#1}}
- {\showmessage\m!regimes3{#1}}%
- \stopreadingfile}
+\beginOLDTEX
-\def\mkenableregime#1%
- {\the\executeifdefined{\@reg@#1}\emptytoks}
+ \def\mkloadregime#1%
+ {\makeshortfilename[\truefilename{\f!regimeprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename
+ {\showmessage\m!regimes2{#1}}
+ {\showmessage\m!regimes3{#1}}%
+ \stopreadingfile}
-\def\mkwalkregime#1%
- {\the\executeifdefined{\@reg@\currentregime}\emptytoks}
+ \def\mkenableregime#1%
+ {\the\executeifdefined{\@reg@#1}\emptytoks}
-\def\mkautosetregime#1#2%
- {\ifnum#2>127
- \expanded{\defineactivetoken #2 \@EA\noexpand\csname#1\endcsname}%
- \fi}
+ \def\mkwalkregime#1%
+ {\the\executeifdefined{\@reg@\currentregime}\emptytoks}
+
+ \def\mkautosetregime#1#2%
+ {\ifnum#2>127
+ \expanded{\defineactivetoken #2 \@EA\noexpand\csname#1\endcsname}%
+ \fi}
+
+\endOLDTEX
+
+\beginXETEX
+
+ \let\mkloadregime \gobbleoneargument
+ \let\mkenableregime \gobbleoneargument
+ \let\mkwalkregime \gobbleoneargument
+ \let\mkautosetregime\gobbletwoarguments
+
+ \def\mkenableregime#1{\XeTeXinputencoding "#1"\relax}
+
+\endXETEX
%D Remark: regimes accumulate, so there is no explicit reset in
%D mkii mode.
@@ -148,6 +163,10 @@
%D Preloading:
-\useregime[def,uni,utf] % we load the rest runtime
+\beginOLDTEX
+
+ \useregime[def,uni,utf] % we load the rest runtime
+
+\endOLDTEX
\protect \endinput
diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex
index 698d54a41..614895f2d 100644
--- a/tex/context/base/s-abr-01.tex
+++ b/tex/context/base/s-abr-01.tex
@@ -57,7 +57,7 @@
\logo [CWEB] {cweb}
\logo [DANTE] {Dante}
\logo [DISTILLER] {distiller}
-\logo [DRATEX] {Dra\TeX}
+\logo [DRATEX] {Dra\TeX}
\logo [DSC] {dsc}
\logo [DTD] {dtd}
\logo [DTK] {dtk}
diff --git a/tex/context/base/s-pre-64.tex b/tex/context/base/s-pre-64.tex
new file mode 100644
index 000000000..b1204f169
--- /dev/null
+++ b/tex/context/base/s-pre-64.tex
@@ -0,0 +1,201 @@
+%D \module
+%D [ file=s-pre-64,
+%D version=2006.05.11,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Presentation Environment 64,
+%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.
+
+% To be documented, used in 2007
+
+\usemodule[s][pre-60]
+
+\newcounter\shapesynctag
+\newdimen\slantedshapedimen
+\newdimen\slantedshapestep
+\newdimen\slantedshapeleftskip
+\newdimen\slantedshapeoffset
+\newdimen\slantedshapeextra
+
+\positioningtrue
+
+\def\AdaptShape
+ {\doglobal\increment\shapesynctag
+ \getnoflines\textheight
+ \slantedshapestep\dimexpr\slantedshapeleftskip/\noflines\relax
+ \leftskip\slantedshapeleftskip
+ \scratchdimen\dimexpr\MPy{text:\MPp\shapesynctag}+\MPh{text:\MPp\shapesynctag}-\topskip-\MPy\shapesynctag\relax
+ \advance\scratchdimen\slantedshapeextra
+ \getnoflines\scratchdimen
+ \slantedshapedimen \noflines \slantedshapestep
+ \scratchtoks\emptytoks
+ \dorecurse{30}
+ {\appendetoks
+ \the\dimexpr-\slantedshapedimen+\slantedshapeoffset \relax\space
+ \the\dimexpr \hsize-2\slantedshapeoffset\relax\space
+ \to\scratchtoks
+ \advance\slantedshapedimen \slantedshapestep}%
+ \parshape 30 \the\scratchtoks
+ \strut\xypos\shapesynctag}
+
+\def\AdaptShapeX
+ {\doglobal\increment\shapesynctag
+ \getnoflines\textheight
+ \slantedshapestep\dimexpr\slantedshapeleftskip/\noflines\relax
+ \leftskip\slantedshapeleftskip
+ \scratchdimen\dimexpr\MPy{text:\MPp\shapesynctag}+\MPh{text:\MPp\shapesynctag}-\topskip-\MPy\shapesynctag\relax
+ \advance\scratchdimen\slantedshapeextra
+ \getnoflines\scratchdimen
+ \slantedshapedimen \noflines \slantedshapestep
+ \scratchtoks\emptytoks
+ \dorecurse{30}
+ {\appendetoks
+ \the\dimexpr-\slantedshapedimen+\slantedshapeoffset +5cm \relax\space
+ \the\dimexpr \hsize-2\slantedshapeoffset\relax\space
+ \to\scratchtoks
+ \advance\slantedshapedimen \slantedshapestep}%
+ \parshape 30 \the\scratchtoks
+ \strut\xypos\shapesynctag}
+
+\setuppapersize[S6][S6]
+
+\setupinteraction
+ [state=start,
+ click=no]
+
+\setupinteractionscreen
+ [option=max]
+
+\setuplayout
+ [backspace=12pt,
+ topspace=24pt,
+ height=middle,
+ width=middle,
+ header=0pt,
+ footer=0pt]
+
+\definecolor[maincolor][b=.5]
+\definecolor[somecolor][g=.5]
+\definecolor[morecolor][r=.5]
+
+\setupcolors
+ [textcolor=maincolor,
+ state=start]
+
+\setupbackgrounds
+ [text]% [text]
+ [background={base,text,invoke}]
+
+\definelayer
+ [text]
+ [width=\textwidth,
+ height=\textheight]
+
+\definelayer
+ [base]
+ [width=\textwidth,
+ height=\textheight]
+
+\definetype [epet] [style=,color=morecolor]
+\setuptype [style=,color=somecolor]
+
+\slantedshapeleftskip150pt
+\slantedshapeoffset12pt
+\slantedshapeextra10pt
+
+\startreusableMPgraphic{page}
+ StartPage ;
+ fill Page withcolor \MPcolor{maincolor} ;
+ path p ; p := Field[Text][Text] enlarged 6pt ;
+ p :=
+ llcorner p shifted (0,-12pt) --
+ lrcorner p shifted (-150pt,0) --
+ urcorner p shifted (0,12pt) --
+ ulcorner p shifted (150pt,0) --
+ cycle ;
+ fill p
+ withcolor .9white ;
+ StopPage ;
+\stopreusableMPgraphic
+
+\defineoverlay[page][\reuseMPgraphic{page}]
+\setupbackgrounds[page][background=page]
+
+\setupalign[flushleft]
+
+\def\StartItem
+ {\blank[line]
+ \begingroup
+ \EveryPar {\AdaptShape}}
+
+\def\StopItem
+ {\endgraf
+ \endgroup
+ \blank[line]}
+
+\def\StartType
+ {\blank[halfline]
+ \begingroup
+ \EveryPar {\AdaptShape}
+ \dontleavehmode \quad}
+
+\def\StopType
+ {\endgraf
+ \endgroup
+ \blank[halfline]}
+
+\def\Title#1%
+ {\page
+ \setlayer
+ [text]
+ [preset=lefttop,
+ rotation=90]
+ {\color[white]{\scale[height=24pt]{\strut#1}}}}
+
+\def\SetBanner#1%
+ {\setuplayer[base][state=repeat]
+ \setlayer[base][preset=rightbottom]{\color[white]{\scale[height=9pt]{\strut#1}}}}
+
+\startmode[atpragma]
+ \definefontfeature[default][method=node,script=latn,language=dflt,liga=yes,onum=yes,kern=yes]
+ \definedfont[palatinosanscom-regular*default at 12pt] \setupinterlinespace[line=15pt]
+ \definefont[titlefont][palatinosanscom-bold*default at 48pt]
+\stopmode
+
+\endinput
+
+% \starttext
+
+% \SetBanner{tug 2007 san diego}
+
+% \Title {hans hagen}
+
+% \startstandardmakeup \titlefont \setupinterlinespace[line=3ex] \vfill
+
+% \StartItem \dontleavehmode \quad {\morecolor zapfino, a} \StopItem
+% \StartItem \dontleavehmode \quad {\morecolor torture test} \StopItem
+% \StartItem \dontleavehmode \quad {\morecolor for luatex} \StopItem
+
+% \vfill \stopstandardmakeup
+
+% \Title{loading fonts}
+
+% \StartSteps
+
+% \StartItem the \OPENTYPE\ font reader is borrowed from \FONTFORGE\ \FlushStep \StopItem
+% \StartItem once it was ready, we could look into such a font \FlushStep \StopItem
+% \StartItem it tooks while to figure out the format due to rather fuzzy specs \FlushStep \StopItem
+% \StartItem it took us even more time to find out that the loader was flawed \FlushStep \StopItem
+% \StartItem one reason was that fonts themselves may have bugs or be incomplete \FlushStep \StopItem
+% \StartItem then we changed to \FONTFORGE\ version 2 \FlushStep \StopItem
+% \StartItem this made the missing pieces surface in more complex feature handling \FlushStep \StopItem
+% \StartItem while implementing features the new table format was cleaned up \FlushStep \StopItem
+
+% \StopSteps
+
+% \stoptext
diff --git a/tex/context/base/spec-mis.tex b/tex/context/base/spec-mis.tex
index 743091bbe..c85498127 100644
--- a/tex/context/base/spec-mis.tex
+++ b/tex/context/base/spec-mis.tex
@@ -101,7 +101,7 @@
% \def\doiffileinsertionsupportedelse#1%
% {\expanded{\doifinstringelse{#1}{\c!tex,\c!tmp,\supportedfileinsertions}}}
-\def\doiffileinsertionsupportedelse#1%
+\def\doiffileinsertionsupportedelse#1% lowercasing happens at tex end
{\expanded{\doifinstringelse{\truegraphictype{#1}}{\c!tex,\c!tmp,\supportedfileinsertions}}}
%D This macro is called with 10 arguments, where the first
diff --git a/tex/context/base/spec-tpd.tex b/tex/context/base/spec-tpd.tex
index 37926efb5..068ac8dfe 100644
--- a/tex/context/base/spec-tpd.tex
+++ b/tex/context/base/spec-tpd.tex
@@ -312,9 +312,8 @@
\ifx\temp\empty
\exitloop
\else
- \let\filesuffix\temp
+ \lowercasestring\temp\to\filesuffix % insertion check also needs lowercase
% a temporary hack
- \doif\filesuffix{PDF}{\pdfimageresolution72}%
\doif\filesuffix{pdf}{\pdfimageresolution72}%
% because pdfTeX scales back
\fi}}
diff --git a/tex/context/base/toks-ini.lua b/tex/context/base/toks-ini.lua
index cf313ceb3..d39188215 100644
--- a/tex/context/base/toks-ini.lua
+++ b/tex/context/base/toks-ini.lua
@@ -72,18 +72,39 @@ function collectors.register(name)
collectors.registered[token.csname_id(name)] = name
end
+--~ function collectors.install(tag,end_cs)
+--~ collectors.data[tag] = { }
+--~ local data = collectors.data[tag]
+--~ local call = token.command_id("call")
+--~ local relax = token.command_id("relax")
+--~ local endcs = token.csname_id(end_cs)
+--~ local expand = collectors.registered
+--~ local get = token.get_next -- so no callback!
+--~ while true do
+--~ local t = get()
+--~ local a, b = t[1], t[3]
+--~ if a == relax and b == endcs then
+--~ return
+--~ elseif a == call and expand[b] then
+--~ token.expand()
+--~ else
+--~ data[#data+1] = t
+--~ end
+--~ end
+--~ end
+
function collectors.install(tag,end_cs)
collectors.data[tag] = { }
local data = collectors.data[tag]
local call = token.command_id("call")
- local relax = token.command_id("relax")
local endcs = token.csname_id(end_cs)
local expand = collectors.registered
- local get = token.get_next -- so no callback!
+ local get = token.get_next
while true do
local t = get()
local a, b = t[1], t[3]
- if a == relax and b == endcs then
+ if b == endcs then
+ tex.print('\\' ..end_cs)
return
elseif a == call and expand[b] then
token.expand()
@@ -93,6 +114,13 @@ function collectors.install(tag,end_cs)
end
end
+function collectors.handle(tag,handle,flush)
+ collectors.data[tag] = handle(collectors.data[tag])
+ if flush then
+ collectors.flush(tag)
+ end
+end
+
collectors.show_methods = { }
function collectors.show(tag, method)
@@ -228,5 +256,68 @@ collectors.show_methods.b_c = function(data,swap) -- no need to store the table,
flush(ct, "\\stoptabulate")
end
+-- Even more experimental ...
+
collectors.show_methods.b = function(tag) collectors.show_methods.b_c(tag,false) end
collectors.show_methods.c = function(tag) collectors.show_methods.b_c(tag,true ) end
+
+collectors.remapper = {
+ -- namespace
+}
+
+collectors.remapper.data = {
+ -- user mappings
+}
+
+function collectors.remapper.store(tag,class,key)
+ local s = collectors.remapper.data[class]
+ if not s then
+ s = { }
+ collectors.remapper.data[class] = s
+ end
+ s[key] = collectors.data[tag]
+ collectors.data[tag] = nil
+end
+
+function collectors.remapper.convert(tag,toks)
+ local data = collectors.remapper.data[tag]
+ local leftbracket, rightbracket = utf.byte('['), utf.byte(']')
+ local skipping = 0
+ -- todo: math
+ if data then
+ local t = { }
+ for s=1,#toks do
+ local tok = toks[s]
+ local one, two = tok[1], tok[2]
+ if one == 11 or one == 12 then
+ if two == leftbracket then
+ skipping = skipping + 1
+ t[#t+1] = tok
+ elseif two == rightbracket then
+ skipping = skipping - 1
+ t[#t+1] = tok
+ elseif skipping == 0 then
+ local new = data[two]
+ if new then
+ if #new > 1 then
+ for n=1,#new do
+ t[#t+1] = new[n]
+ end
+ else
+ t[#t+1] = new[1]
+ end
+ else
+ t[#t+1] = tok
+ end
+ else
+ t[#t+1] = tok
+ end
+ else
+ t[#t+1] = tok
+ end
+ end
+ return t
+ else
+ return toks
+ end
+end
diff --git a/tex/context/base/toks-ini.tex b/tex/context/base/toks-ini.tex
index d3aa9cb5d..48c3d920d 100644
--- a/tex/context/base/toks-ini.tex
+++ b/tex/context/base/toks-ini.tex
@@ -15,6 +15,10 @@
\registerctxluafile{toks-ini}{1.001}
+\unprotect
+
+%D Handy for manuals \unknown
+
\def\starttokens [#1]{\ctxlua{collectors.install("#1", "stoptokens")}}
\let\stoptokens \relax
\def\flushtokens [#1]{\ctxlua{collectors.flush("#1")}}
@@ -22,4 +26,51 @@
\def\testtokens [#1]{\ctxlua{collectors.with_words("#1")}}
\def\registertoken #1{\ctxlua{collectors.register("#1")}}
-\endinput
+%D Inspired by a prototype by Taco for Thomas cum suis.
+
+% \defineremapper[babelgreek]
+%
+% \remapcharacter[babelgreek][`a]{\alpha}
+% \remapcharacter[babelgreek][`b]{\beta}
+% \remapcharacter[babelgreek][`c]{\gamma}
+% \remapcharacter[babelgreek][`d]{OEPS}
+%
+% \starttext
+%
+% [\startbabelgreek
+% a b c some stuff here \blank[big] oeps b d
+% \stopbabelgreek]
+%
+% [\babelgreek{some stuff here}]
+%
+% \stoptext
+
+\def\dograbuntil#1#2%
+ {\long\def\next##1#1{#2##1}\next}
+
+\def\grabuntil#1%
+ {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}}
+
+\def\dostartremapper#1%
+ {\ctxlua{collectors.install("#1", "\e!stop#1")}}
+
+\def\dostopremapper#1%
+ {\ctxlua{collectors.handle("#1",function(str) return collectors.remapper.convert("#1",str) end, true)}}
+
+\def\remaptokens#1%
+ {\ctxlua{collectors.handle("#1",function(str) return collectors.remapper.convert("#1",str) end)}}
+
+\def\defineremapper[#1]%
+ {\setvalue{\e!start#1}{\dostartremapper{#1}}%
+ \setvalue{\e!stop #1}{\dostopremapper {#1}}%
+ \def\next##1{\setvalue{#1}####1{\getvalue{\e!start#1}####1##1}}%
+ \expandafter\next\csname\e!stop#1\endcsname}
+
+\def\remapcharacter
+ {\dodoubleempty\doremapcharacter}
+
+\def\doremapcharacter[#1][#2]#3%
+ {\ctxlua{collectors.install("store", "ctxlua")}#3%
+ \ctxlua{collectors.remapper.store("store","#1",\number#2)}}
+
+\protect \endinput
diff --git a/tex/context/base/type-one.tex b/tex/context/base/type-one.tex
index 09ffc748b..b724466a8 100644
--- a/tex/context/base/type-one.tex
+++ b/tex/context/base/type-one.tex
@@ -156,64 +156,74 @@
\stoptypescript
\starttypescript [serif] [modern,latin-modern] [texnansi,ec,qx,t5]
- \definefontsynonym [LMRoman10-DemiOblique] [\typescriptthree-lmbo10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-Bold] [\typescriptthree-lmbx10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman12-Bold] [\typescriptthree-lmbx12] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman5-Bold] [\typescriptthree-lmbx5] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman6-Bold] [\typescriptthree-lmbx6] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman7-Bold] [\typescriptthree-lmbx7] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman8-Bold] [\typescriptthree-lmbx8] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman9-Bold] [\typescriptthree-lmbx9] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-BoldItalic] [\typescriptthree-lmbxi10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-BoldOblique] [\typescriptthree-lmbxo10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-CapsRegular] [\typescriptthree-lmcsc10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-CapsOblique] [\typescriptthree-lmcsco10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-Regular] [\typescriptthree-lmr10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman12-Regular] [\typescriptthree-lmr12] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman17-Regular] [\typescriptthree-lmr17] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman5-Regular] [\typescriptthree-lmr5] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman6-Regular] [\typescriptthree-lmr6] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman7-Regular] [\typescriptthree-lmr7] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman8-Regular] [\typescriptthree-lmr8] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman9-Regular] [\typescriptthree-lmr9] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-Italic] [\typescriptthree-lmri10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman12-Italic] [\typescriptthree-lmri12] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman7-Italic] [\typescriptthree-lmri7] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman8-Italic] [\typescriptthree-lmri8] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman9-Italic] [\typescriptthree-lmri9] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman10-Oblique] [\typescriptthree-lmro10] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman12-Oblique] [\typescriptthree-lmro12] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman17-Oblique] [\typescriptthree-lmro17] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman8-Oblique] [\typescriptthree-lmro8] [encoding=\typescriptthree]
- \definefontsynonym [LMRoman9-Oblique] [\typescriptthree-lmro9] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman5-Regular] [\typescriptthree-lmr5] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman6-Regular] [\typescriptthree-lmr6] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman7-Regular] [\typescriptthree-lmr7] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman8-Regular] [\typescriptthree-lmr8] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman9-Regular] [\typescriptthree-lmr9] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-Regular] [\typescriptthree-lmr10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman12-Regular] [\typescriptthree-lmr12] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman17-Regular] [\typescriptthree-lmr17] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman5-Bold] [\typescriptthree-lmbx5] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman6-Bold] [\typescriptthree-lmbx6] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman7-Bold] [\typescriptthree-lmbx7] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman8-Bold] [\typescriptthree-lmbx8] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman9-Bold] [\typescriptthree-lmbx9] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-Bold] [\typescriptthree-lmbx10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman12-Bold] [\typescriptthree-lmbx12] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman7-Italic] [\typescriptthree-lmri7] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman8-Italic] [\typescriptthree-lmri8] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman9-Italic] [\typescriptthree-lmri9] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-Italic] [\typescriptthree-lmri10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman12-Italic] [\typescriptthree-lmri12] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-BoldItalic] [\typescriptthree-lmbxi10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman8-Oblique] [\typescriptthree-lmro8] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman9-Oblique] [\typescriptthree-lmro9] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-Oblique] [\typescriptthree-lmro10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman12-Oblique] [\typescriptthree-lmro12] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman17-Oblique] [\typescriptthree-lmro17] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-BoldOblique] [\typescriptthree-lmbxo10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-Demi] [\typescriptthree-lmb10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-DemiOblique] [\typescriptthree-lmbo10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-CapsRegular] [\typescriptthree-lmcsc10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-CapsOblique] [\typescriptthree-lmcsco10] [encoding=\typescriptthree]
+
+ \definefontsynonym [LMRoman10-Dunhill] [\typescriptthree-lmdunh10] [encoding=\typescriptthree]
+ \definefontsynonym [LMRoman10-DunhillOblique] [\typescriptthree-lmduno10] [encoding=\typescriptthree]
\loadmapfile[lm-\typescriptthree.map]
\stoptypescript
\starttypescript [sans] [modern,latin-modern] [texnansi,ec,qx,t5]
+ \definefontsynonym [LMSans8-Regular] [\typescriptthree-lmss8] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans9-Regular] [\typescriptthree-lmss9] [encoding=\typescriptthree]
\definefontsynonym [LMSans10-Regular] [\typescriptthree-lmss10] [encoding=\typescriptthree]
\definefontsynonym [LMSans12-Regular] [\typescriptthree-lmss12] [encoding=\typescriptthree]
\definefontsynonym [LMSans17-Regular] [\typescriptthree-lmss17] [encoding=\typescriptthree]
- \definefontsynonym [LMSans8-Regular] [\typescriptthree-lmss8] [encoding=\typescriptthree]
- \definefontsynonym [LMSans9-Regular] [\typescriptthree-lmss9] [encoding=\typescriptthree]
- \definefontsynonym [LMSans10-BoldOblique] [\typescriptthree-lmssbo10] [encoding=\typescriptthree]
\definefontsynonym [LMSans10-Bold] [\typescriptthree-lmssbx10] [encoding=\typescriptthree]
- \definefontsynonym [LMSans10-DemiCondensed] [\typescriptthree-lmssdc10] [encoding=\typescriptthree]
- \definefontsynonym [LMSans10-DemiCondensedOblique] [\typescriptthree-lmssdo10] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans8-Oblique] [\typescriptthree-lmsso8] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans9-Oblique] [\typescriptthree-lmsso9] [encoding=\typescriptthree]
\definefontsynonym [LMSans10-Oblique] [\typescriptthree-lmsso10] [encoding=\typescriptthree]
\definefontsynonym [LMSans12-Oblique] [\typescriptthree-lmsso12] [encoding=\typescriptthree]
\definefontsynonym [LMSans17-Oblique] [\typescriptthree-lmsso17] [encoding=\typescriptthree]
- \definefontsynonym [LMSans8-Oblique] [\typescriptthree-lmsso8] [encoding=\typescriptthree]
- \definefontsynonym [LMSans9-Oblique] [\typescriptthree-lmsso9] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans10-BoldOblique] [\typescriptthree-lmssbo10] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans10-DemiCondensed] [\typescriptthree-lmssdc10] [encoding=\typescriptthree]
+ \definefontsynonym [LMSans10-DemiCondensedOblique] [\typescriptthree-lmssdo10] [encoding=\typescriptthree]
\definefontsynonym [LMSansQuotation8-Regular] [\typescriptthree-lmssq8] [encoding=\typescriptthree]
- \definefontsynonym [LMSansQuotation8-BoldOblique] [\typescriptthree-lmssqbo8] [encoding=\typescriptthree]
\definefontsynonym [LMSansQuotation8-Bold] [\typescriptthree-lmssqbx8] [encoding=\typescriptthree]
\definefontsynonym [LMSansQuotation8-Oblique] [\typescriptthree-lmssqo8] [encoding=\typescriptthree]
+ \definefontsynonym [LMSansQuotation8-BoldOblique] [\typescriptthree-lmssqbo8] [encoding=\typescriptthree]
\loadmapfile[lm-\typescriptthree.map]
\stoptypescript
\starttypescript [mono] [modern,latin-modern,modern-vari,latin-modern-vari,modern-cond,latin-modern-cond] [texnansi,ec,qx,t5]
+ \definefontsynonym [LMTypewriter8-Regular] [\typescriptthree-lmtt8] [encoding=\typescriptthree]
+ \definefontsynonym [LMTypewriter9-Regular] [\typescriptthree-lmtt9] [encoding=\typescriptthree]
+ \definefontsynonym [LMTypewriter10-Regular] [\typescriptthree-lmtt10] [encoding=\typescriptthree]
+ \definefontsynonym [LMTypewriter12-Regular] [\typescriptthree-lmtt12] [encoding=\typescriptthree]
+ \definefontsynonym [LMTypewriter10-Italic] [\typescriptthree-lmtti10] [encoding=\typescriptthree]
+ \definefontsynonym [LMTypewriter10-Oblique] [\typescriptthree-lmtto10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriter10-CapsRegular] [\typescriptthree-lmtcsc10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriter10-CapsOblique] [\typescriptthree-lmtcso10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriter10-Light] [\typescriptthree-lmtl10] [encoding=\typescriptthree]
@@ -222,12 +232,8 @@
\definefontsynonym [LMTypewriter10-LightCondensedOblique] [\typescriptthree-lmtlco10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriter10-Dark] [\typescriptthree-lmtk10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriter10-DarkOblique] [\typescriptthree-lmtko10] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter10-Regular] [\typescriptthree-lmtt10] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter12-Regular] [\typescriptthree-lmtt12] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter8-Regular] [\typescriptthree-lmtt8] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter9-Regular] [\typescriptthree-lmtt9] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter10-Italic] [\typescriptthree-lmtti10] [encoding=\typescriptthree]
- \definefontsynonym [LMTypewriter10-Oblique] [\typescriptthree-lmtto10] [encoding=\typescriptthree]
+
+ \definefontsynonym [LMTypewriter10-Unslanted] [\typescriptthree-lmu10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriterVarWd10-Regular] [\typescriptthree-lmvtt10] [encoding=\typescriptthree]
\definefontsynonym [LMTypewriterVarWd10-Oblique] [\typescriptthree-lmvtto10] [encoding=\typescriptthree]
@@ -733,43 +739,43 @@
% \stoptypescript
\starttypescript [serif] [antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond] [texnansi,qx,t5,ec,t2a,t2b,t2c,greek]
+ \definefontsynonym [AntykwaTorunska-Regular] [\typescriptthree-anttr] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-Italic] [\typescriptthree-anttri] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-Bold] [\typescriptthree-anttb] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-BoldItalic] [\typescriptthree-anttbi] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-Light] [\typescriptthree-anttl] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-LightItalic] [\typescriptthree-anttli] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-Medium] [\typescriptthree-anttm] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-MedItalic] [\typescriptthree-anttmi] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-Regular] [\typescriptthree-anttr] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-Italic] [\typescriptthree-anttri] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-CondRegular] [\typescriptthree-anttcr] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-CondItalic] [\typescriptthree-anttcri] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondBold] [\typescriptthree-anttcb] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondBoldItalic] [\typescriptthree-anttcbi] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondLight] [\typescriptthree-anttcl] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondLightItalic][\typescriptthree-anttcli] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondMedium] [\typescriptthree-anttcm] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondMedItalic] [\typescriptthree-anttcmi] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-CondRegular] [\typescriptthree-anttcr] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-CondItalic] [\typescriptthree-anttcri] [encoding=\typescriptthree]
\loadmapfile[antt-\typescriptthree.map]
\stoptypescript
\starttypescript [serif] [antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond] [texnansi,qx,t5,ec]
+ \definefontsynonym [AntykwaTorunska-Cap] [\typescriptthree-anttrcap] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-ItalicCap] [\typescriptthree-anttricap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-BoldCap] [\typescriptthree-anttbcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-BoldItalicCap] [\typescriptthree-anttbicap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-LightCap] [\typescriptthree-anttlcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-LightItalicCap] [\typescriptthree-anttlicap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-MediumCap] [\typescriptthree-anttmcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-MedItalicCap] [\typescriptthree-anttmicap] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-Cap] [\typescriptthree-anttrcap] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-ItalicCap] [\typescriptthree-anttricap] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-CondCap] [\typescriptthree-anttcrcap] [encoding=\typescriptthree]
+ \definefontsynonym [AntykwaTorunska-CondItalicCap] [\typescriptthree-anttcricap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondBoldCap] [\typescriptthree-anttcbcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [\typescriptthree-anttcbicap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondLightCap] [\typescriptthree-anttclcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondLightItalicCap][\typescriptthree-anttclicap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondMediumCap] [\typescriptthree-anttcmcap] [encoding=\typescriptthree]
\definefontsynonym [AntykwaTorunska-CondMedItalicCap] [\typescriptthree-anttcmicap] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-CondCap] [\typescriptthree-anttcrcap] [encoding=\typescriptthree]
- \definefontsynonym [AntykwaTorunska-CondItalicCap] [\typescriptthree-anttcricap] [encoding=\typescriptthree]
\loadmapfile[antt-\typescriptthree.map]
\stoptypescript
@@ -824,7 +830,7 @@
\starttypescript [math] [antykwa-torunska] [default]
\definefontsynonym [AntykwaTorunska-Math-Letters-Regular] [rm-anttr]
- \definefontsynonym [AntykwaTorunska-Math-Letters-RegularItalic] [mi-anttri]
+ \definefontsynonym [AntykwaTorunska-Math-Letters-Italic] [mi-anttri]
\definefontsynonym [AntykwaTorunska-Math-Symbols-Regular] [sy-anttrz]
\definefontsynonym [AntykwaTorunska-Math-Extension-Regular] [ex-anttr]
\stoptypescript
@@ -838,7 +844,7 @@
\starttypescript [math] [antykwa-torunska-cond] [default]
\definefontsynonym [AntykwaTorunska-Math-Letters-CondRegular] [rm-anttcr]
- \definefontsynonym [AntykwaTorunska-Math-Letters-CondRegularItalic] [mi-anttcri]
+ \definefontsynonym [AntykwaTorunska-Math-Letters-CondItalic] [mi-anttcri]
\definefontsynonym [AntykwaTorunska-Math-Symbols-CondRegular] [sy-anttcrz]
\definefontsynonym [AntykwaTorunska-Math-Extension-CondRegular] [ex-anttcr]
\stoptypescript
@@ -873,77 +879,78 @@
% maybe this will change in Iwona-Math-Letters and Iwona-Math-Letters-Italic
\starttypescript [sans] [iwona-light,iwona,iwona-medium,iwona-heavy,iwona-light-cond,iwona-cond,iwona-medium-cond,iwona-heavy-cond] [texnansi,ec,el,qx,t5]
- \definefontsynonym[Iwona-Light] [\typescriptthree-iwonal] [encoding=\typescriptthree]
+
\definefontsynonym[Iwona-Regular] [\typescriptthree-iwonar] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-Medium] [\typescriptthree-iwonam] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Italic] [\typescriptthree-iwonari] [encoding=\typescriptthree]
\definefontsynonym[Iwona-Bold] [\typescriptthree-iwonab] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-Heavy] [\typescriptthree-iwonah] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-LightItalic] [\typescriptthree-iwonali] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-RegularItalic] [\typescriptthree-iwonari] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-MediumItalic] [\typescriptthree-iwonami] [encoding=\typescriptthree]
\definefontsynonym[Iwona-BoldItalic] [\typescriptthree-iwonabi] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-HeavyItalic] [\typescriptthree-iwonahi] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Light-Regular] [\typescriptthree-iwonal] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Light-Italic] [\typescriptthree-iwonali] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Medium-Regular] [\typescriptthree-iwonam] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Medium-Italic] [\typescriptthree-iwonami] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Heavy-Regular] [\typescriptthree-iwonah] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-Heavy-Italic] [\typescriptthree-iwonahi] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsLight] [\typescriptthree-iwonalcap] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CapsRegular] [\typescriptthree-iwonarcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsMedium] [\typescriptthree-iwonamcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsItalic] [\typescriptthree-iwonaricap] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CapsBold] [\typescriptthree-iwonabcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsHeavy] [\typescriptthree-iwonahcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsLightItalic] [\typescriptthree-iwonalicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsRegularItalic] [\typescriptthree-iwonaricap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsMediumItalic] [\typescriptthree-iwonamicap] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CapsBoldItalic] [\typescriptthree-iwonabicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CapsHeavyItalic] [\typescriptthree-iwonahicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsLight-Regular] [\typescriptthree-iwonalcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsLight-Italic] [\typescriptthree-iwonalicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsMedium-Regular] [\typescriptthree-iwonamcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsMedium-Italic] [\typescriptthree-iwonamicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsHeavy-Regular] [\typescriptthree-iwonahcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsHeavy-Italic] [\typescriptthree-iwonahicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondLight] [\typescriptthree-iwonacl] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CondRegular] [\typescriptthree-iwonacr] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondMedium] [\typescriptthree-iwonacm] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondItalic] [\typescriptthree-iwonacri] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CondBold] [\typescriptthree-iwonacb] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondHeavy] [\typescriptthree-iwonach] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondLightItalic] [\typescriptthree-iwonacli] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondRegularItalic] [\typescriptthree-iwonacri] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondMediumItalic] [\typescriptthree-iwonacmi] [encoding=\typescriptthree]
\definefontsynonym[Iwona-CondBoldItalic] [\typescriptthree-iwonacbi] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondHeavyItalic] [\typescriptthree-iwonachi] [encoding=\typescriptthree]
-
- \definefontsynonym[Iwona-CondCapsLight] [\typescriptthree-iwonaclcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsRegular] [\typescriptthree-iwonacrcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsMedium] [\typescriptthree-iwonacmcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsBold] [\typescriptthree-iwonacbcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsHeavy] [\typescriptthree-iwonachcap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsLightItalic] [\typescriptthree-iwonaclicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsRegularItalic] [\typescriptthree-iwonacricap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsMediumItalic] [\typescriptthree-iwonacmicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsBoldItalic] [\typescriptthree-iwonacbicap] [encoding=\typescriptthree]
- \definefontsynonym[Iwona-CondCapsHeavyItalic] [\typescriptthree-iwonachicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondLight-Regular] [\typescriptthree-iwonacl] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondLight-Italic] [\typescriptthree-iwonacli] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondMedium-Regular] [\typescriptthree-iwonacm] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondMedium-Italic] [\typescriptthree-iwonacmi] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondHeavy-Regular] [\typescriptthree-iwonach] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CondHeavy-Italic] [\typescriptthree-iwonachi] [encoding=\typescriptthree]
+
+ \definefontsynonym[Iwona-CapsCondRegular] [\typescriptthree-iwonacrcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondItalic] [\typescriptthree-iwonacricap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondBold] [\typescriptthree-iwonacbcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondBoldItalic] [\typescriptthree-iwonacbicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondLight-Regular] [\typescriptthree-iwonaclcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondLight-Italic] [\typescriptthree-iwonaclicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondMedium-Regular][\typescriptthree-iwonacmcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondMedium-Italic] [\typescriptthree-iwonacmicap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondHeavy-Regular] [\typescriptthree-iwonachcap] [encoding=\typescriptthree]
+ \definefontsynonym[Iwona-CapsCondHeavy-Italic] [\typescriptthree-iwonachicap] [encoding=\typescriptthree]
\loadmapfile[iwona-\typescriptthree.map]
\stoptypescript
\starttypescript [math] [iwona] [default]
\definefontsynonym [Iwona-Math-Letters-Regular] [rm-iwonar]
- \definefontsynonym [Iwona-Math-Letters-RegularItalic] [mi-iwonari]
+ \definefontsynonym [Iwona-Math-Letters-Italic] [mi-iwonari]
\definefontsynonym [Iwona-Math-Symbols-Regular] [sy-iwonarz]
\definefontsynonym [Iwona-Math-Extension-Regular] [ex-iwonar]
\stoptypescript
\starttypescript [math] [iwona-light] [default]
- \definefontsynonym [Iwona-Math-Letters-Light] [rm-iwonal]
- \definefontsynonym [Iwona-Math-Letters-LightItalic] [mi-iwonali]
+ \definefontsynonym [Iwona-Math-Letters-Light-Regular] [rm-iwonal]
+ \definefontsynonym [Iwona-Math-Letters-Light-Italic] [mi-iwonali]
\definefontsynonym [Iwona-Math-Symbols-Light] [sy-iwonalz]
\definefontsynonym [Iwona-Math-Extension-Light] [ex-iwonal]
\stoptypescript
\starttypescript [math] [iwona-medium] [default]
- \definefontsynonym [Iwona-Math-Letters-Medium] [rm-iwonam]
- \definefontsynonym [Iwona-Math-Letters-MediumItalic] [mi-iwonami]
+ \definefontsynonym [Iwona-Math-Letters-Medium-Regular][rm-iwonam]
+ \definefontsynonym [Iwona-Math-Letters-Medium-Italic] [mi-iwonami]
\definefontsynonym [Iwona-Math-Symbols-Medium] [sy-iwonamz]
\definefontsynonym [Iwona-Math-Extension-Medium] [ex-iwonam]
\stoptypescript
\starttypescript [math] [iwona-heavy] [default]
- \definefontsynonym [Iwona-Math-Letters-Heavy] [rm-iwonah]
- \definefontsynonym [Iwona-Math-Letters-HeavyItalic] [mi-iwonahi]
+ \definefontsynonym [Iwona-Math-Letters-Heavy-Regular] [rm-iwonah]
+ \definefontsynonym [Iwona-Math-Letters-Heavy-Italic] [mi-iwonahi]
\definefontsynonym [Iwona-Math-Symbols-Heavy] [sy-iwonahz]
\definefontsynonym [Iwona-Math-Extension-Heavy] [ex-iwonah]
\stoptypescript
@@ -958,37 +965,37 @@
% Kurier (JMN)
\starttypescript [sans] [kurier-light,kurier,kurier-medium] [texnansi,ec,qx,t5]
- \definefontsynonym[Kurier-Light] [\typescriptthree-kurierl] [encoding=\typescriptthree]
\definefontsynonym[Kurier-Regular] [\typescriptthree-kurierr] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-Medium] [\typescriptthree-kurierm] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Italic] [\typescriptthree-kurierri] [encoding=\typescriptthree]
\definefontsynonym[Kurier-Bold] [\typescriptthree-kurierb] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-Heavy] [\typescriptthree-kurierh] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-LightItalic] [\typescriptthree-kurierli] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-RegularItalic] [\typescriptthree-kurierri] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-MediumItalic] [\typescriptthree-kuriermi] [encoding=\typescriptthree]
\definefontsynonym[Kurier-BoldItalic] [\typescriptthree-kurierbi] [encoding=\typescriptthree]
- \definefontsynonym[Kurier-HeavyItalic] [\typescriptthree-kurierhi] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Light-Regular] [\typescriptthree-kurierl] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Light-Italic] [\typescriptthree-kurierli] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Medium-Regular][\typescriptthree-kurierm] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Medium-Italic] [\typescriptthree-kuriermi] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Heavy-Regular] [\typescriptthree-kurierh] [encoding=\typescriptthree]
+ \definefontsynonym[Kurier-Heavy-Italic] [\typescriptthree-kurierhi] [encoding=\typescriptthree]
\loadmapfile[kurier-\typescriptthree.map]
\stoptypescript
\starttypescript [math] [kurier] [default]
\definefontsynonym [Kurier-Math-Letters-Regular] [rm-kurierr]
- \definefontsynonym [Kurier-Math-Letters-RegularItalic] [mi-kurierri]
+ \definefontsynonym [Kurier-Math-Letters-Italic] [mi-kurierri]
\definefontsynonym [Kurier-Math-Symbols-Regular] [sy-kurierrz]
\definefontsynonym [Kurier-Math-Extension-Regular] [ex-kurierr]
\stoptypescript
\starttypescript [math] [kurier-light] [default]
- \definefontsynonym [Kurier-Math-Letters-Light] [rm-kurierl]
- \definefontsynonym [Kurier-Math-Letters-LightItalic] [mi-kurierli]
+ \definefontsynonym [Kurier-Math-Letters-Light-Regular] [rm-kurierl]
+ \definefontsynonym [Kurier-Math-Letters-Light-Italic] [mi-kurierli]
\definefontsynonym [Kurier-Math-Symbols-Light] [sy-kurierlz]
\definefontsynonym [Kurier-Math-Extension-Light] [ex-kurierl]
\stoptypescript
\starttypescript [math] [kurier-medium] [default]
- \definefontsynonym [Kurier-Math-Letters-Medium] [rm-kurierm]
- \definefontsynonym [Kurier-Math-Letters-MediumItalic] [mi-kuriermi]
+ \definefontsynonym [Kurier-Math-Letters-Medium-Regular][rm-kurierm]
+ \definefontsynonym [Kurier-Math-Letters-Medium-Italic] [mi-kuriermi]
\definefontsynonym [Kurier-Math-Symbols-Medium] [sy-kuriermz]
\definefontsynonym [Kurier-Math-Extension-medium] [ex-kurierm]
\stoptypescript
diff --git a/tex/context/base/type-otf.tex b/tex/context/base/type-otf.tex
index d1de4bd10..7bfd1ee02 100644
--- a/tex/context/base/type-otf.tex
+++ b/tex/context/base/type-otf.tex
@@ -100,80 +100,91 @@
\starttypescriptcollection[opentype]
\starttypescript [serif] [modern,latin-modern]
- \definefontsynonym [LMRoman10-DemiOblique] [lmroman10-demioblique] [features=default]
- \definefontsynonym [LMRoman10-Bold] [lmroman10-bold] [features=default]
- \definefontsynonym [LMRoman12-Bold] [lmroman12-bold] [features=default]
- \definefontsynonym [LMRoman5-Bold] [lmroman5-bold] [features=default]
- \definefontsynonym [LMRoman6-Bold] [lmroman6-bold] [features=default]
- \definefontsynonym [LMRoman7-Bold] [lmroman7-bold] [features=default]
- \definefontsynonym [LMRoman8-Bold] [lmroman8-bold] [features=default]
- \definefontsynonym [LMRoman9-Bold] [lmroman9-bold] [features=default]
- \definefontsynonym [LMRoman10-BoldItalic] [lmroman10-bolditalic] [features=default]
- \definefontsynonym [LMRoman10-BoldOblique] [lmroman10-boldoblique] [features=default]
- \definefontsynonym [LMRoman10-CapsRegular] [lmroman10-capsregular] [features=default]
- \definefontsynonym [LMRoman10-CapsOblique] [lmroman10-capsoblique] [features=default]
- \definefontsynonym [LMRoman10-Regular] [lmroman10-regular] [features=default]
- \definefontsynonym [LMRoman12-Regular] [lmroman12-regular] [features=default]
- \definefontsynonym [LMRoman17-Regular] [lmroman17-regular] [features=default]
- \definefontsynonym [LMRoman5-Regular] [lmroman5-regular] [features=default]
- \definefontsynonym [LMRoman6-Regular] [lmroman6-regular] [features=default]
- \definefontsynonym [LMRoman7-Regular] [lmroman7-regular] [features=default]
- \definefontsynonym [LMRoman8-Regular] [lmroman8-regular] [features=default]
- \definefontsynonym [LMRoman9-Regular] [lmroman9-regular] [features=default]
- \definefontsynonym [LMRoman10-Italic] [lmroman10-italic] [features=default]
- \definefontsynonym [LMRoman12-Italic] [lmroman12-italic] [features=default]
- \definefontsynonym [LMRoman7-Italic] [lmroman7-italic] [features=default]
- \definefontsynonym [LMRoman8-Italic] [lmroman8-italic] [features=default]
- \definefontsynonym [LMRoman9-Italic] [lmroman9-italic] [features=default]
- \definefontsynonym [LMRoman10-Oblique] [lmroman10-oblique] [features=default]
- \definefontsynonym [LMRoman12-Oblique] [lmroman12-oblique] [features=default]
- \definefontsynonym [LMRoman17-Oblique] [lmroman17-oblique] [features=default]
- \definefontsynonym [LMRoman8-Oblique] [lmroman8-oblique] [features=default]
- \definefontsynonym [LMRoman9-Oblique] [lmroman9-oblique] [features=default]
+ \definefontsynonym [LMRoman5-Regular] [file:lmroman5-regular] [features=default]
+ \definefontsynonym [LMRoman6-Regular] [file:lmroman6-regular] [features=default]
+ \definefontsynonym [LMRoman7-Regular] [file:lmroman7-regular] [features=default]
+ \definefontsynonym [LMRoman8-Regular] [file:lmroman8-regular] [features=default]
+ \definefontsynonym [LMRoman9-Regular] [file:lmroman9-regular] [features=default]
+ \definefontsynonym [LMRoman10-Regular] [file:lmroman10-regular] [features=default]
+ \definefontsynonym [LMRoman12-Regular] [file:lmroman12-regular] [features=default]
+ \definefontsynonym [LMRoman17-Regular] [file:lmroman17-regular] [features=default]
+ \definefontsynonym [LMRoman5-Bold] [file:lmroman5-bold] [features=default]
+ \definefontsynonym [LMRoman6-Bold] [file:lmroman6-bold] [features=default]
+ \definefontsynonym [LMRoman7-Bold] [file:lmroman7-bold] [features=default]
+ \definefontsynonym [LMRoman8-Bold] [file:lmroman8-bold] [features=default]
+ \definefontsynonym [LMRoman9-Bold] [file:lmroman9-bold] [features=default]
+ \definefontsynonym [LMRoman10-Bold] [file:lmroman10-bold] [features=default]
+ \definefontsynonym [LMRoman12-Bold] [file:lmroman12-bold] [features=default]
+ \definefontsynonym [LMRoman7-Italic] [file:lmroman7-italic] [features=default]
+ \definefontsynonym [LMRoman8-Italic] [file:lmroman8-italic] [features=default]
+ \definefontsynonym [LMRoman9-Italic] [file:lmroman9-italic] [features=default]
+ \definefontsynonym [LMRoman10-Italic] [file:lmroman10-italic] [features=default]
+ \definefontsynonym [LMRoman12-Italic] [file:lmroman12-italic] [features=default]
+ \definefontsynonym [LMRoman10-BoldItalic] [file:lmroman10-bolditalic] [features=default]
+ \definefontsynonym [LMRoman8-Oblique] [file:lmroman8-oblique] [features=default]
+ \definefontsynonym [LMRoman9-Oblique] [file:lmroman9-oblique] [features=default]
+ \definefontsynonym [LMRoman10-Oblique] [file:lmroman10-oblique] [features=default]
+ \definefontsynonym [LMRoman12-Oblique] [file:lmroman12-oblique] [features=default]
+ \definefontsynonym [LMRoman17-Oblique] [file:lmroman17-oblique] [features=default]
+ \definefontsynonym [LMRoman10-BoldOblique] [file:lmroman10-boldoblique] [features=default]
+ \definefontsynonym [LMRoman10-Demi] [file:lmroman10-demi] [features=default]
+ \definefontsynonym [LMRoman10-DemiOblique] [file:lmroman10-demioblique] [features=default]
+ \definefontsynonym [LMRoman10-CapsRegular] [file:lmroman10-capsregular] [features=default] % features=smallcaps?
+ \definefontsynonym [LMRoman10-CapsOblique] [file:lmroman10-capsoblique] [features=default]
+
+ \definefontsynonym [LMRoman10-Dunhill] [file:lmroman10-dunhill] [features=default]
+ \definefontsynonym [LMRoman10-DunhillOblique] [file:lmroman10-dunhilloblique] [features=default]
\stoptypescript
\starttypescript [sans] [modern,latin-modern]
- \definefontsynonym [LMSans10-Regular] [lmsans10-regular] [features=default]
- \definefontsynonym [LMSans12-Regular] [lmsans12-regular] [features=default]
- \definefontsynonym [LMSans17-Regular] [lmsans17-regular] [features=default]
- \definefontsynonym [LMSans8-Regular] [lmsans8-regular] [features=default]
- \definefontsynonym [LMSans9-Regular] [lmsans9-regular] [features=default]
- \definefontsynonym [LMSans10-BoldOblique] [lmsans10-boldoblique] [features=default]
- \definefontsynonym [LMSans10-Bold] [lmsans10-bold] [features=default]
- \definefontsynonym [LMSans10-DemiCondensed] [lmsans10-demicondensed] [features=default]
- \definefontsynonym [LMSans10-DemiCondensedOblique] [lmsans10-demicondensedoblique] [features=default]
- \definefontsynonym [LMSans10-Oblique] [lmsans10-oblique] [features=default]
- \definefontsynonym [LMSans12-Oblique] [lmsans12-oblique] [features=default]
- \definefontsynonym [LMSans17-Oblique] [lmsans17-oblique] [features=default]
- \definefontsynonym [LMSans8-Oblique] [lmsans8-oblique] [features=default]
- \definefontsynonym [LMSans9-Oblique] [lmsans9-oblique] [features=default]
- \definefontsynonym [LMSansQuotation8-Regular] [lmsansquotation8-regular] [features=default]
- \definefontsynonym [LMSansQuotation8-BoldOblique] [lmsansquotation8-boldoblique] [features=default]
- \definefontsynonym [LMSansQuotation8-Bold] [lmsansquotation8-bold] [features=default]
- \definefontsynonym [LMSansQuotation8-Oblique] [lmsansquotation8-oblique] [features=default]
+ \definefontsynonym [LMSans8-Regular] [file:lmsans8-regular] [features=default]
+ \definefontsynonym [LMSans9-Regular] [file:lmsans9-regular] [features=default]
+ \definefontsynonym [LMSans10-Regular] [file:lmsans10-regular] [features=default]
+ \definefontsynonym [LMSans12-Regular] [file:lmsans12-regular] [features=default]
+ \definefontsynonym [LMSans17-Regular] [file:lmsans17-regular] [features=default]
+ \definefontsynonym [LMSans10-Bold] [file:lmsans10-bold] [features=default]
+ \definefontsynonym [LMSans8-Oblique] [file:lmsans8-oblique] [features=default]
+ \definefontsynonym [LMSans9-Oblique] [file:lmsans9-oblique] [features=default]
+ \definefontsynonym [LMSans10-Oblique] [file:lmsans10-oblique] [features=default]
+ \definefontsynonym [LMSans12-Oblique] [file:lmsans12-oblique] [features=default]
+ \definefontsynonym [LMSans17-Oblique] [file:lmsans17-oblique] [features=default]
+ \definefontsynonym [LMSans10-BoldOblique] [file:lmsans10-boldoblique] [features=default]
+
+ \definefontsynonym [LMSans10-DemiCondensed] [file:lmsans10-demicondensed] [features=default]
+ \definefontsynonym [LMSans10-DemiCondensedOblique] [file:lmsans10-demicondensedoblique] [features=default]
+
+ \definefontsynonym [LMSansQuotation8-Regular] [file:lmsansquotation8-regular] [features=default]
+ \definefontsynonym [LMSansQuotation8-Bold] [file:lmsansquotation8-bold] [features=default]
+ \definefontsynonym [LMSansQuotation8-Oblique] [file:lmsansquotation8-oblique] [features=default]
+ \definefontsynonym [LMSansQuotation8-BoldOblique] [file:lmsansquotation8-boldoblique] [features=default]
\stoptypescript
\starttypescript [mono] [modern,latin-modern,modern-vari,latin-modern-vari,modern-cond,latin-modern-cond]
- \definefontsynonym [LMTypewriter10-CapsRegular] [lmtypewriter10-capsregular]
- \definefontsynonym [LMTypewriter10-CapsOblique] [lmtypewriter10-capsoblique]
- \definefontsynonym [LMTypewriter10-Light] [lmtypewriter10-light]
- \definefontsynonym [LMTypewriter10-LightOblique] [lmtypewriter10-lightoblique]
- \definefontsynonym [LMTypewriter10-LightCondensed] [lmtypewriter10-lightcondensed]
- \definefontsynonym [LMTypewriter10-LightCondensedOblique] [lmtypewriter10-lightcondensedoblique]
- \definefontsynonym [LMTypewriter10-Dark] [lmtypewriter10-dark]
- \definefontsynonym [LMTypewriter10-DarkOblique] [lmtypewriter10-darkoblique]
- \definefontsynonym [LMTypewriter10-Regular] [lmtypewriter10-regular]
- \definefontsynonym [LMTypewriter12-Regular] [lmtypewriter12-regular]
- \definefontsynonym [LMTypewriter8-Regular] [lmtypewriter8-regular]
- \definefontsynonym [LMTypewriter9-Regular] [lmtypewriter9-regular]
- \definefontsynonym [LMTypewriter10-Italic] [lmtypewriter10-italic]
- \definefontsynonym [LMTypewriter10-Oblique] [lmtypewriter10-oblique]
- \definefontsynonym [LMTypewriterVarWd10-Regular] [lmtypewritervarwd10-regular] [features=default]
- \definefontsynonym [LMTypewriterVarWd10-Oblique] [lmtypewritervarwd10-oblique] [features=default]
- \definefontsynonym [LMTypewriterVarWd10-Light] [lmtypewritervarwd10-light] [features=default]
- \definefontsynonym [LMTypewriterVarWd10-LightOblique] [lmtypewritervarwd10-lightoblique] [features=default]
- \definefontsynonym [LMTypewriterVarWd10-Dark] [lmtypewritervarwd10-dark] [features=default]
- \definefontsynonym [LMTypewriterVarWd10-DarkOblique] [lmtypewritervarwd10-darkoblique] [features=default]
+ \definefontsynonym [LMTypewriter8-Regular] [file:lmtypewriter8-regular]
+ \definefontsynonym [LMTypewriter9-Regular] [file:lmtypewriter9-regular]
+ \definefontsynonym [LMTypewriter10-Regular] [file:lmtypewriter10-regular]
+ \definefontsynonym [LMTypewriter12-Regular] [file:lmtypewriter12-regular]
+ \definefontsynonym [LMTypewriter10-Italic] [file:lmtypewriter10-italic]
+ \definefontsynonym [LMTypewriter10-Oblique] [file:lmtypewriter10-oblique]
+ \definefontsynonym [LMTypewriter10-CapsRegular] [file:lmtypewriter10-capsregular] % features=smallcaps?
+ \definefontsynonym [LMTypewriter10-CapsOblique] [file:lmtypewriter10-capsoblique]
+
+ \definefontsynonym [LMTypewriter10-Light] [file:lmtypewriter10-light]
+ \definefontsynonym [LMTypewriter10-LightOblique] [file:lmtypewriter10-lightoblique]
+ \definefontsynonym [LMTypewriter10-LightCondensed] [file:lmtypewriter10-lightcondensed]
+ \definefontsynonym [LMTypewriter10-LightCondensedOblique] [file:lmtypewriter10-lightcondensedoblique]
+
+ \definefontsynonym [LMTypewriter10-Dark] [file:lmtypewriter10-dark]
+ \definefontsynonym [LMTypewriter10-DarkOblique] [file:lmtypewriter10-darkoblique]
+
+ \definefontsynonym [LMTypewriter10-Unslanted] [file:lmtypewriter10-unslanted]
+
+ \definefontsynonym [LMTypewriterVarWd10-Regular] [file:lmtypewritervarwd10-regular] [features=default]
+ \definefontsynonym [LMTypewriterVarWd10-Oblique] [file:lmtypewritervarwd10-oblique] [features=default]
+ \definefontsynonym [LMTypewriterVarWd10-Light] [file:lmtypewritervarwd10-light] [features=default]
+ \definefontsynonym [LMTypewriterVarWd10-LightOblique] [file:lmtypewritervarwd10-lightoblique] [features=default]
+ \definefontsynonym [LMTypewriterVarWd10-Dark] [file:lmtypewritervarwd10-dark] [features=default]
+ \definefontsynonym [LMTypewriterVarWd10-DarkOblique] [file:lmtypewritervarwd10-darkoblique] [features=default]
\stoptypescript
\starttypescript [math] [modern,latin-modern]
@@ -268,17 +279,17 @@
\definetypescriptprefix [n:cursor] [TeXGyreCursor] \definetypescriptprefix [f:cursor] [cursor]
\definetypescriptprefix [n:chorus] [TeXGyreChorus] \definetypescriptprefix [f:chorus] [chorus] % not the full set
-\starttypescript [serif] [pagella,termes,heros,bonum,schola,adventor]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=oldstyle]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Slanted] [texgyre\typescriptprefix{n:\typescripttwo}-Italic] [features=default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldSlanted] [texgyre\typescriptprefix{n:\typescripttwo}-BoldItalic] [features=default]
+\starttypescript [serif] [adventor,bonum,cursor,heros,pagella,schola,termes]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-regular] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-italic] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bold] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [file:texgyre\typescriptthree\typescriptprefix{f:\typescripttwo}-bolditalic] [features=oldstyle]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Slanted] [\typescriptprefix{n:\typescripttwo}-Italic] [features=default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldSlanted] [\typescriptprefix{n:\typescripttwo}-BoldItalic] [features=default]
\stoptypescript
\starttypescript [serif] [pagella,termes,bonum,schola,chorus] [name]
@@ -377,7 +388,7 @@
% qtmb TeXGyreHeros-Bold
% qtmbi TeXGyreHeros-BoldItalic
-\starttypescript [serif] [helvetica]
+\starttypescript [sans] [helvetica]
\definefontsynonym [Helvetica] [texgyreheros-regular] [features=default]
\definefontsynonym [Helvetica-Oblique] [texgyreheros-italic] [features=default]
\definefontsynonym [Helvetica-Bold] [texgyreheros-bold] [features=default]
@@ -498,44 +509,44 @@
% Antykwa Torunska (GUST)
\starttypescript [serif] [antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond]
- \definefontsynonym [AntykwaTorunska-Bold] [antykwatorunska-bold] [features=default]
- \definefontsynonym [AntykwaTorunska-BoldItalic] [antykwatorunska-bolditalic] [features=default]
- \definefontsynonym [AntykwaTorunska-Light] [antykwatorunskalight-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-LightItalic] [antykwatorunskalight-italic] [features=default]
- \definefontsynonym [AntykwaTorunska-Medium] [antykwatorunskamed-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-MedItalic] [antykwatorunskamed-italic] [features=default]
- \definefontsynonym [AntykwaTorunska-Regular] [antykwatorunska-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-Italic] [antykwatorunska-italic] [features=default]
- \definefontsynonym [AntykwaTorunska-CondBold] [antykwatorunskacond-bold] [features=default]
- \definefontsynonym [AntykwaTorunska-CondBoldItalic] [antykwatorunskacond-bolditalic] [features=default]
- \definefontsynonym [AntykwaTorunska-CondLight] [antykwatorunskacondlight-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-CondLightItalic] [antykwatorunskacondlight-italic] [features=default]
- \definefontsynonym [AntykwaTorunska-CondMedium] [antykwatorunskacondmed-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-CondMedItalic] [antykwatorunskacondmed-italic] [features=default]
- \definefontsynonym [AntykwaTorunska-CondRegular] [antykwatorunskacond-regular] [features=default]
- \definefontsynonym [AntykwaTorunska-CondItalic] [antykwatorunskacond-italic] [features=default]
-
- \definefontsynonym [AntykwaTorunska-BoldCap] [antykwatorunska-bold] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-BoldItalicCap] [antykwatorunska-bolditalic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-LightCap] [antykwatorunskalight-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-LightItalicCap] [antykwatorunskalight-italic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-MediumCap] [antykwatorunskamed-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-MedItalicCap] [antykwatorunskamed-italic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-Cap] [antykwatorunska-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-ItalicCap] [antykwatorunska-italic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondBoldCap] [antykwatorunskacond-bold] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [antykwatorunskacond-bolditalic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondLightCap] [antykwatorunskacondlight-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondLightItalicCap][antykwatorunskacondlight-italic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondMediumCap] [antykwatorunskacondmed-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondMedItalicCap] [antykwatorunskacondmed-italic] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondCap] [antykwatorunskacond-regular] [features=smallcaps]
- \definefontsynonym [AntykwaTorunska-CondItalicCap] [antykwatorunskacond-italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-Regular] [file:AntykwaTorunska-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-Italic] [file:AntykwaTorunska-Italic] [features=default]
+ \definefontsynonym [AntykwaTorunska-Bold] [file:AntykwaTorunska-Bold] [features=default]
+ \definefontsynonym [AntykwaTorunska-BoldItalic] [file:AntykwaTorunska-BoldItalic] [features=default]
+ \definefontsynonym [AntykwaTorunska-Light] [file:AntykwaTorunskaLight-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-LightItalic] [file:AntykwaTorunskaLight-Italic] [features=default]
+ \definefontsynonym [AntykwaTorunska-Medium] [file:AntykwaTorunskaMed-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-MedItalic] [file:AntykwaTorunskaMed-Italic] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondRegular] [file:AntykwaTorunskaCond-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondItalic] [file:AntykwaTorunskaCond-Italic] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondBold] [file:AntykwaTorunskaCond-Bold] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondBoldItalic] [file:AntykwaTorunskaCond-BoldItalic] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondLight] [file:AntykwaTorunskaCondLight-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondLightItalic] [file:AntykwaTorunskaCondLight-Italic] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondMedium] [file:AntykwaTorunskaCondMed-Regular] [features=default]
+ \definefontsynonym [AntykwaTorunska-CondMedItalic] [file:AntykwaTorunskaCondMed-Italic] [features=default]
+
+ \definefontsynonym [AntykwaTorunska-Cap] [file:AntykwaTorunska-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-ItalicCap] [file:AntykwaTorunska-Italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-BoldCap] [file:AntykwaTorunska-Bold] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-BoldItalicCap] [file:AntykwaTorunska-BoldItalic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-LightCap] [file:AntykwaTorunskaLight-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-LightItalicCap] [file:AntykwaTorunskaLight-Italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-MediumCap] [file:AntykwaTorunskaMed-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-MedItalicCap] [file:AntykwaTorunskaMed-Italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondCap] [file:AntykwaTorunskaCond-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondItalicCap] [file:AntykwaTorunskaCond-Italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondBoldCap] [file:AntykwaTorunskaCond-Bold] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [file:AntykwaTorunskaCond-BoldItalic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondLightCap] [file:AntykwaTorunskaCondLight-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondLightItalicCap][file:AntykwaTorunskaCondLight-Italic] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondMediumCap] [file:AntykwaTorunskaCondMed-Regular] [features=smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondMedItalicCap] [file:AntykwaTorunskaCondMed-Italic] [features=smallcaps]
\stoptypescript
\starttypescript [math] [antykwa-torunska] [default]
\definefontsynonym [AntykwaTorunska-Math-Letters-Regular] [rm-anttr]
- \definefontsynonym [AntykwaTorunska-Math-Letters-RegularItalic] [mi-anttri]
+ \definefontsynonym [AntykwaTorunska-Math-Letters-Italic] [mi-anttri]
\definefontsynonym [AntykwaTorunska-Math-Symbols-Regular] [sy-anttrz]
\definefontsynonym [AntykwaTorunska-Math-Extension-Regular] [ex-anttr]
\stoptypescript
@@ -549,7 +560,7 @@
\starttypescript [math] [antykwa-torunska-cond] [default]
\definefontsynonym [AntykwaTorunska-Math-Letters-CondRegular] [rm-anttcr]
- \definefontsynonym [AntykwaTorunska-Math-Letters-CondRegularItalic] [mi-anttcri]
+ \definefontsynonym [AntykwaTorunska-Math-Letters-CondItalic] [mi-anttcri]
\definefontsynonym [AntykwaTorunska-Math-Symbols-CondRegular] [sy-anttcrz]
\definefontsynonym [AntykwaTorunska-Math-Extension-CondRegular] [ex-anttcr]
\stoptypescript
@@ -582,76 +593,81 @@
% maybe this will change in Iwona-Math-Letters and Iwona-Math-Letters-Italic
+% These names are a depressing mess. They have changed over time and are
+% still not consistent. I'd expect Bold-Regular and Bold-Italic.
+
\starttypescript [sans] [iwona-light,iwona,iwona-medium,iwona-heavy,iwona-light-cond,iwona-cond,iwona-medium-cond,iwona-heavy-cond]
- \definefontsynonym [Iwona-Regular] [iwona-regular] [features=default]
- \definefontsynonym [Iwona-RegularItalic] [iwona-italic] [features=default]
- \definefontsynonym [Iwona-Bold] [iwona-bold] [features=default]
- \definefontsynonym [Iwona-BoldItalic] [iwona-bolditalic] [features=default]
- \definefontsynonym [Iwona-Light] [iwonalight-regular] [features=default]
- \definefontsynonym [Iwona-LightItalic] [iwonalight-italic] [features=default]
- \definefontsynonym [Iwona-Medium] [iwonamedium-regular] [features=default]
- \definefontsynonym [Iwona-MediumItalic] [iwonamedium-italic] [features=default]
- \definefontsynonym [Iwona-Heavy] [iwonaheavy-regular] [features=default]
- \definefontsynonym [Iwona-HeavyItalic] [iwonaheavy-italic] [features=default]
-
- \definefontsynonym [Iwona-CondLight] [iwonacond-regular] [features=default]
- \definefontsynonym [Iwona-CondRegular] [iwonacond-italic] [features=default]
- \definefontsynonym [Iwona-CondMedium] [iwonacond-bold] [features=default]
- \definefontsynonym [Iwona-CondBold] [iwonacond-bolditalic] [features=default]
- \definefontsynonym [Iwona-CondHeavy] [iwonacondlight-regular] [features=default]
- \definefontsynonym [Iwona-CondLightItalic] [iwonacondlight-italic] [features=default]
- \definefontsynonym [Iwona-CondRegularItalic] [iwonacondmedium-regular] [features=default]
- \definefontsynonym [Iwona-CondMediumItalic] [iwonacondmedium-italic] [features=default]
- \definefontsynonym [Iwona-CondBoldItalic] [iwonacondheavy-regular] [features=default]
- \definefontsynonym [Iwona-CondHeavyItalic] [iwonacondheavy-italic] [features=default]
-
- \definefontsynonym [Iwona-CapsLight] [iwona-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CapsRegular] [iwona-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CapsMedium] [iwona-bold] [features=smallcaps]
- \definefontsynonym [Iwona-CapsBold] [iwona-bolditalic] [features=smallcaps]
- \definefontsynonym [Iwona-CapsHeavy] [iwonalight-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CapsLightItalic] [iwonalight-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CapsRegularItalic] [iwonamedium-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CapsMediumItalic] [iwonamedium-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CapsBoldItalic] [iwonaheavy-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CapsHeavyItalic] [iwonaheavy-italic] [features=smallcaps]
-
- \definefontsynonym [Iwona-CondCapsLight] [iwonacond-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsRegular] [iwonacond-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsMedium] [iwonacond-bold] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsBold] [iwonacond-bolditalic] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsHeavy] [iwonacondlight-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsLightItalic] [iwonacondlight-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsRegularItalic] [iwonacondmedium-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsMediumItalic] [iwonacondmedium-italic] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsBoldItalic] [iwonacondheavy-regular] [features=smallcaps]
- \definefontsynonym [Iwona-CondCapsHeavyItalic] [iwonacondheavy-italic] [features=smallcaps]
+
+ \definefontsynonym [Iwona-Regular] [file:Iwona-Regular] [features=default]
+ \definefontsynonym [Iwona-Italic] [file:Iwona-Italic] [features=default]
+ \definefontsynonym [Iwona-Bold] [file:Iwona-Bold] [features=default]
+ \definefontsynonym [Iwona-BoldItalic] [file:Iwona-BoldItalic] [features=default]
+ \definefontsynonym [Iwona-Light-Regular] [file:IwonaLight] [features=default]
+ \definefontsynonym [Iwona-Light-Italic] [file:IwonaLight-Italic] [features=default]
+ \definefontsynonym [Iwona-Medium-Regular] [file:IwonaMedium-Regular] [features=default]
+ \definefontsynonym [Iwona-Medium-Italic] [file:IwonaMedium-Italic] [features=default]
+ \definefontsynonym [Iwona-Heavy-Regular] [file:IwonaHeavy-Regular] [features=default]
+ \definefontsynonym [Iwona-Heavy-Italic] [file:IwonaHeavy-Italic] [features=default]
+
+ \definefontsynonym [Iwona-CapsRegular] [file:Iwona-Regular] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsItalic] [file:Iwona-Italic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsBold] [file:Iwona-Bold] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsBoldItalic] [file:Iwona-BoldItalic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsLight] [file:IwonaLight] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsLight-Italic] [file:IwonaLightItalic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsMedium] [file:IwonaMedium] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsMedium-Italic] [file:IwonaMediumItalic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsHeavy] [file:IwonaHeavy] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsHeavy-Italic] [file:IwonaHeavyItalic] [features=smallcaps]
+
+ \definefontsynonym [Iwona-CondRegular] [file:IwonaCond-Regular] [features=default]
+ \definefontsynonym [Iwona-CondItalic] [file:IwonaCond-Italic] [features=default]
+ \definefontsynonym [Iwona-CondBold] [file:IwonaCond-Bold] [features=default]
+ \definefontsynonym [Iwona-CondBoldItalic] [file:IwonaCond-BoldItalic] [features=default]
+ \definefontsynonym [Iwona-CondLight-Regular] [file:IwonaCondLight-Regular] [features=default]
+ \definefontsynonym [Iwona-CondLight-Italic] [file:IwonaCondLight-Italic] [features=default]
+ \definefontsynonym [Iwona-CondMedium-Regular] [file:IwonaCondMedium-Regular] [features=default]
+ \definefontsynonym [Iwona-CondMedium-Italic] [file:IwonaCondMedium-Italic] [features=default]
+ \definefontsynonym [Iwona-CondHeavy-Regular] [file:IwonaCondHeavy-Regular] [features=default]
+ \definefontsynonym [Iwona-CondHeavy-Italic] [file:IwonaCondHeavy-Italic] [features=default]
+
+ \definefontsynonym [Iwona-CapsCondRegular] [file:IwonaCond-Regular] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondItalic] [file:IwonaCond-Italic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondBold] [file:IwonaCond-Bold] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondBoldItalic] [file:IwonaCond-BoldItalic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondLight-Regular] [file:IwonaCondLight-Regular] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondLight-Italic] [file:IwonaCondLight-Italic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondMedium-Regular][file:IwonaCondMedium-Regular] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondMedium-Italic] [file:IwonaCondMedium-Italic] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondHeavy-Regular] [file:IwonaCondHeavy-Regular] [features=smallcaps]
+ \definefontsynonym [Iwona-CapsCondHeavy-Italic] [file:IwonaCondHeavy-Italic] [features=smallcaps]
+
\stoptypescript
\starttypescript [math] [iwona] [default]
\definefontsynonym [Iwona-Math-Letters-Regular] [rm-iwonar]
- \definefontsynonym [Iwona-Math-Letters-RegularItalic] [mi-iwonari]
+ \definefontsynonym [Iwona-Math-Letters-Italic] [mi-iwonari]
\definefontsynonym [Iwona-Math-Symbols-Regular] [sy-iwonarz]
\definefontsynonym [Iwona-Math-Extension-Regular] [ex-iwonar]
\stoptypescript
\starttypescript [math] [iwona-light] [default]
- \definefontsynonym [Iwona-Math-Letters-Light] [rm-iwonal]
- \definefontsynonym [Iwona-Math-Letters-LightItalic] [mi-iwonali]
+ \definefontsynonym [Iwona-Math-Letters-Light-Regular] [rm-iwonal]
+ \definefontsynonym [Iwona-Math-Letters-Light-Italic] [mi-iwonali]
\definefontsynonym [Iwona-Math-Symbols-Light] [sy-iwonalz]
\definefontsynonym [Iwona-Math-Extension-Light] [ex-iwonal]
\stoptypescript
\starttypescript [math] [iwona-medium] [default]
- \definefontsynonym [Iwona-Math-Letters-Medium] [rm-iwonam]
- \definefontsynonym [Iwona-Math-Letters-MediumItalic] [mi-iwonami]
+ \definefontsynonym [Iwona-Math-Letters-Medium-Regular][rm-iwonam]
+ \definefontsynonym [Iwona-Math-Letters-Medium-Italic] [mi-iwonami]
\definefontsynonym [Iwona-Math-Symbols-Medium] [sy-iwonamz]
\definefontsynonym [Iwona-Math-Extension-Medium] [ex-iwonam]
\stoptypescript
\starttypescript [math] [iwona-heavy] [default]
- \definefontsynonym [Iwona-Math-Letters-Heavy] [rm-iwonah]
- \definefontsynonym [Iwona-Math-Letters-HeavyItalic] [mi-iwonahi]
+ \definefontsynonym [Iwona-Math-Letters-Heavy-Regular] [rm-iwonah]
+ \definefontsynonym [Iwona-Math-Letters-Heavy-Italic] [mi-iwonahi]
\definefontsynonym [Iwona-Math-Symbols-Heavy] [sy-iwonahz]
\definefontsynonym [Iwona-Math-Extension-Heavy] [ex-iwonah]
\stoptypescript
@@ -673,7 +689,7 @@
\definefontsynonym[Kurier-Bold] [kurierb]
\definefontsynonym[Kurier-Heavy] [kurierh]
\definefontsynonym[Kurier-LightItalic] [kurierli]
- \definefontsynonym[Kurier-RegularItalic] [kurierri]
+ \definefontsynonym[Kurier-Italic] [kurierri]
\definefontsynonym[Kurier-MediumItalic] [kuriermi]
\definefontsynonym[Kurier-BoldItalic] [kurierbi]
\definefontsynonym[Kurier-HeavyItalic] [kurierhi]
@@ -681,23 +697,23 @@
\starttypescript [math] [kurier] [default]
\definefontsynonym [Kurier-Math-Letters-Regular] [rm-kurierr]
- \definefontsynonym [Kurier-Math-Letters-RegularItalic] [mi-kurierri]
+ \definefontsynonym [Kurier-Math-Letters-Italic] [mi-kurierri]
\definefontsynonym [Kurier-Math-Symbols-Regular] [sy-kurierrz]
\definefontsynonym [Kurier-Math-Extension-Regular] [ex-kurierr]
\stoptypescript
\starttypescript [math] [kurier-light] [default]
- \definefontsynonym [Kurier-Math-Letters-Light] [rm-kurierl]
- \definefontsynonym [Kurier-Math-Letters-LightItalic] [mi-kurierli]
+ \definefontsynonym [Kurier-Math-Letters-Light-Regular] [rm-kurierl]
+ \definefontsynonym [Kurier-Math-Letters-Light-Italic] [mi-kurierli]
\definefontsynonym [Kurier-Math-Symbols-Light] [sy-kurierlz]
\definefontsynonym [Kurier-Math-Extension-Light] [ex-kurierl]
\stoptypescript
\starttypescript [math] [kurier-medium] [default]
- \definefontsynonym [Kurier-Math-Letters-Medium] [rm-kurierm]
- \definefontsynonym [Kurier-Math-Letters-MediumItalic] [mi-kuriermi]
- \definefontsynonym [Kurier-Math-Symbols-Medium] [sy-kuriermz]
- \definefontsynonym [Kurier-Math-Extension-medium] [ex-kurierm]
+ \definefontsynonym [Kurier-Math-Letters-Medium-Regular] [rm-kurierm]
+ \definefontsynonym [Kurier-Math-Letters-Medium-Italic] [mi-kuriermi]
+ \definefontsynonym [Kurier-Math-Symbols-Medium-Regular] [sy-kuriermz]
+ \definefontsynonym [Kurier-Math-Extension-Medium] [ex-kurierm]
\stoptypescript
\starttypescript [math] [kurier,kurier-light,kurier-medium] [default]
diff --git a/tex/context/base/type-tmf.tex b/tex/context/base/type-tmf.tex
index db6240ba5..f4445209c 100644
--- a/tex/context/base/type-tmf.tex
+++ b/tex/context/base/type-tmf.tex
@@ -611,14 +611,14 @@
\starttypescript [math] [antykwa-torunska] [name]
\definefontsynonym [MathRoman] [AntykwaTorunska-Math-Letters-Regular]
- \definefontsynonym [MathItalic] [AntykwaTorunska-Math-Letters-RegularItalic]
+ \definefontsynonym [MathItalic] [AntykwaTorunska-Math-Letters-Italic]
\definefontsynonym [MathSymbol] [AntykwaTorunska-Math-Symbols-Regular]
\definefontsynonym [MathExtension] [AntykwaTorunska-Math-Extension-Regular]
\stoptypescript
\starttypescript [math] [antykwa-torunska-cond] [name]
\definefontsynonym [MathRoman] [AntykwaTorunska-Math-Letters-CondRegular]
- \definefontsynonym [MathItalic] [AntykwaTorunska-Math-Letters-CondRegularItalic]
+ \definefontsynonym [MathItalic] [AntykwaTorunska-Math-Letters-CondItalic]
\definefontsynonym [MathSymbol] [AntykwaTorunska-Math-Symbols-CondRegular]
\definefontsynonym [MathExtension] [AntykwaTorunska-Math-Extension-CondRegular]
\stoptypescript
@@ -658,20 +658,20 @@
\starttypescript [sans] [iwona-light-caps] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsLight]
- \definefontsynonym [SansItalic] [Iwona-CapsLightItalic]
- \definefontsynonym [SansBold] [Iwona-CapsMedium]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsMediumItalic]
+ \definefontsynonym [Sans] [Iwona-CapsLight-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CapsLight-Italic]
+ \definefontsynonym [SansBold] [Iwona-CapsMedium-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CapsMedium-Italic]
\stoptypescript
\starttypescript [sans] [iwona] [name]
\setups[font:fallback:sans]
\definefontsynonym [Sans] [Iwona-Regular]
- \definefontsynonym [SansItalic] [Iwona-RegularItalic]
+ \definefontsynonym [SansItalic] [Iwona-Italic]
\definefontsynonym [SansBold] [Iwona-Bold]
\definefontsynonym [SansBoldItalic] [Iwona-BoldItalic]
\definefontsynonym [SansCaps] [Iwona-CapsRegular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsRegularItalic]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsItalic]
\definefontsynonym [SansBoldCaps] [Iwona-CapsBold]
\definefontsynonym [SansBoldItalicCaps] [Iwona-CapsBoldItalic]
\stoptypescript
@@ -679,135 +679,135 @@
\starttypescript [sans] [iwona-caps] [name]
\setups[font:fallback:sans]
\definefontsynonym [Sans] [Iwona-CapsRegular]
- \definefontsynonym [SansItalic] [Iwona-CapsRegularItalic]
+ \definefontsynonym [SansItalic] [Iwona-CapsItalic]
\definefontsynonym [SansBold] [Iwona-CapsBold]
\definefontsynonym [SansBoldItalic] [Iwona-CapsBoldItalic]
\stoptypescript
\starttypescript [sans] [iwona-medium] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Medium]
- \definefontsynonym [SansItalic] [Iwona-MediumItalic]
- \definefontsynonym [SansBold] [Iwona-Heavy]
- \definefontsynonym [SansBoldItalic] [Iwona-HeavyItalic]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsMediumItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavyItalic]
+ \definefontsynonym [Sans] [Iwona-Medium-Regular]
+ \definefontsynonym [SansItalic] [Iwona-Medium-Italic]
+ \definefontsynonym [SansBold] [Iwona-Heavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsMedium-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
\stoptypescript
\starttypescript [sans] [iwona-medium-caps] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsHeavy]
- \definefontsynonym [SansItalic] [Iwona-CapsMediumItalic]
- \definefontsynonym [SansBold] [Iwona-CapsHeavy]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsHeavyItalic]
+ \definefontsynonym [Sans] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CapsMedium-Italic]
+ \definefontsynonym [SansBold] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CapsHeavy-Italic]
\stoptypescript
\starttypescript [sans] [iwona-heavy] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Heavy]
- \definefontsynonym [SansItalic] [Iwona-HeavyItalic]
- \definefontsynonym [SansBold] [Iwona-Heavy]
- \definefontsynonym [SansBoldItalic] [Iwona-HeavyItalic]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavyItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavyItalic]
+ \definefontsynonym [Sans] [Iwona-Heavy-Regular]
+ \definefontsynonym [SansItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [SansBold] [Iwona-Heavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
\stoptypescript
\starttypescript [sans] [iwona-heavy-caps] [name]
\setups[font:fallback:sans]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavyItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavyItalic]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
\stoptypescript
\starttypescript [sans] [iwona-light-cond] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondLight]
- \definefontsynonym [SansItalic] [Iwona-CondLightItalic]
- \definefontsynonym [SansBold] [Iwona-CondMedium]
- \definefontsynonym [SansBoldItalic] [Iwona-CondMediumItalic]
- \definefontsynonym [SansCaps] [Iwona-CondCapsLight]
- \definefontsynonym [SansItalicCaps] [Iwona-CondCapsLightItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CondCapsMedium]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CondCapsMediumItalic]
+ \definefontsynonym [Sans] [Iwona-CondLight-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CondLight-Italic]
+ \definefontsynonym [SansBold] [Iwona-CondMedium-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CondMedium-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondLight-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondLight-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondMedium-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondMedium-Italic]
\stoptypescript
-\starttypescript [sans] [iwona-light-cond-caps] [name]
+\starttypescript [sans] [iwona-light-cond-caps,iwona-light-caps-cond] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondCapsLight]
- \definefontsynonym [SansItalic] [Iwona-CondCapsLightItalic]
- \definefontsynonym [SansBold] [Iwona-CondCapsMedium]
- \definefontsynonym [SansBoldItalic] [Iwona-CondCapsMediumItalic]
+ \definefontsynonym [Sans] [Iwona-CapsCondLight-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CapsCondLight-Italic]
+ \definefontsynonym [SansBold] [Iwona-CapsCondMedium-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CapsCondMedium-Italic]
\stoptypescript
\starttypescript [sans] [iwona-cond] [name]
\setups[font:fallback:sans]
\definefontsynonym [Sans] [Iwona-CondRegular]
- \definefontsynonym [SansItalic] [Iwona-CondRegularItalic]
+ \definefontsynonym [SansItalic] [Iwona-CondItalic]
\definefontsynonym [SansBold] [Iwona-CondBold]
\definefontsynonym [SansBoldItalic] [Iwona-CondBoldItalic]
- \definefontsynonym [SansCaps] [Iwona-CondCapsRegular]
- \definefontsynonym [SansItalicCaps] [Iwona-CondCapsRegularItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CondCapsBold]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CondCapsBoldItalic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondRegular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondItalic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondBold]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondBoldItalic]
\stoptypescript
-\starttypescript [sans] [iwona-cond-caps] [name]
+\starttypescript [sans] [iwona-cond-caps,iwona-caps-cond] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondCapsRegular]
- \definefontsynonym [SansItalic] [Iwona-CondCapsRegularItalic]
- \definefontsynonym [SansBold] [Iwona-CondCapsBold]
- \definefontsynonym [SansBoldItalic] [Iwona-CondCapsBoldItalic]
+ \definefontsynonym [Sans] [Iwona-CapsCondRegular]
+ \definefontsynonym [SansItalic] [Iwona-CapsCondItalic]
+ \definefontsynonym [SansBold] [Iwona-CapsCondBold]
+ \definefontsynonym [SansBoldItalic] [Iwona-CapsCondBoldItalic]
\stoptypescript
\starttypescript [sans] [iwona-medium-cond] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondMedium]
- \definefontsynonym [SansItalic] [Iwona-CondMediumItalic]
- \definefontsynonym [SansBold] [Iwona-CondHeavy]
- \definefontsynonym [SansBoldItalic] [Iwona-CondHeavyItalic]
- \definefontsynonym [SansCaps] [Iwona-CondCapsHeavy]
- \definefontsynonym [SansItalicCaps] [Iwona-CondCapsMediumItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CondCapsHeavy]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CondCapsHeavyItalic]
+ \definefontsynonym [Sans] [Iwona-CondMedium-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CondMedium-Italic]
+ \definefontsynonym [SansBold] [Iwona-CondHeavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CondHeavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondMedium-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondHeavy-Italic]
\stoptypescript
-\starttypescript [sans] [iwona-medium-cond-caps] [name]
+\starttypescript [sans] [iwona-medium-cond-caps,iwona-medium-caps-cond] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondCapsHeavy]
- \definefontsynonym [SansItalic] [Iwona-CondCapsMediumItalic]
- \definefontsynonym [SansBold] [Iwona-CondCapsHeavy]
- \definefontsynonym [SansBoldItalic] [Iwona-CondCapsHeavyItalic]
+ \definefontsynonym [Sans] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansItalic] [Iwona-CapsCondMedium-Italic]
+ \definefontsynonym [SansBold] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Iwona-CapsCondHeavy-Italic]
\stoptypescript
\starttypescript [math] [iwona-light] [name]
- \definefontsynonym [MathRoman] [Iwona-Math-Letters-Light]
- \definefontsynonym [MathItalic] [Iwona-Math-Letters-LightItalic]
+ \definefontsynonym [MathRoman] [Iwona-Math-Letters-Light-Regular]
+ \definefontsynonym [MathItalic] [Iwona-Math-Letters-Light-Italic]
\definefontsynonym [MathSymbol] [Iwona-Math-Symbols-Light]
\definefontsynonym [MathExtension] [Iwona-Math-Extension-Light]
\stoptypescript
\starttypescript [math] [iwona] [name]
\definefontsynonym [MathRoman] [Iwona-Math-Letters-Regular]
- \definefontsynonym [MathItalic] [Iwona-Math-Letters-RegularItalic]
+ \definefontsynonym [MathItalic] [Iwona-Math-Letters-Italic]
\definefontsynonym [MathSymbol] [Iwona-Math-Symbols-Regular]
\definefontsynonym [MathExtension] [Iwona-Math-Extension-Regular]
\stoptypescript
\starttypescript [math] [iwona-medium] [name]
- \definefontsynonym [MathRoman] [Iwona-Math-Letters-Medium]
- \definefontsynonym [MathItalic] [Iwona-Math-Letters-MediumItalic]
+ \definefontsynonym [MathRoman] [Iwona-Math-Letters-Medium-Regular]
+ \definefontsynonym [MathItalic] [Iwona-Math-Letters-Medium-Italic]
\definefontsynonym [MathSymbol] [Iwona-Math-Symbols-Medium]
\definefontsynonym [MathExtension] [Iwona-Math-Extension-Medium]
\stoptypescript
\starttypescript [math] [iwona-heavy] [name]
- \definefontsynonym [MathRoman] [Iwona-Math-Letters-Heavy]
- \definefontsynonym [MathItalic] [Iwona-Math-Letters-HeavyItalic]
+ \definefontsynonym [MathRoman] [Iwona-Math-Letters-Heavy-Regular]
+ \definefontsynonym [MathItalic] [Iwona-Math-Letters-Heavy-Italic]
\definefontsynonym [MathSymbol] [Iwona-Math-Symbols-Heavy]
\definefontsynonym [MathExtension] [Iwona-Math-Extension-Heavy]
\stoptypescript
@@ -816,45 +816,45 @@
\starttypescript [sans] [kurier-light] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Kurier-Light]
- \definefontsynonym [SansItalic] [Kurier-LightItalic]
- \definefontsynonym [SansBold] [Kurier-Medium]
- \definefontsynonym [SansBoldItalic] [Kurier-MediumItalic]
+ \definefontsynonym [Sans] [Kurier-Light-Regular]
+ \definefontsynonym [SansItalic] [Kurier-Light-Italic]
+ \definefontsynonym [SansBold] [Kurier-Medium-Regular]
+ \definefontsynonym [SansBoldItalic] [Kurier-Medium-Italic]
\stoptypescript
\starttypescript [sans] [kurier] [name]
\setups[font:fallback:sans]
\definefontsynonym [Sans] [Kurier-Regular]
- \definefontsynonym [SansItalic] [Kurier-RegularItalic]
+ \definefontsynonym [SansItalic] [Kurier-Italic]
\definefontsynonym [SansBold] [Kurier-Bold]
\definefontsynonym [SansBoldItalic] [Kurier-BoldItalic]
\stoptypescript
\starttypescript [sans] [kurier-medium] [name]
\setups[font:fallback:sans]
- \definefontsynonym [Sans] [Kurier-Medium]
- \definefontsynonym [SansItalic] [Kurier-MediumItalic]
- \definefontsynonym [SansBold] [Kurier-Heavy]
- \definefontsynonym [SansBoldItalic] [Kurier-HeavyItalic]
+ \definefontsynonym [Sans] [Kurier-Medium-Regular]
+ \definefontsynonym [SansItalic] [Kurier-Medium-Italic]
+ \definefontsynonym [SansBold] [Kurier-Heavy-Regular]
+ \definefontsynonym [SansBoldItalic] [Kurier-Heavy-Italic]
\stoptypescript
\starttypescript [math] [kurier-light] [name]
- \definefontsynonym [MathRoman] [Kurier-Math-Letters-Light]
- \definefontsynonym [MathItalic] [Kurier-Math-Letters-LightItalic]
+ \definefontsynonym [MathRoman] [Kurier-Math-Letters-Light-Regular]
+ \definefontsynonym [MathItalic] [Kurier-Math-Letters-Light-Italic]
\definefontsynonym [MathSymbol] [Kurier-Math-Symbols-Light]
\definefontsynonym [MathExtension] [Kurier-Math-Extension-Light]
\stoptypescript
\starttypescript [math] [kurier] [name]
\definefontsynonym [MathRoman] [Kurier-Math-Letters-Regular]
- \definefontsynonym [MathItalic] [Kurier-Math-Letters-RegularItalic]
+ \definefontsynonym [MathItalic] [Kurier-Math-Letters-Italic]
\definefontsynonym [MathSymbol] [Kurier-Math-Symbols-Regular]
\definefontsynonym [MathExtension] [Kurier-Math-Extension-Regular]
\stoptypescript
\starttypescript [math] [kurier-medium] [name]
- \definefontsynonym [MathRoman] [Kurier-Math-Letters-Medium]
- \definefontsynonym [MathItalic] [Kurier-Math-Letters-MediumItalic]
+ \definefontsynonym [MathRoman] [Kurier-Math-Letters-Medium-Regular]
+ \definefontsynonym [MathItalic] [Kurier-Math-Letters-Medium-Italic]
\definefontsynonym [MathSymbol] [Kurier-Math-Symbols-Medium]
\definefontsynonym [MathExtension] [Kurier-Math-Extension-Medium]
\stoptypescript
diff --git a/tex/context/base/unic-ini.tex b/tex/context/base/unic-ini.tex
index 587edd308..f0f219182 100644
--- a/tex/context/base/unic-ini.tex
+++ b/tex/context/base/unic-ini.tex
@@ -701,36 +701,56 @@
\beginETEX \numexpr
-\chardef \utf@a= 64
-\mathchardef \utf@b= 4096
-\newcount\utf@c\utf@c=262144
-\chardef \utf@d= 192
-\chardef \utf@e= 224
-\chardef \utf@f= 240
-\chardef \utf@g= 128
-\mathchardef \utf@h= 256
-\chardef \utf@i= 127
-\mathchardef \utf@j= 2048
-\chardef \utf@k= 32
-
-\def\numbertoutf#1%
- {\ifnum#1<\utf@g
- \rawcharacter{#1}%
- \else\ifnum#1<\utf@j
- \rawcharacter{\the\numexpr\utf@d+(#1-\utf@k)/\utf@a\relax}%
- \rawcharacter{\the\numexpr\utf@g+(#1-((#1-\utf@k)/\utf@a)*\utf@a)\relax}%
- \else
- \rawcharacter{\the\numexpr\utf@e+(#1-\utf@j)/\utf@b\relax}%
- \rawcharacter{\the\numexpr\utf@g+(#1-(((#1-\utf@j)/\utf@b)*\utf@b)-\utf@k)/\utf@a\relax}%
- \rawcharacter{\the\numexpr\utf@g+(#1-(((#1-\utf@j)/\utf@b)*\utf@b)-((#1-(((#1-\utf@j)/\utf@b)*\utf@b)-\utf@k)/\utf@a)*\utf@a)\relax}%
- \fi\fi}
+ \chardef \utf@a= 64
+ \mathchardef \utf@b= 4096
+ \newcount\utf@c\utf@c=262144
+ \chardef \utf@d= 192
+ \chardef \utf@e= 224
+ \chardef \utf@f= 240
+ \chardef \utf@g= 128
+ \mathchardef \utf@h= 256
+ \chardef \utf@i= 127
+ \mathchardef \utf@j= 2048
+ \chardef \utf@k= 32
+
+ % div: \numexp#1/#2\relax
+ % mod: \numexp#1-(#1/#2)*#2\relax
+
+ % \def\numbertoutf#1%
+ % {\ifnum#1<\utf@g
+ % \rawcharacter{#1}%
+ % \else\ifnum#1<2048
+ % \rawcharacter{\numexpr192+(#1/64)\relax}% 192 + (ud div 64)
+ % \rawcharacter{\numexpr128+(#1-(#1/64)*64)\relax}% 128 + (ud mod 64)
+ % \else\ifnum#1<2097152
+ % \rawcharacter{\numexpr224+(#1-(#1/4096)\relax}% 224 + (ud div 4096)
+ % \rawcharacter{\numexpr128+(#1-((#1/64)-((#1/64)/64)*64)\relax}% 128 + ((ud div 64) mod 64)
+ % \rawcharacter{\numexpr128+(#1-(#1-(#1/64)*64)\relax}% 128 + (ud mod 64)
+ % \else
+ % % todo
+ % \fi\fi}
+
+ \def\numbertoutf#1% okay?
+ {\ifnum#1<\utf@g
+ \rawcharacter{#1}%
+ \else\ifnum#1<\utf@j
+ \rawcharacter{\the\numexpr\utf@d+(#1-\utf@k)/\utf@a\relax}%
+ \rawcharacter{\the\numexpr\utf@g+(#1-((#1-\utf@k)/\utf@a)*\utf@a)\relax}%
+ \else
+ \rawcharacter{\the\numexpr\utf@e+(#1-\utf@j)/\utf@b\relax}%
+ \rawcharacter{\the\numexpr\utf@g+(#1-(((#1-\utf@j)/\utf@b)*\utf@b)-\utf@k)/\utf@a\relax}%
+ \rawcharacter{\the\numexpr\utf@g+(#1-(((#1-\utf@j)/\utf@b)*\utf@b)-((#1-(((#1-\utf@j)/\utf@b)*\utf@b)-\utf@k)/\utf@a)*\utf@a)\relax}%
+ \fi\fi}
\endETEX
+\beginXETEX
+ \def\numbertoutf#1{[\number#1]} % xetex has no way to output 8 bit (i.e. \rawcharacter)
+\endXETEX
+
\beginTEX
-\def\numbertoutf#1%
- {[\number#1]}
+ \def\numbertoutf#1{[\number#1]}
\endTEX
diff --git a/tex/context/base/x-cals.mkiv b/tex/context/base/x-cals.mkiv
index b7274f788..d2281f4d7 100644
--- a/tex/context/base/x-cals.mkiv
+++ b/tex/context/base/x-cals.mkiv
@@ -135,14 +135,16 @@ do
for r, d, k in xml.elements(lxml.id(root),tgroupspec) do
local tgroup = d[k]
+ lxml.directives.before(root,"cdx") -- "cals:table"
texsprint(tex.ctxcatcodes, "\\bgroup")
- lxml.directives.setups(root)
+ lxml.directives.setup(root,"cdx") -- "cals:table"
texsprint(tex.ctxcatcodes, "\\bTABLE")
tablepart(tgroup, hcolspec, hrowspec, "\\bTABLEhead", "\\eTABLEhead")
tablepart(tgroup, bcolspec, browspec, "\\bTABLEbody", "\\eTABLEbody")
tablepart(tgroup, fcolspec, frowspec, "\\bTABLEfoot", "\\eTABLEfoot")
texsprint(tex.ctxcatcodes, "\\eTABLE")
texsprint(tex.ctxcatcodes, "\\egroup")
+ lxml.directives.after(root,"cdx") -- "cals:table"
end
end
diff --git a/tex/context/base/x-ct.mkiv b/tex/context/base/x-ct.mkiv
new file mode 100644
index 000000000..cf7bb64fb
--- /dev/null
+++ b/tex/context/base/x-ct.mkiv
@@ -0,0 +1,202 @@
+%D \module
+%D [ file=x-cals,
+%D version=2007.09.05,
+%D title=\CONTEXT\ XML Modules,
+%D subtitle=\CONTEXT\ Structures,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{Context XML Macros (context)}
+
+\startluacode
+do
+ lxml.context = { }
+
+ local halignments = {
+ left = 'l',
+ flushleft = 'l',
+ right = 'r',
+ flushright = 'r',
+ center = 'c',
+ middle = 'c',
+ centre = 'c',
+ justify = '',
+ }
+
+ local texsprint = tex.sprint
+ local xmlsprint = xml.sprint
+
+ local function roottemplate(root)
+ local rt = root.at.template
+ if rt then
+ if not rt:find("|") then
+ rt = rt:gsub(",","|")
+ end
+ if not rt:find("^|") then rt = "|" .. rt end
+ if not rt:find("|$") then rt = rt .. "|" end
+ end
+ return rt
+ end
+
+ local function specifiedtemplate(root,templatespec)
+ local template = { }
+ for r, d, k in xml.elements(root,templatespec) do
+ local at = d[k].at
+ local tm = halignments[at.align] or ""
+ if toboolean(at.paragraph) then
+ tm = tm .. "p"
+ end
+ template[#template+1] = tm
+ end
+ if #template > 0 then
+ return "|" .. table.join(template,"|") .. "|"
+ else
+ return nil
+ end
+ end
+
+ local function autotemplate(root,rowspec,cellspec)
+ local max = 0
+ for r, d, k in xml.elements(root,rowspec) do
+ local n = xml.count(d[k],cellspec)
+ if n > max then max = n end
+ end
+ if max == 2 then
+ return "|l|p|"
+ elseif max > 0 then
+ return "|" .. string.rep("p|",max)
+ else
+ return nil
+ end
+ end
+
+ local defaulttemplate = "|l|p|"
+
+ function lxml.context.tabulate(root,namespace)
+ if not root then
+ return
+ else
+ root = lxml.id(root)
+ end
+
+ local prefix = (namespace or "context") .. ":"
+
+ local templatespec = "/" .. prefix .. "template" .. "/" .. prefix .. "column"
+ local bodyrowspec = "/" .. prefix .. "body" .. "/" .. prefix .. "row"
+ local cellspec = "/" .. prefix .. "cell"
+
+ local template =
+ roottemplate (root) or
+ specifiedtemplate (root,templatespec) or
+ autotemplate (root,bodyrowspec,cellspec) or
+ defaulttemplate
+
+ lxml.directives.before(root,'cdx')
+ texsprint(tex.ctxcatcodes, "\\bgroup")
+ lxml.directives.setup(root,'cdx')
+ -- todo: head and foot
+ texsprint(tex.ctxcatcodes, string.format("\\starttabulate[%s]",template))
+ for r, d, k in xml.elements(root,bodyrowspec) do
+ texsprint(tex.ctxcatcodes, "\\NC ")
+ for r, d, k in xml.elements(d[k],cellspec) do
+ texsprint(xml.content(d[k]))
+ texsprint(tex.ctxcatcodes, "\\NC")
+ end
+ texsprint(tex.ctxcatcodes, "\\NR")
+ end
+ texsprint(tex.ctxcatcodes, "\\stoptabulate")
+ texsprint(tex.ctxcatcodes, "\\egroup")
+ lxml.directives.after(root,'cdx')
+
+ end
+
+ function lxml.context.combination(root,namespace)
+
+ if not root then
+ return
+ else
+ root = lxml.id(root)
+ end
+
+ local prefix = (namespace or "context") .. ":"
+
+ local pairspec = "/" .. prefix .. "pair"
+ local contentspec = "/" .. prefix .. "content" .. "/text()"
+ local captionspec = "/" .. prefix .. "caption" .. "/text()"
+
+ local nx, ny = root.at.nx, root.at.ny
+
+ if not (nx or ny) then
+ nx = xml.count(root,pairspec) or 2
+ end
+ local template = string.format("%s*%s", nx or 1, ny or 1)
+
+ lxml.directives.before(root,'cdx')
+ texsprint(tex.ctxcatcodes, "\\bgroup")
+ lxml.directives.setup(root,'cdx')
+ -- todo: alignments
+ texsprint(tex.ctxcatcodes, string.format("\\startcombination[%s]",template))
+ for r, d, k in xml.elements(root,pairspec) do
+ local dk = d[k]
+ texsprint(tex.ctxcatcodes,"{")
+ xmlsprint(xml.filter(dk,contentspec) or "")
+ texsprint(tex.ctxcatcodes,"}")
+ texsprint(tex.ctxcatcodes,"{")
+ xmlsprint(xml.filter(dk,captionspec) or "")
+ texsprint(tex.ctxcatcodes,"}")
+ end
+ texsprint(tex.ctxcatcodes, "\\stopcombination")
+ texsprint(tex.ctxcatcodes, "\\egroup")
+ lxml.directives.after(root,'cdx')
+
+ end
+
+end
+\stopluacode
+
+\startxmlsetups xml:context:process
+ \xmlsetfunction {\xmldocument} {context:tabulate} {lxml.context.tabulate}
+ \xmlsetfunction {\xmldocument} {context:combination} {lxml.context.combination}
+\stopxmlsetups
+
+\xmlregistersetup{xml:context:process}
+
+\xmlregisterns{context}{context}
+
+\endinput
+
+% this replaces:
+
+% \startxmlsetups tabulate
+% \starttabulate[||p|]
+% \xmlall{#1}{/body/row}
+% \stoptabulate
+% \stopxmlsetups
+% \startxmlsetups tabulate:row
+% \NC \xmlall{#1}{/cell} \NR
+% \stopxmlsetups
+% \startxmlsetups tabulate:cell
+% \xmlflush{#1} \NC
+% \stopxmlsetups
+
+% \startxmlsetups combination
+% \startcollecting
+% \startcollect
+% \startcombination[\xmlatt{#1}{nx}*\xmlatt{#1}{ny}]
+% \stopcollect
+% \xmlloop {#1} {combiblock} {
+% \startcollect
+% {\xmli{/content}{##1}}
+% {\xmli{/caption}{##1}}
+% \stopcollect
+% }
+% \startcollect
+% \stopcombination
+% \stopcollect
+% \stopcollecting
+% \stopxmlsetups
diff --git a/tex/context/interface/cont-cz.xml b/tex/context/interface/cont-cz.xml
index c177b181e..11174cbbe 100644
--- a/tex/context/interface/cont-cz.xml
+++ b/tex/context/interface/cont-cz.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-de.xml b/tex/context/interface/cont-de.xml
index 28b58b381..5cae23ebe 100644
--- a/tex/context/interface/cont-de.xml
+++ b/tex/context/interface/cont-de.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-en.xml b/tex/context/interface/cont-en.xml
index fc2c28240..9ff000b2c 100644
--- a/tex/context/interface/cont-en.xml
+++ b/tex/context/interface/cont-en.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-fr.xml b/tex/context/interface/cont-fr.xml
index ac5186a6d..aed3c6efb 100644
--- a/tex/context/interface/cont-fr.xml
+++ b/tex/context/interface/cont-fr.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-it.xml b/tex/context/interface/cont-it.xml
index b723620f5..0b5c91052 100644
--- a/tex/context/interface/cont-it.xml
+++ b/tex/context/interface/cont-it.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-nl.xml b/tex/context/interface/cont-nl.xml
index 28bbc4003..02399e877 100644
--- a/tex/context/interface/cont-nl.xml
+++ b/tex/context/interface/cont-nl.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/cont-ro.xml b/tex/context/interface/cont-ro.xml
index 40ac61844..0f34ae02a 100644
--- a/tex/context/interface/cont-ro.xml
+++ b/tex/context/interface/cont-ro.xml
@@ -10021,3 +10021,4 @@
</cd:command>
</cd:interface>
+
diff --git a/tex/context/interface/keys-cz.xml b/tex/context/interface/keys-cz.xml
index e312d3f17..068d08fec 100644
--- a/tex/context/interface/keys-cz.xml
+++ b/tex/context/interface/keys-cz.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml
index 10069b1de..a7488a838 100644
--- a/tex/context/interface/keys-de.xml
+++ b/tex/context/interface/keys-de.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml
index 3a6f3020d..a9a2d6262 100644
--- a/tex/context/interface/keys-en.xml
+++ b/tex/context/interface/keys-en.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml
index d12427994..cbbcd926c 100644
--- a/tex/context/interface/keys-fr.xml
+++ b/tex/context/interface/keys-fr.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml
index b153aa4c8..d2061a6c7 100644
--- a/tex/context/interface/keys-it.xml
+++ b/tex/context/interface/keys-it.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml
index 441d7963c..d38260a5e 100644
--- a/tex/context/interface/keys-nl.xml
+++ b/tex/context/interface/keys-nl.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml
index 4b8f49e13..d08f55ab3 100644
--- a/tex/context/interface/keys-ro.xml
+++ b/tex/context/interface/keys-ro.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2007.09.10 21:31">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2007.09.28 11:58">
<cd:variables>
<cd:variable name="lesshyphenation" value="lesshyphenation"/>
diff --git a/tex/context/test/x-cals-test.cdx b/tex/context/test/x-cals-test.cdx
index e87a947ef..ce90883fa 100644
--- a/tex/context/test/x-cals-test.cdx
+++ b/tex/context/test/x-cals-test.cdx
@@ -1,6 +1,31 @@
-<?xml version="1.0"?>
+<?xml version="1.0" standalone="yes"?>
<directives>
- <directive id="100" setup="xml:directive:noframe"/>
- <directive id="101" setup="xml:directive:colors"/>
+
+ <!--
+ <directive attribute='id' value="100" setup="cdx:100"/>
+ <directive attribute='id' value="101" setup="cdx:101"/>
+ -->
+
+ <!--
+ <directive element="cals:table" attribute='cdx' value="colors" setup="cdx:cals:table:colors"/>
+ <directive element="cals:table" attribute='cdx' value="vertical" setup="cdx:cals:table:vertical"/>
+ <directive element="cals:table" attribute='cdx' value="noframe" setup="cdx:cals:table:noframe"/>
+ -->
+
+ <!--
+ <directive element="cals:table" attribute='cdx' value="*" setup="cdx:cals:table:*"/>
+ <directive element="cals:table" attribute='cdx' value="*" before="cdx:cals:table:before:*"/>
+ <directive element="cals:table" attribute='cdx' value="*" after="cdx:cals:table:after:*"/>
+ -->
+
+ <directive
+ element="cals:table"
+ attribute='cdx'
+ value="*"
+ setup="cdx:cals:table:*"
+ before="cdx:cals:table:before:*"
+ after="cdx:cals:table:after:*"
+ />
+
</directives>
diff --git a/tex/context/test/x-cals-test.tex b/tex/context/test/x-cals-test.tex
index dacfc9626..30645c2bd 100644
--- a/tex/context/test/x-cals-test.tex
+++ b/tex/context/test/x-cals-test.tex
@@ -4,16 +4,44 @@
\setupcolors[state=start]
-\startsetups xml:directive:noframe
+\startsetups cdx:cals:table:noframe
\setupTABLE[frame=off]
\stopsetups
-\startsetups xml:directive:colors
+\startsetups cdx:cals:table:colors
\setupTABLE[row] [odd] [frame=off,background=color,backgroundcolor=red]
\setupTABLE[row] [even][frame=off,background=color,backgroundcolor=green]
\setupTABLE[column][2] [frame=off,background=color,backgroundcolor=blue]
\stopsetups
+\startsetups cdx:cals:table:vertical
+ \setupTABLE[row] [odd] [frame=off,background=color,backgroundcolor=lightblue]
+\stopsetups
+
+\startsetups cdx:cals:table:horizontal
+ \setupTABLE[column] [odd] [frame=off,background=color,backgroundcolor=lightblue]
+\stopsetups
+
+\startsetups cdx:cals:table:before:frame
+ \framed [offset=overlay,frame=off,topframe=on,bottomframe=on,rulethickness=2pt,framecolor=red,align=normal] \bgroup
+ \vskip2pt
+ \framed [offset=overlay,frame=off,leftframe=on,rightframe=on,rulethickness=1pt,framecolor=red,align=normal] \bgroup
+\stopsetups
+
+\startsetups cdx:cals:table:after:frame
+ \egroup
+ \vskip2pt
+ \egroup
+\stopsetups
+
+% \startxmlsetups xml:cals:process
+% \xmlsetsetup {\xmldocument} {cals:table} {*}
+% \stopxmlsetups
+% \startxmlsetups cals:table
+% \ctxlua{lxml.cals.table("#1")}
+% \stopxmlsetups
+% \xmlregistersetup{xml:cals:process}
+
\starttext
\xmlloaddirectives{x-cals-test.cdx}
\xmlprocess{main}{x-cals-test.xml}{}
diff --git a/tex/context/test/x-cals-test.xml b/tex/context/test/x-cals-test.xml
index 55e495c77..a41691acb 100644
--- a/tex/context/test/x-cals-test.xml
+++ b/tex/context/test/x-cals-test.xml
@@ -7,8 +7,80 @@
<root xmlns:cals="http://www.someplace.org/cals"
xmlns:c="http://www.someplace.org/cals">
- <c:table id="100">
- <c:tgroup cols="2">
+ <c:table cdx="vertical">
+ <c:tgroup cols="3">
+ <c:thead>
+ <c:row>
+ <c:entry>alpha</c:entry>
+ <c:entry>beta</c:entry>
+ <c:entry>gamma</c:entry>
+ </c:row>
+ </c:thead>
+ <c:tbody>
+ <c:row>
+ <c:entry>one</c:entry>
+ <c:entry>two</c:entry>
+ <c:entry>three</c:entry>
+ </c:row>
+ <c:row>
+ <c:entry>four</c:entry>
+ <c:entry>five</c:entry>
+ <c:entry>six</c:entry>
+ </c:row>
+ </c:tbody>
+ </c:tgroup>
+ </c:table>
+
+ <c:table cdx="horizontal">
+ <c:tgroup cols="3">
+ <c:thead>
+ <c:row>
+ <c:entry>alpha</c:entry>
+ <c:entry>beta</c:entry>
+ <c:entry>gamma</c:entry>
+ </c:row>
+ </c:thead>
+ <c:tbody>
+ <c:row>
+ <c:entry>one</c:entry>
+ <c:entry>two</c:entry>
+ <c:entry>three</c:entry>
+ </c:row>
+ <c:row>
+ <c:entry>four</c:entry>
+ <c:entry>five</c:entry>
+ <c:entry>six</c:entry>
+ </c:row>
+ </c:tbody>
+ </c:tgroup>
+ </c:table>
+
+ <c:table cdx="frame">
+ <c:tgroup cols="3">
+ <c:thead>
+ <c:row>
+ <c:entry>alpha</c:entry>
+ <c:entry>beta</c:entry>
+ <c:entry>gamma</c:entry>
+ </c:row>
+ </c:thead>
+ <c:tbody>
+ <c:row>
+ <c:entry>one</c:entry>
+ <c:entry>two</c:entry>
+ <c:entry>three</c:entry>
+ </c:row>
+ <c:row>
+ <c:entry>four</c:entry>
+ <c:entry>five</c:entry>
+ <c:entry>six</c:entry>
+ </c:row>
+ </c:tbody>
+ </c:tgroup>
+ </c:table>
+
+ <c:table cdx="colors">
+ <c:tgroup cols="3">
<c:colspec colnum="1" colwidth="4cm" colname="first"/>
<c:colspec colnum="2" colname="second"/>
<c:thead>
@@ -32,7 +104,7 @@
</c:tgroup>
</c:table>
- <cals:table id="101">
+ <cals:table cdx="noframe">
<cals:tgroup cols="2">
<cals:colspec colnum="1" colwidth="4cm" colname="first"/>
<cals:colspec colnum="2" colname="second"/>
diff --git a/tex/context/test/x-ct-test.tex b/tex/context/test/x-ct-test.tex
new file mode 100644
index 000000000..d47563e84
--- /dev/null
+++ b/tex/context/test/x-ct-test.tex
@@ -0,0 +1,7 @@
+% engine=luatex
+
+\usemodule[x][ct]
+
+\starttext
+ \xmlprocess{main}{x-ct-test.xml}{}
+\stoptext
diff --git a/tex/context/test/x-ct-test.xml b/tex/context/test/x-ct-test.xml
new file mode 100644
index 000000000..e61abb054
--- /dev/null
+++ b/tex/context/test/x-ct-test.xml
@@ -0,0 +1,149 @@
+<?xml version='1.0' standalone='yes' ?>
+
+<root xmlns:ct="http://www.pragma-ade.com/context">
+
+ one:
+
+ <tabulate xmlns="http://www.pragma-ade.com/context">
+ <template>
+ <column align='flushleft'/>
+ <column align='flushright'/>
+ <column align='center'/>
+ </template>
+ <body>
+ <row>
+ <cell>one</cell>
+ <cell>two</cell>
+ <cell>three</cell>
+ </row>
+ <row>
+ <cell>a</cell>
+ <cell>b</cell>
+ <cell>c</cell>
+ </row>
+ <row>
+ <cell>alpha</cell>
+ <cell>beta</cell>
+ <cell>gamma</cell>
+ </row>
+ </body>
+ </tabulate>
+
+ two:
+
+ <context:tabulate>
+ <context:template>
+ <context:column align='flushleft'/>
+ <context:column align='flushright'/>
+ <context:column align='center'/>
+ </context:template>
+ <context:body>
+ <context:row>
+ <context:cell>one</context:cell>
+ <context:cell>two</context:cell>
+ <context:cell>three</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>a</context:cell>
+ <context:cell>b</context:cell>
+ <context:cell>c</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>alpha</context:cell>
+ <context:cell>beta</context:cell>
+ <context:cell>gamma</context:cell>
+ </context:row>
+ </context:body>
+ </context:tabulate>
+
+ three:
+
+ <context:tabulate>
+ <context:body>
+ <context:row>
+ <context:cell>one</context:cell>
+ <context:cell>two</context:cell>
+ <context:cell>three</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>a</context:cell>
+ <context:cell>b</context:cell>
+ <context:cell>c</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>alpha</context:cell>
+ <context:cell>beta</context:cell>
+ <context:cell>gamma</context:cell>
+ </context:row>
+ </context:body>
+ </context:tabulate>
+
+ four:
+
+ <context:tabulate template="|l|l|l|">
+ <context:body>
+ <context:row>
+ <context:cell>one</context:cell>
+ <context:cell>two</context:cell>
+ <context:cell>three</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>a</context:cell>
+ <context:cell>b</context:cell>
+ <context:cell>c</context:cell>
+ </context:row>
+ <context:row>
+ <context:cell>alpha</context:cell>
+ <context:cell>beta</context:cell>
+ <context:cell>gamma</context:cell>
+ </context:row>
+ </context:body>
+ </context:tabulate>
+
+ five:
+
+ <ct:combination nx='3' ny='2'>
+ <ct:pair>
+ <ct:content>some content 1</ct:content>
+ <ct:caption>caption a</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 2</ct:content>
+ <ct:caption>caption b</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 3</ct:content>
+ <ct:caption>caption c</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 4</ct:content>
+ <ct:caption>caption d</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 5</ct:content>
+ <ct:caption>caption e</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 6</ct:content>
+ <ct:caption>caption f</ct:caption>
+ </ct:pair>
+ </ct:combination>
+
+ six:
+
+ <ct:combination>
+ <ct:pair>
+ <ct:content>some content 1</ct:content>
+ <ct:caption>caption a</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 2</ct:content>
+ <ct:caption>caption b</ct:caption>
+ </ct:pair>
+ <ct:pair>
+ <ct:content>some content 3</ct:content>
+ <ct:caption>caption c</ct:caption>
+ </ct:pair>
+ </ct:combination>
+
+</ct:root>