%D \module
%D   [       file=grph-inc, % moved from core-fig
%D        version=2006.08.26, % overhaul of 1997.03.31
%D          title=\CONTEXT\ Graphic Macros,
%D       subtitle=Figure Inclusion,
%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.

% todo: messages

\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion}

\registerctxluafile{grph-inc}{1.001}
\registerctxluafile{grph-fil}{1.001}
\registerctxluafile{grph-u3d}{1.001} % this will change
\registerctxluafile{grph-swf}{1.001} % this will change

\unprotect

%D Including graphics is complicated by the fact that  we need to locate them first,
%D optionally manipulate them and scale then next. Lookups are to be done as efficient
%D as possible and inclusion of the data might happens only once. In \MKIV\ much of this
%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's
%D more powerful, flexible, pluggable and some of the extended functionality has been
%D moved from modules to the core. The overall functionality is rather stable and has
%D not changed much over the years.

\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi

\installcorenamespace{externalfigure}
\installcorenamespace{externalfigureinstance}
\installcorenamespace{externalfigurecollection}

\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure

\let\setupexternalfigures\setupexternalfigure

\setupexternalfigures[% we really need the defaults
   \c!method         =,
   \c!label          =,
   \c!size           =,
   \c!conversion     =,
   \c!resolution     =,
   \c!prefix         =,
   \c!cache          =,
   \c!page           =\zerocount,
   \c!display        =,
   \c!mask           =,
   \c!preset         =\v!yes,
   \c!split          =,
   \c!color          =,
   \c!symbol         =\v!no,
   \c!controls       =\v!no,
   \c!resources      =,
   \c!preview        =\v!no
   \c!repeat         =\v!no
   \c!foregroundcolor=,
   \c!interaction    =\v!none,
   \c!hfactor        =,
   \c!wfactor        =,
   \c!factor         =,
   \c!maxwidth       =\externalfigureparameter\c!width,
   \c!maxheight      =\externalfigureparameter\c!height,
   \c!xscale         =,
   \c!yscale         =,
   \c!scale          =,
   \c!sx             =\externalfigureparameter\c!s,
   \c!sy             =\externalfigureparameter\c!s,
   \c!s              =1,
   \c!width          =,
   \c!height         =,
   \c!lines          =,
   \c!grid           =,
   \c!bodyfont       =\bodyfontsize,
   \c!object         =\v!yes,
   \c!corner         =\v!rectangular,
   \c!frame          =\v!off,
   \c!option         =,
   \c!reset          =\v!no,
   \c!directory      =,
   \c!radius         =.5\bodyfontsize,
   \c!background     =,
   \c!splitcolor     =\s!white,
   \c!order          =,
   \c!equalwidth     =,
   \c!equalheight    =,
   \c!location       ={\v!local,\v!global},
   \c!frames         =\v!off,
   \c!ymax           =24,
   \c!xmax           =,
   \c!align          =\v!none, % New, for Tacos extremely large graphics.
  ]

%D Defining figures.

\newcount\c_grph_include_nesting

\newtoks \everyexternalfigureresets % for the moment still public
\newtoks \everyexternalfigurechecks % for the moment still public

% \useexternalfigure[alpha][koe]
% \useexternalfigure[beta] [koe]       [breedte=1cm]
% \useexternalfigure[gamma][koe][alpha]
% \useexternalfigure[delta][koe][alpha][breedte=2cm]
%
% volle breedte: \externalfigure[koe]                 \par
% 3cm breed:     \externalfigure[koe]  [breedte=3cm]  \par
% volle breedte: \externalfigure[alpha]               \par
% 1cm breed:     \externalfigure[beta]                \par
% volle breedte: \externalfigure[gamma]               \par
% 2cm breed:     \externalfigure[delta]               \par
% 4cm breed:     \externalfigure[beta] [breedte=4cm]  \par
% 5cm breed:     \externalfigure[gamma][breedte=5cm]  \par
%
% \defineexternalfigure[a][width=10cm]
% \defineexternalfigure[b][width=5cm]
% \externalfigure[cow][a]
% \externalfigure[cow][b][height=8cm]
%
% \useexternalfigure[x][cow][width=10cm,height=1cm]
% \externalfigure[x]
% \externalfigure[x][width=3cm]
%
% [label] [filename]
% [label] [filename] [parent]
% [label] [filename] [parent] [settings]
% [label] [filename]          [settings]
%
% new: more convenient/efficient than
%
%   \use..[a][a][setting] \externalfigure[b][a]
%
% is equivalent to:
%
%   \def..[a][setting]    \externalfigure[b][a]
%
% see x-res modules for usage:
%
% \defineexternalfigure[name][settings]

