core-con.mkxl /size: 35 Kb    last modification: 2024-01-16 09:02
1%D \module
2%D   [       file=core-con,
3%D        version=1997.26.08,
4%D          title=\CONTEXT\ Core Macros,
5%D       subtitle=Conversion,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Core Macros / Conversion}
15
16\registerctxluafile{core-con}{autosuffix}
17
18% todo: iso date ranges (from/to)
19
20\unprotect
21
22\ifdefined\currentlanguage \else \lettonothing\currentlanguage     \fi
23\ifdefined\labeltext       \else \let\labeltext\firstofoneargument \fi
24
25%D This module deals with all kind of conversions from numbers and dates. I
26%D considered splitting this module in a support one and a core one, but to keep
27%D things simple as well as preserve the overview, I decided against splitting.
28
29\aliased\let\spr\firstofoneargument % separator
30\aliased\let\stp\firstofoneargument % stopper
31
32% needed for arab (but can disappear as no ons used it, experiment for idris)
33
34\permanent\protected\def\isolateseparators % even works with list separator overloading
35  {\enforced\permanent\def\spr##1{{##1}}%  % we can probably best mess around with zwj
36   \enforced\permanent\def\stp##1{{##1}}}  % and friends
37
38%D \macros
39%D   {numbers}
40%D
41%D First we deal with the dummy conversion of numbers using the \TEX\ primitive
42%D \type{\number}. The uppercase alternative is only there for compatibility with
43%D the other conversion macros. We could do without \type{#1} but this way we get
44%D rid of unwanted braces. For the savety we also define a non||sence uppercase
45%D alternative.
46%D
47%D \showsetup{numbers}
48%D
49%D \starttyping
50%D \def\numbers#1{\number#1}
51%D \def\Numbers#1{\number#1}
52%D \stoptyping
53%D
54%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear,
55%D unless we use:
56
57\permanent\def\numbers#1{\purenumber{#1}}
58\permanent\def\Numbers#1{\purenumber{#1}}
59
60%D \macros
61%D   {romannumerals,Romannumerals}
62%D
63%D \TEX\ the program uses a rather tricky conversion from numbers to their roman
64%D counterparts. This conversion could of course be programmed in \TEX\ itself, but
65%D I guess Knuth found the programming trick worth presenting.
66%D
67%D \showsetup{romannumerals}
68%D \showsetup{Romannumerals}
69
70\permanent\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax}
71\permanent\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax}
72
73%D Arabic  etc:
74
75\permanent\def\abjadnumerals     #1{\clf_abjadnumerals     \numexpr#1\relax}
76\permanent\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax}
77\permanent\def\abjadnaivenumerals#1{\clf_alphabetic        \numexpr#1\relax{arabic}} % okay?
78
79\permanent\def\hebrewnumerals    #1{\clf_hebrewnumerals\numexpr#1\relax}
80\aliased  \let\yiddishnumerals      \hebrewnumerals
81
82\permanent\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new
83\permanent\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new
84
85\permanent\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}}
86\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}}
87
88\permanent\def\thainumerals      #1{\clf_alphabetic\numexpr#1\relax{thai}}
89\permanent\def\devanagarinumerals#1{\clf_decimals  \numexpr#1\relax{devanagari}}
90\permanent\def\malayalamnumerals #1{\clf_decimals  \numexpr#1\relax{malayalam}}
91\permanent\def\tamilnumerals     #1{\clf_decimals  \numexpr#1\relax{tamil}}
92\permanent\def\kannadanumerals   #1{\clf_decimals  \numexpr#1\relax{kannada}}
93\permanent\def\telugunumerals    #1{\clf_decimals  \numexpr#1\relax{telugu}}
94\permanent\def\bengalinumerals   #1{\clf_decimals  \numexpr#1\relax{bengali}}
95\permanent\def\gujaratinumerals  #1{\clf_decimals  \numexpr#1\relax{gujarati}}
96\permanent\def\gurmurkhinumerals #1{\clf_decimals  \numexpr#1\relax{gurmurkhi}}
97\permanent\def\tibetannumerals   #1{\clf_alphabetic\numexpr#1\relax{tibetan}}
98\permanent\def\greeknumerals     #1{\clf_alphabetic\numexpr#1\relax{greek}}
99\permanent\def\Greeknumerals     #1{\clf_Alphabetic\numexpr#1\relax{greek}}
100\permanent\def\arabicnumerals    #1{\clf_alphabetic\numexpr#1\relax{arabic}}
101\permanent\def\persiannumerals   #1{\clf_alphabetic\numexpr#1\relax{persian}}
102\permanent\def\arabicdecimals    #1{\clf_decimals  \numexpr#1\relax{arabic}}
103\permanent\def\persiandecimals   #1{\clf_decimals  \numexpr#1\relax{persian}}
104
105\permanent\def\mathgreeknumerals #1{\im{\clf_alphabetic\numexpr#1\relax{greek}}}
106\permanent\def\mathGreeknumerals #1{\im{\clf_Alphabetic\numexpr#1\relax{greek}}}
107
108\aliased  \let\arabicexnumerals     \persiannumerals
109
110\permanent\def\koreannumerals    #1{\clf_alphabetic\numexpr#1\relax{korean}}
111\permanent\def\koreannumeralsp   #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}}
112\permanent\def\koreannumeralsc   #1{\clf_alphabetic\numexpr#1\relax{korean-circle}}
113
114\aliased  \let\koreanparentnumerals     \koreannumeralsp
115\aliased  \let\koreanparenthesisnumerals\koreannumeralsp
116\aliased  \let\koreancirclenumerals     \koreannumeralsc
117
118\permanent\def\chinesenumerals    #1{\clf_chinesenumerals\numexpr#1\relax{normal}}
119\permanent\def\chinesecapnumerals #1{\clf_chinesenumerals\numexpr#1\relax{cap}}
120\permanent\def\chineseallnumerals #1{\clf_chinesenumerals\numexpr#1\relax{all}}
121\permanent\def\chinesedatenumerals#1{\clf_chinesenumerals\numexpr#1\relax{date}}
122
123%D \macros
124%D   {character,Character}
125%D
126%D Converting a number into a character can of course only be done with numbers
127%D less or equal to~26. At the cost of much more macros a faster conversion is
128%D possible, using:
129%D
130%D \starttyping
131%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
132%D \stoptyping
133%D
134%D But we prefer a simpel \type{\case}.
135%D
136%D \showsetup{character}
137%D \showsetup{Character}
138
139\permanent\def\character#1{\clf_character\numexpr#1\relax}
140\permanent\def\Character#1{\clf_Character\numexpr#1\relax}
141
142%D \macros
143%D   {characters,Characters}
144%D
145%D Converting large numbers is supported by the next two macros. This time we
146%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$.
147%D
148%D \showsetup{characters}
149%D \showsetup{Characters}
150
151\permanent\def\characters#1{\clf_characters\numexpr#1\relax}
152\permanent\def\Characters#1{\clf_Characters\numexpr#1\relax}
153
154%D \macros
155%D   {greeknumerals,Greeknumerals}
156%D
157%D Why should we only honour the romans, and not the greek?
158
159% \let\greeknumerals\gobbleoneargument
160% \let\Greeknumerals\gobbleoneargument
161
162%D \macros
163%D   {oldstylenumerals,oldstyleromannumerals}
164%D
165%D These conversions are dedicated to Frans Goddijn.
166
167\permanent\protected\def\oldstylenumerals#1%
168  {\begingroup
169   \os\number#1%
170   \endgroup}
171
172\permanent\protected\def\oldstyleromannumerals#1% will become obsolete
173  {\dontleavehmode
174   \hbox\bgroup
175   \ss\txx
176   \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}%
177   \scratchwidth \wd\scratchbox
178   \scratchheight\ht\scratchbox
179   \scratchdimen .1\exheight
180   \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax
181   \hskip-\scratchwidth
182   \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen
183   \hskip-\scratchwidth
184   \box\scratchbox
185   \egroup}
186
187%D \macros
188%D   {normaltime,normalyear,normalmonth,normalday}
189%D
190%D The last part of this module is dedicated to converting dates. Because we want to
191%D use as meaningful commands as possible, and because \TEX\ already uses up some of
192%D those, we save the original meanings. The above are defined already.
193
194%D \macros
195%D   {month,MONTH}
196%D
197%D Converting the month number into a month name is done using a case statement,
198%D abstact values and the label mechanism. This way users can easily redefine a
199%D label from for instance german into austrian.
200%D
201%D \starttyping
202%D \setuplabeltext [de] [january=J\"anner]
203%D \stoptyping
204%D
205%D Anyhow, the conversion looks like:
206
207\permanent\protected\def\monthlong #1{\clf_monthname\numexpr#1\relax}
208\permanent\protected\def\monthshort#1{\clf_monthmnem\numexpr#1\relax}
209\permanent\protected\def\daylong   #1{\clf_dayname\numexpr#1\relax}
210\permanent\protected\def\dayshort  #1{\clf_daymnem\numexpr#1\relax}
211\aliased            \let\convertmonth\monthlong % for old times sake
212
213%D We redefine the \TEX\ primitive \type{\month} as:
214%D
215%D \showsetup{month}
216%D \showsetup{MONTH}
217
218\pushoverloadmode
219
220\aliased\let\month\monthlong
221
222\popoverloadmode
223
224\permanent\protected\def\MONTH     #1{\WORD{\clf_monthname\numexpr#1\relax}}
225\permanent\protected\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}}
226\permanent\protected\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}}
227
228%D We never explicitly needed this, but Tobias Burnus pointed out that it would be
229%D handy to convert to the day of the week. In doing so, we have to calculate the
230%D total number of days, taking leapyears into account. For those who are curious:
231%D
232%D \startitemize[packed]
233%D \item  years that can be divided by 4 are leapyears
234%D \item  exept years that can be divided by 100
235%D \item  unless years can be divided by 400
236%D \stopitemize
237
238%D \macros
239%D   {weekday,WEEKDAY}
240%D
241%D The first one is sort of redundant. It takes the day number argument.
242%D
243%D \showsetup{weekday}
244%D \showsetup{WEEKDAY}
245
246\permanent\protected\def\weekday #1{\clf_dayname\numexpr#1\relax}
247\permanent\protected\def\WEEKDAY #1{\WORD{\clf_dayname\numexpr#1\relax}}
248\permanent\protected\def\DAYLONG #1{\WORD{\clf_dayname\numexpr#1\relax}}
249\permanent\protected\def\DAYSHORT#1{\WORD{\clf_daymnem\numexpr#1\relax}}
250
251%D \macros
252%D   {getdayoftheweek, dayoftheweek}
253
254\newcount\normalweekday
255
256\permanent          \def\dayoftheweek   #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax}                 % name
257\permanent\protected\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number
258
259%D Using this macro in
260%D
261%D \startbuffer
262%D monday:   \dayoftheweek  {4} {5} {1992}
263%D friday:   \dayoftheweek {16} {6} {1995}
264%D monday:   \dayoftheweek {25} {8} {1997}
265%D saturday: \dayoftheweek {30} {8} {1997}
266%D tuesday:  \dayoftheweek  {2} {1} {1996}
267%D tuesday:  \dayoftheweek  {7} {1} {1997}
268%D tuesday:  \dayoftheweek {13} {1} {1998}
269%D friday:   \dayoftheweek  {1} {1} {2000}
270%D \stopbuffer
271%D
272%D \typebuffer
273%D
274%D gives
275%D
276%D \startlines
277%D \getbuffer
278%D \stoplines
279%D
280%D The macro \type {\getdayoftheweek} can be used to calculate the number \type
281%D {\normalweekday}.
282
283%D \macros
284%D   {doifleapyearelse,
285%D    getdayspermonth}
286%D
287%D Sometimes we need to know if we're dealing with a leapyear, so here is a
288%D testmacro:
289%D
290%D \starttyping
291%D \doifleapyearelse{year}{yes}{no}
292%D \stoptyping
293%D
294%D An example of its use can be seen in the macro
295%D
296%D \starttyping
297%D \getdayspermonth{year}{month}
298%D \stoptyping
299%D
300%D The number of days is available in the macro \type {\numberofdays}.
301
302\permanent\def\doifelseleapyear#1% expandable check
303  {\clf_doifelseleapyear\numexpr#1\relax}
304
305\aliased\let\doifleapyearelse\doifelseleapyear
306
307\mutable\let\numberofdays\!!zerocount
308
309\permanent\protected\def\getdayspermonth#1#2%
310  {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}}
311
312\permanent\def\dayspermonth#1#2%
313  {\clf_nofdays\numexpr#1\relax\numexpr#2\relax}
314
315% \dayoftheweek{2006}{9}{15}
316% \doifleapyearelse{2000}{OK}{NOT OK}
317% \doifleapyearelse{2100}{NOT OK}{OK}
318% \doifleapyearelse{2004}{OK}{NOT OK}
319% \doifleapyearelse{2003}{NOT OK}{OK}
320% \dayspermonth{2000}{2}
321% [\the\normaltime=\the\time]
322
323%D \macros
324%D   {currentdate, rawdate, date}
325%D
326%D We use these conversion macros in the date formatting macro:
327%D
328%D \showsetup{currentdate}
329%D
330%D This macro takes care of proper spacing and delivers for instance:
331%D
332%D \startbuffer
333%D \currentdate[weekday,day,month,year]
334%D \currentdate[WEEKDAY,day,MONTH,year]
335%D \stopbuffer
336%D
337%D \startlines
338%D \getbuffer
339%D \stoplines
340%D
341%D depending of course on the keywords. Here we gave:
342%D
343%D \typebuffer
344%D
345%D If needed one can also add non||keywords, like in
346%D
347%D \startbuffer
348%D \currentdate[dd,--,mm,--,yy]
349%D \stopbuffer
350%D
351%D \typebuffer
352%D
353%D or typeset: \getbuffer.
354%D
355%D When no argument is passed, the current date is given as specified per
356%D language (using \type{\installlanguage}).
357%D
358%D \showsetup{currentdate}
359%D
360%D \startbuffer
361%D \date
362%D \date[d=12,m=12,y=1998][weekday]
363%D \date[d=12,m=12,y=1998]
364%D \stopbuffer
365%D
366%D We can also typeset arbitrary dates, using the previous
367%D command.
368%D
369%D \typebuffer
370%D
371%D The date is specified by one character keys. When no date is given, we get the
372%D current date.
373%D
374%D \startlines
375%D \getbuffer
376%D \stoplines
377
378%D \starttabulate[|l|l|]
379%D \HL
380%D \NC year     \NC (\currentdate[year])     \NC\NR
381%D \NC yy       \NC (\currentdate[yy])       \NC\NR
382%D \NC y        \NC (\currentdate[y])        \NC\NR
383%D \NC Y        \NC (\currentdate[Y])        \NC\NR
384%D \HL
385%D \NC month    \NC (\currentdate[month])    \NC\NR
386%D \NC mm       \NC (\currentdate[mm])       \NC\NR
387%D \NC m        \NC (\currentdate[m])        \NC\NR
388%D \NC M        \NC (\currentdate[M])        \NC\NR
389%D \HL
390%D \NC day      \NC (\currentdate[day])      \NC\NR
391%D \NC dd       \NC (\currentdate[dd])       \NC\NR
392%D \NC d        \NC (\currentdate[d])        \NC\NR
393%D \NC D        \NC (\currentdate[D])        \NC\NR
394%D \HL
395%D \NC weekday  \NC (\currentdate[weekday])  \NC\NR
396%D \NC w        \NC (\currentdate[w])        \NC\NR
397%D \NC W        \NC (\currentdate[W])        \NC\NR
398%D \HL
399%D \NC referral \NC (\currentdate[referral]) \NC\NR
400%D \HL
401%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR
402%D \NC dd:mnem  \NC (\currentdate[dd:mnem])  \NC\NR
403%D \NC d:mnem   \NC (\currentdate[d:mnem])   \NC\NR
404%D \NC D:mnem   \NC (\currentdate[D:mnem])   \NC\NR
405%D \HL
406%D \stoptabulate
407%D
408%D \startbuffer
409%D (\currentdate[D,.,M,.,Y])
410%D (\currentdate[day,month,year])
411%D (\currentdate[day,+,month,+,year])
412%D \stopbuffer
413%D
414%D \typebuffer \getbuffer
415%D
416%D Some indirectness and abstraction:
417%D
418%D \starttyping
419%D \definedate[crap][year]
420%D \currentdate[crap]
421%D \stoptyping
422
423\installcorenamespace{date}
424
425\permanent\tolerant\protected\def\definedate[#1]#,[#2]%
426  {\ifarguments\else\defcsname\??date#1\endcsname{#2}\fi}
427
428\def\syst_converters_check_date_specification#1%
429  {\ifcsname\??date#1\endcsname
430     \edef#1{\lastnamedcs}%
431   \fi}
432
433\newtoks\everycurrentdate
434
435\permanent\tolerant\protected\def\currentdate[#1]%
436  {\dontleavehmode
437   \begingroup
438   \expand\everycurrentdate
439   \edef\m_syst_converters_date{#1}%
440   \syst_converters_check_date_specification\m_syst_converters_date
441   \syst_converters_check_date_specification\currentdatespecification
442   \clf_currentdate
443     {\m_syst_converters_date}{\currentdatespecification}{\labellanguage}%
444     \normalyear\normalmonth\normalday
445   \endgroup}
446
447\permanent\tolerant\protected\def\setdate[#1]% sets the date !
448  {\begingroup
449   \letdummyparameter\c!d\normalday
450   \letdummyparameter\c!m\normalmonth
451   \letdummyparameter\c!y\normalyear
452   \getdummyparameters[#1]%
453   \normalexpanded
454     {\endgroup
455      \ifempty{\directdummyparameter\c!d}\else\normalday  \number\directdummyparameter\c!d\relax\fi
456      \ifempty{\directdummyparameter\c!m}\else\normalmonth\number\directdummyparameter\c!m\relax\fi
457      \ifempty{\directdummyparameter\c!y}\else\normalyear \number\directdummyparameter\c!y\relax\fi}}
458
459\permanent\tolerant\protected\def\date[#1]#,[#2]% sets the date !
460  {\dontleavehmode
461   \begingroup
462   \setdate[#1]% sets the date !
463   \expand\everycurrentdate
464   \edef\m_syst_converters_date{#2}%
465   \syst_converters_check_date_specification\m_syst_converters_date
466   \syst_converters_check_date_specification\currentdatespecification
467   \clf_currentdate
468     {\m_syst_converters_date}{\currentdatespecification}{\labellanguage}%
469     \normalyear\normalmonth\normalday
470   \endgroup}
471
472\permanent\def\rawdate[#1]% expandable and no labels
473  {\clf_currentdate
474     {#1}{\currentdatespecification}{}%
475     \normalyear\normalmonth\normalday}
476
477%D \macros
478%D   {currenttime}
479%D
480%D The currenttime is actually the jobtime. You can specify a pattern similar
481%D to the previous date macro using the keys \type {h}, \type {m} and a separator.
482
483\mutable\let\currenthour  \!!plusone
484\mutable\let\currentminute\!!plusone
485\mutable\let\currentsecond\!!plusone
486
487\permanent\protected\def\calculatecurrenttime
488  {\edef\currenthour  {\clf_hour  }%
489   \edef\currentminute{\clf_minute}%
490   \edef\currentsecond{\clf_second}}
491
492% \def\currenttimespecification{h,:,m}
493
494\permanent\protected\def\currenttime
495  {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop}
496
497\protected\def\syst_converters_current_time_yes[#1]%
498  {\calculatecurrenttime
499   \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
500
501\protected\def\syst_converters_current_time_nop
502  {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}}
503
504%D Because we're dealing with dates, we also introduce a few day loops:
505%D
506%D \starttyping
507%D \processmonth{year}{month}{command}
508%D \processyear{year}{command}{before}{after}
509%D \stoptyping
510%D
511%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday}
512%D can be used for for date manipulations.
513
514\permanent\protected\def\processmonth#1#2#3% year month command
515  {\begingroup
516   \getdayspermonth{#1}{#2}%
517   \dostepwiserecurse\plusone\numberofdays\plusone
518     {\normalyear #1\relax
519      \normalmonth#2\relax
520      \normalday  \recurselevel\relax
521      #3}%
522   \endgroup}
523
524\permanent\protected\def\processyear#1#2#3#4% year command before after
525  {\begingroup
526   \dorecurse\plustwelve
527     {\normalyear #1\relax
528      \normalmonth\recurselevel\relax
529      #3\processmonth\normalyear\normalmonth{#2}#4}%
530   \endgroup}
531
532%D \macros
533%D   {defineconversion, convertnumber}
534%D
535%D Conversion involves the macros that we implemented earlier in this module.
536%D
537%D \showsetup{defineconversion}
538%D \showsetup{convertnumber}
539%D
540%D We can feed this command with conversion macros as well as a set of conversion
541%D symbols. Both need a bit different treatment.
542%D
543%D \starttyping
544%D \defineconversion [roman] [\romannumerals]
545%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
546%D \stoptyping
547%D
548%D You can define a language dependent conversion with:
549%D
550%D \starttyping
551%D \defineconversion [en] [whatever] [\something]
552%D \stoptyping
553
554\installcorenamespace {conversion}
555\installcorenamespace {conversionarguments}
556\installcorenamespace {conversionwords}
557
558%D It might be better to move more to \LUA\ as we also need conversion there and
559%D duplicating logic doesn't make things cleaner. It means that all conversions
560%D will get a language argument too. However, we permit definitions at the \TEX\ end
561%D so we have to provide some hybrid method.
562
563% checkedconversion(method,n,language)
564
565\permanent\tolerant\protected\def\defineconversion[#1]#*[#2]#*[#3]% from now on global (maybe local again some day)
566  {\ifparameter#3\or
567     \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}%
568   \else
569     \syst_converters_define_conversion_indeed{#1}{#1}{#2}%
570   \fi}
571
572\def\syst_converters_define_conversion_indeed#1#2#3%
573  {\doifelseinstring{,}{\detokenize{#3}}
574     {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols
575      \gdefcsname\??conversion#1\endcsname{\syst_converters_checked_conversion{#2}}}
576     {\gdefcsname\??conversion#1\endcsname{#3}}}
577
578\def\syst_converters_checked_conversion#1#2%
579  {\clf_checkedconversion{#1}\numexpr#2\relax}
580
581%D If a conversion is just a font switch then we need to make sure that the number
582%D is indeed ends up as number in the input, so we need to handle the second
583%D argument.
584
585\permanent\def\convertnumber#1#2% expandable
586  {\csname\??conversionarguments
587     \ifcsname\??conversion\currentlanguage#1\endcsname1\else
588     \ifcsname\??conversion                #1\endcsname2\else
589                                                       3\fi\fi
590   \endcsname{#1}{\number#2}}
591
592\permanent\protected\def\uconvertnumber % unexpandable
593  {\convertnumber}
594
595\defcsname\??conversionarguments1\endcsname#1{\csname\??conversion\currentlanguage#1\endcsname}
596\defcsname\??conversionarguments2\endcsname#1{\csname\??conversion                #1\endcsname}
597\letcsname\??conversionarguments3\endcsname  \syst_converters_checked_conversion
598
599% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check
600% if we have definitions that are not matched at the lua end .. eventually we might do
601% that when more shows up
602
603\permanent\def\doifelseconversiondefined#1% expandable
604  {\ifcsname\??conversion\currentlanguage#1\endcsname
605     \expandafter\firstoftwoarguments
606   \orelse\ifcsname\??conversion#1\endcsname
607     \expandafter\firstoftwoarguments
608   \else
609     \expandafter\secondoftwoarguments
610   \fi}
611
612\permanent\def\doifelseconversionnumber#1#2% expandable
613  {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax
614     \expandafter\secondoftwoarguments
615   \else
616     \expandafter\firstoftwoarguments
617   \fi}
618
619\aliased\let\doifconversiondefinedelse\doifelseconversiondefined
620\aliased\let\doifconversionnumberelse \doifelseconversionnumber
621
622%D Handy.
623
624\defcsname\??conversionwords\v!one  \endcsname{1}
625\defcsname\??conversionwords\v!two  \endcsname{2}
626\defcsname\??conversionwords\v!three\endcsname{3}
627\defcsname\??conversionwords\v!four \endcsname{4}
628\defcsname\??conversionwords\v!five \endcsname{5}
629
630%permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
631\permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi}
632
633% \defineconversion[ctx][c,o,n,t,e,x,t]
634%
635% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
636
637%D \macros
638%D   {ordinalnumber, highordinalstr, ordinalstr}
639%D
640%D Efficient general ordinal number converters are sometimes difficult to
641%D implement. Fortunately dates never exceed the number~31.
642
643\permanent\def\highordinalstr#1{\high{\notsmallcapped{#1}}}
644\permanent\def\ordinalstr    #1{\notsmallcapped{#1}}
645\permanent\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}}
646\permanent\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}}
647
648\mutable\let\verbosenumberconnector\space
649
650\permanent\def\verbosenumber#1{\clf_verbose\numexpr#1\relax{\currentlanguage}{\verbosenumberconnector}}
651\permanent\def\VerboseNumber#1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}{\verbosenumberconnector}}}
652
653%D As longs as symbols are linked to levels or numbers, we can also use the
654%D conversion mechanism, but in for instance the itemization macros, we prefer
655%D symbols because they can more easier be (partially) redefined. Symbols are
656%D implemented in another module.
657
658\permanent\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}}
659\permanent\def\smallcappedcharacters   #1{\smallcapped{\characters   {#1}}}
660
661\defineconversion []                     [\numbers] % the default conversion
662\defineconversion [\v!empty]             [\gobbleoneargument]
663\defineconversion [\v!none]              [\numbers]
664\defineconversion [\s!default]           [\numbers]
665
666\defineconversion [month]                [\monthlong]
667\defineconversion [month:mnem]           [\monthshort]
668
669\defineconversion [\v!character]         [\character]
670\defineconversion [\v!Character]         [\Character]
671
672\defineconversion [\v!characters]        [\characters]
673\defineconversion [\v!Characters]        [\Characters]
674
675\defineconversion [a]                    [\alphabeticnumerals]
676\defineconversion [A]                    [\Alphabeticnumerals]
677\defineconversion [AK]                   [\smallcappedcharacters]
678\defineconversion [KA]                   [\smallcappedcharacters]
679
680\defineconversion [\v!alphabetic]        [\alphabeticnumerals]
681\defineconversion [\v!Alphabetic]        [\Alphabeticnumerals]
682
683\defineconversion [\v!number]            [\numbers]
684\defineconversion [\v!numbers]           [\numbers]
685\defineconversion [\v!Numbers]           [\Numbers]
686\defineconversion [\v!mediaeval]         [\mediaeval]
687
688\defineconversion [\v!word]              [\verbosenumber]
689\defineconversion [\v!words]             [\verbosenumber]
690
691\defineconversion [\v!Word]              [\VerboseNumber]
692\defineconversion [\v!Words]             [\VerboseNumber]
693
694\defineconversion[\v!ordinal]            [\ordinalnumber]
695\defineconversion[\v!Ordinal]            [\Ordinalnumber]
696
697\defineconversion [n]                    [\numbers]
698\defineconversion [N]                    [\Numbers]
699\defineconversion [m]                    [\mediaeval]
700\defineconversion [o]                    [\oldstylenumerals]
701\defineconversion [O]                    [\oldstylenumerals]
702\defineconversion [or]                   [\oldstyleromannumerals]
703
704\defineconversion [\v!romannumerals]     [\romannumerals]
705\defineconversion [\v!Romannumerals]     [\Romannumerals]
706
707\defineconversion [i]                    [\romannumerals]
708\defineconversion [I]                    [\Romannumerals]
709\defineconversion [r]                    [\romannumerals]
710\defineconversion [R]                    [\Romannumerals]
711
712\defineconversion [KR]                   [\smallcappedromannumerals]
713\defineconversion [RK]                   [\smallcappedromannumerals]
714
715\defineconversion [\v!greek]             [\greeknumerals]
716\defineconversion [\v!Greek]             [\Greeknumerals]
717
718\defineconversion [\s!math:\v!greek]     [\mathgreeknumerals]
719\defineconversion [\s!math:\v!Greek]     [\mathGreeknumerals]
720
721\defineconversion [g]                    [\greeknumerals]
722\defineconversion [G]                    [\Greeknumerals]
723
724%defineconversion [ñ]                    [\spanishnumerals]
725%defineconversion [Ñ]                    [\Spanishnumerals]
726
727\defineconversion [abjadnumerals]        [\abjadnumerals]
728\defineconversion [abjadnodotnumerals]   [\abjadnodotnumerals]
729\defineconversion [abjadnaivenumerals]   [\abjadnaivenumerals]
730
731\defineconversion [hebrewnumerals]       [\hebrewnumerals]
732\defineconversion [yiddishnumerals]      [\yiddishnumerals]
733
734% users can do: \defineconversion [he] [\hebrewnumerals]
735% users can do: \defineconversion [yi] [\hebrewnumerals]
736
737\defineconversion [thainumerals]         [\thainumerals]
738\defineconversion [devanagarinumerals]   [\devanagarinumerals]
739\defineconversion [malayalamnumerals]    [\malayalamnumerals]
740\defineconversion [tamilnumerals]        [\tamilnumerals]
741\defineconversion [kannadanumerals]      [\kannadanumerals]
742\defineconversion [telugunumerals]       [\telugunumerals]
743\defineconversion [bengalinumerals]      [\bengalinumerals]
744\defineconversion [gurmurkhinumerals]    [\gurmurkhinumerals]
745\defineconversion [gujaratinumerals]     [\gujaratinumerals]
746\defineconversion [tibetannumerals]      [\tibetannumerals]
747\defineconversion [greeknumerals]        [\greeknumerals]
748\defineconversion [Greeknumerals]        [\Greeknumerals]
749\defineconversion [arabicnumerals]       [\arabicnumerals]
750\defineconversion [persiannumerals]      [\persiannumerals]
751\defineconversion [arabicexnumerals]     [\arabicexnumerals]
752\defineconversion [arabicdecimals]       [\arabicdecimals]
753\defineconversion [persiandecimals]      [\persiandecimals]
754
755\defineconversion [mathgreeknumerals]    [\mathgreeknumerals]
756\defineconversion [mathGreeknumerals]    [\mathGreeknumerals]
757
758\defineconversion [koreannumerals]       [\koreannumerals]
759\defineconversion [koreanparennumerals]  [\koreanparenthesisnumerals] % for old times sake (for a while)
760\defineconversion [koreanparenthesisnumerals]
761                                         [\koreanparenthesisnumerals]
762\defineconversion [koreancirclenumerals] [\koreancirclenumerals]
763
764\defineconversion [kr]                   [\koreannumerals]
765\defineconversion [kr-p]                 [\koreanparentnumerals]
766\defineconversion [kr-c]                 [\koreancirclenumerals]
767
768\defineconversion [chinesenumerals]      [\chinesenumerals]
769\defineconversion [chinesecapnumerals]   [\chinesecapnumerals]
770\defineconversion [chineseallnumerals]   [\chineseallnumerals]
771\defineconversion [chinesedatenumerals]  [\chinesedatenumerals]
772
773\defineconversion [cn]                   [\chinesenumerals]
774\defineconversion [cn-c]                 [\chinesecapnumerals]
775\defineconversion [cn-a]                 [\chineseallnumerals]
776\defineconversion [cn-d]                 [\chinesedatenumerals]
777
778%D Moved from lang-def.mkiv:
779%D
780%D Define these as the general character enumeration when language is Slovenian. If
781%D you feel uncomfortable with this, mail Mojca, since she promised to to take the
782%D heat. Pablo was next to request this. We changed characters to numerals for this
783%D feature. We do need these definitions for mechanisms like itemize that check
784%D for converters.
785
786\permanent\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}}
787\permanent\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}}
788
789\permanent\def\spanishnumerals  #1{\clf_alphabetic\numexpr#1\relax{es}}
790\permanent\def\spanishNumerals  #1{\clf_Alphabetic\numexpr#1\relax{es}}
791
792\permanent\def\russiannumerals  #1{\clf_alphabetic\numexpr#1\relax{ru}}
793\permanent\def\russianNumerals  #1{\clf_Alphabetic\numexpr#1\relax{ru}}
794
795%defineconversion [\s!sl] [character]  [\sloveniannumerals]
796%defineconversion [\s!sl] [Character]  [\slovenianNumerals]
797%defineconversion [\s!sl] [characters] [\sloveniannumerals]
798%defineconversion [\s!sl] [Characters] [\slovenianNumerals]
799
800\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals]
801\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals]
802
803\defineconversion [\s!sl] [a]          [\sloveniannumerals]
804\defineconversion [\s!sl] [A]          [\slovenianNumerals]
805\defineconversion [\s!sl] [AK]         [\smallcapped\sloveniannumerals]
806\defineconversion [\s!sl] [KA]         [\smallcapped\sloveniannumerals]
807
808%defineconversion [\s!es] [character]  [\spanishnumerals]
809%defineconversion [\s!es] [Character]  [\spanishNumerals]
810%defineconversion [\s!es] [characters] [\spanishnumerals]
811%defineconversion [\s!es] [Characters] [\spanishNumerals]
812
813\defineconversion [\s!es] [alphabetic] [\spanishnumerals]
814\defineconversion [\s!es] [Alphabetic] [\spanishNumerals]
815
816\defineconversion [\s!es] [a]          [\spanishnumerals]
817\defineconversion [\s!es] [A]          [\spanishNumerals]
818\defineconversion [\s!es] [AK]         [\smallcapped\spanishnumerals]
819\defineconversion [\s!es] [KA]         [\smallcapped\spanishnumerals]
820
821%defineconversion [\s!ru] [character]  [\russiannumerals]
822%defineconversion [\s!ru] [Character]  [\russianNumerals]
823%defineconversion [\s!ru] [characters] [\russiannumerals]
824%defineconversion [\s!ru] [Characters] [\russianNumerals]
825
826\defineconversion [\s!ru] [alphabetic] [\russiannumerals]
827\defineconversion [\s!ru] [Alphabetic] [\russianNumerals]
828
829\defineconversion [\s!ru] [a]          [\russiannumerals]
830\defineconversion [\s!ru] [A]          [\russianNumerals]
831\defineconversion [\s!ru] [AK]         [\smallcapped\russiannumerals]
832\defineconversion [\s!ru] [KA]         [\smallcapped\russiannumerals]
833
834\defineconversion [sloveniannumerals]  [\sloveniannumerals]
835\defineconversion [slovenianNumerals]  [\slovenianNumerals]
836
837\defineconversion [spanishnumerals]    [\spanishnumerals]
838\defineconversion [spanishNumerals]    [\spanishNumerals]
839
840\defineconversion [russiannumerals]    [\russiannumerals]
841\defineconversion [russianNumerals]    [\russianNumerals]
842
843%D In case a font has no greek (WS):
844
845\defineconversion [mathgreek]
846  [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ},
847   \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ},
848   \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ},
849   \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}]
850
851%D Handy too (expanded!):
852
853\permanent\def\unihex#1{\clf_unihex\numexpr#1\relax}
854
855%D Symbol sets:
856
857\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo
858
859% \defineconversion
860%   [set 0]
861%   [{\symbol[bullet]},
862%    {\symbol[dash]},
863%    {\symbol[star]},
864%    {\symbol[triangle]},
865%    {\symbol[circle]},
866%    {\symbol[medcircle]},
867%    {\symbol[bigcircle]},
868%    {\symbol[square]},
869%    {\symbol[checkmark]}]
870
871% \defineconversion
872%   [set 1]
873%   [\mathematics{\star},
874%    \mathematics{\star\star},
875%    \mathematics{\star\star\star},
876%    \mathematics{\ddagger},
877%    \mathematics{\ddagger\ddagger},
878%    \mathematics{\ddagger\ddagger\ddagger},
879%    \mathematics{\ast},
880%    \mathematics{\ast\ast},
881%    \mathematics{\ast\ast\ast}]
882%
883% \defineconversion
884%   [set 2]
885%   [\mathematics{\ast},
886%    \mathematics{\dag},
887%    \mathematics{\ddag},
888%    \mathematics{\ast\ast},
889%    \mathematics{\dag\dag},
890%    \mathematics{\ddag\ddag},
891%    \mathematics{\ast\ast\ast},
892%    \mathematics{\dag\dag\dag},
893%    \mathematics{\ddag\ddag\ddag},
894%    \mathematics{\ast\ast\ast\ast},
895%    \mathematics{\dag\dag\dag\dag},
896%    \mathematics{\ddag\ddag\ddag\ddag}]
897%
898% \defineconversion
899%   [set 3]
900%   [\mathematics{\star},
901%    \mathematics{\star\star},
902%    \mathematics{\star\star\star},
903%    \mathematics{\ddagger},
904%    \mathematics{\ddagger\ddagger},
905%    \mathematics{\ddagger\ddagger\ddagger},
906%    \mathematics{\P},
907%    \mathematics{\P\P},
908%    \mathematics{\P\P\P},
909%    \mathematics{\S},
910%    \mathematics{\S\S},
911%    \mathematics{\S\S\S},
912%    \mathematics{\ast},
913%    \mathematics{\ast\ast},
914%    \mathematics{\ast\ast\ast}]
915
916\defineconversion
917  [set 0]
918  [\symbol{bullet},
919   \symbol{dash},
920   \symbol{star},
921   \symbol{triangle},
922   \symbol{circle},
923   \symbol{medcircle},
924   \symbol{bigcircle},
925   \symbol{square},
926   \symbol{checkmark}]
927
928\defineconversion
929  [set 1]
930  [\textormathchars{},
931   \textormathchars{⋆⋆},
932   \textormathchars{⋆⋆⋆},
933   \textormathchars{},
934   \textormathchars{‡‡},
935   \textormathchars{‡‡‡},
936   \textormathchars{},
937   \textormathchars{∗∗},
938   \textormathchars{∗∗∗}]
939
940\defineconversion
941  [set 2]
942  [\textormathchars{},
943   \textormathchars{},
944   \textormathchars{},
945   \textormathchars{∗∗},
946   \textormathchars{††},
947   \textormathchars{‡‡},
948   \textormathchars{∗∗∗},
949   \textormathchars{†††},
950   \textormathchars{‡‡‡},
951   \textormathchars{∗∗∗∗},
952   \textormathchars{††††},
953   \textormathchars{‡‡‡‡}]
954
955\defineconversion
956  [set 3]
957  [\textormathchars{},
958   \textormathchars{⋆⋆},
959   \textormathchars{⋆⋆⋆},
960   \textormathchars{},
961   \textormathchars{‡‡},
962   \textormathchars{‡‡‡},
963   \textormathchars{},
964   \textormathchars{¶¶},
965   \textormathchars{¶¶¶},
966   \textormathchars{§},
967   \textormathchars{§§},
968   \textormathchars{§§§},
969   \textormathchars{},
970   \textormathchars{∗∗},
971   \textormathchars{∗∗∗}]
972
973%D Iteration of suggestion by WS on mailinglist 2010.12.22:
974%D
975%D \starttyping
976%D \setupfloatsplitting[conversion=continued]
977%D \stoptyping
978
979\permanent\protected\def\continuednumber#1%
980  {\labeltext{\ifcase#1\or\else\v!continued\fi}}
981
982\defineconversion
983  [\v!continued]
984  [\continuednumber]
985
986%D Taken from x-asciimath (see digits-001.tex for an example):
987
988\mutable\lettonothing\spaceddigitsmethod    % alternative methods   : 1 default, 2 and 3 only when > 4
989\mutable\lettonothing\spaceddigitssymbol    % extra splitter symbol : {,}
990\mutable\lettonothing\spaceddigitsseparator % separator symbol      : {\tocharacter{"2008}}
991
992\permanent\protected\def\spaceddigits#1%
993  {\clf_spaceddigits
994      method    {\spaceddigitsmethod}%
995      symbol    {\spaceddigitssymbol}%
996      separator {\spaceddigitsseparator}%
997      data      {#1}%
998   \relax}
999
1000%D For those who sart counting at zero:
1001%D
1002%D \starttyping
1003%D \defineconversionset [zero] [n,zero] [n]
1004%D
1005%D \setuphead [sectionconversionset=zero]
1006%D
1007%D \starttext
1008%D     \startchapter [title=Introduction]
1009%D         \startsection [title=First topic]  \stopsection
1010%D         \startsection [title=Second topic] \stopsection
1011%D     \stopchapter
1012%D \stoptext
1013%D \stoptyping
1014
1015\permanent\def\zeronumberconversion#1{\the\numexpr#1-\plusone\relax}
1016
1017\defineconversion [zero] [\zeronumberconversion]
1018
1019\protect \endinput
1020