%D \module
%D   [       file=spac-prf,
%D        version=2015.11.16, % moved from test module mathplus
%D          title=\CONTEXT\ Spacing Macros,
%D       subtitle=Profiling,
%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 Spacing Macros / Profiling}

%D This is experimental code that we need for a project. The interface and details
%D can change. I moved it into the core because that way we can use it on servers.

% framed: first reflow then profile

\unprotect

\registerctxluafile{spac-prf}{autosuffix}

\definesystemattribute[profilemethod][public]

\installcorenamespace {profile}
\installcorenamespace {profiles}

\installcommandhandler \??profile {profile} \??profile

\setupprofile
  [\c!height=\strutht,
   \c!depth=\strutdp,
   \c!distance=\normallineskip,
   \c!lines=\zerocount,
   \c!factor=\plusone]

\defineprofile
  [\v!strict]
  [\c!method=\v!strict]

\defineprofile
  [\v!fixed]
  [\c!method=\v!fixed]

\defineprofile
  [\v!none]
  [\c!method=\v!none,
   \c!height=\zeropoint,
   \c!depth=\zeropoint,
   \c!distance=\zeropoint,
   \c!factor=\plusone]

\appendtoks
    \ifcstok{\profileparameter\c!define}\v!yes
        \frozen\protected\edefcsname\e!start\currentprofile\endcsname{\spac_profile_start{\currentprofile}}%
        \frozen\protected\defcsname \e!stop \currentprofile\endcsname{\spac_profile_stop}%
    \fi
\to \everydefineprofile

\def\spac_profile_set
  {\clf_setprofile
      name      {\currentprofile}%
      height    {\profileparameter\c!height}%
      depth     {\profileparameter\c!depth}%
      distance  {\profileparameter\c!distance}%
      factor    {\profileparameter\c!factor}%
      lines     {\profileparameter\c!lines}%
      method    {\profileparameter\c!method}%
   \relax}

\tolerant\protected\def\spac_profile_start#profile#spacer[#S#settings]%
  {\begingroup
   \ifparameter#settings\or
     \cdef\currentprofile{#profile}%
     \setupcurrentprofile[#settings]%
   \orelse\ifhastok={#profile}%
      \let\currentprofile\v!none
      \setupcurrentprofile[#profile]%
   \else
      \cdef\currentprofile{#profile}%
   \fi
   \spac_profile_set
   \profileparameter\c!before}

\protected\def\spac_profile_stop
  {\par % otherwise not applied
   \profileparameter\c!after
   \endgroup}

\permanent\protected\def\startprofile[#S#profile]%
  {\spac_profile_start{#profile}}

\permanent\protected\def\stopprofile
  {\spac_profile_stop}

\permanent\protected\def\setprofile[#profile]%
  {\cdef\currentprofile{#profile}%
   \spac_profile_set}

\permanent\protected\def\resetprofile
  {\c_attr_profilemethod\attributeunsetvalue}

\lettonothing\m_spac_profile_asked

\permanent\protected\def\useprofileparameter#getparameter%
  {\edef\m_spac_profile_asked{#getparameter\c!profile}%
   \ifempty\m_spac_profile_asked
     \resetprofile
   \else
     \setprofile[\m_spac_profile_asked]%
   \fi}

% This can become (when being tested):
%
% \permanent\protected\def\useprofileparameter#getparameter%
%   {\edef\m_spac_profile_asked
%    \ifempty{#getparameter\c!profile}%
%      \resetprofile
%    \else
%      \expanded{\setprofile[\lastnamedcs]}%
%    \fi}

\permanent\tolerant\protected\def\profiledbox[#S#profile]#spacer[#S#settings]%
  {\vbox\bgroup
   \ifparameter#settings\or
     \cdef\currentprofile{#profile}%
     \setupcurrentprofile[#settings]%
   \orelse\ifhastok={#profile}%
      \let\currentprofile\v!none
      \setupcurrentprofile[#profile]%
   \else
      \cdef\currentprofile{#profile}%
   \fi
   \dowithnextbox
     {\profilegivenbox\currentprofile\nextbox
      \unvbox\nextbox
      \egroup}%
     \vbox}

\permanent\protected\def\profilegivenbox#profile#box%
  {\begingroup
   \cdef\currentprofile{#profile}%
   \clf_profilebox
      box      {#box}%
      height   {\profileparameter\c!height}%
      depth    {\profileparameter\c!depth}%
      distance {\profileparameter\c!distance}%
      factor   {\profileparameter\c!factor}%
      lines    {\profileparameter\c!lines}%
      method   {\profileparameter\c!method}%
    \relax
    \endgroup}

\defineprofile[halffixed]   [\v!fixed][\c!factor=\plustwo]
\defineprofile[quarterfixed][\v!fixed][\c!factor=\plusfour]
\defineprofile[eightsfixed] [\v!fixed][\c!factor=\pluseight]

% Finally some follow up on this experiment:

\definesystemattribute[lineprofile] [public]

\installcorenamespace {lineprofile}

\installcommandhandler \??lineprofile {lineprofile} \??lineprofile

\setuplineprofile
  [\c!method=\v!a,
   \c!step=.5\emwidth, % maybe 2pt
   \c!paragraph=\v!no,
   \c!factor=.125]     % maybe 0.250

\def\spac_line_profile_set
  {\clf_setlineprofile
      name      {\currentlineprofile}%
      step      {\lineprofileparameter\c!step}%
      factor    {\lineprofileparameter\c!factor}%
      method    {\lineprofileparameter\c!method}%
      paragraph {\lineprofileparameter\c!paragraph}%
   \relax}

\permanent\tolerant\protected\def\setlineprofile[#profile]%
  {\cdef\currentlineprofile{#profile}%
   \spac_line_profile_set}

\permanent\protected\def\resetlineprofile
  {\c_attr_lineprofile\attributeunsetvalue}

\permanent\protected\def\setmainlineprofile
  {\lettonothing\currentlineprofile
   \spac_line_profile_set}

\appendtoks
    \c_attr_lineprofile\attributeunsetvalue % or in general resetter
\to \everyforgetall

\protect \endinput