How is \catcode handled?
\centerline
is defined by \def\centerline#1{\line{\hss#1\hss}}
but \line
is defined by \def\line{\hbox to\hsize}
. It means that \line{next text}
does not take the next text as parameter. The next text is processed inside \hbox
primitive in main processor of TeX. If there is an assignment (like \catcode
setting) then this is done immediately and then next characters are read (and tokenized). On the other hand, \centerline{next text}
reads the next text as a parameter first. All characters are tokenized in this state, but assignment is not done. After parameter is read and tokenized then in is used in the context \hbox...{..next text..}
but all characters are tokenized here. So, \catcode
setting has no effect now. Only, of course, the \the\catcode
report is changed. This report prints the value used by token processor for next characters, which are not tokenized already.
Some complements to wipet's good answer.
The definitions in plain.tex
are as follows (lines 575–578):
\def\line{\hbox to\hsize}
\def\leftline#1{\line{#1\hss}}
\def\rightline#1{\line{\hss#1}}
\def\centerline#1{\line{\hss#1\hss}}
You can notice that \line
is just shorthand for \hbox to\hsize
, so the call
\line{\hss"hello world\the\catcode`\ "\hss}
becomes
\hbox to\hsize{\hss"hello world\the\catcode`\ "\hss}
One might think that such a call will obey the same rules as
\centerline{\hss"hello world\the\catcode`\ "\hss}
that is, {\hss"hello world\the\catcode`\ "\hss}
is absorbed as an argument to \hbox
, but there's a fundamental difference between the two cases.
You should be aware of this, because you're defining active "
to do \hbox\bgroup
and macros taking an argument don't allow such a syntax for denoting the start of the argument. On page 278 of the TeXbook, you find the syntax for \hbox
:
\hbox
⟨box specification⟩{
⟨horizontal mode material⟩}
and such notation means that the braces can also be implicit characters having category code 1 and 2 respectively. In these cases, the material inside these braces is only scanned after {
is processed (here, also after the material in \everyhbox
and possibly \afterassignment
has been inserted). The matching }
will start the operation of converting the horizontal list into a box.
In particular,
\hbox{\catcode`\ =12 a b}
will perform the category code assignment and the space will be absorbed with category code 12.
To the contrary, \centerline{\catcode`\ =12 a b}
will absorb the argument tokenizing it (as explained by Petr). When TeX is absorbing an argument, it performs no expansion and no assignment; if the argument is undelimited (as in the case of \centerline
), the argument will be the next token (after skipping explicit space tokens) unless this token is a left brace (explicit character with category code 1), when the argument will be the tokens up to the matching right brace (explicit character with category code 2). Tokenization is performed, so the spaces will be of category code 10.
Is it possible to solve this problem? Yes, with e-TeX.
\catcode`\"=\active
\def"#1"{%
\leavevmode\hbox{%
\catcode`\ =12
\tt
\scantokens{#1\relax}%
}%
}
\line{\hss X"hello world"X\hss}
\centerline{X"hello world"X}
\bye