#! /bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"

#
# ev	tcl/tk script to update variables exported using the exportvar
#	package
#
#	$Log$
#	Revision 1.9  2007/02/04 22:44:06  cor134
#	MacOS port.  First cut, compiles but only partly tested: threads, error.
#	Still problems with serial module using USB serial port.
#
#	Revision 1.8  2003/06/16 10:17:18  pic
#	Add support for units, fix extant bugs with info lookup, move away from usage
#	of leading ! character to indicate polled.
#	
#	Revision 1.7  2003/02/13 06:09:37  sik057
#	Fixed invalid SRPC calls.
#	
#	Revision 1.6  2003/02/13 05:42:17  sik057
#	Updated to make SRPC behave like RTC.
#	
#	Revision 1.5  2003/01/30 05:44:00  sik057
#	Fixed hard-coded references to automation filesystem.
#	
#	Revision 1.4  2003/01/24 03:35:13  sik057
#	Old ev still needs lappend for handling arrays.
#	
#	Revision 1.3  2003/01/24 03:07:28  sik057
#	Fixed array-handling with SRPC.
#	
#	Revision 1.2  2003/01/22 02:40:00  sik057
#	Export module now uses both RTC and SRPC.
#	
#	Revision 1.1  2002/09/06 06:15:25  sik057
#	Moved from src.
#	
#	Revision 1.4  2002/04/25 23:08:52  pic
#	Fixed bug with stripchart on subscripted variables
#	
#	Revision 1.3  2002/04/11 05:26:36  pic
#	Fixed bug that stopped plot working.
#	Allowed host:program form of specifying target
#	Added -sort, -nosort flags to control variable sorting.
#	
#	Revision 1.2  2002/03/03 23:40:12  jmr
#	Added -dt option
#	
#	Revision 1.1  2002/01/04 06:13:10  pic
#	
#	Add ev to CVS control.
#	
#	Revision 1.17  2000/08/20 06:38:14  pic
#	Added -only flag to allow subset of variables to be selected for display
#	using a command line regexp.
#	Also added catch and error handling for RTC initialization to give
#	tidier error messages.
#	Updated the usage message.
#
#	Revision 1.16  2000/03/08 04:01:14  sik057
#	fixed inadvertantly introduced bug ....
#
#	Revision 1.15  1999/09/20 02:21:06  sik057
#	removed -recreate option from RTC initialzation
#	-should speed things up
#
#	Revision 1.14  1999/07/18 17:54:23  pic
#	fixed problem where exportvar_info() was called with vector element, not
#	vector base name.
#
#	Revision 1.13  1999/07/02 03:46:50  jmr
#	added -transport option and made default transport type udp instead of tcp
#
#	Revision 1.12  1999/04/15 05:04:55  pic
#	make labels go red when polling
#
#	Revision 1.11  1999/04/14 11:08:51  pic
#	add envariable EV_FONTSIZE
#	add batch mode for polled variables
#	added min/max finding for stripchart widget and autoscaling, but not
#	 finished yet.
#
#	Revision 1.10  1999/03/24 14:39:12  pic
#	Add support for service map file
#	Add stripchart widget
#	tidy up fonts
#	add command line switches and usage info
#	support read only variables
#
#	Revision 1.9  1998/10/06 06:36:11  pic
#	changed regexp to allow for variable names with a '.'
#	added initial support for new exportvar_info function
#
#	Revision 1.8  1998/05/26 03:37:06  pic
#	added support for new EV_POLL flag
#
#	Revision 1.7  1998/03/27 05:28:57  jmr
#	*** empty log message ***
#
#	Revision 1.6  1998/03/11 05:52:55  jmr
#	made font smaller
#
#	Revision 1.5  1998/03/10 02:06:27  pic
#	added symbols for common pahts
#	added variable polling checkbox to all variables
#
#	Revision 1.4  1998/02/23 23:09:24  pic
#	added nice bitmaps for up/down arrows.
#
#	Revision 1.3  1998/02/23 22:55:58  pic
#	Added buttons to increase/decrease values by 20%.
#	TODO: create nice icons for the buttons
#	      make the inc/decrement adjustable somehow
#

# EV upgrades:
# optimize polling, batch all poll updates into 1 request
# integrate stripchart widget
# introduce service map file and command line options to use this

