core-mis.tex / last modification: 2008-06-20 18:07
%D \module
%D   [       file=core-mis,
%D        version=1998.01.29,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Miscelaneous,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%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 Core Macros / Misc Commands}

% todo: kleur in legenda + letter

% Obsolete
%
% \startmessages  dutch  library: systems
%   title: systeem
%       3: probeer LaTeX eens
% \stopmessages
%
% \startmessages  english  library: systems
%   title: system
%       3: try LaTeX
% \stopmessages
%
% \startmessages  german  library: systems
%   title: system
%       3: Versuche LaTeX
% \stopmessages
%
% \startmessages  czech  library: systems
%   title: system
%       3: zkuste LaTeX
% \stopmessages
%
% \startmessages  italian  library: systems
%   title: sistema
%       3: provare LaTeX
% \stopmessages
%
% \startmessages  norwegian  library: systems
%   title: system
%       3: forsøker LaTeX
% \stopmessages
%
% \startmessages  romanian  library: systems
%   title: sistem
%       3: incercati LaTeX
% \stopmessages
%

% %D You would not expect the next macro in \CONTEXT,
% %D wouldn't you? It's there to warn \LATEX\ users that
% %D something is wrong.
% %D
% %D Obsolete now:
% %
% % \def\documentstyle{\showmessage\m!systems3\empty\stoptekst}
% %
% % \let\documentclass=\documentstyle
% %D \macros
% %D   {simplifiedcommands, simplifycommands}
% %D
% %D I first needed this simplification in bookmarks. Users can
% %D add their own if needed.

\unprotect

%D Sometimes (for instance in bookmarks) we need to simplify macro
%D behaviour, so here is the hook.

\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi

\def\simplifycommands{\the\simplifiedcommands}

%D A possibly growing list:

%appendtoks        \def\executesynonym#1#2#3#4{#3}\to\simplifiedcommands
%appendtoks             \def\executesort#1#2#3{#3}\to\simplifiedcommands

\appendtoks                                \def\ { }\to\simplifiedcommands
\appendtoks  \def\type#1{\string\\\strippedcsname#1}\to\simplifiedcommands
\appendtoks                  \def\tex#1{\string\\#1}\to\simplifiedcommands
\appendtoks                            \def\TeX{TeX}\to\simplifiedcommands
\appendtoks                    \def\ConTeXt{ConTeXt}\to\simplifiedcommands
\appendtoks                  \def\MetaPost{MetaPost}\to\simplifiedcommands
\appendtoks                  \def\MetaFont{MetaFont}\to\simplifiedcommands
\appendtoks                    \def\MetaFun{MetaFun}\to\simplifiedcommands
%appendtoks                                \def||{-}\to\simplifiedcommands
\appendtoks  \def|#1|{\ifx#1\empty\empty-\else#1\fi}\to\simplifiedcommands

\appendtoks\let\buildtextaccent\secondoftwoarguments\to\simplifiedcommands

% THIS WAS MAIN-002.TEX

%\def\checkinterlineskip
%  {\ifvmode
%     \ifdim\lastskip>\zeropoint
%       \nointerlineskip
%     \else\ifdim\lastkern>\zeropoint
%       \nointerlineskip
%     \fi\fi
%   \fi}

