diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/supp-lan.tex')
-rw-r--r-- | Master/texmf-dist/tex/context/base/supp-lan.tex | 1548 |
1 files changed, 1548 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/supp-lan.tex b/Master/texmf-dist/tex/context/base/supp-lan.tex new file mode 100644 index 00000000000..ebb47424c8f --- /dev/null +++ b/Master/texmf-dist/tex/context/base/supp-lan.tex @@ -0,0 +1,1548 @@ +%D \module +%D [ file=supp-lan, +%D version=1997.03.20, +%D title=\CONTEXT\ Support Macros, +%D subtitle=Language Options, +%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. + +%D This module needs a drastic update: can be made simplier +%D and faster; code can move to core module. + +%D Also, commenting the previous versions code will clear up +%D some memory. + +%D \gdef\starttest +%D {\blank +%D \noindent +%D \halign\bgroup\tt##\hskip2em&##\hskip2em&##\cr} +%D +%D \gdef\stoptest +%D {\egroup +%D \blank} +%D +%D \gdef\test#1% +%D {\convertargument#1\to\ascii\ascii&\hyphenatedword{#1}\cr} + +%D One of \TEX's strong points in building paragraphs is the way +%D hyphenations are handled. Although for real good hyphenation +%D of non||english languages some extensions to the program are +%D needed, fairly good results can be reached with the standard +%D mechanisms and an additional macro, at least in Dutch. + +\unprotect + +\writestatus{loading}{Context Support Macros / Language Options} + +%D \CONTEXT\ originates in the wish to typeset educational +%D materials, especially in a technical environment. In +%D production oriented environments, a lot of compound words +%D are used. Because the Dutch language poses no limits on +%D combining words, we often favor putting dashes between those +%D words, because it facilitates reading, at least for those +%D who are not that accustomed to it. +%D +%D In \TEX\ compound words, separated by a hyphen, are not +%D hyphenated at all. In spite of the multiple pass paragraph +%D typesetting this can lead to parts of words sticking into +%D the margin. The solution lays in saying \type +%D {spoelwater||terugwinunit} instead of \type +%D {spoelwater-terugwinunit}. By using a one character command +%D like \type {|}, delimited by the same character \type {|}, +%D we get ourselves both a decent visualization (in \TEXEDIT\ +%D and colored verbatim we color these commands yellow) and an +%D efficient way of combining words. +%D +%D The sequence \type{||} simply leads to two words connected by +%D a hyphen. Because we want to distinguish such a hyphen from +%D the one inserted when \TEX\ hyphenates a word, we use a bit +%D longer one. +%D +%D \hyphenation {spoel-wa-ter te-rug-win-unit} +%D +%D \starttest +%D \test {spoelwater||terugwinunit} +%D \stoptest +%D +%D As we already said, the \type{|} is a command. This commands +%D accepts an optional argument before it's delimiter, which is +%D also a \type{|}. +%D +%D \hyphenation {po-ly-meer che-mie} +%D +%D \starttest +%D \test {polymeer|*|chemie} +%D \stoptest +%D +%D Arguments like \type{*} are not interpreted and inserted +%D directly, in contrary to arguments like: +%D +%D \starttest +%D \test {polymeer|~|chemie} +%D \test {|(|polymeer|)|chemie} +%D \test {polymeer|(|chemie|)| } +%D \stoptest +%D +%D Although such situations seldom occur |<|we typeset thousands +%D of pages before we encountered one that forced us to enhance +%D this mechanism|>| we also have to take care of comma's. +%D +%D \hyphenation {uit-stel-len} +%D +%D \starttest +%D \test {op||, in|| en uitstellen} +%D \stoptest +%D +%D The next special case (concerning quotes) was brought to my +%D attention by Piet Tutelaers, one of the driving forces +%D behind rebuilding hyphenation patterns for the dutch +%D language.\footnote{In 1996 the spelling of the dutch +%D language has been slightly reformed which made this topic +%D actual again.} We'll also take care of this case. +%D +%D \starttest +%D \test {AOW|'|er} +%D \test {cd|'|tje} +%D \test {ex|-|PTT|'|er} +%D \test {rock|-|'n|-|roller} +%D \stoptest +%D +%D Tobias Burnus pointed out that I should also support +%D something like +%D +%D \starttest +%D \test {well|_|known} +%D \stoptest +%D +%D to stress the compoundness of hyphenated words. +%D +%D Of course we also have to take care of the special case: +%D +%D \starttest +%D \test {text||color and ||font} +%D \stoptest + +%D \macros +%D {installdiscretionaries} +%D +%D The mechanism described here is one of the older inner parts +%D of \CONTEXT. The most recent extensions concerns some +%D special cases as well as the possibility to install other +%D characters as delimiters. The prefered way of specifying +%D compound words is using \type{||}, which is installed by: +%D +%D \starttyping +%D \installdiscretionaries || - +%D \stoptyping +%D +%D Some alternative definitions are: +%D +%D \startbuffer +%D \installdiscretionaries ** - +%D \installdiscretionaries ++ - +%D \installdiscretionaries // - +%D \installdiscretionaries ~~ - +%D \stopbuffer +%D +%D \typebuffer +%D +%D after which we can say: +%D +%D \bgroup +%D \getbuffer +%D \starttest +%D \test {test**test**test} +%D \test {test++test++test} +%D \test {test//test//test} +%D \test {test~~test~~test} +%D \stoptest +%D \egroup + +%D \macros +%D {compoundhyphen, +%D beginofsubsentence,endofsubsentence} +%D +%D Now let's go to the macros. First we define some variables. +%D In the main \CONTEXT\ modules these can be tuned by a setup +%D command. Watch the (maybe) better looking compound hyphen. + +% I've added \hbox's so that in mathmode we get proper chars + +\def\compoundhyphen {\hbox{-\kern-.25ex-}} +\def\beginofsubsentence {\hbox{---}} +\def\endofsubsentence {\hbox{---}} + +%D The last two variables are needed for subsentences +%D |<|like this one|>| which we did not yet mention. +%D +%D We want to enable breaking but at the same time don't want +%D compound characters like |-| or || to be separated from the +%D words. \TEX\ hackers will recognise the next two macro's: + +\def\prewordbreak {\penalty10000\hskip0pt\relax} +\def\postwordbreak {\penalty0\prewordbreak} + +%D We first show the original implementation, which only +%D supports \type{|} as command and delimiter. Before +%D activating \type{|} we save it's value: +%D +%D \starttyping +%D \edef\domathmodediscretionary{\string|} +%D \stoptyping +%D +%D after which we're ready to define it's meaning to: +%D +%D \starttyping +%D \catcode`\|=\@@active +%D +%D \unexpanded\def|% +%D {\ifmmode +%D \expandafter\domathmodediscretionary +%D \else +%D \expandafter\dotextmodediscretionary +%D \fi} +%D \stoptyping +%D +%D We need a two stage \type{\futurelet} because we want to +%D look ahead for both the compound character definition and +%D the (optional) comma that follows it, and because we want to +%D prevent that \TEX\ puts this comma on the next line. We use +%D \type{\next} for easy and fast checking of the argument, we +%D save this argument (which can consist of more tokens) and +%D also save the character following the \type{|#1|} in +%D \type{\nextnext}. +%D +%D \starttyping +%D \def\dotextmodediscretionary% +%D {\bgroup +%D \futurelet\next\dodotextmodediscretionary} +%D +%D \def\dodotextmodediscretionary#1|% +%D {\def\betweendiscretionaries{#1}% +%D \futurelet\nextnext\dododotextmodediscretionary} +%D \stoptyping +%D +%D The main macro consists of quite some \type{\ifx} tests +%D while \type{\checkafterdiscretionary} handles the commas. +%D We show the simplified version here: +%D +%D \starttyping +%D \def\dododotextmodediscretionary% +%D {\let\nextnextnext=\egroup +%D \ifx |\next +%D \checkafterdiscretionary +%D \prewordbreak\hbox{\compoundhyphen\nextnext}\allowbreak\postwordbreak +%D \else\ifx=\next +%D \prewordbreak\compoundhyphen +%D \else\ifx~\next +%D \discretionary{-}{}{\thinspace}\postwordbreak +%D \else\ifx(\next +%D \prewordbreak\discretionary{}{(-}{(}\prewordbreak +%D \else\ifx)\next +%D \prewordbreak\discretionary{-)}{}{)}\prewordbreak +%D \else\ifx'\next +%D \prewordbreak\discretionary{-}{}{'}\postwordbreak +%D \else +%D \checkafterdiscretionary +%D \prewordbreak\hbox{\betweendiscretionaries\nextnext}\allowbreak\postwordbreak +%D \fi\fi\fi\fi\fi\fi +%D \nextnextnext} +%D +%D \def\checkafterdiscretionary% +%D {\ifx,\nextnext +%D \def\nextnextnext{\afterassignment\egroup\let\next=}% +%D \else +%D \let\nextnext=\relax +%D \fi} +%D \stoptyping +%D +%D Handling \type{(} and \type{)} is a a bit special, because +%D \TEX\ sees them as decent hyphenation points, according to +%D their \type{\lccode} being non||zero. For the same reason, +%D later on in this module we cannot manipulate the +%D \type{\lccode} but take the \type{\uccode}. + +%D The most recent implementation is more advanced. As +%D demonstrated we can install delimiters, like: +%D +%D \starttyping +%D \installdiscretionaries || \compoundhyphen +%D \stoptyping +%D +%D This time we have to use a bit more clever way of saving the +%D math mode specification of the character we're going to +%D make active. We also save the user supplied compound hyphen. +%D We show the a bit more traditional implementation first. +%D +%D \starttyping +%D \def\installdiscretionaries#1% +%D {\catcode`#1\@@other +%D \expandafter\doinstalldiscretionaries\string#1} +%D +%D \def\doinstalldiscretionaries#1% +%D {\setvalue{mathmodediscretionary#1}{#1}% +%D \catcode`#1\@@active +%D \dodoinstalldiscretionaries} +%D +%D \def\dodoinstalldiscretionaries#1#2% +%D {\setvalue{textmodediscretionary\string#1}{#2}% +%D \unexpanded\def#1{\discretionarycommand#1}} +%D \stoptyping +%D +%D A bit more \CATCODE\ and character trickery enables us to +%D discard the two intermediate steps. This trick originates +%D on page~394 of the \TEX book, in the appendix full of +%D dirty tricks. The second argument has now become redundant, +%D but I decided to reserve it for future use. At least it +%D remembers us of the symmetry. + +\beginTEX + +\def\installdiscretionaries#1#2#3% + {\convertargument#1\to\ascii + \setevalue{\strippedcsname\mathmodediscretionary\string#1}{\ascii}% + \setvalue {\strippedcsname\textmodediscretionary\string#1}{#3}% + \catcode`#1=\@@active + \scratchcounter=\the\uccode`~ + \uccode`~=`#1 + \uppercase{\unexpanded\def~{\discretionarycommand~}}% + \uccode`~=\scratchcounter} + +\endTEX + +\beginETEX \detokenize + +\def\installdiscretionaries#1#2#3% + {\setevalue{\strippedcsname\mathmodediscretionary\string#1}{\detokenize{#1}}% + \setvalue {\strippedcsname\textmodediscretionary\string#1}{#3}% + \catcode`#1=\@@active + \scratchcounter=\the\uccode`~ + \uccode`~=`#1 + \uppercase{\unexpanded\def~{\discretionarycommand~}}% + \uccode`~=\scratchcounter} + +\endETEX + +\def\dohandlemathmodebar#1% + {\getvalue{\strippedcsname\mathmodediscretionary\string#1}} + +\def\discretionarycommand + {\relax\ifmmode + \expandafter\dohandlemathmodebar + \else + \expandafter\dotextmodediscretionary + \fi} + +%D The next piece of code is a torture test for this previous +%D macro. The \type {\relax} before the \type {\ifmmode} is +%D needed because of the alignment scanner (in \ETEX\ this +%D problem is not present because there a protected macro is +%D not expanded. Thanks to Tobias Burnus for providing this +%D example. +%D +%D \startformula +%D \left|f(x_n)-{1\over2}\right| = +%D {\cases{|{1\over2}-x_n| &for $0\le x_n < {1\over2}$\cr +%D |x_n-{1\over2}| &for ${1\over2}<x_n\le1$ \cr}} +%D \stopformula + +%D \macros +%D {defineactivecharacter} +%D +%D In \type {lang-ger.tex} we define some language specific +%D commands for german input, like: +%D +%D \starttyping +%D \startlanguagespecifics[de] +%D \installcompoundcharacter "a {\moveaccent{-.1ex}\"a\midworddiscretionary} +%D \stoplanguagespecifics +%D \stoptyping +%D +%D Occasionally we have to redefine such an active character, +%D like in: +%D +%D \starttyping +%D \startencoding[pdfdoc] +%D \startlanguagespecifics[de] +%D \defineactivecharacter " {\"} +%D \stoplanguagespecifics +%D \stopencoding +%D \stoptyping +%D +%D Here is the command we used: + +% \def\next{#2}% \unexpanded\def\next is wrong in non||etex +% \uppercase{\let~\next}% + +\def\defineactivecharacter #1 #2% + {\catcode`#1=\@@active + \scratchcounter=\the\uccode`~ + \uccode`~=`#1\relax + \uppercase{\def\next{~}}% + %\expandafter\unexpanded\expandafter\def\next{#2}% + \expandafter\def\next{#2}% unexpanded goes wrong in pdfdoc + \uccode`~=\scratchcounter} + +%D The next alternative also supports character numbers: + +\def\defineactivecharacter #1 #2% + {\scratchcounter\the\uccode`~ + \expandafter\doifnumberelse\expandafter{\string#1} + {\catcode #1=\@@active \uccode`~= #1\relax} + {\catcode`#1=\@@active \uccode`~=`#1\relax}% + \uppercase{\def\next{~}}% + %\expandafter\unexpanded\expandafter\def\next{#2}% + \expandafter\def\next{#2}% unexpanded goes wrong in pdfdoc + \uccode`~\scratchcounter} + +%D One reason for abusing the \type{~} is that it is already +%D an active character, so it is unlikely to appear as argument. + +%D The next implementation is about 20\% faster; 1M +%D definitions on a 1Gig machine takes about 19 seconds +%D (against 24 for the previous alternative). + +\chardef\activehackcode=`~ + +% \def\defineactivecharacter #1 % +% {\scratchcounter\the\uccode\activehackcode +% \uccode\activehackcode\expandafter\doifnumberelse +% \expandafter{\string#1}\empty`#1% +% \catcode\uccode\activehackcode\@@active +% \uppercase{\def\next{~}}% +% \uccode\activehackcode\scratchcounter +% \expandafter\def\next}% unexpanded goes wrong in pdfdoc + +%D But ... + +\def\defineactivecharacter #1 #2% + {\scratchcounter\uccode\activehackcode + \uccode\activehackcode\expandafter\doifnumberelse + \expandafter{\string#1}\empty`#1% + \catcode\uccode\activehackcode\@@active + \uppercase{\def\next{~}}% + \uccode\activehackcode\scratchcounter + % unexpanded goes wrong in pdfdoc + \@EA\@EA\@EA\def\@EA\next\@EA{\@EA\dohandleactivecharacter\next{#2}}} + +\let\dohandleactivecharacter\secondoftwoarguments + +\def\donthandleactivecharacter#1#2{\noexpand#1} + +%D A goody: + +\def\makecharacteractive #1 % + {\catcode`#1\active} + +%D Although adapting character codes and making characters +%D active can interfere with other features of macropackages, +%D normally there should be no problems with things like: +%D +%D \starttyping +%D \installdiscretionary || + +%D \installdiscretionary ++ = +%D \stoptyping +%D +%D The real work is done by the next set of macros. We have +%D to use a double \type{\futurelet} because we have to take +%D following characters into account. + +\def\dotextmodediscretionary#1% + {\bgroup + \def\dodotextmodediscretionary##1#1% + {\def\betweendiscretionary{##1}% + \futurelet\nextnext\dododotextmodediscretionary}% + \let\discretionarycommand=#1% + \def\textmodediscretionary% + {\getvalue{\strippedcsname\textmodediscretionary\string#1}}% + \futurelet\next\dodotextmodediscretionary} + +\def\dododotextmodediscretionary + {\let\nextnextnext\egroup + \ifx\discretionarycommand\next + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak + \egroup + \else\ifx=\next + \prewordbreak\textmodediscretionary + \else\ifx~\next + \prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak + \else\ifx_\next + \prewordbreak\discretionary{\textmodediscretionary} + {\textmodediscretionary}{\textmodediscretionary}\prewordbreak + \else\ifx(\next + \ifdim\lastskip>\zeropoint\relax + (\prewordbreak + \else + \prewordbreak\discretionary{}{(-}{(}\prewordbreak + \fi + \else\ifx)\next + \ifx\nextnext\blankspace + \prewordbreak)\relax + \else + \prewordbreak\discretionary{-)}{}{)}\prewordbreak + \fi + \else\ifx'\next + \prewordbreak\discretionary{-}{}{'}\postwordbreak + \else\ifx<\next + \beginofsubsentence\prewordbreak\beginofsubsentencespacing + \else\ifnum\uccode`>=\nextuccode + \endofsubsentencespacing\prewordbreak\endofsubsentence + \else + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + \prewordbreak + \discretionary{\hbox{\betweendiscretionary}}{}{\hbox{\betweendiscretionary}}% + \allowbreak\postwordbreak + \egroup + \fi\fi\fi\fi\fi\fi\fi\fi\fi + \nextnextnext} + +\def\checkbeforediscretionary + {\setbox0\lastbox + \ifdim\wd0=\zeropoint + \let\postwordbreak\prewordbreak + \fi + \box0\relax} + +\def\checkafterdiscretionary + {\ifx,\nextnext + \def\nextnextnext{\afterassignment\egroup\let\next=}% + \else + \let\nextnext\relax + \fi} + +%D The macro \type{\checkbeforediscretionary} takes care of +%D loners like \type{||word}, while it counterpart +%D \type{\checkafterdiscretionary} is responsible for handling +%D the comma. + +%D \macros +%D {beginofsubsentencespacing,endofsubsentencespacing} +%D +%D In the previous macros we provided two hooks which can be +%D used to support nested sub||sentences. In \CONTEXT\ these +%D hooks are used to insert a small space when needed. + +\let\beginofsubsentencespacing=\relax +\let\endofsubsentencespacing =\relax + +%D Before we show some more tricky alternative, we first install +%D the mechanism: + +\installdiscretionaries || \compoundhyphen + +%D \macros +%D {fakecompoundhyphen} +%D +%D In headers and footers as well as in active pieces of text +%D we need a dirty hack. Try to imagine what is needed to +%D savely break the next text across a line and at the same +%D time make the words interactive. +%D +%D \starttyping +%D \goto{Some||Long||Word} +%D \stoptyping + +\def\currentspaceskip + {\fontdimen2\font\!!plus\fontdimen3\font\!!minus\fontdimen4\font\relax} + +% \def\fakecompoundhyphen% wrong +% {\def|##1|{\compoundhyphen\nobreak\hskip-\currentspaceskip\allowbreak}} + +\ifx\newsignal\undefined + + \let\fakecompoundhyphen\relax + +\else + + \newsignal\compoundbreakpoint + + % \def\fakecompoundhyphen% + % {\def|##1|% + % {\doifelsenothing{##1}{\compoundhyphen}{##1}% + % \kern\compoundbreakpoint\allowbreak}} + + \def\fakecompoundhyphen + {\def\|{\mathortext\vert\dofakecompoundhyphen}} + + \def\dofakecompoundhyphen + {\def##1|% + {\doifelsenothing{##1}\compoundhyphen{##1}% + \kern\compoundbreakpoint\allowbreak}} + +\fi + +%D One of the drawbacks of this mechanism is that characters can +%D be made active afterwards. The next alternative can be used +%D in such situations. This time we don't compare the arguments +%D directly but use the \type{\uccode}'s instead. \TEX\ +%D initializes these codes of the alphabetics glyphs to their +%D uppercase counterparts. Normally the other characters remain +%D zero. If so, we can use the \type{\uccode} as a signal. + +%D \macros +%D {enableactivediscretionaries} +%D +%D The more advanced mechanism is activated by calling: +%D +%D \starttyping +%D \enableactivediscretionaries +%D \stoptyping +%D +%D which is defined as: + +\def\enableactivediscretionaries + {\uccode`'=`'\relax \uccode`~=`~\relax \uccode`_=`_\relax + \uccode`(=`(\relax \uccode`)=`)\relax \uccode`==`=\relax + \uccode`<=`<\relax \uccode`>=`>\relax + \let\dotextmodediscretionary = \activedotextmodediscretionary + \let\dododotextmodediscretionary = \activedododotextmodediscretionary} + +%D We only have to redefine two macros. While saving the +%D \type{\uccode} in a macro we have to take care of empty +%D arguments, like in \type{||}. + +\def\activedotextmodediscretionary#1% + {\bgroup + \def\dodotextmodediscretionary##1#1% + {\def\betweendiscretionary{##1}% + \def\nextuccode####1####2\relax% + {\ifcat\noexpand####1\noexpand\relax + \edef\nextuccode{0}% + \else + \edef\nextuccode{\the\uccode`####1}% + \fi}% + \nextuccode##1@\relax + \futurelet\nextnext\dododotextmodediscretionary}% + \let\discretionarycommand=#1% + \def\textmodediscretionary% + {\getvalue{\strippedcsname\textmodediscretionary\string#1}}% + \futurelet\next\dodotextmodediscretionary} + +%D This time we use \type{\ifnum}: + +\def\activedododotextmodediscretionary + {\let\nextnextnext\egroup + \ifx\discretionarycommand\next + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak + \egroup + \else\ifnum\uccode`==\nextuccode + \prewordbreak\textmodediscretionary + \else\ifnum\uccode`~=\nextuccode + \prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak + \else\ifnum\uccode`_=\nextuccode + \prewordbreak\discretionary{\textmodediscretionary} + {\textmodediscretionary}{\textmodediscretionary}\prewordbreak + \else\ifnum\uccode`(=\nextuccode + \ifdim\lastskip>\zeropoint\relax + (\prewordbreak + \else + \prewordbreak\discretionary{}{(-}{(}\prewordbreak + \fi + \else\ifnum\uccode`)=\nextuccode + \ifx\nextnext\blankspace + \prewordbreak)\relax + \else + \prewordbreak\discretionary{-)}{}{)}\prewordbreak + \fi + \else\ifnum\uccode`'=\nextuccode + \prewordbreak\discretionary{-}{}{'}\postwordbreak + \else\ifnum\uccode`<=\nextuccode + \beginofsubsentence\prewordbreak\beginofsubsentencespacing + \else\ifnum\uccode`>=\nextuccode + \endofsubsentencespacing\prewordbreak\endofsubsentence + \else + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + %\prewordbreak\hbox{\betweendiscretionary\nextnext}\allowbreak + \prewordbreak + \discretionary{\hbox{\betweendiscretionary}}{}{\hbox{\betweendiscretionary}}% + \allowbreak\postwordbreak + \egroup + \fi\fi\fi\fi\fi\fi\fi\fi\fi + \nextnextnext} + +%D Now we can safely do things like: \enableactivediscretionaries +%D +%D \starttyping +%D \catcode`<=\@@active \def<{hello there} +%D \catcode`>=\@@active \def>{hello there} +%D \catcode`(=\@@active \def({hello there} +%D \catcode`)=\@@active \def){hello there} +%D \stoptyping +%D +%D In normal day||to||day production of texts this kind of +%D activation is seldom used.\footnote{In the \CONTEXT\ manual +%D the \type{<} and \type{>} are made active and used for some +%D cross||reference trickery.} If so, we have to take care of +%D the math mode explicitly, just like we did when making +%D \type{|} active. It can be confusing too, especially when we +%D load macropackages afterwards that make use of \type{<} in +%D \type{\ifnum} or \type{\ifdim} statements. + +%D And then came the Polish users, and who can deny them? Like +%D the German \TEX\ users demand an active \type {"}, some +%D Polish users like using the \type {/}. The next alternative +%D is a bit slower but far the most robust alternative. As a +%D bonus it also offers \type {|^|} and even \type {|||} which +%D both result in a breakable|^|bar. +%D +%D The trick we use here is to convert the argument to a +%D string and compare this string to string'd tokens. + +\def\activedotextmodediscretionary#1% + {\bgroup + \let\nextnextnext\egroup + \def\handlecompoundcharacter##1% new, needed for polish + {\getvalue{\@nc@\string##1}}% where / is active + \def\next##1#1% + {\def\next{\activedododotextmodediscretionary#1{##1}}% + \futurelet\nextnext\next}% + \next} + +\def\activedododotextmodediscretionary#1#2% + {\convertargument#2\to\discretionarytoken + \def\textmodediscretionary + {\getvalue{\strippedcsname\textmodediscretionary\string#1}}% + \ifx#1\nextnext % takes care of ||| and +++ and ...... + \prewordbreak\discretionary{\hbox{$#1$}}{}{\hbox{$#1$}}% + \allowbreak\postwordbreak + \def\nextnextnext{\afterassignment\egroup\let\next=}% + \else\ifx\discretionarytoken\empty + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + % this was: + % \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak + % but an hbox blocks a possible \discretionary + \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak + \egroup + \else\convertargument=\to\next\ifx\next\discretionarytoken + \prewordbreak\textmodediscretionary + \else\convertargument~\to\next\ifx\next\discretionarytoken + \prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak + \else\convertargument_\to\next\ifx\next\discretionarytoken + \prewordbreak\discretionary{\textmodediscretionary} + {\textmodediscretionary}{\textmodediscretionary}\prewordbreak + \else\convertargument(\to\next\ifx\next\discretionarytoken + \ifdim\lastskip>\zeropoint\relax + (\prewordbreak + \else + \prewordbreak\discretionary{}{(-}{(}\prewordbreak + \fi + \else\convertargument)\to\next\ifx\next\discretionarytoken + \ifx\nextnext\blankspace + \prewordbreak)\relax + \else\ifx\nextnext\space + \prewordbreak)\relax + \else + \prewordbreak\discretionary{-)}{}{)}\prewordbreak + \fi\fi + \else\convertargument'\to\next\ifx\next\discretionarytoken + \prewordbreak\discretionary{-}{}{'}\postwordbreak + \else\convertargument<\to\next\ifx\next\discretionarytoken + \beginofsubsentence\prewordbreak\beginofsubsentencespacing + \else\convertargument>\to\next\ifx\next\discretionarytoken + \endofsubsentencespacing\prewordbreak\endofsubsentence + \else\convertargument^\to\next\ifx\next\discretionarytoken + \prewordbreak\discretionary{\hbox{$|$}}{}{\hbox{$|$}}% + \allowbreak\postwordbreak + \else + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + \prewordbreak + \discretionary{\hbox{#2}}{}{\hbox{#2}}% + \allowbreak\postwordbreak + \egroup + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \nextnextnext} + +%D Since most things in \CONTEXT\ are configurable, we +%D slightly change the previous definition so that we can +%D install new functionality outside this module. + +\def\@tmd@{@@tmd@@} + +\def\activedododotextmodediscretionary#1#2% + {\convertargument#2\to\discretionarytoken + \def\textmodediscretionary% + {\getvalue{\strippedcsname\textmodediscretionary\string#1}}% + \ifx\discretionarytoken\empty + \ifx#1\nextnext % takes care of ||| and +++ and ...... + \prewordbreak\discretionary{\hbox{$#1$}}{}{\hbox{$#1$}}% + \allowbreak\postwordbreak + \def\nextnextnext{\afterassignment\egroup\let\next=}% + \else + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + % the next line has been changed (20050203) + % \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak + % but an hbox blocks a possible \discretionary + \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak + \egroup + \fi + \else\expandafter\ifx\csname\@tmd@\discretionarytoken\endcsname\relax + \checkafterdiscretionary + \bgroup + \checkbeforediscretionary + \prewordbreak + \discretionary{\hbox{#2}}{}{\hbox{#2}}% + \allowbreak\postwordbreak + \egroup + \else + \csname\@tmd@\discretionarytoken\endcsname + \fi\fi + \nextnextnext} % can be \egroup so \aftergroup\ignorespaces + +\def\definetextmodediscretionary #1 + {\convertargument#1\to\ascii + \setvalue{\@tmd@\ascii}} + +\definetextmodediscretionary {} % empty case, also handled in parser + {\prewordbreak\compoundhyphen\allowbreak\postwordbreak} + +\definetextmodediscretionary = + {\prewordbreak\textmodediscretionary} + +\definetextmodediscretionary ~ + {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak} + +\definetextmodediscretionary _ + {\prewordbreak + \discretionary{\compoundhyphen}{\compoundhyphen}{\compoundhyphen}% + \prewordbreak} + +\definetextmodediscretionary ( + {\ifdim\lastskip>\zeropoint + (\prewordbreak + \else + \prewordbreak\discretionary{}{(-}{(}\prewordbreak + \fi} + +\definetextmodediscretionary ) + {\ifx\nextnext\blankspace + \prewordbreak)\relax + \else\ifx\nextnext\space + \prewordbreak)\relax + \else + \prewordbreak\discretionary{-)}{}{)}\prewordbreak + \fi\fi} + +\definetextmodediscretionary ' + {\prewordbreak\discretionary{-}{}{'}\postwordbreak} + +\definetextmodediscretionary < + {\beginofsubsentence\prewordbreak\beginofsubsentencespacing} + +\definetextmodediscretionary > + {\endofsubsentencespacing\prewordbreak\endofsubsentence} + +\definetextmodediscretionary . % not yet definitive + {\prewordbreak\midsentence\prewordbreak} + +\definetextmodediscretionary ^ + {\prewordbreak\discretionary{\hbox{$|$}}{}{\hbox{$|$}}% + \allowbreak\postwordbreak} + +\definetextmodediscretionary : + {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:} + %\space\aftergroup\ignorespaces} + +\definetextmodediscretionary ; + {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};} + %\space\aftergroup\ignorespaces} + +\definetextmodediscretionary ? + {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?} + %\space\aftergroup\ignorespaces} + +\definetextmodediscretionary ! + {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!} + %\space\aftergroup\ignorespaces} + +\definetextmodediscretionary * + {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak} + +\ifx\hspaceamount\undefined + + \def\hspaceamount#1#2{\kern.16667em} + +\fi + +%D Since we don't have to bother about active characters any +%D longer, we end up with a pretty simple activating macro: + +\def\enableactivediscretionaries + {\let\dotextmodediscretionary=\activedotextmodediscretionary} + +%D Done somewhere else: \type {\enableactivediscretionaries}. + +%D \macros +%D {directdiscretionary} +%D +%D In those situations where the nature of characters is +%D less predictable, we can use the more direct approach: + +\unexpanded\def\directdiscretionary#1% + {\convertargument#1\to\discretionarytoken + \let\textmodediscretionary\compoundhyphen + \expandafter\ifx\csname\@tmd@\string#1\endcsname\relax + \prewordbreak + \discretionary{\hbox{#1}}{}{\hbox{#1}}% + \allowbreak\postwordbreak + \else + \csname\@tmd@\string#1\endcsname + \fi} + +%D \macros +%D {installcompoundcharacter} +%D +%D When Tobias Burnus started translating the dutch manual of +%D \PPCHTEX\ into german, he suggested to let \CONTEXT\ support +%D the \type{german.sty} method of handling compound +%D characters, especially the umlaut. This package is meant for +%D use with \PLAIN\ \TEX\ as well as \LATEX. +%D +%D I decided to implement compound character support as +%D versatile as possible. As a result one can define his own +%D compound character support, like: +%D +%D \starttyping +%D \installcompoundcharacter "a {\"a} +%D \installcompoundcharacter "e {\"e} +%D \installcompoundcharacter "i {\"i} +%D \installcompoundcharacter "u {\"u} +%D \installcompoundcharacter "o {\"o} +%D \installcompoundcharacter "s {\SS} +%D \stoptyping +%D +%D or even +%D +%D \starttyping +%D \installcompoundcharacter "ck {\discretionary {k-}{k}{ck}} +%D \installcompoundcharacter "ff {\discretionary{ff-}{f}{ff}} +%D \stoptyping +%D +%D The support is not limited to alphabetic characters, so the +%D next definition is also valid. +%D +%D \starttyping +%D \installcompoundcharacter ". {.\doifnextcharelse{\spacetoken}{}{\kern.125em}} +%D \stoptyping +%D +%D The implementation looks familiar and uses the same tricks as +%D mentioned earlier in this module. We take care of two +%D arguments, which complicates things a bit. + +\def\@nc@{@nc@} % normal character +\def\@nn@{@nn@} % normal catcode +\def\@cc@{@cc@} % compound character +\def\@cs@{@cs@} % compound characters + +% \def\installcompoundcharacter #1#2#3 #4% {{#4}} keeps move local +% {\setvalue{\@nc@\string#1}{\char`#1}% +% \ifnum\catcode`#1=\@@active \else +% \setevalue{\@nn@\string#1}{\number\catcode`#1}% new +% \fi +% \def\!!stringa{#3}% +% \ifx\!!stringa\empty +% \setvalue{\@cc@\string#1\string#2}{{#4}}% +% \else +% \setvalue{\@cs@\string#1\string#2\string#3}{{#4}}% +% \fi +% \catcode`#1=\@@active +% \scratchcounter=\the\uccode`~ +% \uccode`~=`#1 +% \uppercase{\unexpanded\def~{\handlecompoundcharacter~}}% +% \uccode`~=\scratchcounter} + +\def\installcompoundcharacter #1#2#3 #4% {{#4}} keeps move local + {\chardef\thecompoundcharacter`#1% + %\@EA\def\csname\@nc@\string#1\endcsname{\char`#1}% + \@EA\chardef\csname\@nc@\string#1\endcsname\thecompoundcharacter + \ifnum\catcode\thecompoundcharacter=\@@active \else + \@EA\edef\csname\@nn@\string#1\endcsname + {\number\catcode\thecompoundcharacter}% + \fi + \def\!!stringa{#3}% + \@EA\def\csname\ifx\!!stringa\empty + \@cc@\string#1\string#2% + \else + \@cs@\string#1\string#2\string#3% + \fi\endcsname{{#4}}% + \catcode\thecompoundcharacter\@@active + \scratchcounter\uccode\activehackcode + \uccode\activehackcode\thecompoundcharacter + \uppercase{\unexpanded\def~{\handlecompoundcharacter~}}% + \uccode\activehackcode\scratchcounter} + +%D A compound character can be reset with the following +%D command. +%D +%D \starttyping +%D \restorecompoundcharacter / +%D \stoptyping + +\def\restorecompoundcharacter#1% new + {\catcode`#1=\csname\@nn@\string#1\endcsname\relax} + +%D We can also ignore definitions (needed in for instance \XML). Beware, +%D this macro is supposed to be used grouped! + +\def\ignorecompoundcharacter + {\def\installcompoundcharacter##1 ##2{}} + +%D In handling the compound characters we have to take care of +%D \type{\bgroup} and \type{\egroup} tokens, so we end up with +%D a multi||step interpretation macro. We look ahead for a +%D \type{\bgroup}, \type{\egroup} or \type{\blankspace}. Being +%D no user of this mechanism, the credits for testing them goes +%D to Tobias Burnus, the first german user of \CONTEXT. +%D +%D We define these macros as \type{\long} because we can +%D expect \type{\par} tokens. We need to look into the future +%D with \type{\futurelet} to prevent spaces from +%D disappearing. + +% \def\handlecompoundcharacter#1% +% {\def\dohandlecompoundcharacter% +% {\ifx\next\bgroup +% %\def\next{\dodohandlecompoundcharacter#1}% % handle "{ee} -> \"ee +% %\let\next\relax % forget "{ee} -> ee +% \def\next{\handlecompoundcharacterone#1}% % ignore "{ee} -> "ee +% \else\ifx\next\egroup +% \def\next{\getvalue{\@nc@\string#1}}% +% \else\ifx\next\blankspace +% \def\next{\getvalue{\@nc@\string#1}}% +% \else +% \def\next{\dodohandlecompoundcharacter#1}% +% \fi\fi\fi +% \next}% +% \futurelet\next\dohandlecompoundcharacter} +% +% \def\dodohandlecompoundcharacter#1#2% +% {\def\dododohandlecompoundcharacter% Keep it here and +% {\ifx\next\bgroup % preserve spaces! +% \def\next{\handlecompoundcharacterone#1#2}% +% \else\ifx\next\egroup +% \def\next{\handlecompoundcharacterone#1#2}% +% \else\ifx\next\blankspace +% \def\next{\handlecompoundcharacterone#1#2}% +% \else +% \def\next{\handlecompoundcharactertwo#1#2}% +% \fi\fi\fi +% \next}% +% \futurelet\next\dododohandlecompoundcharacter} + +\def\handlecompoundcharacter#1% + {\def\xhandlecompoundcharacter{\dohandlecompoundcharacter{#1}}% + \futurelet\next\xhandlecompoundcharacter} + +\def\dohandlecompoundcharacter + {\ifx\next\bgroup + %\@EA\dodohandlecompoundcharacter % handle "{ee} -> \"ee + %\@EA\gobbleoneargument % forget "{ee} -> ee + \@EA\handlecompoundcharacterone % ignore "{ee} -> "ee + \else\ifx\next\egroup + \@EAEAEA\donohandlecompoundcharacter + \else\ifx\next\blankspace + \@EA\@EAEAEA\@EA\donohandlecompoundcharacter + \else + \@EA\@EAEAEA\@EA\dodohandlecompoundcharacter + \fi\fi\fi} + +\def\donohandlecompoundcharacter#1{\csname\@nc@\string#1\endcsname} + +\def\dododohandlecompoundcharacter + {\ifx\next\bgroup + \@EA\handlecompoundcharacterone + \else\ifx\next\egroup + \@EAEAEA\handlecompoundcharacterone + \else\ifx\next\blankspace + \@EA\@EAEAEA\@EA\handlecompoundcharacterone + \else + \@EA\@EAEAEA\@EA\handlecompoundcharactertwo + \fi\fi\fi} + +\def\dodohandlecompoundcharacter#1#2% preserve space + {\def\xdodohandlecompoundcharacter{\dododohandlecompoundcharacter#1#2}% + \futurelet\next\xdodohandlecompoundcharacter} + +%D Besides taken care of the grouping and space tokens, we have +%D to deal with three situations. First we look if the next +%D character equals the first one, if so, then we just insert +%D the original. Next we look if indeed a compound character is +%D defined. We either execute the compound character or just +%D insert the first. So we have +%D +%D \starttyping +%D <key><key> <key><known> <key><unknown> +%D \stoptyping +%D +%D In later modules we will see how these commands are used. + +\beginTEX + +\long\def\handlecompoundcharacterone#1#2% + {\if\string#1\string#2% was: \ifx#1#2% + %\def\next{\getvalue{\@nc@\string#1}\getvalue{\@nc@\string#2}}% + \def\next{\getvalue{\@nc@\string#1}}% + \else\expandafter\ifx\csname\@cc@\string#1\string#2\endcsname\relax + \def\next{\getvalue{\@nc@\string#1}#2}% + \else + \def\next{\getvalue{\@cc@\string#1\string#2}}% + \fi\fi + \next} + +\long\def\handlecompoundcharactertwo#1#2#3% + {\if\string#1\string#2% was: \ifx#1#2% + %\def\next{\getvalue{\@nc@\string#1}\getvalue{\@nc@\string#2}#3}% + \def\next{\getvalue{\@nc@\string#1}#3}% + \else\@EA\ifx\csname\@cs@\string#1\string#2\string#3\endcsname\relax + \expandafter\ifx\csname\@cc@\string#1\string#2\endcsname\relax + \def\next{\getvalue{\@nc@\string#1}#2#3}% + \else + \def\next{\getvalue{\@cc@\string#1\string#2}#3}% + \fi + \else + \def\next{\getvalue{\@cs@\string#1\string#2\string#3}}% + \fi\fi + \next} + +\endTEX + +\beginETEX \ifcsname + +\long\def\handlecompoundcharacterone#1#2% + {\if\string#1\string#2% was: \ifx#1#2% + %\def\next{\getvalue{\@nc@\string#1}\getvalue{\@nc@\string#2}}% + \def\next{\getvalue{\@nc@\string#1}}% + \else\ifcsname\@cc@\string#1\string#2\endcsname + \def\next{\getvalue{\@cc@\string#1\string#2}}% + \else + \def\next{\getvalue{\@nc@\string#1}#2}% + \fi\fi + \next} + +\long\def\handlecompoundcharactertwo#1#2#3% + {\if\string#1\string#2% was: \ifx#1#2% + %\def\next{\getvalue{\@nc@\string#1}\getvalue{\@nc@\string#2}#3}% + \def\next{\getvalue{\@nc@\string#1}#3}% + \else\ifcsname\@cs@\string#1\string#2\string#3\endcsname + \def\next{\getvalue{\@cs@\string#1\string#2\string#3}}% + \else\ifcsname\@cc@\string#1\string#2\endcsname + \def\next{\getvalue{\@cc@\string#1\string#2}#3}% + \else + \def\next{\getvalue{\@nc@\string#1}#2#3}% + \fi\fi\fi + \next} + +\endETEX + +%D For very obscure applications (see for an application \type +%D {lang-sla.tex}) we provide: + +\def\dosimplifiedcompoundcharacter#1% + {#1} + +\beginTEX + +\def\simplifiedcompoundcharacter#1#2% + {\@EA\ifx\csname\@cc@\string#1\string#2\endcsname\relax + #2% + \else + \@EA\@EA\@EA\dosimplifiedcompoundcharacter\csname\@cc@\string#1\string#2\endcsname + \fi} + +\endTEX + +\beginETEX \ifcsname + +\def\simplifiedcompoundcharacter#1#2% + {\ifcsname\@cc@\string#1\string#2\endcsname + \@EA\@EA\@EA\dosimplifiedcompoundcharacter\csname\@cc@\string#1\string#2\endcsname + \else + #2% + \fi} + +\endETEX + +%D \macros +%D {nonbreakablespace} +%D +%D The following macro is taken from plain \TEX. + +\def\nonbreakablespace{\penalty\!!tenthousand\ } + +\let~\nonbreakablespace + +% under testing: +% +% \unexpanded\def~{\nonbreakablespace} + +%D \macros +%D {midworddiscretionary} +%D +%D If needed, one can add a discretionary hyphen using \type +%D {\midworddiscretionary}. This macro does the same as +%D \PLAIN\ \TEX's \type {\-}, but, like the ones implemented +%D earlier, this one also looks ahead for spaces and grouping +%D tokens. + +\def\domidworddiscretionary + {\ifx\next\blankspace\else + \ifx\next\bgroup \else + \ifx\next\egroup \else + \discretionary{-}{}{}% + \fi\fi\fi} + +\def\midworddiscretionary% + {\futurelet\next\domidworddiscretionary} + +%D \macros +%D {hyphenatedurl} +%D +%D For those who want to put full \URL's in a text, we offer +%D +%D \startbuffer +%D \hyphenatedurl{http://optimist.optimist/optimist/optimist.optimist#optimist} +%D \stopbuffer +%D +%D \typebuffer +%D +%D which breaks at the appropriate places. Watch the \type{#} +%D hack. +%D +%D When passed as argument, like in \type {\goto}, one needs +%D to substitute a \type {\\} for each \type{#}. +%D +%D \startbuffer +%D \hyphenatedurl{http://this.is.a.rather/strange/reference#indeed} +%D \stopbuffer +%D +%D \typebuffer + +\ifx\\\undefined \let\\\crlf \fi + +\chardef\urlsplitmode=1 + +% 0 => don't split +% 1 => . : na, rest voor +% 2 => alles na +% 3 => alles voor + +% \bgroup \catcode`\~=\active \catcode`\/=\active + +% Why not convert to ascii first? I will redo this one! + +% \unexpanded\gdef\hyphenatedurl#1% {}{} handles accents +% {\bgroup +% \obeyhyphens +% \def\splitbefore##1% +% {\setbox\scratchbox=\hbox{##1{}{}}% +% \ifcase\urlsplitmode +% \box\scratchbox +% \or +% \postwordbreak\box\scratchbox\prewordbreak +% \or +% \prewordbreak\discretionary{\box\scratchbox}{}{\box\scratchbox}\prewordbreak +% \else +% \postwordbreak\box\scratchbox\prewordbreak +% \fi}% +% \def\splitafter##1% +% {\ifcase\urlsplitmode +% ##1{}{}% +% \or +% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak +% \or +% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak +% \else +% \prewordbreak\discretionary{}{##1{}{}}{##1{}{}}\prewordbreak +% \fi}% +% \def\flushurl% +% {\savedurl\let\savedurl\empty}% +% \def\\% +% {\spliturl\#}% +% \let\~=\lettertilde \let~=\~% +% \let\/=\letterslash \let/=\/% +% \let\savedurl\empty +% \handletokens#1\with\scanurl +% \egroup} +% +% Better (a mere copy with \dohyphens): + +% \bgroup \catcode`\~=\active \catcode`\/=\active +% +% \unexpanded\gdef\hyphenatedurl#1% {}{} handles accents +% {\bgroup +% \ifnum\hyphenpenalty<10000 \else +% \def\discretionary##1##2##3{##1\allowbreak##2}% +% \fi +% \obeyhyphens +% \def\splitbefore##1% +% {\setbox\scratchbox=\hbox{##1{}{}}% +% \ifcase\urlsplitmode +% \box\scratchbox +% \or +% \postwordbreak\box\scratchbox\prewordbreak +% \or +% \prewordbreak\discretionary{\box\scratchbox}{}{\box\scratchbox}\prewordbreak +% \else +% \postwordbreak\box\scratchbox\prewordbreak +% \fi}% +% \def\splitafter##1% +% {\ifcase\urlsplitmode +% ##1{}{}% +% \or +% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak +% \or +% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak +% \else +% \prewordbreak\discretionary{}{##1{}{}}{##1{}{}}\prewordbreak +% \fi}% +% \def\flushurl% +% {\savedurl\let\savedurl\empty}% +% \def\\% +% {\spliturl\#}% +% \let\~=\lettertilde\let~=\~% +% \let\/=\letterslash\let/=\/% +% \let\savedurl\empty +% \handletokens#1\with\scanurl\savedurl +% \egroup} +% +% \egroup + +\bgroup \catcode`\~=\active \catcode`\/=\active + +\unexpanded\gdef\hyphenatedurl#1% {}{} handles accents + {\bgroup + \ifnum\hyphenpenalty<10000 \else + \def\discretionary##1##2##3{##1\allowbreak##2}% + \fi + \obeyhyphens + \def\splitbefore##1% + {\setbox\scratchbox=\hbox{##1{}{}}% + \ifcase\urlsplitmode + \box\scratchbox + \or + \postwordbreak\box\scratchbox\prewordbreak + \or + \prewordbreak\discretionary{\box\scratchbox}{}{\box\scratchbox}\prewordbreak + \else + \postwordbreak\box\scratchbox\prewordbreak + \fi}% + \def\splitafter##1% + {\ifcase\urlsplitmode + ##1{}{}% + \or + \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak + \or + \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak + \else + \prewordbreak\discretionary{}{##1{}{}}{##1{}{}}\prewordbreak + \fi}% + \def\flushurl% + {\savedurl\let\savedurl\empty}% + \def\\% + {\spliturl\#}% + \let\~=\lettertilde\let~=\~% + \let\/=\letterslash\let/=\/% + \let\savedurl\empty + \scratchcounter\zerocount % used for hyphenmethod + \handletokens#1\with\scanurl\savedurl + \egroup} + +\egroup + +%D This would be better, but it spoils \type {\~} and so: +%D +%D \starttyping +%D \convertargument#1\to\ascii +%D \expandafter\handletokens\ascii\with\scanurl +%D \stoptyping + +% \def\scanurl#1% +% {\ifx#1\~% +% \flushurl\splitbefore\~% +% \else\ifx#1\#% +% \flushurl\splitbefore\#% +% \else\ifx#1\&% +% \flushurl\splitbefore\&% +% \else\ifx#1\%% +% \flushurl\splitbefore\%% +% \else\ifx#1\_% +% \flushurl\splitbefore\_% +% \else\if\noexpand#1\relax +% #1% +% \else\ifnum\catcode`#1=8 +% \flushurl\splitbefore\_% +% \else\ifnum\catcode`#1=6 +% \flushurl\splitbefore\#% +% \else\ifnum\catcode`#1=4 +% \flushurl\splitbefore\&% +% \else\if#1\lettertilde +% \flushurl\splitbefore\~% +% \else\if#1\letterpercent +% \flushurl\splitbefore\%% +% \else\if#1\letterunderscore +% \flushurl\splitbefore\_% +% \else\if#1\letterquestionmark +% \flushurl\splitafter\letterquestionmark +% \else\if#1\letterat +% \flushurl\splitafter\letterat +% \else\if#1\letterslash +% \edef\savedurl{\savedurl\letterslash}% +% \else\if#1+% +% \flushurl\splitafter+% +% \else\if#1:% +% \flushurl\splitafter:% +% \else\if#1.% +% \flushurl\splitafter.% +% \else\if#1(% +% \flushurl\splitbefore(% +% \else\if#1)% +% \flushurl\splitafter)% +% \else +% \ifx\savedurl\empty\else +% \splitbefore\savedurl +% \let\savedurl\empty +% \fi +% #1% +% \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +\chardef\urlhyphenmethod=0 + +\def\scanurl#1% + {\advance\scratchcounter\plusone + \ifx#1\~% + \flushurl\splitbefore\~% + \else\ifx#1\#% + \flushurl\splitbefore\#% + \else\ifx#1\&% + \flushurl\splitbefore\&% + \else\ifx#1\%% + \flushurl\splitbefore\%% + \else\ifx#1\_% + \flushurl\splitbefore\_% + \else\if\noexpand#1\relax + #1% + \else\ifnum\catcode`#1=8 + \flushurl\splitbefore\_% + \else\ifnum\catcode`#1=6 + \flushurl\splitbefore\#% + \else\ifnum\catcode`#1=4 + \flushurl\splitbefore\&% + \else\if#1\lettertilde + \flushurl\splitbefore\~% + \else\if#1\letterpercent + \flushurl\splitbefore\%% + \else\if#1\letterunderscore + \flushurl\splitbefore\_% + \else\if#1\letterquestionmark + \flushurl\splitafter\letterquestionmark + \else\if#1\letterat + \flushurl\splitafter\letterat + \else\if#1\letterslash + \edef\savedurl{\savedurl\letterslash}% + \else\if#1+% + \flushurl\splitafter+% + \else\if#1:% + \flushurl\splitafter:% + \else\if#1.% + \flushurl\splitafter.% + \else\if#1(% + \flushurl\splitbefore(% + \else\if#1)% + \flushurl\splitafter)% + \else + \ifx\savedurl\empty\else + \splitbefore\savedurl + \let\savedurl\empty + \fi + \ifcase\urlhyphenmethod + #1% + \else + \ifnum\scratchcounter>\plusthree % so, \http: will not break + \edef\savedurl{#1}% + \else + #1% + \fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% \setupinteraction[state=start] +% \def\gotoURL#1{\useURL[foo][#1]\goto{\url[foo]}[url(foo)]} +% \starttext +% \endgraf \chardef\urlhyphenmethod=0 +% \hsize1pt\gotoURL{http://www.physik.fu-berlin.de/SomeVeryVeryVeryLongDirectory/And/AQuiteLongFileName.html} +% \endgraf \chardef\urlhyphenmethod=1 +% \hsize1pt\gotoURL{http://www.physik.fu-berlin.de/SomeVeryVeryVeryLongDirectory/And/AQuiteLongFileName.html} +% \stoptext + +%D When Joop Susan asked (on the \CONTEXT\ mailing list) how +%D to handle url's passed as argument, the following solutions +%D came to my mind: +%D +%D \starttyping +%D \def\whateverurl#1% +%D {{\def~{\string~}\useURL[dummy][#1]\goto{\url[dummy]}[URL(dummy)]}} +%D +%D \def\whateverurl#1% +%D {{\let~\lettertilde\useURL[dummy][#1]\goto{\url[dummy]}[URL(dummy)]}} +%D +%D \def\whateverurl#1% +%D {\convertargument#1\to\ascii +%D \expanded{\useURL[dummy][\ascii]}\goto{\url[dummy]}[URL(dummy)]} +%D \stoptyping + +%D \macros +%D {hyphenatedfile} +%D +%D For the moment we treat filenames in a similar way, +%D +%D \starttyping +%D \hyphenatedfile{here/there/filename.suffix} +%D \stoptyping + +\let\hyphenatedfile\hyphenatedurl + +% to be finished +% +% \def\hyphenatedstring#1% +% {\bgroup +% \nohyphens +% \def\next##1{##1\doif{##1}{-}{\allowbreak}}% +% \handletokens#1\with\next +% \egroup} +% +% {\hsize1cm\hyphenatedstring{ABXXXXXXXXXXC-12345-12345}} + +%D \macros +%D {disablediscretionaries,disablecompoundcharacter} +%D +%D Occasionally we need to disable this mechanism. For the +%D moment we assume that \type {|} is used. + +\def\disablediscretionaries + {\def|##1|{\string##1}% + \def\directdiscretionary##1{\string##1}} + +\def\disablecompoundcharacters + {\let\handlecompoundcharacter\string} + +\protect \endinput |