On 6/9/2021 7:30 PM, Michael Urban wrote:
I am not especially facile with ConTeXt, and it has been years since I did 
anything complex with TeX, so I am hoping someone could help me with this.  The 
following is probably not great code, but it shows what I am trying to do.
The problems are twofold: a benign problem is that I get underfull hbox errors 
(\dontcomplain notwithstanding).  But the other problem is that with text of a 
certain size, the final line is much shorter than the others.  Is there some 
clever way to repeatedly typeset the text (e.g., put it in an hbox, measure the 
width, and repeatedly try .5, .333, .25 of the hbox width until it fits in the 
allocated space)?  How to go about this?



\defineblank[EpigraphDistance][3pt]

\definestartstop[EpigraphText][
    style=\ssa,
    before={\blank[EpigraphDistance]
       \setupnarrower[left=.25\textwidth,right=0pt]
       \startnarrower[left,right]
       \setupalign[flushright,nothyphenated,broad]
       \dontcomplain
       \noindent},
    after={\stopalignment\stopnarrower
       \blank[EpigraphDistance]
       \indenting[next]}]


\long\def\epigraph#1#2#3{%
  \startEpigraphText #1 \par \stopEpigraphText
  \ifx\hfuzz#3\hfuzz
   \rightaligned{\ssa\sl --- #2}
  \else
   \rightaligned{\ssa\sl --- #2, \tf\ssa\symbol[leftquote]#3\symbol[rightquote]}
  \fi
}

\starttext
Testing epigraph

\epigraph{% para
\quotation{My birthday-present!} he whispered to himself, as he had often done
in the endless dark days. \quotation{That's what we\unknown}
}{J.R.R. Tolkien}{The Hobbit}

That was an epigraph.

\stoptext
I assume that when you see some trickery that you can do the rest yourself.


\starttext

First we typeset the box ad one line and then flush it in a vertical box (paragraph). We can of course also typeset each time. When we're okay with the fit (naturalwidth == less than max width) we quit. We can assume that spaces have enough stretch to deal with the close fit.

\protected\def\makeitfit#1#2#3%
  {\begingroup
   \hsize#1\relax
   \setbox\scratchboxone\hbox\bgroup#3\egroup
   \doloop {%
      \setbox\scratchboxtwo\vbox\bgroup\unhcopy\scratchboxone\egroup
      \scratchdimenone\boxlinenw\scratchboxtwo\boxlines\scratchboxtwo
      \scratchdimentwo\boxlinewd\scratchboxtwo\boxlines\scratchboxtwo
      \ifdim\scratchdimenone<\scratchdimentwo
        \advance\hsize-#2\relax
      \else
        \unhbox\scratchboxone
        \exitloop
      \fi
   }%
   \endgroup}

This variant is more neat as it returns the to b eused width. It doesn't flush the content.

\protected\def\guessbestwidth#1#2#3% no \protected when no \dimexpr
  {\beginlocalcontrol
   \begingroup
   \hsize#1\relax
   \setbox\scratchboxone\hbox\bgroup#3\egroup
   \doloop {%
      \setbox\scratchboxtwo\vbox\bgroup\unhcopy\scratchboxone\egroup
      \scratchcounter\boxlines\scratchboxtwo % n of lines
      \scratchdimenone\boxlinenw\scratchboxtwo\scratchcounter
      \scratchdimentwo\boxlinewd\scratchboxtwo\scratchcounter
      \ifdim\scratchdimenone<\scratchdimentwo
        \advance\hsize-#2\relax
      \else
        \exitloop
      \fi
   }%
 % \normalexpanded{\endgroup\endlocalcontrol\the\hsize}}
   \normalexpanded{\endgroup\endlocalcontrol\dimexpr\the\hsize\relax}}

Here are some tests:

\makeitfit{10cm}{1mm}{\input{ward}}

\hsize \guessbestwidth{10cm}{1mm}{\input{ward}}

\input{ward}

\the\guessbestwidth{10cm}{1mm}{\input{ward}}

\stoptext

The mechanisms used are relatively simple:

- good old tex primitives
- few scratch registers
- a loop that we quit
- the boxlines mechanism discussed in some manual (i admit that i already had forgotten about it) - and in the last example some local processing magic which makes sure that all these calculations are unseen

One can then of course try to make it more compact:

\protected\def\guessbestwidth#1#2#3%
  {\beginlocalcontrol
   \begingroup
   \hsize#1\relax
   \setbox\scratchboxone\hbox\bgroup#3\egroup
   \doloop {%
      \setbox\scratchboxtwo\vbox\bgroup\unhcopy\scratchboxone\egroup
      \scratchcounter\boxlines\scratchboxtwo

\ifdim\boxlinenw\scratchboxtwo\scratchcounter<\boxlinewd\scratchboxtwo\scratchcounter
        \advance\hsize-#2\relax
      \else
        \exitloop
      \fi
   }%
   \normalexpanded{\endgroup\endlocalcontrol\dimexpr\the\hsize\relax}}

And of course you now need to wikify it.

Hans


-----------------------------------------------------------------
                                          Hans Hagen | PRAGMA ADE
              Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
       tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the 
Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

Reply via email to