\def\horitems#1#2% #1=breedte #2=commandos
  {\scratchdimen#1%
   \divide\scratchdimen \nofitems
   \!!counta\zerocount
   \def\docommand##1%
     {\advance\!!counta \plusone
      \processaction
        [\@@isalign]
        [   \v!left=>\hbox to \scratchdimen{\strut##1\hss},
           \v!right=>\hbox to \scratchdimen{\hss\strut##1},
          \v!middle=>\hbox to \scratchdimen{\hss\strut##1\hss},
          \v!margin=>\ifnum\!!counta=\plusone\hss\else\hfill\fi
                     \strut##1%
                     \ifnum\!!counta=\nofitems\hss\else\hfill\fi,
         \s!default=>\hbox to \scratchdimen{\hss\strut##1\hss}, % midden
         \s!unknown=>\hbox to \scratchdimen{\strut##1\hss}]}%   % links
   \hbox to #1{\hss#2\hss}}

\def\veritems#1#2% #1=breedte #2=commandos
  {\scratchdimen#1%
   \def\docommand##1%
     {\ifdim\scratchdimen<\zeropoint % the - was a signal
        \hbox to -\scratchdimen{\hss\strut##1}%
      \else\ifdim\scratchdimen>\zeropoint
        \hbox to \scratchdimen{\strut##1\hss}%
      \else
        \hbox{\strut##1}%
      \fi\fi}%
   \vbox{#2}}

\def\dosetupitems[#1]%
  {\getparameters[\??is][#1]%
   \doif\@@iswidth\v!unknown
     {\def\@@iswidth{\hsize}}%
   \doifconversiondefinedelse\@@issymbol
     {\def\doitembullet##1{\convertnumber{\@@issymbol}{##1}}}
     {\doifsymboldefinedelse\@@issymbol
        {\def\doitembullet##1{\symbol[\@@issymbol]}}{}}}

\def\makeitemsandbullets#1%
  {\doifelse\@@isn\v!unknown
     {\getcommalistsize[#1]%
      \edef\nofitems{\commalistsize}}
     {\edef\nofitems{\@@isn}}%
   \setbox0\hbox
     {\doitems \@@iswidth
        {\processcommalist[#1]\docommand}}%
   \setbox2\hbox
     {\doitems \@@isbulletbreedte
        {\dorecurse\nofitems
           {\docommand{\strut\doitembullet\recurselevel}}}}}

\def\dostartitems#1#2#3%
  {\let\doitems#2%
   \def\@@isbulletbreedte{#3}%
   \makeitemsandbullets{#1}%
   \@@isbefore}

\def\dostopitems
  {\@@isafter
   \egroup}

\setvalue{doitems\v!top}#1%
  {\dostartitems{#1}\horitems\@@iswidth
   \noindent\vbox
     {\forgetall
      \doifsomething\@@issymbol
        {\doifnot\@@issymbol\v!none
           {\box2
            \@@isinbetween
            \nointerlineskip}}%
      \box0}%
   \dostopitems}

\setvalue{doitems\v!bottom}#1%
  {\dostartitems{#1}\horitems\@@iswidth
   \noindent\vbox
     {\forgetall
      \box0
      \doifsomething\@@issymbol
        {\@@isinbetween
         \nointerlineskip
         \box2}}%
   \dostopitems}

\setvalue{doitems\v!inmargin}#1%
  {\dostartitems{#1}\veritems{-1.5em}%  - is a signal
   \noindent\hbox{\llap{\box2\hskip\leftmargindistance}\box0}%
   \dostopitems}

\setvalue{doitems\v!left}#1%
  {\advance\hsize -1.5em%
   \dostartitems{#1}\veritems{1.5em}%
   \noindent\hbox{\box2\box0}%
   \dostopitems}

\setvalue{doitems\v!right}#1%
  {\dostartitems{#1}\veritems{0em}%
   \noindent\hbox{\box0\hskip-\wd2\box2}%
   \dostopitems}

\def\setupitems
  {\dosingleargument\dosetupitems}

\def\complexitems[#1]%
  {\bgroup
   \setupitems[#1]%
   \parindent\zeropoint
   \setlocalhsize
   \hsize\localhsize
   \dontcomplain
  %\doifundefined{doitems\@@islocation}%
  %  {\let\@@islocation\v!left}%
  %\getvalue{doitems\@@islocation}}
   \executeifdefined{doitems\@@islocation}{\let\@@islocation\v!left}}

\definecomplexorsimpleempty\items

\setupitems
  [\c!location=\v!left,
   \c!symbol=5,
   \c!width=\hsize,
   \c!align=\v!middle,
   \c!n=\v!unknown,
   \c!before=\blank,
   \c!inbetween={\blank[\v!medium]},
   \c!after=\blank]

% Te zijner tijd [plaats=boven,onder,midden] implementeren,
% in dat geval moet eerst de maximale hoogte worden bepaald.
%
% Overigens kan een en ander mooier met \halign.

% there is quite some historic balast in this mechanism, the next variant
% is a first cleanup

\let\currentparagraph\empty

\newcount\alcounter \newcount\alnsize \newdimen\alhsize

\def\paragraphparameter#1% \checkedparameter\??al\currentparagraph#1
  {\executeifdefined{\??al\currentparagraph#1}{\executeifdefined{\??al#1}\empty}}

\def\paragraphcellmeter#1#2% \checkedparameter\??al\currentparagraph#1
  {\executeifdefined{\??al\currentparagraph\number#1#2}{\paragraphparameter{#2}}}

\def\dodefineparagraphs[#1][#2]%
  {\edef\currentparagraph{#1}%
   \setvalue{\s!do\s!next\currentparagraph}%
     {\def\\{\getvalue\currentparagraph}}%
   \setvalue\currentparagraph
     {\getvalue{\s!do\s!next#1}%
      \dostartparagraphs{#1}}%
   \setvalue{\e!next\currentparagraph}%
     {\getvalue{#1}}%
   \setvalue{\e!start\currentparagraph}%
     {\bgroup
      \edef\currentparagraph{#1}%
      \letvalue{\s!do\s!next\currentparagraph}\empty
      \setvalue{\e!stop\currentparagraph}{\getvalue\currentparagraph\egroup}%
      \getvalue\currentparagraph}%
   \getparameters[\??al\currentparagraph]%
     [%\c!n=3,
      %\c!before=\blank,
      %\c!after=\blank,
      %\c!distance=1em,
      %\c!height=\v!fit,
      %\c!rule=\v!off,
      %\c!command=,
      %\c!align=,
      %\c!tolerance=\v!tolerant,
      %\c!rulethickness=\linewidth,
      %\c!rulecolor=,
      %\c!style=,
      %\c!color=,
      %\c!top=,
      %\c!top=\vss,
      %\c!bottom=\vfill,
      #2]%
   \setvalue{\e!setup#1\e!endsetup}%
     {\setupparagraphs[#1]}%
   \dorecurse
      {\paragraphparameter\c!n}
      {\setupparagraphs
         [\currentparagraph]
         [\recurselevel]
         [\c!width=,
         %\c!bottom=\paragraphparameter\c!bottom,
         %\c!top=\paragraphparameter\c!top,
         %\c!height=\paragraphparameter\c!height,
         %\c!rule=\paragraphparameter\c!rule,
         %\c!rulethickness=\paragraphparameter\c!rulethickness,
         %\c!rulecolor=\paragraphparameter\c!rulecolor,
         %\c!align=\paragraphparameter\c!align,
         %\c!tolerance=\paragraphparameter\c!tolerance, % obsolete
         %\c!distance=\paragraphparameter\c!distance,
          \c!style=\paragraphparameter\c!style,
          \c!color=\paragraphparameter\c!color]}%
   \setupparagraphs[\currentparagraph][1][\c!distance=\zeropoint]}

\def\defineparagraphs
  {\dodoubleargument\dodefineparagraphs}

\def\dosetupparagraphs[#1][#2][#3]%
  {\edef\currentparagraph{#1}%
   \ifsecondargument
     \doifelse{#2}\v!each
       {\dorecurse
          {\paragraphparameter\c!n}
          {\getparameters[\??al\currentparagraph\recurselevel][#3]}}
       {\doifelsenothing{#3}
          {\getparameters[\??al\currentparagraph][#2]}
          {\def\docommand##1{\getparameters[\??al\currentparagraph##1][#3]}%
           \processcommalist[#2]\docommand}}%
   \else
     \getparameters[\??al][#1]%
   \fi}

\def\setupparagraphs
  {\dotripleempty\dosetupparagraphs}

\setupparagraphs
  [\c!n=3,
   \c!before=\blank,
   \c!after=\blank,
   \c!distance=1em,
   \c!height=\v!fit,
   \c!rule=\v!off,
   \c!command=,
   \c!align=,
   \c!tolerance=\v!tolerant, % obsolete
   \c!rulethickness=\linewidth,
   \c!rulecolor=,
   \c!style=,
   \c!color=,
   \c!top=,
   \c!top=\vss,
   \c!bottom=\vfill]

\def\doparagraphrule
  {\doifelse{\paragraphcellmeter\alcounter\c!rule}\v!on
     {\linewidth\paragraphcellmeter\alcounter\c!rulethickness
      \scratchdimen\paragraphcellmeter\alcounter\c!distance
      \advance\scratchdimen-\linewidth
      \divide\scratchdimen \plustwo
      \hskip\scratchdimen
      \color[\paragraphcellmeter\alcounter\c!rulecolor]{\vrule\!!width\linewidth}%
      \hskip\scratchdimen}
     {\hskip\paragraphcellmeter\alcounter\c!distance}}

\def\dostartparagraph
  {\doifelsenothing{\paragraphcellmeter\alcounter\c!width}
     {\!!widtha\alhsize
      \divide\!!widtha \alnsize}
     {\!!widtha\paragraphcellmeter\alcounter\c!width}%
   \dostartattributes{\??al\currentparagraph\number\alcounter}\c!style\c!color\empty
   \doifelse{\paragraphcellmeter\alcounter\c!height}\v!fit
     {\setbox\scratchbox\vtop}
     {\setbox\scratchbox\vtop to \paragraphcellmeter\alcounter\c!height}%
   \bgroup
   \blank[\v!disable]%
   \forgetall
   \paragraphcellmeter\alcounter\c!top
   \paragraphparameter\c!inner
   \hsize\!!widtha % setting \wd afterwards removed
   \paragraphcellmeter\alcounter\c!inner % twice
   \expanded{\setupalign    [\paragraphcellmeter\alcounter\c!align    ]}% {normal,verytolerant,stretch}
   \expanded{\setuptolerance[\paragraphcellmeter\alcounter\c!tolerance]}% obsolete
   \ignorespaces
   \endgraf
   \ignorespaces
   %
   % Nadeel van de onderstaande constructie is dat \everypar
   % binnen een groep kan staan en zo steeds \begstruts
   % worden geplaatst. Mooi is anders dus moet het anders!
   %
   % Hier is \Everypar niet nodig.
   %
   \everypar{\begstrut\everypar\emptytoks}%
   %
   \nospace % remove + ignore
   \paragraphcellmeter\alcounter\c!command}

\def\dostopparagraph
  {\ifvmode
     \removelastskip
   \else
     \unskip\endstrut\endgraf
   \fi
   \paragraphcellmeter\alcounter\c!bottom
   \egroup
   \ifdim\wd\scratchbox=\zeropoint % no data
     \wd\scratchbox\!!widtha
   \fi
   \box\scratchbox
   \dostopattributes
   \ifnum\alcounter<\paragraphparameter\c!n\relax
     \@EA\doparagraphcell
   \else
     \@EA\dostopparagraphs
   \fi}

\def\doparagraphcell
  {\global\advance\alcounter \plusone
   \doifelsenothing{\paragraphcellmeter\alcounter\c!distance}
     {\ifnum\alcounter=\plusone\else
        \hskip\paragraphparameter\c!distance
      \fi}
     {\ifnum\alcounter=\plusone
        \hskip\paragraphcellmeter\alcounter\c!distance
      \else
        \doparagraphrule
      \fi}%
   \letvalue\currentparagraph\dostopparagraph
   \dostartparagraph}

\def\dostartparagraphs#1%
  {\bgroup
   \edef\currentparagraph{#1}%
   \global\alcounter\zerocount
   \parindent\zeropoint
   \setlocalhsize
   \alhsize\localhsize
   \alnsize\paragraphparameter\c!n\relax
   \dorecurse \alnsize
     {\doifelsenothing{\paragraphcellmeter\recurselevel\c!distance}
        {\ifnum\recurselevel=\plusone\else
           \global\advance\alhsize -\paragraphparameter\c!distance
         \fi}
        {\global\advance\alhsize -\paragraphcellmeter\recurselevel\c!distance}%
      \doifsomething{\paragraphcellmeter\recurselevel\c!width}
        {\global\advance\alnsize \minusone
         \global\advance\alhsize -\paragraphcellmeter\recurselevel\c!width}}%
   %whitespace % gaat fout bij \framed
   \paragraphparameter\c!before
   \leavevmode % gaat wel goed bij \framed, brrr
   \setbox\scratchbox\vbox\bgroup\hbox\bgroup\doparagraphcell}

\def\dostopparagraphs
  {\egroup
   \egroup
   \iftrue
     \hbox{\raise\strutheight\box\scratchbox}% new
   \else
     \box\scratchbox % old
   \fi
   \par
   \paragraphparameter\c!after
   \egroup}

\def\dosetuptab[#1]%
  {\getparameters[\??ta]
     [\c!headstyle=\v!normal,
      \c!headcolor=,
      \c!style=\v!normal,
      \c!color=,
      \c!width=\v!broad,
      \c!sample={\hskip4em},
      \c!before=,
      \c!after=,
      #1]%
   \definedescription
     [tab]
     [\c!headstyle=\@@taheadstyle,
      \c!headcolor=\@@tacolor,
      \c!sample=\@@tasample,
      \c!width=\@@tawidth,
      \c!before=\@@tabefore,
      \c!after=\@@taafter]}

\def\setuptab
  {\dosingleargument\dosetuptab}

\setuptab
  [\c!location=\v!left]

% The following macro's are derived from PPCHTEX and
% therefore take some LaTeX font-switching into account.

\newif\ifloweredsubscripts

% Due to some upward incompatibality of LaTeX to LaTeX2.09
% and/or LaTeX2e we had to force \@@chemieletter. Otherwise
% some weird \nullfont error comes up.

\doifundefined{@@chemieletter}{\def\@@chemieletter{\rm}}

\def\beginlatexmathmodehack
  {\ifmmode
     \let\endlatexmathmodehack\relax
   \else
     \def\endlatexmathmodehack{$}$\@@chemieletter
   \fi}

\def\setsubscripts
  {\beginlatexmathmodehack
   \def\dosetsubscript##1##2##3%
     {\dimen0=##3\fontexheight##2%
      \setxvalue{@@\string##1\string##2}{\the##1##2\relax}%
      ##1##2=\dimen0\relax}%
   \def\dodosetsubscript##1##2%
     {\dosetsubscript{##1}{\textfont2}{##2}%
      \dosetsubscript{##1}{\scriptfont2}{##2}%
      \dosetsubscript{##1}{\scriptscriptfont2}{##2}}%
   %dodosetsubscript\mathsupnormal  {?}%
   \dodosetsubscript\mathsubnormal  {.7}%
   \dodosetsubscript\mathsubcombined{.7}%
   \global\loweredsubscriptstrue
   \endlatexmathmodehack}

\def\resetsubscripts
  {\ifloweredsubscripts
     \beginlatexmathmodehack
     \def\doresetsubscript##1##2%
       {\dimen0=\getvalue{@@\string##1\string##2}\relax
        ##1##2=\dimen0}%
     \def\dodoresetsubscript##1%
       {\doresetsubscript{##1}{\textfont2}%
        \doresetsubscript{##1}{\scriptfont2}%
        \doresetsubscript{##1}{\scriptscriptfont2}}%
     %dodoresetsubscript\mathsupnormal
     \dodoresetsubscript\mathsubnormal
     \dodoresetsubscript\mathsubcombined
     \global\loweredsubscriptsfalse
     \endlatexmathmodehack
   \fi}

\let\beginlatexmathmodehack = \relax
\let\endlatexmathmodehack   = \relax

\def\chem#1#2#3%
  {\bgroup
   \setsubscripts
   \mathematics{\hbox{#1}_{#2}^{#3}}%
   \resetsubscripts
   \egroup}

\unexpanded\def\celsius   #1{#1\mathematics{^\circ}C}
\unexpanded\def\inch        {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}

% very dutch

\unexpanded\def\graden      {\mathematics{^\circ}}

\def\bedragprefix {\euro\normalfixedspace}
\def\bedragsuffix {}
\def\bedragempty  {\euro}

\unexpanded\def\bedrag#1%
  {\strut\hbox\bgroup
   \let\normalfixedspace\nonbreakablespace
   \doifelsenothing{#1}
     {\bedragempty}
     {\bedragprefix\digits{#1}\bedragsuffix}%
   \egroup}

% \definieeralineas[test][n=3]
%
% \stelalineasin[test][3][breedte=4cm,uitlijnen=links]
%
% \startopelkaar
% \test hans \\ ton \\ \bedrag{1.000,--} \\
% \test hans \\ ton \\ \bedrag{~.~~1,--} \\
% \test hans \\ ton \\ \bedrag{~.~~1,~~} \\
% \test hans \\ ton \\ \bedrag{~.100,--} \\
% \test hans \\ ton \\ \subtot{1.000,--} \\
% \test hans \\ ton \\ \bedrag{1.000,--} \\
% \test hans \\ ton \\ \bedrag{1.000,--} \\
% \test hans \\ ton \\ \totaal{1.000,--} \\
% \test hans \\ ton \\ \bedrag{nihil,--} \\
% \test hans \\ ton \\ \totaal{nihil,--} \\
% \test hans \\ ton \\ \subtot{nihil,--} \\
% \stopopelkaar

\def\periodswidth  {.5em}
\def\periodsdefault{3}    % was 5, but now it's like \unknown

\unexpanded\def\periods
  {\dosingleempty\doperiods}

\def\doperiods[#1]%
  {\dontleavehmode
   \begingroup
   \scratchdimen\periodswidth
   \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen
     {\leaders\hbox to \scratchdimen{\hss.\hss}\hss}%
   \endgroup}

\unexpanded\def\unknown
  {\periods\relax} % relax prevents lookahead for []

% compatibility macros

\def\doorsnede
  {\hbox{\rlap/$\circ$} }

\unexpanded\def\ongeveer
  {\mathematics\pm}

\chardef\boundarycharactermode\plusone

\def\midboundarycharacter#1#2%
  {\ifcase\boundarycharactermode
   \or
     %\nobreak
     \hskip\hspaceamount\currentlanguage{#2}%
     \languageparameter#1%
     %\nobreak
      \hskip\hspaceamount\currentlanguage{#2}%
   \or
     \languageparameter#1%
   \fi
   \chardef\boundarycharactermode\plusone}

\def\leftboundarycharacter#1#2%
  {\ifcase\boundarycharactermode
   \or
     \languageparameter#1%
     \nobreak
     \hskip\hspaceamount\currentlanguage{#2}%
   \or
     \languageparameter#1%
   \fi
   \chardef\boundarycharactermode\plusone}

\def\rightboundarycharacter#1#2%
  {\ifcase\boundarycharactermode
   \or
     \prewordbreak %\nobreak
     \hskip\hspaceamount\currentlanguage{#2}%
     \languageparameter#1%
   \or
     \languageparameter#1%
   \fi
   \chardef\boundarycharactermode\plusone}

% actually this is pretty old, but temporary moved here
%
% obsolete:

\def\setuphyphenmark
  {\dodoubleargument\getparameters[\??kp]}

\setuphyphenmark
  [\c!sign=\composedhyphen]

\def\defaultdiscretionaryhyphen{\@@kpsign}

\def\composedhyphen
  {\discretionary
     {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
     {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
     {\hbox{\directsymbol\empty\c!compoundhyphen}}}

\definesymbol[\c!leftcompoundhyphen]  [\languageparameter\c!leftcompoundhyphen]
\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
\definesymbol[\c!compoundhyphen]      [\languageparameter\c!compoundhyphen]

\definehspace [sentence]      [\zeropoint]
\definehspace [intersentence] [.250em]

\definesymbol
  [\c!midsentence]
  [\midboundarycharacter\c!midsentence{sentence}]

\definesymbol
  [\c!leftsentence]
  [\leftboundarycharacter\c!leftsentence{sentence}]

\definesymbol
  [\c!rightsentence]
  [\rightboundarycharacter\c!rightsentence{sentence}]

\definesymbol
  [\c!leftsubsentence]
  [\leftboundarycharacter\c!leftsubsentence{sentence}]

\definesymbol
  [\c!rightsubsentence]
  [\rightboundarycharacter\c!rightsubsentence{sentence}]

\newsignal \subsentencesignal
\newcounter\subsentencelevel

\let\beforesubsentence\donothing
\let\aftersubsentence \donothing

% todo: make this language option
%
% \def\beforesubsentence{\removeunwantedspaces}
% \def\aftersubsentence {\ignorespaces}

\def\midsentence
  {\symbol[\c!midsentence]}

\def\beginofsubsentence
  {\beforesubsentence
   \ifdim\lastkern=\subsentencesignal
     \unskip
     \kern\hspaceamount\currentlanguage{intersentence}%
   \fi
   \doglobal\increment\subsentencelevel
   \ifnum\subsentencelevel=\plusone
     \dontleavehmode % was \leaveoutervmode
   \fi
   \symbol[\ifodd\subsentencelevel\c!leftsentence\else\c!leftsubsentence\fi]%
  }%  \ignorespaces}

\def\endofsubsentence % relax prevents space gobbling
  {\symbol[\ifodd\subsentencelevel\c!rightsentence\else\c!rightsubsentence\fi]%
   \doglobal\decrement\subsentencelevel
   \unskip
   \kern\subsentencesignal\relax
   \aftersubsentence}

\def\beginofsubsentencespacing % relax prevents space gobbling
  {\kern\subsentencesignal\relax}% \ignorespaces}

\def\endofsubsentencespacing
  {\ifdim\lastkern=\subsentencesignal
     \unskip
     \hskip\hspaceamount\currentlanguage{intersentence}%
     % no good, actually language dependent:
%     \ignorespaces
   \else
     \unskip
   \fi}

%D \startbuffer
%D test |<|test |<|test|>| test|>| test \par
%D test|<|test|<|test|>|test|>|test \par
%D test |<||<|test|>||>| test \par
%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
%D \stopbuffer
%D
%D \typ