%% \iffalse meta-comment
%
% cutwin.dtx
% Author: Peter Wilson, Herries Press
%         and Alan Hoenig
% Copyright 2010 Peter R. Wilson
%
% Current Maintainer David Carlisle
% Copyright 2021 Peter R. Wilson, David Carlisle
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3 of this license or (at your option) any
% later version.
% The latest version of the license is in
%    http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of
% LaTeX version 2003/06/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% This work consists of the files listed in the README file.
%
%<*driver>
\documentclass[twoside]{ltxdoc}
\usepackage{alltt}
\usepackage{cutwin}
%\usepackage[draft=false,
%            plainpages=false,
%            pdfpagelabels,
%            bookmarksnumbered,
%            hyperindex=false
%           ]{hyperref}
\providecommand{\phantomsection}
\show\makeatletter
\makeatletter
  \@mparswitchfalse
\makeatother
\renewcommand{\MakeUppercase}[1]{#1}
\pagestyle{headings}
\EnableCrossrefs
\CodelineIndex
%%\OnlyDescription
\setcounter{StandardModuleDepth}{1}
\begin{document}
  \raggedbottom
  \DocInput{cutwin.dtx}
\end{document}
%</driver>
%
% \fi
%
%
% \DoNotIndex{\',\.,\@M,\@@input,\@addtoreset,\@arabic,\@badmath}
% \DoNotIndex{\@centercr,\@cite}
% \DoNotIndex{\@dotsep,\@empty,\@float,\@gobble,\@gobbletwo,\@ignoretrue}
% \DoNotIndex{\@input,\@ixpt,\@m}
% \DoNotIndex{\@minus,\@mkboth,\@ne,\@nil,\@nomath,\@plus,\@set@topoint}
% \DoNotIndex{\@tempboxa,\@tempcnta,\@tempdima,\c@twdima}
% \DoNotIndex{\@tempswafalse,\@tempswatrue,\@viipt,\@viiipt,\@vipt}
% \DoNotIndex{\@vpt,\@warning,\@xiipt,\@xipt,\@xivpt,\@xpt,\@xviipt}
% \DoNotIndex{\@xxpt,\@xxvpt,\\,\ ,\addpenalty,\addtolength,\addvspace}
% \DoNotIndex{\advance,\Alph,\alph}
% \DoNotIndex{\arabic,\ast,\begin,\begingroup,\bfseries,\bgroup,\box}
% \DoNotIndex{\bullet}
% \DoNotIndex{\cdot,\cite,\CodelineIndex,\cr,\day,\DeclareOption}
% \DoNotIndex{\def,\DisableCrossrefs,\divide,\DocInput,\documentclass}
% \DoNotIndex{\DoNotIndex,\egroup,\ifdim,\else,\fi,\em,\endtrivlist}
% \DoNotIndex{\EnableCrossrefs,\end,\end@dblfloat,\end@float,\endgroup}
% \DoNotIndex{\endlist,\everycr,\everypar,\ExecuteOptions,\expandafter}
% \DoNotIndex{\fbox}
% \DoNotIndex{\filedate,\filename,\fileversion,\fontsize,\framebox,\gdef}
% \DoNotIndex{\global,\halign,\hangindent,\hbox,\hfil,\hfill,\hrule}
% \DoNotIndex{\hsize,\hskip,\hspace,\hss,\if@tempswa,\ifcase,\or,\fi,\fi}
% \DoNotIndex{\ifhmode,\ifvmode,\ifnum,\iftrue,\ifx,\fi,\fi,\fi,\fi,\fi}
% \DoNotIndex{\input}
% \DoNotIndex{\jobname,\kern,\leavevmode,\let,\leftmark}
% \DoNotIndex{\list,\llap,\long,\m@ne,\m@th,\mark,\markboth,\markright}
% \DoNotIndex{\month,\newcommand,\newcounter,\newenvironment}
% \DoNotIndex{\NeedsTeXFormat,\newdimen}
% \DoNotIndex{\newlength,\newpage,\nobreak,\noindent,\null,\number}
% \DoNotIndex{\numberline,\OldMakeindex,\OnlyDescription,\p@}
% \DoNotIndex{\pagestyle,\par,\paragraph,\paragraphmark,\parfillskip}
% \DoNotIndex{\penalty,\PrintChanges,\PrintIndex,\ProcessOptions}
% \DoNotIndex{\protect,\ProvidesClass,\raggedbottom,\raggedright}
% \DoNotIndex{\refstepcounter,\relax,\renewcommand,\reset@font}
% \DoNotIndex{\rightmarnnnnnnngin,\rightmark,\rightskip,\rlap,\rmfamily,\roman}
% \DoNotIndex{\roman,\secdef,\selectfont,\setbox,\setcounter,\setlength}
% \DoNotIndex{\settowidth,\sfcode,\skip,\sloppy,\slshape,\space}
% \DoNotIndex{\symbol,\the,\trivlist,\typeout,\tw@,\undefined,\uppercase}
% \DoNotIndex{\usecounter,\usefont,\usepackage,\vfil,\vfill,\viiipt}
% \DoNotIndex{\viipt,\vipt,\vskip,\vspace}
% \DoNotIndex{\wd,\xiipt,\year,\z@}
%
% \changes{v0.1}{2010/09/29}{First public release}
% \changes{v0.2}{2021/10/13}{Declare registers}
%
% \def\dtxfile{cutwin.dtx}
% \def\fileversion{v0.2} \def\filedate{2021/10/13}
% \newcommand*{\Lpack}[1]{\textsf {#1}}           ^^A typeset a package
% \newcommand*{\Lopt}[1]{\textsf {#1}}            ^^A typeset an option
% \newcommand*{\file}[1]{\texttt {#1}}            ^^A typeset a file
% \newcommand*{\Lcount}[1]{\textsl {\small#1}}    ^^A typeset a counter
% \newcommand*{\pstyle}[1]{\textsl {#1}}          ^^A typeset a pagestyle
% \newcommand*{\Lenv}[1]{\texttt {#1}}            ^^A typeset an environment
% \newcommand*{\ablankline}{\vspace{\baselineskip}}
%
% \title{Making cutouts in paragraphs\thanks{This
%        file (\texttt{\dtxfile}) has version number \fileversion, last revised
%        \filedate.}}
%
% \author{%
% Peter Wilson\thanks{Herries Press} and Alan Hoenig\and
% Maintained by David Carlisle\thanks{https://github.com/latex-package-repositories/cutwin/issues}%
% }
% \date{\filedate}
% \maketitle
% \begin{abstract}
%    The \Lpack{cutwin} package helps in making a cutout window in the middle
% of a paragraph.
%
% \end{abstract}
% \tableofcontents
%
%
%
% \section{Introduction}
%
%  ^^A  Based on Alan Hoenig, `TeX Does Windows --- The Conclusion',
%  ^^A              TUGboat, 8, 2 pp211-215, 1987
%
%
% This manual is typeset according to the conventions of the
% \LaTeX{} \textsc{docstrip} utility which enables the automatic
% extraction of the \LaTeX{} macro source files~\cite{COMPANION}.
%
%    Section~\ref{sec:usc} describes the usage of the \Lpack{cutwin}
% package and
% commented source code is in Section~\ref{sec:code}.
%
% \section{The \Lpack{cutwin} package} \label{sec:usc}
%
% The code provided by the \Lpack{cutwin} package is meant to help
% in creating windows, or cutouts, in a text-only paragraph. It is
% based on code originally published by Alan Hoenig~\cite{HOENIG87}.
%
% \subsection{General}
%
% \DescribeMacro{\opencutleft}
% \DescribeMacro{\opencutright}
% \DescribeMacro{\opencutcenter}
% Declarations specifying where a window is to be placed. The choices
% are: \cs{opencutleft} open into the left margin, \cs{opencutright}
% open into the right margin, and \cs{opencutcenter}, which is the default,
% open in the `center' of the text, i.e, have text on both sides of the
% window.
%
% \DescribeMacro{\cutfuzz}
%   This is provided as a convenience to reduce the number of overfull
% and underfull warnings. Its default definition is:
% \begin{verbatim}
% \newcommand{\cutfuzz}{%
%   \vbadness=50000
%   \hbadness=50000
%   \sloppy}
% \end{verbatim}
% and it is only applied to the paragraph being windowed.
%
% \subsection{Rectangular cutouts}
%
% \newcommand*{\tinwin}{%
%  \centering\bfseries
%  Text \\ in \\Window \par}
% \newcommand*{\qinwin}{%
%   \centering\bfseries\Huge ?\,
%   \par}
% \let\windowpagestuff\tinwin
% \begin{cutout}{2}{0.2\textwidth}{0.4\textwidth}{3}
% A rectangular space can be placed in a paragraph with the text flowing
% across the gap. The space may break open into the top or side of the
% paragraph or, with some care, into the bottom (the number of lines
% specified for the cutout should not exceed the amount of text
% available for those lines). Some text or a logo or
% graphic may be placed within the window, or it may be left empty.
% In this instance I have put three short bold text lines in the window
% opening. The window should not be too wide as it can be difficult
% to track the exterior text lines across the gap.
% \end{cutout}
%
% \DescribeEnv{cutout}
% The |cutout| environment, the body of which must be a single paragraph,
% enables a rectangular window to be cut out of the paragraph with the
% text flowing across the cutout. Use as:\\
% \verb?\begin{cutout}?\marg{numtop}\marg{leftwidth}\marg{rightwidth}\marg{numcut} \\
% where \meta{numtop} is the number of full lines above the window
% and \meta{numcut} is the number of lines to be cut (giving the height
% of the window).
% The meaning of the lengths \meta{leftwidth} and \meta{rightwidth} depend
% on the location of the cutout:
% \begin{itemize}
% \item for a centered cutout \meta{leftwidth} and \meta{rightwidth} are the
% lengths of the text lines at the left and right sides of the window;
% \item for an open left cutout \meta{leftwidth} is ignored and
% \meta{rightwidth} is the length of the lines to the right of the cutout; and
% \item for an open right cutout \meta{rightwidth} is ignored and
% \meta{leftwidth} is the length of the lines at the left of the cutout.
% \end{itemize}
%
%
% \DescribeMacro{\pageinwindow}
% \DescribeMacro{\windowpagestuff}
% The macro \cs{pageinwindow} puts a zero-sized |picture| positioned
% at the left of the window aligned with the first line of the window (i.e,
% at the top left of the cutout).
% The |picture| consists of a |minipage| sized to fit the window.
% The contents of the minipage is \cs{windowpagestuff}. These two
% macros may be used to put a graphic or text into the windowed area.
%
%    The default definition of \cs{windowpagestuff} is: \\
% \verb?\newcommand*{\windowpagestuff}{}? \\
% and you can change it as you wish. For instance, I used the following
% to put some text centrally within the above cutout.
% \begin{verbatim}
% \renewcommand*{\windowpagestuff}{%
%   \centering\bfseries
%   Text \\ in \\ Window \par}
% \end{verbatim}
% You may well need to experiment to get everything adjusted to your
% satisfaction.
%
% \subsection{Shaped cutouts}
%
% \newcommand*{\mycut}{%
%   0.1\textwidth, 0.3\textwidth,
%   0.2\textwidth, 0.4\textwidth,
%   0.3\textwidth, 0.5\textwidth}
% \renewcommand*{\putstuffinpic}{%
%   \put(0,-8){\makebox(0,0){\Huge\bfseries \$}}}
%
% \begin{shapedcutout}{2}{3}{\mycut}
%     A \emph{shaped cutout} is one where the shape of the window is
% specified by the user who has to supply the length of the text lines
% bordering the cutout. Normally there is text on either side of the
% window but it could be open at either the left or right side of
% the paragraph. It is possible to put a logo or some text in the
% window. In this paragraph with a shaped cutout I have used a large
% \$ sign as a simple logo.
% \end{shapedcutout}
%
%
% \DescribeEnv{shapedcutout}
% The |shapedcutout| environment, the body of which must be a single paragraph,
% enables an arbitrary shaped window to be cut out of the paragraph with the
% text flowing across the cutout. Use as:\\
% \verb?\begin{shapedcutout}?\marg{numtop}\marg{numcut}\marg{shapespec}
% where \meta{numtop} is the number of full lines above the window,
% \meta{numcut} is the number of lines to be cut (giving the height of
% the window) and
% \meta{shapespec} is the specification of the length of the lines
% bordering the cutout.
%
%    More precisely \meta{shapespec} is a comma-separated list of the
% lengths of the
% text lines bordering the window.
% \begin{itemize}
% \item For a centered cutout one pair of entries are required for each cut
% line denoting the length of the left and right part of the cut line.
% There must be exactly \meta{numcut} pairs.
% \item
% For example you might do something along the lines of:
% \begin{verbatim}
% \newcommand*{\mycut}{%
%   0.1\textwidth, 0.3\textwidth,
%   0.2\textwidth, 0.4\textwidth,
%   0.3\textwidth, 0.5\textwidth}
% \begin{shapedcutout}{2}{3}{\mycut}
% ...
% \end{verbatim}
% which is what I used to create the shaped cutout above.
% \item For an open cutout each entry is the text length of a line. There must
% be exactly \meta{numcut} entries. For instance, given the above definition
% of \cs{mycut} then a call out for an open window would be like: \\
% \verb?\begin{shapedcutout}{2}{6}{\mycut}?
% \end{itemize}
%
% \DescribeMacro{\picinwindow}
% In a shaped cutout the macro \cs{picinwindow} is placed at the center
% of the gap in the first line of the
% cutout. The default \cs{picinwindow} is a zero-sized picture whose contents
% is \cs{putstuffinpic}.
%
%    \cs{picinwindow} and \cs{putstuffinpic} are initially defined as
% \begin{verbatim}
% \newcommand*{\picinwindow}{%
%   \begin{picture}(0,0)
%     \putstuffinpic
%   \end{picture}}
% \newcommand*{\putstuffinpic}{}
% \end{verbatim}
%
%    You can change \cs{putstuffinpic} to place what you want in the picture.
% For example, to put the large \$ symbol in the shaped cutout paragraph above
% I used:
% \begin{verbatim}
% \renewcommand*{\putstuffinpic}{%
%   \put(0,-8){\makebox(0,0){\Huge\bfseries \$}}}
% \end{verbatim}
% You have to adjust the placement to suit your purposes and the shape of
% the cutout.
%
% \StopEventually{
% \bibliographystyle{alpha}
% \begin{thebibliography}{GMS04}
% \bibitem[GM04]{COMPANION}
% Frank Mittelbach and Michel Goossens.
% \newblock \emph{The LaTeX Companion}. Second edition.
% \newblock Addison-Wesley Publishing Company, 2004.
% \bibitem[Hoe87]{HOENIG87}
% Alan Hoenig.
% \newblock TeX does windows --- The conclusion,
% \newblock \emph{TUGboat}, vol 8, no 2, pp 211--215, 1987.
% \end{thebibliography}
% }
%
%
% \clearpage
% \section{The package code} \label{sec:code}
%
%    To try and avoid name clashes, all the internal commands include
% the string |c@tw|.
%
% \subsection{Preliminaries}
%
%    Announce the name and version of the package, which requires
% \LaTeXe.
%    \begin{macrocode}
%<*pkg>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{cutwin}[2021/10/13 v0.2 cutout windows]
%    \end{macrocode}
%
%
% \subsection{General}
%
% \begin{macro}{\c@twwinlines}
% \begin{macro}{\c@twtoplines}
% \begin{macro}{\c@twcnt}
% We need lots of variables. First some counts.
%    \begin{macrocode}
\newcount\c@twwinlines % window lines
\newcount\c@twtoplines % top lines
\newcount\c@twcnt      % a count
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twlftside}
% \begin{macro}{\c@twrtside}
% \begin{macro}{\c@twtopht}
% \begin{macro}{\c@twvsilg}
% And some lengths.
%    \begin{macrocode}
\newdimen\c@twlftside  % left width
\newdimen\c@twrtside   % right width
\newdimen\c@twtopht    % height of top text
\newdimen\c@twvsilg    % Vertical Shift or InterLine Glue
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twtoka}
% \begin{macro}{\c@twtokb}
% And some tokens.
%    \begin{macrocode}
\newtoks\c@twtoka      % build of parshape spec
\newtoks\c@twtokb      % build of parshape spec
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twrawtext}
% \begin{macro}{\c@twholdwin}
% \begin{macro}{\c@twwindow}
% \begin{macro}{\c@twfinaltext}
% \begin{macro}{\c@twslicea}
% \begin{macro}{\c@twsliceb}
% And some boxes.
%    \begin{macrocode}
\newbox\c@twrawtext    % text as input
\newbox\c@twholdwin    % text for window sides
\newbox\c@twwindow     % composed window
\newbox\c@twfinaltext  % final assembled cutout paragraph
\newbox\c@twslicea     % slice A of window text
\newbox\c@twsliceb     % slice B of window text
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twdima}
% \begin{macro}{\c@twdimb}
% And some lengths.
%    \begin{macrocode}
\newdimen\c@twdima    % formally \@tempdimb
\newdimen\c@twdimb    % formally \@tempdimc
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\opencutleft}
% \begin{macro}{\opencutright}
% \begin{macro}{\opencutcenter}
% \begin{macro}{\c@twl@c}
% User commands for positioning a cutout; left, right, or center.
% The default is \cs{opencutcenter}.
% \cs{c@twl@c} is the internal representation.
%    \begin{macrocode}
\newcommand*{\opencutleft}{\def\c@twl@c{-1}}
\newcommand*{\opencutright}{\def\c@twl@c{1}}
\newcommand*{\opencutcenter}{\def\c@twl@c{0}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%    \begin{macrocode}
\opencutcenter
%    \end{macrocode}
%
% \begin{macro}{\cutfuzz}
%  An attempt to stop TeX moaning about over/under full h/v boxes.
%    \begin{macrocode}
\newcommand{\cutfuzz}{\vbadness=50000
   \hbadness=50000
%   \hfuzz=1pt
  \sloppy}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c@twcalcilg}
% Calculate the interline glue.
%    \begin{macrocode}
\newcommand*{\c@twcalcilg}{%
  \c@twvsilg=\baselineskip
  \setbox0=\hbox{(}%
  \advance\c@twvsilg-\ht0 \advance\c@twvsilg-\dp0}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Rectangular cutouts}
%
% \begin{macro}{\pageinwindow}
% \begin{macro}{\windowpagestuff}
% User modifiable macros for putting (\cs{pageinwindow}), via a
% zero-sized picture,
% stuff (\cs{windowpagestuff}) in a cutout window.
%    \begin{macrocode}
\newcommand*{\pageinwindow}{%
  \c@twdimb=\c@twwinlines\baselineskip % cutout height
  \c@twdima=\hsize
  \ifnum\c@twl@c=\m@ne % openleft
    \advance\c@twdima -\c@twrtside
  \else
    \ifnum\c@twl@c=\@ne % openright
      \advance\c@twdima -\c@twlftside
    \else% center
      \advance\c@twdima - \c@twlftside
      \advance\c@twdima - \c@twrtside
    \fi
  \fi
  \begin{picture}(0,0)%
    \put(0,0){%
      \raisebox{4pt}{%
%\fbox{%
        \begin{minipage}[t][\c@twdimb][c]{\c@twdima}%
          \windowpagestuff
        \end{minipage}%
%}% end fbox
      }% end raisebox
    }% end put
  \end{picture}}
\newcommand*{\windowpagestuff}{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{environment}{cutout}
% The environment for cutting a rectangular window from a paragraph.
%
% \verb?\begin{cutout}?\marg{numtop}\marg{leftwidth}\marg{rightwidth}\marg{numcut} \\
% where \meta{numtop} is the number of full lines above the window,
% \meta{leftwidth} and \meta{rightwidth} are the widths of the text
% at the sides of the window,
% and \meta{numcut} is the number of lines to be cut (giving the height
% of the window).
%
%    The basic method is to split the paragraph into three parts (a)
% the top lines above the window, (b) the window lines and (c) the rest
% (which will be below the window).  \cs{parshape} is used to do the
% splitting. The top lines are left at their natural length, each line
% crossing the window is treated as a pair of short lines, and the rest
% are left at their natural length.
%
%    The top lines are put into one box, the windowed ones into another
% and then there are the remainder. When being boxed, the window lines
% are combined pairwise to make single lines with space in the middle.
% Finally, the boxes are output.
%    \begin{macrocode}
\newenvironment{cutout}[4]{%
  \cutfuzz
  \c@twtoplines=#1\relax
  \c@twwinlines=#4\relax
  \c@twlftside=#2\relax
  \c@twrtside=#3\relax
  \c@twtoka={}%
%    \end{macrocode}
% Generate the \cs{parshape} specification.
%    \begin{macrocode}
  \c@twmakeparspec
%    \end{macrocode}
% Reset the arguments and calculate a vertical shift.
%    \begin{macrocode}
  \c@twtoplines=#1\relax
  \c@twwinlines=#4\relax
  \c@twcalcshift \vskip-\c@twvsilg
%    \end{macrocode}
% Open the \cs{c@twrawtext} box, call the \cs{parshape} and start
% collecting the text to be windowed.
%    \begin{macrocode}
  \setbox\c@twrawtext=\vbox\bgroup
  \parshape=\c@twcnt \the\c@twtoka}%
%    \end{macrocode}
% Now the code for the actions at \verb?\end{cutout}?, which starts by ending
% the \cs{c@rawtext} box, resetting \cs{parshape} and calculating
% the interline glue.
%    \begin{macrocode}
  {\egroup% end \box\c@twrawtext
  \parshape=0 % reset parshape;
  \c@twcalcilg % find ILG using current font
%    \end{macrocode}
% If there are lines above the window, split them off from \cs{c@twrawtext}
% into \cs{c@twfinaltext}.
%    \begin{macrocode}
  \ifnum\c@twtoplines>\z@
    \setbox\c@twfinaltext=\vsplit\c@twrawtext to\c@twtoplines\baselineskip
  \fi
%    \end{macrocode}
% Calculate the `height' of the lines that make up the window. If
% the window is in the center then this is twice the expected height
% (at this point each final window line is stored as a pair of lines),
% otherwise it is the expected height based on \meta{numcut}.
%    \begin{macrocode}
  \c@twtopht=\c@twwinlines\baselineskip
  \ifnum\c@twl@c=\z@ % center
    \c@twtopht=2\c@twtopht
  \fi
%    \end{macrocode}
% Split the window lines from what is left in the \cs{c@twrawtext} box
% into box \cs{c@twholdwin} which will then contain the narrowed text for the
% window side(s).
%    \begin{macrocode}
  \setbox\c@twholdwin=\vsplit\c@twrawtext to\c@twtopht
%    \end{macrocode}
% Now `compose' the window side(s) text (\cs{c@twholdwin})
% into the final set of windowed lines (\cs{c@twwindow}).
% The process depends on whether the cutout is at the left, right, or center.
%    \begin{macrocode}
  \ifnum\c@twl@c=\z@% center
    \c@twcompctr{\c@twholdwin}{\c@twwindow}%
  \else% left or right
    \c@twcomplftrt{\c@twholdwin}{\c@twwindow}%
  \fi
%    \end{macrocode}
% Assemble the various boxes into the final box (\cs{c@twfinaltext})
% to be output.
%    \begin{macrocode}
  \setbox\c@twfinaltext=
    \vbox{\ifnum\c@twtoplines>\z@\unvbox\c@twfinaltext\vskip\c@twvsilg\fi
    \unvbox\c@twwindow%
    \vskip-\c@twvsilg\unvbox\c@twrawtext}%
%    \end{macrocode}
% We're done, hand off the paragraph.
%    \begin{macrocode}
  \box\c@twfinaltext}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\c@twcompctr}
% \begin{macro}{\c@twfirst}
%  \cs{c@twcompctr}\marg{linepairbox}\marg{composedbox} composes a
% center window box \meta{linepairbox} consisting of pairs of short
% lines into a box \meta{composedbox} where the pairs have been assembled
% into single lines.
%
% \cs{c@twfirst} is used as a flag for indicating the first line of a cutout.
%    \begin{macrocode}
\newcommand*{\c@twcompctr}[2]{%
  \def\c@twfirst{1}%
  \loop\advance\c@twwinlines\m@ne
%    \end{macrocode}
% Get a pair of lines and remove skips.
%    \begin{macrocode}
  \setbox\c@twslicea=\vsplit#1 to\baselineskip
  \setbox\c@twsliceb=\vsplit#1 to\baselineskip
  \c@twprune{\c@twslicea}{\c@twlftside}%
  \c@twprune{\c@twsliceb}{\c@twrtside}%
%    \end{macrocode}
%    \begin{macrocode}
  \ifnum\c@twfirst=\@ne
%    \end{macrocode}
% The first time put the texts into a box at the left and right with
% \cs{pageinwindow} at the end of the left text.
%    \begin{macrocode}
    \setbox#2=\vbox{\unvbox#2\hbox
    to\hsize{\box\c@twslicea\pageinwindow\hfil\box\c@twsliceb}}%
  \else
%    \end{macrocode}
% For further lines just put the texts at the left and right.
%    \begin{macrocode}
    \setbox#2=\vbox{\unvbox#2\hbox
    to\hsize{\box\c@twslicea\hfil\box\c@twsliceb}}%
  \fi
%    \end{macrocode}
%    \begin{macrocode}
  \def\c@twfirst{2}%
  \ifnum\c@twwinlines>\z@\repeat}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twcomplftrt}
% Compose an open (left or right) sided rectangular window.
%    \begin{macrocode}
\newcommand*{\c@twcomplftrt}[2]{%
  \def\c@twfirst{1}%
  \loop\advance\c@twwinlines\m@ne
%    \end{macrocode}
% For an open window we simply deal with one line at a time, not
% pairs. In other respects the code is generally similar to that for
% \cs{c@twcompctr}.
%    \begin{macrocode}
  \setbox\c@twslicea=\vsplit#1 to\baselineskip
  \ifnum\c@twl@c=\m@ne%    open left, text at right
    \c@twprune{\c@twslicea}{\c@twrtside}%
    \ifnum\c@twfirst=\@ne
      \setbox#2=\vbox{\unvbox#2\hbox
      to\hsize{\pageinwindow\hfil\box\c@twslicea}}%
    \else
      \setbox#2=\vbox{\unvbox#2\hbox
      to\hsize{\mbox{}\hfil\box\c@twslicea}}%
    \fi
    \def\c@twfirst{2}%
  \else
    \ifnum\c@twl@c=\@ne% open right, text at left
      \c@twprune{\c@twslicea}{\c@twlftside}%
      \ifnum\c@twfirst=\@ne\relax
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea\pageinwindow}}%
      \else
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea}}%
      \fi
      \def\c@twfirst{2}%
    \fi
  \fi
  \ifnum\c@twwinlines>\z@\repeat}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\c@twprune}
