%% From GameTeX %%%%% %% %% cards.sty builds a cards-layout driver. Cards are things meant to %% be cut out, and can have 1 or 2 sides. They are printed such that %% opposite sides line up correctly. %% %% Commands provided: %% %% \card{} %% \doublecard{}{} %% \mirrorcard{} %% %% \putcard %% \pageof{} %% %% \flushline %% \flushpage %% %% \Atflushpage{} %% %% \SingleCards %% \DoubleCards %% %% \BuildRows %% \BuildColumns %% %% \GridCardsXY{}{} %% \NoGrid %% %% \MarginsXY{}{} %% %% \YesFill %% \NoFill %% %%%%% %%%%% %% Allows _ to be used in TeX command names, for this file, so %% internal commands that use it can't be used directly/messed with %% outside of this file. \catcode`\_11\relax %%%%% %% creating boxes, dimens, numbers, and booleans that will get %% used. \newbox\front_card \newbox\back_card \newbox\front_box \newbox\back_box \newbox\front_page \newbox\back_page \newif\ifdouble_cards \newif\ifgrid_cards \newif\iffirst_card \newif\iffirst_line \newdimen\scratch_dimen \def\_z{0pt} %%%%% %% \card{} %% %% This will print a single-sided card (blank second side). %% %% %% \doublecard{}{} %% %% This will print a double-sided card. If the 2 sides are different %% sizes, they will be centered relative to each other. %% %% %% If either \doublecard or \mirrorcard are used with \SingleCards, %% only the first side will be printed, and a warning will be given. %% %% %% \mirrorcard{} %% %% This will print a double-sided card with the same thing on front %% and back. %% %% %% \putcard %% %% This will repeat the last card. \long\def\card#1{% \card_calc{#1}{}% \putcard} \long\def\doublecard#1#2{% \card_calc{#1}{#2}% \ifdouble_cards\else% \typeout{! \string\SingleCards: back of \noexpand\doublecard ignored}% \fi% \putcard} \long\def\mirrorcard#1{% \card_calc{#1}{#1}% \ifdouble_cards\else% \typeout{! \string\SingleCards: back of \noexpand\mirrorcard ignored}% \fi% \putcard} %%%%% %% \pageof{} %% %% This will print a page full of said card, based on how many will %% fit with the given settings. Don't put more than 1 card in the %% arg. \def\pageof#1{% \flushpage% \begingroup% \let\putcard\relax#1% \scratch_dimen\card_wd% \advance\scratch_dimen\x_marg% \dimen0 \hsize% \advance\dimen0 \x_marg% \count0 \number\dimen0% \divide\count0 \number\scratch_dimen% \scratch_dimen\card_ht% \advance\scratch_dimen\y_marg% \dimen0 \vsize% \advance\dimen0 \y_marg% \count1 \number\dimen0% \divide\count1 \number\scratch_dimen% \multiply\count0 \count1% \xdef\cards_left{\the\count0} \endgroup% \pageof_loop% \flushpage} \def\pageof_loop{% \begingroup% \count0 \cards_left% \advance\count0 -1% \xdef\cards_left{\the\count0}% \endgroup% \ifnum\cards_left<0% \let\_next\relax% \else% \let\_next\pageof_loop% \putcard% \fi\_next} %%%%% %% Cards are printed out a page at a time. Cards are stored until the %% pending page is "full." %% %% %% \flushline %% %% This forces either a new row or new column of cards, depending on %% which of \BuildRows or \BuildColumns is in effect (see below). %% %% %% \flushpage %% %% This prints out the present page (and line) of cards, and starts a %% new page. If there are no pending cards, \flushpage will do %% nothing. %% %% %% \Atflushpage{} %% %% This makes \flushpage do before each page is printed. %% Repeated use of \Atflushpage resets . If there are no %% pending cards, \flushpage will do nothing. \def\flushpage{\flushline\flush_page} \long\def\Atflushpage#1{\gdef\flush_hook{#1}} %%%%% %% \SingleCards %% %% This makes all cards print out 1-sided. \doublecard's and %% \mirrorcard's will give a warning and only print the front. %% %% %% \DoubleCards %% %% This makes cards print 2-sided. \card's with only 1 side will have %% a blank back. %% %% %% Both \SingleCards and \DoubleCards call \flushpage. \def\DoubleCards{\flushpage\global\double_cardstrue} \def\SingleCards{\flushpage\global\double_cardsfalse} %%%%% %% \BuildRows %% %% This makes cards print left-to-right into rows across the page, and %% such rows print top-to-bottom down the page (like text in a %% paragraph). %% %% %% \BuildColumns %% %% This makes cards print top-to-bottom into columns down the page, %% and such columns print left-to-right across the page. %% %% %% Both \BuildRows and \BuildColumns call \flushpage. \def\BuildRows{% \flushpage% \gdef\putcard{\putcard_inrow}% \gdef\flushline{\flush_row}% \gdef\flush_page{\flush_pageofrows}% \gdef\calc_cen{\row_cen}% \gdef\calc_flush{\row_flush}% } \def\BuildColumns{% \flushpage% \gdef\putcard{\putcard_incol}% \gdef\flushline{\flush_col}% \gdef\flush_page{\flush_pageofcols}% \gdef\calc_cen{\col_cen}% \gdef\calc_flush{\col_flush}% } %%%%% %% \GridCardsXY{}{} %% %% This makes card-layout be based on a x grid instead %% of how many cards can fit. Cards are centered within each grid %% space. %% %% NOTE: \GridCardsXY calculates the size of the grid spaces based on %% the height and width of the page for each card in the grid _when %% the card is first made_, so changing such page parameters midpage %% will cause odd effects. %% %% %% \NoGrid %% %% This turns off the grid, and restores settings for margins and %% filling. %% %% %% Both \GridCardsXY and \NoGrid call \flushpage. \def\GridCardsXY#1#2{% \flushpage% \global\grid_cardstrue% \global\let\x_marg\_z% \global\let\y_marg\_z% \global\let\y_extra\relax% \global\let\x_extra\relax% \gdef\x_num{#1}% \gdef\y_num{#2}} \def\NoGrid{% \flushpage% \global\grid_cardsfalse% \global\let\x_marg\x_hold% \global\let\y_marg\y_hold% \global\let\y_extra\yex_hold% \global\let\x_extra\xex_hold} %%%%% %% \MarginsXY{}{} %% %% This sets the minimum spacing between cards. Space equal to %% gets put between cards horizontally (or between %% columns of cards). Space equal to gets put between %% cards vertically (or between rows of cards). Leaving either of the %% args empty doesn't change the empty arg, so \marginsXY{}{} will change the horizontal spacing but not the vertical, %% \marginsXY{}{} will change the vertical spacing but %% not the horizontal, and \marginsXY{}{} will change nothing. %% %% \MarginsXY calls \flushpage and \NoGrid. \def\MarginsXY#1#2{% \flushpage% \NoGrid% \def\_tmp{#1}% \ifx\_tmp\empty% \relax% \else% \scratch_dimen#1% \xdef\x_marg{\the\scratch_dimen}% \global\let\x_hold\x_marg% \fi% \def\_tmp{#2}% \ifx\_tmp\empty% \relax% \else% \scratch_dimen#2% \xdef\y_marg{\the\scratch_dimen}% \global\let\y_hold\y_marg% \fi} %%%%% %% \YesFill %% %% This makes cards and lines have as much spacing between them as %% possible, without changing the numbers of cards per line or page. %% The spacing set by \MarginsXY gets used as the minimum spacing. %% Cards are spread out from the page margins as well as each other; %% e.g. a lone card on a line will be horizontally centered and a lone %% line on a page will be vertically centered. %% %% %% \NoFill %% %% This makes cards and lines print on the page with the spacing set %% by \MarginsXY as the exact spacing. A lone card on a line will be %% put flush against the left margin (right margin if side 2 of a %% 2-sided card). A lone line on a page will be put flush against the %% top margin. %% %% %% Both \YesFill and \NoFill call \flushpage and \NoGrid. \def\YesFill{% \flushpage% \NoGrid% \def\extra_calc{\calc_cen}% \global\let\y_extra\vfill% \global\let\x_extra\hfill% \global\let\yex_hold\y_extra% \global\let\xex_hold\x_extra} \def\NoFill{% \flushpage% \NoGrid% \def\extra_calc{\calc_flush}% \global\let\y_extra\relax% \global\let\x_extra\relax% \global\let\yex_hold\y_extra% \global\let\xex_hold\x_extra} %%%%% %% Internal commands that make this work. \def\nest_error{% \typeout{! Please don't nest cards commands inside \string\card, \string\doublecard, or \string\mirrorcard. ^^J\space\space (command ignored)}% } \def\row_cen{% \scratch_dimen\card_ht\divide\scratch_dimen-2% \global\setbox\front_card\vbox{\smash{\box\front_card}\vskip\scratch_dimen}% \ifdouble_cards% \global\setbox\back_card\vbox{\smash{\box\back_card}\vskip\scratch_dimen}% \fi} \def\row_flush{} \def\col_cen{% \scratch_dimen\card_wd\divide\scratch_dimen-2% \global\setbox\front_card\vbox{% \hbox{\hskip\scratch_dimen\box\front_card\hskip\scratch_dimen}}% \ifdouble_cards% \global\setbox\back_card\vbox{% \hbox{\hskip\scratch_dimen\box\back_card\hskip\scratch_dimen}}% \fi} \def\col_flush{% \ifdouble_cards% \global\setbox\back_card\vbox{% \hbox{\hskip-\card_wd\box\back_card}}% \fi} \long\def\card_calc#1#2{% \begingroup% \long\def\card##1{\nest_error}% \long\def\doublecard##1##2{\nest_error}% \long\def\mirrorcard##1{\nest_error}% \def\putcard{\nest_error}% \long\def\pageof##1{\nest_error}% \def\flushpage{\nest_error}% \def\SingleCards{\nest_error}% \def\DoubleCards{\nest_error}% \def\BuildRows{\nest_error}% \def\BuildColumns{\nest_error}% \def\GridCardsXY##1##2{\nest_error}% \def\NoGrid{\nest_error}% \def\MarginsXY##1##2{\nest_error}% \def\YesFill{\nest_error}% \def\NoFill{\nest_error}% \global\setbox\front_card\hbox{{#1}}% \global\setbox\front_card\hbox{\raise\dp\front_card\box\front_card}% \scratch_dimen\wd\front_card% \xdef\card_wd{\the\scratch_dimen}% \scratch_dimen\ht\front_card% \xdef\card_ht{\the\scratch_dimen}% \ifdouble_cards% \global\setbox\back_card\hbox{{#2}}% \global\setbox\back_card\hbox{\raise\dp\back_card\box\back_card}% \scratch_dimen\wd\front_card% \ifdim\scratch_dimen<\wd\back_card% \scratch_dimen\wd\back_card% \fi% \xdef\card_wd{\the\scratch_dimen}% \scratch_dimen\ht\front_card% \ifdim\scratch_dimen<\ht\back_card% \scratch_dimen\ht\back_card% \fi% \xdef\card_ht{\the\scratch_dimen}% \fi% \ifdim\card_wd>\hsize% \xdef\card_wd{\the\hsize}% \typeout{! card is too wide for the page}% \fi% \ifdim\card_ht>\vsize% \xdef\card_ht{\the\vsize}% \typeout{! card is too tall for the page}% \fi% \ifgrid_cards% \scratch_dimen\hsize% \divide\scratch_dimen\x_num% \xdef\grid_wd{\the\scratch_dimen}% \scratch_dimen\vsize% \divide\scratch_dimen\y_num% \xdef\grid_ht{\the\scratch_dimen}% \ifdim\card_wd>\grid_wd% \typeout{! card is too wide for the grid}% \fi% \ifdim\card_ht>\grid_ht% \typeout{! card is too tall for the grid}% \fi% \global\let\card_wd\grid_wd% \global\let\card_ht\grid_ht% \fi% \global\setbox\front_card\vbox to\card_ht{% \vskip0pt plus1fil minus1fil% \hbox to\card_wd{% \hskip0pt plus1fil minus1fil% \box\front_card% \hskip0pt plus1fil minus1fil}% \vskip0pt plus1fil minus1fil}% \ifdouble_cards% \global\setbox\back_card\vbox to\card_ht{% \vskip0pt plus1fil minus1fil% \hbox to\card_wd{% \hskip0pt plus1fil minus1fil% \box\back_card% \hskip0pt plus1fil minus1fil}% \vskip0pt plus1fil minus1fil}% \fi% \extra_calc% \endgroup} \def\putcard_inrow{% \ifvbox\front_card% \scratch_dimen\cur_wd% \advance\scratch_dimen\card_wd% \iffirst_card\relax\else% \advance\scratch_dimen\x_marg% \fi% \xdef\next_wd{\the\scratch_dimen}% \ifdim\next_wd>\hsize% \flush_row% \scratch_dimen\cur_wd% \advance\scratch_dimen\card_wd% \xdef\cur_wd{\the\scratch_dimen}% \global\let\row_ht\card_ht% \else% \ifdim\row_ht<\card_ht% \global\let\row_ht\card_ht% \fi% \global\let\cur_wd\next_wd% \fi% \global\setbox\front_box\hbox{% \iffirst_card\relax\else% \unhbox\front_box% \hskip\x_marg% \fi% \x_extra% \copy\front_card}% \ifdouble_cards% \global\setbox\back_box\hbox{% \copy\back_card% \x_extra% \iffirst_card\relax\else% \hskip\x_marg% \unhbox\back_box% \fi}% \fi% \global\first_cardfalse% \fi} \def\putcard_incol{% \ifvbox\front_card% \scratch_dimen\cur_ht% \advance\scratch_dimen\card_ht% \iffirst_card\relax\else% \advance\scratch_dimen\y_marg% \fi% \xdef\next_ht{\the\scratch_dimen}% \ifdim\next_ht>\vsize% \flush_col% \scratch_dimen\cur_ht% \advance\scratch_dimen\card_ht% \xdef\cur_ht{\the\scratch_dimen}% \global\let\col_wd\card_wd% \else% \ifdim\col_wd<\card_wd% \global\let\col_wd\card_wd% \fi% \global\let\cur_ht\next_ht% \fi% \global\setbox\front_box\vbox{% \iffirst_card\relax\else% \unvbox\front_box% \vskip\y_marg% \fi% \y_extra% \copy\front_card}% \ifdouble_cards% \global\setbox\back_box\vbox{% \iffirst_card\relax\else% \unvbox\back_box% \vskip\y_marg% \fi% \y_extra% \copy\back_card}% \fi% \global\first_cardfalse% \fi} \def\flush_row{% \ifhbox\front_box% \scratch_dimen\cur_ht% \advance\scratch_dimen\row_ht% \iffirst_line\relax\else% \advance\scratch_dimen\y_marg% \fi% \xdef\next_ht{\the\scratch_dimen}% \ifdim\next_ht>\vsize% \flush_pageofrows% \scratch_dimen\cur_ht% \advance\scratch_dimen\row_ht% \xdef\cur_ht{\the\scratch_dimen}% \else% \global\let\cur_ht\next_ht% \fi% \global\setbox\front_page\vbox{% \iffirst_line\relax\else% \unvbox\front_page% \vskip\y_marg% \fi% \y_extra% \vbox to\row_ht{% \vskip0pt plus1fil minus1fil% \hbox to\hsize{\unhbox\front_box\x_extra\hfil}% \vskip0pt plus1fil minus1fil}}% \ifdouble_cards% \global\setbox\back_page=\vbox{% \iffirst_line\relax\else% \unvbox\back_page% \vskip\y_marg% \fi% \y_extra% \vbox to\row_ht{% \vskip0pt plus1fil minus1fil% \hbox to\hsize{\hfil\x_extra\unhbox\back_box}% \vskip0pt plus1fil minus1fil}}% \fi% \global\let\cur_wd\_z% \global\let\row_ht\_z% \global\first_linefalse% \global\first_cardtrue% \fi} \def\flush_col{% \ifvbox\front_box% \scratch_dimen\cur_wd% \advance\scratch_dimen\col_wd% \iffirst_line\relax\else% \advance\scratch_dimen\x_marg% \fi% \xdef\next_wd{\the\scratch_dimen}% \ifdim\next_wd>\hsize% \flush_pageofcols% \scratch_dimen\cur_wd% \advance\scratch_dimen\col_wd% \xdef\cur_wd{\the\scratch_dimen}% \else% \global\let\cur_wd\next_wd% \fi% \global\setbox\front_page\hbox{% \iffirst_line\relax\else% \unhbox\front_page% \hskip\x_marg% \fi% \x_extra% \hbox to\col_wd{% \hskip0pt plus1fil minus1fil% \vbox to\vsize{\unvbox\front_box\y_extra\vfil}% \hskip0pt plus1fil minus1fil}}% \ifdouble_cards% \global\setbox\back_page\hbox{% \hbox to\col_wd{% \hfill% \vbox to\vsize{\unvbox\back_box\y_extra\vfil}% \x_extra}% \x_extra% \iffirst_line\relax\else% \hskip\x_marg% \unhbox\back_page% \fi}% \fi% \global\let\cur_ht\_z% \global\let\col_wd\_z% \global\first_linefalse% \global\first_cardtrue% \fi} \def\flush_pageofrows{% \ifvbox\front_page% \flush_hook% \vbox to\vsize{\unvbox\front_page\y_extra\vfil}% \vfill\break% \ifdouble_cards% \vbox to\vsize{\unvbox\back_page\y_extra\vfil}% \vfill\break% \fi% \global\let\cur_wd\_z% \global\let\cur_ht\_z% \fi% \global\first_linetrue% \global\first_cardtrue} \def\flush_pageofcols{% \ifhbox\front_page% \flush_hook% \hbox to\hsize{\unhbox\front_page\x_extra\hfil}% \vfill\break% \ifdouble_cards% \hbox to\hsize{\hfil\x_extra\unhbox\back_page}% \vfill\break% \fi% \global\let\cur_wd\_z% \global\let\cur_ht\_z% \fi% \global\first_linetrue% \global\first_cardtrue} %%%%% %% Setting up initialization and defaults. %% %% Default setting are equivalent to: %% \BuildColumns %% \DoubleCards %% \MarginsXY{15pt}{15pt} %% \NoFill \global\let\cur_wd\_z \global\let\cur_ht\_z \global\let\col_wd\_z \global\let\row_ht\_z \global\let\x_marg\_z \global\let\y_marg\_z \global\let\x_hold\x_marg \global\let\y_hold\y_marg \global\let\x_extra\relax \global\let\y_extra\relax \def\extra_calc{\calc_flush}% \gdef\putcard{\putcard_incol} \gdef\flushline{\flush_col} \gdef\flush_page{\flush_pageofcols} \gdef\calc_cen{\col_cen} \gdef\calc_flush{\col_flush} \gdef\flush_hook{} \global\double_cardstrue \global\grid_cardsfalse \global\first_cardtrue \global\first_linetrue \BuildColumns \DoubleCards \MarginsXY{15pt}{15pt} \NoFill %%%%% %% Returns _ to its default behavior, so it can no longer be used in %% TeX command names. \catcode`\_8\relax %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%