%D \module %D [ file=scrn-fld, %D version=1997.05.18, %D title=\CONTEXT\ Screen Macros, %D subtitle=Fields, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA / Hans Hagen \& Ton Otten}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. % \appendtocommalist versus \addtocommalist % % * as default trigger in radiofields ? % % beware: weblink plugin truncates on length, while save as doesn't; % more precise: (1) first time right string is sent, (2) % internal string truncated, (3) second time truncated % string is sent. \writestatus{loading}{ConTeXt Screen Macros / Fields} % messages \definemessageconstant{fields} \unprotect %D First we hook fields into the (viewer based) layering mechanism %D (implemented as properties). \ifx\currentlayerproperty\undefined\else \let\currentlayerproperty\empty\fi \appendtoks \doif\@@iafieldlayer\v!auto {\def\@@iafieldlayer{\currentlayerproperty}}% \to \everysetupinteraction \setupinteraction [\c!fieldlayer=\v!auto] % auto by default %D Internal command, linked to \type{\definesymbol}. \def\dogetfieldsymbol#1% {\getobject{SYM}{#1}} \def\dopresetfieldsymbol#1% {\checkobjectreferences \doifobjectfoundelse{SYM}{#1} {} {\settightobject{SYM}{#1}\hbox{\symbol[#1]}% \flushatshipout {\setbox0\hbox{\hskip-\maxdimen\getobject{SYM}{#1}}% \smashbox0\box0}}} \def\presetfieldsymbols[#1]% slow {\def\dopresetfieldsymbols##1% {\processcommalist[##1]\dopresetfieldsymbol}% \@EA\processcommalist\@EA[#1]\dopresetfieldsymbols} \def\definedefaultsymbols {\definesymbol[defaultyes][$\times$]% \definesymbol[defaultno][$\cdot$]} \def\resetfieldsymbol[#1]% for experimental usage only {\resetobject{SYM}{#1}} %D The interface to the specials. DEFAULT NOG ANDERS \def\preparefieldvariables % evt \def's at the outer level (test) or \edef's here for fast testing {\let\@@DriverFieldNumber \@@fdn \let\@@DriverFieldStyle \@@fdstyle \let\@@DriverFieldColor \@@fdcolor \let\@@DriverFieldBackgroundColor\@@fdfieldbackgroundcolor \let\@@DriverFieldFrameColor \@@fdfieldframecolor \let\@@DriverFieldLayer \@@fdfieldlayer \let\@@DriverFieldOption \@@fdoption \let\@@DriverFieldAlign \@@fdalign \let\@@DriverFieldClickIn \@@fdclickin \let\@@DriverFieldClickOut \@@fdclickout \let\@@DriverFieldRegionIn \@@fdregionin \let\@@DriverFieldRegionOut \@@fdregionout \let\@@DriverFieldAfterKey \@@fdafterkey \let\@@DriverFieldFormat \@@fdformat \let\@@DriverFieldValidate \@@fdvalidate \let\@@DriverFieldCalculate \@@fdcalculate \let\@@DriverFieldFocusIn \@@fdfocusin \let\@@DriverFieldFocusOut \@@fdfocusout} % todo : remove arguments, consider DriverField a namespace \def\presetlinefield {\preparefieldvariables \dopresetlinefield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldNumber} {\@@DriverFieldStyle,\@@DriverFieldColor,\@@DriverFieldBackgroundColor,\@@DriverFieldFrameColor} {\@@DriverFieldOption} {\@@DriverFieldAlign} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presettextfield {\preparefieldvariables \dopresettextfield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldNumber} {\@@DriverFieldStyle,\@@DriverFieldColor,\@@DriverFieldBackgroundColor,\@@DriverFieldFrameColor} {\@@DriverFieldOption} {\@@DriverFieldAlign} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetchoicefield {\preparefieldvariables \dopresetchoicefield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldStyle,\@@DriverFieldColor,\@@DriverFieldBackgroundColor,\@@DriverFieldFrameColor} {\@@DriverFieldOption} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetpopupfield {\preparefieldvariables \dopresetpopupfield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldStyle,\@@DriverFieldColor,\@@DriverFieldBackgroundColor,\@@DriverFieldFrameColor} {\@@DriverFieldOption} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetcombofield {\preparefieldvariables \dopresetcombofield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldStyle,\@@DriverFieldColor,\@@DriverFieldBackgroundColor,\@@DriverFieldFrameColor} {\@@DriverFieldOption} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetcheckfield {\preparefieldvariables \presetfieldsymbols[\@@DriverFieldValues]% \dopresetcheckfield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldOption} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetpushfield {\preparefieldvariables %\edef\@@DriverFieldValues{{\@@DriverFieldValues}}% makes sure {a,b,c} is passed \presetfieldsymbols[\@@DriverFieldValues]% \dopresetpushfield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldOption} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetradiofield {\preparefieldvariables \presetfieldsymbols[\@@DriverFieldValues]% \dopresetradiofield {\@@DriverFieldName} {\@@DriverFieldWidth} {\@@DriverFieldHeight} {\@@DriverFieldDefault} {\@@DriverFieldOption} {\@@DriverFieldRoot} {\@@DriverFieldValues} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\presetradiorecord {\preparefieldvariables \dopresetradiorecord {\@@DriverFieldName} {\@@DriverFieldDefault} {\@@DriverFieldOption} {\@@DriverFieldKids} {\@@DriverFieldClickIn,\@@DriverFieldClickOut,\@@DriverFieldRegionIn,\@@DriverFieldRegionOut,% \@@DriverFieldAfterKey,\@@DriverFieldFormat,\@@DriverFieldValidate,\@@DriverFieldCalculate,% \@@DriverFieldFocusIn,\@@DriverFieldFocusOut}} \def\setfieldmodes#1#2#3% {\xdef\@@DriverFieldMode{#1}% % 0 1 2 3 \xdef\@@DriverFieldFree{#2}% % 0 1 \xdef\@@DriverFieldAuto{#3}} % 0 1 \newevery\everysetfield\relax \def\doiffieldelse#1{\doifdefinedelse{fielddata#1}} \def\setfield#1#2#3#4#5#6#7#8#9% {\bgroup \doglobal\increment\numberoffields \iftracefields \doglobal\addtocommalist{#1}\collectedfields \fi \the\everysetfield \setxvalue{fielddata#1}% kortere tag #7 needs expansion etc {\noexpand\dosetfield{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% \egroup} \def\dosetfield#1#2#3#4#5#6#7#8#9% {\xdef\@@DriverFieldName {#1}% \xdef\@@DriverFieldType {#2}% \xdef\@@DriverFieldRoot {#3}% \xdef\@@DriverFieldParent {#4}% \xdef\@@DriverFieldKids {#5}% \xdef\@@DriverFieldGroup {#6}% \setfieldmodes #7% \bgroup \def\par{\string\n\string\n}% \xdef\@@DriverFieldValues {#8}% \xdef\@@DriverFieldDefault{#9}% \egroup} \def\changefield#1% {\setfield{#1}\@@DriverFieldType\@@DriverFieldRoot\@@DriverFieldParent\@@DriverFieldKids\@@DriverFieldGroup {\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}\@@DriverFieldValues\@@DriverFieldDefault} \def\getfield#1% name {\doifundefinedelse{fielddata#1} {\dosetfield{#1}\empty\empty\empty\empty\empty{\empty00}\empty\empty} {\getvalue{fielddata#1}}} \newif\iftracefields \tracefieldsfalse \let\tracefields\tracefieldstrue \def\doshowfields[#1]% todo: tabulate van maken en runtime {\bgroup \switchtobodyfont[8pt,tt]% \doifsomething{#1}{\def\collectedfields{#1}}% \ifx\collectedfields\empty \par specify [fieldlist] or say \type{\tracefieldstrue} first\par \else \def\normalizedfieldmode##1##2##3% {\ifcase0##2 \else\sl\fi \ifcase0##1 loner\or parent\or clone\or copy\fi}% \def\dosetfield##1##2##3##4##5##6##7##8##9% {##1&##2&##3&##4&##5&##6&\normalizedfieldmode##7&##8&##9\cr}% \halign {&##\strut\hss\quad\cr \noalign{\hrule}% NAME &TYPE &ROOT & PARENT&KIDS &GROUP & MODE &VALUES&DEFAULT\cr \noalign{\hrule}% \@EA\globalprocesscommalist\@EA[\collectedfields]\getfield \noalign{\hrule}}% \fi \egroup} \def\showfields {\dosingleempty\doshowfields} \def\dologfields[#1]% {\bgroup \immediate\openout\scratchwrite=fields.log \doifsomething{#1}{\def\collectedfields{#1}}% \ifx\colledtedfields\empty \immediate\write\scratchwrite{use \tracefieldstrue}% \else \def\normalizedfieldmode##1##2##3% {\edef\@@DriverFieldMode {\ifcase##1 loner \or parent \or clone \or copy \fi \ifcase##2 \else(done)\fi}}% \def\dosetfield##1##2##3##4##5##6##7##8##9% {\normalizedfieldmode##7% \immediate\write\scratchwrite {N=##1 / T=##2 / R=##3 / P=##4 / K=##5 / G=##6 / M=\@@DriverFieldMode\space/ V=##8 / D=##9}}% \processcommacommand[\collectedfields]\getfield \fi \immediate\closeout\scratchwrite \egroup} \def\logfields {\dosingleempty\doLogFields} %D \starttyping %D \definefield [name] [type] [group] [values] [default] %D %D \definefield [WWWW] [text] [textsetup] [default text] %D \definefield [XXXX] [push] [pushsetup] [yes,no] [yes] %D \definefield [XXXX] [check] [checksetup] [yes,no] [yes] %D \definefield [YYYY] [combo] [combosetup] [a,b,c,d] [b] %D \definefield [ZZZZ] [radio] [radiosetup] [W,X,Y,Z] [Y] %D %D \definesubfield [W] [subsetup] [p,q] %D \definesubfield [X,Y] [subsetup] [p,r] %D \definesubfield [Z] [subsetup] [y,z] %D %D evt \definemainfield ... wanneer geplaatst voor subs gegeven %D %D \clonefield [XXXX] [XX,YY] [mysetup] [on,off] %D \clonefield [Z] [AA,BB] [somesetup] [true,false] %D \clonefield [Z] [CC,DD] [anothersetup] %D %D \copyfield [XXXX] [PP,QQ,RR] %D %D \field[XXXX] %D \fitfield[XXXX] %D \stoptyping \newif\ifdefinemainfield \definemainfieldfalse %D We need to keep track of cloned (related) fields and so by %D maintaining lists of field clones. %D %D The first alternative used a two pass data list and was %D implemented as follows: %D %D \starttyping %D \def\getmainfieldkids#1% %D {\let\@@DriverFieldKids\empty %D \ifdefinemainfield %D \definetwopasslist{fld:#1}% defined by system %D \doloop %D {\gettwopassdata{fld:#1}% %D \iftwopassdatafound %D %\addtocommalist\twopassdata\@@DriverFieldKids %D \appendtocommalist\twopassdata\@@DriverFieldKids %D \else %D \exitloop %D \fi}% %D \fi} %D \stoptyping %D %D However, the next alternative is much faster when we have %D a field with thousands of clones, something not that %D imaginary. %D %D \starttyping %D \def\getmainfieldkids#1% %D {\let\@@DriverFieldKids\empty %D \ifdefinemainfield %D \definetwopasslist{fld:#1}% runtime defined by system %D \getnamedtwopassdatalist{fld:#1}\@@DriverFieldKids %D \fi} %D \stoptyping %D %D The data is written by file using: %D %D \starttyping %D \newcounter\nofmainfieldkids %D %D \def\setmainfieldkid#1#2% %D {\doglobal\increment\nofmainfieldkids %D \savetwopassdata{fld:#1}{\nofmainfieldkids}{#2}} %D \stoptyping %D %D The trade of of this mechanism is that for each cloned or %D copied field, the uitlity file is to be read in order to %D fetch the data. %D %D The next, much faster alternative uses a dedicated % %D reference mechanism. \def\setmainfieldkid#1#2% {\immediatewriteutilitycommand{\fieldreference{#1}{#2}}} \def\checkfieldreferences {\startnointerference \protectlabels \doutilities{fieldreferences}\jobname\empty\relax\relax \global\let\checkfieldreferences\relax \stopnointerference} \def\setfieldreferences {\def\fieldreference##1##2% {\ifundefined{\r!widget##1}% \setxvalue{\r!widget##1}{##2}% \else \edef\!!stringa{\getvalue{\r!widget##1}}% \setxvalue{\r!widget##1}{\!!stringa,##2}% \fi}} \def\resetfieldreferences {\let\fieldreference\gobbletwoarguments} \def\getmainfieldkids#1% {\checkfieldreferences \ifdefinemainfield \doifundefinedelse{\r!widget#1}% {\let\@@DriverFieldKids\empty} {\@EA\let\@EA\@@DriverFieldKids\csname\r!widget#1\endcsname}% \else \let\@@DriverFieldKids\empty \fi} \resetfieldreferences %D Of course it costs a few more tokens to implement, but it's %D worth the memory: running for instance the 2000 page %D english examns publishing on demand document went down from %D 1350 seconds to less than 950 on a 650 Mhz pentium. \def\definefield {\definemainfieldfalse\doquintupleempty\dodefinefield} \def\definemainfield {\definemainfieldtrue \doquintupleempty\dodefinefield} \let\collectedfields\empty \newcounter\numberoffields \newcounter\totalnumberoffields \def\savenumberoffields {\ifcase\numberoffields\relax\else \savecurrentvalue\totalnumberoffields\numberoffields \fi} \appendtoks \savenumberoffields \to \everybye % \everylastshipout % \def\presetfieldreferences % {\ifnum\totalnumberoffields>0 % \definereference[AtOpenInitializeForm][\v!ResetForm]% % \fi} % % \definereference[AtOpenInitializeForm][\v!geen] % % \appendtoks \presetfieldreferences \to \everycheckreferences \def\dodefinefield[#1][#2][#3][#4][#5]% {\ifsecondargument \edef\currentfieldname{#1}% just in case we're inside a loop \doifundefinedelse{define#2field} {\writestatus\m!fields{unknown field type #2}} {\doifundefined{fielddata\currentfieldname} {\getmainfieldkids\currentfieldname \ifdefinemainfield \ifx\@@DriverFieldKids\empty \let\@@DriverFieldMode\fieldlonermode \else \let\@@DriverFieldMode\fieldparentmode \fi \def\@@DriverFieldAuto{1}% \else \let\@@DriverFieldMode\fieldlonermode \def\@@DriverFieldAuto{0}% \fi \def\@@DriverFieldFree{0}% \getvalue{define#2field}{\currentfieldname}{#2}{#3}{#4}{#5}}}% \else \writestatus\m!fields{pass fieldname and fieldtype}% \fi} \def\definelinefield#1#2#3#4#5% {\setfield{#1}{#2}{}{}{\@@DriverFieldKids}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{}{#4}} \let\definetextfield=\definelinefield \def\definechoicefield#1#2#3#4#5% {\doifelsenothing{#4} {\def\@@DriverFieldValues{yes,no}} {\def\@@DriverFieldValues{#4}}% \doifelsenothing{#5} {\dogetcommacommandelement2\from\@@DriverFieldValues \to\@@DriverFieldDefault \dogetcommacommandelement1\from\@@DriverFieldDefault\to\@@DriverFieldDefault} {\def\@@DriverFieldDefault{#5}}% \setfield{#1}{#2}{}{}{\@@DriverFieldKids}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{\@@DriverFieldValues}{\@@DriverFieldDefault}} \let\definepopupfield=\definechoicefield \let\definecombofield=\definechoicefield %\def\definecheckfield#1#2#3#4#5% % {\doifelsenothing{#4} % {\definedefaultsymbols % \def\@@DriverFieldValues{defaultyes}} % {\def\@@DriverFieldValues{#4}}% % \doifelsenothing{#5} % {\dogetcommacommandelement2\from\@@DriverFieldValues\to\@@DriverFieldDefault % \dogetcommacommandelement1\from\@@DriverFieldDefault\to\@@DriverFieldDefault} % {\def\@@DriverFieldDefault{#5}}% % \setfield{#1}{#2}{}{}{\@@DriverFieldKids}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{\@@DriverFieldValues}{\@@DriverFieldDefault}} %D Since these fields have an on/off state only, we pass 1/0 %D to the driver as default values. \def\definecheckfield#1#2#3#4#5% {\doifelsenothing{#4} {\definedefaultsymbols \def\@@DriverFieldValues{defaultyes}} {\def\@@DriverFieldValues{#4}}% \doifelsenothing{#5} {\def\@@DriverFieldDefault{2}} {\dogetcommacommandelement1\from\@@DriverFieldValues\to\@@DriverFieldDefault \doifinstringelse{#5}{\@@DriverFieldDefault} {\def\@@DriverFieldDefault{1}} {\def\@@DriverFieldDefault{0}}}% \setfield {#1}{#2}{}{}{\@@DriverFieldKids}{#3}% {\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}% {\@@DriverFieldValues}{\@@DriverFieldDefault}} \let\definepushfield=\definecheckfield \def\defineradiofield#1#2#3#4#5% {\iffourthargument \doifelsenothing{#5} {\dogetcommacommandelement1\from#4\to\SavedFieldDefault \dogetcommacommandelement1\from\SavedFieldDefault\to\SavedFieldDefault} {\def\SavedFieldDefault{#5}}% % when opt works % \@EA\beforesplitstring\SavedFieldDefault\at=>\to\SavedFieldDefault \ifx\@@DriverFieldKids\empty \setfield{#1}{#2}{}{}{#4}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{}{\SavedFieldDefault}% \else \setfield{#1}{#2}{}{}{#4,\@@DriverFieldKids}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{}{\SavedFieldDefault}% \fi % \def\docommand##1% {\doifelse{##1}\SavedFieldDefault {\def\@@DriverFieldDefault{##1}}% {\let\@@DriverFieldDefault\empty}% \setfield{##1}{#2}{#1}{}{}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{}{\@@DriverFieldDefault}}% % when opt works % \def\docommand##1% % {\@EA\beforesplitstring##1\at=>\to\FieldValue % \doifelse\FieldValue\SavedFieldDefault % {\let\@@DriverFieldDefault\FieldValue}% % {\let\@@DriverFieldDefault\empty}% % \setfield\FieldValue{#2}{#1}{}{}{#3}{\@@DriverFieldMode\@@DriverFieldFree\@@DriverFieldAuto}{}{\@@DriverFieldDefault}}% \processcommalist[#4]\docommand \else \writestatus\m!fields{pass values too}% \fi} \def\definesubfield {\dotripleempty\dodefinesubfield} \def\dodefinesubfield[#1][#2][#3]% for the moment only radio ones {\ifsecondargument \def\docommand##1% {\getfield{##1}% \ifx\@@DriverFieldType\empty \writestatus\m!fields{unknown field ##1}% to do \else \doifsomething{#2} {\edef\@@DriverFieldGroup{#2}}% \doifelsenothing{#3} {\definedefaultsymbols \def\@@DriverFieldValues{defaultyes}} {\def\@@DriverFieldValues{#3}}% \changefield{##1}% \fi}% \processcommalist[#1]\docommand \else \writestatus\m!fields{pass fieldname, setupgroup, values and default}% \fi} \def\doclonefield[#1][#2][#3][#4]% parent children setupgroup values {\ifsecondargument \getfield{#1}% \iftrialtypesetting\else \ifx\@@DriverFieldType\empty \writestatus\m!fields{unknown field #1}% \else \let\@@DriverFieldMode\fieldparentmode %\def\docommand##1{\addtocommalist{##1}\@@DriverFieldKids}% \def\docommand##1{\appendtocommalist{##1}\@@DriverFieldKids}% \processcommalist[#2]\docommand \changefield{#1}% \let\@@DriverFieldAutoParent\@@DriverFieldAuto \def\@@DriverFieldParent{#1}% \let\@@DriverFieldKids\empty \let\@@DriverFieldRoot\empty \let\@@DriverFieldMode\fieldchildmode \def\@@DriverFieldFree{0}% \def\@@DriverFieldAuto{0}% \doifsomething{#3}{\edef\@@DriverFieldGroup{#3}}% \doifsomething{#4}{\edef\@@DriverFieldValues{#4}}% \def\docommand##1% {\ifcase\@@DriverFieldAutoParent\else \setmainfieldkid{\@@DriverFieldParent}{##1}% \fi \changefield{##1}}% \processcommalist[#2]\docommand \fi \fi \else \writestatus\m!fields{pass parent field and clones}% \fi} \def\clonefield {\doquadrupleempty\doclonefield} \def\docopyfield[#1][#2]% parent children {\ifsecondargument \getfield{#1}% \iftrialtypesetting\else \ifx\@@DriverFieldType\empty \writestatus\m!fields{unknown field #1}% \else \let\@@DriverFieldMode\fieldparentmode %\def\docommand##1{\addtocommalist{##1}\@@DriverFieldKids}% \def\docommand##1{\appendtocommalist{##1}\@@DriverFieldKids}% \processcommalist[#2]\docommand \changefield{#1}% \let\@@DriverFieldAutoParent\@@DriverFieldAuto \def\@@DriverFieldParent{#1}% \let\@@DriverFieldKids\empty \let\@@DriverFieldRoot\empty \let\@@DriverFieldMode\fieldcopymode \def\@@DriverFieldFree{0}% \def\@@DriverFieldAuto{0}% \def\docommand##1% {\ifcase\@@DriverFieldAutoParent\else \setmainfieldkid{\@@DriverFieldParent}{##1}% \fi \changefield{##1}}% \processcommalist[#2]\docommand \fi \fi \else \writestatus\m!fields{pass parent field and copies}% \fi} \def\copyfield{\dodoubleempty\docopyfield} \unexpanded\def\field {\dotripleempty\dofield[\dohandlefield]} \unexpanded\def\fitfield{\dotripleempty\dofield[\dohandlefitfield]} \def\dofield[#1][#2][#3]% {\iffirstargument \bgroup \getfield{#2}% \ifsecondargument \def\@@DriverFieldLabel{#3}% \else \let\@@DriverFieldLabel\@@DriverFieldName \fi \ifx\@@DriverFieldType\empty \writestatus\m!fields{unknown field #2}% \else\ifcase\@@DriverFieldFree\relax \doifdefinedelse{\strippedcsname\setupfield\@@DriverFieldGroup} {\let\dosetupfield=#1\getvalue{\strippedcsname\setupfield\@@DriverFieldGroup}} {#1[\@@DriverFieldName][\v!label,\v!frame,\v!horizontal][][][]}% \iftrialtypesetting\else \def\@@DriverFieldFree{1}% \changefield{#2}% \fi \else\ifcase\@@DriverFieldAuto\relax % \writestatus\m!fields{field #2 already typeset}% \else % \writestatus\m!fields{field #2 automatically copied}% \nextsystemfield \copyfield[\@@DriverFieldName][\currentsystemfield]% \dotripleempty\dofield[#1][\currentsystemfield][#3]% get the if's right \fi\fi\fi \egroup \fi} \def\typesetfield {\useJSscripts[fld]% \ifx\@@DriverFieldRoot\empty \else \let\@@SavedFieldName\@@DriverFieldName \getfield\@@DriverFieldRoot \ifcase\@@DriverFieldFree\relax \dosetfieldstatus\@@DriverFieldMode\@@DriverFieldParent\@@DriverFieldKids\@@DriverFieldRoot \dopresetrecord \iftrialtypesetting\else \def\@@DriverFieldFree{1}% \changefield\@@DriverFieldName \fi \fi \getfield\@@SavedFieldName \fi \ifx\@@DriverFieldKids\empty \donefalse \else \donetrue \fi \ifdone \let\@@DriverFieldParent\@@DriverFieldName %\addtocommalist\@@DriverFieldParent\@@DriverFieldKids \appendtocommalist\@@DriverFieldParent\@@DriverFieldKids \dosetfieldstatus\@@DriverFieldMode\@@DriverFieldParent\@@DriverFieldKids\@@DriverFieldRoot \dopresetfield \let\@@DriverFieldMode\fieldchildmode \fi \dosetfieldstatus\@@DriverFieldMode\@@DriverFieldParent\@@DriverFieldKids\@@DriverFieldRoot \dopresetfield} \def\dopresetfield {\iftrialtypesetting\else\iflocation\getvalue{preset\@@DriverFieldType field}\fi\fi} \def\dopresetrecord {\iftrialtypesetting\else\iflocation\getvalue{preset\@@DriverFieldType record}\fi\fi} \def\dodefinethefieldset[#1][#2]% {\dodefinefieldset{#1}{#2}} \def\definefieldset% {\dodoubleargument\dodefinethefieldset} \def\normaldodosetupfield[#1][#2][#3][#4][#5]% {\doifdefinedelse{\strippedcsname\setupfield#1} {\pushmacro\dosetupfield \def\dosetupfield[##1][##2][##3][##4][##5]% {\setvalue{\strippedcsname\setupfield#1}{\dosetupfield[#1][##2,#2][##3,#3][##4,#4][##5,#5]}}% \getvalue{\strippedcsname\setupfield#1}% \popmacro\dosetupfield} {\setvalue{\strippedcsname\setupfield#1}{\dosetupfield[#1][#2][#3][#4][#5]}}} \let\dodosetupfield\normaldodosetupfield \def\donosetupfield[#1][#2][#3][#4][#5]% {\setvalue{\strippedcsname\setupfield#1}{\dosetupfield[#1][#2][#3][#4][#5]}} \def\dosetupfield[#1][#2][#3][#4][#5]% {\iffifthargument \def\docommand##1{\dodosetupfield[##1][#2][#3][#4][#5]}% \processcommalist[#1]\docommand \else\ifthirdargument \def\docommand##1{\dodosetupfield[##1][#2][][][#3]}% \processcommalist[#1]\docommand \else\ifsecondargument \doifelse{#2}\v!reset {\def\docommand##1{\donosetupfield[#1][][][][]}} {\def\docommand##1{\dodosetupfield[##1][][][][#2]}}% \processcommalist[#1]\docommand \else\iffirstargument \def\docommand##1{\dodosetupfield[##1][][][][]}% \processcommalist[#1]\docommand \else \writestatus\m!fields{provide either 1, 2, 3 or 5 arguments}% \fi\fi\fi\fi} \def\setupfield {\doquintupleempty\dosetupfield} \def\dosetupfields[#1][#2][#3][#4]% {\ifsecondargument \def\dodosetupfield[##1][##2][##3][##4][##5]% {\doifdefinedelse{\strippedcsname\setupfield##1} {\def\dosetupfield[####1][####2][####3][####4][####5]% {\setvalue{\strippedcsname\setupfield##1}{\dosetupfield[##1][#1,####2,##2][#2,####3,##3][#3,####4,##4][#4,####5,##5]}}% \getvalue{\strippedcsname\setupfield##1}} {\setvalue{\strippedcsname\setupfield##1}{\dosetupfield[##1][#1,##2][#2,##3][#3,##4][#4,##5]}}}% \else\iffirstargument \doifelse{#1}\v!reset {\resetfields} {\setupfields[][][][#1]}% checken \else \writestatus\m!fields{provide either 1 or 4 arguments}% \fi\fi} \def\setupfields {\doquadrupleempty\dosetupfields} \def\resetfields {\let\dodosetupfield\normaldodosetupfield} % \setupfields[\v!reset] % opties: veld, label, kader, vertikaal/horizontaal \newif\ifShowFieldLabel \newif\ifShowFieldFrame \newif\ifVerticalField \newif\ifHorizontalField % way to slow/complicated, we need some simple alternative % as well \def\dohandlefield[#1][#2][#3][#4][#5]% {\presetlocalframed[\??fd]% \processallactionsinset [#2] [ \v!reset=>\ShowFieldLabelfalse\ShowFieldFramefalse \HorizontalFieldfalse\VerticalFieldfalse, \v!label=>\ShowFieldLabeltrue, \v!frame=>\ShowFieldFrametrue, \v!horizontal=>\HorizontalFieldtrue, \v!vertical=>\VerticalFieldtrue]% \ifVerticalField \getparameters[\??fd] [\c!distance=\!!zeropoint,\c!inbetween=\vskip\@@localoffset, \c!align=\v!right,\c!width=20em]% \else\ifHorizontalField \getparameters[\??fd] [\c!distance=\@@localoffset,\c!inbetween=,\c!align=\c!left, \c!height=10ex]% \else \getparameters[\??fd] [\c!distance=\!!zeropoint,\c!inbetween=,\c!align=\c!left]% \fi\fi \getparameters[\??fd] [\c!n=,\c!before=,\c!after=\vss,\c!style=,\c!color=,#3]% \reshapeframeboxfalse % else ugly spacing \ifShowFieldFrame \localframed[\??fd][\c!strut=\v!no,\c!align=]\bgroup \else \vbox\bgroup \fi \dontcomplain \ifShowFieldLabel \setbox0\hbox {\reshapeframeboxtrue % else wrong dimensions \framed [\c!style=,\c!color=,\c!align=\c!right,#4] {\@@DriverFieldLabel}}% \fi \setbox2\hbox {\reshapeframeboxtrue % else wrong dimensions \ifVerticalField \setupframed[\c!height=6ex,\c!width=\hsize]% \else\ifHorizontalField \setupframed[\c!height=\vsize,\c!width=20em]% \else \setupframed[\c!height=2cm,\c!width=2cm]% \fi\fi \framed [\c!align=\v!right,\c!strut=\v!no,#5] {\getparameters [\??fd] [\c!color=,\c!style=,\c!align=\v!right,\c!option=, \c!clickin=,\c!clickout=,\c!regionin=,\c!regionout=, \c!afterkey=,\c!format=,\c!validate=,\c!calculate=, \c!focusin=,\c!focusout=, \c!fieldoffset=\!!zeropoint,\c!fieldbackgroundcolor=, \c!fieldframecolor=,\c!fieldlayer=\@@iafieldlayer,#5]% \scratchdimen\framedwidth \edef\@@DriverFieldWidth {\the\scratchdimen}% \scratchdimen\framedheight\edef\@@DriverFieldHeight{\the\scratchdimen}% \vfill \hbox{\lower\@@fdfieldoffset\hbox{\typesetfield}} \vss}}% \ifShowFieldLabel \ifVerticalField \vbox {\copy0 \@@fdinbetween \copy2}% \else \hbox {\vbox \ifdim\ht2>\ht0 to \ht2 \fi {\@@fdbefore \copy0 \@@fdafter}% \hskip\@@fddistance \vbox \ifdim\ht0>\ht2 to \ht0 \fi {\@@fdbefore \box2 \@@fdafter}}% \fi \else \box2 \fi \egroup} \chardef\fitfieldmode\plusone % 3 = best \def\dohandlefitfield[#1][#2][#3][#4][#5]% alleen check {\presetlocalframed[\??fd]% \localframed [\??fd] [\c!n=1024, % beware: weblink plug in truncates \c!strut=\v!no,\c!color=,\c!style=,\c!option=, \c!clickin=,\c!clickout=,\c!regionin=,\c!regionout=, \c!focusin=,\c!focusout=, \c!afterkey=,\c!format=,\c!validate=,\c!calculate=, \c!fieldoffset=\!!zeropoint,\c!fieldbackgroundcolor=, \c!fieldframecolor=,\c!fieldlayer=\@@iafieldlayer,#5,\c!align=] {\dogetcommacommandelement1\from\@@DriverFieldValues\to\@@DriverFieldValue \ifx\@@DriverFieldValue\empty \let\@@DriverFieldValue\@@DriverFieldDefault \fi \dopresetfieldsymbol\@@DriverFieldValue \setbox\scratchbox\hbox{\dogetfieldsymbol\@@DriverFieldValue}% \scratchdimen\wd\scratchbox \edef\@@DriverFieldWidth {\the\scratchdimen}% \scratchdimen\ht\scratchbox \edef\@@DriverFieldHeight{\the\scratchdimen}% \ifcase\fitfieldmode \typesetfield \or % 1 = ignore depth (original, assumed no depth, actually a bug) \vbox to \ht\scratchbox{\vfill\hbox to \wd\scratchbox{\typesetfield\hfill}\vss}% \or % 2 = add depth to height, but no depth in result \advance\scratchdimen\dp\scratchbox \edef\@@DriverFieldHeight{\the\scratchdimen}% \vbox to \ht\scratchbox{\vfill\hbox to \wd\scratchbox{\typesetfield\hfill}\vss}% \or % 3 = add depth to height, and apply depth to result \advance\scratchdimen\dp\scratchbox \edef\@@DriverFieldHeight{\the\scratchdimen}% \hbox to \wd\scratchbox{\lower\dp\scratchbox\hbox{\typesetfield}\hfill}% \fi}} %D Common stuff \newcounter\nofsystemfields \def\nextsystemfield {\doglobal\increment\nofsystemfields \def\currentsystemfield{sys::\nofsystemfields}} %D An example: \def\fillinfield {\dosingleempty\dofillinfield} \def\dofillinfield[#1]#2% {\dontleavehmode \hbox {\forgetall \setupfields[\v!reset]% \nextsystemfield \useJSscripts[ans]% \doifelsenothing{#1} {\def\therightanswer{#2}} {\def\therightanswer{#1}}% \setbox0\hbox{#2}% \setbox2\hbox{\therightanswer}% \dimen0=\ifdim\wd0>\wd2 \wd0 \else \wd2 \fi \advance\dimen0 .2em \definefield [\currentsystemfield][line][systemfield]% \setupfield [systemfield] [\c!n=1024, % beware: weblink plugin truncates \c!location=\v!low,\c!strut=\v!yes,\c!fieldoffset=0pt, \c!height=1.2\openlineheight,\c!width=\dimen0,\c!offset=\v!overlay, \c!style=,\c!align=\v!middle,\c!frame=\v!off, \c!color=red,\c!fieldbackgroundcolor=\s!white,\c!fieldframecolor=blue, \c!validate=JS(Check_Answer{\currentsystemfield,\therightanswer})]% \switchtobodyfont [\c!small]% \hbox to \wd0 {\copy0\hskip-\wd0\hss\field[\currentsystemfield]\hss}}} %D and another one: \def\tooltip {\dosingleempty\dotooltip} \def\dotooltip[#1]#2#3% {\bgroup \setupfields[\v!reset]% \useJSscripts[fld]% \setbox0\hbox {\dontcomplain \nextsystemfield \setbox0\hbox{#2}% \definesymbol [\currentsystemfield:txt] [{\inframed[\c!frame=\v!off,\c!background=\v!screen]{#3}}]% \setbox2\hbox{\symbol[\currentsystemfield:txt]}% \definefield [\currentsystemfield:txt][check] [dummy][\currentsystemfield:txt][\currentsystemfield:txt]% \setupfield [dummy] [\c!frame=\v!off, \c!regionout=JS(Hide_Field{\currentsystemfield:txt}), \c!option=\v!hidden]% \hbox to \zeropoint {\dimen0\wd2\advance\dimen0 -\wd0 \doifelse{#1}\v!left {\hskip-\dimen0} {\doif{#1}\v!middle {\hskip-.5\dimen0}}% \lower\openlineheight\hbox to \zeropoint {\fitfield[\currentsystemfield:txt]}}% \dimen0=\ifdim\wd0=\zeropoint 3em\else\wd0\fi \definesymbol [\currentsystemfield:but] [{\framed[\c!height=2ex,\c!width=\dimen0,\c!frame=\v!off]{}}]% \definefield [\currentsystemfield:but][push] [dummy][\currentsystemfield:but][\currentsystemfield:but]% \setupfield [dummy] [\c!frame=\v!off, \c!option=, \c!regionin=JS(Vide_Field{\currentsystemfield:txt}), \c!regionout=JS(Hide_Field{\currentsystemfield:txt}), \c!fieldlayer=\@@iafieldlayer]% \lower2ex\hbox to \zeropoint {\fitfield[\currentsystemfield:but]}% #2}% \ht0\strutht\dp0\strutdp\box0 \egroup} %D And one more: \def\definefieldstack {\dotripleargument\dodefinefieldstack} \def\dodefinefieldstack[#1][#2][#3]% name, symbols, settings {\doifundefined{fieldstack:#1} {\setgvalue{fieldstack:#1}{\dodofieldstack[#1][#2][#3]}}} \def\dodofieldstack[#1][#2][#3]% start=n, 0 == leeg {\bgroup \getparameters[\??fd][\c!start=1,#3]% \setupfields[\v!reset]% \definesymbol[\v!empty][]% \useJSscripts[fld][FieldStack]% \newcounter\stackedfieldnumber \def\dododofieldstack##1% {\increment\stackedfieldnumber \ifnum\stackedfieldnumber=\@@fdstart\relax \definefield[#1:\stackedfieldnumber][check][#1][##1,\v!empty][##1]% \else \definefield[#1:\stackedfieldnumber][check][#1][##1,\v!empty][\v!empty]% \fi}% \processcommalist[#2]\dododofieldstack \setupfield[#1][\v!reset]% added \setupfield[#1][\c!option=\v!readonly,#3]% #3 swapped \newcounter\stackedfieldnumber \def\dododofieldstack##1% {\doglobal\increment\stackedfieldnumber \fitfield[#1:\stackedfieldnumber]\egroup\bgroup}% \startoverlay \bgroup \globalprocesscommalist[#2]\dododofieldstack \egroup \stopoverlay \egroup} \def\dofieldstack[#1][#2][#3]% {\ifsecondargument \dodefinefieldstack[#1][#2][#3]\fieldstack[#1]% \else \getvalue{fieldstack:#1}\setgvalue{fieldstack:#1}{[#1]}% \fi} \def\fieldstack {\dotripleempty\dofieldstack} %D When submitting a form, we need to tell the driver module %D that we want \FDF\ or \HTML. \def\setupforms {\dodoubleargument\getparameters[\??fr]} \def\checksubmitform#1% {\setsubmitoutputformat\@@frmethod} \setexecutecommandcheck {submitform} \checksubmitform \setupforms [\c!method=HTML] %D Goodie: \def\definepushbutton % name optional setup {\dodoubleempty\dodefinepushbutton} \def\dodefinepushbutton[#1][#2]% name setup {\dododefinepushbutton{#1}{n}{push}% \dododefinepushbutton{#1}{r}{\symbol[psym:#1:n]}% \dododefinepushbutton{#1}{d}{\symbol[psym:#1:r]}% \setvalue{pushbutton:#1}{\dohandlepushbutton{#1}{#2}}} \def\dododefinepushbutton#1#2#3% {\doifsymboldefinedelse{psym:#1:#2}% \donothing{\definesymbol[psym:#1:#2][{#3}]}} \def\definepushsymbol {\dotripleargument\dodefinepushsymbol} \def\dodefinepushsymbol[#1][#2]% [#3] {\definesymbol[psym:#1:#2]} \def\dopushbutton[#1][#2]% {\executeifdefined{pushbutton:#1}\gobbleoneargument{#2}} \def\pushbutton {\dodoubleargument\dopushbutton} \def\dohandlepushbutton#1#2#3% identifier setup script {\bgroup \nextsystemfield \setupfield [pushbutton] [\c!frame=\v!overlay, \c!offset=\v!overlay, \c!clickout=#3,#2]% \definefield [\currentsystemfield] [push] [pushbutton] [psym:#1:n,psym:#1:r,psym:#1:d]% \fitfield [\currentsystemfield]% \egroup} % \def\do@@ampsh % {\dodoubleargument\dodo@@ampsh} % % \def\dodo@@ampsh[#1][#2]#3\\% % {\txt\pushbutton[#1][#2]\\}% % %\appendtoks \let\psh\do@@ampsh \to \everysetmenucommands \def\@@ampsh{\txt\pushbutton} \appendtoks \let\psh\@@ampsh \to \everysetmenucommands % \definepushbutton [reset] % % \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=green}] % \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=white}] % % \startinteractionmenu[bottom] % \psh [reset] [JS(reset_something)] \\ % \stopinteractionmenu %D Another goodie: % \definecolor[rollover:n][red] % \definecolor[rollover:r][green] % \definecolor[rollover:d][blue] \definepalet [rollover] [n=red, r=green, d=blue] \newcounter\nofrollovers \newcounter\nofrollbuttons \def\dorollbutton[#1][#2]#3[#4]% {\dontleavehmode \bgroup \doglobal\increment\nofrollovers \doglobal\increment\nofrollbuttons \unexpanded\def\dosetlocationbox[##1]##2[##3]% {\getparameters[##1][##3]% \definecolor[rollover][rollover:##2]% \doifelse{##2}{n}{\doifelsevalue{##1\c!alternative}\v!hidden\phantom\hbox}\hbox {\localframed[##1] [\c!framecolor=rollover,\c!backgroundcolor=rollover,\c!color=rollover]% {\dolocationattributes{##1}\c!style\c!color{#3}}}}% \iffirstargument \ifsecondargument \def\setlocationbox##1{\dosetlocationbox[\??am#1]{##1}[#2]}% \else \doifassignmentelse{#1} {\def\setlocationbox##1{\dosetlocationbox[\??bt]{##1}[#1]}} {\def\setlocationbox##1{\dosetlocationbox[\??am#1]{##1}[]}}% \fi \else \def\setlocationbox##1{\dosetlocationbox[\??bt]{##1}[]}% \fi % todo: share symbols, tricky since different dimensions \definesymbol[rsym:\nofrollovers:n][\setlocationbox n]% \definesymbol[rsym:\nofrollovers:r][\setlocationbox r]% \definesymbol[rsym:\nofrollovers:d][\setlocationbox d]% \setupfield [rollbutton] [\c!frame=\v!off, \c!offset=\v!overlay, \c!clickout={#4}]% \definefield [roll:\nofrollbuttons][push][rollbutton] [rsym:\nofrollovers:n,% rsym:\nofrollovers:r,% rsym:\nofrollovers:d]% \fitfield[roll:\nofrollbuttons]% \egroup} \unexpanded\def\rollbutton {\dodoubleempty\dorollbutton} \def\menu@rob[#1]#2\\% {\txt\rollbutton[\currentmenu]{\ignorespaces#2\unskip}[#1]\\}% \appendtoks \let\rob\menu@rob \to \everysetmenucommands % calls: % {..} [JS..] % [left] {..} [JS..] % [a=b] {..} [JS..] % [left] [a=b] {..} [JS..] % % \setupbuttons[offset=0pt,frame=off] % alternative=hidden % % \rollbutton {Manuals} [JS(Goto_File{show-man.pdf})] % \rollbutton {Articles} [JS(Goto_File{show-art.pdf})] % \rollbutton {Papers} [JS(Goto_File{show-pap.pdf})] % \rollbutton {Presentations} [JS(Goto_File{show-pre.pdf})] % \rollbutton {Resources} [JS(Goto_File{show-res.pdf})] % % \rob [JS(...)] bla bla \\ \unexpanded\def\overlayrollbutton {\dodoubleargument\dooverlayrollbutton} \def\dooverlayrollbutton[#1][#2]% {\bgroup \nextsystemfield \setupfield [overlayrollbutton] [\c!frame=\v!off,\c!offset=\v!overlay,\c!regionin={#1},\c!regionout={#2}]% \definesymbol [\currentsystemfield] [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]% \definefield [\currentsystemfield][push][overlayrollbutton][\currentsystemfield][\currentsystemfield]% \fitfield[\currentsystemfield]% \egroup} % \defineoverlay % [ShowMenu] % [{\overlayrollbutton[VideLayer{navigation}][HideLayer{navigation}]}] \protect \endinput