%% \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} % % % \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} % % \end{macrocode} % % % % % \Finale % \PrintIndex % \endinput