%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
%    \expanded
%      {\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}%
   \expanded
     {\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)}%
   \expanded
     {\endgroup
      \clf_setparagraphshape
          left  \todimension{% expanded
                    \wd\b_spac_shapes
                   +(\shapedparagraphparameter\c!distance)%
                   +(\shapedparagraphparameter\c!hoffset)%
                }%
          right \zeropoint
          copy  \tointeger{% expanded
                   \noflines
                  +(\shapedparagraphparameter\c!lines)%
                }%
          left  \zeropoint
          right \zeropoint
        % inspect
          done
      \relax
      \pushparagraphtweak{shift}%
      \dontleavehmode
      \vtop
         \s!xoffset \todimension{% expanded
          \zeropoint % otherwise error
          -(\shapedparagraphparameter\c!distance)%
          -\wd\b_spac_shapes
         }%
         \s!yoffset \todimension{% expanded
           (\shapedparagraphparameter\c!voffset)%
          +\strutht
         }%
         {\smashbox\b_spac_shapes
          \box\b_spac_shapes}}}

\def\spac_shapes_lines
  {\expanded
     {\endgroup
      \clf_setparagraphshape
          left  \todimension{\shapedparagraphparameter\c!width}% expanded
          right \zeropoint
          copy  \tointeger{\shapedparagraphparameter\c!lines}% expanded
          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}%
     \scratchheight {\getshapeparameter{height}\scaledpoint}%
     \scratchhoffset{\getshapeparameter{hoffset}\scaledpoint}%
     \scratchvoffset{\getshapeparameter{voffset}\scaledpoint}%
     \setbox\scratchbox\vpack to \scratchheight
       {\splittopskip\strutheight
        \vskip\scratchvoffset
        \ifcase{\getshapeparameter{first}}\else
          \vskip\lineheight
        \fi
        \hskip\scratchhoffset
        \hpack{\vsplit\shapetextbox to \scratchcounter\lineheight}}%
     \wd\scratchbox{\scratchwidth +\scratchhoffset}%
     \ht\scratchbox{\scratchheight+\scratchvoffset}%
     \dp\scratchbox\strutdp % zeropoint
     \box\scratchbox
   \else
      % what now
   \fi
   \egroup}

\protect
