Weird \hfill behavior with custom length calculations?

I asked a question earlier about trying to write a macro/environment that would take in a number of \choice commands and then write them out in a way to minimize vertical space consumed, but still horizontally align the choices in some visually decent way.

There was an answer submitted that didn't quite give me what I was trying for, but it pointed me in a good direction to attempt another solution method. Unfortunately, after a lot of trial and error and reading documentation I seem to have some very strange behavior when trying to use hspace versus forced hspace (eg hspace*) of various forms. I am pretty sure the problem is in how the \qb@xlen is being calculated in the \printChoices command of the cls file, but I can't write a good MWE that properly reproduces my problem without the full cls (probably because I just don't really know enough about how these things are expanded/calculated). You can find the full cls file here.

The relevant part of the cls file (I think; as I say, I'm not 100% sure) is the following command:

\providecommand{\printChoices}{% \printChoices is an internal macro to print the choices at the end of a MCChoice environment, depending on if we want them shuffled or not.

%First, we make the call vector based on if we are shuffling these or not.
\ifshuffleChoices% If we are shuffling, then shuffle up the call
\make@Vector[InnerShuffle=true]{choiceLoc}{1}{\arabic{choiceNum}}{\arabic{choiceNum}}
\else% Otherwise, display them in original first to last order.
\make@Vector[InnerShuffle=false, Order@Direction=forward]{choiceLoc}{1}{\arabic{choiceNum}}{\arabic{choiceNum}}
\fi

% Now print the results:

\stepcounter{choiceNum}% Step counter for the < symbol in foreloop.
\newdimen\qb@xlen \qb@xlen 0pt

\forloop{Iteration@printChoices}{1}{\arabic{Iteration@printChoices}<\arabic{choiceNum}}{% Begin forloop
%\qb@xlen 0pt
\parindent=0pt
\newbox\ch@icebox
\setbox\ch@icebox\hbox{\textbf{\expandafter\choiceLetter{\arabic{Iteration@printChoices}}} % Print the correct letter of the choice. Note that \hspace*{0pt} forces the \hfill to populate correctly, or else TeX will ignore it at the start of lines which makes everything look super weird.
\csname \Roman{choiceEnvNum}choice\expandafter\roman{choiceLoc\Roman{Iteration@printChoices}}\endcsname }
\ifdim \wd\ch@icebox > \textwidth
% Too wide!
\hfill \par \unhbox\ch@icebox \hfill \par
\qb@xlen=0pt
\else
\ifdim \qb@xlen > \textwidth
\par  \hfill  \box\ch@icebox \hspace*{\fill}
\qb@xlen=\wd\ch@icebox
\else
\hfill \box\ch@icebox \hspace*{0pt} \hfill
\fi
\fi
}% End forloop
%\hspace*{\fill}
% Check to see if we have a "last choice".
\ifcsname\Roman{choiceEnvNum}lastChoice\endcsname% If we do, then we should print it.
\hspace*{0pt}\hfill\hbox{\expandafter\choiceLetter{\arabic{choiceNum}} % Since we stepped choiceNum this hack will work.
\csname \Roman{choiceEnvNum}lastChoice\endcsname}\hfill% Print lastChoice
\fi%
}% End of \printChoices code.


Using that cls, consider the following MWE:

\documentclass[]{MyExam}

\usepackage{gensymb, pgfplots}
\pgfplotsset{my style/.append style={axis x line=middle, axis y line=
middle, xlabel={$x$}, ylabel={$y$} }}
\parindent=0pt
\SetExamForm{A}
\SetExamNum{2}
\SetCoordinator{Jason Nowell}
\SetCourse{MAC 1140}
\SetTerm{Fall}
\SetExamLength{90 minutes}
\writeKey

\begin{document}
%\FrontPage
\begin{MCQuestions}

\question{Identify the coordinates of the points shown on the graph.
\begin{center}
\begin{tikzpicture}
\begin{axis}[my style, axis equal ,grid=both, grid style={line width=.1pt, draw=gray!10}, minor tick num=1, ymax=6, ymin=-4]

\node[label={180:{$c$}},circle,fill,inner sep=2pt] at (axis cs:2,1) {};
\node[label={180:{$a$}},circle,fill,inner sep=2pt] at (axis cs:-5,-3) {};
\node[label={0:{$b$}},circle,fill,inner sep=2pt] at (axis cs:0,4) {};
\end{axis}
\end{tikzpicture}
\end{center}
\begin{choices}
\choice[correct]{a: (-5, -3); b: (0,4); c: (2,1)}
\choice{a: (-3, 5); b: (-4,0); c: (-1,2)}
\choice{a: (5, 3); b: (0,-4); c: (-2,-1)}
\choice{a: (-3,-5); b: (4,0); c: (1,2)}
\choice{a: (5, -3); b: (0,4); c: (-2,1)}
\end{choices}
}

\question{When someone calls you and they are in your contacts, your phone uses their phone number to display their name.  What are the domain and codomain of this relationship?
\begin{choices}
\choice[correct]{Domain: phone numbers in your contacts; Codomain: names}
\choice{Domain: phone numbers; Codomain: names}
\choice{Domain: names in your contacts; Codomain: phone numbers}
\choice{Domain: names; Codomain: phone numbers}
\end{choices}
}
\end{MCQuestions}
\end{document}


If you compile the above, the choices in the first problem are presented with choice A and B on the first line in a (reasonably) nice presentation. Then choice C is on the second line all by itself pushed way off to the right. Then choices D and E are on a single line in a reasonably nice way.

I figured this is because the \hfill is not being forced (at the end of) the line:

\ifdim \qb@xlen > \textwidth
\par  \hfill  \box\ch@icebox \hfill
\qb@xlen=\wd\ch@icebox


However, if I replace that section with:

\ifdim \qb@xlen > \textwidth
\par  \hfill  \box\ch@icebox \hspace*{\fill}
\qb@xlen=\wd\ch@icebox


it fixes the first question, but it causes any long choices that occur after another choice to go off the page to the right, such as with the second question in the MWE. I'm pretty sure this is caused by the hbox not letting the line get shifted to a new line.

Unfortunately, if I find a way to fix one of these problems, it generates the other one. I can't seem to find a way to avoid both issues simultaneously. Honestly I'd even be happy to have some fixed hspace between each choice (say, 1cm) and let it line-break as needed as long as each choice is presented without breaking it across lines unless it takes up more than an entire line itself.

I only sort of know how the hspace* vs hspace works (forcing versus not forcing the space). Moreover, the \par command seems to be acting weird with when the \hspace vs \hspace* are being expanded... some error checking code was showing that things that look like \par\hspace or \par\hfill seem to expand the horizontal space before the new paragraph piece, which seems odd.

• white soace is ignored at the end of a line so \par\hfill is the same as \par perhaps you want to use \hspace*{\fill} instead, but please post a full example. Also you probaly don't want \newdimen inside (any) macro best to do that just once at the start. – David Carlisle Oct 4 '18 at 6:45
• @John The document class is the cls file that I linked to, as I explained in the question. @David That was what I thought, except when I use that \hspace*{\fill} I generate the other problem, as I explain in the question. – Jason Oct 4 '18 at 12:31
• It just seems like every adjustment I do has almost the opposite effect to what I'd expect. For instance... if I get rid of literally every \hspace and \hfill in the alignment section of \printchocies I would expect that I'd get maximal horizontal filling... leading to everything being squished together horizontally and very little vertical expansion on the page. What I ACTUALLY get is suddenly every choice is on it's own line... the literal polar opposite of what I expected. And I have no idea why... :/. – Jason Oct 4 '18 at 14:04
• There is really to much code here to debug, the placement of a tikzpicture is the same as the placement of a \rule{width}{height} of the same size, so can you not make a small example using article class and some rules and spaces that demonstrates whatever you need to ask about, for anyone tracing the behaviour of tex to answer your question, having tikz there adds thousands of extra commands to step through – David Carlisle Oct 4 '18 at 14:37