summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/rjlparshap
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/rjlparshap
Initial commit
Diffstat (limited to 'macros/latex/contrib/rjlparshap')
-rw-r--r--macros/latex/contrib/rjlparshap/README50
-rw-r--r--macros/latex/contrib/rjlparshap/rjlpshap.dtx699
-rw-r--r--macros/latex/contrib/rjlparshap/rjlpshap.ins55
-rw-r--r--macros/latex/contrib/rjlparshap/rjlpshap.pdfbin0 -> 126335 bytes
4 files changed, 804 insertions, 0 deletions
diff --git a/macros/latex/contrib/rjlparshap/README b/macros/latex/contrib/rjlparshap/README
new file mode 100644
index 0000000000..c834e66328
--- /dev/null
+++ b/macros/latex/contrib/rjlparshap/README
@@ -0,0 +1,50 @@
+
+Copyright (C) 2004 by Robert J Lee <latex@rjlee.homelinux.org>
+--------------------------------------------------------------
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.2
+of this license or (at your option) any later version.
+The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.2 or later is part of all distributions of LaTeX
+version 1999/12/01 or later.
+
+
+
+Parshape macros for LaTeX2e
+---------------------------
+
+Provides a front-end to the standard TeX \parshape macro. Allows
+length registers to be reused, and \parshape commands to be generated
+using loops and other TeX and LaTeX constructs.
+
+
+Example usage:
+
+\newlength{\len}
+
+\begin{parshapecollect}
+ \setlength{\len}{1em}
+ \parshapelenout{\len} \parshapelenout{15em}
+ \addtolength{\len}{6em}
+ \parshapelenout{\len} \parshapelenout{9em}
+ \addtolength{\len}{1em}
+ \parshapelenout{0em} \parshapelenout{\len}
+\end{parshapecollect}
+\texttt{The quick brown fox jumps over the lazy dog.}
+
+
+Produces (assuming a tt font with 1em per character):
+
+ The quick brown
+ fox jumps
+over the
+lazy dog
+
+
+
+Commands are also available to process arrays of lengths in various
+different ways; see PDF documentation for details. \ No newline at end of file
diff --git a/macros/latex/contrib/rjlparshap/rjlpshap.dtx b/macros/latex/contrib/rjlparshap/rjlpshap.dtx
new file mode 100644
index 0000000000..6857a8813d
--- /dev/null
+++ b/macros/latex/contrib/rjlparshap/rjlpshap.dtx
@@ -0,0 +1,699 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2004 by Robert J Lee <latex@rjlee.homelinux.org>
+% --------------------------------------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.2
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.2 or later is part of all distributions of LaTeX
+% version 1999/12/01 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{rjlpshap.dtx}
+%</driver>
+%<package> \NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package> \ProvidesPackage{rjlpshap}
+%<*package>
+[2004/11/05 v1.0 .dtx rjlpshap file]
+%</package>
+%
+%<*driver>
+\documentclass{ltxdoc}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\usepackage{lipsum}
+\begin{document}
+\DocInput{rjlpshap.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{0}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \changes{v1.0}{2004/11/05}{Initial version}
+%
+% \GetFileInfo{rjlpshap.dtx}
+%
+% \DoNotIndex{\newcommand,\newenvironment}
+%
+%
+% \title{The \textsf{rjlpshap} class\thanks{This document
+% corresponds to \textsf{rjlpshap}~\fileversion, dated \filedate.}}
+% \author{Robert J Lee \\ \texttt{latex@rjlee.homelinux.org}}
+%
+% \maketitle
+%
+% \section{Introduction}
+%
+% This package provides low-level helper macros and environments. It
+% is intended for authors of \LaTeX\ packages, who wish to
+% programmatically change the shape of paragraphs. It overcomes several
+% difficulties with \TeX's \texttt{$\backslash$parshape} register:
+%
+% \begin{enumerate}
+% \item It is not possible to re-use a length register when issuing a
+% \texttt{$\backslash$parshape} command; this makes it difficult to
+% calculate the shape of a paragraph in \LaTeX\ using some
+% algorithms that re-use one or more variables (registers).
+% \item The number of lines must be known \textit{before} the lengths
+% of each line, which can lead to difficult calculations.
+% \item The format of the \texttt{$\backslash$parshape} command is
+% very strict and evaluated early on by \TeX, and so it doesn't
+% easily allow for parameter-replacement, making it difficult to use
+% any calculations at all.
+% \end{enumerate}
+%
+% It differs from the \texttt{shapepar} package, in that it provides
+% no actual calculations for paragraph shapes. Instead, it provides a
+% framework by which paragraph shapes can be calculated in a single
+% run of the document by the author (or package writer).
+%
+% The package provides both environments and commands by which the
+% author can accumulate any number of lengths and then use them in a
+% \texttt{$\backslash$parshape} command injected into the document,
+% without the need to re-run \LaTeX.
+%
+% \pagebreak[4]
+% \section{Usage}
+%
+% There are two modes of operation: environment mode and command
+% mode. Environment mode has the advantage that it does not
+% require the number of lengths to be known in advance, while command
+% mode provides various options for passing pre-calculated lengths.
+%
+% \subsection{Environment Mode}
+%
+% Environment mode uses a single environment,
+% \texttt{parshapecollect}, which starts and ends before the paragraph
+% of text. The contents of the environment are a \LaTeX\ program,
+% supplied by the user, that calculates the lengths of each line.
+%
+% \DescribeEnv{parshapecollect} The \texttt{parshapecollect}
+% environment goes at the start of a paragraph, and the entire
+% environment defines a single \texttt{$\backslash$parshape} command.
+% Any even number of lengths are collected, and at the end of the
+% environment, the \texttt{$\backslash$parshape} command is
+% automatically generated and inserted into the document.
+%
+% \DescribeMacro{\parshapelenout} This macro takes one mandatory
+% parameter, which is the next length in the
+% \texttt{$\backslash$parshape} command. Note that the parameter is
+% expanded: the value of the length at the time
+% \texttt{$\backslash$parshapelenout} is called is the value which is
+% used --- this means the same length command can be re-used
+% repeatedly. The value may be a length register, and the same
+% register may be re-used after changing its contents, for example:
+%
+% \begin{quote}
+% \begin{verbatim}
+% \newlength{\foo}
+% \begin{parshapecollect}
+% \setlength{\foo}{1in}\parshapelenout{\foo}
+% \setlength{\foo}{3in}\parshapelenout{\foo}
+% \setlength{\foo}{0.5in}\parshapelenout{\foo}
+% \setlength{\foo}{3.5in}\parshapelenout{\foo}
+% \setlength{\foo}{0in}\parshapelenout{\foo}
+% \setlength{\foo}{4in}\parshapelenout{\foo}
+% \end{parshapecollect}
+% \lipsum[1]
+% \end{verbatim}
+% Produces:
+%
+% \parshape 3 1in 4in 0.5in 4.5in 0in 5in
+% \lipsum[1]
+% \end{quote}
+
+%
+% \DescribeMacro{\parshapearrlenout} This macro is the same as
+% \texttt{$\backslash$parshapelenout}, but allows the programmer to
+% pass the length as the value from an array (see the
+% \texttt{arrayjob} package). This is intended for situations where
+% pre-calculated lengths are to be used alongside calculations; to
+% pass an array of lengths the various command modes may be
+% easier. The parameters to the macro are the name of the array and
+% the name of a counter containing the index.
+%
+% For example, the above paragraph could have been created
+% using:
+% \begin{quote}
+% \begin{verbatim}
+% \newarray{foo} \newcounter{ctr}
+% \begin{parshapecollect}
+% \foo(1)={1in}\setcounter{ctr}{1}\parshapearrlenout{foo}{ctr}
+% \foo(2)={3in}\setcounter{ctr}{2}\parshapearrlenout{foo}{ctr}
+% \foo(3)={0.5in}\setcounter{ctr}{3}\parshapearrlenout{foo}{ctr}
+% \foo(1)={3.5in}\setcounter{ctr}{1}\parshapearrlenout{foo}{ctr}
+% \foo(2)={0in}\setcounter{ctr}{2}\parshapearrlenout{foo}{ctr}
+% \foo(2)={4in}\parshapearrlenout{foo}{ctr}
+% \end{parshapecollect}
+% \lipsum[1]
+% \end{verbatim}
+% \end{quote}
+%
+% \subsection{Command Mode}
+
+% Command mode enables the author to use calculated shapes by
+% outputting the $\backslash$parshape command as a single operation at
+% the end of the calculation.
+
+% \DescribeMacro{\parshapeary}
+% This macro takes one parameter, being the name of an array. The
+% contents of the array are simply expanded and passed directly to
+% \texttt{$\backslash$parshape} --- the first parameter is the number
+% of lines, then for each line the left margin and line width are
+% supplied in subsequent elements.
+%
+% For example:
+% \begin{quote}
+% \begin{verbatim}
+% \newcommand{\ltest}{50pt}
+% \newlength{\test}\setlength{\test}{300pt}
+% \newarray{sizes}\readarray{sizes}{2&0em&\the\test&\ltest&\test}
+% \parshapeary{sizes}
+% \lipsum[1]
+% \end{verbatim}
+% produces:
+%
+% \parshape 2 0em 300pt 50pt 300pt \lipsum[1]
+% \end{quote}
+%
+%
+% \DescribeMacro{\parshapearray} This macro takes two parameters. The
+% first is also the name of an array. The only difference to
+% \texttt{$\backslash$parshapeary} is that instead of passing the
+% width of the line, the width of the right margin is passed
+% instead. This means the macro needs to know the width of the line.
+%
+% The second parameter is the length of the line. This is usually
+% $\backslash$columnwidth, passing any other value will effectively
+% change the right margin. ($\backslash$columnwidth is often equal to
+% $\backslash$textwidth, but in multi-column mode,
+% $\backslash$columnwidth is more likely to be correct, unless you
+% want to overstrike the text with text in another column --- so
+% $\backslash$columnwidth is the recommended length to use).
+%
+% In a similar vein to the previous example:
+% \begin{quote}
+% \begin{verbatim}
+%\newcommand{\ltest}{50pt}
+%\newlength{\test}\setlength{\test}{75pt}
+%\newlength{\cwidth}\setlength{\cwidth}{\columnwidth}
+%\addtolength{\cwidth}{-50pt}
+%
+%\newarray{sizes}\readarray{sizes}{2&0em&\the\test&\ltest&\test}
+%\parshapearray{sizes}{\cwidth}
+%\lipsum[1]
+%
+% \end{verbatim}
+% which produces:
+%
+% \parshape 2 0.0pt
+%220.0pt
+%50.0pt
+%170.0pt
+% \lipsum[1]
+% \end{quote}
+%
+% \DescribeMacro{\Parshapearray}
+% This macro also takes two parameters, and is used to combine
+% multiple shapes, where the width of the paragraph is not consistent
+% throughout the paragraph.
+%
+% The first parameter is the name of an array, in the same format as
+% the first parameter to \texttt{$\backslash$parshapeary}.
+%
+% The second parameter is the name of a second array. The first
+% element is the number of lines in this second array, and subsequent
+% elements are the widths of lines (excluding margins) in that array
+% --- starting from the first line. As usual, if an insufficient
+% number of lines are passed, the last line will be re-used.
+%
+% The actual width of a line will be the total width excluding margins
+% (as per the second parameter), minus the left margin (taken from the
+% first parameter, even indexes), minus the right margin (as per the
+% first parameter, odd indexes).
+%
+% In this way, it is possible to set a shaped paragraph that allows
+% for non-straight margins or non-rectangular paper --- for example, to
+% typeset a list item in such a way as to allow for a cut-out on the
+% page.
+%
+% For a larger example, consider that the paper has a sloped shape
+% that extends 1em wider for every line for the first 15 lines
+% only. The author wishes to set a text in an quadrilateral, with
+% margins offset $\frac{1}{8}\verb!"!$ to the right for each line, but
+% extending equally to follow the width of the paper.
+
+% \begin{quote}
+% \begin{verbatim}
+% \newarray{quad}
+% \readarray{quad}{17 & 0.000in & 2.000in & 0.125in & 1.875in &
+% 0.250in & 1.750in & 0.375in & 1.625in & 0.500in & 1.500in &
+% 0.625in & 1.375in & 0.750in & 1.250in & 0.875in & 1.125in &
+% 1.000in & 1.000in & 1.125in & 0.875in & 1.250in & 0.750in &
+% 1.375in & 0.675in & 1.500in & 0.500in & 1.625in & 0.375in &
+% 1.750in & 0.250in & 1.875in & 0.125in & 2.000in & 0.000in}
+% \newarray{papershape}
+% \readarray{papershape}{15& 25em & 26em & 27em & 28em & 29em & 30em & 31em
+% & 32em & 33em & 34em & 35em & 36em & 37em & 38em & 39em}
+% \Parshapearray{quad}{papershape} \lipsum[1]
+% \end{verbatim}
+% Produces:
+%
+% \parshape 17
+% 0.0pt
+% 105.46039pt
+% 9.03374pt
+% 115.46042pt
+% 18.06749pt
+% 125.46043pt
+% 27.10124pt
+% 135.46045pt
+% 36.135pt
+% 145.46045pt
+% 45.16875pt
+% 155.46046pt
+% 54.2025pt
+% 165.46048pt
+% 63.23624pt
+% 175.46051pt
+% 72.26999pt
+% 185.46053pt
+% 81.30374pt
+% 195.46054pt
+% 90.3375pt
+% 205.46054pt
+% 99.37125pt
+% 211.84685pt
+% 108.405pt
+% 225.46057pt
+% 117.43874pt
+% 235.4606pt
+% 126.47249pt
+% 245.46062pt
+% 135.50624pt
+% 235.4606pt
+% 144.54pt
+% 235.46059pt \lipsum[1]
+% \end{quote}
+%
+
+
+% \section{Prerequisites}
+
+% This package requires the \texttt{arrayjob} package from
+% CTAN\footnote{http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=arrayjob}. Arrays
+% are used as a convenient mechanism to pass values to functions,
+% although they may not be used in environment mode.
+
+% \section{Limitations and Possible Improvements}
+
+% \begin{itemize}
+% \item Usage of this package can be slow, because two temporary files
+% are used for each $\backslash$parshape. Theoretically, only one
+% should be needed and so it should be possible to improve this.
+% \item There is no support for combining arrays, other than to change
+% the paper size itself. Extra commands could be provided to
+% calculate the intersection of two cutouts, or to add margins
+% together.
+% \item In a future version, it may be possible to avoid temporary
+% files completely by using token registers, or
+% $\backslash$aftergroup, with some form of string processing.
+% \end{itemize}
+
+% \section{Package Name}
+
+% The somewhat obscure name ``rjlpshap'' was chosen following the
+% guidelines given in \textit{\LaTeXe\ for Class and Package
+% Writers}\footnote{\texttt{http://www.tex.ac.uk/tex-archive/macros/latex/doc/clsguide.pdf}}~(section~2.7.3,
+% ``Make it Portable''). The common prefix used by these packages
+% is~''rjl--'', which was chosen as the author's initials as he is
+% not writing these packages as part of any organisation.
+
+% The postfix of ``--pshap'' was chosen as a contraction of
+% ``parshape'', the \TeX\ command to which this package is a front
+% end. The name was contracted due to the 5-character length
+% restriction. It was also considered that that the obvious package
+% name of ``parshape'' would be best avoided to avoid confusion with
+% the existing shapepar\footnote{\texttt{http://www.ctan.org/tex-archive/macros/latex/contrib/shapepar/}} package, and also because parshape is a
+% standard \TeX\ command --- the only requirement that exists is to
+% avoid the name of a standard package, but avoiding the name of a
+% standard macro also seems like a good idea as this leaves the name
+% free for use as a standard package name in the future.
+
+% \section{Other References}
+
+% The following references were essential in producing this package:
+
+% \begin{itemize}
+% \item The \TeX Book\footnote{ISBN:~978-0201134483}
+% \item \TeX Live package
+% contributions\footnote{http://tug.org/texlive/pkgcontrib.html}
+% \item TDS Guidelines\footnote{http://dante.ctan.org/TDS-guidelines.html}
+% \end{itemize}
+
+% \StopEventually{\PrintChanges\PrintIndex}
+%
+% \section{Implementation}
+%
+% Arrayjob: we need to pass arrays of lengths and length-commands,
+% so build on the established array handling functionality.
+% \begin{macrocode}
+\RequirePackage{arrayjob}
+% \end{macrocode}
+
+% Forloop: we need to iterate over the arrays that are passed in
+% \begin{macrocode}
+\RequirePackage{forloop}
+% \end{macrocode}
+% Internal commands use @ as a letter, not a special character, so
+% switch catcodes
+% \begin{macrocode}
+\makeatletter
+% \end{macrocode}
+
+
+% \subsection{Environment mode}
+
+% \begin{environment}{parshapecollect}
+% Environment to handle writing the file, cleaning up etc.
+%
+% Note the importance of the % at the end of each line here: we're
+% in horizontal mode so any space characters get expanded and added
+% into the start of the paragraph. Any spaces here are output before
+% $\backslash$parshape itself, and so will be visible in the output
+% page. The $\backslash$ignorespaces is a last line of defence
+% against any extra spaces inadvertently introduced by the user.
+%
+% \begin{macrocode}
+\newenvironment{parshapecollect}{%
+ \immediate\openout\rjlpshap@writer=\jobname.parshape%
+ \setcounter{rjlpshap@linecount}{0}%
+ \setboolean{rjlpshap@isodd}{false}%
+ \ignorespaces
+}{%
+ \immediate\closeout\rjlpshap@writer%
+% \end{macrocode}
+% Because the environment forms a group, we need to use aftergroup to
+% delay the $\backslash$parshape command. Otherwise the group will end first and
+% $\backslash$parshape will be discarded.
+% \begin{macrocode}
+ \rjlpshap@doparshape%
+ \aftergroup\input\aftergroup{\aftergroup\jobname\aftergroup%
+ .\aftergroup%
+ p\aftergroup%
+ a\aftergroup%
+ r\aftergroup%
+ s\aftergroup%
+ h\aftergroup%
+ a\aftergroup%
+ p\aftergroup%
+ e\aftergroup%
+ t\aftergroup%
+ m\aftergroup%
+ p\aftergroup}\ignorespaces
+}
+% \end{macrocode}
+% \end{environment}
+
+% \begin{macro}{\rjlpshap@doparshape}
+% Internal method to handle the final processing of the built
+% up $\backslash$parshape command. The lengths have been written to
+% the first temporary file, so write the entire $\backslash$parshape
+% command to the second one, ready to be input.
+% \begin{macrocode}
+\newcommand{\rjlpshap@doparshape}{%
+ \immediate\openout\rjlpshap@finalwriter=\jobname.parshapetmp%
+ \immediate\write\rjlpshap@finalwriter{\noexpand\parshape \arabic{rjlpshap@linecount}}%
+ \openin\rjlpshap@reader=\jobname.parshape%
+ \setboolean{rjlpshap@loop}{true}%
+ \whiledo{\boolean{rjlpshap@loop}}{%
+ \read\rjlpshap@reader to\rjlpshap@temp%
+% NB: \ifeof matches \loop...\repeat
+ \ifeof\rjlpshap@reader%
+ \setboolean{rjlpshap@loop}{false}%
+ \else
+ \immediate\write\rjlpshap@finalwriter{\rjlpshap@temp }%
+ \fi
+ }%
+ \immediate\closeout\rjlpshap@finalwriter%
+ \immediate\closein\rjlpshap@reader%
+ \let\rjlpshap@temp=\relax%
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\parshapelenout}
+% Used inside a parshapecollect environment, writes length \#1 to
+% the $\backslash$parshape command file. (If used anywhere else,
+% it'll just write to the console since the file will not be open).
+% \begin{macrocode}
+\newcommand{\parshapelenout}[1]{%
+ \setlength{\rjlpshap@tempwidth}{#1}%
+ \immediate\write\rjlpshap@writer{\the\rjlpshap@tempwidth}%
+ \ifthenelse{\boolean{rjlpshap@isodd}}{%
+ \setboolean{rjlpshap@isodd}{false}%
+ }{%
+ \stepcounter{rjlpshap@linecount}%
+ \setboolean{rjlpshap@isodd}{true}%
+ }%
+ \ignorespaces
+}
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\parshapearrlenout}
+% Used inside a parshapecollect environment, writes a length to the
+% $\backslash$parshape command file. As $\backslash$parshapelenout,
+% except that the element is passed as the member of an array.
+%
+% Length is taken from array with name \#1, element at index \#2
+% \begin{macrocode}
+\newcommand{\parshapearrlenout}[2]{%
+ \testarray{#1}(\arabic{#2})%
+ \parshapelenout{\temp@macro}%
+ \ignorespaces
+}
+% \end{macrocode}
+% \end{macro}
+
+% \subsection{Command Mode}
+
+% \begin{macro}{\parshapeary}
+% As $\backslash$parshape, but takes one argument being an array
+% name defined in arrayjob form. The array contains the arguments,
+% starting with the count at index 1, then one length per array
+% element.
+% \begin{macrocode}
+\newcommand{\parshapeary}[1]{%
+ \testarray{#1}(1)%
+ \edef\rjlpshap@max{\temp@macro}%
+ \begin{parshapecollect}%
+ \forloop{rjlpshap@ctr}{1}{\not \value{rjlpshap@ctr} > \rjlpshap@max }{%
+ \setcounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ \addtocounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ \parshapearrlenout{#1}{rjlpshap@ctr2}%
+ \stepcounter{rjlpshap@ctr2}%
+ \parshapearrlenout{#1}{rjlpshap@ctr2}%
+ }%
+ \end{parshapecollect}%
+ \typeout{parshapeary end}%
+ \ignorespaces
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\parshapearray}
+% As $\backslash$parshapeary, but the second parameter is the name
+% of a single-parameter macro taking a number and returning the
+% width of the line on that line
+% \begin{macrocode}
+\newcommand{\parshapearray}[2]{%
+ \begin{parshapecollect}%
+ \testarray{#1}(1)%
+ \edef\rjlpshap@max{\temp@macro}%
+ \forloop{rjlpshap@ctr}{1}{\not \value{rjlpshap@ctr} > \rjlpshap@max }{%
+ \setcounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ \addtocounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ \edef\rjlpshap@pos{\arabic{rjlpshap@ctr2}}%
+ \testarray{#1}(\rjlpshap@pos)%
+ \setlength{\rjlpshap@tempwidth}{\temp@macro}%
+ \setlength{\rjlpshap@templinewidth}{#2}%
+ \addtolength{\rjlpshap@templinewidth}{-1\rjlpshap@tempwidth}%
+ \parshapelenout{\rjlpshap@tempwidth}%
+ \stepcounter{rjlpshap@ctr2}%
+ \edef\rjlpshap@pos{\arabic{rjlpshap@ctr2}}%
+ \testarray{#1}(\rjlpshap@pos)%
+ \setlength{\rjlpshap@tempwidth}{\temp@macro}%
+ \addtolength{\rjlpshap@templinewidth}{-1\rjlpshap@tempwidth}%
+ \parshapelenout{\rjlpshap@templinewidth}%
+ }%
+ \end{parshapecollect}%
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\Parshapearray}
+% First parameter is as $\backslash$parshapea\{r,rra\}y, but each pair
+% is left and right margin rather than left margin and text width,
+% while the second tracks the page width.
+%
+% \textit{i.e.}
+%
+% The first parameter (an array) is the shape of the paragraph
+% relative to the page.
+% \begin{itemize}
+% \item first element is the number of pairs of lengths in the array
+% \item subsequent arguments are pairs of lengths, left margin width then
+% right margin width.
+% \end{itemize}
+%
+% The second parameter is the overall text width. This is given in the
+% following format:
+% \begin{itemize}
+% \item first element is the number lengths
+% \item subsequent elements are one width per parameter
+% \end{itemize}
+% \begin{macrocode}
+\newcommand{\Parshapearray}[2]{%
+ \testarray{#1}(1)\edef\rjlpshap@maxA{\temp@macro}%
+ \testarray{#2}(1)\edef\rjlpshap@maxB{\temp@macro}%
+ \ifthenelse{\rjlpshap@maxA > \rjlpshap@maxB} {\edef\rjlpshap@max{\rjlpshap@maxA}}{\edef\rjlpshap@max{\rjlpshap@maxB}}%
+ \begin{parshapecollect}%
+ \forloop{rjlpshap@ctr}{1}{\not \value{rjlpshap@ctr} > \rjlpshap@max}{%
+ \ifthenelse{\value{rjlpshap@ctr} > \rjlpshap@maxA}{%
+ \setcounter{rjlpshap@ctr2}{\rjlpshap@maxA}%
+ \addtocounter{rjlpshap@ctr2}{\rjlpshap@maxA}%
+ }{%
+ \setcounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ \addtocounter{rjlpshap@ctr2}{\value{rjlpshap@ctr}}%
+ }%
+% \end{macrocode}
+% left margin from \#1:
+% \begin{macrocode}
+ \parshapearrlenout{#1}{rjlpshap@ctr2}%
+% \end{macrocode}
+% get the line width
+% \begin{macrocode}
+ \ifthenelse{\value{rjlpshap@ctr} > \rjlpshap@maxB}{%
+ \edef\rjlpshap@pos{\rjlpshap@maxB}%
+ \setcounter{rjlpshap@ctr3}{\rjlpshap@maxB}%
+ \typeout{A pos=\rjlpshap@pos\space of \rjlpshap@maxB}%
+ \testarray{#2}(\arabic{rjlpshap@ctr3})%
+ \typeout{temp=\temp@macro}%
+ \setlength{\rjlpshap@templinewidth}{\temp@macro}%
+ }{%
+ \stepcounter{rjlpshap@ctr}%
+ \edef\rjlpshap@pos{\arabic{rjlpshap@ctr}}%
+ \typeout{B pos=\rjlpshap@pos}%
+ \addtocounter{rjlpshap@ctr}{-1}%
+ \testarray{#2}(\rjlpshap@pos)%
+ \setlength{\rjlpshap@templinewidth}{\temp@macro}%
+ }%
+ \typeout{width=\the\rjlpshap@templinewidth}%
+% \end{macrocode}
+% subtract the left margin from the line width
+% \begin{macrocode}
+ \addtolength{\rjlpshap@templinewidth}{-1\rjlpshap@tempwidth}%
+% \end{macrocode}
+% subtract the right margin from the line width
+% \begin{macrocode}
+ \stepcounter{rjlpshap@ctr2}%
+ \edef\rjlpshap@pos{\arabic{rjlpshap@ctr2}}%
+ \testarray{#1}(\rjlpshap@pos)%
+ \setlength{\rjlpshap@tempwidth}{\temp@macro}%
+ \addtolength{\rjlpshap@templinewidth}{-1\rjlpshap@tempwidth}%
+ \parshapelenout{\rjlpshap@templinewidth}%
+ }%
+ \end{parshapecollect}%
+}
+% \end{macrocode}
+% \end{macro}
+
+% \subsection{Internal Definitions}
+
+% rjlpshap@ctr: outermost loop counter:
+% \begin{macrocode}
+\newcounter{rjlpshap@ctr}
+% \end{macrocode}
+
+% rjlpshap@ctr2: used for index calculations internally:
+% \begin{macrocode}
+\newcounter{rjlpshap@ctr2}
+% \end{macrocode}
+
+% rjlpshap@ctr3: used for index calculations internally:
+% \begin{macrocode}
+\newcounter{rjlpshap@ctr3}
+% \end{macrocode}
+
+% rjlpshap@tempwidth: used as a register to read widths from arrays,
+% and for calculations
+% \begin{macrocode}
+\newlength{\rjlpshap@tempwidth}
+% \end{macrocode}
+
+% rjlpshap@templinewidth: used as a register to calculate the line
+% width when subtracting margins:
+% \begin{macrocode}
+\newlength{\rjlpshap@templinewidth}
+% \end{macrocode}
+
+% boolean used for breaking out of loops
+% \begin{macrocode}
+\newboolean{rjlpshap@loop}
+% \end{macrocode}
+
+% boolean used to track if the number of lengths output is odd or even
+% \begin{macrocode}
+\newboolean{rjlpshap@isodd}
+% \end{macrocode}
+
+% Filehandles needed for reading and writing temporary files
+% \begin{macrocode}
+\newwrite\rjlpshap@writer % holds \parshape lengths
+\newwrite\rjlpshap@finalwriter % holds entire \parshape command
+\newread\rjlpshap@reader % used to read writer to transfer to finalwriter
+% \end{macrocode}
+
+% rjlpshap@linecount: counts the number of lines read in the environment
+% \begin{macrocode}
+\newcounter{rjlpshap@linecount}
+% \end{macrocode}
+
+% Finally, undo the effect of $\backslash$makeatletter, and make @ be
+% a special character again.
+% \begin{macrocode}
+\makeatother
+% \end{macrocode}
+
+% \Finale
+\endinput
diff --git a/macros/latex/contrib/rjlparshap/rjlpshap.ins b/macros/latex/contrib/rjlparshap/rjlpshap.ins
new file mode 100644
index 0000000000..eb789359c1
--- /dev/null
+++ b/macros/latex/contrib/rjlparshap/rjlpshap.ins
@@ -0,0 +1,55 @@
+%%
+%% Copyright (C) 2004 by Robert J Lee <latex@rjlee.homelinux.org>
+%%
+%% This file may be distributed and/or modified under the conditions of
+%% the LaTeX Project Public License, either version 1.2 of this license
+%% or (at your option) any later version. The latest version of this
+%% license is in:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.2 or later is part of all distributions of LaTeX version
+%% 1999/12/01 or later.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/rjlpshap}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2004 by Robert J Lee <latex@rjlee.homelinux.org>
+
+This file may be distributed and/or modified under the conditions of
+the LaTeX Project Public License, either version 1.2 of this license
+or (at your option) any later version. The latest version of this
+license is in:
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.2 or later is part of all distributions of LaTeX version
+1999/12/01 or later.
+
+\endpreamble
+
+\generate{\file{rjlpshap.sty}{\from{rjlpshap.dtx}{package}}}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* rjlpshap.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file rjlpshap.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
diff --git a/macros/latex/contrib/rjlparshap/rjlpshap.pdf b/macros/latex/contrib/rjlparshap/rjlpshap.pdf
new file mode 100644
index 0000000000..5d36be052c
--- /dev/null
+++ b/macros/latex/contrib/rjlparshap/rjlpshap.pdf
Binary files differ