%D \module %D [ file=spac-hor, %D version=2009.10.16, % 1997.03.31, was core-spa.tex %D title=\CONTEXT\ Spacing Macros, %D subtitle=Horizontal, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Spacing Macros / Horizontal} % document: \enabledirectives[backends.spaces] \unprotect \registerctxluafile{spac-hor}{autosuffix} \ifdefined\parfillrightskip\else \aliased\let\parfillrightskip\parfillskip \fi \bitwiseflip \normalizelinemode \normalizelinenormalizecode \bitwiseflip \normalizelinemode \parindentskipnormalizecode \bitwiseflip \normalizelinemode \clipwidthnormalizecode \bitwiseflip \normalizelinemode \flattendiscretionariesnormalizecode \bitwiseflip \normalizelinemode \flattenhleadersnormalizecode %bitwiseflip \normalizelinemode \discardzerotabskipsnormalizecode \bitwiseflip \normalizeparmode \normalizeparnormalizeparcode \bitwiseflip \normalizeparmode \flattenvleadersnormalizeparcode \lettonothing\v_spac_indentation_current % amount/keyword \newdimension\d_spac_indentation_par \parindent \d_spac_indentation_par % for the show \newconditional\c_spac_indentation_indent_first \c_spac_indentation_indent_first\conditionaltrue \newconstant \c_spac_indentation_toggle_state %D After a blank or comparable situation (left side floats) we %D need to check if the next paragraph has to be indented. \permanent\protected\def\presetindentation {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}} \permanent\protected\def\setupindenting {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size} \permanent\protected\def\spac_indentation_setup_size {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}% \ifzeropt\parindent\else \parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand \fi} \aliased\let\synchronizeindenting\spac_indentation_setup_size \lettonothing\m_spac_indentation_options \def\spac_indentation_setup_options[#1]% {\edef\m_spac_indentation_options{#1}% comma separated list \ifempty\m_spac_indentation_options \else \spac_indentation_setup_indeed \fi} \def\spac_indentation_setup_indeed {% not here: \c_spac_indentation_indent_first\conditionaltrue % not here: \parindent\d_spac_indentation_par % not here: \c_spac_indentation_toggle_state\zerocount \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_one % catch small, medium, etc \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_two % catch rest \ifzeropt\parindent\else \doifemptytoks\everypar\spac_indentation_set_everypar \fi \ifconditional\c_spac_indentation_indent_first \spac_indentation_variant_yes % better than: \let\checkindentation\relax \else \spac_indentation_variant_no \fi \spac_indentation_check_toggle} \def\spac_indentation_set_everypar {\everypar{\checkindentation}} \permanent\protected\def\useindentingparameter#1% faster local variant {\edef\m_spac_indentation_options{#1\c!indenting}% \ifempty\m_spac_indentation_options \else \spac_indentation_setup_indeed \fi} % \defineindenting[whatever][yes,2cm] % %defineindenting[whatever][yes,-2cm] % % \setupindenting[yes,-2em] \input ward \par % \setupindenting[yes,2em] \input ward \par % \setupindenting[whatever] \input ward \par \installcorenamespace {indentingpreset} \permanent\tolerant\protected\def\defineindenting[#1]#*[#2]% todo: mixes {\ifarguments\else\edefcsname\??indentingpreset#1\endcsname{#2}\fi} \def\spac_indentation_apply_step_one_nested {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one} \def\spac_indentation_apply_step_two_nested {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_two} \def\spac_indentation_apply_step_one#1% {\ifcsname\??indentingpreset#1\endcsname \spac_indentation_apply_step_one_nested \orelse\ifcsname\??indentingmethod#1\endcsname % case two \else \edef\v_spac_indentation_current{#1}% single entry in list \let\v_spac_indentation_normal\v_spac_indentation_current \spac_indentation_setup_size \fi} \def\spac_indentation_apply_step_two#1% {\ifcsname\??indentingpreset#1\endcsname \spac_indentation_apply_step_two_nested \orelse\ifcsname\??indentingmethod#1\endcsname \lastnamedcs \else % case one \fi} \permanent\protected\def\indenting % kind of obsolete {\doifelsenextoptionalcs\spac_indentation_setup_options\relax} % use \noindentation to suppress next indentation \installcorenamespace{indentingmethod} \permanent\protected\def\installindentingmethod#1#2% {\defcsname\??indentingmethod#1\endcsname{#2}} \installindentingmethod \v!no {\parindent\zeropoint} \installindentingmethod \v!not {\parindent\zeropoint} \installindentingmethod \v!first {\c_spac_indentation_indent_first\conditionaltrue} \installindentingmethod \v!next {\c_spac_indentation_indent_first\conditionalfalse} \installindentingmethod \v!yes {\parindent\d_spac_indentation_par\relax} % not \indent ! \installindentingmethod \v!always{\parindent\d_spac_indentation_par\relax} % not \indent ! \installindentingmethod \v!never {\parindent\zeropoint\relax % no \indent ! \c_spac_indentation_toggle_state\zerocount} \installindentingmethod \v!odd {\c_spac_indentation_toggle_state\plusone} \installindentingmethod \v!even {\c_spac_indentation_toggle_state\plustwo} \installindentingmethod \v!normal{\ifempty\v_spac_indentation_normal\else \let\v_spac_indentation_current\v_spac_indentation_normal \spac_indentation_setup_size \fi} \installindentingmethod \v!reset {\c_spac_indentation_indent_first\conditionaltrue \parindent\zeropoint \c_spac_indentation_toggle_state\zerocount} \installindentingmethod \v!toggle{\parindent\ifzeropt\parindent \d_spac_indentation_par \else \zeropoint \fi\relax} \permanent\protected\def\noindenting{\indenting[\v!no, \v!next ]} \permanent\protected\def\doindenting{\indenting[\v!yes,\v!first]} %D Here come the handlers (still rather messy ... we need states). %newif\ifindentation \indentationtrue % will become a mode \aliased\let\checkindentation\relax \installmacrostack\checkindentation % used? %D Actually we can forget about indent and let everypar insert a kern or so, %D but on the other hand it's kind of consistent to keep it and make the %D width zero. We can do it in \LUA\ or do it natively (which actually makes %D sense. % \permanent\protected\def\undent % {\begingroup % % todo: check subtype too % \ifnum\lastnodetype=\gluenodecode % \unskip % we also need to check for the subtype % \orelse\ifnum\lastnodetype=\hlistnodecode % \setbox\scratchbox\lastbox % we also need to check for the subtype % \else % % forget about it % \fi % \endgroup} \def\spac_indentation_remove {\ifzeropt\parindent \else \undent \fi} \def\spac_indentation_kill_indeed {%\global\indentationfalse \spac_indentation_remove} \permanent\protected\def\spac_indentation_do_toggle_indeed {%\global\indentationfalse \enforced\glet\checkindentation\spac_indentation_no_toggle_indeed \spac_indentation_remove} \permanent\protected\def\spac_indentation_no_toggle_indeed {%\global\indentationtrue \enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} \permanent\protected\def\spac_indentation_do_indeed {}%\global\indentationtrue} \permanent\protected\def\spac_indentation_do_toggle {\enforced\glet\checkindentation\spac_indentation_do_toggle_indeed} \permanent\protected\def\spac_indentation_no_toggle {\enforced\glet\checkindentation\spac_indentation_no_toggle_indeed} \permanent\protected\def\spac_indentation_check_toggle {\ifcase\c_spac_indentation_toggle_state % nothing \or \spac_indentation_no_toggle \or \spac_indentation_do_toggle \fi} \permanent\protected\def\spac_indentation_variant_yes {\enforced\glet\checkindentation\spac_indentation_do_indeed} \permanent\protected\def\spac_indentation_no_next_check {\spac_indentation_remove \enforced\glet\checkindentation\spac_indentation_do_indeed} \permanent\protected\def\spac_indentation_variant_no % made global {\ifinpagebody \else %\global\indentationfalse \enforced\glet\checkindentation\spac_indentation_no_next_check \fi} \permanent\protected\def\nonoindentation % bv bij floats {\ifinpagebody \else %\global\indentationtrue \enforced\glet\checkindentation\spac_indentation_do_indeed \fi} \permanent\protected\def\spac_indentation_variant_force {\ifvmode \ifzeropt\parindent \else % was : \hskip\parindent % can be: \indent % but we test: \noindent\hskip\parindent % hm, we cannot undent this one \fi \fi} % public: \aliased\let\indentation \spac_indentation_variant_force \aliased\let\noindentation\spac_indentation_variant_no % public \aliased\let\doindentation\spac_indentation_variant_yes % public \permanent\protected\def\dontrechecknextindentation % public (in macros) {\global\enforced\let\dorechecknextindentation\relax} \aliased\let\dorechecknextindentation\relax % public (in macros) % \permanent\protected\def\spac_indentation_check_next_indentation % {\global\enforced\let\dorechecknextindentation\relax % \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par \permanent\protected\def\spac_indentation_check_next_indentation {\global\enforced\let\dorechecknextindentation\relax \begingroup \autoparagraphmode\zerocount \doifelsenextchar\par\endgroup{\endgroup\spac_indentation_variant_no}} % messy check as next is seldom \par \def\spac_indentation_variant_auto {\global\enforced\let\dorechecknextindentation\spac_indentation_check_next_indentation} %D This one sets up the local indentation behaviour (i.e. either or not %D a next paragraph will be indented). \installcorenamespace{indentnext} \permanent\protected\def\checknextindentation[#1]% {\begincsname\??indentnext#1\endcsname} \permanent\protected\def\useindentnextparameter#1% new, the more efficient variant {\edef\p_indentnext{#1\c!indentnext}% \ifempty\p_indentnext\else \begincsname\??indentnext\p_indentnext\endcsname \fi} \letcsname\??indentnext \endcsname\donothing \letcsname\??indentnext\v!yes \endcsname\spac_indentation_variant_yes \letcsname\??indentnext\v!no \endcsname\spac_indentation_variant_no \letcsname\??indentnext\v!auto\endcsname\spac_indentation_variant_auto %D An example of usage: %D %D \starttyping %D \setupindenting[small,yes] %D %D \setupitemize [indentnext=auto] %D \setuptyping [indentnext=auto] %D \setupformulas[indentnext=auto] %D %D \input tufte \startitemize \item itemize \stopitemize %D \input tufte \startitemize \item itemize \stopitemize %D \input tufte \startitemize \item itemize \stopitemize %D %D \page %D %D \input tufte %D \starttyping %D verbatim %D \stoptyping %D %D \input tufte %D \starttyping %D verbatim %D \stoptyping %D %D \input tufte %D \starttyping %D verbatim %D \stoptyping %D %D \page %D %D \input tufte \startformula a = b \stopformula %D \input tufte \startformula a = b \stopformula %D \input tufte \startformula a = b \stopformula %D \stoptyping % maybe an everyforgetparindent \permanent\protected\def\forgetparindent {\c_spac_indentation_indent_first\conditionaltrue % recently added \d_spac_indentation_par\zeropoint \parindent\zeropoint \let\v_spac_indentation_current\v!none} \appendtoks \forgetparindent \to \everyforgetall \permanent\protected\def\forgethorizontalstretch {\emergencystretch\zeropoint} \appendtoks \forgethorizontalstretch \to \everyforgetall % needed in pagebody %D Helper: \permanent\protected\def\softbreak {\relax\ifhmode\hskip\parfillskip\break\fi} %D \macros %D {frenchspacing,nonfrenchspacing} %D %D Somehow \type{\frenchspacing} can lead to hyphenation between dashes so we now %D have \type {\newfrenchspacing} (moved from \type {syst-chr}). Maybe it's not %D needed any more. %D Hm ... todo: \installcorenamespace{spacecodemethod} \sfcode`\)=\zerocount \sfcode`\'=\zerocount \sfcode`\]=\zerocount \def\spac_spacecodes_set_fixed#1% {\sfcode`\.#1\relax \sfcode`\,#1\relax \sfcode`\?#1\relax \sfcode`\!#1\relax \sfcode`\:#1\relax \sfcode`\;#1\relax} \def\spac_spacecodes_set_stretch {\sfcode`\.3000 \sfcode`\,1250 \sfcode`\?3000 \sfcode`\!3000 \sfcode`\:2000 \sfcode`\;1500 } \permanent\protected\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand} \permanent\protected\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}} \permanent\protected\def\nonfrenchspacing{\spac_spacecodes_set_stretch} \permanent\protected\def\installspacingmethod#1#2{\defcsname\??spacecodemethod#1\endcsname{#2}} \installspacingmethod \empty {} % keep values \installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere \installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation \installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation \permanent\tolerant\protected\def\setupspacing[#1]% {\ifarguments\or \begincsname\??spacecodemethod#1\endcsname \fi \updateraggedskips} % test test\fsp. test % beats frenchspacing \permanent\protected\def\fsp#1% fixed space puncuation {#1% \ifchknum`#1\or \spacefactor\plusthousand \fi} %D Here's a tweak .. if needed one can configure it in the configuration %D so that initialization happens more efficient. %D %D \starttyping %D \startoverlay %D { %D \green %D \enabledirectives[characters.spaceafteruppercase=normal]% %D \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par} %D } { %D \blue %D \enabledirectives[characters.spaceafteruppercase=traditional]% %D \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par} %D } %D \stopoverlay %D \stoptyping % This is not needed, as \updateraggedskips is taking care of it: \permanent\protected\def\synchronizespacecodes{\updateraggedskips} % \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par % \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par % \dorecurse{100}{\recurselevel\spacefactor 800 \normalspaceprimitive} \par % \dorecurse{100}{\recurselevel\spacefactor1200 \normalspaceprimitive} \par % When we don't add the % here, we effectively get \ and % since we have by default \def\^^M{\ } we get into a loop. \aliased\let\normalspaceprimitive=\ % space-comment is really needed %D As the \type{\ } is convenient in: %D %D \starttyping %D \TEX\space x\crlf %D \TEX\ x\crlf %D \TEX{} x\crlf %D \stoptyping %D %D from now on we treat it as a normal space and not as a space with \type %D {sfcode} 1000. % \permanent\protected\def\specialspaceprimitive % {\begingroup % % so, no fancy extra spacing after: foo i.e.\ bar % \nonfrenchspacing\normalspaceprimitive % \endgroup} \permanent\protected\def\specialspaceprimitive {% is a current state, set explicitly or when a character is appended \ifhmode \spacefactor\plusthousand \else \dontleavehmode \fi \normalspaceprimitive} % \permanent\protected\def\normalnotobeyedspace % {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing) \permanent\protected\def\normalnotobeyedspace {\ifmmode\normalspaceprimitive\else\specialspaceprimitive\fi} % no \dontleavehmode\space (else no frenchspacing) \pushoverloadmode \overloaded\let\ =\normalnotobeyedspace % so we redefine the primitive! \popoverloadmode % Because I strip spaces at the end of lines (in the editor) we need a bit of % a trick to define slash+newline, so \space and \ are the same % We need to be careful with \ and \space and the definition of ~ which uses \ as % we need to associate unicode spacing with it. There is some messy aspect that % I forgot to note down so I will revision the \ once I ran into it again. % \ruledhbox spread 10pt {\frenchspacing xx xx\ X} % \ruledhbox spread 10pt {\nonfrenchspacing xx xx\ X} % \ruledhbox spread 10pt {\frenchspacing xx xx X} % \ruledhbox spread 10pt {\nonfrenchspacing xx xx X} % \ruledhbox spread 10pt {\frenchspacing xx xx~X} % \ruledhbox spread 10pt {\nonfrenchspacing xx xx~X} % \ruledhbox spread 10pt {\frenchspacing xx dr.\ X} % \ruledhbox spread 10pt {\nonfrenchspacing xx dr.\ X} % \ruledhbox spread 10pt {\frenchspacing xx dr. X} % \ruledhbox spread 10pt {\nonfrenchspacing xx dr. X} % \ruledhbox spread 10pt {\frenchspacing xx dr.~X} % \ruledhbox spread 10pt {\nonfrenchspacing xx dr.~X} \permanent\protected\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math \letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later % \def\space { } \permanent\protected\def\removelastspace{\ifhmode\unskip\fi} \permanent\protected\def\nospace {\removelastspace\ignorespaces} \ifdefined\nospaces \permanent\protected\def\nospacing{\normalnospaces\plusone} \permanent\protected\def\dospacing{\normalnospaces\zerocount} \else \permanent\protected\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeroskip} \permanent\protected\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeroskip} % what \fi \ifdefined\softhyphen \else \let\softhyphen\explicitdiscretionary \fi % todo: \cldcontext{"\string\\protected\string\\def\string\\\string\n{\string\\space}"} %cldcontext{"\string\\let\string\\\string\n=\string\\space"} % in tables we need: % % \def\fixedspace {\hskip.5em\relax} % % but, since not all fonts have .5em digits: \permanent\protected\def\fixedspace {\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox \hskip\wd\scratchbox\relax} \permanent\protected\def\fixedspaces {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace %\enforced\let~\fixedspace} % we need to renew it \enforced\letcharcode\tildeasciicode\fixedspace} % why this \appendtoks %\enforced\let~\space \enforced\letcharcode\tildeasciicode\space \enforced\let\ \space \to \everysimplifycommands % \newsignal\d_spac_keep_unwanted_space_signal % % % \parindentmode\plusone % % \permanent\protected\def\keepunwantedspaces % {\ifhmode % \ifdim\lastskip=\d_spac_keep_unwanted_space_signal\else % \hskip\d_spac_keep_unwanted_space_signal\relax % \fi % \fi} % % \permanent\protected\def\removeunwantedspaces % {\ifhmode % \expandafter \spac_helpers_remove_unwantedspace % \fi} % % \def\spac_helpers_remove_unwantedspace % {\ifnum\lastnodetype=\gluenodecode\relax % \ifnum\lastnodesubtype=\indentskipsubtypecode\relax % % keep parindent % \orelse\ifdim\lastskip=\d_spac_keep_unwanted_space_signal\relax % \unskip % \else % \unskip % \doubleexpandafter\spac_helpers_remove_unwantedspace % \fi % \fi} \newboundary\c_spac_keepspaces_boundary \permanent\protected\def\keepunwantedspaces {\ifhmode\ifnum\lastboundary=\c_spac_keepspaces_boundary\else \boundary\c_spac_keepspaces_boundary \fi\fi} \permanent\protected\def\removeunwantedspaces {\ifhmode \expandafter \spac_helpers_remove_unwantedspace \fi} \def\spac_helpers_remove_unwantedspace {\ifnum\lastboundary=\c_spac_keepspaces_boundary \expandafter\unboundary \orunless\ifnum\lastnodetype=\gluenodecode % no skip \orelse\ifnum\lastnodesubtype=\indentskipsubtypecode % keep parindent \else \unskip \expandafter\spac_helpers_remove_unwantedspace \fi} \permanent\protected\def\onlynonbreakablespace {\ifdim\lastskip=\interwordspace \unskip \nonbreakablespace \fi \ignorespaces} % \startbuffer % \startlines \tt \fixedspaces % 0~1~~2~~~3~~~~4~~~~~5 % 0~~~~~~~~~~~~~~~~~~~5 % $0~1~~2~~~3~~~~4~~~~~5$ % $0~~~~~~~~~~~~~~~~~~~5$ % \stoplines % % \starttabulate[|~|] % \NC 0~1~~2~~~3~~~~4~~~~~5 \NC \NR \NC 0~~~~~~~~~~~~~~~~~~~5 \NC \NR % \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \NR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \NR % \stoptabulate % % \starttable[||] % \NC 0~1~~2~~~3~~~~4~~~~~5 \NC \AR \NC 0~~~~~~~~~~~~~~~~~~~5 \NC \AR % \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \AR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \AR % \stoptable % \stopbuffer % % \setupbodyfont[cmr] \getbuffer % \setupbodyfont[lbr] \getbuffer %D A couple of plain macros: \ifdefined\enspace \else \permanent\protected\def\enspace{\kern .5\emwidth} \fi \ifdefined\emspace \else \permanent\protected\def\emspace{\kern \emwidth} \fi \ifdefined\quad \else \permanent\protected\def\quad {\hskip \emwidth\relax} \fi \ifdefined\enskip \else \permanent\protected\def\enskip {\hskip.5\emwidth\relax} \fi \ifdefined\qquad \else \permanent\protected\def\qquad {\hskip 2\emwidth\relax} \fi \permanent\protected\def\negenspace{\kern-.5\emwidth} \permanent\protected\def\negemspace{\kern- \emwidth} % \aliased\let\emspace\quad \permanent\protected\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) \permanent\tolerant\protected\def\quads[#1]% we do robust checking {\dontleavehmode \begingroup %\scratchcounter\ifparameter#1\or#1\else\plusthree\fi \scratchcounter\ifchknumber#1\or\lastchknumber\else\plusthree\fi \zwj\dorecurse\scratchcounter{\hskip\emwidth\zwj}% \endgroup} % Suggested by GB (not the name) so we keep it for sentimental reasons: \permanent\protected\def\rapfillskip{.5\hsize plus .092\hsize minus .5\hsize} % D.A.'s value % Bovendien definieren we enkele extra \fill's: \newgluespec\s_spac_fi \s_spac_fi \zeropoint \s!plus 1\s!fi \relax \newgluespec\s_spac_fil \s_spac_fil \zeropoint \s!plus 1\s!fil \relax \newgluespec\s_spac_fill \s_spac_fill \zeropoint \s!plus 1\s!fill \relax \newgluespec\s_spac_filll \s_spac_filll \zeropoint \s!plus 1\s!filll\relax \newgluespec\s_spac_neg_fi \s_spac_neg_fi \zeropoint \s!plus-1\s!fi \relax \newgluespec\s_spac_neg_fil \s_spac_neg_fil \zeropoint \s!plus-1\s!fil \relax \newgluespec\s_spac_neg_fill \s_spac_neg_fill \zeropoint \s!plus-1\s!fill \relax \newgluespec\s_spac_neg_filll \s_spac_neg_filll \zeropoint \s!plus-1\s!filll\relax \permanent\protected\untraced\def\hfilll {\hskip\s_spac_filll\relax} \permanent\protected\untraced\def\vfilll {\vskip\s_spac_filll\relax} \permanent\protected\untraced\def\hfillneg {\hskip\s_spac_neg_fill \relax} \permanent\protected\untraced\def\hfilllneg{\hskip\s_spac_neg_filll\relax} \permanent\protected\untraced\def\vfillneg {\vskip\s_spac_neg_fill \relax} \permanent\protected\untraced\def\vfilllneg{\vskip\s_spac_neg_filll\relax} \permanent\protected\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} \permanent\protected\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere % maybe we should hash the analysis \installcorenamespace{narrower} \installcorenamespace{narrowermethod} \newgluespec\s_spac_narrower_left \newgluespec\s_spac_narrower_right \newgluespec\s_spac_narrower_middle \installcommandhandler \??narrower {narrower} \??narrower \setupnarrower [\c!before=\endgraf, \c!after=\endgraf, \c!left=1.5\emwidth, \c!right=1.5\emwidth, \c!middle=1.5\emwidth, \c!default=\v!middle] \appendtoks \frozen\instance\protected\edefcsname\e!start\currentnarrower\endcsname{\spac_narrower_start[\currentnarrower]}% \frozen\instance\protected\edefcsname\e!stop \currentnarrower\endcsname{\spac_narrower_stop}% \to \everydefinenarrower \permanent\protected\def\installnarrowermethod#1#2% {\defcsname\??narrowermethod#1\endcsname{#2}} \protected\def\spac_narrower_method_analyze#1% {\ifcsname\??narrowermethod#1\endcsname \lastnamedcs \else \global\advanceby\s_spac_narrower_middle#1\relax \fi} \def\spac_narrower_initialize[#1]% hm, can be dorepeat directly {\dorepeatwithcommand[#1]\spac_narrower_method_analyze} \installnarrowermethod \v!left {\global\advanceby\s_spac_narrower_left \narrowerparameter\c!left \relax} \installnarrowermethod \v!middle {\global\advanceby\s_spac_narrower_middle \narrowerparameter\c!middle\relax} \installnarrowermethod \v!right {\global\advanceby\s_spac_narrower_right \narrowerparameter\c!right \relax} \installnarrowermethod{-\v!left }{\global\advanceby\s_spac_narrower_left -\narrowerparameter\c!left \relax} \installnarrowermethod{-\v!middle}{\global\advanceby\s_spac_narrower_middle-\narrowerparameter\c!middle\relax} \installnarrowermethod{-\v!right }{\global\advanceby\s_spac_narrower_right -\narrowerparameter\c!right \relax} \installnarrowermethod \v!reset {\global \s_spac_narrower_left \zeroskip \global \s_spac_narrower_middle \zeroskip \global \s_spac_narrower_right \zeroskip\relax} \installnarrowermethod \v!none {} \installnarrowermethod \v!reverse {} % never seen \permanent\overloaded\tolerant\protected\def\spac_narrower_start[#1]#*[#2]% {\begingroup \cdef\currentnarrower{#1}% \ifparameter#2\or \spac_narrower_start_apply{#2}% \else \spac_narrower_start_apply{\narrowerparameter\v!default}% \fi} \newgluespec \s_spac_narrower_left_last \newgluespec \s_spac_narrower_right_last \newconditional\s_spac_narrower_last_swap \def\spac_narrower_start_apply#1% {\narrowerparameter\c!before \global\s_spac_narrower_left \zeroskip \global\s_spac_narrower_right \zeroskip \global\s_spac_narrower_middle\zeroskip \edef\scratchstringone{#1}% \ifx\scratchstringone\v!reverse \ifconditional\s_spac_narrower_last_swap \frozen\leftskip \s_spac_narrower_right_last \frozen\rightskip\s_spac_narrower_left_last \s_spac_narrower_last_swap\conditionalfalse \else \frozen\leftskip \s_spac_narrower_left_last \frozen\rightskip\s_spac_narrower_right_last \s_spac_narrower_last_swap\conditionaltrue \fi \else \normalexpanded{\processcommalistwithparameters[\scratchstringone]}\spac_narrower_initialize \frozen\advanceby\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax \frozen\advanceby\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax \fi \seteffectivehsize} \permanent\protected\def\spac_narrower_stop {\narrowerparameter\c!after \normalexpanded{% \endgroup \s_spac_narrower_left_last \the\leftskip \relax \s_spac_narrower_right_last\the\rightskip\relax \ifconditional\s_spac_narrower_last_swap \s_spac_narrower_last_swap\conditionalfalse \else \s_spac_narrower_last_swap\conditionaltrue \fi }} \permanent\tolerant\protected\def\startnarrower[#1]% {\begingroup \lettonothing\currentnarrower \ifparameter#1\or \spac_narrower_start_apply{#1}% \else \spac_narrower_start_apply{\narrowerparameter\v!default}% \fi} \aliased\let\stopnarrower\spac_narrower_stop \permanent\tolerant\protected\def\startnarrow[#S#1]#*[#S#2]% current how {\begingroup \ifnum\lastarguments=\plustwo \expandafter\spac_narrower_start_named_two \else \expandafter\spac_narrower_start_named_one \fi[#1][#2]} % we can combine these: \def\spac_narrower_start_named_one[#S#1]% {\doifelseassignment{#1}\spac_narrower_start_named_one_yes\spac_narrower_start_named_one_nop[#1]} \def\spac_narrower_start_named_one_yes[#S#1][#2]% [settings] [] {\setupcurrentnarrower[#1]% \spac_narrower_start_apply{\narrowerparameter\v!default}} \def\spac_narrower_start_named_one_nop[#1][#2]% [tag] [] {\cdef\currentnarrower{#1}% \spac_narrower_start_apply{\narrowerparameter\v!default}} \def\spac_narrower_start_named_two[#S#1]% {\doifelseassignment{#1}\spac_narrower_start_named_settings_how\spac_narrower_start_named_tag_unknown[#1]} \def\spac_narrower_start_named_settings_how[#S#1][#2]% [settings] [how] {\setupcurrentnarrower[#1]% \spac_narrower_start_apply{#2}} \def\spac_narrower_start_named_tag_unknown[#1][#S#2]% [tag] [...] {\doifelseassignment{#2}\spac_narrower_start_named_tag_settings\spac_narrower_start_named_tag_how[#1][#2]} \def\spac_narrower_start_named_tag_settings[#1][#S#2]% [tag] [settings] {\cdef\currentnarrower{#1}% \setupcurrentnarrower[#2]% \spac_narrower_start_apply{\narrowerparameter\v!default}} \def\spac_narrower_start_named_tag_how[#1][#2]% [tag] [how] {\cdef\currentnarrower{#1}% \spac_narrower_start_apply{#2}} \aliased\let\stopnarrow\spac_narrower_stop \newdimension\d_spac_effective_hsize \permanent\protected\def\effectivehsize {\hsize} \newdimension\d_spac_effective_leftskip \permanent\protected\def\effectiveleftskip {\dimexpr\leftskip \relax} \newdimension\d_spac_effective_rightskip \permanent\protected\def\effectiverightskip{\dimexpr\rightskip\relax} \permanent\protected\def\seteffectivehsize {\setlocalhsize \d_spac_effective_hsize \localhsize \d_spac_effective_leftskip 1\leftskip \d_spac_effective_rightskip1\rightskip \enforced\let\effectivehsize \d_spac_effective_hsize \enforced\let\effectiveleftskip \d_spac_effective_leftskip \enforced\let\effectiverightskip\d_spac_effective_rightskip} \installcorenamespace{skipadaptionleft} \installcorenamespace{skipadaptionright} \newgluespec\leftskipadaption \newgluespec\rightskipadaption \defcsname\??skipadaptionleft \v!yes\endcsname{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} \letcsname\??skipadaptionleft \v!no \endcsname\zeropoint % \zeroskip \letcsname\??skipadaptionleft \empty\endcsname\zeropoint % \zeroskip \defcsname\??skipadaptionright\v!yes\endcsname{\narrowerparameter\c!right} \letcsname\??skipadaptionright\v!no \endcsname\zeropoint % \zeroskip \letcsname\??skipadaptionright\empty\endcsname\zeropoint % \zeroskip \letcsname\??skipadaptionleft \v!standard\expandafter\endcsname\csname\??skipadaptionleft \v!yes\endcsname \letcsname\??skipadaptionright\v!standard\expandafter\endcsname\csname\??skipadaptionright\v!yes\endcsname \permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} \permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} \permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\frozen\advanceby\leftskip \leftskipadaption } \permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\frozen\advanceby\rightskip\rightskipadaption} \permanent\protected\def\forgetbothskips {\leftskip \zeroskip \rightskip\zeroskip \relax} \appendtoks \forgetbothskips \to \everyforgetall % in spac-ver.mkiv % % \protected\def\forgetparskip % {\s_spac_whitespace_parskip\zeroskip % \parskip\zeroskip % \let\v_spac_whitespace_current\v!none} % % \appendtoks % \forgetparskip % \to \everyforgetall %D Tolerance (can also be set with align): \installcorenamespace{tolerancemethods} \mutable\lettonothing\bottomtolerance % why not zero (not used annyway, but for now we keep it) \permanent\protected\def\installtolerancemethod#1#2#3% {\defcsname\??tolerancemethods#1:#2\endcsname{#3}} \installtolerancemethod \v!vertical \v!verystrict {\lettonothing\bottomtolerance} % why not zero \installtolerancemethod \v!vertical \v!strict {\def\bottomtolerance{.050}} \installtolerancemethod \v!vertical \v!tolerant {\def\bottomtolerance{.075}} \installtolerancemethod \v!vertical \v!verytolerant {\def\bottomtolerance{.100}} \installtolerancemethod \v!horizontal \v!stretch {\emergencystretch\bodyfontsize\relax} \installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\s!plus.25em\s!minus.25em\relax} \installtolerancemethod \v!horizontal \v!verystrict {\tolerance\plustwohundred} \installtolerancemethod \v!horizontal \v!strict {\tolerance1500 } \installtolerancemethod \v!horizontal \v!tolerant {\tolerance3000 } \installtolerancemethod \v!horizontal \v!verytolerant {\tolerance4500 } \appendetoks \pretolerance\plushundred \tolerance \plustwohundred \to\everyforgetall \def\spac_tolerances_step_vertical #1{\csname\??tolerancemethods\v!vertical :#1\endcsname} \def\spac_tolerances_step_horizontal#1{\csname\??tolerancemethods\v!horizontal:#1\endcsname} \permanent\tolerant\protected\def\setuptolerance[#1]% {\ifarguments\or \ifinset\v!vertical{#1}% \processcommacommand[#1]\spac_tolerances_step_vertical \else \processcommacommand[#1]\spac_tolerances_step_horizontal \fi \fi} % %D \macros % %D {pushindentation,popindentation} % %D % %D The pushing and popping is done by: % % \newbox\b_spac_indentations_a % \newbox\b_spac_indentations_b % % \permanent\protected\def\pushindentation % {\begingroup % \ifhmode % \unskip % \setbox\b_spac_indentations_a\lastbox % get \strut if present % \unskip % \setbox\b_spac_indentations_b\lastbox % get \indent generated box % \unskip % \else % \dontleavehmode % was \hskip\zeroskip % switch to horizontal mode % \unskip % \setbox\b_spac_indentations_a\lastbox % get \indent generated box % \setbox\b_spac_indentations_b\emptybox % \fi} % % \permanent\protected\def\popindentation % {\box\b_spac_indentations_b % \box\b_spac_indentations_a % \endgroup} %D Struts are done differently now. %D %D The only complication lays in \type{\strut}. In \PLAIN\ \TEX\ a \type{\strut} is %D defined as: %D %D \starttyping %D \def\strut% %D {\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi} %D \stoptyping %D %D But what is a \type {\strut}? Normally it's a rule of width zero, but when made %D visual, it's a rule and a negative skip. The mechanism for putting things in the %D margins described here cannot handle this situation very well. One characteristic %D of \type {\strut} is that the \type {\unhcopy} results in entering horizontal %D mode, which in return leads to some indentation. %D %D To serve our purpose a bit better, the macro \type {\strut} can be redefined as: %D \starttyping %D \def\strut %D {\relax\ifmmode\else\hskip\zeroskip\fi\copy\strutbox} %D \stoptyping %D %D Or more compatible: %D %D \starttyping %D \def\strut %D {\relax\ifmmode %D \copy\strutbox %D \else %D \bgroup\setbox\strutbox=\hbox{\box\strutbox}\unhcopy\strutbox\egroup %D \fi} %D \stoptyping %D %D In \CONTEXT\ however we save some processing time by putting an extra \type %D {\hbox} around the \type {\strutbox}. %D %D \starttyping %D % \setuplayout[gridgrid=yes] \showgrid %D %D \startbuffer %D test 1\crlf %D test 2\crlf %D %D \crlf test 3 %D %D test 4\crlf %D test 5 %D %D \crlf %D \crlf %D \crlf %D test 6 %D \stopbuffer %D %D \hbox %D {\hsize5em %D \ruledvtop{\getbuffer}\enspace %D \ruledvtop{\showstruts\getbuffer}\enspace %D \hsize15em \setuptyping[before=,after=]% %D \ruledvtop{\typebuffer}} %D \stoptyping \permanent\protected\def\justonespace{\removeunwantedspaces\space} %permanent\protected\def\justaperiod {\removeunwantedspaces.} %permanent\protected\def\justacomma {\removeunwantedspaces,} \installcorenamespace{hspace} \permanent\protected\def\ignorecrlf {\enforced\let\crlf\justonespace \enforced\let\\\crlf} \permanent\tolerant\protected\def\definehspace[#1]#*[#2]#*[#3]% #1 = optional namespace {\ifparameter#3\or \defcsname\??hspace#1:#2\endcsname{#3}% \else \defcsname\??hspace :#1\endcsname{#2}% \fi} \permanent\tolerant\protected\def\hspace[#1]#*[#2]% {\ifhmode \removeunwantedspaces \hskip % always a skip even when 0pt \ifparameter#2\or \hspaceamount{#1}{#2}% \orelse\ifparameter#1\or \hspaceamount\empty{#1}% \else \hspaceamount\empty\s!default \fi \relax \expandafter\ignorespaces \fi} \permanent\overloaded\def\hspaceamount #1#2{\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax} \permanent\overloaded\def\directhspaceamount #1{\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} % no installhspace here (this is already an old command) \definehspace [\v!small] [.25\emspaceamount] \definehspace [\v!medium] [.5\emspaceamount] \definehspace [\v!big] [1\emspaceamount] \definehspace [\v!normal] [1\spaceamount] \definehspace [\v!default] [\spaceamount] \definehspace [\v!none] [\zeropoint] % \zeroskip %D Taken from Taco's math module (cq. \AMS\ macros), but %D adapted to \type %D {\hspace}: \permanent\protected\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax} \permanent\protected\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax} \permanent\protected\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax} \overloaded\permanent\protected \def\hairspace {\textormathspace+\hairmuskip{.5}} \overloaded\permanent\protected \def\thinspace {\textormathspace+\thinmuskip 1} %overloaded\permanent\protected \def\medspace {\textormathspace+\medmuskip 2} % 4/18 em \overloaded\permanent\protected \def\thickspace {\textormathspace+\thickmuskip3} \overloaded\permanent\protected \def\neghairspace {\textormathspace-\thinmuskip{.5}} \overloaded\permanent\protected \def\negthinspace {\textormathspace-\thinmuskip 1} \overloaded\permanent\protected \def\negmedspace {\textormathspace-\medmuskip 2} \overloaded\permanent\protected \def\negthickspace{\textormathspace-\thickmuskip3} \overloaded\permanent\protected\edef\medspace {\textormathspacecommand+\medmuskip{\tocharacter"205F}} % maybe % \protected\def\breakablethinskip {\breakabletextormathspace+\thinmuskip1} % \protected\def\twoperemskip {\hskip\dimexpr\emwidth/2\relax} % == \enspace % \protected\def\threeperemskip {\hskip\dimexpr\emwidth/3\relax} % \protected\def\fourperemskip {\hskip\dimexpr\emwidth/4\relax} % \protected\def\fiveperemskip {\hskip\dimexpr\emwidth/5\relax} % goodie % \protected\def\sixperemskip {\hskip\dimexpr\emwidth/6\relax} % \protected\def\figureskip {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this % \protected\def\punctuationskip {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup} % \protected\def\ideographicskip {\hskip\dimexpr\emwidth/1\relax} % \protected\def\ideographichalffillskip{\hskip\dimexpr\emwidth/2\relax} % \protected\def\nobreakskip {\penalty\plustenthousand\kern\interwordspace} % \protected\def\narrownobreakskip {\penalty\plustenthousand\thinspace} % \protected\def\zerowidthnobreakskip {\penalty\plustenthousand\kern\zeropoint} % \protected\def\zerowidthskip {\hskip\zeroskip} \definehspace[.5][.1250\emwidth] % hair \definehspace[1] [.1667\emwidth] % thin \definehspace[2] [.2222\emwidth] % med \definehspace[3] [.2777\emwidth] % thick % These will be redefined anyway in math-ini: \suggestedalias \, \thinspace \suggestedalias \: \medspace \suggestedalias \; \thickspace \suggestedalias \! \negthinspace % plain ... % % \ifdefined\> \else \protected\def\>{\mskip \medmuskip } \fi % \ifdefined\* \else \protected\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi \permanent\def\flexiblespaceamount#1#2#3% {#1\interwordspace \s!plus#2\interwordstretch \s!minus#3\interwordshrink} \permanent\def\fixedspaceamount#1% {#1\interwordspace} % moved from page-lin % % the following code is used in startlines\stoplines % % do we need \normalspaceprimitive here? \installcorenamespace{spacemethods} \permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace {\defcsname\??spacemethods#1\endcsname{#2}} \permanent\def\activatespacehandler#1% {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname} \permanent\protected\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}% \permanent\protected\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% \permanent\protected\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% % hm, order matters when we \let in \obeyspaces \installspacemethod \v!on {\obeyspaces \enforced\let\obeyedspace\spac_spaces_checked_control \enforced\let\ =\obeyedspace} \installspacemethod \v!yes {\obeyspaces \enforced\let\obeyedspace\spac_spaces_checked_normal \enforced\let\ =\obeyedspace} \installspacemethod \v!off % == default {\normalspaces \enforced\let\obeyedspace\normalspace \enforced\let\ =\normalspaceprimitive} % was \normalspace \installspacemethod \v!fixed {\obeyspaces \enforced\let\obeyedspace\spac_spaces_checked_fixed \enforced\let\ =\obeyedspace} \appendtoks \normalspaces % to be sure \to \everybeforeoutput %D A more robust variant of the \MKII\ one: %D %D \startbuffer %D bla \TEX\autoinsertnextspace bla %D bla \TEX\autoinsertnextspace (bla) %D bla (\TEX\autoinsertnextspace) bla %D bla \TEX\autoinsertnextspace\ bla %D \stopbuffer %D %D \typebuffer \getbuffer % \autoinsertnextspace % defined at the lua end %D Moved from bib module: \permanent\protected\def\outdented#1% {\hskip-\hangindent#1\relax} %D Beware: due to char-def this becomes an active character but that might change %D sometime when we will replace all these specials to node insertions. We might %D even expand it to utf then as it then can be used in string comparison (not that %D much needed anyway). % \chardef\zwnj="200C % \chardef\zwj ="200D % TODO (but used in languages): \def\spac_glues_text_or_math#1#2% {\begingroup \ifmmode \mskip#1% \else \scratchdimen#1\hspaceamount\empty{#2}% \scratchskip\scratchdimen\s!plus.5\scratchdimen\s!minus.3\scratchdimen \hskip\scratchskip \fi \endgroup} \permanent\protected\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small} \permanent\protected\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} \permanent\protected\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} %D A rather unknown one: \permanent\protected\def\widened % moved from cont-new {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop} \def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}} \def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}} %D For the moment here (used in page-txt): \permanent\protected\def\ignoredlinebreak{\unskip\space\ignorespaces} %D \macros %D {startignorespaces} %D %D I'll probably forget that this one exists: %D %D \starttyping %D \ruledhbox %D {\startignorespaces %D \def\oeps{a} %D \startignorespaces %D \def\oeps{a} %D \stopignorespaces %D \def\oeps{a} %D \stopignorespaces %D \oeps} %D \stoptyping % \newsignal \d_spac_ignore_spaces_signal % \newinteger\c_spac_ignore_spaces % % \permanent\protected\def\startignorespaces % {\advanceby\c_spac_ignore_spaces\plusone % \ifcase\c_spac_ignore_spaces\or \ifhmode % \hskip\d_spac_ignore_spaces_signal % \fi \fi % \ignorespaces} % % \permanent\protected\def\stopignorespaces % {\ifcase\c_spac_ignore_spaces \or % \ifhmode % \doloop\spac_ignore_spaces_body % \fi % \fi % \advanceby\c_spac_ignore_spaces\minusone} % % \def\spac_ignore_spaces_body % {\ifzeropt\lastskip % \exitloop % \orelse\ifdim\lastskip=\d_spac_ignore_spaces_signal % \unskip % \exitloop % \else % \unskip % \fi} \permanent\protected\def\startignorespaces {\pushmacro\nospaces \nospaces\plusone} \permanent\protected\def\stopignorespaces {\popmacro\nospaces} %D \macros %D {obeyfollowingtoken} \permanent\def\obeyfollowingtoken{{}} % end \cs scanning %D Something new: \permanent\protected\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax} \permanent\protected\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary} \permanent\protected\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore} \permanent\protected\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter} \permanent\protected\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter} %D For mp: \installcorenamespace{mplocation} \defcsname\??mplocation\v!left \endcsname{1} \defcsname\??mplocation\v!right\endcsname{2} \defcsname\??mplocation\v!inner\endcsname{3} \defcsname\??mplocation\v!outer\endcsname{4} \permanent\def\mplocation#1{\ifcsname\??mplocation#1\endcsname\lastnamedcs\else0\fi} %permanent\def\mplocation#1{\csname\??mplocation\ifcsname\??mplocation#1\endcsname#1\else\v!left\fi\endcsname} % new: \lateindent \lateundent % \parinitleftskip1cm \parindent 1cm \indent test \par % \parinitleftskip1cm \parindent 1cm \undent test \par % \parinitleftskip1cm \parindent 1cm \indent \undent test \par % \parinitleftskip1cm \parindent 1cm \indent \strut \undent test \par % \parinitleftskip1cm \parindent 1cm \strut \lateindent 2cm test \par % \parinitleftskip1cm \parindent 1cm \strut \lateindent 2cm test \lateundent \par \protect \endinput