strc-not.mklx /size: 71 Kb    last modification: 2023-12-21 09:44
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\hskip\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\protected\defcsname\??constructionnotehandler\v!notation:\v!note\endcsname % in the running text
473  {\ifnotesenabled
474     % do be done elsewhere
475     %
476     %let\currentnote\currentconstructionmain
477     \let\currentnote\currentconstruction % else wrong inheritance
478     %
479     \iftrialtypesetting
480        \strc_notes_inject_dummy
481     \else
482       \begingroup
483       \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}%
484       \processingnote\conditionaltrue
485       \ifconditional\c_strc_notes_skip
486         \glet\lastnotesymbol\strc_notes_inject_symbol_nop
487       \else
488         \iftypesettinglines % otherwise problems with \type <crlf> {xxx}
489           \ignorelines % makes footnotes work in \startlines ... \stoplines
490         \fi
491         \ifconditional\c_strc_notes_symbol
492           \strc_notes_inject_symbol_yes
493         \else
494           \unskip\unskip
495           \glet\lastnotesymbol\strc_notes_inject_symbol_yes
496         \fi
497       \fi
498       \ifconditional\postponingnotes % todo: per note class
499         \global\postponednote\conditionaltrue
500       \orelse\ifconditional\inlocalnotes % todo: per note class
501         \global\postponednote\conditionaltrue
502       \orelse\ifconditional\c_strc_notes_flushed
503         \handlenoteitself\currentnote\currentnotenumber
504       \orelse\ifconditional\c_strc_notes_delayed
505         % probably end notes
506       \else
507         \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed
508       \fi
509       \endgroup
510     \fi
511   \fi
512   \ifconditional\c_strc_notes_skip
513     \global\c_strc_notes_skip\conditionalfalse
514   \else
515     \boundary\noteboundary
516   \fi}
517
518%D Interaction in notes is somewhat complex due to the way notes get flushed. In
519%D principle it is more or less the same as lists but where in lists we pack whole
520%D entries, in notes this doesn't happen. Okay, in retrospect we could have made
521%D descriptions lists but that will be a backward compatibility mess. At some point
522%D a completely new mechanism might show up, but not now. Also, as notes are inserts
523%D there is some extra mess to be kept in mind and it's easier to maintain two
524%D mechanisms than to combine too much.
525%D
526%D Interaction is also complicated because we want to provide several variants. For
527%D simple reference there is no need for anything special, as page references will
528%D do and we store them in the list anyway. But if we want a destination with
529%D dimensions we will use an additional destination because we can have only one
530%D with the same name and we always have the number as one.
531
532% interaction:
533%
534% all       : text and number
535% number|yes: only number
536% text      : only text
537%
538% \dogetsimple : injects
539
540\installcorenamespace{noteinteractioninline}
541\installcorenamespace{noteinteractiondisplay}
542
543\newconstant\a_strc_notes_symbol_reference
544\newconstant\a_strc_notes_number_reference
545\newconstant\a_strc_notes_text_reference
546\newconstant\a_strc_notes_text_destination
547
548\lettonothing\strc_notes_get_reference_attribute_symbol
549\lettonothing\strc_notes_get_destination_attribute_symbol
550
551\def\strc_notes_interaction_check_inline
552  {\edef\p_interaction{\noteparameter\c!interaction}%
553   \csname\??noteinteractioninline
554     \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi
555   \endcsname}
556
557\def\strc_notes_interaction_check_display
558  {\edef\p_interaction{\noteparameter\c!interaction}%
559   \csname\??noteinteractiondisplay
560     \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi
561   \endcsname}
562
563\mutable\let\currentnotenumber\!!zerocount
564
565\lettonothing\strc_notes_get_reference_attribute_symbol
566\lettonothing\strc_notes_get_destination_attribute_symbol
567
568\let\strc_notes_set_reference_attribute_number\donothing
569\let\strc_notes_set_reference_attribute_text  \donothing
570\let\strc_notes_set_destination_attribute_text\donothing
571
572\let\strc_notes_set_style_color_inline \relax
573\let\strc_notes_set_style_color_display\relax
574
575% inline
576
577\let\m_strc_notes_internal\relax
578
579\def\strc_notes_prepare_inline_references_nop
580  {\lettonothing\strc_notes_get_reference_attribute_symbol
581   \lettonothing\strc_notes_get_destination_attribute_symbol
582   \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop}
583
584\def\strc_notes_prepare_inline_references_yes
585  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
586   \strc_references_set_simple_reference{*\m_strc_notes_internal}% destination
587   \strc_references_get_simple_reference{internal(\m_strc_notes_internal)}% reference
588   \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}%
589   \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
590   \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes}
591
592\letcsname\??noteinteractioninline\v!no    \endcsname\strc_notes_prepare_inline_references_nop
593\letcsname\??noteinteractioninline\v!all   \endcsname\strc_notes_prepare_inline_references_yes
594\letcsname\??noteinteractioninline\v!number\endcsname\strc_notes_prepare_inline_references_yes
595\letcsname\??noteinteractioninline\v!text  \endcsname\strc_notes_prepare_inline_references_yes
596\letcsname\??noteinteractioninline\v!yes   \endcsname\strc_notes_prepare_inline_references_yes
597
598% display (for 'all' we need unique text and number attributes so we resolve twice
599% as we otherwise don't get the number one which is lapped in the margin so we need
600% to explicitly visit it)
601
602\def\strc_notes_prepare_display_references_nop
603  {\let\strc_notes_set_reference_attribute_number\donothing
604   \let\strc_notes_set_reference_attribute_text\donothing
605   \let\strc_notes_set_destination_attribute_text\donothing
606   \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop}
607
608\def\strc_notes_prepare_display_references_yes_number
609  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
610   \ifcase\m_strc_notes_internal\relax
611     \strc_notes_prepare_display_references_nop
612   \else
613     \let\strc_notes_set_reference_attribute_text\donothing
614     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
615     \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}%
616     \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
617   \fi}
618
619\def\strc_notes_prepare_display_references_yes_text
620  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
621   \ifcase\m_strc_notes_internal\relax
622     \strc_notes_prepare_display_references_nop
623   \else
624     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
625     \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
626     \let\strc_notes_set_reference_attribute_number\donothing
627     \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes
628   \fi}
629
630\def\strc_notes_prepare_display_references_yes_all
631  {\edef\m_strc_notes_internal{\clf_noteinternal{\currentnote}\currentnotenumber}%
632   \ifcase\m_strc_notes_internal\relax
633     \strc_notes_prepare_display_references_nop
634   \else
635     \strc_references_get_simple_reference{*\m_strc_notes_internal}% reference
636     \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}%
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\letcsname\??noteinteractiondisplay\v!no    \endcsname\strc_notes_prepare_display_references_nop
643\letcsname\??noteinteractiondisplay\v!all   \endcsname\strc_notes_prepare_display_references_yes_all
644\letcsname\??noteinteractiondisplay\v!number\endcsname\strc_notes_prepare_display_references_yes_number
645\letcsname\??noteinteractiondisplay\v!text  \endcsname\strc_notes_prepare_display_references_yes_text
646\letcsname\??noteinteractiondisplay\v!yes   \endcsname\strc_notes_prepare_display_references_yes_number
647
648\mutable\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor
649\mutable\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor
650
651\protected\def\strc_notes_set_style_color_inline_yes#style#color%
652  {\usenotestyleandcolor#style#color%
653   \iflocation\strc_notes_set_style_color_special\fi}
654
655\protected\def\strc_notes_set_style_color_display_yes#style#color%
656  {\usenotationstyleandcolor#style#color%
657   \iflocation\strc_notes_set_style_color_special\fi}
658
659\def\strc_notes_set_style_color_special
660  {\iftrialtypesetting
661      % keep
662   \orelse\ifempty\currentcolorparameter
663     \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once
664     \setlocationcolorspecified\scratchcounter
665   \fi}
666
667\defcsname\??constructiontexthandler\v!notation\endcsname
668  {\begingroup
669   % we need to retrigger the reference as otherwise it gets lost because we don't do nested
670   % references with the same id ... maybe some day if we can figure out a nice heuristic ...
671   % the problem is that normally it's no issue but here we lap into the margin, so maybe that's
672   % a criterium
673 % \strc_notes_interaction_check_display
674   \strc_notes_set_reference_attribute_number
675   \dotagsetnotation
676   \strc_notes_set_style_color_display\c!headstyle\c!headcolor
677   \strc_enumerations_text
678   \endgroup}
679
680% in mkii the pointer only showed up in pagewise notes
681
682\protected\def\strc_notes_inject_pointer % todo calculate once
683  {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax
684     % unknown
685   \or
686     % same page
687   \or
688     \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}%
689   \or
690     \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}%
691   \fi}
692
693\protected\def\strc_notes_inject_symbol_yes
694  {\strc_notes_inject_symbol_indeed\conditionaltrue}
695
696\protected\def\strc_notes_inject_symbol_nop
697  {\strc_notes_inject_symbol_indeed\conditionalfalse}
698
699\definemargindata
700  [strc_notes_destination_margin]
701  [\v!left]
702  [\c!margin=\zeropoint,
703   \c!width=\zeropoint,
704   \c!style=,
705   \c!color=]
706
707\protected\def\strc_notes_inject_symbol_indeed#synchronize%
708  {\ifconditional\c_strc_notations_anchored_next\else
709     \removeunwantedspaces
710     \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
711   \fi
712   \ifnum\lastboundary=\noteboundary
713     \unboundary
714   % \kern\noteparameter\c!distance % yes or no note font? or main text
715     \strc_notes_inject_separator
716   \fi
717   \nobreak
718   \begingroup
719   \strc_notes_interaction_check_inline\strc_notes_set_style_color_inline\c!textstyle\c!textcolor
720   \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup
721  % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack
722     \strc_references_flush_destination_nodes % a bit late but ok
723     \dostarttagged\t!descriptionsymbol\currentnote
724     \dotagsetnotesymbol
725     \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}%
726     % the next one can cycle so we need to make sure it has no advance width
727     \ifcstok{\noteparameter\c!indicator}\v!yes
728       \strc_notes_inject_pointer
729     \fi
730     \dostoptagged
731   \egroup
732   \endgroup
733   \glettonothing\lastnotesymbol}
734
735\protected\def\strc_notes_inject_dummy % temp hack
736  {\removeunwantedspaces
737   \doifelseitalic\/\donothing % Charles IV \footnote{the fourth}
738   \ifnum\lastboundary=\noteboundary
739     \unboundary
740   % \kern\noteparameter\c!distance % yes or no note font? or main text
741     \strc_notes_inject_separator
742   \fi
743   \nobreak
744   \hpack to .5\emwidth{}%
745   \glettonothing\lastnotesymbol}
746
747\protected\def\strc_notes_inject_separator % patch by WS due to request on list
748  {\edef\p_textseparator{\noteparameter\c!textseparator}%
749   \ifempty\p_textseparator
750     \kern\noteparameter\c!distance
751   \else
752     % skip or kern
753     \nobreak
754     \hbox\bgroup
755       \usenotestyleandcolor\c!textstyle\c!textcolor
756       \noteparameter\c!textcommand{\p_textseparator}%
757       \kern\noteparameter\c!distance
758     \egroup
759     \nobreak
760   \fi}
761
762% this needs a further cleanup ... soon as it's a slow mechanism
763%
764% -- set breakpoint in descriptions
765% -- reset after trialtypesetting
766% -- that way we can trick the symbol space
767
768% removed:
769%
770% \pushsomestates
771%
772% core-ins -> obsolete
773%
774% saveinsertiondata
775% restoreinsertiondata
776% saveinsertionbox
777% eraseinsertionbackup
778% restoreinsertionbackup
779
780% \def\savenotedata      {} % \writestatus{todo}{save    note data}}
781% \def\restorenotedata   {} % \writestatus{todo}{restore note data}}
782% \def\savenotecontent   {} % \writestatus{todo}{save    note content}}
783% \def\restorenotecontent{} % \writestatus{todo}{restore note content}}
784% \def\erasenotebackup   {} % \writestatus{todo}{erase   note backup}}
785
786% page-set:
787
788% \def\enablenotes    {\writestatus{todo}{enable  notes}}
789% \def\disablenotes   {\writestatus{todo}{disable notes}}
790% \def\savenotes      {\writestatus{todo}{save    notes}}
791% \def\flushsavednotes{\writestatus{todo}{flush   notes}}
792
793% experiment: (compare scope=text and scope=page)
794%
795% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0]
796% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
797
798%D Footnotes are can be characterized by three components:
799%D
800%D \startitemize[packed]
801%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes
802%D   [conversion=set 2]\footnote {a footnote}}
803%D \item and a similar mark at the bottom of the page
804%D \item followed by some additional text
805%D \stopitemize
806%D
807%D Because footnotes are declared at the location of their reference they can be
808%D seen as a special kind of floating bodies. Their placement is postponed but has
809%D to be taken into account in the pagebreak calculations. This kind of calculations
810%D are forced by using \type{\insert}s and dealing with all cases is not trivial.
811
812%D \macros
813%D   {notesenabled}
814%D
815%D We need a couple of states because at some moments we don't want to mess around
816%D with inserts at all. Take for instance a table of contents. And so we can
817%D temporary disable footnotes by saying
818%D
819%D \starttyping
820%D \notesenabledfalse
821%D \stoptyping
822
823\newif\ifnotesenabled \notesenabledtrue
824
825% better mark a note .. once flushed no more flushing
826
827%appendtoks \notesenabledfalse \to \everymarking
828\appendtoks \notesenabledfalse \to \everybeforepagebody
829\appendtoks \notesenabledfalse \to \everystructurelist    % quick hack
830\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack
831\appendtoks \notesenabledfalse \to \everypreroll          % quick hack
832
833%D Often we need to process the whole set of notes and to make that fast, we use a
834%D token register:
835
836% we have several synchronizers:
837%
838% - after a definition
839% - after a specific setup
840% - after a general setup (inheritance of dimensions)
841% - just before a note is typeset
842
843\newtoks\t_strc_notes
844
845\let\strc_notes_process_list\gobbleoneargument
846
847\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote
848  {\def\strc_notes_process_list##1{\cdef\currentnote{##1}\let\currentdescription\currentnote#action}%
849   \expand\t_strc_notes}
850
851\newtoks\everychecknote       % just before a note is typeset
852\newtoks\everysynchronizenote % after a general setup has happened
853
854\appendtoks
855    \ifempty\currentnote \else
856        \setupnotations[\currentnote][]% also a synchronize
857    \fi
858\to \everysynchronizenote
859
860\def\strc_notes_synchronize
861  {\expand\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist
862
863\appendtoks
864    \strc_notes_process\strc_notes_synchronize
865\to \everysetupnoteroot
866
867\appendtoks
868    \expand\everysynchronizenote
869\to \everydefinenote
870
871% \starttext
872%     text \startfootnote Test.\stopfootnote
873%     test \footnote{xxxx} \subfootnote{xxxx}
874%     test \footnote{xxxx} \subfootnote{xxxx}
875% \stoptext
876
877\installcorenamespace{notecommand}
878\installcorenamespace{notealign}
879\installcorenamespace{notepenalty}
880\installcorenamespace{noterule}
881
882\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname}
883\permanent\protected\def\currentnoterulealign  {\begincsname\??notealign  \currentnote\endcsname}
884
885\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand}
886\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards
887
888\permanent\protected\def\letcurrentnoterulecommand{\enforced\letcsname\??notecommand\currentnote\endcsname}
889\permanent\protected\def\letcurrentnoterulealign  {\enforced\letcsname\??notealign  \currentnote\endcsname}
890
891\appendtoks
892    \enforced\letcsname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal
893    \enforced\letcsname\??notealign  \currentnote\endcsname\lefttoright
894\to \everysynchronizenote
895
896\def\strc_notes_set_rule
897  {\letcurrentnoterulecommand\relax % so we default to nothing
898   \letcurrentnoterulealign  \relax
899   \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step}
900
901\def\strc_notes_set_rule_step#alternative%
902  {\begincsname\??noterule#alternative\endcsname}
903
904\def\strc_notes_set_rule_autodir
905  {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright}
906
907\defcsname\??noterule  \v!command\endcsname{\letcurrentnoterulecommand\currentnoterulecommandcommand}
908\defcsname\??noterule       \v!on\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal}
909\defcsname\??noterule   \v!normal\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal}
910\defcsname\??noterule     \v!left\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
911                                            \letcurrentnoterulealign  \lefttoright}
912\defcsname\??noterule    \v!right\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
913                                            \letcurrentnoterulealign  \righttoleft}
914\defcsname\??noterule\v!paragraph\endcsname{\letcurrentnoterulecommand\currentnoterulecommandnormal
915                                            \letcurrentnoterulealign  \strc_notes_set_rule_autodir}
916\defcsname\??noterule      \v!off\endcsname{\letcurrentnoterulecommand\relax}
917
918\appendtoks
919    \strc_notes_set_rule
920\to \everysynchronizenote
921
922\permanent\def\currentnotepenalty
923  {\ifcsname\??notepenalty\noteparameter\c!split\endcsname
924     \lastnamedcs
925   \else
926     \numexpr\noteparameter\c!split\relax
927   \fi}
928
929\setnewconstant\notepenaltytolerant  \zerocount
930\setnewconstant\notepenaltystrict    9999
931\setnewconstant\notepenaltyverystrict\maxdimen
932
933\letcsname\??notepenalty\v!tolerant  \endcsname\notepenaltytolerant
934\letcsname\??notepenalty\v!strict    \endcsname\notepenaltystrict
935\letcsname\??notepenalty\v!verystrict\endcsname\notepenaltyverystrict
936\letcsname\??notepenalty             \endcsname\notepenaltytolerant
937
938%D The following switch can be used to disable limiting the height of the footnote
939%D area, something that is needed in multi column balancing. Use this switch with
940%D care.
941
942\newif\ifnotelimit \notelimittrue % shared
943
944\def\strc_notes_set_factor
945  {\edef\p_factor{\noteparameter\c!factor}%
946   \ifempty\p_factor \else
947     \ifnum\p_factor<\zerocount \else
948%        \global
949       \page_inserts_set_multiplier\currentnoteinsertionnumber\p_factor % new: global
950     \fi
951   \fi}
952
953\appendtoks
954    \strc_notes_set_factor
955\to \everysynchronizenote
956
957% locations:
958
959\installcorenamespace{notelocationvariant}
960\installcorenamespace{notepositionvariant}
961\installcorenamespace{notedelayedvariant}
962\installcorenamespace{notelocation}
963
964\newconditional\c_strc_notes_delayed
965\newconditional\c_strc_notes_flushed
966
967\protected\def\strc_notes_set_delayed_yes{\c_strc_notes_delayed\conditionaltrue\c_strc_notes_flushed\conditionalfalse}
968\protected\def\strc_notes_set_delayed_nop{\c_strc_notes_delayed\conditionalfalse\c_strc_notes_flushed\conditionalfalse}
969\protected\def\strc_notes_set_delayed_lst{\c_strc_notes_delayed\conditionaltrue\c_strc_notes_flushed\conditionaltrue}
970
971\defcsname\??notelocation\v!page\endcsname
972  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
973   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_page}
974
975\defcsname\??notelocation\v!columns\endcsname
976  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
977   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_columns}
978
979\defcsname\??notelocation\v!lastcolumn\endcsname
980  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
981   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_lastcolumn}
982
983\defcsname\??notelocation\v!firstcolumn\endcsname
984  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_nop
985   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_firstcolumn}
986
987\defcsname\??notelocation\v!none\endcsname
988  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_yes
989   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_none}
990
991\defcsname\??notelocation\v!list\endcsname
992  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_lst
993   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_none}
994
995\defcsname\??notelocation\v!text\endcsname
996  {\letcsname\??notedelayedvariant \currentnote\endcsname\strc_notes_set_delayed_yes
997   \letcsname\??notelocationvariant\currentnote\endcsname\strc_notes_set_location_text}
998
999\defcsname\??notelocation\v!high\endcsname
1000  {\letcsname\??notepositionvariant\currentnote\endcsname\strc_notes_set_position_high}
1001
1002\defcsname\??notelocation\v!bottom\endcsname
1003  {\letcsname\??notepositionvariant\currentnote\endcsname\strc_notes_set_position_bottom}
1004
1005\defcsname\??notedelayedvariant \??notedelayedvariant \endcsname{\strc_notes_set_delayed_nop    } % not \let
1006\defcsname\??notepositionvariant\??notepositionvariant\endcsname{\strc_notes_set_position_bottom} % not \let
1007\defcsname\??notelocationvariant\??notelocationvariant\endcsname{\strc_notes_set_location_page  } % not \let
1008
1009\protected\def\strc_notes_set_delayed
1010  {\csname\??notedelayedvariant
1011     \ifcsname\??notedelayedvariant\currentnote\endcsname
1012       \currentnote
1013     \else
1014       \??notedelayedvariant
1015     \fi
1016   \endcsname}
1017
1018\protected\def\strc_notes_set_position
1019  {\csname\??notepositionvariant
1020     \ifcsname\??notepositionvariant\currentnote\endcsname
1021       \currentnote
1022     \else
1023       \??notepositionvariant
1024     \fi
1025   \endcsname}
1026
1027\protected\def\strc_notes_set_location
1028  {\csname\??notelocationvariant
1029     \ifcsname\??notelocationvariant\currentnote\endcsname
1030       \currentnote
1031     \else
1032       \??notelocationvariant
1033     \fi
1034   \endcsname}
1035
1036\protected\def\strc_notes_set_variants
1037  {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
1038
1039\protected\def\strc_notes_set_location_step#alternative% the insert related one
1040  {\begincsname\??notelocation#alternative\endcsname}
1041
1042\appendtoks
1043    \strc_notes_set_variants
1044    \strc_notes_set_delayed
1045\to \everysynchronizenote
1046
1047\newgluespec   \s_strc_notes_distance % we need to implement stretch
1048\newinteger    \c_strc_notes_columns
1049\newgluespec   \s_strc_notes_before
1050\newgluespec   \s_strc_notes_inbetween
1051\newconditional\c_strc_notes_first_flushed
1052
1053% we can store them per insert so so real need to redo it
1054
1055\appendtoks
1056    \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}%
1057    \ifempty\p_spacebefore
1058        \global\s_strc_notes_before\zeropoint
1059    \else
1060        \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}%
1061    \fi
1062    \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}%
1063    \ifempty\p_spaceinbetween
1064        \global\s_strc_notes_inbetween\zeropoint
1065    \else
1066        \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}%
1067    \fi
1068\to \everysynchronizenote
1069
1070\def\strc_notes_set_distance
1071  {\begingroup
1072   \restoreglobalbodyfont
1073   \setbox\scratchbox\vbox % no reuse as it can mirror
1074     {\forgetall
1075      \dontcomplain
1076      \noteparameter\c!before
1077      \placenoterule
1078      \strut
1079      \noteparameter\c!after}%
1080   % also dp now
1081   \scratchdimen\dimexpr\htdp\scratchbox-\lineheight\relax
1082   \ifgridsnapping
1083     \getnoflines\scratchdimen
1084     \scratchdimen\noflines\lineheight
1085   \fi
1086   \expandafter\endgroup\expandafter
1087   \s_strc_notes_distance\the\scratchdimen\relax}
1088
1089\def\strc_notes_set_columns
1090  {\c_strc_notes_columns\noteparameter\c!n\relax
1091   \ifcase\c_strc_notes_columns
1092     \c_strc_notes_columns\plusone
1093   \fi}
1094
1095\def\strc_notes_set_location_page
1096  {\c_strc_notes_delayed\conditionalfalse
1097   \strc_notes_set_distance
1098   \strc_notes_set_columns
1099   \page_inserts_set_location  \currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]%
1100   \page_inserts_set_multiplier\currentnoteinsertionnumber\numexpr(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns\relax
1101   \page_inserts_set_limit     \currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
1102   \page_inserts_set_distance  \currentnoteinsertionnumber\s_strc_notes_distance}
1103
1104\def\strc_notes_set_location_columns
1105  {\c_strc_notes_delayed\conditionalfalse
1106   \strc_notes_set_distance
1107   \strc_notes_set_columns
1108 % \ifnum\currentnofcolumns=\zerocount
1109   \ifnum\nofcolumns=\zerocount
1110     \c_strc_notes_columns\plusone
1111   \fi
1112   \page_inserts_set_location  \currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]%
1113   \page_inserts_set_multiplier\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
1114   \page_inserts_set_limit     \currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
1115   \page_inserts_set_distance  \currentnoteinsertionnumber\s_strc_notes_distance}
1116
1117\def\strc_notes_set_location_somecolumn#whatcolumn%
1118  {\c_strc_notes_delayed\conditionalfalse
1119   \strc_notes_set_distance
1120   \strc_notes_set_columns
1121   \page_inserts_set_location  \currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]%
1122   \page_inserts_set_multiplier\currentnoteinsertionnumber\plusthousand
1123   \page_inserts_set_limit     \currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
1124   \page_inserts_set_distance  \currentnoteinsertionnumber\s_strc_notes_distance}
1125
1126\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn}
1127\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn }
1128
1129\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
1130  {\c_strc_notes_delayed\conditionaltrue
1131   \clf_setnotestate{\currentnote}{store}%
1132   \page_inserts_set_location  \currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]%
1133   \page_inserts_set_multiplier\currentnoteinsertionnumber\zerocount
1134   \page_inserts_set_limit     \currentnoteinsertionnumber\maxdimen
1135   \page_inserts_set_distance  \currentnoteinsertionnumber\zeropoint}
1136
1137\let\strc_notes_set_location_none\strc_notes_set_location_text
1138
1139\def\strc_notes_set_properties
1140  {\strc_notes_set_columns
1141   \strc_notes_set_distance
1142   \strc_notes_set_location
1143   \strc_notes_set_delayed}
1144
1145\let\strc_notes_set_position_high\relax
1146
1147\def\strc_notes_set_position_bottom
1148  {\c_notes_bottom_present\conditionaltrue}
1149
1150\appendtoks
1151    \strc_notes_set_properties
1152\to \everysynchronizenote
1153
1154%D A fast checker for bottom notes being used:
1155
1156\newconditional\c_notes_bottom_present
1157
1158% \def\strc_notes_check_if_bottom_present_indeed % in otr !
1159%   {\ifvoid\currentnoteinsertionnumber\else
1160%      \strc_notes_set_position
1161%    \fi}
1162
1163\def\strc_notes_check_if_bottom_present_indeed % in otr !
1164  {\ifzeropt\page_inserts_get_height\currentnoteinsertionnumber\else
1165     \strc_notes_set_position
1166   \fi}
1167
1168\def\strc_notes_check_if_bottom_present_step
1169  {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi}
1170
1171\def\strc_notes_check_if_bottom_present
1172  {\c_notes_bottom_present\conditionalfalse
1173   \strc_notes_process\strc_notes_check_if_bottom_present_step}
1174
1175% Example of using factor:
1176%
1177% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0]
1178% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle]
1179% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][]
1180% \starttext
1181% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} }
1182% \stoptext
1183
1184%D The noterule can be a graphic and therefore calling this setup macro at every
1185%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that
1186%D probably match those of the stretch component. A bit messy:
1187
1188\permanent\protected\def\placenoterule
1189  {\begingroup
1190   \currentnoterulealign
1191   \currentnoterulecommand
1192   \par
1193   \endgroup}
1194
1195\permanent\protected\def\normalnoterule
1196  {\ifvmode
1197     \dontleavehmode \blackrule
1198       [\c!color=\noteparameter\c!rulecolor,
1199        \c!width=.2\hsize,
1200        \c!height=\noteparameter\c!rulethickness,
1201        \c!depth=\zeropoint]%
1202     \endgraf
1203     \kern\strutdepth
1204   \fi}
1205
1206%D The formatting depends on the width of the table, so we have to set \type {n} to
1207%D zero.
1208%D
1209%D \starttyping
1210%D \startbuffer
1211%D \bTABLE
1212%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR
1213%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR
1214%D \eTABLE
1215%D \stopbuffer
1216%D
1217%D \startlocalfootnotes[n=0,location={text,none}]
1218%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes}
1219%D \stoplocalfootnotes
1220%D \stoptyping
1221
1222%D \macros
1223%D   {footnote}
1224%D
1225%D A footnote can have a reference as optional argument and therefore its formal
1226%D specification looks like:
1227%D
1228%D \showsetup{footnote}
1229%D
1230%D This command has one optional command: the reference. By saying \type{[-]} the
1231%D number is omitted. The footnote command is not that sensitive to spacing, so it's
1232%D quite legal to say:
1233%D
1234%D \startbuffer
1235%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the
1236%D ground and not get confused \footnote {Or even crazy.} by all those obscure
1237%D \footnote {But fortunately readable.} parameters.
1238%D \stopbuffer
1239%D
1240%D \typebuffer
1241%D
1242%D When setting the \type{conversion} to \type{set 2} we get
1243%D something like:
1244%D
1245%D \bgroup
1246%D \startnarrower
1247%D \setupfootnotes[conversion=set 1]
1248%D \getbuffer
1249%D \stopnarrower
1250%D \egroup
1251%D
1252%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes.
1253%D The additional macro \type {\footnotetext} and the associated \type {\note} macro
1254%D were implemented at request of users on the mailing list and a suggestion by taco
1255%D to split of the symbol placement. I decided to merge this functionality with the
1256%D existing \type {\note} functionality.
1257
1258\newconditional\c_strc_notes_symbol \c_strc_notes_symbol\conditionaltrue % not used
1259\newconditional\c_strc_notes_skip
1260
1261\permanent\protected\def\setnote    [#tag]{\csname#tag\endcsname}
1262\permanent\protected\def\setnotetext[#tag]{\global\c_strc_notes_skip\conditionaltrue\csname#tag\endcsname}
1263
1264\permanent\protected\def\handlenoteinsert#tag#id%
1265  {\begingroup
1266   \cdef\currentnote{#tag}%
1267   \strc_constructions_initialize{#tag}%
1268   \strc_notes_synchronize
1269   \expand\everybeforenoteinsert
1270   \insert\currentnoteinsertionnumber\bgroup
1271     \expand\everyinsidenoteinsert\relax
1272     \usesetupsparameter\noteparameter % experimental
1273     \useinterlinespaceparameter\noteparameter
1274     \ifcstok{\noteparameter\c!paragraph}\v!yes
1275       \nointerlineskip
1276       \startvboxtohboxseparator
1277         \noteparameter\c!inbetween
1278       \stopvboxtohboxseparator
1279       \startvboxtohbox
1280         \handlenoteitself{#tag}{#id}%
1281       \stopvboxtohbox
1282     \else
1283       \handlenoteitself{#tag}{#id}%
1284     \fi
1285   \egroup
1286   \expand\everyafternoteinsert
1287   \endgroup}
1288
1289\permanent\protected\def\betweennoteitself#tag% used ?
1290  {\cdef\currentnote{#tag}%
1291   \ifcstok{\noteparameter\c!paragraph}\v!yes
1292     \noteparameter\c!inbetween
1293   \fi}
1294
1295\permanent\protected\def\handlenoteitself#tag#id%
1296  {\edef\currentnotenumber{#id}%
1297   \cdef\currentnote{#tag}%
1298   \strc_constructions_initialize{#tag}%
1299   \strc_notes_synchronize
1300   \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache
1301   % as we can have collected notes (e.g. in tables) we need to recover
1302   % \currentdescriptionattribute and \currentdescriptionsynchronize
1303   %
1304   \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table)
1305   %
1306   \dontcomplain
1307   %begingroup
1308   \strc_notes_interaction_check_display
1309   \strc_notes_set_reference_attribute_text
1310   \strc_constructions_stored_start
1311   \begstrut
1312   \strc_references_flush_destination_nodes
1313   \strc_notes_set_destination_attribute_text
1314   \ifconditional\c_strc_notes_flushed\else
1315     \strc_notes_inject_text\relax
1316   \fi
1317   \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10
1318   \strc_constructions_stored_stop
1319   %endgroup
1320   }
1321
1322\protected\def\strc_notes_inject_text % hm main?
1323  {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}
1324
1325\installstructurelistprocessor{construction}{\usestructurelistprocessor{section}}
1326
1327\newboundary\noteboundary
1328
1329\newconditional\processingnote
1330\newconditional\postponednote
1331
1332\newtoks\everybeforenoteinsert
1333\newtoks\everyinsidenoteinsert
1334\newtoks\everyafternoteinsert
1335
1336\permanent\protected\def\doifelseinnote
1337  {\ifconditional\processingnote
1338     \expandafter\firstoftwoarguments
1339   \else
1340     \expandafter\secondoftwoarguments
1341   \fi}
1342
1343\appendtoks
1344   \enforced\lettonothing\flushnotes
1345   \enforced\lettonothing\postponenotes
1346   \forgetall
1347   \resetallattributes   % new, we don't want color bleed into notes
1348   \inheritmaintextcolor % but we do want to obey the textcolor
1349\to \everybeforenoteinsert
1350
1351\def\strc_notes_set_penalties
1352  {% stored in insert node
1353   \floatingpenalty \currentnotepenalty % now per note
1354   \page_inserts_set_penalty\currentnoteinsertionnumber\currentnotepenalty
1355   % used when typesetting
1356   \interlinepenalty\plushundred % plain value
1357   % used when we need to split in columns
1358   \ifnum\noteparameter\c!n>\plusone
1359     \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated)
1360   \fi}
1361
1362\appendtoks
1363    \strc_notes_set_penalties
1364    \forgetall % again
1365    \strc_notes_set_bodyfont
1366    \redoconvertfont % to undo \undo calls in in headings etc
1367    \splittopskip\strutht  % not actually needed here
1368    \splitmaxdepth\strutdp % not actually needed here
1369\page_inserts_set_maxdepth  \currentnoteinsertionnumber\strutdp
1370    %
1371    % not:
1372    %
1373  % \leftmargindistance \noteparameter\c!margindistance
1374  % \rightmargindistance\leftmargindistance
1375  % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
1376  %   \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
1377  % \fi
1378    %
1379    \pickupattributes
1380\to \everyinsidenoteinsert
1381
1382%D Nasty, the might be more:
1383
1384\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert
1385\appendtoks \strc_itemgroups_pop  \to \everyafternoteinsert
1386
1387% maybe but better use [scope=local] here
1388%
1389% \appendtoks
1390%     \inhibitmargindata\conditionalfalse
1391% \to \everyinsidenoteinsert
1392
1393\setupnotes
1394  [\c!width=\v!auto]
1395
1396% \permanent\protected\def\setnotehsize
1397%   {\ifinsidemulticolumns
1398%      \setnoteparameter\c!width{\makeupwidth}%
1399%    \else
1400%      \edef\p_width{\noteparameter\c!width}%
1401%      \ifx\p_width\v!auto
1402%      % \ifinsidecolumns
1403%          \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}%
1404%      % \else
1405%      %   \setnoteparameter\c!width{\makeupwidth}%
1406%      % \fi
1407%      \orelse\ifempty\p_width
1408%        \setnoteparameter\c!width{\hsize}%
1409%      \fi
1410%   \fi
1411%   \hsize\noteparameter\c!width\relax}
1412%
1413% We construct immediately and migrate so:
1414
1415\permanent\protected\def\setnotehsize
1416  {\edef\p_width{\noteparameter\c!width}%
1417   \ifx\p_width\v!auto
1418     % intercept old value
1419     \let\p_width\makeupwidth
1420     \setnoteparameter\c!width{\makeupwidth}%
1421   \fi
1422   \hsize\p_width\relax}
1423
1424\appendtoks
1425    % only needed when columns (could be three \set...)
1426    \setnotehsize
1427    \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1428\to \everyinsidenoteinsert
1429
1430%D Normally footnotes are saved as inserts that are called upon as soon as the
1431%D pagebody is constructed. The footnote insertion routine looks just like the
1432%D \PLAIN\ \TEX\ one, except that we check for the end note state.
1433
1434% testcase for split bottom alignment see (a) below
1435%
1436% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}}
1437
1438\newconditional\c_strc_notes_first_placed
1439
1440\permanent\protected\def\placenoteinserts
1441  {\c_strc_notes_first_placed\conditionalfalse
1442   \strc_notes_process\strc_notes_place_inserts}
1443
1444\def\strc_notes_place_inserts
1445  {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
1446   \ifconditional\c_strc_notes_delayed \else
1447%      \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test
1448     \ifcase\page_inserts_get_height\currentnoteinsertionnumber\else
1449       \strc_notes_place_inserts_indeed
1450       \c_strc_notes_first_placed\conditionaltrue
1451     \fi
1452   \fi}
1453
1454\def\strc_notes_place_inserts_indeed
1455  {\relax
1456%    \ifdim\ht\currentnoteinsertionnumber>\zeropoint
1457   \ifcase\page_inserts_get_height\currentnoteinsertionnumber\else
1458     \endgraf
1459     \ifvmode
1460       \whitespace
1461       \ifconditional\c_strc_notes_first_placed
1462         \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}%
1463         \ifempty\p_spaceinbetween\else
1464           \blank[\p_spaceinbetween]%
1465         \fi
1466       \else
1467         \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}%
1468         \ifempty\p_spacebefore\else
1469           \blank[\p_spacebefore]%
1470         \fi
1471       \fi
1472       \noteparameter\c!before
1473     \fi
1474     \placenoterule
1475     \bgroup
1476     \strc_notes_set_bodyfont
1477     \setbox\scratchbox\hbox
1478       {\strc_notes_flush_inserts}%
1479     \page_postprocessors_linenumbers_deepbox\scratchbox
1480     \setbox\scratchbox\hbox
1481       {\setupcurrentnote
1482          [\c!location=,
1483           \c!width=\v!fit,
1484           \c!height=\v!fit,
1485           \c!strut=\v!no,
1486           \c!offset=\v!overlay]%
1487        \inheritednoteframed
1488          {\ifzeropt\dp\scratchbox                  % this hack is needed because \vadjust
1489             \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement
1490           \else                                    % hides the (always) present depth
1491             \box\scratchbox
1492           \fi}}%
1493     \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}%
1494     \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth
1495     \ifvmode
1496       \nointerlineskip % else sometimes empty line
1497     \fi
1498     \box\scratchbox
1499     \egroup
1500     \endgraf
1501     \ifvmode
1502       \noteparameter\c!after
1503     \fi
1504   \fi}
1505
1506\def\strc_notes_flush_inserts
1507  {\ifcase\noteparameter\c!n\relax
1508     % should not happen
1509   \or
1510     \strc_notes_flush_inserts_normal
1511   \else
1512     \strc_notes_flush_inserts_columns
1513   \fi}
1514
1515\def\strc_notes_flush_inserts_normal
1516  {\strc_notes_flush_global
1517   \obeydepth} % (a) added , since split footnotes will not align properly
1518
1519\def\strc_notes_flush_inserts_columns
1520  {\begingroup
1521   \setnotehsize % probably still not ok for columns
1522   \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1523     \strc_notes_flush_global
1524   \stopsimplecolumns
1525   \endgroup}
1526
1527% idea: tag with attr and then just flush them again
1528
1529\def\strc_notes_flush_global
1530  {\begingroup
1531   \useinterlinespaceparameter\noteparameter
1532   \ifcstok{\noteparameter\c!paragraph}\v!yes
1533     \leftorrightvbox % cf mail from ws to list
1534       {\starthboxestohbox
1535          \iftrialtypesetting
1536            \page_inserts_get_uncopied
1537          \else
1538            \page_inserts_get_unboxed
1539          \fi
1540          \currentnoteinsertionnumber
1541        \stophboxestohbox}%
1542   \else
1543     \iftrialtypesetting
1544       \ifvmode\page_inserts_get_uncopied\else\page_inserts_get_copied\fi
1545     \else
1546       \ifvmode\page_inserts_get_unboxed \else\page_inserts_get_boxed \fi
1547     \fi
1548     \currentnoteinsertionnumber
1549   \fi
1550   \endgroup}
1551
1552%D Supporting end notes is surprisingly easy. Even better, we can combine this
1553%D feature with solving the common \TEX\ problem of disappearing inserts when
1554%D they're called for in deeply nested boxes. The general case looks like:
1555%D
1556%D \starttyping
1557%D \postponenotes
1558%D \.box{whatever we want with footnotes}
1559%D \flushnotes
1560%D \stoptyping
1561%D
1562%D This alternative can be used in headings, captions, tables etc. The latter one
1563%D sometimes calls for notes local to the table, which can be realized by saying
1564%D
1565%D \starttyping
1566%D \setlocalfootnotes
1567%D some kind of table with local footnotes
1568%D \placelocalfootnotes
1569%D \stoptyping
1570%D
1571%D Postponing is accomplished by simply redefining the (local) insert operation. A
1572%D not too robust method uses the \type{\insert} primitive when possible. This
1573%D method fails in situations where it's not entirely clear in what mode \TEX\ is.
1574%D Therefore the auto method can is to be overruled when needed.
1575
1576\newconditional\postponingnotes
1577
1578% we need a proper state: normal, postponing, flushing
1579
1580\permanent\protected\def\postponenotes % will be locally overloaded
1581  {\ifcase\insertionmigrationmode
1582     \ifconditional\postponingnotes\else
1583       \global\postponingnotes\conditionaltrue
1584       \enforced\glet\flushnotes\doflushnotes
1585       \clf_postponenotes
1586     \fi
1587   \fi}
1588
1589\permanent\lettonothing\flushnotes
1590
1591% also \ifcase\insertionmigrationmode here, needs testing:
1592
1593\permanent\protected\def\startpostponingnotes % experimental, page-mix
1594  {\ifconditional\postponingnotes\else
1595     \global\postponingnotes\conditionaltrue
1596    %\glet\flushnotes\doflushnotes
1597     \clf_postponenotes
1598   \fi}
1599
1600\permanent\protected\def\stoppostponingnotes % experimental, page-mix
1601  {\doflushnotes}
1602
1603\permanent\protected\def\doflushnotes
1604  {\ifconditional\postponingnotes
1605     \begingroup
1606     \enforced\lettonothing\flushnotes
1607     \enforced\lettonothing\postponenotes
1608     \ifconditional\postponednote
1609       \ifhmode
1610         % needed for tagging ... otherwise we get some weird node free error
1611         \signalcharacter
1612       \fi
1613     \fi
1614     \clf_flushpostponednotes% this also resets the states !
1615     \global\postponednote\conditionalfalse
1616     \global\postponingnotes\conditionalfalse
1617     \enforced\glettonothing\flushnotes
1618     \endgroup
1619   \fi}
1620
1621%D \macros
1622%D   {startlocalfootnotes,placelocalfootnotes}
1623%D
1624%D The next two macros can be used in for instance tables, as we'll demonstrate
1625%D later on.
1626%D
1627%D \showsetup{startlocalfootnotes}
1628%D \showsetup{placelocalfootnotes}
1629
1630% todo: compatibility mode: when first arg is assignment or missing, then all
1631
1632\newtoks\everyplacelocalnotes
1633
1634\appendtoks
1635    \enforced\lettonothing\flushnotes
1636    \enforced\lettonothing\postponenotes
1637\to \everyplacelocalnotes
1638
1639\newconditional\inlocalnotes
1640
1641\mutable\lettonothing\localnoteslist
1642
1643\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings)
1644  {\inlocalnotes\conditionaltrue
1645   \def\localnoteslist{#list}%
1646   \processcommacommand[\localnoteslist]\strc_notes_local_start_step}
1647
1648\permanent\protected\def\stoplocalnotes
1649  {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step
1650   \inlocalnotes\conditionalfalse}
1651
1652\lettonothing\p_strc_notes_continue
1653
1654\def\strc_notes_local_start_step#tag%
1655  {\p_strc_notes_continue{\noteparameter\c!continue}%
1656   \ifx\p_strc_notes_continue\v!yes \else
1657      \strc_counters_save{#tag}%
1658      \strc_counters_reset{#tag}%
1659   \fi
1660   \clf_savenote{#tag}{store}}
1661
1662\def\strc_notes_local_stop_step#tag%
1663  {\p_strc_notes_continue{\noteparameter\c!continue}%
1664   \ifx\p_strc_notes_continue\v!yes \else
1665     \strc_counters_restore{#tag}%
1666   \fi
1667   \clf_restorenote{#tag}}
1668
1669\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#S#settings]%
1670  {\iftok{\clf_getnotestate{#tag}}{store}%
1671     \strc_notes_local_place_indeed{#settings}{#tag}%
1672   \fi}
1673
1674\def\strc_notes_local_place_indeed#settings#tag%
1675  {\begingroup
1676   \cdef\currentnote{#tag}% is already set?
1677   \expand\everyplacelocalnotes
1678   % beware, we cannot trust setting \currentnote here
1679   \setupcurrentnote[#settings]% later we set height etc for framed
1680   \strc_notes_place_local_alternative
1681   \strc_notes_set_properties % restore globals (if needed)
1682   \endgroup
1683  }% TODO: just restore properties \expand\everychecknote} % we need to restore the old state
1684
1685%D These commands can be used like:
1686%D
1687%D \startbuffer
1688%D \startlocalnotes[footnote]
1689%D   \placetable
1690%D     {Some Table}
1691%D     \placeontopofeachother
1692%D       {\starttable[|l|r|]
1693%D        \HL
1694%D        \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR
1695%D        \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR
1696%D        \HL
1697%D        \stoptable}
1698%D       {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]%
1699%D        \placelocalnotes[footnote]}
1700%D \stoplocalnotes
1701%D \stopbuffer
1702%D
1703%D \typebuffer
1704%D
1705%D Because this table placement macro expect box content, and thanks to the grouping
1706%D of the local footnotes, we don't need additional braces.
1707%D
1708%D \getbuffer
1709
1710%D \macros
1711%D   {placefootnotes}
1712%D
1713%D We still have no decent command for placing footnotes somewhere else than at the
1714%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can
1715%D be placed by using
1716%D
1717%D \showsetup{placefootnotes}
1718
1719\permanent\protected\def\placebottomnotes
1720  {\strc_notes_process\strc_notes_place_inserts}
1721
1722\permanent\tolerant\protected\def\placenotes[#list]#spacer[#S#settings]%
1723  {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}}
1724
1725\def\strc_notes_place_indeed#settings#tag% settings note
1726  {\cdef\currentnote{#tag}% grouping ?
1727   \iftok{\clf_getnotestate{#tag}}{store}%
1728     \expandafter\strc_notes_local_place_indeed
1729   \else
1730     \expandafter\strc_notes_global_place_indeed
1731   \fi
1732   {#settings}{#tag}}
1733
1734\def\strc_notes_global_place_indeed#settings#tag%
1735  {\begingroup
1736   \setupnote[#tag][#settings]%
1737   \strc_notes_place_inserts
1738   \endgroup
1739   \expand\everysetupnote} % to be checked .. synchronize
1740
1741%D Placement
1742
1743\installcorenamespace{notealternative}
1744
1745\permanent\protected\def\installnotealternative#alternative#command%
1746  {\defcsname\??notealternative#alternative\endcsname{#command}}
1747
1748\permanent\protected\def\doifnotescollected#tag%
1749  {\clf_doifnotecontent{#tag}}
1750
1751\def\strc_notes_place_local_alternative % will be a setup (wrapper)
1752  {\doifnotescollected\currentnote
1753     {\endgraf
1754      \ifvmode
1755        \whitespace
1756        \noteparameter\c!before
1757      \fi
1758      \begingroup
1759      \strc_notes_set_bodyfont
1760      \begincsname\??notealternative\noteparameter\c!alternative\endcsname
1761      \endgroup
1762      \ifvmode
1763        \noteparameter\c!after
1764      \fi}}
1765
1766%D A stupid alternative is also provided:
1767%D
1768%D \starttyping
1769%D \setupfootnotes[location=text,alternative=none]
1770%D \stoptyping
1771
1772% setups ?
1773
1774\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}}
1775
1776\installnotealternative \v!none
1777  {\flushlocalnotes\currentnote}
1778
1779\installnotealternative \empty
1780  {\flushlocalnotes\currentnote}
1781
1782\installnotealternative \v!grid % test if n > 0
1783  {\begingroup
1784   \setupcurrentnote[\c!location=]%
1785   \snaptogrid\hbox
1786     {\inheritednoteframed
1787        {\flushlocalnotes\currentnote}}%
1788   \endgroup}
1789
1790\installnotealternative \v!fixed % test if n > 0
1791  {\begingroup
1792   \setupcurrentnote[\c!location=]%
1793   \inheritednoteframed
1794     {\flushlocalnotes\currentnote}%
1795   \endgroup}
1796
1797\installnotealternative \v!columns % redundant
1798  {\begingroup
1799   \setupcurrentnote[\c!location=]%
1800   \inheritednoteframed
1801     {\doifelsedimension{\noteparameter\c!width}\donothing{\setexpandednoteparameter\c!width{\the\hsize}}%
1802      \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
1803        \flushlocalnotes\currentnote
1804      \stopsimplecolumns}%
1805   \endgroup}
1806
1807% 0:page 1:firstcolumn 2:lastcolumn
1808
1809\newconstant\c_strc_notes_page_location
1810
1811\protected\def\strc_notes_check_locations
1812  {\edef\p_strc_notes_location{\rootnoteparameter\c!location}%
1813   \c_strc_notes_page_location
1814      \ifx\p_strc_notes_location\v!firstcolumn\plusone  \else
1815      \ifx\p_strc_notes_location\v!lastcolumn \plustwo  \else
1816                                              \zerocount\fi\fi}
1817
1818\appendtoks
1819    \strc_notes_check_locations
1820\to \everysynchronizenote
1821
1822% still semi public (but will change)
1823
1824\newif\ifnotespresent
1825
1826\permanent\protected\def\checknotepresence
1827  {\notespresentfalse
1828   \strc_notes_process\strc_notes_check_presence}
1829
1830\def\strc_notes_check_presence
1831%   {\ifdim\page_inserts_get_height\currentnoteinsertionnumber>\zeropoint % not reliable
1832  {\ifcase\page_inserts_get_height\currentnoteinsertionnumber\else
1833     \notespresenttrue
1834   \fi}
1835
1836%D \macros
1837%D   {fakenotes}
1838
1839    % used in page-mul
1840
1841 %  \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
1842
1843    \permanent\protected\def\fakenotes
1844      {\ifhmode\endgraf\fi\ifvmode
1845         \calculatetotalclevernoteheight
1846         \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
1847       \fi}
1848
1849    \permanent\protected\def\fakepagenotes
1850      {\ifhmode\endgraf\fi\ifvmode
1851         \calculatetotalpagenoteheight
1852         \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
1853       \fi}
1854
1855    % used in page-not but not yet ok
1856
1857    \newdimen\totalnoteheight
1858
1859    \permanent\protected\def\additionaltotalnoteheight#insert% temp hacks anyway
1860      {\dimexpr
1861         \ifnum\page_inserts_get_height#insert=\zeropoint
1862           \zeropoint
1863         \orelse\ifnum\page_inserts_get_multiplier#insert=\zeropoint
1864           \zeropoint
1865         \else % todo: divide by count
1866           \page_inserts_get_height  #insert
1867          +\page_inserts_get_distance#insert% hm, no stretch but a dimen anyway
1868         \fi
1869      \relax}
1870
1871    \permanent\def\docalculatetotalnoteheight
1872      {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
1873         \advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
1874       \fi}
1875
1876    \permanent\def\docalculatetotalclevernoteheight
1877      {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
1878         \advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
1879       \fi}
1880
1881    \permanent\def\docalculatetotalpagenoteheight
1882      {\advanceby\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}}
1883
1884    \permanent\def\calculatetotalnoteheight      {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
1885    \permanent\def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
1886    \permanent\def\calculatetotalpagenoteheight  {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight}
1887
1888%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing
1889%D footnotes? The solution turned out to be rather simple:
1890%D
1891%D \starttyping
1892%D \everypar  {...\flushnotes...}
1893%D \neverypar {...\postponenotes}
1894%D \stoptyping
1895%D
1896%D We can use \type {\neverypar} because in most commands sensitive to footnote
1897%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact,
1898%D this footnote implementation is the first to use this scheme.
1899
1900%D This is a nasty and new secondary footnote flusher. It can be hooked into \type
1901%D {\everypar} like:
1902%D
1903%D \starttyping
1904%D \appendtoks \synchronizenotes \to \everypar
1905%D \stoptyping
1906
1907% \let\synchronizenotes\relax
1908
1909%D When typesetting footnotes, we have to return to the footnote specific bodyfont
1910%D size, which is in most cases derived from the global document bodyfont size. In
1911%D the previous macros we already used a footnote specific font setting macro.
1912
1913\def\strc_notes_set_bodyfont
1914  {\let\strc_notes_set_bodyfont\relax
1915   \restoreglobalbodyfont
1916   \usebodyfontparameter\noteparameter
1917   \usealignparameter\noteparameter}
1918
1919%D The footnote mechanism defaults to a traditional one column way of showing them.
1920%D By default we precede them by a small line.
1921
1922% end notes in the margin:
1923%
1924% \setuptexttexts
1925%   [margin]
1926%   [] [{\directsetup{notabene}}]
1927%
1928% \startsetups notabene
1929%     \vbox to \textheight \bgroup
1930%         \setupalign[tolerant]
1931%         \topskipcorrection
1932%         \placenotes[endnote][before=,after=]
1933%         \vfilll
1934%     \egroup
1935% \stopsetups
1936
1937\definenote [\v!footnote]
1938\definenote [\v!endnote ] [\c!location=\v!none] % else no break
1939
1940%D Compatibility macros:
1941
1942\permanent\protected\def\setupfootnotedefinition{\setupnotation                   [\v!footnote]}
1943\permanent\protected\def\setupfootnotes         {\setupnote                       [\v!footnote]}
1944\permanent          \def\footnotetext           {\setnotetext                     [\v!footnote]}
1945\permanent\protected\def\placefootnotes         {\strc_notes_place_footnotes      [\v!footnote]}
1946\permanent\protected\def\placelocalfootnotes    {\strc_notes_place_local_footnotes[\v!footnote]}
1947\permanent\protected\def\startlocalfootnotes    {\startlocalnotes                 [\v!footnote]} %  alleen footnote
1948\permanent\protected\def\stoplocalfootnotes     {\stoplocalnotes }
1949
1950\tolerant\def\strc_notes_place_footnotes[#list]#spacer[#S#settings]%
1951  {\ifarguments\or
1952     \placenotes[#list][\c!height=\textheight]%
1953   \or
1954     \placenotes[#list][#settings,\c!height=\textheight]%
1955   \fi}
1956
1957\tolerant\def\strc_notes_place_local_footnotes[#list]#spacer[#S#settings]%
1958  {\ifarguments\or
1959     \placelocalnotes[#list][\c!height=\textheight]%
1960   \or
1961     \placelocalnotes[#list][#settings,\c!height=\textheight]%
1962   \fi}
1963
1964%D Goodies:
1965%D
1966%D \starttyping
1967%D \dorecurse {100} {
1968%D     test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
1969%D }
1970%D \stoptyping
1971
1972\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}}
1973
1974\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage
1975
1976%D New trickery:
1977
1978%D \macros
1979%D   {note}
1980%D
1981%D Refering to a note is accomplished by the rather short command:
1982%D
1983%D \showsetup{note}
1984%D
1985%D This command is implemented rather straightforward as:
1986
1987\installcorenamespace{notesymbol}
1988
1989\mutable\lettonothing\lastnotesymbol % todo: per class
1990
1991\permanent\tolerant\protected\def\notesymbol[#tag]#keepspacer[#reference]%
1992  {\ifnotesenabled
1993     \dontleavehmode
1994     \begingroup
1995     \cdef\currentnote{#tag}%
1996     \usenotestyleandcolor\c!textstyle\c!textcolor
1997     \ifempty{#reference}%
1998       \noteparameter\c!textcommand\lastnotesymbol % check if command double
1999     \else
2000       \unskip
2001       \noteparameter\c!textcommand{\in[#reference]}% command here?
2002     \fi
2003     \endgroup
2004   \fi}
2005
2006\permanent\tolerant\protected\def\note[#tag]#keepspacer[#reference]%
2007  {\ifempty{#reference}%
2008     \notesymbol[\v!footnote][#tag]%
2009   \else
2010     \notesymbol[#tag][#reference]%
2011   \fi}
2012
2013% will be redone if needed
2014%
2015% \def\ownnotesymbol#1% #1 gets number passed
2016%   {\executeifdefined{\??notesymbol\currentnote}\empty}
2017%
2018% \protected\def\setnotesymbol[#1]#2#3%
2019%   {\prewordbreak % prevent lookback
2020%    \gdefcsname\??notesymbol#1\endcsname{#3}
2021%    \strc_notes_inject_symbol}
2022%
2023% \protected\def\ownnote[#1]#2#3#4%
2024%   {\setnotesymbol[#1]{#2}{#3}%
2025%    \setnotetext  [#1]{#4}}
2026%
2027% \defineconversion
2028%   [ownnote]
2029%   [\ownnotesymbol]
2030
2031% tricky:
2032%
2033% \enabletrackers[nodes.areas]
2034% \enabletrackers[nodes.references]
2035% \enabletrackers[nodes.destinations]
2036%
2037% \setupnotes[interaction=all,rule=no]
2038% \setupinteraction[state=start,focus=standard]
2039%
2040% \starttext
2041%     \goto{\input tufte\relax}[page(2)] \par
2042%     \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par
2043%     \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par
2044%     % \completecontent
2045%     % \chapter{Chapter}
2046%     % \dorecurse{5}{\input knuth}
2047%     a\footnote{\input tufte\par\input ward\relax}
2048% \stoptext
2049
2050%D Bonus:
2051
2052\appendtoks
2053   \setsystemmode\currentnote
2054\to \everysynchronizenote
2055
2056\protect \endinput
2057