spac-hor.mkiv /size: 42 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=spac-hor,
3%D        version=2009.10.16, % 1997.03.31, was core-spa.tex
4%D          title=\CONTEXT\ Spacing Macros,
5%D       subtitle=Horizontal,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Spacing Macros / Horizontal}
15
16\unprotect
17
18\registerctxluafile{spac-hor}{}
19
20\let        \parfillrightskip \parfillskip
21\newskip    \parfillleftskip
22\newconstant\parfillleftmode
23
24\let\v_spac_indentation_current\empty % amount/keyword
25
26\newdimen \d_spac_indentation_par
27\parindent\d_spac_indentation_par % for the show
28
29\newconditional\c_spac_indentation_indent_first \settrue\c_spac_indentation_indent_first
30\newconstant   \c_spac_indentation_toggle_state
31
32%D After a blank or comparable situation (left side floats) we
33%D need to check if the next paragraph has to be indented.
34
35\unexpanded\def\presetindentation
36  {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}}
37
38\unexpanded\def\setupindenting
39  {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size}
40
41% \unexpanded\def\spac_indentation_setup_size
42%   {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}}
43
44\unexpanded\def\spac_indentation_setup_size
45  {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}%
46   \ifzeropt\parindent\else
47     \parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand
48   \fi}
49
50\let\synchronizeindenting\spac_indentation_setup_size
51
52\let\m_spac_indentation_options\empty
53
54\def\spac_indentation_setup_options[#1]%
55  {\edef\m_spac_indentation_options{#1}% comma separated list
56   \ifx\m_spac_indentation_options\empty \else
57     \spac_indentation_setup_indeed
58   \fi}
59
60\def\spac_indentation_setup_indeed
61  {% not here: \settrue\c_spac_indentation_indent_first
62   % not here: \parindent\d_spac_indentation_par
63   % not here: \c_spac_indentation_toggle_state\zerocount
64   \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_one % catch small, medium, etc
65   \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_two % catch rest
66   \ifzeropt\parindent\else
67     \doifemptytoks\everypar\spac_indentation_set_everypar
68   \fi
69   \ifconditional\c_spac_indentation_indent_first
70     \spac_indentation_variant_yes % better than: \let\checkindentation\relax
71   \else
72     \spac_indentation_variant_no
73   \fi
74   \spac_indentation_check_toggle}
75
76\def\spac_indentation_set_everypar
77  {\everypar{\checkindentation}}
78
79\unexpanded\def\useindentingparameter#1% faster local variant
80  {\edef\m_spac_indentation_options{#1\c!indenting}%
81   \ifx\m_spac_indentation_options\empty \else
82     \spac_indentation_setup_indeed
83   \fi}
84
85% \def\spac_indentation_apply_step_one#1%
86%   {\ifcsname\??indentingmethod#1\endcsname
87%      % case two
88%    \else
89%      \edef\v_spac_indentation_current{#1}% single entry in list
90%      \let\normalindentation\v_spac_indentation_current
91%      \spac_indentation_setup_size
92%    \fi}
93%
94% \def\spac_indentation_apply_step_two#1%
95%   {\ifcsname\??indentingmethod#1\endcsname
96%      \csname\??indentingmethod#1\endcsname
97%    \else
98%      % case one
99%    \fi}
100
101% \defineindenting[whatever][yes,2cm]
102% %defineindenting[whatever][yes,-2cm]
103%
104% \setupindenting[yes,-2em] \input ward \par
105% \setupindenting[yes,2em]  \input ward \par
106% \setupindenting[whatever] \input ward \par
107
108\installcorenamespace {indentingpreset}
109
110\unexpanded\def\defineindenting
111  {\dodoubleargument\spac_indenting_define}
112
113\def\spac_indenting_define[#1][#2]% todo: mixes
114  {\setevalue{\??indentingpreset#1}{#2}}
115
116% \def\spac_indentation_apply_step_one_nested#1%
117%   {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one}
118%
119% \def\spac_indentation_apply_step_two_nested#1%
120%   {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two}
121%
122% \def\spac_indentation_apply_step_one#1%
123%   {\ifcsname\??indentingpreset#1\endcsname
124%      \spac_indentation_apply_step_one_nested{#1}%
125%    \else\ifcsname\??indentingmethod#1\endcsname
126%      % case two
127%    \else
128%      \edef\v_spac_indentation_current{#1}% single entry in list
129%      \let\normalindentation\v_spac_indentation_current
130%      \spac_indentation_setup_size
131%    \fi\fi}
132%
133% \def\spac_indentation_apply_step_two#1%
134%   {\ifcsname\??indentingpreset#1\endcsname
135%      \spac_indentation_apply_step_two_nested{#1}%
136%    \else\ifcsname\??indentingmethod#1\endcsname
137%      \lastnamedcs
138%    \else
139%      % case one
140%    \fi\fi}
141
142\def\spac_indentation_apply_step_one_nested
143  {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one}
144
145\def\spac_indentation_apply_step_two_nested
146  {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_two}
147
148\def\spac_indentation_apply_step_one#1%
149  {\ifcsname\??indentingpreset#1\endcsname
150     \spac_indentation_apply_step_one_nested
151   \else\ifcsname\??indentingmethod#1\endcsname
152     % case two
153   \else
154     \edef\v_spac_indentation_current{#1}% single entry in list
155     \let\normalindentation\v_spac_indentation_current
156     \spac_indentation_setup_size
157   \fi\fi}
158
159\def\spac_indentation_apply_step_two#1%
160  {\ifcsname\??indentingpreset#1\endcsname
161     \spac_indentation_apply_step_two_nested
162   \else\ifcsname\??indentingmethod#1\endcsname
163     \lastnamedcs
164   \else
165     % case one
166   \fi\fi}
167
168\unexpanded\def\indenting % kind of obsolete
169  {\doifelsenextoptionalcs\spac_indentation_setup_options\relax}
170
171% use \noindentation to suppress next indentation
172
173\installcorenamespace{indentingmethod}
174
175\unexpanded\def\installindentingmethod#1#2%
176  {\setvalue{\??indentingmethod#1}{#2}}
177
178\installindentingmethod \v!no    {\parindent\zeropoint}
179\installindentingmethod \v!not   {\parindent\zeropoint}
180
181\installindentingmethod \v!first {\settrue\c_spac_indentation_indent_first}
182\installindentingmethod \v!next  {\setfalse\c_spac_indentation_indent_first}
183
184\installindentingmethod \v!yes   {\parindent\d_spac_indentation_par\relax} % not \indent !
185\installindentingmethod \v!always{\parindent\d_spac_indentation_par\relax} % not \indent !
186
187\installindentingmethod \v!never {\parindent\zeropoint\relax     % no \indent !
188                                  \c_spac_indentation_toggle_state\zerocount}
189
190\installindentingmethod \v!odd   {\c_spac_indentation_toggle_state\plusone}
191\installindentingmethod \v!even  {\c_spac_indentation_toggle_state\plustwo}
192
193\installindentingmethod \v!normal{\ifx\normalindentation\empty\else
194                                    \let\v_spac_indentation_current\normalindentation
195                                    \spac_indentation_setup_size
196                                  \fi}
197
198\installindentingmethod \v!reset {\settrue\c_spac_indentation_indent_first
199                                  \parindent\zeropoint
200                                  \c_spac_indentation_toggle_state\zerocount}
201
202\installindentingmethod \v!toggle{\parindent\ifzeropt\parindent
203                                    \d_spac_indentation_par
204                                  \else
205                                    \zeropoint
206                                  \fi\relax}
207
208\unexpanded\def\noindenting{\indenting[\v!no, \v!next ]}
209\unexpanded\def\doindenting{\indenting[\v!yes,\v!first]}
210
211%D Here come the handlers (still rather messy ... we need states).
212
213%newif\ifindentation \indentationtrue  % will become a mode
214
215\let\checkindentation\relax
216
217\installmacrostack\checkindentation
218%installmacrostack\ifindentation
219
220\def\spac_indentation_remove
221  {\ifzeropt\parindent \else
222     \begingroup
223     \setbox\scratchbox\lastbox
224     \endgroup
225   \fi}
226
227\def\spac_indentation_kill_indeed
228  {%\global\indentationfalse
229   \spac_indentation_remove}
230
231\def\spac_indentation_do_toggle_indeed
232  {%\global\indentationfalse
233   \glet\checkindentation\spac_indentation_no_toggle_indeed
234   \spac_indentation_remove}
235
236\def\spac_indentation_no_toggle_indeed
237  {%\global\indentationtrue
238   \glet\checkindentation\spac_indentation_do_toggle_indeed}
239
240\def\spac_indentation_do_indeed
241  {}%\global\indentationtrue}
242
243\def\spac_indentation_do_toggle
244  {\glet\checkindentation\spac_indentation_do_toggle_indeed}
245
246\def\spac_indentation_no_toggle
247  {\glet\checkindentation\spac_indentation_no_toggle_indeed}
248
249\def\spac_indentation_check_toggle
250  {\ifcase\c_spac_indentation_toggle_state
251     % nothing
252   \or
253     \spac_indentation_no_toggle
254   \or
255     \spac_indentation_do_toggle
256   \fi}
257
258\def\spac_indentation_variant_yes
259  {\glet\checkindentation\spac_indentation_do_indeed}
260
261\def\spac_indentation_no_next_check
262  {\spac_indentation_remove
263   \glet\checkindentation\spac_indentation_do_indeed}
264
265\def\spac_indentation_variant_no % made global
266  {\ifinpagebody \else
267     %\global\indentationfalse
268     \glet\checkindentation\spac_indentation_no_next_check
269   \fi}
270
271\def\nonoindentation % bv bij floats
272  {\ifinpagebody \else
273     %\global\indentationtrue
274     \glet\checkindentation\spac_indentation_do_indeed
275   \fi}
276
277\def\spac_indentation_variant_force
278  {\ifvmode \ifzeropt\parindent \else
279     % was : \hskip\parindent
280     % can be: \indent
281     % but we test:
282     \noindent\hskip\parindent
283   \fi \fi}
284
285\appendtoks
286    \push_macro_checkindentation
287    \push_macro_ifindentation
288\to \everypushsomestate
289
290\appendtoks
291    \pop_macro_ifindentation
292    \pop_macro_checkindentation
293\to \everypopsomestate
294
295% public:
296
297\let\indentation  \spac_indentation_variant_force
298\let\noindentation\spac_indentation_variant_no    % public
299\let\doindentation\spac_indentation_variant_yes   % public
300
301\def\dontrechecknextindentation              % public (in macros)
302  {\glet\dorechecknextindentation\relax}
303
304\let\dorechecknextindentation\relax          % public (in macros)
305
306\unexpanded\def\spac_indentation_check_next_indentation
307  {\glet\dorechecknextindentation\relax
308   \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par
309
310\def\spac_indentation_variant_auto
311  {\glet\dorechecknextindentation\spac_indentation_check_next_indentation}
312
313%D This one sets up the local indentation behaviour (i.e. either or not
314%D a next paragraph will be indented).
315
316\installcorenamespace{indentnext}
317
318\unexpanded\def\checknextindentation[#1]%
319  {\begincsname\??indentnext#1\endcsname}
320
321\unexpanded\def\useindentnextparameter#1% new, the more efficient variant
322  {\edef\p_indentnext{#1\c!indentnext}%
323   \ifx\p_indentnext\empty\else
324     \begincsname\??indentnext\p_indentnext\endcsname
325   \fi}
326
327\letvalue{\??indentnext       }\donothing
328\letvalue{\??indentnext\v!yes }\spac_indentation_variant_yes
329\letvalue{\??indentnext\v!no  }\spac_indentation_variant_no
330\letvalue{\??indentnext\v!auto}\spac_indentation_variant_auto
331
332%D An example of usage:
333%D
334%D \starttyping
335%D \setupindenting[small,yes]
336%D
337%D \setupitemize [indentnext=auto]
338%D \setuptyping  [indentnext=auto]
339%D \setupformulas[indentnext=auto]
340%D
341%D \input tufte \startitemize \item itemize \stopitemize
342%D \input tufte \startitemize \item itemize \stopitemize
343%D \input tufte \startitemize \item itemize \stopitemize
344%D
345%D \page
346%D
347%D \input tufte
348%D \starttyping
349%D verbatim
350%D \stoptyping
351%D
352%D \input tufte
353%D \starttyping
354%D verbatim
355%D \stoptyping
356%D
357%D \input tufte
358%D \starttyping
359%D verbatim
360%D \stoptyping
361%D
362%D \page
363%D
364%D \input tufte \startformula a = b \stopformula
365%D \input tufte \startformula a = b \stopformula
366%D \input tufte \startformula a = b \stopformula
367%D \stoptyping
368
369% maybe an everyforgetparindent
370
371\unexpanded\def\forgetparindent
372  {\settrue\c_spac_indentation_indent_first % recently added
373   \d_spac_indentation_par\zeropoint
374   \parindent\zeropoint
375   \let\v_spac_indentation_current\v!none}
376
377\appendtoks
378    \forgetparindent
379\to \everyforgetall
380
381\unexpanded\def\forgethorizontalstretch
382  {\emergencystretch\zeropoint}
383
384\appendtoks
385    \forgethorizontalstretch
386\to \everyforgetall % needed in pagebody
387
388%D Helper:
389
390\unexpanded\def\softbreak
391  {\relax\ifhmode\hskip\parfillskip\break\fi}
392
393%D \macros
394%D   {frenchspacing,nonfrenchspacing}
395%D
396%D Somehow \type{\frenchspacing} can lead to hyphenation between dashes so we now
397%D have \type {\newfrenchspacing} (moved from \type {syst-chr}). Maybe it's not
398%D needed any more.
399
400%D Hm ... todo:
401
402\installcorenamespace{spacecodemethod}
403
404\sfcode`\)=\zerocount
405\sfcode`\'=\zerocount
406\sfcode`\]=\zerocount
407
408\def\spac_spacecodes_set_fixed#1%
409  {\sfcode`\.#1\relax \sfcode`\,#1\relax
410   \sfcode`\?#1\relax \sfcode`\!#1\relax
411   \sfcode`\:#1\relax \sfcode`\;#1\relax}
412
413\def\spac_spacecodes_set_stretch
414  {\sfcode`\.3000 \sfcode`\,1250
415   \sfcode`\?3000 \sfcode`\!3000
416   \sfcode`\:2000 \sfcode`\;1500 }
417
418\unexpanded\def\frenchspacing   {\spac_spacecodes_set_fixed\plusthousand}
419\unexpanded\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}}
420\unexpanded\def\nonfrenchspacing{\spac_spacecodes_set_stretch}
421
422\unexpanded\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}}
423
424\installspacingmethod \empty    {}                  % keep values
425\installspacingmethod \v!fixed  {\frenchspacing   } % equal spaces everywhere
426\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation
427\installspacingmethod \v!broad  {\nonfrenchspacing} % more depending on what punctuation
428
429\unexpanded\def\setupspacing
430  {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop}
431
432\def\spac_spacecodes_setup_yes[#1]%
433  {\begincsname\??spacecodemethod#1\endcsname
434   \updateraggedskips}
435
436\def\spac_spacecodes_setup_nop
437  {\updateraggedskips}
438
439%D Here's a tweak .. if needed one can configure it in the configuration
440%D so that initialization happens more efficient.
441%D
442%D \starttyping
443%D \startoverlay
444%D     {
445%D         \green
446%D         \enabledirectives[characters.spaceafteruppercase=normal]%
447%D         \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par}
448%D     } {
449%D         \blue
450%D         \enabledirectives[characters.spaceafteruppercase=traditional]%
451%D         \vbox{\hsize 5em x. X\par x.\ X\par X. X\par X.\ X\par}
452%D     }
453%D \stopoverlay
454%D \stoptyping
455
456% This is not needed, as \updateraggedskips is taking care of it:
457
458\let\synchronizespacecodes\spac_spacecodes_setup_nop % \relax
459
460% \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par
461% \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par
462% \dorecurse{100}{\recurselevel\spacefactor 800 \normalspaceprimitive} \par
463% \dorecurse{100}{\recurselevel\spacefactor1200 \normalspaceprimitive} \par
464
465% When we don't add the % here, we effectively get \<endlinechar> and
466% since we have by default \def\^^M{\ } we get into a loop.
467
468\let\normalspaceprimitive=\ % space-comment is really needed
469
470%D As the \type{\ } is convenient in:
471%D
472%D \starttyping
473%D \TEX\space x\crlf
474%D \TEX\      x\crlf
475%D \TEX{}     x\crlf
476%D \stoptyping
477%D
478%D from now on we treat it as a normal space and not as a space with \type
479%D {sfcode} 1000.
480
481% \unexpanded\def\specialspaceprimitive
482%   {\begingroup
483%    % so, no fancy extra spacing after: foo i.e.\ bar
484%    \nonfrenchspacing\normalspaceprimitive
485%    \endgroup}
486
487\unexpanded\def\specialspaceprimitive
488  {% is a current state, set explicitly or when a character is appended
489   \ifhmode
490     \spacefactor\plusthousand
491   \else
492     \dontleavehmode
493   \fi
494   \normalspaceprimitive}
495
496\unexpanded\def\normalnotobeyedspace
497  {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing)
498
499\let\ =\normalnotobeyedspace
500
501% Because I strip spaces at the end of lines (in the editor) we need a bit of
502% a trick to define slash+newline, so \space and \<newline> are the same
503
504% We need to be careful with \ and \space and the definition of ~ which uses \ as
505% we need to associate unicode spacing with it. There is some messy aspect that
506% I forgot to note down so I will revision the \ once I ran into it again.
507
508% \ruledhbox spread 10pt {\frenchspacing    xx xx\ X}
509% \ruledhbox spread 10pt {\nonfrenchspacing xx xx\ X}
510% \ruledhbox spread 10pt {\frenchspacing    xx xx X}
511% \ruledhbox spread 10pt {\nonfrenchspacing xx xx X}
512% \ruledhbox spread 10pt {\frenchspacing    xx xx~X}
513% \ruledhbox spread 10pt {\nonfrenchspacing xx xx~X}
514
515% \ruledhbox spread 10pt {\frenchspacing    xx dr.\ X}
516% \ruledhbox spread 10pt {\nonfrenchspacing xx dr.\ X}
517% \ruledhbox spread 10pt {\frenchspacing    xx dr. X}
518% \ruledhbox spread 10pt {\nonfrenchspacing xx dr. X}
519% \ruledhbox spread 10pt {\frenchspacing    xx dr.~X}
520% \ruledhbox spread 10pt {\nonfrenchspacing xx dr.~X}
521
522\unexpanded\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math
523
524\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later
525
526           \def\space          { }
527\unexpanded\def\removelastspace{\ifhmode\unskip\fi}
528\unexpanded\def\nospace        {\removelastspace\ignorespaces}
529
530\ifdefined\nospaces
531    \unexpanded\def\nospacing{\normalnospaces\plusone}
532    \unexpanded\def\dospacing{\normalnospaces\zerocount}
533\else
534    \unexpanded\def\nospacing{\spaceskip\scaledpoint     \xspaceskip\zeropoint}
535    \unexpanded\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what
536\fi
537
538\ifdefined\softhyphen \else
539    \let\softhyphen\explicitdiscretionary
540\fi
541
542%D This is a rubish approach vbecause it redefines \typ {\csname \endcsname} to
543%D \type {\space} so we need to fix that.
544
545\expandafter\let\expandafter\next\csname\endcsname
546\cldcontext{"\string\\protected\string\\def\string\\\string\n{\string\\space}"}
547\expandafter\let\csname\endcsname\next
548
549%D Here is an example from \type {newlines-001.tex}:
550%D
551%D \starttyping
552%D \def\TestA#1%
553%D   {\writestatus{Test A}{#1}%
554%D    \ctxlua{str = [[#1]] print(str) context(str) io.savedata("temp.tmp",str)}}
555%D
556%D \def\TestB#1%
557%D   {\writestatus{Test B}{#1}%
558%D    \ctxlua{str = [[\detokenize{#1}]] print(str) context(str) io.savedata("temp.tmp",str)}}
559%D
560%D \def\TestC#1%
561%D   {\writestatus{Test C}{#1}%
562%D    \edef\temp{#1}%
563%D    \ctxlua{str = [[\detokenize\expandafter{\temp}]] print(str) context(str) io.savedata("temp.tmp",str)}%
564%D    \typefile{temp.tmp}}
565%D
566%D \TestA{Test\
567%D A}
568%D
569%D \TestB{Test\
570%D B}
571%D
572%D \TestC{Test\
573%D C}
574%D
575%D Test\
576%D D
577%D
578%D \section{Test\
579%D E}
580%D
581%D Test F\footnote{Note\
582%D F}
583%D \stoptyping
584
585% in tables we need:
586%
587% \def\fixedspace   {\hskip.5em\relax}
588%
589% but, since not all fonts have .5em digits:
590
591\unexpanded\def\fixedspace
592  {\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox
593   \hskip\wd\scratchbox\relax}
594
595\unexpanded\def\fixedspaces
596  {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace
597   \let~\fixedspace} % we need to renew it
598
599\appendtoks
600    \let~\space
601    \let\ \space
602\to \everysimplifycommands
603
604\newsignal\s_spac_keep_unwanted_space
605
606\unexpanded\def\keepunwantedspaces
607  {\ifhmode
608     \ifdim\lastskip=\s_spac_keep_unwanted_space\else
609        \hskip\s_spac_keep_unwanted_space\relax
610     \fi
611   \fi}
612
613\unexpanded\def\removeunwantedspaces
614  {\ifhmode
615     \expandafter \spac_helpers_remove_unwantedspace
616   \fi}
617
618\def\spac_helpers_remove_unwantedspace
619  {\ifnum\lastnodetype=\gluenodecode
620     \ifdim\lastskip=\s_spac_keep_unwanted_space\relax
621       \unskip
622     \else
623       \unskip
624       \doubleexpandafter\spac_helpers_remove_unwantedspace
625     \fi
626   \fi}
627
628\unexpanded\def\onlynonbreakablespace
629  {\ifdim\lastskip=\interwordspace
630     \unskip
631     \nonbreakablespace
632   \fi
633   \ignorespaces}
634
635% \startbuffer
636% \startlines \tt \fixedspaces
637%  0~1~~2~~~3~~~~4~~~~~5
638%  0~~~~~~~~~~~~~~~~~~~5
639% $0~1~~2~~~3~~~~4~~~~~5$
640% $0~~~~~~~~~~~~~~~~~~~5$
641% \stoplines
642%
643% \starttabulate[|~|]
644% \NC  0~1~~2~~~3~~~~4~~~~~5  \NC \NR \NC  0~~~~~~~~~~~~~~~~~~~5  \NC \NR
645% \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \NR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \NR
646% \stoptabulate
647%
648% \starttable[||]
649% \NC  0~1~~2~~~3~~~~4~~~~~5  \NC \AR \NC  0~~~~~~~~~~~~~~~~~~~5  \NC \AR
650% \NC $0~1~~2~~~3~~~~4~~~~~5$ \NC \AR \NC $0~~~~~~~~~~~~~~~~~~~5$ \NC \AR
651% \stoptable
652% \stopbuffer
653%
654% \setupbodyfont[cmr] \getbuffer
655% \setupbodyfont[lbr] \getbuffer
656
657%D A couple of plain macros:
658
659\ifdefined\thinspace \else
660
661    \unexpanded\def\thinspace   {\kern .16667\emwidth}
662    \unexpanded\def\negthinspace{\kern-.16667\emwidth}
663    \unexpanded\def\enspace     {\kern     .5\emwidth}
664    \unexpanded\def\emspace     {\kern       \emwidth}
665
666\fi
667
668\ifdefined\quad \else
669
670    \unexpanded\def\enskip{\hskip.5\emwidth\relax}
671    \unexpanded\def\quad  {\hskip  \emwidth\relax}
672    \unexpanded\def\qquad {\hskip 2\emwidth\relax}
673
674\fi
675
676\unexpanded\def\negenspace{\kern-.5\emwidth}
677\unexpanded\def\negemspace{\kern-  \emwidth}
678
679\unexpanded\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers)
680
681\unexpanded\def\quads
682  {\dosingleempty\spac_quads}
683
684\def\spac_quads[#1]%
685  {\zwj\dorecurse{\iffirstargument#1\else\plusthree\fi}{\hskip\emwidth\zwj}}
686
687% Suggested by GB (not the name -):
688
689\def\rapfillskip{.5\hsize plus .092\hsize minus .5\hsize} % D.A.'s value
690
691% Bovendien definieren we enkele extra \fill's:
692
693\unexpanded\def\hfilll   {\hskip\zeropoint\s!plus1\s!filll\relax}
694\unexpanded\def\vfilll   {\vskip\zeropoint\s!plus1\s!filll\relax}
695
696%unexpanded\def\hfilneg  {\hskip\zeropoint\s!plus-1\s!fil\relax}
697\unexpanded\def\hfillneg {\hskip\zeropoint\s!plus-1\s!fill\relax}
698\unexpanded\def\hfilllneg{\hskip\zeropoint\s!plus-1\s!filll\relax}
699%unexpanded\def\vfilneg  {\vskip\zeropoint\s!plus-1\s!fil\relax}
700\unexpanded\def\vfillneg {\vskip\zeropoint\s!plus-1\s!fill\relax}
701\unexpanded\def\vfilllneg{\vskip\zeropoint\s!plus-1\s!filll\relax}
702
703\unexpanded\def\tfskip    {\begingroup\tf\hskip\emwidth\endgroup}
704\unexpanded\def\dotfskip#1{\begingroup\tf\hskip      #1\endgroup} % used elsewhere
705
706% maybe we should hash the analysis
707
708\installcorenamespace{narrower}
709\installcorenamespace{narrowermethod}
710
711\newskip\s_spac_narrower_left
712\newskip\s_spac_narrower_right
713\newskip\s_spac_narrower_middle
714
715\installcommandhandler \??narrower {narrower} \??narrower
716
717\setupnarrower
718  [\c!before=\endgraf,
719   \c!after=\endgraf,
720   \c!left=1.5\emwidth,
721   \c!right=1.5\emwidth,
722   \c!middle=1.5\emwidth,
723   \c!default=\v!middle]
724
725\appendtoks
726   \setuevalue{\e!start\currentnarrower}{\spac_narrower_start{\currentnarrower}}%
727   \setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}%
728\to \everydefinenarrower
729
730\unexpanded\def\installnarrowermethod#1#2%
731  {\setvalue{\??narrowermethod#1}{#2}}
732
733\unexpanded\def\spac_narrower_method_analyze#1%
734  {\ifcsname\??narrowermethod#1\endcsname
735     \lastnamedcs
736   \else
737     \global\advance\s_spac_narrower_middle#1\relax
738   \fi}
739
740\def\spac_narrower_initialize[#1]% hm, can be dorepeat directly
741  {\dorepeatwithcommand[#1]\spac_narrower_method_analyze}
742
743\installnarrowermethod  \v!left   {\global\advance\s_spac_narrower_left   \narrowerparameter\c!left  \relax}
744\installnarrowermethod  \v!middle {\global\advance\s_spac_narrower_middle \narrowerparameter\c!middle\relax}
745\installnarrowermethod  \v!right  {\global\advance\s_spac_narrower_right  \narrowerparameter\c!right \relax}
746\installnarrowermethod{-\v!left  }{\global\advance\s_spac_narrower_left  -\narrowerparameter\c!left  \relax}
747\installnarrowermethod{-\v!middle}{\global\advance\s_spac_narrower_middle-\narrowerparameter\c!middle\relax}
748\installnarrowermethod{-\v!right }{\global\advance\s_spac_narrower_right -\narrowerparameter\c!right \relax}
749\installnarrowermethod  \v!reset  {\global        \s_spac_narrower_left   \zeropoint
750                                   \global        \s_spac_narrower_middle \zeropoint
751                                   \global        \s_spac_narrower_right  \zeropoint\relax}
752\installnarrowermethod \v!none    {}
753\installnarrowermethod \v!reverse {} % never seen
754
755\unexpanded\def\spac_narrower_start#1%
756  {\begingroup
757   \edef\currentnarrower{#1}%
758   \dosingleempty\spac_narrower_start_indeed}
759
760\unexpanded\def\spac_narrower_start_indeed[#1]%
761  {\iffirstargument
762     \spac_narrower_start_apply{#1}%
763   \else
764     \spac_narrower_start_apply{\narrowerparameter\v!default}%
765   \fi}
766
767\newskip\s_spac_narrower_left_last
768\newskip\s_spac_narrower_right_last
769\newconditional\s_spac_narrower_last_swap
770
771\def\spac_narrower_start_apply#1%
772  {\narrowerparameter\c!before
773   \global\s_spac_narrower_left  \zeropoint
774   \global\s_spac_narrower_right \zeropoint
775   \global\s_spac_narrower_middle\zeropoint
776   \edef\askednarrower{#1}%
777   \ifx\askednarrower\v!reverse
778     \ifconditional\s_spac_narrower_last_swap
779       \leftskip \s_spac_narrower_right_last
780       \rightskip\s_spac_narrower_left_last
781       \setfalse\s_spac_narrower_last_swap
782     \else
783       \leftskip \s_spac_narrower_left_last
784       \rightskip\s_spac_narrower_right_last
785       \settrue\s_spac_narrower_last_swap
786     \fi
787   \else
788     \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize
789     \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
790     \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
791   \fi
792   \seteffectivehsize}
793
794\unexpanded\def\spac_narrower_stop
795  {\narrowerparameter\c!after
796   \normalexpanded{%
797      \endgroup
798      \s_spac_narrower_left_last \the\leftskip \relax
799      \s_spac_narrower_right_last\the\rightskip\relax
800      \ifconditional\s_spac_narrower_last_swap
801        \setfalse\s_spac_narrower_last_swap
802      \else
803        \settrue\s_spac_narrower_last_swap
804      \fi
805   }}
806
807\unexpanded\def\startnarrower
808  {\dosingleempty\spac_narrower_start_basic}
809
810\unexpanded\def\spac_narrower_start_basic[#1]%
811  {\begingroup
812   \let\currentnarrower\empty
813   \iffirstargument
814     \spac_narrower_start_apply{#1}%
815   \else
816     \spac_narrower_start_apply{\narrowerparameter\v!default}%
817   \fi}
818
819\let\stopnarrower\spac_narrower_stop
820
821\unexpanded\def\startnarrow % current how
822  {\begingroup
823   \dodoubleempty\spac_narrower_start_named}
824
825% \def\spac_narrower_start_named[#1][#2]%
826%   {\edef\currentnarrower{#1}%
827%    \ifsecondargument
828%      \spac_narrower_start_apply{#2}%
829%    \else
830%      \spac_narrower_start_apply{\narrowerparameter\v!default}%
831%    \fi}
832
833\def\spac_narrower_start_named
834  {\ifsecondargument
835      \expandafter\spac_narrower_start_named_two
836   \else
837      \expandafter\spac_narrower_start_named_one
838   \fi}
839
840\def\spac_narrower_start_named_one[#1]%
841  {\doifelseassignment{#1}\spac_narrower_start_named_one_yes\spac_narrower_start_named_one_nop[#1]}
842
843\def\spac_narrower_start_named_one_yes[#1][#2]% [settings] []
844  {\setupcurrentnarrower[#1]%
845   \spac_narrower_start_apply{\narrowerparameter\v!default}}
846
847\def\spac_narrower_start_named_one_nop[#1][#2]% [tag] []
848  {\edef\currentnarrower{#1}%
849   \spac_narrower_start_apply{\narrowerparameter\v!default}}
850
851\def\spac_narrower_start_named_two[#1]%
852  {\doifelseassignment{#1}\spac_narrower_start_named_settings_how\spac_narrower_start_named_tag_unknown[#1]}
853
854\def\spac_narrower_start_named_settings_how[#1][#2]% [settings] [how]
855  {\setupcurrentnarrower[#1]%
856   \spac_narrower_start_apply{#2}}
857
858\def\spac_narrower_start_named_tag_unknown[#1][#2]% [tag] [...]
859  {\doifelseassignment{#2}\spac_narrower_start_named_tag_settings\spac_narrower_start_named_tag_how[#1][#2]}
860
861\def\spac_narrower_start_named_tag_settings[#1][#2]% [tag] [settings]
862  {\edef\currentnarrower{#1}%
863   \setupcurrentnarrower[#2]%
864   \spac_narrower_start_apply{\narrowerparameter\v!default}}
865
866\def\spac_narrower_start_named_tag_how[#1][#2]% [tag] [how]
867  {\edef\currentnarrower{#1}%
868   \spac_narrower_start_apply{#2}}
869
870\let\stopnarrow\spac_narrower_stop
871
872\newdimen\d_spac_effective_hsize     \def\effectivehsize    {\hsize}
873\newdimen\d_spac_effective_leftskip  \def\effectiveleftskip {\dimexpr\leftskip \relax}
874\newdimen\d_spac_effective_rightskip \def\effectiverightskip{\dimexpr\rightskip\relax}
875
876\unexpanded\def\seteffectivehsize
877  {\setlocalhsize
878   \d_spac_effective_hsize    \localhsize
879   \d_spac_effective_leftskip 1\leftskip
880   \d_spac_effective_rightskip1\rightskip
881   \let\effectivehsize    \d_spac_effective_hsize
882   \let\effectiveleftskip \d_spac_effective_leftskip
883   \let\effectiverightskip\d_spac_effective_rightskip}
884
885\installcorenamespace{skipadaptionleft}
886\installcorenamespace{skipadaptionright}
887
888\newskip\leftskipadaption
889\newskip\rightskipadaption
890
891\setvalue{\??skipadaptionleft \v!yes     }{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
892\letvalue{\??skipadaptionleft \v!no      }\zeropoint
893\letvalue{\??skipadaptionleft \empty     }\zeropoint
894\setvalue{\??skipadaptionright\v!yes     }{\narrowerparameter\c!right}
895\letvalue{\??skipadaptionright\v!no      }\zeropoint
896\letvalue{\??skipadaptionright\empty     }\zeropoint
897
898% \setvalue{\??skipadaptionleft \v!standard}{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
899% \setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right}
900
901\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname
902\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname
903
904% \unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
905% \unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
906
907\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax}
908\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax}
909
910\unexpanded\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\advance\leftskip \leftskipadaption }
911\unexpanded\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\advance\rightskip\rightskipadaption}
912
913\unexpanded\def\forgetbothskips
914  {\leftskip\zeropoint
915   \rightskip\zeropoint
916   \relax}
917
918\appendtoks
919    \forgetbothskips
920\to \everyforgetall
921
922% in spac-ver.mkiv
923%
924% \unexpanded\def\forgetparskip
925%   {\s_spac_whitespace_parskip\zeropoint
926%    \parskip\zeropoint
927%    \let\v_spac_whitespace_current\v!none}
928%
929% \appendtoks
930%     \forgetparskip
931% \to \everyforgetall
932
933%D Tolerance (can also be set with align):
934
935\installcorenamespace{tolerancemethods}
936
937\unexpanded\def\installtolerancemethod#1#2#3%
938  {\setvalue{\??tolerancemethods#1:#2}{#3}}
939
940\installtolerancemethod \v!vertical   \v!verystrict   {\let\bottomtolerance\empty}
941\installtolerancemethod \v!vertical   \v!strict       {\def\bottomtolerance{.050}}
942\installtolerancemethod \v!vertical   \v!tolerant     {\def\bottomtolerance{.075}}
943\installtolerancemethod \v!vertical   \v!verytolerant {\def\bottomtolerance{.100}}
944
945\installtolerancemethod \v!horizontal \v!stretch      {\emergencystretch\bodyfontsize}
946\installtolerancemethod \v!horizontal \v!space        {\spaceskip.5em\s!plus.25em\s!minus.25em\relax}
947\installtolerancemethod \v!horizontal \v!verystrict   {\tolerance\plustwohundred}
948\installtolerancemethod \v!horizontal \v!strict       {\tolerance1500 }
949\installtolerancemethod \v!horizontal \v!tolerant     {\tolerance3000 }
950\installtolerancemethod \v!horizontal \v!verytolerant {\tolerance4500 }
951
952\appendetoks
953     \pretolerance\plushundred
954     \tolerance   \plustwohundred
955\to\everyforgetall
956
957\def\spac_tolerances_step_vertical  #1{\csname\??tolerancemethods\v!vertical  :#1\endcsname}
958\def\spac_tolerances_step_horizontal#1{\csname\??tolerancemethods\v!horizontal:#1\endcsname}
959
960\unexpanded\def\setuptolerance
961  {\dosingleargument\spac_tolerances_setup}
962
963\def\spac_tolerances_setup[#1]%
964  {\doifelseinset\v!vertical{#1}%
965     {\processcommacommand[#1]\spac_tolerances_step_vertical  }
966     {\processcommacommand[#1]\spac_tolerances_step_horizontal}}
967
968%D \macros
969%D   {pushindentation,popindentation}
970%D
971%D The pushing and popping is done by:
972
973\newbox\b_spac_indentations_a
974\newbox\b_spac_indentations_b
975
976\unexpanded\def\pushindentation
977  {\begingroup
978   \ifhmode
979     \unskip
980     \setbox\b_spac_indentations_a\lastbox       % get \strut if present
981     \unskip
982     \setbox\b_spac_indentations_b\lastbox       % get \indent generated box
983     \unskip
984   \else
985     \dontleavehmode % was \hskip\zeropoint      % switch to horizontal mode
986     \unskip
987     \setbox\b_spac_indentations_a\lastbox       % get \indent generated box
988     \setbox\b_spac_indentations_b\emptybox
989   \fi}
990
991\unexpanded\def\popindentation
992  {\box\b_spac_indentations_b
993   \box\b_spac_indentations_a
994   \endgroup}
995
996%D The only complication lays in \type{\strut}. In \PLAIN\
997%D \TEX\ a \type{\strut} is defined as:
998%D
999%D \starttyping
1000%D \def\strut%
1001%D   {\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
1002%D \stoptyping
1003%D
1004%D But what is a \type{\strut}? Normally it's a rule of width
1005%D zero, but when made visual, it's a rule and a negative skip.
1006%D The mechanism for putting things in the margins described
1007%D here cannot handle this situation very well. One
1008%D characteristic of \type{\strut} is that the \type{\unhcopy}
1009%D results in entering horizontal mode, which in return leads
1010%D to some indentation.
1011%D
1012%D To serve our purpose a bit better, the macro \type{\strut}
1013%D can be redefined as:
1014%D
1015%D \starttyping
1016%D \def\strut
1017%D   {\relax\ifmmode\else\hskip0pt\fi\copy\strutbox}
1018%D \stoptyping
1019%D
1020%D Or more compatible:
1021%D
1022%D \starttyping
1023%D \def\strut
1024%D   {\relax\ifmmode
1025%D      \copy\strutbox
1026%D    \else
1027%D      \bgroup\setbox\strutbox=\hbox{\box\strutbox}\unhcopy\strutbox\egroup
1028%D    \fi}
1029%D \stoptyping
1030%D
1031%D In \CONTEXT\ however we save some processing time by putting
1032%D an extra \type{\hbox} around the \type{\strutbox}.
1033
1034%D \starttyping
1035%D % \setuplayout[gridgrid=yes] \showgrid
1036%D
1037%D \startbuffer
1038%D test 1\crlf
1039%D test 2\crlf
1040%D
1041%D \crlf test 3
1042%D
1043%D test 4\crlf
1044%D test 5
1045%D
1046%D \crlf
1047%D \crlf
1048%D \crlf
1049%D test 6
1050%D \stopbuffer
1051%D
1052%D \hbox
1053%D   {\hsize5em
1054%D    \ruledvtop{\getbuffer}\enspace
1055%D    \ruledvtop{\showstruts\getbuffer}\enspace
1056%D    \hsize15em \setuptyping[before=,after=]%
1057%D    \ruledvtop{\typebuffer}}
1058%D \stoptyping
1059
1060\unexpanded\def\justonespace{\removeunwantedspaces\space}
1061%unexpanded\def\justaperiod {\removeunwantedspaces.}
1062%unexpanded\def\justacomma  {\removeunwantedspaces,}
1063
1064\installcorenamespace{hspace}
1065
1066\unexpanded\def\ignorecrlf
1067  {\let\crlf\justonespace\let\\\crlf}
1068
1069\unexpanded\def\definehspace
1070  {\dotripleempty\spac_hspaces_define}
1071
1072\def\spac_hspaces_define[#1][#2][#3]% #1 = optional namespace
1073  {\ifthirdargument
1074     \setvalue{\??hspace#1:#2}{#3}%
1075   \else
1076     \setvalue{\??hspace:#1}{#2}%
1077   \fi}
1078
1079\unexpanded\def\hspace
1080  {\dodoubleempty\spac_hspaces_insert}
1081
1082\def\spac_hspaces_insert[#1][#2]%
1083  {\ifhmode
1084     \removeunwantedspaces
1085     \hskip % always a skip even when 0pt
1086       \ifsecondargument
1087         \hspaceamount{#1}{#2}%
1088       \else\iffirstargument
1089         \hspaceamount\empty{#1}%
1090       \else
1091         \hspaceamount\empty\s!default
1092       \fi\fi
1093     \expandafter\ignorespaces
1094   \fi}
1095
1096\def\hspaceamount#1#2%
1097  {\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax}
1098
1099\def\directhspaceamount#1%
1100  {\dimexpr\ifcsname\??hspace  :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
1101
1102% no installhspace here (this is already an old command)
1103
1104\definehspace [\v!small]   [.25\emspaceamount]
1105\definehspace [\v!medium]  [.5\emspaceamount]
1106\definehspace [\v!big]     [1\emspaceamount]
1107\definehspace [\v!normal]  [1\spaceamount]
1108\definehspace [\v!default] [\spaceamount]
1109\definehspace [\v!none]    [\zeropoint]
1110
1111%D Taken from Taco's math module (cq. \AMS\ macros), but
1112%D adapted to \type {\hspace}:
1113
1114\unexpanded\def\textormathspace         #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax}
1115\unexpanded\def\textormathspacecommand  #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax}
1116\unexpanded\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax}
1117
1118\newmuskip\hairmuskip \hairmuskip=.15mu
1119
1120\unexpanded\def\hairspace    {\textormathspace+\hairmuskip{.5}}
1121\unexpanded\def\thinspace    {\textormathspace+\thinmuskip 1}
1122%unexpanded\def\medspace     {\textormathspace+\medmuskip  2}      % 4/18 em
1123\unexpanded\def\thickspace   {\textormathspace+\thickmuskip3}
1124\unexpanded\def\neghairspace {\textormathspace-\thinmuskip{.5}}
1125\unexpanded\def\negthinspace {\textormathspace-\thinmuskip 1}
1126\unexpanded\def\negmedspace  {\textormathspace-\medmuskip  2}
1127\unexpanded\def\negthickspace{\textormathspace-\thickmuskip3}
1128
1129\unexpanded\edef\medspace    {\textormathspacecommand+\medmuskip{\Uchar"205F}}
1130
1131% needed for unicode:
1132
1133%unexpanded\def\breakablethinspace      {\breakabletextormathspace+\thinmuskip1}
1134%unexpanded\def\twoperemspace           {\hskip\dimexpr\emwidth/2\relax} % == \enspace
1135%unexpanded\def\threeperemspace         {\hskip\dimexpr\emwidth/3\relax}
1136%unexpanded\def\fourperemspace          {\hskip\dimexpr\emwidth/4\relax}
1137%unexpanded\def\fiveperemspace          {\hskip\dimexpr\emwidth/5\relax} % goodie
1138%unexpanded\def\sixperemspace           {\hskip\dimexpr\emwidth/6\relax}
1139%unexpanded\def\figurespace             {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this
1140%unexpanded\def\punctuationspace        {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup}
1141%unexpanded\def\ideographicspace        {\hskip\dimexpr\emwidth/1\relax}
1142%unexpanded\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax}
1143%unexpanded\def\nobreakspace            {\penalty\plustenthousand\kern\interwordspace}
1144%unexpanded\def\narrownobreakspace      {\penalty\plustenthousand\thinspace}
1145%unexpanded\def\zerowidthnobreakspace   {\penalty\plustenthousand\kern\zeropoint}
1146%unexpanded\def\zerowidthspace          {\hskip\zeropoint}
1147
1148\definehspace[.5][.1250\emwidth] % hair
1149\definehspace[1] [.1667\emwidth] % thin
1150\definehspace[2] [.2222\emwidth] % med
1151\definehspace[3] [.2777\emwidth] % thick
1152
1153\let \, \thinspace
1154\let \: \medspace
1155\let \; \thickspace
1156\let \! \negthinspace
1157
1158% plain ...
1159%
1160% \ifdefined\> \else \unexpanded\def\>{\mskip \medmuskip  }                                \fi
1161% \ifdefined\* \else \unexpanded\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
1162
1163\def\flexiblespaceamount#1#2#3%
1164         {#1\interwordspace
1165   \s!plus#2\interwordstretch
1166  \s!minus#3\interwordshrink}
1167
1168\def\fixedspaceamount#1%
1169  {#1\interwordspace}
1170
1171% moved from page-lin
1172%
1173% the following code is used in startlines\stoplines
1174%
1175% do we need \normalspaceprimitive here?
1176
1177\installcorenamespace{spacemethods}
1178
1179\unexpanded\def\installspacemethod#1#2% needs to set \obeyedspace
1180  {\setvalue{\??spacemethods#1}{#2}}
1181
1182\def\activatespacehandler#1%
1183  {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname}
1184
1185\unexpanded\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}%
1186\unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}%
1187\unexpanded\def\spac_spaces_checked_fixed  {\mathortext\normalspace{\dontleavehmode\fixedspace}}%
1188
1189% hm, order matters when we \let in \obeyspaces
1190
1191\installspacemethod \v!on
1192  {\obeyspaces
1193   \let\obeyedspace\spac_spaces_checked_control
1194   \let\ =\obeyedspace}
1195
1196\installspacemethod \v!yes
1197  {\obeyspaces
1198   \let\obeyedspace\spac_spaces_checked_normal
1199   \let\ =\obeyedspace}
1200
1201\installspacemethod \v!off % == default
1202  {\normalspaces
1203   \let\obeyedspace\normalspace
1204   \let\ =\normalspaceprimitive} % was \normalspace
1205
1206\installspacemethod \v!fixed
1207  {\obeyspaces
1208   \let\obeyedspace\spac_spaces_checked_fixed
1209   \let\ =\obeyedspace}
1210
1211\appendtoks
1212   \normalspaces % to be sure
1213\to \everybeforeoutput
1214
1215%D A more robust variant of the \MKII\ one:
1216%D
1217%D \startbuffer
1218%D bla \TEX\autoinsertnextspace bla
1219%D bla \TEX\autoinsertnextspace (bla)
1220%D bla (\TEX\autoinsertnextspace) bla
1221%D bla \TEX\autoinsertnextspace\ bla
1222%D \stopbuffer
1223%D
1224%D \typebuffer \getbuffer
1225
1226\unexpanded\def\autoinsertnextspace
1227  {\futurelet\nexttoken\spac_spaces_auto_insert_next}
1228
1229\def\spac_spaces_auto_insert_next
1230  {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end
1231
1232%D Moved from bib module:
1233
1234\unexpanded\def\outdented#1%
1235  {\hskip-\hangindent#1\relax}
1236
1237%D Beware: due to char-def this becomes an active character but that
1238%D might change sometime when we will replace all these specials to
1239%D node insertions. We might even expand it to utf then as it then
1240%D can be used in string comparison (not that much needed anyway).
1241
1242% \chardef\zwnj="200C
1243% \chardef\zwj ="200D
1244
1245% TODO (but used in languages):
1246
1247\unexpanded\def\spac_glues_text_or_math#1#2%
1248  {\begingroup
1249   \ifmmode
1250     \mskip#1%
1251   \else
1252     \scratchdimen#1\hspaceamount\empty{#2}%
1253     \scratchskip\scratchdimen\s!plus.5\scratchdimen\s!minus.3\scratchdimen
1254     \hskip\scratchskip
1255   \fi
1256   \endgroup}
1257
1258\unexpanded\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small}
1259\unexpanded\def\medglue  {\spac_glues_text_or_math\medmuskip  \v!medium}
1260\unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big}
1261
1262%D A rather unknown one:
1263
1264\unexpanded\def\widened % moved from cont-new
1265  {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop}
1266
1267\def\spac_widened_yes[#1]#2{\hbox \s!spread       #1{\hss#2\hss}}
1268\def\spac_widened_nop    #1{\hbox \s!spread \emwidth{\hss#1\hss}}
1269
1270\definecomplexorsimple\widened
1271
1272%D For the moment here (used in page-txt):
1273
1274\unexpanded\def\ignoredlinebreak{\unskip\space\ignorespaces}
1275
1276%D \macros
1277%D   {startignorespaces}
1278%D
1279%D I'll probably forget that this one exists:
1280%D
1281%D \starttyping
1282%D \ruledhbox
1283%D   {\startignorespaces
1284%D      \def\oeps{a}
1285%D      \startignorespaces
1286%D        \def\oeps{a}
1287%D      \stopignorespaces
1288%D      \def\oeps{a}
1289%D    \stopignorespaces
1290%D    \oeps}
1291%D \stoptyping
1292
1293\newsignal\s_spac_ignore_spaces
1294\newcount \c_spac_ignore_spaces
1295
1296\unexpanded\def\startignorespaces
1297  {\advance\c_spac_ignore_spaces\plusone
1298   \ifcase\c_spac_ignore_spaces\or \ifhmode
1299     \hskip\s_spac_ignore_spaces
1300   \fi \fi
1301   \ignorespaces}
1302
1303\unexpanded\def\stopignorespaces
1304  {\ifcase\c_spac_ignore_spaces \or
1305     \ifhmode
1306       \doloop\spac_ignore_spaces_body
1307     \fi
1308   \fi
1309   \advance\c_spac_ignore_spaces\minusone}
1310
1311\def\spac_ignore_spaces_body
1312  {\ifzeropt\lastskip
1313     \exitloop
1314   \else\ifdim\lastskip=\s_spac_ignore_spaces
1315     \unskip
1316     \exitloop
1317   \else
1318     \unskip
1319   \fi\fi}
1320
1321%D \macros
1322%D   {obeyfollowingtoken}
1323
1324\def\obeyfollowingtoken{{}}  % end \cs scanning
1325
1326%D Something new:
1327
1328\unexpanded\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax}
1329\unexpanded\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary}
1330
1331\unexpanded\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore}
1332\unexpanded\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter}
1333\unexpanded\def\interwordspaces      #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter}
1334
1335\protect \endinput
1336