% magaz.sty  Ver 0.2   04-Sep-2003  "Magazine style"
% Copyright 1999, Donald Arseneau,   asnd@triumf.ca,  Vancouver, Canada
% This software is free to distribute, unaltered, and to use in any 
% application. It may be altered and incorporated in other software freely.
%
% This version is just a single tool from a larger body of tools I might
% try to implement if I ever have the spare time.  I'm writing this part
% now [1999] in response to a request on comp.text.tex.
%
% Yes Special formatting for first line of text in a paragraph
% No  Special formatting for for first n lines (allow each different)
% No  Also for first character (drop caps) (working together)
% No  "Continued on"/"continued from" markers
% No  wrapfig spanning columns
% No  wrapfig placed at fixed location on page
% NO! Piecing together fragments of gallies to fit page
%
% Instructions:
%
% The "\FirstLine" command takes one argument: Some text.
% 
% The first line of this text will be formatted according to
% "\FirstLineFont"; but if the text occupies less than a line, all 
% that text (and no more) will be affected by "\FirstLineFont".  
% The argument should be ordinary text, not lists and displayed 
% equations. Such things will give you a `Bad text' error.
% 
% This command is intended to be used in a replacement for a normal 
% sectioning command in a document class; "\paragraph" would be 
% appropriate.  In particular, this "\paragraph" (or whatever) should 
% insert vertical space and penalties etc., and probably "\noindent"
% at the start of the argument.  The document class should also define 
% "\FirstLineFont" appropriately as either a switch or a text-command; 
% as in "\renewcommand\FirstLineFont{\MakeUppercase}".  The defult 
% definition is "\providecommand\FirstLineFont{\scshape}".

\ProvidesPackage{magaz}[2003/09/04 v0.2]

\newcommand\FirstLine[1]{\begingroup
 % typeset text 3 times: 1) using all breaks to count segments; 2) with
 % a full first line and \FirstLineFont to get first line and remaining
 % segments; 3) Using current font, keeping only `remaining segments'
 % on a single line. 
 \setbox\z@\box\mz@firstbox \setbox\z@\box\mz@remains % void the global boxes
 \hbadness\maxdimen \hfuzz\maxdimen
 \setbox\@tempboxa\vbox{% 1) use all breaks
   \hsize\z@ \leftskip\z@skip \rightskip\z@skip \parfillskip\fill
   \parshape\z@ \pretolerance\m@ne \tolerance\@ne 
   \doublehyphendemerits\z@ \finalhyphendemerits\z@
   #1\global\mathchardef\mz@spf\spacefactor\@@par
   \global\mathchardef\mz@numl\prevgraf
 }% end vbox "1)"
 \setbox\@tempboxa\vbox{% 2) first line, plus other segments
   \parshape \tw@ \z@\hsize \z@\maxdimen 
   \doublehyphendemerits\z@ \finalhyphendemerits\z@
   \pretolerance\m@ne \parfillskip\fill
   {\FirstLineFont{#1}\@@par}%
   \ifnum\prevgraf>\tw@ % Bad argument: not simple text or too much text
     \mz@handlebad{#1}%
   \else
     \unskip\unkern\unpenalty \unskip\unkern\unpenalty
     \ifnum\prevgraf<\tw@ % All text fits on first line
       \setbox\z@\lastbox
       \global\setbox\mz@firstbox\hbox{\unhbox\z@\unskip}%
       \global\setbox\mz@remains\hbox{}%
     \else % 2 lines: text fills first line with some left over
       \setbox\z@\lastbox
       \ifvoid\z@ % could not grab last line 
         \mz@handlebad{#1}%
       \else
         \unskip\unkern\unpenalty \unskip\unkern\unpenalty
         \global\setbox\mz@firstbox\lastbox % 2a) break up "other segments"
         \hsize\z@ \leftskip\z@skip \rightskip\z@skip \parfillskip\fill
         \parshape\z@ \pretolerance\m@ne \tolerance\@ne 
         \noindent\nobreak % \nobreak because leftskip adds breakpoint
         \unhbox\z@\unskip\@@par % gives number of "extra segments"
         \@tempcnta\mz@numl \advance\@tempcnta-\prevgraf 
         \advance\@tempcnta\@ne % number of segs in 1st line plus 1
         \edef\@tempa{\the\@tempcnta\space}% 3) Collect "other segments"
         \@whilenum \@tempcnta>\@ne\do{% build \parshape lines
           \edef\@tempa{\@tempa \z@\z@}%
           \advance\@tempcnta\m@ne
         }%
         \parshape \@tempa \z@\maxdimen
         #1\@@par
         \unskip\unkern\unpenalty \unskip\unkern\unpenalty
         \global\setbox\mz@remains\lastbox
       \fi
     \fi
   \fi
 }% end vbox "2)"
 \endgroup
 \ifvoid\mz@firstbox #1% Error case: just output the text
 \else
   \noindent
   \unhbox\mz@firstbox\unskip\unskip\unpenalty\break
   \unhbox\mz@remains\unskip\unskip\unpenalty \spacefactor\mz@spf
 \fi
}

\newbox\mz@firstbox
\newbox\mz@remains

\providecommand\FirstLineFont{\scshape}

% In the future, I might allow some non-text material by using \vsplit
% as a fallback method of grabbing lines, and I might allow more or
% unusual text in the `remainders' by skipping the step of setting two
% lines (instead setting one first line plus many tiny lines all together).
% The following macro would then handle those cases as an error recovery
% mechanism.  Right now it just gives an error message and dumps out
% the text.

\def\mz@handlebad{\mz@error}
\def\mz@error#1{%
 \PackageError{magaz}{Bad text for \string\FirstLine\space ending\on@line}{}%
 \global\setbox\mz@remains\box\mz@firstbox % void first box
}
 
\endinput

Test file integrity:  ASCII 32-57, 58-126:  !"#$%&'()*+,-./0123456789
:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