package require RTX_SRPC

if [catch {$env(AUTOM)} AUTOM] {
    set AUTOM /data/aa
}

set mapFile $AUTOM/etc/services.rtc
# set default chart size parameters
set W 400
set W0 50
set H 120
set HM 10
set xmin -100
set xmax 0
set xgrid 10
set dx 2
set bgcol_ok white
set bgcol_failed red
set bgcol $bgcol_ok

# and update rate
set dt 50
set sort_vars 1

set pi 3.1415926535
set poll_all 0


#
# Usage: ev -program num -server hostname
#
#
# simple GUI to examine and set program variables exported using the
# exportvar library.  When a variable is edited its label goes red indicating
# that it is being modified.  On hitting return the value is transmitted and
# the label goes blue.  The refresh button reloads all variable values from
# the remote application.

set count 1
set debug 0
set PKG $AUTOM/pkg
set XBM $AUTOM/lib/bitmaps
set RTC $PKG/rtc
#set font 5x7
set bg white
set lwidth 0
set transport udp
set useRTC 0

# set font size to envariable EV_FONTSIZE if present
if {[info exists env(EV_FONTSIZE)]} {
	set fontSize $env(EV_FONTSIZE)
} else {
	set fontSize -10
}


# when a variable is edited set its label to red
proc tproc {name1 element op} {
		.$element.l configure -fg red
}

# button handlers for increasing/decreasing data values
proc upval {name} {
        global VALS VARS debug

        if {$debug} {
		puts stdout "up $name"
	}
        set VALS($name) [expr $VALS($name) * 1.2]
        sendval $name
}

proc downval {name} {
        global VALS VARS debug

       if {$debug} {
		puts stdout "down $name"
	}
        set VALS($name) [expr $VALS($name) / 1.2]
        sendval $name
}


# create a label and data entry box for the specified variable
proc varbox {var val vbasename} {
        global UNITS XBM VALS VARS count POLL bg font lfont lwidth poll_all
	global useRTC channelId

	puts "varbox: $var $val $vbasename"
	set unique f$count

	# a leading ! means the variable should be set to polling mode
	set lchar [string range $var 0 0]
	if {$lchar == "!"} {
		# trim the bang char
		set var [string range $var 1 end]
		set POLL($unique) 1
	}
	if {$poll_all} {
		set POLL($unique) 1
	}

	# get the info list for each variable
	#	
	#  pollflag readonlyflag type dimension units minvalue maxvalue
	#  pollflag readonlyflag type dimension units

	if {$useRTC == 1} {
		catch {set info [r call exportvar_info $vbasename]} errmsg
	} else {
		catch {set info [rtx_srpc_call $channelId "exportvar_info $vbasename"]} errmsg
	}

	puts "$var $unique"
	puts "$var info is <$info>"

	set pollflag [lindex $info 0]
	set roflag [lindex $info 1]

	set UNITS($unique) [lindex $info 4]

        frame .$unique -bg $bg
        label .$unique.l -text $var -anchor e -width $lwidth \
		-bg $bg -fg black -font $lfont
	pack .$unique.l -side left 
        set VARS($unique) $var
        set VALS($unique) $val

	# check pollflag status
	if {$pollflag} {
		set POLL($unique) 1
	}
	if {$poll_all} {
		set POLL($unique) 1
	}
	checkbutton .$unique.poll -text Poll -variable POLL($unique) \
		-bg $bg -fg black  -font $font
	pack .$unique.poll -side right

	if {$roflag} {
		# READONLY variable
		entry .$unique.e -textvariable VALS($unique) \
			-bg $bg -fg darkgreen -state disabled -font $font
		label .$unique.u -text $UNITS($unique)
		pack .$unique.u -side right
		pack .$unique.e -side right -expand 1 -fill x
	} else {
		entry .$unique.e -textvariable VALS($unique) \
			-bg $bg -fg black -font $font
		label .$unique.u -text $UNITS($unique)
		button .$unique.up -bitmap @$XBM/up.xbm \
			-command "upval $unique" -bg $bg -fg black
		button .$unique.down -bitmap @$XBM/down.xbm \
			-command "downval $unique" -bg $bg -fg black
		pack .$unique.down -side right
		pack .$unique.up -side right
		pack .$unique.u -side right
		pack .$unique.e -side left -expand 1 -fill x
	}

        pack .$unique -expand 1 -fill x
        bind .$unique.e <Return> {
                global VARS
                
                regexp {\.([a-zA-Z][a-zA-Z0-9_]*)} %W matchall unique
                sendval $unique
        }

	bind .$unique.e <Button-3> "stripchart_start [exp2list $var]"
	#bind .$unique.e <Button-3> "stripchart_start $var"
	incr count
}