% \cs{c@twprune}\marg{vbox}\marg{width} chops off the \cs{lastskip}.
% It takes a \meta{vbox} containing a single \cs{hbox}, \cs{unvbox}es
% it,cancels the \cs{lastskip} which can be put at the right of
% a short \cs{parshape} line, then puts it in a box width \meta{width}.
%    \begin{macrocode}
\newcommand*{\c@twprune}[2]{%
  \unvbox#1 \setbox#1=\lastbox % \box#1 is now an \hbox
  \setbox#1=\hbox to#2{\strut\unhbox#1\unskip}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c@twmakeparspec}
% Calculate the required \cs{parshape} spec for a paragraph with a rectangular
% cutout window.
%    \begin{macrocode}
\newcommand*{\c@twmakeparspec}{%
%    \end{macrocode}
% \cs{c@twcnt} is the total number of lines for the \cs{parshape}, i.e.,
% the number of the top lines plus (twice) the number of window line
% plus one for the remaining lines.
%    \begin{macrocode}
  \c@twcnt=\c@twwinlines
  \ifnum\c@twl@c=\z@
    \multiply \c@twcnt by \tw@
  \fi
  \advance\c@twcnt by \c@twtoplines \advance\c@twcnt by \@ne
%    \end{macrocode}
% If there are top lines generate a \verb?0pt \hsize? for each
%    \begin{macrocode}
  \ifnum\c@twtoplines>\z@
    \loop\c@twtoka=\expandafter{\the\c@twtoka 0pt \hsize}%
      \advance\c@twtoplines -1\relax
    \ifnum\c@twtoplines>\z@\repeat
  \fi
%    \end{macrocode}
% Now do the cutout portion of the spec.
%    \begin{macrocode}
  \ifnum\c@twl@c=\m@ne % openleft
%    \end{macrocode}
% For open left calculate the width of the open cutout as \cs{c@twlftside}.
%    \begin{macrocode}
    \c@twlftside=\hsize
    \advance\c@twlftside -\c@twrtside
  \fi
%    \end{macrocode}
% Loop over the windowed lines.
%    \begin{macrocode}
  \loop\c@twtoka=%
    \ifnum\c@twl@c=\m@ne % openleft
%    \end{macrocode}
% For open left generate a \verb?\c@twlftside \c@twrtside? for each.
%    \begin{macrocode}
      \expandafter{\the\c@twtoka \c@twlftside \c@twrtside}%
    \else
      \ifnum\c@twl@c=\@ne % openright
%    \end{macrocode}
% For open right generate a \verb?\0pt c@twlftside? for each
%    \begin{macrocode}
        \expandafter{\the\c@twtoka 0pt \c@twlftside}%
      \else %center
%    \end{macrocode}
% For centered generate \verb?0pt \c@twlftside 0pt \c@twrtside? for each pair.
%    \begin{macrocode}
        \expandafter{\the\c@twtoka 0pt \c@twlftside 0pt \c@twrtside}%
      \fi
    \fi
    \advance\c@twwinlines \m@ne
  \ifnum\c@twwinlines>\z@\repeat
%    \end{macrocode}
% That finishes the cutout portion. For the remaining lines in the
% paragraph just generate a single \verb?0pt \hsize?.
%    \begin{macrocode}
  \c@twtoka=\expandafter{\the\c@twtoka 0pt \hsize}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c@twcalcshift}
% Calculate the estimated vertical shift needed for the window.
% I determined the values experimentally based on a 10pt font.
% In may be different for different fonts, but I hope not.
%    \begin{macrocode}
\newcommand*{\c@twcalcshift}{% vertical shift
  \c@twvsilg=\c@twwinlines\baselineskip
  \ifnum\c@twtoplines<\@ne
    \advance\c@twvsilg -0.25\baselineskip
  \fi
  \c@twvsilg=0.5\c@twvsilg
  \ifnum\c@twl@c=\z@\else
    \c@twvsilg=0.5\c@twvsilg
  \fi}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Shaped cutouts}
