scrn-but.mkvi /size: 33 Kb    last modification: 2021-10-28 13:50
1%D \module
2%D   [       file=scrn-but, % moved code
3%D        version=1995.01.01,
4%D          title=\CONTEXT\ Core Macros,
5%D       subtitle=Interaction,
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 Screen Macros / Buttons}
15
16\registerctxluafile{scrn-but}{}
17
18\unprotect
19
20%D Buttons are just what their names says: things that can be clicked (pushed) on.
21%D They are similar to \type{\goto}, except that the text argument is not
22%D interpreted. Furthermore one can apply anything to them that can be done with
23%D \type {\framed}.
24%D
25%D \startbuffer
26%D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer]
27%D \stopbuffer
28%D
29%D \typebuffer
30%D
31%D gives
32%D
33%D \getbuffer
34%D
35%D This command is formally specified as:
36%D
37%D \showsetup{button}
38%D
39%D The characteristics can be set with:
40%D
41%D \showsetup{setupbuttons}
42
43\installcorenamespace{button}
44\installcorenamespace{buttonlocation}
45
46\installframedcommandhandler \??button {button} \??button
47
48\let\setupbuttons\setupbutton
49
50\appendtoks
51    \setuevalue\currentbutton{\scrn_button_direct{\currentbutton}}%
52\to \everydefinebutton
53
54\unexpanded\def\scrn_button_direct#tag%
55  {\begingroup
56   \edef\currentbutton{#tag}%
57   \doifelselocation
58     {\dosingleempty\scrn_button_direct_status}%
59     {\dosingleempty\scrn_button_direct_ignore}}
60
61\def\scrn_button_direct_status
62  {\doifelse{\buttonparameter\c!state}\v!start
63     \scrn_button_direct_indeed
64     \scrn_button_direct_ignore}
65
66% empty=yes
67%
68% \button[settings]{}[action] % normally used at the tex end
69
70\def\scrn_button_direct_indeed[#settings]#text[#action]%
71  {\iffirstargument
72     \setupcurrentbutton[#settings]%
73   \fi
74   % no \dontleavehmode as it will force a vbox to \hsize which then
75   % spoils a tight box
76   \hpack\bgroup
77     \scrn_button_make
78       \buttonparameter
79       \inheritedbuttonframed
80       \letbuttonparameter
81       \setbuttonparameter
82       {#text}%
83       {#action}%
84   \egroup
85   \endgroup}
86
87\def\scrn_button_direct_ignore[#settings]#text[#destination]%
88  {\endgroup}
89
90\definebutton[button] % english
91
92\setupbuttons
93  [\c!state=\v!start,
94   \c!width=\v!fit,
95   \c!height=\v!broad,
96   \c!offset=0.25\emwidth,
97   \c!frame=\v!on,
98   \c!background=,
99   \c!backgroundcolor=,
100   \c!foregroundstyle=\buttonparameter\c!style,
101   \c!foregroundcolor=\buttonparameter\c!color,
102   \c!style=\interactionparameter\c!style,
103   \c!color=\interactionparameter\c!color,
104   \c!contrastcolor=\interactionparameter\c!contrastcolor,
105   \c!samepage=\v!yes,
106   \c!unknownreference=\v!yes,
107   \c!distance=\zeropoint] % for menubuttons
108
109%D \macros
110%D   {overlaybutton}
111%D
112%D For converience we provide:
113%D
114%D \starttyping
115%D \overlaybutton[reference]
116%D \stoptyping
117%D
118%D This command can be used to define overlays an/or can be used in the whatevertext
119%D areas, like:
120%D
121%D \starttyping
122%D \defineoverlay[PrevPage][\overlaybutton{PrevPage}]
123%D \setupbackgrounds[page][background=PrevPage]
124%D \setuptexttexts[\overlaybutton{NextPage}]
125%D \stoptyping
126%D
127%D For practical reasons, this macro accepts square brackets as well as braces.
128
129\unexpanded\def\overlaybutton
130  {\dosingleempty\scrn_button_overlay}
131
132\def\scrn_button_overlay[#1]%
133  {\iffirstargument
134     \scrn_button_overlay_indeed{#1}%
135   \else
136     \expandafter\scrn_button_overlay_indeed
137   \fi}
138
139\def\scrn_button_overlay_indeed#1%
140  {\iflocation
141     \gotobox{\overlayfakebox}[#1]%
142   \fi}
143
144%D The renderers:
145
146\expandafter\let\csname\??buttonlocation\v!yes    \endcsname\zerocount
147\expandafter\let\csname\??buttonlocation\v!empty  \endcsname\plusone
148\expandafter\let\csname\??buttonlocation\v!no     \endcsname\plustwo
149\expandafter\let\csname\??buttonlocation\v!none   \endcsname\plusthree
150\expandafter\let\csname\??buttonlocation\v!normal \endcsname\plusone % default
151\expandafter\let\csname\??buttonlocation\s!default\endcsname\plusone % default
152\expandafter\let\csname\??buttonlocation          \endcsname\plusone % default
153
154\newconditional\c_scrn_button_skipped
155
156\def\scrn_button_make#currentparameter#inheritedframed#letparameter#setparameter#text#action%
157  {\begingroup
158   \c_attr_reference\attributeunsetvalue
159   \global\setfalse\c_scrn_button_skipped
160   \chardef\locationboxpagestate\csname\??buttonlocation#currentparameter\c!samepage\endcsname % ?? bt: todo
161   \doifelsereferencefound{#action}\scrn_button_make_yes\scrn_button_make_nop
162     #currentparameter%
163     #inheritedframed%
164     #letparameter%
165     #setparameter
166     {#text}%
167   \endgroup}
168
169\def\scrn_button_make_yes
170  {\scratchcounter\referencerealpage\relax % called in otr
171   \ifcase\scratchcounter
172     \expandafter\scrn_button_make_normal   % no state :  something else than a page reference
173   \else\ifnum\scratchcounter=\realpageno
174     \expandafter\expandafter\expandafter\scrn_button_make_yes_same
175   \else
176     \expandafter\expandafter\expandafter\scrn_button_make_yes_other
177   \fi\fi}
178
179\def\scrn_button_make_yes_same
180  {\ifcase\locationboxpagestate\relax
181     \expandafter\scrn_button_make_contrast % same page:  yes: same page or not ... todo
182   \or
183     \expandafter\scrn_button_make_empty    % same page:  empty but frame: no click
184   \or
185     \expandafter\scrn_button_make_nothing  % same page:  empty no frame: no
186   \else
187     \expandafter\scrn_button_make_skipped  % same page:  nothing at all
188   \fi}
189
190\def\scrn_button_make_yes_other
191  {\ifcase\locationboxpagestate\relax
192     \expandafter\scrn_button_make_normal   % other page: yes: same page or not ... todo
193   \or
194     \expandafter\scrn_button_make_normal   % other page: empty but frame: no click
195   \or
196     \expandafter\scrn_button_make_normal   % other page: empty no frame: no
197   \else
198     \expandafter\scrn_button_make_skipped  % other page: nothing at all
199   \fi}
200
201\def\scrn_button_make_nop
202  {\ifcase\locationboxpagestate\relax
203      \expandafter\scrn_button_make_framed
204   \or
205      \expandafter\scrn_button_make_empty
206   \or
207      \expandafter\scrn_button_make_nothing
208   \or
209      \expandafter\scrn_button_make_skipped
210   \fi}
211
212\def\scrn_button_make_framed#currentparameter#inheritedframed#letparameter#setparameter#text%
213  {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}
214
215\def\scrn_button_make_skipped#currentparameter#inheritedframed#letparameter#setparameter#text%
216  {\global\settrue\c_scrn_button_skipped}
217
218\def\scrn_button_make_normal#currentparameter#inheritedframed#letparameter#setparameter#text%
219  {\clf_injectcurrentreference
220   \hbox attr \referenceattribute \lastreferenceattribute
221     {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
222
223\def\scrn_button_make_contrast#currentparameter#inheritedframed#letparameter#setparameter#text%
224  {\clf_injectcurrentreference
225   \hbox attr \referenceattribute \lastreferenceattribute
226     {#setparameter\c!foregroundcolor{#currentparameter\c!contrastcolor}%
227      #inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
228
229\def\scrn_button_make_empty#currentparameter#inheritedframed#letparameter#setparameter#text%
230  {#letparameter\c!empty\v!yes
231   #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
232
233\def\scrn_button_make_nothing#currentparameter#inheritedframed#letparameter#setparameter#text%
234  {#letparameter\c!empty\v!yes
235   #letparameter\c!frame\empty
236   #letparameter\c!background\empty
237   #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
238
239%D Menus:
240%D
241%D \starttyping
242%D \setuppapersize
243%D   [S6][S6]
244%D
245%D \setuplayout
246%D   [backspace=6cm,      cutspace=6cm,
247%D    leftedge=3cm,       rightedge=3cm,
248%D    leftmargin=1cm,     rightmargin=1cm,
249%D    margindistance=5mm, edgedistance=5mm,
250%D    topspace=4cm,       bottomspace=4cm,
251%D    header=0pt,         footer=0pt,
252%D    top=1cm,            bottom=1cm,
253%D    topdistance=5mm,    bottomdistance=5mm,
254%D    width=middle,       height=middle]
255%D
256%D \setupinteraction
257%D   [state=start,
258%D    menu=on]
259%D
260%D \setupinteractionmenu
261%D   [right]
262%D   [state=start,background=color,frame=off,backgroundcolor=red,color=white,contrastcolor=blue]
263%D \setupinteractionmenu
264%D   [left]
265%D   [state=start,background=color,frame=off,backgroundcolor=green,color=white]
266%D \setupinteractionmenu
267%D   [top]
268%D   [state=start,background=color,frame=off,backgroundcolor=blue,color=white]
269%D \setupinteractionmenu
270%D   [bottom]
271%D   [state=start,background=color,frame=off,backgroundcolor=yellow,color=white]
272%D
273%D \setupinteractionmenu
274%D   [left]
275%D   [state=local]
276%D \setupinteractionmenu
277%D   [bottom]
278%D   [state=local]
279%D
280%D \startinteractionmenu[right]
281%D     \startbut [page(2)] Page 2 \stopbut
282%D     \startbut [page(1)] Page 1 \stopbut
283%D     \includemenu[left]
284%D     \includemenu[bottom]
285%D \stopinteractionmenu
286%D
287%D \startinteractionmenu[left]
288%D     \startbut [page(1)] Page 1 \stopbut
289%D     \startbut [page(2)] Page 2 \stopbut
290%D \stopinteractionmenu
291%D
292%D \startinteractionmenu[top]
293%D     \startbut [page(1)] Page 1 \stopbut
294%D     \startbut [page(2)] Page 2 \stopbut
295%D \stopinteractionmenu
296%D
297%D \startinteractionmenu[bottom]
298%D     \startbut [page(2)] Page 2 \stopbut
299%D     \startbut [page(1)] Page 1 \stopbut
300%D \stopinteractionmenu
301%D \stoptyping
302%D
303%D \starttyping
304%D \startinteractionmenu[rechts]
305%D   \startbut [eerste]  eerste  \stopbut
306%D   \starttxt hello world       \stoptxt
307%D   \startbut [tweede]  tweede  \stopbut
308%D   \startnop                   \stopnop
309%D   \startbut [tweede]  tweede  \stopbut
310%D   \startrul whow              \stoprul
311%D   \startbut [tweede]  tweede  \stopbut
312%D   \startraw hello world       \stopraw
313%D   \startbut [tweede]  tweede  \stopbut
314%D   \startcom \vfill            \stopcom
315%D   \startbut [derde]   derde   \stopbut
316%D \stopinteractionmenu
317%D \stoptyping
318%D
319%D \starttyping
320%D \setupinteractionmenu[right][samepage=yes,  unknownreference=yes]
321%D \setupinteractionmenu[right][samepage=empty,unknownreference=empty]
322%D \setupinteractionmenu[right][samepage=no,   unknownreference=no]
323%D \setupinteractionmenu[right][samepage=none, unknownreference=none]
324%D \stoptyping
325
326\installcorenamespace{menu}
327\installcorenamespace{menutoks}
328\installcorenamespace{menustate}
329\installcorenamespace{menupacker}
330\installcorenamespace{menualign}
331
332\installframedcommandhandler \??menu {interactionmenu} \??menu
333
334\let\setupinteractionmenus\setupinteractionmenu
335
336\let\scrn_menu_action\relax
337
338\let\scrn_menu_define_original\defineinteractionmenu
339
340\unexpanded\overloaded\def\defineinteractionmenu
341  {\dotripleempty\scrn_menu_define}
342
343\def\scrn_menu_define[#tag][#category][#settings]% category reflects location, settings can be parent
344  {\ifthirdargument
345     \doifelseassignment{#settings}%
346       {\scrn_menu_define_original[#tag][#category][\c!category=#category,#settings]}% child definition
347       {\scrn_menu_define_original[#tag][#settings][\c!category=#category]}%         % child definition
348     \scrn_menu_register{#tag}{#category}%
349   \else\ifsecondargument
350     \doifelseassignment{#category}%
351       {\scrn_menu_define_original[#tag][#category]}%                                % root definition
352       {\scrn_menu_define_original[#tag][#category][\c!category=#category]%          % child definition
353        \scrn_menu_register{#tag}{#category}}%
354  \else
355     \scrn_menu_define_original[#tag]%                                               % root definition
356   \fi\fi}
357
358\def\scrn_menu_register#tag#category%
359  {\ifcsname\??menutoks#category\endcsname \else
360     \expandafter\newtoks \csname\??menutoks#category\endcsname
361     \expandafter\setfalse\csname\??menustate#category\endcsname
362   \fi
363   \normalexpanded{\csname\??menutoks#category\endcsname{\the\csname\??menutoks#category\endcsname\scrn_menu_action{#tag}}}}
364
365\def\scrn_menu_actions#category%
366  {\the\csname\??menutoks#category\endcsname}
367
368%D Fill menus:
369
370\normalexpanded{\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}%
371  {\def\currentinteractionmenu{#tag}%
372   \expandafter\settrue\csname\??menustate\interactionmenuparameter\c!category\endcsname
373   \setinteractionmenuparameter\c!menu{#content}}
374
375\def\resetinteractionmenu[#tag]%
376  {\def\currentinteractionmenu{#tag}%
377   \resetinteractionmenuparameter\c!menu}
378
379%D Placement of menus:
380%D
381%D The offset mechanism is not the same as in in \MKII. There we
382%D adapted automatically to offsets in the text backgrounds. Here we
383%D have a bit more (but manual) control.
384%D
385%D \starttyping
386%D \setupbackgrounds
387%D   [text][text]
388%D   [background=color,backgroundcolor=gray,backgroundoffset=2mm]
389%D
390%D \setupbackgrounds
391%D   [text]
392%D   [rightedge,leftedge]
393%D   [background=color,backgroundcolor=gray]
394%D
395%D \setupbackgrounds
396%D   [top,bottom]
397%D   [text]
398%D   [background=color,backgroundcolor=gray]
399%D
400%D \setupinteractionmenu
401%D   [right]
402%D   [topoffset=0mm,bottomoffset=0mm]
403%D
404%D \setupinteractionmenu
405%D   [top]
406%D   [topoffset=2mm,bottomoffset=2mm,rightoffset=2mm,leftoffset=2mm]
407%D \stoptyping
408%D
409%D The no longer hard coded text areas offset compensation makes tuning
410%D easier. After all, menus need some setup anyway. The offsets are
411%D added to the width or height (this is different from \MKII).
412
413\newbox  \b_scrn_menu
414
415\newdimen\d_scrn_menu_next_distance
416\newdimen\d_scrn_menu_final_width
417\newdimen\d_scrn_menu_final_height
418\newdimen\d_scrn_menu_used_width
419\newdimen\d_scrn_menu_used_height
420\newdimen\d_scrn_menu_asked_width
421\newdimen\d_scrn_menu_asked_height
422\newdimen\d_scrn_menu_offset_top
423\newdimen\d_scrn_menu_offset_bottom
424\newdimen\d_scrn_menu_offset_left
425\newdimen\d_scrn_menu_offset_right
426
427\newconditional\c_scrn_menu_zerodimensions
428
429\def\scrn_menu_set_used
430  {\doassigncheckedframeoffset\d_scrn_menu_offset_left  {\interactionmenuparameter\c!leftoffset  }%
431   \doassigncheckedframeoffset\d_scrn_menu_offset_right {\interactionmenuparameter\c!rightoffset }%
432   \doassigncheckedframeoffset\d_scrn_menu_offset_top   {\interactionmenuparameter\c!topoffset   }%
433   \doassigncheckedframeoffset\d_scrn_menu_offset_bottom{\interactionmenuparameter\c!bottomoffset}%
434   \d_scrn_menu_asked_width  \interactionmenuparameter\c!maxwidth
435   \d_scrn_menu_asked_height \interactionmenuparameter\c!maxheight
436   \d_scrn_menu_used_width\dimexpr
437     \d_scrn_menu_asked_width  + \d_scrn_menu_offset_left + \d_scrn_menu_offset_right
438   \relax
439   \d_scrn_menu_used_height\dimexpr
440     \d_scrn_menu_asked_height + \d_scrn_menu_offset_top  + \d_scrn_menu_offset_bottom
441   \relax}
442
443\def\scrn_menu_set_final
444  {\d_scrn_menu_final_width \namedinteractionmenuparameter\askedinteractionmenulocation\c!maxwidth
445   \d_scrn_menu_final_height\namedinteractionmenuparameter\askedinteractionmenulocation\c!maxheight}
446
447\def\scrn_menu_apply_final
448  {\ifconditional\c_scrn_menu_zerodimensions
449     \wd\b_scrn_menu\zeropoint
450     \ht\b_scrn_menu\zeropoint
451   \else
452     \wd\b_scrn_menu\d_scrn_menu_final_width
453     \ht\b_scrn_menu\d_scrn_menu_final_height
454   \fi
455   \dp\b_scrn_menu\zeropoint}
456
457\def\scrn_menu_apply_used
458  {\ifzeropt\d_scrn_menu_offset_left \else
459     \setbox\b_scrn_menu\hbox{\hskip-\d_scrn_menu_offset_left   \box\b_scrn_menu}%
460   \fi
461   \ifzeropt\d_scrn_menu_offset_bottom \else
462     \setbox\b_scrn_menu\hbox{\lower \d_scrn_menu_offset_bottom \box\b_scrn_menu}%
463   \fi
464   \wd\b_scrn_menu\d_scrn_menu_asked_width
465   \ht\b_scrn_menu\d_scrn_menu_asked_height
466   \dp\b_scrn_menu\zeropoint}
467
468\setvalue{\??menualign\v!right     }{\let\scrn_menu_left_align\raggedright}
469\setvalue{\??menualign\v!left      }{\let\scrn_menu_left_align\raggedleft}
470\setvalue{\??menualign\v!flushright}{\let\scrn_menu_left_align\raggedleft}
471\setvalue{\??menualign\v!flushleft }{\let\scrn_menu_left_align\raggedright}
472\setvalue{\??menualign\v!middle    }{\let\scrn_menu_left_align\raggedcenter}
473\setvalue{\??menualign\v!low       }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\relax}
474\setvalue{\??menualign\v!high      }{\let\scrn_menu_top_align\relax\let\scrn_menu_bottom_align\vss}
475\setvalue{\??menualign\v!lohi      }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\vss}
476
477\let\scrn_menu_left_align  \relax
478\let\scrn_menu_right_align \relax
479\let\scrn_menu_top_align   \relax
480\let\scrn_menu_bottom_align\relax
481
482\def\scrn_menu_set_align
483  {\csname\??menualign\interactionmenuparameter\c!itemalign\endcsname}
484
485%D Hook into the pagebuilder (as less testing as possible):
486
487\def\scrn_menu_insert
488  {\iflocation
489     \expandafter\scrn_menu_insert_checked
490   \else
491     \expandafter\gobbleoneargument
492   \fi}
493
494\def\scrn_menu_insert_checked#location%
495  {\ifconditional\csname\??menustate#location\endcsname
496     \scrn_menu_insert_indeed{#location}%
497   \fi}
498
499\def\scrn_menu_insert_indeed#location%
500  {\begingroup
501   \xdef\askedinteractionmenulocation{#location}%
502   \scrn_menu_set_final
503   \ifcase\d_scrn_menu_final_width \else \ifcase\d_scrn_menu_final_height \else
504     \forgetall
505     \global\d_scrn_menu_next_distance\zeropoint
506     \let\scrn_menu_action\scrn_menu_package_indeed
507     \the\everysetmenucommands
508     \csname\??menupacker\namedinteractionmenuparameter\askedinteractionmenulocation\c!alternative\endcsname
509   \fi \fi
510   \endgroup}
511
512%D This calls: % can be \c!command for vertical/horizontal
513
514\setvalue{\??menupacker\v!vertical}% all menus
515  {\let\scrn_menu_packager\scrn_menu_packager_vertical
516   \setbox\b_scrn_menu\hbox{\scrn_menu_actions\askedinteractionmenulocation}%
517   \scrn_menu_apply_final
518   \box\b_scrn_menu}
519
520\setvalue{\??menupacker\v!horizontal}% all menus
521  {\let\scrn_menu_packager\scrn_menu_packager_horizontal
522   \setbox\b_scrn_menu\vbox{\scrn_menu_actions\askedinteractionmenulocation}%
523   \scrn_menu_apply_final
524   \box\b_scrn_menu}
525
526% stop : skipped
527% start: processed
528% local: skipped but can be included
529% empty: processed but invisible
530
531\unexpanded\def\scrn_menu_package_indeed#tag% one menu
532  {\begingroup
533   \edef\currentinteractionmenu{#tag}%
534   \edef\currentinteractionmenustate{\interactionmenuparameter\c!state}%
535   \ifx\currentinteractionmenustate\v!start
536     \scrn_menu_packager
537   \else\ifx\currentinteractionmenustate\v!empty
538     \scrn_menu_packager
539   \fi\fi
540   \endgroup}
541
542%D With the packager being one of:
543
544\let\currentinteractionmenudistance\!!zeropoint
545
546\def\scrn_menu_packager_vertical
547  {\scrn_menu_set_used
548   \hskip\d_scrn_menu_next_distance
549   \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width
550     {\ifx\currentinteractionmenustate\v!empty \else
551        \interactionmenuparameter\c!left
552        \scrn_menu_package_vertical{\directinteractionmenuparameter\c!menu}%
553        \interactionmenuparameter\c!right
554      \fi}%
555   \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
556   \ifx\currentinteractionmenudistance\v!overlay
557     \global\d_scrn_menu_next_distance\zeropoint
558     \wd\b_scrn_menu\zeropoint
559   \else
560     \global\d_scrn_menu_next_distance\currentinteractionmenudistance
561     \scrn_menu_apply_used
562   \fi
563   \box\b_scrn_menu}
564
565\def\scrn_menu_packager_horizontal
566  {\scrn_menu_set_used
567   \vskip\d_scrn_menu_next_distance
568   \scrn_menu_set_align
569   \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height
570     {\ifx\currentinteractionmenustate\v!none \else
571        \scrn_menu_top_align
572        \interactionmenuparameter\c!before
573        \scrn_menu_package_horizontal{\directinteractionmenuparameter\c!menu}%
574        \interactionmenuparameter\c!after
575        \scrn_menu_bottom_align
576      \fi}%
577   \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
578   \ifx\currentinteractionmenudistance\v!overlay
579     \global\d_scrn_menu_next_distance\zeropoint
580     \offinterlineskip
581     \dp\b_scrn_menu\zeropoint
582     \ht\b_scrn_menu\zeropoint
583   \else
584     \global\d_scrn_menu_next_distance\currentinteractionmenudistance
585     \scrn_menu_apply_used
586   \fi
587   \box\b_scrn_menu}
588
589%D For a right menu, a sequence of calls to \type
590%D {right_menu_button} is generated.
591%D
592%D \starttyping
593%D right_menu_button (n, p, s=0/1/2, x, y, w, h, d) ;
594%D \stoptyping
595%D
596%D Here, n is the number of the button, s a status variable,
597%D while the rest is positional info. The status variable is
598%D 0, 1 or~2: not found, found and found but current page.
599
600\newcount      \c_scrn_menu_position
601\newconstant   \c_scrn_menu_page_mode % 0=notfound  1=found  2=currentpage
602\newconditional\c_scrn_menu_positioning
603\newtoks       \t_scrn_menu_meta_data
604
605\def\scrn_menu_button_meta_template
606  {\askedinteractionmenulocation _menu_button(%
607     \number\c_scrn_menu_position,%
608     \number\c_scrn_menu_page_mode,%
609     \MPpos{\askedinteractionmenulocation:\number\c_scrn_menu_position}%
610   );}
611
612\def\MPmenubuttons#1{\the\t_scrn_menu_meta_data}
613
614\appendtoks
615    \global\t_scrn_menu_meta_data\emptytoks
616\to \everyshipout
617
618\def\scrn_menu_whole_position % cannot happen in previous due to align
619  {\setbox\b_scrn_menu\hbox \bgroup
620     \hpos{menu:\askedinteractionmenulocation:\the\realpageno}{\box\b_scrn_menu}%
621   \egroup}
622
623% removed: \restorestandardblank (vspacing) ... should happen elsewhere
624
625\def\scrn_menu_package_vertical#content%
626  {\begingroup
627   \global\c_scrn_menu_position\zerocount
628   \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!inbetween}%
629   \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
630   \scrn_menu_set_align
631   \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height \bgroup
632     \hsize\d_scrn_menu_used_width
633     \scrn_menu_left_align
634     \interactionmenuparameter\c!before\relax
635     \ignorespaces#content\unskip
636     \interactionmenuparameter\c!after
637     \scrn_menu_right_align
638   \egroup
639   \ifconditional\c_scrn_menu_positioning
640     \scrn_menu_whole_position
641   \fi
642   \box\b_scrn_menu
643   \endgroup}
644
645\def\scrn_menu_package_horizontal#content%
646  {\begingroup
647   \global\c_scrn_menu_position\zerocount
648   \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!middle}%
649   \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
650   \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width \bgroup
651     \interactionmenuparameter\c!left\relax
652     \ignorespaces#content\unskip
653     \interactionmenuparameter\c!right
654   \egroup
655   \ifconditional\c_scrn_menu_positioning
656     \scrn_menu_whole_position
657   \fi
658   \box\b_scrn_menu
659   \endgroup}
660
661\def\scrn_menu_action_start
662  {\dontleavehmode
663   \begingroup}
664
665\def\scrn_menu_action_stop
666  {\ifconditional\c_scrn_button_skipped \else
667     \scrn_menu_between_action_indeed
668   \fi
669   \endgroup
670   \ignorespaces}
671
672\unexpanded\def\scrn_menu_raw_start[#action]#text\stopraw
673  {\scrn_menu_action_start
674   \gotobox{\ignorespaces#text\unskip}[#action]%
675   \scrn_menu_action_stop}
676
677\unexpanded\def\scrn_menu_but_start[#action]#text\stopbut
678  {\scrn_menu_action_start
679   \ifconditional\c_scrn_menu_positioning
680     \expandafter\scrn_button_make_position
681   \else
682     \expandafter\scrn_button_make
683   \fi
684     \interactionmenuparameter
685     \inheritedinteractionmenuframed
686     \letinteractionmenuparameter
687     \setinteractionmenuparameter
688     {#text}%
689     {#action}%
690   \scrn_menu_action_stop}
691
692\def\scrn_button_make_position#currentparameter#inheritedframed#letparameter#setparameter#text#action%
693  {\global\advance\c_scrn_menu_position\plusone
694   \doifelsereferencefound{#action}% 0=not found, 1=same page, >1=elsewhere
695     {\c_scrn_menu_page_mode\ifnum\currentreferencerealpage=\realpageno\plusone\else\plustwo\fi}%
696     {\c_scrn_menu_page_mode\plustwo}%
697   \doglobal\appendetoks
698     \scrn_menu_button_meta_template
699   \to \t_scrn_menu_meta_data
700   \hpos
701     {\askedinteractionmenulocation:\number\c_scrn_menu_position}%
702     {\scrn_button_make
703        #currentparameter%
704        #inheritedframed%
705        #letparameter%
706        #setparameter%
707        {#text}%
708        {#action}}}
709
710\unexpanded\def\scrn_menu_got_start[#action]#text\stopgot
711  {\scrn_menu_action_start
712   \letinteractionmenuparameter\c!frame\v!off
713   \letinteractionmenuparameter\c!background\empty
714   \scrn_button_make
715     \interactionmenuparameter
716     \inheritedinteractionmenuframed
717     \letinteractionmenuparameter
718     \setinteractionmenuparameter
719     {#text}%
720     {#action}%
721   \scrn_menu_action_stop}
722
723\unexpanded\def\scrn_menu_nop_start#text\stopnop
724  {\scrn_menu_action_start
725   \letinteractionmenuparameter\c!frame\v!off
726   \letinteractionmenuparameter\c!background\empty
727   \letinteractionmenuparameter\c!empty\v!yes
728   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
729   \scrn_menu_action_stop}
730
731\unexpanded\def\scrn_menu_txt_start#text\stoptxt
732  {\scrn_menu_action_start
733   \letinteractionmenuparameter\c!frame\v!off
734   \letinteractionmenuparameter\c!background\empty
735   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
736   \scrn_menu_action_stop}
737
738\unexpanded\def\scrn_menu_rul_start#text\stoprul
739  {\scrn_menu_action_start
740   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
741   \scrn_menu_action_stop}
742
743\unexpanded\def\scrn_menu_com_start#text\stopcom
744  {\ignorespaces#text\removeunwantedspaces
745   \ignorespaces}
746
747\unexpanded\def\scrn_menu_raw#content\\{\scrn_menu_raw_start#content\stopraw} \let\stopraw\relax
748\unexpanded\def\scrn_menu_but#content\\{\scrn_menu_but_start#content\stopbut} \let\stopbut\relax
749\unexpanded\def\scrn_menu_got#content\\{\scrn_menu_got_start#content\stopgot} \let\stopgot\relax
750\unexpanded\def\scrn_menu_nop#content\\{\scrn_menu_nop_start#content\stopnop} \let\stopnop\relax
751\unexpanded\def\scrn_menu_txt#content\\{\scrn_menu_txt_start#content\stoptxt} \let\stoptxt\relax
752\unexpanded\def\scrn_menu_rul#content\\{\scrn_menu_rul_start#content\stoprul} \let\stoprul\relax
753\unexpanded\def\scrn_menu_com#content\\{\scrn_menu_com_start#content\stopcom} \let\stopcom\relax
754
755\newtoks\everysetmenucommands % public
756
757\appendtoks
758    \let\raw\scrn_menu_raw \let\startraw\scrn_menu_raw_start \let\stopraw\relax
759    \let\but\scrn_menu_but \let\startbut\scrn_menu_but_start \let\stopbut\relax
760    \let\got\scrn_menu_got \let\startgot\scrn_menu_got_start \let\stopgot\relax
761    \let\nop\scrn_menu_nop \let\startnop\scrn_menu_nop_start \let\stopnop\relax
762    \let\txt\scrn_menu_txt \let\starttxt\scrn_menu_txt_start \let\stoptxt\relax
763    \let\rul\scrn_menu_rul \let\startrul\scrn_menu_rul_start \let\stoprul\relax
764    \let\com\scrn_menu_com \let\startcom\scrn_menu_com_start \let\stopcom\relax
765\to \everysetmenucommands
766
767%D Sometimes handy:
768%D
769%D \starttyping
770%D \setupinteractionmenu
771%D   [left]
772%D   [state=local]
773%D
774%D \startinteractionmenu[right]
775%D     ...
776%D     \includemenu[left]
777%D     ...
778%D \stopinteractionmenu
779%D \stoptyping
780
781\unexpanded\def\includemenu[#tag]%
782  {\begingroup
783   \edef\currentinteractionmenu{#tag}%
784   \doif{\interactionmenuparameter\c!state}\v!local
785     {\letinteractionmenuparameter\c!state\v!start
786      \directinteractionmenuparameter\c!menu}%
787   \endgroup}
788
789%D Direct call (todo):
790
791\unexpanded\def\interactionmenu
792  {\dodoubleempty\scrn_menu_interaction_menu}
793
794\def\scrn_menu_interaction_menu[#tag][#settings]%
795  {\begingroup
796   \edef\currentinteractionmenu{#tag}%
797   \setupcurrentinteractionmenu[#settings]%
798   \scrn_menu_insert{#tag}%
799   \endgroup}
800
801%D Plugin handler:
802
803\unexpanded\def\scrn_menu_insert_content_indeed
804  {\iflocation % here as we can have a fast turn-off
805     \expandafter\firstofoneargument
806   \else
807     \expandafter\gobbleoneargument
808   \fi}
809
810\let\scrn_menu_insert_content_ignore\gobbleoneargument
811
812\appendtoks
813    \doifelse{\interactionparameter\c!menu}\v!on
814      {\let\scrn_menu_insert_content\scrn_menu_insert_content_indeed}%
815      {\let\scrn_menu_insert_content\scrn_menu_insert_content_ignore}%
816\to \everysetupinteraction
817
818%D Plugs into the page builder:
819
820\unexpanded\def\scrn_menu_leftedge
821  {\hbox to \leftedgewidth \bgroup
822     \hsize\leftedgewidth
823     \settrue\c_scrn_menu_zerodimensions
824     \scrn_menu_insert\v!left
825   \egroup
826   \hskip-\leftedgewidth}
827
828\unexpanded\def\scrn_menu_rightedge
829  {\hbox to \rightedgewidth \bgroup
830     \hsize\rightedgewidth
831     \settrue\c_scrn_menu_zerodimensions
832     \scrn_menu_insert\v!right
833   \egroup
834   \hskip-\rightedgewidth}
835
836\unexpanded\def\scrn_menu_top
837  {\vbox to \topheight \bgroup
838     \vsize\topheight
839     \settrue\c_scrn_menu_zerodimensions
840     \scrn_menu_insert\v!top
841     \kern\zeropoint
842   \egroup
843   \vskip-\topheight}
844
845\unexpanded\def\scrn_menu_bottom
846  {\vbox to \bottomheight \bgroup
847     \vsize\bottomheight
848     \settrue\c_scrn_menu_zerodimensions
849     \scrn_menu_insert\v!bottom
850     \kern\zeropoint
851   \egroup
852   \vskip-\bottomheight}
853
854\appendtoks \scrn_menu_insert_content\scrn_menu_leftedge  \to \leftedgetextcontent
855\appendtoks \scrn_menu_insert_content\scrn_menu_rightedge \to \rightedgetextcontent
856\appendtoks \scrn_menu_insert_content\scrn_menu_top       \to \toptextcontent
857\appendtoks \scrn_menu_insert_content\scrn_menu_bottom    \to \bottomtextcontent
858
859%D Initialization (root definitions, main builders):
860
861\defineinteractionmenu [\v!vertical]   [\c!alternative=\v!vertical]
862\defineinteractionmenu [\v!horizontal] [\c!alternative=\v!horizontal]
863
864%D Initialization (parent definitions, 4 area builders):
865
866\defineinteractionmenu [\v!right ] [\v!right ] [\v!vertical  ]
867\defineinteractionmenu [\v!left  ] [\v!left  ] [\v!vertical  ]
868\defineinteractionmenu [\v!top   ] [\v!top   ] [\v!horizontal]
869\defineinteractionmenu [\v!bottom] [\v!bottom] [\v!horizontal]
870
871\setupinteraction
872  [\c!menu=\v!off]
873
874\setupinteractionmenu
875  [\c!offset=.25em,
876   \c!position=\v!no,
877   \c!frame=\v!on,
878   \c!maxwidth=\hsize,
879   \c!maxheight=\vsize,
880   \c!background=,
881   \c!backgroundcolor=,
882   \c!foregroundstyle=\interactionmenuparameter\c!style,
883   \c!foregroundcolor=\interactionmenuparameter\c!color,
884   \c!style=\interactionparameter\c!style,
885   \c!color=\interactionparameter\c!color,
886   \c!contrastcolor=\interactionparameter\c!contrastcolor,
887   \c!state=\v!start,
888   \c!samepage=\v!yes,
889   \c!unknownreference=\v!empty,
890   \c!distance=\bodyfontsize,
891   \c!topoffset=\zeropoint,
892   \c!bottomoffset=\zeropoint,
893   \c!leftoffset=\zeropoint,
894   \c!rightoffset=\zeropoint]
895
896\setupinteractionmenu
897  [\v!vertical] % not really a menu
898  [\c!inbetween=\blank,
899   \c!before=,
900   \c!after=\vfil,
901  %\c!width=\v!fit,
902   \c!height=\v!broad]
903
904\setupinteractionmenu
905  [\v!horizontal] % not really a menu
906  [\c!middle=\hfil,
907  %\c!left=\hss,
908  %\c!right=\hss,
909   \c!width=\v!fit,
910   \c!height=\v!broad]
911
912\setupinteractionmenu
913  [\v!left]
914  [\c!itemalign=\v!flushright,
915   \c!maxwidth=\leftedgewidth,
916   \c!maxheight=\makeupheight]
917
918\setupinteractionmenu
919  [\v!right]
920  [\c!itemalign=\v!flushleft,
921   \c!maxwidth=\rightedgewidth,
922   \c!maxheight=\makeupheight]
923
924\setupinteractionmenu
925  [\v!top]
926  [\c!itemalign=\v!high,
927   \c!maxwidth=\makeupwidth,
928   \c!maxheight=\topheight]
929
930\setupinteractionmenu
931  [\v!bottom]
932  [\c!itemalign=\v!low,
933   \c!maxwidth=\makeupwidth,
934   \c!maxheight=\bottomheight]
935
936%D Lists:
937
938\definelistalternative [\v!left  ] [\c!renderingsetup=strc:lists:rendering:menu]
939\definelistalternative [\v!right ] [\c!renderingsetup=strc:lists:rendering:menu]
940\definelistalternative [\v!top   ] [\c!renderingsetup=strc:lists:rendering:menu]
941\definelistalternative [\v!bottom] [\c!renderingsetup=strc:lists:rendering:menu]
942
943\startsetups[strc:lists:rendering:menu]
944    \startbut[internal(\currentlistentrylocation)]
945        \limitatetext\currentlistentrytitle{\listparameter\c!maxwidth}\unknown
946    \stopbut
947\stopsetups
948
949%D Sometimes handy:
950
951\unexpanded\def\menubutton % tag settings text action
952  {\dodoubleempty\scrn_menu_menu_button}
953
954\def\scrn_button_direct_status
955  {\doifelse{\buttonparameter\c!state}\v!start
956     {\dosingleempty\scrn_button_direct_indeed}%
957     {\dosingleempty\scrn_button_direct_ignore}}
958
959\def\scrn_menu_menu_button
960  {\iflocation
961     \expandafter\scrn_menu_menu_button_indeed
962   \else
963     \expandafter\scrn_menu_menu_button_ignore
964   \fi}
965
966\def\scrn_menu_menu_button_indeed[#menutag][#settings]#text[#action]%
967  {\ifsecondargument
968     \scrn_menu_menu_button_a
969       {#menutag}{#settings}{#text}{#action}%
970   \else
971     \doifelseassignment{#menutag}\scrn_menu_menu_button_b\scrn_menu_menu_button_c
972       {#menutag}{#text}{#action}%
973   \fi}
974
975\def\scrn_menu_menu_button_ignore[#menutag][#settings]#text[#action]%
976  {}
977
978\def\scrn_menu_menu_button_a#tag#settings#text#action%
979  {\doif{\interactionmenuparameter\c!state}\v!start
980     {\dontleavehmode \begingroup
981        \edef\currentinteractionmenu{#tag}%
982        \setupcurrentinteractionmenu[#settings]%
983        \scrn_button_make
984          \interactionmenuparameter
985          \inheritedinteractionmenuframed
986          \letinteractionmenuparameter
987          \setinteractionmenuparameter
988          {#text}%
989          {#action}%
990      \endgroup}}
991
992\def\scrn_menu_menu_button_b#settings#text#action%
993  {\doif{\buttonparameter\c!state}\v!start
994     {\dontleavehmode \begingroup
995        \let\currentbutton\empty
996        \setupcurrentbutton[#settings]%
997        \scrn_button_make
998          \buttonparameter
999          \inheritedbuttonframed
1000          \letbuttonparameter
1001          \setbuttonparameter
1002          {#text}%
1003          {#action}%
1004      \endgroup}}
1005
1006\def\scrn_menu_menu_button_c#tag#text#action%
1007  {\doif{\interactionmenuparameter\c!state}\v!start
1008     {\dontleavehmode \begingroup
1009        \edef\currentinteractionmenu{#tag}%
1010        \scrn_button_make
1011          \interactionmenuparameter
1012          \inheritedinteractionmenuframed
1013          \letinteractionmenuparameter
1014          \setinteractionmenuparameter
1015          {#text}%
1016          {#action}%
1017      \endgroup}}
1018
1019%D Untested:
1020
1021\unexpanded\def\registermenubuttons
1022  {\dodoubleempty\scrn_menu_register_menu_buttons}
1023
1024\def\scrn_menu_register_menu_buttons[#menu][#register]%
1025  {\begingroup
1026   \ifsecondargument
1027     \clf_registerbuttons{#menu}{#register}{\currentlanguage}%
1028   \else
1029     \clf_registerbuttons{}{#menu}{\currentlanguage}%
1030   \fi
1031   \removeunwantedspaces
1032   \endgroup}
1033
1034\def\doregistermenubutton#1#2#3% used at lua end
1035  {\scrn_menu_menu_button_c{#1}{#2}{#3}%
1036   \space}
1037
1038% or less readable:
1039%
1040% \def\scrn_menu_register_menu_buttons[#menu][#register]%
1041%   {\clf_registerbuttons\ifsecondargument{#menu}{#register}\else{}{#menu}\fi{\currentlanguage}}
1042
1043\protect \endinput
1044