# send specified variable back to the server
proc sendval {name} {
        global VALS VARS debug
	global useRTC channelId

	if {$debug} {
		puts "changing $VARS($name) to $VALS($name)"
	}
	if {$useRTC == 1} {
		catch {r call exportvar_var $VARS($name) $VALS($name)} errmsg
	} else {
		set argstr "exportvar_var $VARS($name) $VALS($name)"
		catch {rtx_srpc_call $channelId $argstr} errmsg
	}	
        .$name.l configure -fg blue
}

# reload all values from the remote application
proc refresh {} {
        global VALS VARS count
	global useRTC channelId

	for {set i 1} {$i<$count} {incr i} {
		set unique f$i
		if {$useRTC == 1} {
			catch {set VALS($unique) [r call exportvar_var $VARS($unique)]} errmsg
		} else {
			set argstr "exportvar_var $VARS($unique)"
			catch {set VALS($unique) [rtx_srpc_call $channelId $argstr]} errmsg
		}
		.$unique.l configure -fg black
	}
}

# convert string of the form foo[4] to a list {foo 4}
proc exp2list {el} {
	regexp {(!?[a-zA-Z][a-zA-Z0-9_\.]*)(\[[0-9]*\])?} $el junk var nels
	if {$nels != ""} {
		set nels [string trim $nels "\[\]"]
		return [list $var $nels]
	} else {
		return $var
	}
}

proc sortproc {a b} {
	set a [string tolower [string trim $a "!"]]
	set b [string tolower [string trim $b "!"]]
	return [string compare $a $b]
}

# Polls marked variables
proc polling {} {
	global	VALS VARS POLL count bg bgcol bgcol_ok bgcol_failed
	global useRTC channelId

	set vlist {}
	set ulist {}

	for {set i 1} {$i<$count} {incr i} {
		set unique f$i
		if {$POLL($unique) == 0} {
			.$unique.poll configure -bg $bg
			.$unique.l configure -fg black
			continue;
		}
		.$unique.poll configure -bg red
		.$unique.l configure -fg red
		if {$useRTC == 1} {
			lappend vlist $VARS($unique)
		} else {
			set vlist [concat $vlist $VARS($unique)]
		}
		lappend ulist $unique
	}

	# get the batch of values
	if {$useRTC == 1} {
		set s [catch {set retvals [eval r call exportvar_multi_var $vlist]} errmsg]
	} else {
		set argstr "exportvar_multi_var $vlist"
		set s [catch {set retvals [rtx_srpc_call $channelId $argstr]} errmsg]
	}

	if {$s == 0} {
		#puts "$vlist $retvals"
		foreach unique $ulist val $retvals {
			#puts "$unique $val"

			set VALS($unique) $val
		}
		if {$bgcol != $bgcol_ok} {
			for {set i 1} {$i<$count} {incr i} {
				set unique f$i

				.$unique.e configure -bg $bgcol_ok
			}
			set bgcol $bgcol_ok
		}
			
	} else {
		# error in reading variables, assume application has died
		# indicate this to the user
		if {$bgcol != $bgcol_failed} {
			for {set i 1} {$i<$count} {incr i} {
				set unique f$i

				.$unique.e configure -bg $bgcol_failed
			}
			set bgcol $bgcol_failed
		}
	}

	after 200 polling
}


############################################################################
# S E R V I C E S   M A P     package
#############################################################################

proc find_service {fname service} {
	set f [open $fname r]

	puts "looking for $service"
	while {[gets $f line] >= 0} {
		# skip blank lines
		if {[string length $line] == 0} continue
		if {[regexp "^#" $line]} continue

		if {[lindex $line 0] == $service} {
			close $f
			return [lindex $line 1]
		}
	}
	close $f
}

############################################################################
# S T R I P    C H A R T     package
#############################################################################

