# Kind of spurious space

I'm trying to write a \spaced macro: it takes a string as parameter, decompose that string and then recompose it spreading avery token from the others according to a given \spreadratio. Here are the macro along with an MWE:

\catcode\@=11

\font\sc="Latin Modern Roman Caps:mapping=tex-text,+onum"

\chardef\box@temp@la=0
\dimendef\dimen@temp@la=0
\dimendef\dimen@temp@lb=2
\toksdef\toks@temp@ga=1

% \boxit is only aimed to highlight the problem.
% If you wanna see the MWE without boxing just comment this
% definition and uncomment the following one.
\def\boxit#1{\vbox{\hrule\hbox{\vrule#1\vrule}\hrule}}
%\def\boxit#1{#1}

% The interface of \spaced is the following:
%
%    \spaced[<number>]{<token list>}
%
% where the optional parameter is the amount of \spreadratio
% other than the predefined one.
\def\spaced{\futurelet\firsttok\@spaced}

\def\@spaced{%
\if\firsttok[\let\next\@paramspaced
\else\let\next\@simplespaced\fi
\next}

\def\@simplespaced#1{\dosp@ced{#1}}

\def\dosp@ced#1{{\setbox\box@temp@la\hbox{#1}%
% the size of the \hbox is changed according
% to the value of \spreadratio
\dimen@temp@la\wd\box@temp@la \dimen@temp@lb\dimen@temp@la
\divide\dimen@temp@lb by\@m
\global\toks@temp@ga={}%
\@split{#1}%
\setbox\box@temp@la\hbox to\dimen@temp@la{\the\toks@temp@ga}%
\box\box@temp@la}}

\def\@split#1{\@@split#1\end}

\def\@@split#1{%
\ifx#1\end
\global\toks@temp@ga=\expandafter{\the\toks@temp@ga\unskip}%
\let\next\relax
\else
\global\toks@temp@ga=\expandafter{\the\toks@temp@ga#1\hfil}%
\let\next\@@split\fi
\next}

\catcode\@=12

\noindent
\boxit{The music}\par\noindent
\boxit{\spaced{The music of Steve Reich}}\par\noindent
\boxit{\spaced[300]{The music of Steve Reich}}\par\noindent
\boxit{{\sc The music of Steve Reich}}\par\noindent
\boxit{\spaced{\sc The music of Steve Reich}}\par\noindent
\boxit{\spaced[300]{\sc The music of Steve Reich}}\par\noindent
% Note that here are no spaces between '\it' and the word 'The'.
\boxit{{\it{}The music of Steve Reich}}\par\noindent
\boxit{\spaced{\it{}The music of Steve Reich}}\par\noindent
\boxit{\spaced[300]{\it{}The music of Steve Reich}}\par\noindent
\boxit{\spaced{The music of Steve Reich}}\par\noindent
\end


The result is the following.

As you can see (note the space before the word 'the') when the first token of the mandatory parameter is a macro (just like \sc or \it), \spaced adds a kind of spurious space before the second token.

I can't imagine where that space comes from, and I'm not able to eliminate it.

Where can be my fault?

-
It seems you want something at least similar to the soul package. Look up that code and you might find an answer. – Toscho Apr 20 '13 at 9:59
@Toscho yes, but above all I would like to understand where I went wrong without reading one thousand of lines or so. – Jean Baldraque Apr 20 '13 at 10:12
With \spaced{\sc A b} the token register is loaded with \sc \hfil A\hfil b\hfil \unskip because you add \hfil after the token no matter what the token is; and spaces disappear, but you probably already knew it. – egreg Apr 20 '13 at 10:18

Your splitting routine doesn't distinguish between letters and commands, so if you try \spaced{\sc A b} the final token list stored in \toks@temp@ga is

\sc \hfil A\hfil b\hfil \unskip


as you can see by adding \showthe\toks@temp@ga to your macros after \let\next\relax.

Of course, the splitting routine also gobbles spaces.

A different strategy is to use XeTeX features.

\catcode\@=11

\font\rm="Latin Modern Roman:mapping=tex-text,+onum" \rm
\font\sc="Latin Modern Roman Caps:mapping=tex-text,+onum"

\def\spaced{\futurelet\next\@spaced}
\def\@spaced{%
\ifx\next[%
\expandafter\@spacedopt
\else
\expandafter\@spacednonopt
\fi}
\def\@spacednonopt#1{#1}
\def\@getfontname{\expandafter\@removequotes\fontname\font}
\def\@removequotes"#1"{#1}
\begingroup\edef\x{\endgroup
\font\noexpand\@temp="\expandafter\@removequotes\fontname\font;#1;"%
\noexpand\@temp}\x}
\catcode@=12

\spaced[10]{The music of Bach} This is not spaced

\sc\spaced[10]{The music of Bach} This is not spaced
\bye


-
It's a good solution, but has some drawbacks: 1) it works only with XeTeX (and LuaTeX?), as far as it uses an Open Type feature; 2) It leave the original parameterization feature, as far as the letterspace Open Type mechanism is a bit strange (letterspace=x where the spreading is x/S with S=fontsize). I'm trying to implement \spaced in plain TeX, but it seems very difficult to determine where to expand a parameter and where not. – Jean Baldraque Apr 20 '13 at 13:33

@egreg says:

Your splitting routine doesn't distinguish between letters and commands, so if you try \spaced{\sc A b} the final token list stored in \toks@temp@ga is

\sc \hfil A\hfil b\hfil \unskip


as you can see by adding \showthe\toks@temp@ga to your macros after \let\next\relax.

Well, according to this explanation (and my concerns about parameterization of the macro) I've changed the splitting routine in the following way

\def\@@split#1{%
\ifx#1\end
\global\toks@temp@ga=\expandafter{\the\toks@temp@ga\unskip}%
\let\next\relax
\else
% here the routine should dinstiguish
% between letters and commands
%
\ifcat\noexpand#1\relax
\global\toks@temp@ga=\expandafter{\the\toks@temp@ga#1}%
\let\next\@@split
%
% %%%
\else
\global\toks@temp@ga=\expandafter{\the\toks@temp@ga#1\hfil}%
\let\next\@@split\fi\fi
\next}


It seems to work properly, but if egreg did not suggest this system there must be a problem.

Is it only a sense of insecurity, or a subtle bug is hidden into the code?

-
I removed my comments. You're using the wrong tool: no letter spacing command can work if you first don't take care of spaces between words. – egreg Apr 21 '13 at 10:24