\ProvidesPackage{cards} % Written by Ken Clary around Jeremy Brown's card TeX hacks % Much modified by Jamie Morris %% Place as many cards on the page as possible while keeping the %% given margins; first build columns of cards, then build pages %% out of the columns, since height is more likely to vary than width. %% Invoke this with %% (\RequirePackage or \usepackage)[options]{cards} %% where ``options'' MUST include exactly one of %% ``single'' (single-sided cards), %% ``double'' (double-sided cards), %% ``mirror'' (mirror-sided cards, same thing on each side) %% and can optionally include a dimension (specifying the margin %% to leave around each side of each card) or two dimensions %% (to specify the horizontal and vertical margins separately). %% %% If invoked without dimensions, double- or mirror-sided cards will %% use the \card@default@margin specified below, while single-sided %% cards will default to zero margin. (Because printer alignment %% isn't a concern with single-sided cards, so you usually want to %% save scissors work via merger of neighboring cards' borders.) %% %% E.g. in a .sty file %% \RequirePackage[double]{cards} % double-sided, default margins %% \RequirePackage[single]{cards} % single-sided, no margins %% \RequirePackage[mirror,0.5cm]{cards} % mirrors, .5cm all around %% \RequirePackage[single,1ex,1em]{cards} % single-sided, 1ex horiz, 1em vert %% %% In a .tex file you'd use \usepackage instead of \RequirePackage, of course. %% Commands provided: %% %% \makecard{front}{back} if you used [double]; make an arbitrary card %% \makecard{front} if you used [single] or [mirror] %% %% \putcard % repeat last card once %% \pageof{some \makecard-based code} % full page of cards %% As usual, this file is arranged so that the things the Czar is %% most likely to possibly want to frob tend towards the start %% and the more magical parts tends towards the end. \RequirePackage{times} \RequirePackage{graphicx} \geometry{margin=.3in} % *page* margin, not card margin \topskip=0pt \unitlength=1in % provide default for those using the picture environment % default margins around each card if not set as a package option; % this value is for double- and mirror-sided cards, if single-sidedness % is selected it will be reset to zero! % \newcommand\card@default@margin{.2cm} % since the sides might be different sizes, we frame the united area % with a border of this width % \newdimen\card@border \card@border=.4pt \newcommand\card@whitespace{% \fboxsep=0pt \fboxrule=\card@border \lineskip=0pt \baselineskip=0pt \parskip=0pt \parindent=0pt \leftskip=0pt \rightskip=0pt } %%%%% %% Process the usage options to determine what kind of cards %% to make and what margins to give them, as described up top. %% % % Exactly one of single, double, mirror should appear. \DeclareOption{single}{ \special{header=simplex} % force single-sided printing \newcommand\makecard[1]{\make@card{#1}{}} \newcommand\card@skip@back{} % no printer-alignment worries here, so save scissors work \renewcommand\card@default@margin{0pt} } \DeclareOption{double}{ \special{header=duplex} % force double-sided printing \newcommand\makecard[2]{\make@card{#1}{#2}} } \DeclareOption{mirror}{ \special{header=mirror} % force mirror-sided printing (respects unmirror) \newcommand\makecard[1]{\make@card{#1}{#1}} } % % Since the margins should never be negative, we use that to mean ``not set'' \newdimen\horiz@margin \horiz@margin -1in \newdimen\vert@margin \vert@margin -1in % All other options should be margin dimensions; if one is given, use % it for both horiz and vert, if two are given, use each. nonnegative. \DeclareOption*{ \ifdim\horiz@margin<0pt\relax \horiz@margin=\CurrentOption \vert@margin=\CurrentOption \else \vert@margin=\CurrentOption \fi } % \ProcessOptions* \ifx\makecard\ThisMacroShouldNotBeDefined \@die{cards.sty used without specifying single, double, or mirror siding} \fi % If either/both margins haven't been set, give them the default. \ifdim\horiz@margin<0pt\relax \horiz@margin=\card@default@margin \fi \ifdim\vert@margin<0pt\relax \vert@margin=\card@default@margin \fi % Want extra margin at top in case there's headers; it can go away % if they're single-sided, but *not* for zero-vert-margins on % asymmetric double-sided since headers can interfere on *either* side. \geometry{headsep=\card@default@margin} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Card-making preliminary setup. % % the single/double/mirror options define \makecard in terms of this \newcommand\make@card[2]{% \def\card@frontside{#1}% \def\card@backside{#2}% \putcard } % current card's front and back \newbox\front@card \newbox\back@card % current column of cards; use \vtop 'cause it looks a bit nicer % if they line up at the tops, with any empty spaces at the bottoms \newbox\front@column \global\setbox\front@column=\vtop{} \newbox\back@column \global\setbox\back@column=\vtop{} % current page of cards \newbox\front@page \global\setbox\front@page=\hbox{} \newbox\back@page \global\setbox\back@page=\hbox{} % for misc calculations \newdimen\card@ht \newdimen\card@wd \newdimen\inner@ht \newdimen\inner@wd \newdimen\card@tmp % this should be left at true almost all the time; \pageof sets % it to false to see if the current card would spark a new page, % in which case it wants to punt it \newif\if@keepcard \@keepcardtrue %%%%% %% \putcard, the macro which places the current card on the page. %% If used without resetting the current \card@frontside and %% \card@backside, it will keep placing copies of the same card. %% \newdef\putcard{% \setbox\front@card=\hbox{\card@frontside}% \setbox\back@card=\hbox{\card@backside}% \card@ht=\ht\front@card \advance\card@ht by \dp\front@card \card@tmp=\ht\back@card \advance\card@tmp by \dp\back@card \ifdim\card@tmp>\card@ht \card@ht=\card@tmp \fi \inner@ht=\card@ht \advance\card@ht by 2\vert@margin \card@wd=\wd\front@card \card@tmp=\wd\back@card \ifdim\card@tmp>\card@wd \card@wd=\card@tmp \fi \inner@wd=\card@wd \advance\card@wd by 2\horiz@margin % now put the margins in and frame it \rebox@card\front@card \rebox@card\back@card % framing may have altered the dimens (at least via the border) \card@wd=\wd\front@card \card@ht=\ht\front@card \advance\card@ht by \dp\front@card % can we fit this in the current column? \card@tmp=\ht\front@column \advance\card@tmp by \dp\front@column \advance\card@tmp by \card@ht \advance\card@tmp by \headsep % lost this space at the top \advance\card@tmp by -\vert@margin % don't count bottommost glue \ifdim\card@tmp>\textheight \put@column \else \@keepcardtrue \fi \if@keepcard % \pageof will punt the card that would make the next page \card@tmp=\wd\front@column \ifdim\card@tmp<\card@wd \card@tmp=\card@wd \fi \global\setbox\front@column=\vtop{\hsize=\card@tmp \card@whitespace % no uncontrolled whitespace; \unvbox\front@column % previous contents, \hbox to \hsize{\box\front@card\hfill}% % plus front of new card }% \global\setbox\back@column=\vtop{\hsize=\card@tmp \card@whitespace % no uncontrolled whitespace; \unvbox\back@column % previous contents, \hbox to \hsize{\hfill\box\back@card}% % plus back of new card }% \fi } % put a frame around the card with the proper margins around that \newcommand\rebox@card[1]{% \setbox#1=\hbox{\card@whitespace % no uncontrolled whitespace \hspace\horiz@margin % left margin \vbox{\hsize=\inner@wd \vspace\vert@margin % top margin \framebox[\hsize]{% % center it in here, both ways \hfill \vbox to \inner@ht{\vfill\box#1\vfill}% \hfill }% \vspace\vert@margin % bottom margin }% \hspace\horiz@margin % right margin }% } % put the current columns onto the page if possible, or start new page \newcommand\put@column{% \ifdim\wd\front@column>0pt \card@tmp=\wd\front@page \advance\card@tmp by \wd\front@column \ifdim\card@tmp>\textwidth \put@page \else \@keepcardtrue \fi \if@keepcard \global\setbox\front@page=\hbox{\card@whitespace % no uncontrolled space; \unhbox\front@page % previous contents, \box\front@column}% % plus front of newly finished column \global\setbox\back@page=\hbox{\card@whitespace % no uncontrolled space; \box\back@column % add back of newly finished column \unhbox\back@page}% % to previous contents \fi \global\setbox\front@column=\vtop{}% \global\setbox\back@column=\vtop{}% \fi } % send out the current page \newcommand\put@page{% \ifdim\wd\front@page>0pt \hbox to \textwidth{\unhbox\front@page\hfill}% \vfil\pagebreak \ifx\card@skip@back\ThisMacroHadBetterNotBeDefined \hbox to \textwidth{\hfill\unhbox\back@page}% \vfil\pagebreak \fi \global\setbox\front@page=\hbox{}% \global\setbox\back@page=\hbox{}% \fi } % \newpage is a standard latex macro that flushes the current page; % cause it to flush pending cards, since we haven't put them on page yet. % Can be called by hand, and is automatically called by \end{document}. % \renewcommand\newpage{\put@column\put@page} % flush pending cards, then fill up the page with the given card \newdef\pageof[1]{% \newpage #1\relax \loop \@keepcardfalse \putcard \if@keepcard \repeat } \vfuzz=10in % shut up about overfull \vbox's! \vbadness=10000 % and underfull ones \hfuzz=10in % and overfull \hbox's \hbadness=10000 % and underfull ones