%% Gezhu Typesetting Macro or TeX/LaTeX %% (Gezhu: Splitted Annotation (warichu in Japanese)) %% File: gezhu.sty %% Author: Dian YIN (yindian@ustc) %% Descr: This macro file provides an environment \withgezhu ... %% \endwithgezhu which which one can typeset gezhu by inserting %% double-line annotations using |{text}. There is no limitations %% in using whatever commands both in withgezhu environment and %% inside |{}, theoretically. The macro use \endgraf to end the %% current paragraph in order to determine the h-offset of the %% current position, so any parshapes will lose efficacy. %% Hist: 07.3.5. Inspired by previous work (xguji) and thought. %% 07.3.6-3.7. Framework done. Buggy. %% 07.3.10. First release comes out. Works to my expectance. %% 07.3.11. Extra \parskip removed. %% 07.3.25. Improved balancing method to prevent overfull. %% Fixed bug when \penalty\gezhu@breakpenalty %% 07.5.13. Added \beforegezhu and \aftergezhu %% 07.9.28. New works began. Adding new features. Use eTeX. %% More comments written. Interline skips reserved. %% Using parshape in order to avoid cjkglue. %% 07.9.29.am Finished rewriting codes until balancing module. %% Fixed some bugs of nested loop. %% 07.9.29.pm More comments written. Finished the new %% implementation. Changed \gezhu@breakpenalty to %% -\@M. Fixed bug that adding \gezhu@strut isn't %% enough for empty line compensation --- simply %% by adding \baselineskip instead of \gezhu@strut %% Added \hfuzz and \hbadness to suppress warning. %% 07.9.30. Want to change \par in withgezhu environment. %% New bug of unexcepted \parskip found. %% 07.10.7. Determined that the above bug is introduced by %% CJKpunct. Removed \hyphenpenalty settings. Added %% \parskip setting to avoid the bug. %% 07.10.8. Fixed bug of unwanted \penalty at end of para. %% Changed \copy to \unhcopy when copying box. %% Found a bug of punct-prohibitionless after %% a gezhu box, which seems hard to fix. %% Added \gezhu@parfillskip setting. Better %% width adjusting for balancing using bigem. %% 07.10.9. Added fbox for debug. Found a bug of two chars %% appear at the end of line when the rest space %% is between the width of 1 char and 2 chars, %% which looks ugly. Fixed it by comparing the %% rest space with 2\gezhu@smallem and adjustment. %% But not very ideal when punct-prohibition %% is concerned. Okay for now. %% Found a bug of not enough space left for a big %% char to appear at the same line after gezhu. %% Fixed it by adding stretches to \aftergezhu. %% 07.10.13. Changed \newdimen\gezhu@tmpskip to \newskip. %% Added \gezhu@leftspace to fix a bug of balanced %% gezhu stretching out of the right margin. %% Fixed the bug of 1em 2 chars. %% Fixed the bug of wrong bigem and smallem %% setting --- \wd\hbox{M} doesn't generate 1em. %% Added gezhu normalize functionality. %% Fixed the bug that the length of a widow hanzi %% box is less than \gezhu@smallem. %% \gezhurevision added. %% 07.10.14. Fixed the bug of breaking after gezhu when %% the rest space is about 1em. %% Added simple interface to set raise and parfil. %% Finally fixed the bug of CJK char wrap. %% 07.10.26. Fixed the bug of wrong baselineskip cause by %% the raising of gezhu box. Fixed the bug of %% wrong baselineskip before and after withgezhu. %% Successfully realized every par ship out. %% 07.10.27. Added \gezhu@shipoutlevel setting, what a %% tough work, expecially level 2!!! %% More debug routines. Found bug in \gezhu %% when shipout level=2: should use \prevdepth %% of the last but one line, but got last line's. %% Fixed the bug of \errmessage misspelling. %% Fixed the last but one line \prevdepth bug %% by using \prevgraf and make decision. %% 07.11.05. Fixed some subtleties of \prevdepth setting. %% Changed balancing mode to find width from less %% than one_line_width/\gezhu@lines. Added %% \lineskiplimit settings. Fixed bug of too much %% space when normailze sometimes. %% 07.11.06. Uncommented last change. Fixed some bugs. Fine %% tuned a bit. %% 07.11.07. Use \numexpr instead of binary search to find %% normalization dimension. %% 07.11.17. Fixed the bug of \gezhu at the start of para. %% TODO: 1. Add a more friendly interface for use under LaTeX. e.g. %% \begin{withgezhu}[raise=-2pt,lines=2,everygezhu={\tiny}] %% 2. Find bugs and fix... %% Note: 1. Chances are that the texts may exceed the right boundary %% because of punctuation prohibitions. %% 2. \gezhu@shipoutlevel =0 : ship out when \endwithgezhu %% =1 : ship out when \par %% =2 : ship out when \gezhu and \par \catcode`@=11 \ifx\gezhurevision\@undefined \ifx\eTeXrevision\@undefined \errmessage{eTeX required to use this package} \fi \def\gezhurevision{2007.11.07.} % user configurable \newcount\gezhu@lines \newcount\gezhu@breakpenalty \newcount\gezhu@shipoutlevel \newskip\gezhu@cjkglue \newskip\gezhu@parfillskip \newdimen\gezhu@gezhuraise \newtoks\everywithgezhu \newtoks\everygezhu \newtoks\beforegezhu \newtoks\aftergezhu \newif\ifgezhunormalize % for self use \newbox\gezhu@tmpbox \newbox\gezhu@tmpboy \newbox\gezhu@tmpboz \newbox\gezhu@tmpb@x \newbox\gezhu@tmpb@y \newbox\gezhu@tmpb@z \newbox\gezhu@tmpb@w \newcount\gezhu@tmpcnt \newcount\gezhu@tmpcns \newdimen\gezhu@tmpdim \newdimen\gezhu@tmpdil \newskip\gezhu@tmpskip \newdimen\gezhu@leftspace \newdimen\gezhu@bigem \newdimen\gezhu@smallem \newtoks\gezhu@strut % \gezhu@lines=2 \gezhu@shipoutlevel=0 \gezhu@cjkglue=0pt plus 0.1em minus 0.1em \gezhu@gezhuraise=-1.5pt \gezhu@parfillskip=0pt \gezhu@breakpenalty=-\@M \gezhunormalizefalse \everywithgezhu={\gezhu@makespecials} \ifdefined\LaTeX \everygezhu={\tiny} \else \everygezhu={\fiverm\baselineskip=6pt} \fi \beforegezhu={\nobreak\hskip 0pt plus 0.1em minus 0.01em} \aftergezhu={\nobreak\hskip 0pt plus 0.4em\penalty 2000\hskip 0pt plus -0.4em \hskip 0pt plus 0.1em minus 0.01em} \gezhu@strut={\vphantom{()}} \def\gezhu@debug#1{} \def\gezhu@message#1{} \def\gezhu@showbox#1{} \def\gezhu@debugbox#1{#1} \def\gezhu@debugboy#1{#1} \def\gezhu@break{\gezhu@debug{Break}\penalty\gezhu@breakpenalty} \def\gezhu@makehboxofhboxesandcount{% % input: none but previous vertical mode nodes % output: \gezhu@tmpb@y as the result hbox, with interline skips % \gezhu@tmpcnt as the result count % uses: \gezhu@tmpb@z, \gezhu@tmpskip, \loop \setbox\gezhu@tmpb@y=\hbox{}% \gezhu@tmpcnt=0 \loop \setbox\gezhu@tmpb@z=\lastbox \ifhbox\gezhu@tmpb@z \setbox\gezhu@tmpb@y=\hbox{\box\gezhu@tmpb@z\unhbox\gezhu@tmpb@y}% \advance\gezhu@tmpcnt by 1 \ifnum\lastnodetype = 11% inter line skip \gezhu@tmpskip=\lastskip \setbox\gezhu@tmpb@y=\hbox{\hskip\gezhu@tmpskip\unhbox\gezhu@tmpb@y}% \fi \unskip \unpenalty \repeat } \def\gezhu@getfirsthboxes#1{% % input: #1 as the precomputed loop count % \gezhu@tmpb@y as the hboxofhbox % output: \gezhu@tmpb@x as vbox of the first hboxes % \gezhu@tmpb@y as vbox of the rest boxes without interlineskips % uses: \gezhu@tmpb@x, \gezhu@tmpb@y, \gezhu@tmpcnt, \gezhu@tmpskip, \loop \hskip 111sp% manual boundary \unhbox\gezhu@tmpb@y \setbox\gezhu@tmpb@x=\copy\voidb@x% first boxes \setbox\gezhu@tmpb@y=\copy\voidb@x% last boxes \gezhu@tmpcnt=0 \loop \ifnum #1>\gezhu@tmpcnt \ifnum\lastnodetype = 11% inter line skip \unskip \fi \setbox\gezhu@tmpb@z=\lastbox \setbox\gezhu@tmpb@y=\vbox{\box\gezhu@tmpb@z\unvbox\gezhu@tmpb@y}% \advance\gezhu@tmpcnt by 1 \repeat \ifnum\lastnodetype = 11% skip \unless\ifdim\lastskip = 111sp % not boundary \unskip \fi \fi \loop \setbox\gezhu@tmpb@z=\lastbox \ifhbox\gezhu@tmpb@z \setbox\gezhu@tmpb@x=\vbox{\box\gezhu@tmpb@z\unvbox\gezhu@tmpb@x}% \ifnum\lastnodetype = 11% skip \unless\ifdim\lastskip = 111sp % not boundary \gezhu@tmpskip=\lastskip \setbox\gezhu@tmpb@x=\vbox{\vskip\gezhu@tmpskip\unvbox\gezhu@tmpb@x}% \unskip \fi \fi \repeat \unskip% remove \hskip 111sp } \def\gezhu@removehboxes{% % input: none but previous hbox nodes % output: \gezhu@tmpb@y as the result hbox % \gezhu@tmpcnt as the result count % uses: \gezhu@tmpb@z, \gezhu@tmpskip \setbox\gezhu@tmpb@z=\lastbox \ifhbox\gezhu@tmpb@z {\gezhu@removehboxes}% grouped for use local tmpb@z \unhbox\gezhu@tmpb@z \unskip % removes \rightskip \hskip\gezhu@cjkglue \fi } \def\gezhu@makeparshape#1{% % input: #1 as the length of the first \gezhu@lines lines % output: \gezhu@parshape as the generated parshape \begingroup % for local loop \xdef\gezhu@parshape{\number\numexpr\gezhu@lines+1}% \gezhu@tmpcnt=1 \loop \xdef\gezhu@parshape{\gezhu@parshape\space 0pt \the#1}% \ifnum\gezhu@tmpcnt < \gezhu@lines \advance\gezhu@tmpcnt by 1 \repeat \xdef\gezhu@parshape{\gezhu@parshape\space 0pt \the\maxdimen}% \endgroup } \def\gezhu@normalize{% % input: \gezhu@tmpdim as the length of the gezhu box % output: \gezhu@tmpdil as the adjustment length, which equals to % \gezhu@bigem * ceil(#1 / \gezhu@bigem) - #1 % uses: \gezhu@tmpcnt, \gezhu@tmpcns, \loop \gezhu@tmpcnt=\numexpr\number\gezhu@tmpdim/\number\gezhu@bigem\relax \gezhu@tmpdil=\dimexpr\gezhu@bigem*\gezhu@tmpcnt-\gezhu@tmpdim\relax \ifdim\gezhu@tmpdil < 0pt \advance\gezhu@tmpdil by \gezhu@bigem \fi } { \catcode`|=\active \gdef\gezhu@makespecials{% \catcode`|=\active \def|{\gezhu}% } } \def\withgezhu{\begingroup \showboxbreadth=999 \showboxdepth=999 \hbadness=\@M\hfuzz=0.4em \def\gezhu##1{% \leavevmode \endgraf \setbox\gezhu@tmpbox=\lastbox \setbox\gezhu@tmpbox=\hbox{\unhbox\gezhu@tmpbox\unskip\unskip\unpenalty}% \ifnum\gezhu@shipoutlevel > 1\relax \unless\ifnum\currentgrouptype = 4 % vbox group \errmessage{\string\gezhu\ cannot be used inside a group}% \fi \gezhu@tmpcnt = \prevgraf \gezhu@message{pg\number\gezhu@tmpcnt}% \ifnum\gezhu@tmpcnt < 2 \ifnum\gezhu@tmpcnt > 0 \global\setbox\gezhu@tmpboy=\box\gezhu@tmpbox \global\gezhu@tmpdim=\dimexpr\baselineskip - \lastskip - \ht\gezhu@tmpboy\relax \unskip % remove interline skip in internal vertical mode \egroup\prevdepth=\gezhu@tmpdim \gezhu@showbox\gezhu@tmpbox\unvbox\gezhu@tmpbox \endgraf%\gezhu@message{<\number\currentgrouptype>}% \setbox\gezhu@tmpbox=\vbox\bgroup \prevdepth=\gezhu@tmpdim \setbox\gezhu@tmpbox=\box\gezhu@tmpboy \else % gezhu at the beginning of vbox \unskip % should have no effect \fi \else \unskip % remove interline skip in internal vertical mode \unpenalty \ifnum\lastnodetype = 1 \global\setbox\gezhu@tmpboz=\lastbox \global\setbox\gezhu@tmpboy=\box\gezhu@tmpbox \global\gezhu@tmpdim=\prevdepth\egroup \gezhu@showbox\gezhu@tmpboz \gezhu@showbox\gezhu@tmpbox\unvbox\gezhu@tmpbox \endgraf\gezhu@message{<\number\currentgrouptype>}% \setbox\gezhu@tmpbox=\vbox\bgroup \setbox\gezhu@tmpbox=\box\gezhu@tmpboy \box\gezhu@tmpboz \vskip -\parskip \else \message{Unexpected lastnodetype \number\lastnodetype, should be an hbox}% \global\setbox\gezhu@tmpboy=\box\gezhu@tmpbox \global\gezhu@tmpdim=\dimexpr\baselineskip - \lastskip - \ht\gezhu@tmpboy\relax \unskip % remove interline skip in internal vertical mode \egroup\prevdepth=\gezhu@tmpdim \gezhu@showbox\gezhu@tmpbox\unvbox\gezhu@tmpbox \endgraf%\gezhu@message{<\number\currentgrouptype>}% \setbox\gezhu@tmpbox=\vbox\bgroup \prevdepth=\gezhu@tmpdim \setbox\gezhu@tmpbox=\box\gezhu@tmpboy \fi \fi \else \prevdepth=\dimexpr\baselineskip - \lastskip - \ht\gezhu@tmpbox\relax \unskip % remove interline skip in internal vertical mode \vskip -\parskip \fi \noindent\gezhu@debug{Copy}\unhcopy\gezhu@tmpbox \the\beforegezhu \def\gezhu@tmpmacro{\setbox\gezhu@tmpboy=\hbox{\hskip 1em}}\gezhu@tmpmacro \ifdefined\CJK@spaceChar % now in CJK, fix me \setbox\gezhu@tmpboy=\hbox{\CJK@spaceChar}% \fi \gezhu@bigem=\wd\gezhu@tmpboy \begingroup \let\gezhu=\relax \let\par\endgraf \the\everygezhu \def\gezhu@tmpmacro{\setbox\gezhu@tmpboy=\hbox{\hskip 1em}}\gezhu@tmpmacro %\setbox\gezhu@tmpboy=\hbox{M}% \ifdefined\CJK@spaceChar % now in CJK, fix me \setbox\gezhu@tmpboy=\hbox{\CJK@spaceChar}% \fi \gezhu@smallem=\wd\gezhu@tmpboy \gezhu@leftspace=\dimexpr\hsize - \wd\gezhu@tmpbox\relax % now \gezhu@leftspace is the width of the rest blank space of the line \ifdim\gezhu@leftspace > 0.9\gezhu@smallem % annotations at the end of line \ifdim\gezhu@leftspace > 1.5\gezhu@smallem \ifdim\gezhu@leftspace < 2\gezhu@smallem \gezhu@leftspace = 1.9\gezhu@smallem \fi \else \gezhu@leftspace = 0.99\gezhu@smallem \fi \gezhu@makeparshape{\gezhu@leftspace}% % place gezhu annotation text in a vbox with specified parshape \setbox\gezhu@tmpboy=\vbox{\hsize=\gezhu@leftspace \leftskip=0pt\rightskip=0pt \pretolerance=9999\tolerance=9999\parindent=0pt\hfuzz=3em \parskip=0pt \parshape\gezhu@parshape\relax ##1}% % extract the first \gezhu@lines lines and get the rest \setbox\gezhu@tmpboy=\vbox{% \unvbox\gezhu@tmpboy \gezhu@makehboxofhboxesandcount% output is \gezhu@tmpb@y \ifnum\gezhu@tmpcnt > \gezhu@lines \advance\gezhu@tmpcnt by -\gezhu@lines \fi \expandafter\gezhu@getfirsthboxes\expandafter{\the\gezhu@tmpcnt}% \global\setbox\gezhu@tmpb@x=\box\gezhu@tmpb@x \global\setbox\gezhu@tmpb@y=\box\gezhu@tmpb@y }% \ifdim\wd\gezhu@tmpb@x > 0pt \setbox0=\hbox{\raise\gezhu@gezhuraise\hbox{\gezhu@debugbox{\box\gezhu@tmpb@x}}}% \ht0=0pt\dp0=0pt\gezhu@debugboy{\box0}% \gezhu@break \gezhu@leftspace=\hsize \fi \else % no annotations at the end of line \setbox\gezhu@tmpb@y=\vbox{\hsize=\maxdimen\hbox{##1}}% %\hskip 0pt plus 0.7em \gezhu@break \gezhu@leftspace=\hsize \fi % now \gezhu@tmpb@y holds the remaining annotation text \loop \gezhu@makeparshape{\hsize}% % place gezhu annotation text in a vbox with specified parshape \setbox\gezhu@tmpboy=\vbox{% the hsize is the main text hsize \leftskip=0pt\rightskip=0pt% plus 0.1em minus 0.1em%\gezhu@tmpdim \pretolerance=9999\tolerance=9999\parindent=0pt\hfuzz=3em \parskip=0pt \parshape\gezhu@parshape \unvbox\gezhu@tmpb@y \gezhu@removehboxes \unskip % remove last \gezhu@cjkglue }% % extract the first \gezhu@lines lines and get the rest \setbox\gezhu@tmpboy=\vbox{% \unvbox\gezhu@tmpboy \gezhu@makehboxofhboxesandcount% output is \gezhu@tmpb@y \ifnum\gezhu@tmpcnt > \gezhu@lines \advance\gezhu@tmpcnt by -\gezhu@lines \fi \global\gezhu@tmpcnt=\gezhu@tmpcnt \expandafter\gezhu@getfirsthboxes\expandafter{\the\gezhu@tmpcnt}% \global\setbox\gezhu@tmpb@x=\box\gezhu@tmpb@x \global\setbox\gezhu@tmpb@y=\box\gezhu@tmpb@y }% \ifdim\wd\gezhu@tmpb@x > 0pt% enough for construct a whole big line \setbox\gezhu@tmpbox=\hbox{\box\gezhu@tmpb@x}% \setbox0=\hbox{\raise\gezhu@gezhuraise\hbox{\gezhu@debugbox{\box\gezhu@tmpbox}}}% \ht0=0pt\dp0=0pt\gezhu@debugboy{\box0}% \gezhu@break \gezhu@leftspace=\hsize \repeat % enter balancing module % \gezhu@tmpcnt is the number of lines in \gezhu@tmpb@y \ifhbox\gezhu@tmpb@y % no \gezhu@getfirsthboxes executed \expandafter\gezhu@getfirsthboxes\expandafter{\the\gezhu@tmpcnt}% \fi % now \gezhu@tmpb@y is vbox of hboxes without interlineskip % make \gezhu@tmpb@y hbox of hboxes without interlineskip \setbox\gezhu@tmpboy=\vbox{% \unvbox\gezhu@tmpb@y \gezhu@makehboxofhboxesandcount \global\gezhu@tmpcnt=\gezhu@tmpcnt \global\setbox\gezhu@tmpb@x=\box\gezhu@tmpb@x \global\setbox\gezhu@tmpb@y=\box\gezhu@tmpb@y }% % merge the inner hboxes, save the text in \gezhu@tmpbox \setbox\gezhu@tmpbox=\hbox{\unhbox\gezhu@tmpb@y\gezhu@removehboxes \unskip\unskip}% remove possible \parfillskip \gezhu@tmpdim=\wd\gezhu@tmpbox \divide\gezhu@tmpdim by \gezhu@lines \advance\gezhu@tmpdim by -0.3\gezhu@bigem % for cases of breaking at spaces % find best hsize for vbox \loop \setbox\gezhu@tmpboy=\vbox{\hsize=\gezhu@tmpdim \leftskip=0pt\rightskip=0pt% plus 0.1em minus 0.1em%\gezhu@tmpdim \pretolerance=9999\tolerance=9999\parindent=0pt\hfuzz=3em \parskip=0pt \parfillskip=\gezhu@parfillskip \unhcopy\gezhu@tmpbox }% \setbox\gezhu@tmpboy=\vbox{% \unvbox\gezhu@tmpboy \gezhu@makehboxofhboxesandcount \global\gezhu@tmpcnt=\gezhu@tmpcnt \global\setbox\gezhu@tmpb@x=\box\gezhu@tmpb@x \global\setbox\gezhu@tmpb@y=\box\gezhu@tmpb@y }% \ifnum\gezhu@tmpcnt > \gezhu@lines \advance\gezhu@tmpdim by 0.1\gezhu@bigem \repeat % now \gezhu@tmpdim is the almost optimal hsize for vbox % now find the longest line width when break with hsize=\gezhu@tmpdim \gezhu@tmpdil=\gezhu@tmpdim \setbox\gezhu@tmpboy=\vbox{% \hskip 0pt \unhbox\gezhu@tmpb@y \loop \ifnum\lastnodetype = 11% inter line skip \unskip \fi \setbox\gezhu@tmpb@x=\lastbox \ifhbox\gezhu@tmpb@x %\showbox\gezhu@tmpb@x \setbox\gezhu@tmpb@x=\hbox{\unhbox\gezhu@tmpb@x}% %\showbox\gezhu@tmpb@x \ifdim\gezhu@tmpdil < \wd\gezhu@tmpb@x \global\gezhu@tmpdil=\wd\gezhu@tmpb@x \fi \repeat \unskip }% % now \gezhu@tmpdil is the length of the longest line % the following lines tries to find a better hsize \advance\gezhu@tmpdil by -\gezhu@tmpdim \ifdim\gezhu@tmpdil > 0.45\gezhu@smallem \advance\gezhu@tmpdim by \gezhu@tmpdil \fi % normalize special treatment \ifgezhunormalize \gezhu@normalize % output in \gezhu@tmpdil \ifdim\gezhu@tmpdil < \dimexpr\gezhu@bigem/(\numexpr\gezhu@lines+1)\relax \gezhu@tmpdim=\dimexpr\gezhu@tmpdim+\gezhu@tmpdil\relax \fi \ifdim\gezhu@tmpdil > 0.9\gezhu@bigem \gezhu@tmpdim=\dimexpr\gezhu@tmpdim+\gezhu@tmpdil-\gezhu@bigem\relax \fi \fi % left space test \ifdim\gezhu@tmpdim > \gezhu@leftspace \gezhu@tmpdim=\gezhu@leftspace \fi % now \gezhu@tmpdim is the should-be length of the gezhu box %%%% \setbox\gezhu@tmpboy=\vbox{\hsize=\gezhu@tmpdim \leftskip=0pt\rightskip=0pt% plus 0.1em minus 0.1em%\gezhu@tmpdim \pretolerance=9999\tolerance=9999\parindent=0pt\hfuzz=3em \parskip=0pt \parfillskip=\gezhu@parfillskip \unhcopy\gezhu@tmpbox }% \setbox\gezhu@tmpboy=\vbox{% \unvbox\gezhu@tmpboy \gezhu@makehboxofhboxesandcount \global\gezhu@tmpcnt=\gezhu@tmpcnt \global\setbox\gezhu@tmpb@y=\box\gezhu@tmpb@y }% % now \gezhu@tmpb@y is the hbox of hboxes with interlineskip % next find the longest line width when break with hsize=\gezhu@tmpdim \gezhu@tmpdil=\gezhu@tmpdim \setbox\gezhu@tmpboy=\vbox{% \hskip 0pt \unhcopy\gezhu@tmpb@y \loop \ifnum\lastnodetype = 11% inter line skip \unskip \fi \setbox\gezhu@tmpb@x=\lastbox \ifhbox\gezhu@tmpb@x \setbox\gezhu@tmpb@x=\hbox{\unhbox\gezhu@tmpb@x}% \ifdim\gezhu@tmpdil < \wd\gezhu@tmpb@x \global\gezhu@tmpdil=\wd\gezhu@tmpb@x \fi \repeat \unskip }% % next, compensate for empty lines {\gezhu@getfirsthboxes{0}\global\setbox\gezhu@tmpb@x=\box\gezhu@tmpb@x}% \loop \ifnum\gezhu@tmpcnt < \gezhu@lines \advance\gezhu@tmpcnt by 1 %\setbox\gezhu@tmpb@y=\hbox{\unhbox\gezhu@tmpb@y\hbox{\the\gezhu@strut}}% \setbox\gezhu@tmpb@x=\vbox{\unvbox\gezhu@tmpb@x\vskip\baselineskip}% \repeat % now \gezhu@tmpb@x is the gezhu box \setbox0=\hbox{\raise\gezhu@gezhuraise\hbox{\gezhu@debugbox{\box\gezhu@tmpb@x}}}% \ht0=0pt\dp0=0pt\gezhu@debugboy{\box0}% \ifgezhunormalize \gezhu@debug{\raise-3pt\hbox{\the\gezhu@tmpdim}}% \gezhu@normalize % output in \gezhu@tmpdil \ifdim\gezhu@tmpdil > 0pt \nobreak\kern\gezhu@tmpdil \gezhu@debug{\raise 8pt\hbox{\the\gezhu@tmpdil, \the\gezhu@bigem}}% \fi \else \advance\gezhu@tmpdil by -\gezhu@tmpdim \ifdim\gezhu@tmpdil > 0.45\gezhu@smallem \nobreak\hskip 0.7\gezhu@tmpdil plus 0.3\gezhu@tmpdil minus 0.7\gezhu@tmpdil \advance\gezhu@tmpdim by 0.7\gezhu@tmpdil \fi \fi \endgroup \the\aftergezhu\relax }% \let\gezhu@oldpar\par \ifnum\gezhu@shipoutlevel > 0\relax \def\par{\unpenalty\unskip\unpenalty\unskip\unpenalty\gezhu@oldpar \global\gezhu@tmpdim=\prevdepth\egroup\prevdepth=\gezhu@tmpdim \gezhu@showbox\gezhu@tmpbox\unvbox\gezhu@tmpbox \endgraf%\gezhu@message{(\number\currentgrouptype)}% \setbox\gezhu@tmpbox=\vbox\bgroup \prevdepth=\gezhu@tmpdim \ifdim\gezhu@tmpdim > -1000pt \vskip 0pt% par skip go go go \fi }% \else \def\par{\ifhmode\unpenalty\unskip\unpenalty\unskip\unpenalty\fi\gezhu@oldpar}% \fi \endgraf \lineskiplimit=-\maxdimen\relax % only \baselineskip is to be used \the\everywithgezhu \ifdim\prevdepth = 0pt% we assume that it is the beginning of the page \gezhu@tmpdim=-1000pt \else \gezhu@tmpdim=\prevdepth \fi \setbox\gezhu@tmpbox=\vbox\bgroup \let\withgezhu\relax \ifdim\gezhu@tmpdim > -1000pt \prevdepth=\gezhu@tmpdim \vskip 0pt% par skip go go go \fi } \def\endwithgezhu{% \ifnum\gezhu@shipoutlevel > 0 \par\egroup \else \gezhu@oldpar\global\gezhu@tmpdim=\prevdepth\egroup\prevdepth=\gezhu@tmpdim \gezhu@showbox\gezhu@tmpbox\unvbox\gezhu@tmpbox \fi \endgroup } \def\setgezhulines#1{\global\gezhu@lines=#1\relax} \def\setgezhuraise#1{\global\gezhu@gezhuraise=#1\relax} \def\setgezhushipoutlevel#1{\global\gezhu@shipoutlevel=#1\relax} \def\gezhuraggedtrue{\global\gezhu@parfillskip=0pt plus 1fil\relax} \def\gezhuraggedfalse{\global\gezhu@parfillskip=0pt\relax} % fbox \newbox\gezhu@fbox@tmpbox \newdimen\gezhu@fbox@linewidth \newdimen\gezhu@fbox@tmpdim \newdimen\gezhu@fbox@tmpdil \gezhu@fbox@linewidth=0.4pt \long\def\gezhu@fbox#1{% \setbox\gezhu@fbox@tmpbox=\hbox{#1}% \gezhu@fbox@tmpdim=2\gezhu@fbox@linewidth \gezhu@fbox@tmpdil=\dp\gezhu@fbox@tmpbox \advance\gezhu@fbox@tmpdim\wd\gezhu@fbox@tmpbox \setbox\gezhu@fbox@tmpbox=\hbox{\hskip-\gezhu@fbox@linewidth\vbox{\vskip -\gezhu@fbox@linewidth\hrule height \gezhu@fbox@linewidth width \gezhu@fbox@tmpdim \hbox{\vrule width \gezhu@fbox@linewidth height \ht\gezhu@fbox@tmpbox \unhcopy\gezhu@fbox@tmpbox\vrule width \gezhu@fbox@linewidth height \ht\gezhu@fbox@tmpbox}% \hrule height \gezhu@fbox@linewidth width \gezhu@fbox@tmpdim \vskip -\gezhu@fbox@linewidth}\hskip-\gezhu@fbox@linewidth}% \leavevmode\raise-\gezhu@fbox@tmpdil\box\gezhu@fbox@tmpbox } \long\def\gezhu@baselinebox#1{% \setbox\gezhu@fbox@tmpbox=\hbox{#1}% \gezhu@fbox@tmpdil=\dp\gezhu@fbox@tmpbox \leavevmode\rlap{\hbox to \wd\gezhu@fbox@tmpbox{\hrulefill}}\box\gezhu@fbox@tmpbox } \fi