diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-not.mkiv')
-rw-r--r-- | Master/texmf-dist/tex/context/base/strc-not.mkiv | 1139 |
1 files changed, 1139 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-not.mkiv b/Master/texmf-dist/tex/context/base/strc-not.mkiv new file mode 100644 index 00000000000..4b033cbf9e7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/strc-not.mkiv @@ -0,0 +1,1139 @@ +%D \module +%D [ file=strc-not, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Note Handling, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright=PRAGMA-ADE / Hans Hagen] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Note Handling} + +\registerctxluafile{strc-not}{1.001} + +\unprotect + +% obsolete + +\let\autopostponenotes\relax + +% removed: +% +% \pushsomestates +% +% core-ins -> obsolete +% +% saveinsertiondata +% restoreinsertiondata +% saveinsertionbox +% eraseinsertionbackup +% restoreinsertionbackup +% +% \def\doprocessnotescs#1#2% #1 == \cs that takes arg +% {\def\currentnote{#2}\@EA#1\csname\??vn:\currentnote\endcsname} +% \def\processnotescs#1{\processcommacommand[\noteinsertions]{\doprocessnotescs#1}} +% \def\noteinsertion #1{\csname\??vn:#1\endcsname} + +\def\savenotedata {\writestatus{todo}{save note data}} +\def\restorenotedata {\writestatus{todo}{restore note data}} +\def\savenotecontent {\writestatus{todo}{save note content}} +\def\restorenotecontent{\writestatus{todo}{restore note content}} +\def\erasenotebackup {\writestatus{todo}{erase note backup}} + +% page-set: + +\def\enablenotes {\writestatus{todo}{enable notes}} +\def\disablenotes {\writestatus{todo}{disable notes}} +\def\savenotes {\writestatus{todo}{save notes}} +\def\flushsavednotes{\writestatus{todo}{flush notes}} + +% experiment: (compare scope=text and scope=page) +% +% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] + +%D Footnotes are can be characterized by three components: +%D +%D \startitemize[packed] +%D \item a small number \footnote {a footnote number} or +%D symbol {\setupfootnotes [conversion=set 2]\footnote +%D {a footnote}} +%D \item and a similar mark at the bottom of the page +%D \item followed by some additional text +%D \stopitemize +%D +%D Because footnotes are declared at the location of their +%D reference they can be seen as a special kind of +%D floating bodies. Their placement is postponed but has to be +%D taken into account in the pagebreak calculations. This kind +%D of calculations are forced by using \type{\insert}s and dealing +%D with all cases is not trivial. + +%D \macros +%D {notesenabled} +%D +%D We need a couple of states because at some moments we don't want +%D to mess around with inserts at all. Take for instance a table +%D of contents. And so we can temporary disable footnotes by saying +%D +%D \starttyping +%D \notesenabledfalse +%D \stoptyping + +\newif\ifnotesenabled \notesenabledtrue + +% better mark a note .. once flushed no more flushing + +%appendtoks \notesenabledfalse \to \everymarking +\appendtoks \notesenabledfalse \to \everypagebody +\appendtoks \notesenabledfalse \to \everystructurelist % quick hack + +%D Often we need to process the whole set of notes and to make that +%D fast, we use a token register: + +\newtoks\tobeprocessednotes + +\def\processnotes#1% #1: \macro that uses \currentnote + {\def\doprocesssomenote##1{\edef\currentnote{##1}\let\currentdescription\currentnote#1}% + \the\tobeprocessednotes} + +%D Notes have their own paremater handlers. The complication here +%D is that we use descriptions to typeset the note, so we have several +%D resolvers. + +\let\currentnote\v!footnote + +\def\noteparameter #1{\csname\donoteparameter{\??vn\currentnote}#1\endcsname} +\def\noteparameterhash#1{\donoteparameterhash {\??vn\currentnote}#1} + +\def\namednoteparameter#1#2{\csname\donoteparameter{\??vn#1}#2\endcsname} + +\def\donoteparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\donoteparentparameter \csname#1\s!parent\endcsname#2\fi} +\def\donoteparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\donoteparentparameterhash\csname#1\s!parent\endcsname#2\fi} + +\def\donoteparentparameter #1#2{\ifx#1\relax\s!empty\else\donoteparameter #1#2\fi} +\def\donoteparentparameterhash#1#2{\ifx#1\relax \else\donoteparameterhash#1#2\fi} + +\def\detokenizednoteparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??vn#1\endcsname}} + +\def\dosetnoteattributes#1#2% style color + {\edef\fontattributehash {\noteparameterhash#1}% + \edef\colorattributehash{\noteparameterhash#2}% + \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi + \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi} + +%D \macros +%D {setupnote,setupnotedefinition} +%D +%D We can influence footnote typesetting with the setup +%D command: +%D +%D \showsetup{setupnotes} +%D \showsetup{setupnote} +%D +%D The definition command indicate that we can frame the footnote +%D area. The footnotes themselves are treated as descriptions. +%D +%D \showsetup{definenote} +%D +%D It's sort of a custom to precede footnotes by a horizontal +%D rule and although fancy rules like +%D +%D \starttyping +%D \hbox to 10em{\hskip-3em\dotfill} +%D \stoptyping +%D +%D Are quite ligitimate, we default to a simple one 20\% of the +%D text width. + +\def\setupnotes + {\dodoubleargument\getparameters[\??vn]} + +\setupnotes + [\c!location=\v!page, + \c!way=\v!by\v!part, + \c!sectionnumber=\v!no, + %\c!conversion=, + \c!rule=\v!on, + \c!before=\blank, + \c!bodyfont=\v!small, + %\c!style=, + %\c!color=, + %\c!after=, + %\c!rulecolor=, + \c!rulethickness=\linewidth, + \c!frame=\v!off, + \c!margindistance=.5em, + \c!columndistance=1em, + \c!distance=.125em, + \c!align=\v!normal, + \c!tolerance=\v!tolerant, + \c!split=\v!tolerant, + %\c!width=\makeupwidth, + %\c!width=\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi, + \c!width=\defaultnotewidth, + \c!height=\textheight, + \c!numbercommand=\high, + \c!command=\noteparameter\c!numbercommand, % downward compatible + \c!separator=,% \@@koseparator, + \c!textcommand=\high, + \c!textstyle=\tx, + %\c!textcolor=, + \c!interaction=\v!yes, + %\c!factor=, + %\c!scope=, % \v!text \v!page +\c!prefixconnector=., +\c!prefix=\v!no, + \c!next=\autoinsertnextspace, % new, experimental with startnotes + \c!n=1] + +\def\@@defaultnotedefloc{\v!inleft} +\def\@@defaultnotedefdis{\!!zeropoint} + +% also s!root +% +% \definedescription +% [\??vn\??vn] +% [\c!location=\@@defaultnotedefloc, +% \c!distance=\@@defaultnotedefdis, +% \c!width=\v!fit, +% \c!headstyle=\noteparameter\c!style, +% \c!headcolor=\noteparameter\c!color, +% \c!before=, +% \c!after=] + +\def\startnotedef{\resetdescriptions\csname\e!start\??vn\??vn\currentnote\endcsname} +\def\stopnotedef {\csname\e!stop \??vn\??vn\currentnote\endcsname} + +\def\currentnoteins{\csname\??vn:\currentnote\endcsname} + +\newtoks \everysetupnote + +\def\definenote + {\dodoubleempty\dodefinenote} + +\def\dodefinenote[#1][#2]% + {\edef\currentnote{#1}% + \ifcsname\??vn:\currentnote\endcsname\else + \@EA\installinsertion\csname\??vn:\currentnote\endcsname\relax + \appendtoks\doprocesssomenote{#1}\to\tobeprocessednotes + \fi + \defineenumeration % description + [\currentnote] + [\c!location=\@@defaultnotedefloc, + \c!distance=\@@defaultnotedefdis, + \c!width=\v!fit, + \c!headstyle=\noteparameter\c!style, + \c!headcolor=\noteparameter\c!color, +\s!handler=\v!note, + \c!text=, + \c!before=, + \c!after=]% + \setupenumerations + [\currentnote] + [\s!parent=\??vn\currentnote, + \c!number=\v!yes] % no inheritance from decriptions which is okay + \presetlocalframed + [\??vn\currentnote]% + \getparameters + [\??vn\currentnote] + [\s!parent=\??vn,#2]% + \definestructurecounter + [\currentnote]% + \ctxlua{structure.notes.define("\currentnote","insert",\number\csname\??vn:\currentnote\endcsname)}% + \the\everysetupnote + \dochecknote} + +\let\setupnotedefinition\setupenumerations + +\appendtoks + \setupenumerations[\currentnote][]% +\to \everysetupnote + +% \appendtoks +% \dochecknote +% \to \everysetupnote + + +\def\setupnote + {\dodoubleempty\dosetupnote} + +\def\dosetupnote[#1][#2]% + {\edef\currentnote{#1}% + \ifsecondargument + \getparameters[\??vn\currentnote][#2]% + \the\everysetupnote + \fi + \dochecknote} + +\appendtoks + \letvalue{\??vn\c!rule:\currentnote}\normalnoterule % hm +\to \everysetupnote + +\appendtoks + \processaction + [\noteparameter\c!rule] + [ \v!on=>\letvalue{\??vn\c!rule:\currentnote}\normalnoterule, + \v!off=>\letvalue{\??vn\c!rule:\currentnote}\relax, + \s!default=>\letvalue{\??vn\c!rule:\currentnote}\relax, + \s!unknown=>\setvalue{\??vn\c!rule:\currentnote}{\noteparameter\c!rule}]% +\to \everysetupnote + +\appendtoks + \processaction % todo + [\noteparameter\c!split] + [ \v!tolerant=>\notepenalty\zeropoint, + \v!strict=>\notepenalty9999, + \v!verystrict=>\notepenalty\maxdimen, + \s!default=>\notepenalty\zeropoint, + \s!unknown=>\notepenalty\commalistelement]% +\to \everysetupnote + +%D The following switch can be used to disable limiting the +%D height of the footnote area, something that is needed in +%D multi column balancing. Use this switch with care. + +\newif\ifnotelimit \notelimittrue % shared + +% bottomnotes endnotes +% clevernotes + +\appendtoks + \doifsomething{\noteparameter\c!factor} + {\ifnum\noteparameter\c!factor<\zerocount\else + \count\currentnoteins\noteparameter\c!factor + \fi}% +\to \everysetupnote + +% compatibility (will go away) + +\newif\ifendnotes +\newif\ifbottomnotes + +% locations: + +\def\s!noteloc{nodeloc} % 1=page 2=columns 3=lastcolumn 4=firstcolumn 5=none +\def\s!notepos{nodepos} % 0=nothing 1=high 2=bottom +\def\s!notefmt{nodefmt} % 1 text +\def\s!notecol{nodecol} + +\def\clevernotes % compatibility hack, will be redone + {\numexpr\ifcase\namednoteparameter\v!footnote\s!noteloc\or0\or2\or2\or1\else0\fi\relax} + +\def\setnotelocation #1{\expandafter\chardef\csname\??vn\currentnote\s!noteloc\endcsname#1\relax} +\def\setnoteposition #1{\expandafter\chardef\csname\??vn\currentnote\s!notepos\endcsname#1\relax} +\def\setnoteformatting#1{\expandafter\chardef\csname\??vn\currentnote\s!notefmt\endcsname#1\relax} +\def\setnotecolumns #1{\expandafter\chardef\csname\??vn\currentnote\s!notecol\endcsname#1\relax} + +\def\currentnofcolumns{\@@kln} + +\setvalue{\??vn @\v!page }{\setnotelocation\plusone} +\setvalue{\??vn @\v!columns }{\setnotelocation\plustwo} +\setvalue{\??vn @\v!firstcolumn}{\setnotelocation\plusthree} +\setvalue{\??vn @\v!lastcolumn }{\setnotelocation\plusfour} +\setvalue{\??vn @\v!none }{\setnotelocation\plusfive} +\setvalue{\??vn @\v!text }{\setnotelocation\plusfive \setnoteformatting\plusone} % test +\setvalue{\??vn @\v!high }{\setnoteposition\plusone} +\setvalue{\??vn @\v!bottom }{\setnoteposition\plustwo} + +\def\dosetcheckednote#1{\csname\??vn @#1\endcsname} + +\def\dochecknote + {% node states + \setnotelocation\plusone + \setnoteposition\plustwo + \normalexpanded{\noexpand\rawprocesscommalist[\noteparameter\c!location]}\dosetcheckednote + % compatibility hack + \ifnum\noteparameter\s!noteloc=\plusfive \endnotestrue \else \endnotesfalse \fi + \ifnum\noteparameter\s!notepos=\plustwo \bottomnotestrue \else \bottomnotesfalse \fi + % set column multiplier + \edef\currentnotenofcolumns{\noteparameter\c!n}% + \ifx\currentnotenofcolumns\empty + \let\currentnotenofcolumns\!!plusone + \fi + \ifcase\noteparameter\s!noteloc\or + % page + \scratchcounter \currentnotenofcolumns + \or + % columns + \scratchcounter\ifnum\currentnofcolumns=\zerocount \plusone \else \currentnotenofcolumns \fi \relax + \or + % firstcolumn + \scratchcounter\plusone + \or + % lastcolumn + \scratchcounter\plusone + \or + % text + \scratchcounter\currentnotenofcolumns + \fi + % column factor + \global\count\currentnoteins\plusthousand + \global\count\currentnoteins\numexpr\plusthousand/\scratchcounter\relax + % maximize height + \ifnotelimit + \global\dimen\currentnoteins\dimexpr\noteparameter\c!height*\scratchcounter\relax + \fi + % distance + \begingroup + \setbox\scratchbox\vbox + {\forgetall + \noteparameter\c!before + \placenoterule + \noteparameter\c!after}% + \global\skip\currentnoteins\ht\scratchbox + \endgroup + % play safe + \ifnum\noteparameter\s!noteloc=\plusfive + \ctxlua{structure.notes.setstate("\currentnote","store")}% + % text notes (e.g. end notes) but we don't use inserts anyway + \global\dimen\currentnoteins\maxdimen + \global\count\currentnoteins\zerocount + \global\skip \currentnoteins\zeropoint + \fi} + +% \def\checknotes +% {\processnotes\dochecknote} + +\let\checknotes\relax % experiment, avoiding this saves a lot of time + +% D When \type{n} exceeds~1, footnotes are typeset in +% D multi||columns, using the algoritm presented on page~397 +% D of \TEX book. Footnotes can be places on a per page basis +% D or whereever suitable. When we set~\type{n} to~0, we get a +% D rearanged paragraph, typeset by the algoritms on pages 398 +% D and~389 (at least in \MKII). We definitely did not reinvent +% D that wheel. + +% Example of using factor: +% +% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0] +% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] +% \starttext +% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} } +% \stoptext + +%D The noterule can be a graphic and therefore calling this +%D setup macro at every skipswitch is tricky (many many MP +%D runs). Let's just reserve a few points, that probably match +%D those of the stretch component. + +\def\placenoterule + {\getvalue{\??vn\c!rule:\currentnote}} + +\def\normalnoterule + {\ifvmode + \color + [\noteparameter\c!rulecolor] + {\hrule\!!width .2\hsize\!!height\noteparameter\c!rulethickness\!!depth \zeropoint}% + \kern\strutdepth + \fi} + +\ifx\setnotehsize\undefined + + \def\setnotehsize{\hsize\noteparameter\c!width\relax} % can be overloaded + +\fi + +%D The formatting depends on the width of the table, so we +%D have to set \type {n} to zero. +%D +%D \starttyping +%D \startbuffer +%D \bTABLE +%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR +%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \startlocalfootnotes[n=0,location={text,none}] +%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes} +%D \stoplocalfootnotes +%D \stoptyping + +%D \macros +%D {footnote} +%D +%D A footnote can have a reference as optional argument and +%D therefore its formal specification looks like: +%D +%D \showsetup{footnote} +%D +%D This command has one optional command: the reference. By +%D saying \type{[-]} the number is omitted. The footnote +%D command is not that sensitive to spacing, so it's quite +%D legal to say: +%D +%D \startbuffer +%D Users of \CONTEXT\ must keep both feet \footnote{Given they +%D have two.} on the ground and not get confused \footnote{Or +%D even crazy.} by all those obscure \footnote{But fortunately +%D readable.} parameters. +%D \stopbuffer +%D +%D \typebuffer +%D +%D When setting the \type{conversion} to \type{set 2} we get +%D something like: +%D +%D \bgroup +%D \startnarrower +%D \setupfootnotes[conversion=set 1] +%D \getbuffer +%D \stopnarrower +%D \egroup +%D +%D Typesetting footnotes is, at least for the moment, disabled +%D when reshaping boxes. +%D +%D The additional macro \type {\footnotetext} and the +%D associated \type {\note} macro were implemented at +%D request of users on the mailing list and a suggestion by +%D taco to split of the symbol placement. I decided to +%D merge this functionality with the existing \type {\note} +%D functionality. + +%D The next implementation runs on top of enumerations (only in \MKIV). + +% TODO: \ifnotesenabled + +\newif\ifnotesymbol \notesymboltrue + +\def\setnote [#1]{\getvalue{#1}} +\def\setnotetext[#1]{\global\settrue\skipnoteplacement\getvalue{#1}} + +\def\domovednote#1#2#3#4% + {\ifcase\ctxlua{structure.notes.deltapage("#1",#2)}\or\symbol[#3]\or\symbol[#4]\fi} + +\setvalue{\??dd:\v!note:\s!handler }{\@@doenumerationhandler} +\setvalue{\??dd:\v!note:\s!handler:\s!do }{\@@somenotedescription} +\setvalue{\??dd:\v!note:\s!handler:\s!start}{\@@startsomenotedescription} + +\def\@@somenotedescription {\@@notemakedescription} +\def\@@startsomenotedescription{\@@notemakedescription} + +\newconditional\skipnoteplacement + +\def\@@notemakedescription[#1]#2#3% todo ... proper [key=value] etc + {\ifnotesenabled + \begingroup + \doenumerationcheckconditions + \let\currentnote\currentdescriptionmain + \dodescriptioncomponent[\c!reference=#1,\c!label={\descriptionparameter\c!text},\c!title={#3},\c!bookmark=,][]% + \xdef\currentnotenumber{\ctxlua{structure.notes.store("\currentnote",\currentdescriptionnumberentry)}}% + \settrue\processingnote + \ifconditional\skipnoteplacement + \globallet\lastnotesymbol\dolastnotesymbol + \else + \iftypesettinglines % otherwise problems with \type <crlf> {xxx} + \ignorelines % makes footnotes work in \startlines ... \stoplines + \fi + \ifnotesymbol + \dolastnotesymbol + \else + \unskip\unskip + \globallet\lastnotesymbol\dolastnotesymbol + \fi + \fi + \ifconditional\postponingnotes + \global\settrue\postponednote + \else + \handlenoteinsert\currentnote\currentnotenumber + \fi + \ifconditional\skipnoteplacement \else + \kern\notesignal\relax % \relax is needed to honor spaces + \iftrialtypesetting \else \global\setfalse\skipnoteplacement \fi + \fi + \endgroup + \fi} + +\def\dolastnotesymbol{\typesetsomenotesymbol\currentnote\currentnotenumber} + +\def\dotypesetsomenotesymbol#1#2% + {\dodonotesymbol + {\synchronizesomenotesymbol{#1}{#2}% + \ctxlua{structure.notes.number("\currentnote",\currentnotenumber)}% \currentdescriptionnumberentry + \domovednote{#1}{#2}\v!previouspage\v!nextpage}} + +\def\typesetsomenotesymbol#1#2% + {\removeunwantedspaces + \doifitalicelse\/\donothing % Charles IV \footnote{the fourth} + \ifdim\lastkern=\notesignal + \dodonotesymbol{\kern\noteparameter\c!distance}% gets the font right, hack ! + \fi + \nobreak + \doifelse{\noteparameter\c!interaction}\v!no + {\dotypesetsomenotesymbol{#1}{#2}} + {\directgotobox{\dotypesetsomenotesymbol{#1}{#2}}[page(\ctxlua{structure.notes.getnumberpage("#1",\number#2)})]}% f: + \globallet\lastnotesymbol\relax} + +\def\currentnotedescriptiontext % todo: can be other number + {\ctxlua{structure.notes.title("\currentnote",\currentdescriptionnumberentry)}} + +\def\currentnoteenumerationfullnumber + {\doifelse{\noteparameter\c!interaction}\v!no + {\docurrentnoteenumerationfullnumber}% + {\directgotobox + {\docurrentnoteenumerationfullnumber}% + [page(\ctxlua{structure.notes.getsymbolpage("\currentnote",\currentdescriptionnumberentry)})]}} + +\def\docurrentnoteenumerationfullnumber + {\noteparameter\c!numbercommand + {\ctxlua{structure.notes.number("\currentnote",\currentdescriptionnumberentry)}% + \domovednote\currentdescription\currentdescriptionnumberentry\v!nextpage\v!previouspage}} + +\def\synchronizesomenotesymbol#1#2% called more often than needed + {\expanded{\noexpand\ctxlatelua{structure.notes.setsymbolpage("#1",#2)}}} + +\def\handlenoteinsert#1#2% + {\begingroup + \edef\currentnote{#1}% + \the\everybeforenoteinsert + \insert\currentnoteins\bgroup + \the\everyinsidenoteinsert + \handlenoteitself{#1}{#2}% + \egroup + \the\everyafternoteinsert + \endgroup} + +\def\handlenoteitself#1#2% tg, id + {\edef\currentdescription{#1}% + \edef\currentnote{#1}% + \edef\currentdescriptionnumberentry{#2}% + \let\currentdescriptiontext\currentnotedescriptiontext + \let\currentenumerationfullnumber\currentnoteenumerationfullnumber + \dostartstoreddescription\begstrut\currentnotedescriptiontext\endstrut\dostopstoreddescription} + +\def\dostartstoreddescription + {\bgroup\@@dostartdescriptionindeed} + +\def\dostopstoreddescription + {\@@stopdescription} + +%D The main typesetting routine is more or less the same as the +%D \PLAIN\ \TEX\ one, except that we only handle one type while +%D \PLAIN\ also has something \type{\v...}. In most cases +%D footnotes can be handled by a straight insert, but we do so +%D by using an indirect call to the \type{\insert} primitive. + +%D Making footnote numbers active is not always that logical, +%D Making footnote numbers active is not always that logical, +%D especially when we keep the reference and text at one page. +%D On the other hand we need interactivity when we refer to +%D previous notes or use end notes. Therefore we support +%D interactive footnote numbers in two ways \footnote{This +%D feature was implemented years after we were able to do so, +%D mainly because endnotes had to be supported.} that is, +%D automatically (vise versa) and by user supplied reference. + +\newcount\internalnotereference + +\let\startpushnote=\relax +\let\stoppushnote =\relax + +\newsignal\notesignal +\newcount \notepenalty + +\notepenalty=0 % needed in order to split in otrset + +\newconditional\processingnote +\newconditional\postponednote + +\newtoks\everybeforenoteinsert +\newtoks\everyinsidenoteinsert +\newtoks\everyafternoteinsert + +\appendtoks + \let\flushnotes\relax + \let\postponenotes\relax + \forgetall +\to \everybeforenoteinsert + +\appendtoks + \doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment + \penalty\notepenalty + \forgetall + \setnotebodyfont + \redoconvertfont % to undo \undo calls in in headings etc + \splittopskip\strutht % not actually needed here + \splitmaxdepth\strutdp % not actually needed here + \leftmargindistance\noteparameter\c!margindistance + \rightmargindistance\leftmargindistance + \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? + \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? + \fi +\to \everyinsidenoteinsert + +\let\lastnotesymbol\relax + +%D \macros +%D {note} +%D +%D Refering to a note is accomplished by the rather short +%D command: +%D +%D \showsetup{note} +%D +%D This command is implemented rather straightforward as: + +\def\notesymbol + {\dodoubleempty\donotesymbol} + +\def\donotesymbol[#1][#2]% + {\bgroup + \ifnotesenabled + \edef\currentnote{#1}% + \ifsecondargument + \unskip + \dodonotesymbol{\in[#2]}% + \else + \dodonotesymbol\lastnotesymbol + \fi + \fi + \egroup} + +\def\dodonotesymbol#1% + {\noteparameter\c!textcommand{\dosetnoteattributes\c!textstyle\c!textcolor#1}} + +%D Normally footnotes are saved as inserts that are called upon +%D as soon as the pagebody is constructed. The footnote +%D insertion routine looks just like the \PLAIN\ \TEX\ one, +%D except that we check for the end note state. + +% testcase for split bottom alignment see (a) below +% +% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}} + +\def\placenoteinserts + {\processnotes\doplacenoteinserts} + +\def\unvboxed {\ifvmode\unvbox \else\box \fi} +\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} + +\def\doplacenoteinserts + {\relax\ifdim\ht\currentnoteins>\zeropoint\relax + \ifnum\noteparameter\s!noteloc=\plusfive + \else + \endgraf + \ifvmode + \whitespace + \noteparameter\c!before + \fi + \placenoterule % alleen in ..mode + \bgroup + \setnotebodyfont + \setbox\scratchbox\hbox + {% this should be checked, smells like a mix-up + % does not split: \ifcase\noteparameter\c!n\unvbox\else\box\fi\currentnoteins + \ifcase\noteparameter\c!n\relax + \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins + \or + \iftrialtypesetting\copy\else\box\fi\currentnoteins + \obeydepth % (a) added , since split footnotes will not align properly + \else + \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins + \fi}% + \setbox\scratchbox\hbox + {\localframed + [\??vn\currentnote] + [\c!width=\v!fit, + \c!height=\v!fit, + \c!strut=\v!no, + \c!offset=\v!overlay] + {\ifdim\dp\scratchbox=\zeropoint % this hack is needed because \vadjust + \hbox{\lower\strutdp\box\scratchbox}% % in margin number placement + \else % hides the (always) present depth + \box\scratchbox + \fi}}% + \setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}% + \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth + \box\scratchbox + \egroup + \endgraf + \ifvmode + \noteparameter\c!after + \fi + \fi + \fi} + +%D Supporting end notes is surprisingly easy. Even better, we +%D can combine this feature with solving the common \TEX\ +%D problem of disappearing inserts when they're called for in +%D deeply nested boxes. The general case looks like: +%D +%D \starttyping +%D \postponenotes +%D \.box{whatever we want with footnotes} +%D \flushnotes +%D \stoptyping +%D +%D This alternative can be used in headings, captions, tables +%D etc. The latter one sometimes calls for notes local to +%D the table, which can be realized by saying +%D +%D \starttyping +%D \setlocalfootnotes +%D some kind of table with local footnotes +%D \placelocalfootnotes +%D \stoptyping +%D +%D Postponing is accomplished by simply redefining the (local) +%D insert operation. A not too robust method uses the +%D \type{\insert} primitive when possible. This method fails in +%D situations where it's not entirely clear in what mode \TEX\ +%D is. Therefore the auto method can is to be overruled when +%D needed. + +\newconditional\postponingnotes + +% we need a proper state: normal, postponing, flushing + +\def\postponenotes + {\ifconditional\postponingnotes\else + \global\settrue\postponingnotes + \global\let\flushnotes\doflushnotes + \ctxlua{structure.notes.postpone()}% + \fi} + +\let\flushnotes\relax + +\def\doflushnotes + {\ifconditional\postponingnotes + \begingroup + \let\flushnotes \relax + \let\postponenotes\relax + \ctxlua{structure.notes.flushpostponed()}% this also resets the states ! + \global\setfalse\postponednote + \global\setfalse\postponingnotes + \global\let\flushnotes\relax + \endgroup + \fi} + +%D \macros +%D {startlocalfootnotes,placelocalfootnotes} +%D +%D The next two macros can be used in for instance tables, as +%D we'll demonstrate later on. +%D +%D \showsetup{startlocalfootnotes} +%D \showsetup{placelocalfootnotes} + +% todo: compatibility mode: when first arg is assignment or missing, then all + +\newtoks\everyplacelocalnotes + +\appendtoks + \let\flushnotes \relax + \let\postponenotes\relax +\to \everyplacelocalnotes + +\def\defaultnotewidth{\makeupwidth} % {\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi} + +\def\startlocalnotes + {\dosingleempty\dostartlocalnotes} + +\def\dostartlocalnotes[#1]% + {\def\localnoteslist{#1}% + \processcommacommand[\localnoteslist]\dodostartlocalnotes} + +\def\stoplocalnotes + {\processcommacommand[\localnoteslist]\dodostoplocalnotes} + +\def\dodostartlocalnotes#1% + {\savestructurecounter[#1]% + \resetstructurecounter[#1]% + \ctxlua{structure.notes.save("#1","store")}} + +\def\dodostoplocalnotes#1% + {\restorestructurecounter[#1]% + \ctxlua{structure.notes.restore("#1")}} + +\def\placelocalnotes + {\dodoubleempty\doplacelocalnotes} + +\def\doplacelocalnotes[#1][#2]% + {\doif{\ctxlua{structure.notes.getstate("#1")}}{store}{\dodoplacelocalnotes{#2}{#1}}} + +\def\dodoplacelocalnotes#1#2% settings note + {\begingroup + \the\everyplacelocalnotes + % beware, we cannot trust setting \currentnote here + \getparameters[\??vn#2][\c!width=\v!fit,\c!height=\v!fit,\c!strut=\v!no,\c!offset=\v!overlay,#1]% we only need a selective one + \donotealternative{#2}% + \endgroup + \dochecknote} % we need to restore the old state + +%D These commands can be used like: +%D +%D \startbuffer +%D \startlocalnotes[width=.3\hsize,n=0] +%D \placetable +%D {Some Table} +%D \placeontopofeachother +%D {\starttable[|l|r|] +%D \HL +%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR +%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR +%D \HL +%D \stoptable} +%D {\placelocalnotes} +%D \stoplocalnotes +%D \stopbuffer +%D +%D \typebuffer +%D +%D Because this table placement macro expect box content, and +%D thanks to the grouping of the local footnotes, we don't need +%D additional braces. +%D +%D \getbuffer + +%D \macros +%D {placefootnotes} +%D +%D We still have no decent command for placing footnotes +%D somewhere else than at the bottom of the page (for which no +%D user action is needed). Footnotes (endnotes) can be +%D placed by using +%D +%D \showsetup{placefootnotes} + +\def\placebottomnotes + {\processnotes\placenoteinserts} + +\def\placenotes + {\dodoubleempty\doplacenotes} + +\def\doplacenotes[#1][#2]% + {\processcommalist[#1]{\dodoplacenotes{#2}}} + +\def\dodoplacenotes#1#2% settings note + {\edef\currentnote{#2}% + \doifelse{\ctxlua{structure.notes.getstate("#2")}}{store} + \dodoplacelocalnotes + \dodoplaceglobalnotes + {#1}{#2}} + +\def\dodoplaceglobalnotes#1#2% + {\begingroup + \setupnote[#2][#1]% + \doplacenoteinserts + \endgroup + \the\everysetupnote} % to be checkes + +%D Placement + +\long\def\installnotealternative#1#2% + {\setvalue{\??vn:\c!alternative:#1}{#2}} + +\def\doifnotescollected#1% + {\ctxlua{structure.notes.doifcontent("#1")}} + +\def\donotealternative#1% + {\edef\currentnote{#1}% + \doifnotescollected\currentnote + {\endgraf + \ifvmode + \whitespace + \noteparameter\c!before + \fi + \begingroup + \setnotebodyfont + \getvalue{\??vn:\c!alternative:\noteparameter\c!alternative}% + \endgroup + \ifvmode + \noteparameter\c!after + \fi}} + +\setvalue{\??vn:\c!alternative:}{\getvalue{\??vn:\c!alternative:\v!none}} + +%D A stupid alternative is also provided: +%D +%D \starttyping +%D \setupfootnotes[location=text,alternative=none] +%D \stoptyping + +\def\flushlocalnotes#1{\ctxlua{structure.notes.flush("#1","store")}} + +\installnotealternative \v!none + {\flushlocalnotes\currentnote} + +\installnotealternative \v!grid % test if n > 0 + {\snaptogrid\hbox + {\localframed + [\??vn\currentnote] + {\flushlocalnotes\currentnote}}} + +\installnotealternative \v!fixed % test if n > 0 + {\localframed + [\??vn\currentnote] + {\flushlocalnotes\currentnote}} + +\installnotealternative \v!columns % redundant + {\localframed + [\??vn\currentnote] + {\edef\currentnotewidth{\noteparameter\c!width}% + \doifdimensionelse\currentnotewidth\donothing + {\edef\currentnotewidth{\the\hsize}}% +% \setupinmargin[\c!align=\v!left]% + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]% + \flushlocalnotes\currentnote + \stopsimplecolumns}} + +%D \macros +%D {fakenotes} + + % is this ok? endnotes and such + + \def\fakenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalclevernoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + \def\fakepagenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalpagenoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + \newdimen\totalnoteheight + + \def\doaddtototalnoteheight#1% + {\ifdim\ht#1>\zeropoint + \advance\totalnoteheight\ht #1% + \advance\totalnoteheight\skip#1% + \fi} + + \def\docalculatetotalnoteheight + {\ifcase\clevernotes % tricky here ! ! ! to be sorted out ! ! ! + \doaddtototalnoteheight\currentnoteins + \else + \doaddtototalnoteheight\currentbackupnoteins + \fi} + + \def\docalculatetotalclevernoteheight + {\ifcase\clevernotes \else % tricky here ! ! ! to be sorted out ! ! ! + \doaddtototalnoteheight\currentnoteins + \fi} + + \def\docalculatetotalpagenoteheight + {\doaddtototalnoteheight\currentnoteins} + + \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\processnotes\docalculatetotalnoteheight} + \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\processnotes\docalculatetotalclevernoteheight} + \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\processnotes\docalculatetotalpagenoteheight} + + \newif\ifnotespresent + + \def\dochecknotepresence + {\ifdim\ht\currentnoteins>\zeropoint + \notespresenttrue + \fi} + + \def\checknotepresence + {\notespresentfalse + \processnotes\dochecknotepresence} + +%D Now how can this mechanism be hooked into \CONTEXT\ without +%D explictly postponing footnotes? The solution turned out to +%D be rather simple: +%D +%D \starttyping +%D \everypar {...\flushnotes...} +%D \neverypar {...\postponenotes} +%D \stoptyping +%D +%D and +%D +%D \starttyping +%D \def\ejectinsert% +%D {... +%D \flushnotes +%D ...} +%D \stoptyping +%D +%D We can use \type{\neverypar} because in most commands +%D sensitive to footnote gobbling we disable \type{\everypar} +%D in favor for \type{\neverypar}. In fact, this footnote +%D implementation is the first to use this scheme. + +%D This is a nasty and new secondary footnote flusher. It +%D can be hooked into \type {\everypar} like: +%D +%D \starttyping +%D \appendtoks \synchronizenotes \to \everypar +%D \stoptyping + + % \def\dosynchronizenotes + % {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi} + % + % \def\synchronizenotes + % {\processnotes\dosynchronizenotes} + +\let\synchronizenotes\relax + +%D When typesetting footnotes, we have to return to the +%D footnote specific bodyfont size, which is in most cases derived +%D from the global document bodyfont size. In the previous macros +%D we already used a footnote specific font setting macro. + +\def\setnotebodyfont + {\let\setnotebodyfont\relax + \restoreglobalbodyfont + \switchtobodyfont[\noteparameter\c!bodyfont]% + \setuptolerance[\noteparameter\c!tolerance]% + \setupalign[\noteparameter\c!align]} + +%D The footnote mechanism defaults to a traditional one +%D column way of showing them. By default we precede them by +%D a small line. + +\ifx\v!endnote\undefined \def\v!endnote{endnote} \fi + +\definenote [\v!footnote] +\definenote [\v!endnote ] [\c!location=\v!none] % else no break + +%D Compatibility macros: + + \def\setupfootnotedefinition{\setupnotedefinition [\v!footnote]} + \def\setupfootnotes {\setupnote [\v!footnote]} +%unexpanded \def\footnote {\setnote [\v!footnote]} +\unexpanded \def\footnotetext {\setnotetext [\v!footnote]} + %def\note {\dodoubleempty\notesymbol [\v!footnote]} % alleen footnote + \def\placefootnotes {\dodoubleempty\doplacefootnotes [\v!footnote]} + \def\placelocalfootnotes {\dodoubleempty\doplacelocalfootnotes[\v!footnote]} + \def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote + \def\stoplocalfootnotes {\stoplocalnotes } + +\def\doplacefootnotes [#1][#2]{\ifsecondargument\placenotes [#1][#2,\c!height=\textheight]\else\placenotes [#1]\fi} +\def\doplacelocalfootnotes[#1][#2]{\ifsecondargument\placelocalnotes[#1][#2,\c!height=\textheight]\else\placelocalnotes[#1]\fi} + +\def\note{\dodoubleempty\donote} + +\def\donote[#1][#2]{\ifsecondargument\donotesymbol[#1][#2]\else\secondargumenttrue\donotesymbol[\v!footnote][#1]\fi} + +%D New trickery: + +\def\ownnotesymbol#1% #1 gets number passed + {\executeifdefined{\??vn::\currentnote}\empty} + +\def\setnotesymbol[#1]#2#3% + {\prewordbreak % prevent lookback + \setgvalue{\??vn::#1}{#3} + \dolastnotesymbol} + +\def\ownnote[#1]#2#3#4% + {\setnotesymbol[#1]{#2}{#3}% + \setnotetext [#1]{#4}} + +\defineconversion + [ownnote] + [\ownnotesymbol] + +\protect \endinput |