From 6db2cd924d26ade933812f90701343f06c8653f2 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Fri, 30 Jul 2021 01:27:40 +0200 Subject: 2021-07-30 00:43:00 --- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkii/mult-en.mkii | 5 + tex/context/base/mkii/mult-it.mkii | 1 + tex/context/base/mkii/mult-nl.mkii | 4 + tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/file-res.lua | 2 +- tex/context/base/mkiv/grph-fil.lua | 1 + tex/context/base/mkiv/lpdf-ano.lua | 20 +- tex/context/base/mkiv/lpdf-mov.lua | 42 +-- tex/context/base/mkiv/mult-def.lua | 3 + tex/context/base/mkiv/scrn-wid.lua | 16 +- tex/context/base/mkiv/status-files.pdf | Bin 23606 -> 24854 bytes tex/context/base/mkiv/status-lua.pdf | Bin 248677 -> 250063 bytes tex/context/base/mkxl/buff-ver.mkxl | 42 +-- tex/context/base/mkxl/colo-ini.mkxl | 7 + tex/context/base/mkxl/cont-new.mkxl | 2 +- tex/context/base/mkxl/context.mkxl | 2 +- tex/context/base/mkxl/lang-ini.mkxl | 8 +- tex/context/base/mkxl/lang-rep.lmt | 467 +++++++++++++++++++++++++++++++++ tex/context/base/mkxl/lang-rep.mkxl | 2 +- tex/context/base/mkxl/lpdf-ano.lmt | 39 ++- tex/context/base/mkxl/lpdf-emb.lmt | 24 +- tex/context/base/mkxl/lpdf-fmt.lmt | 7 + tex/context/base/mkxl/lpdf-lmt.lmt | 48 ++-- tex/context/base/mkxl/lpdf-mov.lmt | 42 +-- tex/context/base/mkxl/lpdf-tag.lmt | 37 ++- tex/context/base/mkxl/node-ref.lmt | 2 +- tex/context/base/mkxl/scrn-wid.mklx | 60 +++-- tex/context/base/mkxl/syst-ini.mkxl | 2 +- tex/context/base/mkxl/typo-duc.lmt | 2 +- 32 files changed, 739 insertions(+), 156 deletions(-) create mode 100644 tex/context/base/mkxl/lang-rep.lmt (limited to 'tex/context/base') diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 24ca54092..4ff589018 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{2021.07.27 19:24} +\newcontextversion{2021.07.30 00:41} %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 d4b21f8d2..ecb8d8069 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{2021.07.27 19:24} +\edef\contextversion{2021.07.30 00:41} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii index a21723db8..5af7737d1 100644 --- a/tex/context/base/mkii/mult-en.mkii +++ b/tex/context/base/mkii/mult-en.mkii @@ -207,6 +207,8 @@ \setinterfacevariable{fixed}{fixed} \setinterfacevariable{flexible}{flexible} \setinterfacevariable{float}{float} +\setinterfacevariable{flushbackward}{flushbackward} +\setinterfacevariable{flushforward}{flushforward} \setinterfacevariable{flushinner}{flushinner} \setinterfacevariable{flushleft}{flushleft} \setinterfacevariable{flushouter}{flushouter} @@ -1236,6 +1238,7 @@ \setinterfaceconstant{splitoffset}{splitoffset} \setinterfaceconstant{spot}{spot} \setinterfaceconstant{stack}{stack} +\setinterfaceconstant{stacking}{stacking} \setinterfaceconstant{stackname}{stackname} \setinterfaceconstant{start}{start} \setinterfaceconstant{starter}{starter} @@ -1265,6 +1268,7 @@ \setinterfaceconstant{symbolset}{symbolset} \setinterfaceconstant{symcolor}{symcolor} \setinterfaceconstant{symstyle}{symstyle} +\setinterfaceconstant{synchronize}{synchronize} \setinterfaceconstant{synonym}{synonym} \setinterfaceconstant{synonymcolor}{synonymcolor} \setinterfaceconstant{synonymcommand}{synonymcommand} @@ -1363,6 +1367,7 @@ \setinterfaceelement{load}{load} \setinterfaceelement{local}{local} \setinterfaceelement{makeup}{makeup} +\setinterfaceelement{namedtyping}{namedtyping} \setinterfaceelement{next}{next} \setinterfaceelement{place}{place} \setinterfaceelement{previous}{previous} diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii index 4ba837a13..d3b670a0a 100644 --- a/tex/context/base/mkii/mult-it.mkii +++ b/tex/context/base/mkii/mult-it.mkii @@ -1367,6 +1367,7 @@ \setinterfaceelement{load}{carica} \setinterfaceelement{local}{locale} \setinterfaceelement{makeup}{makeup} +\setinterfaceelement{namedtyping}{namedtyping} \setinterfaceelement{next}{successivo} \setinterfaceelement{place}{metti} \setinterfaceelement{previous}{precedente} diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii index 78445f695..6996a3730 100644 --- a/tex/context/base/mkii/mult-nl.mkii +++ b/tex/context/base/mkii/mult-nl.mkii @@ -207,6 +207,8 @@ \setinterfacevariable{fixed}{vast} \setinterfacevariable{flexible}{flexibel} \setinterfacevariable{float}{blok} +\setinterfacevariable{flushbackward}{flushbackward} +\setinterfacevariable{flushforward}{flushforward} \setinterfacevariable{flushinner}{lijnbinnen} \setinterfacevariable{flushleft}{lijnlinks} \setinterfacevariable{flushouter}{lijnbuiten} @@ -1236,6 +1238,7 @@ \setinterfaceconstant{splitoffset}{splitsoffset} \setinterfaceconstant{spot}{spot} \setinterfaceconstant{stack}{stapel} +\setinterfaceconstant{stacking}{stapels} \setinterfaceconstant{stackname}{stapelnaam} \setinterfaceconstant{start}{start} \setinterfaceconstant{starter}{opener} @@ -1364,6 +1367,7 @@ \setinterfaceelement{load}{laad} \setinterfaceelement{local}{lokale} \setinterfaceelement{makeup}{opmaak} +\setinterfaceelement{namedtyping}{namedtyping} \setinterfaceelement{next}{volgende} \setinterfaceelement{place}{plaats} \setinterfaceelement{previous}{vorige} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 48164c9fc..d454c8d15 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{2021.07.27 19:24} +\newcontextversion{2021.07.30 00:41} %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 b75a70285..32af5b99b 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.07.27 19:24} +\edef\contextversion{2021.07.30 00:41} %D Kind of special: diff --git a/tex/context/base/mkiv/file-res.lua b/tex/context/base/mkiv/file-res.lua index 8b16ff7da..3ed7abc8d 100644 --- a/tex/context/base/mkiv/file-res.lua +++ b/tex/context/base/mkiv/file-res.lua @@ -64,7 +64,7 @@ local function readfilename(specification,backtrack,treetoo) local fname = names[i] for i=1,backtrack,1 do fname = "../" .. fname - local pname = path and (path .. "/" .. fname) or fname + local pname = path and (path ~= "") and (path .. "/" .. fname) or fname if isfile(pname) then if trace_files then report_files("found by backtracking: %s",pname) diff --git a/tex/context/base/mkiv/grph-fil.lua b/tex/context/base/mkiv/grph-fil.lua index e40420125..005657947 100644 --- a/tex/context/base/mkiv/grph-fil.lua +++ b/tex/context/base/mkiv/grph-fil.lua @@ -97,6 +97,7 @@ function jobfiles.run(name,action) -- can be anything but we assume it gets checked by the sandbox os.execute(action) elseif ta == "table" then + -- these paths will be ignored when they are not set local path = action.path local runpath = action.runpath action.path = environment.arguments.path diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua index a120ff2f4..ebed9aec6 100644 --- a/tex/context/base/mkiv/lpdf-ano.lua +++ b/tex/context/base/mkiv/lpdf-ano.lua @@ -1215,24 +1215,24 @@ local pdf_stop = pdfconstant("Stop") local pdf_resume = pdfconstant("Resume") local pdf_pause = pdfconstant("Pause") -local function movie_or_sound(operation,arguments) +local function movie_or_sound(operation,what,arguments) arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments) return pdfdictionary { S = pdf_movie, - T = format("movie %s",arguments[1] or "noname"), + T = format("%s %s",what,arguments[1] or "noname"), Operation = operation, } end -function executers.startmovie (arguments) return movie_or_sound(pdf_start ,arguments) end -function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,arguments) end -function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,arguments) end -function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,arguments) end +function executers.startmovie (arguments) return movie_or_sound(pdf_start ,"movie",arguments) end +function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,"movie",arguments) end +function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,"movie",arguments) end +function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,"movie",arguments) end -function executers.startsound (arguments) return movie_or_sound(pdf_start ,arguments) end -function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,arguments) end -function executers.resumesound(arguments) return movie_or_sound(pdf_resume,arguments) end -function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,arguments) end +function executers.startsound (arguments) return movie_or_sound(pdf_start ,"sound",arguments) end +function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,"sound",arguments) end +function executers.resumesound(arguments) return movie_or_sound(pdf_resume,"sound",arguments) end +function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,"sound",arguments) end function specials.action(var) local operation = var.operation diff --git a/tex/context/base/mkiv/lpdf-mov.lua b/tex/context/base/mkiv/lpdf-mov.lua index a0f82b25b..0f0eefd2f 100644 --- a/tex/context/base/mkiv/lpdf-mov.lua +++ b/tex/context/base/mkiv/lpdf-mov.lua @@ -17,13 +17,16 @@ local pdfdictionary = lpdf.dictionary local pdfarray = lpdf.array local pdfborder = lpdf.border +-- We should actually make sure that inclusion only happens once. But this mechanism +-- is dropped in pdf anyway so it will go away (read: mapped onto the newer mechanisms). + function nodeinjections.insertmovie(specification) -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname local width = specification.width local height = specification.height local factor = specification.factor or number.dimenfactors.bp local moviedict = pdfdictionary { - F = specification.foundname, + F = specification.foundname or specification.file, Aspect = pdfarray { factor * width, factor * height }, Poster = (specification.preview and true) or false, } @@ -36,7 +39,7 @@ function nodeinjections.insertmovie(specification) Subtype = pdfconstant("Movie"), Border = bs, C = bc, - T = format("movie %s",specification.label), + T = format("movie %s",specification.tag or specification.label), Movie = moviedict, A = controldict, } @@ -44,24 +47,23 @@ function nodeinjections.insertmovie(specification) end function nodeinjections.insertsound(specification) - -- managed in interaction: repeat, label, foundname - local soundclip = interactions.soundclips.soundclip(specification.label) - if soundclip then - local controldict = pdfdictionary { - Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil - } - local sounddict = pdfdictionary { - F = soundclip.filename - } - local bs, bc = pdfborder() - local action = pdfdictionary { - Subtype = pdfconstant("Movie"), - Border = bs, - C = bc, - T = format("sound %s",specification.label), - Movie = sounddict, - A = controldict, + local controldict = nil + if specification["repeat"] then + controldict = pdfdictionary { + Mode = pdfconstant("Repeat") } - context(nodeinjections.annotation(0,0,0,action())) -- test: context(...) end + local sounddict = pdfdictionary { + F = specification.foundname or specification.file + } + local bs, bc = pdfborder() + local action = pdfdictionary { + Subtype = pdfconstant("Movie"), + Border = bs, + C = bc, + T = format("sound %s",specification.tag or specification.label), + Movie = sounddict, + A = controldict, + } + context(nodeinjections.annotation(0,0,0,action())) -- test: context(...) end diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index d720a5b21..d65c7bcf6 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -12884,6 +12884,9 @@ return { ["pe"]="آرایش", ["ro"]="makeup", }, + ["namedtyping"]={ + ["en"]="namedtyping", + }, ["next"]={ ["cs"]="dalsi", ["de"]="folgende", diff --git a/tex/context/base/mkiv/scrn-wid.lua b/tex/context/base/mkiv/scrn-wid.lua index 17c9ebddc..e8688e4b2 100644 --- a/tex/context/base/mkiv/scrn-wid.lua +++ b/tex/context/base/mkiv/scrn-wid.lua @@ -231,13 +231,15 @@ function soundclips.register(specification) end end -function soundclips.insert(tag) - local sc = soundclips[tag] - if not sc then - -- todo: message - return soundclips.register { tag = tag } - else - return sc +function soundclips.insert(specification) + local tag = specification.tag + if tag and tag ~= "" then + local sc = soundclips[tag] + if not sc then + -- todo: message + sc = soundclips.register { tag = tag } + end + nodeinjections.insertsound(sc) end end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index f258bcfba..4edea249a 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 11b45b798..a3561d70c 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/mkxl/buff-ver.mkxl b/tex/context/base/mkxl/buff-ver.mkxl index 65c919556..3cde23d5e 100644 --- a/tex/context/base/mkxl/buff-ver.mkxl +++ b/tex/context/base/mkxl/buff-ver.mkxl @@ -177,8 +177,8 @@ \installcommandhandler \??typing {typing} \??typing \appendtoks - \frozen\instance\setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}% - \frozen\instance\setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}% + \frozen\protected\instance\edefcsname\e!start\currenttyping\endcsname{\buff_verbatim_typing_start{\currenttyping}{\currenttyping}}% + \frozen\protected\instance\edefcsname\e!stop \currenttyping\endcsname{\buff_verbatim_typing_stop}% \ifempty\currenttypingparent \normalexpanded{\definelinenumbering[\currenttyping]}% \else @@ -452,34 +452,33 @@ \mutable\let\beginofverbatimlines\relax % hooks \mutable\let\endofverbatimlines \relax % hooks -\protected\def\buff_verbatim_typing_start#1% tricky non standard lookahead +\protected\def\buff_verbatim_typing_start#1#2% tricky non standard lookahead {\begingroup - \edef\currenttyping{#1}% + \edef\currenttyping {#1}% + \edef\currenttypingwrapper{#2}% \obeylines \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop} -\def\buff_verbatim_typing_start_nop - {\typingparameter\c!before\relax - \startpacked[\v!blank]% - \buff_verbatim_setup_line_numbering - \buff_verbatim_initialize_typing_one - \buff_verbatim_setup_keep_together - \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}} - \def\buff_verbatim_typing_start_yes[#1]% - {\typingparameter\c!before\relax - \startpacked[\v!blank]% - \ifcondition\validassignment{#1}% + {\ifcondition\validassignment{#1}% \setupcurrenttyping[#1]% \else \doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}% \fi + \typingparameter\c!before\relax % moved down + \startpacked[\v!blank]% % moved down \buff_verbatim_setup_line_numbering \buff_verbatim_initialize_typing_one \buff_verbatim_setup_keep_together - \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}} + \normalexpanded{\buff_verbatim_type_block{\e!start\currenttypingwrapper}{\e!stop\currenttypingwrapper}}} -% \startnamedtyping[#1] +\def\buff_verbatim_typing_start_nop + {\typingparameter\c!before\relax + \startpacked[\v!blank]% + \buff_verbatim_setup_line_numbering + \buff_verbatim_initialize_typing_one + \buff_verbatim_setup_keep_together + \normalexpanded{\buff_verbatim_type_block{\e!start\currenttypingwrapper}{\e!stop \currenttypingwrapper}}} \protected\def\buff_verbatim_setup_keep_together {\edef\p_keeptogether{\typingparameter\c!keeptogether}% @@ -518,13 +517,18 @@ \dostoptagged \begincsname#2\endcsname} -\protected\def\buff_verbatim_typing_stop#1% hm, currenttyping +\protected\def\buff_verbatim_typing_stop {\stoppacked \typingparameter\c!after\relax \useindentnextparameter\typingparameter \endgroup \dorechecknextindentation} +\permanent\protected\def\startnamedtyping[#1]% + {\buff_verbatim_typing_start{#1}\e!namedtyping} + +\permanent\let\stopnamedtyping\buff_verbatim_typing_stop + %D Line numbering for files is combined with filtering, while display verbatim has %D the ability to continue. %D @@ -581,7 +585,7 @@ \mutable\let\currenttypingfile\empty \appendtoks - \frozen\instance\setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}% + \frozen\protected\instance\edefcsname\e!type\currenttyping\v!file\endcsname{\typefile[\currenttyping]}% \to \everydefinetyping \permanent\tolerant\protected\def\typefile[#1]#*[#2]#:#3% diff --git a/tex/context/base/mkxl/colo-ini.mkxl b/tex/context/base/mkxl/colo-ini.mkxl index cccbb218e..21f1e1174 100644 --- a/tex/context/base/mkxl/colo-ini.mkxl +++ b/tex/context/base/mkxl/colo-ini.mkxl @@ -331,6 +331,13 @@ \let\colo_helpers_show_message\showmessage \to \everyjob +% handled elsewhere but kind of a reference here: +% +% \def\colo_force_colormodel#1#2% +% {\setcolorsparameter\c!rgb {#1}% +% \setcolorsparameter\c!cmyk{#2}% +% \the\everysetupcolors} + %D We provide stacking independent of grouping. % the old one diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index f8a7700b1..3d35f23e0 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{2021.07.27 19:24} +\newcontextversion{2021.07.30 00:41} %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 01dc31fab..3a28a1a84 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{2021.07.27 19:24} +\immutable\edef\contextversion{2021.07.30 00:41} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/lang-ini.mkxl b/tex/context/base/mkxl/lang-ini.mkxl index 42d365ff8..336dd5d69 100644 --- a/tex/context/base/mkxl/lang-ini.mkxl +++ b/tex/context/base/mkxl/lang-ini.mkxl @@ -811,10 +811,14 @@ \protected\def\lang_basics_traced_discretionary#1#2#3#4% {\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}} +\def\lang_basics_trace_discretionary_yes{\enforced\let\discretionary\traceddiscretionary} % indirect because of overload +\def\lang_basics_trace_discretionary_nop{\enforced\let\discretionary\normaldiscretionary} % indirect because of overload + + \installtextracker {discretionaries} - {\enforced\let\discretionary\traceddiscretionary} - {\enforced\let\discretionary\normaldiscretionary} + {\lang_basics_trace_discretionary_yes} + {\lang_basics_trace_discretionary_nop} \permanent\protected\def\samplediscretionary {\traceddiscretionary diff --git a/tex/context/base/mkxl/lang-rep.lmt b/tex/context/base/mkxl/lang-rep.lmt new file mode 100644 index 000000000..6139a03f7 --- /dev/null +++ b/tex/context/base/mkxl/lang-rep.lmt @@ -0,0 +1,467 @@ +if not modules then modules = { } end modules ['lang-rep'] = { + version = 1.001, + comment = "companion to lang-rep.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- A BachoTeX 2013 experiment, probably not that useful. Eventually I used a simpler +-- more generic example. I'm sure no one ever notices of even needs this code. +-- +-- As a follow up on a question by Alan about special treatment of dropped caps I wonder +-- if I can make this one more clever (probably in a few more dev steps). For instance +-- injecting nodes or replacing nodes. It's a prelude to a kind of lpeg for nodes, +-- although (given experiences so far) we don't really need that. After all, each problem +-- is somewhat unique. + +local type, tonumber, next = type, tonumber, next +local gmatch, gsub = string.gmatch, string.gsub +local utfbyte, utfsplit = utf.byte, utf.split +local P, C, U, Cc, Ct, Cs, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns.utf8character, lpeg.Cc, lpeg.Ct, lpeg.Cs, lpeg.match +local find = string.find + +local zwnj = 0x200C +local grouped = P("{") * ( Ct((U/utfbyte-P("}"))^1) + Cc(false) ) * P("}")-- grouped +local splitter = Ct(( + #P("{") * ( + P("{}") / function() return zwnj end + + Ct(Cc("discretionary") * grouped * grouped * grouped) + + Ct(Cc("noligature") * grouped) + ) + + U/utfbyte + )^1) + +local stripper = P("{") * Cs((1-P(-2))^0) * P("}") * P(-1) + +local trace_replacements = false trackers.register("languages.replacements", function(v) trace_replacements = v end) +local trace_details = false trackers.register("languages.replacements.details", function(v) trace_details = v end) + +local report_replacement = logs.reporter("languages","replacements") + +local glyph_code = nodes.nodecodes.glyph +local glue_code = nodes.nodecodes.glue + +local spaceskip_code = nodes.gluecodes.spaceskip +local xspaceskip_code = nodes.gluecodes.xspaceskip + +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getattr = nuts.getattr +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local isglyph = nuts.isglyph + +local setlink = nuts.setlink +local setnext = nuts.setnext +local setprev = nuts.setprev +local setchar = nuts.setchar +local setattrlist = nuts.setattrlist +local setoptions = nuts.setoptions + +local glyphoptioncodes = tex.glyphoptioncodes +local norightligature_option = glyphoptioncodes.norightligature +local noleftligature_option = glyphoptioncodes.noleftligature + +local insertbefore = nuts.insertbefore +local insertafter = nuts.insertafter +local remove_node = nuts.remove +local copy_node = nuts.copy +local flushlist = nuts.flushlist + +local nodepool = nuts.pool +local new_disc = nodepool.disc + +local texsetattribute = tex.setattribute +local unsetvalue = attributes.unsetvalue + +local enableaction = nodes.tasks.enableaction + +local v_reset = interfaces.variables.reset + +local implement = interfaces.implement + +local processors = typesetters.processors +local splitprocessor = processors.split + +local replacements = languages.replacements or { } +languages.replacements = replacements + +local a_replacements = attributes.private("replacements") + +local lists = { } +local last = 0 +local trees = { } + +table.setmetatableindex(lists,function(lists,name) + last = last + 1 + local list = { } + local data = { name = name, list = list, attribute = last } + lists[last] = data + lists[name] = data + trees[last] = list + return data +end) + +lists[v_reset].attribute = unsetvalue -- so we discard 0 + +-- todo: glue kern attr + +local function add(root,word,replacement) + local processor, replacement = splitprocessor(replacement,true) -- no check + replacement = lpegmatch(stripper,replacement) or replacement + local list = utfsplit(word) -- ,true) + local size = #list + for i=1,size do + local l = utfbyte(list[i]) + if not root[l] then + root[l] = { } + end + if i == size then + local special = find(replacement,"{",1,true) + local newlist = lpegmatch(splitter,replacement) + root[l].final = { + word = word, + replacement = replacement, + processor = processor, + oldlength = size, + newcodes = newlist, + special = special, + } + end + root = root[l] + end +end + +function replacements.add(category,word,replacement) + local root = lists[category].list + if type(word) == "table" then + for word, replacement in next, word do + add(root,word,replacement) + end + else + add(root,word,replacement or "") + end +end + +-- local strip = lpeg.stripper("{}") + +function languages.replacements.addlist(category,list) + local root = lists[category].list + if type(list) == "string" then + for new in gmatch(list,"%S+") do + local old = gsub(new,"[{}]","") + -- local old = lpegmatch(strip,new) + add(root,old,new) + end + else + for i=1,#list do + local new = list[i] + local old = gsub(new,"[{}]","") + -- local old = lpegmatch(strip,new) + add(root,old,new) + end + end +end + +local function tonodes(list,template) + local head, current + for i=1,#list do + local new = copy_node(template) + setchar(new,list[i]) + if head then + head, current = insertafter(head,current,new) + else + head, current = new, new + end + end + return head +end + +local is_punctuation = characters.is_punctuation + +-- We can try to be clever and use the fact that there is no match to skip +-- over to the next word but it is gives fuzzy code so for now I removed +-- that optimization (when I really need a high performance version myself +-- I will look into it (but so far I never used this mechanism myself). +-- +-- We used to have the hit checker as function but is got messy when checks +-- for punctuation was added. + +local function replace(head,first,last,final,hasspace,overload) + local current = first + local prefirst = getprev(first) or head + local postlast = getnext(last) + local oldlength = final.oldlength + local newcodes = final.newcodes + local newlength = newcodes and #newcodes or 0 + if trace_replacements then + report_replacement("replacing word %a by %a",final.word,final.replacement) + end + if hasspace or final.special then + -- It's easier to delete and insert so we do just that. On the todo list is + -- turn injected spaces into glue but easier might be to let the char break + -- handler do that ... + local prev = getprev(current) + local next = getnext(last) + local list = current + setnext(last) + setlink(prev,next) + current = prev + if not current then + head = nil + end + local i = 1 + while i <= newlength do + local codes = newcodes[i] + if type(codes) == "table" then + local method = codes[1] + if method == "discretionary" then + local pre, post, replace = codes[2], codes[3], codes[4] + if pre then + pre = tonodes(pre,first) + end + if post then + post = tonodes(post,first) + end + if replace then + replace = tonodes(replace,first) + end + -- todo: also set attr + local new = new_disc(pre,post,replace) + setattrlist(new,first) + head, current = insertafter(head,current,new) + elseif method == "noligature" then + -- not that efficient to copy but ok for testing + local list = codes[2] + if list then + local n = #list + for i=1,n do + local new = copy_node(first) + setchar(new,list[i]) + if i == 1 then + setoptions(new,norightligature_option) + elseif i == n then + setoptions(new,glyphoptioncodes.noleftligature | norightligature_option) + else + setoptions(new,glyphoptioncodes.noleftligature) + end + head, current = insertafter(head,current,new) + end + else + -- local new = copy_node(first) + -- setchar(new,zwnj) + -- head, current = insertafter(head,current,new) + setoptions(current,norightligature_option) + end + else + report_replacement("unknown method %a",method or "?") + end + else + local new = copy_node(first) + setchar(new,codes) + head, current = insertafter(head,current,new) + end + i = i + 1 + end + flushlist(list) + elseif newlength == 0 then + -- we overload + elseif oldlength == newlength then + if final.word ~= final.replacement then + for i=1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + end + current = getnext(final) + elseif oldlength < newlength then + for i=1,newlength-oldlength do + local n = copy_node(current) + setchar(n,newcodes[i]) + head, current = insertbefore(head,current,n) + current = getnext(current) + end + for i=newlength-oldlength+1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + else + for i=1,oldlength-newlength do + head, current = remove_node(head,current,true) + end + for i=1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + end + if overload then + overload(final,getnext(prefirst),getprev(postlast)) + end + return head, postlast +end + +-- we handle just one space + +function replacements.handler(head) + local current = head + local overload = attributes.applyoverloads + local mode = false -- we're in word or punctuation mode + local wordstart = false + local wordend = false + local prevend = false + local prevfinal = false + local tree = false + local root = false + local hasspace = false + while current do + local id = getid(current) -- or use the char getter + if id == glyph_code then + local a = getattr(current,a_replacements) + if a then + -- we have a run + tree = trees[a] + if tree then + local char = getchar(current) + local punc = is_punctuation[char] + if mode == "punc" then + if not punc then + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + prevfinal = false + root = false + end + mode = "word" + end + elseif mode == "word" then + if punc then + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + prevfinal = false + root = false + end + mode = "punc" + end + else + mode = punc and "punc" or "word" + end + if root then + root = root[char] + if root then + wordend = current + end + else + if prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + prevfinal = false + end + root = tree[char] + if root then + wordstart = current + wordend = current + prevend = false + hasspace = false + end + end + else + root= false + end + else + tree = false + end + current = getnext(current) + elseif root then + local final = root.final + if mode == "word" and id == glue_code then + local s = getsubtype(current) + if s == spaceskip_code or s == xspaceskip_code then + local r = root[32] -- maybe more types + if r then + if not prevend then + local f = root.final + if f then + prevend = wordend + prevfinal = f + end + end + wordend = current + root = r + hasspace = true + goto moveon + end + end + end + if final then + head, current = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head, current = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + prevfinal = false + root = false + ::moveon:: + current = getnext(current) + else + current = getnext(current) + end + end + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + end + return head +end + +local enabled = false + +function replacements.set(n) + if n == v_reset then + n = unsetvalue + else + n = lists[n].attribute + if not enabled then + enableaction("processors","languages.replacements.handler") + if trace_replacements then + report_replacement("enabling replacement handler") + end + enabled = true + end + end + texsetattribute(a_replacements,n) +end + +-- interface + +implement { + name = "setreplacements", + actions = replacements.set, + arguments = "string" +} + +implement { + name = "addreplacements", + actions = replacements.add, + arguments = "3 strings", +} + +implement { + name = "addreplacementslist", + actions = replacements.addlist, + arguments = "2 strings", +} diff --git a/tex/context/base/mkxl/lang-rep.mkxl b/tex/context/base/mkxl/lang-rep.mkxl index 36e484242..03b761bb7 100644 --- a/tex/context/base/mkxl/lang-rep.mkxl +++ b/tex/context/base/mkxl/lang-rep.mkxl @@ -19,7 +19,7 @@ \unprotect -\registerctxluafile{lang-rep}{} +\registerctxluafile{lang-rep}{autosuffix} \definesystemattribute[replacements][public,global] diff --git a/tex/context/base/mkxl/lpdf-ano.lmt b/tex/context/base/mkxl/lpdf-ano.lmt index 5498627b8..485e143a7 100644 --- a/tex/context/base/mkxl/lpdf-ano.lmt +++ b/tex/context/base/mkxl/lpdf-ano.lmt @@ -754,6 +754,8 @@ local nofused = 0 local nofspecial = 0 local share = true +local refobjects = { } + local f_annot = formatters["<< /Type /Annot %s /Rect [ %.6N %.6N %.6N %.6N ] >>"] local f_quadp = formatters["<< /Type /Annot %s /QuadPoints [ %s ] /Rect [ %.6N %.6N %.6N %.6N ] >>"] @@ -803,8 +805,18 @@ local function finishreference(specification) else specifier = f_annot(prerolled,llx,lly,urx,ury) end + local objref = hashed[specifier] + local refatt = specification.reference + specification.objref = objref nofused = nofused + 1 - return pdfregisterannotation(hashed[specifier]) + if refatt then + refobjects[refatt] = objref + end + return pdfregisterannotation(objref) +end + +function codeinjections.getrefobj(refatt) -- bad name but experiment anyway + return refobjects[refatt] end local function finishannotation(specification) @@ -818,18 +830,20 @@ local function finishannotation(specification) pdfdelayedobject(annot,objref) else objref = pdfdelayedobject(annot) + specification.objref = objref end nofspecial = nofspecial + 1 return pdfregisterannotation(objref) end -function nodeinjections.reference(width,height,depth,prerolled,mesh) +function nodeinjections.reference(reference,width,height,depth,prerolled,mesh) if prerolled then if trace_references then report_references("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled) end return new_latelua { action = finishreference, + reference = reference, width = width, height = height, depth = depth, @@ -868,6 +882,7 @@ pdfregisterannotation = function(n) else annotations = pdfarray { pdfreference(n) } -- no need to use lpdf.array cum suis end + return n end lpdf.registerannotation = pdfregisterannotation @@ -1219,24 +1234,24 @@ local pdf_stop = pdfconstant("Stop") local pdf_resume = pdfconstant("Resume") local pdf_pause = pdfconstant("Pause") -local function movie_or_sound(operation,arguments) +local function movie_or_sound(operation,what,arguments) arguments = (type(arguments) == "table" and arguments) or settings_to_array(arguments) return pdfdictionary { S = pdf_movie, - T = format("movie %s",arguments[1] or "noname"), + T = format("%s %s",what,arguments[1] or "noname"), Operation = operation, } end -function executers.startmovie (arguments) return movie_or_sound(pdf_start ,arguments) end -function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,arguments) end -function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,arguments) end -function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,arguments) end +function executers.startmovie (arguments) return movie_or_sound(pdf_start ,"movie",arguments) end +function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,"movie",arguments) end +function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,"movie",arguments) end +function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,"movie",arguments) end -function executers.startsound (arguments) return movie_or_sound(pdf_start ,arguments) end -function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,arguments) end -function executers.resumesound(arguments) return movie_or_sound(pdf_resume,arguments) end -function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,arguments) end +function executers.startsound (arguments) return movie_or_sound(pdf_start ,"sound",arguments) end +function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,"sound",arguments) end +function executers.resumesound(arguments) return movie_or_sound(pdf_resume,"sound",arguments) end +function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,"sound",arguments) end function specials.action(var) local operation = var.operation diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt index f9fb7d3c2..daa7e41a1 100644 --- a/tex/context/base/mkxl/lpdf-emb.lmt +++ b/tex/context/base/mkxl/lpdf-emb.lmt @@ -279,6 +279,12 @@ end includecidset = false forcecidset = false -- for private testing only + function lpdf.setincludecidset(v) + -- incredible ... it's obselete, no viewer needs it so why still this crap + -- so in the end it had to be introduced again + includecidset = v + end + directives.register("backend.pdf.forcecidset",function(v) forcecidset = v end) @@ -873,7 +879,7 @@ do StemV = scale(stemv), XHeight = scale(xheight), FontFile2 = pdfreference(pdfflushstreamobject(fontdata)), --- CIDSet = tocidset, + CIDSet = tocidset, -- no longer needed but verifyers want it Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, } local parent = pdfdictionary { @@ -1827,13 +1833,17 @@ do elseif kind == "user" then return setmetatableindex(function(t,k) local list = data[k] - local kind = list.kind local v - if kind == "values" then - local d = list.data - v = direct(d.r or 0,d.g or 0,d.b or 0) - elseif kind == "attributes" then - v = indirect(list.color,list.transparency) + if list then + local kind = list.kind + if kind == "values" then + local d = list.data + v = direct(d.r or 0,d.g or 0,d.b or 0) + elseif kind == "attributes" then + v = indirect(list.color,list.transparency) + else + v = false -- textcolor + end else v = false -- textcolor end diff --git a/tex/context/base/mkxl/lpdf-fmt.lmt b/tex/context/base/mkxl/lpdf-fmt.lmt index 23534c518..f83432d48 100644 --- a/tex/context/base/mkxl/lpdf-fmt.lmt +++ b/tex/context/base/mkxl/lpdf-fmt.lmt @@ -912,6 +912,11 @@ function codeinjections.setformat(s) -- cmyk = spec.cmyk_colors and variables.yes or variables.no, -- rgb = spec.rgb_colors and variables.yes or variables.no, -- } + -- + local rgb = spec.rgb_colors and variables.yes or variables.no + local cmy = spec.cmyk_colors and variables.yes or variables.no + report_backend("permitted colorspaces: rgb %a, cmyk %a",rgb,cmy) + -- token.expandmacro ("colo_force_colormodel",true,rgb,true,cmy) -- colors.forcesupport( spec.gray_scale or false, @@ -952,6 +957,8 @@ function codeinjections.setformat(s) report_backend("error, format is already set to %a, ignoring %a",formatname,noname.format) end end + -- we could just pass the spec to the backend + lpdf.setincludecidset(spec.include_cidsets) else report_backend("error, format %a is not supported",format) end diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt index f3eea58b4..f722a61e0 100644 --- a/tex/context/base/mkxl/lpdf-lmt.lmt +++ b/tex/context/base/mkxl/lpdf-lmt.lmt @@ -1196,7 +1196,7 @@ local flushimage do BBox = pdfarray(bbox), Resources = lpdf.collectedresources { serialize = false }, } - local objnum = pdfflushstreamobject(content,wrapper,false) + local objnum = pdfflushstreamobject(content,wrapper,false) -- why not compressed ? groups = groups + 1 usedxgroups[groups] = objnum return f_gr(groups) @@ -1770,7 +1770,7 @@ local finalize do boundingbox[4] * bpfactor, } - local contentsobj = pdfflushstreamobject(content,false,false) + local contentsobj = pdfflushstreamobject(content,false,true) pageattributes.Type = pdf_page pageattributes.Contents = pdfreference(contentsobj) @@ -1861,7 +1861,7 @@ local finalize do wrapper.Resources = next(boxresources) and boxresources or nil wrapper.ProcSet = lpdf.procset() - pdfflushstreamobject(content,wrapper,false,specification.objnum) + pdfflushstreamobject(content,wrapper,true,specification.objnum) end @@ -2164,7 +2164,7 @@ do local kind = compressed == "raw" and "raw" or "stream" local nolength = nil if compressed == "raw" then - compressed = nil + compressed = false nolength = true -- data = string.formatters["<< %s >>stream\n%s\nendstream"](attr,data) end @@ -2172,7 +2172,8 @@ do objnum = objnum, immediate = true, nolength = nolength, - compresslevel = compressed == false and 0 or nil, +-- compresslevel = compressed == false and 0 or nil, + compresslevel = compressed, type = "stream", string = data, attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil, @@ -2187,7 +2188,8 @@ do return pdfdeferredobject { objnum = objnum, immediate = true, - compresslevel = compressed == false and 0 or nil, +-- compresslevel = compressed == false and 0 or nil, + compresslevel = compressed, type = "stream", file = filename, attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil, @@ -2279,25 +2281,30 @@ local function flushstreamobj(data,n,dict,comp,nolength) n = nofobjects end local size = #data + if comp ~= false then + comp = compress and size > threshold + end if level == 0 then local b = nil local e = s_stream_e if nolength then - b = f_stream_b_d_r(n,dict) + b = f_stream_b_d_r(n,dict) -- raw object, already treated else - local done = false - if comp ~= false and compress and size > threshold then + if comp then local compdata = compressdata(data,size) if compdata then local compsize = #compdata if compsize <= size - threshold then data = compdata size = compsize - done = true + else + comp = false end + else + comp = false end end - if done then + if comp then b = dict and f_stream_b_d_c(n,dict,size) or f_stream_b_n_c(n,size) else b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) @@ -2310,21 +2317,23 @@ local function flushstreamobj(data,n,dict,comp,nolength) offset = offset + #b + size + #e else if nolength then - data = f_stream_d_r(n,dict,data) + data = f_stream_d_r(n,dict,data) -- raw object, already treated else - local done = false - if comp ~= false and compress and size > threshold then + if comp then local compdata = compressdata(data,size) if compdata then local compsize = #compdata if compsize <= size - threshold then data = compdata size = compsize - done = true + else + comp = false end + else + comp = false end end - if done then + if comp then data = dict and f_stream_d_c(n,dict,size,data) or f_stream_n_c(n,size,data) else data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) @@ -2417,7 +2426,8 @@ pdfimmediateobject = function(a,b,c,d) end -- todo: immediate if kind == "stream" then - flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) +-- flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) -- nil == auto + flushstreamobj(data,objnum,attr,compresslevel,nolength) -- nil == auto elseif objectstream and objcompression ~= false then addtocache(objnum,data) else @@ -2815,8 +2825,8 @@ do specification.type = kind specification.kind = kind end - local compress = compresslevel and compresslevel > 0 or nil - flushstreamobj(stream,objnum,dict,compress,nolength) +-- flushstreamobj(stream,objnum,dict,compresslevel and compresslevel > 0 or nil,nolength) + flushstreamobj(stream,objnum,dict,compresslevel,nolength) specification.objnum = objnum specification.rotation = specification.rotation or 0 specification.orientation = specification.orientation or 0 diff --git a/tex/context/base/mkxl/lpdf-mov.lmt b/tex/context/base/mkxl/lpdf-mov.lmt index a0f82b25b..0f0eefd2f 100644 --- a/tex/context/base/mkxl/lpdf-mov.lmt +++ b/tex/context/base/mkxl/lpdf-mov.lmt @@ -17,13 +17,16 @@ local pdfdictionary = lpdf.dictionary local pdfarray = lpdf.array local pdfborder = lpdf.border +-- We should actually make sure that inclusion only happens once. But this mechanism +-- is dropped in pdf anyway so it will go away (read: mapped onto the newer mechanisms). + function nodeinjections.insertmovie(specification) -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname local width = specification.width local height = specification.height local factor = specification.factor or number.dimenfactors.bp local moviedict = pdfdictionary { - F = specification.foundname, + F = specification.foundname or specification.file, Aspect = pdfarray { factor * width, factor * height }, Poster = (specification.preview and true) or false, } @@ -36,7 +39,7 @@ function nodeinjections.insertmovie(specification) Subtype = pdfconstant("Movie"), Border = bs, C = bc, - T = format("movie %s",specification.label), + T = format("movie %s",specification.tag or specification.label), Movie = moviedict, A = controldict, } @@ -44,24 +47,23 @@ function nodeinjections.insertmovie(specification) end function nodeinjections.insertsound(specification) - -- managed in interaction: repeat, label, foundname - local soundclip = interactions.soundclips.soundclip(specification.label) - if soundclip then - local controldict = pdfdictionary { - Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil - } - local sounddict = pdfdictionary { - F = soundclip.filename - } - local bs, bc = pdfborder() - local action = pdfdictionary { - Subtype = pdfconstant("Movie"), - Border = bs, - C = bc, - T = format("sound %s",specification.label), - Movie = sounddict, - A = controldict, + local controldict = nil + if specification["repeat"] then + controldict = pdfdictionary { + Mode = pdfconstant("Repeat") } - context(nodeinjections.annotation(0,0,0,action())) -- test: context(...) end + local sounddict = pdfdictionary { + F = specification.foundname or specification.file + } + local bs, bc = pdfborder() + local action = pdfdictionary { + Subtype = pdfconstant("Movie"), + Border = bs, + C = bc, + T = format("sound %s",specification.tag or specification.label), + Movie = sounddict, + A = controldict, + } + context(nodeinjections.annotation(0,0,0,action())) -- test: context(...) end diff --git a/tex/context/base/mkxl/lpdf-tag.lmt b/tex/context/base/mkxl/lpdf-tag.lmt index 8c76ca694..3ff058a4e 100644 --- a/tex/context/base/mkxl/lpdf-tag.lmt +++ b/tex/context/base/mkxl/lpdf-tag.lmt @@ -180,7 +180,20 @@ local function finishstructure() end -- for fulltag, element in sortedhash(elements) do -- sorting is easier on comparing pdf - pdfflushobject(element.knum,element.kids) + local kids = element.kids + -- if element.tag == "link" then + -- local d = kids[2] + -- if type(d) == "table" then + -- local refatt = element.refatt + -- if refatt then + -- local refobj = codeinjections.getrefobj(refatt) + -- if refobj then + -- d.Obj = pdfreference(refobj) + -- end + -- end + -- end + -- end + pdfflushobject(element.knum,kids) end end end @@ -192,6 +205,7 @@ local index, pageref, pagenum, list = 0, nil, 0, nil local pdf_mcr = pdfconstant("MCR") local pdf_struct_element = pdfconstant("StructElem") local pdf_s = pdfconstant("S") +local pdf_objr = pdfconstant("OBJR") local function initializepage() index = 0 @@ -251,7 +265,7 @@ local function makeelement(fulltag,parent) local attributes = nil if tagname == "ignore" then return false - elseif tagname == "mstackertop" or tagname == "mstackerbot" or tagname == "mstackermid"then + elseif tagname == "mstackertop" or tagname == "mstackerbot" or tagname == "mstackermid" then -- TODO return true elseif tagname == "tabulatecell" then @@ -338,7 +352,10 @@ end local f_BDC = formatters["/%s <> BDC"] -local function makecontent(parent,id,specification) +local a_destination = attributes.private('destination') +local a_reference = attributes.private('reference') + +local function makecontent(start,parent,id,specification) local tag = parent.tag local kids = parent.kids local last = index @@ -355,6 +372,16 @@ local function makecontent(parent,id,specification) kids[#kids+1] = d elseif pagenum == parent.pnum then kids[#kids+1] = last + -- if tag == "link" then + -- local ra = getattr(start,a_reference) + -- if ra then + -- parent.refatt = ra + -- kids[#kids+1] = pdfdictionary { + -- Type = pdf_objr, + -- Obj = pdfreference(0), + -- } + -- end + -- end else local d = pdfdictionary { Type = pdf_mcr, @@ -530,7 +557,7 @@ function nodeinjections.addtags(head) end end if prev then - literal = setstate(makecontent(prev,id,specification)) + literal = setstate(makecontent(start,prev,id,specification)) elseif ignore then literal = setstate(makeignore(specification)) else @@ -676,7 +703,7 @@ end -- -- else -- prev = prv -- r = r + 1 --- result[r] = makecontent(prev,id) +-- result[r] = makecontent(start,prev,id) -- -- end -- end -- diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt index a7b624591..2a2bf267f 100644 --- a/tex/context/base/mkxl/node-ref.lmt +++ b/tex/context/base/mkxl/node-ref.lmt @@ -566,7 +566,7 @@ do if depth < dp then depth = dp end end -- logs.report("temp","used: ht=%p dp=%p",height,depth) - local annot = nodeinjections.reference(width,height,depth,set,resolved.mesh) + local annot = nodeinjections.reference(reference,width,height,depth,set,resolved.mesh) if annot then annot = tonut(annot) -- todo nofreferences = nofreferences + 1 diff --git a/tex/context/base/mkxl/scrn-wid.mklx b/tex/context/base/mkxl/scrn-wid.mklx index d760e3e2e..724bdb807 100644 --- a/tex/context/base/mkxl/scrn-wid.mklx +++ b/tex/context/base/mkxl/scrn-wid.mklx @@ -171,7 +171,7 @@ \setupattachment[\currentattachment][#settings]% \expandnamespaceparameter\??attachmentmethod\attachmentparameter\c!method\v!normal} -\setvalue{\??attachmentmethod\v!normal}% +\defcsname\??attachmentmethod\v!normal\endcsname {\edef\currentattachmentsymbol{\attachmentparameter\c!symbol}% \edef\currentattachmentwidth {\attachmentparameter\c!width }% \edef\currentattachmentheight{\attachmentparameter\c!height}% @@ -214,7 +214,7 @@ \dp\b_scrn_attachment_link\currentattachmentdepth \expandnamespaceparameter\??attachmentlocation\attachmentparameter\c!location\s!unknown} -\setvalue{\??attachmentmethod\v!hidden}% +\defcsname\??attachmentmethod\v!hidden\endcsname {\clf_insertattachment tag {\currentattachment}% registered {\currentattachmentregistered}% @@ -249,14 +249,14 @@ \let\scrn_attachment_flush\scrn_attachment_flush_normal -\setvalue{\??attachmentlocation\v!inmargin }{\inmargin {\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge {\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge {\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin {\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin{\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!high }{\high {\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!inmargin \endcsname{\inmargin {\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!leftedge \endcsname{\inleftedge {\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!rightedge \endcsname{\inrightedge {\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!leftmargin \endcsname{\inleftmargin {\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!rightmargin\endcsname{\inrightmargin{\scrn_attachment_flush}} +\defcsname\??attachmentlocation\v!high \endcsname{\high {\scrn_attachment_flush}} -\setvalue{\??attachmentlocation\v!none}% +\defcsname\??attachmentlocation\v!none\endcsname {\global\setbox\b_scrn_attachment_collect\hbox\bgroup \ifvoid\b_scrn_attachment_collect\else \box\b_scrn_attachment_collect @@ -265,7 +265,7 @@ \scrn_attachment_flush \egroup} -\setvalue{\??attachmentlocation\s!unknown}% +\defcsname\??attachmentlocation\s!unknown\endcsname {\ifvoid\b_scrn_attachment_collect\else \box\b_scrn_attachment_collect \fi} @@ -409,9 +409,9 @@ \mutable\let\currentcommentwidth \empty \appendtoks - \frozen\instance\setuevalue \currentcomment {\scrn_comment_argument[\currentcomment]}% - \frozen\instance\setuevalue{\e!start\currentcomment}{\scrn_comment_start [\currentcomment]}% - \frozen\instance\setuevalue{\e!stop \currentcomment}{\scrn_comment_stop }% + \frozen\protected\instance\edefcsname \currentcomment\endcsname{\scrn_comment_argument[\currentcomment]}% + \frozen\protected\instance\edefcsname\e!start\currentcomment\endcsname{\scrn_comment_start [\currentcomment]}% + \frozen\protected\instance\edefcsname\e!stop \currentcomment\endcsname{\scrn_comment_stop }% \to \everydefinecomment \tolerant\protected\def\scrn_comment_argument[#category]#spacer[#title]#spacer[#settings]#:#text%% @@ -461,7 +461,7 @@ %D Beware: comments symbols don't scale in acrobat (cf. spec but somewhat %D weird, esp because for instance attachment symbols do scale). -\setvalue{\??commentmethods\v!normal}% +\defcsname\??commentmethods\v!normal\endcsname {\edef\currentcommentsymbol{\commentparameter\c!symbol}% \edef\currentcommentwidth {\commentparameter\c!width }% \edef\currentcommentheight{\commentparameter\c!height}% @@ -527,14 +527,14 @@ % todo: dedicated margin classes -\setvalue{\??commentlocation\v!inmargin }{\inmargin {\scrn_comment_flush}} -\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\scrn_comment_flush}} -\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\scrn_comment_flush}} -\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\scrn_comment_flush}} -\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\scrn_comment_flush}} -\setvalue{\??commentlocation\v!high }{\high {\scrn_comment_flush}} +\defcsname\??commentlocation\v!inmargin \endcsname{\inmargin {\scrn_comment_flush}} +\defcsname\??commentlocation\v!leftedge \endcsname{\inleftedge {\scrn_comment_flush}} +\defcsname\??commentlocation\v!rightedge \endcsname{\inrightedge {\scrn_comment_flush}} +\defcsname\??commentlocation\v!leftmargin \endcsname{\inleftmargin {\scrn_comment_flush}} +\defcsname\??commentlocation\v!rightmargin\endcsname{\inrightmargin{\scrn_comment_flush}} +\defcsname\??commentlocation\v!high \endcsname{\high {\scrn_comment_flush}} -\setvalue{\??commentlocation\v!none}% +\defcsname\??commentlocation\v!none\endcsname {\global\setbox\b_scrn_comment_collect\hbox\bgroup \ifvoid\b_scrn_comment_collect\else \box\b_scrn_comment_collect @@ -543,7 +543,7 @@ \scrn_comment_flush \egroup} -\setvalue{\??commentlocation\s!unknown}% +\defcsname\??commentlocation\s!unknown\endcsname {\ifvoid\b_scrn_comment_collect\else \box\b_scrn_comment_collect \fi} @@ -569,8 +569,20 @@ %D %D associated actions: StartSound StopSound PauseSound ResumeSound %D -%D Todo: like external figures, also search on path, -%D although, they need to be present ar viewing time, so ... +%D Todo: like external figures, also search on path, although, they need to be +%D present at viewing time, so ... +%D +%D A soundtrack needs to be embedded explicitly with \type {\checksoundtrack} +%D although we could hook it into the first goto. +%D +%D \starttyping +%D \useexternalsoundtrack[myaudio][hastobe.wav] % surprise ... no longer mp3 +%D +%D \starttext +%D \checksoundtrack{myaudio} +%D \goto{play sound}[StartSound{myaudio}] +%D \stoptext +%D \starttyping \installcorenamespace{externalsoundtracks} diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl index 90580c471..1f58b42a1 100644 --- a/tex/context/base/mkxl/syst-ini.mkxl +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -765,7 +765,7 @@ \tracingmacros \plusthree % > 2: obey \untraced \tracingoutput \plusone \tracingpages \plusone - \tracingparagraphs\plusone + \tracingparagraphs\plustwo \tracingrestores \plusone \tracinggroups \plusone \tracingifs \plusone diff --git a/tex/context/base/mkxl/typo-duc.lmt b/tex/context/base/mkxl/typo-duc.lmt index 00f761c19..2e3638946 100644 --- a/tex/context/base/mkxl/typo-duc.lmt +++ b/tex/context/base/mkxl/typo-duc.lmt @@ -31,7 +31,7 @@ if not modules then modules = { } end modules ['typo-duc'] = { -- todo: no need for a max check -- todo: collapse bound similar ranges (not ok yet) -- todo: combine some sweeps --- todo: removing is not needed when we inject at the same spot (only chnage the dir property) +-- todo: removing is not needed when we inject at the same spot (only change the dir property) -- todo: isolated runs (isolating runs are similar to bidi=local in the basic analyzer) -- todo: check unicode addenda (from the draft): -- cgit v1.2.3