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