%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 ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Packaging Macros / Objects}

\unprotect

\registerctxluafile{pack-obj}{1.001}

%D \macros
%D   {setobject,getobject,ifinobject}
%D
%D Boxes can be considered reuable objects. Traditionally once passed
%D to the \DVI\ file, such objects cannot be reused. In \PDF\ however,
%D reusing is possible and sometimes even a necessity. Therefore,
%D \CONTEXT\ supports reusable objects and \LUATEX\ has native support
%D for so called box resources.
%D
%D The first application of objects in \CONTEXT\ concerned \METAPOST\
%D graphics and fill||in form fields. Reusing resources can save lots
%D of bytes and sometimes also runtime.
%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 \TEX.
%D Although the implementation in \MKIV\ is somewhat different the
%D principles have not changed.

\installcorenamespace {objects}

\newif   \ifinobject
\newbox  \objectbox

\def\objectoffset{1cm}

\newdimen\objectoff  \def\objectmargin{\the\objectoff}
\newdimen\objectwd   \def\objectwidth {\the\objectwd}
\newdimen\objectht   \def\objectheight{\the\objectht}
\newdimen\objectdp   \def\objectdepth {\the\objectdp}

% If I have time I will use the unreferenced variant for e.g. mp reuse.

% todo formmargin per obj

\unexpanded\def\setreferencedobject       #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
\unexpanded\def\settightreferencedobject  #1#2{\begingroup\objectoff\zeropoint   \inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
\unexpanded\def\setunreferencedobject     #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}}
\unexpanded\def\settightunreferencedobject#1#2{\begingroup\objectoff\zeropoint   \inobjecttrue\dowithnextbox{\pack_objects_set_nop{#1}{#2}}}

\let\setobject     \setreferencedobject
\let\settightobject\settightreferencedobject

\unexpanded\def\pack_objects_set_yes#1#2%
  {\ifdim\objectoff>\zeropoint\relax
     \pack_objects_package
   \else
     \setbox\objectbox\box\nextbox
   \fi
   \clf_registerreferencedobject{#1}{#2}\objectbox
   \endgroup}

\unexpanded\def\pack_objects_set_nop#1#2%
  {\ifdim\objectoff>\zeropoint\relax
     \pack_objects_package
   \else
     \setbox\objectbox\box\nextbox
   \fi
   \clf_registerobject{#1}{#2}\objectbox
   \endgroup}

\def\pack_objects_package
  {\objectwd\dimexpr\wd\nextbox+2\objectoff\relax
   \objectht\dimexpr\ht\nextbox+ \objectoff\relax
   \objectdp\dimexpr\dp\nextbox+ \objectoff\relax
   \setbox\objectbox\hpack
     {\hskip\objectoff
      \box\nextbox}%
   \wd\objectbox\objectwd
   \ht\objectbox\objectht
   \dp\objectbox\objectdp}

\def\pack_objects_repackage
  {\objectwd\dimexpr\wd\objectbox-2\objectoff\relax
   \objectht\dimexpr\ht\objectbox- \objectoff\relax
   \objectdp\dimexpr\dp\objectbox- \objectoff\relax
   \setbox\objectbox\hpack
     {\hskip-\objectoff
      \box\objectbox}%
   \wd\objectbox\objectwd
   \ht\objectbox\objectht
   \dp\objectbox\objectdp}

\unexpanded\def\getobject#1#2%
  {\begingroup
   \clf_restoreobject{#1}{#2}%
   \ifdim\objectoff>\zeropoint
     \pack_objects_repackage
   \fi
   \box\objectbox
   \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}.

\unexpanded\def\getobjectdimensions#1#2%
  {\clf_getobjectdimensions{#1}{#2}}

%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\defaultobjectreference{0}
\def\defaultobjectpage     {\realfolio}

\unexpanded\def\dogetobjectreference        {\clf_getobjectreference}
\unexpanded\def\dogetobjectreferencepage    {\clf_getobjectreferencepage}

\unexpanded\def\doifelseobjectfound         {\clf_doifelseobject}
\unexpanded\def\doifelseobjectreferencefound{\clf_doifelseobjectreference}

\let\doifobjectfoundelse         \doifelseobjectfound
\let\doifobjectreferencefoundelse\doifelseobjectreferencefound

%D For the moment here:

\let\lastpredefinedsymbol\empty % some day we can do more at the lua end

\unexpanded\def\predefinesymbol[#1]%
  {\begingroup
   \xdef\lastpredefinedsymbol{#1}%
   \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting
   \dogetobjectreference{SYM}{#1}\m_back_object_reference
   \clf_registerbackendsymbol{#1}\m_back_object_reference\relax
   \endgroup}

\protect \endinput