##
# create a scaled canvas spanning the given X and Y data range
proc create_axes {can xmin xmax ymin ymax {gx 10} {gy 10}} {
	global W H

	canvas .t_$can.c -width $W -height $H
	pack .t_$can.c -expand true -fill both

	create_axes2 $can $xmin $xmax $ymin $ymax $gx $gy
}

proc rescale can {
	global SCALE W W0 H
	global MIN MAX H SCALE DY HM

	set ymin $MIN($can)
	set ymax $MAX($can)
	set yscal [expr -double($H-2*$HM)/($ymax-$ymin)]
	set y0 [expr ($HM)-($ymax*$yscal)]

	set SCALE($can,Y0) $y0
	set SCALE($can,YS) $yscal

	set gy [expr ($ymax-$ymin)/5]
	grid_it_y $can $MIN($can) $MAX($can) $DY($can)
}


proc create_axes2 {can xmin xmax ymin ymax {gx 10} {gy 10}} {

	global SCALE W W0 H HM
	
	set xscal [expr double($W-$W0)/($xmax-$xmin)]
	set x0 [expr -($xmin*$xscal)]

	set yscal [expr -double($H-2*$HM)/($ymax-$ymin)]
	set y0 [expr ($HM)-($ymax*$yscal)]
	#puts "xs $xscal, ys $yscal, x0 $x0, y0 $y0"


	set SCALE($can,X0) $x0
	set SCALE($can,Y0) $y0
	set SCALE($can,XS) $xscal
	set SCALE($can,YS) $yscal

	grid_it $can $xmin $xmax $ymin $ymax $gx $gy
}

##
# scale x coordinate from user to canvas units
proc xscal {can x} {
	global SCALE

	return [expr ($SCALE($can,XS)*$x)+$SCALE($can,X0)]
}

##
# scale y coordinate from user to canvas units
proc yscal {can y} {
	global SCALE

	return [expr ($SCALE($can,YS)*$y)+$SCALE($can,Y0)]
}

###
# draw X and Y grid lines on a scaled canvas
proc grid_it {can xmin xmax ymin ymax {gx 10} {gy 10}} {

	# delete old text and grid lines
	.t_$can.c delete gridx
	.t_$can.c delete gridy

	# build the vertical lines
	for {set x $gx} {$x < $xmax} {set x [expr $x+$gx]} {
		create_line $can $x $ymin $x $ymax -fill pink -tag gridx
	}
	for {set x -$gx} {$x > $xmin} {set x [expr $x-$gx]} {
		create_line $can $x $ymin $x $ymax -fill pink -tag gridx
	}

	# build the horizontal lines
	for {set y $gy} {$y <= $ymax} {set y [expr $y+$gy]} {
		create_line $can $xmin $y $xmax $y -fill pink -tag gridy
		create_ylabel $can $y -tag gridy
	}
	for {set y -$gy} {$y >= $ymin} {set y [expr $y-$gy]} {
		create_line $can $xmin $y $xmax $y -fill pink -tag gridy
		create_ylabel $can $y -tag gridy
	}
	create_line $can $xmin 0 $xmax 0 -fill blue -tag gridy
	create_ylabel $can 0 -tag gridy
}

proc grid_it_y {can ymin ymax {gy 10}} {
	global xmin xmax

	.t_$can.c delete gridy

	for {set y $gy} {$y <= $ymax} {set y [expr $y+$gy]} {
		create_line $can $xmin $y $xmax $y -fill pink -tag gridy
		create_ylabel $can $y -tag gridy
	}
	for {set y -$gy} {$y >= $ymin} {set y [expr $y-$gy]} {
		create_line $can $xmin $y $xmax $y -fill pink -tag gridy
		create_ylabel $can $y -tag gridy
	}
	create_line $can $xmin 0 $xmax 0 -fill blue -tag gridy
	create_ylabel $can 0 -tag gridy
}

##
# draw a line between given real coordinates with optional widget arguments
proc create_line {can x1 y1 x2 y2 args} {
	set x1 [xscal $can $x1]
	set y1 [yscal $can $y1]
	set x2 [xscal $can $x2]
	set y2 [yscal $can $y2]

	eval .t_$can.c create line $x1 $y1 $x2 $y2 $args
	
}

