summaryrefslogtreecommitdiff
path: root/tex/context/base/java-ini.tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/java-ini.tex')
-rw-r--r--tex/context/base/java-ini.tex636
1 files changed, 636 insertions, 0 deletions
diff --git a/tex/context/base/java-ini.tex b/tex/context/base/java-ini.tex
new file mode 100644
index 000000000..95c7ae08b
--- /dev/null
+++ b/tex/context/base/java-ini.tex
@@ -0,0 +1,636 @@
+% JavaScript support is under development. In the near future
+% a slightly different model will be used. The JScode stuff
+% will probably become just auto function inclusion and the
+% JS_* things will disappear. First I have to find a way to
+% deal with global variables so the 'uses' thing will remain.
+
+% Also, obeylines will be supported.
+
+%D \module
+%D [ file=java-ini,
+%D version=1998.01.30,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Initialization,
+%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. Non||commercial use is
+%C granted.
+
+\writestatus{loading}{Context JavaScript Macros / Initialization}
+
+\unprotect
+
+%D \JAVA\ support is not implemented as a generic support
+%D module. The main reason for this is that passing system
+%D variables to a \JAVASCRIPT\ is closely related to other core
+%D macros. First some messages:
+
+\startmessages dutch library: javascript
+ title: javascript
+ 1: script set -- wordt geladen
+ 2: onbekende preamble --
+\stopmessages
+
+\startmessages english library: javascript
+ title: javascript
+ 1: loading script set --
+ 2: unknown preamble --
+\stopmessages
+
+\startmessages german library: javascript
+ title: javascript
+ 1: Lade Scriptdatei --
+ 2: unbekannte Preamble --
+\stopmessages
+
+%D \TEX\ is not the right tool to check the \JAVA\ code; the
+%D most we can do is reporting some passed variables:
+
+\newif\iftraceJScode \traceJScodefalse
+
+\let\traceJScode\traceJScodetrue
+
+%D A bit out of place, but not dangerous:
+
+\bgroup
+\catcode127=\@@letter
+\gdef\delcharacter{^^7f}
+\egroup
+
+%D The number of passed variables is minimalized by setting the
+%D next switch.
+
+\newif\ifminimalizeJScode \minimalizeJScodetrue
+
+%D \macros
+%D {JS*}
+%D
+%D Because \JAVASCRIPT's are activated by the user, for
+%D instance by activating on a button, their support is closely
+%D related to the referencing mechanism. Integration takes
+%D place by
+%D
+%D \starttypen
+%D \naar{calculate total}[Sum()]
+%D \stoptypen
+%D
+%D The \type{()} classify this as a script. If they are absent,
+%D the keyword is treated as a normal reference.
+%D
+%D One can pass arguments to such a script by saying:
+%D
+%D \starttypen
+%D \naar{calculate total}[Sum(1.5,2.3)]
+%D \stoptypen
+%D
+%D References are passed by using the \type{R{}} classifier.
+%D
+%D \starttypen
+%D \naar{calculate total}[Sum(1.5,2.3,R{overflow})]
+%D \stoptypen
+%D
+%D The last call calls the script \type{Sum} and passes the
+%D next set of variables:
+%D
+%D \starttypen
+%D JS_S_1="1.5";
+%D JS_S_2="2.3";
+%D JS_R_3="overflow";
+%D JS_P_3=3;
+%D \stoptypen
+%D
+%D The first two parameters are just strings, the third one
+%D however is treated as a reference and results in passing the
+%D reference (if needed this references is prefixed) and the
+%D (real) page number. The alternative:
+%D
+%D \starttypen
+%D \naar{calculate total}[JS(Sum{V{1.5},V{2.3},R{overflow}})]
+%D \stoptypen
+%D
+%D does a verbose passing:
+%D
+%D \starttypen
+%D JS_V_1=1.5;
+%D JS_V_2=2.3;
+%D JS_R_3="overflow";
+%D JS_P_3=3;
+%D \stoptypen
+% %D
+% %D Finally we have a counter that tells\JAVA\ how many
+% %D arguments were passed,
+% %D
+% %D \starttypen
+% %D JS_N
+% %D \stoptypen
+
+%D We will also support direct function calls. In that case
+%D no intermediate variables are used.
+
+%D \macros
+%D {startJScode}
+%D
+%D A piece of \JAVASCRIPT\ code is defined by saying:
+%D
+%D \starttypen
+%D \startJScode{SomeScript}
+%D var Item=this.getField("item");
+%D N=Item.getArray();
+%D Total=this.getField("total");
+%D Total.value=0;
+%D for (j=0; j<N.length; j++)
+%D { if (N[j].value!="")
+%D { Total.value += N[j].value } } ;
+%D if ((JS_N>0) && (JS_R_1!=""))
+%D { gotoNamedDest(JS_R_1) };
+%D \stopJScode
+%D \stoptypen
+%D
+%D Such a piece of code is closely related to the interpreter
+%D used. Watch the last two lines, here the script adapts
+%D itself to the presence of a reference.
+%D
+%D While
+%D
+%D \starttypen
+%D \startJScode{name}
+%D name = 4 ;
+%D \stopJScode
+%D \stoptypen
+%D
+%D assumes uses no preamble or presumes that the preamble is
+%D always loaded, the next definition also tells \CONTEXT\ to
+%D actually include the preamble needed.
+%D
+%D \starttypen
+%D \startJScode{uses} uses {later}
+%D uses = 6 ;
+%D \stopJScode
+%D \stoptypen
+
+\long\gdef\startJScode#1 #2
+ {\doifelse{#2}{uses}
+ {\def\next{\dostartJScodeA{#1}}}
+ {\def\next{\dostartJScodeB{#1} #2}}%
+ \next}
+
+\long\gdef\dostartJScodeA#1#2 #3\stopJScode%
+ {\long\setgvalue{\r!java#1}{\do{#2}{#3}}}
+
+\long\gdef\dostartJScodeB#1#2\stopJScode%
+ {\long\setgvalue{\r!java#1}{\do{}{#2}}}
+
+%D \macros
+%D {presetJScode}
+%D
+%D The code can be retrieved by saying
+%D
+%D \starttypen
+%D \presetJScode{SomeScript}{template}
+%D \stoptypen
+%D
+%D Such a template is a comma separated list, where
+%D individual entries can optionally be transformed by
+%D \type{R{}} and \type{V{}}.
+%D
+%D After this call, the code is available in \type{\JScode}.
+
+\def\setverbosecscharacter#1%
+ {\edef#1{\string#1}}
+
+\def\setverbosecscharacters% temporary hack
+ {\setverbosecscharacter |\setverbosecscharacter ~%
+ \setverbosecscharacter\:\setverbosecscharacter\;%
+ \setverbosecscharacter\+\setverbosecscharacter\-%
+ \setverbosecscharacter\[\setverbosecscharacter\]%
+ \setverbosecscharacter\.\setverbosecscharacter\\%
+ \setverbosecscharacter\)\setverbosecscharacter\(%
+ \setverbosecscharacter\0\setverbosecscharacter\1%
+ \setverbosecscharacter\2\setverbosecscharacter\3%
+ \setverbosecscharacter\4\setverbosecscharacter\5%
+ \setverbosecscharacter\6\setverbosecscharacter\7%
+ \setverbosecscharacter\8\setverbosecscharacter\9%
+ \setverbosecscharacter\/\setverbosecscharacter\s}
+
+\newif\ifdirectJScode
+
+\def\presetJScode#1#2% #1=operation #2=arguments
+ {\setverbosecscharacters
+ \def\par{\delcharacter}% was: { }
+ \scratchcounter=0
+ \global\let\JScode=\empty
+ \def\do##1##2%
+ {\doifelse{##2}{!}{\directJScodetrue}{\directJScodefalse}}%
+ \getvalue{\r!java#1}%
+ \edef\!!stringa{#2}%
+ \ifx\!!stringa\empty \else
+ \processcommacommand[\!!stringa]\dopresetJSvariables
+ \fi
+ \def\docommando##1%
+ {\doifundefinedelse{\r!java\r!java##1}
+ {\showmessage{\m!javascript}{2}{##1}}
+ {\doglobal\increment\currentJSpreamble
+ \doglobal\addtocommalist{##1}\allJSpreambles}}%
+ \def\do##1##2%
+ {\xdef\JScode{\ifdirectJScode#1(\JScode)\else\JScode##2\fi}%
+ %\xdef\JScode{JS\string_N=\the\scratchcounter;\JScode}%
+ \processcommalist[##1]\docommando}%
+ \getvalue{\r!java#1}}
+
+\def\dopresetJSvariables#1%
+ {\advance\scratchcounter by 1
+ \donefalse
+ \dodopresetJSvariables#1\end}%
+
+\def\dodopresetJSvariables%
+ {\doifnextcharelse{R}
+ {\dodopresetJSrefvariables}
+ {\doifnextcharelse{V}
+ {\dodopresetJSvervariables}
+ {\doifnextcharelse{S}
+ {\dodopresetJSstrvariables}
+ {\dodopresetJSrawvariables}}}}
+
+\def\dodopresetJSrefvariables R#1\end%
+ {\doifreferencefoundelse{#1}
+ {\donetrue\dododopresetJSvariables R{\referenceprefix#1}%
+ \donefalse\dododopresetJSvariables P{\currentrealreference}}
+ {\unknownreference{#1}}%
+ \ifminimalizeJScode \else
+ \donetrue\dododopresetJSvariables S{#1}%
+ \fi}
+
+\def\dodopresetJSvervariables V#1\end%
+ {\donefalse\dododopresetJSvariables V{#1}%
+ \ifminimalizeJScode \else
+ \donetrue\dododopresetJSvariables S{#1}%
+ \fi}
+
+\def\dodopresetJSstrvariables S#1\end%
+ {\donetrue\dododopresetJSvariables S{#1}}
+
+\def\dodopresetJSrawvariables #1\end%
+ {\donetrue\dododopresetJSvariables S{#1}}
+
+\def\JSprefix#1%
+ {JS\string_#1\string_\the\scratchcounter}
+
+\def\dododopresetJSvariables#1#2%
+ {\iftraceJScode
+ \writestatus{JavaScript}{\JSprefix#1=#2}
+ \xdef\JScode{\JScode console.println("\JSprefix#1=#2"); }%
+ \fi
+ \ifdirectJScode
+ \xdef\JScode{\ifx\JScode\empty\else\JScode,\fi\ifdone"#2"\else#2\fi}%
+ \else
+ \xdef\JScode{\JScode\JSprefix#1=\ifdone"#2"\else#2\fi; }%
+ \fi}
+
+%D \macros
+%D {startJSpreamble, flushJSpreamble}
+%D
+%D One can define insert \JAVASCRIPT\ code at the document level
+%D by using:
+%D
+%D \starttypen
+%D \startJSpreamble{oeps}
+%D oeps = 1 ;
+%D \stopJSpreamble
+%D \stoptypen
+%D
+%D which is the same as:
+%D
+%D \starttypen
+%D \startJSpreamble{now} used now
+%D now = 2 ;
+%D \stopJSpreamble
+%D \stoptypen
+%D
+%D while the next definition is only included when actually
+%D used.
+%D
+%D \starttypen
+%D \startJSpreamble{later} used later
+%D later = 3 ;
+%D \stopJSpreamble
+%D \stoptypen
+%D
+%D This command may be used more that once, but always before
+%D the first page is shipped out.
+
+\newif\ifoneJSpreamble \oneJSpreambletrue
+
+\let\allJSpreambles=\empty
+\newcounter\nofJSpreambles
+\newcounter\currentJSpreamble
+
+\long\gdef\startJSpreamble#1 #2
+ {\doifelse{#2}{used}
+ {\def\next{\dostartJSpreamble{#1} }}
+ {\def\next{\dostartJSpreamble{#1} now #2 }}%
+ \next}
+
+\long\def\dostartJSpreamble#1 #2 #3\stopJSpreamble%
+ {\bgroup
+ \processaction
+ [#2]
+ [ later=>\chardef\JSstatus=0,
+ now=>\chardef\JSstatus=1,
+ \s!default=>\chardef\JSstatus=2,
+ \s!unknown=>\chardef\JSstatus=2]%
+ \presetJSfunctions #3function ()\end%
+ \ifcase\JSstatus
+ \long\setgvalue{\r!java\r!java#1}{#3}%
+ \else
+ \long\setgvalue{\r!java\r!java#1}{#3}%
+ \doglobal\increment\currentJSpreamble
+ \doglobal\addtocommalist{#1}\allJSpreambles
+ \fi
+ \egroup}
+
+%D Because we want to check for valid calls, we preload the
+%D functions. This means that we can call them directly as
+%D well as indirectly when defined by \type {\startJScode} etc.
+
+\long\def\presetJSfunctions#1function #2(#3)%
+ {\doifelsenothing{#2}
+ {\long\def\presetJSfunctions##1\end{}}
+ {\stripspaces\from#2\to\ascii
+ \doifundefined{\r!java\ascii}{\setgvalue{\r!java\ascii}{\do{}{!}}}}%
+ \presetJSfunctions}
+
+\def\getJSpreamble#1%
+ {\getvalue{\r!java\r!java#1}}
+
+\def\presetJSpreamble%
+ {\ifx\allJSpreambles\empty\else
+ \bgroup
+ \setverbosecscharacters
+ \def\par{\delcharacter}% was: { }
+ \global\let\JSpreamble=\empty
+ \def\@@collectedJSpreamble{\r!java\r!java collected}%
+ \letvalue{\@@collectedJSpreamble}=\empty
+ \def\docommando##1%
+ {\xdef\JScode{\getvalue{\r!java\r!java##1}}%
+ \ifoneJSpreamble
+ \@EA\setxvalue\@EA\@@collectedJSpreamble\@EA
+ {\csname\@@collectedJSpreamble\endcsname\JScode}%
+ \else
+ \setxvalue{\r!java\r!java##1}%
+ {\JScode}%
+ \fi}%
+ \processcommacommand[\allJSpreambles]\docommando
+ \ifoneJSpreamble
+ \gdef\allJSpreambles{collected}%
+ \fi
+ \global\let\presetJSpreamble=\relax
+ \egroup
+ \fi}
+
+%\def\flushJSpreamble%
+% {\iflocation\ifx\allJSpreambles\empty\else
+% \bgroup
+% \presetJSpreamble
+% \expanded{\doflushJSpreamble{\allJSpreambles}}%
+% \global\let\flushJSpreamble=\relax
+% \global\let\allJSpreambles=\empty
+% \egroup
+% \fi\fi}
+%
+%\prependtoks \flushJSpreamble \to \everylastshipout
+
+\def\flushJSpreamble%
+ {\iflocation\ifx\allJSpreambles\empty\else
+ \ifcase\nofJSpreambles\else\ifnum\nofJSpreambles=\currentJSpreamble
+ \bgroup
+ \presetJSpreamble
+ \expanded{\doflushJSpreamble{\allJSpreambles}}%
+ \global\let\flushJSpreamble=\relax
+ \global\let\allJSpreambles=\empty
+ \egroup
+ \fi\fi
+ \fi\fi}
+
+\def\finalflushJSpreamble%
+ {\iflocation
+ \flushJSpreamble
+ \ifcase\currentJSpreamble\relax\else
+ \savecurrentvalue\nofJSpreambles\currentJSpreamble
+ \global\let\currentJSpreamble\nofJSpreambles
+ \fi
+ \fi}
+
+\prependtoks \flushJSpreamble \to \everyshipout
+\prependtoks \finalflushJSpreamble \to \everylastshipout
+
+%D \macros
+%D {doPSsanitizeJScode}
+%D
+%D Before the code can be passed to the (\POSTSCRIPT\ or \PDF)
+%D output file, some precautions must be made concerning the
+%D use of \type{(} and~\type{)}. Here we use a beautiful
+%D \type{\aftergroup} trick I discovered in the \TABLE\ format.
+
+\def\doPSsanitizeJScode#1\to#2%
+ {\begingroup
+ \scratchcounter=0 % \aftergroup counter
+ \aftergroup\xdef
+ \aftergroup#2%
+ \aftergroup{%
+ \expanded{\convertargument#1\noexpand\to\noexpand\JScode}%
+ \expandafter\handletokens\JScode\with\dodoPSsanitizeJScode
+ \aftergroup}%
+ \endgroup
+ \iftraceJScode
+ \writestatus{JS trace}{#2}%
+ \fi}
+
+%D I started with:
+%D
+%D \starttypen
+%D \def\dodoPSsanitizeJScode#1%
+%D {\aftergroup\string
+%D \if#1(%
+%D \expandafter\aftergroup\csname#1\endcsname
+%D \else\if#1)%
+%D \expandafter\aftergroup\csname#1\endcsname
+%D \else\if#1;%
+%D \aftergroup;\aftergroup\string\expandafter\aftergroup\
+%D \else
+%D \expandafter\aftergroup#1%
+%D \fi\fi\fi
+%D \advance\scratchcounter by 1
+%D \ifnum\scratchcounter=500
+%D \expandafter\dododoPSsanitizeJScode
+%D \fi}
+%D \stoptypen
+%D
+%D For pretty printing purposes, we need some way to signal
+%D \TEX\ macros. Therefore we introduce a special keyword
+%D \type{TEX}. When followed by a space, this keyword is
+%D ignored, that is, filtered from the stream. Now we have:
+
+\chardef\JSisTEX=0
+\chardef\JScomment=0
+
+\newif\ifaddJSlinebreaks
+
+\def\flushJSisTEX%
+ {\ifcase\JSisTEX
+ \or \aftergroup T%
+ \or \aftergroup T\aftergroup E%
+ \or \aftergroup T\aftergroup E\aftergroup X%
+ \fi
+ \chardef\JSisTEX=0 }
+
+\def\doJSlinebreak%
+ {\ifaddJSlinebreaks
+ \aftergroup\string\aftergroup\n%
+ \fi}
+
+\def\dodoPSsanitizeJScode#1% % input stack>500 & TEX check
+ {\if#1/%
+ \ifnum\JScomment=0
+ \chardef\JScomment=1
+ \else\ifnum\JScomment=1
+ \chardef\JScomment=2
+ \fi\fi
+ \else
+ \ifnum\JScomment=1
+ \aftergroup/%
+ \chardef\JScomment=0
+ \fi
+ \ifnum\JScomment=2
+ \if#1\delcharacter
+ \chardef\JScomment=0
+ \fi
+ \else
+ \if#1\delcharacter
+ \flushJSisTEX\doJSlinebreak
+ \else\if#1(%
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+ \else\if#1)%
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+ \else\if#1;%
+ \flushJSisTEX\aftergroup;\doJSlinebreak
+ \else\if#1T%
+ \ifnum\JSisTEX=0 \chardef\JSisTEX=1 \else\flushJSisTEX\aftergroup T\fi
+ \else\if#1E%
+ \ifnum\JSisTEX=1 \chardef\JSisTEX=2 \else\flushJSisTEX\aftergroup E\fi
+ \else\if#1X%
+ \ifnum\JSisTEX=2 \chardef\JSisTEX=3 \else\flushJSisTEX\aftergroup X\fi
+ \else\if#1\normalspace
+ \ifnum\JSisTEX=3 \chardef\JSisTEX=0 \else\flushJSisTEX\aftergroup#1\fi
+ \else
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup#1%
+ \fi\fi\fi\fi\fi\fi\fi\fi
+ \fi
+ \fi
+ \dododoPSsanitizeJScode}
+
+%D Close reading learns that one line comments (\type{// ...})
+%D are removed from the stream. This permits switching in
+%D pretty printing \JAVASCRIPT\ sources as well as saves
+%D some bytes.
+
+%D The magic 500 in the next hack prevents the input stack from
+%D overflowing when large scripts are sanitized.
+
+\beginTEX
+
+\def\dododoPSsanitizeJScode%
+ {\ifcase\JSisTEX\ifcase\JScomment
+ \advance\scratchcounter by 1
+ \fi\fi
+ \ifnum\scratchcounter=500
+ \expandafter\dodododoPSsanitizeJScode
+ \fi}
+
+\def\dodododoPSsanitizeJScode%
+ {\let\next={%
+ \aftergroup}%
+ \endgroup
+ \begingroup
+ \aftergroup\xdef
+ \aftergroup\sanitizedJScode
+ \aftergroup{%
+ \aftergroup\sanitizedJScode
+ \let\next=}}
+
+\endTEX
+
+\beginETEX \aftergroup
+
+\let\dododoPSsanitizeJScode\relax
+
+\endETEX
+
+%D The macro \type{\doPSsanitizeJScode} converts its argument
+%D into the macro \type{\sanitizedJScode}, thereby prefixing
+%D each \type{(} and \type{)} by a slash.
+
+%D Hooking this mechanism into the general \CONTEXT\ reference
+%D mechanism does not take much effort:
+
+\definespecialtest{JS}
+ {\doifdefinedelse{\r!java\currentreferenceoperation}}
+
+\definespeciallocation{JS}#1#2%
+ {\iflocation
+ \bgroup
+ \presetJScode
+ \currentreferenceoperation
+ \currentreferencearguments
+ \dostartgoto
+ \data
+ {#2}%
+ \start
+ \dostartgotoJS
+ {\number\buttonwidth}{\number\buttonheight}
+ {\JScode}%
+ \stop
+ \dostopgotoJS
+ \dostopgoto
+ \egroup
+ \else
+ {#2}%
+ \fi}
+
+%D \macros
+%D {useJSscripts}
+%D
+%D In due time, users will build their collections of scripts,
+%D which can be used (loaded) when applicable. Although not all
+%D public, we will provide some general purpose scripts,
+%D collected in files with names like \type{java-...}. One can
+%D load these scripts with \type{\useJSscripts}, like:
+%D
+%D \starttypen
+%D \useJSscripts[fld]
+%D \stoptypen
+%D
+%D The not so complicated implementation of this macro is:
+
+\def\douseJSscripts#1%
+ {\doifelse{#1}{\v!reset}
+ {\let\allJSpreambles=\empty}
+ {\doifundefined{\c!file\f!javascriptprefix#1}
+ {\bgroup
+ \setbox0=\hbox % forget spaces and worse
+ {\setgvalue{\c!file\f!javascriptprefix#1}{}%
+ \makeshortfilename[\f!javascriptprefix#1]%
+ \showmessage{\m!javascript}{1}{#1}%
+ \startreadingfile
+ \readsysfile{\shortfilename}{}{}%
+ \stopreadingfile}%
+ \egroup}}}
+
+\def\useJSscripts[#1]%
+ {\processcommalist[#1]\douseJSscripts}
+
+\protect
+
+\endinput