strc-not.mklx /size: 74 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=strc-not,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Structure Macros,
5%D       subtitle=Note Handling,
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 Structure Macros / Note Handling}
15
16\registerctxluafile{strc-not}{autosuffix}
17
18\unprotect
19
20% todo: finish local rendering
21% todo: more p_strc_notations_* (outside trial loop)
22% todo: see if we can now use \insertpenalties (>0 == some left)
23
24\ifdefined\dotagsetnotesymbol \else \aliased\let\dotagsetnotesymbol\relax \fi
25\ifdefined\dotagsetnotation   \else \aliased\let\dotagsetnotation  \relax \fi
26
27%D \LMTX\ testcase:
28%D
29%D \starttyping
30%D \hbox {\hbox{\footnote{HH1}\footnote{HH2}}} \par
31%D \hbox {\hbox{x\footnote{XHH1}x\footnote{XHH2}}} \par
32%D \vbox {\setbox0\hbox{\footnote{VH1}\footnote{VH2}}\box0} \par
33%D \vbox         {\hbox{\footnote{VH1}xxx\footnote{VH2}}} \par
34%D \vbox         {\hbox{\footnote{VH1}\footnote{VH2}}
35%D                \hbox{\footnote{VH1}\footnote{VH2}}} \par
36%D \vbox {\hbox{x\footnote{XVH1}x\footnote{XVH2}}} \par
37%D \vbox {\vbox{\footnote{VV1}\footnote{VV2}}} \par % two lines
38%D \vbox {\vbox{x\footnote{XVV1}x\footnote{XVV2}}} \par
39%D \stoptyping
40
41%D Notes have two handlers: notations and notes. Although notations can be defined
42%D independently it makes not much sense. In principle we can treat notes as lists
43%D but they are currently done as a variant on enumerations. I will provide a list
44%D variant as well. One complication is that for page related notes inserts are used
45%D and therefore notes are typeset immediately and descriptions are better suited
46%D for that. For instance endnotes can as well be typeset using lists.
47
48% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number
49
50%D \macros
51%D   {setupnote,setupnotation}
52%D
53%D We can influence footnote typesetting with the setup command:
54%D
55%D \showsetup{setupnotation}
56%D \showsetup{setupnote}
57%D
58%D The definition command indicate that we can frame the footnote area. The
59%D footnotes themselves are treated as descriptions.
60%D
61%D \showsetup{definenote}
62%D
63%D It's sort of a custom to precede footnotes by a horizontal rule and although
64%D fancy rules like
65%D
66%D \starttyping
67%D \hbox to 10em{\hskip-3em\dotfill}
68%D \stoptyping
69%D
70%D Are quite ligitimate, we default to a simple one 20\% of the text width.
71
72%    \c!headstyle=\noteparameter\c!style,
73%    \c!headcolor=\noteparameter\c!color,
74
75\installcorenamespace{notation}
76
77\installcommandhandler \??notation {notation} \??notation
78
79\installcounterassociation{notation}
80
81\aliased\let\setupnotations\setupnotation
82
83\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}]
84\definesymbol[\v!note:\v!nextpage    ][\llap{\low{\symbol[\v!nextpage    ]}}]
85
86\setupnotations % check with old
87  [\c!alternative=\v!note,
88  %\c!headstyle=,
89  %\c!titlestyle=,
90  %\c!style=,
91  %\c!color=,
92  %\c!headcolor=,
93  %\c!titlecolor=,
94   \c!numbercommand=\high,
95  %\c!symbolcommand=\lowllap, % experiment
96  %\c!indicator=\v!no, % was \v!yes in mkii for page notes
97   \c!width=\v!fit,
98   \c!titledistance=.5em,
99   \c!distance=.5em,
100  %\c!hang=,
101  %\c!sample=,
102  %\c!align=,
103  %\c!headalign=,
104   \c!margin=\v!no,
105   \c!before=,
106   \c!inbetween=,
107   \c!after=,
108   \c!indentnext=\v!yes,
109   \c!indenting=\v!never,
110   \c!titleleft=(,
111   \c!titleright=),
112  %\c!closesymbol=,
113   \c!closecommand=\wordright,
114   \c!display=\v!yes,
115  %\c!command=,
116   \c!titlecommand=,
117   \c!expansion=\v!no,
118  %\c!xmlsetup=,
119  %\s!catcodes=,
120   \c!way=\v!by\v!text,
121   \c!prefix=\v!no,
122   \c!prefixconnector=.,
123  %\c!starter=,
124  %\c!stopper=,
125   \c!number=\v!yes,
126   \c!text=,
127   \c!start=0,
128   \c!state=\v!start,
129   \c!levels=3]
130
131%D The code here is mostly the same as enumerations but we want to keep them
132%D isolated and at some point we might differentiate.
133
134% \installcorenamespace{noteclass}
135
136\protected\def\strc_define_commands_notation#tag#level#parent%
137  {\ifempty{#parent}%
138     \normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}%
139     \edefcsname\??notation#tag:\s!parent\endcsname{\??notation}%
140   \else
141     \normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}%
142     \edefcsname\??note    #tag:\s!parent\endcsname{\??note#parent}% see later for \s!note
143     \edefcsname\??notation#tag:\s!parent\endcsname{\??notation#parent}%
144   \fi
145   \instance\protected\edefcsname\e!next #tag\endcsname{\strc_notations_next{#tag}{\number#level}}% obsolete
146   \instance\protected\edefcsname\c!reset#tag\endcsname{\strc_notations_reset{#tag}{\number#level}}% obsolete
147   \instance\protected\edefcsname        #tag\endcsname{\strc_notations_command[#tag]}%
148   \instance\protected\edefcsname\e!start#tag\endcsname{\strc_notations_start[#tag]}%
149   \instance\protected\edefcsname\e!stop #tag\endcsname{\strc_notations_stop}}
150
151\lettonothing\m_strc_notation_sub
152
153\appendtoks
154    \lettonothing\m_strc_notation_sub
155    \ifempty\currentnotationparent
156       % clone => parent | subclone => clone | subsubclone => subclone
157       \strc_define_commands_notation
158         {\m_strc_notation_sub\currentnotation}%
159         \plusone
160         \empty
161       \edef\p_levels{\notationparameter\c!levels}%
162       \dostepwiserecurse\plustwo\p_levels\plusone
163         {\strc_define_commands_notation
164            {\v!sub\m_strc_notation_sub\currentnotation}%
165            \recurselevel
166            {\m_strc_notation_sub\currentnotation}%
167          \edef\m_strc_notation_sub{\v!sub\m_strc_notation_sub}}%
168        \definelist[\currentnotation]% goodie
169   \else
170       % clone => parent | subclone => subparent | subsubclone => subsubparent
171       \edef\p_levels{\notationparameter\c!levels}%
172       \dorecurse\p_levels
173         {\strc_define_commands_notation
174            {\m_strc_notation_sub\currentnotation}%
175            \recurselevel
176            {\m_strc_notation_sub\currentnotationparent}%
177          \edef\m_strc_notation_sub{\v!sub\m_strc_notation_sub}}%
178        \definelist[\currentnotation][\currentnotationparent]% goodie
179   \fi
180   \edef\p_counter{\notationparameter\s!counter}% can inherit from parent
181   \ifempty\p_counter
182       \let\p_counter\currentnotation
183   \fi
184   \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}%
185   \letnotationparameter\s!counter\p_counter
186  %\strc_notes_setup_counter\currentnotation
187\to \everydefinenotation
188
189\lettonothing\p_strc_constructions_title
190\lettonothing\p_strc_constructions_number
191
192\protected\defcsname\??constructioninitializer\v!notation\endcsname
193  {\let         \currentnotation                 \currentconstruction
194   \enforced\let\constructionparameter           \notationparameter
195   \enforced\let\constructionnamespace           \??notation
196   \enforced\let\detokenizedconstructionparameter\detokenizednotationparameter
197   \enforced\let\letconstructionparameter        \letnotationparameter
198   \enforced\let\useconstructionstyleandcolor    \usenotationstyleandcolor
199   \enforced\let\setupcurrentconstruction        \setupcurrentnotation
200   \edef\p_strc_constructions_number{\constructionparameter\c!number}%
201   \ifx\p_strc_constructions_number\v!yes
202     \c_strc_constructions_number_state\conditionaltrue
203     \iftrialtypesetting
204       \strc_counters_save\currentconstructionnumber
205     \fi
206    %\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
207   \else
208     \c_strc_constructions_number_state\conditionalfalse
209   \fi
210   \edef\p_strc_constructions_title{\constructionparameter\c!title}%
211   \ifx\p_strc_constructions_title\v!yes
212     \c_strc_constructions_title_state\conditionaltrue
213   \else
214     \c_strc_constructions_title_state\conditionalfalse
215   \fi}
216
217\protected\defcsname\??constructionfinalizer\v!notation\endcsname
218  {\ifconditional\c_strc_constructions_number_state
219     \iftrialtypesetting
220       \strc_counters_restore\currentconstructionnumber
221     \fi
222   \fi}
223
224%D Notations (we simply needed a word that relates to notes and is and sounds like
225%D description and enumeration) are a special case in the sense that they are
226%D stored, rendered elsewhere and referered to from where they are specified. For
227%D that reason they have a different set op main commands.
228
229% \notation[ref]{title}
230% \notation[reference=,title=]
231% \startnotation[ref] title \stopnotation
232
233\protected\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2
234\protected\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2
235%protected\def\strc_notations_set  {\strc_constructions_set_indeed  \namednotationparameter} % #1#2
236
237\newconditional\c_strc_notations_anchored_next
238
239\def\strc_notations_finalize
240  {\ifconditional\c_strc_notations_anchored_next
241     \expandafter\strc_notations_finalize_next
242   \else
243     \expandafter\strc_notations_finalize_previous
244   \fi}
245
246\def\strc_notations_finalize_previous
247  {\normalexpanded{\endgroup\noteparameter\c!next}}
248
249\def\strc_notations_finalize_next
250  {\endgroup\ignorespaces}
251
252\tolerant\protected\def\strc_notations_command[#1]#*[#S#2]%
253  {\begingroup
254   \cdef\currentnote{#1}%
255   \strc_constructions_initialize{#1}%
256   \strc_notes_synchronize
257   \edef\p_next{\noteparameter\c!anchor}%
258   \ifx\p_next\v!next % for now only two states
259     \c_strc_notations_anchored_next\conditionaltrue
260   \else
261     \c_strc_notations_anchored_next\conditionalfalse
262   \fi
263   \ifnotesenabled
264     \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
265   \fi
266   \ifhastok={#2}%
267     \expandafter\strc_notations_command_setups
268   \else
269     \expandafter\strc_notations_command_reference
270   \fi[#2]}
271
272\def\strc_notations_command_setups[#S#1]%
273  {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,\c!referencetext=,#1]%
274   \strc_notations_wrapup}
275
276\tolerant\def\strc_notations_command_reference[#1]#*#=%
277  {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=,\c!referencetext=]%
278   \strc_notations_wrapup}
279
280\def\strc_notations_wrapup
281  {\csname\??constructionnotehandler\currentconstructionhandler\endcsname
282   \strc_constructions_finalize
283   \strc_notations_finalize}
284
285\tolerant\protected\def\strc_notations_start
286  {\strc_notations_start_indeed{\csname\e!stop\currentnotation\endcsname}}
287
288\tolerant\protected\defcsname\e!start\e!namednotation\endcsname
289  {\strc_notations_start_indeed{\csname\e!stop\e!namednotation\endcsname}}
290
291\ifdefined\startnamednotation
292    % we're in the english interface
293\else
294    \tolerant\protected\def\startnamednotation
295      {\strc_notations_start_indeed\stopnamednotation}
296\fi
297
298\tolerant\protected\def\strc_notations_start_indeed#1#*[#2]#*[#S#3]%
299  {\begingroup
300   \cdef\currentnote{#2}%
301   \strc_constructions_initialize{#2}%
302   \strc_notes_synchronize
303   \ifnotesenabled
304     \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
305   \fi
306   \ifhastok={#3}%
307     \expandafter\strc_notations_start_setups
308   \else
309     \expandafter\strc_notations_start_reference
310   \fi#1[#3]}
311
312\let\strc_notations_pickup_yes\relax
313
314\protected\def\strc_notations_start_setups#1[#S#2]%
315  {\normalexpanded{\def\noexpand\strc_notations_pickup_yes##/#1{\strc_notations_start_setups_indeed[#2]{##1}}}%
316   \strc_notations_pickup_yes}
317
318\protected\def\strc_notations_start_setups_indeed[#S#1]#*#2%
319  {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#2},\c!bookmark=,\c!list=,\c!referencetext=,#1]%
320   \strc_notations_wrapup}
321
322\protected\def\strc_notations_start_reference#1[#S#2]%
323  {\normalexpanded{\def\noexpand\strc_notations_pickup_yes##/#1{\strc_notations_start_reference_indeed[#2]{##1}}}%
324   \strc_notations_pickup_yes}
325
326\protected\def\strc_notations_start_reference_indeed[#1]#*#2%
327  {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=,\c!referencetext=]%
328   \strc_notations_wrapup}
329
330\protected\def\strc_notations_stop
331  {}
332
333%D A complication is that we need to set up rather specific properties of e.g.
334%D footnotes. It is for this reason that we introduce an extra level of
335%D indirectness. This way notations don't bark on undefined macros when used in
336%D combination.
337
338\protected\defcsname\??constructionnotehandler\v!notation\endcsname
339  {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname}
340
341\protected\defcsname\??constructionnotehandler\v!notation:\endcsname % empty case
342  {[\currentconstructionhandler:\currentconstruction]}
343
344%D Here is a simple renderer for notes
345
346\defineconstructionalternative
347  [\v!note]
348  [\c!renderingsetup=\??constructionrenderings:\v!note]
349
350\startsetups[\??constructionrenderings:\v!note]
351    \noindent
352    \leftboundary % experiment, to be done in more places
353    \llap{\box\constructionheadbox\kern{\constructionparameter\c!distance}}%
354    \useconstructionstyleandcolor\c!style\c!color
355    \ignorespaces
356\stopsetups
357
358%D We now implement the note definer.
359
360\installcorenamespace{note}
361
362\installframedcommandhandler \??note {note} \??note
363
364\let\setupnotes\setupnote
365
366% These only concern the inline symbol/number and wrapping of the whole list.
367
368\setupnotes % not all make sense here
369  [\c!location=\v!page,
370  %\c!conversion=,
371   \c!rule=\v!on,
372   \c!before=\blank,
373   \c!bodyfont=\v!small,
374   \c!anchor=, % can also be v!next
375  %\c!style=,
376  %\c!color=,
377  %\c!after=,
378  %\c!rulecolor=,
379  %\c!rulecommand=,
380   \c!rulethickness=\linewidth,
381   \c!frame=\v!off,
382   \c!distance=.125em, % in the text between symbols
383 % \c!textseparator={,}, % optional separator
384   \c!columndistance=1em,
385 % \c!margindistance=.5em,
386   \c!align=, % also use instead of \c!tolerance
387   \c!split=\v!tolerant,
388   \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi
389   \c!height=\textheight,
390   \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice
391   \c!separator=,%
392   \c!textcommand=\high,
393   \c!textstyle=\tx,
394  %\c!textcolor=,
395   \c!interaction=\v!yes,
396  %\c!factor=,
397  %\c!scope=, % \v!text \v!page
398   \c!prefixconnector=.,
399  %\c!next=\autoinsertnextspace,
400   \c!prefix=\v!no,
401  %\c!continue=\v!no,
402   \c!paragraph=\v!no,
403   \c!inbetween=\hskip\emwidth,
404   \c!symbol=\mathematics{*},
405   \c!n=1]
406
407\setupnotes
408  [\c!expansion=\v!no,
409   \c!xmlsetup=,
410   \s!catcodes=]
411
412%D Insertions are part of notes.
413
414% \installcorenamespace{noteinsertion}
415
416\permanent\def\currentnoteinsertion      {\noteparameter\s!insert}
417\permanent\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}}
418
419\appendtoks
420    \ifempty\currentnoteparent
421        \doifelseinsertion\currentnote
422          \donothing
423          {\defineinsertion[\currentnote]% could be an option
424           \xtoksapp\t_strc_notes{\noexpand\strc_notes_process_list{\currentnote}}}%
425        \letnoteparameter\s!insert\currentnote
426        \definenotation[\currentnote][\c!type=\v!note]%
427    \else
428        \setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}%
429        \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
430    \fi
431    \clf_definenote
432      {\currentnote}%
433      {insert}%
434      \currentnoteinsertionnumber
435    \relax
436\to \everydefinenote
437
438% maybe we will share this at some point:
439
440\def\strc_notes_define_counter#tag% todo: move inline
441  {\definecounter[#tag]%
442   \registerenumerationcounter{#tag}}
443
444\appendtoks
445    \synchronizenotationcounters
446\to \everysetupnotation
447
448\appendtoks
449    \synchronizenotationcounters
450\to \everydefinenotation
451
452% so far
453
454%letcsname\??constructionstarthandler  \v!notation\expandafter\endcsname\csname\??constructionstarthandler  \v!enumeration\endcsname
455\letcsname\??constructionstarthandler  \v!notation\expandafter\endcsname\csname\??constructionstarthandler  \v!construction\endcsname % no par mess
456\letcsname\??constructionstophandler   \v!notation\expandafter\endcsname\csname\??constructionstophandler   \v!enumeration \endcsname
457\letcsname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname
458\letcsname\??constructiontexthandler   \v!notation\expandafter\endcsname\csname\??constructiontexthandler   \v!enumeration \endcsname
459
460\protected\defcsname\??constructionmainhandler\v!notation\endcsname#following%
461  {\iftrialtypesetting \else
462     \begingroup
463     \currentconstructionsynchronize
464     \c_attr_destination\currentconstructionattribute\relax % todo, whole text
465     \signalcharacter
466     \endgroup
467   \fi
468   \ifconditional\c_strc_notes_flushed\else
469     #following\relax
470   \fi}
471
472\newmarks\c_strc_notes_insert_mark
473
474\protected\defcsname\??constructionnotehandler\v!notation:\v!note\endcsname % in the running text
475  {\ifnotesenabled
476     % do be done elsewhere
477     %
478     %let\currentnote\currentconstructionmain
479     \let\currentnote\currentconstruction % else wrong inheritance
480     %
481     \iftrialtypesetting
482        \strc_notes_inject_dummy
483     \else
484       \begingroup
485       \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}%
486       \processingnote\conditionaltrue
487       \ifconditional\c_strc_notes_skip
488         \glet\lastnotesymbol\strc_notes_inject_symbol_nop
489       \else
490         \iftypesettinglines % otherwise problems with \type <crlf> {xxx}
491           \ignorelines % makes footnotes work in \startlines ... \stoplines
492         \fi
493         \ifconditional\c_strc_notes_symbol
494           \strc_notes_inject_symbol_yes
495         \else
496           \unskip\unskip
497           \glet\lastnotesymbol\strc_notes_inject_symbol_yes
498         \fi
499       \fi
500       \ifconditional\postponingnotes % todo: per note class
501         \global\postponednote\conditionaltrue
502       \orelse\ifconditional\inlocalnotes % todo: per note class
503         \global\postponednote\conditionaltrue
504       \orelse\ifconditional\c_strc_notes_flushed
505         \handlenoteitself\currentnote\currentnotenumber
506       \orelse\ifconditional\c_strc_notes_delayed
507         % probably end notes
508       \else
509         \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed
510       \fi
511       \endgroup
512     \fi
513   \fi
514   %
515   \ifcstok{\noteparameter\c!range}\v!yes
516     \normalexpanded{\marks\c_strc_notes_insert_mark{\the\c_strc_notes_n}}%
517   \fi
518   %
519   \ifconditional\c_strc_notes_skip
520     \global\c_strc_notes_skip\conditionalfalse
521   \else
522     \boundary\noteboundary
523   \fi}
524
525%D New, for columnsets:
526
527\permanent\protected\def\flushnoterange[#1]%
528  {\begingroup
529   \cdef\currentnote{#1}%
530  %\clf_flushnoterange
531  %   \numexpr\currentnoteinsertionnumber\relax
532  %   \numexpr\firstmarks\c_strc_notes_insert_mark\relax
533  %   \numexpr\botmarks\c_strc_notes_insert_mark\relax
534  %\relax
535   \clf_flushnoterange
536      {\currentnoteinsertionnumber}%
537      \c_strc_notes_insert_mark
538   \relax
539   \endgroup}
540
541%D Interaction in notes is somewhat complex due to the way notes get flushed. In
542%D principle it is more or less the same as lists but where in lists we pack whole
543%D entries, in notes this doesn't happen. Okay, in retrospect we could have made
544%D descriptions lists but that will be a backward compatibility mess. At some point
545%D a completely new mechanism might show up, but not now. Also, as notes are inserts
546%D there is some extra mess to be kept in mind and it's easier to maintain two
547%D mechanisms than to combine too much.
548%D
549%D Interaction is also complicated because we want to provide several variants. For
550%D simple reference there is no need for anything special, as page references will
551%D do and we store them in the list anyway. But if we want a destination with
552%D dimensions we will use an additional destination because we can have only one
553%D with the same name and we always have the number as one.
554
555% interaction:
556%
557% all       : text and number
558% number|yes: only number
559% text      : only text
560%
561% \dogetsimple : injects
562
563\installcorenamespace{noteinteractioninline}
564\installcorenamespace{noteinteractiondisplay}
565
566\newconstant\a_strc_notes_symbol_reference
567\newconstant\a_strc_notes_number_reference
568\newconstant\a_strc_notes_text_reference
569\newconstant\a_strc_notes_text_destination
570
571\lettonothing\strc_notes_get_reference_attribute_symbol
572\lettonothing\strc_notes_get_destination_attribute_symbol
573
574\def\strc_notes_interaction_check_inline
575  {\edef\p_interaction{\noteparameter\c!interaction}%
576   \csname\??noteinteractioninline
577     \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi
578   \endcsname}
579
580\def\strc_notes_interaction_check_display
581  {\edef\p_interaction{\noteparameter\c!interaction}%
582   \csname\??noteinteractiondisplay
583     \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi
584   \endcsname}
585
586\mutable\let\currentnotenumber\!!zerocount
587
588\lettonothing\strc_notes_get_reference_attribute_symbol
589\lettonothing\strc_notes_get_destination_attribute_symbol
590
591\let\strc_notes_set_reference_attribute_number\donothing
592\let\strc_notes_set_reference_attribute_text  \donothing
593\let\strc_notes_set_destination_attribute_text\donothing
594
595\let\strc_notes_set_style_color_inline \relax
596\let\strc_notes_set_style_color_display\relax
597
598% inline
599
600\let\m_strc_notes_internal\relax
601
602\def\strc_notes_prepare_inline_references_nop
603  {\lettonothing\strc_notes_get_reference_attribute_symbol
604   \lettonothing\strc_notes_get_destination_attribute_symbol
605   \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop}
606
607\def\strc_notes_prepare_inline_references_yes
608  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
609   \strc_references_set_simple_reference{*\m_strc_notes_internal}% destination
610   \strc_references_get_simple_reference{internal(\m_strc_notes_internal)}% reference
611   \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
612   \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
613   \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
614
615\letcsname\??noteinteractioninline\v!no    \endcsname\strc_notes_prepare_inline_references_nop
616\letcsname\??noteinteractioninline\v!all   \endcsname\strc_notes_prepare_inline_references_yes
617\letcsname\??noteinteractioninline\v!number\endcsname\strc_notes_prepare_inline_references_yes
618\letcsname\??noteinteractioninline\v!text  \endcsname\strc_notes_prepare_inline_references_yes
619\letcsname\??noteinteractioninline\v!yes   \endcsname\strc_notes_prepare_inline_references_yes
620
621% display (for 'all' we need unique text and number attributes so we resolve twice
622% as we otherwise don't get the number one which is lapped in the margin so we need
623% to explicitly visit it)
624
625\def\strc_notes_prepare_display_references_nop
626  {\let\strc_notes_set_reference_attribute_number\donothing
627   \let\strc_notes_set_reference_attribute_text\donothing
628   \let\strc_notes_set_destination_attribute_text\donothing
629   \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop}
630
631\def\strc_notes_prepare_display_references_yes_number
632  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
633   \ifcase\m_strc_notes_internal\relax
634     \strc_notes_prepare_display_references_nop
635   \else
636     \let\strc_notes_set_reference_attribute_text\donothing
637     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
638     \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}%
639     \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
640   \fi}
641
642\def\strc_notes_prepare_display_references_yes_text
643  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
644   \ifcase\m_strc_notes_internal\relax
645     \strc_notes_prepare_display_references_nop
646   \else
647     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
648     \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
649     \let\strc_notes_set_reference_attribute_number\donothing
650     \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
651   \fi}
652
653\def\strc_notes_prepare_display_references_yes_all
654  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
655   \ifcase\m_strc_notes_internal\relax
656     \strc_notes_prepare_display_references_nop
657   \else
658     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
659     \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
660     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
661     \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}%
662     \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
663   \fi}
664
665\letcsname\??noteinteractiondisplay\v!no    \endcsname\strc_notes_prepare_display_references_nop
666\letcsname\??noteinteractiondisplay\v!all   \endcsname\strc_notes_prepare_display_references_yes_all
667\letcsname\??noteinteractiondisplay\v!number\endcsname\strc_notes_prepare_display_references_yes_number
668\letcsname\??noteinteractiondisplay\v!text  \endcsname\strc_notes_prepare_display_references_yes_text
669\letcsname\??noteinteractiondisplay\v!yes   \endcsname\strc_notes_prepare_display_references_yes_number
670
671\mutable\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor
672\mutable\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor
673
674\protected\def\strc_notes_set_style_color_inline_yes#style#color%
675  {\usenotestyleandcolor#style#color%
676   \iflocation\strc_notes_set_style_color_special\fi}
677
678\protected\def\strc_notes_set_style_color_display_yes#style#color%
679  {\usenotationstyleandcolor#style#color%
680   \iflocation\strc_notes_set_style_color_special\fi}
681
682\def\strc_notes_set_style_color_special
683  {\iftrialtypesetting
684      % keep
685   \orelse\ifempty\currentcolorparameter
686     \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once
687     \setlocationcolorspecified\scratchcounter
688   \fi}
689
690\defcsname\??constructiontexthandler\v!notation\endcsname
691  {\begingroup
692   % we need to retrigger the reference as otherwise it gets lost because we don't do nested
693   % references with the same id ... maybe some day if we can figure out a nice heuristic ...
694   % the problem is that normally it's no issue but here we lap into the margin, so maybe that's
695   % a criterium
696 % \strc_notes_interaction_check_display
697   \strc_notes_set_reference_attribute_number
698   \dotagsetnotation
699   \strc_notes_set_style_color_display\c!headstyle\c!headcolor
700   \strc_enumerations_text
701   \endgroup}
702
703% in mkii the pointer only showed up in pagewise notes
704
705\protected\def\strc_notes_inject_pointer % todo calculate once
706  {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax
707     % unknown
708   \or
709     % same page
710   \or
711     \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}%
712   \or
713     \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}%
714   \fi}
715
716\protected\def\strc_notes_inject_symbol_yes
717  {\strc_notes_inject_symbol_indeed\conditionaltrue}
718
719\protected\def\strc_notes_inject_symbol_nop
720  {\strc_notes_inject_symbol_indeed\conditionalfalse}
721
722\definemargindata
723  [strc_notes_destination_margin]
724  [\v!left]
725  [\c!margin=\zeropoint,
726   \c!width=\zeropoint,
727   \c!style=,
728   \c!color=]
729
730\protected\def\strc_notes_inject_symbol_indeed#synchronize%
731  {\ifconditional\c_strc_notations_anchored_next\else
732     \removeunwantedspaces
733     \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
734   \fi
735   \ifnum\lastboundary=\noteboundary
736     \unboundary
737   % \kern\noteparameter\c!distance % yes or no note font? or main text
738     \strc_notes_inject_separator
739   \fi
740   \nobreak
741   \begingroup
742   \strc_notes_interaction_check_inline\strc_notes_set_style_color_inline\c!textstyle\c!textcolor
743   \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup
744  % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack
745     \strc_references_flush_destination_nodes % a bit late but ok
746     \dostarttagged\t!descriptionsymbol\currentnote
747     \dotagsetnotesymbol
748     \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}%
749     % the next one can cycle so we need to make sure it has no advance width
750     \ifcstok{\noteparameter\c!indicator}\v!yes
751       \strc_notes_inject_pointer
752     \fi
753     \dostoptagged
754   \egroup
755   \endgroup
756   \glettonothing\lastnotesymbol}
757
758\protected\def\strc_notes_inject_dummy % temp hack
759  {\removeunwantedspaces
760   \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
761   \ifnum\lastboundary=\noteboundary
762     \unboundary
763   % \kern\noteparameter\c!distance % yes or no note font? or main text
764     \strc_notes_inject_separator
765   \fi
766   \nobreak
767   \hpack to .5\emwidth{}%
768   \glettonothing\lastnotesymbol}
769
770\protected\def\strc_notes_inject_separator % patch by WS due to request on list
771  {\edef\p_textseparator{\noteparameter\c!textseparator}%
772   \ifempty\p_textseparator
773     \kern{\noteparameter\c!distance}%
774   \else
775     % skip or kern
776     \nobreak
777     \hbox\bgroup
778       \usenotestyleandcolor\c!textstyle\c!textcolor
779       \noteparameter\c!textcommand{\p_textseparator}%
780       \kern{\noteparameter\c!distance}%
781     \egroup
782     \nobreak
783   \fi}
784
785% this needs a further cleanup ... soon as it's a slow mechanism
786%
787% -- set breakpoint in descriptions
788% -- reset after trialtypesetting
789% -- that way we can trick the symbol space
790
791% removed:
792%
793% \pushsomestates
794%
795% core-ins -> obsolete
796%
797% saveinsertiondata
798% restoreinsertiondata
799% saveinsertionbox
800% eraseinsertionbackup
801% restoreinsertionbackup
802
803% \def\savenotedata      {} % \writestatus{todo}{save    note data}}
804% \def\restorenotedata   {} % \writestatus{todo}{restore note data}}
805% \def\savenotecontent   {} % \writestatus{todo}{save    note content}}
806% \def\restorenotecontent{} % \writestatus{todo}{restore note content}}
807% \def\erasenotebackup   {} % \writestatus{todo}{erase   note backup}}
808
809% page-set:
810
811% \def\enablenotes    {\writestatus{todo}{enable  notes}}
812% \def\disablenotes   {\writestatus{todo}{disable notes}}
813% \def\savenotes      {\writestatus{todo}{save    notes}}
814% \def\flushsavednotes{\writestatus{todo}{flush   notes}}
815
816% experiment: (compare scope=text and scope=page)
817%
818% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0]
819% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
820
821%D Footnotes are can be characterized by three components:
822%D
823%D \startitemize[packed]
824%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes
825%D   [conversion=set 2]\footnote {a footnote}}
826%D \item and a similar mark at the bottom of the page
827%D \item followed by some additional text
828%D \stopitemize
829%D
830%D Because footnotes are declared at the location of their reference they can be
831%D seen as a special kind of floating bodies. Their placement is postponed but has
832%D to be taken into account in the pagebreak calculations. This kind of calculations
833%D are forced by using \type{\insert}s and dealing with all cases is not trivial.
834
835%D \macros
836%D   {notesenabled}
837%D
838%D We need a couple of states because at some moments we don't want to mess around
839%D with inserts at all. Take for instance a table of contents. And so we can
840%D temporary disable footnotes by saying
841%D
842%D \starttyping
843%D \notesenabledfalse
844%D \stoptyping
845
846\newif\ifnotesenabled \notesenabledtrue
847
848% better mark a note .. once flushed no more flushing
849
850%appendtoks \notesenabledfalse \to \everymarking
851\appendtoks \notesenabledfalse \to \everybeforepagebody
852\appendtoks \notesenabledfalse \to \everystructurelist    % quick hack
853\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack
854\appendtoks \notesenabledfalse \to \everypreroll          % quick hack
855
856%D Often we need to process the whole set of notes and to make that fast, we use a
857%D token register:
858
859% we have several synchronizers:
860%
861% - after a definition
862% - after a specific setup
863% - after a general setup (inheritance of dimensions)
864% - just before a note is typeset
865
866\newtoks\t_strc_notes
867
868\let\strc_notes_process_list\gobbleoneargument
869
870\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote
871  {\def\strc_notes_process_list##1{\cdef\currentnote{##1}\let\currentdescription\currentnote#action}%
872   \expand\t_strc_notes}
873
874\newtoks\everychecknote       % just before a note is typeset
875\newtoks\everysynchronizenote % after a general setup has happened
876
877\appendtoks
878    \ifempty\currentnote \else
879        \setupnotations[\currentnote][]% also a synchronize
880    \fi
881\to \everysynchronizenote
882
883\def\strc_notes_synchronize
884  {\expand\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist
885
886\appendtoks
887    \strc_notes_process\strc_notes_synchronize
888\to \everysetupnoteroot
889
890\appendtoks
891    \expand\everysynchronizenote
892\to \everydefinenote
893
894% \starttext
895%     text \startfootnote Test.\stopfootnote
896%     test \footnote{xxxx} \subfootnote{xxxx}
897%     test \footnote{xxxx} \subfootnote{xxxx}
898% \stoptext
899
900\installcorenamespace{notecommand}
901\installcorenamespace{notealign}
902\installcorenamespace{notepenalty}
903\installcorenamespace{noterule}
904
905\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname}
906\permanent\protected\def\currentnoterulealign  {\begincsname\??notealign  \currentnote\endcsname}
907
908\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand}
909\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards
910
911\permanent\protected\def\letcurrentnoterulecommand{\enforced\letcsname\??notecommand\currentnote\endcsname}
912\permanent\protected\def\letcurrentnoterulealign  {\enforced\letcsname\??notealign  \currentnote\endcsname}
913
914\appendtoks
915    \enforced\letcsname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal
916    \enforced\letcsname\??notealign  \currentnote\endcsname\lefttoright
917\to \everysynchronizenote
918
919\def\strc_notes_set_rule
920  {\letcurrentnoterulecommand\relax % so we default to nothing
921   \letcurrentnoterulealign  \relax
922   \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step}
923
924\def\strc_notes_set_rule_step#alternative%
925  {\begincsname\??noterule#alternative\endcsname}
926
927\def\strc_notes_set_rule_autodir
928  {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright}
929
930\defcsname\??noterule  \v!command\endcsname{\letcurrentnoterulecommand\currentnoterulecommandcommand}
931\defcsname\??noterule       \v!on\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal}
932\defcsname\??noterule   \v!normal\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal}
933\defcsname\??noterule     \v!left\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
934                                            \letcurrentnoterulealign  \lefttoright}
935\defcsname\??noterule    \v!right\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
936                                            \letcurrentnoterulealign  \righttoleft}
937\defcsname\??noterule\v!paragraph\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
938                                            \letcurrentnoterulealign  \strc_notes_set_rule_autodir}
939\defcsname\??noterule      \v!off\endcsname{\letcurrentnoterulecommand\relax}
940
941\appendtoks
942    \strc_notes_set_rule
943\to \everysynchronizenote
944
945\permanent\def\currentnotepenalty
946  {\ifcsname\??notepenalty\noteparameter\c!split\endcsname
947     \lastnamedcs
948   \else
949     \numexpr\noteparameter\c!split\relax
950   \fi}
951
952\setnewconstant\notepenaltytolerant  \zerocount
953\setnewconstant\notepenaltystrict    9999
954\setnewconstant\notepenaltyverystrict\maxdimen
955
956\letcsname\??notepenalty\v!tolerant  \endcsname\notepenaltytolerant
957\letcsname\??notepenalty\v!strict    \endcsname\notepenaltystrict
958\letcsname\??notepenalty\v!verystrict\endcsname\notepenaltyverystrict
959\letcsname\??notepenalty             \endcsname\notepenaltytolerant
960
961%D The following switch can be used to disable limiting the height of the footnote
962%D area, something that is needed in multi column balancing. Use this switch with
963%D care.
964
965\newif\ifnotelimit \notelimittrue % shared
966
967\def\strc_notes_set_factor
968  {\edef\p_factor{\noteparameter\c!factor}%
969   \ifempty\p_factor \else
970     \ifnum\p_factor<\zerocount \else
971%        \global
972       \insertmultiplier\currentnoteinsertionnumber\p_factor % new: global
973     \fi
974   \fi}
975
976\appendtoks
977    \strc_notes_set_factor
978\to \everysynchronizenote
979
980% locations:
981
982\installcorenamespace{notelocationvariant}
983\installcorenamespace{notepositionvariant}
984\installcorenamespace{notedelayedvariant}
985\installcorenamespace{notelocation}
986
987\newconditional\c_strc_notes_delayed
988\newconditional\c_strc_notes_flushed
989
990\protected\def\strc_notes_set_delayed_yes{\c_strc_notes_delayed\conditionaltrue\c_strc_notes_flushed\conditionalfalse}
991\protected\def\strc_notes_set_delayed_nop{\c_strc_notes_delayed\conditionalfalse\c_strc_notes_flushed\conditionalfalse}
992\protected\def\strc_notes_set_delayed_lst{\c_strc_notes_delayed\conditionaltrue\c_strc_notes_flushed\conditionaltrue}
993
994\defcsname\??notelocation\v!page\endcsname
995  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
996   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_page}
997
998\defcsname\??notelocation\v!columns\endcsname
999  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
1000   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_columns}
1001
1002\defcsname\??notelocation\v!lastcolumn\endcsname
1003  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
1004   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_lastcolumn}
1005
1006\defcsname\??notelocation\v!firstcolumn\endcsname
1007  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
1008   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_firstcolumn}
1009
1010\defcsname\??notelocation\v!none\endcsname
1011  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_yes
1012   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_none}
1013
1014\defcsname\??notelocation\v!list\endcsname
1015  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_lst
1016   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_none}
1017
1018\defcsname\??notelocation\v!text\endcsname
1019  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_yes
1020   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_text}
1021
1022\defcsname\??notelocation\v!high\endcsname
1023  {\letcsname\??notepositionvariant\currentnote\endcsname\strc_notes_set_position_high}
1024
1025\defcsname\??notelocation\v!bottom\endcsname
1026  {\letcsname\??notepositionvariant\currentnote\endcsname\strc_notes_set_position_bottom}
1027
1028\defcsname\??notedelayedvariant \??notedelayedvariant \endcsname{\strc_notes_set_delayed_nop    } % not \let
1029\defcsname\??notepositionvariant\??notepositionvariant\endcsname{\strc_notes_set_position_bottom} % not \let
1030\defcsname\??notelocationvariant\??notelocationvariant\endcsname{\strc_notes_set_location_page  } % not \let
1031
1032\protected\def\strc_notes_set_delayed
1033  {\csname\??notedelayedvariant
1034     \ifcsname\??notedelayedvariant\currentnote\endcsname
1035       \currentnote
1036     \else
1037       \??notedelayedvariant
1038     \fi
1039   \endcsname}
1040
1041\protected\def\strc_notes_set_position
1042  {\csname\??notepositionvariant
1043     \ifcsname\??notepositionvariant\currentnote\endcsname
1044       \currentnote
1045     \else
1046       \??notepositionvariant
1047     \fi
1048   \endcsname}
1049
1050\protected\def\strc_notes_set_location
1051  {\csname\??notelocationvariant
1052     \ifcsname\??notelocationvariant\currentnote\endcsname
1053       \currentnote
1054     \else
1055       \??notelocationvariant
1056     \fi
1057   \endcsname}
1058
1059\protected\def\strc_notes_set_variants
1060  {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
1061
1062\protected\def\strc_notes_set_location_step#alternative% the insert related one
1063  {\begincsname\??notelocation#alternative\endcsname}
1064
1065\appendtoks
1066    \strc_notes_set_variants
1067    \strc_notes_set_delayed
1068\to \everysynchronizenote
1069
1070\newgluespec   \s_strc_notes_distance % we need to implement stretch
1071\newinteger    \c_strc_notes_columns
1072\newgluespec   \s_strc_notes_before
1073\newgluespec   \s_strc_notes_inbetween
1074\newconditional\c_strc_notes_first_flushed
1075
1076% we can store them per insert so so real need to redo it
1077
1078\appendtoks
1079    \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}%
1080    \ifempty\p_spacebefore
1081        \global\s_strc_notes_before\zeropoint
1082    \else
1083        \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}%
1084    \fi
1085    \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}%
1086    \ifempty\p_spaceinbetween
1087        \global\s_strc_notes_inbetween\zeropoint
1088    \else
1089        \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}%
1090    \fi
1091\to \everysynchronizenote
1092
1093\def\strc_notes_set_distance
1094  {\begingroup
1095   \restoreglobalbodyfont
1096   \setbox\scratchbox\vbox % no reuse as it can mirror
1097     {\forgetall
1098      \dontcomplain
1099      \noteparameter\c!before
1100      \ifvmode
1101        \nointerlineskip
1102      \fi
1103      \placenoterule
1104     %\nointerlineskip
1105      \strut
1106      \noteparameter\c!after}%
1107   % also dp now
1108   \scratchdimen{\htdp\scratchbox-\lineheight}%
1109   \ifconditional\c_page_mvl_active
1110     % quick hack, columnsets already handle the grid .. maybe an option
1111   \orelse\ifgridsnapping
1112     \getnoflines\scratchdimen
1113     \scratchdimen\noflines\lineheight
1114   \fi
1115%    \expandafter\endgroup\expandafter
1116%    \s_strc_notes_distance\the\scratchdimen\relax%
1117   \normalexpanded{%
1118     \endgroup
1119     \s_strc_notes_distance\the\scratchdimen\relax
1120     % this will / has to / might become a plug
1121     \ifconditional\c_page_mvl_split_inserts
1122       \insertlineheight\currentnoteinsertionnumber\relaxedspace\the\strutht\relax
1123       \insertlinedepth \currentnoteinsertionnumber\relaxedspace\the\strutdp\relax
1124     \fi}}
1125
1126\def\strc_notes_set_columns
1127  {\c_strc_notes_columns\noteparameter\c!n\relax
1128   \ifcase\c_strc_notes_columns
1129     \c_strc_notes_columns\plusone
1130   \fi}
1131
1132\def\strc_notes_set_location_page
1133  {\c_strc_notes_delayed\conditionalfalse
1134   \strc_notes_set_distance
1135   \strc_notes_set_columns
1136   \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]%
1137   \insertmultiplier\currentnoteinsertionnumber{(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns}%
1138   \insertlimit     \currentnoteinsertionnumber\ifnotelimit{(\noteparameter\c!height)*\c_strc_notes_columns}\else\maxdimen\fi
1139   \insertdistance  \currentnoteinsertionnumber\s_strc_notes_distance}
1140
1141\def\strc_notes_set_location_columns
1142  {\c_strc_notes_delayed\conditionalfalse
1143   \strc_notes_set_distance
1144   \strc_notes_set_columns
1145 % \ifnum\currentnofcolumns=\zerocount
1146   \ifnum\nofcolumns=\zerocount
1147     \c_strc_notes_columns\plusone
1148   \fi
1149   \page_inserts_set_location  \currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]%
1150   \insertmultiplier\currentnoteinsertionnumber{\plusthousand/\c_strc_notes_columns}%
1151   \insertlimit     \currentnoteinsertionnumber\ifnotelimit{(\noteparameter\c!height)*\c_strc_notes_columns}\else\maxdimen\fi
1152   \insertdistance  \currentnoteinsertionnumber\s_strc_notes_distance}
1153
1154\def\strc_notes_set_location_somecolumn#whatcolumn%
1155  {\c_strc_notes_delayed\conditionalfalse
1156   \strc_notes_set_distance
1157   \strc_notes_set_columns
1158   \page_inserts_set_location  \currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]%
1159   \insertmultiplier\currentnoteinsertionnumber\plusthousand
1160   \insertlimit     \currentnoteinsertionnumber\ifnotelimit{\noteparameter\c!height}\else\maxdimen\fi
1161   \insertdistance  \currentnoteinsertionnumber\s_strc_notes_distance}
1162
1163\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn}
1164\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn }
1165
1166\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
1167  {\c_strc_notes_delayed\conditionaltrue
1168   \clf_setnotestate{\currentnote}{store}%
1169   \page_inserts_set_location  \currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]%
1170   \insertmultiplier\currentnoteinsertionnumber\zerocount
1171   \insertlimit     \currentnoteinsertionnumber\maxdimen
1172   \insertdistance  \currentnoteinsertionnumber\zeropoint}
1173
1174\let\strc_notes_set_location_none\strc_notes_set_location_text
1175
1176\def\strc_notes_set_properties
1177  {\strc_notes_set_columns
1178   \strc_notes_set_distance
1179   \strc_notes_set_location
1180   \strc_notes_set_delayed
1181   \strc_notes_set_factor}
1182
1183\let\strc_notes_set_position_high\relax
1184
1185\def\strc_notes_set_position_bottom
1186  {\c_notes_bottom_present\conditionaltrue}
1187
1188\appendtoks
1189    \strc_notes_set_properties
1190\to \everysynchronizenote
1191
1192%D A fast checker for bottom notes being used:
1193
1194\newconditional\c_notes_bottom_present
1195
1196% \def\strc_notes_check_if_bottom_present_indeed % in otr !
1197%   {\ifvoid\currentnoteinsertionnumber\else
1198%      \strc_notes_set_position
1199%    \fi}
1200
1201\def\strc_notes_check_if_bottom_present_indeed % in otr !
1202  {\ifzeropt\insertheight\currentnoteinsertionnumber\else
1203     \strc_notes_set_position
1204   \fi}
1205
1206\def\strc_notes_check_if_bottom_present_step
1207  {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi}
1208
1209\def\strc_notes_check_if_bottom_present
1210  {\c_notes_bottom_present\conditionalfalse
1211   \strc_notes_process\strc_notes_check_if_bottom_present_step}
1212
1213% Example of using factor:
1214%
1215% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0]
1216% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle]
1217% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
1218% \starttext
1219% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} }
1220% \stoptext
1221
1222%D The noterule can be a graphic and therefore calling this setup macro at every
1223%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that
1224%D probably match those of the stretch component. A bit messy:
1225
1226\permanent\protected\def\placenoterule
1227  {\begingroup
1228   \currentnoterulealign
1229   \currentnoterulecommand
1230   \par
1231   \endgroup}
1232
1233\permanent\protected\def\normalnoterule
1234  {\ifvmode
1235    %\nointerlineskip % maybe, columnsets
1236     \dontleavehmode \blackrule
1237       [\c!color=\noteparameter\c!rulecolor,
1238        \c!width=.2\hsize,
1239        \c!height=\noteparameter\c!rulethickness,
1240        \c!depth=\zeropoint]%
1241     \endgraf
1242     \kern\strutdepth
1243   \fi}
1244
1245%D The formatting depends on the width of the table, so we have to set \type {n} to
1246%D zero.
1247%D
1248%D \starttyping
1249%D \startbuffer
1250%D \bTABLE
1251%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR
1252%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR
1253%D \eTABLE
1254%D \stopbuffer
1255%D
1256%D \startlocalfootnotes[n=0,location={text,none}]
1257%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes}
1258%D \stoplocalfootnotes
1259%D \stoptyping
1260
1261%D \macros
1262%D   {footnote}
1263%D
1264%D A footnote can have a reference as optional argument and therefore its formal
1265%D specification looks like:
1266%D
1267%D \showsetup{footnote}
1268%D
1269%D This command has one optional command: the reference. By saying \type{[-]} the
1270%D number is omitted. The footnote command is not that sensitive to spacing, so it's
1271%D quite legal to say:
1272%D
1273%D \startbuffer
1274%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the
1275%D ground and not get confused \footnote {Or even crazy.} by all those obscure
1276%D \footnote {But fortunately readable.} parameters.
1277%D \stopbuffer
1278%D
1279%D \typebuffer
1280%D
1281%D When setting the \type{conversion} to \type{set 2} we get
1282%D something like:
1283%D
1284%D \bgroup
1285%D \startnarrower
1286%D \setupfootnotes[conversion=set 1]
1287%D \getbuffer
1288%D \stopnarrower
1289%D \egroup
1290%D
1291%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes.
1292%D The additional macro \type {\footnotetext} and the associated \type {\note} macro
1293%D were implemented at request of users on the mailing list and a suggestion by taco
1294%D to split of the symbol placement. I decided to merge this functionality with the
1295%D existing \type {\note} functionality.
1296
1297\newconditional\c_strc_notes_symbol \c_strc_notes_symbol\conditionaltrue % not used
1298\newconditional\c_strc_notes_skip
1299
1300\newcount\c_strc_notes_n
1301
1302\permanent\protected\def\setnote    [#tag]{\csname#tag\endcsname}
1303\permanent\protected\def\setnotetext[#tag]{\global\c_strc_notes_skip\conditionaltrue\csname#tag\endcsname}
1304
1305\permanent\protected\def\handlenoteinsert#tag#id%
1306  {\begingroup
1307   \cdef\currentnote{#tag}%
1308   \strc_constructions_initialize{#tag}%
1309   \strc_notes_synchronize
1310   \global\advanceby\c_strc_notes_n\plusone
1311   \expand\everybeforenoteinsert
1312  %\insert\currentnoteinsertionnumber
1313   \insert
1314     \s!index \currentnoteinsertionnumber
1315     \s!data  \c_strc_notes_n
1316   \bgroup
1317     \expand\everyinsidenoteinsert\relax
1318     \usesetupsparameter\noteparameter % experimental
1319     \useinterlinespaceparameter\noteparameter
1320     \ifcstok{\noteparameter\c!paragraph}\v!yes
1321       \nointerlineskip
1322       \startvboxtohboxseparator
1323         \noteparameter\c!inbetween
1324       \stopvboxtohboxseparator
1325       \startvboxtohbox
1326         \handlenoteitself{#tag}{#id}%
1327       \stopvboxtohbox
1328     \else
1329       \handlenoteitself{#tag}{#id}%
1330     \fi
1331   \egroup
1332   \expand\everyafternoteinsert
1333   \endgroup}
1334
1335\permanent\protected\def\betweennoteitself#tag% used ?
1336  {\cdef\currentnote{#tag}%
1337   \ifcstok{\noteparameter\c!paragraph}\v!yes
1338     \noteparameter\c!inbetween
1339   \fi}
1340
1341\permanent\protected\def\handlenoteitself#tag#id%
1342  {\edef\currentnotenumber{#id}%
1343   \cdef\currentnote{#tag}%
1344   \strc_constructions_initialize{#tag}%
1345   \strc_notes_synchronize
1346   \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache
1347   % as we can have collected notes (e.g. in tables) we need to recover
1348   % \currentdescriptionattribute and \currentdescriptionsynchronize
1349   %
1350   \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table)
1351   %
1352   \dontcomplain
1353   %begingroup
1354   \strc_notes_interaction_check_display
1355   \strc_notes_set_reference_attribute_text
1356   \strc_constructions_stored_start
1357   \begstrut
1358   \strc_references_flush_destination_nodes
1359   \strc_notes_set_destination_attribute_text
1360   \ifconditional\c_strc_notes_flushed\else
1361     \strc_notes_inject_text\relax
1362   \fi
1363   \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10
1364   \strc_constructions_stored_stop
1365   %endgroup
1366   }
1367
1368\protected\def\strc_notes_inject_text % hm main?
1369  {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}
1370
1371\installstructurelistprocessor{construction}{\usestructurelistprocessor{section}}
1372
1373\newboundary\noteboundary
1374
1375\newconditional\processingnote
1376\newconditional\postponednote
1377
1378\newtoks\everybeforenoteinsert
1379\newtoks\everyinsidenoteinsert
1380\newtoks\everyafternoteinsert
1381
1382\permanent\protected\def\doifelseinnote
1383  {\ifconditional\processingnote
1384     \expandafter\firstoftwoarguments
1385   \else
1386     \expandafter\secondoftwoarguments
1387   \fi}
1388
1389\appendtoks
1390   \enforced\lettonothing\flushnotes
1391   \enforced\lettonothing\postponenotes
1392   \forgetall
1393   \resetallattributes   % new, we don't want color bleed into notes
1394   \inheritmaintextcolor % but we do want to obey the textcolor
1395\to \everybeforenoteinsert
1396
1397\def\strc_notes_set_penalties
1398  {% stored in insert node
1399   \floatingpenalty \currentnotepenalty % now per note
1400   \insertpenalty\currentnoteinsertionnumber\currentnotepenalty
1401   % used when typesetting
1402   \interlinepenalty\plushundred % plain value
1403   % used when we need to split in columns
1404   \ifnum\noteparameter\c!n>\plusone
1405     \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated)
1406   \fi}
1407
1408\appendtoks
1409    \strc_notes_set_penalties
1410    \forgetall % again
1411    \strc_notes_set_bodyfont
1412    \redoconvertfont % to undo \undo calls in in headings etc
1413    \splittopskip\strutht  % not actually needed here
1414    \splitmaxdepth\strutdp % not actually needed here
1415\insertmaxdepth  \currentnoteinsertionnumber\strutdp
1416    %
1417    % not:
1418    %
1419  % \leftmargindistance \noteparameter\c!margindistance
1420  % \rightmargindistance\leftmargindistance
1421  % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
1422  %   \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
1423  % \fi
1424    %
1425    \pickupattributes
1426\to \everyinsidenoteinsert
1427
1428%D Nasty, the might be more:
1429
1430\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert
1431\appendtoks \strc_itemgroups_pop  \to \everyafternoteinsert
1432
1433% maybe but better use [scope=local] here
1434%
1435% \appendtoks
1436%     \inhibitmargindata\conditionalfalse
1437% \to \everyinsidenoteinsert
1438
1439\setupnotes
1440  [\c!width=\v!auto]
1441
1442% \permanent\protected\def\setnotehsize
1443%   {\ifinsidemulticolumns
1444%      \setnoteparameter\c!width{\makeupwidth}%
1445%    \else
1446%      \edef\p_width{\noteparameter\c!width}%
1447%      \ifx\p_width\v!auto
1448%      % \ifinsidecolumns
1449%          \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}%
1450%      % \else
1451%      %   \setnoteparameter\c!width{\makeupwidth}%
1452%      % \fi
1453%      \orelse\ifempty\p_width
1454%        \setnoteparameter\c!width{\hsize}%
1455%      \fi
1456%   \fi
1457%   \hsize\noteparameter\c!width\relax}
1458%
1459% We construct immediately and migrate so:
1460
1461\permanent\protected\def\setnotehsize
1462  {\edef\p_width{\noteparameter\c!width}%
1463   \ifx\p_width\v!auto
1464     % intercept old value
1465     \let\p_width\makeupwidth
1466     \setnoteparameter\c!width{\makeupwidth}%
1467   \fi
1468   \hsize{\p_width}}
1469
1470\appendtoks
1471    % only needed when columns (could be three \set...)
1472    \setnotehsize
1473    \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1474\to \everyinsidenoteinsert
1475
1476%D Normally footnotes are saved as inserts that are called upon as soon as the
1477%D pagebody is constructed. The footnote insertion routine looks just like the
1478%D \PLAIN\ \TEX\ one, except that we check for the end note state.
1479
1480% testcase for split bottom alignment see (a) below
1481%
1482% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}}
1483
1484\newconditional\c_strc_notes_first_placed
1485
1486\permanent\protected\def\placenoteinserts
1487  {\c_strc_notes_first_placed\conditionalfalse
1488   \strc_notes_process\strc_notes_place_inserts}
1489
1490\def\strc_notes_place_inserts
1491  {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
1492   \ifconditional\c_strc_notes_delayed \else
1493%      \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test
1494     \ifcase\insertheight\currentnoteinsertionnumber\else
1495       \strc_notes_place_inserts_indeed
1496       \c_strc_notes_first_placed\conditionaltrue
1497     \fi
1498   \fi}
1499
1500\newbox\b_strc_notes_inserts
1501
1502\def\strc_notes_place_inserts_indeed_before
1503  {\endgraf
1504   \ifvmode
1505     \whitespace
1506     \ifconditional\c_strc_notes_first_placed
1507       \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}%
1508       \ifempty\p_spaceinbetween\else
1509         \blank[\p_spaceinbetween]%
1510       \fi
1511     \else
1512       \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}%
1513       \ifempty\p_spacebefore\else
1514         \blank[\p_spacebefore]%
1515       \fi
1516     \fi
1517     \noteparameter\c!before
1518     \nointerlineskip % added, otherwise spacing between multiple classes
1519   \fi
1520   \placenoterule}
1521
1522\def\strc_notes_place_inserts_indeed_after
1523  {\endgraf
1524   \ifvmode
1525     \noteparameter\c!after
1526   \fi}
1527
1528\def\strc_notes_place_inserts_indeed
1529  {\relax
1530%    \ifdim\ht\currentnoteinsertionnumber>\zeropoint
1531   \ifcase\insertheight\currentnoteinsertionnumber\else
1532%  \ifzeropt\insertheight\currentnoteinsertionnumber\else
1533     \strc_notes_place_inserts_indeed_before
1534     \bgroup
1535     \strc_notes_set_bodyfont
1536     \setbox\b_strc_notes_inserts\hbox
1537       {\strc_notes_flush_inserts}%
1538     \page_postprocessors_linenumbers_deepbox\b_strc_notes_inserts
1539     \setbox\b_strc_notes_inserts\hbox
1540       {\setupcurrentnote
1541          [\c!location=,
1542           \c!width=\v!fit,
1543           \c!height=\v!fit,
1544           \c!strut=\v!no,
1545           \c!offset=\v!overlay]%
1546        \inheritednoteframed
1547          {\ifzeropt\dp\b_strc_notes_inserts                  % this hack is needed because \vadjust
1548             \hpack{\lower\strutdp\box\b_strc_notes_inserts}% % in margin number placement
1549           \else                                              % hides the (always) present depth
1550             \box\b_strc_notes_inserts
1551           \fi}}%
1552     \setbox\b_strc_notes_inserts\hpack{\lower\strutdepth\box\b_strc_notes_inserts}%
1553     \dp\b_strc_notes_inserts\strutdepth % so we know that it has the note bodyfont depth
1554     \ifvmode
1555       \nointerlineskip % else sometimes empty line
1556     \fi
1557     \box\b_strc_notes_inserts
1558     \egroup
1559     \strc_notes_place_inserts_indeed_after
1560   \fi}
1561
1562\def\strc_notes_place_inserts_very_indeed#1%
1563  {\strc_notes_place_inserts_indeed_before
1564   \bgroup
1565   \strc_notes_set_bodyfont
1566   #1% set the box here
1567   \page_postprocessors_linenumbers_deepbox\b_strc_notes_inserts
1568   \scratchheight\ht\b_strc_notes_inserts
1569   \scratchdepth \dp\b_strc_notes_inserts
1570   \setbox\b_strc_notes_inserts\hbox
1571     {\setupcurrentnote
1572        [\c!location=,
1573         \c!width=\v!fit,
1574         \c!height=\v!fit,
1575         \c!strut=\v!no,
1576         \c!offset=\v!overlay]%
1577      \inheritednoteframed
1578        {\box\b_strc_notes_inserts}}%
1579   \ht\b_strc_notes_inserts\scratchheight
1580  %\dp\b_strc_notes_inserts\scratchdepth
1581   \dp\b_strc_notes_inserts\strutdepth % so we know that it has the note bodyfont depth
1582   \ifvmode
1583     \nointerlineskip % else sometimes empty line
1584   \fi
1585   \box\b_strc_notes_inserts
1586   \egroup
1587   \strc_notes_place_inserts_indeed_after}
1588
1589\def\strc_notes_flush_inserts
1590  {\ifcase\noteparameter\c!n\relax
1591     % should not happen
1592   \or
1593     \strc_notes_flush_inserts_normal
1594   \else
1595     \strc_notes_flush_inserts_columns
1596   \fi}
1597
1598\def\strc_notes_flush_inserts_normal
1599  {\strc_notes_flush_global
1600   \obeydepth} % (a) added , since split footnotes will not align properly
1601
1602\def\strc_notes_flush_inserts_columns
1603  {\begingroup
1604   \setnotehsize % probably still not ok for columns
1605   \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1606     \strc_notes_flush_global
1607   \stopsimplecolumns
1608   \endgroup}
1609
1610% idea: tag with attr and then just flush them again
1611
1612\def\strc_notes_flush_global
1613  {\begingroup
1614   \useinterlinespaceparameter\noteparameter
1615   \ifcstok{\noteparameter\c!paragraph}\v!yes
1616     \leftorrightvbox % cf mail from ws to list
1617       {\starthboxestohbox
1618          \iftrialtypesetting
1619            \insertuncopy
1620          \else
1621            \insertunbox
1622          \fi
1623          \currentnoteinsertionnumber
1624        \stophboxestohbox}%
1625   \else
1626     \iftrialtypesetting
1627       \ifvmode\insertuncopy\else\insertcopy\fi
1628     \else
1629       \ifvmode\insertunbox \else\insertbox \fi
1630     \fi
1631     \currentnoteinsertionnumber
1632   \fi
1633   \endgroup}
1634
1635%D Supporting end notes is surprisingly easy. Even better, we can combine this
1636%D feature with solving the common \TEX\ problem of disappearing inserts when
1637%D they're called for in deeply nested boxes. The general case looks like:
1638%D
1639%D \starttyping
1640%D \postponenotes
1641%D \.box{whatever we want with footnotes}
1642%D \flushnotes
1643%D \stoptyping
1644%D
1645%D This alternative can be used in headings, captions, tables etc. The latter one
1646%D sometimes calls for notes local to the table, which can be realized by saying
1647%D
1648%D \starttyping
1649%D \setlocalfootnotes
1650%D some kind of table with local footnotes
1651%D \placelocalfootnotes
1652%D \stoptyping
1653%D
1654%D Postponing is accomplished by simply redefining the (local) insert operation. A
1655%D not too robust method uses the \type{\insert} primitive when possible. This
1656%D method fails in situations where it's not entirely clear in what mode \TEX\ is.
1657%D Therefore the auto method can is to be overruled when needed.
1658
1659\newconditional\postponingnotes
1660
1661% we need a proper state: normal, postponing, flushing
1662
1663\permanent\protected\def\postponenotes % will be locally overloaded
1664  {\ifcase\insertionmigrationmode
1665     \ifconditional\postponingnotes\else
1666       \global\postponingnotes\conditionaltrue
1667       \enforced\glet\flushnotes\doflushnotes
1668       \clf_postponenotes
1669     \fi
1670   \fi}
1671
1672\permanent\lettonothing\flushnotes
1673
1674% also \ifcase\insertionmigrationmode here, needs testing:
1675
1676\permanent\protected\def\startpostponingnotes % experimental, page-mix
1677  {\ifconditional\postponingnotes\else
1678     \global\postponingnotes\conditionaltrue
1679    %\glet\flushnotes\doflushnotes
1680     \clf_postponenotes
1681   \fi}
1682
1683\permanent\protected\def\stoppostponingnotes % experimental, page-mix
1684  {\doflushnotes}
1685
1686\permanent\protected\def\doflushnotes
1687  {\ifconditional\postponingnotes
1688     \begingroup
1689     \enforced\lettonothing\flushnotes
1690     \enforced\lettonothing\postponenotes
1691     \ifconditional\postponednote
1692       \ifhmode
1693         % needed for tagging ... otherwise we get some weird node free error
1694         \signalcharacter
1695       \fi
1696     \fi
1697     \clf_flushpostponednotes% this also resets the states !
1698     \global\postponednote\conditionalfalse
1699     \global\postponingnotes\conditionalfalse
1700     \enforced\glettonothing\flushnotes
1701     \endgroup
1702   \fi}
1703
1704%D \macros
1705%D   {startlocalfootnotes,placelocalfootnotes}
1706%D
1707%D The next two macros can be used in for instance tables, as we'll demonstrate
1708%D later on.
1709%D
1710%D \showsetup{startlocalfootnotes}
1711%D \showsetup{placelocalfootnotes}
1712
1713% todo: compatibility mode: when first arg is assignment or missing, then all
1714
1715\newtoks\everyplacelocalnotes
1716
1717\appendtoks
1718    \enforced\lettonothing\flushnotes
1719    \enforced\lettonothing\postponenotes
1720\to \everyplacelocalnotes
1721
1722\newconditional\inlocalnotes
1723
1724\mutable\lettonothing\localnoteslist
1725
1726\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings)
1727  {\inlocalnotes\conditionaltrue
1728   \def\localnoteslist{#list}%
1729   \processcommacommand[\localnoteslist]\strc_notes_local_start_step}
1730
1731\permanent\protected\def\stoplocalnotes
1732  {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step
1733   \inlocalnotes\conditionalfalse}
1734
1735\lettonothing\p_strc_notes_continue
1736
1737\def\strc_notes_local_start_step#tag%
1738  {\p_strc_notes_continue{\noteparameter\c!continue}%
1739   \ifx\p_strc_notes_continue\v!yes \else
1740      \strc_counters_save{#tag}%
1741      \strc_counters_reset{#tag}%
1742   \fi
1743   \clf_savenote{#tag}{store}}
1744
1745\def\strc_notes_local_stop_step#tag%
1746  {\p_strc_notes_continue{\noteparameter\c!continue}%
1747   \ifx\p_strc_notes_continue\v!yes \else
1748     \strc_counters_restore{#tag}%
1749   \fi
1750   \clf_restorenote{#tag}}
1751
1752\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#S#settings]%
1753  {\iftok{\clf_getnotestate{#tag}}{store}%
1754     \strc_notes_local_place_indeed{#settings}{#tag}%
1755   \fi}
1756
1757\def\strc_notes_local_place_indeed#settings#tag%
1758  {\begingroup
1759   \cdef\currentnote{#tag}% is already set?
1760   \expand\everyplacelocalnotes
1761   % beware, we cannot trust setting \currentnote here
1762   \setupcurrentnote[#settings]% later we set height etc for framed
1763   \strc_notes_place_local_alternative
1764   \strc_notes_set_properties % restore globals (if needed)
1765   \endgroup
1766  }% TODO: just restore properties \expand\everychecknote} % we need to restore the old state
1767
1768%D These commands can be used like:
1769%D
1770%D \startbuffer
1771%D \startlocalnotes[footnote]
1772%D   \placetable
1773%D     {Some Table}
1774%D     \placeontopofeachother
1775%D       {\starttable[|l|r|]
1776%D        \HL
1777%D        \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR
1778%D        \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR
1779%D        \HL
1780%D        \stoptable}
1781%D       {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]%
1782%D        \placelocalnotes[footnote]}
1783%D \stoplocalnotes
1784%D \stopbuffer
1785%D
1786%D \typebuffer
1787%D
1788%D Because this table placement macro expect box content, and thanks to the grouping
1789%D of the local footnotes, we don't need additional braces.
1790%D
1791%D \getbuffer
1792
1793%D \macros
1794%D   {placefootnotes}
1795%D
1796%D We still have no decent command for placing footnotes somewhere else than at the
1797%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can
1798%D be placed by using
1799%D
1800%D \showsetup{placefootnotes}
1801
1802\permanent\protected\def\placebottomnotes
1803  {\strc_notes_process\strc_notes_place_inserts}
1804
1805\permanent\tolerant\protected\def\placenotes[#list]#spacer[#S#settings]%
1806  {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}}
1807
1808\def\strc_notes_place_indeed#settings#tag% settings note
1809  {\cdef\currentnote{#tag}% grouping ?
1810   \iftok{\clf_getnotestate{#tag}}{store}%
1811     \expandafter\strc_notes_local_place_indeed
1812   \else
1813     \expandafter\strc_notes_global_place_indeed
1814   \fi
1815   {#settings}{#tag}}
1816
1817\def\strc_notes_global_place_indeed#settings#tag%
1818  {\begingroup
1819   \setupnote[#tag][#settings]%
1820   \strc_notes_place_inserts
1821   \endgroup
1822   \expand\everysetupnote} % to be checked .. synchronize
1823
1824%D Placement
1825
1826\installcorenamespace{notealternative}
1827
1828\permanent\protected\def\installnotealternative#alternative#command%
1829  {\defcsname\??notealternative#alternative\endcsname{#command}}
1830
1831\permanent\protected\def\doifnotescollected#tag%
1832  {\clf_doifnotecontent{#tag}}
1833
1834\def\strc_notes_place_local_alternative % will be a setup (wrapper)
1835  {\doifnotescollected\currentnote
1836     {\endgraf
1837      \ifvmode
1838        \whitespace
1839        \noteparameter\c!before
1840      \fi
1841      \begingroup
1842      \strc_notes_set_bodyfont
1843      \begincsname\??notealternative\noteparameter\c!alternative\endcsname
1844      \endgroup
1845      \ifvmode
1846        \noteparameter\c!after
1847      \fi}}
1848
1849%D A stupid alternative is also provided:
1850%D
1851%D \starttyping
1852%D \setupfootnotes[location=text,alternative=none]
1853%D \stoptyping
1854
1855% setups ?
1856
1857\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}}
1858
1859\installnotealternative \v!none
1860  {\flushlocalnotes\currentnote}
1861
1862\installnotealternative \empty
1863  {\flushlocalnotes\currentnote}
1864
1865\installnotealternative \v!grid % test if n > 0
1866  {\begingroup
1867   \setupcurrentnote[\c!location=]%
1868   \snaptogrid\hbox
1869     {\inheritednoteframed
1870        {\flushlocalnotes\currentnote}}%
1871   \endgroup}
1872
1873\installnotealternative \v!fixed % test if n > 0
1874  {\begingroup
1875   \setupcurrentnote[\c!location=]%
1876   \inheritednoteframed
1877     {\flushlocalnotes\currentnote}%
1878   \endgroup}
1879
1880\installnotealternative \v!columns % redundant
1881  {\begingroup
1882   \setupcurrentnote[\c!location=]%
1883   \inheritednoteframed
1884     {\ifchkdimension\noteparameter\c!width\or\else\setexpandednoteparameter\c!width{\the\hsize}\fi
1885      \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1886        \flushlocalnotes\currentnote
1887      \stopsimplecolumns}%
1888   \endgroup}
1889
1890% 0:page 1:firstcolumn 2:lastcolumn
1891
1892\newconstant\c_strc_notes_page_location
1893
1894\protected\def\strc_notes_check_locations
1895  {\edef\p_strc_notes_location{\rootnoteparameter\c!location}%
1896   \c_strc_notes_page_location
1897      \ifx\p_strc_notes_location\v!firstcolumn\plusone  \else
1898      \ifx\p_strc_notes_location\v!lastcolumn \plustwo  \else
1899                                              \zerocount\fi\fi}
1900
1901\appendtoks
1902    \strc_notes_check_locations
1903\to \everysynchronizenote
1904
1905% still semi public (but will change)
1906
1907\newif\ifnotespresent
1908
1909\permanent\protected\def\checknotepresence
1910  {\notespresentfalse
1911   \strc_notes_process\strc_notes_check_presence}
1912
1913\def\strc_notes_check_presence
1914%   {\ifdim\insertheight\currentnoteinsertionnumber>\zeropoint % not reliable
1915  {\ifcase\insertheight\currentnoteinsertionnumber\else
1916     \notespresenttrue
1917   \fi}
1918
1919%D \macros
1920%D   {fakenotes}
1921
1922    % used in page-mul
1923
1924 %  \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
1925
1926    \permanent\protected\def\fakenotes
1927      {\ifhmode\endgraf\fi\ifvmode
1928         \calculatetotalclevernoteheight
1929         \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
1930       \fi}
1931
1932    \permanent\protected\def\fakepagenotes
1933      {\ifhmode\endgraf\fi\ifvmode
1934         \calculatetotalpagenoteheight
1935         \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
1936       \fi}
1937
1938    % used in page-not but not yet ok
1939
1940    \newdimen\totalnoteheight
1941
1942    \permanent\protected\def\additionaltotalnoteheight#insert% temp hacks anyway
1943      {\dimexpr
1944         \ifnum\insertheight#insert=\zeropoint
1945           \zeropoint
1946         \orelse\ifnum\insertmultiplier#insert=\zeropoint
1947           \zeropoint
1948         \else % todo: divide by count
1949           \insertheight  #insert
1950          +\insertdistance#insert% hm, no stretch but a dimen anyway
1951         \fi
1952      \relax}
1953
1954    \permanent\def\docalculatetotalnoteheight
1955      {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
1956         \advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
1957       \fi}
1958
1959    \permanent\def\docalculatetotalclevernoteheight
1960      {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
1961         \advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
1962       \fi}
1963
1964    \permanent\def\docalculatetotalpagenoteheight
1965      {\advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}}
1966
1967    \permanent\def\calculatetotalnoteheight      {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
1968    \permanent\def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
1969    \permanent\def\calculatetotalpagenoteheight  {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight}
1970
1971%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing
1972%D footnotes? The solution turned out to be rather simple:
1973%D
1974%D \starttyping
1975%D \everypar  {...\flushnotes...}
1976%D \neverypar {...\postponenotes}
1977%D \stoptyping
1978%D
1979%D We can use \type {\neverypar} because in most commands sensitive to footnote
1980%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact,
1981%D this footnote implementation is the first to use this scheme.
1982
1983%D This is a nasty and new secondary footnote flusher. It can be hooked into \type
1984%D {\everypar} like:
1985%D
1986%D \starttyping
1987%D \appendtoks \synchronizenotes \to \everypar
1988%D \stoptyping
1989
1990% \let\synchronizenotes\relax
1991
1992%D When typesetting footnotes, we have to return to the footnote specific bodyfont
1993%D size, which is in most cases derived from the global document bodyfont size. In
1994%D the previous macros we already used a footnote specific font setting macro.
1995
1996\def\strc_notes_set_bodyfont
1997  {\let\strc_notes_set_bodyfont\relax
1998   \restoreglobalbodyfont
1999   \usebodyfontparameter\noteparameter
2000   \usealignparameter\noteparameter}
2001
2002%D The footnote mechanism defaults to a traditional one column way of showing them.
2003%D By default we precede them by a small line.
2004
2005% end notes in the margin:
2006%
2007% \setuptexttexts
2008%   [margin]
2009%   [] [{\directsetup{notabene}}]
2010%
2011% \startsetups notabene
2012%     \vbox to \textheight \bgroup
2013%         \setupalign[tolerant]
2014%         \topskipcorrection
2015%         \placenotes[endnote][before=,after=]
2016%         \vfilll
2017%     \egroup
2018% \stopsetups
2019
2020\definenote [\v!footnote]
2021\definenote [\v!endnote ] [\c!location=\v!none] % else no break
2022\definenote [\v!mathnote] [\c!location=\v!none]
2023
2024%D Compatibility macros:
2025
2026\permanent\protected\def\setupfootnotedefinition{\setupnotation                   [\v!footnote]}
2027\permanent\protected\def\setupfootnotes         {\setupnote                       [\v!footnote]}
2028\permanent          \def\footnotetext           {\setnotetext                     [\v!footnote]}
2029\permanent\protected\def\placefootnotes         {\strc_notes_place_footnotes      [\v!footnote]}
2030\permanent\protected\def\placelocalfootnotes    {\strc_notes_place_local_footnotes[\v!footnote]}
2031\permanent\protected\def\startlocalfootnotes    {\startlocalnotes                 [\v!footnote]} %  alleen footnote
2032\permanent\protected\def\stoplocalfootnotes     {\stoplocalnotes }
2033
2034\tolerant\def\strc_notes_place_footnotes[#list]#spacer[#S#settings]%
2035  {\ifarguments\or
2036     \placenotes[#list][\c!height=\textheight]%
2037   \or
2038     \placenotes[#list][#settings,\c!height=\textheight]%
2039   \fi}
2040
2041\tolerant\def\strc_notes_place_local_footnotes[#list]#spacer[#S#settings]%
2042  {\ifarguments\or
2043     \placelocalnotes[#list][\c!height=\textheight]%
2044   \or
2045     \placelocalnotes[#list][#settings,\c!height=\textheight]%
2046   \fi}
2047
2048%D Goodies:
2049%D
2050%D \starttyping
2051%D \dorecurse {100} {
2052%D     test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
2053%D }
2054%D \stoptyping
2055
2056\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}}
2057
2058\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage
2059
2060%D New trickery:
2061
2062%D \macros
2063%D   {note}
2064%D
2065%D Refering to a note is accomplished by the rather short command:
2066%D
2067%D \showsetup{note}
2068%D
2069%D This command is implemented rather straightforward as:
2070
2071\installcorenamespace{notesymbol}
2072
2073\mutable\lettonothing\lastnotesymbol % todo: per class
2074
2075\permanent\tolerant\protected\def\notesymbol[#tag]#keepspacer[#reference]%
2076  {\ifnotesenabled
2077     \dontleavehmode
2078     \begingroup
2079     \cdef\currentnote{#tag}%
2080     \usenotestyleandcolor\c!textstyle\c!textcolor
2081     \ifempty{#reference}%
2082       \noteparameter\c!textcommand\lastnotesymbol % check if command double
2083     \else
2084       \unskip
2085       \noteparameter\c!textcommand{\in[#reference]}% command here?
2086     \fi
2087     \endgroup
2088   \fi}
2089
2090\permanent\tolerant\protected\def\note[#tag]#keepspacer[#reference]%
2091  {\ifempty{#reference}%
2092     \notesymbol[\v!footnote][#tag]%
2093   \else
2094     \notesymbol[#tag][#reference]%
2095   \fi}
2096
2097% will be redone if needed
2098%
2099% \def\ownnotesymbol#1% #1 gets number passed
2100%   {\executeifdefined{\??notesymbol\currentnote}\empty}
2101%
2102% \protected\def\setnotesymbol[#1]#2#3%
2103%   {\prewordbreak % prevent lookback
2104%    \gdefcsname\??notesymbol#1\endcsname{#3}
2105%    \strc_notes_inject_symbol}
2106%
2107% \protected\def\ownnote[#1]#2#3#4%
2108%   {\setnotesymbol[#1]{#2}{#3}%
2109%    \setnotetext  [#1]{#4}}
2110%
2111% \defineconversion
2112%   [ownnote]
2113%   [\ownnotesymbol]
2114
2115% tricky:
2116%
2117% \enabletrackers[nodes.areas]
2118% \enabletrackers[nodes.references]
2119% \enabletrackers[nodes.destinations]
2120%
2121% \setupnotes[interaction=all,rule=no]
2122% \setupinteraction[state=start,focus=standard]
2123%
2124% \starttext
2125%     \goto{\input tufte\relax}[page(2)] \par
2126%     \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par
2127%     \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par
2128%     % \completecontent
2129%     % \chapter{Chapter}
2130%     % \dorecurse{5}{\input knuth}
2131%     a\footnote{\input tufte\par\input ward\relax}
2132% \stoptext
2133
2134%D Bonus:
2135
2136\appendtoks
2137   \setsystemmode\currentnote
2138\to \everysynchronizenote
2139
2140\protect \endinput
2141