proc create_ylabel {can y args} {
	global W

	eval .t_$can.c create text [expr $W-50] [yscal $can $y] \
		-text [format {%- 8.3g} $y] \
		-anchor w -font Courier $args
}

proc animate {can} {
	global x xl yl dt t ID MIN MAX VARNAME DY
	global useRTC channelId

	# if the window's gone, give up now
	if {[winfo exists .t_$can] == 0} {
		return
	}

	# get the new data point
	set var $VARNAME($can)
	
	if {$useRTC == 1} {
		catch {set ynew [r call exportvar_var $var]} errmsg
	} else {
		catch {set ynew [rtx_srpc_call $channelId "exportvar_var $var"]} errmsg
	}
	#puts "ynew $ynew $MIN($can) $MAX($can)"

	set newscale 0
	if {$ynew < $MIN($can)} {
		set MIN($can) $ynew 
		set newscale 1
	}
	if {$ynew > $MAX($can)} {
		set MAX($can) $ynew 
		set newscale 1
	}

	if {$MAX($can) == $MIN($can)} {
		#puts "are equal"
		set MAX($can) [expr $MIN($can)+0.1]
		#puts "ynew $ynew $MIN($can) $MAX($can)"
		set newscale 1
	}

	if {$newscale} {
		#puts "rescaling  $MIN($can) $MAX($can)"
		set span [expr $MAX($can)-$MIN($can)]
		set mag [expr int(log10($span))]
		set mant [expr $span/pow(10,$mag)]
		if {$mant > 5} {
			set scale 10
		} else {
			if {$mant > 2} {
				set scale 5
			} else {
				set scale 2
			}
		}
		#puts "span $span, mant $mant, scale $scale"
		set dy [expr $scale*pow(10,$mag)/5]
		set DY($can) $dy
		set MAX($can) [expr $dy*ceil($MAX($can)/$dy)]
		set MIN($can) [expr $dy*floor($MIN($can)/$dy)]
		#puts "dy $dy"
		#puts "rescaling  $MIN($can) $MAX($can)"
		rescale $can
	}

	# get the old line data
	set c [.t_$can.c coords myline]

	# now shift all the Y data along, keeping X
	set l {}
		# get x0
	set xx [lindex $c 0]	
	foreach {x y} [lrange $c 2 end] {
		lappend l $xx $y
		set xx $x
	}
		# put new X, Y on the end
	lappend l $xx [yscal $can $ynew]

		# update the line coords
	eval ".t_$can.c coords myline $l"

	# repeat the process
	set ID($can) [after $dt animate $can]
}

proc toggle_anim {can} {
	global dt PAUSE ID

	# the per window pause status is kept in a global assoc array
	if {$PAUSE($can) == 0} {
		set PAUSE($can) 1
		after cancel $ID($can)
	} else {
		set PAUSE($can) 0
		set ID($can) [after $dt animate $can]
	}
}

proc rescale_y {can scal} {
	global SCALE

	.t_$can.c scale grid \
		[xscal $can 0] [yscal $can 0] 1.0 $scal
	set SCALE($can,YS) [expr $SCALE($can,YS)*$scal]
}

##
# create an animation
proc create_anim {can xmin xmax ymin ymax gx gy} {
	global PAUSE dt MIN MAX dx VARNAME

	# create new top level frame, label it, and create axes
	toplevel .t_$can
	wm title .t_$can $VARNAME($can)
	create_axes $can $xmin $xmax $ymin $ymax $gx $gy

	# initially not paused
	set PAUSE($can) 0

	# event handlers:
	#	q	close the scroller
	#	t	stop/start toggle
	#	s	slow the sample interval
	#	f	fast (reduce the sample interval)
	bind .t_$can q "destroy .t_$can"
	bind .t_$can t "toggle_anim $can"
	bind .t_$can s {set dt [expr int($dt*1.5)]}
	bind .t_$can f {set dt [expr int($dt/1.5)]}
	bind .t_$can m "rescale_y $can 2.0"
	bind .t_$can r "rescale_y $can 0.5"
	bind .t_$can a "rescale $can"

	bind .t_$can.c <Configure> "win $can"

	set MAX($can) -1000.0
	set MIN($can) 1000.0

	# create Ymin, Ymax entry boxes to allow vertical scale adjust
	label .t_$can.ymin_l -text "Ymin"
	entry .t_$can.ymin -textvariable MIN($can)
	label .t_$can.ymax_l -text "Ymax"
	entry .t_$can.ymax  -textvariable MAX($can)
	pack .t_$can.ymin_l .t_$can.ymin .t_$can.ymax_l .t_$can.ymax -side left

	# create the initial line
	set l {}
	for {set x $xmin} {$x < $xmax} {set x [expr $x+$dx]} {
		lappend l [xscal $can $x] [yscal $can 0]
	}
	eval ".t_$can.c create line $l -tags {grid myline}"
}

