# Written response spaces for a workbook in ConTeXt

I am making a workbook in ConTeXt. Throughout the workbook, there will be many spaces for the owner to write in short answers of one or two paragraphs. This can be quite simple, perhaps just a question, followed by several thin, horizontal lines on which one can write. E.g.:

1. What was the most interesting part of the story?
__________________________________________________
__________________________________________________
__________________________________________________
__________________________________________________
__________________________________________________
__________________________________________________


Does TeX or ConTeXt have any standard method for providing such a space?

Are there any algorithms in place within TeX or ConTeXt for specifying proper typographical placement of these elements and where breaks should appear? Here is an example of what I mean (although not necessarily ideal):

• No page break should be placed inside the writing area, unless the area before and after the break has at least 3 lines.
• No page break should be placed between the question and the writing area.
• Rather than specifying an exact number of lines, a range can be specified (e.g. 5 to 8 lines). E.g. If it prints 5 lines, but finds the rest of the page is empty, it can add up to 3 additional lines until the page is filled).
-
Btw, use a dotted line if possible, as it lessens the line weight that would otherwise dominate the page. –  Andrey Vihrov Feb 28 '12 at 12:07
Dotted lines seems good. –  Village Feb 28 '12 at 12:43
I don't understand your specifications. What does "fit the page best mean"? If I specify 5-8 lines, and the page has 9 lines remaining, and the next question is two lines followed by a 6 line answer, how should the page breaks occur? Similarly, what should happen if the page has two lines remaining (can't have a page break between question and answer, and can't break the lines)? It will be much easier to give a TeX/ConTeXt solution if you can specify the desired behaviour in pseudo-code with all the corner cases covered. –  Aditya Feb 28 '12 at 13:14
By fitting the page best, I meant, if some empty space was available, it could use 6-8 lines (as needed to fill the empty space, otherwise, it would just use 5 lines. I think that would require ConTeXt to render the questions in reverse order though, which I am not sure if is possible. If it can't put a break between lines, it should move the entire question to the next page. –  Village Feb 28 '12 at 14:25

In addition to egregs solution I want to present another solution that has a more ConTeXtish interface and supports minimal and maximal values.

Warning: I didn't test this code extensively, it might break unexpectedly.

\def\startmyrules{%
\dosingleempty\dostartmyrules}

\def\dostartmyrules[#1]#2\stopmyrules{%
\bgroup
\define\linesleft{\numexpr(\pagegoal-\pagetotal)/\lineheight\relax}
\getparameters[MR][#1]
\setbox\scratchbox\vbox{#2}
\nobreak % avoid page break after head
\determinenoflines{\scratchbox}
% more space available then max lines + head
\ifnum\linesleft>\numexpr\MRmax+\noflines\relax
#2\crlf
\thinrules[n=\MRmax]
\else
\ifnum\linesleft<\numexpr\MRmin+\noflines+1\relax
\page
#2\crlf
\thinrules[n=\MRmax]
% remaining space is between min and max + head
\else
\scratchcounter\MRmax
\loop\ifnum\scratchcounter>\numexpr\MRmin-1\relax
\ifnum\linesleft>\numexpr\scratchcounter+\noflines\relax
#2\crlf
\thinrules[n=\scratchcounter]
\fi
\repeat
\fi
\fi
\egroup
}


Demonstration that it works in some simple cases:

\starttext

\dorecurse{35}{\recurselevel\crlf}

\startmyrules [min=2, max=8]
1. What was the most interesting part of the story?
\stopmyrules
\page

\dorecurse{36}{\recurselevel\crlf}

\startmyrules [min=2, max=8]
1. What was the most interesting part of the story?
\stopmyrules
\page

\dorecurse{37}{\recurselevel\crlf}

\startmyrules [min=2, max=8]
1. What was the most interesting part of the story?
\stopmyrules

\stoptext


The output is:

The algorithm is as follows: If there is enough space for the head (the line what was the most… in this case) and the maximal number of lines provided as an argument, then they get printed. On the other hand if there is not enough space for the minimal amount of lines incl. head, everything is moved to another page. If it is inbetween, then a loop is invoked to determine the optimal number of lines.

-

Here's an attempt. Some code can be added to avoid breaks before three lines have been printed or less than three lines are to be typeset. If you don't want that the rest of last question line has a rule, then delay the setting of \parfillskip=0pt to just before the loop and turn the first four lines of \stopplainlines into \par.

\def\startplainlines#1{%
\par\begingroup
\parindent=0pt
\parfillskip=0pt
\def\numberoflines{#1}%
}
\def\stopplainlines{%
\unskip % emulate \par's behavior
\hskip.5em plus .2em minus .1em\nobreak\penalty-50 % insert a good break point
\hbox{}\nobreak %
\hrulefill\hbox{}\par % fill the remaining space with a rule
\nobreak % don't break a page here
\baselineskip=1.2\baselineskip
\count255=\numberoflines\relax
\loop\ifnum\count255>0 % produce the requested number of lines
\leavevmode\hrulefill\hbox{}\endgraf
\repeat
\endgroup
}

\startplainlines{4}
Give a short proof of Fermat's last theorem
\stopplainlines

\bye


-
Fantastic answer! :) I'd need way more lines though. Cuius rei demonstrationem mirabilem sane detexi hanc marginis exiguitas non caperet. :P –  Paulo Cereda Feb 28 '12 at 14:17