% magaz.sty Ver 0.4 24-Nov-2011 "Magazine style" % Copyright 1999-2011, Donald Arseneau, asnd@triumf.ca, Vancouver, Canada % This software may be freely used, transmitted, reproduced, or modified % provided that the copyright notice and this permission is retained. % % This version is just a single tool from a larger body of tools I am % unlikely to implement. I wrote this in 1999 in response to a request % on comp.text.tex. % % Features: % Yes Special formatting for first line of text in a paragraph % Not Special formatting for for first n lines (allow each different) % Not Also for first character (drop caps) (working together) % No "Continued on"/"continued from" markers (like varioref marks) % No wrapfig spanning columns % No wrapfig placed at fixed location on page % No Piecing together fragments of gallies to fit page (maybe flowfram) % % Instructions: % % \FirstLine{} % % The "\FirstLine" command takes one argument: Some text. % % The "\FirstLine" command is placed at the beginning of a paragraph, % and 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 full line of the paragraph, all that text (and no more) % will be affected by "\FirstLineFont". % % You should define "\FirstLineFont" appropriately as either a switch % or a text-command; as in "\renewcommand\FirstLineFont{\MakeUppercase}". % The defult definition performed in \pkg{magaz.sty} is % "\providecommand\FirstLineFont{\scshape}". % % The parameter for "\FirstLine" should be ordinary text, not containing % lists or displayed equations -- such things will give you a ``Bad text'' % error. If the parameter text ends with a space, that space will be % removed. A line break may sometimes be permitted after the parameter % text even if the ensuing text prohibits one (using "~"). Furthermore, % the text should be constant, or else the successive measurements made % internally will not be consistent, and the output may be corrupted % (with words missing or duplicated). Some subtle sources of inconstant % text are: % - Incrementing a counter (and printing the value). % - "\everypar" that executes once and is cleared. (This occurs after % section heads and inside list/quotation/center/etc. environments, % but those cases are handled, somewhat.) % - A "\FirstLineFont" that affects hyphenation (as "\texttt" or a % language setting will). % - Changing paragraph-layout parameters in "\FirstLineFont". % % Other deviations from simple text can give poor formatting. Here are some % `advanced' tips: % - Using "\FirstLine" in the middle of a paragraph will make a mess. % (It should be used to start a paragraph, or placed at the beginning % of one started with "\noindent". Using it after "\\" should also % work.) % - Multiple "\vspace" or "\\*" or "\\[]" will cause failure; % a single "\vspace" will be ignored. % - Although there is no corruption if used immediately after a % "\section" command (or similar) that suppresses indentation, % the paragraph will likely be indented anyway. The fix for % this (and similar problems) is to begin the paragraph with % "\noindent" before "\FirstLine". % - Using an inflexible "\parfillskip" might cause some highlighted % first-line text to be dragged down to the second line. (Providing % more text in the argument will usually solve this.) (If you % don't know about "\parfillskip" you probably don't have to worry.) % - A large font for "\FirstLineFont" may be too crowded with the % second line, and inserting "\vspace" will not help (this should % be improved) so you may need to resort to a "\strut", as with % "\renewcommand\FirstLineFont{\large\strut\MakeUppercase}" % % The "\FirstLine" system 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{\scshape\textcolor{blue}}". The % defult definition is "\providecommand\FirstLineFont{\scshape}". \ProvidesPackage{magaz}[2011/11/24 v0.4] \newcommand\FirstLine[1]{% \relax\if@inlabel\noindent\fi % produce any pending list item label \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 \setbox\@tempboxa\vbox{% 1) use all breaks \hbadness\maxdimen \hfuzz\maxdimen \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 %{\message{^^J^^J^^JText has \number\mz@numl\space segments:}\showhyphens{#1\unskip\unskip}}% }% end vbox "1)" \setbox\@tempboxa\vbox{% 2) first line, plus other segments \parshape \tw@ \z@\linewidth \z@\maxdimen \doublehyphendemerits\z@ \finalhyphendemerits\z@ %\linepenalty\z@ % note no \hbadness\maxdimen \hfuzz\maxdimen at this stage \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\unskip\unpenalty \unskip\unkern\unskip\unpenalty \ifnum\prevgraf<\tw@ % All text fits on first line \global\setbox\mz@firstbox\lastbox % Grab that line %{\message{Entire text fits: }\showhyphens{\unhcopy\mz@firstbox\unskip\unskip\unpenalty}}% \setbox\z@\hbox{\unhcopy\mz@firstbox}% \begingroup \advance\linewidth-0.4em\relax \expandafter\endgroup \ifdim\wd\z@>0.97\linewidth %\message{^^JHandle wide first line: \the\wd\z@\space vs \the\linewidth. }% \global\setbox\mz@firstbox\hbox to\wd\mz@firstbox{% \unhcopy\mz@firstbox\unskip\unskip\unpenalty}% remove \parfillskip \global\setbox\mz@remains\hbox{}% Trigger keeping of full wide line \fi % else \mz@remains remains void \else % 2 lines: text fills first line with some left over \setbox\z@\lastbox % remainders to \z@ \ifvoid\z@ % could not grab last line \mz@handlebad{#1}% \else \unskip\unkern\unskip\unpenalty \unskip\unkern\unskip\unpenalty \global\setbox\mz@firstbox\lastbox % grab first line % Note: counting segments in this first line will be wrong if the line % ended with a hyphenation. It could be possible to detect and adjust % for the resulting extra segment if it is deemed desirable to count the % first line directly. %{\message{First line is: }\showhyphens{\unhcopy\mz@firstbox\unskip}}% %{\message{Remaining segments are: }\showhyphens{\unhcopy\z@\unskip\unskip}}% % % 2a) break up "remaining segments": \hsize\z@ \hbadness\maxdimen \hfuzz\maxdimen \leftskip\z@skip \rightskip\z@skip \parfillskip\fill \parshape\z@ \pretolerance\m@ne \tolerance\@ne {\everypar{}\noindent}% mid-par so no \everypar or \parindent \nobreak % \nobreak because leftskip adds breakpoint \unhbox\z@\unskip\unskip\unpenalty\@@par % gives number of "extra segments" %\message{There are \number\mz@numl\space segments in total and \the\prevgraf\space "remaining segments". }% \@tempcnta\mz@numl \advance\@tempcnta-\prevgraf %\message{Number of segs in 1st line: \the\@tempcnta. }% \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 }% %\message{Parshape: \@tempa \z@\maxdimen}% \parshape \@tempa \z@\maxdimen #1\@@par \unskip\unkern\unskip\unpenalty \unskip\unkern\unskip\unpenalty \global\setbox\mz@remains\lastbox \fi \fi \fi }% end vbox "2)" \endgroup \ifvoid\mz@firstbox #1% Error case: just output the text \else {\everypar{}\noindent}\nobreak % everypar was captured in firstbox \ifvoid\mz@remains % partial line only % Unbox the partial line. This allows equal stretching of spaces across % the line, but admits a slight chance that some \FirstLineFont may % carry over to the second line. \unhbox\mz@firstbox \unskip\unskip\unpenalty % remove \rightskip \parfillskip \nobreak \allowbreak % allow a break rather than get dragged to next line (??) \else % full first line % Output whole box to prevent unexpected linebreaks, especially for % an overfull line and at the bogus discretionary that TeX leaves before % a final (used) hyphen. \box\mz@firstbox\break \unhbox\mz@remains \unskip\unskip\unpenalty % remove \rightskip \parfillskip \nobreak % (or remove forced \break for empty remains) \fi \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 with a secondary % algorithm 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{|}~