%D Defining is persistent, i.e.\ when you redefine an instance,
%D the already set parameters need to be set again or otherwise
%D the old values will be used.

\newconditional\c_grph_include_trace_inheritance

\installtextracker
  {graphics.inheritance}
  {\settrue \c_grph_include_trace_inheritance}
  {\setfalse\c_grph_include_trace_inheritance}

\installcorenamespace{externalfiguredefinition}

% \unexpanded\def\defineexternalfigure
%   {\dodoubleargument\grph_include_define}
%
% \def\grph_include_define[#1][#2]%
%   {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}}

\let\defineexternalfigures\defineexternalfigure

\unexpanded\def\useexternalfigure
  {\doquadrupleempty\grph_include_use}

% label file parent settings
% label file settings
% label file parent

\def\grph_include_use[#1][#2][#3][#4]%
  {\doifelsenothing{#1}
     {\doifsomething{#2}
        {\doifassignmentelse{#3}
           {\grph_include_use_indeed{#2}{#2}{#3}{#4}}
           {\grph_include_use_indeed{#2}{#2}\empty{#4}}}}
     {\doifelsenothing{#2}
        {\doifassignmentelse{#3}
           {\grph_include_use_indeed{#1}{#1}\empty{#3}}
           {\grph_include_use_indeed{#1}{#1}{#3}{#4}}}
        {\doifassignmentelse{#3}
           {\grph_include_use_indeed{#1}{#2}\empty{#3}}
           {\grph_include_use_indeed{#1}{#2}{#3}{#4}}}}}

\def\grph_include_use_indeed#1#2#3#4%
  {\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}%
   \grph_include_analyze_collection[#2][#4]}

% inclusion

\unexpanded\def\externalfigure
  {\dotripleempty\grph_include_figure}

\def\grph_include_figure[#1][#2][#3]%
  {\docheckassignment{#2}%
   \ifassignment
     \grph_include_place[#1][][#2]%
   \else
     \grph_include_place[#1][#2][#3]%
   \fi}

% todo: chain them

\def\grph_include_setup#1#2#3% name parent settings
  {\edef\m_grph_include_name  {#1}%
   \edef\m_grph_include_parent{#2}%
   \ifx\m_grph_include_name\empty \else
     \let\p_grph_include_name\m_grph_include_name
   \fi
   \ifx\m_grph_include_parent\empty \else
     \grph_include_inherit_from_parent\m_grph_include_parent
   \fi
   \setupcurrentexternalfigure[#3]}

% \def\grph_include_inherit_from_parent#1%
%   {\ifcsname\??externalfiguredefinition#1\endcsname
%      \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
%      \csname\??externalfiguredefinition#1\endcsname
%    \fi
%    \ifcsname\??externalfigureinstance#1\endcsname
%      \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
%      \csname\??externalfigureinstance#1\endcsname
%    \fi}

\def\grph_include_inherit_from_parent#1%
  {%\ifcsname\??externalfiguredefinition#1\endcsname
   %  \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
   %  \csname\??externalfiguredefinition#1\endcsname
   %\fi
   \ifcsname\??externalfigure#1:\s!parent\endcsname
     \let\currentexternalfigure#1%
   \fi
   \ifcsname\??externalfigureinstance#1\endcsname
     \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
     \csname\??externalfigureinstance#1\endcsname
   \fi}

\newtoks\t_grph_include_local_settings

\appendtoks
   \let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode (probably no longer needed)
   %
   \dontcomplain
   \restorecatcodes
   \forgetall
\to \t_grph_include_local_settings

\def\grph_include_place_inherit
  {\ifconditional\c_grph_include_trace_inheritance
     \writestatus\m!figures{label: \p_grph_include_label, name: \p_grph_include_name, parent: \p_grph_include_parent}%
   \fi
   \ifx\p_grph_include_parent\empty
     % nothing to be done
   \else\ifx\p_grph_include_parent\p_grph_include_label
     % redundant
   \else
     \grph_include_inherit_from_parent\p_grph_include_parent
   \fi\fi
   \ifx\p_grph_include_label\empty
     % nothing to be done
   \else
     \grph_include_inherit_from_parent\p_grph_include_label
   \fi}

\def\grph_include_place[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
  {\bgroup
   \advance\c_grph_include_nesting\plusone
   \edef\currentexternalfigure{\the\c_grph_include_nesting}%
   \checkexternalfigureparent % each inherits from the root
   %
   \the\everyexternalfigureresets
   %
   \edef\p_grph_include_label{#1}%
   \let\p_grph_include_name\p_grph_include_label
   \docheckassignment{#2}%
   \ifassignment
     % [label] [settings]
     \let\p_grph_include_parent\p_grph_include_label
     \grph_include_place_inherit
     \setupcurrentexternalfigure[#2]%
   \else
     % [label] [parent] [settings]
     \edef\p_grph_include_parent{#2}%
     \ifx\p_grph_include_parent\empty
        \let\p_grph_include_parent\p_grph_include_label
     \fi
     \grph_include_place_inherit
     \setupcurrentexternalfigure[#3]%
   \fi
   %
   \the\everyexternalfigurechecks
   %
   \the\t_grph_include_local_settings
   %
   \edef\p_width {\externalfigureparameter\c!width}%
   \edef\p_height{\externalfigureparameter\c!height}%
   %
   \dostarttagged\t!image\empty
   \ctxlua{figures.push {
        name       = "\p_grph_include_name",
        label      = "\p_grph_include_label",
        page       = "\externalfigureparameter\c!page",
        size       = "\externalfigureparameter\c!size",
        object     = "\externalfigureparameter\c!object",
        prefix     = "\externalfigureparameter\c!prefix",
        cache      = "\externalfigureparameter\c!cache",
        format     = "\externalfigureparameter\c!method",
        preset     = "\externalfigureparameter\c!prefix",
        controls   = "\externalfigureparameter\c!controls",
        resources  = "\externalfigureparameter\c!resources",
        preview    = "\externalfigureparameter\c!preview",
        display    = "\externalfigureparameter\c!display",
        mask       = "\externalfigureparameter\c!mask",
        conversion = "\externalfigureparameter\c!conversion",
        resolution = "\externalfigureparameter\c!resolution",
        color      = "\internalspotcolorparent{\externalfigureparameter\c!color}", % hack is needed
        ["repeat"] = "\externalfigureparameter\c!repeat",
        \ifx\p_width\empty \else
            width  = \number\dimexpr\p_width,
        \fi
        \ifx\p_height\empty \else
            height = \number\dimexpr\p_height,
        \fi
    } }%
   \ctxlua{figures.identify()}%
   % also mode: checkpresense only
   \ifconditional\c_grph_include_test_only
      \ifcase\figurestatus \else
        \ctxlua{figures.check()}%
        \ctxlua{figures.dummy()}%
        \ctxlua{figures.scale()}%
        \ctxlua{figures.done()}%
      \fi
      \grph_include_set_mode
   \else
      \ifcase\figurestatus
        \ctxlua{figures.dummy()}%
        \ctxlua{figures.scale()}%
      \else
        \ctxlua{figures.check()}%
        \ctxlua{figures.include()}%
        \ctxlua{figures.scale()}%
      \fi
      \ctxlua{figures.done()}%
      \grph_include_set_mode
      \grph_include_finalize
   \fi
   \ctxlua{figures.pop()}%
   \dotagfigure
   \naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}%
   \dostoptagged
   \egroup}

%D Scaling:

\let\dowithfigure\relax % name might change (into a proper hook)

\unexpanded\def\doscalefigure % used at lua end
  {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}

\definescale % some day we will inherit
  [\v!figure]
  [\c!hfactor    =\externalfigureparameter\c!hfactor,
   \c!wfactor    =\externalfigureparameter\c!wfactor,
   \c!factor     =\externalfigureparameter\c!factor,
   \c!maxwidth   =\externalfigureparameter\c!maxwidth ,
   \c!maxheight  =\externalfigureparameter\c!maxheight,
   \c!equalwidth =\externalfigureparameter\c!equalwidth ,
   \c!equalheight=\externalfigureparameter\c!equalheight,
   \c!xscale     =\externalfigureparameter\c!xscale,
   \c!yscale     =\externalfigureparameter\c!yscale,
   \c!scale      =\externalfigureparameter\c!scale,
   \c!sx         =\externalfigureparameter\c!sx,
   \c!sy         =\externalfigureparameter\c!sy,
   \c!s          =\externalfigureparameter\c!s,
   \c!width      =\externalfigureparameter\c!width,
   \c!height     =\externalfigureparameter\c!height,
   \c!lines      =\externalfigureparameter\c!lines]

% % this will become:
%
% \unexpanded\def\doscalefigure % used at lua end
%   {\global\setbox\foundexternalfigure\vbox\bgroup
%      \bgroup
%        \let\currentscale\currentexternalfigure
%        \let\scaleparameter\externalfigureparameter
%        \dowithnextboxcs\grph_scale_finish\hbox{\dowithfigure{\box\foundexternalfigure}}%
%    \egroup}
%
% % or even better:
%
% \def\grph_scale_inherited#1%
%   {\bgroup
%    \expandafter\let\expandafter\currentscale  \csname current#1\endcsname
%    \expandafter\let\expandafter\scaleparameter\csname #1parameter\endcsname
%    \dowithnextboxcs\grph_scale_finish\hbox}
%
% \unexpanded\def\doscalefigure % used at lua end
%   {\global\setbox\foundexternalfigure\vbox\bgroup
%      \grph_scale_inherited{externalfigure}{\dowithfigure{\box\foundexternalfigure}}%
%    \egroup}

%D You can register additional suffixes with the following command:
%D
%D \starttyping
%D \definegraphictypesynonym[jbig] [jb2]
%D \definegraphictypesynonym[jbig2][jb2]
%D \definegraphictypesynonym[jbg]  [jb2]
%D \stoptyping

\unexpanded\def\definegraphictypesynonym
  {\dodoubleargument\grph_include_set_type_synonym}

\def\grph_include_set_type_synonym[#1][#2]%
  {\ctxlua{figures.registersuffix("#1","#2")}}

%D Additional paths can be installed with the regular setup command. The next
%D macro picks up the list.

\unexpanded\def\setfigurepathlist
  {\ctxlua{figures.setpaths("\externalfigureparameter\c!location",\!!bs\externalfigureparameter\c!directory\!!es)}}

%D Variables:

\newbox \foundexternalfigure
\newtoks\externalfigurepostprocessors

\def\defaultfigurewidth  {8\lineheight}
\def\defaultfigureheight {6\lineheight}

\def\figurestatus        {\numexpr\ctxcommand{figurestatus("status",0)}\relax} % number: 0 = not found
\def\figurewidth         {\ctxcommand{figurestatus("width",0)}sp}
\def\figureheight        {\ctxcommand{figurestatus("height",0)}sp}
\def\figurexscale        {\ctxcommand{figurestatus("xscale",1)}}
\def\figureyscale        {\ctxcommand{figurestatus("yscale",1)}}

\def\figuresize          {\ctxcommand{figurerequest("size")}}
\def\figurelabel         {\ctxcommand{figurerequest("label")}}
\def\figurefileoriginal  {\ctxcommand{figurerequest("name")}}
\def\figurefilepage      {\ctxcommand{figurerequest("page",1)}}
\def\figurefileoptions   {\ctxcommand{figurerequest("options")}}
\def\figurefileconversion{\ctxcommand{figurerequest("conversion")}}
\def\figurefilecache     {\ctxcommand{figurerequest("cache")}}
\def\figurefileprefix    {\ctxcommand{figurerequest("prefix")}}

\def\figurenaturalwidth  {\ctxcommand{figureused("width", \number\dimexpr\defaultfigurewidth \relax)}sp}
\def\figurenaturalheight {\ctxcommand{figureused("height",\number\dimexpr\defaultfigureheight\relax)}sp}
\def\figurexresolution   {\ctxcommand{figureused("xresolution",0)}}
\def\figureyresolution   {\ctxcommand{figureused("yresolution",0)}}
\def\figurexsize         {\ctxcommand{figureused("xsize",0)}}
\def\figureysize         {\ctxcommand{figureused("ysize",0)}}
\def\figurecolordepth    {\ctxcommand{figureused("colordepth",0)}}
\def\figuredepth         {\ctxcommand{figureused("depth",0)}}

\def\figurefullname      {\ctxcommand{figureused("fullname")}}
\def\noffigurepages      {\ctxcommand{figureused("pages",0)}}

\def\figurefilepath      {\ctxcommand{figurefilepath()}}
\def\figurefilename      {\ctxcommand{figurefilename()}}
\def\figurefiletype      {\ctxcommand{figurefiletype()}}

\let\naturalfigurewidth  \figurenaturalwidth
\let\naturalfigureheight \figurenaturalheight

\let\figurescalewidth    \figurewidth
\let\figurescaleheight   \figureheight
\let\figurescalexscale   \figurexscale
\let\figurescaleyscale   \figureyscale

%D Abuse:
%D
%D \starttyping
%D \externalfigure[rubish.pdf] \ifcase\figurestatus\relax \ctxlua{os.exit(999)} \fi
%D \stoptyping

%D Calculating:

% \enabletrackers[figures.conversion]
% \externalfigure[demo.svg]
% \externalfigure[demo.svg][conversion=png]

%D The following registers are used (if only to be downward compatible).

\newconditional\c_grph_include_skip
\newconditional\c_grph_include_test_only
\newconditional\c_grph_include_level      \setfalse\c_grph_include_level  % true=background false=normal
\newconditional\c_grph_include_flush      \settrue \c_grph_include_flush  % true=place      false=ignore

\newsystemmode\v!figure

\def\grph_include_set_mode
  {\ifcase\figurestatus
     \global\resetsystemmode\v!figure % todo, also: \v!resource
   \else
     \global\setsystemmode  \v!figure % todo, also: \v!resource
   \fi}

\appendtoks
    \ctxlua { % figures.defaultwidth .. maybe a dimen some day
        figures.setpaths("\externalfigureparameter\c!location","\externalfigureparameter\c!directory") ;
        figures.defaultwidth  = \number\dimexpr\defaultfigurewidth \relax ;
        figures.defaultheight = \number\dimexpr\defaultfigureheight\relax ;
        figures.boxnumber     = \number\foundexternalfigure ;
    }%
\to \everyexternalfigureresets

\appendtoks
    \edef\p_option{\externalfigureparameter\c!option}%
    \ifx\p_option\v!frame
      \setfalse\c_grph_include_skip
      \letexternalfigureparameter\c!frame\v!on
    \else\ifx\p_option\v!empty
      \settrue\c_grph_include_skip
      \letexternalfigureparameter\c!frame\v!off
    \else
      \setfalse\c_grph_include_skip
    \fi\fi
    % fake color in gray bitmaps, assumes that
    % a transparent color is used
    \edef\p_foregroundcolor{\externalfigureparameter\c!foregroundcolor}%
    \ifx\p_foregroundcolor\empty \else
        \setexternalfigureparameter\c!background{\v!foreground,\v!color}%
        \letexternalfigureparameter\c!backgroundcolor\p_foregroundcolor
    \fi
\to \everyexternalfigurechecks

%D Internal graphics are handled at the \TEX\ end:

\def\grph_include_process_tex#1%
  {\global\setbox\foundexternalfigure\vbox\framed
     [\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off,
      \c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit]
     {\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here!

\def\grph_include_process_mps#1% retrofit into mkii
  {\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}}

\def\grph_include_process_cld#1%
  {\global\setbox\foundexternalfigure\vbox{\cldprocessfile{#1}}}

\unexpanded\def\docheckfigurebuffer  #1{\grph_include_process_tex{\getbuffer[#1]}}    % used al lua end
\unexpanded\def\docheckfiguretex     #1{\grph_include_process_tex{\input{#1}}}        % used al lua end
\unexpanded\def\docheckfigurecld     #1{\grph_include_process_cld{#1}}                % used al lua end
\unexpanded\def\docheckfiguremps     #1{\grph_include_process_mps{#1}}                % used al lua end
\unexpanded\def\docheckfiguremprun #1#2{\grph_include_process_tex{\useMPrun{#1}{#2}}} % used al lua end

\unexpanded\def\relocateexternalfigure % easier here than in lua
  {\global\setbox\foundexternalfigure\vbox to \ht\foundexternalfigure\bgroup
     \vss
     \ht\foundexternalfigure\zeropoint
     \hbox to \wd\foundexternalfigure\bgroup
        \box\foundexternalfigure
        \hss
     \egroup
   \egroup}

\unexpanded\def\startfoundexternalfigure#1#2% ht wd
  {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup}

\unexpanded\def\stopfoundexternalfigure
  {\hss\egroup\egroup}

\unexpanded\def\emptyfoundexternalfigure % sort of obsolete
  {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight
   \stopfoundexternalfigure}

% \doifmodeelse{*\v!last}
%   {\settrue \c_grph_include_flush}
%   {\setfalse\c_grph_include_flush}%

\def\grph_include_finalize
  {\global\setbox\foundexternalfigure\vbox
     {\ifcase\figurestatus
        \letexternalfigureparameter\c!frame\v!on
      \fi
      \ifconditional\c_grph_include_flush
        \ifconditional\c_grph_include_level % probably background
          \ifconditional\c_grph_include_skip
            % nothing
            \fakebox\foundexternalfigure
          \else\ifcase\figurestatus
            % nothing
          \else
            \the\externalfigurepostprocessors
            \box\foundexternalfigure
          \fi\fi
        \else
          \iftrialtypesetting \else \feedbackexternalfigure \fi
          \settrue\c_grph_include_level
          \ifconditional\c_grph_include_skip
            \ifcase\figurestatus
              \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
            \else
              \grph_include_replacement\figurelabel\figurefullname{skipped}%
            \fi
          \else\ifcase\figurestatus
            \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
          \else
            \the\externalfigurepostprocessors
            \edef\p_reset{\externalfigureparameter\c!reset}%
            \ifx\p_reset\v!yes
              \wd\foundexternalfigure\figurewidth
              \ht\foundexternalfigure\figureheight
              \dp\foundexternalfigure\zeropoint
              \box\foundexternalfigure
            \else
              \letexternalfigureparameter\c!offset\v!overlay
              \letexternalfigureparameter\c!width \figurewidth
              \letexternalfigureparameter\c!height\figureheight
              \inheritedexternalfigureframed{\vfilll\box\foundexternalfigure}%
            \fi
          \fi\fi
        \fi
      \else
        % maybe also \the\externalfigurepostprocessors
        \iftrialtypesetting \else \feedbackexternalfigure \fi
      \fi}}

\let\feedbackexternalfigure\relax % hook

\unexpanded\def\getfiguredimensions
  {\dodoubleempty\grph_include_get_dimensions}

\def\grph_include_get_dimensions[#1][#2]%
  {\startnointerference
     \settrue\c_grph_include_test_only
     \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
   \stopnointerference}

\unexpanded\def\doiffigureelse#1%
  {\getfiguredimensions[#1]% so data is available !
   \ifcase\figurestatus
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

% No placement, handy for preprocessing:

\unexpanded\def\registerexternalfigure
  {\dotripleempty\grph_include_register}

\def\grph_include_register[#1][#2][#3]%
  {\startnointerference
     \c_grph_include_test_only
     \setfalse\c_grph_include_flush % == test ?
     \externalfigure[#1][#2][#3]% or
     \externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
   \stopnointerference}

% Helpers (will be replaced when xforms are accessible at the lua end)

\unexpanded\def\dosetfigureobject#1%
  {\setobject{FIG}{#1}\vbox{\box\foundexternalfigure}}

\unexpanded\def\doboxfigureobject#1%
  {\global\setbox\foundexternalfigure\vbox{\getobject{FIG}{#1}}} % probably one vbox too many

% Figure bases

\unexpanded\def\usefigurebase[#1]%
  {\ctxlua{figures.bases.use("#1")}}

\appendtoks
   \setfigurepathlist  % the path may be used elsewhere too (as in x-res-04)
\to \everysetupexternalfigure

\appendtoks
    \ctxcommand{setfigurelookuporder("\externalfigureparameter\c!order")}%
\to \everysetupexternalfigure

\definecolor[missingfigurecolor][s=.8]

\def\grph_include_replacement#1#2#3%
  {\bgroup
   \letexternalfigureparameter\c!width\figurewidth
   \letexternalfigureparameter\c!height\figureheight
   \letexternalfigureparameter\c!background\v!color
   \setexternalfigureparameter\c!backgroundcolor{missingfigurecolor}%
   \setexternalfigureparameter\c!align{\v!middle,\v!lohi}% we default to \v!none
   \inheritedexternalfigureframed
     {\tt\tfxx \nohyphens
      name:  \expanded{\verbatimstring{#1}}\\%
      file:  \expanded{\verbatimstring{#2}}\\%
      state: \expanded{\verbatimstring{#3}}}%
   \egroup}

% maybe setuphandler

\newconditional\c_grph_include_in_collection

\newdimen\d_grph_include_collection_minwidth
\newdimen\d_grph_include_collection_maxwidth
\newdimen\d_grph_include_collection_minheight
\newdimen\d_grph_include_collection_maxheight

\def\grph_include_analyze_collection[#1][#2]%
  {\ifconditional\c_grph_include_in_collection
      \setfalse\c_grph_include_in_collection
      \getfiguredimensions[#1][#2]%
      \settrue\c_grph_include_in_collection
      \scratchdimen\naturalfigurewidth
      \ifdim\scratchdimen>\d_grph_include_collection_maxwidth  \d_grph_include_collection_maxwidth \scratchdimen \fi
      \ifdim\scratchdimen<\d_grph_include_collection_minwidth  \d_grph_include_collection_minwidth \scratchdimen \fi
      \scratchdimen\naturalfigureheight
      \ifdim\scratchdimen>\d_grph_include_collection_maxheight \d_grph_include_collection_maxheight\scratchdimen \fi
      \ifdim\scratchdimen<\d_grph_include_collection_minheight \d_grph_include_collection_minheight\scratchdimen \fi
   \fi}

\unexpanded\def\startexternalfigurecollection[#1]%
  {\begingroup
   \def\currentexternalfigurecollection{#1}%
   \settrue\c_grph_include_in_collection
   \d_grph_include_collection_minwidth \maxdimen
   \d_grph_include_collection_maxwidth \zeropoint
   \d_grph_include_collection_minheight\maxdimen
   \d_grph_include_collection_maxheight\zeropoint}

\unexpanded\def\stopexternalfigurecollection
  {\setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minwidth }{\the\d_grph_include_collection_minwidth }%
   \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxwidth }{\the\d_grph_include_collection_maxwidth }%
   \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minheight}{\the\d_grph_include_collection_minheight}%
   \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxheight}{\the\d_grph_include_collection_maxheight}%
   \endgroup}

\def\externalfigurecollectionparameter#1#2%
  {\csname
     \ifcsname\??externalfigurecollection#1:#2\endcsname
       \??externalfigurecollection#1:#2%
     \else
       \s!empty
     \fi
   \endcsname}

\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth }
\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth }
\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight}
\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight}

\let\efcparameter\externalfigurecollectionparameter % still needed ?
\let\efcminwidth \externalfigurecollectionminwidth  % still needed ?
\let\efcmaxwidth \externalfigurecollectionmaxwidth  % still needed ?
\let\efcminheight\externalfigurecollectionminheight % still needed ?
\let\efcmaxheight\externalfigurecollectionmaxheight % still needed ?

% \startexternalfigurecollection[name]
%     \useexternalfigure[cow] [cow.pdf]
%     \useexternalfigure[mill][mill.png]
% \stopexternalfigurecollection
% \starttext
% \bTABLE
%     \bTR
%         \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD
%         \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD
%     \eTR
% \eTABLE
% \stoptext

\unexpanded\def\showexternalfigures
  {\writestatus\m!system{the \string\showexternalfigures\space command is not (yet) implemented in mkiv}}

\unexpanded\def\overlayfigure#1%
  {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}

% Bonus:

\useexternalfigure
  [buffer]
  [\jobname.buffer]
  [\c!object=\v!no]

\protect \endinput
