#!/usr/bin/wish
#  -*- mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*- \
#exec wish "$0" -- "$@"
#
#       $Id: Header.tcl.in,v 1.2 2006-06-27 13:28:05 villate Exp $
#
# Header to allow for Unix execution
#

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifht Floor, Boston,
# MA 02110-1301, USA
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-

# Voodo for CYGWIN
# Is there a canonical way of telling we are under CYGWIN?
global env tcl_platform maxima_priv
if {$tcl_platform(platform) == "windows" && \
	[info exists env(PATH)] && $env(PATH) != "" && \
	[string match {*/usr/bin*} $env(PATH)] && \
	[string match {*:*} $env(PATH)] && \
	![string match {*;*} $env(PATH)]} {
    # CYGWIN uses Unix PATH but Tcl considers it Windows
    # What's even worse auto_execok uses ; but exec uses :
    if {0} {
	set env(PATH) [join [split $env(PATH) ":"] ";"]
    } else {
	set maxima_priv(platform) cygwin
# Windows version.
#
# Note that info executable doesn't work under Windows, so we have to
# look for files with .exe, .com, or .bat extensions.  Also, the path
# may be in the Path or PATH environment variables, and path
# components are separated with semicolons, not colons as under Unix.
#
proc auto_execok name {
    global auto_execs env tcl_platform

    if {[info exists auto_execs($name)]} {
	return $auto_execs($name)
    }
    set auto_execs($name) ""

    set shellBuiltins [list cls copy date del erase dir echo mkdir \
	    md rename ren rmdir rd time type ver vol]
    if {[string equal $tcl_platform(os) "Windows NT"]} {
	# NT includes the 'start' built-in
	lappend shellBuiltins "start"
    }
    if {[info exists env(PATHEXT)]} {
	# Add an initial : to have the {} extension check first.
	set execExtensions [split ":$env(PATHEXT)" ":"]
    } else {
	set execExtensions [list {} .bat .com .exe]
    }

    if {[lsearch -exact $shellBuiltins $name] != -1} {
	return [set auto_execs($name) [list $env(COMSPEC) /c $name]]
    }

    if {[llength [file split $name]] != 1} {
	foreach ext $execExtensions {
	    set file ${name}${ext}
	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    set path "[file dirname [info nameof]]:.:"
    if {[info exists env(WINDIR)]} {
	set windir $env(WINDIR) 
    }
    if {[info exists windir]} {
	if {[string equal $tcl_platform(os) "Windows NT"]} {
	    append path "$windir/system32:"
	}
	append path "$windir/system:$windir:"
    }

    foreach var {PATH Path path} {
	if {[info exists env($var)]} {
	    append path ":$env($var)"
	    break
	}
    }

    foreach dir [split $path {:}] {
	# Skip already checked directories
	if {[info exists checked($dir)] || [string equal {} $dir]} { continue }
	set checked($dir) {}
	foreach ext $execExtensions {
	    set file [file join $dir ${name}${ext}]
	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
    }
    return ""
}

    }

} else {
    set maxima_priv(platform) $tcl_platform(platform)
}

proc lIDEFileTypes {pat} {
    switch -exact -- $pat *.py {
	set types [list {"Python Files" {.py .pyw}} {"All Files" *}]
    } *.txt {
	set types [list {"Text Files" .txt} {"All Files" *}]
    } *.txt {
	set types [list {"Log Files" {.log}} {"All Files" *}]
    } *.out {
	set types [list {"Output Files" .out} {"All Files" *}]
    } *.bat {
	set types [list {"Batch Files" {.bat .clp .tst}} {"All Files" *}]
    } *.bin {
	set types [list {"Binary Files" {.bin .sav}} {"All Files" *}]
    } *.mac {
	set types [list {"Maxima Files" {.mc .mac .dem}} {"All Files" *}]
    } *.lisp {
	set types [list {"Lisp Files" {.lisp}} {"All Files" *}]
    } *.tcl {
	set types [list {"Tcl Files" .tcl} {"All Files" *}]
    } *.clp {
	set types [list {"CLIPS Files" {.clp}} {"All Files" *}]
    } *.pprj {
	set types [list {"Protege Projects" .pprj} {"All Files" *}]
    } * - default {
	set types [list {"All Files" *}]
    }
    return $types
}

proc tide_openfile {title {self "."} {pat "*"} {file ""}} {
    global maxima_default

    if {$self == ""} {set self .}
    set z [winfo toplevel $self]

    set types [lIDEFileTypes $pat]

    # required for a MSFC/Tk bug workaround
    update

    if {$file == ""} {set file $maxima_default(OpenFile)}
    if {$file != ""} {set dir [file dir $file]} {set dir ""}

    set proc tk_getOpenFile
    global tk_strictMotif
    set old $tk_strictMotif
    set tk_strictMotif 0

    # -defaultextension $pattern
    set list [list $proc -title $title \
	    -filetypes $types \
	    -parent $z]
    if {$dir != ""} {
	lappend list  -initialdir [file native $dir]
    }

    if {[catch {eval $list} retval]} {
	global errorInfo
	tide_failure \
		[M "Error opening file:\n%s" $errorInfo]
	return ""
    }
    set tk_strictMotif $old

    if {$retval != ""} { set maxima_default(OpenFile) $retval }

    return $retval
}

proc tide_savefile {title {self "."} {pat "*"} {file ""}} {
    global maxima_default

    if {$self == ""} {set self .}
    set z [winfo toplevel $self]

    set types [lIDEFileTypes $pat]

    # required for a MSFC/Tk bug workaround
    update

    if {$file == ""} {set file $maxima_default(SaveFile)}
    if {$file != ""} {set dir [file dir $file]} {set dir ""}

    set proc tk_getSaveFile
    global tk_strictMotif
    set old $tk_strictMotif
    set tk_strictMotif 0

    # -defaultextension $pattern
    set list [list $proc  \
	    -filetypes $types \
	    -parent $z \
	    -title $title]
    if {$dir != ""} {
	lappend list -initialdir [file native $dir]
    }
    if {[catch {eval $list} retval]} {
	global errorInfo
	tide_failure \
		"Error Saving file:\n$errorInfo"
	return ""
    }
    set tk_strictMotif $old

    if {$retval != ""} { set maxima_default(SaveFile) $retval }

    return $retval
}

proc tide_opendir {title {self "."} {dir ""}} {
    global maxima_default

    set list [list tk_chooseDirectory \
	    -parent $self -title $title -mustexist 1]
    if {$dir == ""} {set dir $maxima_default(OpenDir)}
    if {$dir != ""} {
	lappend list -initialdir [file native $dir]
    }
    if {[catch {eval $list} retval]} {
	global errorInfo
	tide_failure \
		"Error Saving file:\n$errorInfo"
	return ""
    }

    if {$retval != ""} {set maxima_default(OpenDir) $retval}

    return $retval
}

proc tide_savedir {title {self "."} {dir ""}} {
    global maxima_default

    set list [list tk_chooseDirectory \
	    -parent $self -title $title -mustexist 0]
    if {$dir == ""} {set dir $maxima_default(OpenDir)}
    if {$dir != ""} {
	lappend list -initialdir [file native $dir]
    }
    if {[catch {eval $list} retval]} {
	global errorInfo
	tide_failure \
		"Error Saving file:\n$errorInfo"
	return ""
    }

    if {$retval != ""} {set maxima_default(OpenDir) $retval}

    return $retval
}


proc tide_notify {reason {self "."}} {
    update
    # puts stdout $reason
    tk_messageBox -icon info \
	    -title "Info" \
	    -parent $self \
	    -message $reason -type ok
}

proc tide_failure {reason {self "."}} {
    global errorInfo
    update
    # puts stderr $reason
    # puts stderr $errorInfo
    tk_messageBox -icon error \
	    -title "Error" \
	    -parent $self \
	    -message $reason -type ok
}

proc tide_yesno {reason {self "."}} {
    update
    set retval [tk_messageBox -icon question \
	    -title "Question" \
	    -parent $self \
	    -message $reason -type yesno]
    if {$retval == "yes"} {return 1} {return 0}
}

proc tide_yesnocancel {reason {self "."}} {
    update
    set retval [tk_messageBox -icon question \
	    -title "Question" \
	    -message $reason -type yesnocancel]
    switch $retval "yes" {
	return 1
    } no {
	return 0
    } cancel {
	return -1
    }
}


proc M {str args} {
    if {$args == ""} {return $str}
    return [eval [list format $str] $args]
}

proc cIDEMenuCreatePopup {menu fun box} {
    global tcl_platform

    menu $menu -tearoff 0
    if {$fun != ""} {eval $fun $menu}

    bind $box <Button-3> [list tk_popup $menu %X %Y]
    switch -exact -- $tcl_platform(platform) windows {
	bind $box <Key-App> [list tk_popup $menu %X %Y]
    }
    return $menu
}

proc cIDECreateEvent {text label code} {
    set z [winfo toplevel $text]
    set event "<<[join $label -]>>"
    bind $text $event $code
    return [list event generate $text $event]
}

# -*- mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#	$Id: Object.tcl,v 1.3 2006-10-01 23:59:47 villate Exp $
#
# Original Id: object.tcl,v 1.7 1995/02/10 08:32:50 sls Exp sls
#
# This software is copyright (C) 1994 by the Lawrence Berkeley Laboratory.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that: (1) source code distributions
# retain the above copyright notice and this paragraph in its entirety, (2)
# distributions including binary code include the above copyright notice and
# this paragraph in its entirety in the documentation or other materials
# provided with the distribution, and (3) all advertising materials mentioning
# features or use of this software display the following acknowledgement:
# ``This product includes software developed by the University of California,
# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
# the University nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior
# written permission.
# 
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

# Prepare for message catalogues
proc M {str args} {
    if {$args == ""} {return $str}
    return [eval [list format $str] $args]
}

proc object_info {name} {
    # need an object info function like itcl
}

set object_priv(currentClass) {}
set object_priv(objectCounter) 0

proc object_class {name spec} {
    global object_priv
    set object_priv(currentClass) $name
    lappend object_priv(objects) $name
    upvar #0 ${name}_priv class
    set class(members) {}
    set class(params) {}
    set class(methods) {}
    proc doc arg "upvar #0 ${name}_priv class; set class(__doc__) \"\$arg\""
    eval $spec
    proc doc arg ""
    proc $name:config {self args} "uplevel \[concat object_config \$self \$args]"
    proc $name:configure args "uplevel \[concat object_config \$args]"
    proc $name:cget {self option} "uplevel \[list object_cget \$self \$option]"
    proc $name {inst args} "object_new $name \$inst; uplevel \[concat object_config \$inst \$args]"
}


# could do doc as a simple proc that finds if its in a method or a class
# use uplevel and/or look for self as first of info args

proc method {name args body} {
    global object_priv
    set className $object_priv(currentClass)
    upvar #0 ${className}_priv class
    lappend class(methods) $name
    set methodArgs self
    append methodArgs " " $args
    set procbody "upvar #0 \$self slot"
    append procbody "\nproc doc arg \"upvar #0 \$self slot; set slot(${name}.__doc__) \\\$arg\""
    append procbody "\n$body"
    proc $className:$name $methodArgs $procbody
}

# Pythonic method without the implicit self
proc def {name args body} {
    global object_priv
    set className $object_priv(currentClass)
    upvar #0 ${className}_priv class
    lappend class(methods) $name
    set methodArgs $args
    set procbody "set self \$[lindex $methodArgs 0]; upvar #0 \$self slot"
    append procbody "\nproc doc arg \"upvar #0 \$self slot; set slot(${name}.__doc__) \\\$arg\""
    append procbody "\n$body"
    proc $className:$name $methodArgs $procbody
}

proc member {name {defaultValue {}}} {
    global object_priv
    set className $object_priv(currentClass)
    upvar #0 ${className}_priv class
    if {![info exists class(member_info/$name)]} {
	lappend class(members) [list $name $defaultValue]
    }
    set class(member_info/$name) {}
}

proc param {name {defaultValue {}} {resourceClass {}} {configCode {}}} {
    global object_priv
    set className $object_priv(currentClass)
    upvar #0 ${className}_priv class
    if {$resourceClass == ""} {
	set resourceClass \
	    [string toupper [string index $name 0]][string range $name 1 end]
    }
    if ![info exists class(param_info/$name)] {
	lappend class(params) $name
    }
    set class(param_info/$name) [list $defaultValue $resourceClass]
    if {$configCode != {}} {
	proc $className:config:$name self $configCode
    }
}

proc object_include {args} {
    global object_priv
    set className $object_priv(currentClass)
    foreach super_class_name $args {
	if {[info procs $super_class_name] == ""} {auto_load $super_class_name}
	upvar #0 ${className}_priv class
	upvar #0 ${super_class_name}_priv super_class
	foreach p $super_class(params) {
	    lappend class(params) $p
	    set class(param_info/$p) $super_class(param_info/$p)
	}
	set class(members) [concat $super_class(members) $class(members)]
	foreach m $super_class(methods) {
	    set formals {}
	    set proc $super_class_name:$m
	    foreach arg [info args $proc] {
		if {[info default $proc $arg def]} {
		    lappend formals [list $arg $def]
		} else {
		    lappend formals $arg
		}
	    }
	    proc $className:$m $formals [info body $proc]
	}
    }
}

proc object_new {className {name {}}} {
    if {$name == {}} {
	global object_priv
	set name O_[incr object_priv(objectCounter)]
    }
    upvar #0 $name object
    upvar #0 ${className}_priv class
    set object(__class__) $className
    set object(__file__) [info script]
    foreach var $class(params) {
	set info $class(param_info/$var)
	set resourceClass [lindex $info 1]
	if {$resourceClass != "" && \
		![catch {set val [option get $name $var $resourceClass]}]} {
	    if {$val == ""} {
		set val [lindex $info 0]
	    }
	} else {
	    set val [lindex $info 0]
	}
	set object($var) $val
    }
    foreach var $class(members) {
	set object([lindex $var 0]) [lindex $var 1]
    }
    proc $name {method args} [format {
	upvar #0 %s object
	uplevel [concat $object(__class__):$method %s $args]
    } $name $name]
    if {[info procs ${className}:__init__] != ""} {
	$name  __init__
    } elseif {[info procs ${className}:create] != ""} {
	$name  create
    }
    return $name
}

proc object_define_creator {windowType name spec} {
    object_class $name $spec
    if {[info procs $name:create] == {} && [info procs $name:__init__] == {}} {
	error "widget \"$name\" must define a create method"
    }
    if {[info procs $name:reconfig] == {}} {
	error "widget \"$name\" must define a reconfig method"
    }
    proc $name {window args} [format {
	if {[winfo exists $window]} {destroy $window}
	# need to transfer option database from Toplevel/Frame if we use -class
	%s $window -class %s
	rename $window object_window_of$window
	upvar #0 $window object
	set object(__window__) $window
	object_new %s $window
	proc %s:frame {self args} \
	    "uplevel \[concat object_window_of$window \$args]"
	uplevel [concat $window config $args]
	# __init__ is a required method 
	if {![catch {$window __init__} err]} {
	    # create is the oldname
	} elseif {[catch {$window create} err]} {
	    tk_messageBox -icon error -type ok \
		    -message "Error creating widget \"$window\":\n$err"
	    error "Error creating $window:\n$err" 
	}
	set object(__created) 1
	bind $window <Destroy> \
	    "if !\[string compare %%W $window\] { object_delete $window }"
	# reconfig is a required method
	$window reconfig
	return $window
    } $windowType \
	  [string toupper [string index $name 0]][string range $name 1 end] \
	  $name $name]
}

# Class creators and their synonyms
proc object_frame {name spec} {
    # need to transfer option database from Frame to widget?
    object_define_creator frame $name $spec
}
proc widget {args} {
    eval object_frame $args
}

proc object_toplevel {name spec} {
    # need to transfer option database from Toplevel to widget?
    object_define_creator toplevel $name $spec
}
proc dialog {args} {
    eval object_toplevel $args
}

auto_load auto_reset
set arglist {name args} 
set body {
    variable index
    variable scriptFile
    # Do some fancy reformatting on the "source" call to handle platform
    # differences with respect to pathnames.  Use format just so that the
    # command is a little easier to read (otherwise it'd be full of 
    # backslashed dollar signs, etc.
    append index [list set auto_index([fullname $name])] \
	    [format { [list source [file join $dir %s]]} \
	    [file split $scriptFile]] "\n"
}
foreach elt {widget dialog object_toplevel object_frame} {
    auto_mkindex_parser::command $elt $arglist $body
}

auto_mkindex_parser::command object_class {name args} {
    variable index
    variable scriptFile
    # Do some fancy reformatting on the "source" call to handle platform
    # differences with respect to pathnames.  Use format just so that the
    # command is a little easier to read (otherwise it'd be full of 
    # backslashed dollar signs, etc.
    append index [list set auto_index([fullname $name])] \
	    [format { [list source [file join $dir %s]]} \
	    [file split $scriptFile]] "\n"
}


proc object_config {self args} {
    upvar #0 $self object
    set len [llength $args]
    if {$len == 0} {
	upvar #0 $object(__class__)_priv class
	set result {}
	if {![info exists class(params)]} {
	    return {}
	}
	foreach param $class(params) {
	    set info $class(param_info/$param)
	    lappend result \
		[list -$param $param [lindex $info 1] [lindex $info 0] \
		 $object($param)]
	}
	if {[info exists object(__window__)]} {
	    set result [concat $result [object_window_of$object(__window__) config]]
	}
	return $result
    }
    if {$len == 1} {
	upvar #0 $object(__class__)_priv class
	if {[string index $args 0] != "-"} {
	    error "param '$args' didn't start with dash"
	}
	set param [string range $args 1 end]
	if {![info exists class(params)]} {
	    error "Attempt to query an undeclared param: $param"
	}
	if {[set ndx [lsearch -exact $class(params) $param]] == -1} {
	    if {[info exists object(__window__)]} {
		return [object_window_of$object(__window__) config -$param]
	    }
	    error "no param '$args'"
	}
	set info $class(param_info/$param)
	return [list -$param $param [lindex $info 1] [lindex $info 0] \
		$object($param)]
    }
    # accumulate commands and eval them later so that no changes will take
    # place if we find an error
    set cmds ""
    while {$args != ""} {
	set fieldId [lindex $args 0]
        if {[string index $fieldId 0] != "-"} {
            error "param '$fieldId' didn't start with dash"
        }
        set fieldId [string range $fieldId 1 end]
        if ![info exists object($fieldId)] {
	    if {[info exists object(__window__)]} {
		if {[catch [list object_window_of$object(__window__) config -$fieldId]]} {
		    error "tried to set param '$fieldId' which did not exist."
		} else {
		    lappend cmds \
			[list object_window_of$object(__window__) config -$fieldId [lindex $args 1]]
		    set args [lrange $args 2 end]
		    continue
		}
	    }

        }
	if {[llength $args] == 1} {
	    return $object($fieldId)
	} else {
	    lappend cmds [list set object($fieldId) [lindex $args 1]]
	    if {[info procs $object(__class__):config:$fieldId] != {}} {
		lappend cmds [list $self config:$fieldId]
	    }
	    set args [lrange $args 2 end]
	}
    }
    foreach cmd $cmds {
	eval $cmd
    }
    if {[info exists object(__created)] && [info procs $object(__class__):reconfig] != {}} {
	$self reconfig
    }
}

proc object_cget {self var} {
    upvar #0 $self object
    return [lindex [object_config $self $var] 4]
}

proc object_delete self {
    upvar #0 $self object
    if {[info exists object(__class__)] && [info commands $object(__class__):destroy] != ""} {
	catch {$object(__class__):destroy $self}
    }
    if {[info exists object(__window__)]} {
	if {[string length [info commands object_window_of$self]]} {
	    catch {rename $self {}}
	    rename object_window_of$self $self
	}
	destroy $self
    }
    catch {unset object}
}

proc object_slotname slot {
    upvar self self
    return [set self]($slot)
}
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#	$Id: Feedback.tcl,v 1.1 2002-09-19 16:13:50 mikeclarkson Exp $
#
# Id: feedback.tcl,v 1.3 1995/02/23 00:23:04 sls Exp
#
#
#    Description:
#          A little feedback widget, used to indicate progress.
#

object_toplevel Feedback {

    param steps 10
    param title
    param barwidth 200
    param barheight 20
    param barcolor DodgerBlue

    member iCount 0

    doc {
	A little feedback widget, used to indicate progress
    }

    method create {} {

	$self config -bd 4 -relief ridge
	label $self.title
	pack $self.title -side top -fill x -padx 2 -pady 2

        frame $self.spacer
        frame $self.bar -relief raised -bd 2 -highlightthickness 0
	pack $self.spacer $self.bar -side top -padx 10 -anchor w
        label $self.percentage -text 0%
	pack $self.percentage -side top -fill x -padx 2 -pady 2
	# should not be . - should be .main0
        wm transient $self ""
        wm title $self [M "Please wait..."]

	$self.title config -text $slot(title)
	$self.spacer config -width $slot(barwidth)
	$self.bar config -height $slot(barheight) -bg $slot(barcolor)

    }

    method reconfig {} {
        center_window $self
	update
    }

    method destroy {} {
	# catch required
	catch {
	    if {[grab current $self] == $self} {
		grab release $self
	    }
	}
	update
	catch {destroy $self}
    }

    method grab {} {
	while {[catch {grab set $self}]} {
	}
    }

    method reset {} {
	set slot(iCount) -1
	$self step
    }

    method step {{inc 1}} {
	if {$slot(iCount) >= $slot(steps)} {
	    return $slot(steps)
	}
        incr slot(iCount) $inc
        set fraction [expr 1.0*$slot(iCount)/$slot(steps)]
        $self.percentage config -text [format %.0f%% [expr 100.0*$fraction]]
        $self.bar config -width [expr int($slot(barwidth)*$fraction)]
        update
	return $slot(iCount)
    }

    method set_title {title} {
	set slot(title) $title
	$self.title config -text $slot(title)
    }
}

# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Constants.tcl,v 1.29 2011-03-20 23:14:57 villate Exp $
#

proc cMAXINITBeforeIni {} {
    global maxima_default
    set maxima_default(plotwindow) multiple

    # from Send-some.tcl
    set maxima_default(sMathServerHost) genie1.ma.utexas.edu
    set maxima_default(iMathServerPort) 4443

    # from Browser.tcl
    set maxima_default(sMathServerHost) localhost
    set maxima_default(iMathServerPort) 4443

    #mike turn these off by default
    set maxima_default(iShowBalloons) 0

    set maxima_default(fontAdjust) 0

    set maxima_default(iConsoleWidth) 80
    set maxima_default(iConsoleHeight) 32

    # Set up Maxima console font
    set cfont [font actual TkFixedFont -family]
    set cfontsize [font actual TkFixedFont -size]
    catch {font delete ConsoleFont}
    font create ConsoleFont -family $cfont -size $cfontsize 
    set maxima_default(ConsoleFont) [list $cfont $cfontsize]

    set maxima_default(iLocalPort) 4008

    set maxima_default(bDebugParse) 0

    # from FileDlg.tcl
    set maxima_default(OpenDir) "~/"
    set maxima_default(OpenFile) "~/.xmaximrc"
    set maxima_default(SaveFile) "~/.xmaximrc"

    # From Browser.tcl
    set maxima_default(defaultservers) {
	nmtp://genie1.ma.utexas.edu/
	nmtp://linux51.ma.utexas.edu/
	nmtp://linux52.ma.utexas.edu/
    }

    global embed_args
    if { "[info var embed_args]" != "" } {
	# the following will be defined only in the plugin
	set maxima_default(defaultservers) nmtp://genie1.ma.utexas.edu/
    }


    # maxima_default(lProxyHttp)
}

proc cMAXINITReadIni {} {
    if {[file isfile ~/.xmaximarc]} {
	if {[catch {uplevel "#0" [list source ~/.xmaximarc] } err]} {
	    tide_failure [M [mc "Error sourcing %s\n%s"] \
			      [file native ~/.xmaximarc] \
			      $err]
	}
    }
}

proc cMAXINITAfterIni {} {
    global maxima_default maxima_priv MathServer
    lMaxInitSetOpts
    set MathServer [list $maxima_default(sMathServerHost) \
			$maxima_default(iMathServerPort) ]

    # from plot3d.tcl
    set maxima_priv(speed) [expr {(9700.0 / (1 + [lindex [time {set i 0 ; while { [incr i] < 1000} {}} 1] 0]))}]

    # from Wmenu.tcl
    global show_balloons
    set show_balloons $maxima_default(iShowBalloons)

    # From Browser.tcl
    global debugParse
    set debugParse $maxima_default(bDebugParse)

    if {[info exists maxima_default(lProxyHttp)] && \
	    [llength $maxima_default(lProxyHttp)] == "2"} {
	#mike FIXME: make this a _default
	set maxima_priv(proxy,http) $maxima_default(lProxyHttp)
    }

}

# Constants
global maxima_priv
set maxima_priv(date) 14/03/2011

# from
if { ![info exists maxima_priv(date)] } {
    set maxima_priv(date) [clock  format [clock seconds] -format {%m/%d/%Y} ]
}

# from Preamble.tcl
set maxima_priv(clicks_per_second) 1000000

# from Getdata1.tcl
set maxima_priv(cachedir) ~/.netmath/cache

# from Plotconf.tcl
global ftpInfo
set ftpInfo(host) genie1.ma.utexas.edu
set ftpInfo(viahost) genie1.ma.utexas.edu

# from Plot2d.tcl
array set maxima_priv { bitmap,disc4 {#define disc4_width 4
#define disc4_height 4
static unsigned char disc4_bits[] = {
    0x06, 0x0f, 0x0f, 0x06};}
    bitmap,disc6 {#define disc_width 6
#define disc_height 6
static unsigned char disc_bits[] = {
    0xde, 0xff, 0xff, 0xff, 0xff, 0xde};}
}

# from xmaxima.tcl
set maxima_priv(options,maxima) {{doinsert 0 "Do an insertion" boolean}}

# from EOctave.tcl
set maxima_priv(options,octave) {{doinsert 1 "Do an insertion" boolean}}

# from EOpenplot.tcl
set maxima_priv(options,openplot) {{doinsert 0 "Do an insertion" boolean}}

# from EHref.tcl
set maxima_priv(options,href) {
    {src "" [mc "A URL (universal resource locator) such as http://www.ma.utexas.edu/foo.om"]}
    {search "" [mc "A string to search for, to get an initial position"]}
    {searchregexp "" [mc "A regexp to search for, to get an initial position"]}
}

# from Preamle.tcl
set maxima_priv(counter) 0
	
# the linelength initially will have Maxima's default value.
set maxima_priv(linelength) 79

# From Browser.tcl
set maxima_priv(sticky) "^Teval$|^program:"
set maxima_priv(richTextCommands) {Tins TinsSlashEnd}
set maxima_priv(urlHandlers) {
    text/html  netmath
    text/plain netmath
    image/gif  netmath
    image/png  netmath
    image/jpeg netmath
    application/postscript "see %s"
    application/pdf "see %s"
    application/x-dvi "see %s"
}
set maxima_priv(imagecounter) 0

global evalPrograms
set evalPrograms {  gp gap gb }
#set maxima_priv(options,maxima) {{doinsert 1 "Do an insertion" boolean}}
#set maxima_priv(options,gp) {{doinsert 1 "Do an insertion" boolean}}
#set maxima_priv(options,openplot) {{doinsert 0 "Do an insertion" boolean}}

# Icons from the Tango Desktop Project (http://tango.freedesktop.org)
# "The Tango base icon theme is released to the Public Domain.
# "The palette is in public domain. Developers, feel free to ship it
# "along with your application."

image create photo ::img::brokenimage -format GIF -data {
    R0lGODlhHQAgAOMEAAAAAP9jMcbGxoSEhP///zExY/9jzgCEAP/////////////////////
    //////////yH5BAEAAAIALAAAAAAdACAAAATTcMhJqxU440G6/+AnaRkXnuAgqKRJvi+3th
    1sbzWLE/bh+xoTT+d6/Y6lz2xVIx2fO8+sqHkiBYCsNsvkOa1ATGFMBkiaVfAhSDFTM+r1q
    +NGp6Ew+plnMF7zBHV8fTc3ei4GiYU2hzWJioskjYOPLwGXmJdiBYICj5UamZqbI4ifkBii
    mwVEjqckowJkI0mUqDBjtEGut6ucrC+doBq5EzADwoQkwDccwsRkzMeTL6y6MSrU0DotkoF
    7HsU22SGCHbmFKN9bWdwk7PBmK9fYFhQZEQA7
}

image create photo ::img::play -format GIF -data {
    R0lGODlhFgAWAPZZAEpMSVJUUVRWU1dZVVdaVVhaVVhaVlhbVllbVllaV1lbV1lbWFpbWFl
    cWFteWVxeW11eW11fW19hXF5gXV9iXWBiXmFiXmNkYGRlYmRmYmdoZW9wbnN2cnV3c3x9e5
    KTkJGUkJKUkaChn7K0sLO2srq7ur/AvcDCv8/Rz9jZ2OPk4+Tl4+Xm4+fp5Ofp5ejq5unq5
    +nr5+ns5+rs6Ovs6evt6uzt6uzu6uzu6+zt7O7v7O7w7e/w7e/w7u/x7vDx7vDx7/Hy7/Hy
    8PLz8vP08fP08vT08/T18/X19fX29PX29fb39ff39/f49vf49/j5+Pr6+vr7+vv8+/z8+/z
    8/Pz9/P39/P39/f7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFoALAAAAAAWABYAAAejgFqCg4SFhoeI
    iYqLhAQRAoyHBE4jCwCRjVlSQiALmIIEWS9CWSscBJihL6tEWSgWAYyqqzMzTlIjDosIWTM
    2v78/UUggD4mhPsnKNi8+USocxoa8tbWrLy0tSFknCIfUODvKPq0qGxSIvD4/REZI20YfEo
    q87EhPWVkl0vRZOz9OsqTAoCFSvSk5PFz4tCALEhHoPmlBcCKiRC0WMFzcyNFQIAA7
}

image create photo ::img::pause -format GIF -data {
    R0lGODlhFgAWAPUxAFJUUFRWUlVXU1ZYVFdZVVhaVltdWV5hXGVmYmVmY2VnZGZoZW1va9j
    b1Nve2d7g29/h3OHj3+Lk3+Lk4OPl4OPl4eTl4uTm4uXm4uXm4+Xn4+bn4+fp5ujp5ujq5+
    rr6Ovs6e7u7e/w7vj5+Pn5+Pr6+fr7+vv7+/v8+/z8+/z8/Pz9/P39/P39/f3+/f7+/v///
    v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADIA
    LAAAAAAWABYAAAaNQJlwSCwaj8ikcslsOpGAQWAwKAyn0sHhGFB5VYyh4atacFWRSyksLKg
    ol1PiHJGQ2DL3hVJSnCV2eG4UFClzRgMqFxd3YooXhkeJHh5rQ24ODSqHRV0XEZZtaBCbki
    oecYKPKn5GXSAeKXhjlGWmIiBglyohuWaIZKpfv0VUVQUGQ1VUBcRPz9DR0kRBADs=
}

image create photo ::img::start -format GIF -data {
    R0lGODlhFgAWAPZZAElLR0tNSk1OS01QTE5QTVFTT1JTT1NVUVVXU1ZYVFdZVVhZVVhaVVh
    bV1lcV1lbWFpdWFtdWVtdWlxdWV1eW19hXGJkYGRlYmtsaW1wbHBxbYKGgISHhIiKho6Pi5
    SWk6Cin6Kjn6utqrGyr7/AvsLEwMjJx8rMydLT0NfY1dnd1trc2d7h2+Lj4ePm4ebo5Ofp5
    efo5ujq5ejq5unq5ujq5+nr5+rs6Ovt6ezt6uzu6uzu6+3u6+3v7O7v7O/w7e/w7/Dy7/Lz
    8fP08vT19PX29Pb39fb29vb39vf39vf49vf49/j59/n5+Pn6+fr7+vv7+/v8+/z8+/z8/Pz
    9/P39/P39/f7+/f7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFoALAAAAAAWABYAAAe7gFqCg4SFhoeI
    iYqLjI2OhgqRiAGHAoIINgiGBBuahAcengoqCoUUKVaeWgIaMKmXLKoFIUpDVqUAFChSQFY
    JggoupQIYNk83N6kHI09CNja+wDaRJc0511YdRUrXyK9aCj0KECtWQj3oVi1WQTAwz98KQq
    UOHEpWRUWpH/pFQkLRwBUpBcyElYOaGIg4+CQggycEBVXA0EsVAxIIBTEYCCmEKkEQTniCk
    ADCoQsmC1l48Kily5cwYxoKBAA7
}

image create photo ::img::end -format GIF -data {
    R0lGODlhFgAWAPZyAEZIRUtNSUxOSkxOS01OS01PTFBRT1BSTlJUUFRWUlVXU1ZXU1ZYVFd
    ZVFdZVVdaVVdbVlhZVlhaVllbVllaV1lbV1pbWFlcWF5gXF9gXV5hXWBiXmFiX2JjYGJkYG
    NkYGNkYWRmYmZnY2ZoZGdoZmxtaW5xbG9wbW9wbnBxbnBybnByb3FzcHJzcHN0cXN1cnR1c
    XR1cnZ5dXl6d4GDf4iJhpGSj5CSkJOUkJ6enKOkoa+xrrW3s7q8ur6/vMbIxczNytHS0N/h
    3uDh3+Lj4OTm4+fp5Ofp5ejp5ejq5unr5ujp6Onq6Onr6Ovt6ezt6uzt6+zu6u3u6+3t7e3
    v7O7v7e/v7u/w7vDx7vDy7/Dx8PHy8PHz8PLz8PLz8fPz8/P08fT18/X19PX19fT29PX29f
    b29ff39vj4+Pn6+fr6+vv7+vv7+/v8+/z8+/z8/P39/f7+/v///wAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAHMALAAAAAAWABYAAAfLgHOCg4SFhoeI
    iYqLjI2OhgWHAogQFxCCGDQHhRgyk4UvYQ6CJ3FDJJ9zKXFAEYUnUK6qbllrPwoAc6VkZDi
    bgilXsiVrR0lhaDoIJ2tJUGtEIgFzJUuyLG1V2rVaN21QTklbazwKG0LXbWBb62SmbUlHR1
    tvQQsbRReCMHFaWe5farCIs8UdmRn6OizRN4efuzU5LMx5EWdNnB6y5nSowpDfmh0Z+S358
    IHQRoYjfIwi9MGGxEIbZVkQYShjoQgMMDzaybOnz5+GAgEAOw==
}

image create photo ::img::config -format GIF -data {
    R0lGODlhFgAWAPZaAF9fXnl4dHx8fH19fX9/fyBKhzRlpFhthFtxiWB2j2B3kWN7lU50pEV
    xqVR8rll9q2yFoWWErHWQroaGhoeHh4GKlZGRkZmZmZ6enp+fno2YpYGTqYKXsoSctpeltp
    CmvpGmvqenpq2tra+vr6SttqKuvKexvbW1tbu7u5mtw52wyp22zp240qG0yKS60LvByLDG2
    8HBwc/NyszMzNjY19zc3N/f38DR4tPf6tfi7d/n8OPi4ePj4uTj4efm5Ojn5Ojn5uvp5+rp
    6Orq6uzq6O3r6e3r6vLx7+3y9u7z9vDw8PPy8fPz8vD09/T09Pb29fj39vj49/n49/n59/j
    4+Pn5+Pr6+fr6+vv7+/7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFsALAAAAAAWABYAAAfxgFuCggQEg4eI
    iVsERVY0hoqRhFJLj5EcBpEERFaQiAZZDJlbAgIQgiicnoOgMyMRggJBQgQjPZwBiQY2I6N
    bF0JLRURBxVKrBlYGvoIUMlLQU8aQoMyHGAITAidWxU4ZydaSBFY/Lw1O4pKLKrsPIeuHBf
    MGTg4kWQLxWwUSLiAFDJiI0SPLqkT9cJRYsaCAgCxCiBiMVKBDDg0LWCgosCgLEU4TEKbQs
    eEACwkIOHb8aIWCvBZINiQ4mfIQgSw9AGQ5xQ9EEw8zUaq0mWXJklz8YCCpQHMoIgsE9Akq
    AIHFDRA19w2iCqGhVkTznO4LBAA7
}

image create photo ::img::close -format GIF -data {
    R0lGODlhFgAWAPYAAEhKR09STVBSTVBTT1NUUFRVUVRWUlVWUlZXU1VXVFVYVFZYVFZZVFZ
    ZVVdZVVdaVVdZVlhZVFhaVFhaVVhZVlhaVllaVlhaV36BfYCCfYGDfoKDgIKEgIOEgIWGg4
    aHhIaIhYeJhYeJhoiJhYiKhomKhomLhomKh4mLh4mLiIqLiIuNiIuMiY6Qi46QjY+RjZCRj
    ZCSjZCSjpGSjpGSj5GTj5GTkJKUkJSWkZWWkpWXkpaYk5eZlJialZqbl5qcl52fmqWnoqan
    pKaopKeppaeppqippqiqpqmqp6mrp6qrp6qsqKusqKutqaytqqyuqq2uq62vq66vq66wrK+
    wra+xrbCxrrCyrrGyrrGzr7K0sLO0sbS1sQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAF0ALAAAAAAWABYAAAfNgF2Cg4SFhoeI
    iYqLhBYODoiPFocWHEQckIUOGkQbk4UWQTlLJJ+CDiBLPESZjRpLMUspnxYgVDdLmIcOJE4
    5VCwOFixZO1QrrYaoWTxaMTZcPlkgyZQkWT9TVEBcs4xdFi9LPT9SMaaLDi9KPDxO59/DVD
    tKSj1U3oq8SzdSLy9ZcjjJtwuEkhakLFjohQsEukGbhqxQUkpQBBBOWijZUK2LAyExiFAjZ
    OCDkhtKFhgioEEIBwOGDGAI4gGmIQEOACASkIDAt59AgzIKBAA7
}

image create photo ::img::replot -format GIF -data {
    R0lGODlhFgAWAPcAAC9ZjzFbkTRflzZlojZnozNlpDRlpDVlpDRlpTVlpTRmpDVmpDVmpTZ
    mpDZnpDdnpDZmpTdmpTZnpTdnpTZnpjdnpjdopTdopjdopzxpozhopjlopjhppjlppjhopz
    lppztppjpppzpqpztqpztrpzpqqDtqqDprqDtrqDpqqT1rqDxsqD1sqD1sqT5tqT9vqT5tq
    z5uqz9uq0FuqEBuqUBuqkBvq0RxqkFwrENxrEVyrEZ0rkd0rkx4r0d2sEx4sE16sE56sU56
    tFB7slB8slN+s1V+s1eBtVqDt2qOvGqQv2KNw2WOxG+VwWyWynKXw3OYxXeaxXKfz3Sfz3+
    gx36hyn+iy3+kzIKjy4elyoSkzIWmzZSx05Oy1pG02ZS22pa325q42p252Z+52Zu63KC726
    C82qG+3aK+3aO/3aC+3qbA3afA3ajC3qbC4KrE4arG4q3G4a/H4azG4q7I4q7I46/J47DI4
    rHJ47LJ4rTJ4rDJ5LHK5LPK5LTM5bXM5bbN5bfN5bbN5rfN5rjN5brP5rvQ57vR57vR6L3S
    6MDS5sDU6cHV6sPW6sXV6MjY6cja7Mna7Mrb7M3d7c3d7tHf7tTi8NXi8Njj8dnk8Nrl8dv
    m8tzm8tzn8+Dp8+Dp9OHq9OLr9ePs9eTs9eXt9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKUALAAAAAAWABYAA
    Aj+AEsJHEiwoMGDCBMWRIFiwYIRKEYYXGCQYZQyc+ywGVPlB0WBFwoUHIEE0B0zcwAVOoQI
    0ZwmIxZA4VFQxxiPIyZc+LEFECA3d85UYaSD4IgiI2DY+FhqxIkqfMB4ARQJhtEFQpZIHNm
    jjZ0plKwORGHDSSkUB2Ho+SLFEtqBTA+OYBOJkqVOFRQSLPAQosO4Ff4K1gt306fDmYwojL
    vg05kzmrBcqCgQx1uBFT6RSaQJqcELTHgUECtwASlJcxh1kjy5NAwYOYoSNJ0IU6U3iwphS
    TJEhQ0kWLhshetoxIgsj3z+4cN8zpswpOHKLpUhCZc7iUymeTICwESDAQgMELAxYYIAwujT
    6w0IADs=
}

image create photo ::img::zoom-in -format GIF -data {
    R0lGODlhFgAWAPcAAAAAAFhaV15gXV9gXmRmYmZoZGdpZWhpZmhqZmlrZmhqZ2lqaGpraGt
    ra2psaGtsaWttaWxuaWxtamxuam1vamxua21ua21vbG5wa29wbG9xbHBxbXZ4dXp8eH+AfV
    mArVyFs2GKuWaQv2iTwmmUxW2XxW6ayW6aym+czXKdz3GeznKfznOfznKez3Kfz3Ofz3Sfz
    nagzXWhz3ihzXihzoOFgIKEgYSGgoiKhYmKiY+Qj5GSkZaWlpmZmZubm6GhoaOkoaeopqio
    qKipqK2trb6+voqmxY6oxYKkyoWmyompy5apwZutwp6vxIWr1o+x2Zaz0pe005e42626yrn
    K3L7O3qnE4q7I47bN5sLCwsTExMnJyMrKycvMyszMzNHR0dLS0tXV1dHV2dTW2dbY2tfY2t
    jY2NnZ2Nra2dja29ra2trb29vb29rb3Nzc3Nzd3t7e3t/f38fY68fZ7NHZ4dLZ4NXc5NLg7
    9vi6dHg8Nbi8dbj8drl8tvm8tvm8+Hh4eLi4ufn5+zs7OHq9efu9wAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAIUALAAAAAAWABYAA
    Aj3AAsJHEiwoEGDHDRs0KCBQoeDBzV0aTNGTJkyXShAJKgBzZISMlq4GMHkDYaNhSigMdJC
    DgAAeq64OIJGI8QgTVzoIfSSzx0pLqYAgZgAjQgrfAb1vOPEBRI0CQ5SeHPipVWrLk4AkiA
    VjYurV0UCOmlwKownWOa8HPjiRM2DNbQkIeGi0FqBIZR0qQHRRh0XKOwCGOiijoGNEoRQkQ
    Fi4AcYVbwQiQqRwg48UWi4oBHFTgJAQngchiihg44sb4rkIJByDI8elCHioEAbh8AGFMD06
    DEaZVkwP4Qw8H2QARgtYQKgFBTIoIA3gIYTNxjA5vTr2AUGBAA7
}

image create photo ::img::zoom-out -format GIF -data {
    R0lGODlhFgAWAPcAAAAAAFhaV15gXV9gXmRmYmZoZGdpZWhpZmhqZmlrZmhqZ2lqaGpraGt
    ra2psaGtsaWttaWxuaWxtamxuam1vamxua21ua21vbG5wa29wbG9xbHBxbXZ4dXp8eH+AfV
    mArVyFs2GKuWaQv2iTwmmUxW2XxW6ayW6aym+czXKdz3GeznKfznOfznKez3Kfz3Ofz3Sfz
    nagzXWhz3ihzXihzoOFgIKEgYSGgoiKhYmKiY+Qj5GSkZaWlpmZmZubm6GhoaOkoaeopqio
    qKipqK2trb6+voqmxY6oxYKkyoWmyompy5apwZutwp6vxIWr1o+x2Zaz0pe005e42626yrn
    K3L7O3qnE4q7I47bN5sLCwsTExMnJyMrKycvMyszMzNHR0dLS0tXV1dHV2dTW2dbY2tfY2t
    jY2NnZ2Nra2dja29ra2trb29vb29rb3Nzc3Nzd3t7e3t/f38DT6cfY68fZ7NHZ4dLZ4NXc5
    NLg79vi6dHg8Nbi8dbj8drl8tvm8tvm8+Hh4eLi4ufn5+zs7ODq9OHq9eLr9eTs9eTs9ufu
    9+zy+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAIsALAAAAAAWABYAA
    Aj4ABcJHEiwoEGDHDRswKCBQoeDBy90aTNGDBkyXChAJKihzZISMlzAGMHkDYaNiyigMdKC
    zqFCfK64WNKmwcYgTVzsOaQIUR88UlRMAQIxARoRVvoUOuQTjxMZSNAkOEjhzQkAWLNidXE
    ikE2DGNC40KrVhQtAGg1WhfEECx05BLmySVvwRpYkJFwYDKFkyw2INuq4UGHQhZipEBsMoe
    ICxMAPMLB4IYL4YIQdeaDMgEEjyp0IgITwMLCRgoccWeIUyUEg5RkePSofzEGhNg6BDSh86
    dGDNEqqYH4IYfD7IAMwWsIEQDlIkEEBbwIRL24wAF3q2LMvCggAOw==
}

image create photo ::img::save -format GIF -data {
    R0lGODlhFgAWAPYAAFt6clRye1d4fV58eWZoZGdpZG5wa2B9bnJ1a3V5bHd5dXyBbWyFd3+
    Bfj9shjhniz9qiTtskTxtkT9ylklugkJuiEFsik1yglR3gFF5ilN5ilt+iEJwkk15kUR4nE
    d9okd9o22NjnCKgmiJk0qApkqAqE6HsFCIsVCJslGLtVOMtViSvWKWu1uWwVyXw16Zxl6ax
    2CcymCdy2KfzmOgzmeizmOh0Gej0mul03So03So1HWp1YOFgI6PjZGRkZSWkZSUlJeXl5iY
    mJudmaOkoqWlpampqaysrLCwsLGxsLKysri4uLq6uru7u7y8vIGt0Y+228DAwMHBwcTExMX
    FxMXFxcfHx8bMwMnOw8jIyMnJycvLy8zMy8zMzM3Nzc/Pzc7OzsrQxMzRxdLWzNPYzNDQ0N
    HR0dbW1tfX19ja2Nvb2+Dg4OHh4eHi4eLi4eLj4ePj4+Xl5ebm5ufn5+np6Orr6uvr6+zs7
    O3t7fHx8fPz8/b29gAAAAAAAAAAAAAAACH5BAEAAHwALAAAAAAWABYAAAf+gHyCDB0Phg8V
    GIKLjI0cLE85UDszGhSNmHwZNR4TESAzOzggFpmLAyEbixUgMDAtIBWmfBcijREqKy0zAge
    mAAsGwgYJDyvHKyMBwwaNCHvQ0MbIMQ/Re82LPHd7dt7GKMc2D95pdjyMQ3d2e4cr4SszDx
    EPbHU/iwZccN8xMTcoUuhyAYPcHS4IBBmIw8/OmAgxTKCQaMJFBDF27tzJpoCbNztiHkSU6
    OJBGG977jQQ1ONOHGgasYhEUfIktDh3evAxsCSOnTkvoZERGYHMzThs2CgxQGCMnjhQo8a5
    8gCL1KR5wBAwcK2r167C2IAZS5bsFjBn0W45yyZsFjVBPoQUQaLESRMrZqKc0cu3rQE2WdA
    AkWvkyBIpU/LuXRzFL2AwU6JEjhLFShbFfPf63ZK0s+fPnrM0Y0a6NGk+gQAAOw==
}

image create photo ::img::redo -format GIF -data {
    R0lGODlhFgAWAPUAAEmRBUqTBUuUBUyXBU2ZBU6aBlKSDWesD2i/E2nBE2rCFGvEFG7KFG/
    LFXLKHHTUFnXVFnbYFnjbF3XQHHbTHHfTHXfUHXnWHnnXHnrZHnzdHnrUInzWI33aIn3aJJ
    SjA5egIKe0MozPLYDVK4LYKpHTK4XdMJTWPJrcP4fgLInpK4rjMYvjMoriNIvkNIzkNYzkN
    4zqMI7kOo/lO4/lPJDlPZDlPpHlPpHlP5LlQJPlQpnrRqHsVwAAAAAAAAAAACH5BAEAAD0A
    LAAAAAAWABYAAAaMwJ5wSBQWisjksHBUOo2t5jNZaEWnRCazpblOC6CTtWXCOLzKAoo22mw
    8FQwigS4WcK+KXh9pzOlSSyI4FhUOExMQEgsJgFQuGRsvLzg4NDQJDXVZOB0qJVoFMpqBdj
    gqEFJ3m3Y6PIFVpUgFLjuwsrMhdbizHyu8XykGWGkkwF8Hx08AAsRPzc7RQkEAOw==
}

image create photo ::img::home -format GIF -data {
    R0lGODlhFgAWAPYAAFVXU3tMSmVnY3V1dXV2dnJ1enV4e3d4enV4fHZ5fHZ5fZwICKQAAIQ
    iIdwlJdwmJt4mJuAmJuInJ+U5OYhaWJldW511c+xGRvFMTPBRUfJVVfNbW/JeXvNjY/NkZP
    RmZvRsbPR1dX6Ae3+BfIqIZYmIcICCfYiJfjRlpG52gXF4gUp2rl+Gt3eYwnmZw4SGgYSFg
    oWHgoaIg4eJhIiKhY+QjZeZlJiZlpmalpmal5ubmqONi6efnZ+gnqGgnqKjoaKioqOjoqOj
    o6SkpLGztri5uLq6ubq7vL+/vsCKisShocm1tbi8wbm9wcLCwdfX19zQ0NjY2Nra2tvc293
    d3d7e3d7e3uLe3uDg4OLi4uPj4+Tk5OXl5ebm5ufn5+np6erq6uvr6+zs7O3t7e7u7u/v7/
    Dw8PHx8fLy8vPz8/j4+Pn5+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAGwALAAAAAAWABYAAAfygGyCg4QMDISI
    iYUhIYeKj2wMjIyOkIsTjBKNloOSFxiZmpWPkhkajZISopCSGxyNARSSD6uJkh4ejRUwOkm
    ztZ0hIB+NFjVFTkVKv5vBuQw7PUhV1E9LCyEPzYKSjT5BUmHiXmFeUNjbkSENPj9RXfDwWl
    1aWNijkVMA+/thXQcJBiQ4YAYfGwBlAIgQMWIEvAQuBrRIYAZAIgBiAMDYCEOLFgQsBqwoU
    PFiRhkySJSopwLFABQpSiLCCIAGjRMmsKwhwuQIkyEJL4apaZPGlTVBgghRWsXizDICbNyY
    mqYMmatX1TglxK+r166cworlFAgAOw==
}

image create photo ::img::next -format GIF -data {
    R0lGODlhFgAWAPYAAC9dAzNmAjduAzt0Azt1Azt3Azx2AzhwBDlzBDpzBDt0BDp1BDt1BDt
    2BDx3BT13BT12CT53CUR9D0V8EE6aBk+aB0+cBkqDFkuBGE6DHlKhCFSjCFWlCVeoClipCl
    iqDFyvDFywDF6zDV+0DV2qE16uEl+lHGC2DmG3DmCvFWGtFmW9EFWLIlaKIliJKVqNKWaVO
    WufOmGlIWanJ2SpImirJ2aoKGqtK2qqLWurLWutLm2sMm+tNHCtNnCuNnOvOne2OnWwPXax
    PnaxP2fBEWnDEWnCE3HGH3PMGnShSniyQXiyQnqzRHu0RXy0R321R361SX+0Sn+2SoOtW4e
    7V4m8WI23Z5e/cYTER47DWpXTWZjJZ5jFb53HdZzKcJ3FeJ/GeKPfaaTPeqPLfqTLfqbPf6
    bWdqfecqbMgqjNhanUgazYgq7bg6/cg7DSkLXVl7fVm7nXnLzZoLzZob7ao77ZpL/apL/ap
    cDbpsHcqQAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAHoALAAAAAAWABYAAAfGgHqCg4SFhoeI
    iYgLio0JLo2JCHcwBpGGCHlwSQqNCwmgoAp3VG5TlokJeKurc3NNTmhWEKlxUbdOTkpBQTx
    cXBOICXFKxbxBPjs4NlRgwYYLbz42MjIzOTk3MzQmSmMtjIQLaRYUFBYbHB8lKiokQF0s4Y
    MJY+boHiAjKCgjWF4XHBiqZ05DhxAoVhAxomXLs4FkIpZRw6aNESRhskRINQCBRwQK2Bw5E
    2XepQRszPQQcIlQAjEuArR0mQHATEIsb+rcSSgQADs=
}

image create photo ::img::previous -format GIF -data {
    R0lGODlhFgAWAPcAAC1ZAzNlAjduAzpyAzp0Azt1Azt3AzpzBDtzBDp0BDt1BDx0BDx0Bjx
    1Bzx2Bzx1CD11CDx2CD13CD52CT92Cj93C0F7C0F9CUJ5DUR7D06aBlOdDVSeD0mCFUmAFk
    yBG1WeEFKgB1enCVenC1elDFekD1mrClqqC1qsC1uuC1ywDF+zDV+0DVqhF16jHGC2DmK4D
    mO6D2O7D2S7D2GxFGm5HFSIIFSKIFSIJVeLJWKSNGaYNmGlIWOmI2SnJWevI2aoKGmrK2uv
    KWqqLWuvLGqwKG2sMW2sMm+tNHCtNnKvOXOvOnKyNnWwPXWxPnaxPnaxP2fBEWjBEWrFEmv
    GEnGeRXWmRXiyQXiyQnqzRH21R361SX+2Sn6qVYGwU4S5Uoa7U4e6VYu2Y4y5YZS8bJTGY5
    bDa5XAbJ3Ob5rEcZrDdJvEdKPOeaTLf6HQdajUfqrXf6rThKzYga3bgK3Zgq7dgK/dg6/Rj
    rTVlbXUmLjWmrnXnbrWn7vYn7LhhLTlhbXmhrzZoLzZob7ao7/apL/apcDbpgAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAIcALAAAAAAWABYAA
    AjfAA8JHEiwoMGDCBMqPJRgYUIcCxwaPKBjTwWJBBNUyVPoIsZDC7rc+SLIwoEEB1I2RChB
    TBssV/YIKlTIkKFCGBBmIGPGSJIlUK5k0bJlSyAJBz2sCcMDyBAjSIAGxaKHQsEEN9ZAaeG
    iaRAhRX78EMIED1KCBm6kQbKBA4cSIkygUKECxYk4ZzN2OKNFQwgRKVjAmCEDxoo3eQtiGA
    OmROAZUahQiRJDzoOECbyUocGijh9Af/zYoZPY4AAraGrMuXASZcqFAna4mVNaYoAcbGpLB
    PDhwEeDAn4LHy4wIAA7}

image create photo ::img::help -format GIF -data {
    R0lGODlhFgAWAPfmAA8jQRMsURUyWhk4Zh5BcyBFeiFJgiJJgiBJhSFKhiBKhyFLhyFLiCJ
    LiCJMiCNNiSlRiylRjClSjCxTjSxVji5Wjy1WkC9XkTNblDVclDRclTRdlTdelTZeljhglz
    hgmDlhmTpimTtjmjxkmkBnnUFpnkJpn0Rrn0Zrn0psnkxunkxun0RroEVsoUhvo0lvo01uo
    E5xoU5xoktxpUtypUxxpExypU10p050p1BxoFByo1JzolB0pFV1pFV2pVl4pVh4plh5plB2
    qFF3qVJ4qlR6rFV7rFd8rVd9rlh8q1x8qFh9rlp/r1p/sFqAsF2Csl6Dsl6Ds1+Ds2KBrWK
    Fs2GFtGGGtGKGtWKHtWOHtmaIs2OItmSItmSJt2yIsGeLuWiMuWuNuGqOu2uOu2uPu2uPvH
    aRtniTt3CTv3eWvnyWu32Wu3uXvXKVwHOWwXOXwXeZw3yawnibxXmcxXydxX6dxHyfyH2fy
    H2gyH6hyX+hyYKcv4edvoeevoCbwIOix4yiwYGiyYCiyoCjyoOkyoOky4Wnzoanzoaozoao
    z4mqz5CnxZKpx5SoxZesyZaty5mxz5ywzJ2xzIip0Iiq0Imq0I2v1I6v1JGy1pKz15+205i
    11p652J+72pu73Z+83KCyzKGzzaO0zaS1zqa40Ka40aO616a61KS716i50Km50ai60qm60q
    m81K+/1a/A1rPB1rTC17LC2LLF27XE2LTE2bXE2bXF2rXF27bG27fH3LjH27rH2rrI273L3
    b7L3cHO38HQ4sLR48HR5MjT48nU5MjW58nX58vX587Z6NPe69ri7N/l7uDm7uDm7+Ho8eHp
    8ePo8ODo8uXq8ebr8ebr8ufs8ufs8+ft9ejt8+nt8+nu9Onu9env9erv9env9uzw9e3x9u7
    y9/Dz9/P1+Pj5+////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAOcALAAAAAAWABYAA
    Aj+AM8JHEiwoMGD5xQoVMCAgUKEBBXC4AOrmTNafVQogJgQAqhpo87EyLEm1TZQEjYaVJCC
    WSoOFjBw6CBCBAtazWCoHKhAQjMvFqbYmlaO3LJFJ0zsaSahoAJRqWKmMke1aqsZM3qdesA
    zxzQOHESc2sVGyymq3orwSOItB09AoDCIMDFDSJEmYaiOg9KkiC1GKhX0MuNhRN0jULgkoy
    rsSxYnj35xTWgtxogWN4pA6YKMqjM4aMJ8YTMt8DYehok4yTKLqrRCduS4GSNn2mQFv9SYs
    KH5izSqnCYZKiQHjSlgtxudOnHjSJYwcApNuoTpkiE7b4A5Cvxj2ozmWcpyKMO27ZMnTJT0
    zAnnI+KrV+DLbANeHZEdZLImD6ywLY4RKmFgQ9UmkyCiByrbVLDSD9bYQsUWZbgxhx56EII
    MOO0dxEAFtmyjCyR1/GFKMOHYQgFHCSkRCTHhhINMJD8YgKJAAQxQgAIGECAAADP2SFBAAD
    s=
    }

image create photo ::img::stop -format GIF -data {
    R0lGODlhFgAWAPf6AFYAAF4AAG4AAHQAAIIAAIMAAIQAAIYAAIgAAIkAAIkEBIgFBYkHB4w
    HB4kICIoJCZkNDZsPD5wQEJ0SEp8UFKIPD6gPD7UAALMGBrUGBrkAALoAALsAAL0AAL4AAL
    8AALsEBL0EBL8EBKwREb8WFrocHLodHakqKqkrK6srK6wqKqwuLrcoKLspKb4uLq8yMq81N
    bY1Nb8wMLA5ObA7O7E+PsAAAMEAAMIAAMMAAMUAAMYAAMAFBcIFBcMFBcgAAMsAAMsLC88Q
    EMsWFsIdHcMfH9EdHdMeHtUfH8UgIMYgIMgkJMgnJ8cpKcosLNggINkqKsszM80xMcw0NM4
    1Nc02Ns83N8s7O884OMg8PNA4ONE5OdE6OtE7O9I7O9I8PNI9PdE/P9Q8PNc/P9g9Pdg+Pt
    g/P7tERL1ERL1HR8FDQ8VCQsVDQ8BFRcFHR8JGRsRERMxFRc1GRsVJScRLS8xISM1JSc5MT
    M1OTsxPT9lBQdlCQtlDQ9lERNlFRdpGRtpHR9RPT9pISNpJSdpKSttLS9pMTNtMTNtNTdtP
    T91PT8BRUcFTU8BUVMFVVcJVVcBXV8JXV8VWVsxRUc5SUsNcXMVdXcRfX8VfX8lZWctbW85
    fX9BVVdpQUNtTU9xQUNxRUdxSUt9SUuRFRelLS+pNTeRTU+FVVeFXV+RUVOpSUulWVutWVu
    ZYWOdbW+laWuhdXehfX+1dXcViYsVjY8ZiYsZjY8dkZMZnZ8hmZsx2dsx7e8t8fONhYeViY
    uNkZOpiYu1mZu9mZuRoaOVqau9paexqau1sbO9sbOxvb+pycu92dvF7e8+IiNWVlfKBgfKI
    iPSJifWMjPWNjfWOjvSPj/WPj/aQkPSTk/aSkvSUlPSVlfaWlveYmPeZmfeamvebm9miouS
    8vN3T097U1N/V1eXV1eXW1ubW1uLY2ObY2ObZ2ejf3+bi4uri4uvj4+7j4+nk5Ovr6+3s7O
    7u7vHj4/Dk5PXm5vbq6vDu7gAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAPoALAAAAAAWABYAA
    Aj+APUJHEiwoMGDCBIqTJAAQYKDBBHU2AbOm7dt3LJFU4EAor4DNLYRU6SIEKE/fVA944hw
    hkhPnhCZRKnnFDMUHSPC2DbMUyZOMQkJkjPHjKllOAcieIGtV6dMzWZRkmmn0a43YhQpS6p
    PQbVeiDqlKTfuEp5AjdS5S5PFC6FiDwQ2yCYIEaJJs8aZqwRJ3btLa75gsQJXbrU/JgnhmV
    WuXbx4s9aIGRylsL4G1fT06WOSTjN69Jyp+eLFipUpwRQY3rzZTpp1oN/N2iTFSZMmxxYYN
    qNHT5xF6NzpulWvHhoXHzhwKHVAbjQyer40QscO15oMufDdi3GBA4lXzbt+CoMiJAidcI1M
    6LBRIpc4NMqJKAuvr4IsJD+GvJGhY70NDJJkwQERprSQk0AUsHJEf/7Z8EFyHChxCgsHDkS
    BKkj0Z8OGECqRyggVEgQBKUfwwIMIKHKwxCkWhEiQABCMwgowwMDiiiu9VDCARwIBcMABBQ
    QZ5AEB8GjkQQEBADs=}

image create photo ::img::track -format GIF -data {
    R0lGODlhFgAWAPYAACBKhyBLiCFLiCFLiSNNiSJMiiRNiSVPiydRjShSjilUkSxXkS9XkTJ
    clzFdmThfmDZhmzhjnDRlpDVlpDVmpDZmpTZnpT1noT5noDdopjhopjpppzpqpztqpzxqpj
    xrpztrqD5sqD5tqT9uqUNso0BqpEFspUdvpEhuo0FuqEBuqUJvqUFvqklxp0NwqENxq0Nyq
    0Rxq0Vxq0ZxqkVyq0RyrUdzrElzqUtzqEp1rUl2rk53rE15r1J6rkh3sEt4sU15sU96sFF7
    sVZ9sFJ+tFN/tVuCtFuCtVuDtVmDtmOLvGGMvWmQwGuSwWiRwmuTwm+XxXGWw3OaxnKfz3O
    fz3ieynOgz3Sgz3igzYCo04So0IWs1Yas1Yet1Yet1oiu1o+y2JCz2ZW325e425y42Z+72p
    q63Jy73aG/36LA36PA36XB4LDI4rHJ47HK5LjO5gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAHAALAAAAAAWABYAAAfcgHCCg4SFExKF
    iYpwEzxNGYuREzBsb0oTkYoZZGNfZB2ZiTpuVlRsIpEBAYQTUWNTU2hJiwELKKuCE01isGp
    AiwZGRie4cERnsGugiQAQQhNGDIMgaFRfWpDMOCoSNje4NmZUZj+YzD0dEho9BIxFYVtV2c
    w7IRMdO6swUltgqLQXbExQUYLAhCVivEAxtygBjwk2IgTQhcXLk2W0SqgQcSGAhB9bsMyLh
    EBHBxMBCmQAkYFhKggqbjQoFkoQAAQ2VKigWRMOARUeVADoSQiAAg8OePYMAEAp0Z6BAAA7
}

image create photo ::img::plot -format GIF -data {
R0lGODlhFgAWAMIHAAAAAAAAMgAAfwAPAAAZAAAnAAE8AP///yH5BAEKAAcALAAAAAAWABYAAANb
eLrcriDKSSl8eAEVct4H6DkCVI6McQLCORpGeLVvLN80k8OaMiy5ltDWOxB0woWqYRMpXIdYTlG4
PHhPF8ipgBGzVpAXSwqPRysr6pC+rYXbtS4uL1bu9zomAQA7
}

# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Preamble.tcl,v 1.4 2004-10-13 12:08:58 vvzhy Exp $
#
###### preamble.tcl ######

# get the number of clicks per second on this machine..
after idle {after 1000 "set maxima_priv(clicks_per_second) \[expr 1.0 *( \[clock clicks\] - [clock clicks])\]" }

catch {
    # the following will be defined only in the plugin
    global embed_args
    array set embed_args [getattr browserArgs]
    proc wm { args } {}
}

# from Send-some.tcl
#mike - I hope these can be eliminated or encapsulated
global port magic interrupt_signal _waiting _debugSend
if { $argc == 0 } {
    set port 4444
    set magic "billyboy"
}
set interrupt_signal "<<interrupt fayve>>"

set _waiting 0

set _debugSend 0

package require msgcat
namespace import msgcat::*

# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Readdata.tcl,v 1.2 2002-09-07 05:21:42 mikeclarkson Exp $
#
###### Readdata.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################



#
#-----------------------------------------------------------------
#
# readDataTilEof --  read data from CHANNEL appending to VAR
# allowing no more than TIMEOUT milliseconds between reads.
#
#  Results:  1 on success, and -1 if it fails or times out.
#
#  Side Effects: CHANNEL will be closed and the global variable VAR will
#  be set..
#
#----------------------------------------------------------------
#
proc readDataTilEof { channel var timeout } {
    global readDataDone_ _readDataData
    global readDataDone_
    upvar 1 $var variable
    set _readDataData ""
    set readDataDone_ 0
    set $var ""

    set after_id [after $timeout "set readDataDone_ -1"]
    fconfigure $channel -blocking 0
    fileevent $channel readable \
	    [list readDataTilEof1 $channel _readDataData $timeout $after_id]

    myVwait readDataDone_
    after cancel $after_id
    catch { close $channel}
    set res $readDataDone_
    if {$res > 0 } { append variable $_readDataData }
    return $res
}

proc readDataTilEof1 { channel var timeout after_id} {
    global readDataDone_  $var

    set new  [read $channel]
    append $var $new

    if { [eof $channel] } {
	set readDataDone_ 1
	close $channel
    } else {
	after cancel $after_id
        after $timeout "set readDataDone_ -1"
    }
}


## endsource Readdata.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Getdata1.tcl,v 1.7 2004-10-13 12:08:57 vvzhy Exp $
#
###### getdata1.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################





#
#-----------------------------------------------------------------
#
# readAllData --  read data from CHANNEL.
#  Options: -tovar variable    (store in this global variable)
#           -mimeheader store in alist the mime values
#                   and oset $sock contentlength if
#           -tochannel  (store in channel)
#           -timeout   (for non action)
#           -translation  (for the sock)
#           -chunksize   size to do for each read between updating %
#           -command    a call back run on each chunk
# If -command is not specified, wait and return the result code.
# Value of -1 means a timeout, and value of >1 means success.
# If  command is specified, call command each time data is read,
# with 1 argument appended, the result code.
# allowing no more than TIMEOUT millisconds between reads.
#  We set up local variables for the $CHANNEL
#        result
#        bytesread  (after the header if one specified)
#        mimeheader (extracted)
#        length     (0 if not provied by mime header)
# COMMAND can access
# to examine the data read so far.
#
#  Results:  1 on success, and -1 if it fails or times out.
#
#  Side Effects: CHANNEL will be closed and the global variable VAR will
#  be set..
#
#----------------------------------------------------------------
#


proc readAllData { sock args } {
    global readAllData [oarray $sock] maxima_priv

    array set [oarray $sock] {
	timeout 5000
	command ""
	tochannel ""
	translation binary
	chunksize 2024
	mimeheader ""
	tovar ""
	result ""
	done 0
	usecache 0
	percent 0
	bytesread 0
	headervalue ""
	contentlength -1
    }
    oset $sock begin [clock clicks]
    foreach { key val } $args {
	#puts "	oset $sock [string range $key 1 end] $val"
	oset $sock [string range $key 1 end] $val
	
    }
    #puts "locals:[array get [oarray $sock]]"
    # puts "args=$args"
    if { "[oget $sock translation]" != "" } {
	fconfigure $sock -translation [oget $sock translation]
    }
    fconfigure $sock -blocking 0

    catch { 
	$maxima_priv(cStatusWindow).scale \
	    config -variable [oloc $sock percent] 
    }
    lappend [oloc $sock after] [after [oget $sock timeout] "oset $sock done -1"]
    if { "[oget $sock mimeheader]" != "" } {
	fileevent  $sock readable "readMimeHeader $sock"
    } else {
	fileevent  $sock readable "readAllData1 $sock"
    }

    if { "[oget $sock command]" == "" } {
	oset $sock docommand 0
	return [wrWaitRead $sock]
    } else {
	oset $sock docommand 1
	# the command will do things and maybe caller will vwait..
	return ""
    }
}



#
#-----------------------------------------------------------------
#
# readMimeHeader --  read from SOCK until end of mime header.
#  this is done as a fileevent.  Store result in $sock local HEADERVALUE.
#
#  Results: none
#
#  Side Effects:  data read, and the mime header decoded and stored.
#
#----------------------------------------------------------------
#
proc readMimeHeader { sock } {
    global [oarray $sock]
    set result ""
    set ans ""
    while { 1 } {
	set n [gets $sock line]
	if { $n < 0 } {
	    if { [eof $sock] } {
		oset $sock done -1
		close $sock
		return
	    }
	    append [oloc $sock result] $result\n
	    break
	}
	if { $n <=1 && ($n==0 || "$line" == "\r") }  {
	    # we are done the header
	
	    append [oloc $sock result] $result\n
	    regsub -all "\r"  [oget $sock result] "" result
	    set lis [split $result \n]
	    foreach v $lis {
		if { [regexp "^(\[^:]*):\[ \t]*(.*)\$" $v junk key val] } {
		    lappend ans  [string tolower $key] $val
		}
	    }
	    oset $sock headervalue $ans
	    oset $sock contentlength [assoc content-length $ans -1]
	    if { [oget $sock usecache] } {
		set result [tryCache [oget $sock cachename] $ans]
		if { "$result" != "" } {
		    oset $sock bytesread [string length $result]
		    wrFinishRead $sock
		    return
		}
	    }
	    oset $sock percent 0
	    oset $sock bytesread 0
	    oset $sock result ""
	    #puts "mimeheader = <$ans>"
	    #puts "switching to readAllData1 $sock, [eof $sock]"
	    fileevent $sock readable "readAllData1 $sock"
	    #puts "doing     readAllData1 $sock"
	    return
	}
	append result "$line\n"
    }
}


proc readAllData1 { sock } {
    #puts "readAllData1 $sock" ; flush stdout
    global maxima_priv [oarray $sock]

    makeLocal $sock timeout tovar tochannel docommand chunksize after contentlength begin

    upvar #0 [oloc $sock bytesread] bytesread
    #puts "readAllData1 $sock, bytes=$bytesread" ; flush stdout
    if { [catch {
	foreach v $after {after cancel $v}
	while { 1 } {
	    if { "$tochannel" != "" } {
		if { [eof $sock] } {
		    wrFinishRead $sock
		    return finished
		} else {
		    set amt [expr { $contentlength >= 0 ? ($chunksize < $contentlength - $bytesread ? $chunksize : ($contentlength -$bytesread)) : $chunksize } ]
		    set chunksize $amt
		    set n [fcopy $sock $tochannel -size $chunksize]
		}
	    } else {
		set res [read $sock $chunksize]
		set n [string length $res]
		append [oloc $sock result] $res
	    }
	    incr bytesread $n
	    if { $n == 0 } {
		if { [eof $sock] } {
		    wrFinishRead $sock
		    return finished
		}
	    }
	    set maxima_priv(load_rate) "[expr {round ($bytesread * ($maxima_priv(clicks_per_second)*1.0 / ([clock clicks] - $begin)))}] bytes/sec"

	    if { $contentlength > 0 } {
		oset $sock percent \
		    [expr {$bytesread * 100.0 / $contentlength }]
		
	    }

	    if { $docommand } {
		catch { uplevel "#0"  [oget $sock command] }
	    }
	    # puts "percent=[oget $sock percent],bytes=[oget $sock bytesread]"

	    if { $contentlength >= 0 &&  $bytesread >= $contentlength } {
		wrFinishRead $sock
		return finished
	    }
	    if { $n <= $chunksize } { break    }
	
	}
    } errmsg   ] } {
	if { "$errmsg" == "finished" } {
	    return
	} else {
	    global errorInfo ; error [concat [mc "error:"] "$errmsg , $errorInfo"]
	}
    }
    lappend [oloc $sock after] \
	[after $timeout "oset $sock done -1"]
}




#
#-----------------------------------------------------------------
#
# wrFinishRead --  run at the EOF.  It will run the COMMAND one last
# time and look after setting the global variables with the result,
# closing the channel(s).
#
#  Results:  the $sock variable 'done', 1 for success, -1 for failure.
#
#  Side Effects: many!
#
#----------------------------------------------------------------
#
proc wrFinishRead { sock } {
    makeLocal $sock mimeheader contentlength tovar tochannel headervalue \
	bytesread docommand
    #puts "entering wrFinishRead" ; flush stdout

    if { "$mimeheader" != "" } {
	uplevel "#0" set $mimeheader \[oget $sock headervalue\]
    }
    if { "$tovar" != "" } {
	uplevel "#0" set $tovar \[oget $sock result\]
    } else {
	catch { close $tochannel }
    }
    if { $contentlength < 0 || $bytesread >= $contentlength } {
	oset $sock done 1
    } else {
	oset $sock done -1
    }
    catch { close $sock }	
    if { $docommand } {
	catch { uplevel "#0"  [oget $sock command]  }
    }
    set res [oget $sock done]
    #puts "wrFinishRead, tovar=$tovar,tochannel=$tochannel,res=$res,bytesread=$bytesread"	
    clearLocal $sock
    oset $sock done $res

    return $res
}

proc wrWaitRead { sock } {
    #puts "entering wrWaitRead"
    global [oarray $sock]
    if { [oget $sock done] == 0 } {
	myVwait [oloc $sock done]
    }
    #vwait [oloc $sock done]
    set res [oget $sock done]
    return $res
}

proc testit { addr usecommand args } {
    if { [regexp {//([^/]+)(/.*)$} $addr junk server path] } {
	set sock [socket $server 80]
	#puts "server=$server"
	# fconfigure $sock -translation binary
	#puts "GET $path HTTP/1.0\n"
	puts $sock "GET $path HTTP/1.0\nMIME-Version: 1.0\nAccept: text/html\n\nhi there" ;
	flush $sock
	proc _joe { sock } {
	    makeLocal $sock percent contentlength bytesread
	    puts "percent=$percent,contentlength=$contentlength,bytesread=$bytesread"
	}
	if { $usecommand } {	
	    eval readAllData $sock -command  [list "_joe $sock"] $args
	    wrWaitRead $sock
	} else {
	    eval readAllData $sock $args
	}
	catch { close $sock }
    }
}



#
#-----------------------------------------------------------------
#
# tryGetCache --  look up PATH (eg http://www.ma.utexas.edu:80/...)
# in the cache, and if you find success and a matching ETAG,
# then return the data in the file
#
#  Results:  The cached data in FILE or ""
#
#  Side Effects: Will remove the file if the current etag differs.
#
#----------------------------------------------------------------
#
proc tryGetCache { path alist } {
    global ws_Cache maxima_priv
    set tem [ws_Cache($path)]
    if { "$tem" != "" } {
	set filename [file join $maxima_priv(cachedir) [lindex $tem 1]]
	set etag [assoc etag $alist]
	if { "$etag" != "" } {
	    if {  "[lindex $tem 0]" == "$etag" }  {
		if { ! [catch {
		    set fi [open $filename  r]
		}] } {
		    fconfigure $fi -translation binary
		    set result [read $fi]
		    close $fi
		    return $result
		}
	    } else {
		# cache out of date.
		if { [file exists $filename] } {
		    file delete $filename
		    return ""
		}
	    }

	}
    }
}


proc saveInCache { path etag  result} {
    global ws_Cache maxima_priv
    set cachedir $maxima_priv(cachedir)
    # todo add a catch
    set type [lindex [split [file tail $path] .] 1]
    set count 0
    while [ file exists [set tem [file join $cachedir $count$etag.$type]]] {
	incr count
    }
    set fi [open $tem w]
    #puts "writing $tem"
    fconfigure $fi -translation binary
    puts -nonewline $fi $result
    close $fi
    set ws_Cache($path) [list $etag [file tail $tem]]
    set fi [open [cacheName index.dat] a]
    puts $fi "[list [list $path]] {$ws_Cache($path)}"
    close $fi
}

proc cleanCache { } {
    global ws_Cache
    catch {
	foreach v [glob [cacheName *]] {
	    catch { file delete $v }
	}
    }
    catch { unset ws_Cache }
}
proc cacheName { name } {
    global maxima_priv
    return [ file join $maxima_priv(cachedir) $name]
}



#
#-----------------------------------------------------------------
#
# readAndSyncCache --  read the cache index.dat
# and remove duplicates removing files, and if necessary save
# the file out.   Normally this would be done at start up.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc readAndSyncCache { } {
    global maxima_priv ws_Cache
    if { [catch {  set fi [open [cacheName index.dat] r] } ] } {
	return
    }
    set all [read $fi]
    #puts "all=$all"
    set lis [split $all \n]
    #puts "lis=$lis"
    set doWrite 0
    foreach v $lis {
	set key [lindex $v 0]
	set val [lindex $v 1]
	if { "$v" == ""} { continue}
	if { [info exists  ws_Cache($key)] } {
	    set doWrite 1
	    catch {file delete [cacheName [lindex $ws_Cache($key) 1] ] }
	}
	if { "$val" != "badvalue" } {
	    set ws_Cache($key) $val
	}
    }
    close $fi
    if {  $doWrite}  {
	set fi [open [cacheName index.dat] w]
	puts [concat [mc "writing"] "[cacheName index.dat]"]
	foreach { key val } [array get ws_Cache *]  {
	    puts  $fi "[list [list $key]] {$val}"
	}
	close $fi
    }
}


## endsource getdata1.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Macros.tcl,v 1.6 2006-06-29 13:09:58 villate Exp $
#
###### Macros.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################
#
#-----------------------------------------------------------------------
# desetq lis1 lis2 -- sets the values for several variables
#
# Result: each variable name in LIS1 is defined with a value in LIS2
#-----------------------------------------------------------------------
#
proc desetq {lis1 lis2} {
    set i 0
    foreach v $lis1 {
	uplevel 1 set $v [list [lindex $lis2 $i]]
	incr i
    }
}
######  Options parsing functions ######################################
#
#-----------------------------------------------------------------------
# assoc key lis args -- find value of option KEY in options list LIS
#
# Result: value of option or first element of list ARGS
#-----------------------------------------------------------------------
#
proc assoc { key lis args } {
    foreach { k val } $lis { if { "$k" == "$key" } { return $val} }
    return [lindex $args 0]
}
#
#-----------------------------------------------------------------------
# delassoc key lis -- remove option KEY from options list LIS
#
# Result: an options list without option KEY
#-----------------------------------------------------------------------
#
proc delassoc { key lis } {
    set new {}
    foreach { k val } $lis {
	if { "$k" != "$key" } { lappend new $k $val}
    }
    return $new
}
#
#-----------------------------------------------------------------------
# putassoc key lis value -- set VALUE for option KEY in options list LIS
#
# Result: an option list with KEY set to VALUE
#-----------------------------------------------------------------------
#
proc putassoc {key lis value } {
    set done 0
    foreach { k val } $lis {
	if { "$k" == "$key" } {
	    set done 1
	    set val $value
	}
	lappend new $k $val
    }
    if { !$done } { lappend new $key $value }
    return $new
}
######  End options parsing functions #################################
#
#-----------------------------------------------------------------------
# intersect lis1 lis2 -- find common elements of two lists
#
# Result: a list of values found in LIS1 and LIS2
#-----------------------------------------------------------------------
#
proc intersect { lis1 lis2 } {
    set new ""
    foreach v $lis1 { set there($v) 1 }
    foreach v $lis2 { if { [info exists there($v)] } { lappend new $v }}
    return $new
}
#
#-----------------------------------------------------------------------
# ldelete item lis --  remove all copies of ITEM from LIS
#
# Result: new list without ITEM
#-----------------------------------------------------------------------
#
proc ldelete { item list } {
    while { [set ind [lsearch $list $item]] >= 0  } {
	set list [concat [lrange $list 0 [expr {$ind -1}]] [lrange $list [expr {$ind +1}] end]]
    }
    return $list
}
#
#-----------------------------------------------------------------------
# apply f a1 .. am [list u1 .. un] -- apply a function with arguments
#        A1 .. Am and all the elements U1 .. Un in a list
#
# Result: command f is evaluated, in the scope from where APPLY was issued
#-----------------------------------------------------------------------
#
proc apply {f args } {
    set lis1 [lrange $args 0 [expr {[llength $args] -2}]]
    foreach v [lindex $args end] { lappend lis1 $v}
    set lis1 [linsert $lis1  0 $f]
    uplevel 1 $lis1
}
## endsource macros.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Proxy.tcl,v 1.4 2004-10-13 12:08:58 vvzhy Exp $
#
###### Proxy.tcl ######



#
#-----------------------------------------------------------------
#
# openSocketAndSend --  open a Socket to HOST on PORT and then
# send the message MSG to it.   If verify is non 0, then read
# up through the end of the http header and verify this is not
# an error.
#
#  Results:  returns a socket which you can read from using ordinary
#  read and write, but to which you should write only using s
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc openSocketAndSend { host port msg { verify 0}} {
    global maxima_priv  pdata
    dtrace
    if { [info exists maxima_priv(proxy,http)] } {
	global pdata
	set magic "billy-[clock clicks]"
	debugsend "sendViaProxy $msg $host $port $magic"
	
	set sock [sendViaProxy $msg $host $port $magic]

	if { $verify } {
	    fconfigure $sock -blocking  1 -translation {crlf binary}
	    gets $sock tem
	    if { [regexp "503" $tem] } {
		error [concat [mc "Could not connect"] "$host $port"]
	    }
	    while { 1 } {
		gets $sock tem
		if  { [string length $tem] == 0 } { break }
	    }
	}
	set pdata($sock,proxyto) [list $host $port $magic]
	fconfigure $sock -blocking  0
	return $sock
	
	
    } else {
	set sock [socket $host $port]
	if {[info exists pdata($sock,proxyto)]} {
	    unset pdata($sock,proxyto)
	}
	fconfigure $sock -blocking  0
	puts -nonewline $sock $msg
	flush $sock
	return $sock
    }
}





#
#-----------------------------------------------------------------
#
# proxyPuts --  send the MESSAGE to SOCK, not appending a newline.
#
#  Results: none
#
#  Side Effects: message sent
#
#----------------------------------------------------------------
#
proc proxyPuts { sock  message } {
    global pdata
    debugsend "proxyPuts $sock  $message useproxy=[info exists pdata($sock,proxyto)]"
    if { [info exists pdata($sock,proxyto)] } {
	desetq "host port magic" $pdata($sock,proxyto)
	close [sendViaProxy $message $host $port $magic]
    } else {
	puts -nonewline $sock $message
	flush $sock
    }
}


#
#-----------------------------------------------------------------
#
# sendViaProxy --  send a message.
#  this is a private function.
#
#  Results: a socket one can read the answer from.
#   Caller is responsible for closing the socket.
#
#  Side Effects: socket opened and message sent as the body
#  of a post.  The magic is put in the http header request as the
#  filename	
#
#----------------------------------------------------------------
#
proc sendViaProxy { message host port magic  } {
    global maxima_priv
    dtrace
    set ss [eval socket $maxima_priv(proxy,http)]
    fconfigure $ss -blocking 0
    fconfigure $ss -translation {crlf binary}
    set request [getURLrequest http://$host:$port/$magic $host $port "" $message]
    debugsend "<$ss  request=$request>"
    puts $ss $request
    flush $ss
    return $ss
}

## endsource proxy.tcl

# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Send-some.tcl,v 1.9 2011-03-14 20:01:13 villate Exp $
#
###### send-some.tcl ######

# Usage:
# catch {close $socket}
# source send-some.tcl ; openConnection $tohost $port $magic $program
# one linux14 do
# run-one.tcl octave  4448 billy1
# then from any machine do:
# can also open maxima at same time
# source send-some.tcl ; openConnection linux14 4448 billy1 octave
# then
# sendOneWait octave 2+3
# 5
# If you specified -debug when starting the server then you can
#    evaluate tcl commands in the process controlling 'program'
#   eg:  sendCommand octave "list 1 1"



#
#-----------------------------------------------------------------
#
# myVwait --  this is a replacement for vwait which is missing from
# the plugin tcl.   It is 'supposed' to be the same but in fact if it
# is a fileevent handler that is supposed to do the setting, then the
# fileevent handler might indeed get called continuously because the
# file becomes readable, and myVwait which was checking a variable that
# the handler set,  never gets a chance to return, since the handler
# is called again and again.   So Remove the handler when it is invoked.
# Note this uses tracing of the variable or array, and may interfere
# with other tracing.
#  Results:
#
#  Side Effects: waits till the variable is set if it was unset, or
# until its value is different.
#
#----------------------------------------------------------------
#
proc myVwait { var  } {
    global _waiting maxima_priv
    set tem [split $var "(" ]
    set variable [lindex $tem 0]
    global $variable
    lappend maxima_priv(myVwait) $variable


    set index ""
    if { [llength $tem ] > 1 } {
	set index [lindex [split [lindex $tem 1] ")" ] 0]
    }

    set action  "_myaction [list $index]"
    trace variable $variable w $action
    set _waiting 1

    while { [set _waiting] } {
        #puts "still waiting _waiting=$_waiting"
	update
    }
    set maxima_priv(myVwait) [ ldelete $variable $maxima_priv(myVwait)]
    trace vdelete $variable w $action
}

proc _myaction { ind name1 name2 op } {
    global _waiting
    # puts "action $ind $name1 $name2 $op"
    if { "$ind" == "$name2" } {
	
	global $name1
	set _waiting 0

    }

}

# proc myVwait { x args } {uplevel "#0"  vwait $x }
if { "[info commands vwait]" == "vwait"  } {
    proc myVwait { x  } {
        global maxima_priv
# Fix for Tcl 8.5: linking unreachable global variables used to be ignored
# in Tcl 8.4 but in 8.5 it raises an errror. The catch command should
# restore the Tcl 8.4 behavior. (villate, 20080513)
	catch {global $x}
	lappend maxima_priv(myVwait) $x
	vwait $x
	set maxima_priv(myVwait) [ ldelete $x $maxima_priv(myVwait)]
    }
}

proc omDoInterrupt { win } {
    foreach v [ $win tag names] {
	if { [regexp "com:pdata\\((\[a-z_A-Z]*)," $v junk program] } {
	    set var [string range $v 4 end]
	    # puts "interrupt program=$program,$var"
	    after 10 uplevel "#0" set $var <interrupted>
	    catch { sendInterrupt $program }
	}
    }
}


proc omDoAbort { win } {
    foreach v [ $win tag names] {
	set var [string range $v 4 end]
	if { [regexp "com:pdata\\((\[a-z_A-Z]*)," $v junk program] } {
	    set prog [programName $program]
	    if { "[info command abort_$prog]" != "" } {
		abort_$prog $program
		after 200 uplevel "#0" set $var <aborted>
	    }
	    cleanPdata $program
	    set var [string range $v 4 end]
	    # rputs "interrupt program=$program,$var"
	    after 200 uplevel "#0" set $var <aborted>
	}
    }
}



proc  msleep { n } {
    global Msleeping
    set Msleeping 1
    after $n "set Msleeping 0"
    debugsend "waiting Msleeping.."
    myVwait Msleeping
    debugsend "..donewaiting Msleeping"
}
proc message { msg } {
    global maxima_priv _debugSend
    if { $_debugSend } { puts "setting message=<$msg>" }
    catch { set maxima_priv(load_rate) $msg }
}
proc sendOne { program  com }  {
    global  pdata maxima_priv
    incr pdata($program,currentExpr)
    set socket $pdata($program,socket)

    if { [eof $socket] } {
        error [mc "connection closed"]
    }
    # puts "sending $program ([lindex [fconfigure $socket -peername] 1])"

    message [concat [mc "sending"] "$program" [mc "on"] "[lindex [fconfigure $socket -peername] 1]"]
    debugsend "sending.. {$com<$pdata($program,currentExpr)\|fayve>}"
    set msg "$com<$pdata($program,currentExpr)\|fayve>\n"
    proxyPuts $socket $msg
}


#
#-----------------------------------------------------------------
#
# sendOneDoCommand --  sends to PROGRAM the COMMAND and then
# when the result comes back it invokes the script CALLBACK with
# one argument appended: the global LOCATION where the result
# will be.   [uplevel "#0" set $LOCATION] would retrieve it.
#
#  Results: returns immediately the location that will be
#  watched.
#
#  Side Effects: CALLBACK is invoked later by tracing the
#  result field
#
#----------------------------------------------------------------
#
proc sendOneDoCommand {program command callback } {
    global pdata

    if { ![assureProgram $program 5000 2] } { return "cant connect"}

    set ii [expr {$pdata($program,currentExpr) + 1}]
    catch { unset pdata($program,results,$ii)}
    trace variable pdata($program,results,$ii) w \
	    [list invokeAndUntrace $callback]
    sendOne $program $command
    return pdata($program,results,$ii)
}

proc testit { program com } {
    sendOneDoCommand $program $com "jimmy"
    proc jimmy {s} { puts "<result is:[uplevel #0 set $s]>" ; flush stdout}
}

proc invokeAndUntrace { callback name1 name2 op args} {
    #puts "callback:$callback $name1 $name2 $op, args=$args"
    #puts "trace vdelete [set name1]($name2) w [list invokeAndUntrace $callback]"
    trace vdelete [set name1]($name2) w [list invokeAndUntrace $callback]
    lappend callback  [set name1]($name2)
    # puts "callback=$callback" ; flush stdout

    if { [catch { eval $callback } errmsg ] } {
	global errorInfo
	# report the error in the background
	set com [list  error [concat [mc "had error in"] "$callback:[string range $errmsg 0 300].."]	$errorInfo]
	after 1 $com
    }
}

proc sendOneWait { program com } {
    global pdata
    if { ![assureProgram $program 5000 2] } { return "cant connect"}
    set ii [expr {$pdata($program,currentExpr) + 1}]
    catch { unset pdata($program,results,$ii)}


    sendOne $program $com
    set i $pdata($program,currentExpr)
    set socket $pdata($program,socket)
    if { $ii != $i } { error "expected $ii got $i as expression number " }
    debugsend "waiting for pdata($program,results,$i)"

    myVwait pdata($program,results,$i)
    debugsend "..done waiting for pdata($program,results,$i)"
    return $pdata($program,results,$i)
}

proc closeConnection { program } {
    global pdata
    catch {
	set sock $pdata($program,socket)
	set pdata(input,$sock) ""
	cleanPdata $program
	close $sock

    }
}

proc dtrace { } {
    global _debugSend
    if { $_debugSend } {
	puts "at: [info level -1]"
	if { [info level]>2 } {puts "   from:[info level -2 ]"}
    }
}

proc openConnection { tohost port magic program } {
    global  pdata
    dtrace
    set msg "magic: $magic\n"
    set retries 2
    message [concat [mc "connecting to"] "nmtp($port)://$tohost/$program"]
    debugsend "openConnection { $tohost $port $magic $program }"

    while { [incr retries -1] > 0 \
	    && [catch { set socket [openSocketAndSend $tohost $port $msg 1] }] }   {
	debugsend retries=$retries
	msleep 400
    }

    if { $retries == 0 } { return 0}	

    message [concat [mc "connected to"] "nmtp//$tohost:$port/$program"]
    set pdata($program,socket) $socket
    set pdata($program,currentExpr) 0
    set pdata(input,$socket) ""
    catch { fconfigure $socket -blocking 0 }
    fileevent $socket readable "getResults $program $socket"
    return 1

}

proc sendInterrupt { program } {
    global pdata interrupt_signal
    set socket $pdata($program,socket)
    gui status [mc "Sending scoket interrupt"]
    puts $socket $interrupt_signal
    flush $socket
}

proc sendCommand { program c }   {
    global  pdata
    set socket $pdata($program,socket)
    puts $socket "<command:$c>"
    flush $socket
}

proc dumpInfo {program } {
    sendCommand $program dumpInfo
}

proc getResults {  program socket } {
    # debugsend "enter:getResults"
    global pdata  next_command_available next_command results ii
    if { [eof $socket] } {
	close $socket ;
	debugsend "closed $socket"
	cleanPdata $program
	return "<$program exitted>"
    }
    set s [read $socket]
    if { "[string index $s 0]" != "" } {
	set s [append pdata(input,$socket) $s]
	while { [set inds [testForFayve $s]] != "" } {
	    set input $pdata(input,$socket)
	    # set next_command_available 1
	    debugsend "input=$input"
	    set gotback [string range $input 0 [expr {[lindex $inds 0] -1}]]
	    set index [lindex $inds 2]
	    set pdata($program,results,$index) $gotback
    	    if { [string first "exitted>" $gotback] > 0 } {
		close $socket
		cleanPdata $program
	    }

	    debugsend "gotback{$index:$gotback}"
	    set s \
		    [string range $input [expr {1 + [lindex $inds 1]}] end ]
	    set pdata(input,$socket) $s
	}
    }
    return ""
}

proc cleanPdata { program } {
    global pdata
    catch { close $pdata($program,socket) }
    catch { unset pdata($program,socket) }
    catch { unset pdata($program,preeval) }
    catch {
	foreach v [array names $program,results,*] {
	    unset pdata($v)
	}
    }
}



# number from run-main.tcl
# set MathServer { linux1.ma.utexas.edu 4443 }

proc currentTextWinWidth { } {
    set width 79
    catch {
	set t [oget [omPanel .] textwin]
	set width [expr {round([winfo width $t]*1.0 / [font measure [$t cget -font] 0]) - 12 }]
    }
    return $width
}




#
#-----------------------------------------------------------------
#
# assureProgram --
#
#  Results: return 2 if the program was already open, and 1 if it is just
# now opened.   0 if cant open it.
#
#  Side Effects: program is started.
#
#----------------------------------------------------------------
#
proc assureProgram { program timeout tries } {
    # puts "assure: program=$program"
    global pdata MathServer


    if { $tries <=  0   } { return 0}

    if  { [catch { set socket $pdata($program,socket) } ] \
	    || [catch { eof $socket}] \
	    || [eof $socket] \
	    || [catch { set s [read $socket]; append pdata(input,$socket) $s }] } {
	cleanPdata $program
	message [concat [mc "connecting"] "[lindex $MathServer 0]"]
	set msg "OPEN [programName $program] MMTP/1.0\nLineLength: [currentTextWinWidth]\n\n\n"
	if {[catch {openSocketAndSend [lindex $MathServer 0] \
		[lindex $MathServer 1] "$msg\n"} sock] } {
	    error [concat [mc "Can't connect to"] "$MathServer." [mc "You can try another host by altering Base Program under the \"File\" menu."]]
	}
	
	set pdata($program,currentExpr) 0
	fconfigure $sock -blocking 0
	if { [eof $sock] } {return 0}
	message [concat [mc"connected to"] "[lindex $MathServer 0]"]
	debugsend $msg
	set result ""
	set pdata(waiting,$sock) 1
	set script "close $sock ; debugsend {after closing} ; set pdata(waiting,$sock) -1"
	debugsend "script=$script,timeout=$timeout"
	set af [after $timeout $script ]
	debugsend "after=$af"
	while {1 } {
	    debugsend "waiting pdata(waiting,$sock)=$pdata(waiting,$sock)"
	    #	    puts "pdata=[array get pdata *$sock* ]"
	    fileevent $sock readable "if { [eof $sock] }  {set pdata(waiting,$sock) -2} else { set pdata(waiting,$sock) 0 ;} ;fileevent $sock readable {} "
	    set pdata(waiting,$sock) 1
	    debugsend "waiting on  pdata(waiting,$sock)"
	    myVwait pdata(waiting,$sock)
	
	    debugsend "..done now pdata(waiting,$sock)=$pdata(waiting,$sock)"
	    if { $pdata(waiting,$sock) < 0 } {
		debugsend "timed out,$pdata(waiting,$sock)"
		return 0
	    }
	    set me [read $sock]
	    if { "[string index $me 0]" == ""  && [eof $sock] } {
		debugsend "nothing there"
		return 0
	    }
	    append result $me
	    debugsend "result=<$result>"
	    if { [regexp "RUNNING (\[^ \]+) MMTP\[^\n\]*\nHost: (\[^\n ]+)\nPort: (\[0-9\]+)\nMagic: (\[^\n \]+)\n" \
		    $result junk prog tohost port magic] } {
		after cancel $af
		debugsend "doing openConnection  $tohost $port $magic $program"
		close $sock
		return [openConnection  $tohost $port $magic $program]
	    }
	}
    } elseif { [eof $socket] } {
	close $socket
	unset pdata($program,socket)
	return [assureProgram $program $timeout [expr {$tries -1}]]
    } else {
	# already open
	return 2
    }
}

# name may look like "maxima#1.2"
proc programName { name } {
    set name [file tail $name]
    return [lindex [split $name #] 0]
}

global EOFexpr
set EOFexpr "|fayve>"

proc getMatch { s inds } {
    return [string range $s [lindex $inds 0] [lindex $inds 1]]
}

proc testForFayve { input } {
    global EOFexpr
    set ind [string first $EOFexpr $input]
    if { $ind < 0 } { return "" } else {
	regexp -indices {<([0-9]+)\|fayve>} $input all first
	
	set n [getMatch $input $first]
	return "$all $n"
    }
}

#### the following is correct but just a fair bit slower.. ####
##### because of all the arguments to be parsed for the other..
proc statServer1  {server {timeout 1000}} {
    global statServer
    set ans ""
    if { ![catch { set s [eval socket $server]} ] } {
	puts $s "STAT MMTP/1.0\n" ; flush $s
	if { [readAllData $s -tovar statServer(data) \
		-mimeheader statServer(header) -timeout $timeout ] > 0 } {
	    set head $statServer(header)
	    #	   puts "data=<$statServer(data)>"
	    set res $statServer(header)\n\n$statServer(data)
	    unset statServer
	    return $res
	}
    }
    return ""
}


#
#-----------------------------------------------------------------
#
# needToDo --  Check if we have already done OPERATION for  NAME into data
#
#  Results: returns 0 if the data for name is not preloaded, and 1 otherwise
#
#  Side Effects: adds NAME to those preloaded for PROGRAM if not there
#
#----------------------------------------------------------------
#
proc preeval { program name } {
    global pdata
    assureProgram $program 5000 2
    if { ![info exists pdata($program,preeval)] || \
    [lsearch  $pdata($program,preeval) $name] < 0 } {
	lappend pdata($program,preeval) $name
	return 0
    } else {
	return 1
    }
}



proc statServer  {server {timeout 1000}} {
    global statServer1_
    set ans ""
    if { ![catch { set s [eval socket $server]} ] } {
	puts $s "STAT MMTP/1.0\n" ; flush $s
	if { [readDataTilEof $s data $timeout ] } {
	    foreach v { jobs currentjobs } {
		if { [regexp "\n$v: (\[^\n]*)\n" $data junk val] } {
		    lappend ans $v $val
		}
	    }
	}
    }
    return $ans
}

proc isAlive1 { s } {
    global maxima_priv
    if { [catch { read $s } ] } {
	set maxima_priv(isalive) -1
    } else {
	set maxima_priv(isalive) 1
    }
    close $s
}

proc isAlive { server {timeout 1000} } {
    global maxima_priv

    if { [ catch { set s [eval socket -async $server] } ] } { return -1 }
    set maxima_priv(isalive) 0
    fconfigure $s -blocking 0
    fileevent    $s writable     "isAlive1 $s"
    set c1 "set maxima_priv(isalive) -2"
    set after_id [after $timeout $c1]
    myVwait maxima_priv(isalive)
    catch { close $s}
    after cancel $after_id
    return $maxima_priv(isalive)
}


proc debugsend { s } {
    global _debugSend
    if { $_debugSend } {
	
	puts $s
	flush stdout
    }
}


## endsource send-some.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Plotting.tcl,v 1.3 2002-09-07 23:20:49 mikeclarkson Exp $
#
###### plotting.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################


global axisGray
if { "[winfo screenvisual .]" == "staticgray" } {
    set axisGray black
} else  {
    set axisGray gray60
}

global writefile
set writefile  "Save"
# make printing be by ftp'ing a file..

if {[catch { set doExit }] } { set doExit ""}


## endsource plotting.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Fonts.tcl,v 1.8 2006-06-27 13:33:42 villate Exp $
#

# set font {Courier 8}
global maxima_priv fontCourier8 fixedFont fontSize
set maxima_priv(fixedFont) Courier

# Pick a default font size in pixels
set _screenheight [winfo screenheight .]
# if {$_screenheight < 500} {
#     # for 640x480
#     set _pixel 10
#     set _point 8
#     # Pick a default borderwidth which smaller
#     set _bd 1
# } elseif {$_screenheight < 700} {
#     # for 800x600
#     set _pixel 12
#     set _point 8
# } elseif {$_screenheight < 800} {
#     # for 1024x768
#     set _pixel 12
#     set _point 8
# } elseif {$_screenheight < 1100} {
#     # for 1200x1000
#     set _pixel 14
#     set _point 10
# } else {
#     set _pixel 18
#     set _point 12
# }

# ZW: this actually produces better result
set _pixel 10
set _point 8
set fontSize $_pixel

# setup defaults depending on the OS and Window Manager
# Really should do another version for mono
switch -exact -- $tcl_platform(platform) {
    windows {
	if {$tcl_platform(osVersion) < 5} {
	    set _prop_default {MS Sans Serif}
	} else {
	    set _prop_default Tahoma
	}
	set _fixed_default {Courier New}
    }
    default {
	set _prop_default {Bitstream Vera Sans}
	set _fixed_default {Bitstream Vera Sans Mono}
    }
}
# make sure these fonts are installed
set _allowed [string tolow [font families]]
foreach font [list $_prop_default "MS Sans Serif" Tahoma Arial Helvetica \
		 fixed system] {
    if {[lsearch -exact $_allowed [string tolow $font]] > -1} {
	set _prop_default $font
	break
    }
}
foreach font [list $_fixed_default Courier fixed system] {
    if {[lsearch -exact $_allowed [string tolow $font]] > -1} {
	set _fixed_default $font
	break
    }
}
set fontCourier8 [list $_fixed_default $_pixel]
set fixedFont [font create -family $_fixed_default -size $_pixel]
set buttonfont [font create -family $_prop_default -size $_pixel]


global maxima_default
set maxima_default(adjust) 0
# I think this is too crude and wont work with WM schemes
if {0} {
    catch {
	set width_ [expr {.9 * [winfo screenwidth .]}]
	if { [winfo width .] >= 500 } {
	    set width_ [winfo width .]
	}
	set maxima_default(adjust) [expr {
					  $width_<= 640 ? -1 :
					  $width_<= 800 ? 0 :
					  1 } ]
	unset width_
    }
}



######### font choosing utilities #########
global tcl_platform
global isFixedp

if { "$tcl_platform(platform)" == "unix" } {
    array set isFixedp {
	fixed 1 {fangsong ti} 1 {clearlyu alternate glyphs} 0 lucidatypewriter 1 charter 0 lucidabright 0 times 0 ming 1 {lucidux sans} 0 {open look glyph} 0 {song ti} 1 newspaper 0 helvetica 0 {open look cursor} 1 li 1 mincho 1 {clearlyu ligature} 0 {clearlyu pua} 0 {lucidux mono} 1 courier 1 clearlyu 0 utopia 0 lucida 0 nil 1 clean 1 terminal 1 kai 1 gothic 1 cursor 0 symbol 0 {clearlyu arabic extra} 0 {lucidux serif} 0 {new century schoolbook} 0 song 1
    }
}

proc getFontFamilies { fixed } {
    global isFixedp
    foreach font  [font families] {
	if { ![info exists isFixedp($font)] } {
	    set isFixedp($font) [font metrics [list $font] -fixed]
	}
	if { $isFixedp($font) == $fixed } {
	    lappend answer $font
	}
    }
    return [lsort $answer]
}


#  $Id: colors.tcl,v 1.1 2009-11-15 22:55:35 villate Exp $
#
# Copyright (c) 2009, Jaime E. Villate <villate@fe.up.pt>
#
# Procedures to work wih colors
# (the license information can be found in COPYING.tcl)

# transform a (hue, saturation, value) set into a (red, green, blue) set

proc hsv2rgb {hue sat val} {
    if { $sat < 0 } { set sat [expr 1 -  $sat] }
    if { $val < 0 } { set val [expr 1 -  $val] }
    if { $val > 1 } { set val [expr $val - int($val)] }
    if { $sat > 1 } { set sat [expr $sat - int($sat)] }
    set v  [expr round($val*255)]
    if {$sat == 0} {
        return [format "\#%02x%02x%02x" $v $v $v]
    } else {
        set h [expr {round($hue)%360/60.0}]
        set i [expr {round($hue)%360/60}]
        set f [expr {$h-$i}]
        set u [expr {round($v)}]
        set p [expr {round($v*(1-$sat))}]
        set q [expr {round($v*(1-$sat*$f))}]
        set t [expr {round($v*(1-$sat*(1-$f)))}]
        switch $i {
            0 {set r $u; set g $t; set b $p}
            1 {set r $q; set g $u; set b $p}
            2 {set r $p; set g $u; set b $t}
            3 {set r $p; set g $q; set b $u}
            4 {set r $t; set g $p; set b $u}
            5 {set r $u; set g $p; set b $q}
        }
        return [format "\#%02x%02x%02x" $r $g $b]
    }
}

# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Private.tcl,v 1.3 2006-06-30 15:04:58 villate Exp $
#
###### private.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

# a private way of storing variables on a window by window
# basis
#mike FIXME: these stay in memory when the window is destroyed

proc makeLocal { win args } {
    foreach v $args {
	uplevel 1 set  $v \[oget $win $v\]
    }
}

proc linkLocal { win args } {
    foreach v $args {
	uplevel 1 upvar #0 _WinInfo${win}\($v) $v
    }
}

proc clearLocal { win } {
    global _WinInfo$win
    # puts "clearing info for $win in [info level 1]"
    catch { unset _WinInfo$win }
}


proc oset { win var val } {
    global _WinInfo$win
    set _WinInfo[set win]($var) $val
}

proc oarraySet { win vals } {
    global _WinInfo$win
    array set  _WinInfo$win $vals
}

proc oloc { win var } {
    return _WinInfo[set win]($var)
}

proc oarray { win  } {
    return _WinInfo[set win]
}

proc oget { win var } {
    global _WinInfo$win
    return [set _WinInfo[set win]($var)]
}

## endsource private.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Getopt.tcl,v 1.4 2004-10-13 12:08:57 vvzhy Exp $
#
###### Getopt.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

#####sample option list.   Error will be signalled if "Required" option
##### not given.
#set dfplotOptions {
#    {xdot Required {specifies dx/dt = xdot.  eg -xdot "x+y+sin(x)^2"} }
#    {ydot Required {specifies dy/dt = ydot.  eg -ydot "x-y^2+exp(x)"} }
#    {xradius 10 "Width in x direction of the x values" }
#    {yradius 10 "Height in y direction of the y values"}
#}


#
#-----------------------------------------------------------------
#
# optLoc --  if $usearray is not 0, then the OPTION is stored
# in a hashtable, otherwise in the variable whose name is the
# same as OPTION.
#  Results: a form which when 'set' will allow storing value.
#
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc optLoc { op ar }  {
    #  puts "$ar,[lindex $op 0]"
    # puts "return=$ar\([lindex $op 0]\)"
    if { "$ar" == 0 } {
	return [lindex $op 0]
    } else {
	#puts "$ar\([lindex $op 0]\)"
	return "$ar\([lindex $op 0]\)"
    }

}


#
#-----------------------------------------------------------------
#
# getOptions --  given OPTLIST a specification for the options taken,
# parse the alternating keyword1 value1 keyword2 value2 options_supplied
# to make sure they are allowed, and not just typos, and to supply defaults
# for ones not given.   Give an error message listing options.
# a specification is  { varname default_value "doc string" }
# and optlist, is a list of these.   the key should be -varname
#
#  -debug 1 "means print the values on standard out"
#  -allowOtherKeys 1 "dont signal an error if -option is supplied but not in
#                     the list"
#  -usearray "should give a NAME, so that options are stored in NAME(OPTION)
#  -setdefaults "if not 0 (default is 1) do `set OPTION dflt' for all options"
# If a key is specified twice eg.  -key1 val1 -key1 val2, then the first
# value val1 will be used
#  Results:
#
#  Side Effects: set the values in the callers environment
#
#----------------------------------------------------------------
#

proc getOptions { optlist options_supplied args } {
    # global  getOptionSpecs

    set ar [assoc -usearray $args 0]
    set help [assoc -help $args ""]
    if { "$ar" != "0" } { global $ar }
    set debug [assoc -debug $args 0]
    set allowOtherKeys [assoc -allowOtherKeys $args 0]
    set setdefaults [assoc -setdefaults $args 1]
    set supplied ""

    foreach {key val } $options_supplied {
	if { [info exists already($key)] } { continue }
	set already($key) 1
	set found 0
	foreach op $optlist {
	    if { "$key" == "-[lindex $op 0]" } {
		uplevel 1 set [optLoc $op $ar] [list $val]
		
		append supplied " [lindex $op 0]"
		set found 1
		break
	    }
	}
	set caller global

	if { $found == 0  && !$allowOtherKeys } {
	    catch {set caller [lindex [info level -1] 0]}
	    error [concat "`$caller'" [mc "does not take the key"] "`$key':\n[optionHelpMessage $optlist]\n$help"]

	}
    }
    foreach op $optlist {
	if { [lsearch $supplied [lindex $op 0]] < 0 } {
	    if { "[lindex $op 1]" == "Required" } {
		catch {set caller [lindex [info level -1] 0]}	
		error [concat "`-[lindex $op 0]'" [mc "is required option for"] "`$caller':\n[optionHelpMessage $optlist]"]
	    }
	    if { $setdefaults }  {

		uplevel 1 set [optLoc $op $ar] [list [lindex $op 1]]
	    }
	}
	# for debugging see them.
	# if { $debug } {   uplevel 1 puts "[optLoc $op $ar]=\$[optLoc $op $ar]"}
	if { $debug } {   puts "[optLoc $op $ar]=[safeValue [optLoc $op $ar] 2]"}
	
    }
}

proc getOptionDefault { key optionList } {
    foreach v $optionList {
	if { "[lindex $v 0]" == "$key" } { return [lindex $v 1]}
    }
    return ""
}

proc assq {key list {dflt ""}} {
    foreach v $list { if { "[lindex $v 0]" == "$key" } { return $v }}
    return $dflt
}

proc safeValue { loc level} {
    if { ![catch { set me [uplevel $level set $loc] } ] } {
	return $me
    }  else {
	return "`unset'"
    }
}



proc optionFirstItems { lis } {
    set ans ""
    foreach v $lis { append ans " [list [lindex $v 0]]" }
    return $ans
}

proc optionHelpMessage { optlist } {
    set msg ""
    foreach op $optlist  {	
	append msg \
		" -[lindex $op 0] \[ [lindex $op 1] \] --[lindex $op 2]\n"
    }
    return $msg
}


#
#-----------------------------------------------------------------
#
# setSplittingOptionsRest --  takes ARGLIST and splits it into
# two lists, the first part it stores in KEYPAIRS and the second in REST
#
#
#  Results: none
#
#
#  Side Effects: sets the variables in the local frame passed to KEYPAIRS
#
#----------------------------------------------------------------
#	
proc setSplittingOptionsRest {  keypairs rest arglist } {
    upvar 1 $keypairs keys
    upvar 1 $rest res
    set i 0
    while { 1 } {
	if { $i >= [llength $arglist] } { break }
	if { "[string range [lindex $arglist $i] 0 0]" == "-" } {
	    incr i 2
	} else {
	    break
	}
    }
    set keys [lrange $arglist 0 [expr $i -1]]
    set res [lrange $arglist  $i end]
}



## endsource getopt.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Parse.tcl,v 1.8 2009-03-27 00:14:45 villate Exp $
#
###### Parse.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

global Parser parse_table
if {[info exists Parser]} {catch { unset Parser }}

foreach v  { { ( 120 } { \[ 120 } { ) 120 } { \] 120 }  { ^ 110}
{ ^- 110} {* 100} { / 100} {% 100}  {- 90 } { + 90 }
{ << 80} { >> 80 } { < 70 } { > 70 } { <= 70 } {>= 70}
{ == 60 } { & 50} { | 40 } { , 40 } {= 40}
{ && 30 } { || 20 } { ? 10 } { : 10 }  { ; 5 }}  {
    set parse_table([lindex $v 0]) [lindex $v 1]
    set getOp([lindex $v 0]) doBinary

}

proc binding_power {s} {
    global parse_table billy
    set billy $s
    if { [catch { set tem $parse_table($s) }] } {
	return 0
    } else {
	return $tem
    }
}

proc getOneMatch { s inds } {
    return [string range $s [lindex $inds 0] [lindex $inds 1]]
}

proc parseTokenize { str } {
    regsub  -all {[*][*]} $str "^" str
    set ans ""
    while { [string length $str ] > 0 } {
	#    puts "ans=$ans,str=$str"	
	set str [string trimleft $str " \t\n" ]
	set s [string range $str 0 1]
	set bp [binding_power $s]
	if { $bp > 0 } {
	    append ans " $s"
	    set str [string range $str 2 end]
	    continue
	} else {
	    set s [string range $s 0 0]
	    set bp [binding_power $s]
	    if { $bp > 0 } {
		append ans " $s"
		set str [string range $str 1 end]
		continue
	    }
	}
	if { "$s" == "" } {
	    return $ans
	}
	if { [regexp -indices {^[0-9.]+([eE][+---]?[0-9]+)?} $str all] } {
	    append ans " { number [getOneMatch $str $all] }"
	    # append ans " [getOneMatch $str $all]"
	    set str [string range $str [expr {1+ [lindex $all 1]}] end]
	}  elseif { [regexp -indices {^[$a-zA-Z][a-zA-Z0-9]*} $str all] } {
	    append ans " { id [getOneMatch $str $all] } "
	    # append ans " [getOneMatch $str $all]"
	    set str [string range $str [expr {1+ [lindex $all 1]}] end]
	}  else {
	    error [concat [mc "parser unrecognized:"] "$str"]
	}
    }
    return $ans
}

set Parser(reserved) " acos cos hypo sinh asin cosh log sqrt atan exp log10 tan atan2 floor pow tanh ceil fmod sin abs double int round"

set Parser(help) [join [list [mc \
{
The syntax for the definition of functions is like C, except that it is \
permitted to write x^n instead of pow(x,n).
} ] [mc {
Functions:}] $Parser(reserved) [mc {

Operators:}] " == % & || ( << <= ) : * >=  + && , | < >> - > ^ ? /" ] ""]



proc nexttok { } {
    global Parser
    set x [lindex $Parser(tokenlist) [incr Parser(tokenind) ]]
    # puts "nexttok=$x"
    if {[llength $x ] > 1 } {
	set Parser(tokenval) [lindex $x 1]
	return [lindex $x 0]
    } else {
	return $x
    }
}


#
#-----------------------------------------------------------------
#
# parseToSuffixLists -- Convert EXPR1; EXPR2; ..
# to a list of suffix lists.  Each suffix list is suitable for
# evaluating on a stack machine (like postscript) or for converting
# further into another form.  see parseFromSuffixList.
#  "1+2-3^4;" ==>
#   {number 1} {number 2} + {number 3} {number 4} ^ -
#  Results: suffix list form of the original EXPR
#
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc parseToSuffixLists { a }  {
    global    Parser
    set Parser(result) ""
    set Parser(tokenlist) [parseTokenize $a]
    set Parser(tokenind) -1
    set Parser(lookahead)  [nexttok]
    #puts tokenlist=$Parser(tokenlist)
    set ans ""
    while { "$Parser(lookahead)" != ""  } {
	getExpr  ; parseMatch ";"
	#puts "here: $Parser(result) "	
	append ans "[list	$Parser(result)] "
	set Parser(result) "" 	
    }
    regsub \\^- $ans {PRE_MINUS ^} ans2
    return $ans2
}

proc parseMatch { t } {
    global Parser
    if { "$t" == "$Parser(lookahead)" } {
	set Parser(lookahead)  [nexttok]
    } else {
	error "syntax error: wanted $t"
    }
}

proc emit { s args } {
    global Parser
    if { "$args" == "" }   {
	append Parser(result) " $s"
	# puts " $s "
    } else {
	append Parser(result) " {[lindex $args 0 ] $s}"
	#puts " {[lindex $args 0 ] $s} "
    }
}

proc getExpr { } {
    getExprn 0
}

proc getExprn { n } {
    global Parser
    #puts "getExpr $n, $Parser(tokenind),$Parser(tokenlist)"
    if { $n == 110 } {
	getExpr120
	return
    }

    incr n 10
    if  { $n == 110 } {
	if { "$Parser(lookahead)" == "-" || "$Parser(lookahead)" == "+"  } {
            if { "$Parser(lookahead)" == "-" } {
		set this PRE_MINUS
	    } else {
		set this PRE_PLUS
	    }
	    parseMatch $Parser(lookahead)
	    getExprn $n
	    #puts "l=$Parser(lookahead),pl=$Parser(result)"
	    emit $this
	    return
	}
	
    }

    getExprn $n
    while { 1 } {
	if { [binding_power $Parser(lookahead)] == $n } {
	    set this $Parser(lookahead)
	    parseMatch $Parser(lookahead)
	    getExprn $n
	    if { $n == 110 } {
		set toemit ""
		while { "$this" == "^" &&  "$Parser(lookahead)" == "^" } {
		    # puts "p=$Parser(result),$
		    set this $Parser(lookahead)
		    append toemit " $this"
		    parseMatch $Parser(lookahead)
		    getExprn $n
		}
		foreach v $toemit { emit $v }
	    }
	    emit $this

	} else {
	    return
	}
    }
}

proc getExpr120 { } {
    global Parser
    #puts "getExpr120, $Parser(tokenind),[lrange $Parser(tokenlist) $Parser(tokenind) end]"
    while { 1 } {
	if { "$Parser(lookahead)" == "(" } {
	    parseMatch $Parser(lookahead)
	    getExpr
	    parseMatch ")"
	    break;
	} elseif { $Parser(lookahead) == "id" } {
	    emit $Parser(tokenval) id

	    parseMatch $Parser(lookahead)
	    if { "$Parser(lookahead)" == "(" } {
		getExpr120
		emit funcall
	    }
	    break;
	} elseif { $Parser(lookahead) == "number" } {
	    emit $Parser(tokenval) number
	    parseMatch $Parser(lookahead)
	    break;
	} else {
	    bgerror [mc "syntax error"]
	    break;
	}
    }
}

global getOp
set getOp(PRE_PLUS) doPrefix
set getOp(PRE_MINUS) doPrefix
set getOp(funcall) doFuncall
set getOp(^) doPower
set getOp(:) doConditional
set getOp(?) doConditional

proc doBinary { } {
    uplevel 1 {set s $nargs; incr nargs -1 ;
    if { "$x" == "," } {
	set a($nargs) "$a($nargs) $x $a($s)"
    } else {
	set a($nargs) "($a($nargs) $x $a($s))"}
    }
}

proc doPower { } {
    uplevel 1 {set s $nargs; incr nargs -1 ; set a($nargs) "pow($a($nargs),$a($s))" }
}

proc doFuncall {} {
    uplevel 1 {
	#puts nargs=$nargs
	set s $nargs; incr nargs -1 ; set a($nargs) "$a($nargs)($a($s))"
    }
}

proc doPrefix {} {
    uplevel 1  { if { "$x" == "PRE_MINUS" } { set a($nargs) "-$a($nargs)" } }
}

proc doConditional { } {
    set x [uplevel 1 set x]
    if { "$x" == "?" } { return }
    # must be :
    uplevel 1 {
	set s $nargs ; incr nargs -2 ;
	set a($nargs) "($a($nargs) ? $a([expr {$nargs + 1}]) : $a($s))"
    }
}


#
#-----------------------------------------------------------------
#
# parseFromSuffixList --  takes a token list, and turns
# it into a suffix form.  eg: 1 + 2 - 3 ^ 4 --> 1 2 + 3 4 ^ -
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc parseFromSuffixList { list } {
    global getOp
    set stack ""
    set lim [llength $list]
    set i 0
    set nargs 0
    while { $i < $lim } {
	set x [lindex $list $i ]
	set bp [binding_power $x]
	incr i
	# all binary
	if { [llength $x] > 1 } {
	
	    set a([incr nargs]) [lindex $x 1]

	} else {
	    $getOp($x)
	}
    }

    return $a(1)
}


#
#-----------------------------------------------------------------
#
# parseConvert --  given an EXPRESSION, parse it and find out
# what are the variables, and convert a^b to pow(a,b).  If
# -variables "x y" is given, then x and y will be replaced by $x $y
#  doall 1 is giv
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
global Parser
set Parser(convertOptions) {
    { doall 0 "convert all variables x to \$x" }
    { variables "" "list of variables to change from x to \$x" }
}
proc parseConvert { expr args } {
    global   Parser
    getOptions $Parser(convertOptions) $args
    if { "$expr" == "" } { return [list {} {}] }
    set parselist [parseToSuffixLists "$expr;"]
    #puts "parselist=$parselist"
    catch { unset allvars }
    set new ""
    set answers ""
    foreach lis $parselist {

	foreach v $lis {

	    if { ("[lindex $v 0]" == "id")
	    && ([llength $v] == 2)
	    && ([lsearch  $Parser(reserved) [set w [lindex $v 1]]] < 0)
	} {
	    if { ($doall != 0)  || ([lsearch  $variables $w] >= 0) } {
		append new " {id \$$w}"
		set allvars(\$$w) 1
	    } else {
		set allvars($w) 1
		append new " {$v}"
	    }
	}  else {
	    if { [llength $v] > 1 } {
		append new " {$v}"
	    } else {
		append new " $v" }
	    }
	}
	#puts "new=$new"
	append answers "[list [parseFromSuffixList $new]] "
	set new ""
    }
    return [list $answers [array names allvars]]
}

proc test { s } {
    set me [parseFromSuffixList [lindex [parseToSuffixLists "$s;"] 0]]
    puts $me
    return "[eval expr $s] [eval expr $me]"
}




## endsource parse.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Textinsert.tcl,v 1.4 2004-03-21 07:30:58 vvzhy Exp $
#
###### Textinsert.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

proc mkTextItem { c x y args  } {

    global _fixed_default _prop_default fontSize
    set helvetica $_prop_default
    set courier $_fixed_default

    set font [assoc -font $args [list $helvetica $fontSize]]
    set tags [assoc -tags $args {}]
    set item [$c create text $x $y -text " " -width 440 -anchor n -font $font -justify left]
    append tags text
    foreach v $tags { $c addtag $v withtag $item}
    $c bind text <1> "textB1Press $c %x %y"
    $c bind text <B1-Motion> "textB1Move $c %x %y"
    $c bind text <Shift-1> "$c select adjust current @%x,%y"
    $c bind text <Shift-B1-Motion> "textB1Move $c %x %y"
    $c bind text <KeyPress> "textInsert $c %A"
    $c bind text <Return> "textInsert $c \\n"
    $c bind text <Control-h> "textBs $c"
    $c bind text <BackSpace> "textBs $c"
    $c bind text <Delete> "textDel $c"
    $c bind text <2> "textPaste $c @%x,%y"
}


## endsource textinsert.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Printops.tcl,v 1.11 2006-08-24 07:03:23 vvzhy Exp $
#
###### Printops.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

### FIXME: fix a4 size !
global paperSizes printOptions
set paperSizes {{letter 8.5 11} { A4 8.5 11} {legal 8.5 13}}

set printOptions {
    { landscape 0 "Non zero means use landscape mode in printing"}
    { papersize letter "letter, legal or A4"}
    { hoffset 0.5 "Left margin for printing"}
    { voffset 0.5 "Top margin for printing"}
    { xticks 20 "Rough number of ticks on x axis"}
    { yticks 20 "Rough number of ticks on y axis"}
#   { title "" "Title"}
    { psfilename "~/sdfplot.ps" "Postscript filename"}
    { centeronpage 1 ""}
}

# proc getPageOffsets { widthbyheight} {
#     global printOption paperSizes
#     puts "wbh=$widthbyheight"
#     set pwid 8.5
#     set phei 11.0

#     foreach v $paperSizes {
# 	if { "[lindex $v 0]" == "$printOption(papersize)" } {
# 	    set pwid [lindex $v 1]
# 	    set phei [lindex $v 2]
# 	}
#     }
#     set wid [expr {$pwid - 2* $printOption(hoffset)}]
#     set hei [expr {$phei - 2* $printOption(voffset)}]
# #    if { $printOption(landscape) } {set widthbyheight [expr  {1.0 /$widthbyheight}]}
# #    set w $wid ; set hei $wid ; set wid $w

#     puts "pw=$wid,ph=$hei,w/h=$widthbyheight,hh=[expr {$hei * $widthbyheight}], ww=[expr {$wid / $widthbyheight}]"

#     set fac   $widthbyheight
#     puts "fac=$fac"
#     if { $fac * $hei < $wid } {
    # 	set iwid [expr {$fac *$hei}]
# 	set ihei $hei

#     } else {
    # 	set ihei [expr {$wid / $fac}]

# 	set iwid $wid

#     }

#     if { $printOption(landscape) } { set fac1 [expr {1/$fac}] }
#     if { $wid/$hei > $fac } {
# 	set ihei $hei
    # 	set iwid   [expr {$hei / $fac }]

#     } else {
# 	 set iwid $wid
    # 	 set ihei [expr {$wid * $fac }]
#     }

#     #-pagex = left margin (whether landscape or not)
#     #-pagey = right margin (whether landscape or not)
#     #-pagewidth becomes vertical height if landscape
#     #-pageheight becomes horiz width if landscape

#     set xoff [expr {($pwid-$iwid)/2.0}]
#     set yoff [expr  {($phei-$ihei)/2.0}]

#     if { $printOption(landscape) } {
# 	set h $ihei
# 	set ihei $iwid
# 	set iwid $h
#     }

#     puts "phei=$phei,ihei=$ihei,yoff=$yoff,voff=$printOption(voffset)"
#     set ans "-pagex [set xoff]i -pagey [set yoff]i \
# 	    -pagewidth [set iwid]i -pageheight [set ihei]i"
#     set ans "-pagex [set xoff]i -pagey [set yoff]i \
# 	    -pagewidth [set iwid]i -pageheight [set ihei]i"
#     return $ans
# }

proc swap { a b } {
    set me [uplevel 1 set $b]
    uplevel 1 set $b \[set $a\]
    uplevel 1 set $a [list $me]
}

proc getPageOffsets { widthbyheight} {
    global printOption paperSizes
    #puts "wbh=$widthbyheight"
    set pwid 8.5
    set phei 11.0

    foreach v $paperSizes {
	if { "[lindex $v 0]" == "$printOption(papersize)" } {
	    set pwid [lindex $v 1]
	    set phei [lindex $v 2]
	}
    }
    set wid [expr {$pwid - 2* $printOption(hoffset)}]
    set hei [expr {$phei - 2* $printOption(voffset)}]
    if { $printOption(landscape) } {
	swap wid hei
	#	swap pwid phei
    }
    if { $wid / $hei  < $widthbyheight  } {
	# width dominates
	set iwid $wid
	set ihei [expr {$wid / $widthbyheight }]
	append opts " -pagewidth [set wid]i"
    } else {
	set ihei $hei
	set iwid [expr {$hei * $widthbyheight }]
	append opts " -pageheight [set hei]i"
    }

    #-pagex = left margin (whether landscape or not)
    #-pagey = right margin (whether landscape or not)
    #-pagewidth becomes vertical height if landscape
    #-pageheight becomes horiz width if landscape

    append opts " -pagex [expr {$pwid / 2.0}]i -pagey [expr {$phei / 2.0}]i "

    if { $printOption(landscape) } {
	append opts " -rotate $printOption(landscape)"
    }
    return $opts
}

global printOption
set printOption(setupDone) 0

proc getEnv { name } {
    global env
    if { [catch { set tem $env($name) } ] } { return "" }
    return $tem
}
proc setPrintOptions { lis } {
    global browser_version
    global printOptions printOption printSetUpDone
    if { !$printOption(setupDone) } {
	set printOption(setupDone) 1
	getOptions $printOptions $lis -allowOtherKeys 1 \
		-setdefaults [catch { source [getEnv HOME]/.printOptions }] -usearray printOption
    }
}

proc mkentryPr { w var text buttonFont }  {
    set fr $w ; frame $fr
    uplevel 1 append topack [list " $fr"]
    label $fr.lab1
    label $fr.lab -text "$text:" -font $buttonFont -width 0
    entry $fr.e -width 20 -textvariable $var -font $buttonFont
    pack $fr.lab1 -side left -expand 1 -fill x
    pack $fr.lab -side left
    pack $fr.e -side right -padx 3 -fill x
}


proc mkPrintDialog { name args } {
    global printSet argv env printOptions printOption printSetUpDone paperSizes buttonfont

    set canv [assoc -canvas $args ]
    set buttonFont [assoc -buttonfont $args $buttonfont]
    catch { destroy $name }
    set dismiss "destroy $name"
    if { "$canv" == "" } {
	catch {destroy $name}
	toplevel $name
	wm geometry $name -0+20

    } else {
        $canv delete printoptions
        set name [winfo parent $canv].printoptions
	# set name $canv.fr1
        catch {destroy $name}
	frame $name -borderwidth 2 -relief raised
	
	set item [$canv create window [$canv canvasx 10] [$canv canvasy  10] -window $name -anchor nw -tags printoptions]
        $canv raise printoptions
	set dismiss "$canv delete $item; destroy $name "
    }

    frame $name.fr

    set w $name.fr
    label $w.msg  -wraplength 600 -justify left -text [mc "Encapsulated PostScript File Options"] -font $buttonFont
    pack $w
    pack $w.msg
    set wb $w.buttons
    frame $wb
    pack $wb -side left -fill x -pady 2m
    set topack ""
    catch { set printOption(psfilename) \
	    [file nativename $printOption(psfilename)]}
    set win [winfo parent $canv]
    button $wb.save -text [mc "Save"] -font $buttonFont -command "destroy $name; writePostscript $win; $canv delete printoptions"
    button $wb.cancel -text [mc "Cancel"] -font $buttonFont -command "destroy $name ; $canv delete printoptions"
    set writefile "Save"
    mkentryPr  $wb.psfilename printOption(psfilename) [mc "Postscript filename"] $buttonFont
    mkentryPr  $wb.hoffset printOption(hoffset) [mc "Left margin (inches)"] $buttonFont
    mkentryPr  $wb.voffset printOption(voffset) [mc "Top margin (inches)"] $buttonFont
    eval pack $topack -expand 1

    foreach v  $paperSizes {
	set papersize [lindex $v 0]
        set lower [string tolower $papersize]
        radiobutton $wb.$lower -text [lindex $v 0] -variable printOption(papersize) \
		-value [lindex $v 0] -font $buttonFont -highlightthickness 0
	pack $wb.$lower -pady 2 -anchor w -fill x
    }

    checkbutton $wb.b1 -text [mc "Center on Page"] -variable printOption(centeronpage) -relief flat -font $buttonFont
    checkbutton $wb.b2 -text [mc "Landscape Mode"] -variable printOption(landscape) -relief flat -font $buttonFont
    pack $wb.b1 $wb.b2

    frame $w.grid
    pack $w.grid -expand yes -fill both -padx 1 -pady 1
    pack $wb.save $wb.cancel
    grid rowconfig    $w.grid 0 -weight 1 -minsize 0
    grid columnconfig $w.grid 0 -weight 1 -minsize 0
}

proc markToPrint { win tag title } {
    # puts "$win $tag"
    # bind $win <1> "bindBeginDrag $win %x %y $tag [list $title]"
    pushBind $win <1> "$win delete printrectangle ; popBind $win <1>"
    pushBind $win <1> "bindBeginDrag $win %x %y $tag [list $title]; popBind $win <1>"
}

proc bindBeginDrag { win x y tag title } {
    $win delete $tag printrectangle
    set beginRect "[$win canvasx $x] [$win canvasy $y]"
    set it1 [eval $win create rectangle $beginRect $beginRect -tags $tag -width 3]
    set old [bind $win <B1-Motion>]
    set new "eval $win coords $it1 \
	    $beginRect \[$win canvasx %x\] \[$win canvasy %y\]; \
	    "
    if { "$old" == "$new" } {set old ""}
    #mike FIXME: rip this out
    bind $win <B1-Motion> $new
    bind $win <ButtonRelease-1> "bind $win <B1-Motion> [list $old];\
	    bind $win <ButtonRelease-1> {} ; unbindAdjustWidth $win $tag [list $title];"
}

proc unbindAdjustWidth { canv tag title } {
    set win [winfo parent $canv]
    global printOption

    set it [$canv find withtag $tag]
    set co1 [$canv coords $tag]
    set co [$canv coords $it]
    # if { "$co" != "$co1" } {puts differ,$co1,$co}
    desetq "x1 y1 x2 y2" $co
    set center [expr { ($x1+$x2 )/2}]
    set h [expr {$y2 - $y1}]
    set it [$canv find withtag $tag]
    set new [$canv create rectangle $x1 $y1 $x2 $y2 -outline white -width [expr {$h* .04}] -tags [concat $tag bigger] ]

    # puts "<marginTicks $canv $x1 $y1 $x2 $y2 printrectangle>"
    marginTicks $canv [storx$win $x1] [story$win $y2] [storx$win $x2] [story$win $y1] "printrectangle marginticks"
    desetq "a1 b1 a2 b2" [$canv bbox $new]
    set textit [$canv create text $center [expr {$y1 - $h *.03}] \
	    -font [font create -family Courier -size 14 -weight bold] -text "$title" \
	    -anchor s -tags [concat $tag bigger title]]

    set bb [$canv bbox $textit]
    $canv create rectangle $a1 [lindex $bb 1]  $a2 [expr {$y1 - 0.02 * $h}]  -tags $tag -fill white -outline {}
    $canv itemconfig $it -width [expr {$h *.002}]
    $canv raise $it
    $canv raise $textit
    $canv raise marginticks
    if { $printOption(domargin) == 0 } {
	$canv delete marginticks
    }

    $canv create text [expr {($a1 + $a2)/2.0}] [expr {$y2 + .01*$h  }] -anchor nw -tag $tag
    # puts h=$h

}


proc getPSBbox  { } {
    set fi [open /home/wfs/sdfplot.ps r]
    set me [read $fi 500]
    regexp {BoundingBox: (-*[0-9]+) (-*[0-9]+) (-*[0-9]+) (-*[0-9]+)} $me junk x1 y1 x2 y2
    set w [expr {72 * 8.5}]
    set h [expr {72 * 11}]
    # puts "hei=[expr {$y2-$y1}],tm=[expr {$h - $y2}],bm=$y1"
    # puts "wid=[expr {$x2-$x1}],lm=$x1,rm=[expr {$w - $x2}]"
    # puts "hei=[expr {($y2-$y1)/72.0}],tm=[expr {($h - $y2)/72.0}],bm=([expr {$y1/72.0}])"
    #puts "wid=[expr {($x2-$x1)/72.0}],lm=([expr {$x1/72.0}]),rm=[expr {($w - $x2)/72.0}]"
    close $fi
}


## endsource printops.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Push.tcl,v 1.4 2003-01-22 02:59:02 mikeclarkson Exp $
#
###### push.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################



#
#-----------------------------------------------------------------
#
# pushl --  push VALUE onto a stack stored under KEY
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

global __pushl_ar
proc pushl { val key  } {
    global __pushl_ar
    append __pushl_ar($key) " [list $val]"
}


#
#-----------------------------------------------------------------
#
# peekl --  if a value has been pushl'd under KEY return the
# last value otherwise return DEFAULT.   If M is supplied, get the
# M'th one pushed... M == 1 is the last one pushed.
#  Results:  a previously pushed value or DEFAULT
#
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc peekl {key default {m 1}} {
    global __pushl_ar
    if {![info exists __pushl_ar($key)]} {
	return $default
    } elseif { [catch { set val [set __pushl_ar($key) ] } ] } {
	return $default
    } else {
	set n [llength $val]
	if { $m > 0 && $m <= $n } {
	    return [lindex $val [incr n -$m]]
	} else {
	    return $default
	}
    }
}



#
#-----------------------------------------------------------------
#
# popl --  pop off  last value stored under KEY, or else return DFLT
#
#  Results: last VALUE stored or DEFAULT
#
#  Side Effects: List stored under KEY becomes one shorter
#
#----------------------------------------------------------------
#
proc popl { key  dflt} {
    global __pushl_ar

    if { [catch { set val [set __pushl_ar($key) ] } ] } {
	return $dflt
    } else {
	set n [llength $val]
	set result [lindex $val [incr n -1]]
	
	if { $n > 0 } {
	    set __pushl_ar($key) [lrange $val 0 [expr {$n -1}]]
	} else {
	    unset __pushl_ar($key)
	}
	return $result
    }
}


#
#-----------------------------------------------------------------
#
# clearl --  clear the list stored under KEY
#
#  Result: none
#
#  Side Effects:  clear the list stored under KEY
#
#----------------------------------------------------------------
#
proc clearl { key } {
    global __pushl_ar
    catch { unset __pushl_ar($key) }
}



## endsource push.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Plotconf.tcl,v 1.26 2011-03-15 01:16:10 villate Exp $
#
###### plotconf.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

proc makeFrame { w type } {
    global   writefile doExit fontSize buttonfont maxima_priv
    set win $w
    if { "$w" == "." } {
        set w ""
    } else {
	catch { destroy $w}
	
	frame $w
	# toplevel $w
	# set w $w.new
	# frame $w
	# puts "making $w"	
	
    }

    set dismiss "destroy $win"
    catch { set  parent [winfo parent $win]
	if { "$parent" == "." } {
	    set dismiss "destroy ."
	}
	if { [string match .plot* [winfo toplevel $win]] } {
	    set dismiss "destroy [winfo toplevel $win]"
	}
    }

    if { "$doExit" != "" } {set dismiss $doExit } 	
    oset $w type $type

    frame $w.grid
    #positionWindow $w
    set c $w.c
    oset $win c $c
    bboxToRadius $win

    set buttonFont $buttonfont
    oset $win buttonFont $buttonfont

    label $w.position -text [mc "Pointer Coordinates"] -background white -font $buttonFont
    set dismiss [concat $dismiss "; clearLocal $win "]
    set mb [frame $w.menubar]
    pack $mb -fill x
    button $mb.close -image ::img::close -text [mc "Close"] \
        -command $dismiss -relief flat -width 30 -height 30
    button $mb.config -image ::img::config -text [mc "Config"] \
        -command "doConfig$type $win" -relief flat -width 30 -height 30
    button $mb.replot -image ::img::replot -text [mc "Replot"] \
        -command "replot$type $win" -relief flat -width 30 -height 30
    button $mb.save  -image ::img::save -text [mc "Save"] \
        -command "mkPrintDialog .dial -canvas $c -buttonfont $buttonFont " \
        -relief flat -width 30 -height 30
    button $mb.zoomin -image ::img::zoom-in -text [mc "Zoom in"] \
        -command "doZoom $win 1" -relief flat -width 30 -height 30
    button $mb.zoomout -image ::img::zoom-out -text [mc "Zoom out"] \
        -command "doZoom $win -1" -relief flat -width 30 -height 30
    button $mb.help -image ::img::help -text [mc "Help"] \
        -command "doHelp$type $win" -relief flat -width 30 -height 30
    pack $mb.close $mb.config $mb.replot $mb.save $mb.zoomin $mb.zoomout -side left
    pack $mb.help -side right
    scrollbar $w.hscroll -orient horiz -command "$c xview"
    scrollbar $w.vscroll -command "$c yview"
    # -relief sunken
    canvas $c  -borderwidth 2 \
	-scrollregion {-1200 -1200 1200 1200} \
	-xscrollcommand "$w.hscroll set" \
	-yscrollcommand "$w.vscroll set" -cursor arrow -background white
    # puts "$c config  -height [oget $win height] -width [oget $win width] "
    set buttonsLeft 1
    set wid [oget $win width]
    catch {$c config  -height [oget $win height] -width  $wid
	oset $win oldCheight [oget $win height]
	oset $win oldCwidth $wid
    }
    # puts "$c height =[$c cget   -height],$c width =[$c cget   -width]"
    # bind $c <2> "$c scan mark %x %y"

    bind $c <B3-Motion> "$c scan dragto %x %y"
    bind $c <3> "$c scan mark %x %y"
    bind $c <B3-Motion> "$c scan dragto %x %y"
    bind $c <Motion> "showPosition $w %x %y"
    bind $c <Configure> "reConfigure $c %w %h"
    ##bind $c <Enter> "raise $win.position"
    ##bind $c <Leave> "after 200 lower $win.position"

    $w.position config -background [$c cget -background]

    ##pack  $wb.dismiss $wb.help $wb.zoom   \
    ##	$wb.postscript $wb.markrect $wb.replot $wb.config -side top -expand 1 -fill x
    if { 0 } {
	pack $w.hscroll -side bottom -expand 1 -fill x
	pack $w.vscroll -side right -expand 1 -fill y
    }
    pack $w.c -side right -expand 1 -fill both

    pack $w

    # update
    #    set wid [ winfo width $win]
    #    if { $wid > [      $c cget -width ] } {
    #    $c config -width $wid
    #	    oset $win width $wid
    #    }

    # place the coordinates in the lower right-hand corner.
    place $w.position -in $w.c -relx 0.99 -rely 0.99 -anchor se

    raise $w.position
    focus $w
    bind $w <Configure> "resizePlotWindow $w %w %h"
    bind $w <Control-w> $dismiss
    bind $w <Configure> "resizePlotWindow $w %w %h"
    addSliders $w
    return $w
}

proc mkentry { newframe textvar text buttonFont } {
    frame $newframe
    set parent $newframe
    set found 0
    while { !$found } {
	set parent [winfo parent $parent]
	if { "$parent" == "" } { break }
	if { ![catch {  set type [oget $parent type] } ] } {
	    global plot[set type]Options
	    foreach v [set plot[set type]Options] {
		if { "[oloc $parent [lindex $v 0]]" == "$textvar" } {
		    setBalloonhelp $parent $newframe [lindex $v 2]
		    set found 1
		    break

		}
	    }
	}
    }
    label $newframe.lab1
    label $newframe.lab -text "$text:" -font $buttonFont -width 0
    entry $newframe.e -width 20 -textvariable $textvar -font $buttonFont
    pack $newframe.lab1 -side left -expand 1 -fill x
    pack $newframe.lab -side left
    pack $newframe.e -side right -padx 3 -fill x
    # pack $newframe.lab $newframe.e -side left -padx 3 -expand 1 -fill x
}


proc doHelp { win msg } {
    makeLocal $win c
    set atx [$c canvasx 0]
    set aty [$c canvasy 0]
    $c create rectangle [expr {$atx -1000}] [expr  {$aty -1000}] 10000 10000 -fill white -tag help

    $c create text [expr {$atx +10}] [expr {$aty + 10.0}] -tag help  -anchor nw  -width 400 -text $msg

    pushBind $c <1> "$c delete help; popBind $c <1>"
}

proc pushBind { win key action } {
    pushl [bind $win $key] [list $win $key ]
    bind $win $key $action
}

proc popBind { win key  } {
    set binding [popl [list $win $key] {}]

    bind $win $key $binding
}

# exit if not part of openmath browser
proc maybeExit { n } {
    if { "[info proc OpenMathOpenUrl]" != "" } {
	uplevel 1 return
    } else {
	exit 0
    }
}

proc showPosition { win x y } {
    # global position c
    makeLocal $win c
    # we catch so that in case have no functions or data..
    catch {
	$win.position config -text \
	    "[format {(%.6g,%.6g)}  [storx$win [$c canvasx $x]] [story$win [$c canvasy $y]]]"
    }
}

proc doZoom { win direction } {
    set zf [oget $win zoomfactor]
    if { $direction < 0 } {
	set zf 	"[expr {1/[lindex $zf 0]}] [expr {1/[lindex $zf 1]}]"
    }
    eval doZoomXY $win $zf
}



#
#-----------------------------------------------------------------
#
# doZoomXY --  given screen coordinates (x,y) and factors (f1,f2)
#  perform a scaling on the canvas, centered at (x,y) so that
#  the distance in the x direction from this origin is multiplied by f1
#  and similarly in the y direction
#  Results:
#
#  Side Effects: scale the canvas, and set new transforms for translation
#   from real to canvas coordinates.
#----------------------------------------------------------------
#

proc doZoomXY { win facx facy } {
    if { [catch {
	makeLocal $win c transform
    } ] } {
	# not ready
	return
    }

    set x [$c canvasx [expr {[oget $win oldCwidth]/2.0}]]
    set y [$c canvasy [expr {[oget $win oldCheight]/2.0}]]

    $c scale all $x $y $facx $facy

    set ntransform [composeTransform \
			"$facx 0 0 $facy [expr {(1-$facx)* $x}] [expr {(1-$facy)* $y}]" \
			$transform  ]
    oset $win transform $ntransform
    getXtransYtrans $ntransform rtosx$win rtosy$win
    getXtransYtrans [inverseTransform $ntransform] storx$win story$win
    # axisTicks $win $c
}


#
#-----------------------------------------------------------------
#
# scrollPointTo --  attempt to scroll the canvas so that point
#  x,y on the canvas appears at screen (sx,sy)
#
#  Results: none
#
#  Side Effects: changes x and y view of canvas
#
#----------------------------------------------------------------
#
proc scrollPointTo { c x y sx sy } {
    desetq "x0 y0 x1 y1" [$c cget -scrollregion]
    $c xview moveto [expr { 1.0*($x-$x0-$sx)/($x1-$x0)} ]
    $c yview moveto [expr { 1.0*($y-$y0-$sy)/($y1-$y0)} ]
}



#
#-----------------------------------------------------------------
#
# reConfigure --
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc reConfigure { c width height  } {
    set w [winfo parent $c]
    if { [catch { makeLocal $w oldCwidth oldCheight } ] } {
	oset $w oldCwidth $width
	oset $w oldCheight $height
	return
    }
    set oldx [$c canvasx [expr {$oldCwidth/2.0}]]
    set oldy [$c canvasy [expr {$oldCheight/2.0}]]
    doZoomXY $w [expr {1.0*$width/$oldCwidth}] [expr {1.0*$height/$oldCheight}]

    scrollPointTo $c $oldx $oldy [expr {$width/2.0}] [expr {$height/2.0}]
    # update
    oset $w oldCwidth $width
    oset $w oldCheight $height
}

proc writePostscript { win } {
    global  printOption argv
    makeLocal $win c transform transform0 xmin ymin xmax ymax
    set rtosx rtosx$win ; set rtosy rtosy$win
    drawPointsForPrint $c
    if { "[$c find withtag printrectangle]" == "" } {
	$c create rectangle [$c canvasx 0] [$c canvasy 0] \
          [$c canvasx [$c cget -width ]] [$c canvasy [$c cget -height ]] \
          -tags printrectangle -outline white	
    }

    set bbox [eval $c bbox [$c find withtag printrectangle]]
    desetq "x1 y1 x2 y2" $bbox
    # set title "unknown plot"
    # catch { set title [eval $printOption(maintitle)] }
    # $c create text [expr {($x1 + $x2)/2}]  [expr {$y1 + .04 * ($y2 - $y1)}] \
    # 	    -anchor center -text $title -tag title

    update
    #set diag [vectorlength [expr {$y1-$x1}] [expr {$y2-$x2}]]
    #  get rid of little arrows that creep onto the outside, ie let
    #  the blank rectangle cover them.
    #set x1 [expr {$x1+.01 * $diag}]
    #set x2 [expr {$x2-.01 * $diag}]
    #set y1 [expr {$y1+.01 * $diag}]
    #set y2 [expr {$y2-.01 * $diag}]

    # Set up font replacement list
    catch {set fontMap([font create -family {BitstreamVeraSansMono} -size 10]) [list Courier 14]}
    catch {set fontMap([font create {helvetica 16 normal}]) [list Helvetica 16]}
    set com "$c postscript  \
      	    -x [expr {($x1 - 35)}] -y [expr {($y1 -25)}] \
	    -width [expr {($x2 - $x1 + 60)}] \
            -height [expr {($y2 - $y1 + 45)}] \
            -fontmap fontMap \
	    [getPageOffsets [expr {($x2 - $x1 + 55)/(1.0*($y2 - $y1 + 45))}] ]"

    #puts com=$com
    set output [eval $com]
    set fi [open $printOption(psfilename) w]
    puts $fi $output
    close $fi
}


#
#-----------------------------------------------------------------
#
# ftpDialog --  open up a dialog to send ftpInfo(data) to a file
# via http and ftp.   The http server can be specified.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc ftpDialog { win args } {
    global ftpInfo buttonFont fontSize
    set fr ${win}plot
    set usefilename [assoc -filename $args  0]
    if { "$usefilename" != "0"} {
	set ftpInfo(filename) $usefilename
	set usefilename 1
    }
    catch { destroy $fr }
    set ftpInfo(percent) 0

    frame $fr -borderwidth 2 -relief raised
    if { [catch { set ftpInfo(directory) } ] } { set ftpInfo(directory) homework }
    label $fr.title -text [mc "Ftp Dialog Box"]
    mkentry $fr.host ftpInfo(host) [mc "host to write file on"] $buttonFont
    mkentry $fr.viahost ftpInfo(viahost) [mc "host to write to via"] $buttonFont
    mkentry $fr.username ftpInfo(username) [mc "Your User ID on host"] $buttonFont
    mkentry $fr.password ftpInfo(password) [mc "Your password on host"] $buttonFont
    $fr.password.e config -show *
    mkentry $fr.directory ftpInfo(directory) [mc "remote subdirectory for output"] $buttonFont

    if { $usefilename } {
	mkentry $fr.filename ftpInfo(filename) [mc "filename "] $buttonFont
    } else {
	mkentry $fr.chapter ftpInfo(chapter) [mc "chapter "] $buttonFont
	mkentry $fr.section ftpInfo(section) [mc "section"] $buttonFont
	mkentry $fr.problemnumber ftpInfo(number) [mc "Problem number"] $buttonFont
    }
    scale   $fr.scale -orient horizontal -variable ftpInfo(percent) -length 100
    button $fr.doit -text [mc "Send it"] -command "doFtpSend $fr" -font $buttonFont
    button $fr.cancel -text [mc "Cancel"] -command "destroy $fr" -font $buttonFont
    set ftpInfo(message) ""
    label $fr.message  -width 30 -height 3 -textvariable ftpInfo(message) -font $buttonFont
    eval pack  [winfo  children $fr] -side top
    raise $fr
    place $fr -in $win -relx .5 -rely .5 -anchor center
}

proc doFtpSend { fr } {
    global ftpInfo om_ftp

    set error ""
    if { [winfo exists $fr.filename] } {
	set filename $ftpInfo(filename)
	set check "host username directory filename"
    } else {
	set check "host username directory chapter section number"
    }
    foreach v $check {
	if { $ftpInfo($v) == "" } {
	    if  { "$error" == "" } { set error [concat [mc "Failed to specify"] "$v " } else {
		append error ", $v"}
	}
    }
    if { "$error" != "" } {
	set ftpInfo(message) $error
	return -1
    }
    if { [winfo exists $fr.chapter] } {
	set filename "$ftpInfo(chapter).$ftpInfo(section)-$ftpInfo(number).ps"
    }


    set res [submitFtp $ftpInfo(viahost) $ftpInfo(host) $ftpInfo(username) $ftpInfo(password) $ftpInfo(directory) $filename]
    if { "$res" == 1 }  {
	after 1000 "destroy $fr"
    }
    return $res

    #    set counter [ ftp $ftpInfo(host) $ftpInfo(username) $ftpInfo(password)]
    #    if { $counter < 0 } {
    #	set ftpInfo(message) [concat "Failed:" $om_ftp($counter,log)]
    #	return -1
    #    }

    #     if { [ftpDoCd $counter $ftpInfo(directory)] < 0 &&
    #          [ftpDoMkdir $counter $ftpInfo(directory)] > -10 &&
    #        [ftpDoCd $counter $ftpInfo(directory)] < 0 } {
    # 	set ftpInfo(message) [concat "Failed:" $om_ftp($counter,log)]
    # 	return -1
    #     }


    #     set res [ftpDoStore $counter $ftpInfo(chapter).$ftpInfo(section)-$ftpInfo(number).ps $ftpInfo(data)]
    #     if { $res < 0 } {
    # 	set ftpInfo(message) "Failed: $om_ftp($counter,log)"
    # 	return -1
    #     } else {
    # 	set ftpInfo(message) "Wrote $ftpInfo(directory)/$ftpInfo(chapter).$ftpInfo(section)-$ftpInfo(number).ps"
    # 	after 1000 destroy $fr
    #     }
    #     ftpClose $counter
}

proc vectorlength { a b } {
    return [expr {sqrt($a*$a + $b * $b)} ]
}

proc setupCanvas { win } {
    makeLocal $win   xcenter xradius ycenter yradius

    oset $win xmin [expr {$xcenter - $xradius}]
    oset $win xmax [expr { $xcenter + $xradius}]
    oset $win ymin [expr { $ycenter - $yradius}]
    oset $win ymax [expr { $ycenter + $yradius} ]

}


#
#-----------------------------------------------------------------
#
# compose --  A and B are transformations of the form "origin scalefac"
# and composing them means applying first b then a, as in a.b.x
#  "o s" . x ==> (x-o)*s + o
#  Results: the "origin scalefac" which corresponds to the composition.
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc compose { a b } {
    return  "[expr {-[lindex $a 1]*[lindex $b 0]*[lindex $b 1] \
      +[lindex $a 1]*[lindex $b 0]-[lindex $a 0]*[lindex $a 1] \
      +[lindex $a 0]}] [expr {[lindex $a 1]*[lindex $b 1]}]"
}

# the following two have been replaced
# proc sparseList { s } {
#     if  { [catch {
# 	set val [parseConvert "$s" -variables "x y t"] } err ] } {
# 	    error "Syntax error with `$s'\n $err"
# 	}
# 	return [lindex $val 0]
#     }
#
# proc sparse { s } {
#     set val [sparseList $s]
#     set first $val
#     if { [llength $first] != 1 } {
# 	error "only one function wanted" }
# 	
# 	return [lindex $first 0]
#    }

proc sparseListWithParams { form variables paramlist } {
    set tem [parseConvert $form -doall 1]
    #puts tem=$tem
    set params [splitParams $paramlist]
    if { [catch {set res [substParams [lindex $tem 0] $variables $params] }\
	      err ] } {
	set vars [lindex $tem 1]
	set all $variables
	foreach { v val }  $params { lappend all $v}
	foreach v $vars { if { [lsearch $all [string range $v 1 end]] < 0 } {
	    error [M [mc "The variable %s appeared in %s but was not in allowed variables: %s or in parameters: %s"] "`[string range $v 1 end]'" "$form" "{$variables}" "{$paramlist}" ]
	}
	}
	error [M [mc "The form %s may involve variables other than %s or the parameters %s, or the latter may have invalid expressions: %s"] "$form" "{$variables}" "{$paramlist}" "$err" ]
    }
    return $res
}

proc sparseWithParams { form variables params } {
    set tem [sparseListWithParams $form $variables $params]
    if { [llength $tem ] > 1 } { error [concat [mc "only wanted one function:"] "$form"]}
    lindex $tem 0
}



#
#-----------------------------------------------------------------
#
# myVarSubst --  into FORM substitute where
# listVarsVals where each element of this list may mention
# the previous values eg "k 7 ll sin(k+8)"
# eg:
#myVarSubst [lindex [parseConvert "k*x+l" -doall 1] 0] {x $x k 27+4 l 93+k^3}
# ==> {((31 * $x) + 29884.0)}
#
#  Results: FORM with the substitutions done
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc myVarSubst { form listVarsVals } {
    foreach {_u _v} $listVarsVals {
	if { "\$$_u" == "$_v" } {
	    set $_u $_v
	} else {
	    set _f1 [lindex [parseConvert  $_v -doall 1] 0]
	    set $_u [expr [lindex $_f1 0]]
	    # puts "$_u = [set $_u]"
	}
    }
    subst -nobackslashes -nocommands $form

}

proc splitParams { paramlist } {
    set params ""
    foreach v [split $paramlist ,] {
	set tem [split $v =]
	if { [llength $tem] == 2 } {
	    lappend params [lindex $tem 0] [lindex $tem 1]
	}
    }
    return $params
}



#
#-----------------------------------------------------------------
#
# substParams --  substitute into FORM keeping VARIABLES as they are
# and the PARAMLIST (of the form k=23, l=k+7,...) into FORM
#
#  Results: substituted FORM
#
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc substParams { form variables params } {
    foreach v $variables { lappend params $v \$$v}
    set res [myVarSubst $form $params]
    return $res
}





#
#-----------------------------------------------------------------
#
# setUpTransforms --  set up transformations for the canvas of WINDOW
# so that the image is on FACTOR fractionof the window
# these transforms are used for real to screen and vice versa.
#  Results:
#
#  Side Effects: transform functions rtosx$win rtosy$win storx$win story$win
#  are defined.
#
#----------------------------------------------------------------
#
proc setUpTransforms { win fac } {
    makeLocal $win xcenter ycenter xradius yradius c

    set delx [$c cget -width]
    set dely [$c cget -height]
    set f1 [expr {(1 - $fac)/3.0}]

    set x1 [expr {2* $f1 *$delx}]
    set y1 [expr {$f1 *$dely}]
    set x2 [expr {$x1 + $fac*$delx}]
    set y2 [expr {$y1 + $fac*$dely}]

    set xmin [expr {$xcenter - $xradius}]
    set xmax [expr {$xcenter + $xradius}]
    set ymin [expr {$ycenter - $yradius}]
    set ymax [expr {$ycenter + $yradius}]

    oset $win xmin $xmin
    oset $win xmax $xmax
    oset $win ymin $ymin
    oset $win ymax $ymax

    oset $win transform [makeTransform "$xmin $ymin $x1 $y2" "$xmin $ymax $x1 $y1 " "$xmax $ymin $x2 $y2"]
    set transform [makeTransform "$xmin $ymin $x1 $y2" "$xmin $ymax $x1 $y1 " "$xmax $ymin $x2 $y2"]
    oset $win transform $transform
    oset $win transform0 $transform

    getXtransYtrans $transform rtosx$win rtosy$win
    getXtransYtrans [inverseTransform $transform] storx$win story$win

}

proc inputParse { in } {
    if { [regexp -indices \
	      {D\[([a-zA-Z][0-9a-zA-Z]*[ ]*),([a-zA-Z][0-9a-zA-Z]*[ ]*)\] *=} \
	      $in all1 i1 i2] } {
	set v1 [getOneMatch $in $i1]
	set v2 [getOneMatch $in $i2]
	set s1 [string range $in [lindex $all1 1] end]

	if { [regexp -indices {,[ \n]*D\[([a-zA-Z][0-9a-zA-Z]*[ ]*),([a-zA-Z][0-9a-zA-Z]*[ ]*)\] *=} \
		  $s1 all2 i1 i2] } {
	    set v3  [getOneMatch $s1 $i1]
	    set v4 [getOneMatch $s1 $i2]
	    set end [string first \} $s1 ]
	    set form2 [string range $s1 [expr {1 + [lindex $all2 1]}] [expr {$end -1}]]
	    if { "$v4" != "$v2" } {error [concat [mc "different variables"] "$v2" [mc "and"] "$v4"]}

	    set form1 [string range $in [expr {1 + [lindex $all1 1]}] [expr {[lindex $all2 0] + -1 + [lindex $all1 1]}]]
	    return [list  $v2 $v1 $v3 $form1 $form2]
	    # puts "v1=$v1,form1=$form1,form2=$form2"
	}
    }
}

proc composeTransform { t1 t2  } {
    desetq "a11 a12 a21 a22 e1 e2" $t1
    desetq "b11 b12 b21 b22 f1 f2" $t2
    return  [list \
		 [expr {$a11*$b11+$a12*$b21}] \
		 [expr {$a11*$b12+$a12*$b22}] \
		 [expr {$a21*$b11+$a22*$b21}] \
		 [expr {$a22*$b22+$a21*$b12}] \
		 [expr {$a11*$f1+$a12*$f2+$e1}] \
		 [expr {$a21*$f1+$a22*$f2+$e2}] ]
}



#
#-----------------------------------------------------------------
#
# makeTransform --  Given three points mapped to three other points
# write down the affine transformation (A.X+B) which performs this.
# the arguments are of the form "x1 y1 u1 v1" "x2 y2 u2 v2" "x3 y3 u3 v3"
# where (x1,y1) --> (u1,v1)  etc.
#  Results: an affine transformation "a b c d e f" which is
#     [ a  b ]  [ x1 ] + [ e ]
#     [ c  d ]  [ y1 ]   [ f ]
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc makeTransform { P1 P2 P3 } {
    desetq  "X1 Y1 U1 V1" $P1
    desetq  "X2 Y2 U2 V2" $P2
    desetq  "X3 Y3 U3 V3" $P3
    set tem [expr {double((($X2-$X1)*$Y3+($X1-$X3)*$Y2+($X3-$X2)*$Y1))}]
    set A [expr {(($U2-$U1)*$Y3+($U1-$U3)*$Y2+($U3-$U2)*$Y1) \
		     /$tem}]
    set B [expr {-(($U2-$U1)*$X3+($U1-$U3)*$X2+($U3-$U2)*$X1) \
		     /$tem}]
    set E [expr {(($U1*$X2-$U2*$X1)*$Y3+($U3*$X1-$U1*$X3)*$Y2+($U2*$X3-$U3*$X2)*$Y1) \
		     /$tem}]
    set C [expr {(($V2-$V1)*$Y3+($V1-$V3)*$Y2+($V3-$V2)*$Y1) \
		     /$tem}]
    set D [expr {-(($V2-$V1)*$X3+($V1-$V3)*$X2+($V3-$V2)*$X1) \
		     /$tem}]
    set F [expr {(($V1*$X2-$V2*$X1)*$Y3+($V3*$X1-$V1*$X3)*$Y2+($V2*$X3-$V3*$X2)*$Y1) \
		     /$tem}]
    set xf ""
    set yf ""
    if { $B == 0  && $C == 0 } {
	set xf "$A*\$X+$E"
	set yf "$D*\$Y+$F"
    }
    return [list $A $B $C $D $E $F]
}


#
#-----------------------------------------------------------------
#
# getXtransYtrans --   If the x coordinate transforms independently
#  of the y and vice versa, give expressions suitable for building a
# proc.
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc getXtransYtrans { transform p1 p2 } {
    desetq "a b c d e f"  $transform
    if { $b == 0  && $c == 0 } {
	proc $p1 { x } "return \[expr {$a*\$x+$e}\]"
	proc $p2 { y } "return \[expr {$d*\$y+$f} \]"
	return 1
    }
    return 0
}


#
#-----------------------------------------------------------------
#
# inverseTransform --   Find the inverse of an affine transformation.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc inverseTransform { transform } {
    desetq "a b c d e f" $transform
    set det [expr {double($a*$d - $b*$c)}]
    return [list [expr {$d/$det}] [expr {- $b / $det }] [expr {- $c / $det}] [expr {$a / $det}]  [expr {($b*$f-$d*$e)/ $det }] [expr {-($a*$f-$c*$e)/ $det}]]

}


#
#-----------------------------------------------------------------
#
# getTicks --  given an interval (a,b) subdivide it and
# calculate where to put the ticks and what to print there.
# we want DESIRED number of ticks, but we also want the ticks
# to be at points in the real coords of the form .2*10^i or .5*10^j
#  Results: the ticks
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc getTicks { a b n } {
    set len [expr {(($b - $a))}]
    if { $len < [expr {pow(10,-40)}] } { return ""}
    set best 0
    foreach v { .1 .2 .5 } {
	# want $len/(.1*10^i) == $n
	set val($v)  [expr {ceil(log10($len/(double($n)*$v)))}]
	set use [expr {$v*pow(10,$val($v))}]
	set fac [expr {1/$use}]
	set aa [expr {$a * $fac}]
	set bb [expr {$b * $fac}]
	set j [expr {round(ceil($aa)) }]
	set upto [expr {floor($bb) }]
	if { $upto-$j > 14} {
	    set step 5
	} else {
	    set step 2
	}
	set ticks ""
	while { $j <= $upto } {
	    set tt [expr {$j / $fac}]
	    if { $j%$step == 0 } {
		append ticks " { $tt $tt }"
	    } else  {
		append ticks " $tt"
	    }
	    incr j
	}
	set answer($v) $ticks
	set this [llength $ticks]
	if { $this  > $best } {
	    set best $this
	    set at $v
	}
	#puts "for $v [llength $ticks] ticks"
    }
    #puts "using $at [llength $answer($at)]"

    return $answer($at)
}

proc axisTicks { win c }  {
    $c delete axisTicks
    if { ![catch {oget $win noaxisticks}] } { return }
    set swid [$c cget -width]
    set shei [$c cget -height]
    set x1 [storx$win [$c canvasx 0]]
    set y1 [story$win [$c canvasy 0]]
    set x2 [storx$win [$c canvasx $swid]]
    set y2 [story$win [$c canvasy $shei]]
    #puts "x1=$x1,y1=$y1,y2=$y2,x2=$x2"
    if { $y1 > 0  &&  $y2 < 0 } {
	set ticks [getTicks $x1 $x2 [expr {$swid/50}] ]
	#puts "ticks=$ticks"
	set eps [expr {.005 * abs($y1 - $y2)}]
	set neps [expr {-.005 * abs($y1 - $y2)}]
	set donext 0
	foreach v $ticks {
	    set x [lindex $v 0]
	    set text [lindex $v 1]
	    if { $donext } {set text [lindex $v 0] ; set donext 0 }
	    if { [lindex $v 0] == 0 } { set text "" ; set donext 1 }
	    #puts " drawTick $c $x 0 0 $neps 0 $eps  $text axisTicks"
	    drawTick $c $x 0 0 $neps 0 $eps  $text axisTicks
	}
    }
    if { 0 < $x2 && 0 > $x1 } {
	set ticks [getTicks $y2 $y1 [expr {$shei/50}]]
	set eps [expr {.005 * ($x2 - $x1)}]
	set neps [expr {-.005 * ($x2 - $x1)}]
	set donext 0
	foreach v $ticks {
	    set y [lindex $v 0]
	    set text [lindex $v 1]
	    if { $donext } {set text [lindex $v 0] ; set donext 0}
	    if { [lindex $v 0] == 0 } { set text "" ; set donext 1}

	    drawTick $c 0 $y $neps 0 $eps 0  $text axisTicks
	}
    }

}


#
#-----------------------------------------------------------------
#
# marginTicks --  draw ticks around the border of window
#  x1,y1  top left x2,y2 bottom right.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc marginTicks { c x1 y1 x2 y2 tag }  {
    global printOption
    set win [winfo parent $c]

    if { ![catch {oget $win noaxisticks}] } { return }
    $c delete marginTicks
    set ticks [getTicks $x1 $x2 $printOption(xticks)]
    # puts "x=$x1 $x2"
    set eps [expr {.008 * ($y1 - $y2)}]
    set neps [expr {-.008 * ($y1 - $y2)}]
    foreach v $ticks {
	set x [lindex $v 0]
	set text [lindex $v 1]
	drawTick $c $x $y1 0 0 0 $eps $text $tag
	drawTick $c $x $y2 0 0 0 $neps {} $tag
	
    }
    #puts "y=$y2,$y1"
    set ticks [getTicks $y1 $y2 $printOption(yticks)]
    set eps [expr {.005 * ($x2 - $x1)}]
    set neps [expr {-.005 * ($x2 - $x1)}]
    set donext 0
    foreach v $ticks {
	set y [lindex $v 0]
	set text [lindex $v 1]
	drawTick $c $x1 $y 0 0 $neps 0 $text $tag
	drawTick $c $x2 $y 0 0 $eps 0 {} $tag
    }
}

proc drawTick {c x y dx dy ex ey n tags} {
    global axisGray     fontCourier8
    set win [winfo parent $c]
    set rtosx rtosx$win ; set rtosy rtosy$win
    set it [$c create line [$rtosx [expr {$x +$dx}]] [$rtosy [expr {$y +$dy}]] [$rtosx [expr {$x +$ex}]] [$rtosy [expr {$y +$ey}]] -fill $axisGray -tags $tags]
    $c lower $it

    if { "$n" != "" } {
	if { $ey > 0 } { set anch s
	} elseif { $ex > 0 } {set anch w
	} elseif { $ex < 0 } {set anch e
	} elseif { $ey < 0 } {set anch n}

	$c create text  [$rtosx [expr {$x +1.5*$ex}]] [$rtosy [expr {$y +1.5*$ey}]] \
	    -text [format "%.8g" $n] -font $fontCourier8 -tags $tags \
	    -anchor $anch
    }
}

proc doConfig { win }  {
    makeLocal $win c buttonFont
    $c delete configoptions
    set canv $c
    # set w $c.config
    set w $win.config
    catch {destroy $w}
    frame $w -borderwidth 2 -relief raised

    label $w.msg  -wraplength 600 -justify left -text [mc "Plot Setup"] -font $buttonFont
    pack $w
    pack $w.msg -side top
    set wb1 $w.choose1
    frame $wb1
    set wb2 $w.choose2
    frame $wb2
    pack $wb1 $wb2 -side left -fill x -pady 2m
    set item [$canv create window [$canv canvasx 10] [$canv canvasy  10] -window $w -anchor nw -tags configoptions]
    button $wb1.dismiss -command  "$canv delete $item; destroy $w " -text "ok" -font $buttonFont
#    button $wb1.printoptions -text [mc "Print Options"] -command "mkPrintDialog .dial -canvas $c -buttonfont $buttonFont " -font $buttonFont

    pack $wb1.dismiss -side top
    return "$wb1 $wb2"
}
# mkentry { newframe textvar text }

# turn off the horrible show_balloons by default.
global show_balloons
set show_balloons 0

proc balloonhelp { win subwin msg } {
    global show_balloons

    if { $show_balloons == 0 } {return}
    linkLocal  [oget $win c] helpPending
    if { [info exists helpPending] } {after cancel $helpPending}
    set helpPending [after 1000 [list balloonhelp1 $win $subwin $msg]]
}

proc balloonhelp1 { win subwin msg } {
    if { ![winfo exists $win] } { return }
    makeLocal $win c buttonFont
    set x0 [winfo rootx $win]
    set y0 [winfo rooty $win]


    set atx [expr {[winfo rootx $subwin] + [winfo width $subwin] - $x0} ]
    set aty [expr {[winfo rooty $subwin] + [winfo height $subwin] - $y0} ]

    set wid [$c cget -width]
    set wid2 [expr {round ($wid /2.0)}]
    set wid10 [expr {round ($wid /10.0)}]

    if { $aty <=1 } { set aty 30 }
    incr aty 10
    incr atx 10
    set atx [$c canvasx $atx]
    set aty [$c canvasy $aty]
    #puts "$atx $aty"
    $c delete balloon
    $c create text $atx $aty -anchor nw -text $msg -font $buttonFont -width $wid2 -fill white -fill black -tags "balloon btext"
    desetq "x1 y1 x2 y2" [$c bbox btext]

    set x1 [expr {$x1 - .3*($x2-$x1)}]
    set x2 [expr {$x2 + .3*($x2-$x1)}]

    set y1 [expr {$y1 - .3*($y2-$y1)}]
    set y2 [expr {$y2 + .3*($y2-$y1)}]

    eval $c create polygon $x1 $y1  $x2 $y1 $x2 $y2 $x1 $y2  -fill beige -tags balloon -smooth 1
    $c raise btext

}

proc setBalloonhelp { win subwin msg } {
    makeLocal $win c
    bind $subwin <Enter> "balloonhelp $win $subwin [list $msg]"
    bind $subwin <Leave> "deleteBalloon $c"
}

proc deleteBalloon { c } {
    linkLocal $c helpPending
    if { [info exists helpPending] } {
	after cancel $helpPending
	unset helpPending
    }
    $c delete balloon
}


#
#-----------------------------------------------------------------
#
# minMax --  Compute the max and min of the arguments, which may
# be vectors or numbers
#
#  Results: list of MIN and MAX
#
#  Side Effects: none
#
#----------------------------------------------------------------
#
proc minMax { args } {
    set max [lindex [lindex $args 0] 0] ; set min $max ;
    foreach vec $args {
	foreach v $vec {
	    if { $v > $max } {set max $v }
	    if { $v < $min} {set min $v }
	}
    }
    return [list $min $max]
}

proc matrixMinMax { list } {
    # compute the min max of the list
    set min +10e300
    set max -10e300
    foreach mat $list {
	foreach row $mat {
	    foreach v [ldelete nam $row] {
		if { $v > $max } {catch  { set max [expr {$v + 0}] }}
		if { $v < $min} {catch  { set min [expr {$v + 0}] }}
	    }
	}
    }
    list $min $max
}

proc omPlotAny { data args } {
    # puts "data=<[lindex $data 0]>"
    set command [list [lindex [lindex $data 0] 0]  -data [lindex $data 0] ]
    if { "[lindex $command 0]" == "plot2d" } {
	lappend command -xfun {}
    }
    foreach v $args { lappend command $v }
    eval $command
    #eval [lindex [lindex $data 0] 0] -xfun [list {}] -data [list [lindex $data 0]] $args
}


proc resizeSubPlotWindows { win wid height } {
    set at [$win yview "@0,0"]
    foreach w [winfo children $win] {
	if { [string match plot* [lindex [split $w .] end]] } {
	    resizePlotWindow $w [winfo width $w] $height
	}
    }
    if { "$at" != "" } { $win yview $at}
}



proc resizePlotWindow  { w width height } {
    if { [winfo width $w.c] <= 1 } {
	after 100 update ;
	return }
    if { ![catch { set tem [oget $w lastResize] } ] && [expr {[clock seconds] - $tem }] < 2 } { return
    } else {
	oset $w lastResize [clock seconds ]
    }
    #puts "resizePlotWindow $w $width $height"

    # return
    set par [winfo parent $w]
    set facx 1.0
    set facy 1.0
    set wid [winfo width $par]
    set hei [winfo height $par]

    if { "[winfo class $par]" == "Text" } {
	set dif 10

	set wid1 $wid ; set hei1 $hei
	#puts "now w=$w"
	#set wid1 [getPercentDim [oget $w widthDesired] width $par]
	catch {set wid1 [getPercentDim [oget $w widthDesired] width $par] }
	catch {set hei1 [getPercentDim [oget $w heightDesired] height $par] }
	set wid [expr {($wid1 > $wid - 30 ? $wid - 30 : $wid1 )}]
	set hei [expr {($hei1 > $hei - 30 ? $hei - 30 : $hei1 )}]
    } else {
	set dif 10

    }

    #     if { $width > $wid -20 || $wid > $width -20 }
    if { (abs($width-$wid) > $dif ||  abs($height-$hei) > $dif)
	 &&  [winfo width $w.c] > 1 } {
	set eps [expr {2 * [$w.c cget -insertborderwidth] + [$w.c cget -borderwidth] }]
	set epsx $eps
	set epsy $eps
	set extrawidth [expr {([winfo width $w] - [winfo width  $w.c]) +$epsx}]
	set extraheight [expr {([winfo height $w] - [winfo height  $w.c]) +$epsy}]
	set nwidth [expr {$wid - ($extrawidth > 0  ? $extrawidth : 0)}]
	set nheight [expr {$hei - ($extraheight > 0  ? $extraheight : 0)}]

	#puts "$w.c config -width $nwidth  -height $nheight, extraheight=$extraheight,epsy=$epsy"
	$w.c config -width $nwidth  -height $nheight

    }

}



proc bboxToRadius { win  } {
    makeLocal $win bbox
    if { "$bbox" != "" } {
	linkLocal $win       xradius yradius xcenter ycenter
	set i 0
	foreach v { x y z } {

	    set min [lindex $bbox $i]
	    set max [lindex $bbox [expr $i +2]]
	    if { "$min" != "" } {
		if { $min >= $max } {error "bad bbox $bbox since $min >= $max"}
		set ${v}radius [expr { ($max - $min) /2.0}]
		set ${v}center [expr { ($max + $min) /2.0}]
	    }
	}
    }
}

proc updateParameters { win var value} {
    linkLocal $win parameters
    #    puts "$win $var $value"
    set ans ""
    set comma ""

    foreach {v val} [splitParams $parameters] {
        if { "$v" == "$var" } {
	    set val $value
	}
	append ans $comma $v=$val
	set comma ","
    }
    #    puts "parameters=$ans"
    set parameters $ans
}

proc addSliders { win } {
    linkLocal $win sliders c width parameters
    set i 0
    if { "$sliders" == "" } { return }
    catch { destroy $c.sliders }
    set bg "#22aaee"
    set trough "#22ccff"
    frame $c.sliders -relief raised -highlightthickness 2 -highlightbackground $trough
    foreach v [split $sliders ,] {
	if { [regexp {([a-zA-Z0-9]+)[ ]*=?(([---0-9.]+):([---0-9.]+))?} $v  junk var junk x0 x1] } {
	    incr i
	    if { "$x0" == "" } { set x0 -5  ; set x1 5}

	    set fr $c.sliders.fr$i
	    frame $fr -background $bg
	    label $fr.lab -text $var: -background $bg
	    label $fr.labvalue -textvariable [oloc $win slidevalue$i]  -background $bg -relief sunken -justify left
	    scale $fr.scale -command "sliderUpdate $win $var" \
		-from "$x0" -to $x1 -orient horizontal \
		-resolution [expr ($x1 - $x0) < 1 ? ($x1-$x0)/100.0 : .01] \
		-length [expr {$width/2}] -showvalue 0 -variable [oloc $win slidevalue$i] -background $bg -troughcolor "#22ccff" -highlightthickness 0
	    pack $fr.lab -side left -expand 1 -fill x
	    pack $fr.labvalue $fr.scale -side left
	    pack  $fr -side top -expand 1 -fill x
	    set found 0
	    set val  [assoc $var [splitParams $parameters] no]
	    if { "$val" == "no" } {
		set val  [expr ($x1 + $x0)/2.0]
		if { "$parameters" != "" }  { append parameters , }
		append parameters $var=$val
	    }
	    $fr.scale set $val
	}
    }

    place  $c.sliders -in $c -x 4 -rely 1.0 -y -4 -anchor sw

}


proc sliderUpdate { win var val } {
    linkLocal $win sliderCommand parameters
    set params $parameters
    updateParameters $win $var $val
    if { "$params" != "$parameters" &&
	 [info exists sliderCommand] } {

	$sliderCommand $win $var $val
    }
}




## endsource plotconf.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Adams.tcl,v 1.2 2002-09-07 05:21:42 mikeclarkson Exp $
#
###### Adams.tcl ######


proc adamsMoulton { f g t0 x0 y0  h nsteps } {
    set ans [rungeKutta $f $g $t0 $x0 $y0 $h 3]
    catch {
	set i 0
	set h24 [expr {$h /24.0}]
	foreach { x y } $ans {
	    lappend listXff [xff  [expr {$t0 + $i * $h} ] $x $y]
	    lappend listYff [yff  [expr {$t0 + $i * $h} ] $x $y]
	    incr i
	    set xn $x
	    set yn $y
	}

	set n [expr $nsteps -3]

	while { [incr n -1] >= 0 } {

	    #puts "listXff = $listXff"
	    #puts "listYff = $listYff"		
	    # adams - bashford formula:
	    set xp [expr {$xn + ($h24)*(55 *[lindex $listXff 3]-59*[lindex $listXff 2]+37*[lindex $listXff 1]-9*[lindex $listXff 0]) }]
	    set yp [expr {$yn + ($h24)*(55 *[lindex $listYff 3]-59*[lindex $listYff 2]+37*[lindex $listYff 1]-9*[lindex $listYff 0]) }]
	    #puts "i=$i,xp=$xp,yp=$yp"
	    # adams-moulton corrector-predictor:
	    # compute the yp = yn+1 value..
	    set t [expr {$t0 + $i * $h}]
	    incr i
	    if { 1 } {
		set xap [expr { $xn+($h24)*(9*[xff $t $xp $yp]+19*[lindex $listXff 3]-5*[lindex $listXff 2]+[lindex $listXff 1]) }]
		set yap [expr { $yn+($h24)*(9*[yff $t $xp $yp]+19*[lindex $listYff 3]-5*[lindex $listYff 2]+[lindex $listYff 1]) }]

		set xn $xap
		set yn $yap
		# puts "after correct:i=[expr $i -1],xn=$xn,yn=$yn"	
		# could repeat it, or check against previous to see if changes too much.
	    }
	    set listXff [lrange $listXff 1 end]
	    set listYff [lrange $listYff 1 end]

	    lappend listXff [xff $t $xn $yn]
	    lappend listYff [yff $t $xn $yn]

	    lappend ans $xn $yn
	    # puts "ans=$ans"	
	}
	#puts "adams:t=$t"
    }
    return $ans
}

## endsource adams.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Rk.tcl,v 1.2 2002-09-07 05:21:42 mikeclarkson Exp $
#
###### Rk.tcl ######
#######################################################################
#######  Copyright William F. Schelter.  All rights reserved.  ########
#######################################################################

proc rungeKutta_try { } {
    proc ff { a b c } { return [expr {$b + $c}] }
    proc gg { a b c } { return [expr {$b - $c}] }
    rungeKutta ff gg 0.2 0.2 0 .01 10
}

proc rungeKutta { f g t0 x0 y0  h nsteps } {
    set n $nsteps
    set ans "$x0 $y0"
    set xn $x0
    set yn $y0
    set tn $t0
    set h2 [expr {$h / 2.0 }]
    set h6 [expr {$h / 6.0 }]
    catch {
	while { [incr nsteps -1] >= 0 } {


	    set kn1 [$f $tn $xn $yn]
	    set ln1 [$g $tn $xn $yn]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn1}] [expr {$yn + $h2*$ln1}]]
	    set kn2 [eval $f $arg]
	    set ln2 [eval $g $arg]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn2}] [expr {$yn +$h2*$ln2}]]
	    set kn3 [eval $f $arg]
	    set ln3 [eval $g $arg]

	    set arg [list [expr {$tn + $h}] [expr {$xn + $h * $kn3}] [expr {$yn + $h*$ln3}]]
	    set kn4 [eval $f $arg]
	    set ln4 [eval $g $arg]

	    set xn [expr {$xn + $h6 * ($kn1+2*$kn2+2*$kn3+$kn4)}]
	    set yn [expr {$yn + $h6 * ($ln1+2*$ln2+2*$ln3+$ln4)}]
	    set tn [expr {$tn+ $h}]

	    lappend ans  $xn $yn
	}
    }

    return $ans
}

proc pathLength { list } {
    set sum 0
    foreach { x y } $list {
	set sum [expr {$sum + sqrt($x*$x+$y*$y)}]
    }
    return $sum
}
proc rungeKuttaA { f g t0 x0 y0  h nsteps } {
    set ans [rungeKutta $f $g $t0 $x0 $y0 $h $nsteps]
    set count 0
    # puts "retrying([llength $ans]) .."
    while { [llength $ans] < $nsteps * .5  && $count < 7 } {
	incr count
	#set leng [pathLength $ans]
	#if { $leng == 0 } {set leng .001}
	set th [expr {$h / 3.0}]
	if { $th  < $h }  { set h $th }
	set ans  [rungeKutta $f $g $t0 $x0 $y0 $h $nsteps]
	# puts -nonewline "..(h=[format "%.5f" $h],pts=[llength $ans])"
	# flush stdout
    }
    return $ans
}



## endsource rk.tcl
#  $Id: rk4.tcl,v 1.5 2009-11-15 23:00:37 villate Exp $
#
# Copyright (C) 2008 Jaime E. Villate <villate@fe.up.pt>
#
# Fourth order Runge-Kutta method, with fixed-lenght steps in phase space.
# Based on Rk.tcl by William F. Schelter
# (the license information can be found in COPYING.tcl)

proc fieldlines { f g t0 x0 y0 sx sy nsteps dir} {
    set n $nsteps
    set ans "$t0 $x0 $y0"
    set xn $x0
    set yn $y0
    set tn $t0
    catch {
	while { [incr nsteps -1] >= 0 } {
	    set kn1 [$f $tn $xn $yn]
	    set ln1 [$g $tn $xn $yn]

	    set h [expr {$dir/[vectorlength [expr {$kn1/$sx}] [expr {$ln1/$sy}]]}]
	    set h2 [expr {$h / 2.0 }]
	    set h6 [expr {$h / 6.0 }]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn1}] [expr {$yn + $h2*$ln1}]]
	    set kn2 [eval $f $arg]
	    set ln2 [eval $g $arg]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn2}] [expr {$yn +$h2*$ln2}]]
	    set kn3 [eval $f $arg]
	    set ln3 [eval $g $arg]

	    set arg [list [expr {$tn + $h}] [expr {$xn + $h * $kn3}] [expr {$yn + $h*$ln3}]]
	    set kn4 [eval $f $arg]
	    set ln4 [eval $g $arg]

	    set dx [expr {$h6 * ($kn1+2*$kn2+2*$kn3+$kn4)}]
	    set dy [expr {$h6 * ($ln1+2*$ln2+2*$ln3+$ln4)}]

	    if { [vectorlength $dx $dy] > 5*[vectorlength $sx $sy] } { return $ans }
	    set xn [expr {$xn + $dx}]
	    set yn [expr {$yn + $dy}]
	    set tn [expr {$tn + $h}]

	    lappend ans $tn $xn $yn
	}
    }
    return $ans
}

proc curves { f g t0 x0 y0 sx sy nsteps dir} {
    set n $nsteps
    set ans "$t0 $x0 $y0"
    set xn $x0
    set yn $y0
    set tn $t0
    catch {
	while { [incr nsteps -1] >= 0 } {
	    set kn1 [expr -1*[$g $tn $xn $yn] ]
	    set ln1 [$f $tn $xn $yn]

	    set h [expr {$dir/[vectorlength [expr {$kn1/$sx}] [expr {$ln1/$sy}]]}]
	    set h2 [expr {$h / 2.0 }]
	    set h6 [expr {$h / 6.0 }]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn1}] [expr {$yn + $h2*$ln1}]]
	    set kn2 [expr -1*[eval $g $arg] ]
	    set ln2 [eval $f $arg]

	    set arg [list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn2}] [expr {$yn +$h2*$ln2}]]
	    set kn3 [expr -1*[eval $g $arg] ]
	    set ln3 [eval $f $arg]

	    set arg [list [expr {$tn + $h}] [expr {$xn + $h * $kn3}] [expr {$yn + $h*$ln3}]]
	    set kn4 [expr -1*[eval $g $arg] ]
	    set ln4 [eval $f $arg]

	    set dx [expr {$h6 * ($kn1+2*$kn2+2*$kn3+$kn4)}]
	    set dy [expr {$h6 * ($ln1+2*$ln2+2*$ln3+$ln4)}]

	    if { [vectorlength $dx $dy] > 5*[vectorlength $sx $sy] } { return $ans }
	    set xn [expr {$xn + $dx}]
	    set yn [expr {$yn + $dy}]
	    set tn [expr {$tn + $h}]

	    lappend ans $tn $xn $yn
	}
    }
    return $ans
}
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Plotdf.tcl,v 1.23 2011-03-20 16:33:16 villate Exp $
#
###### Plotdf.tcl ######
#######################################################################
#######  Copyright William F. Schelter.  All rights reserved.  ########
#######################################################################

global plotdfOptions
set plotdfOptions {
    {dxdt "x-y^2+sin(x)*.3" {specifies dx/dt = dxdt.  eg -dxdt "x+y+sin(x)^2"} }
    {dydt "x+y" {specifies dy/dt = dydt.  eg -dydt "x-y^2+exp(x)"} }
    {dydx "" { may specify dy/dx = x^2+y,instead of dy/dt = x^2+y and dx/dt=1 }}
    {vectors blue "Color for the vectors"}
    {fieldlines red "Color for the fieldlines"}
    {curves "" "Color for the orthogonal curves"}
    {xradius 10 "Width in x direction of the x values" }
    {yradius 10 "Height in y direction of the y values"}
    {width 560 "Width of canvas in pixels"}
    {height 560 "Height of canvas in pixels" }
    {scrollregion {} "Area to show if canvas is larger" }
    {xcenter 0.0 {(xcenter,ycenter) is the origin of the window}}
    {ycenter 0.0 "see xcenter"}
    {bbox "" "xmin ymin xmax ymax .. overrides the -xcenter etc"}
    {tinitial 0.0 "The initial value of variable t"}
    {nsteps 300 "Number of steps to do in one pass"}
    {xfun "" "A semi colon separated list of functions to plot as well"}
    {tstep "" "t step size"}
    {direction "both" "May be both, forward or backward" }
    {versus_t 0 "Plot in a separate window x and y versus t, after each trajectory" }
    {windowname ".dfplot" "window name"}
    {windowtitle "Plotdf" "window title"}
    {parameters "" "List of parameters and values eg k=3,l=7+k"}
    {linecolors { green black  brown gray black} "colors for functions plots"}
    {sliders "" "List of parameters ranges k=3:5,u"}
    {trajectory_at "" "Place to calculate trajectory"}
    {linewidth "2.0" "Width of integral lines" }
    {nolines 0 "If not 0, plot points and nolines"}
    {bargraph 0 "If not 0 this is the width of the bars on a bar graph" }
    {plotpoints 0 "if not 0 plot the points at pointsize" }
    {pointsize 2 "radius in pixels of points" }
    {autoscale "x y" "Set {x,y}center and {x,y}range depending on data and function. "}
    {zoomfactor "1.6 1.6" "Factor to zoom the x and y axis when zooming.  Zoom out will be reciprocal" }
    {errorbar 0 "If not 0 width in pixels of errorbar.  Two y values supplied for each x: {y1low y1high y2low y2high  .. }"}
    {data "" "List of data sets to be plotted.  Has form { {xversusy {x1 x2 ... xn} {y1 .. yn ... ym}} .. {againstIndex {y1 y2 .. yn}}  .. }"}
    {labelposition "10 15" "Position for the curve labels nw corner"}
    {xaxislabel "" "Label for the x axis"}
    {yaxislabel "" "Label for the y axis"}
    {psfile "" "A filename where the graph will be saved in PostScript."}
    {nobox 0 "if not zero, do not draw the box around the plot."}
    {axes "xy" "if zero, no axes are drawn. x, y or xy to draw the axes."}
    {nolegend 0 "if not zero, do not write down the legend."}
}

proc makeFrameDf { win } {
    set w [makeFrame $win df]
    makeLocal $win c dydx

    set top $win
    # puts "w=$w,win=$win"
    catch { set top [winfo parent $win]}
    catch {

	wm title $top [oget $win windowtitle]
	wm iconname $top "plotdf"
	#    wm geometry $top 750x700-0+20
    }
    set wb $w.menubar
    makeLocal $win buttonFont
    button $wb.versust -image ::img::plot -text [mc "Time Plots"] \
        -command "plotVersusT $w" -relief flat -width 30 -height 30
    pack $wb.versust -side left
    setForIntegrate $w
    return $win
}

proc swapChoose {win msg winchoose } {
    # global dydx dxdt dydt

    if { "$msg" == "dydt" } {
	pack $winchoose.dxdt -before $winchoose.dydt -side bottom
	oset $win dydx ""
	$winchoose.dydt.lab config -text "dy/dt"
    } else {
	pack forget $winchoose.dxdt
	oset $win dxdt 1
	oset $win dydx " "
	$winchoose.dydt.lab config -text "dy/dx"
    }
}


proc doHelpdf { win } {
    global Parser
    doHelp $win [join [list \
			 [mc  {
SOLVER/PLOTTER FOR SYSTEMS OF DIFFERENTIAL EQUATIONS

To quit this help click anywhere on this text.

Clicking at a point computes the trajectory (x(t),y(t)) starting at that \
point, and satisfying the differential equations		
      dx/dt = dxdt       dy/dt = dydt

By clicking on Zoom, the mouse will allow you to zoom in on a region \
of the plot. Each click near a point magnifies the plot, keeping the center \
at the point you clicked. Depressing the SHIFT key while clicking \
zooms in the opposite direction. To resume computing trajectories click \
on Integrate.

Clicking on Config will open a menu where several settings can be changed, \
such as the differential equations being solved, the intial point for the \
trajectory to be computed, the direction of integration for that trajectory, \
the time step for each integration interval and the number of integration \
steps (nsteps). Replot is used to update the plot with the \
changes made in the Config menu.

Holding the right mouse button down while moving the mouse will drag \
(translate) the plot sideways or up and down.

The plot can be saved as a postscript file, by clicking on Save.
} ] $Parser(help)]]
}

proc setForIntegrate { win} {
    makeLocal $win c
#    $c delete printrectangle
    bind $c  <1> "doIntegrateScreen $win %x %y "
}

# sample procedures
# proc xff { t x y } { return [expr {$x + $y }] }
# proc yff { t x y } { return [expr {$x - $y }] }

proc doIntegrateScreen { win sx sy  } {
    makeLocal $win c
    doIntegrate $win [storx$win [$c canvasx $sx]] [story$win [$c canvasy $sy]]
}

proc doIntegrate { win x0 y0 } {
    # global xradius yradius c tstep  nsteps
    #    puts "dointegrate $win $x0 $y0"
    makeLocal $win xradius yradius c tstep  nsteps direction linewidth tinitial versus_t xmin xmax ymin ymax
    linkLocal $win didLast trajectoryStarts
    set rtosx rtosx$win ; set rtosy rtosy$win
    set x1 [$rtosx $xmin]
    set y1 [$rtosy $ymax]
    set x2 [$rtosx $xmax]
    set y2 [$rtosy $ymin]
    oset $win trajectory_at [format "%.10g  %.10g" $x0 $y0]
    lappend trajectoryStarts [list $x0 $y0]

    set didLast {}
    # puts "doing at $trajectory_at"
    set steps $nsteps
    set hx [expr {$xradius / 100.0}]
    set hy [expr {$yradius / 100.0}]
    if { "$tstep" == "" } {
	set h [expr {[vectorlength $xradius $yradius] / 200.0}]
	set tstep $h
    } else {set h $tstep }

    # puts h=$h
    set todo "1"
    switch -- $direction {
	forward { set todo "1" }
	backward { set todo "-1" }
	both { set todo "-1 1" }
    }
    set methods ""
    foreach method { fieldlines curves } {
				    set color [oget $win $method]
				    if {"$color" != "" && "$color" != "blank"} {
					lappend methods $method
					lappend useColors $method $color
				    }
				}
    set methodNo -1
    foreach method $methods {
			     incr methodNo
			     set linecolor [assoc $method $useColors ]
			     #    puts method=$method
			     set signs $todo
			     if {"$method" == "curves"} {
				 set signs "-1 1"
				 set coords {}
			     }
			     foreach sgn $signs {
				 set arrow "none"
				 if { "$method"=="fieldlines" } {
				     if { $sgn < 0 } {
					 set arrow "first"
					 set coords {}
				     } else {
					 if { "$direction" == "forward"} {
					     set arrow "last"
					     set coords {}
					 }
				     }
				 }
				 set h1 [expr {- $hx}]
				 set h2 [expr {- $hy}]
				 set form [list $method xff yff $tinitial $x0 $y0 $hx $hy $steps $sgn]
				 set ans [eval $form]
				 lappend didLast $form

				 #puts "doing: $form"
				 set i 0
				 set lim [expr {$steps * 3}]
				 catch {
				     while { $i <= $lim } {
					 set xn [$rtosx [lindex $ans [incr i]]]
					 set yn [$rtosy [lindex $ans [incr i]]]
					 incr i
					 # puts "$xn $yn"
					 # Tests if point is inside the domain.
					 # In version 1.14 there was an if:
					 # abs($xn1)+abs($yn1)+abs($xn2)
					 # +abs($yn2) < [expr {pow(10.0,9)}]
					 # to fix a bug in win95 version.
					 # That's now out of context, but the
					 # bug might reappear. (J. Villate)
					 if { ($xn-$x1)*($xn-$x2) <= 0 &&
					      ($yn-$y1)*($yn-$y2) <= 0 } {
					     lappend coords $xn $yn
					 }
				     }
				 }
				 if { [llength $coords] > 3 } {
				     $c create line $coords -tags path \
					 -width $linewidth -fill $linecolor \
					 -arrow $arrow
				     if { "$direction" == "both" } {
					 set coords [lrange $coords 2 3]
				     }
				 }
			     }
			 }
    if { $versus_t } { plotVersusT $win}
}


proc plotVersusT {win } {
    linkLocal $win didLast dydt dxdt parameters xcenter xradius ycenter yradius
    set nwin .versust.plot2d
    if { "$parameters" != ""  } {
	set pars ", $parameters"
    } else {
	set pars ""
    }
    oset $nwin themaintitle "dy/dt=$dydt, dx/dt=$dxdt $pars"
    lappend plotdata [list maintitle [list oget $nwin themaintitle]]

    set max [expr {$xcenter + $xradius}]
    set min [expr {$xcenter - $xradius}]
    if { ($ycenter + $yradius) > $max } {
	set max [expr {$ycenter + $yradius}]
    }
    if { ($ycenter - $yradius) < $min } {
	set min [expr {$ycenter - $yradius}]
    }

    foreach v $didLast {
	set ans [eval $v]
	desetq "tinitial x0 y0 hx hy steps sgn" [lrange $v 3 end]
	set this [lrange $v 0 5]
	if { [info exists doing($this) ] } { set tem $doing($this) } else {
	    set tem ""
	}
	set doing($this) ""
	set allx "" ; set ally "" ; set allt ""
	set ii 0
	foreach {t x y } $ans {
	    lappend allx $x
	    lappend ally $y
	    lappend allt $t
	    incr ii
	}
	
	foreach u $tem v [list $allx $ally $allt] {
	    if { $sgn > 0 } { lappend doing($this) [concat $u $v]} else {
		lappend doing($this) [concat [lreverse $v] $u]
	    }
	}
    }

    foreach {na val } [array get doing] {
	lappend plotdata [list xaxislabel "t"]
	lappend plotdata [list label [oget $win xaxislabel]] [list plotpoints 0]
	lappend plotdata [list xversusy [lindex $val 2] [lindex $val 0] ]
	lappend plotdata [list label [oget $win yaxislabel]]	
	lappend plotdata [list xversusy [lindex $val 2] [lindex $val 1] ]
    }
    if { ![winfo exists .versust] } {
	toplevel .versust
    }

    plot2d -data $plotdata -windowname $nwin -ycenter [expr {($max+$min)/2.0}] -yradius [expr {($max-$min)/2.0}]
    wm title .versust [concat [oget $win xaxislabel] [mc " and "] [oget $win yaxislabel] [mc " versus t"]]
}

proc lreverse { lis } {
    set ans ""
    set i [llength $lis]
    while { [incr i -1]>=0 } {
	lappend ans [lindex $lis $i]
    }
    return $ans
}


#
#-----------------------------------------------------------------
#
# $rtosx,$rtosy --  convert Real coordinate to screen coordinate
#
#  Results: a window coordinate
#
#  Side Effects:
#
#----------------------------------------------------------------


#
#-----------------------------------------------------------------
#
# $storx,$story --  Convert a screen coordinate to a Real coordinate.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc drawArrowScreen { c atx aty dfx dfy color } {

    set x1 [expr {$atx + $dfx}]
    set y1 [expr {$aty + $dfy}]
    #   set x2 [expr {$atx + .8*$dfx +.1* $dfy}]
    #   set y2 [expr {$aty + .8*$dfy - .1* $dfx}]
    #   set x3 [expr {$atx + .8*$dfx -.1* $dfy}]
    #   set y3 [expr {$aty + .8*$dfy + .1* $dfx}]
    $c create line $atx $aty $x1 $y1 -tags arrow -fill $color -arrow last -arrowshape {3 5 2}
    #  $c create line $x2 $y2  $x1 $y1 -tags arrow -fill red
    #  $c create line $x3 $y3 $x1 $y1 -tags arrow -fill red
}

proc drawDF { win tinitial } {
    global axisGray
    makeLocal  $win xmin xmax xcenter ycenter c ymin ymax transform vectors xaxislabel yaxislabel
    linkLocal $win nobox axes

    # flush stdout
    set rtosx rtosx$win ; set rtosy rtosy$win
    set storx   storx$win  ;   set story   story$win
    set stepsize 30
    set min 100000000000.0
    set max 0.0
    set t0 $tinitial
    set xfactor [lindex $transform 0]
    set yfactor [lindex $transform 3]
    set extra $stepsize
    set uptox [$rtosx $xmax]
    set uptoy [$rtosy $ymin]
#    set uptox [expr {[$rtosx $xmax] + $extra}]
#    set uptoy [expr {[$rtosy $ymin] + $extra}]
#    set uptox [expr {[$rtosx $xmax] + $extra}]
#    set uptoy [expr {[$rtosy $ymin] + $extra}]
    # draw the axes:
    #puts "draw [$rtosx $xmin] to $uptox"
    if { "$vectors" != "" && "$vectors" != "blank" } {
	for { set x [expr {[$rtosx $xmin] + $extra}] } { $x < $uptox } { set x [expr {$x +$stepsize}] } {
	    for { set y [expr {[$rtosy $ymax] + $extra}] } { $y < $uptoy } { set y [expr {$y + $stepsize}] } {
		set args "$t0 [$storx $x] [$story $y]"
		set dfx [expr {$xfactor * [eval xff $args]}]
		# screen y is negative of other y
		set dfy [expr  {$yfactor * [eval yff $args]}]
		# puts "$dfx $dfy"
		set len  [vectorlength $dfx $dfy]
		append all " $len $dfx $dfy "
		if { $min > $len } { set min $len }
		if { $max < $len } {set  max $len}
	    }
	}
	set fac [expr {($stepsize -5 -8)/($max - $min)}]
	set arrowmin 8
	set arrowrange [expr {$stepsize -4 - $arrowmin}]
	set s1 [expr {($arrowrange*$min+$arrowmin*$min-$arrowmin*$max)/($min-$max)}]
	set s2 [expr {$arrowrange/($max-$min) }]
	# we calculate fac for each length, so that
	# when we multiply the vector times fac, its length
	# will fall somewhere in [arrowmin,arrowmin+arrowrange].
	# vectors of length min and max resp. should get mapped
	# to the two end points.
	# To do this we set fac [expr {$s1/$len + $s2}]
	# puts "now to draw,s1=$s1 s2=$s2,max=$max,min=$min"
	# puts "xfactor=$xfactor,yfactor=$yfactor"
	
	set i -1
	for { set x [expr {[$rtosx $xmin] + $stepsize}] } { $x < $uptox } { set x [expr {$x +$stepsize}] } {
	    for { set y [expr {[$rtosy $ymax] + $stepsize}] } { $y < $uptoy } { set y [expr {$y + $stepsize}] } {
		
		
		set len [lindex $all [incr i]]
	
		set fac [expr {$s1/$len + $s2}]
		set dfx [lindex $all [incr i]]
		set dfy [lindex $all [incr i]]
		#puts "[$storx $x] [$story $y] x=$x y=$y dfx=$dfx dfy=$dfy fac=$fac"
		# puts "$len $dfx $dfy"
		drawArrowScreen $c $x $y [expr {$fac * $dfx}] [expr {$fac * $dfy} ] $vectors
	    }
	}
    }

    set x1 [rtosx$win $xmin]
    set y1 [rtosy$win $ymax]
    set x2 [rtosx$win $xmax]
    set y2 [rtosy$win $ymin]
    # Draw the two axes
    $c del axes
    if { $xmin*$xmax < 0 && ($axes == {y} || $axes == {xy}) } {
	if { $nobox == 0 } {
	    $c create line [$rtosx 0] $y1 [$rtosx 0] $y2 -fill $axisGray \
		-tags axes
	} else {
	    $c create line [$rtosx 0] $y1 [$rtosx 0] $y2 -width 2 \
		-arrow "first" -tags axes
	}
    }
    if { $ymin*$ymax < 0  && ($axes == {x} || $axes == {xy}) } {
	if { $nobox == 0 } {
	    $c create line $x1 [$rtosy 0] $x2 [$rtosy 0] -fill $axisGray \
		-tags axes
	} else {
	    $c create line $x1 [$rtosy 0] $x2 [$rtosy 0] -width 2 \
		-arrow "last" -tags axes
	}
    }
    # Draw the plot box
    if { "[$c find withtag printrectangle]" == "" && $nobox == 0 } {
	$c create rectangle $x1 $y1 $x2 $y2 -tags printrectangle -width 2
	marginTicks $c [storx$win $x1] [story$win $y2] [storx$win $x2] \
	    [story$win $y1] "printrectangle marginticks"

    }
    # Write down the axes labels
    $c del axislabel
    if {$nobox != 0  && $xmin*$xmax < 0  && ($axes == {y} || $axes == {xy})} {
	set xbound [expr { [$rtosx 0] - 30}]
    } else {
	set xbound [expr {$x1 - 30}]
    }
    $c create text $xbound [expr {$y1 - 6}] -anchor sw \
       -text [oget $win yaxislabel] -font {helvetica 16 normal} -tags axislabel
    if {$nobox != 0  && $ymin*$ymax < 0  && ($axes == {x} || $axes == {xy})} {
	$c create text [expr {$x2 - 5}] [expr { [$rtosy 0] + 15}] \
	    -anchor ne -text [oget $win xaxislabel] \
	    -font {helvetica 16 normal} \
	    -tags axislabel
    } else {
	$c create text [expr {($x1 + $x2)/2}] [expr {$y2 + 35}] \
	    -anchor center -text [oget $win xaxislabel] \
	    -font {helvetica 16 normal} -tags axislabel
    }

}

proc parseOdeArg {  s } {
    set orig $s
    set w "\[ ]*"
    set exp "\[dD]$w\\($w\(\[xyz])$w,$w\(\[xyt])$w\\)$w=(\[^;]+)"
    while { [regexp -- $exp $s junk x t expr ] } {
	lappend ans  -d${x}d$t
	lappend ans $expr
	regexp -indices $exp $s junk x t expr
	set s [string range $s [lindex $junk 1] end]
    }
    if { ![info exists ans] || ([llength $ans] == 2 && "[lindex $ans 0]" != "-dydx") } {
	error [mc "bad -ode argument:\n$orig\nShould be d(y,x)=f(x,y)
       OR d(x,t)=f(x,y) d(y,t)=g(x,y)"]
    }
    return $ans
}



proc plotdf { args } {
    global plotdfOptions   printOption printOptions plot2dOptions
    # puts "args=$args"
    # to see options add: -debug 1
    set win [assoc -windowname $args]
    if { "$win" == "" } {set win [getOptionDefault windowname $plotdfOptions] }
    if { "[set ode [assoc "-ode" $args]]" != "" }  {
	set args [delassoc -ode $args]
	set args [concat [parseOdeArg $ode] $args]
    }
    global [oarray $win]
    getOptions $plotdfOptions $args -usearray [oarray $win]

    makeLocal $win dydx

    if { "$dydx" !="" } { oset $win dxdt 1 ; oset $win dydt $dydx }
    setPrintOptions $args
    foreach v {trajectoryStarts recompute} {
	catch { unset [oloc $win $v]  }
    }

    makeFrameDf $win
    oset $win sliderCommand sliderCommandDf
    oset $win trajectoryStarts ""

    oset $win maintitle [concat "makeLocal $win  dxdt dydt dydx ;"  \
			     {if { "$dydx" == "" } { concat "dx/dt = $dxdt , dy/dt = $dydt"}  else {
				 concat "dy/dx = $dydt" } } ]
    replotdf $win
}

proc replotdf { win } {
    global printOption plotdfOptions
    linkLocal $win xfundata data psfile
    if { ![info exists data] } {
	set data ""
	
    }
    makeLocal $win c dxdt dydt tinitial nsteps xfun trajectory_at parameters
    setUpTransforms $win 0.8
    setXffYff $dxdt $dydt $parameters
    $c delete all
    setForIntegrate $win
    oset $win curveNumber -1
    drawDF $win $tinitial
    if { "$trajectory_at" != "" } {
	eval doIntegrate $win  $trajectory_at
    }
    set xfundata ""
    foreach v [sparseListWithParams $xfun {x y t} $parameters ] {
	proc _xf {  x  } "return \[expr { $v } \]"
	regsub "\\$" $v "" label
	lappend xfundata [list label $label] \
	    [linsert [calculatePlot $win _xf $nsteps]  \
		 0 xversusy]
    }
    redraw2dData $win -tags path

    # Create a PostScript file, if requested
    if { $psfile != "" } {
	set printOption(psfilename) $psfile
	writePostscript $win
	$c delete printoptions
	eval [$win.menubar.close cget -command]
    }
}

proc setXffYff { dxdt dydt parameters } {

    proc xff { t x y } "expr { [sparseWithParams $dxdt { x y} $parameters] }"
    proc yff { t x y } "expr { [sparseWithParams $dydt { x y} $parameters] } "
}

proc doConfigdf { win } {
    desetq "wb1 wb2" [doConfig $win]
    makeLocal $win buttonFont
    frame $wb1.choose1
    set frdydx $wb1.choose1
    button $frdydx.dydxbut -command "swapChoose $win dydx $frdydx " \
	-text "dy/dx" -font $buttonFont
    button $frdydx.dydtbut -command "swapChoose $win dydt $frdydx" \
	-text "dy/dt,dx/dt" -font $buttonFont
    mkentry $frdydx.dxdt [oloc $win dxdt] "dx/dt" $buttonFont
    mkentry $frdydx.dydt [oloc $win dydt] "dy/dt" $buttonFont
    pack $frdydx.dxdt  $frdydx.dydt -side bottom  -fill x -expand 1
    pack $frdydx.dydxbut $frdydx.dydtbut -side left -fill x -expand 1

    foreach w {parameters xfun linewidth xradius yradius xcenter ycenter tinitial versus_t nsteps direction curves vectors fieldlines } {
	mkentry $wb1.$w [oloc $win $w] $w $buttonFont
	pack $wb1.$w -side bottom -expand 1 -fill x
    }
    mkentry $wb1.trajectory_at [oloc $win trajectory_at] \
	"Trajectory at" $buttonFont
    bind $wb1.trajectory_at.e <KeyPress-Return> \
	"eval doIntegrate $win \[oget $win trajectory_at\] "
    pack  $wb1.trajectory_at   $frdydx    -side bottom -expand 1 -fill x
    if { "[oget $win dydx]" != "" } { swapChoose $win dydx $frdydx }
    setForIntegrate $win
}

proc sliderCommandDf { win var val } {
    linkLocal $win recompute
    updateParameters $win $var $val
    set com "recomputeDF $win"
    # allow for fast move of slider...
    #mike FIXME: this is a wrong use of after cancel
    after cancel $com
    after 50 $com
}

proc recomputeDF { win } {
    linkLocal $win  recompute
    if { [info exists recompute]  } {
	incr recompute
	return
    } else {
	#	puts "set recompute 1"
	set recompute 1
    }
    linkLocal $win trajectoryStarts  c tinitial dxdt dydt parameters
    set redo 0
    set trajs ""

    catch {     set trajs $trajectoryStarts}


    while { $redo != $recompute } {
	#	puts "	setXffYff $dxdt $dydt $parameters"
	setXffYff $dxdt $dydt $parameters
	#	$c delete path point arrow
	$c delete all
	catch { unset  trajectoryStarts }
	set redo $recompute
	foreach pt $trajs {
	    desetq "x0 y0" $pt
	    catch { doIntegrate $win $x0 $y0 }
	    update
	    if { $redo != $recompute } { break }
	}
	if  { $redo == $recompute } {
	    catch { drawDF $win $tinitial }
	}
    }
    #    puts "    unset recompute"
    unset recompute
}


## endsource plotdf.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Plot2d.tcl,v 1.20 2011-03-09 11:28:25 villate Exp $
#
###### Plot2d.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

global p
set p .plot
if {[winfo exists $p]} {catch { destroy $p }}

global plot2dOptions
set plot2dOptions {
    {xradius 10 "Width in x direction of the x values" }
    {yradius 10 "Height in y direction of the y values"}
    {width 560 "Width of canvas in pixels"}
    {height 560 "Height of canvas in pixels" }
    {xcenter 0.0 {(xcenter,ycenter) is the origin of the window}}
    {xfun "" {function of x to plot eg: sin(x) or "sin(x);x^2+3" }}
    {parameters "" "List of parameters and values eg k=3,l=7+k"}
    {sliders "" "List of parameters ranges k=3:5,u"}
    {nsteps "100" "mininmum number of steps in x direction"}
    {ycenter 0.0 "see xcenter"}
    {bbox "" "xmin ymin xmax ymax .. overrides the -xcenter etc"}
    {screenwindow "20 20 700 700" "Part of canvas on screen"}

    {windowname ".plot2d" "window name"}
    {nolines 0 "If not 0, plot points and nolines"}
    {bargraph 0 "If not 0 this is the width of the bars on a bar graph" }
    {linewidth "0.6" "Width of plot lines" }
    {plotpoints 0 "if not 0 plot the points at pointsize" }
    {pointsize 2 "radius in pixels of points" }
    {linecolors {blue green red brown gray black} "colors to use for lines in data plots"}
    {labelposition "10 15" "Position for the curve labels nw corner"}
    {xaxislabel "" "Label for the x axis"}
    {yaxislabel "" "Label for the y axis"}
    {autoscale "y" "Set {x,y}center and {x,y}range depending on data and function. Value of y means autoscale in y direction, value of {x y} means scale in both.  Supplying data will automatically turn this on."}
    {zoomfactor "1.6 1.6" "Factor to zoom the x and y axis when zooming.  Zoom out will be reciprocal" }
    {errorbar 0 "If not 0 width in pixels of errorbar.  Two y values supplied for each x: {y1low y1high y2low y2high  .. }"}
    {data "" "List of data sets to be plotted.  Has form { {xversusy {x1 x2 ... xn} {y1 .. yn ... ym}} .. {againstIndex {y1 y2 .. yn}}  .. }"}
    {psfile "" "A filename where the graph will be saved in PostScript."}
    {nobox 0 "if not zero, do not draw the box around the plot."}
    {axes "xy" "if zero, no axes are drawn. x, y or xy to draw the axes."}
    {nolegend 0 "if not zero, do not write down the legend."}
}

proc argSuppliedp { x } {
    upvar 1 args a
    return [expr [set i [lsearch $a $x]] >= 0 && $i%2 == 0]
}

proc mkPlot2d { args } {
    global plot2dOptions  printOption axisGray
    #puts "args=<$args>"
    # global  screenwindow c xmax xmin ymin ymax
    # eval global [optionFirstItems $plot2dOptions]
    set win [assoc -windowname $args]
    if { "$win" == "" } {
	set win [getOptionDefault windowname $plot2dOptions]
    }
    global  [oarray $win]
    set data [assoc -data $args ]
    # puts ranges=[plot2dGetDataRange $data]

    getOptions $plot2dOptions $args -usearray [oarray $win]
    linkLocal $win autoscale
    if { [argSuppliedp -data] && ![argSuppliedp -autoscale] && \
	     ![argSuppliedp -xradius] } {
	lappend autoscale x
    }
    if { ![argSuppliedp -autoscale] & [argSuppliedp -yradius] } {
	set autoscale [ldelete y $autoscale]
    }	

    oset $win curveNumber -1
    setPrintOptions $args
    oset $win maintitle ""	
    setupCanvas $win
    catch { destroy $windowname }

    makeFrame2d $win
    oset $win sliderCommand sliderCommandPlot2d
    makeLocal $win c
    return $win

}

proc  makeFrame2d  { win } {
    set w [makeFrame $win 2d]
    set top $w
    catch { set top [winfo parent $w]}
    catch {
	wm title $top [mc "Xmaxima: Plot2d"]
	wm iconname $top "plot2d"
	# wm geometry $top 750x700-0+20
    }
    pack $w
    return $w

}

proc doConfig2d { win } {
    desetq "wb1 wb2" [doConfig $win]
    makeLocal $win buttonFont
    mkentry $wb1.nsteps [oloc $win nsteps]  [mc "Number of mesh grids"]  $buttonFont
    mkentry $wb1.xfun [oloc $win xfun]  "y=f(x)"  $buttonFont
    bind $wb1.xfun.e <Return> "replot2d $win"

    pack $wb1.xfun  $wb1.nsteps -expand 1 -fill x
    foreach w {xradius yradius xcenter ycenter linecolors autoscale linewidth parameters} {
	mkentry $wb1.$w [oloc $win $w] $w $buttonFont
	pack $wb1.$w -side bottom -expand 1 -fill x
    }
}

proc doHelp2d {win } {
    global Parser

    doHelp $win [join [list \
			[mc {

XMAXIMA'S PLOTTER FOR TWO-DIMENSIONAL GRAPHICS

To quit this help click anywhere on this text.

Clicking on Config will open a menu where several settings can be changed, \
such as the function being plotted, the line width, and the \
x and y centers and radii. Replot is used to update the plot with the \
changes made in the Config menu.

By clicking on Zoom, the mouse will allow you to zoom in on a region \
of the plot. Each click near a point magnifies the plot, keeping the center \
at the point you clicked. Depressing the SHIFT key while clicking \
zooms in the opposite direction.

Holding the right mouse button down while moving the mouse will drag \
(translate) the plot sideways or up and down.

The plot can be saved as a postscript file, by clicking on Save.
}] $Parser(help)]]
}

global plot
set   plot(numberPlots) 4

proc mkExtraInfo { name args } {
    # global plot 	
    catch { destroy $name }

    toplevel $name
    wm geometry $name -10+10
    # pack $name
    set canv [assoc -canvas $args ]
    set i 0
    set w $name
    frame $w.grid
    pack $w.grid -expand yes -fill both -padx 1 -pady 1
    grid $w.grid
    grid rowconfig    $w.grid 0 -weight 1 -minsize 0
    grid columnconfig $w.grid 0 -weight 2 -minsize 0

    set i 0
    label $w.title -text [mc "Extra Plotting Information"] -width 50
    grid $w.title -in $w.grid -columnspan 2 -row 0 -column 0
    incr i
    label $w.labppl -text [mc "Plot Function f(x)"]
    label $w.labcol -text [mc "plot color"]
    grid $w.labppl -padx 1 -in $w.grid  -pady 1 -row $i -column 0 -sticky news
    grid $w.labcol -padx 1 -in $w.grid  -pady 1 -row $i -column 1 -sticky news
    incr i
    set k 1
    proc mkPlotEntry { w k i } {
	entry $w.plot$k -textvariable plot(fun$k)
	entry $w.color$k -textvariable plot(col$k)
	grid $w.plot$k -padx 10 -in $w.grid  -pady 1 -row $i -column 0 -sticky news
	grid $w.color$k -padx 4 -in $w.grid  -pady 1 -row $i -column 1 -sticky news
    }
    while { $k <= $plot(numberPlots) } { mkPlotEntry $w $i $k ; incr i ; incr k}
}

proc calculatePlot { win fun  nsteps } {
    #  global xmin xmax  ymax ymin
    makeLocal $win xmin xmax  ymax ymin
    set h0 [expr {($xmax - $xmin)/double($nsteps )}]
    set x0 $xmin
    set res ""
    set limit [expr {100 * (abs($ymax)> abs($ymin) ? abs($ymax) : abs($ymin))}]
    while { $x0 < $xmax } {
	set lastx0 $x0
	#puts xmax=$xmax
	append res " " [calculatePlot1 $win $x0 $h0 $fun $limit]
	#puts res:[lrange $res [expr [llength $res] -10] end]
	if { $x0 <= $lastx0 }	{
	    # puts "x0=$x0,($lastx0)"
	    set x0 [expr {$x0 + $h0/4}]
	    #error "how is this?"
	}
    }
    # puts "plength=[llength $res]"
    return $res
}


#
#-----------------------------------------------------------------
#
# calculatePlot1 --   must advance x0 in its caller
#
#  Results: one connected line segment as "x0 y0 x1 y1 x2 y2 .."
#
#  Side Effects: must advance x0 in its caller
#
#----------------------------------------------------------------
#
proc  calculatePlot1 { win x0 h0 fun  limit } {
    #puts "calc:$win $x0 $h0 $limit $fun"
    makeLocal $win xmax
    set ansx ""
    set ansy ""
    while { [catch { set y0 [$fun $x0] } ] && $x0 <= $xmax }  {
	set x0 [expr {$x0 + $h0}]
    }
    if { $x0 > $xmax } {
	# puts "catching {$fun $x0}"
	uplevel 1 set x0 $x0
	return ""
    }
    set ans "$x0 $y0"
    set delta 0
    set littleLimit [expr {$limit/50.0 }]
    set veryLittleLimit [expr {$littleLimit * 10}]
    # now have one point..
    # this is really set below for subsequent iterations.
    set count 10
    set heps [expr {$h0/pow(2,6)}]
    set h2 [expr {$h0 *2 }]
    set ii 0
    set x1 [expr {$x0 + $h0}]
    while { $x1 <= $xmax  && $ii < 5000 } {
	# puts $x1
	incr ii
	if { [catch { set y1 [$fun $x1] } ] } {
	    #puts "catching1 {$fun $x1}"
	    if { $count > 0 } {
		# try a shorter step.
		set x1 [expr {($x1 -$x0)/2 + $x0}]
		incr count -1
		continue
	    } else {
		uplevel 1 set x0 [expr {$x0 + $heps}]
		return [list $ansx $ansy]
	    }
	}
	# ok have x1,y1
	# do this on change in slope!! not change in limit..

	set nslope [expr {($y1-$y0)/($x1-$x0)}]
	catch { set delta [expr {($slope * $nslope < 0 ? abs($slope-$nslope) : .1*abs($slope-$nslope))}]}
	# catch { set delta [expr {abs($slope - ($y1-$y0)/($x1-$x0))}] }
	
	if { $count > 0 && (abs($y1 - $y0) > $h2 || $delta > $h2)  && (0 || abs($y1) < $littleLimit)
	 } {
	    #puts "too  big $y1 [expr {abs($y1-$y0)}] at $x1"
	    set x1 [expr {($x1 -$x0)/2 + $x0}]
	    incr count -1
	    continue
	} elseif { abs($y1) > $limit || abs($y1-$y0) > $limit
		   || $delta > $littleLimit } {
	    incr ii
	    if { $count == 0 } {
		uplevel 1 set x0 [expr {$x0 + $heps}]
		return [list $ansx $ansy]
	    } else {
		
		set x1 [expr {($x1 -$x0)/2 + $x0}]
		incr count -1
		continue
	    }
	} else {
	    if {   abs($y1-$y0) > $limit/4} {
		
		# puts "x0=$x0,x1=$x1,y0=$y0,y1=$y1"
		uplevel 1 set x0 $x1
		return [list $ansx $ansy]
	    }

	
	    # hopefully common case!!
	    # puts "got it: $x1,$y1,"
	    lappend ansx $x1
	    lappend ansy $y1
	    #append ans " $x1 $y1"
	    set slope [expr {($y1-$y0)/($x1-$x0)} ]
	    set x0 $x1
	    set y0 $y1
	    set x1 [expr {$x0 + $h0}]
	    set count 4
	}
    }
    uplevel 1 set x0 $x1
    return [list $ansx $ansy]
}





#
#-----------------------------------------------------------------
#
# nextColor --  get next COLOR and advance the curveNumber
#
#  Results: a color
#
#  Side Effects: the local variable for WIN called curveNumber is incremented
#
#----------------------------------------------------------------
#
proc nextColor { win } {
    makeLocal $win linecolors
    if { [catch { set i [oget $win curveNumber] } ] } { set i -1 }
    set color [lindex $linecolors [expr {[incr i]%[llength $linecolors]}]]
    oset $win curveNumber $i
    return $color
}


proc plot2d {args } {
    #puts "args=$args"
    set win [apply mkPlot2d $args]
    replot2d $win
    return $win
}

proc replot2d {win } {
    global printOption axisGray plot2dOptions
    linkLocal $win xfundata data psfile nobox axes
    foreach v $data {
	if { "[assq [lindex $v 0] $plot2dOptions notthere]" != "notthere" } {
	    oset $win [lindex $v 0] [lindex $v 1]
	}
    }
    linkLocal $win parameters
    makeLocal $win xfun nsteps c linecolors xaxislabel yaxislabel autoscale sliders
    if { "$sliders" != "" && ![winfo exists $c.sliders] } {
	addSliders $win
    }
    set xfundata ""
    #   puts xfun=$xfun,parameters=$parameters,[oget $win xradius],[oget $win xmax]
    foreach v [sparseListWithParams $xfun x $parameters] {
	#	puts v=$v
	#	proc _xf {  x  } "return \[expr { $v } \]"
	proc _xf {  x  } "expr { $v }"	
	regsub "\\$" $v "" label
	lappend xfundata [list label $label] \
	    [linsert [calculatePlot $win _xf $nsteps]  \
		 0 xversusy]
    }

    # in case only functions and no y autoscale dont bother.
    if { "$data" != "" || [lsearch $autoscale y]>=0  } {
	set ranges [plot2dGetDataRange [concat $data $xfundata]]
	#      puts ranges=$ranges
	foreach {v k} [eval plot2dRangesToRadius $ranges] {
	    if { [lsearch $autoscale [string index $v 1] ] >= 0 } {
		oset $win [string range $v 1 end] $k
	    }
	}
    }

    setUpTransforms $win 0.8
    set rtosx rtosx$win ; set rtosy rtosy$win
    makeLocal $win xmin ymin xmax ymax
    set x1 [rtosx$win $xmin]
    set x2 [rtosx$win $xmax]
    set y2 [rtosy$win $ymin]
    set y1 [rtosy$win $ymax]

    # Draw the two axes
    $c del axes
    if { $xmin*$xmax < 0 && ($axes == {y} || $axes == {xy}) } {
	if { $nobox == 0 } {
	    $c create line [$rtosx 0] $y1 [$rtosx 0] $y2 -fill $axisGray \
		-tags axes
	} else {
	    $c create line [$rtosx 0] $y1 [$rtosx 0] $y2 -width 2 \
		-arrow "first" -tags axes
	}
    }
    if { $ymin*$ymax < 0  && ($axes == {x} || $axes == {xy}) } {
	if { $nobox == 0 } {
	    $c create line $x1 [$rtosy 0] $x2 [$rtosy 0] -fill $axisGray \
		-tags axes
	} else {
	    $c create line $x1 [$rtosy 0] $x2 [$rtosy 0] -width 2 \
		-arrow "last" -tags axes
	}
    }

    if { "$xfun" != "" } {
	oset $win maintitle [concat list "Plot of y = \[oget $win xfun\]" ]
    }
    $c del path
    $c del label
    oset  $win curveNumber -1
    redraw2dData $win -tags path

    # Draw the plot box
    if { "[$c find withtag printrectangle]" == "" && $nobox == 0 } {
	$c create rectangle $x1 $y1 $x2 $y2 -tags printrectangle -width 2
	marginTicks $c [storx$win $x1] [story$win $y2] [storx$win $x2] \
	    [story$win $y1] "printrectangle marginticks"

    }
    # Write down the axes labels
    $c del axislabel
    if {$nobox != 0  && $xmin*$xmax < 0  && ($axes == {y} || $axes == {xy})} {
	set xbound [expr { [$rtosx 0] - 30}]
    } else {
	set xbound [expr {$x1 - 30}]
    }
    $c create text $xbound [expr {$y1 - 6}] -anchor sw \
       -text [oget $win yaxislabel] -font {helvetica 16 normal} -tags axislabel
    if {$nobox != 0  && $ymin*$ymax < 0  && ($axes == {x} || $axes == {xy})} {
	$c create text [expr {$x2 - 5}] [expr { [$rtosy 0] + 15}] \
	    -anchor ne -text [oget $win xaxislabel] \
	    -font {helvetica 16 normal} \
	    -tags axislabel
    } else {
	$c create text [expr {($x1 + $x2)/2}] [expr {$y2 + 35}] \
	    -anchor center -text [oget $win xaxislabel] \
	    -font {helvetica 16 normal} -tags axislabel
    }

    # Create a PostScript file, if requested
    if { $psfile != "" } {
	set printOption(psfilename) $psfile
	writePostscript $win
	$c delete printoptions
	eval [$win.menubar.close cget -command]
    }
}



#
#-----------------------------------------------------------------
#  Should change name to plotData since works for 3d to now..
# plot2dData --  create WIN and plot 2d OR 3d DATA which is a list of
#  data sets.  Each data set must begin with xversusy or againstIndex
#  In the first case the data set looks like:
#       { xversusy {x1 x2 ...xn} {y1 ... yn yn+1 ... ym} }
#  and will be plotted as m/n curves : (x1,y1) (x2,y2) .. (xn,yn)
#  and (x1,yn+1) (x2,yn+2) ..
#  In the againstIndex case the x values are replace by the indices
#  0,1,2,... [length $yvalues]-1
#  Results: none
#
#  Side Effects: curves draw
#
#----------------------------------------------------------------
#
proc plot2dData { win data args } {
    clearLocal $win
    #puts "data=$data, [regexp plot2d $data junk ]"
    if { [regexp plot2d $data junk] } {
	# eval plot2d $args -windowname $win  [plot2dGetRanges $data] -xfun [list {}] -data [list $data]
	eval plot2d $args -windowname $win   -xfun [list {}] -data [list $data]	
    } else {
	# puts data=$data
	set com [concat \
		     plot3d $args -windowname $win -zfun {{}} -data [lrange $data 1 end]]
	# puts com=$com
	eval $com
    }
}



proc plot2dGetDataRange { data } {
    set rangex ""
    set rangey ""
    #puts "data=$data"
    set extra ""
    foreach d $data {
	#puts first=[lindex $d 0]
	if { [catch { 	
	    switch -exact -- [lindex $d 0] {
		xversusy {
		    foreach { xx yy } [lrange $d 1 end] {
			# puts "hi xx=[llength $xx],yy=[llength $yy]"
			if { [llength $xx] > 0 } {
			    set rangex [minMax $xx $rangex]
			    set rangey [minMax $yy $rangey]
			}
		    }
		    #puts "rangex=$rangex,rangey=$rangey"
		}
		againstIndex {
		    set rangex [minMax [list 0 [llength [lindex $d 1]]] $rangex]
		    set rangey [minMax [lindex $d 1] $rangey]
		}
		default {
		    set vv [lindex $d 0]
		    if { [lsearch {xrange yrange   } $vv] >= 0 } {
			set radius [expr {([lindex $d 2] -[lindex $d 1])/2.0 }]
			set center [expr {([lindex $d 2] +[lindex $d 1])/2.0 }]
			set var [string range $vv 0 0]
			lappend extra -${var}radius $radius -${var}center $center
		    }
		    if { [lsearch bargraph $vv] >= 0 } {
			set rangey [minMax 0 $rangey]
		    }


		    if { [lsearch {xradius yradius xcenter ycenter } $vv] >= 0 } {
			# these arguments must have numerical values
			lappend extra -$vv [expr {1*[lindex $d 1]}]
		    }

		}
	    }
	} errmsg ] } {
	    bgerror "bad data: [string range $d 0 2].."
# 	    set com [list error "bad data: [string range $d 0 200].." $errmsg]
# 	    after 1 $com
	}
    }

    list $rangex $rangey $extra
}



proc plot2dRangesToRadius  { rangex rangey extra } {
    set ranges ""
    # puts "extra=$extra"
    foreach u { x y } {
	if { "[assoc -[set u]radius $extra]" == "" } {
	    desetq "min max" [set range$u]
	    if { "$min" == "$max" } {
		set min [expr {$min - .5}]
		set max [expr {$max + .5}]
	    }
	    #puts "$u has $min,$max"
	    if { "$max" != "" } {
		
		lappend extra -[set u]radius [expr {($max-$min)/2.0}] \
		    -[set u]center [expr {($max+$min)/2.0}]
	    }
	}
    }
    # puts "extra=$extra"
    return $extra
}


proc redraw2dData { win  args } {
    makeLocal $win c linecolors data xfundata errorbar linewidth
    set tags [assoc -tags $args {} ]
    set rtosx rtosx$win ; set rtosy rtosy$win
    set i -1
    set label _default
    append data " " $xfundata
    #    set linewidth 2.4

    #puts "data=$data"
    foreach d $data {
	set type [lindex $d 0]
	switch  $type {
	    xversusy {
		#puts "starting .. [oget $win curveNumber]"
		set curvenumber [oget $win curveNumber]
		# the data can be multiple lists and each list
		# will not be line connected to previous
		foreach {xvalues yvalues} [lrange $d 1 end] {
		    # puts "xvalues=$xvalues"
		    #puts "here:$curvenumber,[oget $win curveNumber]"
		    oset $win curveNumber $curvenumber
		    set n [expr {[llength $xvalues] -1}]
		    while { [llength $yvalues] > 0 } {
			set ans ""
			set color [nextColor $win]
			catch { set color [oget $win color] }
			
			if { [info exists didLabel([oget $win curveNumber])] } {
			    set label ""
			} else {
			    set didLabel([oget $win curveNumber]) 1
			}
			set errorbar [oget $win errorbar]
			# puts "errorbar=$errorbar"
			if { $errorbar != 0 } {
			    set j 0
			    # puts "xvalues=$xvalues,yvalues=$yvalues"
			    for { set i 0 } { $i <= $n } {incr i} {
				set x [lindex $xvalues $i]
				set y1 [lindex $yvalues [expr {$i * 2}]]
				set y2 [lindex $yvalues [expr { $i * 2 +1}]]
				if { 1 } {
				    # puts "x=$x,y1=$y1,y2=$y2"
				    set xx [$rtosx $x]
				    set y1 [$rtosy $y1]
				    set y2 [$rtosy $y2]
				    $c create line [expr {$xx - $errorbar}] $y1 [expr {$xx +$errorbar}] $y1 $xx $y1 $xx $y2 [expr {$xx -$errorbar}] $y2 [expr {$xx + $errorbar}] $y2  -tags [list [concat $tags line[oget $win curveNumber]]]  -fill $color
				}
			    }
			    set yvalues [lrange $yvalues [llength $xvalues] end]
			} else {

			    foreach x $xvalues y [lrange $yvalues 0 $n] {
				append ans "[$rtosx $x] [$rtosy $y] "
				
			    }

			    drawPlot $win [list $ans] -tags [list [concat $tags line[oget $win curveNumber]]]  -fill $color -label $label
			}
			set label _default
			set yvalues [lrange $yvalues [llength $xvalues] end]
		    }
		}
	    }
	    againstIndex {
		set color [nextColor $win]
		set ind 0
		set ans ""
		foreach y [lindex $d 1] {
		    append ans "[$rtosx $ind] [$rtosy $y] "
		    incr ind
		}
		
		drawPlot $win [list $ans] -tags \
		    [list [concat $tags line[oget $win curveNumber]]] \
		    -fill $color -width $linewidth -label $label
		set label _default

		# eval $c create line $ans -tags \
		#  [list [concat $tags line[oget $win curveNumber]]] \
		#  -fill $color -width .2
	    }
	    label {
		set label [lindex $d 1]
	    }
	    default {

		# puts "$type,[lindex $d 1]"
		if { [lsearch { xfun color plotpoints linecolors pointsize \
				    nolines bargraph errorbar maintitle \
				    linewidth labelposition xaxislabel \
				    yaxislabel dydx } $type] >= 0 } {
		    # puts "setting oset $win $type [lindex $d 1]"
		    oset $win $type [lindex $d 1]
		} elseif { "$type" == "text" } {
		    desetq "x y text" [lrange $d 1 end]
		    $c create text [$rtosx $x] [$rtosy $y] -anchor nw \
			-text $text -tags "text all" -font {times 16 normal}
		}
	    }
	}
    }
}

proc plot2dDrawLabel { win label color } {
    makeLocal $win c labelposition xmin ymax
    #puts "$win $label $color"
    if { "$label" == ""} {return }
    set bb [$c bbox label]
    desetq "a0 b0" $labelposition
    set a0 [expr $a0 + [rtosx$win $xmin]]
    set b0 [expr $b0 + [rtosy$win $ymax]]
    if { "$bb" == "" } { set bb "$a0 $b0 $a0 $b0" }
    desetq "x0 y0 x1 y1" $bb
    set leng  15
    set last [$c create text [expr {$a0 +$leng +4}] \
		  [expr {2 + $y1}] \
		  -anchor nw       -text "$label" -tags label]
    desetq "ux0 uy0 ux1 uy1" [$c bbox $last]
    $c create line $a0 [expr {($uy0+$uy1) /2}] [expr {$a0 +$leng}] [expr {($uy0+$uy1) /2}]   -tags "label" -fill $color
}


proc RealtoScreen { win listPts } {
    set rtosx rtosx$win ; set rtosy rtosy$win
    set ans ""
    if { [llength [lindex $listPts  0]] != 1 } {
	foreach v $listPts {
	    append ans " {"
	    append ans [RealtoScreen $win $v]
	    append ans "}"
	}
    }    else {
	foreach {x y } $listPts {
	    append ans " [$rtosx $x] [$rtosy $y]"
	}
    }
    return $ans
}

proc drawPlot {win listpts args } {
    makeLocal $win  c nolines nolegend plotpoints  pointsize bargraph linewidth
    #    set linewidth 2.4
    # puts ll:[llength $listpts]
    set tags [assoc -tags $args ""]
    if { [lsearch $tags path] < 0 } {lappend tags path}
    set fill [assoc -fill $args black]
    set label [assoc -label $args ""]
    if { "$label" == "_default" } {
	set label line[oget $win curveNumber]
    }

    catch { set fill [oget $win color] }

    if { $nolines == 1 && $plotpoints == 0 && $bargraph == 0} {
	set plotpoints 1
    }

    catch {
	foreach pts $listpts {
	    if { $bargraph } {
		set rtosy rtosy$win
		set rtosx rtosx$win
		set width [expr {abs([$rtosx $bargraph] - [$rtosx 0])}]
		set w2 [expr {$width/2.0}]
		# puts "width=$width,w2=$w2"
		set ry0 [$rtosy 0]
		foreach { x y } $pts {
		    $c create rectangle [expr {$x-$w2}] $y  [expr {$x+$w2}] \
			$ry0 -tags $tags -fill $fill }
	    } else {
		if { $plotpoints } {
		    set im [getPoint $pointsize $fill]
		
		    # there is no eval, so we need this.
		    if { "$im" != "" } {
			foreach { x y } $pts {
			    $c create image $x $y -image $im -anchor center \
				-tags "$tags point"
			}
		    } else {
			foreach { x y } $pts {
			    $c create oval [expr {$x -$pointsize}] \
				[expr {$y -$pointsize}] [expr {$x +$pointsize}] \
				[expr {$y +$pointsize}] -tags $tags \
				-fill $fill -outline {}
			
			}
		    }
		}
		
		if { $nolines == 0 } {
		    set n [llength $pts]
		    set i 0
		    set res "$win create line "
		    #puts npts:[llength $pts]
		    if { $n >= 6 } {
			eval $c create line $pts -tags [list $tags] -width $linewidth -fill $fill
		    }
		}
	    }
	
	}
    }
    if { $nolegend == 0 } {
	plot2dDrawLabel $win $label $fill
    }
}



proc drawPointsForPrint { c } {
    global maxima_priv
    foreach v [$c find withtag point] {
	set tags [ldelete point [$c gettags $v]]
	desetq "x y" [$c coords $v]
	
	
	desetq "pointsize fill" $maxima_priv(pointimage,[$c itemcget $v -image])
	catch {
	    $c create oval [expr {$x -$pointsize}] \
		[expr {$y -$pointsize}] [expr {$x +$pointsize}] \
		[expr {$y +$pointsize}] -tags $tags \
		-fill $fill -outline {}
	    $c delete $v			
	}


    }

}

proc getPoint { size color } {
    global maxima_priv
    set im ""
    if { ![catch { set im $maxima_priv(pointimage,$size,$color) }] } {
	return $im
    }
    catch { set data $maxima_priv(bitmap,disc[expr {$size * 2}])
	set im [image create bitmap -data $data -foreground $color]
	set maxima_priv(pointimage,$size,$color) $im
	set maxima_priv(pointimage,$im) "$size $color"
    }
    return $im
}




proc sliderCommandPlot2d { win var val } {
    linkLocal $win recompute

    updateParameters $win $var $val
    set com "recomputePlot2d $win"
    # allow for fast move of slider...
    #mike FIXME: this is a wrong use of after cancel
    after cancel $com
    after 10 $com
}

proc recomputePlot2d { win } {
    replot2d $win
}


## endsource plot2d.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Matrix.tcl,v 1.4 2006-10-01 23:58:29 villate Exp $
#
###### Matrix.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

# In this file a matrix is represented by a list of M*N entries together
# with an integer N giving the number of columns: {1 0 0 1} 2  would give
# the two by two identity

proc comment {args } {
}
global mee
set mee " } \] \[ expr { "

proc mkMultLeftExpr { mat n prefix { constant "" } } {
    #create a function body that does MAT (prefix1,prefix2,..) + constant
    global mee
    set all ""

    set vars ""
    for { set i 0} { $i < $n} {incr i} { append vars " $prefix$i" }
    set j 0
    set k 0

    foreach v $mat {
	if { $j == 0 } {
	    set ro ""
	    # append ans ""
	    set op ""
	}
        append ro " $op $v*\$$prefix$j"
	set op "+"
	if { $j == [expr {$n -1}] } {
	    append ans " "
	    if { "[lindex $constant $k]" != "" } {
		append ro " + [lindex $constant $k] "
	    }
	    incr k
	    append ans [concat \[ expr [list $ro] \]]
	    set j -1
	}
	incr j
    }
    # puts [list $vars $ans]
    return [list $vars $ans]
}

proc mkMultLeftFun { mat n name { constant ""} } {
    set expr [mkMultLeftExpr $mat $n _a $constant]
    set bod1 [string trim [lindex $expr 1] " "]
    #    set bod "return \"$bod1\""
    set bod [concat list [lindex $expr 1]]
    proc $name [lindex $expr 0] $bod
}

proc rotationMatrix { th ph } {
    return [list \
		[expr {cos($ph)*cos($th)}] [expr {- cos($ph)*sin($th)}] [expr {sin($ph)}] \
		[expr {sin($th)}] [expr {cos($th)}] 0.0 \
		[expr {- sin($ph)*cos($th)}] [expr {sin($ph)*sin($th)}] [expr {cos($ph)}]]
}

proc rotationMatrix { thx thy thz } {
    return \
	[list  \
	     [expr { cos($thy)*cos($thz) } ] \
	     [expr { cos($thy)*sin($thz) } ] \
	     [expr { sin($thy) } ] \
	     [expr { sin($thx)*sin($thy)*cos($thz)-cos($thx)*sin($thz) } ] \
	     [expr { sin($thx)*sin($thy)*sin($thz)+cos($thx)*cos($thz) } ] \
	     [expr { -sin($thx)*cos($thy) } ] \
	     [expr { -sin($thx)*sin($thz)-cos($thx)*sin($thy)*cos($thz) } ] \
	     [expr { sin($thx)*cos($thz)-cos($thx)*sin($thy)*sin($thz) } ] \
	     [expr { cos($thx)*cos($thy) } ] ]
}

# cross [a,b,c] [d,e,f] == [B*F-C*E,C*D-A*F,A*E-B*D]
# cross_product([a,b,c],[d,e,f]):=[B*F-C*E,C*D-A*F,A*E-B*D]
# cross_product(u,v):=sublis([a=u[1],b=u[2],c=u[3],d=v[1],e=v[2],f=v[3]],[B*F-C*E,C*D-A*F,A*E-B*D]);
# the rotation by azimuth th, and elevation ph
# MATRIX([COS(TH),SIN(TH),0],[-COS(PH)*SIN(TH),COS(PH)*COS(TH),SIN(PH)],
#	    [SIN(PH)*SIN(TH),-SIN(PH)*COS(TH),COS(PH)]);

proc rotationMatrix { th ph {ignore {} } } {
    return \
	[list \
	     [	    expr {cos($th)   } ]\
	     [expr {sin($th)   } ]\
	     0 \
	     [expr {-cos($ph)*sin($th)   } ]\
	     [expr {cos($ph)*cos($th)   } ]\
	     [expr {sin($ph)   } ]\
	     [expr {sin($ph)*sin($th)   } ]\
	     [expr {-sin($ph)*cos($th)   } ]\
	     [expr {cos($ph)   } ]]
}

proc setMatFromList {name lis n} {
    set i 1
    set j 1
    foreach v $lis {
	uplevel 1 set [set name]($i,$j) $v
	if { $j == $n } {set j 1; incr i} else { incr j}
    }
}

proc matRef { mat cols i j } {
    [lindex $mat [expr {$i*$cols + $j}]]
}

proc matTranspose { mat cols } {
    set j 0
    set m [expr {[llength $mat ] / $cols}]
    while { $j < $cols} {
	set i 0
	while { $i < $m } {
	    append ans " [lindex $mat [expr {$i*$cols + $j}]]"
	    incr i
	}
	incr j
    }
    return $ans
}


proc matMul { mat1 cols1 mat2 cols2 } {
    mkMultLeftFun $mat1 $cols1 __tem
    set tr [matTranspose $mat2 $cols2]
    set rows1 [expr {[llength $mat1] / $cols1}]
    #puts "tr=$tr"
    set upto [llength $tr]
    set j 0
    set ans ""
    set i 0
    while { $j < $cols2  } {
	append ans " [eval __tem [lrange $tr $i [expr {$i+$cols1 -1}]]]"
	incr i $cols1
	incr j
    }
    #   return $ans
    # puts "matTranspose $ans $rows1"
    return [matTranspose $ans $rows1]
}



proc invMat3 { mat } {
    setMatFromList xx $mat 3
    set det [expr { double($xx(1,1))*($xx(2,2)*$xx(3,3)-$xx(2,3)*$xx(3,2))-$xx(1,2)* \
			($xx(2,1)*$xx(3,3)-$xx(2,3)*$xx(3,1))+$xx(1,3)*($xx(2,1)*$xx(3,2)\
									    -$xx(2,2)*$xx(3,1)) }]

    return [list   [expr { ($xx(2,2)*$xx(3,3)-$xx(2,3)*$xx(3,2))/$det}] \
		[expr { ($xx(1,3)*$xx(3,2)-$xx(1,2)*$xx(3,3))/$det}] \
		[expr { ($xx(1,2)*$xx(2,3)-$xx(1,3)*$xx(2,2))/$det}] \
		\
		[expr { ($xx(2,3)*$xx(3,1)-$xx(2,1)*$xx(3,3))/$det}] \
		[expr { ($xx(1,1)*$xx(3,3)-$xx(1,3)*$xx(3,1))/$det}] \
		[expr { ($xx(1,3)*$xx(2,1)-$xx(1,1)*$xx(2,3))/$det}] \
		\
		[expr { ($xx(2,1)*$xx(3,2)-$xx(2,2)*$xx(3,1))/$det}] \
		[expr { ($xx(1,2)*$xx(3,1)-$xx(1,1)*$xx(3,2))/$det}] \
		[expr { ($xx(1,1)*$xx(2,2)-$xx(1,2)*$xx(2,1))/$det}]]
}


proc vectorOp { a op b} {
    set i [llength $a]
    set k 0
    set ans [expr [list [lindex $a 0]  $op [lindex $b 0]]]
    while { [incr k] < $i } {
	lappend ans  [expr  [list [lindex $a $k] $op [lindex $b $k]]]
    }
    return $ans
}
## endsource matrix.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Plot3d.tcl,v 1.19 2011-03-12 17:29:04 villate Exp $
#
###### Plot3d.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

global plot3dOptions
set plot3dOptions {
    {xradius 1 "Width in x direction of the x values" }
    {yradius 1 "Height in y direction of the y values"}

    {width 500 "Width of canvas in pixels"}
    {height 500 "Height of canvas in pixels" }
    {xcenter 0.0 {(xcenter,ycenter) is the origin of the window}}
    {ycenter 0.0 "see xcenter"}
    {zcenter 0.0 "see xcenter"}
    {bbox "" "xmin ymin xmax ymax zmin zmax overrides the -xcenter etc"}
    {zradius auto " Height in z direction of the z values"}
    {az 30 "azimuth angle" }
    {el 60 "elevation angle" }

    {thetax 10.0 "ignored is obsolete: use az and el"}
    {thetay 20.0 "ignored is obsolete: use az and el"}
    {thetaz 30.0 "ignored is obsolete: use az and el"}

    {flatten 1 "Flatten surface when zradius exceeded" }
    {zfun "" "a function of z to plot eg: x^2-y^2"}
    {parameters "" "List of parameters and values eg k=3,l=7"}
    {sliders "" "List of parameters ranges k=3:5,u"}
    {data  "" "a data set of type { variable_grid xvec yvec zmatrix}
    or {matrix_mesh xmat ymat zmat} or {grid {xmin xmax} {ymin ymax} zmatrix}"}
    {nsteps "10 10" "steps in x and y direction"}
    {rotationcenter "" "Origin about which rotation will be done"}
    {zoomfactor "1.6 1.6" "Factor to zoom the x and y axis when zooming.  Zoom out will be reciprocal" }
    {screenwindow "20 20 700 700" "Part of canvas on screen"}
    {windowname ".plot3d" "window name"}
    {psfile "" "A filename where the graph will be saved in PostScript."}
    {nobox 0 "if not zero, do not draw the box around the plot."}
    {hue 0.25 "Default hue value."}
    {saturation 0.7 "Default saturation value."}
    {value 0.8 "Default brightness value."}
    {colorrange 0.5 "Range of colors used."}
    {ncolors 180 "Number of colors used."}
    {colorscheme "hue" "Coloring Scheme (hue, saturation, value, gray or 0)."}
    {mesh_lines "black" "Color for the meshes outline, or 0 for no outline."}
}


## source Matrix.tcl

proc transformPoints { pts fun } {
    set ans ""
    foreach { x y z } $pts {
	append ans " "
	append ans [$fun $x $y $z]
    }
    return $ans
}

proc calculatePlot3d {win fun  nx ny } {
    global plot3dMeshes$win
    set meshes  plot3dMeshes$win
    makeLocal $win xradius xmin yradius ymin zradius zcenter flatten

    set stepx [expr { 2*$xradius / double($nx)}]
    set stepy [expr { 2*$yradius / double($ny)} ]
    set i 0
    set j 0
    set zmax -1000000000
    set zmin 1000000000
    # check if zradius is a number
    set dotruncate [expr ![catch {expr {$zradius + 1} }]]
    if { $dotruncate } {
	if { $flatten } { set dotruncate 0 }
	set zzmax [expr {$zcenter + $zradius}]
	set zzmin [expr {$zcenter - $zradius}]
	#puts "zzmax=$zzmax,$zzmin"
    } else {
	set flatten 0
    }

    catch { unset  $meshes }
    set k 0
    for {set i 0} { $i <= $nx } { incr i} {
	set x [expr { $xmin + $i * $stepx }]
	for {set j 0} { $j <= $ny } { incr j} {
	    set y [expr { $ymin + $j *$stepy }]
	    if { [catch {  set z [$fun $x $y] }] } {
		set z nam
	    } elseif { $dotruncate  &&  ($z > $zzmax || $z < $zzmin) } {
		set z nam

	    } else {
		if { $flatten } {
		    if { $z > $zzmax } { set z $zzmax } elseif {
								$z < $zzmin } { set z $zzmin }}
		
		if { $z < $zmin }  { set zmin $z } elseif {
							   $z > $zmax } { set zmax $z }
		if { $j != $ny && $i != $nx } {
		    set [set meshes]($k) \
			"$k [expr { $k+3 }] [expr { $k+3+($ny+1)*3 }] \
		      [expr { $k+($ny+1)*3 }]"} else {
			  # set plot3dMeshes($k) ""
		      }
	    }
	    incr k 3
	    append ans " $x $y $z"
	}
    }
    oset $win zmin $zmin
    oset $win zmax $zmax
    oset $win points $ans
    oset $win nx $nx
    oset $win ny $ny
    oset $win colorfun plot3dcolorFun
    addAxes $win
    setupPlot3dColors $win
}

proc calculatePlot3data {win fun  nx ny } {
    # calculate the 3d data from function:
    makeLocal $win xradius xmin xmax ymax yradius ymin zradius zcenter flatten

    set rowx [linspace $xmin $xmax $nx]
    set rowy [linspace $ymin $ymax $ny]
    foreach  y $rowy {
	set row ""
	foreach x $rowx {
	    if { [catch {  set z [$fun $x $y] }] } {
		set z nam
	    }
	    lappend row $z
	}
	lappend matrix $row
    }
    global silly
    set silly [list variable_grid $rowx $rowy $matrix ]
    return [list variable_grid $rowx $rowy $matrix ]

}

proc addAxes { win } {
    #global plot3dPoints plot3dMeshes xradius yradius xcenter ycenter
    global [oarray $win] plot3dMeshes$win
    linkLocal $win lmesh
    makeLocal $win   xradius yradius xcenter ycenter  points zmax zcenter zmin
    set meshes plot3dMeshes$win
    set ll [llength $points]

    # puts "oset $win  axisstart  $ll"
    oset $win  axisstart  $ll
    set nx2 5
    set ny2 5
    set xstep [expr { 1.2 * $xradius/double($nx2) }]
    set ystep [expr { 1.2 * $yradius/double($ny2) }]
    set nz2 $ny2

    set ans " "
    set x0 $xcenter
    set y0 $ycenter
    set z0 $zcenter

    set k $ll
    for { set i 0 } { $i < $nx2 } { incr i } {
	append ans "[expr {$x0 +$i * $xstep}] $y0 $z0 "
	lappend lmesh [list $k [incr k 3]]
	#set [set meshes]($k) "$k [incr k 3]"
    }
    append ans "[expr {$x0 +$nx2 * $xstep}] $y0 $z0 "
    incr k 3
    # set plot3dMeshes($k) ""

    for { set i 0 } { $i < $ny2 } { incr i } {
	append ans "$x0 [expr {$y0 +$i * $ystep}] $z0 "
	lappend lmesh [list $k [incr k 3]]
	#set [set meshes]($k) "$k [incr k 3]"
    }
    append ans "$x0 [expr {$y0 +$ny2 * $ystep}] $z0 "
    incr k 3
    # set $meshes($k) ""

    set zstep [expr {1.2 * $zmax/double($nz2)}]
    if { $zstep < $ystep } { set zstep $ystep }

    for { set i 0 } { $i < $ny2 } { incr i } {
	append ans "$x0 $y0 [expr {$z0 +$i * $zstep}] "
	# puts "set [set meshes]($k) \"$k [incr k 3]\""
	lappend lmesh [list $k [incr k 3]]
	# set [set meshes]($k) "$k [incr k 3]"
    }
    append ans "$x0 $y0 [expr {$z0 +$nz2 * $zstep}] "
    incr k 3
    # puts "ans=$ans"
    append [oloc $win points] $ans

    # set $meshes($k) ""

}

proc addBbox { win } {
    global plot3dMeshes$win
    makeLocal $win xmin xmax ymin ymax zmin zmax  cmap
    linkLocal $win points lmesh
    set ll [llength $points]
    append points " $xmin $ymin $zmin \
	    $xmax $ymin $zmin \
            $xmin $ymax $zmin \
            $xmax $ymax $zmin \
            $xmin $ymin $zmax \
	    $xmax $ymin $zmax \
            $xmin $ymax $zmax \
            $xmax $ymax $zmax "
    foreach  { a b } { 0 1 0 2 2 3 3 1
	4 5 4 6 6 7 7 5
	0 4 1 5 2 6 3 7  }  {
	set k [expr {$a*3 + $ll}]
	set l [expr {$b*3 + $ll}]
	# set plot3dMeshes${win}($k) [list $k $l]
	lappend lmesh [list $k $l]
    }
    lappend lmesh [list $ll]
    oset $win $cmap,[list $ll [expr {$ll + 3}]] red
    oset $win $cmap,[list $ll [expr {$ll + 6}]] blue
    oset $win $cmap,[list $ll [expr {$ll + 12}]] green

    oset $win special($ll) "drawOval [oget $win c] 3 -fill red -tags axis"
}

proc drawOval { c radius args } {
    set ll [llength $args]
    set x [lindex $args [expr {$ll -2}]]
    set y [lindex $args [expr {$ll -1}]]
    set rest [lrange $args 0 [expr {$ll -3}]]
    set com [concat $c create oval [expr {$x - $radius}]  [expr {$y - $radius}] [expr {$x + $radius}]  [expr {$y + $radius}] $rest]
    eval $com
}

proc plot3dcolorFun {win z } {
    makeLocal $win zmin zmax ncolors hue saturation value colorrange colorscheme
    if { $z < $zmin || $z > $zmax } {
	return "none"
    }
    set h [expr { 360*$hue }]
    if { ($value > 1) || ($value < 0) } {
	set value [expr { $value - floor($value) }]
    }
    set tem [expr {(double($colorrange)/$ncolors)*round(($z - $zmin)*$ncolors/($zmax - $zmin+.001))}]
    switch -exact $colorscheme {
	"hue" { return [hsv2rgb [expr { 360*$tem+$h }] $saturation $value] }
	"saturation" { return [hsv2rgb $h [expr { $tem+$saturation }] $value] }
	"value" { return [hsv2rgb $h $saturation [expr {$tem+$value}]] }
	"gray"  { set g [expr { round( ($tem+$value)*255 ) } ]
	    return  [format "\#%02x%02x%02x" $g $g $g] }
	"0" { return "#ffffff" }
    }
}

proc setupPlot3dColors { win first_mesh} {
    upvar #0 [oarray $win] wvar
    # the default prefix for cmap
    set wvar(cmap) c1
    makeLocal $win colorfun points lmesh
    foreach tem [lrange $lmesh $first_mesh end] {
        set k [llength $tem]
	if { $k == 4 } {
	    set z [expr { ([lindex $points [expr { [lindex $tem 0] + 2 } ]] +
			   [lindex $points [expr { [lindex $tem 1] + 2 } ]] +
			   [lindex $points [expr { [lindex $tem 2] + 2 } ]] +
			   [lindex $points [expr { [lindex $tem 3] + 2 } ]])/
			  4.0 } ]
	    catch { set wvar(c1,[lindex $tem 0]) [$colorfun $win $z] }
	}
    }
}

proc calculateRotated { win } {
    set pideg [expr {3.14159/180.0}]
    linkLocal $win scale
    makeLocal $win az el rotationcenter xradius zradius yradius
    set rotmatrix [rotationMatrix [expr {$az * $pideg }] \
		       [expr {$el * $pideg }] \
		      ]

    # shrink by .2 on z axis
    # set fac [expr  {[vectorlength $xradius $yradius] / (sqrt(2) * $zradius)}]

    set rotmatrix [ matMul  $rotmatrix 3 $scale 3 ]
    set tem [matMul $scale 3 $rotationcenter 1]

    mkMultLeftFun  $rotmatrix 3 _rot$win
    set rot _rot$win
    set ans ""
    # puts "points=[oget $win points]"
    if { "$rotationcenter" != "" } {
	#puts "rotationcenter = $rotationcenter"
	set constant [vectorOp $tem - [eval $rot $rotationcenter]]
	mkMultLeftFun  $rotmatrix 3 _rot$win $constant
    }
    #puts "win $win"
    foreach { x y z } [oget $win points] {
	if { [catch { append ans " " [$rot $x $y $z] } ] } {
	    append ans "  nam nam nam " }
    }
    oset $win rotatefun $rot
    oset $win rotated $ans
}

proc getOrderedMeshIndices { win } {
    #   global  plot3dMeshes$win
    #    set meshes plot3dMeshes$win
    linkLocal $win lmesh
    # puts "array names $meshes =[array names $meshes ]"
    # get the list offset by 2, so the lindex indices grab the Z coordinate.
    # without having to add 2.
    set pts2 [lrange [oget $win rotated] 2 end]
    set i 0
    foreach tem $lmesh {
        set k [llength $tem]
	if { [catch {
	    if {  $k == 4 } {
		set z [expr { ([lindex $pts2 [lindex $tem 0]] \
				   +[lindex $pts2 [lindex $tem 1]] \
				   + [lindex $pts2 [lindex $tem 2]] \
				   + [lindex $pts2 [lindex $tem 3]])/4.0 }]
	    } elseif { $k == 2 } {
		set z [expr { ([lindex $pts2 [lindex $tem 0]] \
				   +[lindex $pts2 [lindex $tem 1]])/2.0 }]
	    } else {
		set z 0
		foreach w $tem {
		    set z [expr {$z + [lindex $pts2 $w] }  ]
		
		}	
		set z [expr { $z/double($k)}]
	    }
	    lappend ans [list $z $i]
	    # append pp($z) "$i "
	    incr i
	
	} ]} {
	    set lmesh [lreplace $lmesh $i $i]
	}
    }
    set ttem [lsort -real -index 0 $ans]
    set ans {}
    foreach v $ttem {
	lappend ans [lindex $v 1]
    }
    oset $win meshes $ans
    return
}


proc setUpTransforms3d { win } {
    global screenwindow
    #set scr $screenwindow
    # setUpTransforms $win .7
    # set screenwindow $scr
    linkLocal $win scale
    makeLocal $win xcenter ycenter xradius yradius c zmin zmax xmin xmax ymin ymax zradius
    #dshow xcenter ycenter xradius yradius c zmin zmax xmin xmax ymin ymax zradius
    set fac .5

    set delx [$c cget -width]
    set dely [$c cget -height]
    set f1 [expr {(1 - $fac)/2.0}]

    set scale [list [expr {1.5/($xradius)}] 0 0 0 [expr {1.5/($yradius)}] 0 0 0 [expr {1.5/($zradius)}] ]

    set x1 [expr {$f1 *$delx}]
    set y1 [expr {$f1 *$dely}]
    set x2 [expr {$x1 + $fac*$delx}]
    set y2 [expr {$y1 + $fac*$dely}]
    # set xmin [expr {($xcenter - $xradius) * 1.5/ ($xradius)}]
    # set ymin [expr {($ycenter - $yradius) * 1.5/ ($yradius)}]
    # set xmax [expr {($xcenter + $xradius) * 1.5/ ($xradius)}]
    # set ymax [expr {($ycenter + $yradius) * 1.5/ ($yradius)}]
    #puts "RANGES=$xmin,$xmax $ymin,$ymax $zmin,$zmax"
    desetq "xmin ymin" [matMul $scale 3 "$xmin $ymin 0" 1]
    desetq "xmax ymax" [matMul $scale 3 "$xmax $ymax 0" 1]
    #puts "RANGES=$xmin,$xmax $ymin,$ymax $zmin,$zmax"
    # set transform [makeTransform "$xmin $ymin $x1 $y2" "$xmin $ymax $x1 $y1 " "$xmax $ymin $x2 $y2"]
    # desetq "xmin xmax ymin ymax" "-2 2 -2 2"

    set transform [makeTransform "$xmin $ymin $x1 $y2" "$xmin $ymax $x1 $y1 " "$xmax $ymin $x2 $y2"]
    oset $win transform $transform
    oset $win transform0 $transform

    getXtransYtrans $transform rtosx$win rtosy$win
    getXtransYtrans [inverseTransform $transform] storx$win story$win

}

#

proc plot3d { args } {
    global  plot3dOptions
    set win [assoc -windowname $args]
    if { "$win" == "" } {
	set win [getOptionDefault windowname $plot3dOptions] }
    clearLocal $win
    apply mkPlot3d  $win $args
    #    bind $win <Configure> {}	
    replot3d $win
}

proc replot3d { win } {
    global printOption
    makeLocal $win nsteps zfun data c
    linkLocal $win parameters sliders psfile nobox

    oset $win maintitle    "concat \"Plot of z = [oget $win zfun]\""
    if { [llength $nsteps] == 1 }    {
	oset $win nsteps \
	    [set nsteps  [list [lindex $nsteps 0] [lindex $nsteps 0]]]
    }

    set sliders [string trim $sliders]
    if { "$sliders" != "" && ![winfo exists $c.sliders] } {
	addSliders $win
    }

    set zfun [string trim $zfun]
    if { "$zfun" != "" } {
	proc _xf {  x  y } "return \[expr { [sparseWithParams $zfun {x y} $parameters ] } \]"
	addOnePlot3d $win [calculatePlot3data $win _xf  [lindex $nsteps 0] [lindex $nsteps 1]]
	# calculatePlot3d $win _xf [lindex $nsteps 0] [lindex $nsteps 1]
    }

    set data [string trim $data]
    if { "$data" != "" } {
	if { 0 } {
	    puts "here"
	    set ranges [ plot3dGetDataRange [list $data]]
	    linkLocal $win zmin zmax
	    desetq "zmin zmax" [lindex $ranges 2]
	    puts "ranges=$ranges"
	    set some [plot2dRangesToRadius [lindex $ranges 0] [lindex $ranges 1] ""]
	    puts "and now"
	    foreach {v k} $some {
		puts "oset $win [string range $v 1 end] $k"
		oset $win [string range $v 1 end] $k
	    }
        }
	
	addOnePlot3d $win $data
    }

    setUpTransforms3d $win

    if { $nobox == 0 } {
	addBbox $win
    }
    # grab the bbox just as itself
    global maxima_priv
    linkLocal $win lmesh
    if { [llength $lmesh] >   100 * $maxima_priv(speed)  } {
	# if we judge that rotation would be too slow, we make a secondary list
	# of meshes (random) including the bbox, and display those.
	linkLocal $win  points lmeshBbox pointsBbox
	set n [llength $lmesh]
	set lmeshBbox [lrange $lmesh [expr {$n -13}] end]
	set i 0 ;
	while { [incr i ] < ( 35*$maxima_priv(speed)) } {
	    set j [expr {round(floor(rand()*($n-13))) }]
	    if { ![info exists temm($j)] } {
		lappend lmeshBbox [lindex $lmesh $j ]
		set temm(j) 1
	    }
	}
	resetPtsForLmesh $win
    }
    oset $win lastAnglesPlotted ""
    setView $win ignore

    # Create a PostScript file, if requested
    if { $psfile != "" } {
	set printOption(psfilename) $psfile
	writePostscript $win
	$c delete printoptions
	eval [$win.menubar.close cget -command]
    }

}

proc setView { win ignore } {
    global timer
    foreach v [after info] {
	#puts "$v=<[after info $v]>"
	if {[lindex [after info $v] 0] == "setView1" } {
	    after cancel $v
	}
    }
    after 2 setView1 $win
}

proc setView1 { win  } {
    linkLocal $win lastAnglesPlotted points
    set new [list [oget  $win az] [oget  $win el] ]
    if { "$new" != "$lastAnglesPlotted" } {
   	makeLocal $win c
	calculateRotated $win
	getOrderedMeshIndices $win
	drawMeshes $win $c
	oset $win lastAnglesPlotted $new
    }
}

proc setQuick { win on } {
    linkLocal $win  lmesh  points savedData cmap 	lmeshBbox pointsBbox
    if { $on } {
	if { ![info exists savedData] && [info exists lmeshBbox] } {
	    set savedData [list $lmesh $points $cmap]
	    set lmesh $lmeshBbox
	    set points $pointsBbox
	    set cmap c2
	}
    } else {
	if { [info exists savedData] } {
	    desetq "lmesh points cmap" $savedData
	    unset savedData
	    oset $win lastAnglesPlotted ""
	}
    }
}


# reduce the set of pointsBbox to include only those needed by lmeshBbox
proc resetPtsForLmesh { win } {
    upvar 1 lmeshBbox lmeshBbox
    upvar 1 pointsBbox pointsBbox
    upvar 1 points points
    upvar #0 [oarray $win] wvar
    set k 0
    foreach v $lmeshBbox {
	if { [llength $v] == 1 } {
	    lappend nmesh $v
	} else {
	    set s ""
	    foreach w $v {
		if { [info exists tem($w)] } {
		    lappend s $tem($w)
		} else {
		    set tem($w) $k
		    lappend s $k
		    lappend pointsBbox \
			[lindex $points $w] \
			[lindex $points [expr {$w +1}]] \
			[lindex $points [expr {$w +2}]]
		    catch {set wvar(c2,$k) $wvar(c1,$w)}
		    incr k 3
		
		}
		
	    }
	    lappend nmesh $s
	    if { [info exists wvar(c1,$v)] } {
		set wvar(c2,$s) $wvar(c1,$v)
	    }
	}
    }
    set lmeshBbox  $nmesh
}

proc drawMeshes {win canv} {
    # $canv delete poly
    # only delete afterwards, to avoid relinquishing the colors
    $canv addtag oldpoly withtag poly
    $canv delete axis
    makeLocal $win lmesh rotated cmap
    upvar #0 [oarray $win] ar
    proc _xf { x} [info body rtosx$win]
    proc _yf { y} [info body rtosy$win]
    foreach { x y z} $rotated { lappend rotatedxy [_xf $x] [_yf $y] 0 }

    foreach k [oget $win meshes] {
	#puts "drawOneMesh $win $canv $k"
	#puts "drawOneMesh $win $canv $k"
	set mesh [lindex $lmesh $k]
	set col black
	catch { set col $ar($cmap,[lindex $mesh 0]) }
	drawOneMesh $win $canv $k $mesh $col
    }
    $canv delete oldpoly
}


#
#-----------------------------------------------------------------
# plot3dMeshes  --  given K an index in plot3dPoints(points)
# if this is the index of a lower grid corner, return the other points.
# k takes values 0,3,6,9,... the values returned all have a 3 factor,
# and so are true lindex indices into the list of points.
# returns {} if this is not a mesh point.
#  Results:
#
#  Side Effects: none... NOTE we should maybe cash this in an array.
#
#----------------------------------------------------------------
#

proc drawOneMesh { win  canv k mesh color } {
    #k=i*(ny+1)+j
    # k,k+1,k+1+nyp,k+nyp
    makeLocal $win mesh_lines
    upvar 1 rotatedxy ptsxy
    set n [llength $mesh]

    foreach kk $mesh {
	lappend coords [lindex $ptsxy $kk] [lindex $ptsxy [expr {$kk + 1}]]
    }
    if { $n <= 2 } {
	#puts "drawing $k,n=$n $coords, points $mesh "
	#desetq "a b" $mesh
	#puts "<[lrange $points $a [expr {$a +2}]]> <[lrange $points $b [expr {$b +2}]]"
	if { $n == 2 } {
	    #	    set color black
	    #	    catch { set color [oget $win $cmap,$mesh]}

	    eval $canv create line $coords -tags [list [list axis mesh.$k]] \
		-fill $color -width 2
	} else {
	    # puts "doing special $mesh, $coords"
	    catch { set tem [oget $win special([lindex $mesh 0])]
		eval [concat $tem $coords]
	    }
	}
    } elseif { [string length $color] < 8 && $color != "none"} {
	if { $mesh_lines != 0 } {
	    set outline "-outline $mesh_lines"
	} else {
	    set outline ""
	}
	eval $canv create polygon $coords -tags [list [list poly mesh.$k]] \
	    -fill $color $outline
    }
}

proc doHelp3d { win } {
    global Parser
    doHelp $win [join [list \
			[mc {

XMAXIMA'S PLOTTER FOR THREE-DIMENSIONAL GRAPHICS

To quit this help click anywhere on this text.

Clicking on Config will open a menu where several settings can be changed, \
such as the function being plotted, the azimuth and elevation angles, \
and the x and y centers and radii. Replot is used to update the plot with \
the changes made in the Config menu.

By clicking on Zoom, the mouse will allow you to zoom in on a region \
of the plot. Each click near a point magnifies the plot, keeping the center \
at the point you clicked. Depressing the SHIFT key while clicking \
zooms in the opposite direction.

Clicking on Rotate will return the mouse to its default behavior, namely, \
pressing the left mouse button while the mouse is moved will rotate the \
graph.

Holding the right mouse button down while moving the mouse will drag \
(translate) the plot sideways or up and down.

The plot can be saved as a postscript file, by clicking on Save.
} ] $Parser(help)]]
}

proc makeFrame3d { win } {
    global plot3dPoints
    set w [makeFrame $win 3d]
    set top $w
    catch { set top [winfo parent $w]}
    catch {
	wm title $top [mc "Xmaxima: Plot3d"]
	wm iconname $top "plot3d"
	#   wm geometry $top 750x700-0+20
    }

    pack $w

}

proc mkPlot3d { win  args } {
    global plot3dOptions  printOption [oarray $win] axisGray

    getOptions $plot3dOptions $args -usearray [oarray $win]
    #puts "$win width=[oget $win width],args=$args"
    setPrintOptions $args
    set printOption(maintitle) ""
    set wb $win.menubar
    setupCanvas $win
    # catch { destroy $win }
    makeFrame3d $win
    oset $win sliderCommand sliderCommandPlot3d
    oset $win noaxisticks 1

    makeLocal $win buttonFont c
    [winfo parent $c].position config -text {}
    bind $c <Motion> ""
#    setBalloonhelp $win $wb.rotate [mc {Dragging the mouse with the left button depressed will cause the object to rotate.  The rotation keeps the z axis displayed in an upright position (ie parallel to the sides of the screen), but changes the viewpoint.   Moving right and left changes the azimuth (rotation about the z axis), and up and down changes the elevation (inclination of z axis).   The red,blue and green sides of the bounding box are parallel to the X, Y and Z axes, and are on the smaller side.}]

    #$win.position config -width 15
    setForRotate $win
}

proc doConfig3d { win } {
    desetq "wb1 wb2" [doConfig $win]
    makeLocal $win buttonFont

    mkentry $wb1.zfun [oloc $win zfun]  "z=f(x,y)" $buttonFont
    mkentry $wb1.nsteps [oloc $win nsteps]  [mc "Number of mesh grids"]  $buttonFont

    pack $wb1.zfun  $wb1.nsteps
    pack	    $wb1.zfun  $wb1.nsteps
    foreach w {xradius yradius xcenter ycenter zcenter zradius parameters } {
	mkentry $wb1.$w [oloc $win $w] $w $buttonFont
	pack $wb1.$w
    }

    scale $wb1.rotxscale -label [mc "azimuth"]  \
	-orient horizontal -length 150 -from -180 -to 180 -resolution 1 \
	-command "setView $win" -variable [oloc $win az] -tickinterval 120 -font $buttonFont

    scale $wb1.rotyscale -label [mc "elevation"]  \
	-orient horizontal -length 150 -from -180 -to 180 -resolution 1 \
	-command "setView $win" -variable [oloc $win el] -tickinterval 120 -font $buttonFont


    #    scale $wb1.rotzscale -label "thetaz"  \
	#	    -orient horizontal -length 150 -from -180 -to 180 \
	#	    -command "setView $win" -variable [oloc $win thetaz] -tickinterval 120 -font $buttonFont

    pack   $wb1.rotxscale   $wb1.rotyscale

}


proc showPosition3d { win x y } {
    # global position c
    makeLocal $win c
    set x [$c canvasx $x]
    set y [$c canvasy $y]
    set it [ $c find closest $x $y]
    set tags [$c gettags $it]
    if { [regexp {mesh[.]([0-9]+)} $tags junk k] } {
	set i 0
	set min 1000000
	set at 0
	# find closest.
	foreach {x1 y1} [$c coords $it] {
	    set d [expr {($x1 - $x)*($x1 - $x)+($y1 - $y)*($y1 - $y)}]
	    if { $d < $min} { set at $i ; set min $d }
	    incr i
	}
	set mesh [lindex [oget $win lmesh] $k]
	set ll [lindex $mesh $at]
	set pt [lrange [oget $win points] $ll [expr {$ll + 2}]]
	# puts pt=$pt
	catch { $win.position config -text [eval [concat "format {(%.2f %.2f %.2f)}" $pt]] }	
    }
    #    oset $win position [format {(%.1f %.1f)} $x $y]
    #    oset $win position \
	#      "[format {(%.2f,%.2f)}  [storx$win [$c canvasx $x]] [story$win [$c canvasy $y]]]"
}



#
#-----------------------------------------------------------------
#
# rotateRelative --  do a rotation indicated by a movement
# of dx,dy on the screen.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc rotateRelative { win x1 x2 y1 y2 } {
    makeLocal $win c az el rotatefun
    set x1 [$c canvasx $x1]
    set x2 [$c canvasx $x2]
    set y1 [$c canvasy $y1]
    set y2 [$c canvasy $y2]
    set xx [expr {$x2-$x1}]
    set yy [expr {($y2-$y1)}]
    set res [$rotatefun 0 0 1]
    set res1 [$rotatefun 0 0 0]
    set fac [expr {([lindex $res 1] > [lindex $res1 1] ? -1 : 1) }] ;
    # puts "fac=$fac,[lindex $res 1],[lindex $res1 1]"
    oset $win az [reduceMode360 [expr   {round($az + $fac *  $xx /2.0) }]]
    oset $win el [reduceMode360 [expr   {round($el -  $yy /2.0) }]]
    setView $win ignore
}

proc reduceMode360 { n } {
    return [  expr fmod(($n+180+5*360),360)-180]

}

proc setForRotate { win} {
    makeLocal $win c
    $c delete printrectangle
    bind $c  <Button-1> "setQuick $win 1 ; doRotateScreen $win %x %y "
    bind $c  <ButtonRelease-1> "setQuick $win 0 ; setView $win ignore"
}
proc doRotateScreen { win x y } {
    makeLocal $win c
    oset $win lastx $x
    oset $win lasty $y
    bind $c <B1-Motion> "doRotateScreenMotion $win %x %y"
}

proc doRotateScreenMotion {win x y } {
    makeLocal $win lastx lasty
    set dx [expr {$x - $lastx}]
    set dy [expr {$y - $lasty}]
    if { [vectorlength $dx $dy] < 4 } { return }
    rotateRelative $win $lastx $x $lasty $y
    oset $win lastx $x
    oset $win lasty $y
    # show values of azimuth and elevation angles
    set az [oget $win az]
    set el [oget $win el]
    catch { $win.position config -text [eval [concat "format {Azimuth: %.2f, Elevation: %.2f}" $az $el]] }
}


proc sliderCommandPlot3d { win var val } {
    linkLocal $win recompute

    updateParameters $win $var $val
    set com "recomputePlot3d $win"
    # allow for fast move of slider...
    #mike FIXME: this is a wrong use of after cancel
    after cancel $com
    after 10 $com
}

proc recomputePlot3d { win } {
    linkLocal $win  recompute
    if { [info exists recompute]  } {
	incr recompute
	return
    } else {
	set recompute 1
    }
    set redo 0
    while { $redo != $recompute } {
	set redo $recompute
	#	puts "replot3d $win,[oget $win parameters]"
	catch {replot3d $win }
	update
    }
    unset recompute
}


## endsource plot3d.tcl
#  $Id: scene.tcl,v 1.2 2011-03-19 23:13:04 villate Exp $
#
###### scene.tcl ######
# Copyright (c) 2011, Jaime E. Villate <villate@fe.up.pt>
#
# Interface to the Visualization Toolkit (VTK) for Xmaxima
# (the license information can be found in COPYING.tcl)

global sceneOptions
set sceneOptions {
    {background {0 0 0} {red green and blue values for the background}}
    {width 500 {Rendering screen width in pixels}}
    {height 500 {Rendering screen height in pixels}}
    {windowname {.scene} {Window name}}
    {windowtitle {Xmaxima: scene} {Window title}}
    {azimuth 135 {Azimuth angle}}
    {elevation 60 {Elevation angle}}
    {tstep 10 {Time interval between iterations, in miliseconds}}
    {restart 0 {If different from zero, the animation will loop forever.}}
    {objects  {} {A list of Objects of the form {{Class {options}} ...}}} 
}


proc PlayStep {frame} {
    linkLocal $frame playing iteration prev_iteration maxiter trackers \
        restart animate tstep renwin
    if { $iteration<0 } {
        foreach obj $trackers {
            set name [lindex $obj 0]
            "$name:points" Initialize
            "$name:points" Modified
            "$name:lines" Initialize
            "$name:lines" Modified
        }
      }
    if {$iteration < $maxiter } {
        incr iteration
        uplevel $frame.mb.play configure -image ::img::pause
        foreach anim_obj $animate {
            set name [lindex $anim_obj 0]
            set prop [lindex $anim_obj 1]
            set values [lindex $anim_obj 3]
            if { $iteration < [llength $values] } {
                eval "$name:actor" "Set$prop" [lindex $values $iteration]
            } elseif { $prev_iteration < [llength $values] } {
                eval "$name:actor" "Set$prop" [lindex $values end]
            }
        }
        foreach obj $trackers {
            set name [lindex $obj 0]
            if { $iteration <= [lindex $obj 1] } {
                eval "$name:points" InsertPoint $iteration ["$name:actor" GetPosition]
                "$name:points" Modified
                if { $iteration<1 } {
                    "$name:lines" InsertNextCell 1
                    "$name:lines" InsertCellPoint $iteration
                } else {
                    "$name:lines" InsertNextCell 2
                    "$name:lines" InsertCellPoint $prev_iteration
                    "$name:lines" InsertCellPoint $iteration
                    "$name:lines" Modified
                }
            } elseif { $prev_iteration < [lindex $obj 1] } {
                eval "$name:points" InsertPoint [lindex $obj 1] ["$name:actor" GetPosition]
                "$name:points" Modified
                "$name:lines" InsertNextCell 2
                "$name:lines" InsertCellPoint $prev_iteration
                "$name:lines" InsertCellPoint [lindex $obj 1]
                "$name:lines" Modified
            }
        }
        if { $iteration<1 } {
            set prev_iteration 0
        } else {
            set prev_iteration [expr $iteration-1]
        }
        $renwin Render
    }
    if {$iteration < $maxiter } {
        if {$playing == 1} {
            after $tstep PlayStep $frame
        }
    } else {
        if {$restart} {
            set iteration -1
            set trackers {}
            after $tstep PlayStep $frame
        } else {
            uplevel stopAnimation $frame
        }
    }
}

proc playAnimation {frame} {
    linkLocal $frame playing
    if {$playing == 0} {
        set playing 1
        uplevel PlayStep $frame
    } else {
        uplevel stopAnimation $frame
    }
}
proc stopAnimation {frame} {
    linkLocal $frame iteration playing
    after cancel PlayStep $frame
    set playing 0
    uplevel $frame.mb.play configure -image ::img::play
}
proc startAnimation {frame} {
    linkLocal $frame iteration prev_iteration playing
    after cancel PlayStep $frame
    set playing 0
    set iteration -1
    set prev_iteration 0
    uplevel PlayStep $frame
    uplevel $frame.mb.play configure -image ::img::play
}
proc endAnimation {frame} {
    linkLocal $frame maxiter iteration prev_iteration
    after cancel PlayStep $frame
    set prev_iteration $iteration
    set iteration [expr $maxiter-1]
    uplevel PlayStep $frame
}

proc makeVTKFrame { w type } {
    global writefile doExit fontSize buttonfont maxima_priv 
    linkLocal $w width height restart renwin windowtitle
    set win $w
    if { "$w" == "." } {
        set w ""
    } else {
	catch { destroy $w}
	frame $w
    }
    set dismiss "destroy [winfo toplevel $win]"
    if { "$doExit" != "" } {set dismiss $doExit } 	
    oset $w type $type

    set top $w
    catch { set top [winfo parent $w]}
    catch {
	wm title $top $windowtitle
	wm iconname $top "scene"
    }

    set buttonFont $buttonfont
    oset $win buttonFont $buttonfont
    set mb [frame $w.menubar]
    pack $mb -fill x

    set dismiss [concat "vtkCommand DeleteAllObjects;" \
                     "after cancel PlayStep $mb.play;" $dismiss \
                     "; clearLocal $win"]
    # define exit command fot the scene window
    wm protocol $top WM_DELETE_WINDOW \
        "after cancel PlayStep $mb.play; vtkCommand DeleteAllObjects; destroy $top; clearLocal $win"
 
    button $mb.play -image ::img::play -text [mc "Play"] \
        -command "playAnimation $w"
    button $mb.start -image ::img::start -text [mc "Start"] \
        -command "startAnimation $w"
    button $mb.end -image ::img::end -text [mc "End"] \
        -command "endAnimation $w"
    button $mb.config -image ::img::config -text [mc "Config"]
    button $mb.close -image ::img::close -text [mc "Close"] -command $dismiss
    if {$restart} {
        $mb.end configure -state disabled
    }
    set c $w.c
    oset $win c $c
    canvas $c  -borderwidth 2 -scrollregion {-1200 -1200 1200 1200}

    # Create a Tk widget that we can render into.
    set vtkw [vtkTkRenderWidget $c.ren -width $width -height $height -rw $renwin]
    # Setup Tk bindings and VTK observers for that widget.
    ::vtk::bind_tk_render_widget $vtkw

    pack $vtkw -side left -fill both -expand 1
    pack $mb.play $mb.start $mb.end -side left
    pack $mb.close $mb.config -side right
# FIX ME: these bindings do not work inside the VTK frame, because it
# has its own bindings.
    bind $c <Control-w> $dismiss
    bind $c <p> "playAnimation $w"
    pack $c -side right -expand 1 -fill both
    pack $w
    focus $w
    return $w
}

proc scene { args } {
    if {[catch {package require vtk; package require vtkinteraction}]} {
	 bgerror [mc "VTK is not installed, which is required for Scene"]
	 return
    }
    global sceneOptions
    set win [assoc -windowname $args]
    if { "$win" == "" } {set win [getOptionDefault windowname $sceneOptions] }
    global [oarray $win]
    getOptions $sceneOptions $args -usearray [oarray $win]
    set renderer [set win]:renderer
    set renwin [set win]:renwin
    set iren [set win]:iren
    oset $win maxiter 0
    oset $win trackers "" 
    oset $win playing 0
    oset $win iteration 0
    oset $win prev_iteration 0
    oset $win animate ""
    oset $win renderer $renderer
    oset $win renwin $renwin

    vtkRenderer $renderer

    # Create the render window and put the renderer in it
    vtkRenderWindow $renwin
    $renwin AddRenderer $renderer
    # Change from the default interaction style to Trackball
    vtkRenderWindowInteractor $iren
    $iren SetRenderWindow $renwin
    vtkInteractorStyleTrackballCamera style
    $iren SetInteractorStyle style
    # create the frame with the buttons and the rendering widget
    makeVTKFrame $win scene
    # put the objects into the widget
    updateScene $win
}

proc updateScene { win } {
    linkLocal $win background azimuth elevation objects maxiter trackers \
        animate renwin renderer
    set objcount 0
    foreach obj $objects {
        incr objcount
        set name "object$objcount"
        set class [lindex $obj 0]
        set anim_obj [lindex $obj 4]
        "vtk$class\Source" $name
        foreach prop [lindex $obj 1] {
            eval $name "Set$prop"
        }
        vtkPolyDataMapper "$name:mapper"
        "$name:mapper" SetInputConnection [$name GetOutputPort]
        vtkLODActor "$name:actor"
        "$name:actor" SetMapper "$name:mapper"
        foreach prop [lindex $obj 2] {
            eval ["$name:actor" GetProperty] "Set$prop"
        }
        foreach prop [lindex $obj 3] {
            eval "$name:actor" "Set$prop"
        }
        $renderer AddActor "$name:actor"
        if { [llength $anim_obj] > 2 } {
            lappend animate [linsert $anim_obj 0 $name]
            set n [expr [llength [lindex $anim_obj 2]] - 1]
            if { $n > $maxiter } {
                set maxiter $n
            }
            if { [lindex $anim_obj 1] } {
                lappend trackers "$name [llength [lindex $anim_obj 2]]"
                vtkPoints "$name:points"
                eval "$name:points" InsertPoint 0 [lindex [lindex $anim_obj 2] 0]
                vtkCellArray "$name:lines"
                "$name:lines" InsertNextCell 1
                "$name:lines" InsertCellPoint 0
                vtkPolyData "$name:track"
                "$name:track" SetPoints "$name:points"
                "$name:track" SetLines "$name:lines"
                vtkPolyDataMapper "$name:track:mapper"
                "$name:track:mapper" SetInput "$name:track"
                vtkActor "$name:track:actor"
                "$name:track:actor" SetMapper "$name:track:mapper"
                eval ["$name:track:actor" GetProperty] SetColor [["$name:actor" GetProperty] GetColor]
                $renderer AddActor "$name:track:actor"
            }
        }
    }
    eval "$renderer SetBackground $background"

    # Rotate the camera so the axis are in the position familiar to Physicists
    [$renderer GetActiveCamera] Elevation -90
    [$renderer GetActiveCamera] SetViewUp 0.0 0.0 1.0

    # Set azimuth and elevation
    [$renderer GetActiveCamera] Azimuth $azimuth
    [$renderer GetActiveCamera] Elevation [expr "90 - $elevation"]
    $renderer ResetCamera
    $renwin Render

}

## endsource scene.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: NPlot3d.tcl,v 1.9 2009-11-16 22:41:47 villate Exp $
#
###### NPlot3d.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

# source plotting.tcl ; source nplot3d.tcl ; catch { destroy .plot3d} ;  plot3d -zfun "" -data $sample -xradius 10 -yradius 10
# newidea:
# { plot3d
#  { gridequal {minx maxx} {miny maxy}
#   {{z00 z01 z02 .. z0n } { z10 z11 z12 .. z1n} {..  } ...}
#  { grid {x0 x1  xm} {y0 y1 yn } miny maxy}
#   {{z00 z01 z02 .. z0n } { z10 z11 z12 .. z1n} {..  } ...}
#  { xyzgrid {{x00 y00 z00 x01 y01 z01 .. x0  }{x0 x1  xm} {y0 y1 yn } miny maxy}
#   {{z00 z01 z02 .. z0n } { z10 z11 z12 .. z1n} {..  } ...}
# tclMesh(2*[0,0,0,0,0;1,1,1,1,1]-1,2*[0,1,1,0,0;0,1,1,0,0]-1,2*[0,0,1,1,0;0,0,1,1,0]-1)

#     { gridequal {

# z00 z01 .. all belong to x=minx and y = miny,.... up y=maxy in n+1 steps
#{ grid {minx maxx} {miny maxy}
#  {{z00 z01 z02 .. z0n } { z10 z11 z12 .. z1n} {..  } ...}
# }
# where a mesh(1) {z00 z01 z11 z10} above



# { mesh {{{x00 y00 z00 } { x01 y01 z01} { x02 y02 z02}  ..}{{x10 y10 z10} {x11 y11 z11} ......} ..}}
# mesh(1) = P00 P01 P11 P10

set sample { variable_grid { 0 1 2 } { 3 4 5} { {21 111 2} {3 4 5 } {6 7 8 }}}
set sample { variable_grid { 0 1 2 } { 3 4 5} { {0 1 2} {3 4 5 } {6 7 8 }}}
set sample { matrix_mesh {{0 1} { 2 3 } {4 5 }}  {{0 1} { 2 3 } {4 5 }}  {{0 1} { 2 3 } {4 5 }} }
set sample { matrix_mesh {{0 1 2} {0 1 2 } {0 1 2 }} {{3 4 5} {3 4 5} {3 4 5}} { {0 1 2} {3 4 5 } {6 7 8 }}}
set sample1 { variable_grid  { 1 2 3 4 5 6 7 8 9 10 }
    { 1 2 3 }
    {  { 0 0 0 0 0 0 0 0 0 0 }
	{ 0 0.68404 1.28558 1.73205 1.96962 1.96962 1.73205 1.28558 0.68404 2.44921e-16 }
	{ 0 1.36808 2.57115 3.4641 3.93923 3.93923 3.4641 2.57115 1.36808 4.89843e-16 }
    }
}

set sample { matrix_mesh  {  { 0 0 0 0 0 }
    { 1 1 1 1 1 }
}  {  { 0 1 1 0 0 }
    { 0 1 1 0 0 }
}  {  { 0 0 1 1 0 }
    { 0 0 1 1 0 }
}
}

proc  fixupZ { } {
    uplevel 1 {
	if { [catch { expr $z + 0 } ] } {
	    set z nam
	}
    }
}

proc vectorLength { v } {
    expr { sqrt(1.0 * [lindex $v 0]*[lindex $v 0] + [lindex $v 1]*[lindex $v 1] + [lindex $v 2]*[lindex $v 2]) }
}

proc normalizeToLengthOne { v } {
    set norm [expr { sqrt(1.0 * [lindex $v 0]*[lindex $v 0] + [lindex $v 1]*[lindex $v 1] + [lindex $v 2]*[lindex $v 2]) }]
    if { $norm != 0.0 } {
	return [list [expr { [lindex $v 0] / $norm  } ] \
		    [expr { [lindex $v 1] / $norm  } ] \
		    [expr { [lindex $v 2] / $norm  } ] ]
	
    } else {
	return "1.0 0.0 0.0 "
    }
}



proc vectorCross { x1 x2 }  {
    list \
	[expr { [lindex $x1 1]*[lindex $x2 2]- [lindex $x2 1]*[lindex $x1 2]}] \
	[expr { [lindex $x1 2]*[lindex $x2 0]- [lindex $x2 2]*[lindex $x1 0] } ] \
	[expr { [lindex $x1 0]*[lindex $x2 1]- [lindex $x2 0]*[lindex $x1 1] }]
}

proc linspace { a b n } {
    if { $n < 2 } { error [M [mc "from %s to %s requires at least 2 points"] "$a" "$b" ] }
    set del [expr {($b - $a)*1.0/($n -1)  }]
    for { set i 0 } { $i < $n } { incr i } {
	lappend ans [expr {$a + $del * $i}]
    }
    return $ans
}


proc addOnePlot3d { win data } {
    upvar #0 plot3dMeshes$win meshes
    #puts " adding meshes = plot3dMeshes$win"
    #puts "data=$data"
    linkLocal $win points zmax zmin zcenter zradius rotationcenter xradius yradius xmin xmax ymin ymax lmesh
    makeLocal $win flatten
    oset $win colorfun plot3dcolorFun
    oset $win cmap c1
    global plot3dOptions
    catch { unset  meshes }
    set points ""

    # check whether zradius is a number or "auto"
    set dotruncate [expr ![catch {expr {$zradius + 1} }]]
    if { $dotruncate } {
		set zzmax [expr {$zcenter + $zradius}]
		set zzmin [expr {$zcenter - $zradius}]
    }

    set k [llength $points]
    set type [lindex $data 0]
    # in general the data should be a list of plots..
    if { [lsearch {grid mesh variable_grid matrix_mesh }  $type ]>=0 } {
	set alldata [list $data]
    } else {set alldata $data}
    set lmesh {}
    set first_mesh 0
    foreach data $alldata {	
	set type [lindex $data 0]
	if { "$type" == "grid" } {
	    desetq "xmin xmax" [lindex $data 1]
	    desetq "ymin ymax" [lindex $data 2]
	    set pts [lindex $data 3]
	
	    set ncols [llength $pts]
	    set nrows  [llength [lindex $pts 0]]
	    set data [list variable_grid [linspace $xmin $xmax $ncols] \
			  [linspace $ymin $ymax $nrows] \
			  $pts ]
	    set type "variable_grid"
	}
	if { "$type" == "variable_grid" } {
	    set first_mesh [llength $lmesh]
	    desetq "xrow yrow zmat" [lrange $data 1 end]
	    # puts "xrow=$xrow,yrow=$yrow,zmat=$zmat"
	    set nx [expr {[llength $xrow] -1}]
	    set ny [expr {[llength $yrow] -1}]
	    #puts "nx=$nx,ny=$ny"
	    #	set xmin [lindex $xrow 0]
	    #	set xmax [lindex $xrow $nx]
	    #	set ymin [lindex $yrow 0]
	    #	set ymax [lindex $yrow $ny]
	    desetq "xmin xmax" [minMax $xrow ""]
	    desetq "ymin ymax" [minMax $yrow ""]
	    desetq "zmin zmax" [matrixMinMax [list $zmat]]
	    if { $dotruncate } {
		set zmax  $zzmax
		set zmin  $zzmin
	    }
	    #	puts "and now"
	    #	dshow nx xmin xmax ymin ymax zmin zmax

	    for {set j 0} { $j <= $ny } { incr j} {
		set y [lindex $yrow $j]
		set row [lindex $zmat $j]
		for {set i 0} { $i <= $nx } { incr i} {
		    set x [lindex $xrow $i]
		    set z [lindex $row $i]
		    #puts "x=$x,y=$y,z=$z, at ($i,$j)"
		    fixupZ
		    if { $j != $ny && $i != $nx } {
			lappend lmesh [list $k [expr { $k+3 }] \
					   [expr { $k+3+($nx+1)*3 }] \
					   [expr { $k+($nx+1)*3 }]]
		    }
		    incr k 3
		    lappend points $x $y $z
		}
	    }
	    setupPlot3dColors $win $first_mesh
	} elseif { "$type" == "matrix_mesh" } {
	    set first_mesh [llength $lmesh]
	    desetq "xmat ymat zmat" [lrange $data 1 end]
	    foreach v {x y z} {
		desetq "${v}min ${v}max" [matrixMinMax [list [set ${v}mat]]]
	    }
	    if { $dotruncate } {
		set zmax  $zzmax
		set zmin  $zzmin
	    }
	    set nj [expr {[llength [lindex $xmat 0]] -1 }]
	    set ni [expr {[llength $xmat ] -1 }]
	    set i -1
	    set k [llength $points]
	    foreach rowx $xmat rowy $ymat rowz $zmat {
		set j -1
		incr i
		if { [llength $rowx] != [llength $rowy] } {
		    error [concat [mc "mismatch"] "rowx:$rowx,rowy:$rowy"]
		}
		if { [llength $rowx] != [llength $rowz] } {
		    error [concat [mc "mismatch"] "rowx:$rowx,rowz:$rowz"]
		}
		foreach x $rowx y $rowy z $rowz {
		    incr j
		    if { $j != $nj && $i != $ni } {
			#puts "tes=($i,$j) $x, $y, $z"
			lappend lmesh [ list \
					    $k [expr { $k+3 } ] [expr { $k + 3  + ($nj+1)*3}] \
					    [expr { $k+($nj+1)*3 }] ]
		    }
		    incr k 3
		    lappend points $x $y $z
		}
	    }
	    setupPlot3dColors $win $first_mesh
	} elseif { 0 && "$type" == "mesh" } {
	    set first_mesh [llength $lmesh]
	    # walk thru compute the xmin, xmax, ymin , ymax...
	    # and then go thru setting up the mesh array..
	    # and maybe setting up the color map for these meshes..
	    #
	    # { mesh {{{x00 y00 z00 } { x01 y01 z01} { x02 y02 z02}  ..}{{x10 y10 z10} {x11 y11 z11} ......} ..}}
	    # mesh(1) = P00 P01 P11 P10
	    set mdata [lindex $data 1]
	    set nx [llength $mdata]
	    set ny [llength [lindex $mdata 0]]

	    for {set i 0} { $i <= $nx } { incr i} {
		set pts [lindex $mdata $i]
		set j 0
		foreach { x y z} $pts {
		    fixupZ $z
		    if { $j != $ny && $i != $nx } {
			lappend lmesh [list
				       $k [expr { $k+3 }] [expr { $k+3+($ny+1)*3 }] \
					   [expr { $k+($ny+1)*3 }] ]
		    }
		}
		incr k 3
		lappend points $x $y $z
		incr j
	    }
	    setupPlot3dColors $win $first_mesh
	} elseif { "[assq $type $plot3dOptions notthere]" != "notthere" } {
	    oset $win $type [lindex $data 1]
	    if { $type == "zradius" } {
		# check whether zradius is a number or "auto"
		set dotruncate [expr ![catch {expr {$zradius + 1} }]]
		if { $dotruncate } {
		    set zzmax [expr {$zcenter + $zradius}]
		    set zzmin [expr {$zcenter - $zradius}]
		}
	    }
	}
	if { $first_mesh != [llength $lmesh] } {
	    # set up the min/max values for the complete plot
	    foreach v { x y z } {
		if { [info exists ${v}gmin] } {
		    if { [set ${v}min] < [set ${v}gmin] } {
			set ${v}gmin [set ${v}min]
		    }
		} else {
		    set ${v}gmin [set ${v}min]
		}
		if { [info exists ${v}gmax] } {
		    if { [set ${v}max] > [set ${v}gmax] } {
			set ${v}gmax [set ${v}max]
		    }
		} else {
		    set ${v}gmax [set ${v}max]
		}
	    }
	}
    }
    foreach v { x y z } {
	set ${v}min [set ${v}gmin]
	set ${v}max [set ${v}gmax]
	set a [set ${v}min]
	set b  [set ${v}max]
	if { $a == $b } {
	    set ${v}min [expr {$a -1}]
	    set ${v}max [expr {$a +1}]
	}
	set ${v}radius [expr {($b - $a)/2.0}]
	set ${v}center [expr {($b + $a)/2.0}]
    }
    set rotationcenter "[expr {.5*($xmax + $xmin)}] [expr {.5*($ymax + $ymin)}]   [expr {.5*($zmax + $zmin)}] "

    #puts "meshes data=[array get meshes]"
    #global plot3dMeshes.plot3d
    #puts "array names plot3dMeshes.plot3d = [array names plot3dMeshes.plot3d]"
}

proc vectorDiff { x1 x2 } {
    list [expr { [lindex $x1 0] - [lindex $x2 0] }] \
	[expr { [lindex $x1 1] - [lindex $x2 1] }] \
	[expr { [lindex $x1 2] - [lindex $x2 2] }]
}


proc oneCircle { old2 old1 pt radius nsides { angle 0 } } {
    set dt  [expr {  3.14159265358979323*2.0/($nsides-1.0) + $angle }]
    for  { set i 0 } { $i < $nsides } { incr i } {
	set t [expr {$dt*$i }]
	lappend ans [expr { $radius*([lindex $old2 0]*cos($t) + [lindex $old1 0] * sin($t)) + [lindex $pt 0] } ] \
	    [expr { $radius*([lindex $old2 1]*cos($t) + [lindex $old1 1] * sin($t)) + [lindex $pt 1] } ] \
	    [expr { $radius*([lindex $old2 2]*cos($t) + [lindex $old1 2] * sin($t)) + [lindex $pt 2] } ]
    }
    return $ans
}

proc curve3d { xfun yfun zfun trange } {
    foreach u { x y z} {
	set res [parseConvert [set ${u}fun] -variables t]
	proc _${u}fun { t } [list expr [lindex [lindex $res 0] 0]]
    }
}

proc tubeFromCurveData { pts nsides radius } {
    set n [llength $pts] ;
    set closed [ expr { [vectorLength [vectorDiff [lindex $pts 0] [lindex $pts end]]] < .02} ]
    if { $closed } {
	set f1 [expr {$n -2}]
	set f2 1
    } else {
	set f1 0
	set f2 1
    }
    set delta [vectorDiff [lindex $pts $f2] [lindex $pts $f1]]
    if { [lindex $delta 0] == 0 && [lindex $delta 1] == 0 && [lindex $delta 2] == 0 } { set delta "0 0 1.0" }
    set old ".6543654 0.0765456443 0.2965433"
    set old1 [normalizeToLengthOne [vectorCross $delta $old]]
    set n1 $old1
    set n2 [normalizeToLengthOne [vectorCross $delta $old1]]
    set first1 $n1 ; set first2 $n2

    lappend ans [oneCircle $n2   old1 [lindex $pts 0]]
    for { set j 1 } { $j < $n -1 } { incr j } {
	set delta [vectorDiff [lindex $pts $j] [lindex $pts [expr {$j+1}]]]
	if { [lindex $delta 0] == 0 && [lindex $delta 1] == 0 && [lindex $delta 2] == 0 } { set delta $old
	}
	set old $delta
	set old1 [normalizeToLengthOne [vectorCross $delta $n1]]
	set old2 [normalizeToLengthOne [vectorCross $delta $n2]]
	set n2 $old1
	set n1 $old2
	lappend ans [oneCircle $n2 $n1 [lindex $pts $j] $radius $nsides]
    }
    if { $closed } {
	set f2 1 ; set f1 [expr {$n -2}] ; set f3 0
    } else {
	set f1 [expr {$n -2}] ; set f2 [expr {$n-1}] ; set f3 $f2
    }

    set delta [vectorDiff [lindex $pts $f2] [lindex $pts $f1]]
    if { [lindex $delta 0] == 0 && [lindex $delta 1] == 0 && \
	     [lindex $delta 2] == 0 } { set delta $old }
    set old1 [normalizeToLengthOne [vectorCross delta $n1]]
    set old2 [normalizeToLengthOne [vectorCross $n2 $delta]]
    set n2 $old1 ; set n1 $old2
    if { $closed } {
	set angle [vangle $first1 $n1]
	set n1 $first1 ; st n2 $first2;
    }
    lappend ans [oneCircle $n2 $n1 [lindex $pts $f3] $radius $nsides $angle]
    return $ans
}


#
#-----------------------------------------------------------------
#
# vangle --  angle between two unit vectors
#
#  Results: an angle
#
#  Side Effects: none.
#
#----------------------------------------------------------------
#
proc vangle { x1 x2 } {
    set dot [expr { [lindex $x1 0]*[lindex $x2 0] +\
			[lindex $x1 1]*[lindex $x2 1] +\
			[lindex $x1 2]*[lindex $x2 2]} ]
    if { $dot >= 1 } { return 0.0 }
    if { $dot <= -1.0 } { return 3.141592653589 }
    return [expr { acos($dot) } ]
}

## endsource nplot3d.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: EOctave.tcl,v 1.3 2011-03-19 23:17:20 villate Exp $
#
###### EOctave.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################


#
#-----------------------------------------------------------------
#
# insertResult_octave --  insert result RES, in text window W,
# into RESULTRANGE.  The command which was sent to octave came
# from THISRANGE.   For plots if a resultRANGE is missing,
# we use a space just after the end of the line of THISRANGE.
# checks if this is plotdata, and if so makes plot win for it.
#
#  Results: none
#
#  Side Effects:  inserts in text or graph in window W.
#
#----------------------------------------------------------------
#

proc insertResult_octave {  w thisRange resultRange res } {
    #puts "res=$res"
    if { [regexp "\{plot\[23\]d" $res] || [regexp "\{plotdf" $res] \
             || [regexp "\{scene" $res] } {
	#puts "its a plot"
	set name [plotWindowName $w [lindex $res 0]]
	set tem [setDesiredDims $w $name $thisRange ]
	eval plot2dData $name $res [getDimensions $w $name]
	ShowPlotWindow $w $name  $thisRange $resultRange $tem
	return 0
    } elseif { "$resultRange" != "" } {
	insertResult $w $resultRange $res
    }
    return 0
}


## endsource eoctave.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: EOpenplot.tcl,v 1.7 2011-03-19 23:15:44 villate Exp $
#
###### EOpenplot.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################



#
#-----------------------------------------------------------------
#
# eval_openplot --  invoke OPENPLOT on the substring of Window given
# by thisRange, and substitute the result into resultRange, if the
# latter is not the empty list.   If it is, then the window is placed
# on the next line from this command.
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc eval_openplot { program w thisRange resultRange } {


    set tem [eval $w get $thisRange]
    lappend tem -windowname $name
    foreach v [getDimensions $w $name] { lappend tem $v }
    set allowed "plot2d plotdf plot3d scene"
    set f [lindex $tem 0]
    if { [lsearch $allowed $f] >= 0 } {
	apply $f [lrange $tem 1 end]
	ShowPlotWindow $w $name $thisRange $resultRange $desired
    } else {
	error [concat "$f" [mc "not allowed, only"] "{$allowed}"]
    }
    set name  [plotWindowName $w $f]
    set desired [setDesiredDims $w $name $thisRange ]
    return 0
}


#
#-----------------------------------------------------------------
#
# plotWindowName --  checks preferences to see if separate or multiple
#  or nontoplevel windows are desired, and chooses a name accordingly.
#  in the first two cases it also assures that the toplevel window exists.
#
#  Results: window name
#
#  Side Effects:  possibly make a new toplevel window.
#
#----------------------------------------------------------------
#
proc plotWindowName { w command } {
    upvar #0 maxima_default(plotwindow) plot
    upvar #0 maxima_priv(plot,count) count
    set name ""

    if { "$command" == "scene" } {
        set name ".plotfr"	
        if { [winfo exists $name ] } {
            after cancel PlayStep $name.plot.menubar.play
            vtkCommand DeleteAllObjects
            destroy $name
            clearLocal $name.plot
        }
        toplevel $name
        if { "[info proc setIcon]" != "" } {
            after 1000 setIcon $name
        }
    } else {
        if { ![info exists plot] || "$plot" == "embedded" } {
            linkLocal $w counter
            if { ![info exists counter] } {set counter 0}
            return $w.plot[incr counter]
        }
        set name ".plotfr"	
        if { "$plot" == "multiple" } {
            if { ![info exists count] } {
                set count 1
            } else {
                incr count
            }
            append name $count
        }
        if { ![winfo exists $name ] } {
            toplevel $name
            set h [expr {round ([winfo screenheight $name]*.6) }]
            set wid [expr round ($h * 1.2) ]
            set r1 [expr {round(10+rand()*30)} ]
            set r2 [expr {round(10+rand()*30)} ]
            wm geometry $name ${wid}x${h}+${r1}+${r2}
            if { "[info proc setIcon]" != "" } {
                after 1000 setIcon $name
            }   
        }
    }
    append name .plot
    return $name
}


proc whereToPutPlot { w thisRange resultRange } {
    if { "$resultRange" != "" } {
	eval $w  delete $resultRange
	set at [lindex $resultRange 0]
	$w insert $at " " { Tresult}
	set at [$w index "$at + 1char"]
    } else {
	set at "[lindex $thisRange 1] lineend + 1 chars"
    }
    return $at
}


proc setDesiredDims { w name range } {
    #puts "setDesiredDims  $w $name $range"
    foreach v [getTagsMatching $w "^(width|height):" $range] {
	set tem [split $v :]
	lappend ans [lindex $tem 0]Desired [lindex $tem 1]
    }
    if { [info exists ans] } {
	oarraySet $name $ans
	return $ans
    }
    return ""
}

proc getDimensions { w name } {
    # puts "getDimensions  $w $name"
    set parent [winfo parent $w]
    set scrollwidth 15
    catch { set scrollwidth [ [winfo parent $parent].scroll cget -scrollwidth] }
    set width [winfo width $w]
    set height [winfo height $w]
    #set width [getPercentDim [oget $name widthDesired] width $w]
    catch {set width [getPercentDim [oget $name widthDesired] width $w] }
    catch {set height [getPercentDim [oget $name heightDesired] height $w] }

    set width [expr {round ($width-4) }]
    set height [expr {round ($height-4)}]
    #puts "using width,height=$width,$height"

    if { $width <0 } {
	set width [expr {[oget $parent width] - 2*$scrollwidth}]
	set height [expr {round(.85*[oget $parent height])}]
    }
    return " -width $width -height $height"
}


proc insertResult_openplot {w args } {
    puts "insert=[$w index insert]" 
}

proc ShowPlotWindow { w name thisRange resultRange desired } {
    if { "[winfo toplevel $w]" != "[winfo toplevel $name]" } {
	$name config -relief sunken -borderwidth 2
	pack $name -expand 1 -fill both
	raise [winfo toplevel $name ]
	return
    }
    oarraySet $name $desired
    set at [whereToPutPlot $w $thisRange $resultRange]
    set col [lindex [split $at .] 1]

    if { $col > 0 } {
	$w insert $at "\n \n" "$name"
	set at [$w index "$at +1char"]
    }
    # compute where we will try to display.
    # try to leave top of window where it is, but if not
    # scroll lines up just the amount necessary to make the
    # window visible.

    set h1 [winfo height $w]
    set h2 [oget  $name height]
    set begin [$w index @0,0]
    set ind $at
    set dl [$w dlineinfo $ind]
    set y0 [lindex $dl 1]
    set prev ""
    if { "$y0" != "" } {
	while { [$w compare $begin <= $ind] } {
	    set dl [$w dlineinfo $ind]

	    if { "$dl" == "" } { break }
	    if { $y0 - [lindex $dl 1] + $h2 +5 < $h1  } {
		set prev $ind
		set ind [$w index "$ind - 1 line" ]
	    } else {
		break
	    }
	}
    }

    bind $name <Destroy> "catch {$w yview [$w index @0,0] } ; eval $w delete \[$w tag  nextrange $name 0.0 \]"

    if { "$prev" != "" } { set ind $prev }
    $w insert $at " " "$name center"
    $w window create  $at+1char -window $name
    $w tag add "center $name" $at "$at+2char"
    update
    $w yview $ind
    # somehow the single button click gets run positioning the cursor
    # near where the
    after 1 $w mark set insert [$w index insert]
    return $ind
}

## endsource eopenplot.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: EMaxima.tcl,v 1.4 2011-03-19 23:16:41 villate Exp $
#
###### EMaxima.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################


#
#-----------------------------------------------------------------
#
# insertResult_maxima --  insert result RES, in text window W,
# into RESULTRANGE.  The command which was sent to maxima came
# from THISRANGE.   For plots if a resultRANGE is missing,
# we use a space just after the end of the line of THISRANGE.
# checks if this is plotdata, and if so makes plot win for it.
#
#  Results: none
#
#  Side Effects:  inserts in text or graph in window W.
#
#----------------------------------------------------------------
#

proc insertResult_maxima {  w thisRange resultRange res } {
    set program maxima

    #    puts <lengthres=[llength $res],thisRange=$thisRange,resultRange=$resultRange>

    if { 0 == [string compare "$res" "cant connect"] } {
	bgerror [concat [mc "unable to call"] "$program"]
    }
    if { [regexp "\{plot\[23\]d" $res] || [regexp "\{plotdf" $res] \
             || [regexp "\{scene" $res] } {
	#puts "its a plot"
	set name [plotWindowName $w [lindex $res 0]]
	eval plot2dData $name $res [getDimensions $w $name]
	set desired [setDesiredDims $w $name $thisRange ]
	ShowPlotWindow $w $name  $thisRange $resultRange $desired
	return 0
    }

    if { "$resultRange" != "" }   {
	set name $w.plot[oset $w counter [expr {1 + [oget $w counter]}]]
	insertResult $w $resultRange $res
	
    }
    return 0
}

## endsource emaxima.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: EHref.tcl,v 1.3 2004-10-13 12:08:57 vvzhy Exp $
#
###### EHref.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################


#
#-----------------------------------------------------------------
#
# eval_href --  Follow a link to another om document
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc obsoleteeval_href { program w this nextResult} {
    set arg ""
    foreach v [$w tag names [lindex $this 0]] {
	if { [string first "\{ThrefArg" $v] == 0 } {
	    set arg $v
	    break
	}
    }
    set arglist [getTargTags $w $this]
    if { [llength $arglist] != 1 } {
	return -code error -errorinfo  [concat "[llength $arglist]" [mc "args to href.  Wanted 1, got:"] "$arglist"]
    }
    puts "arglist=$arglist"

    set arg [lindex $arglist 0]
    puts "arg=$arg"
    set list [lrange $arg 1 end]
    set doc [assoc -src $list ""]

    set searchregexp [assoc -searchregexp $list ""]
    set search [assoc -search $list ""]

    puts "doc=$doc"

    if { "$doc" != "" } {
	puts "       OpenMathOpenUrl $doc -commandpanel [omPanel $w]"
	OpenMathOpenUrl $doc -commandpanel [omPanel $w]
    }
    makeLocal  [omPanel $w] textwin
    set ind ""
    if { "$searchregexp" != "" } {
	set ind [ $textwin search -regexp -- $searchregexp 1.0]
    } elseif { "$search" != "" } {
	set ind [ $textwin search -exact -- $search 1.0]
    }
    if { "$ind" != "" } {
	$textwin yview $ind
    }
    return 0
}



## endsource ehref.tcl
# -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
#
#       $Id: Browser.tcl,v 1.25 2011-03-21 09:18:58 villate Exp $
#
###### Browser.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

## source keyb.tcl

###### keyb.tcl ######
############################################################
# Netmath       Copyright (C) 1998 William F. Schelter     #
# For distribution under GNU public License.  See COPYING. #
############################################################

proc peekLastCommand {win} {
    global maxima_priv
    if { [info exists maxima_priv(lastcom,$win)] } {
	return $maxima_priv(lastcom,$win)
    }
}

proc pushCommand { win command arglist } {
    global maxima_priv
    set maxima_priv(lastcom,$win) [list $command $arglist]
}



#
#-----------------------------------------------------------------
#
# tkTextInsert --  we add some things to the default tkTextInsert
#  so that tags present before or after the insert, which are sticky
#  are added to the inserted string.   As usual, ones on both sides
#  are added.
#
#  Results:
#
#  Side Effects:
#
#----------------------------------------------------------------
#

proc tkTextInsert { w s } {
    global maxima_priv
    set after [$w tag names insert]
    set before [$w tag names "insert-1char"]
    set both [intersect $after $before]
    # puts "after=$after"
    # puts "before=$before"

    foreach v [concat $after $before] {
	if { [regexp -- $maxima_priv(sticky) $v] } {
	    lappend both $v
	}
    }

    if { [info exists maxima_priv($w,inputTag) ] } {
	lappend both $maxima_priv($w,inputTag)
    }

    if {($s == "") || ([$w cget -state] == "disabled")} {
	return
    }
    catch {
	if {[$w compare sel.first <= insert]
	    && [$w compare sel.last >= insert]} {
	    $w delete sel.first sel.last
	}
    }
    $w insert insert $s $both
    $w see insert

}
proc getRange { win a b }  {
    if { [$win compare $a < $b ] } {
	return "$a $b" 
    } else { 
	return "$b $a"
    }
}


#
#-----------------------------------------------------------------
#
# tagRanges --  find ranges on WINDOW for TAG from FROMINDEX below TOINDEX
#
#  Results: a list of ranges start1 stop1 start2 stop2 ..
# which are contained in [fromindex,toindex] such that TAG is on from
# start1 to stop1 etc.
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc tagRanges { win tag begin end } {
    if {  [$win  compare $begin <= 1.0 ]  && \
	      [$win  compare $end >= end ] } {
	return [$win tag ranges $tag ] 
    } else {
	set answer ""
	    set begin [$win index $begin]
	    set end [$win index $end]
	    if { [lsearch [$win tag names $begin] $tag ]>=0 } {
		set prev [$win tag prevrange $tag $begin+1chars]
		set to [lindex $prev 1]
		if { [$win compare $to > $end ] } {
		    set to $end
		}
		append answer "$begin $to "
		set begin $to
	    }
	    #puts "<$begin $end>"
	    while { [$win compare $begin < $end ] } {
		set next [$win tag nextrange $tag $begin]
		#puts "next=$next"
		if { "$next" == "" } { return $answer }
		if { [$win compare [lindex $next 1] <= $end]} {
		    append answer "$next "
		    set begin [lindex $next 1]
		} elseif {[$win compare [lindex $next 0] < $end ]} {
		    append answer "[lindex $next 0] $end"
		    return $answer
		} else {
		    return $answer
		}
	    }
	    return $answer
	
	}
}


#
#-----------------------------------------------------------------
#
# quoteBraces --  given a STRING such that
# puts $file "set new [quoteBraces $string]"
# when re read by eval would make value of NEW identical to STRING
#
#  Results: a string
#
#  Side Effects:
#
#----------------------------------------------------------------
#
proc quoteBraces {string } {
    regsub -all {[{}]} $string {\\&} val
    return [list $val]
}

proc thisRange { win tag index } {
    set prev [$win tag prevrange $tag $index]
    if { "$prev" != "" && [$win compare [lindex $prev 1] >= $index] } {
	return $prev
    }
    set next [$win tag nextrange $tag $index]
    if { "$next" != ""  && [$win compare [lindex $next 0] <= $index] } {
	return $next
    }
    return ""
}




#
#-----------------------------------------------------------------
#
# insertRichText --  insert rich text in TEXTWINDOW at INDEX according
# to commands and data in LIST.   The latter must be of the form
#  command1 arg1 ..argn command2 arg1 ..argn2 ..
# for example if `Tins' takes two args
#  and the commands must be in
# since the rich text might come from a selection or some or an untrusted
# file we want to be careful not to do any bad evals.
#  Results: none
#
#  Side Effects:  the rich text commands are invoked to do insertions
# on the window.
#
#----------------------------------------------------------------
#
proc insertRichText {win index list } {
    global maxima_priv
    set maxima_priv(currentwin) $win
    set maxima_priv(point) $index
    foreach v $maxima_priv(richTextCommands) {
	set maxima_priv($v,richTextCommand) [llength [info args $v]]
    }
    set i 0
    set ll [llength $list]
    while { $i < $ll } {
	set com [lindex $list $i]
	incr i
	if { [catch { set n $maxima_priv($com,richTextCommand)} ] } {
	    return -code error -errorinfo [concat [mc "illegal command in rich text:"] "$com"]
	}
	set form [concat $com [lrange $list $i [expr {$i +$n -1}]]]
	if { [catch {eval $form } ] } {
	    return -code error -errorinfo [concat [mc "unable to evaluate command:"] "`$form'"] }
	
	incr i $n
    }
}


proc Tins { tags text } {
    global maxima_priv
    # foreach v $args { append text $v }
    $maxima_priv(currentwin) insert $maxima_priv(point) $text  $tags
}

proc TinsSlashEnd { tags text } {
    global maxima_priv
    # foreach v $args { append text $v }
    $maxima_priv(currentwin) insert $maxima_priv(point) "$text\\"  $tags
}



## endsource keyb.tcl

proc underTop {top win} {
    if { "$top" == "." } {
	return $win
    } else {
	return $top$win
    }
}

# now unused
proc showHistory { window } {
    set top [winfo toplevel $window]
    set win [omPanel $window]
    makeLocal $win history historyIndex

    set w [underTop $top .historylist]
    if {[winfo exists $w]} {catch {destroy $w}}

    frame $w -borderwidth 2 -relief raised
    label $w.title -text [mc "History List"] -relief raised
    pack $w.title -side top -fill x
    setHelp $w.title [mc "This window may be dragged elsewhere by grabbing this title bar with the mouse.  Double clicking on a history item, moves to that page."]

    button $w.dismiss -command "destroy $w" -text [mc "Close"]
    pack $w.dismiss -side bottom -fill x
    setHelp $w.dismiss [mc "Remove the history list"]

    scrollbar $w.scrolly -command "$w.list yview"
    scrollbar $w.scrollx -orient horizontal -command "$w.list xview"
    pack $w.scrollx -side bottom -fill x -expand 1
    pack $w.scrolly -side right -fill y -expand 1
    listbox $w.list -yscroll "$w.scrolly set" \
	-width 35 -height 16 -setgrid 1 -xscroll "$w.scrollx set"
    $w.title configure -font [$w.list cget -font]
    set l $w.list

    pack $w.list  -side top -fill both -expand 1
    resetHistory $win $w.list junk history
    global [oarray $win]

    #puts "    trace variable [oloc $win history] w {resetHistory $win $w.list}"
    trace vdelete  [oloc $win history] w "resetHistory $win $w.list"
    trace variable [oloc $win history] w "resetHistory $win $w.list"
    trace vdelete [oloc $win historyIndex] w "resetHistory $win $w.list"
    trace variable [oloc $win historyIndex] w "resetHistory $win $w.list"
    bind $l <Double-1> {OpenMathMoveHistory [omPanel %W] [expr [%W index @%x,%y]-[oget [omPanel %W] historyIndex]]}
    bind  $w.title <B1-Motion> "dragPlacedWindow $w %W %X %Y"
    bind  $w.title <1> "startDragPlacedWindow $w %X %Y"
    place $w -relx .4 -rely .8 -in $top


}

proc deleteAllTraces {var} {
    foreach v [uplevel "#0" trace vinfo $var] {
	uplevel "#0" trace vdelete $var [lindex $v 0] [list [lindex $v 1]]
    }
}

# now unused
proc resetHistory { win list args } {
    set action [lindex $args 1]
    if { [catch {
	if { "$action" == "history" } {
	    $list delete 0 end
	    if { [winfo exists $list] } {
		foreach v [oget $win history] {
		    $list insert end [oget $v location]
		}
	    }
	}
	$list selection clear 0 end
	$list selection set [oget $win historyIndex]
	after 200 raise [winfo parent $list]

    } ] } {
	deleteAllTraces [oloc $win history]
	deleteAllTraces [oloc $win historyIndex]
    }
}


proc startDragPlacedWindow { win x y } {
    oset $win placeinfo [list $x $y [place info $win]]
}

proc dragPlacedWindow { win w1 x y } {
    global me recursive
    makeLocal $win placeinfo
    catch { after cancel [oget $win after]}
    set me [oget $win placeinfo]
    #puts "have=[oget $win placeinfo]"
    desetq "px py pinfo" [oget $win placeinfo]
    set dx [expr {$x - $px}]
    set dy [expr {$y - $py}]
    set nx [expr {$dx + [assoc -x $pinfo]}]
    set ny [expr {$dy + [assoc -y $pinfo]}]
    set new "-x $nx -y $ny"
    eval place $win $new
    oset $win placeinfo [list $x $y $new]
}

# now unused
proc OpenMathMoveHistory { win  n } {
    makeLocal $win history historyIndex
    incr historyIndex $n
    if { $historyIndex >= [llength $history] } {
	set historyIndex  [expr {[llength $history] -1}] 
    }
    if { $historyIndex < 0 } { set historyIndex 0}
    if { "[lindex $history $historyIndex]" != ""} {
	OpenMathGetWindow $win [lindex $history $historyIndex]
	oset $win historyIndex $historyIndex
    }
}

proc toLocalFilename { url } {
    set type [assoc type $url]
    switch -- $type {
	http {
	    return [assoc filename $url]
	}
	file {
	    return [file join / [assoc dirname $url] [assoc filename $url] ]

	}
	default "unknown type: $type"
    }

}

proc OpenMathGetWindow { commandPanel win } {
    if { "[winfo parent [oget $commandPanel textwin]]" != "$win" } {
	catch { pack forget [winfo parent [oget $commandPanel textwin]] }
	pack $win -expand 1 -fill both
	# pack $win
	oset $commandPanel textwin $win.text
	oset $commandPanel location [oget $win location]
	set tem [toLocalFilename [decodeURL [oget $win location]]]
	oset $commandPanel savefilename  [file root $tem].txt
    }
}

proc getw { s } {
    eval pack forget [winfo children . ] ; pack $s
}

proc try1 { file } {
    global ccc
    eval pack forget [winfo children . ]
    mkOpenMath [set w .t[incr ccc]]
    uplevel "#0" source $file
}

proc filesplit { x } {
    set l [split $x /]
    set n [llength $l ]
    set dir [lrange $l 0 [expr {$n - 2}]]
    set file [lindex $l [expr {$n - 1}]]
    return [list [join $dir /] $file]
}



proc decodeURL { name } {
    set server ""
    if { [regexp  {([^#]*)#(.*)$} $name junk name anchor] } {
	lappend answer anchor $anchor
	# puts "answer=$answer"
    }


    if { [regexp {^([a-z]+)[(]?([0-9]*)[)]?:/([^ ]+)$} $name all type port path ] } {
	lappend answer type $type
    } else {
	set path $name ; set type ""
    }

    set path [removeDotDot $path]
    #puts "path=$path"
    desetq "dirname filename" [filesplit $path]
    #puts "dirname=$dirname,path=$path,filename=$filename"
    set po [assoc $type {http 80 nmtp 4443} ]
    if { "$po" != "" } {
	if { "$port" == "" } {set port $po }

	if { [regexp {^/([^/:]*)(:([0-9]+))?(.*)$} $dirname all server \
		  jun po dirname] } {
	    # puts "hi ther,server=$server"
	    if { "$po" != ""} {set port $po}
	    if { "$dirname" == "" } {set dirname / }
	} elseif { "$server" == "" } {
	    set server $filename
	    set dirname /
	    set filename {}
	}
	lappend answer port $port server $server
    }
    lappend answer dirname $dirname filename $filename
    return $answer
}

proc removeDotDot { path } {
    while { [regsub  {/[^/]+/[.][.](/|$)} $path "\\1" path] } {list}
    return $path
}

proc appendSeparate { var before item separator } {
    if { "$item" != "" } {
	uplevel 1 append $var $before $item $separator
    }
}

proc dirnamePlusFilename { lis } {
    return  [string trimright [assoc dirname $lis ""] /]/[assoc filename $lis ""]
}
proc encodeURL { lis } {
    set type [assoc type $lis ""]
    switch -- $type {
	nmtp {
	    if { [ set port [assoc port $lis 4443]] != 4443 } {
		append type "($port)"
	    }
	    appendSeparate ans "" $type ://[assoc server $lis ""]
	    append ans [dirnamePlusFilename $lis]
	    appendSeparate ans "#" [assoc anchor $lis ""] ""
	}
	http  {
	    if { [ set port [assoc port $lis 80]] != 80 } {
		append type "($port)"
	    }
	    appendSeparate ans "" $type ://[assoc server $lis ""]
	    append ans [dirnamePlusFilename $lis]
	    #appendSeparate ans "" [assoc dirname $lis ""]
	    #appendSeparate ans "/" [assoc filename $lis ""] ""
	    appendSeparate ans "#" [assoc anchor $lis ""] ""
	}
	file {
	    appendSeparate ans "" $type :/
	    append ans  [dirnamePlusFilename $lis]
	    #	   appendSeparate ans "" [assoc dirname $lis ""] "/"
	    #	   appendSeparate ans "" [assoc filename $lis ""] ""
	    appendSeparate ans "#" [assoc anchor $lis ""] ""
	}
	default "error unsupported url type: $type"
    }
    return $ans
}

proc resolveURL { name current {post ""} } {
    set decode [decodeURL $name]
    #puts "name=$name,current=$current"
    set ans ""
    set relative 0
    if { "[assoc type $decode {} ]" == "" } {set relative 1}
    if { $relative == 0 } {
	set ans  $decode
    } else {
	foreach {x y } $current {
	    switch -- $x {
		dirname {
		    set ndir [assoc dirname $decode ""]
		    set cdir [assoc dirname $current ""]
		    if { [string match /* $ndir] } {
			set new $ndir
		    } elseif { "$ndir" != "" } {
			if { "$cdir" != ""  } {
			    set new [string trimright $cdir /]/$ndir
			} else {
			    set new $ndir
			}
		    } else {
			set new $cdir
		    }
		    lappend ans dirname [removeDotDot $new]
		}
		filename {
		    if { "[assoc filename $decode]" == "" && "[assoc anchor $decode]" != "" } {
			lappend ans $x $y
		    }
		}
		post {
		    list
		}
		default {
		    lappend ans $x  [assoc $x $decode $y]
		}
	    }
	}
	foreach { key val } $decode {
	    if { "[assoc $key $ans --none--]" == "--none--" } {
		lappend ans $key $val
	    }
	}
	

    }
    if { "$post" != "" } {
	set ans [putassoc post $ans $post]
    }
    return $ans
}

proc getURLrequest { path server port types {post ""} {meth ""} } {
    global maxima_priv

    if { "$meth" != "" } {
	set method $meth 
    } else {
	set method GET
	if { "$post" != "" } {set method POST}
    }

    #puts "getURLrequest $path $server $port [list $types]"
    foreach {v handler}  $maxima_priv(urlHandlers) {
	lappend types $v,
    }

    set ans "$method $path HTTP/1.0\nConnection: Keep-Alive\nUser-agent: netmath\nHost: $server:$port\nAccept: $types\n"
    if { "$post" != "" } {
	# append ans "Content-length: [string length $post]\n\n$post"
	append ans "Content-type: application/x-www-form-urlencoded\nContent-length: [string length $post]\n\n$post"
    }

    return $ans

}

proc canonicalizeContentType { type } {
    regexp -nocase {([---a-zA-Z]+)/([---a-zA-Z]+)} $type type
    return [string tolower $type]
}

proc getURL { resolved type {mimeheader ""} {post ""} } {
    global maxima_priv
    set res $resolved

    set ans ""
    set method ""
    if { "$mimeheader" != ""} {
	uplevel 1 set $mimeheader \[list\]
    }
    uplevel 1 set $type "unknown"


    #puts "getting $resolved,post=<$post>"
    switch [assoc type $res] {
	http {
	    #mike FIXME: replace with http get
	    # puts $res
	    # puts "socket [assoc server $res] [assoc port $res 80]"
	    if { [info exists maxima_priv(proxy,http) ] } {
		set sock [eval socket $maxima_priv(proxy,http)]
		#		puts "opening proxy request socket $maxima_priv(proxy,http)"
	    } else {
		set server [assoc server $res]
		set port [assoc port $res 80]
		#mike FIXME - use async sockets and dns
		if {[catch {socket $server $port} sock]} {
		    global errorInfo
		    tide_failure [M [mc "Error connecting to %s on %s\n%s"] \
				      $server $port $sock]
		    return
		}
	    }
	
	    fconfigure $sock -blocking 0
	    ##DO NOT DELETE THE FOLLOWING !!!!!puts!!!!!!!!
	    #puts request=[getURLrequest [dirnamePlusFilename $res] [assoc server $res] [assoc port $res] image/gif $post]
	    #	    set path [dirnamePlusFilename $res]
	    set path [encodeURL $res]
	    set server [assoc server $res]
	    set port  [assoc port $res]
	    puts $sock [getURLrequest $path $server $port image/gif $post]
	    if { "$post" == "" } {
		oset $sock cachename "http://$server:$port$path"
	    } else {
		oset $sock cachename ""
	    }
	    flush $sock
	    if { [readAllData $sock -tovar maxima_priv(url_result) \
		      -translation binary -mimeheader maxima_priv(mimeheader)  \
		      -timeout 120000 -chunksize 2024] > 0 } {
		
		#puts "length=[string length $maxima_priv(url_result)]"
		#	flush stdout
		
		set contentType [canonicalizeContentType [assoc content-type $maxima_priv(mimeheader) text/plain]]
		uplevel 1 set $type [list $contentType]
		if { "$mimeheader" != "" } {
		    uplevel 1 set $mimeheader \[ uplevel "#0" set maxima_priv(mimeheader) \]
		}
		set ans $maxima_priv(url_result)
		unset maxima_priv(url_result)
		return $ans
	    } else {
		return "had error"
	    }
	}
	file {
	    set name [toLocalFilename $res]
	    set fi [open $name r]
	    set answer [read $fi]
	    if { [regexp -nocase {[.]html?$} $name ] || [regexp -nocase "^(\[ \n\t\r\])*<html>" $answer] } {
		set contentType text/html
	    } elseif {  [regexp {[.]gif([^/]*)$} $name ] } {
		set contentType image/gif
	    } elseif {  [regexp {[.]png([^/]*)$} $name ] } {
		set contentType image/png
	    } elseif {  [regexp {[.]jpe?g([^/]*)$} $name ] } {
		set contentType image/jpeg
	    } else {
		set contentType text/plain
	    }
	    uplevel 1 set $type $contentType

	    close $fi
	    return $answer
	}
	default {
	    #mike dirpath?
	    error [concat [mc "not supported"] "[lindex $res 0]"]
	}
    }
}




proc getImage { resolved width height} {
    global maxima_priv
    set res $resolved
    #puts [list getImage [list $resolved] $width $height]
    set ans ""
    catch {
	if { "" != "[image type $maxima_priv(image,$res,$width,$height)]" } {
	    set ans $maxima_priv(image,$res,$width,$height)
	}
    }
    if { "$ans" != "" } { return $ans }

    set image [image create photo -width $width -height $height]
    after 10 backgroundGetImage $image [list $resolved] $width $height
    set maxima_priv(image,$res,$width,$height) $image
    return $image
}


proc backgroundGetImage  { image res width height }   {
    global maxima_priv
    #puts [list backgroundGetImage  $image $res $width $height ]
    if { [catch { backgroundGetImage1 $image $res $width $height } err ] } {
        set im ::img::brokenimage
	$image config -width [image width $im] -height [image height $im]
	$image copy $im
    }
}


proc backgroundGetImage1  { image res width height }   {
    #puts  "resolved=$res"
    global maxima_priv
    #puts [list backgroundGetImage $image $res $width $height]
    switch [assoc type $res] {
	http {
	    set server [assoc server $res]
	    set port [assoc port $res 80]
	    if { [info exists maxima_priv(proxy,http) ] } {
		set s [eval socket $maxima_priv(proxy,http)]
		#		puts "opening proxy request socket $maxima_priv(proxy,http)"
	    } else {
		set s [socket [assoc server $res] [assoc port $res 80]]
	    }
	    fconfigure $s -blocking 0
	    ##DO NOT DELETE THE FOLLOWING !!!!!puts!!!!!!!!
	    puts $s [getURLrequest [encodeURL $res] \
			 $server $port {image/gif image/png image/jpeg image/x-bitmap}]
	    flush $s


	    if { [regexp -nocase $maxima_priv(imgregexp) [assoc filename $res] mm extension] } {
		fconfigure $s -translation binary
		set tmp xxtmp[incr maxima_priv(imagecounter)].$extension

		if { [info exists maxima_priv(inbrowser)] ||  [catch {set out [open $tmp w] } ] } {
		    # if have binary..
		    if { "[info command binary]" != "binary" } {
			error [mc "need version of tk with 'binary' command for images"]}
		    #puts "hi binary" ; flush stdout
		    if {  [readAllData $s -tovar \
			       maxima_priv($s,url_result) -mimeheader \
			       maxima_priv($s,mimeheader)
			  ] > 0  && [string match *$extension [assoc content-type $maxima_priv($s,mimeheader)]] } {
			set ans $image
			$image configure -data [tobase64 $maxima_priv($s,url_result)]

			unset maxima_priv($s,mimeheader)
			unset maxima_priv($s,url_result)
			
		    } else  {
			error [mc "could not get image"]
		    }
		} else {
		    fconfigure $out -translation binary -blocking 0
		    if { [readAllData $s -tochannel $out \
			      -translation binary \
			      -mimeheader \
			      maxima_priv($s,mimeheader) -timeout 15000 -chunksize 2024 ] > 0 } {
			set ans $image
			$image config  -file \
			    $tmp
			unset maxima_priv($s,mimeheader)
		    }

		
		
		    # all the below just to try to remove the file..
		    #  depending on versions and in environments..
		
		}
	    }
	}
	file {
	    $image config -file [toLocalFilename $res]
	    set ans $image
	    # puts "$image config -file [toLocalFilename $res]"
	    #set ans [image create photo -file [toLocalFilename $res]]
	
	
	}
	default { error [mc "unknown type of image"] }
    }
    ## if we opened an out channel try hard to remove the tmp file.
    if { [info exists out] &&
	 [catch { file delete $tmp } ] && [catch { rm $tmp }]
	 && [catch { exec rm $tmp }] } {
	puts [concat [mc "cant remove tmp file"] "$tmp"]
    }
    if { "$ans" == "" } {
	error [concat [mc "Unable to open an image for"] "[encodeURL $res]"]
    }

}


#
#-----------------------------------------------------------------
#
# readData --  read data from S, storing the result
# in maxima_priv($s,url_result).   It times out after TIMEOUT without any data coming.
# it can be aborted by setting set maxima_priv($s,done)  -1
#
#
#  Results: -1 on failure and 1 on success.
#
#  Side Effects: it initially  empties maxima_priv($s,url_result) and then
#  adds data to it as read.   maxima_priv($s,done) is initialized to 0
#
#----------------------------------------------------------------
#
proc readData { s { timeout 10000 }} {
    global maxima_priv

    after $timeout "set maxima_priv($s,done) -1"
    fconfigure $s  -blocking 0
    set maxima_priv($s,done) 0
    set maxima_priv($s,url_result) ""

    #mike FIXME: this is a wrong use of after cancel
    fileevent $s readable \
	"after cancel {set maxima_priv($s,done) -1} ; after $timeout {set maxima_priv($s,done) -1} ; set da \[read $s 8000] ; append maxima_priv($s,url_result) \$da; if { \[string length \$da] < 8000  && \[eof $s] } {after cancel {set maxima_priv($s,done) -1} ; set maxima_priv($s,done) 1; fileevent $s readable {} ;  }"
    myVwait maxima_priv($s,done)
    catch { close $s }
    #mike FIXME: this is a wrong use of after cancel
    after cancel "set maxima_priv($s,done) -1"
    return $maxima_priv($s,done)
}



proc doRead { sock } {
    global maxima_priv

    #puts reading; flush stdout;
    set tem [read $sock]
    append maxima_priv(url_result)  $tem
    # puts read:<$tem>
    # flush stdout
    if { [eof $sock] } {
	set maxima_priv(done) 1
	close $sock
    }
}

proc tempName { name extension } {
    set count [pid]
    while { [file exists $name[incr count].$extension] } { list }
    return $name$count.$extension
}

proc ws_outputToTemp { string file ext encoding } {
    upvar 1 $string result
    set tmp [tempName $file $ext ]
    set open $tmp
    if { [lsearch {x-gzip x-compress}  $encoding] >= 0 } { 
	# FIXME: Unix only
	lappend dogzip |gzip -dc > $open ; set open $dogzip
    }
    set fi [open $open w]
    fconfigure $fi -translation binary
    puts -nonewline $fi $result
    flush $fi
    close $fi
    return $tmp
}

proc OpenMathOpenUrl { name args} {
    global maxima_priv
    
    # Removes any white spaces at the end of the Url given
    set name [string trimright $name]

    gui status [concat [mc "Opening"] "$name"]

    #puts "OpenMathOpenUrl  $name $args "
    set history "" ; set historyIndex -1 ; set currentUrl ""
    set prevwindow ""
    set commandPanel [assoc -commandpanel $args ]
    if { "$commandPanel" == "" } {
	linkLocal . omPanel
	if { [info exists omPanel] } {
	    set commandPanel $omPanel
	}
    }
    set toplevel [assoc -toplevel $args ""]
    if { "$toplevel" == "" } {set toplevel ".browser"}
    if { "$toplevel" == "." } {set toplevel ""}
    set reload [assoc -reload $args 0]
    set post [assoc -post $args ""]
    #puts "post=$post"
    if { [winfo exists $commandPanel ] }  {
	makeLocal $commandPanel history historyIndex textwin
#	set toplevel [winfo paren $commandPanel]
#	if { "$toplevel" == "." } {set toplevel ""}
	# eval pack forget [winfo parent $textwin ]
	set prevwin [winfo parent $textwin]
	set currentUrl [oget $textwin currentUrl]
	catch { set currentUrl [decodeURL [oget $textwin baseurl]] }

	if { $reload == 0} {
	
	    set new [resolveURL $name $currentUrl $post]
	    if { [set anchor [assoc anchor $new]] != "" } {
		set new [delassoc anchor $new]
	    }
	    set ii -1
	    foreach v $history {
		incr ii
		if { "[delassoc post $new]" == "[delassoc post [oget $v.text currentUrl]]" } {
		    # puts "new=$new\nold=[oget $v.text currentUrl]"
		}
		if   { "$new" == "[delassoc anchor [oget $v.text currentUrl]]" } {
		    OpenMathMoveHistory $commandPanel [expr {$ii - $historyIndex }]
		    if { "$anchor" != "" } {
			update
			catch {  $v.text yview anchor:$anchor }
		    }
		
		    #    OpenMathGetWindow $commandPanel $v
		    #    pushHistory $commandPanel $v
		    return
		}
		
	    }
	} else {
	    # reload=1
	    list
	}
    }
    set count 5
    while { [incr count -1] > 0 } {
	set new [resolveURL $name $currentUrl $post]
	set result [getURL $new contentType mimeheader $post]
	if { [set tem [assoc location $mimeheader]] == "" } {
	    break
	}
	set name $tem
    }

    #puts "contentType defined:[info exists contentType]"
    set handler [assoc $contentType $maxima_priv(urlHandlers)]
    if { "$handler" != "netmath" && "$handler" != "" } {
	set tmp [ws_outputToTemp result netmath ps "[assoc content-encoding $mimeheader]"]
	# to do fix this for windows #####
	exec sh -c "[format $handler $tmp] ; rm -f $tmp" &
	return
    }
    #puts contentType=$contentType

    #puts "got [string length $result] bytes"
    #puts ", result= [string range $result 0 70] .."

    if { [catch { set baseprogram [oget $textwin baseprogram] }] } {
	set baseprogram [decodeURL [getBaseprogram]]
    }
    # puts "using  $baseprogram"
    if { $reload } {   forgetCurrent $commandPanel }

    #puts "maxima_priv(counter)=$maxima_priv(counter)"

    set win [mkOpenMath [set w $toplevel.t[incr maxima_priv(counter)]] ]

    #puts "maxima_priv(counter)=$maxima_priv(counter)"

    makeLocal $w commandPanel
    #puts "resolveURL $name $currentUrl"

    if { [set anchor [assoc anchor $new]] != "" } {
	set new [delassoc anchor $new]
    }
    if { "[assoc filename $new]" == "" } {
	set new [putassoc  filename $new index.html]
    }
    # puts "...> $new"
    oset $w.text currentUrl $new
    oset $commandPanel location [encodeURL $new]
    oset $commandPanel textwin $win
    oset $w location  [encodeURL $new]
    # puts "new=$new"
    oset $commandPanel savefilename [file root [toLocalFilename $new]].txt

    set tem [assoc filename $new ""]
    #puts $contentType
    if { "$contentType" != "text/html" } {
	if { [string match "image/*" $contentType] } {
	    set im [image  create photo -data $result]
	    $win image create 0.0 -image $im
	    set err 0
	} else {
	    set err [catch {   $win insert 0.0 $result } ]
	}
    } elseif { 1 }  {
	xHMinit_win $win
	xHMset_state $win url [encodeURL $new]
	oset $win baseprogram $baseprogram
	# puts win=$win,lengres=[string length $result]
	set errmsg1 ""
	set err 0
	global debugParse
	if { $debugParse } {
	    xHMparse_html $result "xHMrender $win"
	    set err 0
	} else {
	    set err [catch {
		xHMparse_html $result "xHMrender $win"
	    } errmsg1 ]
	}
	catch {
	    if { "$anchor" != "" } {
		update
		$win yview anchor:$anchor
	    }
	}
	
	#   foreach v {Tresult Teval} {  $win tag raise $v}	


    } else {
	###Never get here.. must change to make be the rich text case..	
	# drop comment lines
	regsub -all "(^|\n)#\[^\n\]*\n" $result \n result ;
	#puts input=$result
	
	# note sensible-browser would just truncate the history
	# at historyIndex, and start to grow it there,
	# losing the record of all files you have visited after..
	# maybe we should do this.
	#puts "history=$history"
	set err [catch { insertRichText $win insert $result }]
    }
    if { $err == 0 } {
	pushHistory $commandPanel $w
    }
    if { $err } {
	global errorInfo
	#puts "======begin======"
	#puts $result
	#puts "======end========"
	puts "$errmsg1"
	error [concat [mc "unable to evaluate"] "[encodeURL $new]\n$errmsg1\n$errorInfo"]
    }

}


proc pushHistory { commandPanel win } {
    global [oarray $commandPanel]
    makeLocal $commandPanel history historyIndex

    if { [llength $history] == 0 } {
	oset $commandPanel historyIndex -1
    }
    if { "[lindex $history $historyIndex ]" != "$win" } {
	oset $commandPanel history [linsert $history [incr [oloc $commandPanel historyIndex]] $win]
    }
}


#
#-----------------------------------------------------------------
#
# omScrollPage --  scroll the page by N pages, keeping the insert
# cursor visible.
#
#  Results: none
#
#  Side Effects: page scrolls
#
#----------------------------------------------------------------
#
proc omScrollPage { win n } {
    tkTextScrollPages $win $n
    set bbox [$win bbox insert]
    if { "" == "$bbox" } {
	if { $n > 0 } {
	    $win mark set insert @0,0
	} else {$win mark set insert @0,[$win cget -height]}
    }
}

proc addTagSameRange { win oldtag newtag index } {
    if { [lsearch [$win tag names $index] $oldtag ] >= 0 } {
	set this [$win tag prevrange $oldtag $index+1char]
	if { "$this" != "" && [$win compare $index < [lindex $this 1]] } {
	    $win tag remove $newtag 0.0 end
	    $win tag add $newtag [lindex $this 0] [lindex $this 1]
	    $win tag raise $newtag
	}
    }
}

proc getBaseprogram { } {
    global maxima_default
    return [lindex  $maxima_default(defaultservers) 0]
}

#mike FIXME: This is an abomination
proc fileBaseprogram { textwin parent x y } {
    set e $textwin.e
    catch { destroy $e }
    set x [expr {[winfo rootx $parent] + $x +30 - [winfo rootx $textwin]} ]
    set x 30
    set y [expr {[winfo rooty $parent] + $y - [winfo rooty $textwin]} ]
    global xHMpriv
    set xHMpriv(baseprogram) [encodeURL [oget $textwin baseprogram]]
    entry $e -width 40 -textvariable xHMpriv(baseprogram)
    place $e -in $textwin -x $x -y $y
    raise $e
    set com "destroy $e ; oset $textwin baseprogram \[decodeURL \$xHMpriv(baseprogram)] "
    bind $e <Leave> $com
    bind $e <Return> $com

}

proc fontDialog { top } {
    global maxima_default

    set font [xHMmapFont font:propor:normal:r:3]
    if {[winfo exists $top]} {catch { destroy $top }}

    toplevel $top
    wm iconify  $top

    set win $top.text
    text $win -font [list [font config $font -family] [font config $font -size]] -height 20
    wm deiconify $top

    foreach fam {propor fixed} {
	set lis ""
	set i 0
	while { $i <= 8 } {
	    lappend lis [expr {$i - 3}]
	    incr i
	}
	if { "$fam" == "fixed" } { set fixed 1 } else {
	    set fixed 0
	}
	mkLabelListBoxChooser $win.size$fam "list $lis" maxima_default($fam,adjust)
	mkLabelListBoxChooser $win.family$fam "getFontFamilies $fixed " maxima_default($fam)
	set fo [xHMmapFont "font:$fam:normal:r:3"]
	catch { set maxima_default($fam) [assoc -family [font actual $fo]]}
    }
    $win insert insert [mc "Font Settings\nThe proportional font is "]
    $win window create insert -window $win.familypropor
    $win insert insert [mc "with a size adjustment of "]
    $win window create insert -window $win.sizepropor
    $win insert insert [mc "\nThe fixed font is "]
    $win window create insert -window $win.familyfixed
    $win insert insert [mc "with a size adjustment of "]
    $win window create insert -window $win.sizefixed
    $win insert insert "\n"
    $win insert insert [mc "Default nmtp servers  "]
    global _servers
    set _servers $maxima_default(defaultservers)
    entry $win.entry -textvariable _servers -width 40
    $win window create insert -window $win.entry
    $win insert insert "\n\n"
    global maxima_priv
    $win insert insert [mc "http Proxy host and port:"]
    entry $win.entryproxy  -width 40
    catch { $win.entryproxy insert 0 $maxima_priv(proxy,http) }
    $win window create insert -window $win.entryproxy
    $win insert insert [mc "\nIf you are behind a firewall enter the name of your http proxy host and port,\n eg: `foo.ma.utexas.edu 3128', otherwise leave this blank"]

    set men [tk_optionMenu $win.plottype maxima_default(plotwindow) embedded separate multiple ]
    $win insert insert [mc "\nShould plot windows be "]
    $win window create insert -window $win.plottype
    $win insert insert "?"


    $win insert insert "\n\n\n"
    $win insert insert [mc " Apply and Quit "] "bye raised"
    $win insert insert "      "
    $win insert insert [mc " Apply "] "click raised"
    $win insert insert "      "
    $win insert insert [mc " Cancel "] "cancel raised"
    proc _FontDialogApply { win } {
	global maxima_default _servers maxima_priv
	set maxima_default(defaultservers) $_servers
	catch {xHMresetFonts .}
	if { [llength [$win.entryproxy get]] == 2 } {
	    set maxima_priv(proxy,http) [$win.entryproxy get]
	}
    }
    $win tag bind click <1> "_FontDialogApply $win"
    $win tag bind bye <1> "_FontDialogApply $win ; destroy $top"
    $win tag bind cancel <1> "destroy $top"
    $win tag configure raised -relief raised -borderwidth 2
    $win insert insert "      "
    $win insert insert [mc " Save Preferences "] "save raised"
    $win tag bind save <1> "_FontDialogApply $win ; savePreferences"

    pack $win
    #    place $win -in [oget [omPanel .] textwin] -x 10 -y 10
}
proc savePreferences {} {
    global maxima_default maxima_priv

    # Save current console size in maxima_default
    set console [lindex [array get maxima_priv cConsoleText] end]
    set maxima_default(iConsoleWidth) [textWindowWidth $console]
    set maxima_default(iConsoleHeight) [textWindowHeight $console]

    if {[catch {open  "~/.xmaximarc" w} fi]} {return}

    puts $fi "array set maxima_default {"
    foreach {k v} [array get maxima_default *] {
	lappend all [list $k $v]
    }
    set $maxima_priv(image,$res,$width,$height)]" } {
	    set ans $maxima_priv(image,$res,$width,$height)
	}
    }
    if { "$ans" != "" } { return $ans }

    set image [image create photo -width $width -height $height]
    after 10 backgroundGetImage $image [list $resolved] $width $height
    set maxima_priv(image,$res,$width,$height) $image
    return $image
}


proc backgroundGetImage  { image res width height }   {
    global maxima_priv
    #puts [list backgroundGetImage  $image $res $width $height ]
    if { [catch { backgroundGetImage1 $image $res $width $height } err ] } {
        set im ::img::brokenimage
	$image config -width [image width $im] -height [image height $im]
	$image copy $im
    }
}


proc backgroundGetImage1  { image res width height }   {
    #puts  "resolved=$res"
    global maxima_priv
    #puts [list backgroundGetImage $image $res $width $height]
    switch [assoc type $res] {
	http {
	    set server [assoc server $res]
	    set port [assoc port $res 80]
	    if { [info exists maxima_priv(proxy,http) ] } {
		set s [eval socket $maxima_priv(proxy,http)]
		#		puts "opening proxy request socket $maxima_priv(proxy,http)"
	    } else {
		set s [socket [assoc server $res] [assoc port $res 80]]
	    }
	    fconfigure $s -blocking 0
	    ##DO NOT DELETE THE FOLLOWING !!!!!puts!!!!!!!!
	    puts $s [getURLrequest [encodeURL $res] \
			 $server $port {image/gif image/png image/jpeg image/x-bitmap}]
	    flush $s


	    if { [regexp -nocase $maxima_priv(imgregexp) [assoc filename $res] mm extension] } {
		fconfigure $s -translation binary
		set tmp xxtmp[incr maxima_priv(imagecounter)].$extension

		if { [info exists maxima_priv(inbrowser)] ||  [catch {set out [open $tmp w] } ] } {
		    # if have binary..
		    if { "[info command binary]" != "binary" } {
			error [mc "need version of tk with 'binary' command for images"]}
		    #puts "hi binary" ; flush stdout
		    if {  [readAllData $s -tovar \
			       maxima_priv($s,url_result) -mimeheader \
			       maxima_priv($s,mimeheader)
			  ] > 0  && [string match *$extension [assoc content-type $maxima_priv($s,mimeheader)]] } {
			set ans $image
			$image configure -data [tobase64 $maxima_priv($s,url_result)]

			unset maxima_priv($s,mimeheader)
			unset maxima_priv($s,url_result)
			
		    } else  {
			error [mc "could not get image"]
		    }
		} else {
		    fconfigure $out -translation bi                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       