5

I like that (La)TeX by default puts extra space between sentences, but I find that the default settings, at for most fonts, can make inter-sentence spaces too "stretchy" compared to regular spaces when a line must be stretched to achieve full justification.

I want to tweak my document class so that it puts extra space after periods and question marks, etc., but so that these are larger by regular spaces by a constant amount: they should still stretch to achieve full justification, but they should stretch no more than a regular space would stretch.

(For example, if a regular space is 3.3pt, and a inter-sentence space is 4.4pt where there is no stretch, if a regular space on a given line stretches to 4.3pt, the inter-sentence space should stretch to 5.4pt, and not stretch more than the regular space does.)

Or at least I think that's what I want. I haven't actually accomplished it yet, so it's hard to know for sure if I'll like it!

I read Chapter 20 of TeX by Topic, which deals with some of the issues. It was a bit over my head at points, but as near as I can tell, the value \fontdimen7, which is the extra space after periods and question marks, is only ever used when the spacefactor set by \sfcode for the punctuation marks in question is 2000 or greater. But then, by definition, the "strechiness" for the generated spaces is multiplied by two. If the spacefactor is less than 2000, then no extra space is added, as one can see in this example:

\documentclass[12pt]{article}
\usepackage{kantlipsum}

\begin{document}
% this sets a really high fontdim7 to make it obvious 
% when the extra space is added
\fontdimen7\font=15pt

\sfcode`.=2000

\kant[1]

% i really want this to be 1000, but anything lower than 2000 makes
% \fontdimen7 irrelevant
\sfcode`.=1999

\kant[1]

\end{document}

Is there a way to achieve non-french-spacing where the added extra space is a constant amount?

6

Yes it's possible. For example, you can do

\xspaceskip=\fontdimen2\font plus \fontdimen3\font minus \fontdimen4\font
\advance\xspaceskip by \fontdimen7\font

Example

results

\hsize = 0.7\hsize
\parindent=0pt

\bigskip Without stretch:

In this line. Do spaces stretch? Equally or not?

\bigskip Default stretch:

\line{In this line. Do spaces stretch? Equally or not?}

\xspaceskip=\fontdimen2\font plus \fontdimen3\font minus \fontdimen4\font
\advance\xspaceskip by \fontdimen7\font

\bigskip Modified stretch:

\line{In this line. Do spaces stretch? Equally or not?}

\bye

Seeing the defaults

First, for an understanding of what the “normal” glue values are, and how those values are computed, you can try the following file with tex:

A sentence. Another.
\tracingoutput=1 \tracingonline=1 \showboxbreadth=30
\bye

or, with LaTeX:

\documentclass{article}
\begin{document}
A sentence. Another.
\showoutput
\end{document}

(You can also add \showthe\fontdimen7\font and \showthe\sfcode`. to see those respective values.) What the output shows is that the inter-word glue and inter-sentence glue are, respectively:

3.33333 plus 1.66498 minus 1.11221
4.44444 plus 4.99997 minus 0.37036

with larger values for \documentclass[12pt]{article} of course.

Where do these come from? How does TeX decide spaces?

How TeX turns spaces into glue

This is explained on pages 75–76 of The TeXbook. (See also the useful answer to How Can I Find the Length of a Space in TeX?.) Basically, TeX maintains an integer called the current “space factor” (denoted f), which is updated after every character (every box in a horizontal list).

  • Initially (and most of the time), f is 1000.

  • Every character has an \sfcode. By default, this is 999 for uppercase letters (A-Z), and 1000 for all other characters. Further, plain TeX sets the \sfcode of some more characters:

    • of ) and ' and ] to 0,
    • (under \nonfrenchspacing) of . and ? and ! to 3000
    • (under \nonfrenchspacing) of : to 2000,
    • (under \nonfrenchspacing) of ; to 1500,
    • (under \nonfrenchspacing) of , to 1250.

    In fact, the only effect of \nonfrenchspacing and \frenchspacing is to set the \sfcodes of the above characters to the above values and back to 1000, respectively. And after a character with \sfcode equal to some number (say g), the effect on f is:

    • If g = 0, then f remains unchanged.
    • If f < 1000 < g, then f gets the value 1000. (Consider M.)
    • Otherwise, f gets the value of g.
  • There is also the normal interword glue. If \spaceskip has been set nonzero, then it is \spaceskip. Else it comes from the font: specifically, it is \fontdimen2\font plus \fontdimen3\font minus \fontdimen4\font. Whatever it is (whether it comes from \spaceskip or the font), let's say it is <x> plus <y> minus <z>, meaning a glue whose ideal width is x, stretchability is y, and shrinkability is z.

Got all that? Good, now when TeX encounters a space, it computes a glue as follows:

  • If f ≥ 2000 and \xspaceskip is nonzero, then the glue is \xspaceskip. Done. (Ignore all cases below.) Else,
  • As said above, suppose the “normal” interword glue (coming from either \spaceskip or the font) is <x> plus <y> minus <z>.
  • If f ≥ 2000 then the “ideal” width is <x> + \fontdimen7\font. The thing added here is the “extra space” parameter that comes from the font.
  • The stretchability is y * f/1000. (That is, the normal stretch is multiplied by f/1000.)
  • The shrinkability is z * 1000/f. (That is, the normal shrink is multiplied by 1000/f.)

Conclusion

For the purposes of this question, the main thing to remember from all this is that, with \nonfrenchspacing and with . having its usual \sfcode of 3000,

  • The inter-word glue is either \spaceskip (if nonzero), or else \fontdimen2\font with stretchability \fontdimen3\font and shrinkability \fontdimen4\font
  • The inter-sentence glue is either \xspaceskip (if nonzero) or else \fontdimen7\font more than the inter-word glue (as above), with stretchability 3 times that of the inter-word glue, and shrinkability 1/3rd of it.

Note that under the default settings, the inter-sentence glue has three times the stretchability of the inter-word glue, which is what you're complaining about. But to change this, you really don't have to bother with \sfcode; you can just set \spaceskip and \xspaceskip to whatever values of ideal width, stretchability and shrinkability you'd like.

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.