proc win {can} {
        global W H xmin xmax xgrid MIN MAX DY dx

	set HH [winfo height .t_$can.c]
	set WW [winfo width .t_$can.c]
	set W [expr $WW]
	set H [expr $HH]
	#puts "resize: $can $W $H"

	create_axes2 $can $xmin $xmax $MIN($can) $MAX($can) $xgrid $DY($can)

	# rescale the line
	set l [.t_$can.c coords myline]
	set ll {}
	set xx $xmin
	foreach {x y} $l {
		lappend ll [xscal $can $xx] $y
		set xx [expr $xx+$dx]
	}
	eval ".t_$can.c coords myline $ll"
}


#
# right-click on a variable starts up a simple strip chart widget
#
proc stripchart_start {var {dim  ""} } {
	global VARNAME xmin xmax xgrid
	global useRTC channelId

	puts "var $var"
	puts "dim $dim"
	# cant pass the variable name with square brackets, send it as a
	# list and reconstruct it here...
	if {$dim == ""} {
		set vardim $var
	} else {
		set vardim [format {%s[%s]} $var $dim]
	}
	if {$useRTC == 1} {
		catch {set info [r call exportvar_info $var]} errmsg
	} else {
		catch {set info [rtx_srpc_call $channelId "exportvar_info $var"]} errmsg
	}

	if {[llength $info] > 4} {
		set ymin [lindex $info 4]
		set ymax [lindex $info 5]
	} else {
		set ymin 1000.0
		set ymax -1000.0
	}
	puts "start stripchart on $vardim, span $ymin to $ymax"

	# convert variable name (maybe with dot) to a dotfree canvas name
	regsub -all -- "\\." $var "_" can
	set can [format {%s_%s} $can $dim]
	set VARNAME($can) $vardim

	# create the axes and grid them
	create_anim $can $xmin $xmax $ymin $ymax $xgrid [expr (($ymax-$ymin)/5.0)]

	animate $can
}

set usage {
Usage: ev [switches] [host:service]

The host and service can be specified by a final argument of the form

     host:program
     host:serviceName
     serviceName

where serviceName is a text name that is resolved through the service map
file.  If host is not specified it defaults to the current host.

* Switches:

        SWITCH     ARG     DESCRIPTION
                   TYPE

	-only      string     wildcard name of variable subset to display
	-server    string     name of host on which server runs
        -host      string	      "          "
	-program   int	      identifier for remote service
	-fsize     int        font size (in points if > 0, else pixels)
	-transport string     tcp OR udp (default is udp)
	-dt	   int	      poll time in msec (default is 50)
	-sort                 sort variables in display (default)
	-nosort               dont sort variables in display
	-rtc                  use old RTC server (default: SRPC)

* GUI options
	q	     quits ev
	<RightClick> on a variable invokes a strip chart widget which has
		     options:
			t	stop/start toggle
			s	slower sampling
			f	faster sampling
			m	magnify
			r	reduce
			q	quit
	new values can be typed into the data entry fields
}

proc show_usage {} {
        global  usage

        puts stdout $usage
        exit
}

###################### main ##################################

set host {}

if {[llength $argv] ==  0} {
	show_usage
}

set only ""

