lang-ini.mkxl /size: 31 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=lang-ini,
3%D        version=1996.01.25,
4%D          title=\CONTEXT\ Language Macros,
5%D       subtitle=Initialization,
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% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]}
15
16%D This module implements multi||language support of \CONTEXT, which should not be
17%D confused with the multi||lingual interface. This support will be extended when
18%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\
19%D files.
20
21\writestatus{loading}{ConTeXt Language Macros / Initialization}
22
23\registerctxluafile{lang-ini}{autosuffix}
24\registerctxluafile{lang-def}{}
25\registerctxluafile{lang-cnt}{}
26
27\unprotect
28
29\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi
30\ifdefined\frenchspacing   \else \let\frenchspacing   \relax \fi
31
32%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table,
33%D starting with~0. Switching to a specific table is done by assigning the relevant
34%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot
35%D of management is delegated to \LUA.
36
37%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This
38%D just one of those situations in which we don't want to spent a real one. Language
39%D zero has no patterns, first of all because I like to start numbering at one. It
40%D may come in handy for special purposes as well.
41
42\normallanguage\zerocount
43
44%D \macros
45%D   {currentlanguage, setupcurrentlanguage}
46%D
47%D Instead of numbers,we are going to use symbolic names for the languages. The
48%D current langage is saved in the macro \type {\currentlanguage}. The setup macro
49%D is mainly used for cosmetic purposes.
50%D
51%D \starttyping
52%D \dorecurse{3}
53%D   {\language[nl]
54%D    \startmode[*en] english \stopmode
55%D    \startmode[*nl] dutch   \stopmode
56%D    \language[en]
57%D    \startmode[*en] english \stopmode
58%D    \startmode[*nl] dutch   \stopmode}
59%D \stoptyping
60
61\mutable\lettonothing\askedlanguage
62\mutable\lettonothing\currentlanguage
63\mutable\lettonothing\currentmainlanguage
64
65%D \macros
66%D   {defaultlanguage,languageparameter,specificlanguageparameter}
67%D
68%D We don't use the commandhandler here (yet) because we have a rather special
69%D fallback mechanism so quite some compatibility testing is needed.
70
71\installcorenamespace{language}
72\installcorenamespace{languagelinked}
73
74\mutable\def\currentusedlanguage{\currentlanguage} % no \cdef
75
76\permanent\def\defaultlanguage#1%
77  {\ifcsname\??language#1\s!default\endcsname
78     \expandafter\defaultlanguage\lastnamedcs
79   \else
80     #1%
81   \fi}
82
83\permanent\def\languageparameter#1%
84  {\ifcsname\??language\currentlanguage#1\endcsname
85     \lastnamedcs
86   \orelse\ifcsname\??language\currentlanguage\s!default\endcsname
87     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
88   \orelse\ifcsname\??language\s!default#1\endcsname
89     \lastnamedcs
90   \fi}
91
92\permanent\def\specificlanguageparameter#1#2%
93  {\ifcsname\??language#1#2\endcsname
94     \lastnamedcs
95   \orelse\ifcsname\??language#1\s!default\endcsname
96     \expandafter\specificlanguageparameter\lastnamedcs{#2}%
97   \orelse\ifcsname\??language\s!default#2\endcsname
98     \lastnamedcs
99   \fi}
100
101\permanent\def\mainlanguageparameter#1%
102  {\ifcsname\??language\currentmainlanguage#1\endcsname
103     \lastnamedcs
104   \orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname
105     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
106   \orelse\ifcsname\??language\s!default#1\endcsname
107     \lastnamedcs
108   \fi}
109
110\aliased\let\usedlanguageparameter\languageparameter
111
112\permanent\def\askedlanguageparameter#1% assumes \currentusedlanguage being set
113  {\ifcsname\??language\currentusedlanguage#1\endcsname
114     \lastnamedcs
115   \orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname
116     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
117   \orelse\ifcsname\??language\s!default#1\endcsname
118     \lastnamedcs
119   \fi}
120
121\permanent\protected\def\setusedlanguage#1%
122  {\cdef\currentusedlanguage{\reallanguagetag{#1}}%
123   \ifempty\currentusedlanguage
124     \let\currentusedlanguage  \currentlanguage
125     \enforced\let\usedlanguageparameter\languageparameter
126   \orelse\ifx\currentusedlanguage\v!global
127     \let\currentusedlanguage  \currentmainlanguage
128     \enforced\let\usedlanguageparameter\mainlanguageparameter
129   \orelse\ifx\currentusedlanguage\v!local
130     \let\currentusedlanguage  \currentlanguage
131     \enforced\let\usedlanguageparameter\languageparameter
132   \else
133     \enforced\let\usedlanguageparameter\askedlanguageparameter
134   \fi}
135
136\permanent\protected\def\setupcurrentlanguage[#1]%
137  {\setcurrentlanguage\currentmainlanguage{#1}}
138
139\permanent\protected\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
140  {\edef\p_askedlanguage{#1}% otherwise clash with \askedlanguage
141   \ifempty\p_askedlanguage \else
142     \ifempty\currentmainlanguage\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
143     \let\currentmainlanguage\p_askedlanguage
144     \setsystemmode{\systemmodeprefix\currentmainlanguage}%
145   \fi
146   \edef\p_askedlanguage{#2}%
147   \ifempty\p_askedlanguage \else
148     \ifempty\currentlanguage\else\resetsystemmode\currentlanguage\fi
149     \let\currentlanguage\p_askedlanguage
150     \setsystemmode\currentlanguage
151   \fi}
152
153%D The internal macros will be defined later.
154
155%D \macros
156%D   {installlanguage}
157%D
158%D Hyphenation patterns can only be loaded when the format file is prepared. The
159%D next macro takes care of this loading. A language is specified with
160%D
161%D \showsetup{installlanguage}
162%D
163%D When \type {state} equals \type {start}, both patterns and additional hyphenation
164%D specifications are loaded. These files are seached for in the patterns path
165%D have names like \type {lang-nl.lua}.
166%D
167%D The \type {spacing} variable specifies how the spaces after punctuation has to be
168%D handled. English is by tradition more tolerant to inter||sentence spacing than
169%D other languages.
170%D
171%D This macro also defines \type {\identifier} as a shortcut switch to the language.
172%D Furthermore the command defined as being language specific, are executed. With
173%D \type {default} we can default to another language (patterns) at format
174%D generation time. Patterns are loaded at runtime.
175
176\newtoks \everysetuplanguage
177
178\aliased\let\installedlanguages\clf_installedlanguages % no need for \clf_
179
180\permanent\protected\def\doifelselanguage#1%
181  {\ifcsname\??language#1\c!state\endcsname
182     \expandafter\firstoftwoarguments
183   \else
184     \expandafter\secondoftwoarguments
185   \fi}
186
187\aliased\let\doiflanguageelse\doifelselanguage
188
189\permanent\def\reallanguagetag#1%
190  {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi}
191
192% \language[#1] gave unwanted side effect of loading language specifics
193
194\mutable\lettonothing\currentsetuplanguage
195
196\permanent\tolerant\protected\def\installlanguage[#1]#*[#S#2]%
197  {\ifhastok={#2}%
198     \doifelselanguage{#1}
199       {\getparameters[\??language#1][#2]}
200       {\defcsname\??languagelinked#1\endcsname{#1}%
201        \getparameters[\??language#1][\c!state=\v!start,#2]%
202        \lang_basics_install_indeed{#1}{#1}}%
203     \cdef\currentsetuplanguage{#1}%
204     \clf_definelanguage{#1}{\specificlanguageparameter{#1}\s!default}%
205     \expand\everysetuplanguage
206   \else
207     \defcsname\??languagelinked#1\endcsname{#2}%
208     \clf_setlanguagesynonym{#1}{#2}%
209     \lang_basics_install_indeed{#1}{#2}%
210  \fi}
211
212\def\lang_basics_install_indeed#1#2%
213  {\ifcstok{\specificlanguageparameter{#1}\c!define}\v!no\orelse\ifcsname#1\endcsname\else
214     \frozen\instance\protected\defcsname#1\endcsname{\lang_basics_set_current[#2]}%
215   \fi}
216
217%D When the second argument is a language identifier, a synonym is created. This
218%D feature is present because we used dutch mnemonics in the dutch version, but
219%D nowadays conform a standard.
220
221\permanent\protected\def\doifelsepatterns#1%
222  {\begingroup % will change
223   \lang_basics_set_current[#1]%
224   \ifnum\normallanguage>\zerocount
225     \endgroup\expandafter\firstoftwoarguments
226   \else
227     \endgroup\expandafter\secondoftwoarguments
228   \fi}
229
230\aliased\let\doifpatternselse\doifelsepatterns
231
232%D \macros
233%D   {setuplanguage}
234%D
235%D Quick and dirty, but useful:
236%D
237%D \showsetup{setuplanguage}
238%D
239%D Beware, this command can only be used when a language is installed.
240
241\ifdefined\lang_basics_synchronize \else
242    \let\lang_basics_synchronize\relax % be nice for setups till we have one
243\fi
244
245\installmacrostack\currentlanguage
246
247\permanent\tolerant\protected\def\setuplanguage[#S#1]#*[#S#2]%
248  {\ifarguments
249     % only synchronize
250   \or
251     \let\currentsetuplanguage\currentlanguage
252     \getparameters[\??language\currentsetuplanguage][#1]%
253     \expand\everysetuplanguage
254   \or
255     \push_macro_currentlanguage % can be default
256     \cdef\currentsetuplanguage{\reallanguagetag{#1}}%
257     \getparameters[\??language\currentsetuplanguage][#2]%
258     \expand\everysetuplanguage
259     \pop_macro_currentlanguage
260   \fi
261   \lang_basics_synchronize}
262
263\appendtoks
264    \clf_unloadlanguage{\currentsetuplanguage}%
265\to \everysetuplanguage
266
267\setuplanguage
268  [\s!default]
269  [\s!patterns=,
270   \s!goodies=,
271   \s!lefthyphenmin=2,
272   \s!righthyphenmin=2,
273   \s!lefthyphenchar=-1,
274   \s!righthyphenchar=45,
275   \s!explicitlefthyphenchar=\languageparameter\s!lefthyphenchar,
276   \s!explicitrighthyphenchar=\languageparameter\s!righthyphenchar,
277   % used in compound i.e. interfaced with c! and can be anything so no numbers
278   \c!lefthyphen=,
279   \c!righthyphen=-,
280   \c!hyphen=-,
281   \c!spacing=\v!packed,
282   \c!compoundhyphen=\compoundhyphen,
283   \c!rightcompoundhyphen=\compoundhyphen,
284   \c!leftcompoundhyphen=,
285   \c!midsentence=---,
286   \c!leftsentence=---,
287   \c!rightsentence=---,
288   \c!leftsubsentence=---,
289   \c!rightsubsentence=---,
290   \c!leftquote=\upperleftsinglesixquote,
291   \c!rightquote=\upperrightsingleninequote,
292   \c!leftquotation=\upperleftdoublesixquote,
293   \c!rightquotation=\upperrightdoubleninequote,
294   \c!leftspeech=\languageparameter\c!leftquotation,
295   \c!middlespeech=,
296   \c!rightspeech=\languageparameter\c!rightquotation,
297   \c!limittext=\unknown,
298   \c!time={h,:,m},
299   \c!date={\v!year,\ ,\v!month,\ ,\v!day},
300   \c!text=Ag,
301   \c!font=] % \v!auto : experimental !
302
303% to be tested:
304%
305% \setuplanguage
306%   [\s!default]
307%   [\c!righthyphenchar="AD]
308
309%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used
310%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french
311%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like
312%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into
313%D view \quotation {when we quote} or \quote {quote} something.
314
315%D \macros
316%D  {currentdatespecification, currenttimespecification}
317%D
318%D Just to make things easy we can ask for the current date specification by saying:
319
320\permanent\def\currentdatespecification{\languageparameter\c!date}
321\permanent\def\currenttimespecification{\languageparameter\c!time}
322
323%D Carefull reading of these macros shows that it's legal to say
324%D
325%D \starttyping
326%D \installlanguage [du] [de]
327%D \stoptyping
328
329%D \macros
330%D   {language,mainlanguage}
331%D
332%D Switching to another language (actually another hyphenation pattern) is done
333%D with:
334%D
335%D \starttyping
336%D \language[identifier]
337%D \stoptyping
338%D
339%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still
340%D support the original meaning, so
341%D
342%D \starttyping
343%D \language=1
344%D \stoptyping
345%D
346%D is a valid operation, where the relation between number and language depends on
347%D the order in installing languages.
348%D
349%D \showsetup{language}
350%D \showsetup{mainlanguage}
351%D
352%D Both commands take a predefined language identifier as argument. We can use \type
353%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the
354%D language used for translating labels like {\em figure} and {\em table}. The main
355%D language defaults to the current language.
356
357\newtoks \everylanguage
358
359\installcorenamespace{languagenumbers}
360
361\appendtoks
362    % we need to reassign the number because new patterns can be defined later on
363    % so let's hope not that many \setups happen during a run
364    \gletcsname\??languagenumbers\currentlanguage\endcsname\undefined
365\to \everysetuplanguage
366
367\def\lang_basics_synchronize_yes
368  {\zerocount % see below
369   \global\expandafter\chardef\csname\??languagenumbers\currentlanguage\endcsname
370      \clf_languagenumber
371        {\currentlanguage}%
372        {\defaultlanguage\currentlanguage}%
373        {\languageparameter\s!patterns}%
374        {\languageparameter\s!goodies}%
375        {\languageparameter\c!factor}%
376      \relax
377   \normallanguage\csname\??languagenumbers\currentlanguage\endcsname}
378
379\let\lang_basics_synchronize_nop\zerocount % not loaded anyway
380
381\letcsname\??languagenumbers\endcsname\lang_basics_synchronize_nop % initime
382
383\appendtoks
384    \letcsname\??languagenumbers\endcsname\lang_basics_synchronize_yes % runtime
385\to \everydump
386
387\def\lang_basics_synchronize
388  {\normallanguage\csname\??languagenumbers
389     \ifcsname\??languagenumbers\currentlanguage\endcsname
390       \currentlanguage
391     \fi
392   \endcsname
393   \relax
394   \expand\everylanguage
395   \relax}
396
397\newinteger\hyphenstate
398\newinteger\hyphenminoffset
399
400% This is the old implementation: a hack that sets the min values, because we want
401% to keep the language set:
402%
403% \protected\def\nohyphens % nicer for url's
404%   {\ifrelax\dohyphens
405%      \protected\edef\dohyphens
406%        {\hyphenminoffset\the\hyphenminoffset\relax
407%         \lang_basics_synchronize_min_max}%
408%    \fi
409%    \hyphenminoffset\plusthousand
410%    \lang_basics_synchronize_min_max}
411%
412% \let\dohyphens\relax
413
414% But this one is nicer because we do keep the language set as well as don't mess
415% with the min values (it's more efficient too). We might get some more bits in
416% this mode (engine specific).
417
418\exhyphenchar 45 % to permit breaking at explicit hyphens
419
420% \uchyph\plusone :
421
422% \chardef \completehyphenationcode \numexpr
423\permanent \integerdef \completehyphenationcode \numexpr
424    \normalhyphenationcode            % \discretionary
425  + \automatichyphenationcode         % -
426  + \explicithyphenationcode          % \-
427  + \syllablehyphenationcode          % pattern driven
428  + \uppercasehyphenationcode         % replaces \uchyph
429  + \compoundhyphenationcode          % replaces \compoundhyphenmode
430  % \strictstarthyphenationcode       % replaces \hyphenationbounds (strict = original tex)
431  % \strictendhyphenationcode         % replaces \hyphenationbounds (strict = original tex)
432  + \automaticpenaltyhyphenationcode  % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty)
433  + \explicitpenaltyhyphenationcode   % replaces \hyphenpenaltymode (otherwise use \exhyphenpenalty)
434  + \permitgluehyphenationcode        % turn glue into kern in \discretionary
435  + \permitallhyphenationcode         % okay, let's be even more tolerant
436  + \permitmathreplacehyphenationcode % and again we're more permissive
437  + \forcehandlerhyphenationcode      % kick in the handler (could be an option)
438  + \feedbackcompoundhyphenationcode  % feedback compound snippets
439  + \ignoreboundshyphenationcode      % just in case we have hyphens at the edges
440  + \collapsehyphenationcode          % collapse -- and ---
441  + \replaceapostrophehyphenationcode % replace ' by 0x2019
442\relax
443
444\permanent \integerdef \partialhyphenationcode \numexpr
445    \ignoreboundshyphenationcode      % just in case we have hyphens at the edges
446% + \explicithyphenationcode          % \-
447  + \collapsehyphenationcode          % collapse -- and ---
448  + \replaceapostrophehyphenationcode % replace ' by 0x2019
449\relax
450
451\hccode"002D "002D % hyphen
452\hccode"00B7 "00B7 % centered text period (used in some languages)
453
454\permanent\protected\def\keephyphensequences
455  {\hccode"2010 \zerocount
456   \hccode"2013 \zerocount
457   \hccode"2014 \zerocount}
458
459\permanent\protected\def\collapsehyphensequences
460  {\hccode"2010 "2010\relax
461   \hccode"2013 "2013\relax
462   \hccode"2014 "2014\relax}
463
464\collapsehyphensequences
465
466% maybe a (un)setter for handlers
467
468\permanent\protected\def\dohyphens{\hyphenationmode\completehyphenationcode}
469\permanent\protected\def\nohyphens{\hyphenationmode\partialhyphenationcode}
470
471\permanent\protected\def\doapostrophes{\hyphenationmode\bitwiseflip\hyphenationmode \replaceapostrophehyphenationcode}
472\permanent\protected\def\noapostrophes{\hyphenationmode\bitwiseflip\hyphenationmode-\replaceapostrophehyphenationcode}
473
474% \permanent\protected\def\dohyphens
475%   {\ifbitwiseand\hyphenationmode\collapsehyphenationcode
476%      \hyphenationmode\completehyphenationcode
477%    \else
478%      \hyphenationmode\numexpr\completehyphenationcode-\collapsehyphenationcode\relax
479%    \fi}
480
481% \permanent\protected\def\nohyphens
482%   {\ifbitwiseand\hyphenationmode\collapsehyphenationcode
483%      \hyphenationmode\partialhyphenationcode
484%    \else
485%      \hyphenationmode\numexpr\partialhyphenationcode-\collapsehyphenationcode\relax
486%    \fi}
487
488\permanent\protected\def\dohyphencollapsing{\hyphenationmode\bitwiseflip\hyphenationmode \collapsehyphenationcode}
489\permanent\protected\def\nohyphencollapsing{\hyphenationmode\bitwiseflip\hyphenationmode-\collapsehyphenationcode}
490
491\permanent\protected\def\doexplicithyphens{\hyphenationmode\bitwiseflip\hyphenationmode \explicithyphenationcode}
492\permanent\protected\def\noexplicithyphens{\hyphenationmode\bitwiseflip\hyphenationmode-\explicithyphenationcode}
493
494\permanent\protected\def\usehyphensparameter#1%
495  {\ifcstok{#1\c!hyphens}\v!no
496     \ifbitwiseand\hyphenationmode\collapsehyphenationcode
497       \nohyphens
498     \else
499       \nohyphens
500       \nohyphencollapsing
501     \fi
502   \fi}
503
504\dohyphens
505
506%D The rest stays the same as in mkiv:
507
508\permanent\protected\def\lesshyphens
509  {\advanceby\hyphenminoffset\plusone
510   \lang_basics_synchronize_min_max}
511
512\permanent\protected\def\morehyphens
513  {\ifcase\hyphenminoffset \else
514     \advanceby\hyphenminoffset\minusone
515   \fi
516   \lang_basics_synchronize_min_max}
517
518% \protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end
519%   {% these values are stored along with glyph nodes
520%    \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
521%    \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax
522%    \hyphenationmin\numexpr0\languageparameter\s!hyphenmin\relax
523%    % these values are stored with the language (global!)
524%    \prehyphenchar \languageparameter\s!righthyphenchar\relax
525%    \posthyphenchar\languageparameter\s!lefthyphenchar \relax}
526
527\protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end
528  {% these values are stored along with glyph nodes
529  %\lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
530  %\righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax
531  %\hyphenationmin\numexpr0\languageparameter\s!hyphenmin\relax
532   \lefthyphenmin {\ifchknumexpr\languageparameter\s!lefthyphenmin \or\lastchknumber+\fi\hyphenminoffset}%
533   \righthyphenmin{\ifchknumexpr\languageparameter\s!righthyphenmin\or\lastchknumber+\fi\hyphenminoffset}%
534   \hyphenationmin{\ifchknumexpr\languageparameter\s!hyphenmin     \or\lastchknumber\else\zeropoint\fi}%
535   % these values are stored with the language (global!)
536   \prehyphenchar   \languageparameter\s!righthyphenchar\relax
537   \posthyphenchar  \languageparameter\s!lefthyphenchar \relax
538   \preexhyphenchar \languageparameter\s!explicitrighthyphenchar\relax
539   \postexhyphenchar\languageparameter\s!explicitlefthyphenchar \relax}
540
541\appendtoks
542    \lang_basics_synchronize_min_max % todo: also sync when already in language
543\to \everylanguage
544
545\appendtoks
546    \ifcstok{\languageparameter\s!apostrophe}\v!yes
547      \doapostrophes
548    \else
549      \noapostrophes
550    \fi
551\to \everylanguage
552
553\exapostrophechar\singlequoteasciicode
554
555\permanent\protected\def\unhyphenated
556  {\groupedcommand{\lefthyphenmin\maxdimen}\donothing}
557
558% \appendtoks
559%     \setups[\languageparameter\c!setups]%
560% \to \everylanguage
561
562%D You can setup the default language to reset settings.
563
564\mutable\lettonothing\currentlanguagesetups
565
566\appendtoks
567    \edef\currentlanguagesetups{\languageparameter\c!setups}%
568    \ifempty\currentlanguagesetups \else
569        \setups[\currentlanguagesetups]%
570    \fi
571\to \everylanguage
572
573% new
574
575\appendtoks
576    \usebidiparameter\languageparameter
577\to \everylanguage
578
579% this will move to core-spa !
580
581\appendtoks
582    \ifcstok{\languageparameter\c!spacing}\v!broad
583      \nonfrenchspacing
584    \else
585      \frenchspacing
586    \fi
587\to \everylanguage
588
589% \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?]
590%
591% \dorecurse{100}{dit is toch wel een heel\normalhyphendiscretionary lang\normalhyphendiscretionary woord \recurselevel\ }
592% \dorecurse{100}{dit is toch wel een heellangwoord \recurselevel\ }
593
594% new experimental feature
595
596\permanent\protected\def\setuplanguages
597  {\setuplanguage[\s!default]}
598
599% \setuplanguages[\c!font=\v!auto]
600% \setuplanguage[\s!default][\c!font=\v!auto]
601% \setuplanguage[nl][\c!font=\v!auto]
602
603\appendtoks
604    \edef\p_language_font{\languageparameter\c!font}%
605    \ifempty\p_language_font
606    \orelse\ifx\p_language_font\v!auto
607      \doaddfeature\currentlanguage
608    \else
609      \doaddfeature\p_language_font
610    \fi
611\to \everylanguage
612
613%D Fast switcher
614
615\def\lang_basics_switch_asked
616  {\ifcsname\??languagelinked\askedlanguage\endcsname
617     \edef\askedlanguage{\lastnamedcs}%
618     \ifx\currentlanguage\askedlanguage \else
619       \setcurrentlanguage\currentmainlanguage\askedlanguage
620       \lang_basics_synchronize
621     \fi
622   \fi}
623
624\permanent\protected\def\uselanguageparameter#1%
625  {\edef\askedlanguage{#1\c!language}%
626   \ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
627
628\permanent\protected\def\douselanguageparameter#1% fast setter
629  {\edef\askedlanguage{#1}%
630   \ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
631
632\protected\def\lang_basics_set_current[#1]%
633  {\edef\askedlanguage{#1}%
634   \ifempty\askedlanguage\else\lang_basics_switch_asked\fi}
635
636\pushoverloadmode
637
638    \permanent\protected\def\language
639      {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
640
641    \aliased\let\setlanguage\language % we make these synonyms
642
643    \aliased\let\patterns\gobbleoneargument
644
645\popoverloadmode
646
647\newinteger\mainlanguagenumber
648
649%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par}
650%D inside the group!
651
652\permanent\protected\def\startlanguage
653  {\begingroup\language}
654
655\permanent\let\stoplanguage\endgroup
656
657\permanent\protected\def\mainlanguage[#1]%
658  {\edef\askedlanguage{#1}%
659   \ifempty\askedlanguage
660   \orelse\ifcsname\??languagelinked\askedlanguage\endcsname
661    %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
662     \edef\askedlanguage{\lastnamedcs}%
663     \ifx\currentlanguage\askedlanguage
664       \ifx\currentmainlanguage\askedlanguage \else
665         \setcurrentlanguage\askedlanguage\askedlanguage
666         \lang_basics_synchronize
667       \fi
668     \else
669       \setcurrentlanguage\askedlanguage\askedlanguage
670       \lang_basics_synchronize
671     \fi
672   \fi
673   \mainlanguagenumber\normallanguage}
674
675\appendtoks
676    \normallanguage\mainlanguagenumber
677\to \everybeforepagebody
678
679%D Used at all?
680
681\permanent\def\splitsequence#1#2% append periods etc
682  {\ifcstok{#1}\v!no
683     #2%
684   \orelse\ifcstok{#1}\v!yes
685      \languageparameter\c!limittext
686   \else
687     #1%
688   \fi}
689
690\permanent\def\splitsymbol#1%
691  {\splitsequence{#1}{\languageparameter\c!limittext}}
692
693%D Just like with subsentence boundary symbols, quotes placement depends on the
694%D current language, therefore we show the defaults here.
695%D
696%D \def\ShowLanguageValues [#1] [#2] #3 #4
697%D   {\blank
698%D    \startlinecorrection
699%D    \vbox\bgroup
700%D    \language[#1]
701%D    \midaligned{\bf#2 subsentence symbol and quotes}
702%D    \framed[width=\hsize,frame=off,topframe=on,bottomframe=on,offset=.5ex]
703%D      {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
704%D       \startsubsentence\startsubsentence#3\stopsubsentence#4\stopsubsentence\hfil}
705%D    \egroup
706%D    \stoplinecorrection
707%D    \blank}
708%D
709%D \ShowLanguageValues [af] [afrikaans]  afrikaanse ...
710%D \ShowLanguageValues [ca] [catalan]    catalan ...
711%D \ShowLanguageValues [cs] [czech]      tjechisch tex
712%D \ShowLanguageValues [cs] [slovak]     slowaakse ...
713%D \ShowLanguageValues [da] [danish]     deense ...
714%D \ShowLanguageValues [de] [german]     duitse degelijkheid
715%D \ShowLanguageValues [en] [english]    engelse humor
716%D \ShowLanguageValues [et] [estonian]   ...
717%D \ShowLanguageValues [fi] [finnish]    finse ...
718%D \ShowLanguageValues [fr] [french]     franse slag
719%D \ShowLanguageValues [it] [italian]    italiaanse ...
720%D \ShowLanguageValues [la] [latin]      latijnse missen
721%D \ShowLanguageValues [nl] [dutch]      nederlandse zuinigheid
722%D \ShowLanguageValues [nb] [bokmal]     noorse zalm
723%D \ShowLanguageValues [nn] [nnynorsk]   noorse zalm
724%D \ShowLanguageValues [pl] [polish]     poolse vlag
725%D \ShowLanguageValues [pt] [portuguese] portugese ...
726%D \ShowLanguageValues [es] [spanish]    spaans benauwd
727%D \ShowLanguageValues [sv] [swedish]    zweedse ...
728%D \ShowLanguageValues [tr] [turkish]    turks fruit
729
730%D We support a lot of languages. These are specified and loaded in separate files,
731%D according to their roots. Here we only take care of (postponed) setting of the
732%D current language.
733%D
734%D \unprotect
735%D \placetable{The germanic languages (\type{lang-ger})}
736%D \starttable[||||]
737%D \HL
738%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
739%D \HL
740%D \NC \s!nl        \NC dutch        \NC germanic  \NC\FR
741%D \NC \s!en        \NC english      \NC germanic  \NC\MR
742%D \NC \s!de        \NC german       \NC germanic  \NC\MR
743%D \NC \s!da        \NC danish       \NC germanic  \NC\MR
744%D \NC \s!sv        \NC swedish      \NC germanic  \NC\MR
745%D \NC \s!af        \NC afrikaans    \NC germanic  \NC\MR
746%D \NC \s!nb        \NC bokmal       \NC germanic  \NC\LR
747%D \NC \s!nn        \NC nynorsk      \NC germanic  \NC\LR
748%D \HL
749%D \stoptable
750%D \protect
751%D
752%D \unprotect
753%D \placetable{The italic languages (\type{lang-ita})}
754%D \starttable[||||]
755%D \HL
756%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
757%D \HL
758%D \NC \s!fr        \NC french       \NC italic    \NC\FR
759%D \NC \s!ca        \NC catalan      \NC italic    \NC\MR
760%D \NC \s!es        \NC spanish      \NC italic    \NC\MR
761%D \NC \s!it        \NC italian      \NC italic    \NC\MR
762%D \NC \s!la        \NC latin        \NC italic    \NC\MR
763%D \NC \s!pt        \NC portuguese   \NC italic    \NC\LR
764%D \HL
765%D \stoptable
766%D \protect
767%D
768%D \unprotect
769%D \placetable{The slavic languages (\type{lang-sla})}
770%D \starttable[||||]
771%D \HL
772%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
773%D \HL
774%D \NC \s!pl        \NC polish       \NC slavic    \NC\FR
775%D \NC \s!cs        \NC czech        \NC slavic    \NC\MR
776%D \NC \s!sk        \NC slavik       \NC slavic    \NC\LR
777%D \HL
778%D \stoptable
779%D \protect
780%D \unprotect
781%D
782%D \placetable{The altaic languages (\type{lang-alt})}
783%D \starttable[||||]
784%D \HL
785%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
786%D \HL
787%D \NC \s!tr        \NC turkish      \NC altaic    \NC\SR
788%D \HL
789%D \stoptable
790%D
791%D \placetable{The uralic languages (\type{lang-ura})}
792%D \starttable[||||]
793%D \HL
794%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
795%D \HL
796%D \NC \s!fi        \NC finnish      \NC uralic    \NC\SR
797%D \HL
798%D \stoptable
799%D \protect
800
801\permanent\protected\def\nopatterns{\normallanguage\minusone}
802
803%D We default to the language belonging to the interface. This is one of the few
804%D places outside the interface modules where \type {\startinterface} is used.
805
806\setupcurrentlanguage[\s!en]
807
808\permanent\protected\def\initializemainlanguage
809  {\mainlanguage[\currentlanguage]%
810   \showmessage\m!languages9\currentlanguage}
811
812%D New:
813
814\permanent\let\stopexceptions\relax
815
816\tolerant\permanent\protected\def\startexceptions[#1]#:#2\stopexceptions
817  {\begingroup
818   \edef\askedlanguage{\reallanguagetag{#1}}%
819   \ifempty\askedlanguage
820     \let\askedlanguage\currentlanguage
821   \fi
822   \clf_setlanguageexceptions{\askedlanguage}{#2}%
823   \endgroup}
824
825\permanent\let\stoppatterns\relax
826
827\tolerant\permanent\protected\def\startpatterns[#1]#:#2\stoppatterns
828  {\begingroup
829   \edef\askedlanguage{\reallanguagetag{#1}}%
830   \ifempty\askedlanguage
831     \let\askedlanguage\currentlanguage
832   \fi
833   \clf_setlanguagepatterns{\askedlanguage}{#2}%
834   \endgroup}
835
836
837\pushoverloadmode
838
839\permanent\protected\def\hyphenation{\clf_setlanguageexceptions{\currentlanguage}}
840\permanent\protected\def\patterns   {\clf_setlanguagepatterns  {\currentlanguage}}
841
842\popoverloadmode
843
844%D New:
845
846\permanent\protected\def\traceddiscretionary#1#%
847  {\dontleavehmode\lang_basics_traced_discretionary{#1}}
848
849\protected\def\lang_basics_traced_discretionary#1#2#3#4%
850  {\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}}
851
852\def\lang_basics_trace_discretionary_yes{\enforced\let\discretionary\traceddiscretionary} % indirect because of overload
853\def\lang_basics_trace_discretionary_nop{\enforced\let\discretionary\normaldiscretionary} % indirect because of overload
854
855
856\installtextracker
857  {discretionaries}
858  {\lang_basics_trace_discretionary_yes}
859  {\lang_basics_trace_discretionary_nop}
860
861\permanent\protected\def\samplediscretionary
862  {\traceddiscretionary
863     {pre\clf_currentprehyphenchar}%
864     {\clf_currentposthyphenchar post}%
865     {replace}}
866
867%D A typical \LMTX\ feature:
868%D
869%D \starttyping
870%D whatever\par
871%D {\nokerning whatever}\par
872%D efficient ff fi\par
873%D {\noligaturing efficient ff fi}\par
874%D {\nokerning\noligaturing efficient ff fi}\par
875%D {e{\noligaturing ffi}cient}\par
876%D {ef{\noleftligaturing f}icient ff fi}\par
877%D {ef{\norightligaturing f}icient ff fi}\par
878%D \stoptyping
879
880\immutable\integerdef\nokerningcode   \numexpr\noleftkernglyphoptioncode        +\norightkernglyphoptioncode           \relax
881\immutable\integerdef\noligaturingcode\numexpr\noleftligatureglyphoptioncode    +\norightligatureglyphoptioncode       \relax
882\immutable\integerdef\noitalicscode   \numexpr\noitaliccorrectionglyphoptioncode+\nozeroitaliccorrectionglyphoptioncode\relax
883
884\permanent\protected\def\nokerning         {\bitwiseflip\glyphoptions\nokerningcode}
885\permanent\protected\def\noligaturing      {\bitwiseflip\glyphoptions\noligaturingcode}
886\permanent\protected\def\noitaliccorrection{\bitwiseflip\glyphoptions\noitalicscode}
887
888\permanent\protected\def\noleftkerning     {\bitwiseflip\glyphoptions\noleftkernglyphoptioncode}
889\permanent\protected\def\noleftligaturing  {\bitwiseflip\glyphoptions\noleftligatureglyphoptioncode}
890\permanent\protected\def\norightkerning    {\bitwiseflip\glyphoptions\norightkernglyphoptioncode}
891\permanent\protected\def\norightligaturing {\bitwiseflip\glyphoptions\norightligatureglyphoptioncode}
892
893\bitwiseflip\glyphoptions\nozeroitaliccorrectionglyphoptioncode % for the moment default avoid the side effect
894
895%D Also \LMTX:
896
897% \startlanguageoptions[de]
898%     Zapf|innovation
899% \stoplanguageoptions
900
901\permanent\let\stoplanguageoptions\relax
902
903\permanent\protected\def\startlanguageoptions
904  {\begingroup
905   \catcode`|\othercatcode
906   \lang_startlanguageoptions}
907
908\tolerant\def\lang_startlanguageoptions[#1]#:#2\stoplanguageoptions
909  {\edef\askedlanguage{\reallanguagetag{#1}}%
910   \ifempty\askedlanguage
911     \let\askedlanguage\currentlanguage
912   \fi
913   \clf_setlanguageoptions{\askedlanguage}{#2}%
914   \endgroup}
915
916% \startluacode
917%     table.save("oeps-fixes.llg", {
918%         name    = "demo",
919%         options = {
920%             { patterns = { fio  = "f|io" }, words = [[ fioot fiots ]] },
921%             { patterns = { fio  = "t|h"  }, words = [[ this that ]]   },
922%         },
923%     })
924% \stopluacode
925%
926% \setuplanguage[en][goodies={oeps-fixes.llg}] \setupbodyfont[ebgaramond]
927%
928% \starttext
929%     fiets fiots fiats fioot this that
930% \stoptext
931
932\protect \endinput
933