summaryrefslogtreecommitdiff
path: root/tex/context/base/pack-obj.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/pack-obj.mkiv')
-rw-r--r--tex/context/base/pack-obj.mkiv399
1 files changed, 399 insertions, 0 deletions
diff --git a/tex/context/base/pack-obj.mkiv b/tex/context/base/pack-obj.mkiv
new file mode 100644
index 000000000..81220e324
--- /dev/null
+++ b/tex/context/base/pack-obj.mkiv
@@ -0,0 +1,399 @@
+%D \module
+%D [ file=pack-obj,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Objects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Objects}
+
+\unprotect
+
+\let\objectreference\gobblefourarguments % catch mkii tuo stuff
+
+\registerctxluafile{pack-obj}{1.001}
+
+% \startluacode
+% local texbox, texdimen, texcount, texwrite = tex.box, tex.dimen, tex.count, tex.write
+% local pdfxform, pdfrefxform = pdf.xform, pdf.refxform
+%
+% function pdf.xform (l) texbox["objectbox"] = nil return l end
+% function pdf.refxform(l) return node.copy_list(l) end
+%
+% backends.codeinjections.register = pdf.xform
+% backends.codeinjections.restore = pdf.refxform
+%
+% local codeinjections = backends.codeinjections
+%
+% objects = objects or { }
+%
+% local data = { }
+%
+% objects.data = data
+% objects.n = 0
+%
+% function objects.register(name)
+% objects.n = objects.n + 1
+% local list = texbox.objectbox
+% nodes.process_page(list)
+% data[name] = {
+% codeinjections.restore(list),
+% texdimen.objectwd,
+% texdimen.objectht,
+% texdimen.objectdp,
+% texdimen.objectoff,
+% }
+% end
+%
+% function objects.restore(name)
+% local d = data[name]
+% if d then
+% texbox .objectbox = codeinjections.restore(d[1])
+% texdimen.objectwd = d[2]
+% texdimen.objectht = d[3]
+% texdimen.objectdp = d[4]
+% texdimen.objectoff = d[5]
+% else
+% texbox .objectbox = nil
+% texdimen.objectwd = 0
+% texdimen.objectht = 0
+% texdimen.objectdp = 0
+% texdimen.objectoff = 0
+% end
+% end
+%
+% function objects.reference(name)
+% local d = data[name]
+% texwrite((d and d[1]) or 0)
+% end
+%
+% function objects.enhance(name)
+% local d = data[name]
+% if d then
+% d[6] = texcount.realpageno
+% end
+% end
+%
+% function objects.page(name)
+% local d = data[name]
+% texwrite((d and d[6]) or texcount.realpageno)
+% end
+%
+% function objects.doifelse(name)
+% commands.testcase(data[name])
+% end
+% \stopluacode
+%
+% \newbox \objectbox
+% \newtoks \everyobject
+% \newif \ifinobject
+%
+% \newdimen\objectoff \def\objectmargin{\the\objectoff}
+% \newdimen\objectwd \def\objectwidth {\the\objectwd }
+% \newdimen\objectht \def\objectheight{\the\objectht }
+% \newdimen\objectdp \def\objectdepth {\the\objectdp }
+%
+% \def\objectoffset{1cm}
+%
+% \everyobject{\the\everyPDFxform}
+%
+% \let\doresetobjects\relax
+%
+% \def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
+% \def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
+%
+% \let\objectsetvbox\vbox %\def\objectsetvbox{\ruledvbox}
+% \let\objectgetvbox\vbox %\def\objectgetvbox{\ruledvbox}
+% \let\objectsethbox\hbox %\def\objectsethbox{\ruledhbox}
+% \let\objectgethbox\hbox %\def\objectgethbox{\ruledhbox}
+%
+% \def\dosetobject#1#2%
+% {\objectwd\wd\nextbox
+% \objectht\ht\nextbox
+% \objectdp\dp\nextbox
+% \ifdim\objectoff=\zeropoint\relax
+% \setbox\objectbox\box\nextbox
+% \else
+% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\flushnextbox\hss}\vss}%
+% \fi
+% \ctxlua{objects.register("#1::#2")}%
+% \endgroup}
+%
+% \def\getobject#1#2%
+% {\begingroup
+% \ctxlua{objects.restore("#1::#2")}%
+% \ifdim\objectoff=\zeropoint\relax \else
+% \setbox\objectbox\objectgetvbox to \dimexpr\objectht+\objectdp\relax
+% {\vss\objectgethbox to \objectwd{\hss\box\objectbox\hss}\vss}%
+% \wd\objectbox\objectwd
+% \ht\objectbox\objectht
+% \dp\objectbox\objectdp
+% \fi
+% \box\objectbox
+% \endgroup}
+%
+% \def\getpageobject#1#2%
+% {\begingroup
+% \ctxlua{objects.restore("#1::#2")}%
+% \ifdim\objectoff=\zeropoint\relax
+% \setbox\objectbox\objectgethbox{\ctxlatelua{objects.enhance("#1::#2")}\box\objectbox}
+% \else
+% \setbox\objectbox\objectgetvbox to \dimexpr\objectht+\objectdp\relax
+% {\vss\objectgethbox to \objectwd{\ctxlatelua{objects.enhance("#1::#2")}\hss\box\objectbox\hss}\vss}%
+% \wd\objectbox\objectwd
+% \ht\objectbox\objectht
+% \dp\objectbox\objectdp
+% \fi
+% \box\objectbox
+% \endgroup}
+%
+% \def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}}
+% \def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}}
+% \def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}}
+%
+% \let\objectreferenced\relax
+% \let\driverreferenced\relax
+%
+% \def\doregisterobjectreference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments}
+% \def\dooverloadobjectreference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments}
+% \def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments}
+% \def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments}
+%
+% \def\defaultobjectreference{0}
+% \def\defaultobjectpage {\realfolio}
+%
+% \def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}}
+% \def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}}
+%
+% \protect
+%
+% \starttext
+% test \setobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test
+% \vskip3cm
+% test \settightobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test
+% test \settightobject{a}{c}\ruledhbox{xxx}\getobject{a}{c} test
+% \dorecurse{5000}{test \setobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test }
+% \stoptext
+
+%D \macros
+%D {setobject,getobject,ifinobject}
+%D
+%D Boxes can be considered reuable objects. Unfortunaltely once
+%D passed to the \DVI\ file, such objects cannot be reused. In
+%D \PDF\ however, reusing is possible and sometimes even a
+%D necessity. Therefore, \CONTEXT\ supports reusable objects.
+%D
+%D During the \TEX\ processing run, boxes can serve the purpose
+%D of objects, and the \DVI\ driver module implements objects
+%D using packed boxes.
+%D
+%D The \PDF\ and \PDFTEX\ driver modules implement objects
+%D using \PDF\ forms. There is no (real) restriction on the
+%D number of objects there.
+%D
+%D The first application of objects in \CONTEXT\ concerned
+%D \METAPOST\ graphics and fill||in form fields. The first
+%D application can save lots of bytes, while the latter use is
+%D more a necessity than byte saving.
+%D
+%D \starttyping
+%D \setobject{class}{name}\somebox{}
+%D \getobject{class}{name}
+%D \stoptyping
+%D
+%D Here \type{\somebox} can be whatever box specification suits
+%D \TEX. We save the dimensions of an object, although some
+%D drivers will do so themselves. This means that when for
+%D instance using \PDFTEX\ we could save a hash entry plus some
+%D 20+ memory locations per object by delegating this
+%D housekeeping to the driver. The current approach permits
+%D us to keep the box characteristic too.
+
+\newif\ifinobject
+
+\def\objectplaceholder{NOT YET FLUSHED}%
+
+\def\presetobject#1#2% \global added
+ {\ifcsname\r!object#1::#2\endcsname\else
+ \global\@EA\let\csname\r!object#1::#2\endcsname\objectplaceholder
+ \fi}
+
+\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout
+ {% \initializepaper
+ \ifcsname\r!object#2::#3\endcsname
+ \expandafter\gobblefivearguments
+ \else % tzt, overload internal referenced objects to save entries
+ \expandafter\dodosetobject
+ \fi
+ {#1}{#2}{#3}}
+
+\def\resetobject#1#2%
+ {\letbeundefined{\r!object#1::#2}}
+
+%D \macros
+%D {finalizeobjectbox}
+%D
+%D This one provides a hook for last minute object box processing
+%D we need this in \MKIV.
+
+\ifx\finalizeobjectbox\undefined
+ \let\finalizeobjectbox\gobbleoneargument
+\fi
+
+%D Somehow there is a rounding error problem in either \PDFTEX\
+%D or in viewers, or maybe it is conforming the specs. The next
+%D variable compensate for it by removing the rather tight
+%D clip.
+
+\def\objectoffset{1cm}
+
+\def\dodosetobject#1#2#3%
+ {\bgroup
+ \globalpushmacro\crossreferenceobject \objectreferenced
+ \inobjecttrue
+ \dowithnextbox
+ {\globalpopmacro\crossreferenceobject
+ \dododosetobject{#1}{#2}{#3}\egroup}}
+
+\def\dododosetobject#1#2#3%
+ {\begingroup
+ \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox
+ \scratchdimen\objectoffset
+ \@EA\xdef\csname\r!object#2::#3\endcsname
+ {\noexpand\dohandleobject{#2}{#3}%
+ {\ifhbox\nextbox\hbox\else\vbox\fi}%
+ {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
+ {\number\scratchdimen}}%
+ \expanded % freeze the dimensions since \dostartobject may use \nextbox
+ {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
+ \setbox\nextbox\vbox spread 2\scratchdimen
+ {\forgetall \offinterlineskip
+ \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
+ \fi \fi
+ \flushnextbox
+ \dostopobject
+ \endgroup}
+
+\def\getobject#1#2%
+ {\begingroup
+ \let\dohandleobject\dogetobject
+ \csname\r!object#1::#2\endcsname}
+
+\def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf
+ {% \initializepaper
+ \forgetall
+ \dontshowcomposition
+ \setbox\scratchbox\vbox attr \viewerlayerattribute \attribute\viewerlayerattribute
+ {\doinsertobject{#1}{#2}}%
+ \setbox\scratchbox#3%
+ {\vbox to #5\scaledpoint
+ {\ifdim\ht\scratchbox>#5\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else\ifdim\wd\scratchbox>#4\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else
+ %\vss\box\scratchbox
+ \vss\hbox to #4\scaledpoint{\box\scratchbox\hss}% fix Chof
+ \fi\fi}}%
+% \forcecolorhack % needed in order to use layers etc
+ \box\scratchbox
+ \endgroup}
+
+%D If needed one can ask for the dimensions of an object with:
+%D
+%D \starttyping
+%D \getobjectdimensions{class}{name}
+%D \stoptyping
+%D
+%D The results are reported in \type {\objectwidth}, \type
+%D {\objectheight} and \type {\objectdepth}.
+
+\def\dogetobjectdimensions#1#2#3#4#5#6#7%
+ {\def\objectwidth {#4\s!sp}%
+ \def\objectheight{#5\s!sp}%
+ \def\objectdepth {#6\s!sp}%
+ \def\objectmargin{#7\s!sp}}
+
+\def\getobjectdimensions#1#2%
+ {\let\dohandleobject\dogetobjectdimensions
+ \let\objectwidth \!!zeropoint
+ \let\objectheight\!!zeropoint
+ \let\objectdepth \!!zeropoint
+ \csname\r!object#1::#2\endcsname}
+
+%D Apart from this kind of objects, that have typeset content,
+%D we can have low level driver specific objects. Both types
+%D can have references to internal representations, hidden for
+%D the user. We keep track of such references by means of a
+%D dedicated cross reference mechanism. Normally, objects are
+%D defined before they are used, but forward referencing
+%D sometimes occurs.
+%D
+%D \starttyping
+%D \dosetobjectreference {class} {identifier} {reference value} {page}
+%D \dogetobjectreference {class} {identifier} \csname
+%D \stoptyping
+%D
+%D These commands are to be called by the \type{\startobject},
+%D \type{\stopobject} and \type{\insertobject} specials.
+
+\def\objectreferenced{\global\chardef\crossreferenceobject\plusone}
+\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount}
+
+\objectreferenced
+
+% no undefined test ! ! ! ! (pdftex fails on undefined objects)
+
+\def\doregisterobjectreference#1#2#3{\normalexpanded{\noexpand\ctxlatelua{jobobjects.save("#1::#2",#3,\noexpand\the\realpageno)}}}
+\def\dooverloadobjectreference#1#2#3{\ctxlua{jobobjects.set("#1::#2",#3,\the\realpageno)}}
+
+\def\dosetobjectreference
+ {\ifcase\crossreferenceobject
+ \objectreferenced
+ \expandafter\dooverloadobjectreference
+ \else
+ \expandafter\doregisterobjectreference
+ \fi}
+
+\def\dosetdriverreference
+ {\driverreferenced\dosetobjectreference}
+
+\def\defaultobjectreference#1#2{0} % driver dependent
+\def\defaultobjectpage #1#2{\realfolio}
+
+\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{jobobjects.number("#1::#2","\defaultobjectreference{#1}{#2}")}}}
+\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{jobobjects.page("#1::#2","\defaultobjectpage{#1}{#2}")}}}
+
+\def\setobject {\driverreferenced\dosetobject1}
+\def\settightobject{\driverreferenced\dosetobject0}
+
+%D \macros
+%D {doifobjectfoundelse,doifobjectreferencefoundelse}
+%D
+%D To prevent redundant definition of objects, one can use
+%D the next tests:
+%D
+%D \starttyping
+%D \doifobjectfoundelse{class}{object}{do then}{do else}
+%D \doifobjectreferencefoundelse{class}{object}{do then}{do else}
+%D \stoptyping
+
+\def\doifobjectfoundelse#1#2%
+ {\ifcsname\r!object#1::#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifobjectreferencefoundelse#1#2{\ctxlua{jobobjects.doifelse("#1::#2")}}
+
+\protect \endinput