# handle command line switches
while {[llength $argv] > 0} {
switch -regexp -- [lindex $argv 0] {
^-poll     {    set poll_all 1; \
		set argv [lrange $argv 1 end] ; \
		}
^-only     {    set only [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-host -
^-server     {    set host [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-program     {    set prognum [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-fsize     {    set fontSize [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-transport     {    set transport [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-dt		{    set dt [lindex $argv 1]; \
		set argv [lrange $argv 2 end] ; \
		}
^-sort		{    set sort_vars 1; \
		set argv [lrange $argv 1 end] ; \
		}
^-nosort	{    set sort_vars 0; \
		set argv [lrange $argv 1 end] ; \
		}
^-rtc	        {    set useRTC 1; \
		set argv [lrange $argv 1 end] ; \
		}
^-help -
^-.* {	show_usage}
default	{break}
}
}

# load the RTC module
if {$useRTC == 1} {
        load $RTC/lib/rtc-[ exec platform ].so Rtc\
}

if {[llength $argv] > 0} {
set service [lindex $argv 0]

	if {[scan $service {%[^:]:%s} host service_name] == 1} {
		set service_name $host
		if {[info exists env(EV_HOST)]} {
			set host $env(EV_HOST)
		} else {
			set host {}
		}
	}
	if {[string match {[0-9]*} $service_name]} {
		set prognum $service_name
	} else {
		set prognum [find_service $mapFile $service_name]
		puts "mapping service $service_name -> program number $prognum"
	}
}

# connect to the server
if {$useRTC == 1} {
        if {$host == {}} {
	        # eval "rtc r -transport $transport -recreate  -program $prognum"
	        # dont use recreate unless its required
	        if {[catch {eval "rtc r -transport $transport -recreate -program $prognum"} errmsg] != 0} {
		        puts "Can't connect to server ($errmsg)"
		        exit
	        }
        } else {
	        # eval "rtc r -transport $transport -recreate -server $host -program $prognum"
	        if {[catch {eval "rtc r -recreate -transport $transport -server $host -program $prognum"} errmsg] != 0} {
		        puts "Can't connect to server <$host> ($errmsg)"
		        exit
	        }
        }
} else {
        if {[catch {set channelId [rtx_srpc_initconn $host $prognum]} errmsg] != 0} {
                puts "rtx_srpc_initconn ($host:$prognum) failed: $errmsg"
                exit
        }
}

set lfont [font create -family courier -weight bold -size $fontSize]
set font [font create -family courier  -size $fontSize]


# get the list of variables and sort them
if {$useRTC == 1} {
        if {[catch {set varlist [r call exportvar_list]} errmsg] != 0} {
		puts "No exportvar server <$host:$prognum> ($errmsg)"
		exit
        }
} else {
    global rtx_srpc_channels
        if {[catch {set varlist [rtx_srpc_call $channelId exportvar_list]} errmsg] != 0} {
		puts "No exportvar server <$host:$prognum> ($errmsg)"
	        exit
	}
}

puts "varlist: $varlist"
if {$sort_vars} {
	set varlist [lsort -command sortproc $varlist]
}

# if the -only flag is given then extract from the variable list only
# those variables names that match, using regexp.
if {$only != ""} {
	set varlist2 $varlist
	set varlist {}
	foreach v $varlist2 {
		if {[regexp $only $v] == 1} {
			lappend varlist $v
		}
	}
}

# figure width of the widest label
foreach el $varlist {
	if {[string length $el] > $lwidth} {
		set lwidth [string length $el]
	}
}
incr lwidth

# create a line in the table for each variable, and get initial value
foreach el $varlist {
	set v [exp2list $el]
	if {[llength $v] > 1} {
		# deal with the vector case
		set nels [lindex $v 1]
		set v [lindex $v 0]
		for {set i 0} {$i<$nels} {incr i} {
			if {$useRTC == 1} {
			        catch {set val [r call exportvar_var "$v\[$i\]"]} errmsg
			} else {
				catch {set val [rtx_srpc_call $channelId "exportvar_var $v\[$i\]"]} errmsg
			}
			varbox "$v\[$i\]" $val $v
		}
	} else {
		# deal with the scalar case
		if {$useRTC == 1} {
			catch {set val [r call exportvar_var $v]} errmsg
		} else {
			catch {set val [rtx_srpc_call $channelId "exportvar_var $v"]} errmsg
		}
		varbox $v $val $v
	}
}

trace variable VALS w tproc
button .refresh -text "Refresh" -command refresh -bg $bg -fg black 
	
pack .refresh -fill x

. configure -bg $bg

bind . q {exit}
if {[info exists service_name]} {
	wm title . "$host:$service_name"
} else {
	wm title . "$host:$prognum"
}


polling
