From e12b4fabeb0ce3ce6d256b54250cf38a8f940561 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 6 Mar 2023 15:17:09 +0100 Subject: 2023-03-06 14:47:00 --- .../general/manuals/luametatex/luametatex.tex | 7 + scripts/context/lua/mtxrun.lua | 42 ++++- scripts/context/stubs/mswin/mtxrun.lua | 42 ++++- scripts/context/stubs/unix/mtxrun | 42 ++++- scripts/context/stubs/win64/mtxrun.lua | 42 ++++- source/luametatex/build.sh | 9 ++ source/luametatex/cmake/luametatex.cmake | 10 +- source/luametatex/cmake/mingw-64-ucrt.cmake | 14 ++ source/luametatex/source/lua/lmtenginelib.c | 35 +++-- source/luametatex/source/luametatex.h | 6 +- source/luametatex/source/luarest/lmtfilelib.c | 83 +++------- source/luametatex/source/utilities/auxfile.c | 53 ++++++- source/luametatex/source/utilities/auxfile.h | 2 + tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkii/mult-ro.mkii | 2 + tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/data-ini.lua | 20 +++ tex/context/base/mkiv/l-dir.lua | 2 +- tex/context/base/mkiv/l-file.lua | 22 ++- tex/context/base/mkiv/lang-txt.lua | 93 ++++++++++-- tex/context/base/mkiv/mult-def.lua | 8 + tex/context/base/mkiv/page-flt.lua | 8 +- tex/context/base/mkiv/status-files.pdf | Bin 24601 -> 24648 bytes tex/context/base/mkiv/status-lua.pdf | Bin 265852 -> 266020 bytes tex/context/base/mkiv/strc-def.mkiv | 2 + tex/context/base/mkiv/util-sql-imp-client.lua | 2 +- tex/context/base/mkiv/util-sql-imp-ffi.lua | 2 +- tex/context/base/mkiv/util-sql-imp-library.lua | 2 +- tex/context/base/mkiv/util-sql-imp-sqlite.lua | 1 + tex/context/base/mkiv/util-sql.lua | 29 +++- tex/context/base/mkxl/cont-new.mkxl | 2 +- tex/context/base/mkxl/context.mkxl | 2 +- tex/context/base/mkxl/core-con.mkxl | 25 ++- tex/context/base/mkxl/core-uti.lmt | 60 +++----- tex/context/base/mkxl/lang-lab.lmt | 37 +++-- tex/context/base/mkxl/lang-lab.mkxl | 10 +- tex/context/base/mkxl/libs-imp-sqlite.lmt | 1 + tex/context/base/mkxl/lpdf-mis.lmt | 17 +-- tex/context/base/mkxl/math-ali.mkxl | 60 +++++++- tex/context/base/mkxl/math-def.mkxl | 5 + tex/context/base/mkxl/math-ini.mkxl | 160 ++++++++++++++----- tex/context/base/mkxl/math-spa.lmt | 137 +++++++++++++---- tex/context/base/mkxl/mult-dim.mklx | 2 +- tex/context/base/mkxl/node-ali.lmt | 15 +- tex/context/base/mkxl/node-aux.lmt | 16 ++ tex/context/base/mkxl/page-one.mkxl | 91 +++++++++-- tex/context/base/mkxl/page-sel.lmt | 2 +- tex/context/base/mkxl/page-txt.mklx | 21 ++- tex/context/base/mkxl/strc-def.mkxl | 2 + tex/context/base/mkxl/strc-flt.mklx | 16 +- tex/context/base/mkxl/strc-itm.mklx | 19 ++- tex/context/base/mkxl/strc-lst.lmt | 138 ++++++++++++----- tex/context/base/mkxl/strc-lst.mklx | 6 + tex/context/base/mkxl/strc-mat.mkxl | 30 ++-- tex/context/base/mkxl/strc-ref.lmt | 169 ++++++++++++++++----- tex/context/base/mkxl/strc-ref.mklx | 2 +- tex/context/base/mkxl/strc-reg.lmt | 148 +++++++++++++----- tex/context/base/mkxl/strc-reg.mkxl | 122 +++++++++++++-- tex/context/base/mkxl/strc-sec.mkxl | 15 +- tex/context/base/mkxl/tabl-tbl.mkxl | 16 +- tex/context/base/mkxl/tabl-xtb.lmt | 4 +- tex/context/base/mkxl/task-ini.lmt | 1 + tex/context/base/mkxl/typo-scr.mkxl | 38 ++++- tex/context/base/mkxl/typo-wrp.lmt | 95 +++++++++++- tex/context/base/mkxl/typo-wrp.mkxl | 13 ++ tex/context/interface/mkii/keys-ro.xml | 2 + tex/generic/context/luatex/luatex-fonts-merged.lua | 22 ++- 69 files changed, 1615 insertions(+), 494 deletions(-) create mode 100644 source/luametatex/cmake/mingw-64-ucrt.cmake diff --git a/doc/context/sources/general/manuals/luametatex/luametatex.tex b/doc/context/sources/general/manuals/luametatex/luametatex.tex index bb20761bc..f845fed17 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex.tex @@ -105,6 +105,13 @@ % means that 43 pages per seconds is now the new normal but that might of course % become less again as we evolve. +% End Feburari 2023 I observed 8.2 seconds for 360 pages and making a format needed +% 1.9 seconds instead if the usual 2.1 but that can be a side effect of the terminal +% because the amount of output which is sensitive for refresh delays set. The new +% target is nwo 50 pages per second for this manual but on this laptop that is +% unlikely to happen any time soon. With tabulateusesize and tabulatesparseskips +% experimends enabled we needed 8.1 second and 44.3 pps. + % \enableexperiments [tabulateusesize] % \enableexperiments [tabulatesparseskips] diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index a00dc5928..e53152d53 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -4298,7 +4298,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-file"] = package.loaded["l-file"] or true --- original size: 22186, stripped down to: 10313 +-- original size: 22637, stripped down to: 10595 if not modules then modules={} end modules ['l-file']={ version=1.001, @@ -4704,9 +4704,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end @@ -20734,7 +20748,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 10947, stripped down to: 7176 +-- original size: 11605, stripped down to: 7467 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -20801,6 +20815,20 @@ do local ownpath=environment.ownpath or os.selfdir ownbin=file.collapsepath(ownbin) ownpath=file.collapsepath(ownpath) + local symlinktarget=lfs.symlinktarget + if symlinktarget then + while true do + local new=symlinktarget(ownpath) or ownpath + if new==ownpath then + break + else + ownpath=new + end + end + ownpath=file.collapsepath(ownpath) + else + lfs.symlinktarget=function() return nil end + end if not ownpath or ownpath=="" or ownpath=="unset" then ownpath=args[-1] or arg[-1] ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) @@ -26072,8 +26100,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1034927 --- stripped bytes : 407861 +-- original bytes : 1036036 +-- stripped bytes : 408397 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index a00dc5928..e53152d53 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -4298,7 +4298,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-file"] = package.loaded["l-file"] or true --- original size: 22186, stripped down to: 10313 +-- original size: 22637, stripped down to: 10595 if not modules then modules={} end modules ['l-file']={ version=1.001, @@ -4704,9 +4704,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end @@ -20734,7 +20748,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 10947, stripped down to: 7176 +-- original size: 11605, stripped down to: 7467 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -20801,6 +20815,20 @@ do local ownpath=environment.ownpath or os.selfdir ownbin=file.collapsepath(ownbin) ownpath=file.collapsepath(ownpath) + local symlinktarget=lfs.symlinktarget + if symlinktarget then + while true do + local new=symlinktarget(ownpath) or ownpath + if new==ownpath then + break + else + ownpath=new + end + end + ownpath=file.collapsepath(ownpath) + else + lfs.symlinktarget=function() return nil end + end if not ownpath or ownpath=="" or ownpath=="unset" then ownpath=args[-1] or arg[-1] ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) @@ -26072,8 +26100,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1034927 --- stripped bytes : 407861 +-- original bytes : 1036036 +-- stripped bytes : 408397 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index a00dc5928..e53152d53 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -4298,7 +4298,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-file"] = package.loaded["l-file"] or true --- original size: 22186, stripped down to: 10313 +-- original size: 22637, stripped down to: 10595 if not modules then modules={} end modules ['l-file']={ version=1.001, @@ -4704,9 +4704,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end @@ -20734,7 +20748,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 10947, stripped down to: 7176 +-- original size: 11605, stripped down to: 7467 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -20801,6 +20815,20 @@ do local ownpath=environment.ownpath or os.selfdir ownbin=file.collapsepath(ownbin) ownpath=file.collapsepath(ownpath) + local symlinktarget=lfs.symlinktarget + if symlinktarget then + while true do + local new=symlinktarget(ownpath) or ownpath + if new==ownpath then + break + else + ownpath=new + end + end + ownpath=file.collapsepath(ownpath) + else + lfs.symlinktarget=function() return nil end + end if not ownpath or ownpath=="" or ownpath=="unset" then ownpath=args[-1] or arg[-1] ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) @@ -26072,8 +26100,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1034927 --- stripped bytes : 407861 +-- original bytes : 1036036 +-- stripped bytes : 408397 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index a00dc5928..e53152d53 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -4298,7 +4298,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-file"] = package.loaded["l-file"] or true --- original size: 22186, stripped down to: 10313 +-- original size: 22637, stripped down to: 10595 if not modules then modules={} end modules ['l-file']={ version=1.001, @@ -4704,9 +4704,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end @@ -20734,7 +20748,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-ini"] = package.loaded["data-ini"] or true --- original size: 10947, stripped down to: 7176 +-- original size: 11605, stripped down to: 7467 if not modules then modules={} end modules ['data-ini']={ version=1.001, @@ -20801,6 +20815,20 @@ do local ownpath=environment.ownpath or os.selfdir ownbin=file.collapsepath(ownbin) ownpath=file.collapsepath(ownpath) + local symlinktarget=lfs.symlinktarget + if symlinktarget then + while true do + local new=symlinktarget(ownpath) or ownpath + if new==ownpath then + break + else + ownpath=new + end + end + ownpath=file.collapsepath(ownpath) + else + lfs.symlinktarget=function() return nil end + end if not ownpath or ownpath=="" or ownpath=="unset" then ownpath=args[-1] or arg[-1] ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) @@ -26072,8 +26100,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1034927 --- stripped bytes : 407861 +-- original bytes : 1036036 +-- stripped bytes : 408397 -- end library merge diff --git a/source/luametatex/build.sh b/source/luametatex/build.sh index 60e7d13d5..56ed63497 100644 --- a/source/luametatex/build.sh +++ b/source/luametatex/build.sh @@ -33,6 +33,15 @@ then cd build/mingw-32 cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw-32.cmake ../.. +elif [ "$1" = "mingw-64-ucrt" ] || [ "$1" = "mingw64ucrt" ] || [ "$1" = "--mingw64ucrt" ] || [ "$1" = "ucrt" ] || [ "$1" = "--ucrt" ] +then + + PLATFORM="win64" + SUFFIX=".exe" + mkdir -p build/mingw-64-ucrt + cd build/mingw-64-ucrt + cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=./cmake/mingw-64-ucrt.cmake ../.. + else PLATFORM="native" diff --git a/source/luametatex/cmake/luametatex.cmake b/source/luametatex/cmake/luametatex.cmake index 396b33d5a..eabef915b 100644 --- a/source/luametatex/cmake/luametatex.cmake +++ b/source/luametatex/cmake/luametatex.cmake @@ -25,9 +25,13 @@ target_link_libraries(luametatex miniz ) -target_link_libraries(luametatex - ${CMAKE_DL_LIBS} -) +if (LUAMETATEX_NOLDL) + # mingw ucrt +else() + target_link_libraries(luametatex + ${CMAKE_DL_LIBS} + ) +endif() install(TARGETS luametatex EXPORT luametatex diff --git a/source/luametatex/cmake/mingw-64-ucrt.cmake b/source/luametatex/cmake/mingw-64-ucrt.cmake new file mode 100644 index 000000000..c5f3915ff --- /dev/null +++ b/source/luametatex/cmake/mingw-64-ucrt.cmake @@ -0,0 +1,14 @@ +# if (NOT __MINGW64_TOOLCHAIN_) +# add_compile_options(-DLUASOCKET_INET_PTON) +# endif() + +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32ucrt) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) + +add_compile_options(-mtune=nocona) + +set(LUAMETATEX_MINGW 64) +set(LUAMETATEX_NOLDL 1) + +# set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc") diff --git a/source/luametatex/source/lua/lmtenginelib.c b/source/luametatex/source/lua/lmtenginelib.c index fef2ed819..8e99aa29a 100644 --- a/source/luametatex/source/lua/lmtenginelib.c +++ b/source/luametatex/source/lua/lmtenginelib.c @@ -32,8 +32,10 @@ typedef struct environment_state_info { char *ownbase; char *ownname; char *owncore; + char *ownlink; char *input_name; int luatex_lua_offset; + int padding; } environment_state_info; static environment_state_info lmt_environment_state = { @@ -47,8 +49,10 @@ static environment_state_info lmt_environment_state = { .ownbase = NULL, .ownname = NULL, .owncore = NULL, + .ownlink = NULL, .input_name = NULL, .luatex_lua_offset = 0, + .padding = 0, }; /*tex todo: make helpers in loslibext which has similar code */ @@ -57,18 +61,21 @@ static void enginelib_splitnames(void) { char *p = lmt_memory_strdup(lmt_environment_state.ownpath); /*tex We need to make copies! */ /* - printf("ownpath = %s\n",environment_state.ownpath); - printf("ownbase = %s\n",environment_state.ownbase); - printf("ownname = %s\n",environment_state.ownname); - printf("owncore = %s\n",environment_state.owncore); + We loose some here but not enough to worry about. Maybe eventually we will use our own + |basename| and |dirname| anyway. I need to check if all are set to something we can + indeed free. */ /* - We loose some here but not enough to worry about. Maybe eventually we will use our own - |basename| and |dirname| anyway. + if (lmt_environment_state.ownbase) { lmt_memory_free(lmt_environment_state.ownbase); } + if (lmt_environment_state.ownname) { lmt_memory_free(lmt_environment_state.ownbase); } + if (lmt_environment_state.ownpath) { lmt_memory_free(lmt_environment_state.ownbase); } + if (lmt_environment_state.ownlink) { lmt_memory_free(lmt_environment_state.ownlink); } */ + /* */ lmt_environment_state.ownbase = aux_basename(lmt_memory_strdup(p)); lmt_environment_state.ownname = aux_basename(lmt_memory_strdup(p)); lmt_environment_state.ownpath = aux_dirname(lmt_memory_strdup(p)); /* We could use p and not free later, but this is cleaner. */ + lmt_environment_state.ownlink = aux_utf8_readlink(lmt_environment_state.ownpath); /* */ for (size_t i = 0; i < strlen(lmt_environment_state.ownname); i++) { if (lmt_environment_state.ownname[i] == '.') { @@ -77,12 +84,6 @@ static void enginelib_splitnames(void) } } lmt_environment_state.owncore = lmt_memory_strdup(lmt_environment_state.ownname); - /* - printf("ownpath = %s\n",environment_state.ownpath); - printf("ownbase = %s\n",environment_state.ownbase); - printf("ownname = %s\n",environment_state.ownname); - printf("owncore = %s\n",environment_state.owncore); - */ lmt_memory_free(p); } @@ -221,7 +222,7 @@ static void enginelib_show_version_info(void) "\n" "Functionality : level " LMT_TOSTRING(luametatex_development_id) "\n" "Support : " luametatex_support_address "\n" - "Copyright : The Lua(Meta)TeX Team(s) (2005-2022+)\n" + "Copyright : The Lua(Meta)TeX Team(s) (2005-2023+)\n" "\n" "The LuaMetaTeX project is related to ConTeXt development. This macro package\n" "tightly integrates TeX and MetaPost in close cooperation with Lua. Updates will\n" @@ -333,6 +334,11 @@ static void enginelib_show_credits(void) "compiler : " LMT_COMPILER_USED "\n" # endif ); + printf("own path : %s\n", lmt_environment_state.ownpath); + printf("own base : %s\n", lmt_environment_state.ownbase); + printf("own name : %s\n", lmt_environment_state.ownname); + printf("own core : %s\n", lmt_environment_state.owncore); + printf("own link : %s\n", lmt_environment_state.ownlink ? lmt_environment_state.ownlink : ""); exit(EXIT_SUCCESS); } @@ -357,7 +363,7 @@ static void enginelib_prepare_cmdline(int zero_offset) lua_set_string_by_key(L, "selfbin", lmt_environment_state.argv[0]); lua_set_string_by_key(L, "selfpath", lmt_environment_state.ownpath); lua_set_string_by_key(L, "selfdir", lmt_environment_state.ownpath); /* for old times sake */ - lua_set_string_by_key(L, "selfbase", lmt_environment_state.ownbase); + lua_set_string_by_key(L, "selflink", lmt_environment_state.ownlink); lua_set_string_by_key(L, "selfname", lmt_environment_state.ownname); lua_set_string_by_key(L, "selfcore", lmt_environment_state.owncore); lua_createtable(L, lmt_environment_state.argc, 0); @@ -613,6 +619,7 @@ void tex_engine_initialize(int ac, char **av) lmt_engine_state.luatex_banner = lmt_memory_strdup(lmt_version_state.banner); /* preparations */ lmt_environment_state.ownpath = aux_utf8_getownpath(lmt_environment_state.argv[0]); + lmt_environment_state.ownlink = aux_utf8_readlink(lmt_environment_state.ownpath); enginelib_splitnames(); aux_set_run_time(); /*tex diff --git a/source/luametatex/source/luametatex.h b/source/luametatex/source/luametatex.h index 410d4dd68..4d79c6cf2 100644 --- a/source/luametatex/source/luametatex.h +++ b/source/luametatex/source/luametatex.h @@ -90,9 +90,9 @@ # include "tex/textypes.h" # define luametatex_version 210 -# define luametatex_revision 06 -# define luametatex_version_string "2.10.06" -# define luametatex_development_id 20230224 +# define luametatex_revision 07 +# define luametatex_version_string "2.10.07" +# define luametatex_development_id 20230306 # define luametatex_name_camelcase "LuaMetaTeX" # define luametatex_name_lowercase "luametatex" diff --git a/source/luametatex/source/luarest/lmtfilelib.c b/source/luametatex/source/luarest/lmtfilelib.c index 8a814d713..f78c05e64 100644 --- a/source/luametatex/source/luarest/lmtfilelib.c +++ b/source/luametatex/source/luarest/lmtfilelib.c @@ -37,6 +37,7 @@ # include "../lua/lmtinterface.h" # include "../utilities/auxmemory.h" +# include "../utilities/auxfile.h" # ifndef R_OK # define F_OK 0x0 @@ -107,8 +108,6 @@ # ifdef _WIN32 - # include "../utilities/auxfile.h" - # ifndef S_ISDIR # define S_ISDIR(mode) (mode & _S_IFDIR) # endif @@ -173,11 +172,15 @@ return r; } + // # if defined(__MINGW64__) || defined(__MINGW32__) + // extern int CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags); + // # endif + static int mk_symlink(const char *t, const char *f) { LPWSTR wt = aux_utf8_to_wide(t); LPWSTR wf = aux_utf8_to_wide(f); - int r = (CreateSymbolicLinkA(t, f, 0x2) != 0); + int r = CreateSymbolicLinkW((LPCWSTR) t, (LPCWSTR) f, 0x2) != 0; lmt_memory_free(wt); lmt_memory_free(wf); return r; @@ -187,7 +190,7 @@ { LPWSTR wt = aux_utf8_to_wide(t); LPWSTR wf = aux_utf8_to_wide(f); - int r = (CreateSymbolicLinkA(t, f, 0x3) != 0); + int r = CreateSymbolicLinkW((LPCWSTR) t, (LPCWSTR) f, 0x3) != 0; lmt_memory_free(wt); lmt_memory_free(wf); return r; @@ -290,7 +293,7 @@ static int filelib_chdir(lua_State *L) { lua_pushboolean(L, 0); break; } else if (_wgetcwd(wpath, size)) { - char * path = aux_utf8_from_wide(wpath); + char *path = aux_utf8_from_wide(wpath); lua_pushstring(L, path); lmt_memory_free(path); break; @@ -787,64 +790,16 @@ static int filelib_setexecutable(lua_State *L) link("name","target") : targetname */ -// # ifdef _WIN32 -// -// static int filelib_symlinkattributes(lua_State *L) -// { -// lua_pushnil(L); -// return 1; -// } -// -// # else -// -// static int push_link_target(lua_State *L) -// { -// const char *file = luaL_checkstring(L, 1); -// char *target = NULL; -// int tsize, size = 256; /* size = initial buffer capacity */ -// while (1) { -// target = lmt_memory_realloc(target, size); -// if (! target) { -// return 0; -// } -// tsize = readlink(file, target, size); -// if (tsize < 0) { -// /* error */ -// lmt_memory_free(target); -// return 0; -// } -// if (tsize < size) { -// break; -// } -// /* possibly truncated readlink() result, double size and retry */ -// size *= 2; -// } -// target[tsize] = '\0'; -// lua_pushlstring(L, target, tsize); -// lmt_memory_free(target); -// return 1; -// } -// -// static int filelib_symlinkattributes(lua_State *L) -// { -// if (lua_isstring(L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) { -// if (! push_link_target(L)) { -// lua_pushnil(L); -// } -// } else { -// int ret = filelib_attributes(L); -// if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) { -// if (push_link_target(L)) { -// lua_setfield(L, -2, "target"); -// } -// } else { -// lua_pushnil(L); -// } -// } -// return 1; -// } -// -// # endif +static int filelib_symlinktarget(lua_State *L) +{ + const char *file = aux_utf8_readlink(luaL_checkstring(L, 1)); + if (file) { + lua_pushstring(L, file); + } else { + lua_pushnil(L); + } + return 1; +} static const struct luaL_Reg filelib_function_list[] = { { "attributes", filelib_attributes }, @@ -858,7 +813,7 @@ static const struct luaL_Reg filelib_function_list[] = { { "link", filelib_link }, { "symlink", filelib_symlink }, { "setexecutable", filelib_setexecutable }, - /* { "symlinkattributes", filelib_symlinkattributes }, */ + { "symlinktarget", filelib_symlinktarget }, /* */ { "isdir", filelib_isdir }, { "isfile", filelib_isfile }, diff --git a/source/luametatex/source/utilities/auxfile.c b/source/luametatex/source/utilities/auxfile.c index 0021cb229..c4a03d605 100644 --- a/source/luametatex/source/utilities/auxfile.c +++ b/source/luametatex/source/utilities/auxfile.c @@ -14,6 +14,7 @@ # include # include # include + # include LPWSTR aux_utf8_to_wide(const char *utf8str) { if (utf8str) { @@ -123,7 +124,7 @@ if (file) { char *path = NULL; char buffer[MAX_PATH]; - GetModuleFileName(NULL,buffer,sizeof(buffer)); + GetModuleFileName(NULL, buffer, sizeof(buffer)); path = lmt_memory_strdup(buffer); if (strlen(path) > 0) { for (size_t i = 0; i < strlen(path); i++) { @@ -137,6 +138,31 @@ return lmt_memory_strdup("."); } + /*tex We alwways return a copy so that we're consistent with windows/unix. */ + + // # if defined(__MINGW64__) || defined(__MINGW32__) + // extern DWORD GetFinalPathNameByHandleW(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags); + // # endif + + char *aux_utf8_readlink(const char *file) + { + LPWSTR wide = aux_utf8_to_wide(file); + HANDLE handle = CreateFileW(wide, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + char *link = NULL; + if (handle == INVALID_HANDLE_VALUE) { + LPWSTR path = (LPWSTR) lmt_memory_malloc((MAX_PATH+1) * sizeof(WCHAR)); + DWORD size = GetFinalPathNameByHandleW(handle, path, MAX_PATH, VOLUME_NAME_NT); + if (size > 0 && size < MAX_PATH) { + path[size] = '\0'; + link = aux_utf8_from_wide(path); + } + lmt_memory_free(path); + } + CloseHandle(handle); + lmt_memory_free(wide); + return link ? link : lmt_memory_strdup(file); + } + # else # include @@ -209,6 +235,31 @@ } } + /*tex We alwways return a copy so that we're consistent with windows/unix. */ + + char *aux_utf8_readlink(const char *file) + { + int size = 256; + while (1) { + char *target = lmt_memory_malloc(size); + if (! target) { + break; + } else { + int tsize = readlink(file, target, size); + if (tsize <= 0) { + lmt_memory_free(target); + break; + } else if (tsize < size) { + target[tsize] = '\0'; + return target; + } else { + size *= 2; + } + } + } + return lmt_memory_strdup(file); + } + # endif # ifndef S_ISREG diff --git a/source/luametatex/source/utilities/auxfile.h b/source/luametatex/source/utilities/auxfile.h index 19a4815c2..8ed4dee40 100644 --- a/source/luametatex/source/utilities/auxfile.h +++ b/source/luametatex/source/utilities/auxfile.h @@ -107,6 +107,7 @@ extern int aux_utf8_rename (const char *oldname, const char *newname); extern int aux_utf8_setargv (char * **av, char **argv, int argc); extern char *aux_utf8_getownpath (const char *file); + extern char *aux_utf8_readlink (const char *file); # else @@ -118,6 +119,7 @@ extern int aux_utf8_setargv (char * **av, char **argv, int argc); extern char *aux_utf8_getownpath (const char *file); + extern char *aux_utf8_readlink (const char *file); # include diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 5f1de5611..aeb112d22 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2023.02.23 21:23} +\newcontextversion{2023.03.06 14:44} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 6e61cb41f..6905179fe 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2023.02.23 21:23} +\edef\contextversion{2023.03.06 14:44} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-ro.mkii b/tex/context/base/mkii/mult-ro.mkii index 914ea076f..b5151ad56 100644 --- a/tex/context/base/mkii/mult-ro.mkii +++ b/tex/context/base/mkii/mult-ro.mkii @@ -832,6 +832,7 @@ \setinterfaceconstant{exitoffset}{exitoffset} \setinterfaceconstant{expansion}{expansiune} \setinterfaceconstant{export}{export} +\setinterfaceconstant{extradata}{extradata} \setinterfaceconstant{extras}{extras} \setinterfaceconstant{factor}{factor} \setinterfaceconstant{fallback}{fallback} @@ -955,6 +956,7 @@ \setinterfaceconstant{lastpage}{ultimapagina} \setinterfaceconstant{lastpagesep}{lastpagesep} \setinterfaceconstant{lastpubsep}{lastpubsep} +\setinterfaceconstant{lasttextseparator}{lasttextseparator} \setinterfaceconstant{layout}{layout} \setinterfaceconstant{left}{stanga} \setinterfaceconstant{leftclass}{leftclass} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 0fe54e581..0abf3e46e 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2023.02.23 21:23} +\newcontextversion{2023.03.06 14:44} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index ea936fd95..cb0821994 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -49,7 +49,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2023.02.23 21:23} +\edef\contextversion{2023.03.06 14:44} %D Kind of special: diff --git a/tex/context/base/mkiv/data-ini.lua b/tex/context/base/mkiv/data-ini.lua index 6cf5669b3..c36e0bb9c 100644 --- a/tex/context/base/mkiv/data-ini.lua +++ b/tex/context/base/mkiv/data-ini.lua @@ -109,6 +109,26 @@ do ownbin = file.collapsepath(ownbin) ownpath = file.collapsepath(ownpath) + -- We need to follow the symlink on osx - texlive. This only works luametatex and + -- lmtx so we might as wel forget abnotu luatex/mkiv there. The regular context + -- installation doesn't have this link issue. + + local symlinktarget = lfs.symlinktarget + + if symlinktarget then + while true do + local new = symlinktarget(ownpath) or ownpath + if new == ownpath then + break + else + ownpath = new + end + end + ownpath = file.collapsepath(ownpath) + else + lfs.symlinktarget = function() return nil end -- forget about it, luatex is frozen + end + if not ownpath or ownpath == "" or ownpath == "unset" then ownpath = args[-1] or arg[-1] ownpath = ownpath and filedirname(gsub(ownpath,"\\","/")) diff --git a/tex/context/base/mkiv/l-dir.lua b/tex/context/base/mkiv/l-dir.lua index ac8e2f4e8..c8543f025 100644 --- a/tex/context/base/mkiv/l-dir.lua +++ b/tex/context/base/mkiv/l-dir.lua @@ -197,7 +197,7 @@ local function collectpattern(path,patt,recurse,result) if not find(path,"/$") then path = path .. '/' end - for name in scanner, first do -- cna be optimized + for name in scanner, first do -- can be optimized if name == "." then -- skip elseif name == ".." then diff --git a/tex/context/base/mkiv/l-file.lua b/tex/context/base/mkiv/l-file.lua index 9f8fd6548..70f8188dc 100644 --- a/tex/context/base/mkiv/l-file.lua +++ b/tex/context/base/mkiv/l-file.lua @@ -741,8 +741,24 @@ end -- not used in context but was in luatex once: -local symlinkattributes = lfs.symlinkattributes +do + + local symlinktarget = lfs.symlinktarget -- luametatex (always returns string) + local symlinkattributes = lfs.symlinkattributes -- luatex (can return nil) + + if symlinktarget then + function lfs.readlink(name) + local target = symlinktarget(name) + return name ~= target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil end diff --git a/tex/context/base/mkiv/lang-txt.lua b/tex/context/base/mkiv/lang-txt.lua index 1b278926e..cb8053fb6 100644 --- a/tex/context/base/mkiv/lang-txt.lua +++ b/tex/context/base/mkiv/lang-txt.lua @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['lang-txt'] = { -- bg Bulgarian Vladislav Hinkin, Aleš Ďurčanský (2019) -- ca Catalan ...; additions Javier Gambin Monzo + Samuel Conca Coles (2022) -- cn Chinese Wang Lei, ... --- cs Czech Tom Hudec, Petr Sojka, Richard Gabriel +-- cs Czech Tom Hudec, Petr Sojka, Richard Gabriel; additions Tomáš Hála (2022) -- da Danish Arne Jorgensen -- de German Tobias Burnus, ... -- en English Hans Hagen, ... @@ -52,7 +52,7 @@ if not modules then modules = { } end modules ['lang-txt'] = { -- pt Portuguese Pedro F. M. Mendonça -- ro Romanian Dan Seracu, ... -- ru Russian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ... --- sk Slovak Tomáš Hála (2012) +-- sk Slovak Tomáš Hála (2012, 2022) -- sl Slovenian Mojca Miklavec -- sr Serbian Ivan Pešić (2020) -- sr-latn Serbian Ivan Pešić (2020) @@ -84,6 +84,7 @@ data.labels={ ["be"]="У", ["bg"]="в", ["ca"]="En", + ["cs"]={ "In", "V" }, ["de"]="In", ["en"]="In", ["eo"]="En", @@ -92,6 +93,7 @@ data.labels={ ["fr"]="Dans", ["hy"]="Մեջ", ["mk"]="во", + ["sk"]={ "In", "V" }, ["sr"]="У", ["sr-latn"]="U", }, @@ -101,6 +103,7 @@ data.labels={ ["be"]="Нумар", ["bg"]="номер", ["ca"]="Nombre", + ["cs"]="Číslo", ["de"]="Nummer", ["en"]="Number", ["eo"]="Nombro", @@ -110,6 +113,7 @@ data.labels={ ["hy"]="Համար", ["mk"]="Број", ["nl"]="Nummer", + ["sk"]="Číslo", ["sr"]="Број", ["sr-latn"]="Broj", }, @@ -119,6 +123,7 @@ data.labels={ ["be"]="Гук", ["bg"]="обем", ["ca"]="Volum", + ["cs"]="Svazek", ["de"]="Band", ["en"]="Volume", ["eo"]="Volumo", @@ -129,6 +134,7 @@ data.labels={ ["hy"]="Ծավալ", ["mk"]="Том", ["nl"]="Deel", + ["sk"]="Zväzok", ["sr"]="Том", ["sr-latn"]="Tom", }, @@ -138,6 +144,7 @@ data.labels={ ["be"]="i", ["bg"]="a", ["ca"]="i", + ["cs"]="a", ["de"]="und", ["en"]="and", ["eo"]="kaj", @@ -149,6 +156,7 @@ data.labels={ ["it"]="e", ["mk"]="и", ["nl"]="en", + ["sk"]="a", ["sr"]="и", ["sr-latn"]="i", }, @@ -158,6 +166,7 @@ data.labels={ ["be"]="Выданне", ["bg"]="издание", ["ca"]="Edició", + ["cs"]="Vydání", ["de"]="Auflage", ["en"]="edition", ["eo"]="eldono", @@ -170,6 +179,7 @@ data.labels={ ["it"]="edizione", ["mk"]="издание", ["nl"]="editie", + ["sk"]="Vydanie", ["sr"]="издање", ["sr-latn"]="izdanje", }, @@ -179,6 +189,7 @@ data.labels={ ["be"]="Рэдактар", ["bg"]="редактор", ["ca"]="Editor", + ["cs"]={ "Editor", "Editorka" }, ["de"]="Herausgeber", ["en"]="editor", ["eo"]="eldonisto", @@ -189,6 +200,7 @@ data.labels={ ["hy"]="խմբագիր", ["it"]="a cura di", ["mk"]="уредник", + ["sk"]={ "Editor", "Editorka" }, ["sr"]="уредник", ["sr-latn"]="urednik", }, @@ -198,6 +210,7 @@ data.labels={ ["be"]="Рэдактары", ["bg"]="редактори", ["ca"]="Editors", + ["cs"]="Editoři", ["de"]="Herausgeber", ["en"]="editors", ["eo"]="eldonistoj", @@ -207,15 +220,29 @@ data.labels={ ["hy"]="խմբագիրներ", ["it"]="a cura di", ["mk"]="уредници", + ["sk"]="Editori", ["sr"]="уредници", ["sr-latn"]="urednici", }, }, + ["editors:f"]={ + ["labels"]={ + ["cs"]="Editorky", + ["sk"]="Editorky", + }, + }, + ["editors:m"]={ + ["labels"]={ + ["cs"]="Editoři", + ["sk"]="Editori", + }, + }, ["in"]={ ["labels"]={ ["be"]="у", ["bg"]="в", ["ca"]="en", + ["cs"]="v", ["de"]="in", ["en"]="in", ["eo"]="en", @@ -224,6 +251,7 @@ data.labels={ ["fr"]="dans", ["hy"]="մեջ", ["mk"]="во", + ["sk"]="v", ["sr"]="у", ["sr-latn"]="u", }, @@ -233,6 +261,7 @@ data.labels={ ["be"]="Дыпломная работа", ["bg"]="дипломна работа", ["ca"]="Tesi de maestria", + ["cs"]="Diplomová práce", ["de"]="Masterarbeit", ["en"]="Master's thesis", ["eo"]="Magistreca disertaĵo", @@ -245,6 +274,7 @@ data.labels={ ["it"]="Tesi di laurea", ["mk"]="Магистерска дисертација", ["nl"]="Masterproef", + ["sk"]="Diplomová práca", ["sr"]="Мастер дисертација", ["sr-latn"]="Master disertacija", }, @@ -254,6 +284,7 @@ data.labels={ ["be"]="нумар", ["bg"]="номер", ["ca"]="nombre", + ["cs"]="číslo", ["de"]="Nummer", ["en"]="number", ["eo"]="numero", @@ -264,6 +295,7 @@ data.labels={ ["hy"]="համար", ["mk"]="број", ["nl"]="nummer", + ["sk"]="číslo", ["sr"]="број", ["sr-latn"]="broj", }, @@ -273,6 +305,7 @@ data.labels={ ["be"]="з", ["bg"]="на", ["ca"]="de", + ["cs"]="z", ["de"]="von", ["en"]="of", ["eo"]="de", @@ -281,6 +314,7 @@ data.labels={ ["hy"]="-ից", ["mk"]="од", ["nl"]="van", + ["sk"]="z", ["sr"]="од", ["sr-latn"]="od", }, @@ -288,6 +322,7 @@ data.labels={ ["others"]={ ["labels"]={ ["ca"]="et al.", + ["cs"]={ "a~kol.", "et al."}, ["de"]="et al.", ["en"]="et al.", ["eo"]="aliaj", @@ -296,6 +331,7 @@ data.labels={ ["fr"]="et al.", ["hy"]="եւ այլն", ["mk"]="и др.", + ["sk"]={ "a~kol.", "et al."}, ["sr"]="и др.", ["sr-latn"]="i dr.", }, @@ -304,6 +340,7 @@ data.labels={ ["labels"]={ ["be"]="стар.", ["ca"]="p.", + ["cs"]="s.", ["de"]="S.", ["en"]="p.", ["eo"]="p.", @@ -313,6 +350,7 @@ data.labels={ ["fr"]="p.", ["hy"]="էջ", ["mk"]="стр.", + ["sk"]="s.", ["sr"]="стр.", ["sr-latn"]="str.", }, @@ -322,6 +360,7 @@ data.labels={ ["be"]="старонка", ["bg"]="страни", ["ca"]="pagines", + ["cs"]="strany", ["de"]="Seiten", ["en"]="pages", ["eo"]="paĝoj", @@ -333,6 +372,7 @@ data.labels={ ["hy"]="էջեր", ["mk"]="страници", ["nl"]="paginas", + ["sk"]="strany", ["sr"]="страницa", ["sr-latn"]="stranica", }, @@ -342,6 +382,7 @@ data.labels={ ["be"]="патэнт", ["bg"]="патент", ["ca"]="Patent", + ["cs"]="Patent", ["de"]="Patent", ["en"]="Patent", ["eo"]="Patento", @@ -353,6 +394,7 @@ data.labels={ ["it"]="Brevetto", ["mk"]="Патент", ["nl"]="Octrooi", + ["sk"]="Patent", ["sr"]="Патент", ["sr-latn"]="Patent", }, @@ -362,6 +404,7 @@ data.labels={ ["be"]="Доктарская дысертацыя", ["bg"]="дисертачна работа", ["ca"]="Tesi doctoral", + ["cs"]="Disertační práce", ["de"]="Dissertation", ["en"]="PhD thesis", ["eo"]="Doktoriĝa disertaĵo", @@ -373,6 +416,7 @@ data.labels={ ["it"]="Tesi di dottorato", ["mk"]="Докторска дисертација", ["nl"]="Proefschrift", + ["sk"]="Dizertačná práca", ["sr"]="Докторска дисертација", ["sr-latn"]="Doktorska disertacija", }, @@ -380,6 +424,7 @@ data.labels={ ["pp"]={ ["labels"]={ ["ca"]="pp", + ["cs"]="s.", ["de"]="S.", ["en"]="pp.", ["eo"]="pp.", @@ -388,6 +433,7 @@ data.labels={ ["fa"]="صص", ["hy"]="էջ", ["mk"]="стр.", + ["sk"]="s.", ["sr"]="стр.", ["sr-latn"]="str.", }, @@ -397,6 +443,7 @@ data.labels={ ["be"]="Тэхнічны даклад", ["bg"]="технически доклад", ["ca"]="Report tecnic", + ["cs"]="Technická zpráva", ["de"]="Technischer Bericht", ["en"]="Technical report", ["eo"]="Teknika raporto", @@ -409,6 +456,7 @@ data.labels={ ["it"]="Relazione tecnica", ["mk"]="Технички извештај", ["nl"]="Technisch rapport", + ["sk"]="Technická zpráva", ["sr"]="Технички извештај", ["sr-latn"]="Tehnički izveštaj", }, @@ -418,6 +466,7 @@ data.labels={ ["be"]="гучнасць", ["bg"]="обем", ["ca"]="volum", + ["cs"]="svazek", ["de"]="Band", ["en"]="volume", ["eo"]="volumo", @@ -428,6 +477,7 @@ data.labels={ ["hy"]="ծավալ", ["mk"]="том", ["nl"]="deel", + ["sk"]="zväzok", ["sr"]="том", ["sr-latn"]="tom", }, @@ -437,6 +487,7 @@ data.labels={ ["be"]="з", ["bg"]="със", ["ca"]="en", + ["cs"]="s", ["de"]="mit", ["en"]="with", ["eo"]="kun", @@ -448,6 +499,7 @@ data.labels={ ["it"]="con", ["mk"]="со", ["nl"]="met", + ["sk"]="s", ["sr"]="са", ["sr-latn"]="sa", }, @@ -500,7 +552,7 @@ data.labels={ ["sr-latn"]="arccosh", }, }, - ["arcctg"]={ + ["arccot"]={ ["labels"]={ ["ca"]="arc cot", ["cs"]="arccotg", @@ -666,7 +718,7 @@ data.labels={ ["sr-latn"]="cosec", }, }, - ["ctg"]={ +--[[ ["ctg"]={ ["labels"]={ ["ca"]="cot", ["cs"]="cotg", @@ -682,6 +734,7 @@ data.labels={ ["sr-latn"]="ctg", }, }, +--]] ["deg"]={ ["labels"]={ ["ca"]="gr", @@ -712,9 +765,11 @@ data.labels={ ["diff"]={ ["labels"]={ ["ca"]="d", + ["cs"]="d", ["en"]="d", ["eo"]="dif", - ["hy"]="diff", + ["hy"]="d", + ["sk"]="d", }, }, ["dim"]={ @@ -903,7 +958,7 @@ data.labels={ }, ["ln"]={ ["labels"]={ - ["ca"]="En", + ["ca"]="ln", ["cs"]="ln", ["en"]="ln", ["eo"]="ln", @@ -947,14 +1002,16 @@ data.labels={ ["median"]={ ["labels"]={ ["ca"]="mitjana", - ["cs"]="\\tilde", + -- ["cs"]="\\tilde", -- won't work + ["cs"]="Me", ["en"]="median", ["eo"]="mediano", ["es"]="Mediana", ["fi"]="mediaani", ["fr"]="médiane", ["hy"]="միջին", - ["sk"]="\\tilde", + -- ["sk"]="\\tilde", -- won't work + ["sk"]="Med", ["sr"]="median", ["sr-latn"]="median", }, @@ -1501,6 +1558,7 @@ data.labels={ ["labels"]={ ["bg"]="ден", ["ca"]="dia", + ["cs"]="den", -- {"den", "dne" } ["de"]="Tag", ["en"]="day", ["eo"]="tago", @@ -1512,6 +1570,7 @@ data.labels={ ["kr"]="일", ["mk"]="ден", ["nl"]="dag", + ["sk"]="deň", -- {"deň", "dňa" } ["sr"]="дан", ["sr-latn"]="dan", }, @@ -1756,25 +1815,30 @@ data.labels={ }, ["following:plural"]={ ["labels"]={ + ["cs"]="násl.", ["de"]="ff.", ["en"]="ff.", ["eo"]="sekvv", ["fr"]=hairspace .. "sqq", ["hy"]="ff.", + ["sk"]="násl.", }, }, ["following:singular"]={ ["labels"]={ + ["cs"]="násl.", ["de"]="f.", ["en"]="f.", ["eo"]="sekv", ["fr"]=hairspace .. "sq", ["hy"]="f.", + ["sk"]="násl.", }, }, ["followingpage"]={ ["labels"]={ ["ca"]="en la seguent pagina", + ["cs"]="na následující straně", ["de"]="auf einer Folgeseite", ["en"]="on a following page", ["eo"]="je sekvanta paĝo", @@ -1786,6 +1850,7 @@ data.labels={ ["hy"]="Հաջորդ էջում", ["mk"]="на следната страница", ["nl"]="op een volgende bladzijde", + ["sk"]="na nasledujúcej strane", ["sr"]="на следећој страници", ["sr-latn"]="na sledećoj stranici", }, @@ -2979,6 +3044,7 @@ data.labels={ ["precedingpage"]={ ["labels"]={ ["ca"]="en una pagina anterior", + ["cs"]="na předchozí straně", ["de"]="oben", -- "auf der vorigen Seite" ok, but not "auf einer vorigen Seite" ["en"]="on a preceding page", ["eo"]="sur antaŭa paĝo", @@ -2990,6 +3056,7 @@ data.labels={ ["hy"]="նախորդ էջ", ["mk"]="на претходната страница", ["nl"]="op een voorgaande bladzijde", + ["sk"]="na predchádzajúcej strane", ["sr"]="на претходној страници", ["sr-latn"]="na prethodnoj stranici", }, @@ -3678,6 +3745,7 @@ data.labels={ ["labels"]={ ["bg"]="година", ["ca"]="any", + ["cs"]="rok", ["de"]="Jahr", ["en"]="year", ["eo"]="jaro", @@ -3690,6 +3758,7 @@ data.labels={ ["kr"]="년", ["mk"]="година", ["nl"]="jaar", + ["sk"]="rok", ["sr"]="година", ["sr-latn"]="godina", }, @@ -3704,7 +3773,7 @@ data.labels={ ["bg"]="Съкращения", ["ca"]="Abreviacions", ["cn"]="缩略语", - ["cs"]="Zkratky", + ["cs"]="Seznam zkratek", --"Zkratky" ["da"]="Forkortelser", ["de"]="Abkürzungen", ["en"]="Abbreviations", @@ -3731,7 +3800,7 @@ data.labels={ ["pt"]="Abreviaturas", ["ro"]="Abrevieri", ["ru"]="Список сокращений", - ["sk"]="Skratky", + ["sk"]="Zoznam skratiek", -- "Skratky" ["sl"]="Kratice", ["sr"]="Скраћенице", ["sr-latn"]="Skraćenice", @@ -3914,7 +3983,7 @@ data.labels={ ["pt"]="Índice", ["ro"]="Index", ["ru"]="Алфавитный указатель", - ["sk"]="Zoznam", + ["sk"]="Register", ["sl"]="Stvarno kazalo", ["sr"]="Индекс појмова", ["sr-latn"]="Indeks pojmova", @@ -4161,6 +4230,8 @@ functions.acosh = functions.arccosh functions.atanh = functions.arctanh functions.tg = functions.tan +functions.ctg = functions.cot functions.arctg = functions.arctan +functions.arcctg = functions.arccot functions.arctgh = functions.arctanh diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index 4ac851371..b0aba96d6 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -8660,6 +8660,10 @@ return { ["fr"]="entrees", ["nl"]="ingangen", }, + ["extradata"]={ + ["en"]="extradata", + ["nl"]="extragegevens", + }, ["processors"]={ ["en"]="processors", }, @@ -12319,6 +12323,10 @@ return { ["pe"]="روش‌متن", ["ro"]="textmethod", }, + ["lasttextseparator"]={ + ["en"]="lasttextseparator", + ["nl"]="laatstetekstscheider", + }, ["textseparator"]={ ["cs"]="oddelovactextu", ["de"]="textseparator", diff --git a/tex/context/base/mkiv/page-flt.lua b/tex/context/base/mkiv/page-flt.lua index 7c2220840..8df38b406 100644 --- a/tex/context/base/mkiv/page-flt.lua +++ b/tex/context/base/mkiv/page-flt.lua @@ -51,6 +51,8 @@ local function initialize() return { text = { }, page = { }, + top = { }, + bottom = { }, leftpage = { }, rightpage = { }, somewhere = { }, @@ -317,11 +319,13 @@ function floats.checkedpagefloat(packed) end function floats.nofstacked(which) - return #stacks[which or default] or 0 + local s = stacks[which or default] + return s and #s or 0 end function floats.hasstacked(which) - return (#stacks[which or default] or 0) > 0 + local s = stacks[which or default] + return (s and #s or 0) > 0 end -- todo: check for digits ! diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 95229e3fe..28a82c9a9 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 07a4610e0..ef3a87add 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/strc-def.mkiv b/tex/context/base/mkiv/strc-def.mkiv index 52b3b3ad9..520a9e311 100644 --- a/tex/context/base/mkiv/strc-def.mkiv +++ b/tex/context/base/mkiv/strc-def.mkiv @@ -27,6 +27,8 @@ % \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta} % \stoptext +\defineseparatorset [\v!none] [] [] + \defineseparatorset [\s!default] [] [.] \defineconversionset [\s!default] [] [numbers] \defineresetset [\s!default] [] [1] % each level diff --git a/tex/context/base/mkiv/util-sql-imp-client.lua b/tex/context/base/mkiv/util-sql-imp-client.lua index a2763feac..2f72ef138 100644 --- a/tex/context/base/mkiv/util-sql-imp-client.lua +++ b/tex/context/base/mkiv/util-sql-imp-client.lua @@ -23,7 +23,6 @@ local preparetemplate = helpers.preparetemplate local splitdata = helpers.splitdata local replacetemplate = utilities.templates.replace local serialize = sql.serialize -local deserialize = sql.deserialize local getserver = sql.getserver local osclock = os.gettimeofday @@ -264,6 +263,7 @@ end local wraptemplate = [[ local converters = utilities.sql.converters local deserialize = utilities.sql.deserialize +local fromjson = utilities.sql.fromjson local tostring = tostring local tonumber = tonumber diff --git a/tex/context/base/mkiv/util-sql-imp-ffi.lua b/tex/context/base/mkiv/util-sql-imp-ffi.lua index cbfd7bcf5..9cf306df7 100644 --- a/tex/context/base/mkiv/util-sql-imp-ffi.lua +++ b/tex/context/base/mkiv/util-sql-imp-ffi.lua @@ -169,7 +169,6 @@ local validspecification = helpers.validspecification local querysplitter = helpers.querysplitter local dataprepared = helpers.preparetemplate local serialize = sql.serialize -local deserialize = sql.deserialize local mysql_open_session = mysql.mysql_init @@ -564,6 +563,7 @@ local ffi_tostring = ffi.string local converters = utilities.sql.converters local deserialize = utilities.sql.deserialize +local fromjson = utilities.sql.fromjson local tostring = tostring local tonumber = tonumber diff --git a/tex/context/base/mkiv/util-sql-imp-library.lua b/tex/context/base/mkiv/util-sql-imp-library.lua index dbbeb32cc..e43afc2f3 100644 --- a/tex/context/base/mkiv/util-sql-imp-library.lua +++ b/tex/context/base/mkiv/util-sql-imp-library.lua @@ -79,7 +79,6 @@ local validspecification = helpers.validspecification local querysplitter = helpers.querysplitter local dataprepared = helpers.preparetemplate local serialize = sql.serialize -local deserialize = sql.deserialize local formatters = string.formatters local initialize = mysql.mysql @@ -251,6 +250,7 @@ end local wraptemplate = [[ local converters = utilities.sql.converters local deserialize = utilities.sql.deserialize +local fromjson = utilities.sql.fromjson local tostring = tostring local tonumber = tonumber diff --git a/tex/context/base/mkiv/util-sql-imp-sqlite.lua b/tex/context/base/mkiv/util-sql-imp-sqlite.lua index 781c92c89..a82244bad 100644 --- a/tex/context/base/mkiv/util-sql-imp-sqlite.lua +++ b/tex/context/base/mkiv/util-sql-imp-sqlite.lua @@ -234,6 +234,7 @@ end local wraptemplate = [[ local converters = utilities.sql.converters local deserialize = utilities.sql.deserialize +local fromjson = utilities.sql.fromjson local tostring = tostring local tonumber = tonumber diff --git a/tex/context/base/mkiv/util-sql.lua b/tex/context/base/mkiv/util-sql.lua index 55c4961f7..f729acfb9 100644 --- a/tex/context/base/mkiv/util-sql.lua +++ b/tex/context/base/mkiv/util-sql.lua @@ -87,12 +87,22 @@ sql.helpers = helpers local serialize = table.fastserialize local deserialize = table.deserialize +local json = require("util-jsn") +local tojson = json.tostring +local fromjson = json.tolua + sql.serialize = serialize sql.deserialize = deserialize helpers.serialize = serialize -- bonus helpers.deserialize = deserialize -- bonus +sql.tojson = tojson +sql.fromjson = fromjson + +helpers.tojson = tojson -- bonus +helpers.fromjson = fromjson -- bonus + local defaults = { __index = { resultfile = "result.dat", @@ -174,6 +184,8 @@ local function makeconverter(entries,celltemplate,wraptemplate) assignments[#assignments+1] = format("[%q] = tab_%s[%s],",name,#converters,value) elseif kind == "deserialize" then assignments[#assignments+1] = format("[%q] = deserialize(%s),",name,value) + elseif kind == "fromjson" then + assignments[#assignments+1] = format("[%q] = fromjson(%s),",name,value) elseif kind == "key" then -- hashed instead of indexed key = value @@ -392,13 +404,25 @@ function sql.usedatabase(presets,datatable) name = name or "data" for i=1,#records do local record = records[i] - local data = record[name] + local data = record[name] if data then record[name] = deserialize(data) end end end end + local function unpackjson(records,name) + if records then + name = name or "json" + for i=1,#records do + local record = records[i] + local data = record[name] + if data then + record[name] = fromjson(data) + end + end + end + end return { usedmethod = usedmethod, presets = preset, @@ -408,7 +432,10 @@ function sql.usedatabase(presets,datatable) execute = execute, serialize = serialize, deserialize = deserialize, + tojson = tojson, + fromjson = fromjson, unpackdata = unpackdata, + unpackjson = unpackjson, } else report_state("missing name in usedatabase specification") diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 45393d871..78ec6d63d 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2023.02.23 21:23} +\newcontextversion{2023.03.06 14:44} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index f5d46c9db..24619c289 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2023.02.23 21:23} +\immutable\edef\contextversion{2023.03.06 14:44} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/core-con.mkxl b/tex/context/base/mkxl/core-con.mkxl index f9aa1a69d..bf607c34d 100644 --- a/tex/context/base/mkxl/core-con.mkxl +++ b/tex/context/base/mkxl/core-con.mkxl @@ -86,14 +86,14 @@ \permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}} \permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}} -\permanent\def\devanagarinumerals#1{\clf_decimals\numexpr#1\relax{devanagari}} -\permanent\def\malayalamnumerals #1{\clf_decimals\numexpr#1\relax{malayalam}} -\permanent\def\tamilnumerals #1{\clf_decimals\numexpr#1\relax{tamil}} -\permanent\def\kannadanumerals #1{\clf_decimals\numexpr#1\relax{kannada}} -\permanent\def\telugunumerals #1{\clf_decimals\numexpr#1\relax{telugu}} -\permanent\def\bengalinumerals #1{\clf_decimals\numexpr#1\relax{bengali}} -\permanent\def\gujaratinumerals #1{\clf_decimals\numexpr#1\relax{gujarati}} -\permanent\def\gurmurkhinumerals #1{\clf_decimals\numexpr#1\relax{gurmurkhi}} +\permanent\def\devanagarinumerals#1{\clf_decimals \numexpr#1\relax{devanagari}} +\permanent\def\malayalamnumerals #1{\clf_decimals \numexpr#1\relax{malayalam}} +\permanent\def\tamilnumerals #1{\clf_decimals \numexpr#1\relax{tamil}} +\permanent\def\kannadanumerals #1{\clf_decimals \numexpr#1\relax{kannada}} +\permanent\def\telugunumerals #1{\clf_decimals \numexpr#1\relax{telugu}} +\permanent\def\bengalinumerals #1{\clf_decimals \numexpr#1\relax{bengali}} +\permanent\def\gujaratinumerals #1{\clf_decimals \numexpr#1\relax{gujarati}} +\permanent\def\gurmurkhinumerals #1{\clf_decimals \numexpr#1\relax{gurmurkhi}} \permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}} \permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}} \permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}} @@ -102,6 +102,9 @@ \permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}} \permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}} +\permanent\def\mathgreeknumerals #1{\im{\clf_alphabetic\numexpr#1\relax{greek}}} +\permanent\def\mathGreeknumerals #1{\im{\clf_Alphabetic\numexpr#1\relax{greek}}} + \aliased \let\arabicexnumerals \persiannumerals \permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}} @@ -711,6 +714,9 @@ \defineconversion [\v!greek] [\greeknumerals] \defineconversion [\v!Greek] [\Greeknumerals] +\defineconversion [\s!math:\v!greek] [\mathgreeknumerals] +\defineconversion [\s!math:\v!Greek] [\mathGreeknumerals] + \defineconversion [g] [\greeknumerals] \defineconversion [G] [\Greeknumerals] @@ -745,6 +751,9 @@ \defineconversion [arabicdecimals] [\arabicdecimals] \defineconversion [persiandecimals] [\persiandecimals] +\defineconversion [mathgreeknumerals] [\mathgreeknumerals] +\defineconversion [mathGreeknumerals] [\mathGreeknumerals] + \defineconversion [koreannumerals] [\koreannumerals] \defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while) \defineconversion [koreanparenthesisnumerals] diff --git a/tex/context/base/mkxl/core-uti.lmt b/tex/context/base/mkxl/core-uti.lmt index 48737d7f6..966428b36 100644 --- a/tex/context/base/mkxl/core-uti.lmt +++ b/tex/context/base/mkxl/core-uti.lmt @@ -20,7 +20,7 @@ saves much runtime but at the cost of more memory usage.

local math = math local next, type, tostring, tonumber, setmetatable, load = next, type, tostring, tonumber, setmetatable, load local format, match = string.format, string.match -local concat = table.concat +local concat, sortedkeys = table.concat, table.sortedkeys local definetable = utilities.tables.definetable local accesstable = utilities.tables.accesstable @@ -282,7 +282,7 @@ directives.register("job.pack",function(v) job.pack = v end) local savedfiles = { } local loadedfiles = { } -- for now only timers -local otherfiles = { } -- for now only timers +local othercache = { } function job.save(filename) -- we could return a table but it can get pretty large statistics.starttiming(savedfiles) @@ -381,18 +381,12 @@ function job.load(filename) statistics.stoptiming(loadedfiles) end -local othercache = { } - -function job.loadother(filename,cache) - local unpacked = false +function job.loadother(filename) statistics.starttiming(loadedfiles) filename = file.addsuffix(filename,"tuc") - if cache then - unpacked = othercache[filename] - end + local unpacked = othercache[filename] if not unpacked then -- so we can register the same name twice(in loading order) - otherfiles[#otherfiles+1] = file.nameonly(filename) local utilitydata = load(filename) if utilitydata then local jobpacker = utilitydata.job.packed @@ -408,34 +402,12 @@ function job.loadother(filename,cache) end end unpacked.job.packed = nil -- nicer in inspecting - if cache then - othercache[filename] = unpacked - end - -- - local lists = utilitydata.structures.lists.collected or { } - local sections = utilitydata.structures.sections.collected or { } - local pages = utilitydata.structures.pages .collected or { } - for i=1,#lists do - local entry = lists[i] - local references = entry.references - if references then - local section = references.section - local realpage = references.realpage - -- maybe entry.* instead: - references.sectiondata = section and sections[section] - references.pagedata = realpage and pages[realpage] - -- get rid of these, maybe even crash as these are bogus - -- references.internal = nil - -- references.realpage = nil - -- references.section = nil - references.x = nil - references.y = nil - end - end - -- - -- also do the references here + othercache[filename] = unpacked + -- + structures.lists .integrate(utilitydata) + structures.registers .integrate(utilitydata) + structures.references.integrate(utilitydata) -- - structures.references.registerfromlist(lists,derived,pages,sections) end end statistics.stoptiming(loadedfiles) @@ -447,17 +419,19 @@ statistics.register("startup time", function() end) statistics.register("jobdata time",function() + local elapsedsave = statistics.elapsedtime(savedfiles) + local elapsedload = statistics.elapsedtime(loadedfiles) if enabled then - if #otherfiles > 0 then - return format("%s seconds saving, %s seconds loading, other files: %s",statistics.elapsedtime(savedfiles),statistics.elapsedtime(loadedfiles),concat(otherfiles," ")) + if next(othercache) then + return format("%s seconds saving, %s seconds loading, other files: %s",elapsedsave,elapsedload,concat(sortedkeys(othercache), ", ")) else - return format("%s seconds saving, %s seconds loading",statistics.elapsedtime(savedfiles),statistics.elapsedtime(loadedfiles)) + return format("%s seconds saving, %s seconds loading",elapsedsave,elapsedload) end else - if #otherfiles > 0 then - return format("nothing saved, %s seconds loading, other files: %s",statistics.elapsedtime(loadedfiles),concat(otherfiles," ")) + if next(othercache) then + return format("nothing saved, %s seconds loading, other files: %s",elapsedload,concat(sortedkeys(othercache), ", ")) else - return format("nothing saved, %s seconds loading",statistics.elapsedtime(loadedfiles)) + return format("nothing saved, %s seconds loading",elapsedload) end end end) diff --git a/tex/context/base/mkxl/lang-lab.lmt b/tex/context/base/mkxl/lang-lab.lmt index b82721b76..f1f9b3580 100644 --- a/tex/context/base/mkxl/lang-lab.lmt +++ b/tex/context/base/mkxl/lang-lab.lmt @@ -91,29 +91,28 @@ function labels.define(class,name,prefixed) report_labels("defining label set %a",name) for tag, data in next, list do tag = variables[tag] or tag - if data.hidden then - -- skip - elseif prefixed then - local first, second = lpegmatch(splitter,tag) - if second then - if rawget(variables,first) then - if rawget(variables,second) then - definelanguagelabels(data,class,f_key_key(first,second),tag) + if not data.hidden then + local key = tag + if prefixed then + local first, second = lpegmatch(splitter,tag) + if second then + if rawget(variables,first) then + if rawget(variables,second) then + key = f_key_key(first,second) + else + key = f_key_raw(first,second) + end + elseif rawget(variables,second) then + key = f_raw_key(first,second) else - definelanguagelabels(data,class,f_key_raw(first,second),tag) + key = f_raw_raw(first,second) end - elseif rawget(variables,second) then - definelanguagelabels(data,class,f_raw_key(first,second),tag) - else - definelanguagelabels(data,class,f_raw_raw(first,second),tag) + elseif rawget(variables,rawtag) then + key = f_key(tag) end - elseif rawget(variables,rawtag) then - definelanguagelabels(data,class,f_key(tag),tag) - else - definelanguagelabels(data,class,tag,tag) end - else - definelanguagelabels(data,class,tag,tag) + -- report_labels("defining class %a, key %a, tag %a",class,key,tag) + definelanguagelabels(data,class,key,tag) end end else diff --git a/tex/context/base/mkxl/lang-lab.mkxl b/tex/context/base/mkxl/lang-lab.mkxl index a1d758f09..6152d2874 100644 --- a/tex/context/base/mkxl/lang-lab.mkxl +++ b/tex/context/base/mkxl/lang-lab.mkxl @@ -50,10 +50,10 @@ %D These commands accept all kind of inputs: %D %D \starttyping -%D \setuplabeltext [language] [labellabel=text] -%D \setuplabeltext [language] [labellabel=text,labellabel=text,...] -%D \setuplabeltext [labellabel=text] -%D \setuplabeltext [labellabel=text,labellabel=text,...] +%D \setuplabeltext [language] [label1=text] +%D \setuplabeltext [language] [label1=text,label2=text,...] +%D \setuplabeltext [label1=text] +%D \setuplabeltext [label1=text,label2=text,...] %D \stoptyping %D %D The last two cases concern the current language. @@ -141,7 +141,7 @@ \else \enforced\let\thetextprefix\dummytextprefix \fi}% - \permanent \instance\protected\def#6##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass + \permanent\instance\protected\def#6##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass \permanent\instance\protected\def#7##1{#3{##1}\expandafter\secondoftwoarguments \thetextprefix}% \flushrightlabelclass \permanent\instance\protected\def#8##1{#3{##1}\expandafter\lang_labels_flush_both\thetextprefix}% \flushbothlabelclass #2 \permanent\instance\protected\def#9##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass diff --git a/tex/context/base/mkxl/libs-imp-sqlite.lmt b/tex/context/base/mkxl/libs-imp-sqlite.lmt index 5d38986f3..4b2925bcc 100644 --- a/tex/context/base/mkxl/libs-imp-sqlite.lmt +++ b/tex/context/base/mkxl/libs-imp-sqlite.lmt @@ -156,6 +156,7 @@ end local wraptemplate = [[ local converters = utilities.sql.converters local deserialize = utilities.sql.deserialize +local fromjson = utilities.sql.fromjson local tostring = tostring local tonumber = tonumber diff --git a/tex/context/base/mkxl/lpdf-mis.lmt b/tex/context/base/mkxl/lpdf-mis.lmt index a3a78c49f..577dbed5a 100644 --- a/tex/context/base/mkxl/lpdf-mis.lmt +++ b/tex/context/base/mkxl/lpdf-mis.lmt @@ -415,14 +415,7 @@ local function documentspecification() addtocatalog("Lang", pdfstring(tokens.getters.macro("currentmainlanguage"))) end --- temp hack: the mediabox is not under our control and has a precision of 5 digits - -local factor = number.dimenfactors.bp -local f_value = formatters["%.6N"] - -local function boxvalue(n) -- we could share them - return pdfverbose(f_value(factor * n)) -end +local bpfactor = number.dimenfactors.bp local function pagespecification() local canvas = getcanvas() @@ -439,10 +432,10 @@ local function pagespecification() local function extrabox(WhatBox,offset,always) if offset ~= 0 or always then addtopageattributes(WhatBox, pdfarray { - boxvalue(llx + offset), - boxvalue(lly + offset), - boxvalue(urx - offset), - boxvalue(ury - offset), + (llx + offset) * bpfactor, + (lly + offset) * bpfactor, + (urx - offset) * bpfactor, + (ury - offset) * bpfactor, }) end end diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl index baaa4666a..b37887332 100644 --- a/tex/context/base/mkxl/math-ali.mkxl +++ b/tex/context/base/mkxl/math-ali.mkxl @@ -330,6 +330,7 @@ \tabskip\centeringskip % fails in some cases \aligntab \span +\hss % for MS to test this \boundary\c_math_align_r_marker \math_alignment_lbox{\aligncontent}% \tabskip\zeropoint}% @@ -1593,6 +1594,9 @@ \newdimension\d_math_matrix_margin_t \newdimension\d_math_matrix_margin_b +\newdimension\d_math_matrix_max_left +\newdimension\d_math_matrix_max_right + \newboundary \c_math_matrix_ornament_l \newboundary \c_math_matrix_ornament_r \newboundary \c_math_matrix_ornament_t @@ -1610,7 +1614,7 @@ {\NC \enablematrixornaments \global\settrue\c_math_matrix_text - \global\settrue#1 + \global\settrue#1% \boundary#2% \ignorespaces} @@ -1642,6 +1646,8 @@ \d_math_matrix_margin_r\mathmatrixparameter\c!rightmargin\relax \d_math_matrix_margin_t\strutdp \d_math_matrix_margin_b\strutht + \global\d_math_matrix_max_left \zeropoint + \global\d_math_matrix_max_right\zeropoint %\tabskip.5\d_math_eqalign_distance \tabskip\zeropoint \math_matrix_pickup @@ -1672,6 +1678,9 @@ \mathmatrixright % experimental hook \egroup} +\permanent\protected\def\mathmatrixmaxleftwidth {\d_math_matrix_max_left } +\permanent\protected\def\mathmatrixmaxrightwidth{\d_math_matrix_max_right} + \let\math_matrix_strut \strut \let\math_matrix_set_style\relax @@ -1752,7 +1761,7 @@ \normalstopimath \egroup \ifconditional\c_math_matrix_text - \ifcstok{\mathmatrixparameter\c!left\mathmatrixparameter\c!right}\emptytoks\else + \ifcstok{\mathmatrixparameter\c!left\mathmatrixparameter\c!right\mathmatrixparameter\c!fences}\emptytoks\else \scratchdistance\dimexpr(\wd\scratchbox-\scratchwidth)/\plustwo\relax \advanceby\d_math_matrix_margin_l\scratchdistance \advanceby\d_math_matrix_margin_r\scratchdistance @@ -1765,7 +1774,15 @@ \ifconditional\c_math_matrix_text_t \ht\scratchbox\dimexpr\ht\scratchbox+\lineheight\relax \fi - \box\scratchbox} + \edef\p_leftedge {\mathmatrixparameter\c!leftedge }% + \edef\p_rightedge{\mathmatrixparameter\c!rightedge}% + \ifempty\p_leftedge\else + \hskip\dimexpr\d_math_matrix_max_left+\p_leftedge\relax + \fi + \box\scratchbox + \ifempty\p_rightedge\else + \hskip\dimexpr\d_math_matrix_max_right+\p_rightedge\relax + \fi} \definemathmatrix[matrix] \definemathmatrix[\v!mathmatrix] @@ -1956,25 +1973,54 @@ % \definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle] % \definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle] +\definemathmatrix + [matrix:none] + [\c!align=\v!middle, + \c!simplecommand=matrix] + \definemathmatrix [matrix:brackets] [\c!fences=bracket, - \c!align=\v!middle] + \c!align=\v!middle, + \c!simplecommand=bmatrix] \definemathmatrix [matrix:parentheses] [\c!fences=parenthesis, - \c!align=\v!middle] + \c!align=\v!middle, + \c!simplecommand=pmatrix] \definemathmatrix [matrix:bars] [\c!fences=bar, - \c!align=\v!middle] + \c!align=\v!middle, + \c!simplecommand=vmatrix] + +\definemathmatrix + [matrix:doublebars] + [\c!fences=doublebar, + \c!align=\v!middle, + \c!simplecommand=vvmatrix] + +\definemathmatrix + [matrix:triplebars] + [\c!fences=triplebar, + \c!align=\v!middle, + \c!simplecommand=vvvmatrix] + +\definemathmatrix + [matrix:groups] + [\c!fences=group, + \c!align=\v!middle, + \c!simplecommand=gmatrix] \definemathmatrix [matrix:braces] [\c!fences=brace, - \c!align=\v!middle] + \c!align=\v!middle, + \c!simplecommand=bracematrix]%Seldom used, bmatrix occupied by brackets + +% MPS: Is this one really used? Yes, in the test suite ... \definemathmatrix [thematrix] diff --git a/tex/context/base/mkxl/math-def.mkxl b/tex/context/base/mkxl/math-def.mkxl index be33bac86..a423a6a79 100644 --- a/tex/context/base/mkxl/math-def.mkxl +++ b/tex/context/base/mkxl/math-def.mkxl @@ -74,6 +74,11 @@ \definemathfunction [tan] \definemathfunction [diff] +% When [\c!command=] the label kicks in: + +\definemathfunction [cs:median] [\c!command=\widetilde] +\definemathfunction [sk:median] [\c!command=\widetilde] + \aliased\let\normalmatharg\arg % todo: maybe automatically %D This needs checking: diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index c76d7313a..7d0c8ef81 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -1932,37 +1932,135 @@ % \startformula[functionstyle=sans] \sin(x) = 10 \stopformula % \stopTEXpage -\protected\def\math_function_handle#1#2#3% +% \protected\def\math_function_handle#1#2#3% +% {\begingroup +% \resetdummyparameter\c!mathlimits +% \getdummyparameters[#1]% +% \edef\p_limits{\dummyparameter\c!mathlimits}% +% \mathatom +% mathfont +% class \mathfunctioncode +% \ifx\p_limits\v!no +% nolimits +% \orelse\ifx\p_limits\v!yes +% limits +% \orelse\ifx\p_limits\v!auto +% nolimits +% limits +% \fi +% \bgroup % textfont +% \math_tags_mfunctionlab{#3}\c_apply_function +% \usemathematicscolorparameter\c!functioncolor +% \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}% +% \ifempty\p_functionstyle +% \expandafter\math_upright +% \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname +% \expandafter\lastnamedcs +% \else +% \expandafter\p_functionstyle +% \fi +% #2{#3}% +% \egroup +% \endgroup} + +\installcorenamespace{mathfunction} + +\installcommandhandler \??mathfunction {mathfunction} \??mathfunction + +\appendtoks + \frozen\protected\edefcsname\currentmathfunction\endcsname{\math_function_handle\plusone{\currentmathfunction}{}}% \instance +\to \everydefinemathfunction + +\aliased\let\setupmathfunctions\setupmathfunction + +\setupmathfunctions + [\c!color=\mathematicsparameter\c!functioncolor, + \c!style=\mathematicsparameter\c!functionstyle] + +\def\math_function_handle_normal#1#2#3% {\begingroup - \resetdummyparameter\c!mathlimits - \getdummyparameters[#1]% - \edef\p_limits{\dummyparameter\c!mathlimits}% - \mathatom - mathfont - class \mathfunctioncode - \ifx\p_limits\v!no - nolimits - \orelse\ifx\p_limits\v!yes - limits - \orelse\ifx\p_limits\v!auto - nolimits - limits - \fi - \bgroup % textfont - \math_tags_mfunctionlab{#3}\c_apply_function - \usemathematicscolorparameter\c!functioncolor - \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}% - \ifempty\p_functionstyle - \expandafter\math_upright - \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname - \expandafter\lastnamedcs - \else - \expandafter\p_functionstyle - \fi - #2{#3}% - \egroup + \edef\currentmathfunction{#2}% + \setupcurrentmathfunction[#3]% + \edef\p_limits{\mathfunctionparameter\c!mathlimits}% + \mathatom + mathfont + class \mathfunctioncode + \ifx\p_limits\v!no + nolimits + \orelse\ifx\p_limits\v!yes + limits + \orelse\ifx\p_limits\v!auto + nolimits + limits + \fi + \bgroup % textfont +% +% for now we reserve command for languages and it completely bypasses +% the atom! +% +% \edef\p_command{\mathfunctionparameter\c!command}% +% \ifempty\p_command + \math_tags_mfunctionlab{#2}\c_apply_function + \usemathfunctioncolorparameter\c!color + \edef\p_functionstyle{\mathfunctionparameter\c!style}% + \ifempty\p_functionstyle + \expandafter\math_upright + \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname + \expandafter\lastnamedcs + \else + \expandafter\p_functionstyle + \fi + \ifcase#1\relax + \expandafter\firstofoneargument + \or + \expandafter\mathlabeltext + \fi{#2}% +% \else +% \p_command\relax +% \fi + \egroup \endgroup} +\def\math_function_handle_language_indeed#1#2#3% + {\edef\currentmathfunction{#2}% + \setupcurrentmathfunction[#3]% + \edef\p_command{\mathfunctionparameter\c!command}% + \ifempty\p_command + \endgroup\math_function_handle_normal#1{#2}{#3}% + \else + \normalexpanded{\endgroup\p_command\expandafter}% + \fi} + +\def\math_function_handle_language#1#2% + {\begingroup + \let\math_function_handle\math_function_handle_language_indeed + \csname\currentmainlanguage:#2\endcsname} + +\tolerant\protected\def\math_function_handle#1#2#3% + {\ifcsname\currentmainlanguage:#2\endcsname + \expandafter\math_function_handle_language + \else + \expandafter\math_function_handle_normal + \fi#1{#2}{#3}} + +\permanent\tolerant\protected\def\mfunctionlabeltext[#1]% + {\math_function_handle\plusone{#1}{}} + +% \mfunction [settings][name] [settings]{name} [name] {name} + +\permanent\tolerant\protected\def\mfunction[#1]% + {\ifhastok={#1}% + \expandafter\mfunction_yes + \orelse\ifparameter#1\or + \expandafter\mfunction_nop + \else + \expandafter\mfunction_yop + \fi{#1}} + +\permanent\tolerant\protected\def\mfunction_yes#1#*[#2]#;#3{\math_function_handle\zerocount{#2#3}{#1}} +\permanent\protected\def\mfunction_nop #1{\math_function_handle\zerocount{#1}{}} +\permanent\protected\def\mfunction_yop #1#2{\math_function_handle\zerocount{#2}{}} + \appendtoks \edef\p_functionstyle{\formulaparameter\c!functionstyle}% \ifempty\p_functionstyle\else @@ -1974,12 +2072,6 @@ \fi \to \everybeforedisplayformula -\permanent\tolerant\protected\def\mfunction [#1]{\math_function_handle{#1}\firstofoneargument} -\permanent\tolerant\protected\def\mfunctionlabeltext[#1]{\math_function_handle{#1}\mathlabeltext} - -\permanent\tolerant\protected\def\definemathfunction[#1]#*[#2]% - {\frozen\protected\defcsname#1\endcsname{\math_function_handle{#2}\mathlabeltext{#1}}} % \instance - \let\math_tags_mfunctiontxt\gobbletwoarguments \let\math_tags_mfunctionlab\gobbletwoarguments diff --git a/tex/context/base/mkxl/math-spa.lmt b/tex/context/base/mkxl/math-spa.lmt index 126bb739b..9875f8b2d 100644 --- a/tex/context/base/mkxl/math-spa.lmt +++ b/tex/context/base/mkxl/math-spa.lmt @@ -28,6 +28,7 @@ local tonode = nodes.tonode local getid = nuts.getid local getsubtype = nuts.getsubtype local getnext = nuts.getnext +local getprev = nuts.getprev local getwidth = nuts.getwidth local getdata = nuts.getdata local getdepth = nuts.getdepth @@ -47,6 +48,7 @@ local nextboundary = nuts.traversers.boundary local nextnode = nuts.traversers.node local texsetdimen = tex.setdimen +local texgetdimen = tex.getdimen local texsetcount = tex.setcount local texisdimen = tex.isdimen local texiscount = tex.iscount @@ -63,44 +65,125 @@ local d_strc_math_first_height = texisdimen("d_strc_math_first_height") local d_strc_math_last_depth = texisdimen("d_strc_math_last_depth") local d_strc_math_indent = texisdimen("d_strc_math_indent") +local function moveon(s) + for n, id, subtype in nextnode, getnext(s) do + s = n + if id == kern_code then + -- move on (s_2 case) + elseif id == glue_code then + -- move on + elseif id == penalty_code then + -- move on (untested) + elseif id == hlist_code and subtype == ghost_code then + -- move on + else + break + end + end + return s +end + +-- stages[1] = function(specification,stage) +-- local box = getbox(specification.box) +-- local head = getlist(box) +-- local align = specification.alignstate +-- local distance = specification.distance +-- for s in nextboundary, head do +-- local data = getdata(s) +-- if data == boundary then +-- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop +-- s = moveon(s) +-- for n, id, subtype in nextnode, getnext(s) do +-- s = n +-- if id == kern_code then +-- -- move on (s_2 case) +-- elseif id == glue_code then +-- -- move on +-- elseif id == penalty_code then +-- -- move on (untested) +-- elseif id == hlist_code and subtype == ghost_code then +-- -- move on +-- else +-- break +-- end +-- end +-- distance = distance + getdimensions(head,s) +-- break +-- end +-- end +-- texsetdimen("global",d_strc_math_indent,distance) +-- if align == 2 then +-- for n in nextglue, head do +-- setglue(n,getwidth(n),0,0,0,0) +-- end +-- end +-- end + +-- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop +-- +-- local n = getnext(s) +-- if n and getid(n) == kern_code then -- also needed +-- n = getnext(n) +-- end +-- while n and getid(n) == hlist_code and getsubtype(n) == ghost_code do +-- n = getnext(n) +-- end +-- while n and getid(n) == glue_code do +-- if n and getid(n) == glue_code then +-- n = getnext(n) +-- end + +local getpenalty = nuts.getpenalty + stages[1] = function(specification,stage) local box = getbox(specification.box) local head = getlist(box) local align = specification.alignstate local distance = specification.distance + local found = { } + local max = 0 for s in nextboundary, head do - if getdata(s) == boundary then - -- todo: skip over ghost, maybe penalty, maybe glues all in one loop --- local n = getnext(s) --- if n and getid(n) == kern_code then -- also needed --- n = getnext(n) --- end --- while n and getid(n) == hlist_code and getsubtype(n) == ghost_code do --- n = getnext(n) --- end --- -- while n and getid(n) == glue_code do --- if n and getid(n) == glue_code then --- n = getnext(n) --- end - for n, id, subtype in nextnode, getnext(s) do - s = n - if id == kern_code then - -- move on (s_2 case) - elseif id == glue_code then - -- move on - elseif id == penalty_code then - -- move on (untested) - elseif id == hlist_code and subtype == ghost_code then - -- move on - else + local data = getdata(s) + if data == boundary then + s = moveon(s) + found[#found+1] = { s, 0, head } + end + end + if #found > 0 then + if found[1] then + max = distance + getdimensions(head,found[1][1]) + found[1][2] = max + end + for i=2,#found do + local f = found[i] + local n = f[1] + local p = n + while p do + if getid(p) == penalty_code and getpenalty(p) == -10000 then + local d = distance + getdimensions(p,n) + f[2] = d + f[3] = p + if d > max then + max = d + end break end + p = getprev(p) end - distance = distance + getdimensions(head,s) - break + end + -- we use a hangindent so we need to treat the first one + local f = found[1] + local delta = f[2] - max + if delta ~= 0 then + nuts.insertafter(head,moveon(head),nuts.pool.kern(-delta)) + end + for i=2,#found do + local f = found[i] + local delta = f[2] - max + nuts.insertafter(head,moveon(f[3]),nuts.pool.kern(-f[2])) -- check head end end - texsetdimen("global",d_strc_math_indent,distance) + texsetdimen("global",d_strc_math_indent,max) if align == 2 then for n in nextglue, head do setglue(n,getwidth(n),0,0,0,0) diff --git a/tex/context/base/mkxl/mult-dim.mklx b/tex/context/base/mkxl/mult-dim.mklx index 0526b3775..e2ed1993c 100644 --- a/tex/context/base/mkxl/mult-dim.mklx +++ b/tex/context/base/mkxl/mult-dim.mklx @@ -88,7 +88,7 @@ %D \macros %D {assignvalue} %D -%D A variant that does not assume dimenions ios the following: +%D A variant that does not assume dimenions is the following: %D %D \starttyping %D \assignvalue diff --git a/tex/context/base/mkxl/node-ali.lmt b/tex/context/base/mkxl/node-ali.lmt index 510e56b8e..ba2ccdde7 100644 --- a/tex/context/base/mkxl/node-ali.lmt +++ b/tex/context/base/mkxl/node-ali.lmt @@ -343,6 +343,7 @@ do local nextnode = nuts.traversers.node local texgetdimen = tex.getdimen + local texsetdimen = tex.setdimen local texgetglue = tex.getglue local texget = tex.get @@ -405,12 +406,12 @@ do if subtype == linepenalty_code then if l == 1 then if splitmethod == v_both or splitmethod == v_first then -print("FIRST") +-- print("FIRST") setpenalty(n, 10000) end elseif l == noflines then if splitmethod == v_both or splitmethod == v_last then -print("LAST") +-- print("LAST") setpenalty(n, 10000) end end @@ -772,6 +773,8 @@ end local topornament = tex.boundaries.system("c_math_matrix_ornament_t") local bottomornament = tex.boundaries.system("c_math_matrix_ornament_b") + local verticalline = tex.boundaries.system("c_math_matrix_vl_boundary") + local left = 0 local right = 0 local nofcells = 0 @@ -802,7 +805,11 @@ end c = c + 1 for bound in nextboundary, list do local ornament = getdata(bound) - if ornament == leftornament then + if ornament == verticalline then + -- this hack is is beyond ugly as we omit and span + c = c + 1 + break + elseif ornament == leftornament then if c == 1 then local w = getwidth(cell) if w > left then @@ -874,6 +881,8 @@ end rights = false tops = false bottoms = false + texsetdimen("global","d_math_matrix_max_left", left) + texsetdimen("global","d_math_matrix_max_right",right) end end diff --git a/tex/context/base/mkxl/node-aux.lmt b/tex/context/base/mkxl/node-aux.lmt index a640addc1..9794d4ab8 100644 --- a/tex/context/base/mkxl/node-aux.lmt +++ b/tex/context/base/mkxl/node-aux.lmt @@ -98,6 +98,22 @@ function nodes.takebox(id) end end +if not nuts.migratebox then -- todo: add to nodes.direct, or maybe getmigrate, setmigrate + + local setpre = nuts.setpre + local setpost = nuts.setpost + local getpre = nuts.getpre + local getpost = nuts.getpost + + function nuts.migratebox(source,target) + setpre(target,getpre(source)) + setpost(target,getpost(source)) + setpre(source) + setpost(source) + end + +end + local splitbox = tex.splitbox nodes.splitbox = splitbox diff --git a/tex/context/base/mkxl/page-one.mkxl b/tex/context/base/mkxl/page-one.mkxl index 8571c2982..aece474a7 100644 --- a/tex/context/base/mkxl/page-one.mkxl +++ b/tex/context/base/mkxl/page-one.mkxl @@ -366,6 +366,10 @@ \protected\def\page_one_command_set_top_insertions {\bgroup + % a bit strange place but okay + \page_one_command_set_always_insertions_top + \page_one_command_set_always_insertions_bottom + % \ifconditional\c_page_floats_some_waiting \noffloatinserts\zerocount \let\totaltopinserted\!!zeropoint @@ -756,22 +760,79 @@ \fi \fi}} +% \def\page_one_place_float_otherwise_else +% {\doifelseinset\v!always\floatlocationmethod +% {\page_otr_command_check_if_float_fits +% \ifconditional\c_page_floats_room +% \page_one_place_float_auto_top_bottom +% \else +% \showmessage\m!floatblocks9\empty +% \page_floats_resave\s!text +% \fi} +% {\page_otr_command_check_if_float_fits +% \ifconditional\c_page_floats_room +% \page_one_place_float_auto_top_bottom +% \else +% \page_floats_save\s!text +% \nonoindentation +% \fi}} + +% Some new always top/bottom trickery. +% +% Musical timestamp: 2023/3/2, listening to / watching Camille Bigeault on YT +% (ANATMAN, Room 8, and others), a bit late discovery, creative drumming! Gavin +% Harrison level creativity. + \def\page_one_place_float_otherwise_else - {\doifelseinset\v!always\floatlocationmethod - {\page_otr_command_check_if_float_fits - \ifconditional\c_page_floats_room - \page_one_place_float_auto_top_bottom - \else - \showmessage\m!floatblocks9\empty - \page_floats_resave\s!text - \fi} - {\page_otr_command_check_if_float_fits - \ifconditional\c_page_floats_room - \page_one_place_float_auto_top_bottom - \else - \page_floats_save\s!text - \nonoindentation - \fi}} + {\doifelseinset\v!always\floatlocationmethod + {\page_otr_command_check_if_float_fits + \ifconditional\c_page_floats_room + \page_one_place_float_auto_top_bottom + \else + \showmessage\m!floatblocks9\empty + \doifelseinset\v!top\floatlocationmethod + {\page_floats_save\s!top} + {\doifelseinset\v!bottom\floatlocationmethod + {\page_floats_save\s!bottom} + {\page_floats_resave\s!text}}% + \fi} + {\page_otr_command_check_if_float_fits + \ifconditional\c_page_floats_room + \page_one_place_float_auto_top_bottom + \else + \page_floats_save\s!text + \nonoindentation + \fi}} + +\protected\def\page_one_command_set_always_insertions_bottom_indeed + {\page_floats_flush\s!bottom\plusone + \floatingpenalty\zerocount + \page_inserts_inject\namedinsertionnumber\s!bottomfloat\bgroup + \forgetall + \blank[\rootfloatparameter\c!spacebefore]% + \page_otr_command_flush_float_box + \egroup} + +\protected\def\page_one_command_set_always_insertions_bottom % will become an otr command + {\ifzero\nofstackedfloatsincategory\s!bottom\else + \page_one_command_set_always_insertions_bottom_indeed + \expandafter\page_one_command_set_always_insertions_bottom + \fi} + +\protected\def\page_one_command_set_always_insertions_top_indeed + {\page_floats_flush\s!top\plusone + \floatingpenalty\zerocount + \page_inserts_inject\namedinsertionnumber\s!bottomfloat\bgroup + \forgetall + \blank[\rootfloatparameter\c!spacebefore]% + \page_otr_command_flush_float_box + \egroup} + +\protected\def\page_one_command_set_always_insertions_top % will become an otr command + {\ifzero\nofstackedfloatsincategory\s!top\else + \page_one_command_set_always_insertions_top_indeed + \expandafter\page_one_command_set_always_insertions_top + \fi} \mutable\def\floatautofactor{.5} diff --git a/tex/context/base/mkxl/page-sel.lmt b/tex/context/base/mkxl/page-sel.lmt index a6ea84f47..2ca93c039 100644 --- a/tex/context/base/mkxl/page-sel.lmt +++ b/tex/context/base/mkxl/page-sel.lmt @@ -19,7 +19,7 @@ do local filedata = sections[filename] if not filedata then filedata = { - data = job.loadother(addsuffix(filename,"tuc")) or false, + data = job.loadother(filename,"tuc") or false, list = { } } sections[filename] = filedata diff --git a/tex/context/base/mkxl/page-txt.mklx b/tex/context/base/mkxl/page-txt.mklx index 76aa15cab..67ca325b2 100644 --- a/tex/context/base/mkxl/page-txt.mklx +++ b/tex/context/base/mkxl/page-txt.mklx @@ -728,18 +728,31 @@ %D A few more page breakers: +% \installpagebreakmethod \v!empty +% {\page_otr_flush_all_floats +% \page_otr_command_next_page +% \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}% +% \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}% +% \page_otr_insert_dummy_page} +% +% \installpagebreakmethod \v!header +% {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}} +% +% \installpagebreakmethod \v!footer +% {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}} + \installpagebreakmethod \v!empty {\page_otr_flush_all_floats \page_otr_command_next_page - \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}% - \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}% + \ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi + \ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi \page_otr_insert_dummy_page} \installpagebreakmethod \v!header - {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}} + {\ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi} \installpagebreakmethod \v!footer - {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}} + {\ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi} %D While the header and footer lines are moved away from the main text, the top and %D bottom lines are centered. diff --git a/tex/context/base/mkxl/strc-def.mkxl b/tex/context/base/mkxl/strc-def.mkxl index 52b3b3ad9..520a9e311 100644 --- a/tex/context/base/mkxl/strc-def.mkxl +++ b/tex/context/base/mkxl/strc-def.mkxl @@ -27,6 +27,8 @@ % \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta} % \stoptext +\defineseparatorset [\v!none] [] [] + \defineseparatorset [\s!default] [] [.] \defineconversionset [\s!default] [] [numbers] \defineresetset [\s!default] [] [1] % each level diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx index 55b825fe1..b82a80a71 100644 --- a/tex/context/base/mkxl/strc-flt.mklx +++ b/tex/context/base/mkxl/strc-flt.mklx @@ -737,10 +737,10 @@ \strc_floats_set_current_tag{#tag}% \strc_floats_reset_variables % save - \edef\m_location {\floatcaptionparameter\c!location}% - \edef\m_topoffset {\floatcaptionparameter\c!topoffset}% - \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}% - \edef\m_freeregion {\floatcaptionparameter\c!freeregion}% + \edef\p_location {\floatcaptionparameter\c!location}% + \edef\p_topoffset {\floatcaptionparameter\c!topoffset}% + \edef\p_bottomoffset{\floatcaptionparameter\c!bottomoffset}% + \edef\P_freeregion {\floatcaptionparameter\c!freeregion}% % preset \resetfloatcaptionparameter \c!location \setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}% @@ -773,10 +773,10 @@ \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}% \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}% % restore - \letfloatcaptionparameter\c!location \m_location - \letfloatcaptionparameter\c!topoffset \m_topoffset - \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset - \letfloatcaptionparameter\c!freeregion \m_freeregion + \letfloatcaptionparameter\c!location \p_location + \letfloatcaptionparameter\c!topoffset \p_topoffset + \letfloatcaptionparameter\c!bottomoffset\p_bottomoffset + \letfloatcaptionparameter\c!freeregion \P_freeregion % \strc_floats_analyze_location \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal diff --git a/tex/context/base/mkxl/strc-itm.mklx b/tex/context/base/mkxl/strc-itm.mklx index a3a4c0040..cecb01cfc 100644 --- a/tex/context/base/mkxl/strc-itm.mklx +++ b/tex/context/base/mkxl/strc-itm.mklx @@ -1221,7 +1221,16 @@ % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex \strc_itemgroups_set_text_item_distance% HH: moved out and made configurable (sort of) \removeunwantedspaces - \hskip\m_strc_itemgroups_text_distance\relax + \ifnum\numexpr\c_strc_itemgroups_n_of_items+\plusone\relax=\c_strc_itemgroups_max_items + \itemgroupparameter\c!lasttextseparator + \else + \itemgroupparameter\c!textseparator + \fi + \ifempty\m_strc_itemgroups_text_distance + % safeguard + \else + \hskip\m_strc_itemgroups_text_distance\relax + \fi \fi \else \strc_itemgroups_between_command @@ -1502,7 +1511,9 @@ \dostoptagged \fi \box\b_strc_itemgroups - \hskip\interwordspace}% + \ifzerodim\wd\b_strc_itemgroups\else + \hskip\interwordspace % not configureable (yet), could be \c!textdistance + \fi}% \nobreak} \def\strc_itemgroups_handle_groups_inline_item @@ -1659,7 +1670,7 @@ \protected\def\strc_itemgroups_set_text_item_distance {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}% \ifempty\m_strc_itemgroups_text_distance - % + % \let\m_strc_itemgroups_text_distance\zeropoint % safeguard elsewhere \orelse\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname \lastnamedcs \else @@ -1978,6 +1989,8 @@ \c!criterium=\v!all, % permits 0 and negative numbers %\c!option=, \c!textdistance=\v!space, % none big medium small + \c!lasttextseparator=\itemgroupparameter\c!textseparator, + %\c!lasttextseparator=, \c!command=\strc_itemgroups_default_command, \c!indenting=\v!next, %\c!alignsymbol=v!no, diff --git a/tex/context/base/mkxl/strc-lst.lmt b/tex/context/base/mkxl/strc-lst.lmt index 359fbd6b6..b60b75208 100644 --- a/tex/context/base/mkxl/strc-lst.lmt +++ b/tex/context/base/mkxl/strc-lst.lmt @@ -95,6 +95,7 @@ local v_intro = variables.intro local v_here = variables.here local v_component = variables.component local v_product = variables.product +local v_file = variables.file local v_local = variables["local"] local v_default = variables.default @@ -443,6 +444,42 @@ local listsorters = { local filters = setmetatableindex(function(t,k) return t[v_default] end) + +local used = { } + +function lists.use(tag,filename,class) + used[tag] = { + names = names, -- optional + filename = filename, + data = job.loadother(filename), + } +end + +implement { + name = "uselist", + arguments = "3 strings", + actions = lists.use, +} + +filters.external = function(specification) + local collected = specification.collected or { } + local result = { } + local nofresult = 0 + local all = specification.all + local names = specification.names + setmetatableindex(result,{ external = specification.reference }) -- brr, we also have the name in + for i=1,#collected do + local v = collected[i] + local m = v.metadata + if m and names[m.name] or all then + nofresult = nofresult + 1 + result[nofresult] = v + end + end + return result +end + + local function filtercollected(specification) -- local names = specification.names or { } @@ -453,10 +490,10 @@ local function filtercollected(specification) local forced = specification.forced or { } local nested = specification.nested or false local sortorder = specification.sortorder or specification.order - -- local numbers = documents.data.numbers local depth = documents.data.depth local block = false -- all + -- local wantedblock, wantedcriterium = lpegmatch(splitter,criterium) -- block:criterium if wantedblock == "" or wantedblock == v_all or wantedblock == v_text then criterium = wantedcriterium ~= "" and wantedcriterium or criterium @@ -473,7 +510,7 @@ local function filtercollected(specification) names = settings_to_set(names) end local all = not next(names) or names[v_all] or false - -- + -- -- specification.names = names specification.criterium = criterium specification.number = 0 -- obsolete @@ -853,47 +890,26 @@ filters[v_component] = function(specification) return result end --- filters[v_product] = function(specification) --- local reference = specification.reference --- if reference and reference ~= "" then --- -- local utilitydata = job.loadother(reference,true) --- local fullname = file.replacesuffix(reference,"tuc") --- if lfs.isfile(fullname) then --- local utilitydata = job.loadother(fullname) --- if utilitydata then --- local collected = utilitydata.structures.lists.collected or { } --- setmetatableindex(collected,{ external = reference }) --- return collected --- end --- end --- end --- return { } --- end - filters[v_product] = function(specification) local reference = specification.reference if reference and reference ~= "" then - local utilitydata = job.loadother(reference,true) --- local fullname = file.replacesuffix(reference,"tuc") --- if lfs.isfile(fullname) then --- local utilitydata = job.loadother(fullname) - if utilitydata then - local collected = utilitydata.structures.lists.collected or { } - local result = { } - local nofresult = 0 - local all = specification.all - local names = specification.names + local utilitydata = job.loadother(reference) + if utilitydata then + local collected = utilitydata.structures.lists.collected or { } + local result = { } + local nofresult = 0 + local all = specification.all + local names = specification.names setmetatableindex(result,{ external = reference }) -- brr - for i=1,#collected do - local v = collected[i] - local m = v.metadata - if m and names[m.name] or all then - nofresult = nofresult + 1 - result[nofresult] = v - end + for i=1,#collected do + local v = collected[i] + local m = v.metadata + if m and names[m.name] or all then + nofresult = nofresult + 1 + result[nofresult] = v end - return result --- end + end + return result end end return { } @@ -977,6 +993,14 @@ function lists.getresult(r) end function lists.process(specification) + local names = specification.names + local external = used[names or ""] + if external then + specification.reference = names + specification.names = external.names + specification.collected = external.data.structures.lists.collected + specification.criterium = "external" + end local result = filtercollected(specification) local total = #result lists.result = result @@ -1542,3 +1566,41 @@ function lists.reordered(entry) end return numberdata end + +-- external data + +function lists.integrate(utilitydata) + local filename = utilitydata.comment.file + if filename then + local structures = utilitydata.structures + if structures then + local lists = structures.lists.collected or { } + if lists then + local sections = structures.sections.collected or { } + local pages = structures.pages.collected or { } + for i=1,#lists do + local entry = lists[i] + local references = entry.references + if references then + local section = references.section + local realpage = references.realpage + -- maybe entry.* instead: + references.sectiondata = section and sections[section] + references.pagedata = realpage and pages[realpage] + -- get rid of these, maybe even crash as these are bogus + -- references.internal = nil + -- references.realpage = nil + -- references.section = nil + if references.x then + references.x = nil + end + if references.y then + references.y = nil + end + references.external = filename + end + end + end + end + end +end diff --git a/tex/context/base/mkxl/strc-lst.mklx b/tex/context/base/mkxl/strc-lst.mklx index 66a801241..6b8f2504f 100644 --- a/tex/context/base/mkxl/strc-lst.mklx +++ b/tex/context/base/mkxl/strc-lst.mklx @@ -78,6 +78,12 @@ %\c!expansion=, \c!limittext=\languageparameter\c!limittext] % not used currently +%D Kind of new: + +\permanent\protected\tolerant\def\uselist[#1]#*[#2]#*[#3]% tag file + {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}% + \clf_uselist{#1}{#2}{#3}} + %D Helpers: \permanent\protected\def\usenestedliststyleandcolor#style#color% will change diff --git a/tex/context/base/mkxl/strc-mat.mkxl b/tex/context/base/mkxl/strc-mat.mkxl index bcbe4a6f8..516e82190 100644 --- a/tex/context/base/mkxl/strc-mat.mkxl +++ b/tex/context/base/mkxl/strc-mat.mkxl @@ -141,6 +141,12 @@ \permanent\protected\defcsname\e!start\v!formula\endcsname{\strc_formulas_start_formula{}} \permanent\protected\defcsname\e!stop \v!formula\endcsname{\strc_formulas_stop_formula} +\permanent\protected\def\startnamedformula[#1]% + {\strc_formulas_start_formula{#1}} + +\permanent\protected\def\stopnamedformula + {\strc_formulas_stop_formula} + \let\strc_formulas_start_formula\relax % defined later \let\strc_formulas_stop_formula \relax % defined later @@ -975,13 +981,12 @@ \setupformula % [\c!split=\v!no, - [\c!split=\v!text, % multi line no page breaks + [\c!split=\v!yes, \c!numberlocation=, \c!textdistance=\zeropoint, - %\c!interlinespace=1.5\lineheight, + \c!interlinespace=1.125\lineheight, % back again, to be tuned \c!textmargin=2\emwidth, - \c!numbermethod=\v!down, - \c!interlinespace=] + \c!numbermethod=\v!down] % for the moment (when testing) we use a penalty 1 @@ -1206,12 +1211,15 @@ \fi{#2}% \fi} +\def\strc_math_break_here_indeed + {\strut\break} + \protected\def\strc_math_page_here {\ifmmode \ifconditional\c_strc_math_trace_hang \strc_math_trace_okay{darkyellow}{B P}% \fi - \break + \strc_math_break_here_indeed \vadjust pre {\vfill\penalty-100000}% \strc_math_pickup_again \fi} @@ -1221,7 +1229,7 @@ \ifconditional\c_strc_math_trace_hang \strc_math_trace_okay{darkyellow}{B S}% \fi - \break + \strc_math_break_here_indeed \vadjust pre {\penalty\plustenthousand}% \strc_math_pickup_again \fi} @@ -1231,7 +1239,7 @@ \ifconditional\c_strc_math_trace_hang \strc_math_trace_okay{darkgreen}{B}% \fi - \break + \strc_math_break_here_indeed \strc_math_pickup_again \fi} @@ -1392,7 +1400,10 @@ \doadaptleftskip\p_margin \doadaptrightskip\p_margin \fi - % + % this was lost + \edef\p_interlinespace{\formulaparameter\c!interlinespace}% + \ifempty\p_interlinespace\else\baselineskip\p_interlinespace\fi + % and is now back \global\setfalse\c_strc_math_aligned_here \hsize\d_strc_formulas_display_width \displaywidth\hsize @@ -1557,7 +1568,8 @@ \iftrialtypesetting\else \global\advanceby\c_strc_formulas_n\plusone \fi - \def\currentformula{#1}% + \edef\currentformula{#1}% + \usesetupsparameter\formulaparameter % new \dostarttaggedchained\t!formula\currentformula\??formula \strc_math_set_options{#2}% \strc_math_set_split diff --git a/tex/context/base/mkxl/strc-ref.lmt b/tex/context/base/mkxl/strc-ref.lmt index b97a1619b..26b189475 100644 --- a/tex/context/base/mkxl/strc-ref.lmt +++ b/tex/context/base/mkxl/strc-ref.lmt @@ -18,7 +18,7 @@ local format, gmatch, match, strip = string.format, string.gmatch, string.match, local floor = math.floor local rawget, tonumber, type, next = rawget, tonumber, type, next local lpegmatch = lpeg.match -local insert, remove, copytable = table.insert, table.remove, table.copy +local insert, remove, copytable, sortedhash = table.insert, table.remove, table.copy, table.sortedhash local formatters = string.formatters local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match @@ -130,6 +130,9 @@ local c_locationcount = texiscount("locationcount") local c_locationorder = texiscount("locationorder") local c_lastdestinationattribute = texiscount("lastdestinationattribute") +local p_splitter = lpeg.splitat(":") +local p_lower = lpeg.patterns.utf8lower + local context = context local ctx_pushcatcodes = context.pushcatcodes @@ -494,7 +497,7 @@ implement { -- no metatable here .. better be sparse -local function register_from_list(collected,derived,pages,sections) +local function register_from_list(collected,derived,external) local derived_g = derived[""] -- global local derived_p = nil local derived_c = nil @@ -556,11 +559,24 @@ local function register_from_list(collected,derived,pages,sections) end end -references.registerfromlist = function(collected,pages,sections) - register_from_list(collected,derived,pages,sections) +function references.integrate(utilitydata) + local filename = utilitydata.comment.file + if filename then + -- lists are already internalized + local structures = utilitydata.structures + if structures then + local lists = structures.lists.collected + if lists then + register_from_list(lists,derived,filename) + end + end + end end -references.registerinitializer(function() register_from_list(lists.collected,derived) end) +references.registerinitializer(function() + -- the main document + register_from_list(lists.collected,derived) +end) -- tracing @@ -953,7 +969,8 @@ local function resolve(prefix,reference,args,set) -- we start with prefix,refere local var = splitreference(ri) if var then var.reference = ri - local vo, vi = var.outer, var.inner + local vo = var.outer + local vi = var.inner -- we catch this here .. it's a way to pass references with commas if vi == "name" then local arguments = var.arguments @@ -1154,11 +1171,14 @@ local function loadproductreferences(productname,componentname,utilitydata) report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a", "product","regular",productname,prefix,reference) end - if not reference.sectiondata then - reference.sectiondata = sections[reference.section or false] - end - if not reference.pagedata then - reference.pagedata = pages[reference.realpage or false] + local references = data.references + if references then + if not references.sectiondata then + references.sectiondata = sections[references.section or false] + end + if not references.pagedata then + references.pagedata = pages[references.realpage or false] + end end end end @@ -1296,26 +1316,37 @@ end) function references.loadpresets(product,component) -- we can consider a special components hash if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename - productdata.product = product + productdata.product = product productdata.component = component -- todo: use other locator - local fullname = file.replacesuffix(product,"tuc") - if lfs.isfile(fullname) then - local utilitydata = job.loadother(fullname) - if utilitydata then - if trace_importing then - report_importing("loading references for component %a of product %a from %a",component,product,fullname) - end - loadproductvariables (product,component,utilitydata) - loadproductreferences(product,component,utilitydata) - loadproductcomponents(product,component,utilitydata) + local utilitydata = job.loadother(product) + if utilitydata then + if trace_importing then + report_importing("loading references for component %a of product %a",component,product) end + loadproductvariables (product,component,utilitydata) + loadproductcomponents(product,component,utilitydata) + loadproductreferences(product,component,utilitydata) +-- loadproductcomponents(product,component,utilitydata) end end end references.productdata = productdata +implement { + name = "usereferences", + public = true, + protected = true, + arguments = "optional", + actions = function(product) + local utilitydata = job.loadother(product) + if utilitydata then + loadexternalreferences(product,utilitydata) + end + end +} + local useproduct = commands.useproduct if useproduct then @@ -1392,6 +1423,10 @@ local function report_identify_outer(set,var,i,type) end end +local function report_identify_auto(set,var,i,type) + report_identifying("type %a, reference %a, using auto outer %a",type,reference,var.outer) +end + local function identify_special(set,var,i) local special = var.special local s = specials[special] @@ -1547,6 +1582,61 @@ local function unprefixed_inner(set,var,prefix,collected,derived,tobesaved) return var end +local function identify_auto(set,var,i) + local inner = var.inner + local prefix = set.prefix or "" + if prefix == "" then + prefix, inner = lpegmatch(p_splitter,inner) + if not inner then + inner = var.inner + prefix = false + end + end + local function okay(o,where) + var.outer = o + if trace_identifying then + report_identify_auto(set,var,i,where) + end + return true + end + for o, odata in sortedhash(externals) do + if o == outer or not odata then + -- skip this one + elseif prefix and prefix ~= "" then + local pdata = odata[prefix] + if pdata then + local r = pdata[inner] + if r then + return okay(o,"2h") + end + end + -- escape from prefix +-- local pdata = odata[""] +-- if pdata then +-- local r = pdata[inner] +-- if r then +-- return okay(o,"2h") +-- end +-- end + else + for p, pdata in sortedhash(odata) do + local r = pdata[inner] + if r then + return okay(o,"2j") + end + end + local pdata = odata[""] + if pdata then + r = pdata[inner] + if r then + return okay(o,"2k") + end + end + end + end + return false +end + local function identify_outer(set,var,i) local outer = var.outer local inner = var.inner @@ -1587,18 +1677,6 @@ local function identify_outer(set,var,i) end end end - local external = productdata.componentreferences[outer] - if external then - local v = identify_inner(set,var,"",external) - if v then - v.kind = "outer with inner" - set.external = true - if trace_identifying then - report_identify_outer(set,v,i,"2c") - end - return v - end - end local external = productdata.productreferences[outer] if external then local vi = external[inner] @@ -1612,6 +1690,18 @@ local function identify_outer(set,var,i) return var end end + local external = productdata.componentreferences[outer] + if external then + local v = identify_inner(set,var,"",external) + if v then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2c") + end + return v + end + end -- the rest local special = var.special local arguments = var.arguments @@ -1675,6 +1765,7 @@ end local function identify_inner_or_outer(set,var,i) -- here we fall back on product data local inner = var.inner + if inner and inner ~= "" then -- first we look up in collected and derived using the current prefix @@ -1689,6 +1780,10 @@ local function identify_inner_or_outer(set,var,i) return v end + if var.inner == var.reference and identify_auto(set,var,i) and var.outer and var.outer ~= "" then + return identify_outer(set,var,i) + end + -- nest we look at each component (but we can omit the already consulted one local jobstructure = job.structure @@ -1861,6 +1956,9 @@ local function identify(prefix,reference) elseif spe then var = identify_special(set,var,i) elseif var.outer then + if var.outer == "auto" then + identify_auto(set,var,i) + end var = identify_outer(set,var,i) elseif var.arguments then var = identify_arguments(set,var,i) @@ -2837,9 +2935,6 @@ end -- experimental: -local p_splitter = lpeg.splitat(":") -local p_lower = lpeg.patterns.utf8lower - -- We can cache lowercased titles which saves a lot of time, but then -- we can better have a global cache with weak keys. diff --git a/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx index e7073b36d..a1b6ac22d 100644 --- a/tex/context/base/mkxl/strc-ref.mklx +++ b/tex/context/base/mkxl/strc-ref.mklx @@ -557,7 +557,7 @@ %D \NC \NC $\star$ \NC \NC\NR %D \stoptabulate -\permanent\protected\def\usereferences[#filename]{} % obsolete +% \permanent\protected\def\usereferences[#filename]{} % defined at the lua end %D As mentioned we will also use the cross reference mechanism for navigational %D purposes. The main reason for this is that we want to treat both categories diff --git a/tex/context/base/mkxl/strc-reg.lmt b/tex/context/base/mkxl/strc-reg.lmt index a3a7dae6c..e2c4fdf02 100644 --- a/tex/context/base/mkxl/strc-reg.lmt +++ b/tex/context/base/mkxl/strc-reg.lmt @@ -1037,38 +1037,68 @@ function registers.finalize(data,options) -- maps character to index (order) data.result = split end --- local function analyzeregister(class,options) --- local data = collected[class] --- if data and data.entries then --- options = options or { } --- sorters.setlanguage(options.language,options.method,options.numberorder) --- registers.filter(data,options) -- filter entries into results (criteria) --- registers.prepare(data,options) -- adds split table parallel to list table --- registers.sort(data,options) -- sorts results --- registers.unique(data,options) -- get rid of duplicates --- registers.finalize(data,options) -- split result in ranges --- data.metadata.sorted = true --- return data.metadata.nofsorted or 0 --- else --- return 0 --- end --- end +local used = { } + +function registers.use(tag,filename,class,prefix) + used[tag] = { + class = class, + filename = filename, + data = job.loadother(filename), + prefix = prefix or class, + } +end + +implement { + name = "useregister", + arguments = "4 strings", + actions = registers.use, +} + +implement { + name = "registerprefix", + arguments = "string", + actions = function(tag) + local u = used[tag] + if u then + context(u.prefix) + end + end +} local function analyzeregister(class,options) local data = rawget(collected,class) if not data then - local list = utilities.parsers.settings_to_array(class) - local entries = { } - local metadata = false + local list = utilities.parsers.settings_to_array(class) + local entries = { } + local nofentries = 0 + local metadata = false for i=1,#list do local l = list[i] + local u = used[l] local d = collected[l] - local e = d.entries - for i=1,#e do - entries[#entries+1] = e[i] + if u then + local collected = u.data.structures.registers.collected + local class = u.class + if collected and class then + d = collected[class] + end end - if not metadata then - metadata = d.metadata + if d then + local e = d.entries + local u = u and { u.prefix } or nil + for i=1,#e do + local ei = e[i] + nofentries = nofentries + 1 + entries[nofentries] = ei + if u then + local eil = ei.list + eil[#eil+1] = u + ei.external = l -- this is the (current) abstract tag, used for prefix + end + end + if not metadata then + metadata = d.metadata + end end end data = { @@ -1080,11 +1110,11 @@ local function analyzeregister(class,options) if data and data.entries then options = options or { } sorters.setlanguage(options.language,options.method,options.numberorder) - registers.filter(data,options) -- filter entries into results (criteria) - registers.prepare(data,options) -- adds split table parallel to list table - registers.sort(data,options) -- sorts results - registers.unique(data,options) -- get rid of duplicates - registers.finalize(data,options) -- split result in ranges + registers.filter(data,options) -- filter entries into results (criteria) + registers.prepare(data,options) -- adds split table parallel to list table + registers.sort(data,options) -- sorts results + registers.unique(data,options) -- get rid of duplicates + registers.finalize(data,options) -- split result in ranges data.metadata.sorted = true return data.metadata.nofsorted or 0 else @@ -1131,12 +1161,12 @@ local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec) ctx_registerpagerange( f_entry.metadata.name or "", f_entry.processors and f_entry.processors[2] or "", - fer.internal or 0, + f_entry.external or fer.internal or 0, fer.realpage or 0, function() h_prefixpage(f_entry,prefixspec,pagespec) end, - ter.internal or 0, + t_entry.external or ter.internal or 0, ter.lastrealpage or ter.realpage or 0, function() if is_last then @@ -1153,7 +1183,7 @@ local function pagenumber(entry,prefixspec,pagespec) ctx_registeronepage( entry.metadata.name or "", entry.processors and entry.processors[2] or "", - er.internal or 0, + entry.external or er.internal or 0, er.realpage or 0, function() h_prefixpage(entry,prefixspec,pagespec) end ) @@ -1162,9 +1192,10 @@ end local function packed(f_entry,t_entry) local fer = f_entry.references local ter = t_entry.references +-- todo: make sure we don't end up here with external ctx_registerpacked( - fer.internal or 0, - ter.internal or 0 + f_entry.external or fer.internal or 0, + t_entry.external or ter.internal or 0 ) end @@ -1286,6 +1317,10 @@ function registers.flush(data,options,prefixspec,pagespec) -- report_registers("invalid see entry in register %a, reference %a",entry.metadata.name,list[1][1]) end end + if entry.external then + local list = entry.list + list[#list] = nil + end end -- ok, this is tricky: we use e[i] delayed so we need it to be local -- but we don't want to allocate too many entries so there we go @@ -1497,7 +1532,7 @@ function registers.flush(data,options,prefixspec,pagespec) local seeword = entry.seeword local seetext = seeword.text or "" local processor = seeword.processor or (entry.processors and entry.processors[1]) or "" - local seeindex = entry.references.seeindex or "" + local seeindex = entry.external or entry.references.seeindex or "" ctx_registerseeword( metadata.name or "", i, @@ -1696,3 +1731,46 @@ interfaces.implement { arguments = { "string", "string", "integer" }, actions = { registers.findinternal, context }, } + +-- external data + +function registers.integrate(utilitydata) + local filename = utilitydata.comment.file + if filename then + local structures = utilitydata.structures + if structures then + local registers = structures.registers.collected or { } + if registers then + local sections = structures.sections.collected or { } + local pages = structures.pages .collected or { } + for class, register in next, registers do + local entries = register.entries + if entries then + for i=1,#entries do + local entry = entries[i] + local references = entry.references + if references then + local section = references.section + local realpage = references.realpage + -- maybe entry.* instead: + references.sectiondata = section and sections[section] + references.pagedata = realpage and pages[realpage] + -- get rid of these, maybe even crash as these are bogus + -- references.internal = nil -- or 0 + -- references.realpage = nil -- or 0 + -- references.section = nil -- or 0 + if references.x then + references.x = nil + end + if references.y then + references.y = nil + end + references.external = filename -- not really needed + end + end + end + end + end + end + end +end diff --git a/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl index 485b68b74..afe3d27a0 100644 --- a/tex/context/base/mkxl/strc-reg.mkxl +++ b/tex/context/base/mkxl/strc-reg.mkxl @@ -757,6 +757,41 @@ % todo \index{todo} % \stoptext +%D Kind of new: + +% % index-1.tex: +% +% \setupinteraction[state=start] +% \starttext +% test \index{entry WB.1} \page empty \page +% test \index{another WB.1} \page empty \page +% test \index{onemore WB.1} \page empty \page +% test \index{whatever WB.1} \page empty \page +% test \index{common} \page empty \page +% \placeregister[index] +% \stoptext +% +% % index-2.tex: +% +% \setupinteraction[state=start] +% \defineregister[xedni] +% \useregister[workbook][index-1][index][WB ] +% \starttext +% test \index{onemore TB.1} \page +% test \index{another TB.1} \page +% test \index{entry TB.1} \page +% test \index{common} \page +% test \xedni{onemore TB.2} \page +% test \xedni{another TB.2} \page +% test \xedni{entry TB.2} \page +% test \xedni{common} \page +% \placeregister[index,xedni,workbook] +% \stoptext + +\permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]% tag file class prefix + {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}% + \clf_useregister{#1}{#2}{#3}{#4}} + %D Character rendering (sections): \installcorenamespace{registerindicator} @@ -1070,17 +1105,45 @@ \let\currentregisterrealpage\!!zerocount % todo: more general accessor -\permanent\protected\def\withregisterpagecommand#1#2#3#4% +% keep as reference +% +% \permanent\protected\def\withregisterpagecommand#1#2#3#4% +% {\ifcase#3\relax +% {\tt [entry\space not\space flushed]}% +% \else +% \def\currentregisterpageindex{#2}% +% \def\currentregisterrealpage{#3}% +% \iflocation +% \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% +% \else +% \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% +% \fi +% \fi} +% +% todo: adapt \strc_references_goto_internal to take an extra argument, the ref + +\permanent\protected\def\withregisterpagecommand#1#2#3#4% #1:processor #2:internal #3:realpage #4:page {\ifcase#3\relax {\tt [entry\space not\space flushed]}% \else \def\currentregisterpageindex{#2}% \def\currentregisterrealpage{#3}% - \iflocation - \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% + \ifchknum\currentregisterpageindex\or + \lettonothing\currentregisterpageprefix \else - \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% + \def\currentregisterpageprefix{\clf_registerprefix{\currentregisterpageindex}}% \fi + \iflocation + \ifempty\currentregisterpageprefix + \strc_references_get_simple_reference{internal(\currentregisterpageindex)}% + \else + \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}% + \fi + \global\lastsavedreferenceattribute\currentreferenceattribute + \c_attr_reference\currentreferenceattribute + \setlocationattributes + \fi + \applyprocessor{#1}{\currentregisterpageprefix\registerparameter\c!pagecommand{#4}}% \fi} \lettonothing\m_current_register @@ -1151,7 +1214,9 @@ \iflocation \def\currentregisterseeindex{#4}% \ifconditional\c_strc_registers_text_interaction - \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% + \ifchknum\currentregisterpageindex\or + \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% + \fi \else \doapplyregisterentrycommand{#2}{#5}% \fi @@ -1179,6 +1244,30 @@ \applyprocessor{#1}{#2}% \fi} +% \permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word +% {\pushcurrentregister{#1}% +% \ifnum#2=\plusone +% \registerpageseparator +% \fi +% \global\setconstant\c_strc_registers_page_state\plustwo +% \def\currentregisterpageindex{#5}% +% \dostarttagged\t!registersee\empty +% \settrue\c_strc_registers_page_done +% \iflocation +% \def\currentregisterseeindex{#6}% +% \else +% \lettonothing\currentregisterseeindex +% \fi +% \ifnum#2=\plusone +% \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% +% \orelse\ifnum#2=#3\relax +% \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% +% \else +% ,\space\doapplyregisterseecommand{#4}{#7}% +% \fi +% \dostoptagged +% \popcurrentregister} + \permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word {\pushcurrentregister{#1}% \ifnum#2=\plusone @@ -1186,19 +1275,30 @@ \fi \global\setconstant\c_strc_registers_page_state\plustwo \def\currentregisterpageindex{#5}% + \def\currentregisterseeindex{#6}% \dostarttagged\t!registersee\empty \settrue\c_strc_registers_page_done - \iflocation - \def\currentregisterseeindex{#6}% + \ifchknum\currentregisterseeindex\or + \lettonothing\currentregisterpageprefix \else - \lettonothing\currentregisterseeindex + \def\currentregisterpageprefix{\clf_registerprefix{\currentregisterseeindex}}% + \fi + \iflocation + \ifempty\currentregisterpageprefix + \strc_references_get_simple_reference{internal(\currentregisterseeindex)}% + \else + \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}% + \fi + \global\lastsavedreferenceattribute\currentreferenceattribute + \c_attr_reference\currentreferenceattribute + \setlocationattributes \fi \ifnum#2=\plusone - \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% + \labeltexts\v!see{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}% \orelse\ifnum#2=#3\relax - \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% + \labeltexts\v!and{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}% \else - ,\space\doapplyregisterseecommand{#4}{#7}% + ,\space\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}% \fi \dostoptagged \popcurrentregister} diff --git a/tex/context/base/mkxl/strc-sec.mkxl b/tex/context/base/mkxl/strc-sec.mkxl index 002945208..227d24704 100644 --- a/tex/context/base/mkxl/strc-sec.mkxl +++ b/tex/context/base/mkxl/strc-sec.mkxl @@ -125,6 +125,8 @@ % \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2} % } +\mutable\lettonothing\currentstructureextradata + \protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported) {\begingroup \setupstructure[\c!name={#1},#2]% @@ -143,6 +145,7 @@ \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}% \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}% \xdef\currentstructureplaceholder {\structureparameter\c!placeholder}% + \xdef\currentstructureextradata {\structureparameter\c!extradata}% \ifx\currentstructureexpansion\s!xml \xmlstartraw \xdef\currentstructuretitle {\structureparameter\c!title}% @@ -774,10 +777,6 @@ \newtoks\everyheadsynchronization -% \appendtoks -% \currentstructuresynchronize -% \to \everyheadsynchronization - \aliased\let\currentstructuresynchronize\donothing \appendtoks @@ -785,9 +784,15 @@ \enforced\glet\currentstructuresynchronize\donothing \to \everyheadsynchronization + \permanent\protected\def\theheadsynchronization % public {% no, interferes: \signalcharacter - \the\everyheadsynchronization} + \the\everyheadsynchronization + % new, this might move to a better place, e.g. first in the box + \currentstructureextradata + \lettonothing\currentstructureextradata + % done (can be used for e.g. index entries) + } % BEWARE: \marking[section]{my text} does not work as we use list indices instead % so we need a 'keep track of raw set option' (or maybe a funny internal prefix) diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl index b3b4b4c88..6c4c3fd47 100644 --- a/tex/context/base/mkxl/tabl-tbl.mkxl +++ b/tex/context/base/mkxl/tabl-tbl.mkxl @@ -1997,23 +1997,23 @@ \edef\currenttabulatemove{#1}% \setupcurrenttabulatemove[#2]% \fi - \edef\m_orientation{\theorientation{\tabulatemoveparameter\c!orientation}}% - \edef\m_xoffset {\tabulatemoveparameter\c!xoffset}% - \edef\m_yoffset {\tabulatemoveparameter\c!yoffset}% + \edef\p_orientation{\theorientation{\tabulatemoveparameter\c!orientation}}% + \edef\p_xoffset {\tabulatemoveparameter\c!xoffset}% + \edef\p_yoffset {\tabulatemoveparameter\c!yoffset}% \scratchyoffset - \ifx\m_yoffset\v!depth + \ifx\p_yoffset\v!depth -\strutdp - \orelse\ifx\m_yoffset\v!height + \orelse\ifx\p_yoffset\v!height -\strutht \else - \m_yoffset + \p_yoffset \fi \relax - \scratchxoffset\m_xoffset\relax + \scratchxoffset\p_xoffset\relax \xdef\tabl_tabulate_tm {\ifzeropt\scratchxoffset\else\s!xmove \the\scratchxoffset\fi % or move \ifzeropt\scratchyoffset\else\s!ymove \the\scratchyoffset\fi % or move - \ifzero \m_orientation \else\s!orientation\m_orientation \fi + \ifzero \p_orientation \else\s!orientation\p_orientation \fi }% \endlocalcontrol \noalign\tabl_tabulate_tm{}} diff --git a/tex/context/base/mkxl/tabl-xtb.lmt b/tex/context/base/mkxl/tabl-xtb.lmt index b69bfd873..c475d6233 100644 --- a/tex/context/base/mkxl/tabl-xtb.lmt +++ b/tex/context/base/mkxl/tabl-xtb.lmt @@ -79,6 +79,7 @@ local copynodelist = nuts.copylist local hpacknodelist = nuts.hpack local flushnodelist = nuts.flushlist local takebox = nuts.takebox +local migratebox = nuts.migratebox local nodepool = nuts.pool @@ -562,7 +563,7 @@ end local function showwidths(where,widths,autowidths) local result = { } for i=1,#widths do - result[#result+1] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ") + result[i] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ") end return report_xtable("%s widths: %s",where,concat(result," ")) end @@ -872,6 +873,7 @@ function xtables.construct() -- setwhd(list,0,0,0) -- faster: local h = new_hlist(list) + migratebox(list,h) list = h -- if start then diff --git a/tex/context/base/mkxl/task-ini.lmt b/tex/context/base/mkxl/task-ini.lmt index 6d4ebfcc2..d2ce7f770 100644 --- a/tex/context/base/mkxl/task-ini.lmt +++ b/tex/context/base/mkxl/task-ini.lmt @@ -63,6 +63,7 @@ appendaction("processors", "lists", "typesetters.rubies.check", appendaction("processors", "lists", "typesetters.characteralign.handler", nil, "nut", "disabled" ) appendaction("processors", "lists", "typesetters.spacings.handler", nil, "nut", "disabled" ) appendaction("processors", "lists", "typesetters.kerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.tighten.handler", nil, "nut", "disabled" ) appendaction("processors", "lists", "typesetters.digits.handler", nil, "nut", "disabled" ) appendaction("processors", "lists", "typesetters.italics.handler", nil, "nut", "disabled" ) appendaction("processors", "lists", "languages.visualizediscretionaries", nil, "nut", "disabled" ) diff --git a/tex/context/base/mkxl/typo-scr.mkxl b/tex/context/base/mkxl/typo-scr.mkxl index bb67228cd..159b0be6b 100644 --- a/tex/context/base/mkxl/typo-scr.mkxl +++ b/tex/context/base/mkxl/typo-scr.mkxl @@ -48,11 +48,36 @@ \appendtoks \frozen\protected\edefcsname\currentlow \endcsname{\typo_scripts_low [\currentlow ]}\to \everydefinelow \appendtoks \frozen\protected\edefcsname\currenthigh\endcsname{\typo_scripts_high[\currenthigh]}\to \everydefinehigh +\def\typo_scripts_distance#1% + {\edef\p_distance{#1\c!distance}% + \ifx\p_distance\v!tight + \tightfitboundary + \else + \kern\p_distance\relax + \fi} + +%D \startbuffer +%D \setuplow [distance=\zeropoint] +%D \setuphigh[distance=\zeropoint] +%D +%D {\showglyphs f\high{x}\quad p\high{x}\quad} +%D +%D \setuplow [\c!distance=\v!tight] +%D \setuphigh[\c!distance=\v!tight] +%D +%D {\showglyphs f\high{x}\quad p\high{x}\quad} +%D \stopbuffer +%D +%D \typebuffer {\getbuffer} + +% \type{f\kern\tightfitcompensation\high{x}} +% \type{f\tightfitboundary \high{x}} + \protected\def\typo_scripts_low[#1]#2% {\dontleavehmode \begingroup \edef\currentlow{#1}% - \kern\lowparameter\c!distance\relax + \typo_scripts_distance\lowparameter \setbox\scratchbox\runninghbox\bgroup \lower\lowparameter\c!down\hbox\bgroup \ifempty\fontsize @@ -78,7 +103,7 @@ {\dontleavehmode \begingroup \edef\currenthigh{#1}% - \kern\highparameter\c!distance\relax + \typo_scripts_distance\highparameter \setbox\scratchbox\runninghbox\bgroup \raise\highparameter\c!up\hbox\bgroup \ifempty\fontsize @@ -131,15 +156,15 @@ \c!down=.58\exheight] % values \appendtoks - \frozen\setuevalue\currentlowhigh{\typo_scripts_lowhigh[\currentlowhigh]}% + \frozen\edefcsname\currentlowhigh\endcsname{\typo_scripts_lowhigh[\currentlowhigh]}% \to \everydefinelowhigh \tolerant\protected\def\typo_scripts_lowhigh[#1]#*[#2]#:#3#4% todo: align .. [#1] is compatible hack {\dontleavehmode \runninghbox\bgroup \edef\currentlowhigh{#1}% + \typo_scripts_distance\lowhighparameter \dostarttagged\t!subsup\currentlowhigh - \scratchdimen\lowhighparameter\c!distance\relax \setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#3}}% \setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#4}}% \edef\p_align{#2}% @@ -163,8 +188,7 @@ \egroup} \def\typo_scripts_lowhigh_low_high#1#2#3#4% - {\kern\scratchdimen - \setbox\scratchbox\hpack\bgroup + {\setbox\scratchbox\hpack\bgroup #1\lowhighparameter#2\hbox\bgroup \ifempty\fontsize \ifmmode @@ -221,7 +245,7 @@ \c!down=.8\struthtdp] \appendtoks - \frozen\setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh[\currentlowmidhigh]}% + \frozen\edefcsname\currentlowmidhigh\endcsname{\typo_scripts_lowmidhigh[\currentlowmidhigh]}% \to \everydefinelowmidhigh \protected\def\typo_scripts_lowmidhigh[#1]#2#3#4% diff --git a/tex/context/base/mkxl/typo-wrp.lmt b/tex/context/base/mkxl/typo-wrp.lmt index 5b31c4015..b77e27532 100644 --- a/tex/context/base/mkxl/typo-wrp.lmt +++ b/tex/context/base/mkxl/typo-wrp.lmt @@ -9,7 +9,9 @@ if not modules then modules = { } end modules ['typo-wrp'] = { -- begin/end par wrapping stuff ... more to come local boundary_code = nodes.nodecodes.boundary +local glyph_code = nodes.nodecodes.glyph local wordboundary_code = nodes.boundarycodes.word +local userboundary_code = nodes.boundarycodes.user local nuts = nodes.nuts @@ -17,16 +19,25 @@ local findtail = nuts.tail local getprev = nuts.getprev local setnext = nuts.setnext local getid = nuts.getid +local getdata = nuts.getdata +local isglyph = nuts.isglyph local getsubtype = nuts.getsubtype local getattr = nuts.getattr local flushnodelist = nuts.flushlist +local traverse_boundary = nuts.traversers.boundary +local insertnodebefore = nuts.insertbefore +local newkern = nuts.pool.kern + +local fontdata = fonts.hashes.identifiers local enableaction = nodes.tasks.enableaction +local implement = interfaces.implement + local wrappers = { } typesetters.wrappers = wrappers -local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end) +local trace_wrappers trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end) local report = logs.reporter("paragraphs","wrappers") -- In luametatex we don't have the parfilskip attached yet but we can have final glue @@ -64,18 +75,86 @@ local function remove_dangling_crlf(head,tail) return head, tail end -function wrappers.handler(head) - if head then - local tail = findtail(head) - head, tail = remove_dangling_crlf(head,tail) -- will be action chain +implement { + name = "enablecrlf", + onlyonce = true, + actions = function() + enableaction("processors","typesetters.wrappers.handler") + end +} + +-- Here's a solution for a trivial challenge by MS who got it from the internet +-- (SE). If needed we can make it a bit more granular. + +local tighten = { } +typesetters.tighten = tighten + +local trace_tighten trackers.register("typesetters.tighten",function(v) trace_tighten = v end) +local report = logs.reporter("typesetters","tighten") + +local a_tightfit_boundary = tex.boundaries.system("c_tightfit_boundary") -- private, not defined with \defineboundary + +local function bbcompensation(font,char) + local tfmdata = fontdata[font] + local character = tfmdata.characters[char] + if character then + local compensation = character.compensation + if not compensation then + local description = tfmdata.descriptions[char] + if description then + local boundingbox = description.boundingbox + return boundingbox and (boundingbox[3] - (description.width or 0)) * tfmdata.parameters.hfactor + end + character.compensation = compensation + end + end + return 0 +end + +function tighten.handler(head) + for n, subtype in traverse_boundary, head do + if subtype == userboundary_code and getdata(n) == a_tightfit_boundary then + local prev = getprev(n) + if prev then + local char, font = isglyph(prev) + if char then + local compensation = bbcompensation(font,char) + if compensation > 0 then + if trace_tighten then + report("compensating %p after %C",compensation,char) + end + insertnodebefore(head,n,newkern(compensation)) + end + end + end + end end return head end -interfaces.implement { - name = "enablecrlf", +implement { + name = "enabletighten", onlyonce = true, actions = function() - enableaction("processors","typesetters.wrappers.handler") + enableaction("processors","typesetters.tighten.handler") end } + +local dimension_value = tokens.values.dimension +local texgetnest = tex.getnest + +implement { + name = "tightfitcompensation", + public = true, + protected = true, + usage = "value", + actions = function() + local list = texgetnest() + if list then + list = list.tail + end + return + dimension_value, + list and list.id == glyph_code and bbcompensation(list.font,list.char) or 0 + end, +} diff --git a/tex/context/base/mkxl/typo-wrp.mkxl b/tex/context/base/mkxl/typo-wrp.mkxl index 71559a8a3..2f536bc06 100644 --- a/tex/context/base/mkxl/typo-wrp.mkxl +++ b/tex/context/base/mkxl/typo-wrp.mkxl @@ -59,4 +59,17 @@ \let\spac_crlf\space \to \everysimplifycommands +% experiment, triggered by MS: +% +% \type{f\kern\tightfitcompensation\high{x}} +% \type{f\tightfitboundary \high{x}} + +% \tightfitcompensation : defined at the lua end + +\newboundary\c_tightfit_boundary + +\permanent\protected\def\tightfitboundary + {\clf_enabletighten + \boundary\c_tightfit_boundary} + \protect \endinput diff --git a/tex/context/interface/mkii/keys-ro.xml b/tex/context/interface/mkii/keys-ro.xml index 2abf5c5b9..5ecd5196a 100644 --- a/tex/context/interface/mkii/keys-ro.xml +++ b/tex/context/interface/mkii/keys-ro.xml @@ -838,6 +838,7 @@ + @@ -961,6 +962,7 @@ + diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index b7d60eefb..a66ee0752 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2023-02-23 21:23 +-- merge date : 2023-03-06 14:44 do -- begin closure to overcome local limits and interference @@ -2952,9 +2952,23 @@ function file.withinbase(path) end return true end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil +do + local symlinktarget=lfs.symlinktarget + local symlinkattributes=lfs.symlinkattributes + if symlinktarget then + function lfs.readlink(name) + local target=symlinktarget(name) + return name~=target and name or nil + end + elseif symlinkattributes then + function lfs.readlink(name) + return symlinkattributes(name,"target") or nil + end + else + function lfs.readlink(name) + return nil + end + end end end -- closure -- cgit v1.2.3