%
% \begin{macro}{\picinwindow}
% A zero-sized picture, with contents \cs{putstuffinpic}, which is placed in
% the center of the first gap in a shaped cutout.
%    \begin{macrocode}
\newcommand*{\picinwindow}{%
  \begin{picture}(0,0)
  \putstuffinpic
  \end{picture}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\putstuffinpic}
% Default \cs{putstuffinpic} is empty.
%    \begin{macrocode}
\newcommand*{\putstuffinpic}{}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{shapedcutout}
% \begin{macro}{\c@twb}
% A shaped cutout where the user defines the shape. \\
% \verb?\begin{shapedcutout}?\marg{numtop}\marg{numcut}\marg{shapespec} \\
% where \meta{numtop} is the number of full lines above the window,
% \meta{numcut} is the number of lines to be cut (giving the height
% of the window) and
% \meta{shapespec} is the user's specification of the shape of the
% surroundings of the cutout. This is in the form of a comma-separated
% list of either the pairs of widths of the left and right texts of a centered
% cutout or the widths of the left or right texts of an open cutout.
%
% \cs{c@twb} holds arg 3 (\meta{shapespec}), the user's parspec.
%
%  The code is very similar to that for the |cutout| environment.
%    \begin{macrocode}
\newenvironment{shapedcutout}[3]{%
  \cutfuzz
  \c@twtoplines=#1\relax
  \c@twwinlines=#2\relax
  \edef\c@twb{#3}%       user's parspec
%    \end{macrocode}
% Generate the top lines portion of the parspec followed by the cutout
% portion.
%    \begin{macrocode}
  \c@twmaketopoddspec
  \c@twbuildoddspec{#3}
%    \end{macrocode}
% Continue like the |cutout| code.
%    \begin{macrocode}
  \c@twtoplines=#1\relax
  \c@twwinlines=#2\relax
  \c@twcalcshift \vskip-\c@twvsilg
  \setbox\c@twrawtext=\vbox\bgroup
%    \end{macrocode}
% \cs{c@twcnt} is the total number of parshape lines; \cs{c@twtoka} is the
% spec for the top lines; \cs{c@twtokb} is the spec for the cutout lines;
% and \verb?0pt \hsize? is the spec for the remainder of the paragraph.
%    \begin{macrocode}
  \parshape=\c@twcnt \the\c@twtoka \the\c@twtokb 0pt \hsize}%
%    \end{macrocode}
% \end{macro}
% The code for the end of the environment, where most of the work is done.
% It is similar to the code for the end of the |cutout| environment.
%    \begin{macrocode}
 {\egroup
  \parshape=0
  \c@twcalcilg
  \ifnum\c@twtoplines>\z@
    \setbox\c@twfinaltext=\vsplit\c@twrawtext to\c@twtoplines\baselineskip
  \fi
  \c@twtopht=\c@twwinlines\baselineskip
  \ifnum\c@twl@c=\z@ % center
    \c@twtopht=2\c@twtopht
  \fi
  \setbox\c@twholdwin=\vsplit\c@twrawtext to\c@twtopht
  \ifnum\c@twl@c=\z@%    center
    \c@twcompoddctr{\c@twholdwin}{\c@twwindow}%
  \else% open left or right
    \c@twcompoddlftrt{\c@twholdwin}{\c@twwindow}%
  \fi
  \setbox\c@twfinaltext=
    \vbox{\ifnum\c@twtoplines>\z@\unvbox\c@twfinaltext\vskip\c@twvsilg\fi
    \unvbox\c@twwindow%
    \vskip-\c@twvsilg\unvbox\c@twrawtext}%
  \box\c@twfinaltext}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\c@twmaketopoddspec}
%  Make up the easy part of the odd \cs{parshape} specification;
% total number \cs{c@twcnt} and the toplines spec (\cs{c@twtoka}).
%    \begin{macrocode}
\newcommand*{\c@twmaketopoddspec}{%
  \c@twcnt=\c@twwinlines
  \ifnum\c@twl@c=\z@
    \multiply \c@twcnt by \tw@
  \fi
  \advance\c@twcnt by \c@twtoplines \advance\c@twcnt by \@ne
%% \c@twcnt is total of toplines + 2(window lines) + 1
  \c@twtoka={}%
  \ifnum\c@twtoplines>\z@
    \loop\c@twtoka=\expandafter{\the\c@twtoka 0pt \hsize}%
      \advance\c@twtoplines -1\relax
      \ifnum\c@twtoplines>\z@\repeat
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c@twaddtospec}
% Adds a `zero-indented line' to a parshape spec being assembled in
% \cs{c@twtokb}.
%    \begin{macrocode}
\newcommand*{\c@twaddtospec}[1]{%
  \c@twtokb=\c@twxpf{\the\c@twtokb 0pt #1 }}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\c@twbuildoddspec}
% \begin{macro}{\c@twxpf}
% \cs{c@twbuildoddspec}\marg{commalist} builds up the parshape spec for
% the odd cutout lines from the comma-separated list of lengths
% in \meta{commalist}.
%
% \cs{c@twxpf} is a shorthand for \cs{expandafter}
% to try and make the code shorter to read.
% \begin{macro}{\c@twlspec}
% \cs{c@twlspec} is used as a temporary variable when iterating over
% a comma-separated list.
% \end{macro}
%
%    \begin{macrocode}
\let\c@twxpf\expandafter
\newcommand*{\c@twbuildoddspec}[1]{%
  \c@twtokb={}%
  \@for\c@twlspec:=#1\do{%
    \c@twxpf\c@twxpf\c@twxpf\c@twaddtospec\c@twxpf{\c@twlspec}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twcompoddctr}
% \begin{macro}{\c@twrounds}
% Compose the lines of an odd shaped center cutout.
%
% We go through the user's shape list an item at a time but we need to
% collect pairs of items. The \cs{c@twrounds} variable is for managing the
% pairing. \cs{c@twfirst} is a flag for positioning the \cs{picinwindow} in
% the first line of the cutout.
%    \begin{macrocode}
\newcommand*{\c@twcompoddctr}[2]{%
  \def\c@twrounds{1}%
  \def\c@twfirst{1}%
  \@for\c@twlspec:=\c@twb\do{%
    \ifnum\c@twrounds=1
      \setbox\c@twslicea=\vsplit#1 to\baselineskip % first of pair
      \c@twprune{\c@twslicea}{\c@twlspec}%
      \def\c@twrounds{2}%
    \else
      \setbox\c@twsliceb=\vsplit#1 to\baselineskip % second of pair
      \c@twprune{\c@twsliceb}{\c@twlspec}%
      \ifnum\c@twfirst=1
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea\hfil\picinwindow\hfil\box\c@twsliceb}}%
        \def\c@twfirst{2}%
      \else
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea\hfil\box\c@twsliceb}}%
      \fi
      \def\c@twrounds{1}%
    \fi}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\c@twcompoddlftrt}
% Compose the open (left or right) lines of an odd shaped cutout.
%    \begin{macrocode}
\newcommand*{\c@twcompoddlftrt}[2]{%
  \def\c@twfirst{1}%
  \@for\c@twlspec:=\c@twb\do{%
    \setbox\c@twslicea=\vsplit#1 to\baselineskip % get a line
    \c@twprune{\c@twslicea}{\c@twlspec}%
    \ifnum\c@twl@c=\m@ne%   open left, text at right
      \ifnum\c@twfirst=1
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\mbox{}\hfil\picinwindow\hfil\box\c@twslicea}}%
        \def\c@twfirst{2}%
      \else
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\mbox{}\hfil\box\c@twslicea}}%
      \fi
    \else
      \ifnum\c@twl@c=\@ne%  open right, text at left
        \ifnum\c@twfirst=1
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea\hfil\picinwindow\hfil}}%
        \def\c@twfirst{2}%
      \else
        \setbox#2=\vbox{\unvbox#2\hbox
        to\hsize{\box\c@twslicea\hfil}}%
      \fi
    \fi
  \fi}}
%    \end{macrocode}
% \end{macro}
%
%
%
%
%    The end of this package.
%    \begin{macrocode}
%</pkg>
%    \end{macrocode}
%
%
%
%
% \Finale
% \PrintIndex
%
\endinput