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