1

The codes of the two \vtop in the example below look very similar.

Difference is:

  • In case 1 you have \hbox{ccc\hfill}. Due to \hrule no \baselineskip-glue is inserted between bbb and ccc. TeX does not go into horizontal mode. No \parskip-glue is inserted between bbb and ccc. (No vertical glue at all is inserted between bbb and ccc.)
  • In case 2 you have ccc. Due to \hrule no \baselineskip-glue is inserted between bbb and ccc. TeX does go into horizontal mode. \parskip-glue is inserted between bbb and ccc.

Now assume a situation where you don't know if TeX will go into horizontal mode after the \hrule but in any case you don't want \parskip-glue/any vertical glue after the \hrule. In any case you want the thing to look like in case 1.

Is there a method to cancel or prevent \parskip glue in case material following the \hrule switches to horizontal mode without knowing before if this switching will happen?

\parindent=0ex
\parskip=4cm

\baselineskip=2cm

\hbox to\hsize{%
\vtop{\hsize=.3\hsize
  \hbox{aaa}
  \hbox{bbb}
  \hrule height 0mm depth 0mm\relax

  \hbox{ccc} %<- TeX stays in restricted vertical mode
  \par\hbox to\hsize{This is case 1\hfill}

}\hfill\vrule\hfill
\vtop{\hsize=.3\hsize
  \hbox{aaa}
  \hbox{bbb}
  \hrule height 0mm depth 0mm\relax

  ccc %<- TeX switches to horizontal mode
  \par\hbox to\hsize{This is case 2\hfill}
}%
}
\bye

enter image description here

0
1

You could do something like this

enter image description here

\parindent=0ex
\parskip=4cm

\baselineskip=2cm

\hbox to\hsize{%
\vtop{\hsize=.3\hsize
  \hbox{aaa}
  \hbox{bbb}
  \hrule height 0mm depth 0mm\relax
  \everypar{\setbox0=\lastbox\endgraf\everypar{}\vskip-2\parskip}

  \hbox{ccc} %<- TeX stays in restricted vertical mode
  \par\hbox to\hsize{This is case 1\hfill}

}\hfill\vrule\hfill
\vtop{\hsize=.3\hsize
  \hbox{aaa}
  \hbox{bbb}
  \hrule height 0mm depth 0mm\relax
  \everypar{\setbox0=\lastbox\endgraf\everypar{}\vskip-2\parskip}

  ccc %<- TeX switches to horizontal mode
  \par\hbox to\hsize{This is case 2\hfill}
}%
}
\bye
1

This answer is an attempt at further developing the answer of David Carlisle which aims at the hook \everypar whose tokens are delivered whenever TeX due to switching to horizontal mode has just delivered vertical \parskip-glue and started a horizontal list by inserting the \hbox of width \parindent.

As you focus on the "codes of the \vtop" and not on the \vtop itself I assume that the desired method is to work out also in (non-internal) vertical mode where probably some \begingroup..\endgroup-thingie might precede and more paragraphs might follow the \hbox{ccc}/ccc/\noindent ccc(?)-thingie.

Probably you can mess around with \everypar, \everyhbox, \everyvbox, \everymath, \everydisplay to make sure that not only the next paragraph but generally the next thing that is typeset will cancel the changes to \everyar. I have not yet thought about whether there are more obscure situations to consider in regard to "the next thing that is typeset".

In the example below the token \skiprestore respective \resetskiprestore is prepended permanently to each of the above-mentioned hooks. Usually these macros are no-ops.

The macro \makemydamnverticalgap redefines

  • \resetskiprestore to redefine \skiprestore and \resetskiprestore as no-ops.
  • \skiprestore to apply the redefined \resetskiprestore and to do some negative vertical skipping for cancelling out vertical \parskip-glue, to do \noindent in case the \hbox inserted for starting the horizontal list had the width 0pt.

I decided for prepending tokens to the hooks permanently because then redefining these tokens can be done in terms of \global which means that the desired changes will survive the wrapping into groups.

I don't know about the best way of implementing such a thing in LaTeX 2ε where the kernel itself plays around with all these \every...-hooks.

