summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/tclldoc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/tclldoc
Initial commit
Diffstat (limited to 'macros/latex/contrib/tclldoc')
-rw-r--r--macros/latex/contrib/tclldoc/README.txt45
-rw-r--r--macros/latex/contrib/tclldoc/examples/README.txt40
-rw-r--r--macros/latex/contrib/tclldoc/examples/parsetcl.dtx1155
-rw-r--r--macros/latex/contrib/tclldoc/examples/parsetcl.ins54
-rw-r--r--macros/latex/contrib/tclldoc/examples/pdf.dtx796
-rw-r--r--macros/latex/contrib/tclldoc/examples/pdf.ins55
-rw-r--r--macros/latex/contrib/tclldoc/tclldoc.dtx4065
-rw-r--r--macros/latex/contrib/tclldoc/tclldoc.ins51
-rw-r--r--macros/latex/contrib/tclldoc/tclldoc.pdfbin0 -> 436262 bytes
-rw-r--r--macros/latex/contrib/tclldoc/tools/README.txt46
-rw-r--r--macros/latex/contrib/tclldoc/tools/eemenu.dtx4477
-rw-r--r--macros/latex/contrib/tclldoc/tools/eemenu.ins66
-rw-r--r--macros/latex/contrib/tclldoc/tools/sourcedtx.dtx234
-rw-r--r--macros/latex/contrib/tclldoc/tools/sourcedtx.ins31
14 files changed, 11115 insertions, 0 deletions
diff --git a/macros/latex/contrib/tclldoc/README.txt b/macros/latex/contrib/tclldoc/README.txt
new file mode 100644
index 0000000000..8ee02ad0c7
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/README.txt
@@ -0,0 +1,45 @@
+README for the tclldoc package:
+===============================
+
+The purpose of the tclldoc package and class is to
+simplify using the classical doc/docstrip style of
+literate programming with Dr. John Ousterhout's
+Tool Command Language (Tcl, pronounced "tickle",
+a.k.a. The Cool Language). The tclldoc package is
+a bit like the doc package is for LaTeX, whereas
+the tclldoc class more parallels the ltxdoc class.
+
+tclldoc.dtx contains an introduction to how one
+uses the .dtx file format for writing Tcl code.
+
+The tclldoc class uses the tclldoc package for most
+of its functionality. The tclldoc package depends
+on the xdoc2 and docidx2e packages for some of its
+functionality. The latter two packages can be found
+in the CTAN directory
+ macros/latex/contrib/xdoc
+
+The tools subdirectory of this directory contains
+two tools that you may find useful complements to
+the tclldoc package. Both are Tcl scripts that make
+it possible to source Tcl code stored in a .dtx file
+without using docstrip to generate any .tcl file in
+between. Naturally, they are both distributed as
+pairs of .dtx and .ins files, so they can also be
+used as examples of using the tclldoc package.
+
+The examples subdirectory of this directory contains
+two more examples of Tcl packages written in the
+doc/docstrip style of literate programming. One is
+a package for writing PDF files, the other a package
+for parsing Tcl scripts.
+
+The LaTeX Project Public License applies for the
+tclldoc package and class, as well as to all the
+examples provided in the tools and examples folders.
+
+More information about Tcl can be found on
+http://www.tcl.tk/
+
+Lars Hellström,
+20 July 2003
diff --git a/macros/latex/contrib/tclldoc/examples/README.txt b/macros/latex/contrib/tclldoc/examples/README.txt
new file mode 100644
index 0000000000..2d3d8abe5d
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/examples/README.txt
@@ -0,0 +1,40 @@
+README for the parsetcl and writepdf packages:
+==============================================
+
+The parsetcl package implements basic parsing
+of Tcl scripts, and is written completely in
+Tcl. To generate parsetcl.tcl, run LaTeX on
+parsetcl.ins. To typeset the documentation,
+run LaTeX on parsetcl.dtx. To see an example
+of what it does, you can try the following
+commands in a Tcl shell:
+
+ source parsetcl.tcl
+ auto_load parray
+ set tree [parsetcl::simple_parse_script [info body parray]]
+ parsetcl::format_tree $tree {} { }
+
+The tree variable will be set to a parser tree
+for the body of the parray procedure. The last
+command reformats this tree (mostly replacing
+whitespace between list elements) to make the
+structure more visible.
+
+
+The writepdf package is written completely in
+Tcl and provides basic commands for writing
+well-formed PDF files. To generate writepdf.tcl,
+run LaTeX on pdf.ins. To typeset the
+documentation, run LaTeX on pdf.dtx. To see an
+example of what it does, you can try the following
+commands in a Tcl shell:
+
+ source writepdf.tcl
+ source hellopdf.tcl
+
+This will generate a file hello.pdf that contains
+a single page with the two words "Hello world!".
+
+
+Lars Hellström,
+20 July 2003
diff --git a/macros/latex/contrib/tclldoc/examples/parsetcl.dtx b/macros/latex/contrib/tclldoc/examples/parsetcl.dtx
new file mode 100644
index 0000000000..22609d6fa4
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/examples/parsetcl.dtx
@@ -0,0 +1,1155 @@
+%
+% \iffalse
+%<*driver>
+\documentclass{tclldoc}
+
+\newcommand{\ParseTcl}{Parse\Tcllogo}
+\providecommand{\href}[2]{#2}
+
+\begin{document}
+\DocInput{parsetcl.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+%
+% \title{\ParseTcl\ --- a parser for \Tcllogo\ code}
+% \author{Lars Hellstr\"om}
+%
+% \maketitle
+%
+%
+% \begin{abstract}
+% \ParseTcl\ is a \Tcllogo\ package for parsing \Tcllogo\ code.
+% It is written completely in \Tcllogo, and make heavy use of some
+% new additions in \Tcllogo\,8.4.
+% \end{abstract}
+%
+% \begin{tcl}
+%<*pkg>
+namespace eval parsetcl {}
+package require Tcl 8.4
+package provide parsetcl 0.1
+% \end{tcl}
+% \setnamespace{parsetcl}
+%
+% \tableofcontents
+%
+% \section{Parser results}
+%
+% The values returned by the parser are conceptually rooted trees, but
+% technically the return values are lists. The general format of a
+% subtree is
+% \begin{quote}
+% \word{type} \word{interval} \word{text} \word{subtree}\regstar
+% \end{quote}
+% where there is one \word{subtree} for each component that remains if
+% the root of the subtree under consideration is deleted. The
+% \word{type} specifies what kind of construction the subtree
+% corresponds to. The \word{interval} is a list with the structure
+% \begin{quote}
+% \word{first} \word{last}
+% \end{quote}
+% where \word{first} and \word{last} are integers; the indices into
+% the input string of the first and last respectively character that
+% corresponds to this part of the parser tree. The \word{text} is,
+% depending on the \word{type}, either empty or the explicit string
+% that corresponds to this subtree.
+%
+% The \word{type}s are generally two-character strings, where the first
+% letter specifies a major category and the second letter an exact type
+% within that category, but this system is not enforced by any code.
+% \begin{description}
+% \item[Null types]
+% The \emph{null} types all begin with an |N|. These correspond to
+% information which isn't part of the script proper, but still is
+% useful to include in the parse result. It is generally possible
+% to add or remove subtrees of this type without changing the
+% meaning of the reconstruction of the script.
+% \begin{enumerate}
+% \item[\texttt{Nc}] \describestring[subtree type]{Nc}
+% This type is for comments, and it normally appears only in
+% places where one would expect a command subtree. The
+% \word{interval} includes the |#| beginning the comment, but not
+% the newline ending it. The \word{text} is the text in the
+% comment (initial |#| not included).
+% \item[\texttt{Ne}] \describestring[subtree type]{Ne}
+% This type is for syntax errors; rather than stopping at every
+% error, the parser routines will try to recover as best they can,
+% and an error item will be inserted in the parser tree. This
+% type of item generally appears as a \word{subtree} of whatever
+% was being parsed when the error was detected. The \word{text} is
+% a human-readable error message. The \word{interval} specifies
+% the erroneous characters; if the error is that some character(s)
+% is missing then the end of the interval is the index of the
+% character before that which is missing, and the start of the
+% interval is the character after that which is missing.
+% \item[\texttt{Np}] \describestring[subtree type]{Np}
+% This type is merely a placeholder; both the \word{interval} and
+% the \word{text} are empty strings. It is used when there was
+% nothing to return, but call syntax requires that a subtree is
+% returned. If some call returns an item of this type then it
+% usually means that its caller also has reached the end of
+% whatever that was parsing.
+% \end{enumerate}
+%
+% \item[Literate types]
+% The literate, or verbatim, types all begin with an |L|. Words (of
+% a command) where no variable or command substitution will happen
+% usually belong in this category. There are three types of
+% literates: \describestring[subtree type]{Lb}|Lb|s are delimited by
+% braces and \describestring[subtree type]{Lq}|Lq|s are delimited by
+% quotes, whereas \describestring[subtree type]{Lr}|Lr|s have no
+% particular delimiters. In each case, the \word{text} is the string
+% that this interval of the input gets parsed into.
+%
+% Backslash--newline substitution is silently performed, but other
+% types of substitution will result in that the item is considered
+% to consist of one or more parts, each of which will be
+% represented as a separate \word{subtree}. The delimiting quotes
+% of an |Lq| is never included in the \word{interval} of any
+% \word{subtree}. An |Lb| never has any \word{subtree}s due to
+% substitution, since it can only be subject to backslash--newline
+% substitution, but it may have |Ne| subtrees.
+%
+% \item[Merge types]
+% The merge types all begin with an |M|. They are similar to the
+% literate types, but are used for intervals of the input for which
+% the \emph{text} cannot be completely determined.
+% \describestring[subtree type]{Mq}|Mq|s are delimited by quotes,
+% whereas \describestring[subtree type]{Mr}|Mr|s have no particular
+% delimiters. The \word{text} is set to an empty string. There is
+% always at least one \word{subtree}.
+%
+% \item[Substitution types]
+% The substitution types all begin with an |S|. As the name
+% indicates, they are used for intervals of the input that will be
+% substituted by a \Tcllogo\ parser.
+% \begin{enumerate}
+% \item[\texttt{Sb}] \describestring[subtree type]{Sb}
+% This type is for backslash substitution. The \word{text} is
+% the character produced by this substitution. There is always
+% an |Lr| subtree for the text following the initial backslash.
+% \item[\texttt{Sv}] \describestring[subtree type]{Sv}
+% This type is for scalar variable substitution. The
+% \word{text} is empty, and there is one \word{subtree} for the
+% name of the variable being substituted. The type of this
+% subtree is either |Lr| or |Lb|, depending on whether the name
+% is surrounded by braces or not.
+% \item[\texttt{Sa}] \describestring[subtree type]{Sa}
+% This type is for array variable substitution. The
+% \word{text} is empty, and there are two \word{subtree}s: one
+% for the name of the array (always an |Lr|) and one for the
+% index into the array (either an |Lr| or an |Mr|).
+% \item[\texttt{Sc}] \describestring[subtree type]{Sc}
+% This type is for command substitution. The \word{text} is
+% empty, and there is one \word{subtree} for each command in
+% the script.
+% \end{enumerate}
+%
+% \item[The command type]
+% The \describestring[subtree type]{Cd}|Cd| type is for complete
+% commands. The \word{text} is empty, and each word in the command
+% has its own \word{subtree} (naturally, these are in the order of
+% the words in the command).
+%
+% \item[Root types]
+% The root types are used for the root in a parser tree, but they
+% may also appear as proper subtrees if the parser is invoked
+% recursively. This is for example what one does with the body
+% argument of the |while| command: technically it is a string just
+% like any other string, but it makes most sense to parse that
+% string as a script and replace the original literate item by the
+% entire tree generated by parsing this string.
+%
+% The root types all begin with an |R|. They are
+% \begin{enumerate}
+% \item[\texttt{Rs}] \describestring[subtree type]{Rs}
+% This type is for script parsing. The \word{text} is usually
+% empty, and each \word{subtree} is a command of the script.
+% \item[\texttt{Rx}] \describestring[subtree type]{Rx}
+% This type is for |expr| expression parsing.
+% \end{enumerate}
+%
+% \end{description}
+%
+% \subsection{Some examples}
+%
+% The script
+% \begin{quote}
+% |set a "b\nc"|
+% \end{quote}
+% will be parsed as the list
+%\begin{verbatim}
+% Rs {0 11} {} \
+% {Cd {0 11} {}
+% {Lr {0 2} set}
+% {Lr {4 4} a}
+% {Lq {6 11} b\nc
+% {Lr {7 7} b}
+% {Sb {8 9} \n {Lr {9 9} n}}
+% {Lr {10 10} c}
+% }
+% }
+%\end{verbatim}
+% NB: This is not the canonical string representation, but one that was
+% chosen for clarity of exposition. The |parsetcl::format_tree|
+% procedure can be used to reformat a parser tree with indentation as
+% shown above.
+%
+%
+% \section{Basic script parsing}
+%
+% Basic script parsing makes a purely syntactic parsing of a script. It
+% does not make any assumptions about the meaning of the commands used
+% in the script, and hence it will not try to parse as scripts any
+% argument of a commands (not even the byte-compiled commands).
+%
+% The parsing relies on a set of procedures which parses the next item
+% of a particular sort, and returns the corresponding parse subtree.
+% These procedures can call each other recursively in complicated ways,
+% following the actual structure of the script that is being parsed.
+% The general syntax for calling such a procedure is
+% \begin{quote}
+% \word{proc name} \word{string} \word{index-var-name}
+% \word{extra}\regstar
+% \end{quote}
+% where \word{string} is the string from which something should be
+% parsed and \word{index-var-name} is the name of a variable in the
+% local context of the caller which holds the index of the first
+% character that hasn't been parsed yet (or possibly the last character
+% that has been parsed, it may depend on what is most convenient for
+% that particular procedure). There are two reasons for using this
+% set-up. One is that the calling procedure usually needs to continue
+% parsing the string after the part that it made a recursive call to
+% have parsed, and for that purpose this variable provides a convenient
+% method of returning the value. The other reason is one of efficiency:
+% If the script as a whole is passed as an argument to all procedures
+% that are involved in the parsing process, as opposed to passing only
+% the part that hasn't been parsed yet, then the need to copy the data
+% decreases drastically.
+%
+%
+% \subsection{Commands and scripts}
+%
+% \begin{proc}{flush_whitespace}
+% The |flush_whitespace| procedure advances the index past a
+% whitespace sequence. The syntax is
+% \begin{quote}
+% |parsetcl::flush_whitespace| \word{script} \word{index-var-name}
+% \word{cmdsep}
+% \end{quote}
+% where \word{cmdsep} is |1| if command separators (newlines and
+% semicolons) should be flushed as well, but |0| if they should be
+% treated separately. The return value is the number of characters
+% that were flushed.
+% \begin{tcl}
+proc parsetcl::flush_whitespace {script index_var cmdsep} {
+ upvar 1 $index_var index
+ if {[
+ if {$cmdsep} then {
+ regexp -start $index -- {\A([ \t-\r;]|\\\n)+} $script match
+ } else {
+ regexp -start $index -- {\A([ \t\v\f\r]|\\\n)+} $script match
+ }
+ ]} then {
+ incr index [string length $match]
+ return [string length $match]
+ } else {
+ return 0
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{parse_command}
+% The |parse_command| procedure parses the next command, returning a
+% |Cd|, |Nc|, or |Np| item to its caller. The syntax is
+% \begin{quote}
+% |parsetcl::parse_command| \word{script} \word{index-var-name}
+% \word{nested}
+% \end{quote}
+% The \word{nested} argument is |1| if the context is that of command
+% substitution (in which case |]| acts as command terminator), and |0|
+% otherwise. Upon return, the index variable generally points to the
+% character that terminates the command.
+%
+% The procedure skips past any whitespace or command separators in front
+% of the actual command.
+% \begin{tcl}
+proc parsetcl::parse_command {script index_var nested} {
+ upvar 1 $index_var index
+% \end{tcl}
+% The first step is to scan past the whitespace in front of the
+% command.
+% \begin{tcl}
+ flush_whitespace $script index 1
+% \end{tcl}
+% Then there are two ``not a command'' cases to take care of: there
+% might be a comment or the command sequence might have ended. In the
+% former case, the extent of the comment is determined and a
+% corresponding |Nc| item is returned. Backslash--newline
+% substitution adds a bit complexity to the problem of finding the end
+% of the comment, since an escaped newline may be part of the comment,
+% although a backslash is only escaping if it isn't itself escaped.
+% \begin{tcl}
+ switch -- "[string index $script $index]$nested" {#0} - {#1} {
+ regexp -start $index -indices -- {\A#([^\n\\]|\\.)*(\\$)?}\
+ $script interval
+ incr index
+ regsub -all -- {\\\n[ \t]*}\
+ [string range $script $index [lindex $interval 1]]\
+ { } text
+ set index [expr {[lindex $interval 1] + 1}]
+ return [list Nc $interval $text]
+ } 0 - 1 - \]1 {
+% \end{tcl}
+% In the latter case, an |Np| item is returned. It happens if
+% |$index| is past the last character in the string, but also if
+% |$index| is at a right bracket and the command is \word{nested}.
+% \begin{tcl}
+ return [list Np "" ""]
+ }
+% \end{tcl}
+% But if we get this far, then there is a command to parse. One only
+% has to parse all the words.
+% \begin{tcl}
+ set res [list Cd [list $index ""] ""]
+ set next [parse_word $script index $nested]
+ while {[lindex $next 0] ne "Np"} {
+ lappend res $next
+ set next [parse_word $script index $nested]
+ }
+ lset res 1 1 [lindex $res end 1 1]
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{basic_parse_script}
+% The |basic_parse_script| procedure parses a script (that is to say, a
+% sequence of commands) and returns the corresponding |Rs| item.
+% The syntax is
+% \begin{quote}
+% |parsetcl::basic_parse_script| \word{script}
+% \end{quote}
+% \begin{tcl}
+proc parsetcl::basic_parse_script {script} {
+ set index 0
+ set res [list Rs [list $index ""] ""]
+ while {[lindex [set next [parse_command $script index 0]] 0] ne "Np"} {
+ lappend res $next
+ }
+ incr index -1
+ lset res 1 1 $index
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Parsing words}
+%
+% \begin{proc}{parse_word}
+% The |parse_word| procedure parses the next command word, returning
+% an |Lb|, |Lq|, |Lr|, |Mq|, |Mr|, or |Np| item to its caller. The
+% syntax is
+% \begin{quote}
+% |parsetcl::parse_word| \word{script} \word{index-var-name}
+% \word{nested}
+% \end{quote}
+% The \word{nested} argument is |1| if the context is that of command
+% substitution (in which case |]| acts as command terminator), and |0|
+% otherwise. It is assumed that the index variable points to the first
+% character of the word when this procedure is called. Upon return,
+% the index variable points to the first none-whitespace character
+% (or command separator) after the word that was parsed.
+%
+% Most of the actual work is done by the helper procedures
+% |parse_raw_word|, |parse_quoted_word|, and |parse_braced_word|.
+% \begin{tcl}
+proc parsetcl::parse_word {script index_var nested} {
+ upvar 1 $index_var index
+ switch -- [string index $script $index] \{ {
+ parse_braced_word $script index $nested
+ } \" {
+ parse_quoted_word $script index $nested
+ } "" - \; - \n {
+ list Np "" ""
+ } \] {
+ if {$nested} then {
+ list Np "" ""
+ } else {
+ parse_raw_word $script index $nested
+ }
+ } default {
+ parse_raw_word $script index $nested
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{parse_braced_word}
+% The |parse_braced_word| procedure parses a brace-delimited word and
+% returns the corresponding |Lb| item to its caller. The syntax is
+% \begin{quote}
+% |parsetcl::parse_braced_word| \word{script} \word{index-var-name}
+% \word{nested}
+% \end{quote}
+% where the arguments and call conventions are as for |parse_word|.
+% In case the braced word is followed by some non-whitespace
+% characters, then this will be interpreted as though a space was
+% missing after the brace. A corresponding |Ne| subtree will be
+% attached to the |Lb| item returned, and the index variable will be
+% pointed to that none-whitespace character after the brace.
+% \begin{tcl}
+proc parsetcl::parse_braced_word {script index_var nested} {
+ upvar 1 $index_var index
+ set res [list Lb [list $index ""]]
+ set depth 1
+ set text ""
+ incr index
+ while {$depth>0} {
+% \end{tcl}
+% Each iteration of this loop takes care of one non-trivial character
+% combination and whatever piece of trivial material that preceeds
+% it. Braces which are not escaped obviously constitute non-trivial
+% material (because they change the nesting depth), but escaped
+% newlines are also non-trivial (because they are subject to
+% substitution).
+% \begin{tcl}
+ regexp -start $index -- {\A([^{}\\]|\\[^\n])*} $script match
+ append text $match
+ incr index [string length $match]
+ switch -- [string index $script $index] \{ {
+ incr depth
+ incr index
+ } \} {
+ incr depth -1
+ incr index
+ } \\ {
+ if {[regexp -start $index -- {\A\\\n[ \t]*} $script match]}\
+ then {
+ incr index [string length $match]
+ append text { }
+ } else {
+% \end{tcl}
+% In this (rather curious) case, the \word{script} ended with an
+% escaping backslash, but there is nothing to escape. This is
+% interpreted as just the backslash. However, there will be an error
+% since the braces apparently haven't been properly balanced.
+% \begin{tcl}
+ append text \\
+ break
+ }
+ } "" {
+ break
+ }
+ }
+ if {$depth>0} then {
+ lset res 1 1 $index
+ lappend res $text [list Ne [list "" $index] {missing close-brace}]
+ lset res 3 1 0 [incr index]
+ return $res
+ }
+ lset res 1 1 [expr {$index - 1}]
+ lappend res $text
+% \end{tcl}
+% What remains now is to check that there aren't any stray characters
+% following the close-brace. If there is whitespace to flush then
+% everything is alright. Things are also alright if the next character
+% is a command terminator or we're at the end of the string.
+% \begin{tcl}
+ if {[flush_whitespace $script index 0]} then {return $res}
+ switch -- [string index $script $index] \n - \; - {} {
+ return $res
+ } \] {
+ if {$nested} then {return $res}
+ }
+% \end{tcl}
+% But if that is not the case then there is an error, and an |Ne| item
+% should be appended to |res|. The exact appearence of this item does
+% however depend on how the parser attempts to recover from the error,
+% and that is not immediately obvious. The \Tcllogo\ parser makes no
+% attempt to recover---and can therefore report the error as ``extra
+% characters after close-brace''---but the best way to recover rather
+% seems to be to assume that a space is missing. That is why the
+% following error message is non-standard.
+% \begin{tcl}
+ lappend res [list Ne [list $index [expr {$index - 1}]]\
+ {missing space after close-brace}]
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{parse_quoted_word}
+% The |parse_quoted_word| procedure parses a quote-delimited word and
+% returns the corresponding |Lq| or |Mq| item to its caller. The
+% syntax is
+% \begin{quote}
+% |parsetcl::parse_quoted_word| \word{script} \word{index-var-name}
+% \word{nested}
+% \end{quote}
+% where the arguments and call conventions are as for |parse_word|.
+% In case the quoted word is followed by some non-whitespace
+% characters, then this will be interpreted as though a space was
+% missing after the last quote. A corresponding |Ne| subtree will
+% be be put last in the |Lq| or |Mq| item returned, and the index
+% variable will be pointed to that none-whitespace character after
+% the quote.
+% \begin{tcl}
+proc parsetcl::parse_quoted_word {script index_var nested} {
+ upvar 1 $index_var index
+ set res [list Lq [list $index ""] ""]
+ set text ""
+ incr index
+ while {1} {
+% \end{tcl}
+% Each iteration of this loop adds one subtree to |res| and the
+% corresponding literate material to |text|. If some substitution
+% happens which does not produce literate material then the |Lq|
+% in |res| is changed to an |Mq|.
+% \begin{tcl}
+ switch -- [string index $script $index] \\ {
+ lappend res [parse_backslash $script index]
+ append text [lindex $res end 2]
+ } \$ {
+ lappend res [parse_dollar $script index]
+ lset res 0 Mq
+ } \[ {
+ lappend res [parse_bracket $script index]
+ lset res 0 Mq
+ } \" {
+ incr index
+ break
+ } "" {
+ lappend res [list Ne [list $index [expr {$index - 1}]]\
+ {missing close-quote}]
+ break
+ } default {
+ regexp -start $index -- {[^\\$\["]*} $script match
+ set t $index
+ incr index [string length $match]
+ lappend res [list Lr [list $t [expr {$index - 1}]] $match]
+ append text $match
+ }
+ }
+ lset res 1 1 [expr {$index - 1}]
+ if {[lindex $res 0] eq "Lq"} then {
+ lset res 2 $text
+% \end{tcl}
+% An |Lq| item that has precisely one subtree that furthermore is of
+% type |Lr| can do without that subtree, since all the interesting
+% information is in the |text|.
+% \begin{tcl}
+ if {[llength $res] == 4 && [lindex $res 3 0] eq "Lr"} then {
+ set res [lrange $res 0 2]
+ }
+ }
+% \end{tcl}
+% What remains now is to check that there aren't any stray characters
+% following the close-quote. If there is whitespace to flush then
+% everything is alright. Things are also alright if the next character
+% is a command terminator or we're at the end of the string.
+% \begin{tcl}
+ if {[flush_whitespace $script index 0]} then {return $res}
+ switch -- [string index $script $index] \n - \; - {} {
+ return $res
+ } \] {
+ if {$nested} then {return $res}
+ }
+% \end{tcl}
+% But if that is not the case then there is an error, and an |Ne| item
+% should be appended to |res|. As with characters after close-quotes,
+% it is assumed that a space is missing.
+% \begin{tcl}
+ lappend res [list Ne [list $index [expr {$index - 1}]]\
+ {missing space after close-quote}]
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{parse_raw_word}
+% The |parse_raw_word| procedure parses a whitespace-delimited word
+% of a command and returns the corresponding |Lr| or |Mr| item to its
+% caller. The syntax is
+% \begin{quote}
+% |parsetcl::parse_raw_word| \word{script} \word{index-var-name}
+% \word{nested}
+% \end{quote}
+% where the arguments and call conventions are as for |parse_word|.
+% \begin{tcl}
+proc parsetcl::parse_raw_word {script index_var nested} {
+ upvar 1 $index_var index
+ set res [list]
+ set type Lr
+ set interval [list $index]
+ set text ""
+ while {1} {
+% \end{tcl}
+% Each iteration of this loop adds one subtree to |res| and the
+% corresponding literate material to |text|. If some substitution
+% happens which does not produce literate material then |type| is set
+% to an |Mr|.
+% \begin{tcl}
+ switch -- [string index $script $index] \\ {
+ if {[string index $script [expr {$index+1}]] eq "\n"} then {
+ break
+ }
+ lappend res [parse_backslash $script index]
+ append text [lindex $res end 2]
+ continue
+ } \$ {
+ lappend res [parse_dollar $script index]
+ set type Mr
+ continue
+ } \[ {
+ lappend res [parse_bracket $script index]
+ set type Mr
+ continue
+ } \t - \n - \v - \f - \r - " " - \; - "" {
+ break
+ }
+ if {$nested} then {
+ if {![
+ regexp -start $index -- {\A[^\\$\[\]\t-\r ;]+} $script match
+ ]} then {break}
+ } else {
+ regexp -start $index -- {\A[^\\$\[\t-\r ;]+} $script match
+ }
+ set t $index
+ incr index [string length $match]
+ lappend res [list Lr [list $t [expr {$index - 1}]] $match]
+ append text $match
+ }
+% \end{tcl}
+% In case there is only a single element in |res| then that will be
+% the result.
+% \begin{tcl}
+ if {[llength $res]==1} then {
+ set res [lindex $res 0]
+ } else {
+ lappend interval [expr {$index - 1}]
+ if {$type ne "Lr"} then {set text ""}
+ set res [linsert $res 0 $type $interval $text]
+ }
+ flush_whitespace $script index 0
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Parsing substitutions}
+%
+% \begin{proc}{parse_backslash}
+% The |parse_backslash| procedure parses a backslash sequence and
+% returns the corresponding |Sb| item. The syntax is
+% \begin{quote}
+% |parsetcl::parse_backslash| \word{script} \word{index-var-name}
+% \end{quote}
+% and it is assumed that the index character in \word{script} is the
+% initial backslash in the sequence. Upon return, the index character
+% is the first character after the backslash sequence.
+% \begin{tcl}
+proc parsetcl::parse_backslash {script index_var} {
+ upvar 1 $index_var index
+ set start $index
+ incr index
+ set ch [string index $script $index]
+ set res [list Lr [list $index $index] $ch]
+ switch -- $ch a {
+ set res [list Sb [list $start $index] \a $res]
+ } b {
+ set res [list Sb [list $start $index] \b $res]
+ } f {
+ set res [list Sb [list $start $index] \f $res]
+ } n {
+ set res [list Sb [list $start $index] \n $res]
+ } r {
+ set res [list Sb [list $start $index] \r $res]
+ } t {
+ set res [list Sb [list $start $index] \t $res]
+ } v {
+ set res [list Sb [list $start $index] \v $res]
+ } x {
+ if {[regexp -start [expr {$index + 1}] -- {\A[0-9A-Fa-f]+}\
+ $script match]} then {
+ scan [string range $match end-1 end] %x code
+ incr index [string length $match]
+ lset res 1 1 $index
+ lset res 2 "x$match"
+ set res [list Sb [list $start $index]\
+ [format %c $code] $res]
+ } else {
+ set res [list Sb [list $start $index] x $res]
+ }
+ } u {
+ if {[regexp -start [expr {$index + 1}] -- {\A[0-9A-Fa-f]{1,4}}\
+ $script match]} then {
+ scan $match %x code
+ incr index [string length $match]
+ lset res 1 1 $index
+ lset res 2 "u$match"
+ set res [list Sb [list $start $index]\
+ [format %c $code] $res]
+ } else {
+ set res [list Sb [list $start $index] u $res]
+ }
+ } \n {
+ regexp -start [expr {$index + 1}] -- {\A[ \t]*} $script match
+ incr index [string length $match]
+ lset res 1 1 $index
+ lset res 2 "\n$match"
+ set res [list Sb [list $start $index] " " $res]
+ } "" {
+ return [list Sb [list $start $start] \\]
+ } default {
+ if {[regexp -start $index -- {\A[0-7]{1,3}} $script match]} then {
+ scan $match %o code
+ incr index [expr {[string length $match]-1}]
+ lset res 1 1 $index
+ lset res 2 $match
+ set res [list Sb [list $start $index] [format %c $code] $res]
+ } else {
+ set res [list Sb [list $start $index] $ch $res]
+ }
+
+ }
+ incr index
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{parse_bracket}
+% The |parse_bracket| procedure parses one pair of command
+% substitution brackets and returns the corresponding |Sc| item.
+% The syntax is
+% \begin{quote}
+% |parsetcl::parse_bracket| \word{script} \word{index-var-name}
+% \end{quote}
+% and it is assumed that the index character in \word{script} is the
+% initial bracket in the sequence. Upon return, the index character
+% is the first character after the close-bracket.
+% \begin{tcl}
+proc parsetcl::parse_bracket {script index_var} {
+ upvar 1 $index_var index
+ set res [list Sc [list $index ""] ""]
+ incr index
+ while {[lindex [set next [parse_command $script index 1]] 0] ne "Np"} {
+ lappend res $next
+ }
+ if {[string index $script $index] eq "\]"} then {
+ lset res 1 1 $index
+ incr index
+ return $res
+ } else {
+ lappend res [list Ne [list $index [expr {$index-1}]]\
+ {missing close-bracket}]
+ lset res 1 1 [expr {$index-1}]
+ return $res
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{variable}{varname_RE}
+% The |varname_RE| is the regular expression used with |$|
+% substitution for grabbing the name of the variable.
+% \begin{tcl}
+set parsetcl::varname_RE {\A(\w|::)+}
+% \end{tcl}
+% The reason for factoring this out into a variable is that
+% \Tcllogo\ isn't using the natural (Unicode) definition of an
+% alphanumeric character here, but relies on a locale-dependent
+% C~library function to perform this test. They generally agree on
+% ASCII characters, but outside that one probably cannot rely on that
+% the test produces sensible results. Hence if a script needs to be
+% parsed where some non-Unicode behaviour of this library function is
+% significant, then you might need to change the above regexp.
+%
+% There is a \Tcllogo\ bug report~\cite{Letter-bug} on the matter,
+% and hopefully there will be no need to ever change this regexp
+% once that has been resolved.
+% \end{variable}
+%
+% \begin{proc}{parse_dollar}
+% The |parse_dollar| procedure parses one |$|-sequence and returns
+% the corresponding |Sv|, |Sa|, or |Lr| item. The syntax is
+% \begin{quote}
+% |parsetcl::parse_dollar| \word{script} \word{index-var-name}
+% \end{quote}
+% and it is assumed that the index character in \word{script} is the
+% initial |$| in the sequence. Upon return, the index character
+% is the first character after the parsed sequence.
+% \begin{tcl}
+proc parsetcl::parse_dollar {script index_var} {
+ upvar 1 $index_var index
+ set res [list "" [list $index ""] ""]
+ incr index
+% \end{tcl}
+% If the first character after the |$| is a left brace, then the
+% variable is scalar and its name is terminated by the next right
+% brace. Note that braces do not nest in this case.
+% \begin{tcl}
+ if {[string index $script $index] eq "\{"} then {
+ lset res 0 Sv
+ set end [string first \} $script $index]
+ if {$end<0} then {
+ set end [expr {[string length $script] - 1}]
+ lappend res [list Lb [list $index $end]\
+ [string range $script [expr {$index + 1}] end]]\
+ [list Ne [list [expr {$end+1}] $end]\
+ {missing close-brace for variable name}]
+ } else {
+ lappend res [list Lb [list $index $end]\
+ [string range $script [expr {$index + 1}] [expr {$end-1}]]]
+ }
+ lset res 1 1 $end
+ set index [expr {$end + 1}]
+ return $res
+ }
+% \end{tcl}
+% Otherwise see if there is something which can be interpreted as an
+% alphanumeric variable name. First treat the case when there isn't;
+% in that case the |$| is just a literate |$| and it is returned as an
+% |Lr| iterm. Then treat the case that the variable is scalar.
+% \begin{tcl}
+ variable varname_RE
+ if {![regexp -start $index -- $varname_RE $script match]} then {
+ if {[string index $script $index] eq "("} then {
+ set match ""
+ } else {
+ return [list Lr [list [lindex $res 1 0] [lindex $res 1 0]] \$]
+ }
+ }
+ set t $index
+ incr index [string length $match]
+ lappend res [list Lr [list $t [expr {$index-1}]] $match]
+ if {[string index $script $index] ne "("} then {
+ lset res 0 Sv
+ lset res 1 1 [lindex $res 3 1 1]
+ return $res
+ }
+% \end{tcl}
+% What remains is to treat the case of an array variable. This is
+% very much like |parse_quoted_word|, but it is the right parenthesis
+% rather than |"| that acts as terminator.
+% \begin{tcl}
+ lset res 0 Sa
+ incr index
+ set subres [list Lr [list $index ""] ""]
+ lappend res ""
+ set text ""
+ while {1} {
+% \end{tcl}
+% Each iteration of this loop adds one subtree to |subres| and the
+% corresponding literate material to |text|. If some substitution
+% happens which does not produce literate material then the |Lr|
+% in |subres| is changed to an |Mr|.
+% \begin{tcl}
+ switch -- [string index $script $index] \\ {
+ lappend subres [parse_backslash $script index]
+ append text [lindex $subres end 2]
+ } \$ {
+ lappend subres [parse_dollar $script index]
+ lset subres 0 Mr
+ } \[ {
+ lappend subres [parse_bracket $script index]
+ lset subres 0 Mr
+ } ) {
+ lset subres 1 1 [expr {$index - 1}]
+ break
+ } "" {
+ lappend res\
+ [list Ne [list $index [incr index -1]] {missing )}]
+ lset subres 1 1 $index
+ break
+ } default {
+ regexp -start $index -- {[^\\$\[)]*} $script match
+ set t $index
+ incr index [string length $match]
+ lappend subres [list Lr [list $t [expr {$index - 1}]] $match]
+ append text $match
+ }
+ }
+ if {[lindex $subres 0] eq "Lr"} then {lset subres 2 $text}
+ if {[llength $subres] == 4} then {set subres [lindex $subres 3]}
+ lset res 1 1 $index
+ incr index
+ lset res 4 $subres
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+%
+% \section{Some utility procdures}
+%
+% \subsection{Viewing parser trees}
+%
+% It is useful to have a surveyable presentation of parser trees. An
+% easy step towards this would be to ensure that nesting depth is
+% mirrored in the indentation.
+%
+% \begin{proc}{format_tree}
+% The |format_tree| procedure takes a parser tree, a base indentation
+% (string of whitespace), and an indentation step (string of whitespace)
+% as argument. It returns a string that is list-wise equivalent to
+% |[list]| of the original tree, but has indentation mirroring the
+% nesting depth.
+% \begin{tcl}
+proc parsetcl::format_tree {tree base step} {
+ set res $base
+ append res \{ [lrange $tree 0 1] { }
+% \end{tcl}
+% The following is a trick to make a list element string
+% representation for the \word{text} that does not contain any sort
+% of newline: making the element unbalanced with respect to braces
+% forces escape-quoting also for newlines.
+% \begin{tcl}
+ if {[regexp {[\n\r]} [lindex $tree 2]]} then {
+ append res [string range [list "[lindex $tree 2]\{"] 0 end-2]
+ } else {
+ append res [lrange $tree 2 2]
+ }
+ if {[llength $tree]<=3} then {
+ append res \}
+ return $res
+ } elseif {[llength $tree] == 4 &&\
+ [string match {S[bv]} [lindex $tree 0]]} then {
+% \end{tcl}
+% This is a slight optimization: |Sb| and |Sv| trees look better on
+% one line than on three.
+% \begin{tcl}
+ append res " " [format_tree [lindex $tree 3] "" ""] \}
+ return $res
+ }
+ append res \n
+ foreach subtree [lrange $tree 3 end] {
+ append res [format_tree $subtree $base$step $step] \n
+ }
+ append res $base \}
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Offsetting intervals}
+%
+% \begin{proc}{offset_intervals}
+% This procedure modifies a \word{tree} by adding \word{offset} to
+% all endpoints of each interval in that tree, and returns the
+% modified tree. The syntax is
+% \begin{quote}
+% |parsetcl::offset_intervals| \word{tree} \word{offset}
+% \end{quote}
+% \begin{tcl}
+proc parsetcl::offset_intervals {tree offset} {
+ set res [lrange $tree 0 2]
+ foreach i {0 1} {
+ lset res 1 $i [expr {[lindex $res 1 $i] + $offset}]
+ }
+ foreach subtree [lrange $tree 3 end] {
+ lappend res [offset_intervals $subtree $offset]
+ }
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{reparse_Lb_as_script}
+% The |reparse_Lb_as_script| procedure replaces an |Lb| node from an
+% existing parser tree with the |Rs| node produced by parsing the text
+% between the braces as a script. The syntax is
+% \begin{quote}
+% |parsetcl::reparse_Lb_as_script| \word{tree-var} \word{node-index}
+% \word{parsed string}
+% \end{quote}
+% where \word{tree-var} is the name in the caller's local context of
+% the variable in which the tree to substitute is stored and
+% \word{node-index} is the index list of the node to replace. The
+% procedure returns |2| if the node was an |Lb| node, |1| if is was
+% an |Lr| or |Lq| node, and |0| if the node was not of any of these
+% types. In the last case, the tree is not modified. In the case that
+% |1| is returned, the node has been substituted, but the intervals
+% may be slightly off since the string to parse was taken from the
+% \word{text} part of the substituted node. The normal case is that |2|
+% is returned, and in this case the intervals unambiguously refer to
+% positions in the \word{parsed string}.
+% \begin{tcl}
+proc parsetcl::reparse_Lb_as_script {tree_var index parsed} {
+ upvar 1 $tree_var tree
+ set node [lindex $tree $index]
+ switch -- [lindex $node 0] Lb - Lr - Lq {
+ set base [expr {[lindex $node 1 0] + 1}]
+ if {[lindex $node 0] eq "Lb"} then {
+ set script [string range $parsed $base\
+ [expr {[lindex $node 1 1] - 1}]]
+ } else {
+ set script [lindex $node 2]
+ }
+ lset tree $index\
+ [offset_intervals [basic_parse_script $script] $base]
+ if {[lindex $node 0] eq "Lb"} then {
+ return 2
+ } else {
+ return 1
+ }
+ } default {
+ return 0
+ }
+}
+% \end{tcl}
+% \end{proc}
+
+
+%
+%
+% \subsection{Traversing parser trees}
+%
+% \begin{proc}{walk_tree}
+% The |walk_tree| procedure has the syntax
+% \begin{quote}
+% |parsetcl::walk_tree| \word{tree-var} \word{index-var}
+% \begin{regblock}[\regplus]\word{type-pattern}
+% \word{body}\end{regblock}
+% \end{quote}
+% It walks through each node in the tree stored in the
+% \word{tree-var} in the order that they appear in the string, i.e.,
+% first the root of a tree, then it walks through each subtree in
+% sequence. When visiting a node, the type of the node is
+% regexp-matched against the \word{type-pattern}s, and the first
+% matching \word{body} is evaluated (entirely using |switch -regexp|)
+% in the local context of the caller. While walking, the procedure is
+% updating the \word{index-var} variable so that it always contains
+% the index list specifying the current node in the tree.
+%
+% It is OK to modify the tree while walking through it, provided that
+% the index list of the current node remains valid throughout. It is
+% particular possible to change the contents of the current node (add
+% or remove children) without messing things up.
+%
+% There is no particular return value from this procedure.
+% \begin{tcl}
+proc parsetcl::walk_tree {tree_var index_var args} {
+ upvar 1 $tree_var tree $index_var idxL
+ set idxL [list]
+ set i 0
+ while {$i>=0} {
+ if {$i==0} then {
+ uplevel 1 [list switch -regexp --\
+ [lindex [lindex $tree $idxL] 0] $args]
+ set i 3
+ } elseif {$i < [llength [lindex $tree $idxL]]} then {
+ lappend idxL $i
+ set i 0
+ } elseif {[llength $idxL]} then {
+ set i [lindex $idxL end]
+ set idxL [lrange $idxL 0 end-1]
+ incr i
+ } else {
+ set i -1
+ }
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{simple_parse_script}
+% The |simple_parse_script| procedure is similar to
+% |basic_parse_script|, but it tries to recognise some common control
+% structures (|if|, |for|, etc.) and reparses those arguments that
+% (for standard command definitions) are scripts. The syntax is
+% \begin{quote}
+% |parsetcl::simple_parse_script| \word{script}
+% \end{quote}
+% and it returns the parsed script.
+% \begin{tcl}
+proc parsetcl::simple_parse_script {script} {
+ set tree [parsetcl::basic_parse_script $script]
+ walk_tree tree indices Cd {
+ switch -- [lindex [lindex $tree $indices] 3 2] if {
+ for {set i 3} {$i < [llength [lindex $tree $indices]]}\
+ {incr i} {
+ switch -- [lindex [lindex $tree $indices] $i 2]\
+ if - elseif {
+ incr i; continue
+ } then - else {
+ incr i
+ }
+ parsetcl::reparse_Lb_as_script tree\
+ [linsert $indices end $i] $script
+ }
+ } while {
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 5]\
+ $script
+ } for {
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 4]\
+ $script
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 6]\
+ $script
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 7]\
+ $script
+ } foreach {
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end end]\
+ $script
+ } catch {
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 4]\
+ $script
+ } proc {
+ parsetcl::reparse_Lb_as_script tree [linsert $indices end 6]\
+ $script
+ }
+ }
+ return $tree
+}
+% \end{tcl}
+% \end{proc}
+%
+% \section{Parsing expressions}
+%
+% This hasn't been implemented yet.
+%
+%
+% \section{Advanced script parsing}
+%
+% Most of the meaning of a \Tcllogo\ script depends on its commands
+% rather than being given by the syntax---there is e.g. nothing in the
+% general syntax that makes the last argument of a |foreach| command
+% more likely to contain a script than any of the other arguments---and
+% therefore any higher level parsing of \Tcllogo\ scripts must employ a
+% table of commands
+%
+% This hasn't been implemented yet.
+%
+%
+% \section{Script reconstruction}
+%
+% This hasn't been implemented yet, but the parser trees contain
+% the necessary information. Applications of script reconstruction
+% includes writing a |proc|-like command that inlines code in the body
+% argument before the procedure is created.
+%
+%
+% \begin{thebibliography}{9}
+% \bibitem{Letter-bug}
+% Kevin B. Kenny and Jeffrey Hobbs:
+% \textit{Dollar-substitution and non-Latin-1},
+% \Tcllogo~project bug \#408568 (2001, still open April~2003);
+% \href{https://sourceforge.net/tracker/^^A
+% ?func=detail&aid=408568&group_id=10894&atid=110894}^^A
+% {\textsc{https}:/\slash \texttt{sourceforge.net}\slash
+% \texttt{tracker}\slash
+% \texttt{?func=detail\&}\penalty\exhyphenpenalty
+% \texttt{aid=408568\&}\penalty\exhyphenpenalty
+% \texttt{group\_id=10894\&}\penalty\exhyphenpenalty
+% \texttt{atid=110894}.}
+%
+% \end{thebibliography}
+%
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/tclldoc/examples/parsetcl.ins b/macros/latex/contrib/tclldoc/examples/parsetcl.ins
new file mode 100644
index 0000000000..645dc77f8a
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/examples/parsetcl.ins
@@ -0,0 +1,54 @@
+% parsetcl.ins --- DOCSTRIP installation script for parsetcl.
+\input docstrip
+
+% Redefine the \MetaPrefix; it should be something which starts a
+% until-end-of-line comment:
+\edef\MetaPrefix{\string#\string#}
+
+
+% Redefine the file preamble and postamble; this is necessary because
+% otherwise the old \metaPrefix is inserted at the beginning of these
+% lines.
+\preamble
+
+In other words:
+ ***************************************
+ * This Source is not the True Source. *
+ ***************************************
+The True Source is parsetcl.dtx in
+ http://ftp.ctan.org/tex-archive/macros/latex/contrib/tclldoc/examples
+
+It is preferred that you apply the distribution and modification
+conditions of the LaTeX Project Public License (LPPL) for this file,
+but you may alternatively choose to apply BSD/Tcl-style license
+conditions (either is OK). The latest version of the LPPL is in
+ http://www.latex-project.org/lppl.txt
+and version 1.2 or later is part of all distributions of LaTeX
+version 1999/12/01 or later.
+
+\endpreamble
+
+\postamble
+\endpostamble
+
+
+% Actually make the files:
+\generate{
+ \file{parsetcl.tcl}{\from{parsetcl.dtx}{pkg}}
+}
+
+
+\Msg{}
+\Msg{************************************************}
+\Msg{*}
+\Msg{* To complete installation,}
+\Msg{* place parsetcl.tcl in a Tcl library directory}
+\Msg{* and run pkg_mkIndex to rebuild the package}
+\Msg{* index.}
+\Msg{*}
+\Msg{************************************************}
+\Msg{}
+
+
+\end
+
diff --git a/macros/latex/contrib/tclldoc/examples/pdf.dtx b/macros/latex/contrib/tclldoc/examples/pdf.dtx
new file mode 100644
index 0000000000..249a28ee6c
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/examples/pdf.dtx
@@ -0,0 +1,796 @@
+%
+% \iffalse
+%<*driver>
+\documentclass{tclldoc}
+\PageIndex\CodelineNumbered
+\IndexPrologue{%
+ \section*{Index}%
+ All numbers in this index are page numbers.
+ Underlined entries refer to places where the item in
+ question is defined.%
+}
+\setcounter{IndexColumns}{2}
+\begin{document}
+\DocInput{pdf.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{A simple PDF writer in \Tcllogo}
+% \author{Lars Hellstr\"om}
+% \maketitle
+%
+% \begin{abstract}
+% This file contains some basic routines that allow a \Tcllogo\
+% script to write PDF files.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \section{PDF files and objects}
+%
+% A Portable Document Format (PDF) file is, when compared with for example
+% a PostScript file or HTML file, a rather disorganised document. This
+% is because at the basic level, a PDF file is a heap rather than a
+% text; it \emph{can} be ``disorganised'' since its logical structure
+% is based on cross-referencing rather than on sequentiality. The first
+% step is therefore to provide support for writing well-formed heaps.
+%
+% \changes{0.0}{2003/01/02}{Initial version. (LH)}
+%
+% \begin{tcl}
+%<*pkg>
+package require Tcl 8.1
+package provide writepdf 0.1
+namespace eval pdf {}
+% \end{tcl}
+% \setnamespace{pdf}
+%
+%
+% \subsection{Building objects}
+%
+% The independent units in a PDF file are called objects. An
+% \emph{object} is essentially a value (which includes a type). The
+% procedures below construct strings of PDF code that encode objects of
+% various types. The strings returned are generally such that one must
+% insert whitespace between two such strings if the data is to be
+% properly encoded. The strings may contain newlines if some building
+% routine thinks the lines should otherwise be too long.
+%
+% \begin{proc}{boolean_obj}
+% The |boolean_obj| procedure returns a boolean object, corresponding
+% to the string passed as its only argument. Most of it is about
+% parsing this string: \texttt{true}, \texttt{yes}, \texttt{on}, and
+% nonzero numbers are interpreted as boolean true, whereas
+% \texttt{false}, \texttt{no}, \texttt{off}, and the zero number is
+% interpreted as boolean false. The matching is case-insensitive.
+% \begin{tcl}
+proc pdf::boolean_obj {value} {
+ switch -nocase -- $value {
+ true - yes - on {return true}
+ false - no - off {return false}
+ default {
+ if {$value} then {return true} else {return false}
+ }
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{int_obj}
+% The |int_obj| procedure returns the PDF object corresponding to
+% the integer supplied as argument.
+% \begin{tcl}
+proc pdf::int_obj {value} {format %d $value}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{real_obj}
+% \begin{variable}{precision}
+% The |real_obj| procedure returns the PDF object corresponding to
+% the real number supplied as argument. The syntax is
+% \begin{quote}
+% |pdf::real_obj| \word{value} \word{precision}\regopt
+% \end{quote}
+% where \word{precision} is the number of decimals that will be
+% included in the object. If omitted, the value of the |precision|
+% variable is used, and that defaults to $3$.
+% \begin{tcl}
+set pdf::precision 3
+proc pdf::real_obj {value {precision -1}} {
+ if {$precision<0} then {
+ unset precision
+ variable precision
+ }
+ format %.[format %d $precision]f $value
+}
+% \end{tcl}
+% \end{variable}\end{proc}
+%
+% \begin{proc}{string_obj}
+% The |string_obj| procedure returns the PDF string object
+% corresponding to the argument. Backslashes and parentheses are
+% escaped. Control characters are converted to escape sequences.
+% Characters with character code above 255 cause an error to be
+% thrown (PDF strings correspond more to \Tcllogo\ byte arrays than to
+% general strings). If the string produced is longer than 100
+% characters, then backslash--newline sequences are inserted in
+% suitable places.
+% \begin{tcl}
+proc pdf::string_obj {str} {
+ if {[regexp "\[^\n\r -\xff\]" $str]} then {
+ set estr [string map [list \\ \\\\ ( \\( ) \\) \r \\r \n \\n] $str]
+ set str "("
+ set len 1
+ foreach ch [split $estr {}] {
+ scan $ch %c code
+ if {$code==92} then {
+ append str \\
+ incr len
+ continue
+ } elseif {$code<32} then {
+ append str "\\[format %03o $code]"
+ incr len 4
+ } elseif {$code<256} then {
+ append str $ch
+ incr len
+ } else {
+ error "Bad character $ch [format (U+%04x) $code]\
+ in PDF string."
+ }
+ if {$len > 100} then {
+ append str \\\n
+ set len 0
+ }
+ }
+ append str ")"
+ } else {
+ set L [list]
+ while {[string length $str]>=100} {
+ lappend L [string map [list \\ \\\\ ( \\( ) \\) \r \\r \n \\n]\
+ [string range $str 0 99]]
+ set str [string range $str 100 end]
+ }
+ if {[string length $str]} then {
+ lappend L\
+ [string map [list \\ \\\\ ( \\( ) \\) \r \\r \n \\n] $str]
+ }
+ set str ([join $L \\\n])
+ }
+ return $str
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{hexstring_obj}
+% The |hexstring_obj| procedure returns the PDF string object,
+% encoded as hexadecimal digits, that corresponds to the argument.
+% If the string is longer than 31 characters then it will be broken
+% on several lines.
+% \begin{tcl}
+proc pdf::hexstring_obj {str} {
+ set hstr "<"
+ set len 1
+ foreach ch [split $str {}] {
+ scan $ch %c code
+ if {$len>=63} then {
+ append hstr \n
+ set len 0
+ }
+ if {$code<256} then {
+ append hstr [format %02x $code]
+ incr len 2
+ } else {
+ error "Bad character $ch [format (U+%04x) $code]\
+ in PDF string."
+ }
+ }
+ append hstr ">"
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{text_obj}
+% The |text_obj| procedure returns the PDF string object, encoded as
+% hexadecimal digits, that corresponds to the argument string. This is
+% meant to be used for \emph{text strings}
+% (see~\cite[Ssec.~4.4.1]{PDFspec}), which are \Tcllogo-style strings
+% rather than byte arrays. Text strings may contain general Unicode
+% characters, although they will then be encoded using UTF-16BE.
+%
+% The implementation constructs the 8-bit and 16-bits encodings of the
+% string in parallel, and only when it is done will it decide which to
+% return.
+% \begin{tcl}
+proc pdf::text_obj {str} {
+ set hstr "<"
+ set ustr "<FEFF"
+ set lenh 1
+ set lenu 5
+ set eight_ok 1
+ foreach {chh chl} [split [encoding convertto unicode $str] {}] {
+ scan $chh %c codeh
+ scan $chl %c codel
+ if {$lenu>=62} then {
+ append ustr \n
+ set lenu 0
+ }
+ append ustr [format %02x%02x $codeh $codel]
+ incr lenu 4
+ if {$codeh>0} then {set eight_ok 0}
+ if {!$eight_ok} then {continue}
+ if {$lenh>=63} then {
+ append hstr \n
+ set lenh 0
+ }
+ append hstr [format %02x $codel]
+ incr lenh 2
+ }
+ append hstr ">"
+ append ustr ">"
+ if {$eight_ok && ![string match {<feff*} $hstr]} then {
+ return $hstr
+ } else {
+ return $ustr
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{name_obj}
+% The |name_obj| procedure returns the PDF name object corresponding
+% to its argument. It is useful mainly for names with strange
+% characters in them (such as spaces), but most names (e.g.\ dictionary
+% keys) appearing in PDF files do not require any quoting and can
+% therefore just as well be written as explicit PDF code.
+% \begin{tcl}
+proc pdf::name_obj {str} {
+ if {[string length $str]>126} then {
+ error "String too long to be a PDF name."
+ }
+ set res /
+ foreach ch [split $str {}] {
+ switch -glob -- $ch {
+ ( - ) - < - > - \\[ - \\] - \{ - \} - / - % - # {
+ scan $ch %c code
+ append res [format #%02x $code]
+ }
+ [!-~] {append res $ch}
+ default {
+ scan $ch %c code
+ append res [format #%02x $code]
+ }
+ }
+ }
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{array_obj}
+% The |array_obj| procedure builds an array object of the objects it
+% is given as arguments. The syntax is
+% \begin{quote}
+% |pdf::array_obj| \word{object}\regstar
+% \end{quote}
+% Newlines are inserted between the objects if it does not appear as
+% if the object would fit on a single (100 character) line.
+% \begin{tcl}
+proc pdf::array_obj {args} {
+ set res \[
+ set len 1
+ foreach item $args {
+ if {[string length $item] + $len >= 100} then {
+ append res \n
+ set len 0
+ } elseif {[string length $res]>1} then {
+ append res " "
+ incr len
+ }
+ append res $item
+ incr len [string length $item]
+ }
+ if {$len >= 100} then {
+ append res \n
+ }
+ append res \]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{dict_obj}
+% The |dict_obj| procedure builds a dictionary object from its
+% arguments. The syntax is
+% \begin{quote}
+% |pdf::dict_obj|
+% \begin{regexp}[\regstar]\word{key} \word{value}\end{regexp}
+% \end{quote}
+% where each \word{key} must be a name object and each \word{value}
+% must be an object. It is checked that the number of elements is
+% correct and that the keys begin with a slash.
+% \begin{tcl}
+proc pdf::dict_obj {args} {
+ if {[llength $args] % 2 != 0} then {
+ error "Not the same number of keys and values."
+ }
+ set res "<<\n"
+ foreach {key value} $args {
+ if {![string match {/*} $key]} then {
+ error "'$key' isn't a name object."
+ }
+ if {[string length $key] + [string length $value]>99} then {
+ append res $key \n $value \n
+ } else {
+ append res $key { } $value \n
+ }
+ }
+ append res ">>"
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{null_obj}
+% The |null_obj| procedure returns a null object. It has no arguments.
+% \begin{tcl}
+proc pdf::null_obj {} {return null}
+% \end{tcl}
+% \end{proc}
+%
+%
+% Objects can also be \emph{streams}, but those have a special relation
+% to the file structure and are therefore best treated in conjunction
+% with that. In particular, streams cannot be used as arguments of
+% |array_obj| or |dict_obj|. The arguments of these procedures can
+% however be \emph{indirect references} to objects of any type, but
+% these too are best treated in the context of the basic PDF file
+% structure.
+%
+%
+% \subsection{File structure}
+%
+% The body of a PDF file consists of a sequence of \emph{indirect
+% objects}, which are mainly a sort of declarations: a pair of integers
+% are associated with an object value. Since any composite object can
+% (and in several cases must) contain a reference to any indirect object,
+% this makes it possible to build up arbitrary data structures. It is
+% however also a complication, since it requires that there is a
+% mechanism for allocating these numbers.
+%
+% \begin{arrayvar}{file\meta{fnum}}
+% Every file that \Tcllogo\ opens gets a unique identifier which is
+% used in calls to |puts| and such. This identifier is also used as
+% the name of an array in the |pdf| namespace, in which the
+% procedures below store all auxiliary information they need to create
+% a proper PDF file.
+% \end{arrayvar}
+%
+% \begin{arrayentry}{file\meta{fnum}}{!\meta{reference label}}
+% \begin{arrayentry}{file\meta{fnum}}{last_object_num}
+% In this API, references to indirect objects can be arbitrary
+% strings, called \emph{reference labels}. The correspondence to the
+% object numbers actually found in the file is given by the
+% \texttt{!}\meta{reference label} entries in the array of the file in
+% question. The entries in this array are lists with the structure
+% \begin{quote}
+% \word{object number} \word{generation number} \word{file
+% position}\regopt
+% \end{quote}
+% where the \word{file position} is present only if the indirect
+% object in question has been written to file already. The
+% \word{object number} is the number of the object referred to. The
+% \word{generation number} is currently always zero; it appears that
+% it can only be nonzero for files that have incrementally updated,
+% and this API only supports creating a file from scratch. The
+% \word{file position} is the position in the file of the beginning
+% of the indirect object begin referred to.
+%
+% The |last_object_num| entry in the array holds the most recently
+% allocated object number. It is incremented whenever a new reference
+% label is encountered.
+% \end{arrayentry}\end{arrayentry}
+%
+% \begin{proc}{obj_ref}
+% The |obj_ref| procedure returns PDF code for an indirect reference
+% to an object. The syntax is
+% \begin{quote}
+% |pdf::obj_ref| \word{file} \word{reference label}
+% \end{quote}
+% where \word{file} is the indentifier of the PDF file in question.
+% If the \word{reference label} has not been encountered before for
+% this particular file, then a new object number is allocated for it.
+% \begin{tcl}
+proc pdf::obj_ref {F label} {
+ upvar #0 [namespace current]::$F A
+ if {![info exists A(!$label)]} then {
+ incr A(last_object_num)
+ set A(!$label) [list $A(last_object_num) 0]
+ }
+ format {%d %d R} [lindex $A(!$label) 0] [lindex $A(!$label) 1]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{begin_stream}
+% \begin{proc}{end_stream}
+% The |begin_stream| and |end_stream| procedures delimit the creation
+% of a \emph{stream object}. Between two such commands, it is possible
+% to write arbitrary text (usually page descriptors or some sort of
+% embedded data) to the PDF file and have it inserted correctly into
+% the file as the data stored in the stream object.
+%
+% The syntax for |begin_stream| is
+% \begin{quote}
+% |pdf::begin_stream| \word{file} \word{reference label}
+% \begin{regexp}[\regstar]\word{key} \word{value}\end{regexp}
+% \end{quote}
+% where \word{file} of course is the file to write to and
+% \word{reference label} is the string that should be used to
+% reference this object. Each stream consists of one dictionary part
+% and one data part, where the primary task of the dictionary part is
+% to specify how the data part should be interpreted. The most
+% important element in the dictionary is the \texttt{/Length} key and
+% its value---these are inserted by the |begin_stream| and
+% |end_stream| commands, so one needs not worry about those---but if
+% for example the data part is encoded in some special way (for
+% example, it might be compressed) then it is necessary to include
+% additional elements in the dictionary. This is what the \word{key}
+% and \word{value} arguments are for.
+%
+% \begin{arrayentry}{file\meta{fnum}}{current_stream}
+% The |current_stream| entry in a PDF file array is set if and only
+% if the current position in that file is inside a stream. It is
+% not possible to begin a new stream when this entry is set. The
+% value of this entry is a list with the structure
+% \begin{quote}
+% \word{reference label} \word{start}
+% \end{quote}
+% where \word{reference label} is the reference label of the stream
+% and \word{start} is the position in the file of the first byte in
+% the stream data. Both of these are needed at |end_stream| to
+% record the length of the stream data.
+% \end{arrayentry}
+%
+% \begin{arrayentry}{file\meta{fnum}}{?\meta{reference label}}
+% This kind of entry is used for indirect objects that are lengths
+% of the stream whose reference label is the \meta{reference label}.
+% They have the same syntax as their |!| ordinary counterparts.
+% \end{arrayentry}
+%
+% \begin{tcl}
+proc pdf::begin_stream {F label args} {
+ upvar #0 [namespace current]::$F A
+ if {[info exists A(current_stream)]} then {
+ error "There is already a stream ([lindex $A(current_stream) 0])\
+ being written to in this file."
+ }
+ if {![info exists A(!$label)]} then {
+ incr A(last_object_num)
+ set A(!$label) [list $A(last_object_num) 0]
+ }
+ set A(?$label) [list [incr A(last_object_num)] 0]
+ lappend A(!$label) [tell $F]
+ puts $F\
+ [format {%d %d obj} [lindex $A(!$label) 0] [lindex $A(!$label) 1]]
+ puts $F [eval\
+ [list dict_obj /Length [format {%d 0 R} $A(last_object_num)]]\
+ $args]
+ puts $F stream
+ set A(current_stream) [list $label [tell $F]]
+}
+% \end{tcl}
+%
+% The |end_stream| procedure takes the target file as its only argument.
+% It finishes off the stream as necessary. It also evaluates
+% everything that has been placed in the backlog of the file.
+%
+% \begin{arrayentry}{file\meta{fnum}}{backlog}
+% It is not possible to output a new indirect object when a stream
+% is being written to, but it can still be at such a time that the
+% need for such an object is discovered. The |backlog| entry
+% provides a way around that limitation---this entry is a script
+% that is evaluated (and cleared) at the end of every |end_stream|,
+% hence commands can be delayed by appending them to this script,
+% instead of evaluating them immediately.
+%
+% New commands are appended to the |backlog|, and must be preceeded
+% by a command separator.
+% \end{arrayentry}
+%
+% \begin{tcl}
+proc pdf::end_stream {F} {
+ upvar #0 [namespace current]::$F A
+ if {![info exists A(current_stream)]} then {
+ error "There is no stream to end."
+ }
+ set length [expr {[tell $F] - [lindex $A(current_stream) 1]}]
+ set label [lindex $A(current_stream) 0]
+ unset A(current_stream)
+ puts $F "endstream endobj"
+ lappend A(?$label) [tell $F]
+ puts $F [format {%d %d obj %d endobj} [lindex $A(?$label) 0]\
+ [lindex $A(?$label) 1] $length]
+ eval "set A(backlog) {}; $A(backlog)"
+}
+% \end{tcl}
+% \end{proc}\end{proc}
+%
+% \begin{proc}{put_obj}
+% The |put_obj| procedure writes a direct object to a PDF file. The
+% syntax is
+% \begin{quote}
+% |pdf::put_obj| \word{file} \word{reference label} \word{object}
+% \end{quote}
+% \begin{tcl}
+proc pdf::put_obj {F label obj} {
+ upvar #0 [namespace current]::$F A
+ if {[info exists A(current_stream)]} then {
+ append A(backlog) \n [list put_obj $F $label $obj]
+ return
+ }
+ if {![info exists A(!$label)]} then {
+ incr A(last_object_num)
+ set A(!$label) [list $A(last_object_num) 0]
+ }
+ lappend A(!$label) [tell $F]
+ puts $F\
+ [format {%d %d obj} [lindex $A(!$label) 0] [lindex $A(!$label) 1]]
+ puts $F $obj
+ puts $F endobj
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{rewrite_pdf}
+% The |rewrite_pdf| procedure opens a new PDF file for writing and
+% initialises the associated data structures. The syntax is
+% \begin{quote}
+% |pdf::rewrite_pdf| \word{file name} \meta{options}
+% \end{quote}
+% and the return value is the identifier of the file opened. The
+% \word{file name} is of course the name of that file. The
+% \meta{options} is zero or more of
+% \begin{quote}
+% |-permissions| \word{integer}\\
+% |-header| \word{string}
+% \end{quote}
+% The permissions are the default permissions for the file in question.
+% If this is not specified, then no such value is specified to |open|,
+% The header is a string that will be put first in the file (as header).
+% It defaults to
+% \begin{quote}
+% \texttt{\%PDF-1.3}\\
+% \texttt{\%\r{a}\"a\"o}
+% \end{quote}
+% where the first line is a standard header line, and the second line
+% is there to help some software understand that the file should be
+% treated as a binary file. \textbf{Note} that no newline is inserted
+% after this string; be sure to include it in the string if necessary.
+% \begin{tcl}
+proc pdf::rewrite_pdf {name args} {
+ set Opt(-header) %PDF-1.3\n%\xe5\xe4\xf6\n
+ array set Opt $args
+ if {[info exists Opt(-permissions)]} then {
+ set F [open $name w $Opt(-permissions)]
+ } else {
+ set F [open $name w]
+ }
+ fconfigure $F -translation binary
+ puts -nonewline $F $Opt(-header)
+ upvar #0 [namespace current]::$F A
+ array unset A
+ set A(last_object_num) 0
+ set A(backlog) ""
+ return $F
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}{close_pdf}
+% The |close_pdf| procedure performs the non-trivial task of finishing
+% off the PDF file and closing it. The syntax is
+% \begin{quote}
+% |pdf::close_pdf| \word{file} \word{catalog label}
+% \begin{regexp}[\regstar]\word{key} \word{value}\end{regexp}
+% \end{quote}
+% and the return value is a report detailing any problems
+% encountered (such as objects that are referred to but never
+% defined). This is a report rather than an error, because there is
+% in many cases no sharp distinction. If the return value is
+% non-empty, then there is probably a bug in your program that needs
+% to be fixed.
+%
+% The \word{file} is the identifier of the file to write. The
+% \word{catalog label} is the reference label of the Catalog object
+% in the document. The remaining arguments can be used to insert
+% additional information (such as a reference to the Info dictionary
+% of the document) in the trailer dictionary.
+%
+% \begin{tcl}
+proc pdf::close_pdf {F label args} {
+ upvar #0 [namespace current]::$F A
+ set reportL [list]
+% \end{tcl}
+% The first step is to compile the cross-reference table of the
+% document. I originally made one subsection for each range of defined
+% indirect objects, giving the mandatory free entry \#0 a separate
+% subsection, but for some reason Adobe software didn't like that at
+% all.\footnote{Whether this means Adobe isn't following their own
+% standard I leave to others to decide. Neither GhostScript nor
+% Quartz (the PDF-based graphics system in Mac~OS~X) seemed to have
+% any problems with this arrangement.} Hence the current
+% implementation is to make a cross-reference table with only one
+% subsection, with an explicit free entry for every missing item.
+%
+% \changes{0.1}{2003/02/24}{Changed cross-reference section to avoid
+% what is probably a bug in Adobe PDF readers. (LH)}
+%
+% The |xrA| array constructed below is a prototype for the
+% cross-reference section. It is indexed by object number and the
+% entries have the list structure
+% \begin{quote}
+% \word{file position} \word{generation number} \word{type}
+% \end{quote}
+% Just as in a PDF file, the \word{type} is either \texttt{f} or
+% \texttt{n} depending on whether the entry is ``free'' or
+% ``in use''. The \word{file position} and \word{generation number}
+% are however not padded with zeros, and the \word{file position} is
+% initially an empty string in the ``free'' entries.
+%
+% This first round simply collects the information and detects
+% collisions.
+% \begin{tcl}
+ set xrA(0) [list "" 65535 f]
+ foreach lbl [array names A {[!?]*}] {
+ set idx [lindex $A($lbl) 0]
+ set ent [list [lindex $A($lbl) 2] [lindex $A($lbl) 1] n]
+ if {[llength $A($lbl)]<3} then {
+ lappend reportL "There is no indirect object with label:\
+ [string range $lbl 1 end]"
+ set ent [replace $ent 2 2 f]
+ } elseif {[llength $A($lbl)]>3} then {
+ lappend reportL "Multiple indirect objects for label\
+ [string range $lbl 1 end]; at\
+ [join [lrange $A($lbl) 2 end]]."
+ }
+ if {![info exists xrA($idx)]} then {
+ set xrA($idx) $ent
+ } elseif {[lindex $xrA($idx) 2]=="f" && [lindex $ent 2]=="n"}\
+ then {
+ lappend reportL "This shouldn't happen:\
+ There are several reference labels for\
+ indirect object $idx. Using that with label:\
+ [string range $lbl 1 end]"
+ set xrA($idx) $ent
+ } else {
+ lappend reportL "This shouldn't happen:\
+ There are several reference labels for\
+ indirect object $idx. Ignoring that with label:\
+ [string range $lbl 1 end]"
+ }
+ }
+% \end{tcl}
+% The second round makes sure that there is a contiguous sequence of
+% reference numbers and constructs the linked list of free entries.
+% \begin{tcl}
+ set last_free 0
+ set maxidx [lindex [lsort -integer -decreasing [array names xrA]] 0]
+ for {set n $maxidx} {$n>=0} {incr n -1} {
+ if {![info exists xrA($n)]} then {
+ set xrA($n) [list "" 0 f]
+ lappend reportL "This shouldn't happen:\
+ Object number $n was allocated, but not\
+ assigned a reference label."
+ }
+ if {[lindex $xrA($n) 2]=="f"} then {
+ set xrA($n) [lreplace $xrA($n) 0 0 $last_free]
+ set last_free $n
+ }
+ }
+% \end{tcl}
+% Now the cross-reference section can be written to file.
+% \begin{tcl}
+ set startxref [tell $F]
+ puts $F xref
+ puts $F [format {%d %d} 0 [expr {$maxidx + 1}]]
+ for {set n 0} {$n<=$maxidx} {incr n} {
+ puts $F [eval [list format {%010d %05d %1s }] $xrA($n)]
+ }
+% \end{tcl}
+% Having completed the cross-reference table, the second step is
+% to write the trailer.
+% \begin{tcl}
+ puts $F trailer
+ if {[info exists A(!$label)]} then {
+ lappend args /Root [format {%d %d R} [lindex $A(!$label) 0]\
+ [lindex $A(!$label) 1]]
+ } else {
+ lappend reportL "ERROR: The document does not have a catalog."\
+ "There is no indirect object with label: $label"
+ }
+ lappend args /Size [array size xrA]
+ puts $F [eval [list dict_obj] $args]
+ puts $F "startxref\n${startxref}\n%%EOF"
+% \end{tcl}
+% The final step is to close the file and compile the report.
+% \begin{tcl}
+ close $F
+ join $reportL \n
+}
+%</pkg>
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Hello World}
+%
+% The code below creates a PDF file matching the basic ``Hello World''
+% example \cite[Sec.~A.2]{PDFspec}.
+%
+% \begin{tcl}
+%<*example1>
+set F [pdf::rewrite_pdf hello.pdf]
+pdf::put_obj $F "The catalog" [pdf::dict_obj\
+%
+ /Type /Catalog\
+%
+ /Pages [pdf::obj_ref $F "The pages"]\
+%
+ /Outlines [pdf::obj_ref $F "The outlines"]]
+pdf::put_obj $F "The outlines"\
+ [pdf::dict_obj /Type /Outlines /Count [pdf::int_obj 0]]
+pdf::put_obj $F "The pages" [pdf::dict_obj\
+%
+ /Type /Pages\
+%
+ /Count [pdf::int_obj 1]\
+%
+ /Kids [pdf::array_obj [pdf::obj_ref $F "Page 1"]]]
+pdf::put_obj $F "Page 1" [pdf::dict_obj\
+%
+ /Type /Page\
+%
+ /Parent [pdf::obj_ref $F "The pages"]\
+%
+ /Resources [pdf::dict_obj\
+%
+ /Font [pdf::dict_obj /F1 [pdf::obj_ref $F "Helvetica"]]\
+%
+ /ProcSet [pdf::obj_ref $F "The procs"]]\
+%
+ /MediaBox [pdf::array_obj [pdf::int_obj 0] [pdf::int_obj 0]\
+ [pdf::int_obj 612] [pdf::int_obj 792]]\
+%
+ /Contents [pdf::obj_ref $F "Page 1 contents"]]
+pdf::begin_stream $F "Page 1 contents"
+puts $F {BT}
+puts $F {/F1 24 Tf}
+puts $F {100 100 Td (Hello World) Tj}
+puts $F {ET}
+pdf::end_stream $F
+pdf::put_obj $F "The procs" [pdf::array_obj /PDF /Text]
+pdf::put_obj $F "Helvetica" [pdf::dict_obj\
+ /Type /Font /Subtype /Type1\
+ /Name /F1 /BaseFont /Helvetica /Encoding /MacRomanEncoding]
+pdf::close_pdf $F "The catalog"
+%</example1>
+% \end{tcl}
+%
+%
+% \begin{thebibliography}{9}
+% \bibitem{PDFspec}
+% Adobe Systems Incorporated:
+% \textit{Portable Document Format Reference Manual},
+% version~1.3 (second edition), Addison--Wesley, 1999;
+% ISBN 0-201-61588-6;
+% \textsc{http:}/\slash \texttt{partners.adobe.com}\slash
+% \texttt{asn}\slash \texttt{developer}\slash \texttt{acrosdk}\slash
+% \texttt{docs}\slash \texttt{filefmtspecs}\slash
+% \texttt{PDFReference13.pdf}.
+% \emph{Note:} There is now a version~1.4 of this specification.
+% \end{thebibliography}
+%
+% \PrintIndex
+%
+%
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/tclldoc/examples/pdf.ins b/macros/latex/contrib/tclldoc/examples/pdf.ins
new file mode 100644
index 0000000000..00bea9f775
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/examples/pdf.ins
@@ -0,0 +1,55 @@
+% pdf.ins --- DOCSTRIP installation script for writepdf.
+\input docstrip
+
+% Redefine the \MetaPrefix; it should be something which starts a
+% until-end-of-line comment:
+\edef\MetaPrefix{\string#\string#}
+
+
+% Redefine the file preamble and postamble; this is necessary because
+% otherwise the old \metaPrefix is inserted at the beginning of these
+% lines.
+\preamble
+
+In other words:
+ ***************************************
+ * This Source is not the True Source. *
+ ***************************************
+The True Source is pdf.dtx in
+ http://ftp.ctan.org/tex-archive/macros/latex/contrib/tclldoc/examples
+
+It is preferred that you apply the distribution and modification
+conditions of the LaTeX Project Public License (LPPL) for this file,
+but you may alternatively choose to apply BSD/Tcl-style license
+conditions (either is OK). The latest version of the LPPL is in
+ http://www.latex-project.org/lppl.txt
+and version 1.2 or later is part of all distributions of LaTeX
+version 1999/12/01 or later.
+
+\endpreamble
+
+\postamble
+\endpostamble
+
+
+% Actually make the files:
+\generate{
+ \file{writepdf.tcl}{\from{pdf.dtx}{pkg}}
+ \file{hellopdf.tcl}{\from{pdf.dtx}{example1}}
+}
+
+
+\Msg{}
+\Msg{************************************************}
+\Msg{*}
+\Msg{* To complete installation,}
+\Msg{* place pdfwrite.tcl in a Tcl library directory}
+\Msg{* and run pkg_mkIndex to rebuild the package}
+\Msg{* index.}
+\Msg{*}
+\Msg{************************************************}
+\Msg{}
+
+
+\end
+
diff --git a/macros/latex/contrib/tclldoc/tclldoc.dtx b/macros/latex/contrib/tclldoc/tclldoc.dtx
new file mode 100644
index 0000000000..6106dcce36
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tclldoc.dtx
@@ -0,0 +1,4065 @@
+% \CheckSum{1849}
+%
+% \title{The \package{tclldoc} package and class}
+% \author{Lars Hellstr\"om^^A
+% \thanks{E-mail: \texttt{Lars.Hellstrom@math.umu.se}}
+% \emph{et al.}}
+% \date{2003/07/19}
+% \maketitle
+%
+% \iffalse
+%
+%<class|pkg>\NeedsTeXFormat{LaTeX2e}
+%<class>\ProvidesClass{tclldoc}
+%<compclass>\ProvidesClass{tcldoc}
+%<pkg>\ProvidesPackage{tclldoc}
+%<comppkg>\ProvidesPackage{tcldoc}
+%<class|pkg|compclass|comppkg> [2003/04/05 v2.40
+%<class|pkg> Tcl documentation
+%<compclass|comppkg> tclldoc compatibility
+%<class|compclass> class]
+%<pkg|comppkg> package]
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{amsmath}
+\IfFileExists{xdoc2.sty}{\usepackage[dolayout]{xdoc2}[2000/11/18]}{}
+
+\makeatletter
+\@ifpackageloaded{xdoc2}{}{%
+ \@ifpackagelater{doc}{2000/05/20}{}{%
+ \let\XD@fragile@meta=\meta
+ \def\meta{%
+ \ifx \protect\@typeset@protect
+ \expandafter\futurelet \expandafter\@let@token
+ \expandafter\XD@fragile@meta
+ \else
+ \noexpand\meta
+ \fi
+ }%
+ }%
+}
+\@ifundefined{option}{%
+ \newenvironment{option}[1]{%
+ \trivlist
+ \if@inlabel\else \macro@cnt=\z@ \fi
+ \item[]\ignorespaces
+ }{\endtrivlist}%
+}{}
+\@ifundefined{instance}{%
+ \newenvironment{instance}[2]{%
+ \trivlist
+ \if@inlabel\else \macro@cnt=\z@ \fi
+ \item[]\ignorespaces
+ }{\endtrivlist}%
+}{}
+\makeatother
+
+\DeclareRobustCommand\package[1]{\textsf{#1}}
+\DeclareRobustCommand\Tcl{T\kern-0.1em cl}
+\DeclareRobustCommand\word[1]{\mbox{$\{$\itshape#1\/$\}$}}
+
+\makeatletter
+\newcommand{\swtpc}{%
+ \sbox\z@{ }%
+ \expandafter\makebox \expandafter[\the\wd\z@]%
+ {\textperiodcentered}%
+}
+\makeatother
+
+\providecommand*\describeoption[1]{\marginpar{\texttt{#1} option}}
+\providecommand*\PrintChar[1]{\char#1\relax}
+\providecommand*{\DoNotIndexHarmless}[1]{}
+\providecommand*{\DoNotIndexBy}[1]{}
+\DoNotIndexBy{@}
+\DoNotIndexBy{@@}
+\DoNotIndexBy{TD@}
+\newenvironment{isyntax}{%
+ \list{}{%
+ \setlength\parsep{0pt plus 1pt}%
+ \setlength\listparindent{-1em}%
+ \setlength\itemindent{\listparindent}%
+ \addtolength\leftmargin{1em}%
+ }%
+ \item\relax \rightskip=1.0\rightskip plus 5cm
+}{\endlist}
+
+\setcounter{IndexColumns}{2}
+\hfuzz=10pt
+\expandafter\def \expandafter\GlossaryParms \expandafter{%
+ \GlossaryParms \hbadness=10000
+}
+
+\CodelineIndex
+\EnableCrossrefs
+\RecordChanges
+
+\begin{document}
+\DocInput{tclldoc.dtx}
+\PrintChanges
+\PrintIndex
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \begin{abstract}
+% The \package{tclldoc} package defines a couple of environments and
+% macros for documenting \Tcl\ source code in \texttt{.dtx}-style
+% documented source files, much like what the \package{doc}
+% package~\cite{doc} does for \TeX\ source code. The \package{tclldoc}
+% class is analogous to the \package{ltxdoc} document
+% class~\cite{ltxdoc}---it loads the package to gain the basic
+% functionality and changes some layout parameters to values that
+% are better suited for documented source than those set by the
+% standard \package{article} document class.
+%
+% The \package{tclldoc} package builds on the \package{doc},
+% \package{xdoc}~\cite{xdoc}, and \package{docindex}~\cite{docindex}
+% packages.
+%
+% Note: The \package{tclldoc} package and class used to be called
+% \package{tcldoc}, but it turned out that there already existed a
+% Perl~(!!)\ script \Tcl Doc that has a similar function. Therefore I
+% added an extra `\textsf{l}'---which stands for both \LaTeX\ and
+% Literate---to avoid confusing the community of \Tcl\ programmers.
+% For compatibility, a package and a class named \package{tcldoc} are
+% installed with \package{tclldoc}, but they shouldn't be used for
+% new documents.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \DoNotIndex{\advance,\begingroup,\bgroup,\big,\Big,\bigg,\Bigg,\box}
+% \DoNotIndex{\catcode,\char,\chardef,\cleaders,\color@begingroup}
+% \DoNotIndex{\color@endgroup,\copy,\csname,\DeclareOption}
+% \DoNotIndex{\DeclareRobustCommand,\DeclareTextCommand}
+% \DoNotIndex{\DeclareTextSymbol,\def,\discretionary,\divide,\do}
+% \DoNotIndex{\edef,\egroup,\else,\@empty,\endcsname,\endgroup}
+% \DoNotIndex{\expandafter,\fi,\@firstoftwo,\font,\fontdimen}
+% \DoNotIndex{\futurelet,\gdef,\global,\@gobble,\hb@xt@,\hbox}
+% \DoNotIndex{\hfill,\if,\ifcase,\ifcat,\ifmmode,\ifnum,\ifvbox}
+% \DoNotIndex{\ifvmode,\ifvoid,\ifx,\ignorespaces,\immediate,\indent}
+% \DoNotIndex{\input,\@@input,\InputIfFileExists,\IfFileExists}
+% \DoNotIndex{\item,\kern,\language,\lastbox,\lastpenalty,\lastskip}
+% \DoNotIndex{\lccode,\leavevmode,\let,\llap,\LoadClass,\lowercase}
+% \DoNotIndex{\m@ne,\m@th,\@makeother,\mathord,\mkern,\multiply}
+% \DoNotIndex{\@ne,\newbox,\newcommand,\newcount,\NewDescribeCommand}
+% \DoNotIndex{\newenvironment,\newif,\NewMacroEnvironment,\nfss@text}
+% \DoNotIndex{\noexpand,\normalfont,\null,\number,\or,\p@,\@@par}
+% \DoNotIndex{\parshape,\PassOptionsToClass,\PassOptionsToPackage}
+% \DoNotIndex{\penalty,\@plus,\predisplaypenalty,\prevdepth,\prevgraf}
+% \DoNotIndex{\ProcessOptions,\protect,\protected@edef}
+% \DoNotIndex{\providecommand,\ProvideTextCommandDefault,\relax}
+% \DoNotIndex{\RequirePackage,\RequirePackageWithOptions,\rightarrow}
+% \DoNotIndex{\sbox,\selectfont,\setbox,\skewchar,\space,\string}
+% \DoNotIndex{\TextSymbolUnavailable,\texttt,\the,\tracingparagraphs}
+% \DoNotIndex{\ttfamily,\tw@,\typeout,\unhbox,\unpenalty,\unskip}
+% \DoNotIndex{\unrestored@protected@xdef,\unskip,\unvbox,\vadjust}
+% \DoNotIndex{\vbox,\vert,\vrule,\vskip,\wd,\write,\xdef,\z@,\z@skip}
+%
+% \section{Introduction}
+% \label{Sec:Introduction}
+%
+% This introduction is meant to be comprehensible even for readers
+% unfamiliar with writing \texttt{.dtx} files and using the \package{doc}
+% package. Readers who are experienced with this will probably want to
+% skip right to the next section.
+%
+% A \texttt{.dtx} file has a dual nature. On one hand it is a container
+% for some lines of code---it could be a program, a macro package, a
+% configuration file for some program, merely a part of any of the
+% aforementioned, or even arbitrary combinations of the above---and on
+% the other hand it is a \LaTeX\ document which documents this code. One
+% important advantage with this arrangement is that one can keep all the
+% pieces of a project that has to do with a specific task at one place;
+% experience has shown that this greatly furthers really keeping all
+% parts of a project up to date with each other.
+%
+% Slightly simplified, one can say that a \texttt{.dtx} file contains
+% three kinds of lines. A \emph{code line} is a line that doesn't begin
+% with a `|%|' character; such lines can be extracted (copied) using the
+% \package{docstrip} program~\cite{docstrip}. A \emph{guard line} is a
+% line that begins with the two characters `|%<|'; guards are used to
+% structure the set of code lines so that \package{docstrip} can extract
+% different code lines to different generated files. A \emph{comment
+% line}, finally, is a line that begins with a `|%|' character that is
+% not immediately followed by a `|<|' character. The comment lines are
+% ignored by \package{docstrip}, but are part of (and usually make up
+% most of) the \LaTeX\ document in the \texttt{.dtx} file.
+%
+%
+% \subsection{Special conventions and basic features in a \texttt{.dtx}
+% \LaTeX\ document}
+%
+% An important difference between normal \LaTeX\ documents and
+% \texttt{.dtx} \LaTeX\ documents is that the percent character `|%|'
+% doesn't start a comment in the latter; in fact it is usually ignored.
+% This allows \LaTeX\ to see and typeset the text in the comment lines
+% of a \texttt{.dtx} file. Hence if one wants to include the sentence
+% ``Your hovercraft is full of eels!'', which in a normal \LaTeX\
+% document could have been written as the line\iffalse
+%<*example>
+% \fi
+%\begin{verbatim}
+%Your hovercraft is full of eels!
+%\end{verbatim}
+% one would instead write the line as
+%\begin{verbatim}
+%% Your hovercraft is full of eels!
+%\end{verbatim}
+% in a \texttt{.dtx} document. The space after the |%| is not
+% necessary, but most \texttt{.dtx} documents you see include
+% it---probably because the ``comment out \TeX\ code'' action of most
+% text editors consists of inserting a percent \emph{and} a space at
+% the beginning of each line.
+%
+% The code lines present the opposite problem, as they usually
+% shouldn't be treated as normal \LaTeX\ code although the normal \LaTeX\
+% reading conventions would make them the entire document. The usual way
+% around this is to surround each group of code lines with two comment
+% lines that begin and end an environment in which the code lines get
+% typeset verbatim. The \package{tclldoc} package provides the \texttt{tcl}
+% environment for this purpose, so the code lines
+%\begin{verbatim}
+%proc factorial {n} {
+% set result 1
+% for {set i 1} {$i<=$n} {incr i} {
+% set result [expr {$result * $i}]
+% }
+% return $result
+%}
+%\end{verbatim}
+% could be included in a \texttt{.dtx} document as the lines
+%\begin{verbatim}
+%% \begin{tcl}
+%proc factorial {n} {
+% set result 1
+% for {set i 1} {$i<=$n} {incr i} {
+% set result [expr {$result * $i}]
+% }
+% return $result
+%}
+%% \end{tcl}
+%\end{verbatim}
+% When typeset, this will look as
+% \begin{macrocode}
+proc factorial {n} {
+ set result 1
+ for {set i 1} {$i<=$n} {incr i} {
+ set result [expr {$result * $i}]
+ }
+ return $result
+}
+% \end{macrocode}
+% The tiny numbers at the beginning of each line enumerate the code lines.
+% Index references to code usually specify such code line numbers, but
+% the enumeration can be switched off.
+%
+% In mathematical papers, the statements of e.g.\ theorems are usually
+% made inside a \texttt{theorem} (or whatever) environment which
+% provides certain text formatting, a heading, and a position in the
+% document that can be referenced from other parts of it. In \texttt{.dtx}
+% documents one usually does something similar for each named piece of
+% code: macros, environments, templates, etc. In particular, the
+% \package{tclldoc} package provides two environments \texttt{proc} (for
+% procedures) and \texttt{variable} (for variables).
+% Figure~\ref{Fig:procex} contains an example of how \texttt{proc}
+% might be used in describing a procedure for computing the greatest
+% common divisor of two integers.
+%
+% \begin{figure}
+%
+% \begin{trivlist}
+% \item[]\leavevmode\llap{\texttt{gcd} (proc)\kern\marginparsep}^^A
+% The |gcd| procedure takes two arguments $a$ and $b$ which must be
+% integers and returns their greatest common divisor $\gcd(a,b)$,
+% which is computed using Euclid's algorithm. As a special case,
+% $\gcd(0,0)$ is considered to be $0$, so formally |gcd $a $b|
+% computes $\lvert a \rvert \wedge \lvert b \rvert$, where $\wedge$
+% denotes the meet operation in the divisor lattice of non-negative
+% integers.
+% \begin{macrocode}
+proc gcd {a b} {
+ set a [expr {abs($a)}]
+ set b [expr {abs($b)}]
+ while {$b>0} {
+ set r [expr {$a%$b}]
+ set a $b
+ set b $r
+ }
+ return $a
+}
+% \end{macrocode}
+% \end{trivlist}
+%
+% \begin{center}
+% (a) A typeset procedure with description
+% \end{center}
+%
+%\begin{verbatim}
+%% \begin{proc}{gcd}
+%% The |gcd| procedure takes two arguments $a$ and $b$ which must be
+%% integers and returns their greatest common divisor $\gcd(a,b)$,
+%% which is computed using Euclid's algorithm. As a special case,
+%% $\gcd(0,0)$ is considered to be $0$, so formally |gcd $a $b|
+%% computes $\lvert a \rvert \wedge \lvert b \rvert$, where $\wedge$
+%% denotes the meet operation in the divisor lattice of non-negative
+%% integers.
+%% \begin{tcl}
+%proc gcd {a b} {
+% set a [expr {abs($a)}]
+% set b [expr {abs($b)}]
+% while {$b>0} {
+% set r [expr {$a%$b}]
+% set a $b
+% set b $r
+% }
+% return $a
+%}
+%% \end{tcl}
+%% \end{proc}
+%\end{verbatim}
+%
+% \begin{center}
+% (b) The code for the example in (a)
+% \end{center}
+%
+% \caption{An example of the \texttt{proc} environment}
+% \label{Fig:procex}
+% \end{figure}
+%
+% What does the \texttt{proc} environment do more precisely? First
+% there's the marginal heading which can be seen in Figure~^^A
+% \ref{Fig:procex}. Such headings make it easier to find the procedure in
+% the typeset form of the document. Then the \texttt{proc} environment
+% makes an index entry which tells you where the procedure is defined,
+% and finally it stores the procedure name in a variable so that
+% subsequent |\changes|\footnote{The \cs{changes} command is defined by
+% the \package{doc} package~\cite{doc}. It is used for adding entries
+% to a global list of changes for code in the \texttt{.dtx} document.}
+% commands know to what the change that they are recording was made.
+%
+% The \texttt{variable} environment does the same things except that it
+% writes ``(var.)'' rather than ``(proc)''. This environment wasn't used
+% for describing the three local variables |a|, |b|, and |r| in the
+% example; this is since there is no point in referring to these
+% variables from elsewhere in the program. Instead the \texttt{variable}
+% environment is primarily meant for global variables (although it could
+% also be useful for local variables that are meant to be accessed using
+% |upvar| or |uplevel|), and as such it can often be of great help, since
+% the description of a global variable can otherwise be hard to find,
+% especially with languages like \Tcl\ where variables don't have to be
+% declared and thus have no natural ``home'' in the code.
+%
+% Another noteworthy feature in the example is the use of vertical
+% bar `\verb+|+' characters to delimit short pieces of verbatim \Tcl\
+% code in the comment lines. It is often necessary for the explanation
+% to include short examples of code in the documentation, and the
+% standard \LaTeX\ |\verb| command is exactly what one would need for
+% this. As such code sections are rather frequent however, it has become
+% the custom to use a single character for both starting and ending such
+% a piece of code. The \package{tclldoc} document class defines \verb+|+
+% as a shorthand for \verb+\tclverb|+, where |\tclverb| is a variant of
+% |\verb| which has been designed specifically for \Tcl\ code.
+%
+% The above description was meant to give a basic understanding of how
+% \Tcl\ code and documentation thereof can be mixed in a \texttt{.dtx}
+% file, it neither explains all the environments and commands that
+% the \package{tclldoc} package provides, nor mentions all the
+% features of the environments that were described. That information can
+% instead be found in Section~\ref{Sec:Manual} of this paper. It should
+% also be mentioned that the \package{doc} package~\cite{doc} defines
+% several commands and environments that may be of use for describing
+% code, and it is well worth getting acquainted with the features of
+% that package as well (although parts of its documentation has become
+% rather archaic).
+%
+%
+% \subsection{Guards and \package{docstrip} installation scripts}
+%
+% The central command in a \package{docstrip} installation script is
+% |\generate|, since this is the command which actually causes code to
+% be extracted. |\generate|'s syntax is
+% \begin{quote}
+% |\generate|\marg{files}
+% \end{quote}
+% where \meta{files} consists of one or several |\file| commands, each
+% of which has the syntax
+% \begin{quote}
+% |\file|\marg{output}\marg{sources}
+% \end{quote}
+% where \meta{output} is a filename and \meta{sources} consists of one
+% or several |\from| commands, each of which has the syntax
+% \begin{quote}
+% |\from|\marg{input}\marg{options}
+% \end{quote}
+% where, finally, \meta{input} is a filename and \meta{options} is a
+% comma-separated list of alphanumerical strings. Thus a |\generate|
+% command might look like
+%\begin{verbatim}
+% \generate{\file{p1.sty}{\from{s1.dtx}{foo,bar}}
+% \file{p2.sty}{\from{s2.dtx}{baz}
+% \from{s3.dtx}{baz}}
+% \file{p3.sty}{\from{s1.dtx}{zip}
+% \from{s2.dtx}{zap}}
+% }
+%\end{verbatim}
+% The meaning of this command is
+% \begin{quote}
+% Generate the three files \texttt{p1.sty}, \texttt{p2.sty}, and
+% \texttt{p3.sty}. Extract the code for \texttt{p1.sty} from
+% \texttt{s1.dtx} with options \texttt{foo} and \texttt{bar}, extract
+% the code for \texttt{p2.sty} from \texttt{s2.dtx} with option
+% \texttt{baz} and \texttt{s3.dtx} (the code from \texttt{s2.dtx}
+% will be put before the code from \texttt{s3.dtx}) with option
+% \texttt{baz}, and finally extract the code for \texttt{p3.sty} from
+% \texttt{s1.dtx} with option \texttt{zip} and \texttt{s2.dtx} with
+% option \texttt{zap}.
+% \end{quote}
+% The \emph{options} are used to control which parts of the source files
+% should be extracted to which generated file. A source file can
+% contain a number of \emph{modules}, and at the beginning of each
+% module \package{docstrip} decides, for each output file separately,
+% whether the code lines in that module should be extracted to the
+% output file. The beginning of a module is marked by a guard line which
+% has the syntax
+% \begin{quote}
+% |%<*|\meta{expression}|>|
+% \end{quote}
+% and the end by a corresponding
+% \begin{quote}
+% |%</|\meta{expression}|>|
+% \end{quote}
+% guard line. In their simplest form, the \meta{expression}s are names
+% of options, and in that case the code lines in the module are only
+% extracted if that option appears in the \meta{options} for that
+% combination of input file and output file. The \meta{expression}s can
+% however be arbitrarily complicated boolean expressions;
+% see~\cite{docstrip} for more information.
+% Modules may nest inside each other, and in that case the code lines in
+% an inner module can only be included if all surrounding modules are
+% being included. It is checked that matching |*| and |/| guard lines
+% contain the same (as strings) \meta{expression}, and case is
+% significant in the names of options.
+%
+% One application of modules which has already been mentioned is to
+% bundle code for several different generated files in the same
+% \texttt{.dtx} file---one example of this is the file
+% \texttt{doc.dtx} (part of the \LaTeX\ base distribution) which
+% contains both the \package{doc} package (\texttt{doc.sty}), the
+% \package{shortvrb} package (\texttt{shortvrb.sty}), and two
+% \package{makeindex} style files (\texttt{gglo.ist} and
+% \texttt{gind.ist}). Another application is to keep variant sections
+% of code---such as special code for debugging or gathering
+% statistics---in the \texttt{.dtx} source file for a program without
+% thereby making it a part of the normal form of that program. It is
+% quite possible to use \package{docstrip} as a simple pre-processor
+% for languages whose compiler\slash interpreter has not got one built
+% in.
+%
+% There are many other commands available in a \package{docstrip}
+% installation script beside those listed above, but those are well
+% described in the \package{docstrip} manual~\cite{docstrip} and need
+% little attention here. Instead I'm going to finish this subsection
+% with a quick guide to the particular difficulties one faces when using
+% \package{docstrip} to extract \Tcl\ code, and how to overcome them.
+%
+% The main problem is that \package{docstrip} insert a few comment lines
+% at the beginning and end of each file it generates. This is a good
+% thing, because a file consisting entirely of extracted code lines
+% would normally be completely void of commentary and quite
+% unintelligible for the casual user. These few comment lines explain
+% that the file was generated by \package{docstrip} from other files
+% (which contain the documentation of the code), lists those files,
+% and normally also contains a copyright (or more commonly some kind of
+% copyleft) notice. The problem lies in that comments look different in
+% different languages, and as the default is to write \TeX\ style
+% comments, one must tell \package{docstrip} to write \Tcl\ style
+% comments. This can be done through the command
+%\begin{verbatim}
+%\edef\MetaPrefix{\string#}
+%\end{verbatim}
+% which tells \package{docstrip} to begin each inserted comment line
+% with the character `|#|'.
+%
+% The comment lines inserted at the beginning of a generated file are
+% called the \emph{preamble} and those at the end the \emph{postamble}.
+% To set the preamble, one writes
+% \begin{trivlist}
+% \item |\preamble|\\
+% \meta{preamble lines}\\
+% |\endpreamble|
+% \end{trivlist}
+% and correspondingly to set the postamble
+% \begin{trivlist}
+% \item |\postamble|\\
+% \meta{postamble lines}\\
+% |\endpostamble|
+% \end{trivlist}
+% The \meta{preamble lines} and \meta{postamble lines} can be any number
+% of lines (including zero). Unlike the text in source files, the text in
+% these preamble and postamble lines is not read verbatim, so things in
+% these lines which have special meaning to \TeX\ (such as control
+% sequences) will be treated as such; the only exception is that spaces
+% and newlines are preserved (instead of concatenated to single spaces
+% as they normally would). It is important that the preamble and
+% postamble \emph{are} set after |\MetaPrefix| is changed, because each
+% line specified between |\preamble| and |\endpreamble| or |\postamble|
+% and |\endpostamble| respectively will be prefixed by the current value
+% of |\MetaPrefix|.
+%
+% Finally, some programs (such as the UNIX core) assign special meaning
+% to the first line of a file, so one might want to control what gets
+% put there. Merely using |\preamble| doesn't achieve this, because the
+% \meta{preamble lines} specified that way are put after the lines
+% saying ``this is a generated file \textellipsis''. You can however
+% add things to the preamble by explicitly setting the macro
+% |\defaultpreamble|, which is where \package{docstrip} stores the
+% preamble. To make the first line a comment which simply contains the
+% text `|-*-Tcl-*-|', you could give the command
+%\begin{verbatim}
+%\edef\defaultpreamble{\MetaPrefix\space -*-Tcl-*-^^J\defaultpreamble}
+%\end{verbatim}
+% Similarly to begin the file by the three standard lines
+%\begin{verbatim}
+%#! /bin/sh
+%#\
+%exec tclsh "$0" ${1+"$@"}
+%\end{verbatim}
+% (for an explanation see~\cite{execMagic})---which on UNIX allow the file
+% to function both as a \Tcl\ script and a shell script which terminates
+% the shell and runs \texttt{tclsh} on the script instead---you can use
+% the command
+%\begin{verbatim}
+%\edef\defaultpreamble{%
+% \MetaPrefix! /bin/sh^^J%
+% \MetaPrefix\string\^^J%
+% exec tclsh "$0" ${1+"$@"}^^J%
+% \defaultpreamble
+%}
+%\end{verbatim}
+% The full explanation of these commands is however far beyond this
+% introduction.\footnote{Those who want to fully understand them should
+% read \emph{The \TeX book}~\cite{TeXbook}, in particular Chapter~8.}
+%
+% In summary, a \package{docstrip} installation script for extracting a
+% file \texttt{foo.tcl} from \texttt{foo.dtx}, using \Tcl\ style
+% comments, inserting a BSD-style license notice in the preamble, and
+% beginning with the line |# -*-Tcl-*-| could look as follows:
+%\begin{verbatim}
+%\input docstrip.tex
+%
+%\edef\MetaPrefix{\string#}
+%
+%\preamble
+%
+%Copyright (c) <YEAR>, <OWNER>
+%All rights reserved.
+%
+%Redistribution and use in source and binary forms, with or without
+%modification, are permitted provided that the following conditions
+%are met:
+%* Redistributions of source code must retain the above copyright
+%notice, this list of conditions and the following disclaimer.
+%* Redistributions in binary form must reproduce the above
+%copyright notice, this list of conditions and the following
+%disclaimer in the documentation and/or other materials provided
+%with the distribution.
+%
+%THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+%"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+%LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+%FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+%COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+%INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+%BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+%LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+%CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+%LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+%ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+%POSSIBILITY OF SUCH DAMAGE.
+%
+%\endpreamble
+%
+%\postamble
+%\endpostamble
+%
+%\edef\defaultpreamble{\MetaPrefix\space -*-Tcl-*-^^J\defaultpreamble}
+%
+%\generate{\file{foo.tcl}{\from{foo.dtx}{bar}}}
+%
+%\end
+%\end{verbatim}
+%
+% The generated file \texttt{foo.tcl} will contain
+%\begin{verbatim}
+%# -*-Tcl-*-
+%#
+%# This is file `foo.tcl',
+%# generated with the docstrip utility.
+%#
+%# The original source files were:
+%#
+%# foo.dtx (with options: `bar')
+%#
+%# Copyright (c) <YEAR>, <OWNER>
+%# All rights reserved.
+%#
+%# Redistribution and use in source and binary forms, with or without
+%# modification, are permitted provided that the following conditions
+%# are met:
+%# * Redistributions of source code must retain the above copyright
+%# notice, this list of conditions and the following disclaimer.
+%# * Redistributions in binary form must reproduce the above
+%# copyright notice, this list of conditions and the following
+%# disclaimer in the documentation and/or other materials provided
+%# with the distribution.
+%#
+%# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+%# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+%# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+%# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+%# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+%# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+%# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+%# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+%# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+%# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+%# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+%# POSSIBILITY OF SUCH DAMAGE.
+%#
+%\end{verbatim}
+% \meta{lines extracted from \texttt{foo.dtx}}
+%\begin{verbatim}
+%#
+%#
+%# End of file `foo.tcl'.
+%\end{verbatim}
+%
+%
+%
+% \subsection{The structure of the \LaTeX\ document}
+%
+% All this has been about the local appearance of a \texttt{.dtx} file,
+% but what about the overall structure? There are several points to
+% raise about that as well.
+%
+% The first is that \LaTeX\ to begin with treat \texttt{.dtx} documents
+% just like any other document---a `|%|' starts a comment and only lines
+% \emph{not} beginning with a `|%|' contain anything that \LaTeX\ can
+% see. Somehow \LaTeX\ must be instructed to start applying the special
+% reading rules that were described above. This is the job of the
+% so-called \emph{driver}, which (for a file \texttt{myfile.dtx}) in its
+% simplest form can look like
+%\begin{verbatim}
+%\documentclass{tclldoc}
+%\begin{document}
+%\DocInput{myfile.dtx}
+%\end{document}
+%\end{verbatim}
+% The important command here is |\DocInput|, because that is what tells
+% \LaTeX\ to apply the special \texttt{.dtx} reading rules. More
+% precisely it means ``Start ignoring `|%|' characters in the text you
+% read, input the file \texttt{myfile.dtx}, and when you're done return
+% to treating `|%|' characters as before.''
+%
+% The driver is usually put in the very first stretch of code lines in
+% the \texttt{.dtx} file. This means that \LaTeX, when ordered to typeset
+% the \texttt{.dtx} file, will start to read along, possibly ignoring
+% hundreds of lines beginning with `|%|' because they are comments. Then
+% it encounters the driver, and after the |\documentclass| and
+% |\begin{document}| commands it executes the |\DocInput|. This will
+% cause it to not ignore lines beginning with `|%|', so when it starts
+% reading the file again it will see all the lines it skipped the first
+% time through. The file will be read to end, after which \LaTeX\
+% returns to the command after the |\DocInput|. As that command happens
+% to be |\end{document}|, it finishes the typeset document and stops.
+% This stop prevents it from seeing and interpreting as \LaTeX\ commands
+% the remaining code lines in the file.
+%
+% The second time through the driver shouldn't be interpreted as
+% \LaTeX\ commands, since for example the |\documentclass| command may
+% only be used once in a \LaTeX\ document. One way of achieving this is
+% to put an |\iffalse| command right before the driver and a |\fi|
+% command right after it. This says to \LaTeX\ that the driver code is
+% conditional material, and since the condition evaluates to false
+% (|\iffalse| always evaluates to false), this conditional material
+% should be skipped. Thus the first few lines of \texttt{myfile.dtx}
+% typically might be
+%\begin{verbatim}
+%% \iffalse
+%%<*driver>
+%\documentclass{tclldoc}
+%\begin{document}
+%\DocInput{myfile.dtx}
+%\end{document}
+%%</driver>
+%% \fi
+%\end{verbatim}
+% The \texttt{driver} guard lines are there to stop \package{docstrip}
+% from including the driver code in the generated files.
+%
+% After the driver comes the actual \LaTeX\ document. The document
+% usually consists of two parts, where the first part is a manual for
+% the \emph{usage} of the code defined in the file, and the second part
+% contains the actual \emph{implementation} (documented code). The idea
+% is that most people are (at least the first time) quite content with
+% learning how to use something, so one should make it simple for them
+% to find that information.\footnote{One needn't take this as an absolute
+% rule---I for one haven't written all my packages that way---but
+% structuring the document like this generally makes it more accessible.}
+% To further this approach one puts the command |\StopEventually| at the
+% start of the implementation part and the command |\Finale| at the end
+% of it. Normally |\StopEventually| doesn't make itself felt, but if one
+% previously has given the command |\OnlyDescription| then rest of the
+% file will not be read; this can be used to produce a ``manual only''
+% version of the documentation. |\StopEventually| takes one argument and
+% the code in this argument is executed at the |\Finale| (if the
+% implementation part is being included) or immediately (if the
+% implementation part isn't being included). Thus this argument is the
+% place to put things that should appear at the very end of the
+% document.
+%
+% The \texttt{tcl}, \texttt{proc}, and \texttt{variable} environments
+% described above all typically appear in the implementation part of the
+% document.
+%
+%
+% \section{Usage of commands and environments}
+% \label{Sec:Manual}
+%
+%
+% \subsection{The actual source code}
+%
+% The \DescribeEnv{tcl}\texttt{tcl} environment is used for wrapping up
+% a group of code lines which contain \Tcl\ code. Lines inside this
+% environment which begin with a percent character are called
+% \emph{command} lines and can contain \LaTeX\ commands which get
+% executed, whereas lines that do not begin with a percent character are
+% called \emph{normal} lines and get typeset verbatim (or nearly
+% verbatim). Lines that begin with |%<| (\package{docstrip} guard lines)
+% do however constitute a special case, as the guard expression will get
+% typeset as in \package{doc}'s \texttt{macrocode} environment and the
+% remainder of the line will get processed in command mode if it is a
+% |*| or |/| guard, but in normal mode if the guard line was of any other
+% type.
+%
+% The \texttt{tcl} environment uses the same general formatting
+% parameters as \package{doc}'s \texttt{macrocode} environment. In
+% particular this means that the text on a normal line is typeset in
+% |\MacroFont| (by default the same thing as \cs{normalfont}\penalty0
+% \cs{ttfamily}\penalty0\cs{small}) or |\AltMacroFont| (by default the same
+% thing as \cs{normalfont}\penalty0\cs{ttfamily}\penalty0\cs{itshape}^^A
+% \penalty0\cs{small}) depending on the current \package{docstrip} module
+% nesting level. The \package{tclldoc} class sets the
+% \texttt{StandardModuleDepth} counter to 1, which means that the
+% |\AltMacroFont| is used when the modules are nested two levels deep or
+% more.
+%
+% If a normal line is too long to fit on one line then the \texttt{tcl}
+% environment will try to break it. Legal breakpoints are spaces which
+% could be replaced by a backslash and a newline without changing the
+% meaning of the command; thus most spaces are legal breakpoints. When a
+% line is broken at a space like this, the space is replaced by a
+% backslash so that the line is still ``syntactically correct''. The
+% opposite happens to lines which actually end with an escaped newline;
+% such lines are concatenated with the following line and are treated as
+% one long line. This is so that a sequence of breakpoints can be chosen
+% which is optimal for the actual line width of the document (as opposed
+% to the line width used in the text file, which can be something quite
+% different). For example
+%\begin{verbatim}
+%% \begin{tcl}
+%lsearch -exact\
+% [concat $a [lrange $b $first end] c d e f]\
+% [lindex $g $h]
+%% \end{tcl}
+%\end{verbatim}
+% could be typeset as any of the code examples in
+% Figure~\ref{Fig:Radbrytning}, depending on how wide a line is.
+% \begin{figure}
+% \begin{center}
+% \small
+% \(\left\lvert
+% \begin{minipage}{350pt}
+% \begin{flushleft}
+% |lsearch -exact [concat $a [lrange $b $first end] c d e f]|^^A
+% | [lindex $g $h]|
+% \end{flushleft}
+% \end{minipage}
+% \right\rvert\)
+%
+% \smallskip
+%
+% \(\left\lvert
+% \begin{minipage}{298pt}
+% \begin{flushright}
+% \noindent |lsearch -exact [concat $a [lrange $b $first|^^A
+% | end] c d e f]|\textbackslash\hfill\vadjust{}\\
+% |[lindex $g $h]|
+% \end{flushright}
+% \end{minipage}
+% \right\rvert\)
+%
+% \smallskip
+%
+% \(\left\lvert
+% \begin{minipage}{241pt}
+% \begin{flushright}
+% \noindent |lsearch -exact|\textbackslash\hfill\vadjust{}\\
+% |[concat $a [lrange $b $first end] c d e f]|\textbackslash\\
+% |[lindex $g $h]|
+% \end{flushright}
+% \end{minipage}
+% \right\rvert\)
+%
+% \smallskip
+%
+% \(\left\lvert
+% \begin{minipage}{184pt}
+% \begin{flushright}
+% \noindent |lsearch -exact [concat $a|\textbackslash\hfill
+% \vadjust{}\\
+% |[lrange $b $first end] c d e f]|\textbackslash\\
+% |[lindex $g $h]|
+% \end{flushright}
+% \end{minipage}
+% \right\rvert\)
+% \end{center}
+%
+% \caption{The same \Tcl\ code, set in different linewidths}
+% \label{Fig:Radbrytning}
+% \end{figure}
+% The environment tries to put the linebreaks at the lowest possible
+% nesting (of braces and brackets) level; I believe this gives the best
+% readability.\footnote{When I first started programming in \Tcl\ I
+% used a completely different method for breaking long lines in the
+% code---I mainly implemented the current method because it was
+% simple to program---but I was quite surprised by how readable it made
+% the code.} There is however a way to override this automatic choice
+% of breakpoints: if a normal line which ends with an escaped newline is
+% followed by a command line (even a command line that doesn't contain
+% any commands) then it will not be concatenated with the next normal
+% line.
+%
+% There are a couple of restrictions on the code in command lines. First
+% of all it is not allowed to start a new paragraph (there will be an
+% error message). Secondly a command may not be broken across several
+% lines---all the arguments must appear on the same line as the
+% control sequence. Thirdly some characters have other catcodes than
+% in normal \LaTeX, so it is not certain that all commands work. Some
+% commands that do work and may be useful are:
+% \begin{itemize}
+% \item Vertical space commands (|\smallskip|, |\medskip|, etc.)
+% The command line `|% \medskip|' is more to type than a blank
+% normal line, but it looks slightly better.
+% \item Indexing commands (|\index|, |\IndexEntry|,\footnote{This
+% command is defined by the \package{xdoc} package~\cite{xdoc}.}
+% etc.)
+% \item The \cs{TclInput} and |\settabsize| commands (see below).
+% \end{itemize}
+% And of course the |\end{tcl}| command works in a command line, since
+% that is how one ends a \texttt{tcl} environment.
+%
+% Besides the \texttt{tcl} environment there is also a
+% \DescribeEnv{tcl*}\texttt{tcl*} environment which is different from
+% \texttt{tcl} only in that spaces and tabs are typeset as special
+% visible space `\textvisiblespace' and visible tab
+% `\makebox[6\fontdimen2\font]{\( - \mkern-7mu
+% \cleaders\hbox{$\mkern-2mu - \mkern-2mu$}\hfill \mkern-7mu
+% \mathord\rightarrow \mkern-1mu \vrule \mkern1mu\)}' characters. This
+% can be useful for pieces of code where the exact number of spaces in
+% a sequence is significant, such as code for writing tables that align.
+%
+% For shorter pieces of \Tcl\ code, e.g.\ examples, there's the
+% \DescribeMacro{\tclverb}|\tclverb| command. |\tclverb| is very similar
+% to the standard \LaTeX\ command |\verb|, but there are two differences.
+% The first is that text typeset by |\tclverb| can contain breakpoints
+% at whitespace; these behave just as in the \texttt{tcl} environment.
+% The second is that the verbatim text that follows |\tclverb| may contain
+% newlines, provided that these newlines are escaped by a backslash. Like
+% a \Tcl\ interpreter, |\tclverb| ignores whitespace following an escaped
+% newline. Unlike a \Tcl\ interpreter, |\tclverb| also ignores one percent
+% character before the ignored whitespace, if it is the first character
+% on the following line. Thus
+%\begin{verbatim}
+%% \tclverb|append a $b| is much more efficient than \tclverb|set a\
+%% $a$b| if \tclverb|$a| is long.
+%\end{verbatim}
+% is perfectly legal, and the escaped newline between |a| and |$a$b| is
+% treated just like the space between |set| and |a|. Like |\verb|, the
+% |\tclverb| command has a starred form \DescribeMacro{\tclverb*}^^A
+% |\tclverb*| which also typesets spaces and tabs as visible characters.
+%
+%
+% The \DescribeMacro{\MakeShortTclverb}|\MakeShortTclverb| command works
+% just like the \package{doc}\slash\package{shortvrb} command
+% |\MakeShortVerb|, except that it makes the active character a shorthand
+% reference for |\tclverb|\textellipsis\ instead of |\verb|\textellipsis.
+% Use |\DeleteShortVerb| to undo the effect of a |\MakeShortTclverb|. The
+% \package{tclldoc} class executes the command
+% \begin{quote}
+% \verb"\MakeShortTclverb{\|}"
+% \end{quote}
+% which makes \verb"|" a shorthand for \verb"\tclverb|".
+%
+% Since there is no universally accepted standard for the size
+% (equivalent number of spaces) of a tab, there is a command
+% \DescribeMacro{\settabsize}|\settabsize| for changing this.
+% |\settabsize| takes as its only argument the new tab size, which must
+% be an integer in the range 2--255. The default value is 8.
+% |\settabsize| makes a local assignment to the tab size. The tab size
+% can be changed inside a \texttt{tcl} (or \texttt{tcl*}) environment.
+%
+% There is also a command \DescribeMacro{\TclInput}|\TclInput| which
+% is used for typesetting ``raw'' (not in \texttt{.dtx} format) \Tcl\ code
+% files. |\TclInput| is meant to be used on a \emph{command} line of a
+% \texttt{tcl} or \texttt{tcl*} environment, and it efficiently makes
+% things look as if the |\TclInput| command had been replaced by the
+% inputted file in its entirety (preceded by a newline, and followed
+% by a percent and a space). |\TclInput| takes as its only argument the
+% name of the file to input.
+%
+% To typeset the file \texttt{myscript.tcl} one would write
+%\begin{verbatim}
+%% \begin{tcl}
+%% \TclInput{myscript.tcl}
+%% \end{tcl}
+%\end{verbatim} \iffalse
+%</example>
+% \fi
+% or even
+%\begin{verbatim}
+% \begin{tcl}\TclInput{myscript.tcl}\end{tcl}
+%\end{verbatim}
+% anywhere in a \package{tclldoc} document. This works since the
+% \texttt{tcl} environment is in command mode right after the initial
+% |\begin{tcl}|, and the |\end{tcl}| needs not be the first command on a
+% command mode line.
+%
+%
+% \subsection{Markup of named things}
+%
+% The two environments \DescribeEnv{proc}\texttt{proc} and
+% \DescribeEnv{variable}\texttt{variable}, which are analogues of
+% \package{doc}'s \texttt{macro} environment, for procedures and
+% variables respectively have already been mentioned in
+% Section~\ref{Sec:Introduction}. In addition to those there are two
+% environments \DescribeEnv{arrayentry}\texttt{arrayentry} and
+% \DescribeEnv{arrayvar}\texttt{arrayvar} which are meant for entries
+% in array variables and array variables as a whole. The complete
+% syntaxes of these environments are
+% \begin{quote}
+% |\begin{proc}|\oarg{namespace}\marg{proc name}\\
+% \vadjust{}\quad$\vdots$\\
+% |\end{proc}|
+%
+% |\begin{variable}|\oarg{namespace}\marg{variable name}\\
+% \vadjust{}\quad$\vdots$\\
+% \quad|\end{variable}|
+%
+% |\begin{arrayentry}|\oarg{namespace}\marg{array name}^^A
+% \marg{entry name}\\
+% \vadjust{}\quad$\vdots$\\
+% |\end{arrayentry}|
+%
+% |\begin{arrayvar}|\oarg{namespace}\marg{array name}^^A
+% \oarg{index-des}\\
+% \vadjust{}\quad$\vdots$\\
+% |\end{arrayvar}|
+% \end{quote}
+% The \meta{proc name}, \meta{variable name}, and \meta{array name}
+% arguments are quite evidently the names of the procedure, variable,
+% and array respectively. The \meta{namespace} argument can be to
+% specify the namespace part of a qualified name; having the name split
+% like this makes it easier to treat the namespace differently from the
+% rest of the qualified name. The command \DescribeMacro{\buildname}
+% |\buildname| is used by the commands and environments described here to
+% construct a qualified name from a namespace and a name.
+% If there is no \meta{namespace} argument then the namespace used will
+% be the default namespace. The default namespace is set using the
+% \DescribeMacro{\setnamespace}|\setnamespace| command, which takes the
+% namespace name as its only argument. The default namespace at the
+% beginning of the document is the global namespace, whose name is the
+% empty string.
+%
+% The \texttt{arrayentry} environment is intended for certain
+% distinguished entries in an array, such as entries inserted to
+% make the boundary cases of an algorithm work correctly and entries
+% which have a special meaning to the program. Not all arrays contain
+% such special entries, but when they do it is a good practice
+% to explain them explicitly. The \meta{index-des} argument of the
+% \texttt{arrayvar} environment can be used to specify what is used as
+% index into the array; the text in this argument will appear both in
+% the margin and in the index, but note that \meta{index-des} is a
+% moving argument. There is little difference between the
+% \texttt{variable} and \texttt{arrayvar} environments when the
+% \meta{index-des} argument of the latter isn't used, but the index
+% entries they make behave differently with respect to
+% \texttt{arrayentry} index entries. An \texttt{arrayentry} index entry
+% will be put as a subentry of the corresponding \texttt{arrayvar}
+% entry, whereas a \texttt{variable} entry would appear separately.
+%
+% The above environments usually only appear in the implementation part
+% of a \texttt{.dtx} file. For the usage part there is a command
+% \DescribeMacro{\describestring}|\describestring| which produces
+% marginal headings and index entries. The syntax of |\describestring|
+% is
+% \begin{quote}
+% |\describestring|\oarg{type}\oarg{namespace}\marg{text}
+% \end{quote}
+% The \meta{text} is the string for which a heading and index entry will
+% be made, whereas the \meta{type} (if given) is put after the text.
+% If the \meta{namespace} is given then the thing described is supposed
+% to be the name of something namespace-relative (like a procedure or
+% global variable) and in this case the complete name is formed by
+% passing \meta{namespace} and \meta{text} to |\buildname|. If
+% \meta{type} is \texttt{proc}, \texttt{var.}, or \texttt{array} and a
+% namespace is given then the index entry made will fit that made by
+% a corresponding \texttt{proc}, \texttt{variable}, or
+% \texttt{arrayvar} respectively environment. The \meta{type} argument
+% is, in \LaTeX\ terminology, moving.
+%
+% The \meta{text} and \meta{namespace} arguments can contain arbitrary
+% characters and most characters can be entered verbatim. Amongst the
+% exceptions are `|%|', `|\|', `|{|', and `|}|', which instead can be
+% entered as
+% |\PrintChar|\discretionary{}{}{}|{`\%}|,
+% |\PrintChar|\discretionary{}{}{}|{`\\}|,
+% |\PrintChar|\discretionary{}{}{}|{`\{}|, and
+% |\PrintChar|\discretionary{}{}{}|{`\}}| respectively. See the
+% \package{xdoc} package~\cite{xdoc} documentation for an explanation of
+% the |\PrintChar| command. The \meta{text} argument can also contain
+% ``variant'' parts made using the \DescribeMacro{\meta}|\meta| command.
+% As an example,
+% \begin{quote}
+% |\describestring[array]{\meta{mode}modeVars}|
+% \end{quote}
+% puts the text
+% \begin{quote}
+% \meta{mode}|modeVars| (array)
+% \end{quote}
+% in the margin and index. The arguments of such |\meta| commands are
+% moving.
+%
+% A case which deserves special treatment is that of options of
+% commands and for that there is the \DescribeMacro{\describeopt}
+% |\describeopt| command. The syntax of this command is
+% \begin{quote}
+% |\describeopt|*\oarg{namespace}\marg{command}\oarg{type}^^A
+% \marg{option}
+% \end{quote}
+% where \meta{command} is the command whose option is being described
+% and \meta{option} is the name of the option. \meta{namespace} is the
+% namespace of the \meta{command} and defaults to the global namespace.
+% \meta{type} is the type of the command and defaults to |proc| for
+% procedure. The \meta{namespace}, \meta{command}, and \meta{type} are
+% (currently) only used in the index entry that is generated. Options
+% for procedures will be put as subentries of the main procedure entry.
+% For built-in commands it might be more appropriate to use |command| as
+% \meta{type}, e.g.
+% \begin{quote}
+% |\describeopt{lsort}[command]{-real}|
+% \end{quote}
+% will put ``\texttt{-real} option'' in the margin and in the index as
+% a subentry of ``\texttt{lsort} (command), global namespace''. The |*|
+% is optional---including it will supress the marginal note normally
+% generated by this command.
+%
+% Since \Tcl\ is often used together with C, it might be useful to
+% also have something similar to the \texttt{proc} environment for C
+% things. This is what the \DescribeEnv{Cfunction}\texttt{Cfunction},
+% \DescribeEnv{Cvariable}\texttt{Cvariable}, and \DescribeEnv{Ctype}
+% \texttt{Ctype} environments are for. These take as their only
+% argument the name of the identifier that is defined, e.g.
+%\begin{verbatim}
+% \begin{Cfunction}{main}
+%\end{verbatim}
+% Since there seems to be several schools on how C code should be
+% formatted when typeset, the formatting of identifiers passed to these
+% environments is configurable. The three commands
+% \DescribeMacro{\Cfunctionidentifier}|\Cfunctionidentifier|,
+% \DescribeMacro{\Cvariableidentifier}|\Cvariableidentifier|, and
+% \DescribeMacro{\Ctypeidentifier}|\Ctypeidentifier| handle all
+% typesetting of identifiers; each takes as its only argument the
+% identifier (as a harmless string) to typeset. The default is to set
+% the argument in italic; this is what CWEB does.
+%
+% If you are using the \texttt{C}\dots\ environments for identifiers
+% whose names contain underscores (\_), you may want to pass the
+% \describeoption{notrawchar}\texttt{notrawchar} to \package{tclldoc}
+% (it is really an option of the \package{xdoc} package and will be
+% passed on to that automatically). This option addresses a problem
+% with \texttt{OT1}-encoded fonts that may cause underscores to display
+% as a quite different character (the \texttt{cmtt} typewriter fonts are
+% however not affected by this problem).
+%
+%
+%
+% \subsection{Describing command syntaxes}
+%
+% One important part of documentation is to describe the syntaxes of
+% commands. The previous subsection contains examples of the conventions
+% for this that has been developed for \LaTeX\
+% commands---mandatory arguments are denoted as `\marg{argument}' and
+% optional arguments are denoted as `\oarg{argument}'. These two classes
+% suffice rather well for \LaTeX\ commands, but the syntaxes of \Tcl\
+% commands are not seldom much more complex. Therefore a more powerful
+% form of syntax specification is called for, and one which is close at
+% hand is that used in regular expressions since it is already part of
+% the \Tcl\ language anyway.
+%
+% \DescribeMacro\regopt
+% \DescribeMacro\regstar
+% \DescribeMacro\regplus
+% The simplest commands available are the modifiers |\regopt|,
+% |\regstar|, and |\regplus|, which correspond to the |?|,
+% |*|, and |+| metacharacters in a regular expression; using |\regopt|
+% after a term says that it is optional, |\regstar| says that the term
+% can be repeated an arbitrary number of times (including zero), and
+% |\regplus| says that the term occurs at least once. The typeset
+% results of these commands are $^?$, $^*$, and $^+$ respectively
+% (recall that exponents are sometimes used to denote repetition).
+%
+% The terminals in the expression are best made using |\tclverb| (for
+% ``fixed'' material, e.g.\ procedure names) and
+% \DescribeMacro{\word}|\word| (for variable material, e.g.\
+% arguments). The syntax of |\word| is
+% \begin{quote}
+% |\word|\marg{text}
+% \end{quote}
+% and e.g.\ |\word{script}| gets typeset as
+% \begin{quote}
+% \word{script}
+% \end{quote}
+% Using these, one can for example specify the syntaxes of the \Tcl\
+% commands |append| and |catch| through
+% \begin{quote}
+% \verb"|append| \word{var-name} \word{value}\regplus"\\
+% \verb"|catch| \word{script} \word{var-name}\regopt"
+% \end{quote}
+% (recall that `\verb"|"' is a shorthand for `\verb"\tclverb|"'). These
+% get typeset as
+% \begin{quote}
+% |append| \word{var-name} \word{value}\(^+\)\\
+% |catch| \word{script} \word{var-name}\(^?\)
+% \end{quote}
+%
+% Terms in regular expressions can also consist of parenthesised
+% subexpressions, which are made using the \DescribeEnv{regblock}^^A
+% \texttt{regblock} environment. The syntax of this environment is
+% \begin{quote}
+% |\begin{regblock}|\oarg{modifier}\quad\dots\quad |\end{regblock}|
+% \end{quote}
+% If \texttt{regblock} environments are nested then the parentheses of
+% the outer environment will grow to be larger than those of the inner
+% environment. A side-effect of this is that the \texttt{regblock}
+% environment wants to know if a modifier will be applied to it, since
+% the amount by which the modifier should be raised in this case depends
+% on the size of the parenthesis before it, and this is what the
+% \meta{modifier} optional argument is for. \LaTeX\ does not provide
+% for arguments at the |\end| of an environment, so it has to be placed
+% at the |\begin|. Using these elements, the syntax of |if| can be
+% specified through
+% \begin{quote}
+% \verb"|if| \word{expression} |then|\regopt\ \word{script}"\\
+% \verb"\begin{regblock}[\regstar]|elseif| \word{expression}"\\
+% \verb"|then|\regopt\ \word{script}\end{regblock}"\\
+% \verb"\begin{regblock}[\regopt]|else| \word{script}\end{regblock}"
+% \end{quote}
+% which typesets as
+% \begin{isyntax}
+% |if| \word{expression} |then|\(^?\) \word{script} \(\bigl(\)^^A
+% |elseif| \word{expression} |then|\(^?\) \word{script}\(\bigr)^*\)
+% \(\bigl(\)|else|~\word{script}\(\bigr)^?\)
+% \end{isyntax}
+% In versions of \package{tclldoc} before 2.40, the \texttt{regblock}
+% environment used to be called \DescribeEnv{regexp}\texttt{regexp}.
+% That other name is still supported, but should be avoided in new
+% documents.
+%
+% The final regular expression construction that is supported is that
+% of branches of a regular expression. A \texttt{regblock} environment
+% consist of one or several branches that are separated by
+% \DescribeMacro{\regalt}|\regalt| commands. Visually the |\regalt|
+% command gets typeset as a vertical bar that has the same size as the
+% parentheses of the surrounding \texttt{regblock} environment. The
+% |\regalt| command may only be used inside a \texttt{regblock}
+% environment.
+% An example of the use of |\regalt| is the following specification of
+% the syntax of \Tcl's |regexp| command:
+% \begin{quote}
+% \verb"|regexp| \begin{regblock}[\regstar]|-nocase|\regalt"\\
+% \verb"|-indices|\end{regblock} |--|\regopt \word{regular expression}"\\
+% \verb"\word{string} \word{var-name}\regstar"
+% \end{quote}
+% which typesets as
+% \begin{isyntax}
+% |regexp| \((\)|-nocase|~\(\mid\) |-indices|\()^*\) |--|\(^?\)
+% \word{regular expression} \word{string} \word{var-name}\(^*\)
+% \end{isyntax}
+%
+% Finally a note about the relationship between the |\word| command and
+% \package{doc}'s |\meta| command. Whereas the argument of |\word| is
+% encapsulated in braces (and thus ought to be a separate word for a
+% \Tcl\ interpreter), the argument of |\meta| is encapsulated in angle
+% brackets. The idea is that |\word| should be used for things which are
+% separate words to \Tcl, whereas |\meta| should be used for things which
+% corresponds to parts of words or to several words. Thus in the command
+% |set b Z${a}Y|, the second word |b| would be a `\word{var-name}' and
+% the third word |Z${a}Y| would be a `|Z|\meta{string}|Y|'. In the
+% command |label .a -text "Hello there!"|, the last two arguments could
+% be summarised as an \meta{option}, but not as an \word{option}.
+%
+%
+% \subsection{Non-ASCII characters}
+%
+% One problem, which is only going to be more common in the future, is
+% how to deal with non-ASCII characters in scripts. The main problem
+% here lies not on the output side, as \LaTeX\ is actually pretty good
+% at producing a requested character as long as it is available in some
+% font, but on the input side. \LaTeX\ can handle input in most 8-bit
+% encodings, but in order for that to work the file must contain an
+% |\inputencoding| command which tells \LaTeX\ which encoding is being
+% used. As transporting a file from one platform to another most likely
+% changes the encoding, but not the argument of |\inputencoding|, this
+% method is rather fragile. Certainly there is room for improvements
+% but the world of 8-bit encodings is generally such a mess anyway that
+% it probably isn't worth the effort.
+%
+% A more progressive approach is to decide that all source code is in
+% Unicode (more precisely in UTF-8). The main arguments for this are:
+% (i)~\Tcl\ uses Unicode internally, (ii)~it is equally foreign on
+% all platforms and can be treated as binary data rather than ``extended
+% ASCII'' text, and (iii)~since it isn't converted, there is no loss of
+% data. Interestingly enough, \emph{it is possible to use UTF-8 ``out of
+% the box'' today!} Using the \package{ucs} package~\cite{ucs-package}
+% allows \LaTeX\ to interpret UTF-8 input and this works just as well
+% for the \Tcl\ code in a \texttt{tcl} environment as for the normal
+% \LaTeX\ text outside it. If \package{docstrip} is run on a \LaTeX\
+% format\footnote{Or, in some implementations, the \TeX\ program gets a
+% suitable option.} that preserves characters whose most significant
+% bit is set\footnote{Rather than converting them to
+% \texttt{\^{}\^{}}-sequences, which is the default.} then the non-ASCII
+% characters are simply copied verbatim and it makes no difference that
+% they may occupy more than one byte of data. Alternatively one can run
+% \package{docstrip} on Omega and (with a little extra work) get the
+% ability to have the \Tcl\ code translated to some other encoding as
+% the files are being generated!\footnote{At least in theory; I have to
+% admit I haven't actually tested the \package{docstrip} part of it.}
+%
+% But although the above paragraph describes the way to go in the long
+% run, there are some matters which make this approach slightly
+% unfeasible in the near future. This is of course my own subjective
+% opinion, but I find that two good reasons not to start using Unicode
+% throughout quite yet are that (i)~my favourite text editor doesn't
+% support Unicode (yet) and (ii)~even if I do start using it, there
+% wouldn't be that much people around who could make sense of such files
+% if I were to send it to them. Therefore I \emph{intend} to implement,
+% but as yet haven't, a kind of intermediate format where non-ASCII
+% Unicode characters are encoded using only ASCII characters plus an
+% extra escape character. The basic idea is simply that any string
+% `\meta{escape}\meta{hex digits}\meta{escape}' should be interpreted as
+% the Unicode character \texttt{U+}\meta{hex digits}, so that arbitrary
+% Unicode characters can be encoded using a character set that only
+% comprises ASCII plus one extra \meta{escape} character. Supposing that
+% this \meta{escape} character is the centered dot `\textperiodcentered',
+% I could then encode my name as
+% \begin{quote}
+% \texttt{Lars Hellstr\swtpc 00f6\swtpc m}
+% \end{quote}
+% whereas the centered dot itself would be \texttt{\swtpc 00b7\swtpc}.
+% The idea is that the file itself should contain the declaration of
+% which character is used as this Unicode escape, so that a change due
+% to translation from one 8-bit encoding to another will identically
+% alter both declaration and use of the escape character, thereby
+% preserving the internal logic of the file.
+%
+% The weak point with this scheme is that \package{docstrip} would have
+% to translate the escape sequences to proper characters when it
+% generates files. Implementing that under \TeX\ is highly non-trivial.
+% It can be done with a reasonable effort under Omega, but it still
+% requires hacking \package{docstrip}. The really interesting approach
+% would however be to implement it in a port of \package{docstrip} to
+% \Tcl, as that would remove the need to have \TeX\ to install the files.
+% Porting \package{docstrip} to \Tcl\ is by the way a project of mine
+% which I unfortunately haven't spent much time on, but if it is to be
+% of any use to have the Unicode escape format described above
+% implemented in \package{tclldoc} then I will have to make some
+% progress with it.
+%
+% \medskip
+%
+% One rather recent advancement in this direction is the code in
+% \texttt{sourcedtx.tcl}, which can be generated from the file
+% \texttt{sourcedtx.dtx} that is distributed with \package{tclldoc} as
+% an example. This implements a \Tcl\ command |dtx::source| that makes
+% it possible to source \Tcl\ code in a \texttt{.dtx} file without
+% docstripping it to a file first. This code does currently not bother
+% about encodings, but that is easy enough to add.
+%
+% \medskip
+%
+% Finally, a few notes on the old mechanism for non-ASCII characters
+% that is included in the \package{tcldoc} compatibility class. It
+% cooperates with the \package{rtkinenc} package~\cite{rtkinenc}, when
+% that has been loaded, in order to detect when an input character isn't
+% avaiable in any active font encoding. Rather than raising an error and
+% printing nothing it these cases, missing characters are written as the
+% corresponding |\x|\meta{hh} backslash sequence in a slightly different
+% font than the rest of the text. A problem here is however that most
+% input encodings contain a few characters which are interpreted as
+% \emph{math} character by \LaTeX. When such a character appears on a
+% code line it makes \TeX\ switch to math mode and things generally get
+% quite messy afterwards.
+%
+% The cure for this is to redeclare these input characters to \LaTeX\
+% so that they work as intended in text mode, but that does take some
+% lines of code. The \package{tcldoc} class does contain the
+% declarations needed for the \texttt{applemac} input encoding; passing
+% it the \describeoption{macinputenc}\texttt{macinputenc} option will
+% load the \package{rtkinenc} package, the \texttt{applemac} (macRoman)
+% input encoding, the \texttt{TS1} output encoding, and make the
+% necessary redeclarations to allow all input characters to work in
+% text. As nothing is provided for any other input encoding however,
+% this solution never was a good solution. The \texttt{macinputenc}
+% should be considered as unsupported as of \package{tclldoc} v\,2.30.
+%
+%
+%
+% \subsection{Options and customisation}
+%
+% The \package{tclldoc} package does not have any options of its own, but
+% all options passed to it are passed on to the \package{xdoc} package.
+% The \package{tclldoc} class accepts all options that the standard
+% \LaTeX\ document class \package{article} accepts, with the exception
+% of \texttt{a5paper}.
+%
+% Like the \package{ltxdoc} class, the \package{tclldoc} class will look
+% for a special configuration file \texttt{tclldoc.cfg} and input that
+% file if it exists. This file can be used to declare extra options for
+% the class, have certain options always given, etc. Section~2 of
+% \texttt{ltxdoc.dtx}~\cite{ltxdoc} is a good introduction to how such
+% configuration files can be used with \texttt{.dtx} sources in general.
+%
+% When you use a \texttt{tclldoc.cfg} file to customise the
+% \package{tclldoc} document class, you affect how all documents using
+% that class will be typeset in your particular \TeX\ installation. It
+% is \emph{not} something you have to do, but it can
+% make \package{tclldoc} documents work better with the printers, paper
+% formats, fonts, etc.\ that are available in your installation. It
+% will usually cause line and page breaks to occur at other places than
+% they would do if typeset using an uncustomised \package{tclldoc}
+% class, so the typographical quality of the document can be decreased,
+% but it is uncommon to find an \texttt{.dtx} document whose author
+% have given these matters much attention anyway. Hence the typographic
+% arguments against customisation are weak.
+%
+% A common form of customisation is to use additional packages, since
+% various kinds of document-wide font selection is often done by
+% packages. Due to that the code in \texttt{tclldoc.cfg} is executed when
+% the \package{tclldoc} class does its option processing, at which time
+% \LaTeX\ does not allow loading packages, such customisation is not
+% straightforward. There is a way around that however; to load e.g.\ the
+% \package{times} package, use the command
+%\begin{verbatim}
+%\AtEndOfClass{\usepackage{times}}
+%\end{verbatim}
+% Using |\AtEndOfClass| like this delays the command until it may be
+% executed.
+%
+%
+% \subsection{Miscellanea}
+%
+% For writing ``\Tcl'', the \package{tclldoc} package defines the command
+% \DescribeMacro{\Tcllogo}|\Tcllogo|, which for most fonts look slightly
+% better than simply typing |Tcl|. (|\Tcllogo| becomes \Tcl, whereas
+% |Tcl| becomes Tcl.)
+%
+% Between the namespace and the tail part of a qualified name, the
+% \package{tclldoc} package commands naturally put the name\-space
+% separator `|::|'. This text is stored in the macro
+% \DescribeMacro{\namespaceseparator}|\namespaceseparator|, which can be
+% redefined using the |\Declare|\-|Robust|\-|Command| command. This is
+% mainly useful for modifying how this separator behaves with respect to
+% line breaking; the default behaviour is that a line break can occur
+% between the colons.
+%
+% Another configurable piece of text is stored in the
+% \DescribeMacro{\namespacephrase}|\namespacephrase| macro. This
+% contains word `namespace' as that appears in index entries, e.g.~in
+% the last word of
+% \begin{quote}
+% \texttt{platform} (var.), \texttt{alpha} name\-space
+% \end{quote}
+% It is often convenient to replace this by something shorter. The
+% redefinition
+% \begin{quote}
+% |\renewcommand{\namespacephrase}{\textsc{ns}}|
+% \end{quote}
+% turns the above into
+% \begin{quote}
+% \texttt{platform} (var.), \texttt{alpha} \textsc{ns}
+% \end{quote}
+% Note however that either |\namespacephrase| itself or its expansion
+% must be robust.
+%
+%
+% \section{Acknowledgements}
+%
+% The \package{tclldoc} document class and \LaTeX\ package were
+% constructed starting from three other sources: (i)~the \package{ltxdoc}
+% document class~\cite{ltxdoc} by David Carlisle,
+% (ii)~the \package{doc} package~\cite{doc} by Frank Mittelbach,
+% B.~Hamilton Kelly, Andrew Mills, Dave Love, and Joachim Schrod, and
+% (iii)~my own \package{pasdoc} document class. Hence the `et al.'\ in
+% the author field above. This complicated heritage in the code is
+% mirrored by the documented source---there are paragraphs below that
+% are rather about one of (i)--(iii), than about \package{tclldoc}.
+%
+%
+%
+% \StopEventually{
+% \begin{thebibliography}{9}
+% \bibitem{ltoutenc}
+% Johannes Braams, David Carlisle, Alan Jeffrey, Frank
+% Mittelbach, Chris Rowley, and Rainer Sch\"opf:
+% \textit{ltoutenc.dtx}, The \LaTeX3 Project;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{base}\slash \texttt{ltoutenc.dtx}.
+% \bibitem{ltxdoc}
+% David Carlisle:
+% \textit{The file \texttt{ltxdoc.dtx} for use with \LaTeXe},
+% The \LaTeX3 Project;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{base}\slash \texttt{ltxdoc.dtx}.
+% \bibitem{rtkinenc}
+% Lars Hellstr\"om:
+% \textit{The \package{rtkinenc} package}, 2000;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{contrib}\slash
+% \texttt{supported}\slash \texttt{rtkinenc}\slash
+% \texttt{rtkinenc.dtx}.
+% \bibitem{xdoc}
+% Lars Hellstr\"om:
+% \textit{The \package{xdoc} package --- experimental
+% reimplementations of features from \package{doc},
+% second~prototype}, 2000, 2001;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{exptl}\slash \texttt{xdoc}\slash
+% \texttt{xdoc2.dtx}.
+% \bibitem{docindex}
+% Lars Hellstr\"om:
+% \textit{The \package{docindex} package}, 2001;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{exptl}\slash \texttt{xdoc}\slash
+% \texttt{docindex.dtx}.
+% \bibitem{TeXbook}
+% Donald E.\ Knuth, Duane Bibby (illustrations):
+% \textit{The \TeX book}, Ad\-di\-son--Wes\-ley, 1984;
+% ISBN~0-201-13448-9 and~0-201-13447-0.
+% \bibitem{docstrip}
+% Frank Mittelbach, Denys Duchier, Johannes Braams, Marcin
+% Woli\'nski, and Mark Wooding: \textit{The \textsf{DocStrip}
+% program}, The \LaTeX3 Project;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{base}\slash \texttt{docstrip.dtx}.
+% \bibitem{doc}
+% Frank Mittelbach, B.~Hamilton Kelly, Andrew Mills, Dave Love, and
+% Joachim \mbox{Schrod}: \textit{The \package{doc} and
+% \package{shortvrb} Packages}, The \LaTeX3 Project;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{base}\slash \texttt{doc.dtx}.
+% \bibitem{execMagic}
+% ``Tom'', Donal Fellows, Larry Virden, Richard Suchenwirth:
+% \textit{exec magic}, The \Tcl'ers Wiki page \textbf{812};
+% \textsc{http}:/\slash \texttt{mini.net}\slash \texttt{tcl}\slash
+% \texttt{812.html}.
+% \bibitem{ucs-package}
+% Dominique~P.~G.~Unruh:
+% \textit{\texttt{ucs.sty} - Unicode Support}, 2000;
+% \textsc{ctan}:\discretionary{}{}{\thinspace}\texttt{macros}\slash
+% \texttt{latex}\slash \texttt{contrib}\slash
+% \texttt{supported}\slash \texttt{unicode}/.
+% \end{thebibliography}
+% \begin{flushleft}\footnotesize
+% The ``\textsc{ctan}:'' above is short for ``any of the servers
+% in the Comprehensive \TeX\ Archive Network (or mirror thereof)''.
+% You get a working URL if you replace this by e.g.\
+% ``\texttt{ftp://ftp.tex.ac.uk/tex-archive/}''.%
+% \end{flushleft}
+% }
+%
+%
+% \changes{v\,1.90}{2000/01/02}{Took a copy of \texttt{pasdoc.dtx} and
+% started modifying it into \texttt{tcldoc.dtx}. (LH)}
+%
+% \section{Initial stuff in the \package{tclldoc} package}
+%
+% The |\NeedsTeXFormat| and |\ProvidesPackage| commands for the
+% \package{tclldoc} package appear at the top of \texttt{tclldoc.dtx} (not
+% shown in the typeset document). Apart from that the only initial
+% action required is to load the \package{xdoc} package (and thereby
+% the \package{doc} package) and the \package{docindex} (or rather the
+% \LaTeXe\ version \package{docidx2e}) package.
+% \SortIndex{docindex package}{\package{docindex} package}
+%
+% \changes{v\,2.23}{2001/07/21}{Added message about using
+% docindex.ist. (LH)}
+% \begin{macrocode}
+%<*pkg>
+\RequirePackageWithOptions{xdoc2}[2001/11/03]
+\RequirePackage{docidx2e}
+\AtEndDocument{%
+ \typeout{********************************}%
+ \typeout{* Use docindex.ist when\@spaces\@spaces*}%
+ \typeout{* sorting .idx and .glo files. *}%
+ \typeout{********************************}%
+}%
+% \end{macrocode}
+%
+%
+% \section{Verbatim typesetting of \Tcl\ code}
+%
+% \changes{v\,2.10}{2000/10/03}{Major overhaul of the \texttt{tcl}
+% environment, to make it possible to assign different penalties to
+% different breakpoints. (LH)}
+%
+% The main feature in the \package{tclldoc} package is the \texttt{tcl}
+% environment, which typesets embedded code in a way more adapted to
+% \Tcl\ code than what the \texttt{macrocode} environment does.
+%
+%
+% \subsection{Beginning of line processing}
+%
+% The organization of the text in \emph{lines} is crucial for its
+% interpretation by the \texttt{tcl} environment. In particular the
+% following features rely on being at the beginning of a line:
+% \begin{itemize}
+% \item indentation of \Tcl\ code,
+% \item invoking command mode,
+% \item recognizing \package{docstrip} guards.
+% \end{itemize}
+%
+% \begin{macro}{\TD@percent@token}
+% A control sequence |\let| to a |%|$_{12}$, mainly for use in |\ifx|
+% comparisons.
+% \DoNotIndex{\%}
+% \begin{macrocode}
+\begingroup
+ \catcode`\%=12
+ \global\let\TD@percent@token=%
+\endgroup
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@start@n@line}
+% \begin{macro}{\TD@start@n@line@}
+% \begin{macro}{\TD@start@n@line@i}
+% The macro |\TD@start@n@line| is used at the beginning of every line.
+% The macro first clears the |\TD@line@indent| and |\TD@nesting@level|
+% registers and the |\TD@nesting@stack| stack. Then it checks if the
+% next character is a percent. If it is then this is a command line.
+% If it isn't then it is a normal line and it is time to start a
+% codeline paragraph and count the character indentation.
+%
+% |\TD@|\-|start@|\-|n@|\-|line@| is the macro which actually does
+% these things; |\TD@|\-|start@|\-|n@|\-|line| is usually |\let| to
+% |\TD@|\-|start@|\-|n@|\-|line@|. When a file is being |\TclInput|ed
+% however, |\TD@|\-|start@|\-|n@|\-|line| is |\let| to
+% |\TD@|\-|start@|\-|n@|\-|line@i| which peeks at the next token
+% before calling |\TD@|\-|start@|\-|n@|\-|line@|. If it didn't,
+% |\TD@|\-|start@|\-|n@|\-|line@| would have a problem at the end of
+% the file, since the end of a file counts as being |\outer|.
+% \begin{macrocode}
+\def\TD@start@n@line@#1{%
+ \global\TD@line@indent=\z@
+ \TD@nesting@level=\z@
+ \def\TD@nesting@stack{\TD@nesting@level}%
+ \ifx #1\TD@percent@token
+ \expandafter\TD@module
+ \else
+ \global\advance \c@codelineno \@ne
+ \TD@begin@tclpar
+ \expandafter\TD@count@indent \expandafter#1%
+ \fi
+}
+% \end{macrocode}
+% \begin{macrocode}
+\let\TD@start@n@line=\TD@start@n@line@
+\def\TD@start@n@line@i{\futurelet\next\TD@start@n@line@}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+%
+% \begin{macro}{\TD@count@indent}
+% The purpose of the |\TD@count@indent| macro is to compute the
+% indentation of the current line. It grabs the next character, and
+% as long as that is a space or tab it will just increment
+% |\TD@line@indent| accordingly and continue with the next character.
+% |!| and |"| are used to make space and tab respectively with
+% suitable catcode.
+% \DoNotIndex{\!,\",\ ,\^}
+% \begin{macrocode}
+\begingroup
+ \catcode`\!=\active
+ \catcode`\"=\active
+ \lccode`\!=`\ %
+ \lccode`\"=`\^^I%
+ \lowercase{%
+\endgroup
+ \def\TD@count@indent#1{%
+ \ifx !#1%
+ \global\advance \TD@line@indent \@ne
+ \expandafter\TD@count@indent
+ \else \ifx "#1%
+ \global\divide \TD@line@indent \TD@tab@size
+ \global\advance \TD@line@indent \@ne
+ \global\multiply \TD@line@indent \TD@tab@size
+ \expandafter\expandafter \expandafter\TD@count@indent
+ \else
+ \TD@setup@parshape
+ \expandafter\expandafter \expandafter#1%
+ \fi\fi
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@module}
+% When command mode has been properly established it is time to
+% check if the next character is |<|, in which case the following
+% \package{docstrip} guard must be processed. |\TD@command| must
+% appear before the |\futurelet| so that the following character
+% won't get tokenized with incorrect catcodes.
+% \changes{v\,2.13}{2000/12/20}{Always check whether the current line
+% is a guard line, since the \texttt{\PrintChar{\number`\<}} in
+% the guard would otherwise start a new paragraph, which is an
+% error. (LH)}
+% \begin{macrocode}
+\def\TD@module{%
+ \TD@command
+ \futurelet\next
+ \TD@ch@angle
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@ch@angle}
+% The module checking in \package{tclldoc} takes advantage of the
+% macros for this in \package{doc}---|\ch@plus@etc| is a \package{doc}
+% macro. |<| is active because it is in the nolig list
+% (|\verbatim@|\-|nolig@|\-|list|).
+% \changes{v\,2.20}{2001/03/12}{Moved \cs{TD@normal} previously in
+% \cs{TD@pm@module} to here. This means \package{docstrip} guard are
+% now read in normal mode rather than command mode. This change
+% was made because of grouping problems that occured on non-block
+% guard lines. Also added local redefinition of \PrintChar{13} to
+% prevent that guard lines are concatenated with the following
+% line. (LH)}
+% \DoNotIndex{\^}
+% \begin{macrocode}
+\begingroup
+ \catcode`<=\active
+ \catcode`\^^I=\catcode`\^^M \endlinechar=`\^^I \relax
+ \catcode`\^^M=\active
+ \gdef\TD@ch@angle{%
+ \ifx <\next
+ \TD@normal
+ \global\advance \c@codelineno \@ne
+ \TD@begin@tclpar
+ \def^^M{\TD@active@CR}%
+ \expandafter\futurelet \expandafter\next
+ \expandafter\ch@plus@etc
+ \fi
+ }
+\endgroup
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@pm@module}
+% The |\TD@pm@module| macro is used instead of \package{doc}'s
+% |\pm@module| when in the \texttt{tcl} environment. This is necessary
+% since the paragraph man\oe uvres of the \texttt{tcl} environment would
+% not work right with \package{doc}'s |\pm@module|.
+%
+% If we're not dealing with a block directive (|*| or |/|), i.e.,
+% it's a single special line, we set everything up to the next |>|
+% appropriately, return to normal mode, possibly change font, and
+% start counting indentation spaces.
+% \DoNotIndex{\>}
+% \begin{macrocode}
+\begingroup
+ \catcode`\>=\active
+ \gdef\TD@pm@module#1>{%
+ \Module{#1}%
+ \ifnum \guard@level<\c@StandardModuleDepth \else
+ \AltMacroFont
+ \fi
+ \TD@count@indent
+ }
+\endgroup
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@star@module}
+% \changes{v\,2.20}{2001/03/12}{Removed \cs{TD@end@tclpar}. (LH)}
+% \changes{v\,2.22}{2001/06/13}{Reinserted \cs{TD@end@tclpar} and
+% added \cs{TD@command}; this solves a problem with grouping that
+% prevented a font change from getting effect. (LH)}
+% \begin{macro}{\TD@slash@module}
+% \changes{v\,2.20}{2001/03/12}{Removed \cs{TD@end@tclpar}. (LH)}
+% \changes{v\,2.22}{2001/06/13}{Same change as in
+% \cs{TD@star@module}. (LH)}
+% The |\TD@star@module| and |\TD@slash@module| macros are, like
+% |\TD@pm@module|, used instead of \package{doc}'s |\star@module| and
+% |\slash@module| respectively when in the \texttt{tcl} environment.
+% \DoNotIndex{\>}
+% \begin{macrocode}
+\begingroup
+ \catcode`\>=\active
+ \gdef\TD@star@module#1>{%
+ \Module{#1}%
+ \TD@end@tclpar
+ \TD@command
+ \global\advance \guard@level \@ne
+ \ifnum \c@StandardModuleDepth<\guard@level
+ \global\let\macro@font=\AltMacroFont
+ \macro@font
+ \fi
+ }
+ \gdef\TD@slash@module#1>{%
+ \Module{#1}%
+ \TD@end@tclpar
+ \TD@command
+ \global\advance \guard@level \m@ne
+ \ifnum \guard@level=\c@StandardModuleDepth
+ \global\let\macro@font\MacroFont
+ \macro@font
+ \fi
+ }
+\endgroup
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+%
+% \begin{macro}{\TD@gobble@whitespace}
+% This macro gobbles all normal mode spaces and tabs following it.
+% \begin{macrocode}
+\def\TD@gobble@whitespace#1{%
+ \if \ifx #1\TD@active@space
+ 0%
+ \else
+ \ifx #1\TD@active@tab 0\else 1\fi
+ \fi 0%
+ \expandafter\TD@gobble@whitespace
+ \else
+ \expandafter#1%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Typographical elements}
+%
+% This subsection contains definitions of the typographical
+% elements---special symbols and the like--that are used in the
+% \texttt{tcl} and \texttt{tcl*} environments.
+%
+%
+% \begin{macro}{\TD@typography}
+% \begin{macro}{\TD@nontcl@font}
+% The |\TD@typography| macro does all the typographic set-up that is
+% common to the \texttt{tcl} environment, the \texttt{tcl*}
+% environment, and the |\tclverb| command.
+%
+% The |\TD@nontcl@font| macro selects an ``escape'' font for \Tcl\
+% material. This font is used for various kinds of escape codes that
+% are typeset instead of some character---either because the
+% character is not available, or because the line needs to be broken.
+% The escape font will have the same font family (and same encoding)
+% as the text surrounding the \texttt{tcl} environment or |\tclverb|
+% command. Therefore |\TD@nontcl@font| must be defined before the
+% \Tcl\ material font is selected. I don't think it is necessary to
+% use |\protected@edef| below, but it can't hurt either.
+% \begin{macrocode}
+\def\TD@typography{%
+ \protected@edef\TD@nontcl@font{%
+ \noexpand\fontencoding{\cf@encoding}%
+ \noexpand\fontfamily{\f@family}\noexpand\selectfont
+ }%
+% \end{macrocode}
+% The most frequent escape symbol is the single backslash used for
+% escaping the end of lines, and this is stored in the
+% |\TD@backslash@box| box.
+%
+% The following code have to do with how characters outside
+% visible ASCII are typeset when they appear in the \texttt{tcl} or
+% \texttt{tcl*} environment. The commands are defined by the
+% \package{rtkinenc} package.
+% \begin{macrocode}
+ \InputModeCode
+ \SetUnavailableAction{\leavevmode{%
+ \TD@nontcl@font\textbackslash x\TypesetHexNumber{##1}%
+ }}%
+ \DeclareInputMath{0}{\RIE@undefined{0}}%
+ \DeclareInputMath{12}{\RIE@undefined{12}}%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@typeset@space}
+% This macro typesets a space, as it should be in the \texttt{tcl}
+% environment (and other places too). It generates a kern, not glue, so
+% that it can be used in a |\discretionary|.
+% \begin{macrocode}
+\def\TD@typeset@space{\kern\fontdimen\tw@\font}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@discretionary@space}
+% This is the macro which offers all the breakpoints in |\tclverb|
+% code. The name comes from the fact that all the breakpoints are
+% discretionaries which appear to be spaces when not broken. When
+% they are broken, they are backslashes. To give some visual hint
+% that these backslashes need not be backslashes in the source, they
+% are typeset in the same font family (and same encoding) as the
+% text surrounding the \texttt{tcl} environment.
+% \begin{macrocode}
+\def\TD@discretionary@space{%
+ \discretionary{\copy\TD@backslash@box}{}{\TD@typeset@space}%
+}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@breakable@space}
+% The valid breakpoints inside \texttt{tcl} and \texttt{tcl*}
+% environments are made in the |\TD@|\-|breakable@|\-|space| macro.
+% This macro contributes an |\hbox| (which contains a
+% |\TD@typeset@space|), a penalty, and an empty |\vadjust| to the
+% current horizontal list. If a line break is made at the penalty,
+% the |\hbox| will later be removed and replaced by a non-macro font
+% backslash (from |\TD@backslash@box|). The |\vadjust| is there to
+% prevent that any discardable items disappears after the breakpoint.
+% \begin{macrocode}
+\def\TD@breakable@space{%
+ \hbox{\TD@typeset@space}%
+ \TD@nesting@penalty
+ \vadjust{}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@typeset@tab}
+% This is an unbreakable space whose width equals that of
+% |\TD@tab@size| spaces.
+% \begin{macrocode}
+\def\TD@typeset@tab{\kern\TD@tab@size\fontdimen\tw@\font}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@visible@whitespace}
+% The |\TD@visible@whitespace| macro locally redefines the macros
+% which typesets spaces and tabs to make visible symbols. The visible
+% tab is roughly a |\rightarrowfill| and a |\vrule|, but a difference
+% is that the minuses that form the extensible ``tail'' to the
+% |\rightarrow| are not smashed. Not doing that gives the |\vrule| a
+% suitable height, but I had rather expected the nominal height of
+% the |\rightarrow| to be larger \textellipsis\ It's yet another
+% mysterious math font feature, I suppose.
+%
+% \begin{macrocode}
+\def\TD@visible@whitespace{%
+ \def\TD@typeset@space{\char32 }%
+ \def\TD@typeset@tab{%
+ \hb@xt@\TD@tab@size\fontdimen\tw@\font{%
+ $\m@th-\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu-\mkern-2mu$}\hfill
+ \mkern-7mu\mathord\rightarrow\mkern-1mu\vrule\mkern1mu$%
+ }%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Catcodes and active characters}
+%
+% Like any \texttt{verbatim}-like environment, the \texttt{tcl}
+% environment does some rather extensive alterations of catcodes. This
+% is handled by the three macros |\TD@general|, |\TD@normal|, and
+% |\TD@command|. Set-up that is common for both modes is made by
+% |\TD@general| when the \texttt{tcl} environment is entered.
+% Mode-dependent set-up is made by |\TD@normal| and |\TD@command|
+% whenever a mode switch occurs.
+%
+% \begin{macro}{\TD@let@active}
+% One technicality here is that all of these routines need to set the
+% definition of some active character, and this character is often not
+% active with normal \LaTeX\ catcodes. To overcome this difficulty,
+% there is a macro |\TD@let@active| which takes two arguments: a
+% control sequence with a single character name, and an arbitrary
+% control sequence. The active character with the same name as the
+% first control sequence is |\let| locally to the second control
+% sequence.
+% \begin{macrocode}
+\begingroup
+ \catcode\z@=\active
+ \gdef\TD@let@active#1{%
+ \begingroup
+ \lccode\z@=`#1%
+ \lowercase{%
+ \endgroup
+ \let^^@%
+ }%
+ }%
+\endgroup
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@general}
+% The |\TD@general| macro does the initial set-ups that are common for
+% both modes of the \texttt{tcl} environment and for the |\tclverb|
+% command. These include definitions of various active characters and
+% |\catcode| assignments.
+%
+% \DoNotIndex{\^,\ ,\\,\[,\]}
+% \DoNotIndexHarmless{\PrintChar{`\{}}
+% \DoNotIndexHarmless{\PrintChar{`\}}}
+% \begin{macrocode}
+\def\TD@general{%
+ \let\do\do@noligs
+ \verbatim@nolig@list
+ \let\do\@makeother
+ \dospecials
+ \catcode`\^^M=\active
+ \TD@let@active\^^I\TD@active@tab
+ \TD@let@active\^^M\TD@active@CR
+ \TD@let@active\ \TD@active@space
+ \TD@let@active\\\TD@active@backslash
+ \TD@let@active\{\TD@active@braceleft
+ \TD@let@active\}\TD@active@braceright
+ \TD@let@active\[\TD@active@bracketleft
+ \TD@let@active\]\TD@active@bracketright
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@normal}
+% This macro sets up the normal mode, changing everything that is
+% different in any of the other modes. Note that the catcodes in
+% normal mode are such that no character is a space. This makes it
+% possible for macros used in normal mode to look ahead by simply
+% grabbing the next character in an undelimited argument.
+% \DoNotIndex{\^,\ ,\\,\[,\]}
+% \DoNotIndexHarmless{\PrintChar{`\{}}
+% \DoNotIndexHarmless{\PrintChar{`\}}}
+% \begin{macrocode}
+\def\TD@normal{%
+ \catcode`\^^I=\active
+ \catcode`\ =\active
+ \catcode`\\=\active
+ \catcode`\{=\active
+ \catcode`\}=\active
+ \catcode`\[=\active
+ \catcode`\]=\active
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@command}
+% This macro switches from normal mode to command mode.
+% \DoNotIndex{\^,\ ,\\,\[,\]}
+% \DoNotIndexHarmless{\PrintChar{`\{}}
+% \DoNotIndexHarmless{\PrintChar{`\}}}
+% \begin{macrocode}
+\def\TD@command{%
+ \catcode`\^^I=10%
+ \catcode`\ =10%
+ \catcode`\[=12%
+ \catcode`\]=12%
+ \catcode`\\=\z@
+ \catcode`\{=\@ne
+ \catcode`\}=\tw@
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@active@space}
+% \begin{macro}{\TD@active@space@}
+% This macro is used for spaces in normal mode. Its main problem is
+% to determine whether it is followed by more whitespace or not. If it
+% is, then it is an unbreakable space. If it isn't, then it is a
+% breakable space.
+% \begin{macrocode}
+\def\TD@active@space#1{%
+ \ifx #1\TD@active@backslash
+ \expandafter\TD@active@space@
+ \else
+ \ifx #1\TD@active@space
+ \TD@typeset@space
+ \else\ifx #1\TD@active@tab
+ \TD@typeset@space
+ \else
+ \TD@breakable@space
+ \fi\fi
+ \expandafter#1%
+ \fi
+}
+% \end{macrocode}
+% The special case to look out for is that the next character is a
+% backslash which escapes a newline.
+% \begin{macrocode}
+\def\TD@active@space@#1{%
+ \ifx #1\TD@active@CR
+ \TD@typeset@space
+ \else
+ \TD@breakable@space
+ \fi
+ \TD@active@backslash #1%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@active@tab}
+% The |\TD@active@tab| macro is what the active character tab is
+% |\let| to inside the \texttt{tcl} and \texttt{tcl*} environments.
+% \begin{macrocode}
+\def\TD@active@tab{\TD@typeset@tab}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@active@CR}
+% This macro is called at the end of a line. The |\catcode| tests the
+% current mode.
+% \DoNotIndex{\\}
+% \begin{macrocode}
+\def\TD@active@CR{%
+ \ifnum \catcode`\\=\z@
+ \ifvmode\else
+ \PackageError{tclldoc}{Horizontal material on command line}\@ehc
+ \@@par
+ \fi
+ \TD@normal
+ \else
+ \TD@end@tclpar
+ \fi
+ \TD@start@n@line
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@active@CRv}
+% This is what |\tclverb| defines the |^^M| active character as
+% being. Cf.\ the standard \LaTeX\ macro |\verb@eol@error|.
+% \begin{macrocode}
+\def\TD@active@CRv{%
+ \verb@egroup
+ \PackageError{tclldoc}{\protect\tclverb\space ended by end of line}%
+ \@ehc
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@active@backslash}
+% \changes{v\,2.10}{2000/10/08}{First checking if next character is
+% active, and only expands the macro containing the detailed tests
+% if it is. (LH)}
+% \begin{macro}{\TD@active@backslash@}
+% \begin{macro}{\TD@active@backslash@v}
+% |\TD@active@backslash| is used for backslashes in normal mode. Its
+% main problem is to determine whether the backslash is escaping
+% something (which would normally be treated specially by the
+% environment) or not. The primary test for this is whether the
+% argument grabbed is an active character, and if it is then
+% processing continues (in |\TD@active@backslash@|) to determine what
+% should be done.
+% \begin{macrocode}
+\def\TD@active@backslash#1{%
+ \ifcat \noexpand#1\noexpand~%
+ \expandafter\TD@active@backslash@
+ \else
+ \@backslashchar
+ \fi
+ #1%
+}
+% \end{macrocode}
+%
+% In order to have guard lines processed correctly, the first test
+% below really must be for |\TD@active@CR| rather than for an
+% active |^^M|.
+% \changes{v\,2.11}{2000/11/06}{Escaped spaces are no longer breakable.
+% (LH)}
+% \begin{macrocode}
+\def\TD@active@backslash@#1{%
+ \ifcase
+ \ifx #1\TD@active@CR 0%
+ \else\ifx #1\TD@active@backslash 1%
+ \else\ifx #1\TD@active@braceleft 2%
+ \else\ifx #1\TD@active@braceright 2%
+ \else\ifx #1\TD@active@bracketleft 2%
+ \else\ifx #1\TD@active@bracketright 2%
+ \else\ifx #1\TD@active@space 3%
+ \else 4\fi\fi\fi\fi\fi\fi\fi
+ \space
+ \expandafter\TD@active@backslash@i
+ \or
+ \@backslashchar\@backslashchar
+ \or
+ \@backslashchar \string#1%
+ \or
+ \@backslashchar \TD@typeset@space
+ \else
+ \@backslashchar
+ \expandafter#1%
+ \fi
+}
+% \end{macrocode}
+% Escaped newlines that are followed by command mode lines are not
+% converted to discretionary spaces.
+% \begin{macrocode}
+\def\TD@active@backslash@i#1{%
+ \ifx #1\TD@percent@token
+ \copy\TD@backslash@box
+ \expandafter\TD@active@CR
+ \else
+ \TD@breakable@space
+ \global\advance \c@codelineno \@ne
+ \expandafter\TD@gobble@whitespace
+ \fi
+ #1%
+}
+% \end{macrocode}
+% The |\tclverb| command uses |\TD@active|\-|@backslash@v| instead of
+% |\TD|\-|@active|\-|@backslash@i|, since it is intended for use on
+% lines that may begin with |%|.
+% \begin{macrocode}
+\def\TD@active@backslash@v#1{%
+ \TD@discretionary@space
+ \ifx #1\TD@percent@token
+ \expandafter\@firstoftwo
+ \fi
+ \TD@gobble@whitespace #1%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+%
+% \begin{macro}{\TD@active@bracketleft}
+% \begin{macro}{\TD@active@bracketright}
+% These macros mainly typeset the corresponding characters, but they
+% also increase or decrease the |\TD@nesting@level| count by one.
+% \begin{macrocode}
+\def\TD@active@bracketleft{[\advance\TD@nesting@level\@ne}
+\def\TD@active@bracketright{]\advance\TD@nesting@level\m@ne}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@active@braceleft}
+% \begin{macro}{\TD@active@braceright}
+% \begin{macro}{\TD@nesting@stack}
+% \changes{v\,2.14}{2001/01/19}{Nesting stack added to cope with code
+% (brace-delimited strings) where brackets aren't properly balanced.
+% (LH)}
+% The |\TD@active@braceleft| and |\TD@active@braceright| work very
+% much like their \texttt{bracket} counterparts, but they also push
+% and pop the current nesting level on and off the |\TD@nesting@stack|
+% macro. The reason for doing this is that brackets aren't always
+% properly balanced in \Tcl\ code, which may result in a
+% |\TD@nesting@level| value which does not mirror how the code really
+% will be interpreted. Braces must however be properly balanced, and
+% therefore it is always right to restore the value of
+% |\TD@nesting@level| that was in force before a brace group began
+% when it is ended.
+%
+% The |\TD@nesting@stack| macro is a \meta{nesting stack}, which is
+% one of the following two things
+% \begin{quote}
+% |\TD@nesting@level|
+% \meta{number}|\def\TD@nesting@stack{|\meta{nesting stack}|}|
+% \end{quote}
+% This means a value is popped off the stack by doing
+% \begin{quote}
+% |\TD@nesting@level=\TD@nesting@stack|
+% \end{quote}
+% and |\TD@nesting@level| is unchanged if the stack is empty.
+% \DoNotIndex{\[,\]}
+% \DoNotIndexHarmless{\PrintChar{`\{}}
+% \DoNotIndexHarmless{\PrintChar{`\}}}
+% \begin{macrocode}
+\begingroup
+ \catcode`\{=12 \catcode`\}=12
+ \catcode`\[=1 \catcode`\]=2
+ \gdef\TD@active@braceleft[{%
+ \expandafter\def \expandafter\TD@nesting@stack \expandafter[%
+ \the\expandafter\TD@nesting@level
+ \expandafter\def \expandafter\TD@nesting@stack
+ \expandafter[\TD@nesting@stack]%
+ ]%
+ \advance\TD@nesting@level\@ne
+ ]
+ \gdef\TD@active@braceright[}%
+ \advance\TD@nesting@level\m@ne
+ \TD@nesting@level=\TD@nesting@stack
+ ]
+\endgroup
+\def\TD@nesting@stack{\TD@nesting@level}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+%
+%
+% \subsection{Paragraph formatting}
+%
+% This subsection contains definitions of control sequences that are
+% mainly related to the formatting of paragraphs.
+%
+% The new implementation of the \texttt{tcl} and \texttt{tcl*}
+% environments is based on inserting the ``discretionary'' backslashes
+% at the linebreaks \emph{after} the paragraph has been broken.
+% Doing this involves reboxing every line in the paragraph, and in this
+% process the line adjustments are changed as well.
+%
+% \begin{macro}{\TD@backslash@box}
+% The |\TD@backslash@box| box register is set to a backslash in the
+% special |\TD@nontcl@font| at the beginning of each \texttt{tcl} and
+% \texttt{tcl*} environment. These backslashes are used to denote
+% ``backslash escaping newline''. The primary reason for keeping this
+% glyph in a box is not that this might be slightly faster to
+% typeset, but to have the \emph{width} of it easily accessible.
+% \begin{macrocode}
+\newbox\TD@backslash@box
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@nesting@level}
+% \begin{macro}{\TD@nesting@penalty}
+% |\TD@nesting@level| is a count register which keeps track of how
+% many brace\slash bracket groups surrounds the current position in
+% the line. It is cleared to zero at the beginning of each paragraph.
+% \begin{macrocode}
+\newcount\TD@nesting@level
+% \end{macrocode}
+% |\TD@nesting@penalty| makes a |\penalty| whose value should depend
+% on the nesting level (the deeper the nest, the larger the penalty).
+% It may also adjust the value of |\linepenalty| to counter that
+% the nesting level has become negative. This is typically needed for
+% lines which say things like ``|} else {|''. The default definition is
+% to make the nesting penalty $100$ times the nesting level and to
+% make the |\linepenalty| equal to
+% \(10 - \min\{0,\mbox{least penalty}\}\).
+% \begin{macrocode}
+\def\TD@nesting@penalty{%
+ \penalty \the\TD@nesting@level 00\relax
+ \ifnum \lastpenalty<-\linepenalty
+ \linepenalty=10%
+ \advance \linepenalty -\lastpenalty
+ \fi
+}
+% \end{macrocode}
+% I doubt that this is necessarily the best algorithm for computing
+% these penalties, so if you are really thorough about your
+% typography you may well want to experiment with other definitions of
+% |\TD@nesting@penalty|. In case you should then find something which
+% works even better then I'm interested to learn about it.
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@reformat@lines}
+% The |\TD@reformat@lines| macro calls itself recursively to reformat
+% all lines on the current vertical list. The first line will remain
+% flush left, but all other lines will be reset flush right. The
+% visible material on the last line will be left as it is, but the
+% last box in all other lines will be replaced by a non-macro font
+% backslash.
+%
+% It is very important that the current vertical list is not the main
+% vertical list.
+% It is assumed that the current vertical list consists of a sequence
+% of \meta{box}, \meta{penalty}, \meta{glue}, with an extra glue item
+% at the top of the list. It is OK if some penalty or glue item is
+% missing. In case the list contains other material as well the line
+% reformatting may be stopped prematurely, but there is a trick that
+% allows one to put arbitrary material between the lines of the
+% reformatted paragraph: rather than doing e.g.
+% \begin{quote}
+% |\mark|\marg{text}
+% \end{quote}
+% in the paragraph, do
+% \begin{quote}
+% |\vadjust{\vbox{\mark{|\meta{text}|}}}|
+% \end{quote}
+% The |\vbox| will be recognised by the paragraph reformatting
+% mechanism as a container for vertical mode material that appears
+% between the lines of the paragraph, so it will simply be unboxed.
+% \changes{v\,2.12}{2000/11/11}{\cs{vbox} containers for vertical
+% material are allowed between the lines of a reformatted
+% paragraph. (LH)}
+%
+% Each line's horizontal list ends with
+% \begin{itemize}
+% \item a box (which contains the space that is to be replaced by a
+% backslash),
+% \item a penalty (at which the paragraph was broken), and
+% \item a glue item (the |\rightskip|).
+% \end{itemize}
+%
+% A tricky feature in the implementation is that the
+% |\bgroup|--|\egroup| nesting will be off by one. The |\bgroup| at
+% the beginning of a |\TD@reformat@line| will be matched by the
+% |\egroup| at the end of the |\TD@reformat@line| that the first one
+% calls!
+% \begin{macrocode}
+\def\TD@reformat@lines{%
+ \bgroup
+ \unskip
+ \count@=\lastpenalty \unpenalty
+ \setbox\z@=\lastbox
+ \ifvoid\z@
+% \end{macrocode}
+% The recursion had already descended down to the last line of the
+% paragraph, and it is now time to reformat it.
+% \begin{macrocode}
+ \egroup
+ \prevdepth=\TD@prevdepth
+ \hbox{%
+ \unhbox\z@
+ \unskip \unpenalty
+ \setbox\z@=\lastbox
+ \copy\TD@backslash@box
+ }%
+ \else
+% \end{macrocode}
+% Else there may be another line, and the |\TD@reformat@lines| recursion
+% must continue to descend. Upon return the box currently in box
+% register zero must be reformatted as a non-first line (flush
+% right) and it cannot be the last line in the paragraph, so it is
+% always correct to replace the last box by a backslash.
+% \begin{macrocode}
+ \TD@reformat@lines
+ \ifvbox\z@ \unvbox\z@ \else
+ \hb@xt@\dimen@{%
+ \hfill
+ \unhbox\z@
+ \unskip \unpenalty
+ \setbox\z@=\lastbox
+ \copy\TD@backslash@box
+ }%
+ \fi
+ \fi
+ \ifnum \count@=\z@ \else \penalty\count@ \fi
+ \egroup
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@reformat@par}
+% The |\TD@reformat@par| macro reformats all lines (they're supposed
+% to constitute a paragraph, but that isn't so important) in the
+% current vertical list. The restrictions of |\TD@reformat@lines| on
+% what may appear in the list apply and there must be at least two
+% lines in the list. |\dimen@| is used to hold the desired width of
+% reformatted paragraphs.
+%
+% More precisely |\TD@reformat@par| takes care of the last line of
+% the paragraph and the possible |\vbox| containers for vertical
+% material that may follow it. Everything in the paragraph that comes
+% before the last line is handled by |\TD@reformat@lines|.
+% \changes{v\,2.12}{2000/11/11}{\cs{vbox} containers for vertical
+% material are allowed after the last line of a reformatted
+% paragraph. (LH)}
+% \begin{macrocode}
+\def\TD@reformat@par{%
+ \unskip
+ \count@=\lastpenalty \unpenalty
+ \setbox\z@=\lastbox
+ \ifvbox\z@
+ \bgroup
+ \TD@reformat@par
+ \egroup
+ \unvbox\z@
+ \else\ifnum \prevgraf>\@ne
+ \dimen@=\@totalleftmargin
+ \advance \dimen@ \linewidth
+ \bgroup
+ \unskip
+ \count@=\lastpenalty \unpenalty
+ \setbox\z@=\lastbox
+ \TD@reformat@lines
+ \hb@xt@\dimen@{\hfill \unhbox\z@ \unskip}%
+ \else
+ \unskip
+ \prevdepth=\TD@prevdepth
+ \box\z@
+ \fi\fi
+ \ifnum \count@=\z@ \else \penalty\count@ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@prevdepth}
+% |\TD@prevdepth| is a macro which is used for storing the value of
+% |\prevdepth| at times where \TeX\ modifies the primitive in unwanted
+% ways. It should always be set globally.
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@begin@tclpar}
+% The |\TD@begin@tclpar| macro is called when a paragraph in a
+% \texttt{tcl} or \texttt{tcl*} environment is about to start. It
+% takes care of setting up things so that the paragraph can later be
+% reformatted using |\TD@reformat@par|, but it also has to make sure
+% that this reformatting doesn't affect the way the paragraph blends
+% in with vertical material before and after it.
+%
+% Reformatting requires that the paragraph is first built in
+% restricted vertical mode, i.e., it has to be built in an explicit
+% |\vbox|. A problem with this is however that it changes the value of
+% |\prevdepth|, which must therefore be explicitly restored.
+% \begin{macrocode}
+\def\TD@begin@tclpar{%
+ \xdef\TD@prevdepth{\the\prevdepth}%
+ \setbox\z@=\vbox\bgroup
+ \color@begingroup
+ \prevdepth=\TD@prevdepth
+ \indent
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@end@tclpar}
+% The |\TD@end@tclpar| macro ends a paragraph begun by
+% |\TD@begin@tclpar|, reformats it (|\TD@reformat@par|), and
+% contributes it to the surrounding vertical list. The |\begingroup|
+% and |\endgroup| are there to sort things out in case the recursion
+% in |\TD@reformat@par| fails to match as intended. The second
+% |\@@par| sees to that the page builder is exercised (without it,
+% several pages may go onto the main vertical list without anything
+% being shipped out).
+% \begin{macrocode}
+\def\TD@end@tclpar{%
+ \@@par
+ \begingroup
+ \skip@=\lastskip
+ \TD@reformat@par
+ \vskip\skip@
+ \endgroup
+ \xdef\TD@prevdepth{\the\prevdepth}%
+ \color@endgroup
+ \egroup
+ \unvbox\z@
+ \prevdepth=\TD@prevdepth
+ \@@par
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\TD@line@indent}
+% |\TD@line@indent| is a |\count| register holding the indentation of
+% the current line, in number of spaces. |\TD@line@indent| should
+% always be assigned globally.
+% \begin{macrocode}
+\newcount\TD@line@indent
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@par@setup}
+% This macro sets up various paragraph formatting parameters for the
+% normal mode. It mainly consists of code from |\macro@code| of
+% \package{doc}.
+% \begin{macrocode}
+\def\TD@par@setup{%
+% \end{macrocode}
+%
+% In theory a \texttt{tcl} environment should consist of a
+% \texttt{trivlist} environment, but the empty space before and after
+% the environment should not be too large.
+% \begin{macrocode}
+ \topsep\MacrocodeTopsep
+% \end{macrocode}
+%
+% The next parameter we set is |\@beginparpenalty|, in order
+% to prevent a page break before such an environment.
+% \begin{macrocode}
+ \@beginparpenalty\predisplaypenalty
+% \end{macrocode}
+%
+% We then start a |\trivlist|, set |\parskip| back to
+% zero and start an empty |\item|.
+% \changes{ \package{doc} v\,1.9b}{1993/12/03}{Forcing any label
+% from macro env.}
+% \begin{macrocode}
+ \if@inlabel\leavevmode\fi
+ \trivlist
+ \parskip\z@skip
+ \item[]%
+% \end{macrocode}
+% However, the \texttt{trivlist} environment is only started to make
+% standard \LaTeX\ happy (and to have the various list-related
+% measurements properly calculated). Everything below will instead
+% by done with \TeX\ primitives.
+% \changes{ \package{pasdoc} v\,1.31}{1999/09/02}{\cs{parshape}
+% assignment added. (LH)}
+% \changes{v\,2.10}{2000/10/08}{\cs{parshape} assignment removed (now
+% done in \cs{TD@begin@tclpar}). (LH)}
+%
+% It is important that the change to a special font does not take
+% place before the above |\item|, otherwise a change to
+% |\baselineskip| will affect the paragraph above.
+% \begin{macrocode}
+ \macro@font
+ \frenchspacing
+% \end{macrocode}
+%
+% \leavevmode
+% \changes{v\,2.12}{2000/11/11}{Assignment to \cs{TD@backslash@box}
+% moved from \cs{TD@typography} to here, so that the size will be
+% right. (LH)}^^A
+% One escape symbol that is particularly common is a single
+% backslash, and this is stored in the |\TD@backslash@box| box. As
+% some encodings (e.g.\ \texttt{OT1}) does not contain a backslash,
+% these escape backslashes are made with |\textbackslash|, rather
+% than an explicit character.
+% \begin{macrocode}
+ \sbox\TD@backslash@box{\TD@nontcl@font\textbackslash}%
+% \end{macrocode}
+%
+% The |\rightskip| is given a generous stretchability of |\linewidth|
+% so that it doesn't matter too much if the lengths of lines in the
+% paragraph varies. Decreasing this value would make the nesting in
+% the code less important.
+% \begin{macrocode}
+ \parindent=\@totalleftmargin
+ \advance \parindent \MacroIndent
+ \leftskip=\z@skip
+ \rightskip=\z@ \@plus \linewidth\relax
+% \end{macrocode}
+% The next two lines are from the definition of the
+% \texttt{macrocode} environment, and I (LH) have no idea what they are
+% good for, but I suppose I can keep them, at least for now.
+% \begin{macrocode}
+ \global\@newlistfalse
+ \global\@minipagefalse
+% \end{macrocode}
+% \changes{ \package{pasdoc} v\,1.31}{1999/09/02}{Made list
+% environments indent line numbers. (LH)}
+% \changes{v\,2.33}{2001/12/12}{Made list environments not indent
+% line numbers per default, but providing a way for the user to
+% change this. (LH)}
+% Line numbers are inserted using |\everypar|.
+% \begin{macrocode}
+ \ifcodeline@index
+ \everypar={\llap{%
+ \PrintCodelineNo\ \hskip\codelineindentfactor\@totalleftmargin
+ }}%
+ \else
+ \everypar={}%
+ \fi
+% \end{macrocode}
+%
+% These commands replace \package{doc}'s final module processing
+% macros with macros that work in the \texttt{tcl} environment.
+% \begin{macrocode}
+ \let\pm@module=\TD@pm@module
+ \let\star@module=\TD@star@module
+ \let\slash@module=\TD@slash@module
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\codelineindentfactor}
+% The |\codelineindentfactor| macro specifies by which fraction of
+% |\@totalleftmargin| that the list environment indentation of
+% codeline numbers will be countered. |0| means that the numbers will
+% be indented, |1| or empty (the default) that they will not be
+% indented. |0.5| would mean that the effective indentation is half
+% that of other material.
+% \begin{macrocode}
+\let\codelineindentfactor\@empty
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@setup@parshape}
+% This macro sets the shape of the current paragraph, primarily based
+% on the value in |\TD@line@indent|, and makes the final indentation
+% of the first line. By the time it gets called, there usually already
+% is some material (|\indent|, codeline number, and possibly a
+% \package{docstrip} guard) in the paragraph horizontal list.
+%
+% The basic area in which the paragraph material is to be put has a
+% left margin at |\@totalleftmargin|${}+{}$|\MacroIndent| and a right
+% margin at |\@totalleftmargin|${}+{}$|\linewidth| (in both cases the
+% position is that much to the right of the left edge of the galley).
+% The printed codeline number (if there is one) will be put to the
+% left of the left margin, but all other material is indented at least
+% the width of another |\TD@line@indent| spaces. In the first line
+% that will be done through an explicit kern, but in subsequent lines
+% it will instead be done through a |\parshape| assignment. On these
+% subsequent lines, there will be an additional indentation of\/
+% $1\,\mathrm{em}$ to mark the continuation.
+%
+% When the paragraph is broken, the right margin will be moved to the
+% right by the width of a space minus the width of the
+% |\TD@backslash@box|. The reason for this is that the paragraph will
+% be broken with spaces (from |\TD@breakable@space|) at the end of
+% lines, but that these spaces will later be replaced by the
+% backslash in |\TD@backslash@box|. As that doesn't happen in the
+% very last line of the paragraph however, something special must be
+% done there. The option chosen is to give the |\parfillskip| a
+% nonzero natural width.
+%
+% The length |\@totalleftmargin|${}+{}$|\MacroIndent| is put in
+% |\parindent| at the beginning of the environment.
+% \begin{macrocode}
+\def\TD@setup@parshape{%
+ \parfillskip=\fontdimen\tw@\font \@plus 1fil%
+ \advance \parfillskip -\wd\TD@backslash@box
+ \dimen@=\MacroIndent
+ \advance \dimen@ \TD@line@indent\fontdimen\tw@\font
+ \advance \dimen@ 1em%
+ \dimen@ii=\linewidth
+ \advance \dimen@ii -\dimen@
+ \dimen4=\linewidth
+ \advance \dimen@ \@totalleftmargin
+ \advance \dimen4 \@totalleftmargin
+ \advance \dimen@ii -\parfillskip
+ \advance \dimen4 -\parfillskip
+ \parshape \tw@ \z@ \dimen4 \dimen@ \dimen@ii
+% \end{macrocode}
+% Then one just needs one more kern to indent the first line
+% properly.
+% \begin{macrocode}
+ \kern \TD@line@indent\fontdimen\tw@\font
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@trace@pardimen}
+% This macro is for tracing dimens that are of interest for paragraph
+% breaking. Its call syntax is
+% \begin{quote}
+% |\TD@trace@pardimen|\marg{text}\marg{dimen}
+% \end{quote}
+% where \meta{text} will be written to the log file to identify the
+% dimension, and \meta{dimen} is the dimen register in question (it
+% can be anything that can appear after |\the|).
+%
+% To reduce the amount of text written, this macro only does anything
+% if the \TeX\ parameter |\tracingparagraphs| is positive.
+% \begin{macrocode}
+%<*partrace>
+\def\TD@trace@pardimen#1#2{%
+ \ifnum \tracingparagraphs>\z@
+ \immediate\write\m@ne{#1 \the#2}%
+ \fi
+}
+%</partrace>
+% \end{macrocode}
+% \changes{ \package{pasdoc} v\,1.21}{1999/08/15}{Added macro and
+% some calls of it. All of those are however surrounded by
+% \texttt{partrace} guards. (LH)}
+% \end{macro}
+%
+%
+%
+% \subsection{User interface}
+%
+% This subsection defines the actual environment and the
+% commands and parameters intended to be user-definable.
+%
+%
+% \begin{macro}{\settabsize}
+% \changes{v\,2.12}{2000/11/09}{New command for setting the tab size.
+% (LH)}
+% \begin{macro}{\TD@tab@size}
+% \changes{v\,2.12}{2000/11/09}{New name for \cs{c@tabSize}; no longer a
+% count register. (LH)}
+% The |\TD@tab@size| control sequence stores (as a |\chardef| token)
+% the number of spaces that are equivalent to one tab; the default
+% value is 8. To set this number, one uses the command |\settabsize|,
+% which has the syntax
+% \begin{quote}
+% |\settabsize|\marg{new size}
+% \end{quote}
+% The effect of |\settabsize| is local.
+% \begin{macrocode}
+\newcommand*\settabsize[1]{\chardef\TD@tab@size=#1\relax}
+\settabsize{8}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+%
+% \begin{environment}{tcl}
+% \begin{environment}{tcl*}
+% This is some kind of a definition. There are aspects of the
+% interaction with \texttt{trivlist} that I (LH) don't understand,
+% but it appears to work.
+% \begin{macrocode}
+\newenvironment{tcl}{%
+ \TD@general
+ \TD@typography
+ \TD@par@setup
+ \TD@command
+}{%
+ \global\@inlabelfalse
+ \endtrivlist
+}
+% \end{macrocode}
+% \begin{macrocode}
+\newenvironment{tcl*}{%
+ \TD@visible@whitespace
+ \TD@general
+ \TD@typography
+ \TD@par@setup
+ \TD@command
+}{%
+ \global\@inlabelfalse
+ \endtrivlist
+}
+% \end{macrocode}
+% \end{environment}\end{environment}
+%
+% \begin{macro}{\tclverb}
+% \begin{macro}{\TD@verb}
+% The |\tclverb| macro is for typesetting short passages of \Tcl\ code
+% which one does not want to have a special paragraph for. It is
+% similar to the standard \LaTeX\ command |\verb|, but it has a couple
+% of extra features. One is that spaces that are not followed by more
+% whitespace are discretionary breakpoints, just as in the \texttt{tcl}
+% environment. Another is that a newline can be escaped by putting a
+% backslash at the end of an input line. Such an escaped newline will
+% count as a space, and whitespace at the beginning of the line
+% following it will be ignored. A percent character immediately
+% following an escaped newline will also be ignored.
+%
+% |\tclverb| has a |*| form |\tclverb*|, which is analogous to the
+% standard \LaTeX\ |\verb*|, i.e., spaces are typeset using ``visible
+% space'' symbols.
+% \begin{macrocode}
+\newcommand\tclverb{%
+ \relax\ifmmode\hbox\else\leavevmode\null\fi
+ \bgroup
+ \@ifstar{\TD@visible@whitespace\TD@verb}\TD@verb
+}
+% \end{macrocode}
+% \DoNotIndex{\ ,\^,\\}
+% \begin{macrocode}
+\def\TD@verb{%
+ \let\TD@active@backslash@i=\TD@active@backslash@v
+ \let\TD@active@CR=\TD@active@CRv
+ \let\TD@breakable@space=\TD@discretionary@space
+ \TD@general
+ \catcode`\^^I=\active
+ \catcode`\ =\active
+ \catcode`\\=\active
+ \TD@typography
+ \verbatim@font
+ \sbox\TD@backslash@box{\TD@nontcl@font\textbackslash}%
+ \@sverb
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+%
+% \begin{macro}{\TclInput}
+% The |\TclInput| macro is very much like the standard \LaTeX\
+% |\input|, but it is intended to be used in command mode, for
+% inputting \Tcl\ files that have not been marked up. |\input| would
+% work in this case, but there would be errors at the first and last
+% lines of the |\input|ted file.
+% \begin{macrocode}
+\newcommand\TclInput[1]{%
+ \IfFileExists{#1}{%
+ \@addtofilelist{#1}%
+ \begingroup
+ \TD@normal
+ \let\TD@start@n@line=\TD@start@n@line@i
+ \expandafter\TD@start@n@line
+ \@@input\@filef@und\TD@percent@token
+ \endgroup
+ }{\PackageError{tclldoc}{No file #1}\@eha}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MakeShortTclverb}
+% This definition follows \package{doc}'s |\MakeShortVerb| pretty
+% close.
+% \DoNotIndex{\~}
+% \begin{macrocode}
+\newcommand\MakeShortTclverb[1]{%
+ \expandafter\ifx \csname cc\string#1\endcsname\relax
+ \PackageInfo{tclldoc}{%
+ Made \expandafter\@gobble\string#1 a short %
+ reference for \string\tclverb}%
+ \add@special{#1}%
+ \expandafter\xdef \csname cc\string#1\endcsname{\the\catcode`#1}%
+ \begingroup
+ \lccode`\~=`#1%
+ \lowercase{%
+ \global\expandafter\let
+ \csname ac\string#1\endcsname ~%
+ \gdef~{\tclverb~}}%
+ \endgroup
+ \global\catcode`#1\active
+ \else
+ \PackageInfo{tclldoc}{%
+ \expandafter\@gobble\string#1 already a short verb %
+ reference}%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \section{Miscellaneous markup features}
+%
+% \subsection{Namespaces}
+%
+% \changes{v\,2.10}{2000/10/13}{Added namespace support. (LH)}
+%
+% \begin{macro}{\setnamespace}
+% \begin{macro}{\TD@convert@colons}
+% Since it is common that many identifiers in the same namespace are
+% defined in sequence, one can specify a default namespace to use for
+% all commands where no explicit namespace is given. This is done
+% using the |\setnamespace| command, whose syntax is
+% \begin{quote}
+% |\setnamespace|\marg{namespace}
+% \end{quote}
+% This converts the \meta{namespace} to a harmless character string
+% and locally assigns it to the |\TD@namespace| macro, which stores
+% the current default namespace. |\TD@convert@colons| replaces all
+% |::| substrings in the namespace by |\namespaceseparator|s.
+% \changes{v\,2.33}{2001/12/12}{Converting \texttt{::} in namespace
+% names. (LH)}
+% \begin{macrocode}
+\newcommand\setnamespace[1]{%
+ \MakeHarmless\TD@namespace{#1}%
+ \protected@edef\TD@namespace{%
+ \expandafter\TD@convert@colons \TD@namespace ::\relax
+ }
+}
+% \end{macrocode}
+% \begin{macrocode}
+\def\TD@convert@colons#1::#2{%
+ #1%
+ \ifx \relax#2\else
+ \noexpand\namespaceseparator
+ \TD@convert@colons #2%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@namespace}
+% At the beginning of a document, the default namespace is the global
+% namespace, which is represented by the empty string.
+% \begin{macrocode}
+\let\TD@namespace\@empty
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\buildname}
+% \changes{v\,2.13}{2000/12/16}{Added \cs{@empty} after test for
+% \cs{NoValue}, so that it works for empty arguments. (LH)}
+% \begin{macro}{\namespaceseparator}
+% \changes{v\,2.12}{2000/11/25}{Command added. (LH)}
+% The |\buildname| macro builds a qualified name from a namespace and
+% a name tail. It has the syntax
+% \begin{quote}
+% |\buildname|\marg{namespace}\marg{name}
+% \end{quote}
+% where \meta{name} is a harmless character sequence and
+% \meta{namespace} is a harmless character sequence or the token
+% |\NoValue|. If \meta{namespace} is |\NoValue| then the default
+% namespace is used. |\buildname| does all processing at expand-time.
+%
+% If the namespace is the empty string (the global namespace) then
+% \meta{name} is returned without a `|::|' prefix; this is for the
+% sake of compatibility with pre-v\,8 \Tcl s.
+% \begin{macrocode}
+\newcommand\buildname[2]{%
+ \ifx \NoValue#1\@empty
+ \ifx \@empty\TD@namespace \else
+ \TD@namespace\namespaceseparator
+ \fi
+ \else
+ \ifx $#1$\else #1\namespaceseparator \fi
+ \fi
+ #2%
+}
+% \end{macrocode}
+% The |\namespaceseparator| command typesets a namespace separator. By
+% default it is two colons separated by a penalty, but the user may
+% redefine it.
+% \begin{macrocode}
+\DeclareRobustCommand\namespaceseparator{:\penalty\hyphenpenalty:}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\namespacephrase}
+% The |\namespacephrase| macro stores the phrase that will be used
+% for `namespace' in indices and the like. It is meant to be
+% redefinable. The contents must be robust.
+% \changes{v\,2.25}{2001/08/14}{Macro added. (LH)}
+% \begin{macrocode}
+\providecommand*\namespacephrase{name\-space}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{instance}{docindex}{index}
+% \changes{v\,2.21}{2001/03/26}{Modified as per the v\,1.00 change to
+% \package{docindex}. (LH)}
+% The \texttt{index} instance of template type \texttt{docindex}
+% (defined by the \package{docindex} package) is redefined to allow
+% name and namespace levels to be joined.
+% \begin{macrocode}
+\@ifpackagewith{docidx2e}{usedocindexps}{%
+ \@namedef{TP@I{}{docindex}{index}}#1#2{%
+ \begingroup
+ \@letinstance\DI@indexitem@i{indexitem}{fixed-r1a}%
+ \@letinstance\DI@indexitem@ii{indexitem}{aloneaccept2}%
+ \@letinstance\DI@indexitem@iii{indexitem}{fixed3}%
+ \columnsep=10pt%
+ \parskip=0pt plus 1pt%
+ \def\DI@letter@skip{10pt plus 2pt minus 3pt}%
+ \def\DI@letter@format##1{%
+ \par
+ \hb@xt@\hsize{\hfil\textbf{##1}\hfil}%
+ \nopagebreak
+ }%
+ \def\+{-}%
+ \IfFileExists{\jobname.ind}{%
+ \ifnum \c@IndexColumns>\@ne
+ \begin{multicols}{\c@IndexColumns}[#1][\IndexMin]%
+ \else
+ \enough@room{\IndexMin}%
+ #1\par
+ \addvspace\multicolsep
+ \fi
+ \pagestyle{docindex}%
+ \small
+ \@nobreakfalse
+ \DI@ind@setup
+ \input{\jobname.ind}%
+ \DI@item@nojoin
+ \thispagestyle{docindex}
+ \ifnum \c@IndexColumns>\@ne
+ \end{multicols}%
+ \else
+ \enough@room\postmulticols
+ \addvspace\multicolsep
+ \fi
+ \normalsize #2\par
+ }{\typeout{No file \jobname.ind.}}%
+ \endgroup
+ }
+}{%
+ \@namedef{TP@I{}{docindex}{index}}#1#2{%
+ \begingroup
+ \@letinstance\DI@indexitem@i{indexitem}{fixed-r1a}%
+ \@letinstance\DI@indexitem@ii{indexitem}{aloneaccept2}%
+ \@letinstance\DI@indexitem@iii{indexitem}{fixed3}%
+ \columnsep=10pt%
+ \parskip=0pt plus 1pt%
+ \def\DI@letter@skip{10pt plus 2pt minus 3pt}%
+ \def\DI@letter@format##1{%
+ \par
+ \hb@xt@\hsize{\hfil\textbf{##1}\hfil}%
+ \nopagebreak
+ }%
+ \def\+{-}%
+ \IfFileExists{\jobname.ind}{%
+ \ifnum \c@IndexColumns>\@ne
+ \begin{multicols}{\c@IndexColumns}[#1][\IndexMin]%
+ \else
+ \enough@room{\IndexMin}%
+ #1\par
+ \addvspace\multicolsep
+ \fi
+ \small
+ \@nobreakfalse
+ \DI@ind@setup
+ \input{\jobname.ind}%
+ \DI@item@nojoin
+ \ifnum \c@IndexColumns>\@ne
+ \end{multicols}%
+ \else
+ \enough@room\postmulticols
+ \addvspace\multicolsep
+ \fi
+ \normalsize #2\par
+ }{\typeout{No file \jobname.ind.}}%
+ \endgroup
+ }
+}
+% \end{macrocode}
+% \end{instance}
+%
+%
+%
+% \subsection{\texttt{macro}-like environments}
+%
+% This subsection contains the definitions of a couple of environments
+% which, like \package{doc}'s \texttt{macro}, are for marking up the
+% document (what is defined and where). These environments are defined
+% using the |\New|\-|Macro|\-|Environment| command of the \package{xdoc2}
+% package.
+% \changes{ \package{pasdoc} v\,1.40}{1999/12/05}{\texttt{macro}-like
+% environments redefined. (LH)}
+% \changes{v\,2.00}{2000/07/17}{\texttt{macro}-like environments are
+% defined using the \cs{NewMacroEnvironment} command. The
+% \cs{TD@identifier}, \cs{SpecialMainTclIndex}, and
+% \cs{PrintTclName} macros were removed. (LH)}
+% \changes{v\,2.12}{2000/11/26}{Using starred form of
+% \cs{NewMacroEnvironment} for the \texttt{variable}, \texttt{proc},
+% \texttt{arrayvar}, and \texttt{arrayentry} environments, so that
+% the marginal headings can be broken. (LH)}
+%
+% \begin{macrocode}
+\MetaNormalfont
+% \end{macrocode}
+% \changes{v\,2.32}{2001/11/30}{Added \cs{MetaNormalfont} as a global
+% declaration and removed it from the commands that did this locally.
+% There were simply so many places where it should have been
+% otherwise that the resulting code would have looked rudiculous.
+% (LH)}
+%
+% \begin{environment}{variable}
+% The \texttt{variable} environment has the syntax
+% \begin{quote}
+% |\begin{variable}|\oarg{namespace}\marg{variable}
+% \end{quote}
+% It makes a marginal heading, index entry, etc.\@ for the
+% \meta{variable} variable in the \meta{namespace} namespace
+% (if specified, otherwise in the default namespace).
+% \begin{macrocode}
+\NewMacroEnvironment*{variable}%
+ {\XD@grab@harmless@oarg\XD@grab@harmless\relax}{2}%
+ {\XDParToMargin{\MacroFont\buildname{#1}{#2} \normalfont (var.)}}%
+ {\TD@main@index{#1}{#2}{var.}{}}%
+ {{\buildname{#1}{#2}}{\texttt{\buildname{#1}{#2}} variable}}
+ {}%
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{proc}
+% The \texttt{proc} environment has the syntax
+% \begin{quote}
+% |\begin{proc}|\oarg{namespace}\marg{proc}
+% \end{quote}
+% It makes a marginal heading, index entry, etc.\@ for the \meta{proc}
+% procedure in the \meta{namespace} namespace (if specified, otherwise
+% in the default namespace).
+% \begin{macrocode}
+\NewMacroEnvironment*{proc}%
+ {\XD@grab@harmless@oarg\XD@grab@harmless\relax}{2}%
+ {\XDParToMargin{\MacroFont\buildname{#1}{#2} \normalfont (proc)}}%
+ {\TD@main@index{#1}{#2}{proc}{}}%
+ {{\buildname{#1}{#2}}{\texttt{\buildname{#1}{#2}} proc}}
+ {}%
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{arrayvar}
+% \changes{v\,2.00}{2000/07/17}{Environment added. (LH)}
+% \changes{v\,2.12}{2000/11/09}{Made last argument optional. (LH)}
+% \changes{v\,2.13}{2000/12/15}{Not using \cs{meta} for the
+% \meta{index-des} argument. (LH)}
+% \begin{environment}{arrayentry}
+% \changes{v\,2.02}{2000/08/21}{Environment added. (LH)}
+% The \texttt{arrayvar} and \texttt{arrayentry} environments are for
+% array variables; \texttt{arrayvar} is for the array as a whole,
+% whereas \texttt{arrayentry} is for individual entries in the array
+% that (for some reason) are important enough to warrant special
+% attention. The respective syntaxes are
+% \begin{quote}
+% |\begin{arrayvar}|\oarg{namespace}\marg{array}\oarg{index-des}\\
+% |\begin{arrayentry}|\oarg{namespace}\marg{array}\marg{entry}
+% \end{quote}
+% Here \meta{array} is the name of an array variable, \meta{entry} is
+% the name of an entry, and \meta{index-des} is a short piece of text
+% (seldom more than one word) which describes what is used as indices
+% into that array.
+% \changes{v\,2.14}{2001/01/12}{Corrected grabbing of the third
+% argument of the \texttt{arrayvar} environment: it should be an
+% oarg, not a harmless oarg. (LH)}
+% \begin{macrocode}
+\NewMacroEnvironment*{arrayvar}{%
+ \XD@grab@harmless@oarg\XD@grab@harmless\relax\XD@grab@oarg
+}{3}%
+ {\XDParToMargin{\MacroFont \buildname{#1}{#2}%
+ \ifx \NoValue#3%
+ \space\normalfont (array)%
+ \else
+ \penalty\hyphenpenalty(\mbox{\meta@font@select#3})%
+ \fi
+ }}%
+ {\TD@main@index{#1}{#2}{array}{%
+ \ifx \NoValue#3\@empty\else
+ \LevelSorted{#3}{\protect\mbox{\textit{#3}} entries}%
+ \fi
+ }}%
+ {{\buildname{#1}{#2}}{\texttt{\buildname{#1}{#2}} array}}
+ {}%
+% \end{macrocode}
+% \begin{macrocode}
+\NewMacroEnvironment*{arrayentry}{%
+ \XD@grab@harmless@oarg\XD@grab@harmless\relax\XD@grab@harmless\relax
+}{3}%
+ {\XDParToMargin{%
+ \MacroFont \buildname{#1}{#2}%
+ \penalty\hyphenpenalty(#3)%
+ }}%
+ {\TD@main@index{#1}{#2}{array}{\LevelSorted{#3}{\texttt{#3}}}}%
+ {{\buildname{#1}{#2}(#3)}{\texttt{\buildname{#1}{#2}(#3)}}}
+ {}%
+% \end{macrocode}
+% \end{environment}\end{environment}
+%
+% \begin{macro}{\describestring}
+% \changes{v\,2.01}{2000/08/12}{Command added. (LH)}
+% \changes{v\,2.12}{2000/11/21}{Optional argument added. (LH)}
+% \changes{v\,2.13}{2000/12/16}{Second optional argument added. (LH)}
+% \changes{v\,2.20}{2001/03/03}{Putting namespace on the second
+% level. (LH)}
+% The |\describestring| command has the syntax
+% \begin{quote}
+% |\describestring|\oarg{type}\oarg{namespace}\marg{string}
+% \end{quote}
+% It is similar to \package{xdoc}'s own |\describe|\-|cs|\-|family|
+% command, but it has a couple of extra features which are connected
+% to the optional arguments and it doesn't prepend a backslash to
+% the name of the thing being described. When the \meta{type} argument
+% is present, it is taken as a ``type declaration'' of the
+% \meta{string} being described and `(\meta{type})' will be put as a
+% suffix to the \meta{string}. When the \oarg{namespace} argument is
+% present it means that the string being described is really the name
+% of something (e.g.\ a procedure or variable) which exists in a
+% namespace, and the complete name is formed by passing both
+% \meta{namespace} and \meta{string} as arguments to |\buildname|.
+% Note that an empty \meta{namespace} argument is not quite the
+% same thing as no \meta{namespace} argument.
+% \begin{macrocode}
+\NewDescribeCommand{\describestring}{%
+ \XD@grab@oarg\XD@grab@harmless@oarg\XD@grab@harmless{}%
+}{3}{%
+ \GenericDescribePrint{%
+ \MacroFont
+ \ifx \NoValue#2\@empty
+ #3%
+ \else
+ \buildname{#2}{#3}%
+ \fi
+ \ifx \NoValue#1\@empty \else\ \normalfont(#1)\fi
+ }%
+ \begingroup
+ \def\meta##1{(##1)}%
+ \unrestored@protected@xdef\@gtempa{#3}%
+ \endgroup
+ \IndexEntry{%
+ \ifx \NoValue#2\@empty
+ \LevelSorted{\@gtempa}{%
+ \texttt{#3}%
+ \ifx \NoValue#1\@empty \else\space(#1)\fi
+ }%
+ \else
+ \LevelSorted{\@gtempa}{%
+ \texttt{#3}\ifx \NoValue#1\@empty \else\space(#1)\fi
+ }%
+ \ifx $#2$%
+ \LevelSorted{ }{global \namespacephrase}%
+ \else
+ \LevelSorted{#2}{\texttt{#2} \namespacephrase}%
+ \fi
+ \fi
+ }{usage}{\thepage}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\describeopt}
+% \changes{v\,2.24}{2001/08/11}{Command added. (LH)}
+% \changes{v\,2.31}{2001/11/03}{Star-form added. (LH)}
+% The |\describeopt| macro is a |\describe|\dots\ command for options
+% of commands. The syntax is
+% \begin{quote}
+% |\describeopt|*\oarg{namespace}\marg{command}\oarg{type}^^A
+% \marg{option}
+% \end{quote}
+% where \meta{command} is the name of the command and \meta{option} is
+% the name of the option. \meta{namespace} is the namespace of the
+% \meta{command}, if that is not the global namespace. \meta{type} is
+% the type description for the command, if different from `proc'.
+% The |*| form of this command does not print a marginal note: it
+% only makes an index entry.
+% \begin{macrocode}
+\NewDescribeCommand{\describeopt}{%
+ \XD@grab@sarg{*}\XD@grab@harmless@oarg\XD@grab@harmless{}%
+ \XD@grab@oarg\XD@grab@harmless{}%
+}{5}{%
+ \ifx \BooleanFalse#1%
+ \GenericDescribePrint{%
+ \MacroFont #5\ \normalfont option%
+ }%
+ \fi
+ \begingroup
+ \def\meta##1{(##1)}%
+ \unrestored@protected@xdef\@gtempa{#3}%
+ \endgroup
+ \IndexEntry{%
+ \LevelSorted{\@gtempa}{%
+ \texttt{#3} (\ifx \NoValue#4\@empty proc\else #4\fi)%
+ }%
+ \ifx \NoValue#2\@empty
+ \LevelSorted{ }{global \namespacephrase}%
+ \else
+ \LevelSorted{#2}{\texttt{#2} \namespacephrase}%
+ \fi
+ \LevelSorted{#5}{\texttt{#5} option}%
+ }{usage}{\thepage}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\TD@main@index}
+% \changes{v\,2.10}{2000/10/14}{Generalized macro. (LH)}
+% \changes{v\,2.12}{2000/11/25}{Sorting by base name first, not by
+% namespace first. (LH)}
+% \changes{v\,2.20}{2001/03/03}{Putting namespace on the second
+% level. (LH)}
+% The |\TD@main@index| macro has the syntax
+% \begin{quote}
+% |\TD@main@index|\marg{namespace}\marg{name}\marg{type}^^A
+% \marg{extra}
+% \end{quote}
+% It makes a \texttt{main} index entry. The top level of this entry
+% is like an entry for the \meta{name} object of type \meta{type} in
+% the \meta{namespace} namespace. The entry may have one or more
+% sublevels\footnote{But no more than one extra level is recommended,
+% as \package{makeindex} can handle at most three levels.} specified
+% in the \meta{extra}; these are then made using explicit
+% |\LevelSame| or |\LevelSorted| commands. \meta{name} and
+% \meta{namespace} are as for the |\buildname| macro, whereas
+% \meta{type} is a description, e.g. `\texttt{proc}', that gets
+% appended to the printed text of the entry's top level.
+% \begin{macrocode}
+\def\TD@main@index#1#2#3#4{%
+ \XDMainIndex{%
+ \LevelSorted{#2}{\texttt{#2} (#3)}%
+ \ifx \NoValue#1\@empty
+ \ifx \@empty\TD@namespace
+ \LevelSorted{ }{global \namespacephrase}%
+ \else
+ \LevelSorted{\TD@namespace}%
+ {\texttt{\TD@namespace} \namespacephrase}%
+ \fi
+ \else
+ \ifx $#1$%
+ \LevelSorted{ }{global \namespacephrase}%
+ \else
+ \LevelSorted{#1}{\texttt{#1} \namespacephrase}%
+ \fi
+ \fi
+ #4%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{Cfunction}
+% \changes{v\,2.40}{2003/04/05}{Environment added. (LH)}
+% \begin{environment}{Cvariable}
+% \changes{v\,2.40}{2003/04/05}{Environment added. (LH)}
+% \begin{environment}{Ctype}
+% \changes{v\,2.40}{2003/04/05}{Environment added. (LH)}
+% The \texttt{Cfunction}, \texttt{Cvariable}, and \texttt{Ctype}
+% environments are for making a marginal heading, index entry, etc.\@
+% for a C function, variable, or type respectively. They all take as
+% their single argument the name of the thing that will be defined.
+% \begin{macrocode}
+\NewMacroEnvironment*{Cfunction}{\XD@grab@harmless\relax}{1}%
+ {\XDParToMargin{\small\Cfunctionidentifier{#1} (C~function)}}%
+ {\XDMainIndex{%
+ \LevelSorted{#1}{\Cfunctionidentifier{#1} (C~function)}%
+ }}%
+ {{#1}{\Cfunctionidentifier{#1} C~function}}
+ {}%
+\NewMacroEnvironment*{Cvariable}{\XD@grab@harmless\relax}{1}%
+ {\XDParToMargin{\small\Cvariableidentifier{#1} (C~variable)}}%
+ {\XDMainIndex{%
+ \LevelSorted{#1}{\Cvariableidentifier{#1} (C~variable)}%
+ }}%
+ {{#1}{\Cvariableidentifier{#1} C~variable}}
+ {}%
+\NewMacroEnvironment*{Ctype}{\XD@grab@harmless\relax}{1}%
+ {\XDParToMargin{\small\Ctypeidentifier{#1} (C~type)}}%
+ {\XDMainIndex{%
+ \LevelSorted{#1}{\Ctypeidentifier{#1} (C~type)}%
+ }}%
+ {{#1}{\Ctypeidentifier{#1} C~type}}
+ {}%
+% \end{macrocode}
+% \end{environment}\end{environment}\end{environment}
+%
+% \begin{macro}{\Cfunctionidentifier}
+% \changes{v\,2.40}{2003/04/05}{Macro added. (LH)}
+% \begin{macro}{\Cvariableidentifier}
+% \changes{v\,2.40}{2003/04/05}{Macro added. (LH)}
+% \begin{macro}{\Ctypeidentifier}
+% \changes{v\,2.40}{2003/04/05}{Macro added. (LH)}
+% These macros are used by \texttt{Cfunction}, \texttt{Cvariable}, and
+% \texttt{Ctype} to format the identifiers of C functions, variables,
+% and types respectively; the syntax is e.g.
+% \begin{quote}
+% |\Cfunctionidentifier|\marg{function name}
+% \end{quote}
+% They default to typeset them in an italic font---this is what CWEB
+% uses---but it is meant to be configurable.
+% \begin{macrocode}
+\newcommand*{\Cfunctionidentifier}[1]{\textit{#1}}
+\newcommand*{\Cvariableidentifier}[1]{\textit{#1}}
+\newcommand*{\Ctypeidentifier}[1]{\textit{#1}}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+%
+% \subsection{Regular expressions and friends}
+%
+% I have noticed that when one is describing the syntax of some \Tcl\
+% command\slash procedure, one often ends up writing argument lists with
+% lots of optional, repeated, or variant parts. In general one can of
+% course specify these using BNF syntax diagrams, but whereas occurrences
+% of the three syntactic constructions mentioned above are plenty,
+% there are much fewer occurrences of for example nesting. Since
+% furthermore even the simplest optional or repeated element
+% requires an extra syntactic term to be defined, it becomes interesting
+% to search for an alternative way of specifying these constructions.
+% One that is close at hand is that of regular expressions, as that is
+% anyway a part of the \Tcl\ language.
+%
+% \begin{macro}{\regstar}
+% \begin{macro}{\regplus}
+% \begin{macro}{\regopt}
+% These commands are used to modify the meaning of another syntactic
+% element. |\regstar| puts a star $^*$ on something, meaning it is
+% repeated zero or more times. |\regplus| puts a plus $^+$ on
+% something, meaning it is repeated one or more times. |\regopt| puts
+% a question mark $^?$ on something, meaning it is optional. Normally
+% these commands are simply put right after what they should modify,
+% but if the ``something'' is a regular expression block, i.e., a
+% \texttt{regblock} environment, then these things should be put as
+% the \meta{modifier} in
+% \begin{quote}
+% |\begin{regblock}|\oarg{modifier}\\
+% | |\textellipsis\\
+% |\end{regblock}|
+% \end{quote}
+% In particular, they should \emph{not} be put after the
+% |\end{regblock}|, as that may impair the placement of the exponent.
+% \begin{macrocode}
+\newcommand\regstar{\ensuremath{^*}}
+\newcommand\regplus{\ensuremath{^+}}
+\newcommand\regopt{\ensuremath{^?}}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+% \begin{macro}{\TD@delim@size}
+% \begin{macro}{\TD@delim@size@G}
+% These control sequences are used in determining what size the
+% delimiters (parentheses) around a regular expression block should
+% have. The values specify what should be the least size of a
+% delimiter that bracket a piece of text, and are interpreted as
+% follows: \(0={}\)normal size, \(1={}\)|\big| size, \(2={}\)|\Big|
+% size, \(3={}\)|\bigg| size, and $4$ and above is |\Bigg| size.
+%
+% |\TD@delim@size@G| is a macro which is always set globally and
+% which keeps track of the delimiter size at the innermost level.
+% |\TD@delim@size| is a |\count| register that is assigned locally
+% and is used for keeping track of delimiter sizes at all other
+% levels. Commands like |\word|, which contribute a delimiter to some
+% piece of text, should set |\TD@delim@size@G|.
+% \begin{macrocode}
+\newcount\TD@delim@size
+\gdef\TD@delim@size@G{0}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{environment}{regblock}
+% The \texttt{regblock} environment embarks upon a rather tricky scheme
+% of boxing and unboxing to determine the proper delimiter size. The
+% basic idea is that the contents of the environment are first typeset
+% in an \texttt{lrbox} environment, and |\TD@delim@size@G| is set to
+% its proper value. Then the left delimiter is set at this size, the
+% saved box is unboxed, and finally the right delimiter is set. All
+% through the process, the value of |\TD@delim@size@G| at the
+% beginning of the \texttt{regblock} environment has been saved in
+% |\TD@delim@size| and at the end |\TD@delim@size@G| is set to the
+% maximum of its old value and one plus its value inside the
+% \texttt{regblock} environment. This makes it possible to nest
+% \texttt{regblock} environments.
+%
+% It is not quite that easy, though. A regular expression can consist
+% of several branches, which must be separated by vertical bars.
+% These bars should be the same size as the delimiters around the
+% regular expression, and hence the bars cannot be typeset before
+% every branch has been typeset. Therefore the \texttt{regblock}
+% environment starts an extra horizontal list (the |\hbox|) for the
+% sole purpose of storing the branches that have already been typeset
+% (and \emph{only} these). Each branch is put on the list as a box.
+% When all branches have been typeset, they are first removed from the
+% list (by |\TD@join@branches|), and then they are inserted again, but
+% this time they are unboxed and separated by suitable delimiters.
+% Finally the |\hbox| is ended and almost immediately unboxed.
+%
+% \changes{v\,2.40}{2003/04/05}{Renamed the \texttt{regexp}
+% environment to \texttt{regblock}. A \texttt{regexp} environment
+% is provided for compatibility. (LH)}
+% \begin{macrocode}
+\newenvironment{regblock}[1][]{%
+ \leavevmode
+ \def\TD@modifier{#1}%
+ \TD@delim@size=\TD@delim@size@G
+ \let\regalt=\TD@regalt
+ \setbox\z@=\hbox\bgroup
+ \TD@delim@size=\z@
+ \begin{lrbox}{\z@}%
+ \gdef\TD@delim@size@G{0}%
+ \ignorespaces
+}{%
+ \end{lrbox}%
+ \ifnum \TD@delim@size@G>\TD@delim@size
+ \TD@delim@size=\TD@delim@size@G\relax
+ \fi
+ {\TD@join@branches}%
+ \unhbox\z@
+ $\TD@size@delimiter)\TD@modifier$%
+ \advance \TD@delim@size \@ne
+ \xdef\TD@delim@size@G{\the\TD@delim@size}%
+ \egroup
+ \ifnum \TD@delim@size@G<\TD@delim@size
+ \xdef\TD@delim@size@G{\the\TD@delim@size}%
+ \fi
+ \unhbox\z@
+}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{regexp}
+% This is an alias to the \texttt{regblock} environment, provided for
+% compatibility.
+% \begin{macrocode}
+\newenvironment{regexp}{\regblock}{\endregblock}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\TD@join@branches}
+% \changes{v\,2.12}{2000/11/13}{Made penalty for linebreak after
+% \cs{regalt} depend on the delimiter size. (LH)}
+% The |\TD@join@branches| macro uses |\lastbox| to retrieve all boxes
+% in the current horizontal list, and unboxes them. Between the
+% unboxed boxes it puts a |\vert| delimiter, and before the first it
+% puts a left parenthesis. Both will be the current delimiter size.
+% \begin{macrocode}
+\def\TD@join@branches{%
+ \setbox\z@=\lastbox
+ \ifvoid\z@
+ $\TD@size@delimiter($%
+ \else
+ {\TD@join@branches}%
+ \unhbox\z@
+ ~$\TD@size@delimiter\vert$%
+ \count@=\TD@delim@size
+ \advance \count@ \@ne
+ \multiply \count@ -\@lowpenalty
+ \penalty\count@\ %
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\regalt}
+% \begin{macro}{\TD@regalt}
+% The |\regalt| command is used in a \texttt{regblock} environment
+% to separate two branches. It ends an \texttt{lrbox} environment,
+% puts the box collected in the surrounding horizontal list (which
+% was begun by the |\hbox| in |\lrbox|), and begins a new
+% \texttt{lrbox} environment. As this would not make sense outside a
+% \texttt{regblock} environment however, the |\regalt| command does by
+% default only produce an error message. The ``real'' definition is
+% kept in |\TD@regalt| and the \texttt{regblock} environment locally
+% redefines |\regalt|.
+% \begin{macrocode}
+\newcommand\regalt{%
+ \PackageError{tclldoc}{%
+ Lonely \protect\regalt--perhaps a missing regblock environment%
+ }\@eha
+}
+\def\TD@regalt{%
+ \end{lrbox}%
+ \box\z@
+ \ifnum \TD@delim@size@G>\TD@delim@size
+ \TD@delim@size=\TD@delim@size@G\relax
+ \fi
+ \begin{lrbox}{\z@}%
+ \gdef\TD@delim@size@G{0}%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\TD@size@delimiter}
+% This macro expands to nothing, |\big|, |\Big|, |\bigg|, or |\Bigg|
+% depending on the value of |\TD@delim@size|.
+% \begin{macrocode}
+\def\TD@size@delimiter{%
+ \ifcase\TD@delim@size
+ \or \expandafter\big \or \expandafter\Big \or
+ \expandafter\bigg \else \expandafter\Bigg
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\word}
+% \changes{v\,2.10}{2000/10/13}{Reimplemented like the new \cs{meta}.
+% (LH)}
+% \changes{v\,2.12}{2000/11/21}{Using braces instead of angle brackets.
+% (LH)}
+% This command works like |\meta|, but the argument is enclosed in
+% braces rather than angle brackets and it communicates with the
+% \texttt{regblock} environment (the braces count as a smallest-size
+% delimiter). Something marked out using |\word| rather than |\meta|
+% is meant to always denote a separate \Tcl\ word.
+% \begin{macrocode}
+\DeclareRobustCommand\word[1]{%
+ \leavevmode
+ \ifmmode \expandafter \nfss@text \fi
+ {%
+ $\{$%
+ \meta@font@select
+ \edef\meta@hyphen@restore
+ {\hyphenchar\the\font\the\hyphenchar\font}%
+ \hyphenchar\font\m@ne
+ \language\l@nohyphenation
+ #1\/%
+ \meta@hyphen@restore
+ $\}$%
+ }%
+ \ifnum \TD@delim@size@G<\@ne \gdef\TD@delim@size@G{1}\fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Logos}
+%
+% \begin{macro}{\Tcllogo}
+% \changes{v\,2.03}{2000/09/15}{Macro added. (LH)}
+% The |\Tcllogo| command makes a \Tcl\ ``logo'', which simply consists
+% of the three letters `T', `c', and `l' in the current font. The only
+% special thing about it is that there is a kern between the `T' and
+% the `c', since most fonts doesn't have that kern. No work has been
+% put into tuning the kern, but the size is about right. As a
+% comparison the kern between `T' and `o' in \texttt{cmr10} is
+% $-0.083334\,\mathrm{em}$.
+% \begin{macrocode}
+\DeclareRobustCommand\Tcllogo{T\kern-0.1em cl}
+%</pkg>
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v\,2.03}{2000/09/15}{\cs{DescribeResource} command removed.
+% Just in case anyone is interested in using it, I have included it as
+% a code example in the source for the \package{xdoc} package. (LH)}
+%
+%
+% \section{The \package{tclldoc} class}
+%
+% \subsection{Option declarations and processing}
+%
+% \begin{option}{a5paper}
+% \begin{option}{olddocinclude}
+% The \texttt{a5paper} (to the \package{article} document class) and
+% the \texttt{olddocinclude} (to the \package{xdoc} package) are not
+% supported for the \package{tclldoc} class.
+% \begin{macrocode}
+%<*class>
+\DeclareOption{a5paper}{%
+ \ClassError{tclldoc}{The a5paper option is not supported}\@eha
+}
+\DeclareOption{olddocinclude}{%
+ \ClassError{tclldoc}{The olddocinclude option is not supported}\@eha
+}
+% \end{macrocode}
+% \end{option}\end{option}
+%
+% \begin{option}{notrawchar}
+% The \texttt{notrawchar} option is passed on to the
+% \package{tclldoc} package (which will pass it on to the
+% \package{xdoc} package).
+% \changes{v\,2.40}{2003/04/05}{Added processing of this option; it
+% wouldn't take if it was simply given as a global option. (LH)}
+% \begin{macrocode}
+\DeclareOption{notrawchar}{%
+ \PassOptionsToPackage{notrawchar}{tclldoc}%
+}
+% \end{macrocode}
+% \end{option}
+%
+%
+% \begin{macrocode}
+\DeclareOption*{%
+ \PassOptionsToClass{\CurrentOption}{article}}
+% \end{macrocode}
+%
+%
+%
+% Input a local configuration file, if it exists.
+% \begin{macrocode}
+\InputIfFileExists{tclldoc.cfg}
+ {\typeout{*************************************^^J%
+ * Local config file tclldoc.cfg used^^J%
+ *************************************}}
+ {}
+% \end{macrocode}
+%
+%
+%
+% \begin{macrocode}
+\ProcessOptions\relax
+% \end{macrocode}
+%
+% \subsection{Loading the base class}
+%
+% \begin{macrocode}
+\LoadClass{article}
+% \end{macrocode}
+%
+%
+% \subsection{The layout}
+%
+% Increase the text width slightly so that with the standard fonts
+% 72 columns of code may appear in a |macrocode| environment.
+% \changes{ \package{ltxdoc} v\,2.0c}{1994/03/15}{Set \cs{textwidth}.}
+% \begin{macrocode}
+\setlength{\textwidth}{355pt}
+% \end{macrocode}
+%
+% Increase the marginpar width slightly, for long command names.
+% And increase the left margin by a similar amount
+% \changes{ \package{ltxdoc} v\,2.0l}
+% {1994/05/25}{Increase \cs{marginparwidth}}
+% \changes{ \package{ltxdoc} v\,2.0q}{1995/11/28}
+% {Increase \cs{marginparwidth} and page margin.}
+% \begin{macrocode}
+\addtolength\oddsidemargin{20pt}
+\addtolength\evensidemargin{20pt}
+% \end{macrocode}
+%
+%
+% Change some defaults for list formatting. In particular, continue to
+% indent paragraphs in |\list| environments and don't put extra space
+% between them.
+% \changes{ \package{pasdoc} v\,1.30}{1999/08/31}{Modifying the list
+% formatting. (LH)}
+%
+% \begin{macro}{\TD@list}
+% \begin{macro}{\@listi}
+% \begin{macro}{\@listI}
+% \begin{macro}{\@listii}
+% \begin{macro}{\@listiii}
+% \begin{macro}{\@listiv}
+% \begin{macro}{\@listv}
+% \begin{macro}{\@listvi}
+% \begin{macrocode}
+\def\@tempa#1{%
+ \expandafter\def \expandafter#1\expandafter{#1\TD@list}%
+}
+\def\TD@list{%
+ \advance \itemsep \parsep
+ \parsep=\z@\@plus\p@\relax
+ \advance \itemsep -\parsep
+ \listparindent=1em\relax
+}
+\@tempa\@listi
+\let\@listI\@listi
+\@tempa\@listii
+\@tempa\@listiii
+\@tempa\@listiv
+\@tempa\@listv
+\@tempa\@listvi
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+% \end{macro}\end{macro}
+%
+%
+% \subsection{Loading the \package{tclldoc} package}
+%
+% \begin{macrocode}
+\RequirePackage[dolayout]{tclldoc}
+% \end{macrocode}
+%
+% \begingroup
+% Make \verb+|+ be a `short verb' character, but not in the document
+% preamble, where an active character may interfere with packages that
+% are loaded.
+% \DoNotIndex{\|}
+% \begin{macrocode}
+\AtBeginDocument{\MakeShortTclverb{\|}}
+% \end{macrocode}
+% \endgroup
+%
+% As \texttt{.dtx} documents tend to have a lot of monospaced material,
+% set up some \texttt{cmtt} substitutions to occur silently.
+% \changes{ \package{ltxdoc} v\,2.0p}{1995/11/02}{Add font substitutions}
+% \begin{macrocode}
+\DeclareFontShape{OT1}{cmtt}{bx}{n}{<-> ssub * cmtt/m/n}{}
+\DeclareFontFamily{OMS}{cmtt}{\skewchar\font'60}
+\DeclareFontShape{OMS}{cmtt}{m}{n}{<-> ssub * cmsy/m/n}{}
+\DeclareFontShape{OMS}{cmtt}{bx}{n}{<-> ssub * cmsy/b/n}{}
+% \end{macrocode}
+% This substitution is in the standard fd file, but not silent.
+% \begin{macrocode}
+\DeclareFontShape{OT1}{cmss}{m}{it}{<->ssub*cmss/m/sl}{}
+% \end{macrocode}
+%
+%
+% \subsection{More layout}
+%
+% \changes{v\,2.12}{2000/11/26}{Setting \cs{marginparwidth} so that the
+% outer edge of the marginpar is $1\,\mathrm{cm}$ from the paper
+% edge. (LH)}
+% \changes{v\,2.12}{2000/11/27}{Rearranged code so that
+% the \cs{marginparwidth} is set after \package{tclldoc} has been
+% loaded; otherwise \package{doc} might overwrite it! (LH)}
+% \begin{macrocode}
+\setlength\marginparwidth{\evensidemargin}
+\addtolength\marginparwidth{1in}
+\addtolength\marginparwidth{-\marginparsep}
+\addtolength\marginparwidth{-1cm}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\CodelineNumbered
+\DisableCrossrefs
+% \end{macrocode}
+%
+% \begin{macrocode}
+\setcounter{StandardModuleDepth}{1}
+%</class>
+% \end{macrocode}
+%
+%
+% \section{The \package{tcldoc} compatibility package and class}
+%
+% \changes{v\,2.30}{2001/09/02}{Renamed the package and class to
+% \package{tclldoc} to prevent confusion with the \Tcl Doc Perl
+% script. Added files \texttt{tcldoc.sty} and \texttt{tcldoc.cls}
+% for compatibility. Moved code related to the \texttt{macinputenc}
+% option to \texttt{tcldoc.cls}; this option is now unsupported.
+% (LH)}
+%
+% \subsection{Pre-options definitions}
+%
+% \begin{macro}{\if@rtkinenc@}
+% Switch. True iff the \package{rtkinenc} package should be loaded.
+% It starts out false.
+% \begin{macrocode}
+%<*compclass>
+\newif\if@rtkinenc@
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Option declarations and processing}
+%
+% \begin{option}{macinputenc}
+% The \texttt{macinputenc} option enables some special code for
+% supporting the typesetting of \Tcl\ code written for the Macintosh
+% input encoding (cf.\ the \texttt{applemac} option to the
+% \package{inputenc} package).
+% \begin{macrocode}
+\DeclareOption{macinputenc}{%
+ \PassOptionsToPackage{applemac}{rtkinenc}%
+ \@rtkinenc@true
+}
+% \end{macrocode}
+% \end{option}
+%
+%
+% \begin{macrocode}
+\DeclareOption*{%
+ \PassOptionsToClass{\CurrentOption}{tclldoc}}
+% \end{macrocode}
+%
+%
+%
+% Input a local configuration file, if it exists.
+% \begin{macrocode}
+\InputIfFileExists{tcldoc.cfg}
+ {\typeout{*************************************^^J%
+ * Local config file tcldoc.cfg used^^J%
+ *************************************}}
+ {}
+% \end{macrocode}
+%
+%
+%
+% \begin{macrocode}
+\ProcessOptions\relax
+% \end{macrocode}
+%
+% \subsection{Loading the base package or class}
+%
+% \begin{macrocode}
+\LoadClass{tclldoc}
+%</compclass>
+%<comppkg>\LoadPackageWithOptions{tclldoc}
+% \end{macrocode}
+%
+%
+% \subsection{Input encoding and font representations}
+%
+% There are some rather tricky issues concerning interpretation of the
+% input in \Tcl\ code. If the |\MacroFont| font contains a character that
+% correctly represents a character in the input, then that character is
+% obviously what one would like to appear in the typeset output. If no
+% font in the entire \TeX\ system contains a character that looks like
+% the one in the input, then just as obviously must one examine whether
+% there exists some other method of specifying that character. In the
+% case of \Tcl\ code, a suitable method seems to be to typeset the
+% equivalent |\x|\meta{dd} escape sequence instead. It is for the
+% purpose of being able to detect these cases that the
+% \package{tcldoc} class (if the user so requests) loads the
+% \package{rtkinenc} package, rather than the standard \LaTeX\
+% \package{inputenc} package.
+%
+% The problem of determining for each input character which method of
+% representation that should be used---single character or escape
+% sequence---does not have a unique solution. Therefore the default
+% set-up is to not define any special fakes at all, which means the
+% escape sequence method will be chosen in the doubtful cases. There are
+% also a couple of options for the \package{tcldoc} class that define
+% all (or nearly all) possible fakes---the difference between them lie
+% in which fonts are assumed to be present in the system. A user who
+% does not like any of these predefined options also has the option of
+% putting the corresponding |\Declare|\-|Text|\-|Default|\textellipsis
+% \ commands directly into the \texttt{tcldoc.cfg} file.
+%
+% \begin{macro}{\InputModeCode}
+% \begin{macro}{\SetUnavailableAction}
+% \begin{macro}{\DeclareInputMath}
+% \begin{macro}{\RIE@undefined}
+% The \package{tclldoc} package calls some commands defined by the
+% \package{rtkinenc} package, but since \package{rtkinenc} is not
+% required by the \package{tclldoc} package, the \package{tclldoc}
+% package must provide its own definitions, even though these can be
+% no-ops. Definition of these commands is delayed until
+% |\begin|\nolinebreak[1]|{document}| to avoid problems if the user
+% loads the \package{rtkinenc} package after the \package{tclldoc}
+% package.
+% \begin{macrocode}
+%<*pkg>
+\AtBeginDocument{%
+ \providecommand*\InputModeCode{}%
+ \providecommand*\SetUnavailableAction[1]{}%
+ \providecommand*\DeclareInputMath[2]{}%
+ \providecommand*\RIE@undefined[1]{\@inpenc@undefined}%
+}
+%</pkg>
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}
+%
+% \begin{macrocode}
+%<*compclass>
+\if@rtkinenc@
+ \RequirePackage{rtkinenc}
+% \end{macrocode}
+%
+% \begin{macro}{\.}
+% \begin{macro}{\H}
+% \begin{macro}{\textemdash}
+% \begin{macro}{\textendash}
+% \begin{macro}{\textexclamdown}
+% \begin{macro}{\textquestiondown}
+% \begin{macro}{\textquotedblleft}
+% The following text commands are defined by \texttt{OT1enc.def}, but
+% their definitions will not work for \texttt{OT1}-encoded typewriter
+% fonts. Therefore they are redefined, either so that they work
+% anyway (|\textexclamdown| and |\textquestiondown|) or so that they
+% call |\TextSymbolUnavailable| when \package{rtkinenc} is in code
+% mode. This should make things work for the best in most
+% reasonable situations.
+%
+% It could be noted here that the definitions below for |\.| and |\H|
+% does not quite behave as if the commands had not been defined at
+% all (I'm assuming that \package{rtkinenc} is in code mode here); an
+% undefined command would leave its argument to be typeset, but the
+% definitions below will swallow it in those cases.
+% \begin{macrocode}
+ \DeclareTextCommand{\.}{OT1}[1]{%
+ \IfInputModeCode{\TextSymbolUnavailable\.}%
+ {\add@accent{95}{#1}}%
+ }
+ \DeclareTextCommand{\H}{OT1}[1]{%
+ \IfInputModeCode{\TextSymbolUnavailable\H}%
+ {\add@accent{125}{#1}}%
+ }
+ \DeclareTextCommand{\textemdash}{OT1}{%
+ \IfInputModeCode{\TextSymbolUnavailable\textemdash}{\char 124 }%
+ }
+ \DeclareTextCommand{\textendash}{OT1}{%
+ \IfInputModeCode{\TextSymbolUnavailable\textendash}{\char 123 }%
+ }
+ \DeclareTextCommand{\textexclamdown}{OT1}{!`}
+ \DeclareTextCommand{\textquestiondown}{OT1}{?`}
+ \DeclareTextCommand{\textquotedblleft}{OT1}{%
+ \IfInputModeCode{\TextSymbolUnavailable\textquotedblleft}%
+ {\char 92 }%
+ }
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+% \end{macro}
+%
+% Several of the definitions in \texttt{applemac.def} can be improved.
+% Most of it is about seeing to that all characters have a proper text
+% mode definition, so that their unavailability can be trapped.
+%
+% \begin{macrocode}
+ \def\@tempa{applemac}
+ \ifx \@tempa\RIE@encoding
+ \DeclareInputBoth{173}{\textneq}{\neq}
+ \DeclareInputBoth{176}{\textinfty}{\infty}
+ \DeclareInputBoth{177}{\textpm}{\pm}
+ \DeclareInputBoth{178}{\textleq}{\leq}
+ \DeclareInputBoth{179}{\textgeq}{\geq}
+ \DeclareInputBoth{181}{\textmu}{\mu}
+ \DeclareInputBoth{182}{\textpartial}{\partial}
+ \DeclareInputBoth{183}{\textSigma}{\Sigma}
+ \DeclareInputBoth{184}{\textPi}{\Pi}
+ \DeclareInputBoth{185}{\textpi}{\pi}
+ \DeclareInputBoth{186}{\textint}{\int}
+ \DeclareInputBoth{189}{\textohm}{\Omega}
+ \DeclareInputBoth{194}{\textlnot}{\lnot}
+ \DeclareInputBoth{195}{\textsurd}{\surd}
+ \DeclareInputBoth{197}{\textapprox}{\approx}
+ \DeclareInputBoth{198}{\textDelta}{\Delta}
+ \DeclareInputBoth{214}{\textdiv}{\div}
+ \DeclareInputBoth{215}{\textdiamond}{\diamond}
+ \DeclareInputBoth{218}{\textfractionsolidus}{/}
+% \end{macrocode}
+%
+% Several of the above text commands are not defined in the \LaTeX\
+% kernel. Therefore one must either define them in some encoding, or
+% define a default for them, to make them proper text commands. If they
+% are not then their unavailability cannot be trapped. |\textapplelogo|
+% appears in \texttt{applemac.def}.
+% \begin{macrocode}
+ \ProvideTextCommandDefault{\textneq}{%
+ \TextSymbolUnavailable\textneq
+ }
+ \ProvideTextCommandDefault{\textapplelogo}{%
+ \TextSymbolUnavailable\textapplelogo
+ }
+ \DeclareTextSymbol{\textinfty}{OMS}{49}
+ \DeclareTextSymbol{\textpm}{OMS}{6}
+ \DeclareTextSymbol{\textleq}{OMS}{20}
+ \DeclareTextSymbol{\textgeq}{OMS}{21}
+% \DeclareTextSymbol{\textmu}{TS1}{181}
+ \DeclareTextSymbol{\textpartial}{OML}{64}
+ \DeclareTextSymbol{\textSigma}{OT1}{6}
+ \DeclareTextSymbol{\textPi}{OT1}{5}
+ \DeclareTextSymbol{\textpi}{OML}{25}
+ \DeclareTextSymbol{\textint}{OMS}{115}
+ \DeclareTextSymbol{\textohm}{OT1}{10} % Kind of \textOmega
+% \DeclareTextSymbol{\textlnot}{TS1}{172}
+% \DeclareTextSymbol{\textsurd}{TS1}{187}
+ \DeclareTextSymbol{\textapprox}{OMS}{25}
+ \DeclareTextSymbol{\textDelta}{OT1}{1}
+% \DeclareTextSymbol{\textdiv}{TS1}{246}
+ \DeclareTextSymbol{\textdiamond}{OMS}{5}
+% \DeclareTextSymbol{\textfractionsolidus}{TS1}{47}
+ \input{TS1enc.def}
+ \fi
+\fi
+% \end{macrocode}
+% \begin{macrocode}
+\let\if@rtkinenc@=\@undefined
+\let\@rtkinenc@true=\@undefined
+\let\@rtkinenc@false=\@undefined
+% \end{macrocode}
+% The |@rtkinenc@| switch isn't needed any more, so it might just as
+% well be undefined.
+%
+%
+% \subsection{Useful abbreviations}
+% \changes{v\,2.10}{2000/10/11}{\LaTeX\ abbreviation commands from
+% \package{ltxdoc} commented out. (LH)}
+%
+% The commands currently found in this section are inherited from the
+% \package{ltxdoc} package, but as they aren't of much use with \Tcl,
+% they have been commented out.
+%
+% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving
+% arguments. |\cs{foo}| also prints |\foo|, for those who prefer that
+% syntax. (This second form may even be used when |\foo| is |\outer|).
+% \begin{macro}{\cmd}
+% \begin{macro}{\cs}
+% \DoNotIndex{\\}
+% \begin{macrocode}
+% \def\cmd#1{\cs{\expandafter\cmd@to@cs\string#1}}
+% \def\cmd@to@cs#1#2{\char\number`#2\relax}
+% \DeclareRobustCommand\cs[1]{\texttt{\char`\\#1}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\marg}
+% |\marg{text}| prints \marg{text}, `mandatory argument'.
+% \DoNotIndexHarmless{\PrintChar{`\{}}
+% \DoNotIndexHarmless{\PrintChar{`\}}}
+% \begin{macrocode}
+% \providecommand\marg[1]{%
+% {\ttfamily\char`\{}\meta{#1}{\ttfamily\char`\}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\oarg}
+% |\oarg{text}| prints \oarg{text}, `optional argument'.
+% \begin{macrocode}
+% \providecommand\oarg[1]{%
+% {\ttfamily[}\meta{#1}{\ttfamily]}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\parg}
+% |\parg{te,xt}| prints \parg{te,xt}, `picture mode argument'.
+% \begin{macrocode}
+% \providecommand\parg[1]{%
+% {\ttfamily(}\meta{#1}{\ttfamily)}}
+%</compclass>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \changes{v\,2.00}{2000/07/17}{Section with \cs{DocInclude} removed,
+% since that is defined by \package{xdoc}. (LH)}
+%
+% \Finale
+%
+\endinput
+
diff --git a/macros/latex/contrib/tclldoc/tclldoc.ins b/macros/latex/contrib/tclldoc/tclldoc.ins
new file mode 100644
index 0000000000..aeb0a96841
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tclldoc.ins
@@ -0,0 +1,51 @@
+% This file is the docstrip installation script for the tclldoc package.
+%
+% It may be distributed under the conditions of the LaTeX
+% Project Public License, either version 1.2 of this license or
+% (at your option) any later version. The latest version of this
+% license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.2 or later is part of all distributions of LaTeX
+% version 1999/12/01 or later.
+%
+% Copyright 2000 2001 Lars Hellstr\"om
+
+\input docstrip.tex
+
+\preamble
+
+This file may be distributed and/or modified under the conditions
+of the LaTeX Project Public License, either version 1.2 of this
+license or (at your option) any later version. The latest version
+of this license is in
+ http://www.latex-project.org/lppl.txt
+and version 1.2 or later is part of all distributions of LaTeX
+version 1999/12/01 or later.
+
+This file may only be distributed together with a copy of the source
+file from which it was generated. You may distribute that source file
+without this generated file.
+
+\endpreamble
+
+\usedir{tex/latex/tclldoc}
+
+\keepsilent
+
+\generate{%
+ \file{tclldoc.cls}{%
+ \from{tclldoc.dtx}{class}
+ }%
+ \file{tclldoc.sty}{%
+ \from{tclldoc.dtx}{pkg}
+ }%
+ \file{tcldoc.cls}{%
+ \from{tclldoc.dtx}{compclass}
+ }%
+ \file{tcldoc.sty}{%
+ \from{tclldoc.dtx}{comppkg}
+ }%
+}
+
+\endbatchfile
+\endinput
diff --git a/macros/latex/contrib/tclldoc/tclldoc.pdf b/macros/latex/contrib/tclldoc/tclldoc.pdf
new file mode 100644
index 0000000000..c2646fff73
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tclldoc.pdf
Binary files differ
diff --git a/macros/latex/contrib/tclldoc/tools/README.txt b/macros/latex/contrib/tclldoc/tools/README.txt
new file mode 100644
index 0000000000..c8fd744afd
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tools/README.txt
@@ -0,0 +1,46 @@
+README for eemenu and sourcetcl:
+=====================================
+
+eemenu is a package for the Alpha/Alphatk text
+editors. Among other things, it implements
+a command that makes it possible to evaluate
+all Tcl code in an open .dtx file window with
+a single keypress. For more information, run
+LaTeX on eemenu.dtx.
+
+Running LaTeX on eemenu.ins generates the two
+files
+ eemenu.tcl
+ eefor7menu.tcl
+Both implement the same commands, but eemenu.tcl
+requires version 8 of the AlphaTcl library,
+whereas eefor7menu.tcl requires version 7.5 or
+7.6 of that library.
+
+See http://alphatcl.sourceforge.net/ and the
+links there for more information about the
+Alpha/Alphatk text editors.
+
+
+
+sourcedtx implements a Tcl command dtx::source
+that one can use to source Tcl code directly from
+a .dtx file. To generate sourcetcl.tcl, run LaTeX
+on sourcetcl.ins. To typeset the documentation,
+run LaTeX on sourcetcl.dtx. To see an example of
+what it does, you can try the following commands
+in a Tcl shell:
+
+ source sourcedtx.tcl
+ dtx::source ../examples/pdf.dtx {pkg example1}
+
+(It assumes the tclldoc/examples directory is a
+sibling of the current directory.) This should
+generate a file hello.pdf in the current
+directory, which contains a single page with the
+two words "Hello world!".
+
+
+
+Lars Hellström,
+20 July 2003
diff --git a/macros/latex/contrib/tclldoc/tools/eemenu.dtx b/macros/latex/contrib/tclldoc/tools/eemenu.dtx
new file mode 100644
index 0000000000..d2383b7c1e
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tools/eemenu.dtx
@@ -0,0 +1,4477 @@
+%
+% \iffalse
+%<*driver>
+\documentclass[a4paper]{tclldoc}
+
+\newcommand{\eemenu}{\textsf{EE} menu}
+\DeclareRobustCommand\Alpha{\textit{Alpha}}
+\DeclareRobustCommand\AlphaEight{\textit{Alpha\,8}}
+\DeclareRobustCommand\AlphaTk{\textit{Alphatk}}
+\DeclareRobustCommand\AlphaTcl{\textit{Alpha\Tcllogo}}
+\DeclareRobustCommand\TclAE{\Tcllogo\AE}
+\DeclareRobustCommand\package[1]{\textsf{#1}}
+
+\providecommand{\href}[2]{#2}
+
+\usepackage{xdoc2}
+\newenvironment{details}[1]{%
+ \description
+ \def\commandmethod{#1}%
+}{\enddescription}
+\makeatletter
+\newcommand{\detailitem}{%
+ \XD@grab@arguments{\@detailitem}{\XD@grab@harmless\relax}%
+}
+\def\@detailitem#1{%
+ \item[\texttt{#1}%
+ \IndexEntry{\LevelSame{\commandmethod\ method}%
+ \LevelSorted{#1}{\texttt{#1} detail}%
+ }{main}{\TheXDIndexNumber}%
+ ]%
+}
+\makeatother
+
+% \addtolength{\marginparwidth}{0.7cm}
+
+\CodelineIndex
+\setcounter{IndexColumns}{2}
+
+\begin{document}
+\DocInput{eemenu.dtx}
+\PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \eemenu}
+% \author{Lars Hellstr\"om}
+% \date{17 July 2003}
+% \maketitle
+%
+%
+% \begin{abstract}
+% The \eemenu\ package for the \Alpha\ family of text editors provides
+% commands for sending small pieces of code from a source file window
+% to various interpreters. It can handle multiple languages and
+% multiple source file formats.
+% \end{abstract}
+%
+% \tableofcontents
+%
+%
+% \section{Introduction}
+%
+% When writing code for an interpreted language, it is a great
+% convenience to be able to test arbitrary pieces of code by sending
+% them to a relevant interpreter and examining the results. Many of
+% \Alpha's modes provide such functionality, but not always with the
+% full generality one would need. Furthermore these features are usually
+% tied to the specific mode and thus become much less convenient if code
+% in several different languages are mixed in the same file. The
+% \eemenu\ provides a general mechanism for constructing new commands
+% of this kind, thereby making it possible to better tailor them for the
+% case at hand.
+%
+%
+% \subsection{Using an \eemenu\ command}
+%
+% The basic usage is straightforward: you select a piece of text and
+% invoke one of the \eemenu\ commands. This will \emph{extract}
+% the part of that selection which is code and send it to the relevant
+% interpreter, where it will be \emph{evaluated}. (Indeed, the \textsf{EE}
+% in \eemenu\ is for ``extract and evaluate''.) You will also get
+% a \emph{report} (by default a message on the status line) about the
+% result of the command. This is all quite similar to how the
+% \textsf{Evaluate} command in the \Tcllogo\ menu works, but it is much
+% more general.
+%
+% Two very natural questions at this point are of course ``How does it
+% know what part of the selection is `code'?'' and ``How does it know
+% which the `relevant interpreter' is?''. The answer to both these
+% questions is that this information is built into the particular command
+% you invoke. Just as the standard \textsf{Evaluate} command has its
+% definition of what `code' is (the entire selection is code) and which
+% the `relevant interpreter' is (\Alpha's internal \Tcllogo\
+% interpreter), each \eemenu\ command has built-in definitions of
+% these things. The difference is that with \textsf{Evaluate} you would
+% have to do some programming to change these things, whereas with the
+% \eemenu\ commands you don't, since there is a multitude of ways in
+% which each part of the exatract-and-evaluate process can be configured.
+%
+% To begin with, each \eemenu\ command consists of four pieces which
+% are quite independent of each other. When the \emph{extract} piece is
+% called it looks at the selection and returns the next line of code in
+% it, or says that there are no more code lines that can be extracted.
+% What happens to the extracted lines of code is of no concern to the
+% extractor. The \emph{evaluate} piece takes a list of lines and sends
+% them to an interpreter (internal or external). It also compiles a
+% sort of report on the result of the evaluation, based on the reply
+% (if there was any) that it recieves from the interpreter. This is
+% then given to the \emph{reporter}, which displays the report (or more
+% often, for brevity, the central part of the report) to the user. The
+% fourth piece is called the \emph{completeness test} and determines
+% whether a list of code lines constitute a unit that can be evaluated.
+%
+% The way it goes is that lines are extracted until the completeness
+% test says OK, then the lines are sent for evaluation and the report on
+% evaluation is sent to the reporter, after which the whole thing starts
+% again and lines are extracted until the form a new complete unit,
+% which is then evaluated, and so on. The \eemenu\ command doesn't stop
+% until all code lines in the selection have been extracted or evaluation
+% reports an error.
+% If there is an error in evaluation then the report will say so, and
+% futhermore the cursor will be moved to the beginning of the first
+% line in the code unit that failed to evaluate correctly. Furthermore
+% the pin will be moved to the end of the selection, so that a simple
+% \textsf{Hilite} will reselect the part of the original selection that
+% still has not been successfully evaluated. If there wasn't any
+% selection to start with then the extractor behaves as if the entire
+% file was selected.
+%
+%
+% \subsection{Editing and invoking \eemenu\ commands}
+%
+% Each of the four pieces of what a command does are handled by a
+% \emph{method}. There are extraction methods, completeness test
+% methods, evaluation methods, and report methods, all of which can be
+% combined arbitrarily to make up a new \eemenu\ command. This is done
+% in the \textsf{Edit Commands} dialog, which is brought up by
+% choosing that item in the \textsf{EE} menu.
+%
+% The \textsf{Edit Commands} dialog has one page for each \eemenu\
+% command that is defined. At the bottom of the dialog there is a row
+% of four buttons \textsf{New}, \textsf{Duplicate}, \textsf{Rename}, and
+% \textsf{Delete} which add, remove, or rename \eemenu\ commands. Above
+% those are four pop-up menus, in which one chooses which four methods
+% the command should consist of. Above these are four other items which
+% control how the command is invoked.
+%
+% There are two ways of invoking an \eemenu\ command. One possibility
+% is to choose it directly in the \textsf{EE} menu, although it is not
+% necessarily the case that all commands are available there. Whether a
+% command is available is controlled through the \textsf{Put in menu}
+% item on the \textsf{Edit Commands} dialog page of that command. The
+% other possibility of invoking a command is through a key binding, and
+% that is controlled through the three remaining items \textsf{Active},
+% \textsf{Command keybinding}, and \textsf{Binding mode} in the
+% \textsf{Edit Commands} dialog. The \textsf{Command keybinding} item
+% controls which key binding one should use for a command. The
+% \textsf{Binding mode} item is used to specify a mode for this
+% binding; a binding without mode will be global. Finally, a command is
+% said to be \emph{active} if there is a key binding to it. The
+% \textsf{Active} item controls whether the command should be active by
+% default (at startup).
+%
+% For temporary activation and deactivation of commands, one should
+% instead use the \textsf{Active Commands} submenu of the \textsf{EE}
+% menu. This submenu lists all \eemenu\ commands. Those that are
+% currently active have a check mark next to them, and selecting an item
+% in this menu toggles activation state of that command. If two commands
+% have the same binding then activating one will deactivate the other.
+%
+% Besides the items mentioned above, the \textsf{Edit Commands} dialog
+% also has a \textsf{Details} button in the lower left corner. This
+% button is very important, since it brings up a subdialog that shows
+% all the method-specific settings. The methods and their details are
+% described below, but it should be observed here that it is to a large
+% extent these detail settings that decide, amogst other things, what
+% text should count as extractable code and which interpreter should
+% evaluate the code. To get back from the details subdialog to the main
+% \textsf{Edit Commands} dialog, one presses the \textsf{Back} button.
+% The details subdialog is logically a part (which is normally hidden)
+% of the main \textsf{Edit Commands} dialog. Changes to items in the
+% dialog, whether those appear in the main dialog or in the subdialog,
+% are kept if one presses \textsf{OK} in the main dialog and forgotten
+% if one presses the \textsf{Cancel} button.
+%
+%
+% \subsection{Extraction methods and their details}
+%
+% The default extraction method is the \textsf{Raw} method. It
+% considers the entire selection to be extractable code and has no
+% detail settings.
+%
+% The \textsf{Regexp} extraction method uses line-oriented regular
+% expressions to decide what is extractable code. This extraction
+% process works in two steps. First the lines in the selection are
+% tested against a filter, and those lines that passes are considered to
+% contain code. The filter works in one of three modes: \texttt{off}
+% (all lines pass), \texttt{grep} (only those lines that match a
+% specific regular expression passes), and \texttt{anti-grep} (only
+% those lines that \emph{don't} match a specific regular expression
+% passes). The filter mode and the regular expression used in the
+% filter are the two detail settings that affect the filter.
+% The second step in \textsf{Regexp} extraction is to feed each line
+% that passes the filter through |regsub|. This can be used to remove
+% from the lines some piece of text that is markup rather than part of
+% the code. Both the search and the replace regular expressions in this
+% step are detail settings of the \textsf{Regexp} extraction method.
+%
+% The \textsf{Docstrip} extraction method, finally, emulates what the
+% \textsf{docstrip} program\footnote{\textsf{docstrip} is part of the
+% standard \LaTeX\ distribution.} would do with the selection. It
+% recognises all kinds of guards and processes them correctly, but it
+% does not attempt to evaluate the guard expressions---instead it will
+% ask the user whether modules guarded by a given expression should be
+% included whenever it needs to know this. The values assigned to the
+% guard expressions will be forgotten each time the entire selection
+% is evaluated without error. Unlike \textsf{docstrip} the program,
+% \textsf{Docstrip} the extraction method will not include lines
+% beginning with |%%| in what is extracted, since those anyway only
+% contains comments.
+%
+% Besides the filtering that \textsf{docstrip} the program would do,
+% \textsf{Docstrip} the extraction method has two extra filtering
+% mechanisms that are designed mainly to prevent user errors. The first
+% is that extraction will only take place if the file name matches one
+% listed in the \textsf{File patterns} detail. The default pattern is
+% \texttt{*.dtx} which is usually what one wants, but changing it to
+% \texttt{*} will let anything through. The second mechanism, which is
+% off by default, sees to that code lines will only be considered for
+% extraction if they appear to be in an environment for code lines
+% (such as \texttt{macrocode}). This is useful if you in places tend to
+% leave a few lines of documentation not commented out during
+% development. To activate this mechanism, check the \textsf{Filter by
+% environments} detail. The \textsf{Source environments} detail is the
+% list of environments that are OK to extract from.
+%
+% As an example of how this works, consider a file that looks as
+% follows:
+% \DontCheckModules\iffalse
+%<*example>
+%<<EXAMPLE
+% \fi\begin{macrocode}
+% Text text text text text
+% \begin{tcl}
+set a A
+%<*andB>
+append a B
+%</andB>
+append a C
+%<*andD>
+append a D
+%</andB>
+expr $a
+string length $a
+% \end{tcl}
+% text text text.
+% \end{macrocode}\iffalse
+%EXAMPLE
+%</example>
+% \fi \CheckModules
+% If lines 1--7 above are selected and the \textsf{dtx -\textgreater\
+% internal Tcl} command is invoked (the \eemenu\ by default binds this
+% to \textsf{Cmd--L}), then three messages will flash by on the
+% status line, the last (and therefore the lasting) of which is the
+% message \texttt{Tcl eval OK: ABC}. If using instead a command that
+% uses the \textsf{Log Window} report method, then in addition to this
+% one would have the following lines added to the log window:
+% \begin{trivlist}\item\small
+% |% set a A|\\
+% |A|\\[\smallskipamount]
+% |% append a B|\\
+% |AB|\\[\smallskipamount]
+% |% append a C|\\
+% |ABC|
+% \end{trivlist}
+% The |%| lines show the commands that were evaluated and the
+% lines after these contain the respective results of these commands.
+% Before the |append a B| command is evaluated, \Alpha\ will stop and
+% ask
+% \begin{quote}
+% \textsf{Should \textless andB\textgreater\ modules be included?}
+% \end{quote}
+% In the case above the answer given was `Yes'; if it had been `No' then
+% the |append a B| command would neither be logged nor evaluated, and
+% the result of the |append a C| command would have been |AC|.
+%
+% If one continues by selecting lines 9--12 and invokes the same
+% command again then the status line will settle for the message
+% ``\texttt{Tcl\ eval\ error:\ syntax\ error\ in\ expression\ "ABCD"}'',
+% the insertion point will be moved to the beginning of line 11, and
+% the following information will be found in the log:
+% \begin{trivlist}\item\small
+% |% append a D|\\
+% |ABCD|\\[\smallskipamount]
+% |% expr $a|\\
+% |Error: syntax error in expression "ABCD"|\\
+% |Error info:|\\
+% |syntax error in expression "ABCD"|\\
+% | while executing|\\
+% |"expr $a"|
+% \end{trivlist}
+% If then line 11 is changed to |expr {$a}|, lines 11--12 are again
+% selected (e.g. using \textsf{Mark Hilite}), and the command is invoked
+% then logged material will be:
+% \begin{trivlist}\item\small
+% |% expr {$a}|\\
+% |ABCD|\\[\smallskipamount]
+% |% string length $a|\\
+% |4|
+% \end{trivlist}
+%
+% Finally, if lines 3--12 are selected and the command is invoked then
+% the user will be asked the following questions:
+% \begin{itemize}
+% \item \textsf{Should \textless andB\textgreater\ modules be included?}
+% (Possible answers are `Yes' and `No'.)
+% \item \textsf{Should \textless andD\textgreater\ modules be included?}
+% (Possible answers are `Yes' and `No'.)
+% \item \textsf{Module nesting error: \textless*andD\textgreater\
+% module ended by \textless/andB\textgreater. For which
+% guards should the positions be pushed?}
+% (Possible answers are `None', `Start', `End', and `Both'.)
+% \end{itemize}
+% In the last case, the extraction method has noticed that the guard
+% expressions that began (\textsf{andD}) and ended (\textsf{andB}) a
+% module are not equal (which is an error). Answering `Both' here will
+% push the positions of (the beginning of) both guard lines (8 and 10) onto
+% the bookmark stack so that they can easily be jumped to and corrected
+% later. After this, the \eemenu\ command will continue as if nothing had
+% happened.
+%
+%
+% \subsection{Completeness tests}
+%
+% The three completeness tests that come with \eemenu\ are
+% \textsf{\Tcllogo\ Info Complete}, \textsf{Entire Selection}, and
+% \textsf{Every Line}. The first of these uses the |info complete|
+% command in \Alpha's built-in \Tcllogo\ interpreter test whether the
+% list of lines extracted so far constitute a complete \Tcllogo\
+% script. \textsf{Entire Selection} and \textsf{Every Line} don't look
+% at the extracted lines at all however; instead the \textsf{Entire
+% Selection} test waits until the entire selection has been extracted
+% before it says it does constitute a complete unit, whereas
+% \textsf{Every Line} thinks every line is a complete unit. None of
+% these methods have any details.
+%
+%
+% \subsection{Evaluation methods}
+%
+% The list of available evaluation methods depends very much on the
+% current platform. The basic \eemenu\ package contains code for four
+% methods named \textsf{Internal Tcl}, \textsf{Do Script AE}, \textsf{Tk
+% Send}, and \textsf{Windoze DDE}, but only those for which the
+% underlying command can be found in the interpreter are actually
+% defined. The effect is usually that only two methods are available:
+% the \textsf{Internal Tcl} method and one method which depends on the
+% platform.
+%
+% The \textsf{Internal Tcl} method joins the lines of code with
+% linefeeds and passes the resulting string to \Alpha's internal
+% \Tcllogo\ interpreter for evaluation (at the global level). Errors
+% are caught and reported with a complete |errorInfo|. There are no
+% details for this method.
+%
+% The \textsf{Do Script AE} method sends a \texttt{dosc} AppleEvent with
+% the code to evaluate; hence it is only available on Mac~OS. The target
+% application for this event is one of the detail settings. The `Wait
+% for reply' detail setting controls whether the AppleEvent requests a
+% reply (not all target applications will provide one). If no reply is
+% requested then the report will only tell how many lines were sent.
+% If a reply is requested then that reply will be the report. Finally,
+% there are three detail settings that control how the list of lines
+% are converted to the string put in the \texttt{dosc} AppleEvent. The
+% lines can be joined using either of the following four strings: line
+% feed, carriage return, carriage return plus line feed, or just a
+% single space. It is also possible to specify a prefix and a suffix,
+% which are strings put before and after the extracted code that should
+% be evaluated.
+%
+% The \textsf{Tk Send} method uses the Tk |send| command to communicate
+% with the target interpreter; hence it is probably only useful with
+% \AlphaTk\ in an X-windows environment (typically on some Unix platform).
+% Most of the details work as for the \textsf{Do Script AE} method, but
+% there is a difference in how the target is identified. One detail
+% setting is the string used for identifying the target, but since the
+% names of targets for |send| are made unique on each server, there is
+% a chance that the intended target has not got the expected name. In
+% that case, a mechanism called `aliasing' will be invoked. It usually
+% displays a list of the available targets (which includes the option to
+% start a new Wish process) for the user to choose from, and the target
+% detail setting will then be considered to be an \emph{alias} for the
+% actual name of that target. If the alias behaviour is to ``Ask once''
+% then this choice will be remembered as long as \Alpha\ is running, but
+% if it is to ``Ask each time'' then it will only work for this invocation
+% of the \eemenu\ command. The behaviour can also be to fail, in which
+% case the command stops as for an error without presenting the user with
+% a list of available targets.
+%
+% The \textsf{Windoze DDE} method uses Dynamic Data Exchange to communicate
+% with the target interpreter; hence it is probably only useful with
+% \AlphaTk\ on the Windows platform. Most of the details work as for the
+% \textsf{Tk Send} method, but there are a few extra details that have
+% to do with how the target is identified. The target is identified with
+% two details called \textsf{Service} and \textsf{Target}. For sending
+% commands to a \Tcllogo\ interpreter it seems like the \textsf{Service}
+% should be \texttt{TclEval} and the \textsf{Target} is assigned as the
+% \textsf{Target} for the \textsf{Tk Send} method, but the \Tcllogo\
+% manual seems to suggest that the normal case is that the
+% \textsf{Service} is the name of an application and the
+% \textsf{Target} the name of a document open in that application (I
+% haven't had any chance to try it out in practice). Aliasing works as
+% for the \textsf{Tk Send} method, but since the target isn't
+% necessarily a \Tcllogo sh or Wish in this case, the actual command for
+% launching the new target must be configurable as well. This is the
+% purpose of the \textsf{Launch command} detail, whose value is a piece
+% of \Tcllogo\ code that \Alpha\ evaluates at the global level whenever
+% the user requests that a new target is launched. It is typically an
+% |exec| command.
+%
+% I am well aware that there are interpreters for which neither of these
+% methods may be appropriate. The method concept has however deliberately
+% been designed so that separate \AlphaTcl\ extensions can define new
+% methods that are just as easily available as the built-in ones. I
+% recommend that anyone who finds the available methods insufficient
+% tries to work out how one might otherwise communicate with the target
+% interpreter, so that the capabilities of \eemenu\ can be extended. One
+% particular possibility that should be explored is to (on Unix) hook up
+% interpreters as `slaves' of \Alpha\ (seizing control of
+% \texttt{stdin}, \texttt{stdout}, and \texttt{stderr}), so that the
+% target interpreter thinks it is getting text typed at an interactive
+% prompt. Since one would typically not want to start a new such `slave'
+% for each time an \eemenu\ command is invoked, it would probably be
+% necessary to add some functionality for managing slaves to the
+% \eemenu.
+%
+%
+% \subsection{Report methods}
+%
+% The default report method is \textsf{Status Line}, which shows the
+% most recent evaluation result on the status line. This is often
+% sufficient when all you're interested in is whether there was an
+% error or not.
+%
+% The \textsf{Log Window} report method creates a detailed log of the
+% commands evaluated and the results returned. This can be useful for
+% example when one is trying to debug a complex mathematical calculation
+% with several intermediate results. The first two details of this
+% method---\textsf{Window name} and \textsf{Window mode}---refer to the
+% window used to log the results. The logged text is inserted at the
+% end of this window. If no window with the specified name exists, then
+% a new one with mode \textsf{Window mode} and the shell flag set is
+% opened. The other details---\textsf{Prompt} and
+% \textsf{Antiprompt}---are text strings that are prepended to the
+% lines inserted into the log window. The \textsf{Prompt} is prepended
+% to extracted code lines, whereas the \textsf{Antiprompt} is prepended
+% to result lines.
+%
+%
+% \subsection{Writing new methods}
+%
+% A method consists of a couple of procedures which reside in a child
+% namespace of the \texttt{eemenu} namespace. Declaring a new method
+% simply amounts to writing these procedures and defining the detail
+% settings for the method. The general relation between method names and
+% namespace names is explained in Subsection~\ref{Ssec:Namespaces}. It
+% is suggested that one uses the \texttt{eemenu}\namespaceseparator
+% \texttt{define\_detail} command of Subsection~\ref{Ssec:CmdDialogs}
+% for defining detail settings. Different kinds of methods need to
+% provide different procedures for the main executive to call. The
+% interfaces used are described in the beginnings of
+% Sections~\ref{Sec:Extraction}--\ref{Sec:Report}.
+%
+%
+%
+%
+% \section{Main menu functionality}
+%
+% The rest of this paper describes the implementation of \eemenu\ and
+% its methods. The information here is useful mainly for those who want
+% to extend \eemenu\ by writing additional methods for it or otherwise
+% modify the code, but it could of course be of interest also for
+% advanced users.
+%
+%
+% \subsection{Initialization}
+%
+% \changes{v\,0.1}{2001/12/15}{Renamed package from \textsf{Eval~Menu}
+% to \textsf{EE~Menu}. (LH)}
+% \changes{v\,0.3}{2003/04/02}{Updated code for \AlphaTcl\,8. (LH)}
+% \changes{v\,0.3.1}{2003/07/19}{Added help. (LH)}
+%
+% \begin{tcl}
+%<*pkg>
+alpha::menu eeMenu 0.3.1 global "EE" {
+ auto_load eemenu::main
+} {
+ eemenu::init_bindings
+ eemenu::build_menu
+} {
+ eval eemenu::deactivate [array names eemenu::cmdA]
+} requirements {
+%<atcl7> alpha::package require AlphaTcl 7.5b1
+%<!atcl7> alpha::package require AlphaTcl 8.0d1
+} uninstall {this-file} help {
+ The EE menu provides commands for sending small pieces of code
+ from a source file window to various interpreters. It can handle
+ multiple languages and multiple source file formats.
+
+ The commands are built by combining four simple pieces called
+ methods. The choice of methods and parameters for methods to
+ use in a command is completely configurable through a dialog.
+ It is also possible to write extensions that define additional
+ methods and provide these through the same easy interface.
+
+ See the file eemenu.dtx for the full documentation.
+} maintainer\
+%<atcl7> [list "Lars Hellstr[text::Ascii 154 1]m" Lars.Hellstrom@math.umu.se]
+%<!atcl7> [list "Lars Hellstr\u00f6m" Lars.Hellstrom@math.umu.se]
+namespace eval eemenu {}
+% \end{tcl}
+% \setnamespace{eemenu}
+%
+%
+% \subsection{Methods and namespaces}
+% \label{Ssec:Namespaces}
+%
+% Each method for doing something is put in its own namespace, which
+% must be a child of the |eemenu| namespace.
+%
+% \begin{proc}{Prettify}
+% \begin{proc}{Unprettify}
+% In dialogs and preferences, method names are kept in ``prettified''
+% form, similar to that used in most of \Alpha's menus. Since the
+% preference values must be restored to ``unpretty'' form before they
+% can be used, \eemenu\ has two procedures of its own that handle
+% these conversions, although the conversion is almost always the same
+% as the conversion that the standard |quote::Prettify| procedure
+% would make. The syntaxes are
+% \begin{quote}
+% |eemenu::Prettify| \word{unpretty string}\\
+% |eemenu::Unprettify| \word{pretty string}
+% \end{quote}
+% \begin{tcl}
+proc eemenu::Prettify str {
+ set a [string toupper [string index $str 0]]
+ regsub -all {([^A-Z])([A-Z])} [string range $str 1 end] {\1 \2} b
+ regsub -all {((La|Bib|Oz|CMac) )?Te X} $a$b {\2TeX } a
+ return $a
+}
+proc eemenu::Unprettify str {
+ regsub -all { } $str {} a
+ return "[string tolower [string index $a 0]][string range $a 1 end]"
+}
+% \end{tcl}
+% For these procedures to be inverses of each other, unpretty strings
+% must begin with a lower case letter and not contain any spaces.
+% \end{proc}\end{proc}
+%
+% \begin{arrayvar}{extract}[method]
+% \begin{arrayvar}{complete}[method]
+% \begin{arrayvar}{evaluate}[method]
+% \begin{arrayvar}{report}[method]
+% A method declares itself by setting its entry in the |extract|,
+% |complete|, |evaluate|, or |report| respectively array. The
+% entries in these arrays are lists of dialog item names, more
+% precisely the names of those setting details that are relevant for
+% the method in question. The indices into these arrays are unpretty
+% method names.
+% \end{arrayvar}\end{arrayvar}\end{arrayvar}\end{arrayvar}
+%
+% Most method types employ a model with distinct ``begin'', ``iterate'',
+% and ``end'' procedures that the main executive calls. For each command
+% and method, the ``begin'' is called first once, then the ``iterate''
+% may be called any number of times, and last the ``end'' is called once.
+% The details to use for the method are only provided in the call to
+% ``begin'' as that procedure is expected to store the relevant data
+% into variables private to the method (residing in its namespace). In
+% most cases, the actual code being evaluated is only handled by the
+% ``iterate'' procedure, and only the ``end'' procedure gets to know
+% how it all turned out.
+%
+% In many methods, some of these procedures do nothing at all. This is
+% then because there is nothing that needs to be done for that particular
+% method.
+%
+% \begin{proc}{multiupvar}
+% The |multiupvar| procedure does |upvar #0| for a number of
+% variables, prepending the namespace of the caller to each of the
+% \word{other-var} arguments of |upvar|. The syntax is
+% \begin{quote}
+% |eemenu::multiupvar| \word{my-var}\regplus
+% \end{quote}
+% \changes{v\,0.2}{2002/12/26}{Corrected a minor bug: one must look
+% at the first element in the list that info level returns. (LH)}
+% \begin{tcl}
+%<*!atcl7>
+proc eemenu::multiupvar {args} {
+ foreach var $args {uplevel 1 [list variable $var]}
+}
+%</!atcl7>
+%<*atcl7>
+proc eemenu::multiupvar {args} {
+ if {[info level]>1} then {
+ set ns [lindex [info level -1] 0]
+ set t [string last :: $ns]
+ if {$t<0} then {set ns {}} else {
+ set ns [string range $ns 0 [expr {$t+1}]]
+ }
+ } else {set ns {}}
+ set t 1
+ set call [list upvar #0]
+ foreach var $args {lappend call ${ns}${var} $var}
+ uplevel 1 $call
+}
+%</atcl7>
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{The main executive}
+%
+% \begin{arrayvar}{cmdA}[command name]
+% The |cmdA| array stores all definitions of \eemenu\ commands. The
+% indices into the array are the command names. The entries are
+% key--value lists which contain the settings for the command.
+%
+% The \describestring[key]{active}|active|,
+% \describestring[key]{binding}|binding|, and
+% \describestring[key]{mode}|mode| keys have to do with the key
+% binding for this command. If |active| is |1| then the binding should
+% be made upon startup. |binding| is the actual binding to use. |mode|
+% is the mode for which the binding should be made; if this is
+% |<none>| then the binding should be global.
+%
+% The \describestring[key]{in_menu}|in_menu| key controls whether
+% this command should appear as a command in the main \textsf{EE}
+% menu.
+%
+% The \describestring[key]{extractor}|extractor|,
+% \describestring[key]{complete}|complete|,
+% \describestring[key]{evaluator}|evaluator|, and
+% \describestring[key]{reporter}|reporter| keys store the particular
+% methods that are used by the command. The values are prettified
+% method names. For each of these keys there is also an \dots|_extra|
+% key whose value is the key--value list of detail settings for that
+% method. The exact names are \describestring[key]{extract_extra}
+% |extract_extra|, \describestring[key]{complete_extra}
+% |complete_extra|, \describestring[key]{eval_extra}|eval_extra|, and
+% \describestring[key]{report_extra}|report_extra|.
+%
+% If the |cmdA| array isn't set then it will be initialised in
+% Section~\ref{Sec:DefCmdA}.
+% \end{arrayvar}
+%
+%
+%
+% \begin{proc}{main}
+% The |main| procedure is meant to be called from key binding scripts
+% and menu procs to actually carry out an \eemenu\ command. The
+% syntax is
+% \begin{quote}
+% |eemenu::main| \word{command name} \meta{selection-args}
+% \end{quote}
+% The \word{command name} is the name of the \eemenu\ command. The
+% \meta{selection-args} can be used to specify what the command
+% should extract from; they are passed straight on to the extraction
+% method |start| procedure.
+%
+% If there was an error during the execution of the command then |main|
+% terminates with an error. There is no particular result from this
+% procedure.
+%
+% The first part of |main| calls the begin procedures of the methods
+% used.
+% \begin{tcl}
+proc eemenu::main {command args} {
+ global eemenu::cmdA
+ if {![info exists eemenu::cmdA($command)]} then {
+ error "Command '$command' undefined."
+ }
+ array set CMD [set eemenu::cmdA($command)]
+% \smallskip
+ set extract [eemenu::Unprettify $CMD(extractor)]
+ set cmpl [eemenu::Unprettify $CMD(complete)]
+ set eval [eemenu::Unprettify $CMD(evaluator)]
+ set report [eemenu::Unprettify $CMD(reporter)]
+% \smallskip
+ set win\
+ [eval [list eemenu::${extract}::start $CMD(extract_extra)] $args]
+ upvar #0 eemenu::${cmpl}::complete complete
+ eemenu::${report}::log_open $CMD(report_extra) $win
+% \end{tcl}
+% The main part of |main| is the following loop over extracted lines.
+% The |res| variable stores the last result returned by the evaluation
+% method. The |safe| variable is a boolean for whether the current
+% position should be considered safe. The |lines| variable contains
+% the lines extracted but not yet evaluated. The |at_end| variable is
+% |0| until the end of the extractable portion of the code has been
+% encountered.
+% \begin{tcl}
+ set res [eemenu::${eval}::begin $CMD(eval_extra) $win]
+ eval [list eemenu::${report}::log_result] $res
+ set lines [list]
+ set safe 1
+ while {![lindex $res 0]} {
+% \end{tcl}
+% First extract the next line of code and append it to |lines|.
+% \begin{tcl}
+ set at_end [catch {eemenu::${extract}::next $safe} line]
+ if {$at_end == 1} then {
+ global errorInfo
+ return -code error -errorinfo $errorInfo
+ } elseif {$at_end == 0} then {
+ lappend lines $line
+ } elseif {![llength $lines]} then {break}
+% \end{tcl}
+% Secondly check if there is a complete block of code in |lines|.
+% \begin{tcl}
+ set safe [expr $complete]
+ if {$at_end && !$safe} then {
+ set safe [expr {![dialog::yesno -y No -n Yes\
+ "The last [llength $lines] lines do not appear to be a\
+ complete block of code. Evaluate anyway?"]}]
+ if {!$safe} then {
+ set res [list 1 "" ""]
+ break
+ }
+ }
+% \end{tcl}
+% Finally log code, evaluate it, and log the result. This should
+% happen when |lines| contains a complete block of code. If there is
+% no error in evaluating the code then the current position will be
+% safe at the next iteration of the loop, and if there is an error
+% then the loop will not be iterated anyway. Hence the use of |safe|
+% is correct.
+% \begin{tcl}
+ if {$safe} then {
+ eemenu::${report}::log_code $lines
+ set res [eemenu::${eval}::item $lines]
+ eval [list eemenu::${report}::log_result] $res
+ set lines [list]
+ }
+ }
+% \end{tcl}
+% If an error has already been detected then it doesn't matter if
+% |end| evaluates without error, but it could also be that no error
+% results are returned before |end|.
+% \begin{tcl}
+ if {[lindex $res 0]} then {
+ eval [list eemenu::${report}::log_result] [eemenu::${eval}::end]
+ } else {
+ set res [eemenu::${eval}::end]
+ eval [list eemenu::${report}::log_result] $res
+ }
+ eemenu::${extract}::finish [lindex $res 0]
+ eemenu::${report}::log_close
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{The key bindings}
+%
+% There is a small system for managing the \eemenu\ key bindings. There
+% are two reasons for this: deactivating a command should only unbind a
+% binding if that binding is really currently used for that command,
+% and the \textsf{Active~Commands} submenu should match the actual
+% bindings.
+%
+% \begin{proc}{binding_index}
+% The |binding_index| procedure makes an index into the |binding| array.
+% The syntax is
+% \begin{quote}
+% |eemenu::binding_index| \word{mode} \word{binding}
+% \end{quote}
+% Both an empty string and |<none>| as \word{mode} are interpreted as
+% ``global''.
+% \begin{tcl}
+proc eemenu::binding_index {mode binding} {
+ if {"<none>"==$mode} then {set mode ""}
+ set mode [string range "[string trim $mode] " 0 3]
+ return "$mode$binding"
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{arrayvar}{binding}
+% The |binding| array is used to keep track of which command is
+% currently using a particular binding. The entries in this array are
+% command names. The indices have the form
+% \begin{quote}
+% \meta{mode}\meta{binding}
+% \end{quote}
+% where \meta{mode} is the mode and \meta{binding} is the menu-style
+% code for the binding. \meta{mode} is padded on the right with
+% spaces to exactly four characters. The \meta{mode} for global
+% bindings is four spaces.
+% \end{arrayvar}
+%
+% \begin{proc}{init_bindings}
+% The |init_bindings| procedure initialises the |binding| array and
+% the actual key bindings to match the data in the |cmdA| array. It
+% should be called when the menu is activated, but before the menu
+% itself is built.
+% \begin{tcl}
+proc eemenu::init_bindings {} {
+ eemenu::multiupvar cmdA binding
+ foreach cmd [array names cmdA] {
+% \end{tcl}
+% Only commands that are active needs to be considered.
+% \begin{tcl}
+ array set A $cmdA($cmd)
+ if {!$A(active)} then {continue}
+% \end{tcl}
+% The state of the binding must also be determined. It could be that
+% some other \textsf{EE~Menu} command is using the same binding, in
+% which case the user should be informed of this.
+% \begin{tcl}
+ set idx [eemenu::binding_index $A(mode) $A(binding)]
+ if {[info exists binding($idx)] &&\
+ ![dialog::yesno "To activate '$cmd', I must first deativate\
+ '$binding($idx)'. Proceed?"]}\
+%
+ then {continue}
+% \end{tcl}
+% Now the binding can be made for the command.
+% \begin{tcl}
+ set binding($idx) $cmd
+ set call [keys::bindKey $A(binding)]
+ lappend call [list eemenu::main $cmd]
+ if {[string compare "<none>" $A(mode)]} then {lappend call $A(mode)}
+ eval $call
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{deactivate}
+% The |deactivate| procedure has the syntax
+% \begin{quote}
+% |eemenu::deactivate| \word{\eemenu\ command}\regplus
+% \end{quote}
+% It deactivates the bindings for all commands listed as arguments
+% and updates the \textsf{Active Commands} submenu accordingly.
+% \begin{tcl}
+proc eemenu::deactivate {args} {
+ eemenu::multiupvar binding cmdA
+ foreach cmd $args {
+% \end{tcl}
+% First make sure the binding is actually active.
+% \begin{tcl}
+ array set A $cmdA($cmd)
+ set idx [eemenu::binding_index $A(mode) $A(binding)]
+ if {![info exists binding($idx)] ||\
+ [string compare $binding($idx) $cmd]} then {continue}
+% \end{tcl}
+% Then unset everything that has to do with it.
+% \begin{tcl}
+ unset binding($idx)
+ set call [keys::unbindKey $A(binding)]
+ lappend call ""
+ if {[string compare "<none>" $A(mode)]} then {lappend call $A(mode)}
+ eval $call
+ markMenuItem -m "Active Commands" $cmd off
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{activate}
+% The |activate| procedure activates the bindings for the \eemenu\
+% commands listed as arguments. It has the syntax
+% \begin{quote}
+% |eemenu::activate| \word{noisy} \word{\eemenu\ command}\regplus
+% \end{quote}
+% The procedure notices and handles the case that the binding for an
+% already active command coincides with that of some command to
+% activate, usually by deactivating the active command. The \word{noisy}
+% argument controls how it will behave in this. If \word{noisy} is |0|
+% then it will merely show a list of deactivations on the status bar,
+% but if it is |1| then it will put up a dialog and ask first.
+% \begin{tcl}
+proc eemenu::activate {noisy args} {
+ eemenu::multiupvar binding cmdA
+ set deactiveL [list]
+ foreach cmd $args {
+% \end{tcl}
+% First determine the state of the binding.
+% \begin{tcl}
+ array set A $cmdA($cmd)
+ set idx [eemenu::binding_index $A(mode) $A(binding)]
+ if {[info exists binding($idx)]} then {
+ if {![string compare $binding($idx) $cmd]} then {continue}
+% \end{tcl}
+% In this case the binding is being used by some other command.
+% Should that be deactivated?
+% \begin{tcl}
+ if {$noisy && ![dialog::yesno "To activate '$cmd', I must\
+ first deativate '$binding($idx)'. Proceed?"]} then {continue}
+% \end{tcl}
+% Here we know it should. Deactivation can be simplified since the
+% binding will anyway be overwritten later.
+% \begin{tcl}
+ lappend deactiveL $binding($idx)
+ markMenuItem -m "Active Commands" $binding($idx) off
+ }
+% \end{tcl}
+% Now activate the binding, as was the original intention.
+% \begin{tcl}
+ set binding($idx) $cmd
+ set call [keys::bindKey $A(binding)]
+ lappend call [list eemenu::main $cmd]
+ if {[string compare "<none>" $A(mode)]} then {lappend call $A(mode)}
+ eval $call
+ markMenuItem -m "Active Commands" $binding($idx) on\
+ [text::Ascii 18 1]
+ }
+ if {!$noisy && [llength $deactiveL]} then {
+ status::msg "Deactivated commands: [join $deactiveL ", "]"
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Building and handling the menu}
+%
+% \begin{proc}{build_menu}
+% The |build_menu| procedure builds the menu. It is called when the
+% menu is initially created and whenever some command settings have
+% been edited.
+% \begin{tcl}
+proc eemenu::build_menu {} {
+ eemenu::multiupvar cmdA binding
+ set items [list "Edit Commands[text::Ascii 201 1]"]
+ if {[array size cmdA] > 0} then {
+%<atcl7> set cmdL [lsort -ignore [array names cmdA]]
+%<!atcl7> set cmdL [lsort -dictionary [array names cmdA]]
+ lappend items [list Menu -n "Active Commands" -m\
+ -p eemenu::menu_proc $cmdL]
+ lappend items "(-)"
+ foreach cmd $cmdL {
+ array set A $cmdA($cmd)
+ if {$A(in_menu)} then {lappend items $cmd}
+ }
+ }
+ global eeMenu
+ Menu -n $eeMenu -m -p eemenu::menu_proc $items
+ if {[array size cmdA]} then {
+ foreach idx [array names binding] {
+ markMenuItem -m "Active Commands" $binding($idx) on\
+ [text::Ascii 18 1]
+ }
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{menu_proc}
+% The |menu_proc| handles selection of items in the \emph{EE} menu and
+% its submenu. The syntax is the standard
+% \begin{quote}
+% |eemenu::menu_proc| \word{menu} \word{item}
+% \end{quote}
+% \begin{tcl}
+proc eemenu::menu_proc {menu item} {
+ global eeMenu
+ eemenu::multiupvar cmdA binding
+ switch -- $menu $eeMenu {
+ switch -- $item "Edit Commands" {
+ eemenu::edit_commands
+ } default {
+ eemenu::main $item
+ }
+ } "Active Commands" {
+ array set A $cmdA($item)
+ set idx [eemenu::binding_index $A(mode) $A(binding)]
+ if {[info exists binding($idx)] &&\
+ ![string compare $binding($idx) $item]} then {
+ eemenu::deactivate $item
+ } else {
+ eemenu::activate 1 $item
+ }
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{The command dialogs}
+% \label{Ssec:CmdDialogs}
+%
+% The dialog for editing command settings has two levels. On the top
+% level, the dialog has one page per command. This dialog allows one to
+% select methods, but does not show any detail settings for the methods.
+% The other level has one page for each method type (or less) and shows
+% only the detail settings for that method.
+%
+% \begin{arrayvar}{detail_typeA}
+% \begin{arrayvar}{detail_helpA}
+% \begin{arrayvar}{detail_keyA}
+% The |detail_typeA| and |detail_helpA| arrays define the items in the
+% setting details dialog. They are sent as arguments to
+% |dialog::handle|, and thus the indices have the form
+% \meta{page}|,|\meta{name}. The \meta{page} is either |Extract|
+% for the extraction method page, |Complete| for the completion
+% method page, |Evaluate| for the evaulation method page, or |Report|
+% for the report method page. The |detail_keyA| array gives the keys
+% associated with the items.
+% \end{arrayvar}\end{arrayvar}\end{arrayvar}
+%
+% \begin{arrayvar}{detail_defaultA}
+% The |detail_defaultA| array is indexed by the name of a detail page
+% (|Extract|, |Complete|, |Evaluate|, or |Report|). The entries are
+% key--value lists that constitute suggested defaults for the
+% \dots|_extra| items in the main dialog.
+% \begin{tcl}
+array set eemenu::detail_defaultA\
+ {Extract {} Complete {} Evaluate {} Report {}}
+% \end{tcl}
+% \end{arrayvar}
+%
+% \begin{proc}{define_detail}
+% The |define_detail| procedure is a helper to simplify the definition
+% of items in the detail dialogs by handling internally all the odd
+% variable names that are involved. The syntax is
+% \begin{quote}
+% |eemenu::define_detail| \word{page} \word{name} \word{key}
+% \word{type} \word{value}\regopt\ \word{help}\regopt
+% \end{quote}
+% \word{page} and \word{name} specify the item. \word{key},
+% \word{type}, \word{value}, and \word{help} are what will be stored
+% into the arrays. The return value is precisely \word{name}, so that
+% one can put that in the |extract|, |complete|, |evaluate|, or
+% |report| array in the same command as the item is defined.
+%
+% It is OK to define the same item several times, provided that the
+% definitions are equal (or different only in the \word{value}s or
+% in that one has a \word{help} and the other doesn't), but it is an
+% error if they are different.
+% \begin{tcl}
+proc eemenu::define_detail {page name key type {val ""} {help ""}} {
+ upvar #0 eemenu::detail_typeA typeA eemenu::detail_helpA helpA\
+ eemenu::detail_keyA keyA eemenu::detail_defaultA valA
+ set error ""
+ set idx "$page,$name"
+ if {![info exists keyA($idx)]} then {
+ set keyA($idx) $key
+ } elseif {"$key" != "$keyA($idx)"} then {
+ append error " Different keys: '$keyA($idx)' and '$key'."
+ }
+ if {![info exists typeA($idx)]} then {
+ set typeA($idx) $type
+ } elseif {"$type" != "$typeA($idx)"} then {
+ append error " Different types: '$typeA($idx)' and '$type'."
+ }
+ if {[string length $val]} then {
+ if {[info exists valA($page)]} then {array set A $valA($page)}
+ if {![info exists A($key)] || ![string length $A($key)]} then {
+ set A($key) $val
+ set valA($page) [array get A]
+ }
+ }
+ if {[string length $help]} then {
+ if {![info exists helpA($idx)]} then {
+ set helpA($idx) $help
+ } elseif {"$help" != "$helpA($idx)"} then {
+ append error " Different help texts: '$helpA($idx)' and '$help'."
+ }
+ }
+ if {[string length $error]} then {
+ dialog::alert "The detail setting '$name' for '$page' methods\
+ has conficting definitions.$error This is an error that should
+ be fixed; for now, the second definition will be ignored."
+ }
+ return $name
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}{edit_commands}
+% The |edit_commands| procedure puts up a dialog that lets the user
+% edit the command settings. It takes no arguments and returns nothing.
+% \begin{tcl}
+proc eemenu::edit_commands {} {
+ global eemenu::extract eemenu::complete eemenu::evaluate\
+ eemenu::report
+% \end{tcl}
+% The first thing to do is to determine the layout for command pages.
+% \begin{tcl}
+ set layout [list]
+ lappend layout [list active flag Active "Is the binding active?"]
+ lappend layout [list binding binding "Command keybinding"]
+ lappend layout [list mode mode "Binding mode"]
+ lappend layout [list in_menu flag "Put in menu"]
+% \smallskip
+%<*atcl7>
+ set M [list]
+ foreach method [lsort -ignore [array names eemenu::extract]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list extractor [list menu $M] "Extraction method"]
+ lappend layout [list extract_extra [list hidden keyval] extract_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -ignore [array names eemenu::complete]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list complete [list menu $M] "Completion test"]
+ lappend layout [list complete_extra [list hidden keyval] complete_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -ignore [array names eemenu::evaluate]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list evaluator [list menu $M] "Evaluation method"]
+ lappend layout [list eval_extra [list hidden keyval] eval_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -ignore [array names eemenu::report]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list reporter [list menu $M] "Report method"]
+ lappend layout [list report_extra [list hidden keyval] report_extra]
+%</atcl7>
+%<*!atcl7>
+ set M [list]
+ foreach method [lsort -dictionary [array names eemenu::extract]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list extractor [list menu $M] "Extraction method"]
+ lappend layout [list extract_extra [list hidden keyval] extract_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -dictionary [array names eemenu::complete]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list complete [list menu $M] "Completion test"]
+ lappend layout [list complete_extra [list hidden keyval] complete_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -dictionary [array names eemenu::evaluate]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list evaluator [list menu $M] "Evaluation method"]
+ lappend layout [list eval_extra [list hidden keyval] eval_extra]
+% \smallskip
+ set M [list]
+ foreach method [lsort -dictionary [array names eemenu::report]] {
+ lappend M [eemenu::Prettify $method]
+ }
+ lappend layout [list reporter [list menu $M] "Report method"]
+ lappend layout [list report_extra [list hidden keyval] report_extra]
+%</!atcl7>
+% \end{tcl}
+% Then the call to |dialog::make_paged| can be constructed (in the
+% |call| variable), but as it is convenient to do that in order, the
+% page arguments (which are the easiest) will be constructed last.
+% \begin{tcl}
+ global dialog::ellipsis
+ if {![info exists dialog::ellipsis]} then {auto_load dialog::make_paged}
+ set call [list dialog::make_paged]
+ set buttons [list]
+ lappend buttons "New${dialog::ellipsis}" "Add new command"\
+ {eemenu::add_command ""}
+ lappend buttons "Duplicate${dialog::ellipsis}"\
+ "Duplicate this command" {eemenu::add_command $currentpage}
+ lappend buttons "Rename${dialog::ellipsis}"\
+ "Rename this command" {eemenu::rename_command}
+ lappend buttons "Delete${dialog::ellipsis}"\
+ "Delete this command" {
+ if {[dialog::yesno "Are you sure you want to\
+ delete '$currentpage'?"]} {
+ set pages [dialog::delete_pages $pages\
+ [list $currentpage] delta_pages]
+ }
+ }
+ lappend buttons "Details${dialog::ellipsis}"\
+ "Setting details for this command" {
+ eemenu::command_details $dial $currentpage
+ }
+ lappend call -addbuttons $buttons -changeditems mods\
+ -alpha7pagelimit 2
+% \end{tcl}
+% Finally the page arguments to |dialog::make_paged| can be appended
+% and the actuall call made.
+% \begin{tcl}
+ global eemenu::cmdA
+%<atcl7> foreach cmd [lsort -ignore [array names eemenu::cmdA]] {
+%<!atcl7> foreach cmd [lsort -dictionary [array names eemenu::cmdA]] {
+ lappend call [list $cmd [set eemenu::cmdA($cmd)] $layout]
+ }
+ set res [eval $call]
+% \end{tcl}
+% If |make_paged| terminates with an error (the user pressed
+% \textsf{Cancel}) then processing of this procedure should stop here.
+% Thus the |eval| above is quite in order.
+%
+% After that, the settings should be updated. The first step is to
+% deactivate those commands whose activation state, binding, or mode
+% has changed, since that has to be done before the old settings
+% are cleared.
+% \begin{tcl}
+ set call [list eemenu::deactivate]
+ newforeach {cmd keys} $mods {
+ if {[lsearch -regexp $keys {^(active|binding|mode)$}]>=0 &&\
+ [info exists eemenu::cmdA($cmd)]} then {
+ lappend call $cmd
+ }
+ }
+ if {[llength $call]>1} then {eval $call}
+% \end{tcl}
+% Now the new settings can replace the old.
+% \begin{tcl}
+ unset eemenu::cmdA
+ array set eemenu::cmdA $res
+% \end{tcl}
+% Then what remains is (i) to inform \Alpha\ that the changed command
+% settings need to be saved, (ii) to make bindings for those commands
+% that are active, and (iii) to add or remove items from the menu.
+% \begin{tcl}
+ set call [list eemenu::activate 0]
+ set build_menu 0
+%<atcl7> newforeach {cmd keys} $mods {
+%<!atcl7> foreach {cmd keys} $mods {
+ prefs::modified eemenu::cmdA($cmd)
+ if {![info exists eemenu::cmdA($cmd)]}\
+ then {set build_menu 1; continue}
+ array set A [set eemenu::cmdA($cmd)]
+ if {$A(active) &&\
+ [lsearch -regexp $keys {^(active|binding|mode)$}]>=0}\
+ then {lappend call $cmd}
+ if {[lsearch -exact $keys in_menu]>=0} then {set build_menu 1}
+ }
+ if {[llength $call]>2} then {eval $call}
+ if {$build_menu} then {eemenu::build_menu}
+}
+% \end{tcl}
+% The conditions used above rely to some extent on the fact that
+% \emph{all} items on a dialog page that is added or deleted count as
+% having been changed.
+% \end{proc}
+%
+% \begin{proc}{add_command}
+% The |add_command| procedure is called by a button script to add a
+% new command page to the dialog. The syntax is
+% \begin{quote}
+% |eemenu::add_command| \word{template}
+% \end{quote}
+% where \word{template} is the name of a command whose settings should
+% be copied, or an empty string if the default settings should be used.
+% \begin{tcl}
+proc eemenu::add_command {templ} {
+ set name [getline "Name of new command"]
+ if {![string length $name]} then {return}
+%<atcl7> newforeach {page items} [uplevel 1 {set pages}] {
+%<!atcl7> foreach {page items} [uplevel 1 {set pages}] {
+ if {![string compare $page $name]} then {
+ alternote "That name is already in use!"
+ return
+ }
+ }
+% \end{tcl}
+% By default, make new commands inactive and don't put them in the
+% menu. This is to avoid silly errors in case the user wants to do
+% a ``backup'' of a command.
+% \begin{tcl}
+ set keyvals [list active 0 in_menu 0]
+ if {[string length $templ]} then {
+ set dial [uplevel 1 {set dial}]
+ set cpage [uplevel 1 {set currentpage}]
+%<atcl7> newforeach {key item}\
+%<!atcl7> foreach {key item}\
+ {binding {Command keybinding} mode {Binding mode}
+ extractor {Extraction method} extract_extra extract_extra
+ complete {Completion test} complete_extra complete_extra
+ evaluator {Evaluation method} eval_extra eval_extra
+ reporter {Report method} report_extra report_extra} {
+ lappend keyvals $key [dialog::valGet $dial "${cpage},${item}"]
+ }
+ } else {
+ lappend keyvals binding "" mode "" extractor "Raw"
+ upvar #0 eemenu::detail_defaultA defaultA
+ lappend keyvals extract_extra $defaultA(Extract)
+ lappend keyvals complete "Entire Selection" complete_extra\
+ $defaultA(Complete)
+ lappend keyvals evaluator "Internal Tcl" eval_extra\
+ $defaultA(Evaluate)
+ lappend keyvals reporter "Status Line" report_extra $defaultA(Report)
+ }
+ uplevel 1 [list dialog::add_page $name $keyvals [uplevel 2 set layout]]
+ uplevel 1 [list set currentpage $name]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{rename_command}
+% The |rename_command| procedure is called by a button script to rename
+% an existing command. There are no arguments.
+% \begin{tcl}
+proc eemenu::rename_command {} {
+ upvar 1 currentpage cpage dial dial
+ set name [getline "New name for command '$cpage'"]
+ if {![string length $name]} then {return}
+%<atcl7> newforeach {page items} [uplevel 1 {set pages}] {
+%<!atcl7> foreach {page items} [uplevel 1 {set pages}] {
+ if {![string compare $page $name]} then {
+ alternote "That name is already in use!"
+ return
+ }
+ }
+% \end{tcl}
+% Technically, the page with the old name is deleted and a new page
+% with the new name is added. The keyvals have to saved to a list in
+% between.
+% \begin{tcl}
+ set keyvals [list]
+%<atcl7> newforeach {key item} {active Active in_menu {Put in menu}\
+%<!atcl7> foreach {key item} {active Active in_menu {Put in menu}\
+ binding {Command keybinding} mode {Binding mode}\
+ extractor {Extraction method} extract_extra extract_extra\
+ complete {Completion test} complete_extra complete_extra\
+ evaluator {Evaluation method} eval_extra eval_extra\
+ reporter {Report method} report_extra report_extra} {
+ lappend keyvals $key [dialog::valGet $dial "${cpage},${item}"]
+ }
+ uplevel 1 {
+ set pages [dialog::delete_pages $pages [list $currentpage]\
+ delta_pages]
+ }
+ uplevel 1 [list dialog::add_page $name $keyvals [uplevel 2 set layout]]
+ set cpage $name
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{command_details}
+% The |command_details| procedure is called by a button script to let
+% the user see and edit the details of a command. The syntax is
+% \begin{quote}
+% |eemenu::command_details| \word{dialog ref.} \word{command}
+% \end{quote}
+% The \word{dialog ref.} is the reference to pass on to
+% |dialog::valGet| and the like, as that is the only way to access the
+% data that should be shown in the dialog. The \word{command} is the
+% name of the command whose details should be shown, which is also the
+% \meta{page} part of the array index that |dialog::valGet| needs.
+%
+% Most of this procedure consists of moving data from the data
+% structures of one dialog to those of another, and back again. More
+% precisely, data is taken from the \dots|_extra| items in the main
+% dialog and put (using |array set|) into the local arrays |A1|, |A2|,
+% |A3|, and |A4|. Then those entries in these arrays which correspond
+% to details for the current set of methods are stored as dialog item
+% values for |dial2|. At the end, those |dial2| items values that were
+% changed are copied back to the corresponding |A| array, and then
+% these arrays are put back (using |array get|) into the corresponding
+% \dots|_extra| items in the main dialog.
+%
+% At the same time as the data are copied from the main dialog to the
+% details dialog, the list of pages and items in the latter is being
+% built. The information about this is taken from the |extract|,
+% |complete|, |evaluate|, and |report| arrays.
+% \begin{tcl}
+proc eemenu::command_details {dial command} {
+ global eemenu::detail_typeA eemenu::detail_helpA\
+ eemenu::detail_keyA eemenu::extract eemenu::complete\
+ eemenu::evaluate eemenu::report
+ set pages [list]
+ set dial2 [dialog::create]
+% \end{tcl}
+% Exactly the same processing is done for all four pages of the
+% details dialog, but since the location of the source data varies a
+% bit irregularly between the pages, it is easiest to make a table of
+% which variables and indices should be used. There is one line per
+% page in the |newforeach| below.
+% \begin{tcl}
+%<atcl7> newforeach {which page layoutarr data arr} {
+%<!atcl7> foreach {which page layoutarr data arr} {
+ {Extraction method} Extract eemenu::extract extract_extra A1
+ {Completion test} Complete eemenu::complete complete_extra A2
+ {Evaluation method} Evaluate eemenu::evaluate eval_extra A3
+ {Report method} Report eemenu::report report_extra A4
+ } {
+ set method [eemenu::Unprettify\
+ [dialog::valGet $dial ${command},${which}]]
+ set L [set ${layoutarr}($method)]
+ if {[llength $L]} then {
+ lappend pages $page $L
+ array set $arr [dialog::valGet $dial ${command},${data}]
+ foreach l $L {
+ set v [set eemenu::detail_keyA($page,$l)]
+ if {[info exists ${arr}($v)]} then {
+ dialog::valSet $dial2 "$page,$l" [set ${arr}($v)]
+ } else {
+% \end{tcl}
+% It turns out \AlphaEight\ doesn't like an empty string as value for
+% a checkbox, so the value is explicitly set to |0| for flags.
+% \changes{v\,0.3}{2003/04/11}{Added special default for flag items.
+% A similar fix should be put in the dialogs code. (LH)}
+% \begin{tcl}
+ switch -- [set eemenu::detail_typeA($page,$l)] flag {
+ dialog::valSet $dial2 "$page,$l" 0
+ } default {
+ dialog::valSet $dial2 "$page,$l" ""
+ }
+ }
+ }
+ }
+ }
+% \smallskip
+ if {![llength $pages]} then {
+ dialog::alert "There are no details for these methods."
+ dialog::cleanup $dial2
+ return
+ }
+ dialog::handle $pages eemenu::detail_typeA $dial2\
+ eemenu::detail_helpA page [list]\
+ [list [list "Back" "Return to overall dialog" ""] right first]
+% \smallskip
+ set L [dialog::changed_items $dial2]
+ foreach item $L {
+ switch -glob $item {
+ Extract,* {set arr A1}
+ Complete,* {set arr A2}
+ Evaluate,* {set arr A3}
+ Report,* {set arr A4}
+ }
+ set ${arr}([set eemenu::detail_keyA($item)])\
+ [dialog::valGet $dial2 $item]
+ }
+%<atcl7> newforeach {page data arr} {
+%<!atcl7> foreach {page data arr} {
+ Extract extract_extra A1
+ Complete complete_extra A2
+ Evaluate eval_extra A3
+ Report report_extra A4
+ } {
+ if {[lsearch -glob $L "${page},*"] >= 0} then {
+ dialog::valChanged $dial "${command},${data}" [array get $arr]
+ }
+ }
+ dialog::cleanup $dial2
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{\texttt{dialogsNew} patch}
+%
+% In the testing stage, I discovered that the |edit_commands| procedure
+% managed to overstress \Alpha7's |dialog| command almost without
+% trying. It is probably the large number of popup menus that is causing
+% trouble, but regardless of the cause, I found that I couldn't use this
+% dialog if it tried to show more than two commands.
+%
+% The \textsf{Edit Filesets} command faces a similar limitation and to
+% work around that there is a separate \textsf{Edit A Fileset} command.
+% As I didn't feel that much like reconstructing the \textsf{Edit
+% Commands} dialog however, I instead redesigned |dialog::make_paged|
+% so that \emph{it} automatically splits the dialog when there are too
+% many pages in it. The redesigned |make_paged| will however probably
+% not make it into Alpha\Tcllogo\ before v\,7.6d3 and at the moment
+% that seems like a bit restrictive to me. Hence \emph{EE~Menu} will
+% patch the \texttt{dialogsNew} code if this change hasn't already
+% been incorporated.
+%
+% \begin{tcl}
+%<*dialogspatch&atcl7>
+if {![llength [info commands dialog::make_paged]]} then {
+ auto_load dialog::make_paged
+}
+if {![regexp -- -alpha7pagelimit [info body dialog::make_paged]]} then {
+% \end{tcl}
+% The following is copied from \texttt{dialogsNew.dtx} v\,1.4.
+%
+% \setnamespace{dialog}
+%
+% \begin{proc}{make_paged}
+% The |make_paged| procedure is similar to the |make| procedure, but
+% its argument argument structure is slightly different, its return
+% value is very different, and it does have a couple of features that
+% |make| doesn't (such as adding or removing pages or items in a
+% dialog). The basic syntax is the same
+% \begin{quote}
+% |dialog::make_paged| \meta{option}\regstar\ \word{page}\regplus
+% \end{quote}
+% but here each \word{page} is a list with the structure
+% \begin{quote}
+% \word{page name} \word{key--value list} \word{item list}
+% \end{quote}
+% and each \word{item list} in turn is a list of items, each of with
+% are themselves lists and have the structure
+% \begin{quote}
+% \word{key} \word{type} \word{name} \word{help}\regopt
+% \end{quote}
+% The return value is a list with the structure
+% \begin{quote}
+% \begin{regexp}[\regplus]\word{page name}
+% \word{key--value list}\end{regexp}
+% \end{quote}
+% and in both cases the \word{key--value list} has the format of a
+% list returned by |array get|, i.e.,
+% \begin{quote}
+% \begin{regexp}[\regstar]\word{key} \word{value}\end{regexp}
+% \end{quote}
+%
+% Rather than (as with |make|) including the value of an item in its
+% \word{item} list, that list contains a \word{key} which references
+% a value stored in the \word{key--value list} of that page. The idea
+% with this is that the input and output formats for values should be
+% the same, so that the caller has little overhead in converting from
+% one data format to another. The \word{key--value list} format is
+% furthermore flexible in that is completely insensitive to changes
+% that add, remove, or rearrange items within a page. Extra
+% key--value pairs in the input are ignored and an empty string is
+% substituted as value for pairs that are missing.
+%
+% The \meta{option}s understood by |make_paged| are
+% \begin{quote}
+% |-ok| \word{OK button title}\\
+% |-cancel| \word{cancel button title}\\
+% |-title| \word{dialog window title}\\
+% |-defaultpage| \word{name of default page}\\
+% |-addbuttons| \word{button list}\\
+% |-width| \word{dialog window width}\\
+% |-alpha7pagelimit| \word{maximal number of pages}\\
+% |-debug| \word{debug level}\\
+% |-changedpages| \word{var-name}\\
+% |-changeditems| \word{var-name}
+% \end{quote}
+% Those that are common with |make| work exactly the same. The
+% |-changedpages| option specifies that the caller wants to know on
+% which pages something was changed. The \word{var-name} is the name
+% of a variable in the caller's local context which will be set to
+% the list of (names of) pages where some item value was changed. The
+% |-changeditems| option is similar, but here the variable will be set
+% to a list with the structure
+% \begin{quote}
+% \begin{regexp}[\regstar]\word{page name}
+% \word{key list}\end{regexp}
+% \end{quote}
+% where the \word{key list}s are lists of the \emph{keys} of items on
+% that page whose values were changed.
+%
+% \begin{tcl}
+proc dialog::make_paged {args} {
+% \end{tcl}
+%
+% |make_paged| largely has the same local variables as |make|, but
+% there are some additions. The major arrays are
+% \begin{description}
+% \item[\texttt{pageA}]
+% The index into this array is the name of a page. An entry
+% contains the list of names of items on that page.
+% \item[\texttt{typeA}]
+% The index into this array has the form
+% \meta{page}|,|\meta{item}, where \meta{page} is the name of a
+% page and \meta{item} is the name of an item on that page. An
+% entry contains the type of that item.
+% \item[\texttt{keyA}]
+% The index has the same form as in the |typeA| array. An entry
+% contains the \word{key} for that item.
+% \item[\texttt{helpA}]
+% The index has the same form as in the |typeA| array. An entry
+% contains the help text for that entry, but an item needs not
+% have an entry in this array (it can be left unset).
+% \end{description}
+% There are a couple of additional scalar variables that are of
+% interest.
+% \begin{description}
+% \item[\texttt{retCode}, \texttt{retVal}]
+% When the |retCode| variable is set, the dialog is logically
+% closed and the procedure returns. If the variable is set to |0|
+% then |make| executes a normal return and the returned value will
+% be the list of item values. If the variable is set to anything
+% else then that will used for the |-code| option of |return| and
+% the returned value will be taken from the |retVal| variable,
+% which must then be initalised.
+% \item[\texttt{dial}]
+% This contains the reference string to use with |valGet|,
+% |valSet|, and friends when accessing the values of items in
+% the dialog.
+% \item[\texttt{currentpage}]
+% This contains the name of the current page in the dialog.
+% \item[\texttt{delta\_pages}]
+% This is the list of all pages which have been added to or
+% deleted from the dialog since it was called. The |add_page| and
+% |delete_page| procedures both directly access this list. It is
+% needed to get the information for the |-changedpages| and
+% |-changeditems| correct.
+% \item[\texttt{pages}]
+% This is a list of pages and items to show in the dialog. It is
+% similar to the result of |array get pageA|, but the order of
+% pages is as specified in the call and hidden pages are not
+% included.
+% \item[\texttt{opts(-addbuttons)}]
+% This is \word{button list} specified by the caller. Button
+% scripts can modify this list to change the text on their button.
+% \item[\texttt{state}]
+% This is initialized to |0| before the first time the dialog is
+% shown and then the procedure leaves it alone. Button scripts may
+% change it to keep track of what ``state'' (mostly: which
+% items\slash pages are currently hidden) the dialog is in.
+% \item[\texttt{splitstate}]
+% This is the dialog splitting state and works as for
+% |dialog::make|.
+% \item[\texttt{optionL}]
+% The list of additional options to pass to |dialog::handle|.
+% \end{description}
+%
+% The first part of |dialog::make_paged| processes the arguments.
+% \begin{tcl}
+ set opts(-ok) OK
+ set opts(-cancel) Cancel
+ set opts(-title) ""
+ set opts(-width) 400
+ set opts(-debug) 0
+ getOpts {-title -defaultpage -ok -cancel -addbuttons -width -debug\
+ -alpha7pagelimit -changedpages -changeditems}
+ set dial [dialog::create]
+% \end{tcl}
+% The page arguments are interpreted by the |add_page| procedure.
+% Since these pages aren't new in the sense that is relevant for the
+% |delta_pages| list, that variable is reset afterwards. The
+% |splitstate| variable is implicitly updated by |add_page|.
+% \begin{tcl}
+ set pages [list]
+ set delta_pages [list]
+ if {[info exists opts(-alpha7pagelimit)] && [info tclversion]<8.0}\
+ then {
+ set splitstate below
+ } else {
+ set splitstate off
+ }
+ foreach pagearg $args {
+ eval [list dialog::add_page] $pagearg
+ }
+ set delta_pages [list]
+ if {$splitstate=="page"} then {set splitstate menu}
+ if {[info exists opts(-defaultpage)]} then {
+ set currentpage $opts(-defaultpage)
+ } else {
+ set currentpage [lindex $pages 0]
+ }
+ set optionL [list -width $opts(-width) -title $opts(-title)]
+ set main_buttons [list\
+%
+ [list $opts(-ok) "Click here to use the current settings."\
+ {set retCode 0}\
+%
+ $opts(-cancel) "Click here to discard any\
+ changes you've made to the settings."\
+ {set retCode 1; set retVal "cancel"}]\
+%
+ first right]
+ set view_button [list [list {View dialog page}\
+ {Click here to see the items on this page.}\
+ {set splitstate page}]]
+ set back_button [list [list "Back"\
+ {Click here to go back to the pages menu.}\
+ {set splitstate menu}] first right]
+% \end{tcl}
+%
+% The second part is the loop which lets the user edit the settings.
+% \begin{tcl}
+ set state 0
+ while {![info exists retCode]} {
+ switch -exact -- $splitstate off - below {
+ if {[info exists opts(-addbuttons)]} then {
+ set script [dialog::handle $pages typeA $dial helpA\
+ currentpage $optionL [list $opts(-addbuttons)]\
+ $main_buttons]
+ } else {
+ set script [dialog::handle $pages typeA $dial helpA\
+ currentpage $optionL $main_buttons]
+ }
+ } menu {
+ set altpages [list]
+ set n 1
+ foreach item $pages {
+ if {$n} then {
+ lappend altpages $item
+ set n 0
+ } else {
+ lappend altpages {}
+ set n 1
+ }
+ }
+ set script [dialog::handle $altpages typeA $dial helpA\
+ currentpage $optionL $view_button $main_buttons]
+ } page {
+% \end{tcl}
+% This is a small test to make sure that the value of |currentpage|
+% is valid. If it isn't then one should return to the |menu| state.
+% \begin{tcl}
+ if {![info exists pageA($currentpage)]} then {
+ set splitstate menu
+ continue
+ }
+ set altpages [list $currentpage $pageA($currentpage)]
+ if {[info exists opts(-addbuttons)]} then {
+ set script [dialog::handle $altpages typeA $dial helpA\
+ currentpage $optionL [list $opts(-addbuttons)]\
+ $back_button]
+ } else {
+ set script [dialog::handle $altpages typeA $dial helpA\
+ currentpage $optionL $back_button]
+ }
+ }
+ if {[catch $script err]} then {
+% \end{tcl}
+% The rest of this loop is simply for gracefully handling errors that
+% occur when button scripts are evaluated.
+% \begin{tcl}
+ global errorInfo
+ set errinfo $errorInfo
+ if {$opts(-debug)} then {
+ tclLog "Error in button script '$script'"
+ tclLog $err
+ }
+ dialog::cleanup $dial
+ return -code 1 -errorinfo $errinfo\
+ "Error '$err' when evaluating button script."
+ }
+ }
+% \end{tcl}
+%
+% The third part is as in |make| responsible for constructing the result
+% to return (at normal returns). Unlike the case with |make|, the
+% return value covers only the items currently in |pages|. This
+% part is also responsible for constructing the lists of changed
+% pages and items. Two important variables in this are |cS| and |cA|.
+% |cS| is an array which is used to test whether a certain item has
+% been changed (via |valChanged|), but the only thing that matters is
+% whether an entry has been set or not. |cA| is an array indexed by
+% page name, whereas the entries are lists of keys of items on that
+% page which have been changed.
+% \begin{tcl}
+ if {$retCode==0} then {
+ set retVal [list]
+ global dialog::mute_types
+ foreach page $delta_pages {
+ foreach name $pageA($page) {
+ lappend cA($page) $keyA($page,$name)
+ }
+ }
+ foreach item [dialog::changed_items $dial] {set cS($item) ""}
+ newforeach {page items} $pages {
+ set res [list]
+ foreach name $items {
+ set T "$page,$name"
+ if {[lsearch -exact ${dialog::mute_types}\
+ [lindex $typeA($T) 0]] < 0} then {
+ lappend res $keyA($T) [dialog::valGet $dial $T]
+ if {[info exists cS($T)]} then {
+ lunion cA($page) $keyA($T)
+ }
+ }
+ }
+ lappend retVal $page $res
+ }
+ if {[info exists opts(-changedpages)]} then {
+ upvar 1 $opts(-changedpages) cp
+ set cp [array names cA]
+ }
+ if {[info exists opts(-changeditems)]} then {
+ upvar 1 $opts(-changeditems) ci
+ set ci [array get cA]
+ }
+ }
+ dialog::cleanup $dial
+ return -code $retCode $retVal
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{add_page}
+% The |add_page| procedure can be called from within the |make_paged|
+% procedure to add a new page to the dialog. The syntax is
+% \begin{quote}
+% |dialog::add_page| \word{page name} \word{key--value list}
+% \word{item list} \word{position}\regopt
+% \end{quote}
+% Here the \word{page name}, \word{key--value list}, and \word{item
+% list} coincide with those parts of a \word{page} argument of
+% |make_paged|.
+%
+% |add_page| works by modifying the arrays |typeA|, |keyA|, |helpA|,
+% and |pageA|, the lists |pages| and |delta_pages|, and the variable
+% |splitstate| in the caller's local context. It also uses the value
+% in the |dial| variable there as an argument to |valSet| and the
+% |opts| array to access the |-alpha7pagelimit| value. All of these
+% variables are assumed to function as they do in the |make_paged|
+% procedure.
+%
+% The \word{position} argument can be used to specify where in the
+% |pages| list that the new page should be inserted. It defaults to
+% |end|, which puts the new page last. Otherwise the argument should
+% be numeric: |0| means put first, |1| means put second, |2| means put
+% third, etc.
+%
+% If |splitstate| is |below| and the number of pages equals (or is
+% greater than) the |-alpha7pagelimit| then the |splitstate| is
+% changed to |page|. If |splitstate| is |menu| then it is also
+% changed to |page|.
+% \begin{tcl}
+proc dialog::add_page {page keyvalL itemsL {pos end}} {
+ upvar pageA pageA typeA typeA helpA helpA keyA keyA\
+ dial dial pages pages delta_pages delta_pages\
+ splitstate splitstate opts opts
+ array set local $keyvalL
+ set pageA($page) [list]
+ lunion delta_pages $page
+ foreach item $itemsL {
+ set key [lindex $item 0]
+ set name [lindex $item 2]
+ set keyA($page,$name) $key
+ if {[info exists local($key)]} then {
+ dialog::valSet $dial $page,$name $local($key)
+ } else {
+ dialog::valSet $dial $page,$name ""
+ }
+ set typeA($page,$name) [lindex $item 1]
+ if {[llength $item]>3} then {
+ set helpA($page,$name) [lindex $item 3]
+ }
+ lappend pageA($page) $name
+ }
+ if {$pos!="end"} then {
+ set pages [linsert $pages [expr {2*$pos}] $page $pageA($page)]
+ } else {
+ lappend pages $page $pageA($page)
+ }
+ if {$splitstate=="menu" || ($splitstate=="below" &&\
+ [llength $pages]>2*$opts(-alpha7pagelimit))} then {
+ set splitstate page
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{delete_pages}
+% In one sense, this procedure does the opposite of |add_page|, but
+% it can be used to achieve different effects as well. Basically it
+% takes a list of page names and items, in the format for the first
+% argument of |handle|, and returns the same list with some pages
+% removed. The syntax is
+% \begin{quote}
+% |dialog::delete_pages| \word{pages} \word{delete-list}
+% \word{deleted-var}\regopt
+% \end{quote}
+% where the \word{delete-list} is the list of names of pages to
+% remove. \word{deleted-var} is, if it is given, the name of a
+% variable in the caller's local context containing a list of page
+% names. The deleted pages are then unioned with this list. The most
+% common value for \word{deleted-var} is |delta_pages|.
+%
+% If there is a \word{deleted-var} argument then this procedure might
+% also modify the |splitstate| variable in the caller's local
+% context. A value of |page| is changed to |menu| or |below| depending
+% on how meny pages are returned and the value of
+% |opts(-alpha7pagelimit)| in the caller's local context. (Both these
+% variables must exist if |delete_pages| is called with a
+% \word{deleted-var} argument.)
+% \begin{tcl}
+proc dialog::delete_pages {pages deleteL {deletedvar {}}} {
+ set res [list]
+ if {[string length $deletedvar]} then {upvar 1 $deletedvar diffL}
+ newforeach {page items} $pages {
+ if {[lsearch -exact $deleteL $page] == -1} then {
+ lappend res $page $items
+ } else {
+ lunion diffL $page
+ }
+ }
+ if {[string length $deletedvar]} then {
+ upvar splitstate state opts(-alpha7pagelimit) limit
+ switch -exact -- $state page - menu {
+ if {[llength $res]<=2*$limit} then {
+ set state below
+ } else {
+ set state menu
+ }
+ }
+ }
+ return $res
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{tcl}
+}
+%</dialogspatch&atcl7>
+% \end{tcl}
+% \setnamespace{eemenu}
+%
+%
+% \section{Extraction methods}
+% \label{Sec:Extraction}
+%
+% The extraction method is mainly a source of input for an \eemenu\
+% command, but it is also responsible for providing some feedback to the
+% user in the event that an error occurs. This feedback should take the
+% simple form of positioning the cursor at the beginning of the first
+% piece of code that could not be evaluated successfully. Extraction
+% methods are therefore expected to constantly keep track of the
+% position where the cursor should be put if an error occurs: this is
+% called the \emph{safe} position. As no other part of an \eemenu\
+% cares about positions, these are regarded as internal matters for
+% the extraction mathod. The feedback from the main executive is
+% restricted to answers to the simple questions ``Is the current position
+% safe?'' and ``Did an error occur?''
+%
+% Extractions are begun by a call to the
+% \describestring[proc][eemenu::\meta{method}]{start}|start|
+% procedure, which has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::start| \word{settings}
+% \word{window}\regopt\
+% \begin{regexp}[\regopt]\word{start} \word{end}\end{regexp}
+% \end{quote}
+% The \word{settings} is the |extract_extra| list of the command, and
+% contain the settings that should be used until the next call to
+% |start|. This list may contain key--value pairs for details not used
+% by the current method (but which presumably are used by others), and
+% it needs not contain key--value pairs for every detail that the
+% current method uses. Therefore the method should provide defaults
+% when necessary.
+%
+% The \word{window} is the name of the window from which code should be
+% extracted. If this is omitted then the extraction should default to
+% using the current window. The \word{start} and \word{end} are
+% positions of the beginning and end respectively of the interval from
+% which code should be extracted, but they are normally not used. When
+% these are omitted then the method may do whatever seems reasonable,
+% but the following algorith is recommended:
+% \begin{itemize}
+% \item If there is a selection in the window, then substitute the
+% position of its beginning for \word{start} and the position of its
+% end for \word{end}.
+% \item Otherwise do the entire window, i.e., let \word{start} be the
+% |minPos| and \word{end} be the |maxPos|.
+% \end{itemize}
+% The main reason that \word{start} and \word{end} at all exist as
+% arguments is that this simplifies testing and debugging, but it also
+% enables virtual methods to make their own decisions about from where
+% the code should be extracted.
+%
+% The |start| procedure returns the file name (complete path, no count)
+% of the source window. This is passed on to the begin procedures of
+% other methods, but most of them ignore it anyway. If something is
+% wrong with the arguments supplied to it then |start| terminates with
+% an error.
+%
+% To actually extract a line, the main executive calls the
+% \describestring[proc][eemenu::\meta{method}]{next}|next| procedure,
+% which has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::next| \word{is safe}
+% \end{quote}
+% This procedure returns the next extractable code line, or terminates
+% with return code 9 if there is no more line.
+% \changes{v\,0.2}{2002/12/26}{Throwing abort instead of error, since
+% it otherwise catches too many real errors. (LH)}
+% The \word{is safe} argument is |1| if the current position should be
+% considered safe and |0| otherwise.
+%
+% Extraction is terminated by a call to the
+% \describestring[proc][eemenu::\meta{method}]{finish}|finish|
+% procedure. This has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::finish| \word{error?}
+% \end{quote}
+% where the \word{error?} argument is |1| if there was an error in
+% evaluation and |0| otherwise. This procedure does not return any data.
+%
+%
+% \subsection{Some position utilities}
+%
+% \textit{\textbf{Note:} The procedures in this subsection were probably
+% not a good idea to start with, so they are no longer included by
+% default.} For the historically interested reader, it may be remarked
+% that the code below predates the addition in \AlphaTcl\,7.6 of |-w|
+% options to most standard position procedures.
+%
+% Extraction procedures should generally not assume that the window from
+% which code is being extracted is the current window. The reason for
+% this is that if \Alpha\ is evaulating internally then the extracted
+% code may bring some other window to front or, more commonly, create a
+% new window (which will by default go on top of all others). This is
+% kind of tricky since many of \Alpha's commands for working with
+% positions implicitly assume that the positions are in the current
+% window, but it can be delt with by storing positions are a pair
+% |{|\word{row} \word{column}|}| instead, as the |rowColToPos| command
+% which converts this to a standard position does accept a window
+% argument.
+%
+% Handling explicitly such positions is however more work that it
+% should be, so here follows some generic utility procs to deal with
+% positions specified as lists with the structure
+% \begin{quote}
+% \word{window} \word{row} \word{column} \word{standard pos}\regopt
+% \end{quote}
+% Here, \word{window} is a full window name (as returned by the
+% |win::Current| procedure), whereas \word{row} and \word{column}
+% are integers. The optional \word{standard pos} element is the standard
+% position (that which should be used in calls to \Alpha\ primitives) if
+% it has been computed by a call to |rowColToPos|. If it has not been
+% computed then this element should not be present in the list.
+%
+% For \AlphaTk, there isn't much point in a distinction between the
+% ``standard'' and row--column position formats as standard
+% positions there are composed from a row and a column anyway.
+%
+% These procedures are put in the
+% \describestring[namespace]{pos}|pos| namespace, as there is nothing
+% in them that is specific to \eemenu.
+% \begin{tcl}
+%<*rowcol>
+namespace eval pos {}
+% \end{tcl}
+% \setnamespace{pos}
+%
+% \begin{proc}{incr_row}
+% \begin{proc}{incr_col}
+% The |incr_row| and |incr_col| procedures increment the row and
+% column respectively component of a position list. Their syntaxes are
+% \begin{quote}
+% |pos::incr_row| \word{pos-var} \word{row increment}\\
+% |pos::incr_col| \word{pos-var} \word{column increment}
+% \end{quote}
+% Incrementing the column can not cause the row to be incremented.
+% Incrementing the row sets the column to |0|. The minimal column
+% value is |0| and the minimal row value is |1|. There are no
+% maximums in either.
+% \begin{tcl}
+proc pos::incr_row {var diff} {
+ upvar 1 $var V
+ set t [expr {[lindex $V 1] + $diff}]
+ if {$t<1} then {
+ set V [list [lindex $V 0] 1 0]
+ } else {
+ set V [list [lindex $V 0] $t 0]
+ }
+}
+proc pos::incr_col {var diff} {
+ upvar 1 $var V
+ set t [expr {[lindex $V 2] + $diff}]
+ set V [lrange $V 0 1]
+ if {$t<0} then {lappend V 0} else {lappend V $t}
+}
+% \end{tcl}
+% \end{proc}\end{proc}
+%
+% \begin{proc}{get_standard}
+% The |get_standard| procedure returns the standard position
+% corresponding the row--column position stored in a variable. It has
+% the syntax
+% \begin{quote}
+% |pos::get_standard| \word{pos-var}
+% \end{quote}
+% \begin{tcl}
+proc pos::get_standard {var} {
+ upvar 1 $var V
+ if {[llength $V]<4} then {
+ lappend V [eval [list rowColToPos -w] $V]
+ }
+ return [lindex $V 3]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{polyset}
+% The |polyset| procedure is used to convert a list of standard
+% positions in a certain window to row--column form and store those
+% in variables, also given as a list. The syntax is
+% \begin{quote}
+% |pos::polyset| \word{window} \word{var-list} \word{pos-list}
+% \end{quote}
+% If there are more elements in the \word{var-list} than in the
+% \word{pos-list} then the remaining elements will not be set.
+%
+% The reason this procedure works on lists is that \Alpha\ cannot
+% (or at least will not) determine the row and column for a position
+% unless that is in the current window. Therefore this procedure might
+% have to temporarily bring some other window to front to do its stuff.
+% \begin{tcl}
+proc pos::polyset {win varL posL} {
+ if {$win != [win::Current]} then {
+ set top [win::Current]
+ bringToFront $win
+ }
+ set N [llength $varL]
+ if {$N > [llength $posL]} then {set N [llength $posL]}
+ for {set n 0} {$n < $N} {incr n} {
+ upvar 1 [lindex $varL $n] V
+ set V [concat [list $win]\
+ [posToRowCol [lindex $posL $n]] [lindex $posL $n]]
+ }
+ if {[info exists top]} then {bringToFront $top}
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{RC_compare}
+% The |RC_compare| procedure can be used to compare two row--column
+% positions. The syntax is
+% \begin{quote}
+% |pos::RC_compare| \word{first pos} \word{second pos}
+% \end{quote}
+% and the result is as for |string compare|. It is an error if the
+% \word{window} elements of the two arguments are different.
+% \begin{tcl}
+proc pos::RC_compare {a b} {
+ if {"[lindex $a 0]" != "[lindex $b 0]"} then {
+ error "Not the same <window>."
+ }
+ if {[lindex $a 1] < [lindex $b 1]} then {
+ return -1
+ } elseif {[lindex $a 1] > [lindex $b 1]} then {
+ return 1
+ } elseif {[lindex $a 2] < [lindex $b 2]} then {
+ return -1
+ } elseif {[lindex $a 2] > [lindex $b 2]} then {
+ return 1
+ } else {
+ return 0
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}[eemenu]{get_extract_positions}
+% The |get_extract_positions| procedure interprets the three optional
+% arguments for a |start| procedure and sets two specified variables
+% in the caller's local context to the row--column positions
+% corresponding to the beginning and the end respectively of interval
+% from which code should be extracted. The syntax is
+% \begin{quote}
+% |eemenu::get_extract_positions| \word{start-var} \word{end-var}
+% \word{window}\regopt\
+% \begin{regexp}[\regopt]\word{start} \word{end}\end{regexp}
+% \end{quote}
+% This procedure returns the complete window name (including count).
+% \begin{tcl}
+proc eemenu::get_extract_positions {startvar endvar {win ""}\
+ {startpos ""} {endpos ""}} {
+ if {![string length $win]} then {set win [win::Current]}
+ if {![string length $startpos]} then {
+ set startpos [getPos -w $win]
+ set endpos [selEnd -w $win]
+ if {[pos::compare $startpos == $endpos]} then {
+ set startpos [minPos]
+ set endpos [maxPos -w $win]
+ }
+ }
+ uplevel 1 [list pos::polyset $win [list $startvar $endvar]\
+ [list $startpos $endpos]]
+ return $win
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}[eemenu]{get_text}
+% The |get_text| procedure is mainly a wrapper around the |getText|
+% command. The syntax is
+% \begin{quote}
+% |eemenu::get_text| \word{start-var} \word{end-var}
+% \end{quote}
+% where \word{start-var} and \word{end-var} are names of variables
+% in the caller's local context of row--column positions. The return
+% value is the text between those positions.
+% \begin{tcl}
+proc eemenu::get_text {startvar endvar} {
+ upvar 1 $startvar S $endvar E
+ if {"[lindex $S 0]" != "[lindex $E 0]"} then {
+ error "Not the same <window>."
+ }
+ getText -w [lindex $S 0] [pos::get_standard S] [pos::get_standard E]
+}
+%</rowcol>
+% \end{tcl}
+% \end{proc}
+%
+%
+%
+%
+% \subsection{Raw extraction}
+%
+% \begin{arrayentry}[eemenu]{extract}{raw}
+% Raw extraction has no details.
+% \begin{tcl}
+set eemenu::extract(raw) [list]
+namespace eval eemenu::raw {}
+% \end{tcl}
+% \end{arrayentry}
+% \setnamespace{eemenu::raw}
+%
+% \subsubsection{Row--column based extraction}
+%
+% This was my original implementation of raw extraction. Unfortunately
+% it seems that |rowColToPos| is rather slow in \AlphaEight. Hence
+% there is an alternative implementation below.
+%
+% \begin{proc}{start}
+% \begin{variable}{cur_pos}
+% \begin{variable}{safe_pos}
+% \begin{variable}{end_pos}
+% As this |start| procedure has no details to deal with, it only
+% has to initialize the three position variables |cur_pos| (current
+% position), |safe_pos| (most recent safe position), and |end_pos|
+% (the end position).
+% \begin{tcl}
+%<*rowcol>
+proc eemenu::raw::start {details args} {
+ eemenu::multiupvar cur_pos safe_pos end_pos
+ set win\
+ [eval [list eemenu::get_extract_positions cur_pos end_pos] $args]
+ set safe_pos $cur_pos
+ return [win::StripCount $win]
+}
+% \end{tcl}
+% \end{variable}\end{variable}\end{variable}\end{proc}
+%
+%
+% \begin{proc}{next}
+% The |next| procedure is also as simple as it can possibly be. The
+% only nontrivial thing about it is that it removes carriage returns
+% and linefeeds at the end of the text returned by
+% |eemenu::get_text|.
+% \begin{tcl}
+proc eemenu::raw::next {at_safe} {
+ eemenu::multiupvar cur_pos safe_pos end_pos
+ if {[pos::RC_compare $cur_pos $end_pos]>=0} then {return -code 9 "Done"}
+ set this $cur_pos
+ if {$at_safe} then {set safe_pos $this}
+ pos::incr_row cur_pos 1
+ if {[pos::RC_compare $cur_pos $end_pos]>0} then {
+ set cur_pos $end_pos
+ }
+ string trimright [eemenu::get_text this cur_pos] "\n\r"
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{finish}
+% The |finish| procedure is slightly trickier that it has to be.
+% Rather than doing a |goto| to the safe position, it does a |select|
+% followed by a |markHilite|, with the end position as end, so that
+% the mark will be at the end.
+% \begin{tcl}
+proc eemenu::raw::finish {was_error} {
+ if {!$was_error} then {return}
+ eemenu::multiupvar safe_pos end_pos
+ bringToFront [lindex $safe_pos 0]
+ select [pos::get_standard safe_pos] [pos::get_standard end_pos]
+ markHilite
+}
+%</rowcol>
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsubsection{Queued extraction}
+%
+% This alternative implementation of the \textsf{raw} method is based on
+% extracting a bit more than one would usually need and store the
+% surplus in a queue of lines that haven't been extracted yet.
+%
+% \begin{variable}{line_queue}
+% \begin{variable}{window}
+% \begin{variable}{cur_pos}
+% \begin{variable}{from_pos}
+% \begin{variable}{safe_pos}
+% \begin{variable}{end_pos}
+% The |window| variable holds the name of the window from which text
+% is being extracted.
+% The |line_queue| variable is the text that has been gotten from the
+% window but not yet been properly extracted, split into lines. The
+% last line is incomplete and thus text must be added to the queue
+% whenever it has length less than two.
+%
+% The |cur_pos| variable is the standard position of the beginning of
+% the first line in |line_queue|. The |from_pos| variable is the
+% first position after the last piece of data in |line_queue|. The
+% |safe_pos| is the last position reported to be safe and the |end_pos|
+% is the position at which extraction should stop.
+% \end{variable}\end{variable}\end{variable}\end{variable}\end{variable}
+% \end{variable}
+%
+% \begin{proc}{start}
+% As this |start| procedure has no details to deal with, it only
+% has to initialize the six above variables.
+% \changes{v\,0.3}{2003/05/28}{Storing the tail of the file name, not
+% the whole path. This avoids unnecessary file system accesses. (LH)
+% Cf. bug 919.}
+% \changes{v\,0.3.1}{2003/07/19}{Using complete paths in \AlphaTk, due
+% to bug~1026. (LH)}
+% \begin{tcl}
+%<*!rowcol>
+proc eemenu::raw::start {details {win ""} {startpos ""} {endpos ""}} {
+ eemenu::multiupvar line_queue window cur_pos from_pos safe_pos end_pos
+ global alpha::platform
+ if {![string length $win]} then {set win [win::Current]}
+ switch -- ${alpha::platform} alpha {
+ set win_tail [file tail $win]
+ } default {
+ set win_tail $win
+ }
+ if {![string length $startpos]} then {
+ set startpos [getPos -w $win_tail]
+ set endpos [selEnd -w $win_tail]
+ if {[pos::compare $startpos == $endpos]} then {
+ set startpos [minPos]
+ set endpos [maxPos -w $win_tail]
+ }
+ }
+ set line_queue [list ""]
+ set window $win_tail
+ set cur_pos $startpos
+ set from_pos $startpos
+ set safe_pos $startpos
+ set end_pos $endpos
+ return [win::StripCount $win]
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}{next}
+% The |next| procedure first retrieves data from the window (if
+% necessary) and then it extracts the first line from the queue. Data
+% beyond the |end_pos| are never read into the queue.
+%
+% There are two versions of this procedure to account for the new
+% addition of a |-w| option to |pos::compare| and |pos::math|.
+% \changes{v\,0.1.2}{2002/12/26}{Fixed a bug concerning pos::compare,
+% where string compare syntax was used. (LH, who is sure he has
+% fixed this bug before.)}
+% \begin{tcl}
+%<*atcl7>
+if {[alpha::package vsatisfies -loose\
+ [alpha::package versions AlphaTcl] 7.6d2]} then {
+%</atcl7>
+ proc eemenu::raw::next {at_safe} {
+ eemenu::multiupvar line_queue window cur_pos from_pos safe_pos\
+ end_pos
+ if {[llength $line_queue] < 2} then {
+ if {[pos::compare -w $window $cur_pos >= $end_pos]} then {
+ return -code 9 "Done"
+ }
+ set next_pos [pos::math -w $window $from_pos + 1024]
+ if {[pos::compare -w $window $next_pos >= $end_pos]} then {
+ set next_pos $end_pos
+ }
+ set text [lindex $line_queue end]
+ append text [getText -w $window $from_pos $next_pos]
+ set line_queue [split $text "\n\r"]
+ set from_pos $next_pos
+ }
+ if {$at_safe} then {set safe_pos $cur_pos}
+ set line [lindex $line_queue 0]
+ set line_queue [lreplace $line_queue 0 0]
+ set cur_pos\
+ [pos::math -w $window $cur_pos + [expr {[string length $line]+1}]]
+ set line
+ }
+%<*atcl7>
+} else {
+ proc eemenu::raw::next {at_safe} {
+ eemenu::multiupvar line_queue window cur_pos from_pos safe_pos end_pos
+ if {[llength $line_queue] < 2} then {
+ if {[pos::compare $cur_pos >= $end_pos]} then {
+ return -code 9 "Done"
+ }
+ set next_pos [pos::math $from_pos + 1024]
+ if {[pos::compare $next_pos >= $end_pos]} then {
+ set next_pos $end_pos
+ }
+ set text [lindex $line_queue end]
+ append text [getText -w $window $from_pos $next_pos]
+ set line_queue [split $text "\n\r"]
+ set from_pos $next_pos
+ }
+ if {$at_safe} then {set safe_pos $cur_pos}
+ set line [lindex $line_queue 0]
+ set line_queue [lreplace $line_queue 0 0]
+ set cur_pos [pos::math $cur_pos + [expr {[string length $line]+1}]]
+ set line
+ }
+}
+%</atcl7>
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{finish}
+% This |finish| procedure clears the |line_queue|. It should usually
+% be empty already, but better safe than sorry!
+% \begin{tcl}
+proc eemenu::raw::finish {was_error} {
+ eemenu::multiupvar line_queue window safe_pos end_pos
+ set line_queue [list]
+ if {!$was_error} then {return}
+ bringToFront $window
+ select $safe_pos $end_pos
+ markHilite
+}
+%</!rowcol>
+% \end{tcl}
+% \end{proc}
+%
+%
+% \subsection{Regexp extraction}
+%
+% Regular expression extraction adds two features to what the raw
+% extraction does. One is the filter---only lines meeting a certain
+% condition are extracted, the others are skipped---and the other is the
+% substitution---each line returned is first fed through a |regsub|.
+% It would of course be possible to implement this from scratch, but it
+% is more instructive (and slightly shorter) to base it on the |raw|
+% method.
+%
+% \begin{arrayentry}[eemenu]{extract}{regexp}
+% Regular expression extraction has four detail settings.
+% \begin{tcl}
+set eemenu::extract(regexp) [list\
+% \end{tcl}
+% The first
+% two are used in a ``filter'' that selects which lines will be
+% extracted:
+% \begin{details}{Extraction}
+% \detailitem{filter_mode}
+% This is the mode of operation for the filter. There are three
+% possible values: |off| (no filtering, all lines are extracted),
+% |grep| (only lines matching the |filterRE| regular expression
+% are extracted), and |anti-grep| (only lines \emph{not} matching
+% the |filterRE| regular expression are extracted).
+% \begin{tcl}
+ [eemenu::define_detail Extract "Filter mode"\
+ filter_mode [list menu [list off grep anti-grep]] off]\
+% \end{tcl}
+% \detailitem{filterRE}
+% This is the regular expression for the filter
+% \begin{tcl}
+ [eemenu::define_detail Extract "Filter regular expression"\
+ filterRE var]\
+% \end{tcl}
+% \end{details}
+% The last two are used in a straightforward |regsub| that is applied
+% to each extracted line before it is returned to the main executive.
+% \begin{details}{Extraction}
+% \detailitem{searchRE}
+% This is the regular expression searched for in the line.
+% \begin{tcl}
+ [eemenu::define_detail Extract "Search (regexp):" searchRE var]\
+% \end{tcl}
+% \detailitem{replaceRE}
+% This is the regular expression for the replacement.
+% \begin{tcl}
+ [eemenu::define_detail Extract "Replace (regexp):" replaceRE var]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::regexp {}
+% \end{tcl}
+% \setnamespace{eemenu::regexp}
+%
+% \begin{proc}{start}
+% \begin{arrayvar}{detA}
+% This |start| procedure stores its details in the |D| array and calls
+% the |evalmemu::raw::start| procedure to handle everything else.
+% Note how it provides defaults for the detail settings it
+% unconditionally uses, in case these are not present in the
+% \word{details}.
+% \begin{tcl}
+proc eemenu::regexp::start {details args} {
+ global eemenu::regexp::detA
+ array set eemenu::regexp::detA\
+ {filter_mode off searchRE {} replaceRE {}}
+ array set eemenu::regexp::detA $details
+ eval [list eemenu::raw::start $details] $args
+}
+% \end{tcl}
+% \end{arrayvar}\end{proc}
+%
+% \begin{proc}{next}
+% The |next| procedure starts with a loop that continues until it
+% finds a line that passes the filter.
+% \begin{tcl}
+proc eemenu::regexp::next {at_safe} {
+ upvar #0 eemenu::regexp::detA D
+ while {1} {
+ set line [eemenu::raw::next $at_safe]
+ switch -- $D(filter_mode) {
+ off {break}
+ grep {if {[regexp -- $D(filterRE) $line]} then {break}}
+ anti-grep {
+ if {![regexp -- $D(filterRE) $line]} then {break}
+ }
+ }
+ }
+% \end{tcl}
+% Then it applies the |regsub| to the line.
+% \begin{tcl}
+ regsub -all -- $D(searchRE) $line $D(replaceRE) line
+ return $line
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{finish}
+% The |finish| procedure simply calls its equivalent for the |raw|
+% method.
+% \begin{tcl}
+proc eemenu::regexp::finish {err} {eemenu::raw::finish $err}
+% \end{tcl}
+% \end{proc}
+%
+%
+%
+% \subsection{Docstrip extraction}
+%
+% Docstrip extraction is a descendant of the extraction mechanisms from
+% the \textsf{dtxload} package.
+%
+%
+% \begin{arrayentry}[eemenu]{extract}{docstrip}
+% There are three detail settings for |docstrip| extraction.
+% \begin{tcl}
+set eemenu::extract(docstrip) [list\
+% \end{tcl}
+% \begin{details}{Extraction}
+% \detailitem{filePatL}
+% This is a list of file patterns that the file name is tested
+% against using |string match|. If none of them fits then
+% extraction is stopped before is begins.
+% \begin{tcl}
+ [eemenu::define_detail Extract "File patterns" filePatL var\
+ "*.dtx" "List of glob-style file patterns the window must match"]\
+% \end{tcl}
+% \detailitem{lookAtEnvs}
+% If this is checked then extraction will be further conditioned
+% by that the code line is in one of the environements listed in
+% the next setting. I find this very convenient, since I often
+% forget to comment out some lines here and there in the file.
+% \begin{tcl}
+ [eemenu::define_detail Extract "Filter by environments"\
+ lookAtEnvs flag 0]\
+% \end{tcl}
+% \detailitem{sourceEnvsL}
+% The list of environments from which code may be extracted.
+% \begin{tcl}
+ [eemenu::define_detail Extract "Source environments"\
+ sourceEnvsL var {tcl tcl*}]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::docstrip {}
+% \end{tcl}
+% \setnamespace{eemenu::docstrip}
+%
+% \begin{variable}{cur_pos}
+% \begin{variable}{safe_pos}
+% \begin{variable}{end_pos}
+% The |cur_pos|, |safe_pos|, and |end_pos| variables are as for the
+% |raw| mathod. A special case is however that |safe_pos| will never
+% be inside a verbatim section, even if it is safe there, since the
+% extraction wouldn't remember that is was inside a verbatim section
+% if it was restarted. Therefore the \word{is safe} argument to |next|
+% will be ignored in verbatim sections.
+%
+% These variables are only used by the \Module{rowcol} variant.
+% \end{variable}\end{variable}\end{variable}
+%
+% \begin{variable}{module_included}
+% \begin{variable}{in_code_env}
+% \begin{variable}{in_verbatim}
+% The |module_included| variable keeps track of whether the current
+% position is in an included module. It is |1| if the current
+% position should be included and |0| if it shouldn't.
+% The |in_code_env| variable is used for keeping track of the markup
+% context of the currently considered line in the file when the
+% |lookAtEnvs| setting is on. |in_code_env| is set to |1| when a
+% |\begin{|\meta{env}|}| for an \meta{env} in the |sourceEnvsL| is
+% scanned, and set to |0| when an |\end{|\meta{env}|}| is scanned.
+% The |in_verbatim| variable is |1| when the current position is in
+% a \textsf{docstrip} verbatim module and |0| (which is the normal
+% case) otherwise.
+% \end{variable}\end{variable}\end{variable}
+%
+% \begin{variable}{module_stack}
+% \begin{variable}{next_module_idx}
+% The |module_stack| variable is keeps track of how modules
+% are nested around the currently considered line. The variable is a
+% stack implemented as a list in which the last element corresponds to
+% the innermost module. Each element in this list is itself a list
+% with the structure
+% \begin{quote}
+% \word{expression} \word{start pos.} \word{previous}\regopt
+% \end{quote}
+% The \word{expression} is the guard expression, as a string. The
+% \word{start pos.} is the (row--column) position in the file where
+% the module started.
+% Finally, the \word{previous} is a boolean value which
+% records the inclusion status (value of |module_included|)
+% that was in force before the module was entered.
+%
+% The |next_module_idx| variable holds the index in the
+% |module_stack| list of the next module whose expression has not yet
+% been evaluated; it is equal to |llength ${module_stack}| if all
+% module expressions have been evaluated. Those elements in the
+% |module_stack| list which have index $\geq$ |next_module_idx| do
+% not have a \word{previous} element.
+% \end{variable}\end{variable}
+%
+%
+% \begin{proc}{start}
+% The |docstrip| extraction |start| procedure is by far the most
+% complicated, due to the many mechanisms it must initialize.
+% \begin{tcl}
+proc eemenu::docstrip::start {details args} {
+ eemenu::multiupvar detA module_included module_stack\
+ next_module_idx in_code_env in_verbatim
+% \end{tcl}
+% First there are the position variables
+% \begin{tcl}
+%<*rowcol>
+ eemenu::multiupvar cur_pos safe_pos end_pos
+ set win [win::StripCount\
+ [eval [list eemenu::get_extract_positions cur_pos end_pos] $args]]
+ set safe_pos $cur_pos
+%</rowcol>
+%<*!rowcol>
+ set win [eval [list eemenu::raw::start $details] $args]
+%</!rowcol>
+% \end{tcl}
+% and secondly the setting details
+% \begin{tcl}
+ array set detA {filePatL *.dtx lookAtEnvs 0}
+ array set detA $details
+% \end{tcl}
+% Then the method must check whether the detail setting permit
+% extracting from this window. If not, the procedure raises an error
+% (which isn't caught by |eemenu::main|).
+% \begin{tcl}
+ set ok 0
+ foreach pat $detA(filePatL) {
+ if {[string match $pat $win]} then {set ok 1; break}
+ }
+ if {!$ok} then {
+ status::msg "Can't extract from that window. Must be\
+ [join $detA(filePatL) " or "]."
+ return -code 9 "Bad window name"
+ }
+% \end{tcl}
+% Now that it has been established that extraction will take place,
+% the various variables defining the ``state of \textsf{dostrip}''
+% must be initialised. Four of them have standard values at start and
+% present no problem.
+% \begin{tcl}
+ set module_included 1
+ set in_verbatim 0
+ set module_stack [list]
+ set next_module_idx 0
+% \end{tcl}
+% The |in_code_env| variable is however another matter, as the
+% reasonable value for it depends very much on what characters follow
+% the start position. The special value |-1| for |in_code_env| means
+% ``change to |0| or |1| as appropriate when you get the first line''.
+% \begin{tcl}
+ if {!$detA(lookAtEnvs)} then {
+ set in_code_env 1
+ } else {
+%<*rowcol>
+ set t_pos $cur_pos
+ pos::incr_col t_pos 2
+ switch -regexp -- [eemenu::get_text cur_pos t_pos] {
+ ^%< {set in_code_env 1}
+ ^% {set in_code_env 0}
+ default {set in_code_env 1}
+ }
+%</rowcol>
+%<!rowcol> set in_code_env -1
+ set detA(envsRE) {\\(begin|end) *\{(}
+ foreach env $detA(sourceEnvsL) {
+ append detA(envsRE) [quote::Regfind $env] "|"
+ }
+ append detA(envsRE) ")\}(.*)\$"
+ }
+ return $win
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{arrayentry}{detA}{envsRE}
+% The |envsRE| entry in the |detA| array is used for storing the
+% regular expression that is used when searching for code environment
+% markup in comment lines.
+% \end{arrayentry}
+%
+% Next comes a couple of utility procs that are called from the |next|
+% procedure.
+%
+% \begin{arrayvar}{known}[expression]
+% The |known| array records the values of all known expressions,
+% i.e., those expressions about whose values the user has been
+% inquired. The entries are either |0| (for ``don't include'') or
+% |1| (for ``include''). Note that this array is not initialised by
+% the |start| procedure---instead is cleared by the |finish|
+% procedure if no error occurred.
+% \end{arrayvar}
+%
+% \begin{proc}{eval_guard}
+% The |eval_guard| procedure takes the string that is a guard
+% expression as argument. It returns |1| if the expression evaluates
+% to true and |0| if it evaluates to false.
+%
+% If the expression has an entry in the |known| array then the
+% |eval_guard| procedure returns that value, and if it does not the
+% user is inquired for the value.
+% \begin{tcl}
+proc eemenu::docstrip::eval_guard {e} {
+ global eemenu::docstrip::known
+ if {![info exists eemenu::docstrip::known($e)]} then {
+ set eemenu::docstrip::known($e)\
+ [dialog::yesno "Should <$e> modules be included?"]
+ }
+ set eemenu::docstrip::known($e)
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}{push_module}
+% The |push_module| procedure pushes a block module onto the
+% module stack, but it does not modify the value of
+% |module_included|. The syntax is
+% \begin{quote}
+% |eemenu::docstrip::push_module| \word{expression} \word{position}
+% \end{quote}
+% where \word{expression} is the expression string and
+% \word{position} is the position (row--column or standard, depending
+% on which kind of positions are being used) where the guard begins.
+% \begin{tcl}
+proc eemenu::docstrip::push_module {e p} {
+ global eemenu::docstrip::module_stack
+ lappend eemenu::docstrip::module_stack [list $e $p]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{pop_module}
+% The |pop_module| procedure pops a block module off the module
+% stack and checks that the modules are properly nested. Its
+% syntax is
+% \begin{quote}
+% |eemenu::docstrip::pop_module| \word{expression} \word{position}
+% \end{quote}
+% where \word{expression} is the expression string of the module to
+% pop and \word{position} is the position (row--column or standard,
+% depending on which kind of positions are being used) where the
+% end of module guard begins.
+%
+% If the module nesting is incorrect then the user is presented with
+% a dialog with buttons for pushing the positions of the incorrect
+% modules. It is not an error if the module stack is empty, since it
+% is perfectly reasonable that the beginning of the code to evaluate
+% is in the middle of a module.
+%
+% \changes{ \textsf{dtxload} v\,1.11}{2001/05/11}{Corrected ugly bug
+% which messed up the value of \texttt{next\_module\_idx}. (LH)}
+% \begin{tcl}
+proc eemenu::docstrip::pop_module {e p} {
+ eemenu::multiupvar module_stack module_included next_module_idx
+ set len [llength $module_stack]
+ if {$len==0} then {return}
+ set L [lindex $module_stack [expr {$len-1}]]
+ if {[lindex $L 0] != $e} then {
+ switch [buttonAlert "Module nesting error: <*[lindex $L 0]>\
+ module ended by </$e>. For which guards should the positions\
+ be pushed?" None Start End Both]\
+ {
+ Start {eemenu::docstrip::push_bookmarks [lindex $L 1]}
+ End {eemenu::docstrip::push_bookmarks $p}
+ Both {eemenu::docstrip::push_bookmarks [lindex $L 1] $p}
+ }
+ }
+ set module_stack [lreplace $module_stack end end]
+ if {$len<=$next_module_idx} then {
+ set next_module_idx [llength $module_stack]
+ }
+ if {[llength $L]>2} then {
+ set module_included [lindex $L 2]
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{push_bookmarks}
+% The |push_bookmarks| procedure pushes one or several positions
+% (row--column or standard, depending on which kind of positions are
+% being used) onto the bookmarks stack. The arguments are the
+% positions to push.
+% \changes{v\,0.3}{2003/05/28}{Changed some \texttt{win::Current} to
+% \texttt{win::CurrentTail}. This avoids unnecessary file system
+% accesses. (LH) Cf. bug 919.}
+% \begin{tcl}
+proc eemenu::docstrip::push_bookmarks {args} {
+ global markStack markName
+%<!rowcol> upvar #0 eemenu::raw::window win
+ set topWin [win::CurrentTail]
+ foreach pos $args {
+ set name mark$markName
+ incr markName
+%<*rowcol>
+ set win [lindex $pos 0]
+ if {"[win::CurrentTail]" != "$win"} then {bringToFront $win}
+ createTMark $name [pos::get_standard pos]
+ set fileName [win::Current]
+ set markStack [linsert $markStack 0\
+ [list $fileName $name [pos::get_standard pos]]]
+%</rowcol>
+%<*!rowcol>
+ if {[string compare [win::CurrentTail] $win]}\
+ then {bringToFront $win}
+ createTMark $name $pos
+ set fileName [win::Current]
+ set markStack [linsert $markStack 0 [list $fileName $name $pos]]
+%</!rowcol>
+ }
+ if {[string compare [win::CurrentTail] $topWin]}\
+ then {bringToFront $topWin}
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{update_included}
+% Simply pushing a module onto the module stack does not update the
+% |module_included| variable; that is instead done by the
+% |update_included| procedure, which should be called right before the
+% value of |module_included| is used. The reason for this arrangement
+% is that it avoids evaluating guard expressions whose values do not
+% matter.
+%
+% |update_included| has no arguments.
+% \begin{tcl}
+proc eemenu::docstrip::update_included {} {
+ eemenu::multiupvar module_stack module_included next_module_idx
+ while {$module_included && $next_module_idx<[llength $module_stack]} {
+ set L [lindex $module_stack $next_module_idx]
+ lappend L $module_included
+ set module_stack\
+ [lreplace $module_stack $next_module_idx $next_module_idx $L]
+ incr next_module_idx
+ set module_included [eemenu::docstrip::eval_guard [lindex $L 0]]
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{variable}{end_verb_line}
+% The |end_verb_line| variable stores the line which terminates
+% verbatim mode. It is only initialised when verbatim mode is begun.
+% \end{variable}
+%
+% \begin{proc}{next}
+% The overall structure of the |next| procedure is that of an endless
+% loop, from which the code |break|s out when it has found an
+% extractable line. Should this loop run into the |end_pos| it
+% terminates instead with a |return -code 9|. The local variable
+% |next_pos| stores the position of the beginning of the next line.
+% \begin{tcl}
+proc eemenu::docstrip::next {is_safe} {
+ eemenu::multiupvar detA module_included in_code_env\
+ in_verbatim module_stack next_module_idx end_verb_line
+%<*rowcol>
+ eemenu::multiupvar cur_pos safe_pos end_pos
+ set next_pos $cur_pos
+%</rowcol>
+%<!rowcol> upvar #0 eemenu::raw::cur_pos raw_cur_pos
+ while {1} {
+%<*rowcol>
+ pos::incr_row next_pos 1
+ if {[pos::RC_compare $next_pos $end_pos]>0} then {
+ set next_pos $end_pos
+ }
+ if {[pos::RC_compare $cur_pos $next_pos]>=0} then {
+ return -code 9 "Done"
+ }
+% \end{tcl}
+% No matter what state the extraction process is in, it will need to
+% look at the current line, so it is extracted and put in the |line|
+% variable. Spaces at end of the line are ignored for compatibility
+% with the \TeX\ \package{docstrip} (\TeX\ throws away spaces at the
+% end of a line as part of the reading process, so \package{docstrip}
+% cannot see them).
+% \begin{tcl}
+ set line [string trimright [eemenu::get_text cur_pos next_pos]\
+ "\r\n "]
+%</rowcol>
+% \end{tcl}
+% In the standard positions implementation, getting text from the
+% window is instead done by calling |eemenu::raw::next|. The position
+% at the beginning of the line (the value of |eemenu::raw::cur_pos|
+% before the call to |eemenu::raw::next|) is saved since it might be
+% needed for making bookmarks later.
+% \begin{tcl}
+%<*!rowcol>
+ set cur_pos $raw_cur_pos
+ set line [eemenu::raw::next [expr {$is_safe && !$in_verbatim}]]
+ set line [string trimright $line "\r\n "]
+ if {$in_code_env<0} then {
+ switch -glob -- $line {
+ %<* {set in_code_env 1}
+ %* {set in_code_env 0}
+ default {set in_code_env 1}
+ }
+ }
+%</!rowcol>
+% \end{tcl}
+% Verbatim mode is pretty simple. Either a line is an extractable
+% code line or it is the end of verbatim mode guard.
+% \begin{tcl}
+ if {$in_verbatim} then {
+ if {![string compare $line $end_verb_line]} then {
+ set in_verbatim 0
+ } elseif {$module_included && $in_code_env} then {
+ break
+ }
+ } else {
+% \end{tcl}
+% In non-verbatim mode, lines are classified based on the first few
+% characters of the line.
+% \begin{tcl}
+ switch -glob -- $line {
+% \end{tcl}
+% Lines that begin with |%<<| are \package{docstrip} guard lines that
+% start verbatim mode. The part of the guard line which comes after
+% the |%<<| is called an end-tag. Verbatim mode ends with the next line
+% which consists of a percent character followed by this end-tag
+% \begin{tcl}
+ %<<* {
+ eemenu::docstrip::update_included
+%<*rowcol>
+ if {$module_included && $in_code_env && $is_safe} then {
+ set safe_pos $cur_pos
+ }
+%</rowcol>
+ set in_verbatim 1
+ set end_verb_line "%[string range $line 3 end]"
+ }
+% \end{tcl}
+% Lines that begin with |%<*| or |%</| are \package{docstrip} guard
+% lines that delimit block modules, but they do not contain any code
+% themselves. The module is pushed onto or popped off the module stack
+% when the guard line is encountered, but evaluating the guard
+% expression is deferred until its value is needed.
+% \begin{tcl}
+ %<[*/]* {
+ if {![regexp {^%<(\*|/)([^>]+)>} $line foo modifier\
+ expression]}\
+ then {
+ if {[dialog::yesno "Malformed guard line '$line'\
+ encountered. Push position?"]}\
+%
+ then {eemenu::docstrip::push_bookmarks $cur_pos}
+ } elseif {$modifier=="*"} then {
+ eemenu::docstrip::push_module $expression $cur_pos
+ } else {
+ eemenu::docstrip::pop_module $expression $cur_pos
+ }
+ }
+% \end{tcl}
+% Other lines that begin with |%<| are also \package{docstrip}
+% guard lines, but in these cases the guard is followed by some code
+% and the guard only affects the code on that particular line. There
+% must be a |>| somewhere on the line, and the part of the line after
+% the |>| is code that \package{docstrip} can extract.
+% \begin{tcl}
+ %<* {
+ if {![regexp {^%<(-|\+|)([^>]+)>(.*)$} $line\
+ foo modifier expression code]}\
+ then {
+ if {[dialog::yesno "Malformed guard line '$line'\
+ encountered. Push position?"]}\
+ then {eemenu::docstrip::push_bookmarks $cur_pos}
+ } elseif {$in_code_env} then {
+ eemenu::docstrip::update_included
+ if {$module_included &&\
+ [eemenu::docstrip::eval_guard $expression] !=\
+ ($modifier=="-")} then {
+ set line $code
+ break
+ }
+ }
+ }
+% \end{tcl}
+% Remaining lines that begin with |%| are considered comment lines,
+% but they could technically be metacomment lines (begin with |%%|).
+% In that case \package{docstrip} would copy the line, but as there
+% is little point in using this \package{docstrip} features for
+% lines that the \Tcllogo\ interpreter would be interested in,
+% the |docstrip| extraction method ignores that subtlety. Comment
+% lines are ignored unless the |lookAtEnvs| details is |1|, in which
+% case they are scanned for code environment markup.
+% \begin{tcl}
+ %* {
+ while {$detA(lookAtEnvs) &&\
+ [regexp -- $detA(envsRE) $line foo type env line]} {
+ set in_code_env [expr {"$type"=="begin"}]
+ }
+ }
+% \end{tcl}
+% Finally, all lines that do not begin with a |%| are code lines.
+% \begin{tcl}
+ default {
+ if {$in_code_env} then {
+ eemenu::docstrip::update_included
+ if {$module_included} then {break}
+ }
+ }
+ }
+ }
+% \end{tcl}
+% That ends the large |switch| command and the large |if|. Now all
+% that remains in the loop is to update |cur_pos|.
+% \begin{tcl}
+%<rowcol> set cur_pos $next_pos
+ }
+% \end{tcl}
+% Whenever the procedure gets past the loop, the line that has been
+% extracted is in |line| and the only thing that remains is to update
+% the positions.
+% \begin{tcl}
+%<*rowcol>
+ if {$is_safe && !$in_verbatim} then {set safe_pos $cur_pos}
+ set cur_pos $next_pos
+%</rowcol>
+ return $line
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{finish}
+% In addition to the |raw| method |finish| procedure, this |finish|
+% also unsets the |known| array when there wasn't an error.
+% \begin{tcl}
+proc eemenu::docstrip::finish {was_error} {
+%<!rowcol> eemenu::raw::finish $was_error
+ if {$was_error} then {
+%<*rowcol>
+ eemenu::multiupvar safe_pos end_pos
+ bringToFront [lindex $safe_pos 0]
+ select [pos::get_standard safe_pos] [pos::get_standard end_pos]
+ markHilite
+%</rowcol>
+ } else {
+ global eemenu::docstrip::known
+ catch {unset eemenu::docstrip::known}
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \section{Completeness tests}
+%
+% \setnamespace{eemenu}
+%
+% Unlike the other method types, completion methods are not implemented
+% as procedures that can be called, but as an expression string stored
+% in a global variable. The string in question is called
+% \describestring[var.][eemenu::\meta{method}]{complete}|complete|
+% and it will be evaluated as an \emph{expression} in the local context
+% of the |main| procedure. The reason for this different set-up is that
+% these methods are usually much simpler to handle that way.
+%
+% Completion methods are expected to get their data from the following
+% variables:
+% \begin{description}
+% \item[\texttt{lines}]
+% A list of the lines that have been extracted by not yet evaluated.
+% This is (at least in theory) what the completion method is testing
+% for being complete.
+% \item[\texttt{at\_end}]
+% A boolean. It is |0| if the extraction has not yet reached the
+% end, and then it is set to |1|.
+% \item[\texttt{CMD(complete\_extra)}]
+% The key--value list of detail settings for completion methods.
+% None of the methods currently implemented have any detail settings.
+% \end{description}
+%
+% \begin{arrayentry}{complete}{entireSelection}
+% \setnamespace{eemenu::entireSelection}
+% \begin{variable}{complete}
+% The |entireSelection| method says `No' until the entire selection
+% has been extracted, then `Yes'. It has no detail settings.
+% \begin{tcl}
+set eemenu::complete(entireSelection) [list]
+namespace eval eemenu::entireSelection {}
+set eemenu::entireSelection::complete {$at_end}
+% \end{tcl}
+% \end{variable}\end{arrayentry}
+%
+% \begin{arrayentry}{complete}{everyLine}
+% \setnamespace{eemenu::everyLine}
+% \begin{variable}{complete}
+% The |everyLine| method says `Yes' after every line.
+% \begin{tcl}
+set eemenu::complete(everyLine) [list]
+namespace eval eemenu::everyLine {}
+set eemenu::everyLine::complete {1}
+% \end{tcl}
+% \end{variable}\end{arrayentry}
+%
+% \begin{arrayentry}{complete}{tclInfoComplete}
+% \setnamespace{eemenu::tclInfoComplete}
+% \begin{variable}{complete}
+% The |tclInfoComplete| method is the only one (defined so far) which
+% actually cares to look at what has been extracted. It calls the
+% |info complete| of \Alpha's \Tcllogo\ interpreter.
+% \begin{tcl}
+set eemenu::complete(tclInfoComplete) [list]
+namespace eval eemenu::tclInfoComplete {}
+set eemenu::tclInfoComplete::complete\
+ {[info complete [join $lines \n]\n]}
+% \end{tcl}
+% \end{variable}\end{arrayentry}
+%
+%
+% \section{Evaluation methods}
+%
+% The evaluation\slash execution method is what actually does anything
+% (all the other methods just move data around). From an input\slash
+% output perspective it takes the input from the extraction method and
+% generates the output that the report method should handle. Like
+% extraction methods, evaluation methods must declare three procedures
+% for |main| to call. These are: |begin|, |item|, and |end|. All of
+% these procedures return a \emph{result list}, which has the structure
+% \begin{quote}
+% \word{error?} \word{passing} \word{permanent}
+% \end{quote}
+% \word{error?} is a boolean that the main executive interprets to see
+% if there was an error. It is |0| when there wasn't an error.
+% \word{passing} and \word{permanent} are result strings. \word{passing}
+% should be suitable for output channels where new results replace old,
+% whereas \word{permanent} should be suitable for output channels where
+% the results are appended to each other. If the \word{passing} string
+% is empty then there is no reason to have it replace a previous
+% \word{passing} string. If the \word{permanent} string is nonempty
+% then it must end with a newline character.
+%
+% The \describestring[proc][eemenu::\meta{method}]{begin}|begin|
+% procedure is called to initialize the evaluation process. It has the
+% syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::begin| \word{details} \word{source}
+% \end{quote}
+% where the \word{details} is the key--value list of setting details
+% and \word{source} is the source window name as returned by the
+% extraction method |start| procedure. If the result of |begin| has a
+% nonzero \word{error?} then the corresponding |end| procedure will not
+% be called.
+%
+% The \describestring[proc][eemenu::\meta{method}]{item}|item|
+% procedure recieves a bunch of code to evaluate. It has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::item| \word{lines}
+% \end{quote}
+% where \word{lines} is the list of lines of code to evaluate. The
+% \describestring[proc][eemenu::\meta{method}]{end}|end| procedure is
+% called when no more lines of code will be sent for evaluation. |end|
+% takes no arguments.
+%
+% It is not necessarily in the call to |item| that the code gets
+% evaluated. The obvious alternative is that |item| simply stores the
+% code somewhere, for example by writing it to a temporary file, and
+% that it is the call to |end| that actually causes the code to be
+% evaluated. This is an important reason why all the procedures have the
+% same format for returned data.
+%
+%
+%
+% \subsection{Internal evaluation}
+%
+% The |internalTcl| evaluation method sends the code to \Alpha's internal
+% \Tcllogo\ interpreter and evaluates it there.
+%
+% \begin{arrayentry}[eemenu]{evaluate}{internalTcl}
+% There are no details for this method.
+% \begin{tcl}
+set eemenu::evaluate(internalTcl) [list]
+% \end{tcl}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::internalTcl {}
+% \end{tcl}
+% \setnamespace{eemenu::internalTcl}
+%
+% \begin{proc}{begin}
+% \begin{proc}{end}
+% Neither the |begin| nor the |end| procedure does anything.
+% \begin{tcl}
+proc eemenu::internalTcl::begin {details source} {
+ list 0 "" ""
+}
+proc eemenu::internalTcl::end {} {list 0 "" ""}
+% \end{tcl}
+% \end{proc}\end{proc}
+%
+% \begin{proc}{item}
+% The |item| procedure actually evaluates the code and suitably
+% formats the result.
+% \begin{tcl}
+proc eemenu::internalTcl::item {lines} {
+ set code [catch [list uplevel #0 [join $lines \n]] res]
+ if {$code == 1} then {
+% \end{tcl}
+% If there was an error, the last part of the value of |errorInfo|
+% will be due to the |uplevel| command. As that command was not
+% requested by the user, it would be confusing and it is therefore
+% best to remove it.
+% \begin{tcl}
+ global errorInfo
+ set L [split $errorInfo \n]
+ set L [lrange $L 0 [expr {[llength $L] - 4}]]
+ list 1 "Tcl eval error: $res"\
+ "Error: $res\nError info:\n[join $L \n]\n"
+% \end{tcl}
+% When there wasn't an error, a distinction is made between the case
+% of an empty string result (very common, e.g.\ from |proc|) and that
+% of a nonempty string result. This might seem inconsistent, but in
+% practice it looks much better.
+% \begin{tcl}
+ } elseif {[string length $res]} then {
+ list 0 "Tcl eval OK: $res" "$res\n"
+ } else {
+ list 0 "Tcl eval OK." ""
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+%
+% \subsection{DoScript AppleEvent evaluation}
+%
+% The |doScriptAE| evaluation method sends a |dosc| AppleEvent to some
+% external application, to have the script evaluated that way. Of
+% course, this only works if \TclAE\ is available, so this method is
+% only defined if that is the case.
+% \begin{tcl}
+%<atcl7>if {[llength [info commands tclAE::send]]} then {
+%<!atcl7>if {![catch {package require tclAE}]} then {
+% \end{tcl}
+%
+% \begin{arrayentry}[eemenu]{evaluate}{doScriptAE}
+% The details for the |doScriptAE| method roughly fall into three
+% categories: what is the target application, how should the
+% extracted lines be combined to a script, and what about a reply?
+% \begin{tcl}
+set eemenu::evaluate(doScriptAE) [list\
+% \end{tcl}
+% \begin{details}{Evaluate}
+% \detailitem{targetApp}
+% This is the appspec of the target application.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Target application"\
+ targetApp appspec]\
+% \end{tcl}
+% \detailitem{joinString}
+% The extracted lines is a list, but the script to send should be
+% a string, so they will have to be joined somehow. This item
+% offers a choice between some common forms of whitespace.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Join lines using"\
+ joinString [list menuindex [list Lf Cr CrLf Space]] 1]\
+% \end{tcl}
+% \detailitem{prefix}
+% This will be prepended to the script sent. It can for example be
+% used to add some command that takes care of the result.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Prefix" prefix var]\
+% \end{tcl}
+% \detailitem{suffix}
+% This will be appended to the script sent.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Suffix" suffix var]\
+% \end{tcl}
+% \detailitem{replyQ}
+% This flag controls whether the method should request a reply to
+% the AE sent.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Wait for reply" replyQ flag]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::doScriptAE {}
+% \end{tcl}
+% \setnamespace{eemenu::doScriptAE}
+%
+%
+% \begin{arrayvar}{A}
+% The |doScriptAE| method keeps its detail settings, and some derived
+% quantities, in the |A| array. Those are all the global variables it
+% has.
+% \end{arrayvar}
+%
+%
+% \begin{proc}{begin}
+% The main task of this |begin| procedure is to make sure that the
+% target application is running.
+% \begin{tcl}
+proc eemenu::doScriptAE::begin {details source} {
+ upvar #0 eemenu::doScriptAE::A A
+ array set A {prefix {} suffix {} joinString 1 targetApp {} replyQ 0}
+ array set A $details
+% \end{tcl}
+% The |targetApp| is either a quoted application signature or a full
+% path name. Exactly what will have to be done gets affected by this.
+% \begin{tcl}
+ if {[regexp {'(....)'} $A(targetApp) foo sig]} then {
+ set err [catch {app::ensureRunning $sig} passing]
+ if {$err == 1} then {set permanent $passing} else {
+ set permanent ""
+ set A(app) $A(targetApp)
+ }
+ } else {
+ set tail [file tail $A(targetApp)]
+%<*atcl7>
+ if {[info tclversion]<8.0} then {
+ set running\
+ [regexp "\{\"[quote::Regfind $tail]\" \"" [processes]]
+ } else {
+%</atcl7>
+ set running 0
+ foreach pr [processes] {
+ if {![string compare $tail [lindex $pr 0]]} then {
+ set running 1
+ break
+ }
+ }
+%<atcl7> }
+ set err 0
+ set permanent ""
+ set A(app) $tail
+ if {$running} then {
+ set passing "App is running."
+ } elseif {![catch {launch $A(targetApp)} passing]} then {
+ set passing "Launched '$A(targetApp)'"
+ } else {
+ set err 1
+ if {![file exists $A(targetApp)]} then {
+ set passing "File '$A(targetApp)' not found."
+ }
+ set permanent $passing
+ unset A(app)
+ }
+ }
+% \end{tcl}
+% The |joinString| is also decoded.
+% \begin{tcl}
+ set A(joinString) [lindex [list \n \r \r\n " "] $A(joinString)]
+ return [list $err $passing $permanent]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{item}
+% The |item| procedure is mainly about formatting data on its way
+% back and forth.
+% \begin{tcl}
+proc eemenu::doScriptAE::item {lines} {
+ upvar #0 eemenu::doScriptAE::A A
+ set script "$A(prefix)[join $lines $A(joinString)]$A(suffix)"
+ if {$A(replyQ)} then {
+ if {[catch {tclAE::build::resultData -t 30000 $A(app) misc dosc\
+ ---- [tclAE::build::TEXT $script]} res]} then {
+ list 1 "Error: $res" "Error: $res\n"
+ } elseif {[string length $res]} then {
+ list 0 $res "$res\n"
+ } else {
+ list 0 "Eval OK." ""
+ }
+ } else {
+ tclAE::send $A(app) misc dosc ---- [tclAE::build::TEXT $script]
+ list 0 "Sent [llength $lines] lines." ""
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{end}
+% The |end| procedure does nothing
+% \begin{tcl}
+proc eemenu::doScriptAE::end {} {list 0 "" ""}
+% \end{tcl}
+% \end{proc}
+%
+% This ends the |if| begun at the top of this subsection.
+% \begin{tcl}
+}
+% \end{tcl}
+%
+%
+% \subsection{\texttt{send} evaluation}
+%
+% The \texttt{send} command can be used to communicate with other Tk
+% applications via an X-windows server. This is a bit restrictive, but
+% it is anyway what \AlphaTk\ uses for remote execution of \Tcllogo\
+% code, so I suppose it is what we've got. Right now this method is
+% defined whenever the |send| command exists, but it is not uncommon
+% that the definition of |send| merely provides communication between
+% different interpreters in the same application.
+% \begin{tcl}
+if {[llength [info commands send]] && [info tclversion]>=8.0} then {
+% \end{tcl}
+%
+% \begin{arrayentry}[eemenu]{evaluate}{tkSend}
+% Many details for the |doScriptAE| method have natural counterparts
+% for the |tkSend| method, the main difference lies in the
+% identification of the target. Whereas \TclAE\ uses static
+% information (creator code or file name) to identify the target, the
+% name used by the |send| command is in principle dynamic. The
+% relevant identifier may change between different times that an
+% \textsf{EE~menu} command is used. This is handled by providing a
+% fallback for unknown targets.
+% \begin{tcl}
+set eemenu::evaluate(tkSend) [list\
+% \end{tcl}
+% \begin{details}{Evaluate}
+% \detailitem{target}
+% This is a string that identifies the target.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Target" target var]\
+% \end{tcl}
+% \detailitem{aliasing}
+% This detail controls how the |tkSend| method should behave when
+% |begin| is called but the specified target isn't available.
+% ``Ask each time'' means present the user with a list of available
+% targets each time |begin| is called, and use what the user
+% selected there. ``Ask once'' is similar, but the choice will be
+% remembered as an \emph{alias} for the specified target (until
+% \Alpha\ is quited or the alias target no longer is available).
+% ``Fail'' means fail immediately.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Alias behaviour"\
+ aliasing [list menu [list "Ask once" "Ask each time" "Fail"]]\
+ "Ask once" "The thing to do when the target is unavailable."]\
+% \end{tcl}
+% \detailitem{joinString}
+% The extracted lines is a list, but the script to send should be
+% a string, so they will have to be joined somehow. This item
+% offers a choice between some common forms of whitespace.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Join lines using"\
+ joinString [list menuindex [list Lf Cr CrLf Space]] 0]\
+% \end{tcl}
+% \detailitem{prefix}
+% This will be prepended to the script sent. It can for example be
+% used to add some command that takes care of the result.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Prefix" prefix var]\
+% \end{tcl}
+% \detailitem{suffix}
+% This will be appended to the script sent.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Suffix" suffix var]\
+% \end{tcl}
+% \detailitem{replyQ}
+% This flag controls whether the method should wait for the
+% remote shell to return a result.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Wait for reply" replyQ flag 1]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::tkSend {}
+% \end{tcl}
+% \setnamespace{eemenu::tkSend}
+%
+% \begin{arrayvar}{alias}
+% The |alias| array is used to keep track of which targets are treated
+% as aliases for other targets. The index is a value of the
+% \texttt{target} detail, the entry value is what it should be
+% replaced by.
+% \end{arrayvar}
+%
+% \begin{variable}{last_target}
+% The |last_target| variable contains the name of the most recently
+% selected target. This is so that the relevant |listpick| dialog
+% can ``remember'' the user's preference in this respect.
+% \begin{tcl}
+set eemenu::tkSend::last_target {}
+% \end{tcl}
+% \end{variable}
+%
+% \begin{arrayvar}{A}
+% The |tkSend| method keeps its detail settings, and some derived
+% quantities, in the |A| array for convenience of access.
+% \end{arrayvar}
+%
+%
+% \begin{proc}{begin}
+% The main task of this |begin| procedure is to verify that the target
+% is available.
+% \begin{tcl}
+proc eemenu::tkSend::begin {details source} {
+ eemenu::multiupvar A alias last_target
+ array set A {prefix {} suffix {} joinString 1 target {} replyQ 1\
+ aliasing "Ask once"}
+ array set A $details
+% \end{tcl}
+% The treatment of aliases depend on the |aliasing| setting. If it is
+% \texttt{Ask once} then an alias will be used even if a target with
+% the given name is available. The rationale for this is that the user
+% has specified that the commands should be sent to that application.
+% \begin{tcl}
+ set T [lsort -dictionary [winfo interps]]
+ switch -- $A(aliasing) "Ask each time" {
+ if {[lsearch -exact $T $A(target)]>=0} then {
+ set target $A(target)
+ }
+ } "Fail" {
+ if {[lsearch -exact $T $A(target)]>=0} then {
+ set target $A(target)
+ } else {
+ set passing "Target '$A(target)' unavailable."
+ return [list 1 $passing $passing]
+ }
+ } default {
+ set target $A(target)
+ if {[info exists alias($target)]} then {
+ set target $alias($target)
+ }
+ if {[lsearch -exact $T $target]<0} then {unset target}
+ }
+% \end{tcl}
+% If the local |target| variable is not set at this point then it is
+% time to ask the user.
+% \begin{tcl}
+ if {![info exists target]} then {
+ if {[catch {listpick -p "Target '$A(target)' unavailable.\
+ Please pick a new one." -L [list $last_target]\
+ [linsert $T end "------------------" "Launch new shell"]}\
+ target]} then {
+ return [list 1 "Canceled" ""]
+ }
+ switch -exact -- $target\
+ "------------------" - "Launch new shell" {
+ set before [clock seconds]
+ app::launchElseTryThese [uplevel #0 {set tclshSigs}] tclshSig\
+ {Please locate the remote Tcl application}
+ while {![string compare $T\
+ [lsort -dictionary [winfo interps]]] &&\
+ [clock seconds] - $before < 60} {update}
+ set T2 [lsort -dictionary [winfo interps]]
+ if {![string compare $T $T2]} then {
+ return [list 1 {Timed out; no new shell started within\
+ 60 seconds.} ""]
+ }
+ foreach target $T2 t $T {
+ if {[string compare $target $t]} then {break}
+ }
+ set passing "Launched new shell '$target'."
+ } default {
+ set passing "Sending code to '$target'."
+ }
+% \end{tcl}
+% The last |foreach| above locates the first |target| in |$T2| which
+% is not in |$T|. This |foreach| is the reason this code requires
+% \Tcllogo\,8.
+%
+% Now the target should be stored in the necessary variables.
+% \begin{tcl}
+ set last_target $target
+ if {![string compare $A(aliasing) "Ask once"]} then {
+ set alias($A(target)) $target
+ }
+ } else {
+ set passing "Sending code to '$target'."
+ }
+ set A(target) $target
+% \end{tcl}
+% The |joinString| is also decoded.
+% \begin{tcl}
+ set A(joinString) [lindex [list \n \r \r\n " "] $A(joinString)]
+ return [list 0 $passing ""]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{item}
+% The |item| procedure is mainly about formatting data on its way
+% back and forth.
+% \begin{tcl}
+proc eemenu::tkSend::item {lines} {
+ upvar #0 eemenu::tkSend::A A
+ set script "$A(prefix)[join $lines $A(joinString)]$A(suffix)"
+ if {$A(replyQ)} then {
+ if {[catch {send $A(target) $script} res]} then {
+ list 1 "Error: $res" "Error: $res\n"
+ } elseif {[string length $res]} then {
+ list 0 "Eval OK: $res" "$res\n"
+ } else {
+ list 0 "Eval OK." ""
+ }
+ } else {
+ send -async $A(target) $script
+ list 0 "Sent [llength $lines] lines." ""
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{end}
+% The |end| procedure does nothing
+% \begin{tcl}
+proc eemenu::tkSend::end {} {list 0 "" ""}
+% \end{tcl}
+% \end{proc}
+%
+% This ends the |if| begun at the top of this subsection.
+% \begin{tcl}
+}
+% \end{tcl}
+%
+% \subsubsection*{Test code}
+%
+% The code below fakes definitions of |send| and |winfo interps| using
+% \Tcllogo\AE\ and |processes| for the purpose of testing the above code.
+% \begin{tcl}
+%<*sendtest>
+proc send {target cmd args} {
+ set sync 1
+ if {![string compare $target -async]} then {
+ set sync 0
+ set target $cmd
+ set cmd [lindex $args 0]
+ }
+ set cmd [tclAE::build::TEXT $cmd]
+ if {$sync} then {
+ tclAE::build::resultData -t 30000 $target misc dosc ---- $cmd
+ } else {
+ tclAE::send $target misc dosc ---- $cmd
+ }
+}
+proc winfo {subcmd args} {
+ if {[string compare $subcmd "interps"]} then {
+ error "Unimplemented winfo subcommand: $subcmd"
+ }
+ set res [list]
+ global tclshSigs
+ foreach pr [processes] {
+ if {[lsearch -exact $tclshSigs [lindex $pr 1]]>=0} then {
+ lappend res [file tail [lindex $pr 0]]
+ }
+ }
+ return $res
+}
+%</sendtest>
+% \end{tcl}
+%
+%
+% \subsection{\texttt{dde} evaluation}
+%
+% Dynamic Data Exchange (\texttt{dde}) is, as I understand it, the
+% Windoze equivalent of AppleEvents, although the events sent have much
+% less structure. The machinery needed here is quite similar to that
+% for \texttt{send} evaluation, but there are a few extra details that
+% can be set.
+% \changes{v\,0.1.1}{2002/07/21}{Renamed the \textsf{Dde} method to
+% \textsf{Windoze DDE}. (LH)}
+%
+% \begin{tcl}
+if {[llength [info commands dde]] && [info tclversion]>=8.0} then {
+% \end{tcl}
+%
+% \begin{arrayentry}[eemenu]{evaluate}{windozeDDE}
+% The details for the |windozeDDE| method constitute a superset of those for
+% the |tkSend| method.
+% \begin{tcl}
+set eemenu::evaluate(windozeDDE) [list\
+% \end{tcl}
+% \begin{details}{Evaluate}
+% \detailitem{service}
+% This is a string that specifies the service to use.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Service" service var "TclEval"]\
+% \end{tcl}
+% \detailitem{target}
+% This is a string that identifies the target application, or as
+% it appears to be called, the ``topic''.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Target" target var]\
+% \end{tcl}
+% \detailitem{aliasing}
+% This detail controls how the |windozeDDE| method should behave when
+% |begin| is called but the specified target isn't available.
+% ``Ask each time'' means present the user with a list of available
+% targets each time |begin| is called, and use what the user
+% selected there. ``Ask once'' is similar, but the choice will be
+% remembered as an \emph{alias} for the specified target (until
+% \Alpha\ is quited or the alias target no longer is available).
+% ``Fail'' means fail immediately.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Alias behaviour"\
+ aliasing [list menu [list "Ask once" "Ask each time" "Fail"]]\
+ "Ask once" "The thing to do when the target is unavailable."]\
+% \end{tcl}
+% \detailitem{launchCmd}
+% This is a \Tcllogo\ command which, when executed by \Alpha,
+% should launch an application that provides a new target for
+% the given service. The command is evaluated at a global level.
+% If it is an empty string, then no option for launching will be
+% presented in the target selection dialog.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Launch command" launchCmd var2]\
+% \end{tcl}
+% \detailitem{joinString}
+% The extracted lines is a list, but the script to send should be
+% a string, so they will have to be joined somehow. This item
+% offers a choice between some common forms of whitespace.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Join lines using"\
+ joinString [list menuindex [list Lf Cr CrLf Space]] 2]\
+% \end{tcl}
+% \detailitem{prefix}
+% This will be prepended to the script sent. It can for example be
+% used to add some command that takes care of the result.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Prefix" prefix var]\
+% \end{tcl}
+% \detailitem{suffix}
+% This will be appended to the script sent.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Suffix" suffix var]\
+% \end{tcl}
+% \detailitem{request}
+% This is the name of the item to request as result from the
+% evaluation. If it is an empty string then no request is made.
+% \begin{tcl}
+ [eemenu::define_detail Evaluate "Requested data" request var]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::windozeDDE {}
+% \end{tcl}
+% \setnamespace{eemenu::windozeDDE}
+%
+% \begin{arrayvar}{alias}
+% The |alias| array is used to keep track of which targets are treated
+% as aliases for other targets. The index is a value of the
+% \texttt{target} detail, the entry value is what it should be
+% replaced by.
+% \end{arrayvar}
+%
+% \begin{variable}{last_target}
+% The |last_target| variable contains the name of the most recently
+% selected target. This is so that the relevant |listpick| dialog
+% can ``remember'' the user's preference in this respect.
+% \begin{tcl}
+set eemenu::windozeDDE::last_target {}
+% \end{tcl}
+% \end{variable}
+%
+% \begin{arrayvar}{A}
+% The |windozeDDE| method keeps its detail settings, and some derived
+% quantities, in the |A| array for convenience of access.
+% \end{arrayvar}
+%
+%
+% \begin{proc}{begin}
+% The main task of this |begin| procedure is to verify that the target
+% is available.
+% \begin{tcl}
+proc eemenu::windozeDDE::begin {details source} {
+ eemenu::multiupvar A alias last_target
+ array set A {service {} target {} aliasing "Ask once" launchCmd {}\
+ prefix {} suffix {} joinString 2 request {}}
+ array set A $details
+ if {![string length $A(service)]} then {
+ return [list 1 "No service has been specified." ""]
+ }
+% \end{tcl}
+% The treatment of aliases depend on the |aliasing| setting. If it is
+% \texttt{Ask once} then an alias will be used even if a target with
+% the given name is available. The rationale for this is that the user
+% has specified that the commands should be sent to that application.
+% \begin{tcl}
+ set T [list]
+ foreach st [dde services $A(service) {}] {lappend T [lindex $st 1]}
+ set T [lsort -dictionary $T]
+ switch -- $A(aliasing) "Ask each time" {
+ if {[lsearch -exact $T $A(target)]>=0} then {
+ set target $A(target)
+ }
+ } "Fail" {
+ if {[lsearch -exact $T $A(target)]>=0} then {
+ set target $A(target)
+ } else {
+ set passing "Target '$A(target)' unavailable."
+ return [list 1 $passing $passing]
+ }
+ } default {
+ set target $A(target)
+ if {[info exists alias($target)]} then {
+ set target $alias($target)
+ }
+ if {[lsearch -exact $T $target]<0} then {unset target}
+ }
+% \end{tcl}
+% If the local |target| variable is not set at this point then it is
+% time to ask the user.
+% \begin{tcl}
+ if {![info exists target]} then {
+ set T2 $T
+ if {[string length $A(launchCmd)]} then {
+ if {[llength $T2]} then {lappend T2 "------------------"}
+ lappend T2 "Launch another"
+ }
+ if {![llength $T2]} then {
+ return [list 1 "No '$A(service)' targets are, or could be\
+ made, available." ""]
+ }
+ if {[catch {listpick -p "Target '$A(target)' unavailable.\
+ Please pick a new one." -L [list $last_target] $T2}\
+ target]} then {
+ return [list 1 "Canceled" ""]
+ }
+ switch -exact -- $target\
+ "------------------" - "Launch another" {
+ set before [clock seconds]
+ uplevel #0 $A(launchCmd)
+ set target {}
+ while {[clock seconds] - $before < 60 &&\
+ ![string length $target]} {
+ foreach st [dde services $A(service) {}] {
+ if {[lsearch -exact $T [lindex $st 1]]<0} then {
+ set target [lindex $st 1]
+ break
+ }
+ }
+ update
+ }
+ if {![string length $target]} then {
+ return [list 1 {Timed out; no new target launched within\
+ 60 seconds.} ""]
+ }
+ set passing "Launched new shell '$target'."
+ } default {
+ set passing "Sending code to '$target'."
+ }
+% \end{tcl}
+% The last |foreach| above locates the first |target| in |$T2| which
+% is not in |$T|. This |foreach| is the reason this code requires
+% \Tcllogo\,8.
+%
+% Now the target should be stored in the necessary variables.
+% \begin{tcl}
+ set last_target $target
+ if {![string compare $A(aliasing) "Ask once"]} then {
+ set alias($A(target)) $target
+ }
+ } else {
+ set passing "Sending code to '$target'."
+ }
+ set A(target) $target
+% \end{tcl}
+% The |joinString| is also decoded.
+% \begin{tcl}
+ set A(joinString) [lindex [list \n \r \r\n " "] $A(joinString)]
+ return [list 0 $passing ""]
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{item}
+% The |item| procedure is mainly about formatting data on its way
+% back and forth.
+% \begin{tcl}
+proc eemenu::windozeDDE::item {lines} {
+ upvar #0 eemenu::windozeDDE::A A
+ set script "$A(prefix)[join $lines $A(joinString)]$A(suffix)"
+ if {[catch {dde execute $A(service) $A(target) $script} res]} then {
+ list 1 "dde error: $res" "$res\n"
+ } elseif {![string length $A(request)]} then {
+ list 0 "Sent [llength $lines] lines." ""
+ } else {
+ if {[catch {dde request $A(service) $A(target) $A(request)} res]}\
+ then {
+ list 1 "dde error: $res" "dde error: $res\n"
+ } elseif {[string length $res]} then {
+ list 0 $res "$res\n"
+ } else {
+ list 0 "Eval OK." ""
+ }
+ }
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{end}
+% The |end| procedure does nothing
+% \begin{tcl}
+proc eemenu::windozeDDE::end {} {list 0 "" ""}
+% \end{tcl}
+% \end{proc}
+%
+% This ends the |if| begun at the top of this subsection.
+% \begin{tcl}
+}
+% \end{tcl}
+%
+% \subsubsection*{Test code}
+%
+% The code below fakes a definition of |dde| using |interp|.
+% \begin{tcl}
+%<*ddetest>
+proc dde {subcmd args} {
+ switch -- $subcmd servername {
+ error "dde servername is not implemented."
+ } execute {
+ if {[llength $args] != 3} then {
+ error "Wrong number of arguments for dde execute."
+ }
+ if {"TclEval" != [lindex $args 0]} then {
+ error "Unknown servername: [lindex $args 0]"
+ }
+ interp eval [lindex $args 1] [lindex $args 2]
+ } poke {
+ if {[llength $args] != 4} then {
+ error "Wrong number of arguments for dde poke."
+ }
+ if {"TclEval" != [lindex $args 0]} then {
+ error "Unknown servername: [lindex $args 0]"
+ }
+ interp eval [lindex $args 1]\
+ [list set [lindex $args 2] [lindex $args 3]]
+ } request {
+ if {[llength $args] != 3} then {
+ error "Wrong number of arguments for dde request."
+ }
+ if {"TclEval" != [lindex $args 0]} then {
+ error "Unknown servername: [lindex $args 0]"
+ }
+ interp eval [lindex $args 1] [list set [lindex $args 2]]
+ } services {
+ if {[llength $args] != 2} then {
+ error "Wrong number of arguments for dde services."
+ }
+ set server [lindex $args 0]
+ if {[string length $server] && $server != "TclEval"} then {
+ return ""
+ }
+ set topic [lindex $args 1]
+ if {![string length $topic]} then {
+ set res [list]
+ foreach slave [interp slaves] {
+ lappend res [list TclEval $slave]
+ }
+ return $res
+ } elseif {[interp exists $topic]} then {
+ return [list [list TclEval $topic]]
+ } else {
+ return ""
+ }
+ } default {
+ error "Unimplemented subcommand: $subcmd"
+ }
+}
+%</ddetest>
+% \end{tcl}
+%
+%
+% \section{Report methods}
+% \label{Sec:Report}
+%
+% The report method takes care of sending output to the user. Like
+% extraction and evaluation methods there is one `begin' procedure
+% |log_open| and one `end' procedure |log_close| for each method, but
+% there are actually two `iterate' procedures. This is because the
+% extracted code is logged using |log_code| \emph{before} it is
+% evaluated, whereas the result is only known after the code has been
+% evaluated and is then logged using |log_result|.
+%
+% The \describestring[proc][eemenu::\meta{method}]{log_open}|log_open|
+% procedure has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::log_open| \word{details} \word{source}
+% \end{quote}
+% where the \word{details} is the key--value list of setting details
+% and \word{source} is the source window name as returned by the
+% extraction method |start| procedure. There is no result from this
+% procedure, but if there is something wrong with its argument then it
+% may stop the \eemenu\ command by returning with an error.
+%
+% The reason the \word{source} argument is provided is that some report
+% methods might want to make some aspect of their output, such as for
+% example a window title or log file name, dependent on the input source.
+% Neither the |statusLine| nor the |logWindow| method do this, though.
+%
+% The \describestring[proc][eemenu::\meta{method}]{log_code}|log_code|
+% procedure has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::log_code| \word{lines}
+% \end{quote}
+% where \word{lines} is the list of lines that will be sent to the
+% evaluation method. The
+% \describestring[proc][eemenu::\meta{method}]{log_result}|log_result|
+% procedure has the syntax
+% \begin{quote}
+% |eemenu::|\meta{method}|::log_result| \word{error?}
+% \word{passing result} \word{permanent result}
+% \end{quote}
+% where the \word{error?} is |1| if there was an evaluation error and
+% |0| otherwise. The \word{passing result} is a result string that
+% describes the current state of the evaluation process; it is meant
+% to be replaced by the next \word{passing result} the next time
+% |log_result| is called. By constrast the \word{permanent result} is
+% meant to be accumulated for each call to |log_result|. Whether a
+% report method uses one or the other (or both) depends on which makes
+% most sense for the output channels it employs. If the \word{passing
+% result} string is empty then it should not replace a previous
+% \word{passing result} string. If the \word{permanent} string is
+% nonempty then it must end with a newline character.
+%
+% The \describestring[proc][eemenu::\meta{method}]{log_close}|log_close|
+% procedure is responsible for cleaning up after the method, but only
+% to the extent that this is necessary. If |log_open| opened a file then
+% |log_close| should close it, but if |log_open| merely opened a window
+% then |log_close| should most likely not close it since the user will
+% want to see what is written in that window. The syntax is simply
+% \begin{quote}
+% |eemenu::|\meta{method}|::log_close|
+% \end{quote}
+% and there is no result from the procedure.
+%
+%
+%
+% \subsection{Status line reports}
+%
+% The |statusLine| method shows the \word{passing result}s on the
+% status line, but does nothing else.
+%
+% \setnamespace{eemenu::statusLine}
+% \begin{arrayentry}[eemenu]{report}{statusLine}
+% There are no details settings for this method.
+% \begin{tcl}
+namespace eval eemenu::statusLine {}
+set eemenu::report(statusLine) [list]
+% \end{tcl}
+% \end{arrayentry}
+%
+% \begin{proc}{log_open}
+% \begin{proc}{log_close}
+% \begin{proc}{log_code}
+% \begin{proc}{log_result}
+% Only the |log_result| procedure needs to do anything.
+% \begin{tcl}
+proc eemenu::statusLine::log_open {details source} {}
+proc eemenu::statusLine::log_close {} {}
+proc eemenu::statusLine::log_code {lines} {}
+proc eemenu::statusLine::log_result {was_err passing permanent} {
+ if {[string length $passing]} then {status::msg $passing}
+}
+% \end{tcl}
+% \end{proc}\end{proc}\end{proc}\end{proc}
+%
+%
+% \subsection{Log window reports}
+%
+% The |logWindow| method opens a particular window and inserts
+% everything that is logged there.
+%
+% \begin{arrayentry}[eemenu]{report}{logWindow}
+% There are three detail settings for |logWindow| reports.
+% \begin{tcl}
+set eemenu::report(logWindow) [list\
+% \end{tcl}
+% \begin{details}{Report}
+% \detailitem{winName}
+% This is the name of the log window.
+% \begin{tcl}
+ [eemenu::define_detail Report "Window name" winName var "Log"]\
+% \end{tcl}
+% \detailitem{winMode}
+% This is the mode to use for the log window.
+% \begin{tcl}
+ [eemenu::define_detail Report "Window mode" winMode mode "Text"]\
+% \end{tcl}
+% \detailitem{prompt}
+% This is a ``prompt'' string that will be put at the beginning of
+% each code line.
+% \begin{tcl}
+ [eemenu::define_detail Report "Prompt" prompt var\
+ "[text::Ascii 200 1] "]\
+% \end{tcl}
+% \detailitem{antiprompt}
+% This is a string that will be put at the beginning of each line
+% that is not a code line.
+% \begin{tcl}
+ [eemenu::define_detail Report "Antiprompt" antiprompt var ""]]
+% \end{tcl}
+% \end{details}
+% \end{arrayentry}
+% \begin{tcl}
+namespace eval eemenu::logWindow {}
+% \end{tcl}
+% \setnamespace{eemenu::logWindow}
+%
+% \begin{arrayvar}{A}
+% The |logWindow| method keeps its detail settings in the |A|
+% array. Those are all the global variables it has.
+% \end{arrayvar}
+%
+% \begin{proc}{log_open}
+% This procedure opens the log window (if it isn't open already)
+% and positions the cursor at the end of the window. This is
+% assumed to be at the beginning of a line.
+% \begin{tcl}
+proc eemenu::logWindow::log_open {details source} {
+ upvar #0 eemenu::logWindow::A A
+ array set A {winName {Log window} prompt {} antiprompt {}}
+ array set A $details
+ set win $A(winName)
+ if {[lsearch -exact [winNames] $win] == -1} then {
+ set call [list new -n $win -shell 1]
+ if {[mode::exists $A(winMode)]} then {lappend call -m $A(winMode)}
+ eval $call
+ }
+ set t [maxPos -w $win]
+ select -w $win $t $t
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{log_code}
+% The |log_code| procedure inserts the lines at the current position
+% in the file. This will be at the end of the file, unless the
+% evaluation modifies this.
+% \begin{tcl}
+proc eemenu::logWindow::log_code {lines} {
+ upvar #0 eemenu::logWindow::A A
+ insertText -w $A(winName) "$A(prompt)[join $lines "\n$A(prompt)"]\n"
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{log_result}
+% The |log_result| procedure inserts the \word{permanent result} at
+% the current position in the file. If the |antiprompt| is
+% nonempty then the result is first broken into lines and then
+% reassembled, however. It also displays the \word{passing result} on
+% the status line (this has to be done last, since |insertText|
+% clears the status line).
+% \begin{tcl}
+proc eemenu::logWindow::log_result {was_err passing permanent} {
+ if {[string length $permanent]} then {
+ upvar #0 eemenu::logWindow::A A
+ if {[string length $A(antiprompt)]} then {
+ set L [lreplace [split $permanent \n\r] end end]
+ set permanent "[join $L "\n$A(antiprompt)"]\n"
+ }
+ insertText -w $A(winName) "$A(antiprompt)$permanent"
+ }
+ if {[string length $passing]} then {status::msg $passing}
+}
+% \end{tcl}
+% \end{proc}
+%
+% \begin{proc}{log_close}
+% This procedure does nothing.
+% \begin{tcl}
+proc eemenu::logWindow::log_close {} {}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \section{Default command definitions}
+% \label{Sec:DefCmdA}
+%
+% This section contains some examples of \eemenu\ commands and
+% it also provides defaults for the |cmdA| array.
+%
+% \setnamespace{eemenu}
+%
+% \begin{arrayvar}{cmdA}
+% If this array is already set then there is no need to source the
+% rest of the file.
+% \begin{tcl}
+if {[info exists eemenu::cmdA]} then {return}
+% \end{tcl}
+% \end{arrayvar}
+%
+%
+% \begin{arrayentry}{cmdA}{dtx -> internal Tcl}
+% This is the command that corresponds most closely to that provided
+% by the old \textsf{dtxload} package.
+% \begin{tcl}
+set {eemenu::cmdA(dtx -> internal Tcl)} [list\
+% \end{tcl}
+% By default the command is active and bound to \textsf{Cmd--L} in
+% \TeX\ mode, but it is not put in the menu.
+% \begin{tcl}
+ active 1 binding /L<O mode TeX\
+ in_menu 0\
+% \end{tcl}
+% The extraction method is docstripping. Only code in \texttt{.dtx}
+% files that is furthermore in a \texttt{tcl} or \texttt{tcl*}
+% environment is kept. Again, these are the defaults in the
+% \textsf{dtxload} package.
+% \begin{tcl}
+ extractor Docstrip extract_extra [list\
+ filePatL *.dtx sourceEnvsL {tcl tcl*} lookAtEnvs 1\
+ ]\
+% \end{tcl}
+% The command uses |info complete| to test if it has got a complete
+% command, sends the extracted code to \Alpha's internal \Tcllogo\
+% interpreter, and logs the result on the status line.
+% \begin{tcl}
+ complete "Tcl Info Complete" complete_extra {}\
+%
+ evaluator "Internal Tcl" eval_extra {}\
+%
+ reporter "Status Line" report_extra {}\
+%
+]
+% \end{tcl}
+% Of course, this default setting needs to be saved.
+% \begin{tcl}
+prefs::modified {eemenu::cmdA(dtx -> internal Tcl)}
+% \end{tcl}
+% \end{arrayentry}
+%
+%
+% \begin{arrayentry}{cmdA}{dtx -> remote Tcl}
+% This is a command that I have lately found to be increasingly useful.
+% The functionality was provided in the \textsf{dtxload} package, but
+% it was always slightly awkward as it was not a distinct command.
+% Instead the |evaluateRemotely| variable was used as a selector
+% between this and the previous command.
+%
+% Since these two commands are anyway quite similar, I'll copy
+% settings from the above, only changing those that are different.
+% \begin{tcl}
+catch {unset A}
+array set A [set {eemenu::cmdA(dtx -> internal Tcl)}]
+% \end{tcl}
+% Since keys combinations are sort of in short supply, this command
+% is by default inactive but has the same binding and mode as its
+% \textsf{internal~Tcl} counterpart. This means that if one of these
+% commands is activated then the other is automatically deactivated
+% and so it is anyway easy to switch between them. I also put this
+% remote \Tcllogo\ command in the menu.
+% \begin{tcl}
+set A(active) 0
+set A(in_menu) 1
+% \end{tcl}
+%
+% Communication with remote interpreters is a messy business, due to
+% the many technical details one has do deal with. It is also very
+% platform-dependent. The Mac\,OS settings are however not too
+% complicated, much thanks to \TclAE.
+% \changes{v\,0.3}{2003/06/01}{Corrected condition used for selecting
+% remote evaluation method. (LH)}
+% \begin{tcl}
+if {[info exists eemenu::evaluate(doScriptAE)]} then {
+ set A(evaluator) "Do Script AE"
+ set A(eval_extra)\
+ [list targetApp '${tclshSig}' joinString 0 replyQ 1]
+} \
+% \end{tcl}
+%
+% The Windoze settings are the most complicated. One reason for this
+% is that |dde execute| does not return the result of the script, so
+% that a separate call is needed for this.
+% \begin{tcl}
+elseif {[info exists eemenu::evaluate(windozeDDE)]} then {
+ set A(evaluator) "Windoze DDE"
+ set A(eval_extra) [list\
+%
+ service TclEval target Tcl_1 launchCmd\
+ {exec $tclshSig [file join $HOME Tools winRemoteShell.tcl] &}\
+%
+ joinString 0 prefix "catch \{" suffix "\} alpha_result"\
+ request alpha_result]
+} \
+% \end{tcl}
+%
+% Finally, there are the settings for |send|, which are used on all
+% other platforms.
+% \begin{tcl}
+else {
+ set A(evaluator) "Tk Send"
+ set A(eval_extra) [list target wish joinString 0 replyQ 1]
+}
+% \end{tcl}
+% Then all that remains is to store the settings into the |cmdA| array.
+% \begin{tcl}
+set {eemenu::cmdA(dtx -> remote Tcl)} [array get A]
+prefs::modified {eemenu::cmdA(dtx -> remote Tcl)}
+unset A
+% \end{tcl}
+% \end{arrayentry}
+%
+% \begin{arrayentry}{cmdA}{Tcl example in AIDA}
+% AIDA probably isn't that well known, but in brief it is an
+% experimental source format for \Alpha\ documentation, which can
+% be converted to plain text, \LaTeX, HTML, and some other formats too.
+% Verbatim text lines (as needed for code examples) can of course be
+% included expressed in AIDA; the required markup is mainly that each
+% such line begins with the two characters \verb"(|". Such code can
+% easily be extracted using the regexp extractor.
+%
+% This code is no longer included, since AIDA isn't much used anymore.
+% \begin{tcl}
+%<*aidacode>
+set {eemenu::cmdA(Tcl example in AIDA)} [list\
+%
+ extractor Regexp extract_extra [list\
+% \end{tcl}
+% The filter should get the lines matching the expression, i.e., it
+% should work in \texttt{grep} mode, and the characters that are
+% matched should be removed.
+% \begin{tcl}
+ filter_mode grep filterRE {^\(\|} searchRE {^\(\|} replaceRE {}]\
+% \end{tcl}
+% Evaluation is internally in \Alpha, and the completion test can use
+% |info complete|.
+% \begin{tcl}
+ complete "Tcl Info Complete" complete_extra {}\
+%
+ evaluator "Internal Tcl" eval_extra {}\
+% \end{tcl}
+% Then there's the matter of how to report the result. Since that
+% hasn't been used yet, it seems a good idea to try to use a log
+% window here.
+% \begin{tcl}
+ reporter "Log Window" report_extra {winName {AIDA example log}\
+ winMode Tcl prompt {% } antiprompt {}}\
+% \end{tcl}
+% Finally there's the matter of the binding and the menu. There isn't
+% anything new here, except that the binding is only made active if
+% \texttt{AIDA} mode is installed (since modes not installed will
+% sometimes be interpreted as |<none>|, i.e., global).
+% \begin{tcl}
+ active [mode::exists AIDA] binding /L<O mode AIDA in_menu 1]
+prefs::modified {eemenu::cmdA(Tcl example in AIDA)}
+%</aidacode>
+% \end{tcl}
+% \end{arrayentry}
+%
+% \begin{arrayentry}{cmdA}{Tcl Wiki}
+% When editing a page on the \Tcllogo'ers Wiki~\cite{TclWiki} or the
+% \AlphaTcl\ Wiki~\cite{AlphaTclWiki}, one occasionally finds the need
+% to test some piece of \Tcllogo\ code on that page. This is down to a
+% single keypress with the following command, that extracts lines of
+% verbatim text from a Wiki page and feeds them to the internal
+% interpreter.
+%
+% The syntax of verbatim lines on the \Tcllogo'ers Wiki is
+% basically ``any line that starts with a space'', but unfortunately
+% there are a few exceptions. The equivalents of \LaTeX\ \verb|\item|s
+% for \texttt{itemize} or \texttt{enumerate} are coded as lines that
+% begin with three spaces, a \texttt{*} or \meta{digit}\texttt{.}
+% respectively, and another space. The equivalents of \LaTeX\
+% \verb|\item|s for \texttt{description} are coded as lines that
+% begin with \emph{at least} three spaces, some other characters, a
+% colon, and another three spaces (exactly). It is possible to write a
+% regular expression to filter out such lines.
+% \begin{tcl}
+set {eemenu::cmdA(Tcl Wiki)} [list\
+%
+ extractor Regexp extract_extra [list\
+% \end{tcl}
+% The filter works in \texttt{anti-grep} mode, and has to filter out
+% four different types of non-code lines. There is however no need
+% for further substitutions on the code lines.
+% \begin{tcl}
+ filter_mode anti-grep searchRE {} replaceRE {}\
+ filterRE {^[^ ]|^ (\*|[0-9]\.) |^ .+: [^ ]} ]\
+% \end{tcl}
+% Evaluation is internally in \Alpha, and the completion test can use
+% |info complete|.
+% \begin{tcl}
+ complete "Tcl Info Complete" complete_extra {}\
+%
+ evaluator "Internal Tcl" eval_extra {}\
+% \end{tcl}
+% Then there's the matter of how to report the result. Since that
+% hasn't been used yet, it seems a good idea to try to use a log
+% window here.
+% \begin{tcl}
+ reporter "Log Window" report_extra {winName {Wiki code log}\
+ winMode Tcl prompt {% } antiprompt {}}\
+% \end{tcl}
+% Finally there's the matter of the binding and the menu. There isn't
+% anything new here, except that the binding is only made active if
+% \texttt{Wiki} mode is installed (since modes not installed will
+% sometimes be interpreted as |<none>|, i.e., global).
+% \begin{tcl}
+ mode Wiki active [mode::exists Wiki] binding /L<O in_menu 1]
+prefs::modified {eemenu::cmdA(Tcl Wiki)}
+% \end{tcl}
+% \end{arrayentry}
+%
+% Finally, let's try something which isn't \Tcllogo.
+%
+% \begin{arrayentry}{cmdA}{Mathematica}
+% It is a fairly small modification to make a command which sends
+% DoScript AEs to Mathematica instead of Wish. There's probably a way
+% to do this using |dde| too, but I don't know what that could be.
+%
+% Since Mathematica code presumably concerns rather mathematical
+% problems, the comments to the code is likely to contain fairly
+% advanced mathematical formulae. This makes the \texttt{.dtx}
+% format an interesting choice for source format, and hence I choose
+% to use docstripping as extraction method. As there is no special
+% environment for Mathematica code, the source environments are the
+% generic \texttt{macrocode} and \texttt{macrocode*}.
+% \begin{tcl}
+set eemenu::cmdA(Mathematica) [list\
+%
+ extractor Docstrip extract_extra [list\
+ filePatL *.dtx sourceEnvsL {macrocode macrocode*} lookAtEnvs 1\
+ ]\
+% \end{tcl}
+% The extracted code is sent in a DoScript AppleEvent to the
+% Mathematica kernel. Unfortunately the kernel doesn't seem to
+% produce any result, so we'll have to leave it at that. Since there
+% is no convenient way of testing whether something is a complete
+% command in this case, all code from the entire selection is sent in
+% one event.
+% \begin{tcl}
+ evaluator "Do Script AE" eval_extra\
+ [list targetApp 'Math' joinString 1 replyQ 0]\
+%
+ complete "Entire Selection" complete_extra {}\
+%
+ reporter "Status Line" report_extra {}\
+% \end{tcl}
+% The binding and menu settings are the same as for the remote
+% \Tcllogo\ command.
+% \begin{tcl}
+ active 0 binding /L<O mode TeX in_menu 0]
+% \end{tcl}
+% Of course, this default setting needs to be saved.
+% \begin{tcl}
+prefs::modified {eemenu::cmdA(Mathematica)}
+% \end{tcl}
+% \end{arrayentry}
+%
+%
+% \begin{thebibliography}{9}
+% \bibitem{TclWiki}
+% The \Tcllogo'ers Wiki,
+% \href{http://purl.org/tcl/wiki/}{\textsc{http:}/\slash
+% \texttt{purl.org}\slash \texttt{tcl}\slash \texttt{wiki}/}
+% \bibitem{AlphaTclWiki}
+% \AlphaTcl\ Wiki, \href{http://alphatcl.sourceforge.net/wikit/}
+% {\textsc{http:}/\slash \texttt{alphatcl.sourceforge.net}\slash
+% \texttt{wikit}/}
+% \end{thebibliography}
+%
+%
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/tclldoc/tools/eemenu.ins b/macros/latex/contrib/tclldoc/tools/eemenu.ins
new file mode 100644
index 0000000000..6b28dcfde2
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tools/eemenu.ins
@@ -0,0 +1,66 @@
+% eemenu.ins --- DOCSTRIP installation script for eemenu.
+\input docstrip
+
+% Redefine the \MetaPrefix; it should be something which starts a
+% until-end-of-line comment:
+\edef\MetaPrefix{\string#\string#}
+
+
+% Redefine the file preamble and postamble; this is necessary because
+% otherwise the old \metaPrefix is inserted at the beginning of these
+% lines.
+\preamble
+
+This file may be distributed and/or modified under the conditions
+of the LaTeX Project Public License, either version 1.2 of this
+license or (at your option) any later version. The latest version
+of this license is in
+ http://www.latex-project.org/lppl.txt
+and version 1.2 or later is part of all distributions of LaTeX
+version 1999/12/01 or later.
+
+This file may only be distributed together with a copy of the source
+file from which it was generated. You may distribute that source file
+without this generated file.
+
+You may alternatively distribute, use, and modify this files under
+the conditions of a BSD-style license. In so doing, you should
+however note that
+**************************************
+* This Source is not the True Source *
+**************************************
+the true source is the file from which this one was generated.
+
+\endpreamble
+
+\postamble
+\endpostamble
+
+% Add a (auto-install) line at the top of the preamble, so that
+% Alpha will auto-install it.
+\edef\defaultpreamble{%
+ \MetaPrefix\space (auto-install)^^J%
+ \defaultpreamble
+}
+
+% Actually make eemenu.tcl:
+\generate{
+ \file{eemenu.tcl}{\from{eemenu.dtx}{pkg}}
+ \file{eefor7menu.tcl}{\from{eemenu.dtx}{pkg,atcl7,dialogspatch}}
+}
+
+
+\Msg{}
+\Msg{*********************************************}
+\Msg{*}
+\Msg{* To complete installation, have Alpha open}
+\Msg{* the file eemenu.tcl somewhere outside the}
+\Msg{* Alpha folder hierarchy. You may also have}
+\Msg{* to rebuild Alpha's Tcl and Package indices}
+\Msg{* (Alpha normally does this automatically).}
+\Msg{*}
+\Msg{*********************************************}
+\Msg{}
+
+
+\end
diff --git a/macros/latex/contrib/tclldoc/tools/sourcedtx.dtx b/macros/latex/contrib/tclldoc/tools/sourcedtx.dtx
new file mode 100644
index 0000000000..3b024427ab
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tools/sourcedtx.dtx
@@ -0,0 +1,234 @@
+%
+% \iffalse
+%<*driver>
+\documentclass{tclldoc}
+\begin{document}
+\DocInput{sourcedtx.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{sourcedtx} package}
+% \author{Lars Hellstr\"om}
+% \date{18 July 2003}
+% \maketitle
+%
+% \begin{abstract}
+% The \textsf{sourcedtx} package provides a \Tcllogo\ command
+% |dtx::source| that makes it possible to |source| \Tcllogo\ code
+% from a \textsf{doc}-style \texttt{.dtx} file without docstripping
+% it first.
+% \end{abstract}
+%
+%
+% \begin{tcl}
+%<*pkg>
+namespace eval dtx {}
+% \end{tcl}
+% \setnamespace{dtx}
+%
+% \begin{proc}{strip_string}
+% The |strip_string| procedure does the actual docstripping for
+% |source_dtx|. The syntax is
+% \begin{quote}
+% |dtx::strip_string| \word{text} \word{option list}
+% \word{meta prefix}\regopt\ \word{interaction}\regopt
+% \end{quote}
+% where \word{text} is the string to docstrip and \word{option list}
+% is the list of options to use. The \word{meta prefix} (by default
+% two percent signs) is the string to use for the \textsc{docstrip}
+% parameter \verb|\MetaPrefix|. The \word{interation} (by default 1)
+% is a flag for the ``interaction'' level to use. |0| means error
+% messages are simply written to |stderr|, whereas |1| means an error
+% will be raised. (It is possible that \word{interaction} will be
+% extended to a ``flag word'' where each bit controls some aspect of
+% the interaction.)
+%
+% When errors are raised, the |errorCode| is set to a list with the
+% format
+% \begin{quote}
+% |DOCSTRIP| \word{situation} \word{lineno}
+% \end{quote}
+% where \word{lineno} is the line number (starting at one) of the line
+% where the error was detected. The \word{situation}s are described
+% below, at the positions in the code where they can occur.
+%
+% \begin{tcl}
+proc dtx::strip_string {text options {metaprefix %%} {interaction 1}} {
+% \end{tcl}
+% The |O| array has entires for precisely the specified options, so
+% that an opion can be tested using |info exists|.
+% \begin{tcl}
+ foreach option $options {set O($option) ""}
+% \end{tcl}
+% |stripped| is where the text that passes docstripping is collected.
+% \begin{tcl}
+ set stripped ""
+% \end{tcl}
+% |block_stack| is the list of modules inside which the current line
+% lies. |offlevel| is the number of modules that must be exited
+% before code lines should once again be included. |verbatim| is a
+% flag for whether verbatim mode is in force.
+% \begin{tcl}
+ set block_stack [list]
+ set offlevel 0
+ set verbatim 0
+% \end{tcl}
+% |lineno| is the input line number counter, for use in error
+% messages.
+% \begin{tcl}
+ set lineno 1
+% \end{tcl}
+% Here starts the main loop over lines in the \word{text}. It
+% constitutes the majority of the procedure and is split in two
+% parts. The smaller part handles lines in verbatim mode (unusual),
+% the large part handles lines in normal mode (with comment lines,
+% code lines, guard lines, and so on).
+% \begin{tcl}
+ foreach line [split $text \n] {
+ if {$verbatim} then {
+ if {$line eq $endverbline} then {
+ set verbatim 0
+ } elseif {!$offlevel} then {
+ append stripped $line \n
+ }
+ } else {
+ switch -glob -- $line %%* {
+ if {!$offlevel} then {
+ append stripped $metaprefix\
+ [string range $line 2 end] \n
+ }
+ } %<<* {
+ set endverbline "%[string range $line 3 end]"
+ set verbatim 1
+ } %<* {
+ if {[regexp -- {^%<([*/+-]?)([^>]*)>(.*)$} $line ""\
+ modifier expression line]} then {
+% \end{tcl}
+% There is a well-formed guard line. First the expression is
+% evaluated, by converting it to an |expr| expression.
+% \begin{tcl}
+ regsub -all -- {\\|\{|\}|\$|\[|\]| |;} $expression\
+ {\\&} E
+ regsub -all -- {,} $E {|} E
+ regsub -all -- {[^()|&!]+} $E {[info exists O(&)]} E
+ set val [expr $E]
+ switch -exact -- $modifier * {
+ lappend block_stack $expression
+ if {$offlevel || !$val} then {incr offlevel}
+ } / {
+ if {![llength $block_stack]} then {
+% \end{tcl}
+% In this case there was no open block for this guard to end. That
+% is a \describestring[error situation]{SPURIOUS}|SPURIOUS|
+% \word{situation}.
+% \begin{tcl}
+ if {$interaction} then {
+ error "Spurious end block </$expression>\
+ ignored." ""\
+ [list DOCSTRIP SPURIOUS $lineno]
+ } else {
+ puts stderr "docstrip: Spurious end\
+ block </$expression> ignored on line\
+ $lineno."
+ }
+ } else {
+ if {[string compare $expression\
+ [lindex $block_stack end]]} then {
+% \end{tcl}
+% In this case the expression of the block being closed does not match
+% the expression on the block on top of the stack. That is a
+% \describestring[error situation]{MISMATCH}|MISMATCH|
+% \word{situation}. \textsc{docstrip} by default raises an error and
+% recovers by treating this situation as a typo.
+% \begin{tcl}
+ if {$interaction} then {
+ error "Found </$expression> instead of\
+ </[lindex $block_stack end]>." ""\
+ [list DOCSTRIP MISMATCH $lineno]
+ }
+ puts stderr "docstrip:\
+ Found </$expression> instead of\
+ </[lindex $block_stack end]> on line\
+ $lineno."
+ }
+% \end{tcl}
+% All that error processing makes it easy to lose track, but the
+% following two lines are what does the real work for an end of block
+% guard: pop a block off the stack and decrement the |offlevel|.
+% \begin{tcl}
+ if {$offlevel} then {incr offlevel -1}
+ set block_stack [lreplace $block_stack end end]
+ }
+ } - {
+ if {!$offlevel && !$val} then {
+ append stripped $line \n
+ }
+ } default {
+ if {!$offlevel && $val} then {
+ append stripped $line \n
+ }
+ }
+ } else {
+% \end{tcl}
+% In this case the line looks like a guard line, but there is no |>|
+% terminating the guard expression. This is a
+% \describestring[error situation]{BADGUARD}|BADGUARD|
+% \word{situation}.
+% \begin{tcl}
+ if {$interaction} then {
+ error "Malformed guard on line $lineno." ""\
+ [list DOCSTRIP BADGUARD $lineno]
+ } else {
+ puts stderr "docstrip: Malformed guard\
+ on line $lineno:"
+ puts stderr $line
+ }
+ }
+ } %* {}\
+% \end{tcl}
+% With comment lines, nothing is done. A line being the exact string
+% |\endinput| terminates the stripping.
+% \begin{tcl}
+ {\\endinput} {
+ break
+ } default {
+% \end{tcl}
+% Other lines are code lines. These are included or not, depending on
+% the |offlevel|.
+% \begin{tcl}
+ if {!$offlevel} then {append stripped $line \n}
+ }
+ }
+ incr lineno
+ }
+ return $stripped
+}
+% \end{tcl}
+% \end{proc}
+%
+%
+% \begin{proc}{source}
+% This procedure behaves as a docstripping |source| command: it reads
+% a file, docstrips its contents in memory, and evaluates the result
+% as a \Tcllogo\ script in the context of the caller. The syntax is
+% \begin{quote}
+% |dtx::source| \word{dtx-file} \word{options}
+% \end{quote}
+% where \word{dtx-file} is the file name and \word{options} is the
+% list of options.
+% \begin{tcl}
+proc dtx::source {name options} {
+ set F [open $name r]
+ set text [read $F]
+ close $F
+ uplevel 1 [dtx::strip_string $text $options #]
+}
+%</pkg>
+% \end{tcl}
+% \end{proc}
+%
+%
+\endinput
+
+ \ No newline at end of file
diff --git a/macros/latex/contrib/tclldoc/tools/sourcedtx.ins b/macros/latex/contrib/tclldoc/tools/sourcedtx.ins
new file mode 100644
index 0000000000..f26acf7ee7
--- /dev/null
+++ b/macros/latex/contrib/tclldoc/tools/sourcedtx.ins
@@ -0,0 +1,31 @@
+% sourcedtx.ins --- DOCSTRIP installation script for sourcedtx.tcl.
+\input docstrip
+
+% Redefine the \MetaPrefix; it should be something which starts a
+% until-end-of-line comment:
+\edef\MetaPrefix{\string#\string#}
+
+
+% Redefine the file preamble and postamble; this is necessary because
+% otherwise the old \metaPrefix is inserted at the beginning of these
+% lines.
+\preamble
+
+This file is put in the public domain. Note however that
+**************************************
+* This Source is not the True Source *
+**************************************
+the true source is the file from which this one was generated.
+
+\endpreamble
+
+\postamble
+\endpostamble
+
+% Actually make sourcedtx.tcl:
+\generate{
+ \file{sourcedtx.tcl}{\from{sourcedtx.dtx}{pkg}}
+}
+
+
+\end