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