# Wrong calculation of Length of Text if its at the end of the sentence. (shrinking problem)

My goal: I need the exact length of the printed text

The default width is 345 pt as you see.

But if I calculate

the textwidth of "some text .... some" I get 347.069 pt and

if I calculate "some text .... someE" I get 352.039 pt

This should not happen, because both text are 1 full line and therefore it should be max. 345 pt. How can I fix this issue? Thanks!

\documentclass[10pt]{article}
\usepackage[T1]{fontenc}
\usepackage[sfdefault,condensed,light]{roboto}
\usepackage[utf8]{inputenc}
\setlength{\parindent}{0pt} % = global \noindent

\begin{document}

The text width is: \the\textwidth

some text some text some text some text some text some text some text some text some

\newlength{\myl}
\settowidth{\myl}{some text some text some text some text some text some text some text some text some}
\the\myl

some text some text some text some text some text some text some text some text someE
\newlength{\myle}
\settowidth{\myle}{some text some text some text some text some text some text some text some text someE}
\the\myle

\end{document}

• \settowidth just calculates the natural length of the text, where spaces do not stretch or shrink as it happens when TeX builds paragraphs. It has nothing to do with \textwidth. What exactly are you trying to achieve? – campa Mar 3 at 11:38
• I need the length of "some text .... someE" including the spaces. The whole length from beginning (s) to end (E). – Bilal Yilmaz Mar 3 at 11:40
• Well, \settowidth is doing just that. But as I said, it has nothing to do with \textwidth. – campa Mar 3 at 11:41
• ...but spaces are elastic in TeX (this is probably one of the best parts of it!). You can have the "natural length", but that will change if you don't freeze it in a box. But I suspect this is an XY problem: meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Rmano Mar 3 at 11:42
• \settowidth{\nlen}{blah blah} gives in \nlen the natural length. You have exactly that length (minus surrounding spaces) if you typeset \mbox{blah blah} (now the space between the words is frozen). But I still think this is an XY problem... – Rmano Mar 3 at 11:50

tabto to the rescue. It can measure the horizontal text location "in place". So, one can measure at two locations and subtract the difference. But beware!! If the text being measured line wraps, then it will produce likely a negative number, as the final position of the text may end up to the left of the initial position.

In such a case, perhaps something could be done, if the OP could constrain the problem more...for example, the total width of the measured text must be less than \linewidth, but allowing for a single line-wrap if the measurement starts mid-line. That is what I do below.

\documentclass[10pt]{article}
\usepackage[T1]{fontenc}
\usepackage[sfdefault,condensed,light]{roboto}
\usepackage[utf8]{inputenc}
\setlength{\parindent}{0pt} % = global \noindent
\usepackage{tabto}
\makeatletter
\newcommand\settoactualwidth[2]{%
\tabto*{0pt}%
\@tempdima=\TabPrevPos\relax
\tabto{\TabPrevPos}
#2%
\tabto*{0pt}%
\ifdim\TabPrevPos>\@tempdima\relax
#1=\dimexpr\TabPrevPos-\@tempdima\relax
\else
#1=\dimexpr\TabPrevPos-\@tempdima + \linewidth\relax
\fi
\tabto{\TabPrevPos}}
\makeatother
\begin{document}
The text width is: \the\textwidth

some text some text some text some text some text some text some text some text some

\newlength{\myl}
\settoactualwidth{\myl}{some text some text some text some text some text some text some text some text some}
\the\myl

some text some text some text some text some text some text some text some text someE
\newlength{\myle}
\settoactualwidth{\myle}{some text some text some text some text some text some text some text some text someE}
\the\myle

\hspace{.8in}\settoactualwidth{\myl}{some text some text some text some text some text some text some text some}
\the\myl

\end{document}


• I have to upvote for the mind-reading powers :-) because I still have no idea what the OP is actually wanting... – campa Mar 3 at 13:55
• @campa Thanks. The only logical conclusion I could reach is that, if he wants glue to be accounted for, he must actually be interested in a position on the paper, rather than a characteristic of the abstract text itself. – Steven B. Segletes Mar 3 at 13:57

I suggest the macro \measurew{text} which measures the width of the text in \vbox and sets the result to \tmpdim register.

The macro \try only shows the effect, i.e. it draws the rule below measured text with the width \tmpdim and prints the value of \tmpdim.

\newdimen\tmpdim
\def\measurew#1{\setbox0=\vbox{#1\par
\setbox0=\lastbox \global\setbox0=\hbox{\unhbox0}
\global\tmpdim=\ifdim\wd0>\hsize \hsize \else \wd0 \fi
\unskip\unskip\unpenalty \setbox0=\lastbox
\ifvoid0 \else \global\tmpdim=\hsize \fi
}}

\def\try#1{#1\medskip\measurew{#1}\hrule width\the\tmpdim
\medskip \hbox{\the\tmpdim}\bigskip}

\hsize=8cm

\noindent hsize=\the\hsize
\medskip

\try{Text.}

\try{Long long text.}

\try{Long long text. Long long text. Long long text.}

\try{Long long text. Long long text. Long long texttt.}

\try{Long long text. Long long text. Long long long text.}

\bye