scrn-but.mklx /size: 34 Kb    last modification: 2023-12-21 09:44
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\protected\instance\edefcsname\currentbutton\endcsname{\scrn_button_direct{\currentbutton}}%
54\to \everydefinebutton
55
56\protected\def\scrn_button_direct#tag%
57  {\begingroup
58   \cdef\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[#S#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[#S#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\c_scrn_button_skipped\conditionalfalse
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\c_scrn_button_skipped\conditionaltrue}
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\lettonothing\currentinteractionmenudistance
332\mutable\lettonothing\currentinteractionmenustate
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[#S#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\newconditional\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\expandafter\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\csname\e!stop\v!interactionmenu\endcsname}%
377  {\cdef\currentinteractionmenu{#tag}%
378  %\ifcsname\??menustate\interactionmenuparameter\c!category\endcsname\else
379  %  \expandafter\newconditional\csname\??menustate\interactionmenuparameter\c!category\endcsname
380  %\fi
381   \csname\??menustate\interactionmenuparameter\c!category\endcsname\conditionaltrue
382   \setinteractionmenuparameter\c!menu{#content}}
383
384\permanent\protected\def\resetinteractionmenu[#tag]%
385  {\cdef\currentinteractionmenu{#tag}%
386   \resetinteractionmenuparameter\c!menu}
387
388%D Placement of menus:
389%D
390%D The offset mechanism is not the same as in in \MKII. There we adapted
391%D automatically to offsets in the text backgrounds. Here we have a bit more (but
392%D manual) control.
393%D
394%D \starttyping
395%D \setupbackgrounds
396%D   [text][text]
397%D   [background=color,backgroundcolor=gray,backgroundoffset=2mm]
398%D
399%D \setupbackgrounds
400%D   [text]
401%D   [rightedge,leftedge]
402%D   [background=color,backgroundcolor=gray]
403%D
404%D \setupbackgrounds
405%D   [top,bottom]
406%D   [text]
407%D   [background=color,backgroundcolor=gray]
408%D
409%D \setupinteractionmenu
410%D   [right]
411%D   [topoffset=0mm,bottomoffset=0mm]
412%D
413%D \setupinteractionmenu
414%D   [top]
415%D   [topoffset=2mm,bottomoffset=2mm,rightoffset=2mm,leftoffset=2mm]
416%D \stoptyping
417%D
418%D The no longer hard coded text areas offset compensation makes tuning easier.
419%D After all, menus need some setup anyway. The offsets are added to the width or
420%D height (this is different from \MKII).
421
422\newbox      \b_scrn_menu
423
424\newdimension\d_scrn_menu_next_distance
425\newdimension\d_scrn_menu_final_width
426\newdimension\d_scrn_menu_final_height
427\newdimension\d_scrn_menu_used_width
428\newdimension\d_scrn_menu_used_height
429\newdimension\d_scrn_menu_asked_width
430\newdimension\d_scrn_menu_asked_height
431\newdimension\d_scrn_menu_offset_top
432\newdimension\d_scrn_menu_offset_bottom
433\newdimension\d_scrn_menu_offset_left
434\newdimension\d_scrn_menu_offset_right
435
436\newconditional\c_scrn_menu_zerodimensions
437
438\mutable\lettonothing\currentinteractionmenulocation
439
440\def\scrn_menu_set_used
441  {\d_scrn_menu_offset_left  \ifchkdimension\interactionmenuparameter\c!leftoffset  \or\lastchkdimension\else\zeropoint\fi
442   \d_scrn_menu_offset_right \ifchkdimension\interactionmenuparameter\c!rightoffset \or\lastchkdimension\else\zeropoint\fi
443   \d_scrn_menu_offset_top   \ifchkdimension\interactionmenuparameter\c!topoffset   \or\lastchkdimension\else\zeropoint\fi
444   \d_scrn_menu_offset_bottom\ifchkdimension\interactionmenuparameter\c!bottomoffset\or\lastchkdimension\else\zeropoint\fi
445   \d_scrn_menu_asked_width  \interactionmenuparameter\c!maxwidth
446   \d_scrn_menu_asked_height \interactionmenuparameter\c!maxheight
447   \d_scrn_menu_used_width\dimexpr
448     \d_scrn_menu_asked_width  + \d_scrn_menu_offset_left + \d_scrn_menu_offset_right
449   \relax
450   \d_scrn_menu_used_height\dimexpr
451     \d_scrn_menu_asked_height + \d_scrn_menu_offset_top  + \d_scrn_menu_offset_bottom
452   \relax}
453
454\def\scrn_menu_set_final
455  {\d_scrn_menu_final_width \namedinteractionmenuparameter\currentinteractionmenulocation\c!maxwidth
456   \d_scrn_menu_final_height\namedinteractionmenuparameter\currentinteractionmenulocation\c!maxheight}
457
458\def\scrn_menu_apply_final
459  {\ifconditional\c_scrn_menu_zerodimensions
460     \wd\b_scrn_menu\zeropoint
461     \ht\b_scrn_menu\zeropoint
462   \else
463     \wd\b_scrn_menu\d_scrn_menu_final_width
464     \ht\b_scrn_menu\d_scrn_menu_final_height
465   \fi
466   \dp\b_scrn_menu\zeropoint}
467
468\def\scrn_menu_apply_used
469  {\ifzeropt\d_scrn_menu_offset_left \else
470     \setbox\b_scrn_menu\hbox{\hskip-\d_scrn_menu_offset_left   \box\b_scrn_menu}%
471   \fi
472   \ifzeropt\d_scrn_menu_offset_bottom \else
473     \setbox\b_scrn_menu\hbox{\lower \d_scrn_menu_offset_bottom \box\b_scrn_menu}%
474   \fi
475   \wd\b_scrn_menu\d_scrn_menu_asked_width
476   \ht\b_scrn_menu\d_scrn_menu_asked_height
477   \dp\b_scrn_menu\zeropoint}
478
479\defcsname\??menualign\v!right     \endcsname{\let\scrn_menu_left_align\raggedright}
480\defcsname\??menualign\v!left      \endcsname{\let\scrn_menu_left_align\raggedleft}
481\defcsname\??menualign\v!flushright\endcsname{\let\scrn_menu_left_align\raggedleft}
482\defcsname\??menualign\v!flushleft \endcsname{\let\scrn_menu_left_align\raggedright}
483\defcsname\??menualign\v!middle    \endcsname{\let\scrn_menu_left_align\raggedcenter}
484\defcsname\??menualign\v!low       \endcsname{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\relax}
485\defcsname\??menualign\v!high      \endcsname{\let\scrn_menu_top_align\relax\let\scrn_menu_bottom_align\vss}
486\defcsname\??menualign\v!lohi      \endcsname{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\vss}
487
488\let\scrn_menu_left_align  \relax
489\let\scrn_menu_right_align \relax
490\let\scrn_menu_top_align   \relax
491\let\scrn_menu_bottom_align\relax
492
493\def\scrn_menu_set_align
494  {\begincsname\??menualign\interactionmenuparameter\c!itemalign\endcsname}
495
496%D Hook into the pagebuilder (as less testing as possible):
497
498\def\scrn_menu_insert
499  {\iflocation
500     \expandafter\scrn_menu_insert_checked
501   \else
502     \expandafter\gobbleoneargument
503   \fi}
504
505\def\scrn_menu_insert_checked#location%
506  {\ifconditional\csname\??menustate#location\endcsname
507     \scrn_menu_insert_indeed{#location}%
508   \fi}
509
510\def\scrn_menu_insert_indeed#location%
511  {\begingroup
512   \xdef\currentinteractionmenulocation{#location}%
513   \scrn_menu_set_final
514   \ifcase\d_scrn_menu_final_width \orelse \ifcase\d_scrn_menu_final_height \else
515     \forgetall
516     \global\d_scrn_menu_next_distance\zeropoint
517     \let\scrn_menu_action\scrn_menu_package_indeed
518     \expand\everysetmenucommands
519     \csname\??menupacker\namedinteractionmenuparameter\currentinteractionmenulocation\c!alternative\endcsname
520   \fi
521   \endgroup}
522
523%D This calls: % can be \c!command for vertical/horizontal
524
525\let\scrn_menu_packager\relax
526
527\defcsname\??menupacker\v!vertical\endcsname % all menus
528  {\let\scrn_menu_packager\scrn_menu_packager_vertical
529   \setbox\b_scrn_menu\hbox{\scrn_menu_actions\currentinteractionmenulocation}%
530   \scrn_menu_apply_final
531   \box\b_scrn_menu}
532
533\defcsname\??menupacker\v!horizontal\endcsname % all menus
534  {\let\scrn_menu_packager\scrn_menu_packager_horizontal
535   \setbox\b_scrn_menu\vbox{\scrn_menu_actions\currentinteractionmenulocation}%
536   \scrn_menu_apply_final
537   \box\b_scrn_menu}
538
539% stop : skipped
540% start: processed
541% local: skipped but can be included
542% empty: processed but invisible
543
544\protected\def\scrn_menu_package_indeed#tag% one menu
545  {\begingroup
546   \cdef\currentinteractionmenu{#tag}%
547   \edef\currentinteractionmenustate{\interactionmenuparameter\c!state}%
548   \ifx\currentinteractionmenustate\v!start
549     \scrn_menu_packager
550   \orelse\ifx\currentinteractionmenustate\v!empty
551     \scrn_menu_packager
552   \fi
553   \endgroup}
554
555%D With the packager being one of:
556
557\let\currentinteractionmenudistance\!!zeropoint
558
559\def\scrn_menu_packager_vertical
560  {\scrn_menu_set_used
561   \hskip\d_scrn_menu_next_distance
562   \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width
563     {\ifx\currentinteractionmenustate\v!empty \else
564        \interactionmenuparameter\c!left
565        \scrn_menu_package_vertical{\directinteractionmenuparameter\c!menu}%
566        \interactionmenuparameter\c!right
567      \fi}%
568   \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
569   \ifx\currentinteractionmenudistance\v!overlay
570     \global\d_scrn_menu_next_distance\zeropoint
571     \wd\b_scrn_menu\zeropoint
572   \else
573     \global\d_scrn_menu_next_distance\currentinteractionmenudistance
574     \scrn_menu_apply_used
575   \fi
576   \box\b_scrn_menu}
577
578\def\scrn_menu_packager_horizontal
579  {\scrn_menu_set_used
580   \vskip\d_scrn_menu_next_distance
581   \scrn_menu_set_align
582   \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height
583     {\ifx\currentinteractionmenustate\v!none \else
584        \scrn_menu_top_align
585        \interactionmenuparameter\c!before
586        \scrn_menu_package_horizontal{\directinteractionmenuparameter\c!menu}%
587        \interactionmenuparameter\c!after
588        \scrn_menu_bottom_align
589      \fi}%
590   \edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
591   \ifx\currentinteractionmenudistance\v!overlay
592     \global\d_scrn_menu_next_distance\zeropoint
593     \offinterlineskip
594     \dp\b_scrn_menu\zeropoint
595     \ht\b_scrn_menu\zeropoint
596   \else
597     \global\d_scrn_menu_next_distance\currentinteractionmenudistance
598     \scrn_menu_apply_used
599   \fi
600   \box\b_scrn_menu}
601
602%D For a right menu, a sequence of calls to \type {right_menu_button} is generated.
603%D
604%D \starttyping
605%D right_menu_button (n, p, s=0/1/2, x, y, w, h, d) ;
606%D \stoptyping
607%D
608%D Here, n is the number of the button, s a status variable, while the rest is
609%D positional info. The status variable is 0, 1 or~2: not found, found and found but
610%D current page.
611
612\newinteger    \c_scrn_menu_position
613\newconstant   \c_scrn_menu_page_mode % 0=notfound  1=found  2=currentpage
614\newconditional\c_scrn_menu_positioning
615\newtoks       \t_scrn_menu_meta_data
616
617\def\scrn_menu_button_meta_template
618  {\currentinteractionmenulocation _menu_button(%
619     \the\c_scrn_menu_position,%
620     \the\c_scrn_menu_page_mode,%
621     \MPpos{\currentinteractionmenulocation:\the\c_scrn_menu_position}%
622   );}
623
624\permanent\def\MPmenubuttons#1{\expand\t_scrn_menu_meta_data}
625
626\appendtoks
627    \global\t_scrn_menu_meta_data\emptytoks
628\to \everyshipout
629
630\def\scrn_menu_whole_position % cannot happen in previous due to align
631  {\setbox\b_scrn_menu\hbox \bgroup
632     \hpos{menu:\currentinteractionmenulocation:\the\realpageno}{\box\b_scrn_menu}%
633   \egroup}
634
635% removed: \restorestandardblank (vspacing) ... should happen elsewhere
636
637\let\scrn_menu_between_action_indeed\relax
638
639\def\scrn_menu_package_vertical#content%
640  {\begingroup
641   \global\c_scrn_menu_position\zerocount
642   \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!inbetween}%
643   \ifcstok{\interactionmenuparameter\c!position}\v!yes
644     \c_scrn_menu_positioning\conditionaltrue
645   \else
646     \c_scrn_menu_positioning\conditionalfalse
647   \fi
648   \scrn_menu_set_align
649   \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height \bgroup
650     \hsize\d_scrn_menu_used_width
651     \scrn_menu_left_align
652     \interactionmenuparameter\c!before\relax
653     \ignorespaces#content\unskip
654     \interactionmenuparameter\c!after
655     \scrn_menu_right_align
656   \egroup
657   \ifconditional\c_scrn_menu_positioning
658     \scrn_menu_whole_position
659   \fi
660   \box\b_scrn_menu
661   \endgroup}
662
663\def\scrn_menu_package_horizontal#content%
664  {\begingroup
665   \global\c_scrn_menu_position\zerocount
666   \def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!middle}%
667   \ifcstok{\interactionmenuparameter\c!position}\v!yes
668     \c_scrn_menu_positioning\conditionaltrue
669   \else
670     \c_scrn_menu_positioning\conditionalfalse
671   \fi
672   \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width \bgroup
673     \interactionmenuparameter\c!left\relax
674     \ignorespaces#content\unskip
675     \interactionmenuparameter\c!right
676   \egroup
677   \ifconditional\c_scrn_menu_positioning
678     \scrn_menu_whole_position
679   \fi
680   \box\b_scrn_menu
681   \endgroup}
682
683\def\scrn_menu_action_start
684  {\dontleavehmode
685   \begingroup}
686
687\def\scrn_menu_action_stop
688  {\ifconditional\c_scrn_button_skipped \else
689     \scrn_menu_between_action_indeed
690   \fi
691   \endgroup
692   \ignorespaces}
693
694\aliased\let\startraw\relax \aliased\let\stopraw\relax \ifdefined\raw\else \aliased\let\raw\relax \fi
695\aliased\let\startbut\relax \aliased\let\stopbut\relax \ifdefined\but\else \aliased\let\but\relax \fi
696\aliased\let\startgot\relax \aliased\let\stopgot\relax \ifdefined\got\else \aliased\let\got\relax \fi
697\aliased\let\startnop\relax \aliased\let\stopnop\relax \ifdefined\nop\else \aliased\let\nop\relax \fi
698\aliased\let\starttxt\relax \aliased\let\stoptxt\relax \ifdefined\txt\else \aliased\let\txt\relax \fi
699\aliased\let\startrul\relax \aliased\let\stoprul\relax \ifdefined\rul\else \aliased\let\rul\relax \fi
700\aliased\let\startcom\relax \aliased\let\stopcom\relax \ifdefined\com\else \aliased\let\com\relax \fi
701
702\protected\def\scrn_menu_raw_start[#action]#text\stopraw
703  {\scrn_menu_action_start
704   \gotobox{\ignorespaces#text\unskip}[#action]%
705   \scrn_menu_action_stop}
706
707\protected\def\scrn_menu_but_start[#action]#text\stopbut
708  {\scrn_menu_action_start
709   \ifconditional\c_scrn_menu_positioning
710     \expandafter\scrn_button_make_position
711   \else
712     \expandafter\scrn_button_make
713   \fi
714     \interactionmenuparameter
715     \inheritedinteractionmenuframed
716     \letinteractionmenuparameter
717     \setinteractionmenuparameter
718     {#text}%
719     {#action}%
720   \scrn_menu_action_stop}
721
722\def\scrn_button_make_position#currentparameter#inheritedframed#letparameter#setparameter#text#action%
723  {\global\advanceby\c_scrn_menu_position\plusone
724   \doifelsereferencefound{#action}% 0=not found, 1=same page, >1=elsewhere
725     {\c_scrn_menu_page_mode\ifnum\currentreferencerealpage=\realpageno\plusone\else\plustwo\fi}%
726     {\c_scrn_menu_page_mode\plustwo}%
727   \xtoksapp\t_scrn_menu_meta_data{\scrn_menu_button_meta_template}%
728   \hpos
729     {\currentinteractionmenulocation:\the\c_scrn_menu_position}%
730     {\scrn_button_make
731        #currentparameter%
732        #inheritedframed%
733        #letparameter%
734        #setparameter%
735        {#text}%
736        {#action}}}
737
738\permanent\protected\def\scrn_menu_got_start[#action]#text\stopgot
739  {\scrn_menu_action_start
740   \letinteractionmenuparameter\c!frame\v!off
741   \resetinteractionmenuparameter\c!background
742   \scrn_button_make
743     \interactionmenuparameter
744     \inheritedinteractionmenuframed
745     \letinteractionmenuparameter
746     \setinteractionmenuparameter
747     {#text}%
748     {#action}%
749   \scrn_menu_action_stop}
750
751\permanent\protected\def\scrn_menu_nop_start#text\stopnop
752  {\scrn_menu_action_start
753   \letinteractionmenuparameter\c!frame\v!off
754   \resetinteractionmenuparameter\c!background
755   \letinteractionmenuparameter\c!empty\v!yes
756   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
757   \scrn_menu_action_stop}
758
759\permanent\protected\def\scrn_menu_txt_start#text\stoptxt
760  {\scrn_menu_action_start
761   \letinteractionmenuparameter\c!frame\v!off
762   \resetinteractionmenuparameter\c!background
763   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
764   \scrn_menu_action_stop}
765
766\permanent\protected\def\scrn_menu_rul_start#text\stoprul
767  {\scrn_menu_action_start
768   \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
769   \scrn_menu_action_stop}
770
771\permanent\protected\def\scrn_menu_com_start#text\stopcom
772  {\ignorespaces#text\removeunwantedspaces
773   \ignorespaces}
774
775\permanent\protected\def\scrn_menu_raw#content\\{\scrn_menu_raw_start#content\stopraw}
776\permanent\protected\def\scrn_menu_but#content\\{\scrn_menu_but_start#content\stopbut}
777\permanent\protected\def\scrn_menu_got#content\\{\scrn_menu_got_start#content\stopgot}
778\permanent\protected\def\scrn_menu_nop#content\\{\scrn_menu_nop_start#content\stopnop}
779\permanent\protected\def\scrn_menu_txt#content\\{\scrn_menu_txt_start#content\stoptxt}
780\permanent\protected\def\scrn_menu_rul#content\\{\scrn_menu_rul_start#content\stoprul}
781\permanent\protected\def\scrn_menu_com#content\\{\scrn_menu_com_start#content\stopcom}
782
783\newtoks\everysetmenucommands % public
784
785\appendtoks
786    \enforced\let\raw\scrn_menu_raw \enforced\let\startraw\scrn_menu_raw_start \enforced\let\stopraw\relax
787    \enforced\let\but\scrn_menu_but \enforced\let\startbut\scrn_menu_but_start \enforced\let\stopbut\relax
788    \enforced\let\got\scrn_menu_got \enforced\let\startgot\scrn_menu_got_start \enforced\let\stopgot\relax
789    \enforced\let\nop\scrn_menu_nop \enforced\let\startnop\scrn_menu_nop_start \enforced\let\stopnop\relax
790    \enforced\let\txt\scrn_menu_txt \enforced\let\starttxt\scrn_menu_txt_start \enforced\let\stoptxt\relax
791    \enforced\let\rul\scrn_menu_rul \enforced\let\startrul\scrn_menu_rul_start \enforced\let\stoprul\relax
792    \enforced\let\com\scrn_menu_com \enforced\let\startcom\scrn_menu_com_start \enforced\let\stopcom\relax
793\to \everysetmenucommands
794
795%D Sometimes handy:
796%D
797%D \starttyping
798%D \setupinteractionmenu
799%D   [left]
800%D   [state=local]
801%D
802%D \startinteractionmenu[right]
803%D     ...
804%D     \includemenu[left]
805%D     ...
806%D \stopinteractionmenu
807%D \stoptyping
808
809\permanent\protected\def\includemenu[#tag]%
810  {\begingroup
811   \cdef\currentinteractionmenu{#tag}%
812   \ifcstok{\interactionmenuparameter\c!state}\v!local
813     \letinteractionmenuparameter\c!state\v!start
814     \directinteractionmenuparameter\c!menu
815   \fi
816   \endgroup}
817
818%D Direct call (todo):
819
820\permanent\tolerant\protected\def\interactionmenu[#tag]#spacer[#S#settings]%
821  {\begingroup
822   \cdef\currentinteractionmenu{#tag}%
823   \setupcurrentinteractionmenu[#settings]%
824   \scrn_menu_insert{#tag}%
825   \endgroup}
826
827%D Plugin handler:
828
829\protected\def\scrn_menu_insert_content_indeed
830  {\iflocation % here as we can have a fast turn-off
831     \expandafter\firstofoneargument
832   \else
833     \expandafter\gobbleoneargument
834   \fi}
835
836\let\scrn_menu_insert_content_ignore\gobbleoneargument
837
838\appendtoks
839    \ifcstok{\interactionparameter\c!menu}\v!on
840        \let\scrn_menu_insert_content\scrn_menu_insert_content_indeed
841    \else
842        \let\scrn_menu_insert_content\scrn_menu_insert_content_ignore
843    \fi
844\to \everysetupinteraction
845
846%D Plugs into the page builder:
847
848\protected\def\scrn_menu_leftedge
849  {\hbox to \leftedgewidth \bgroup
850     \hsize\leftedgewidth
851     \c_scrn_menu_zerodimensions\conditionaltrue
852     \scrn_menu_insert\v!left
853   \egroup
854   \hskip-\leftedgewidth}
855
856\protected\def\scrn_menu_rightedge
857  {\hbox to \rightedgewidth \bgroup
858     \hsize\rightedgewidth
859     \c_scrn_menu_zerodimensions\conditionaltrue
860     \scrn_menu_insert\v!right
861   \egroup
862   \hskip-\rightedgewidth}
863
864\protected\def\scrn_menu_top
865  {\vbox to \topheight \bgroup
866     \vsize\topheight
867     \c_scrn_menu_zerodimensions\conditionaltrue
868     \scrn_menu_insert\v!top
869     \kern\zeropoint
870   \egroup
871   \vskip-\topheight}
872
873\protected\def\scrn_menu_bottom
874  {\vbox to \bottomheight \bgroup
875     \vsize\bottomheight
876     \c_scrn_menu_zerodimensions\conditionaltrue
877     \scrn_menu_insert\v!bottom
878     \kern\zeropoint
879   \egroup
880   \vskip-\bottomheight}
881
882\appendtoks \scrn_menu_insert_content\scrn_menu_leftedge  \to \leftedgetextcontent
883\appendtoks \scrn_menu_insert_content\scrn_menu_rightedge \to \rightedgetextcontent
884\appendtoks \scrn_menu_insert_content\scrn_menu_top       \to \toptextcontent
885\appendtoks \scrn_menu_insert_content\scrn_menu_bottom    \to \bottomtextcontent
886
887%D Initialization (root definitions, main builders):
888
889\defineinteractionmenu [\v!vertical]   [\c!alternative=\v!vertical]
890\defineinteractionmenu [\v!horizontal] [\c!alternative=\v!horizontal]
891
892%D Initialization (parent definitions, 4 area builders):
893
894\defineinteractionmenu [\v!right ] [\v!right ] [\v!vertical  ]
895\defineinteractionmenu [\v!left  ] [\v!left  ] [\v!vertical  ]
896\defineinteractionmenu [\v!top   ] [\v!top   ] [\v!horizontal]
897\defineinteractionmenu [\v!bottom] [\v!bottom] [\v!horizontal]
898
899\setupinteraction
900  [\c!menu=\v!off]
901
902\setupinteractionmenu
903  [\c!offset=.25em,
904   \c!position=\v!no,
905   \c!frame=\v!on,
906   \c!maxwidth=\hsize,
907   \c!maxheight=\vsize,
908   \c!background=,
909   \c!backgroundcolor=,
910   \c!foregroundstyle=\interactionmenuparameter\c!style,
911   \c!foregroundcolor=\interactionmenuparameter\c!color,
912   \c!style=\interactionparameter\c!style,
913   \c!color=\interactionparameter\c!color,
914   \c!contrastcolor=\interactionparameter\c!contrastcolor,
915   \c!state=\v!start,
916   \c!samepage=\v!yes,
917   \c!unknownreference=\v!empty,
918   \c!distance=\bodyfontsize,
919   \c!topoffset=\zeropoint,
920   \c!bottomoffset=\zeropoint,
921   \c!leftoffset=\zeropoint,
922   \c!rightoffset=\zeropoint]
923
924\setupinteractionmenu
925  [\v!vertical] % not really a menu
926  [\c!inbetween=\blank,
927   \c!before=,
928   \c!after=\vfil,
929  %\c!width=\v!fit,
930   \c!height=\v!broad]
931
932\setupinteractionmenu
933  [\v!horizontal] % not really a menu
934  [\c!middle=\hfil,
935  %\c!left=\hss,
936  %\c!right=\hss,
937   \c!width=\v!fit,
938   \c!height=\v!broad]
939
940\setupinteractionmenu
941  [\v!left]
942  [\c!itemalign=\v!flushright,
943   \c!maxwidth=\leftedgewidth,
944   \c!maxheight=\makeupheight]
945
946\setupinteractionmenu
947  [\v!right]
948  [\c!itemalign=\v!flushleft,
949   \c!maxwidth=\rightedgewidth,
950   \c!maxheight=\makeupheight]
951
952\setupinteractionmenu
953  [\v!top]
954  [\c!itemalign=\v!high,
955   \c!maxwidth=\makeupwidth,
956   \c!maxheight=\topheight]
957
958\setupinteractionmenu
959  [\v!bottom]
960  [\c!itemalign=\v!low,
961   \c!maxwidth=\makeupwidth,
962   \c!maxheight=\bottomheight]
963
964%D Lists:
965
966\definelistalternative [\v!left  ] [\c!renderingsetup=strc:lists:rendering:menu]
967\definelistalternative [\v!right ] [\c!renderingsetup=strc:lists:rendering:menu]
968\definelistalternative [\v!top   ] [\c!renderingsetup=strc:lists:rendering:menu]
969\definelistalternative [\v!bottom] [\c!renderingsetup=strc:lists:rendering:menu]
970
971\startsetups[strc:lists:rendering:menu]
972    \startbut[internal(\currentlistentrylocation)]
973        \limitatetext\currentlistentrytitle{\listparameter\c!maxwidth}\unknown
974    \stopbut
975\stopsetups
976
977%D Sometimes handy:
978
979\def\scrn_button_direct_status
980  {\ifcstok{\buttonparameter\c!state}\v!start
981     \expandafter\scrn_button_direct_indeed
982   \else
983     \expandafter\scrn_button_direct_ignore
984   \fi}
985
986\permanent\protected\def\menubutton % tag settings text action
987  {\iflocation
988     \expandafter\scrn_menu_menu_button_indeed
989   \else
990     \expandafter\scrn_menu_menu_button_ignore
991   \fi}
992
993\tolerant\def\scrn_menu_menu_button_indeed[#menutag]#spacer[#S#settings]#:#text[#action]%
994  {\ifcstok{\interactionmenuparameter\c!state}\v!start
995     \ifparameter#settings\or
996       \expandafter\scrn_menu_menu_button_a
997     \orelse\ifhastok={#menutag}%
998       \expandafter\scrn_menu_menu_button_b
999     \else
1000       \expandafter\scrn_menu_menu_button_c
1001     \fi{#menutag}{#settings}{#text}{#action}%
1002   \fi}
1003
1004\tolerant\def\scrn_menu_menu_button_ignore[#menutag]#spacer[#S#settings]#:#text[#action]%
1005  {}
1006
1007\def\scrn_menu_menu_button_a#tag#settings#text#action%
1008  {\dontleavehmode \begingroup
1009     \cdef\currentinteractionmenu{#tag}%
1010     \setupcurrentinteractionmenu[#settings]%
1011     \scrn_button_make
1012       \interactionmenuparameter
1013       \inheritedinteractionmenuframed
1014       \letinteractionmenuparameter
1015       \setinteractionmenuparameter
1016       {#text}%
1017       {#action}%
1018   \endgroup}
1019
1020\def\scrn_menu_menu_button_b#settings#dummy#text#action%
1021  {\dontleavehmode \begingroup
1022     \lettonothing\currentbutton
1023     \setupcurrentbutton[#settings]%
1024     \scrn_button_make
1025       \buttonparameter
1026       \inheritedbuttonframed
1027       \letbuttonparameter
1028       \setbuttonparameter
1029       {#text}%
1030       {#action}%
1031   \endgroup}
1032
1033\def\scrn_menu_menu_button_c#tag#dummy#text#action%
1034  {\dontleavehmode \begingroup
1035     \cdef\currentinteractionmenu{#tag}%
1036     \scrn_button_make
1037       \interactionmenuparameter
1038       \inheritedinteractionmenuframed
1039       \letinteractionmenuparameter
1040       \setinteractionmenuparameter
1041       {#text}%
1042       {#action}%
1043   \endgroup}
1044
1045%D Untested:
1046
1047\permanent\tolerant\protected\def\registermenubuttons[#menu]#spacer[#register]%
1048  {\begingroup
1049   \ifparameter#register\or
1050     \clf_registerbuttons{#menu}{#register}{\currentlanguage}%
1051   \else
1052     \clf_registerbuttons{}{#menu}{\currentlanguage}%
1053   \fi
1054   \removeunwantedspaces
1055   \endgroup}
1056
1057\permanent\protected\def\doregistermenubutton#1#2#3% used at lua end
1058  {\ifcstok{\interactionmenuparameter\c!state}\v!start
1059     \scrn_menu_menu_button_c{#1}{}{#2}{#3}%
1060   \fi
1061   \space}
1062
1063\protect \endinput
1064