%D \module
%D   [       file=typo-shp,
%D        version=2021.02.27, % was meta-txt / meta-imp-txt / 2000.07.06
%D          title=\CONTEXT\ Typesetting Macros,
%D       subtitle=Paragraph Shapes,
%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.

%D I finally decided to move some of the code written in 2000 for the
%D \METAFUN\ manual to its own core module. Of course it got adapted
%D to the way \LMTX\ does things.

\writestatus{loading}{ConTeXt Spacing Macros / Paragraph Shapes}

\registerctxluafile{typo-shp}{autosuffix}

\unprotect

%D Something new (experimental and evolving):
%D
%D \starttyping
%D \parshape
%D      3
%D      options 1 % repeat
%D      0cm 10cm 2cm 8cm 4cm 6cm
%D      lots of text
%D \stoptyping
%D
%D \starttyping
%D \parshape 4 5mm 125mm 0mm 120mm 5mm 125mm 0mm 120mm
%D \pushparagraphtweak {repeat}
%D     verse line 1\crlf
%D     verse line 2\crlf
%D     verse line 3\crlf
%D     verse line 4\par
%D     etc
%D \popparagraphtweak
%D \stoptyping

%D But we wrap this in a more abstract interface:

\installcorenamespace {parshapes}
\installcorenamespace {shapedparagraph}

\installbasicnativeautosetuphandler \??shapedparagraph {shapedparagraph}

\setupshapedparagraph
  [\c!method=,
   \c!list=,
   \c!lines=\zerocount,
   \c!mp=,
   \c!repeat=,
   \c!hoffset=\zeropoint,
   \c!voffset=\zeropoint,
   \c!distance=\zeropoint]

\permanent\protected\lettonothing\stopparagraphshape

\permanent\protected\def\startparagraphshape[#1]#2\stopparagraphshape
  {\gdefcsname\??parshapes#1\endcsname{#2}} % global

\permanent\protected\def\rawparagraphshape#1%
  {\begincsname\??parshapes#1\endcsname}

\permanent\protected\def\setparagraphshape[#1]%
  {\ifcsname\??parshapes#1\endcsname
     \expandafter\clf_setparagraphshape\lastnamedcs done\relax
   \fi}

\def\spac_shapes_calculate#1% called locally in \LUA
  {\startMPcalculation \includeMPgraphic{#1} \stopMPcalculation}

% \permanent\protected\tolerant\def\startshapedparagraph[#1]% no grouping
%   {\begingroup
%    \lettonothing\currentshapedparagraph
%    \setupshapedparagraph[#1]%
%    \edef\p_mp    {\shapedparagraphparameter\c!mp}%
%    \edef\p_repeat{\shapedparagraphparameter\c!repeat}%
%    \setlocalhsize
%    \normalexpanded
%      {\endgroup
%       \ifempty\p_mp
%         \setparagraphshape[\shapedparagraphparameter\c!list]%
%       \else
%         \setparagraphmetashape[\shapedparagraphparameter\c!mp][\ifx\p_repeat\v!yes repeat\fi]%
%       \fi
%       \pushparagraphtweak{\shapedparagraphparameter\c!method}\relax}}

\newbox\b_spac_shapes

\def\spac_shapes_list
  {\edef\p_mp    {\shapedparagraphparameter\c!mp}%
   \edef\p_repeat{\shapedparagraphparameter\c!repeat}%
   \normalexpanded
     {\endgroup
      \ifempty\p_mp
        \setparagraphshape[\shapedparagraphparameter\c!list]%
      \else
        \setparagraphmetashape[\p_mp][\ifx\p_repeat\v!yes repeat\fi]%
      \fi
      \pushparagraphtweak{\shapedparagraphparameter\c!method}\relax}}

\def\spac_shapes_text
  {\getnoflines{\dimexpr\htdp\b_spac_shapes+\shapedparagraphparameter\c!voffset}%
   \normalexpanded
     {\endgroup
      \clf_setparagraphshape
          left  \the\dimexpr
                    \wd\b_spac_shapes+\shapedparagraphparameter\c!distance
                   +\shapedparagraphparameter\c!hoffset
                \relax
          right \zeropoint
          copy  \the\numexpr
                   \noflines
                  +\shapedparagraphparameter\c!lines
                \relax
          left  \zeropoint
          right \zeropoint
        % inspect
          done
      \relax
      \pushparagraphtweak{shift}%
      \dontleavehmode
      \vtop
         xoffset \the\dimexpr
          -\shapedparagraphparameter\c!distance
          -\wd\b_spac_shapes
         \relax
         yoffset \the\dimexpr
           \shapedparagraphparameter\c!voffset
          +\strutht
         \relax
         {\smashbox\b_spac_shapes
          \box\b_spac_shapes}}}

\def\spac_shapes_lines
  {\normalexpanded
     {\endgroup
      \clf_setparagraphshape
          left  \shapedparagraphparameter\c!width
          right \zeropoint
          copy  \shapedparagraphparameter\c!lines
          left  \zeropoint
          right \zeropoint
        % inspect
          done
      \relax
      \pushparagraphtweak{shift}}}

\permanent\protected\tolerant\def\startshapedparagraph[#S#1]% no grouping
  {\begingroup
   \lettonothing\currentshapedparagraph
   \setupshapedparagraph[#1]%
   \setlocalhsize
   \ifempty{\shapedparagraphparameter\c!text}\else
     \global\setbox\b_spac_shapes\vpack\bgroup
       \forgetall
       \shapedparagraphparameter\c!text
     \egroup
   \fi
   \ifvoid\b_spac_shapes
     \ifnum\shapedparagraphparameter\c!lines>\zerocount
       \spac_shapes_lines
     \else
       \spac_shapes_list
     \fi
   \else
     \spac_shapes_text
   \fi
   \ignorespaces}

\permanent\protected\def\stopshapedparagraph
  {\popparagraphtweak}

%D As it is not much code we now put it here:

\newbox    \shapetextbox
\newinteger\shapetextindex

\permanent\protected\def\startshapetext[#S#1]%
  {\begingroup
   \global\shapetextindex\zerocount
   \global\setbox\shapetextbox\vbox\bgroup
     \setparagraphmetashape[#1]%
     \forgetall
     \dontcomplain
     \setuptolerance[\v!verytolerant,\v!stretch]% default
   % \setuplayout[\c!grid=\v!yes]% goes wrong, we need a local one
     \pushparagraphtweak{shift}}

\permanent\protected\def\stopshapetext
  {\popparagraphtweak
   \egroup
   \endgroup}

% \permanent\protected\def\getshapetext
%   {\vbox\bgroup
%    \forgetall
%    \dontcomplain
%    \global\advanceby\shapetextindex\plusone
%    \scratchcounter\getshapeparameter{lines}\relax
%    \ifnum\scratchcounter>\zerocount
%      \scratchwidth  \getshapeparameter{width}\scaledpoint\relax
%      \scratchheight \getshapeparameter{height}\scaledpoint\relax
%      \setbox\scratchbox\vpack to \scratchheight
%        {\splittopskip\strutheight
%         \vskip\dimexpr\getshapeparameter{voffset}\scaledpoint\relax
%         \ifcase\numexpr\getshapeparameter{first}\relax\else
%           \vskip\lineheight
%         \fi
%         \hskip\dimexpr\getshapeparameter{hoffset}\scaledpoint\relax
%         \hpack{\vsplit\shapetextbox to \scratchcounter\lineheight}}%
%      \wd\scratchbox\scratchwidth
%      \ht\scratchbox\scratchheight
%      \dp\scratchbox\zeropoint
%      \box\scratchbox
%    \else
%       % what now
%    \fi
%    \egroup}

\permanent\protected\def\getshapetext
  {\vbox\bgroup
   \forgetall
   \dontcomplain
   \global\advanceby\shapetextindex\plusone
   \scratchcounter\getshapeparameter{lines}\relax
   \ifnum\scratchcounter>\zerocount
     \scratchwidth  \getshapeparameter{width}\scaledpoint\relax
     \scratchheight \getshapeparameter{height}\scaledpoint\relax
     \scratchhoffset\dimexpr\getshapeparameter{hoffset}\scaledpoint\relax
     \scratchvoffset\dimexpr\getshapeparameter{voffset}\scaledpoint\relax
     \setbox\scratchbox\vpack to \scratchheight
       {\splittopskip\strutheight
        \vskip\scratchvoffset
        \ifcase\numexpr\getshapeparameter{first}\relax\else
          \vskip\lineheight
        \fi
        \hskip\scratchhoffset
        \hpack{\vsplit\shapetextbox to \scratchcounter\lineheight}}%
     \wd\scratchbox\dimexpr\scratchwidth +\scratchhoffset\relax
     \ht\scratchbox\dimexpr\scratchheight+\scratchvoffset\relax
     \dp\scratchbox\strutdp % zeropoint
     \box\scratchbox
   \else
      % what now
   \fi
   \egroup}

\protect