Also in LaTeX there is, e.g., the package everyhook which allows you to mess around with the \every...-hooks. Be aware that the current release (everyhook v1.2, dated 2014/11/26) has a bug which leads to amounts of consecutve hashes being halveed , e.g., ######## being halved to ####, whenever e.g., \PushPreHook, \PopPreHook, \PushPostHook, \PopPostHook and the like is carried out. (I addressed the issue on the package's GitHub-repository some months ago.)

\parindent=3ex
\parskip=.5cm

\long\def\exchange#1#2{#2#1}
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}

\newbox\mybox

\long\gdef\prependtohook#1#2{%
  #1=\expandafter{\romannumeral0\expandafter\exchange\expandafter{\the#1}{ #2}}
}%
\prependtohook\everypar{\skiprestore}
\prependtohook\everyhbox{\resetskiprestore}
\prependtohook\everyvbox{\resetskiprestore}
\prependtohook\everymath{\resetskiprestore}
\prependtohook\everydisplay{\resetskiprestore}
% I am not sure whether \resetskiprestore should be done with other hooks also.

\newbox\mybox

\gdef\skiprestore{}%
\gdef\resetskiprestore{}%
\long\def\makemydamnverticalgap#1{%
  \endgraf
  \hrule height 0mm depth 0mm\relax\nobreak
  \kern#1\nobreak
  \hrule height 0mm depth 0mm\relax
  \gdef\resetskiprestore{\gdef\skiprestore{}\gdef\resetskiprestore{}}%
  \gdef\skiprestore{%
    \resetskiprestore
    \setbox\mybox=\lastbox
    \vskip-2\parskip
    \endgraf\ifdim\wd\mybox>0pt \else\expandafter\noindent\fi
  }%
  \ignorespaces
}%


\noindent This is some paragraph.\xleaders\hbox{This is some paragraph.}\hfill This is some paragraph.
\begingroup
\makemydamnverticalgap{2cm}
\endgroup
\hbox{This does not switch to horizontal mode. There should be a vertical 2cm gap above this.}

This is another paragraph.

\noindent This is some paragraph.\xleaders\hbox{This is some paragraph.}\hfill This is some paragraph.
\begingroup
\makemydamnverticalgap{2cm}
\endgroup
\leavevmode This does switch to horizontal mode. There should be a vertical 2cm gap above this.

This is another paragraph.

\noindent This is some paragraph.\xleaders\hbox{This is some paragraph.}\hfill This is some paragraph.
\begingroup
\makemydamnverticalgap{2cm}
\endgroup
\noindent This does switch to horizontal mode. There should be a vertical 2cm gap above this.

This is another paragraph.

\xleaders\vbox{\hrule height 0pt width 0pt\par This is another paragraph.}\vfill\break

\parindent=1cm
\parskip=4cm
\baselineskip=2cm

\hbox to\hsize{%
  \vtop{\hsize=.25\hsize
    \hbox{aaa}
    \hbox{bbb}
    \makemydamnverticalgap{0cm}%

    \hbox{ccc} %<- TeX stays in restricted vertical mo\-de
    \par\vtop{\noindent This is case 1 - \TeX{} staying in restricted vertical mo\-de}
  }\hfill\vrule\hfill
  \vtop{\hsize=.25\hsize
    \hbox{aaa}
    \hbox{bbb}
    \makemydamnverticalgap{0cm}%

    ccc %<- TeX switches to horizontal mo\-de
    \par\vtop{\noindent This is case 2 - \TeX{} switching to horizontal mo\-de and inserting {\tt\string\par\-in\-dent}}
  }\hfill\vrule\hfill
  \vtop{\hsize=.25\hsize
    \hbox{aaa}
    \hbox{bbb}
    \makemydamnverticalgap{0cm}%

    \noindent ccc %<- TeX switches to horizontal mo\-de
    \par\vtop{\noindent This is case 3 - \TeX{} switching to horizontal mo\-de and not inserting {\tt\string\par\-in\-dent}}
  }
}

\bye

enter image description here

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.