#!/usr/local/bin/wish -f
### $Id: omnimoni.tcl,v 0.22 1995/02/19 03:58:21 RainerMager Exp $
### $Author: RainerMager $
### OmniMoni verion:  $Revision: 0.22 $

### TODO:
### - allow any packing commands
### - change config -text to change variable

### This file was created with a tab size of 4 and a window width of 120 columns.
### I used a ;# for comments because a # alone following a set command fails.

### Notes:
### - Variables starting with capitals in the form "First" or "First_Second"
###   are global.
### - All of my functions are in the capitalization form of "firstSecond",
###   except some special functions like Debug.

#proc tkerror { err_msg } {														;# handle tkerrors
#	puts stderr "A Tk error occurred, program execution will continue."			;# show message
#	Debug 16 "\nThe actual Tk error was:\n$err_msg\n"							;# generate the debug message
#	flush stdout
#}																				;# END tkerror



proc doGlobals {} {																;# set some global variables
	global OM_title Debug Elapsed_Seconds Stripped_Rc Indent Update_Delta
	global OmniRcFile Indent_Chars OM_legal Active_Back Temp_Path Unpacked
	set revision {$Revision: 0.22 $}											;# parse the revision string
	set OM_title "OmniMoni v[lindex [string trim $revision {$}] 1]"				;# put it into the OmniMoni title
	set OM_legal1 "$OM_title, Copyright (C) 1995  Rainer Mager"					;# setup some legal strings
	set OM_legal2 "OmniMoni comes with ABSOLUTELY NO WARRANTY; for details use \"--legal\" option."
	set OM_legal "$OM_legal1\n$OM_legal2\n"										;# concat the above 2 together
	set Elapsed_Seconds 0														;# init seconds counter
	set Update_Delta 1000														;# the time between update checks
	set OmniRcFile "~/.omnirc"													;# the default config file name
	set Indent_Chars "    "														;# the default indention characters
	set Active_Back white														;# the default active menu background
	set Debug 0																	;# flag for debugging messages
	set Indent 0																;# the starting indention level
	set Unpacked(temp) temp														;# this forces Unpacked to...
	unset Unpacked(temp)														;# ...be an array
}																				;# END doGlobals



proc getENVs {} {																;# get and parse env vars
	global OmniRcFile Indent_Chars Update_Delta env
	set env_list {OMNIMONI_RC OMNIMONI_INDENT OMNIMONI_DELTA}					;# the list of possible vars
	foreach var $env_list {														;# go through them all
		if {[info exists env($var)]} {											;# if that one's set
			switch $var {
				OMNIMONI_RC {													;# if it's the RC file
					set OmniRcFile $env(OMNIMONI_RC)							;# set it
				}
				OMNIMONI_INDENT {												;# if it's the indents chars
					set Indent_Chars $env(OMNIMONI_INDENT)						;# set it
				}
				OMNIMONI_DELTA {												;# if its the update time
					set Update_Delta $env(OMNIMONI_DELTA)						;# set it
				}
			}																	;# end switch
		}																		;# end if this one exists
	}																			;# end foreach
}																				;# END getENVs



proc getCLAs {} {																;# get and parse command line args
	global argv0 argc argv Debug Update_Delta OmniRcFile Indent_Chars OM_title OM_legal
	if {$argc > 0} {															;# if there are any CLAs
		for {set count 0} {$count < $argc} {incr count} {						;# go through them all
			switch -- [lindex $argv $count] {
				--d {															;# if it is --d
					if {![catch "expr [lindex $argv [incr count]] + 1"]} {		;# if it's a number
						set Debug [lindex $argv $count]							;# set the Debug flag
					}
				}
				--i {															;# if it is --i
					set Indent_Chars [lindex $argv [incr count]]				;# set the indention characters
				}
				--r {															;# if it is --r
					set OmniRcFile [lindex $argv [incr count]]					;# set the new Rc file
				}
				--u {															;# if it is --u
					set Update_Delta [lindex $argv [incr count]]				;# set the new Update_Delta
				}
				--help {														;# if it is --help
					puts stderr $OM_legal
					puts stderr "Usage: $argv0 \[OPTION\]...\n"
					puts stderr " --d 0-7        the or'd debug level(s) out of possible 3                \[0\]"
					puts stderr " --i x          the characters used for indents during debugging      \[    \]"
					puts stderr " --r rcfile     load the file \"rcfile\" instead of the default    \[~/.omnirc\]"
					puts stderr " --u m_secs     the number of milliseconds between checks for updates \[1000\]"
					puts stderr "\n  -help         help for possible wish arguments"
					puts stderr " --help         show this help information"
					puts stderr " --legal        show legal notices about the program"
					exit
				}
				--legal {														;# if it is --legal
					puts stderr {
OmniMoni is a highly configurable, realtime, information monitoring system.
OmniMoni, Copyright (C) 1995  Rainer Mager

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., 675 Mass
Ave, Cambridge, MA 02139, USA.
					}
					exit														;# and exit
				}
				default {														;# of if it is anything else
					puts stderr $OM_legal
					puts stderr "Usage: $argv0 \[--d 0-7\] \[--i x\] \[--r rcfile\]"
					puts stderr "       \[--u m_secs\] \[-help\] \[--help\] \[--legal\]"
					exit
				}
			}																	;# end switch
		}																		;# end for each arg
	}																			;# end if there are args
}																				;# END getCLAs



proc configOptions { opt_list } {												;# config options in the rc file
	global OmniRcFile Update_Delta
	foreach opt $opt_list {														;# for all of the options
		Debug 1 "Configured option    >---< $opt\n"								;# generate debug message
		switch [lindex $opt 0] {
			"\#" -
			comment {															;# if it's a comment
			}
			OMNIMONI_DELTA {													;# if its the update time
				set Update_Delta [lindex $opt 1]								;# set it
			}
			default {															;# if it's anything else
				myCatch "option add [lindex $opt 0] [lindex $opt 1]" \
					"Error setting option \"[lindex $opt 0]\" to \"[lindex $opt 1]\".";# try to set a Tk option

			}
		}																		;# end switch
	}																			;# end foreach options
}																				;# END configOptions



proc Indent { indent } {														;# indent to stdout
	global Indent_Chars
	for {set temp 0} {$temp < $indent} {incr temp} {							;# for each indent level
		puts -nonewline $Indent_Chars											;# print the indent chars
	}
}																				;# END Indent



proc setDebug { mode } {														;# set debug mode
	global Debug
	set Debug [expr $Debug ^ 1<<[expr $mode - 1]]								;# calculate new debug mode
	puts "Debug mode set to $Debug."											;# print new debug mode
}																				;# END setDebug



proc Debug { level string } {													;# display debugging information
	global Debug Indent
	;# Debug levels are:
	;# 1 - displays what is being done while parsing the Rc and Stripped Rc files
	;# 2 - displays the stripped Rc file as it is stripped
	;# 4 - makes all labels static and displays the label code instead of the result in the widgets
	;# 8 - displays what widgets are Unpacked and Repacked
	;# 16 - displays actual Tk error messages
	if {$string != {}} {														;# if there is a string
		if {$Debug & $level} {													;# if Debug flag is set
			if {[set first_half [string first "->" $string]] > 0} {				;# if there is a -> in the string
				puts -nonewline [string range $string 0 $first_half]			;# print the first half
				puts -nonewline [format "%3d>" [incr Indent]]					;# print the pointer and number
				puts -nonewline [string range $string [expr $first_half + 2] end];# print the last half
			} elseif {[set first_half [string first "<-" $string]] > 0} {		;# elseif there is a <- in the string
				puts -nonewline [string range $string 0 $first_half]			;# print the first half
				puts -nonewline [format "%3d-" $Indent]							;# print the pointer and number
				puts -nonewline [string range $string [expr $first_half + 2] end];# print the last half
				incr Indent -1													;# decrement the Indent var
			} elseif {[string index $string 0] == "\{"} {						;# elseif there's a \{ in the string
				puts -nonewline [Indent $Indent]$string							;# call Indent to indent
				incr Indent														;# increment the Indent var
			} elseif {[string index $string 0] == "\}"} {						;# elseif there's a \} in the string
				puts -nonewline [Indent [incr Indent -1]]$string				;# call Indent to indent
			} else {															;# else nothing special in string
				puts -nonewline $string											;# display the string
			}																	;# end if what kind of debug message
		}																		;# end if debug flag is set
	} else {																	;# else not a string
		return [expr $Debug & $level]											;# return bit and of level
	}																			;# end if there is a string
}																				;# END Debug



proc loadRcFile { file_name } {													;# load the Rc file
	if {[file readable $file_name]} {											;# if file is readable
		set file [open $file_name]												;# open it
		while {![eof $file]} {													;# while not EOF
			append temp [read $file 1024]										;# add the next K to the var
		}
		close $file																;# close it
		return $temp															;# return the text of the file
	} else {																	;# else we can't open Rc
		puts stderr "Error, could not find or read the file \"$file_name\"!"	;# inform them of problem
		exit 1																	;# and exit
	}
}																				;# END loadRcFile



proc myCatch { command err_msg } {												;# error checking catch
	if {[catch $command out]} {													;# if there was an error
		Debug 16 "The actual error message was:\n\n$out\n\n"					;# print the actual 
		switch [string index $err_msg [expr [string length $err_msg] - 1]] {
			"!" {																;# if the message ended in "!"
				puts stderr $err_msg											;# display the message
				exit 1															;# then exit
			}
			":" {																;# if the message ended in ":"
				puts stderr "$err_msg  $out"									;# display the message
				exit 1															;# then exit
			}
		}																		;# end switch
		puts stderr $err_msg													;# disply the error message
	}																			;# end if there was an error
	return $out																	;# return the result
}																				;# END myCatch



proc checkList { list } {														;# check a list for syntax
	myCatch "llength {$list}" "Error in a section of the Rc file:"				;# getting a llength checks the list
}																				;# END checkList



proc demandUpdate { frame_name } {												;# demand an update on a dynamic label
	global Times Stripped_Rc
    while { $frame_name != {} } {												;# while we still have a string left
		set frame_name [string range $frame_name 0 [expr [string last . $frame_name] - 1]] ;# strip from last . on
		set Times($frame_name) 0												;# reset the Times for this one
	}																			;# end while
	updateSection $Stripped_Rc "" ""											;# recheck everything
}																				;# END demandUpdate



proc Unpack { widget_name } {													;# unpack a widget
	global Unpacked Toggle_Pack
	bind $widget_name <Button-2> {}												;# stop the bindings while I do this
	set Toggle_Pack($widget_name) 0												;# mark it asunpacked
	set pack_info [pack newinfo $widget_name]									;# find all the packing info
	set real_parent [string range $widget_name 0 [expr [string last . $widget_name] - 1]];# find its parent
	if {$real_parent == {}} {													;# if it is a top widget
		set parent .															;# set its parent to just a .
	} else {																	;# else not top widget
		set parent $real_parent													;# so take the discovered parent
	}																			;# end else not top widget
	set list_index [lsearch -exact [pack slaves $parent] $widget_name]			;# find its position in the pack list
	if {$list_index == 0} {														;# if it was the first widget
		set packed_after first$real_parent										;# it was packed after nothing
	} else {																	;# else it was not first widget
		set packed_after [lindex [pack slaves $parent] [expr $list_index - 1]]	;# find what it was packed after
	}
	foreach var [array names Unpacked] {										;# for each widget unpacked so far
		if {[lindex $Unpacked($var) 0] == $packed_after} {						;# was it unpacked after $packed_after
			set packed_after $var												;# then we should be unpacked after it
			break																;# done with the search
		}
	}																			;# end foreach
	set Unpacked($widget_name) "$packed_after $pack_info"						;# remember the side and who after
	pack forget $widget_name													;# remove it
	update																		;# update the change
	Debug 8 "Unpacked $widget_name\n"											;# generate debug message
	bind $widget_name <Button-2> "Unpack $widget_name"
}																				;# END Unpack



proc Repack { widget_name } {													;# repack an unpacked widget
	global Unpacked
	set pack_after [lindex $Unpacked($widget_name) 0]							;# find who to pack it after
	set pack_info [lrange $Unpacked($widget_name) 1 end]						;# find all the old packing info
	while {[info exists Unpacked($pack_after)]} {								;# check if after has been unpacked
		set pack_after [lindex $Unpacked($pack_after) 0]						;# then point to after's after
	}
	set parent [string range $widget_name 0 [expr [string last . $widget_name] - 1]];# find parent's name
	if {$pack_after == "first$parent"} {										;# if it needs to be packed first
		if {$parent == {}} {													;# if parent is a top widget
			set parent .														;# set parent to just a .
		}
		set pack_before [lindex [pack slaves $parent] 0]						;# find first in pack list
		if {$pack_before == {}} {												;# if there is no first
			eval "pack $widget_name -expand yes $pack_info"						;# pack as first
		} else {																;# else there is a first
			eval "pack $widget_name $pack_info -before $pack_before"			;# pack before first
		}
	} else {																	;# else there is someone to pack after
		eval "pack $widget_name $pack_info -after $pack_after"					;# pack after them
	}																			;# end if it needs to be packed first
	unset Unpacked($widget_name)												;# stop remember info
	Debug 8 "Repacked $widget_name\n"											;# generate debug message
}																				;# END Repack


	
proc TogglePack { widget_name } {												;# toggle Unpack Repack
	global Toggle_Pack
	if {$Toggle_Pack($widget_name)} {											;# if has been Unpacked
		Repack $widget_name														;# repack it
	} else {																	;# else not unpacked
		Unpack $widget_name														;# so unpack it
	}
}																				;# END TogglePack



proc ToggleGraph { frame_name id color } {										;# toggle unpack or repack a line
	global Toggle_Pack
	if {!$Toggle_Pack($frame_name.$id)} {										;# if was just unmarked
		Debug 8 "Unpacked $id\n"												;# generate the debug message
		$frame_name itemconfigure $id -fill ""									;# change the color to clear
	} else {																	;# else it was just remarked
		Debug 8 "Repacked $id\n"												;# generate the debug message
		$frame_name itemconfigure $id -fill $color								;# change the color to $color
	}																			;# end if it was just remarked
}																				;# END ToggleGraph



proc scrollCanvas { frame_name type direction width height history x y } {		;# scroll a canvas with the mouse
	switch $direction {
		up {																	;# if the direction's up
			$frame_name scan $type 0 $y											;# mark or dragto the new y position
			if {[$frame_name canvasy 0] > 0} {									;# if it dragged too far up
				$frame_name yview 0												;# reset it to max
				$frame_name scan mark 0 $y										;# reset the mark to where we are now
			}
			if {[$frame_name canvasy 0] < [expr $height - $history]} {			;# if it dragged too far down
				$frame_name yview [expr $height - $history]						;# reset to to max
				$frame_name scan mark 0 $y										;# reset the mark to where we are now
			}
		}
		down {																	;# if the direction's down
			$frame_name scan $type 0 $y											;# mark or dragto the new y position
			if {[$frame_name canvasy 0] < 0} {									;# if we dragged too far down
				$frame_name yview 0												;# reset it to max
				$frame_name scan mark 0 $y										;# reset the mark to where we are now
			}
			if {[$frame_name canvasy 0] > [expr $history - $height]} {			;# if we dragged too far down
				$frame_name yview [expr $history - $height]						;# reset it to max
				$frame_name scan mark 0 $y										;# reset the mark to where we are now
			}
		}
		left {																	;# if the direction's left
			$frame_name scan $type $x 0											;# mark or dragto the new x position
			if {[$frame_name canvasx 0] > 0} {									;# if we dragged too far
				$frame_name xview 0												;# reset it to max
				$frame_name scan mark $x 0										;# reset the mark to where we are now
			}
			if {[$frame_name canvasx 0] < [expr $width - $history]} {			;# if we dragged too far
				$frame_name xview [expr $width - $history]						;# reset it to max
				$frame_name scan mark $x 0										;# reset the mark to where we are now
			}
		}
		right {																	;# if the direction's right
			$frame_name scan $type $x 0											;# mark or dragto the new x position
			if {[$frame_name canvasx 0] < 0} {									;# if we dragged too far
				$frame_name xview 0												;# reset it to max
				$frame_name scan mark $x 0										;# reset the mark to where we are now
			}
			if {[$frame_name canvasx 0] > [expr $history - $width]} {			;# if we dragged too far
				$frame_name xview [expr $history - $width]						;# reset it to the max
				$frame_name scan mark $x 0										;# reset the mark to where we are now
			}
		}
	}																			;# end switch direction
}																				;# END scrollCanvas



proc reHash { frame_name height width direction history hash_value zero_color hash_color } {;# redraw hash marks
	global Graph_Maxes Graph_Mins Graph_Scale
	$frame_name.graph addtag below_hashes below hashes							;# find our who's just below the hashes
	$frame_name.graph delete hashes												;# delete the old hashes
	switch $direction {
		up -
		down {																	;# if it's up or down
			if {$direction == "up"} {											;# if it's up
				set start_y [expr $height - $history]							;# find the starting y
				set end_y $height												;# find the ending y
			} else {															;# else it's down
				set start_y 0													;# find the starting y
				set end_y $history												;# find the ending y
			}																	;# end if direction
			for {set hash $Graph_Mins($frame_name)} {$hash <= [expr $Graph_Maxes($frame_name) + $hash_value]} \
					{set hash [expr $hash + $hash_value]} {						;# for min val to max val
				set mark [expr -($hash - fmod($hash, $hash_value))]				;# find the val rounded to hash_val
				if {$mark != 0} {												;# if it's not the zero mark
					$frame_name.graph create line $mark $start_y $mark $end_y \
						-fill $hash_color -tags hashes							;# draw the new hash line
				}
			}																	;# end for all hashes
			$frame_name.graph create line 0 $start_y 0 $end_y -fill $zero_color -tags hashes;# draw the zero hash
		}
		left -
		right {																	;# if it's left or right
			if {$direction == "left"} {											;# if it's left
				set start_x [expr $width - $history]							;# find the starting x
				set end_x $width												;# find the ending x
			} else {															;# else it's right
				set start_x 0													;# find the starting x
				set end_x $history												;# find the ending x
			}																	;# end if direction
			for {set hash $Graph_Mins($frame_name)} {$hash <= [expr $Graph_Maxes($frame_name) + $hash_value]} \
					{set hash [expr $hash + $hash_value]} {						;# for min val to max val
				set mark [expr -($hash - fmod($hash, $hash_value))]				;# find the val rounded to hash_val
				if {$mark != 0} {												;# if it's not the zero mark
					$frame_name.graph create line $start_x $mark $end_x $mark \
						-fill $hash_color -tags hashes							;# draw the new hash line
				}
			}
			$frame_name.graph create line $start_x 0 $end_x 0 -fill $zero_color -tags hashes;# draw the zero hash
		}
	}																			;# end switch direction
	if {[$frame_name.graph gettags below_hashes] != ""} {						;# if there was anything below hashes
		$frame_name.graph raise hashes below_hashes								;# put these hashes above them
		$frame_name.graph dtag below_hashes										;# forget about the old position
	} else {																	;# else nothing below hashes
		$frame_name.graph raise hashes											;# put these on the bottom
	}																			;# end if anything below
}																				;# END reHash



proc createLabel {label_string label_name} {									;# create a message label widget
	global Last_Value
	checkList $label_string														;# check the syntax of the list
 	set label_text [lindex $label_string 0]										;# find the name of it
 	set label_side [lindex $label_string 1]										;# find the packing side
 	set label_args [lindex $label_string 2]										;# find the other arguments
	checkList $label_args														;# check the syntax of the list
	myCatch "message $label_name -justify center -aspect 5000" \
		"Error creating label $label_name!"										;# create the static message widget
	bind $label_name <Button-2> "Unpack $label_name"							;# mouse b3 unpack this label
	if {[string match {*[$%][0-9s]*} $label_text] && ![Debug 4 ""]} {			;# if it's dynamic !Debug 4
		if {[string match {*=*} $label_text]} {									;# if there's an = sign in it
			set Last_Value($label_name) {}										;# add it to the Last_Val array
		}
		set to_return 1															;# flag it as dynamic
		Debug 1 "Packed dynamic label >---< $label_name\n"						;# generate a debug message
		bind $label_name <Button-1> "demandUpdate $label_name"					;# mouse B1 demands update on label
 	} else {																	;# else not a "grab" string
		set to_return 0															;# flag it as static
		Debug 1 "Packed static label  >---< $label_name\n"						;# generate a debug message
	}
	foreach arg $label_args {													;# go through each additional arg
		myCatch "$label_name configure [lindex $arg 0] \{[lindex $arg 1]\}" \
	   		"Error configuring label $label_name."								;# configure it in
	}
	myCatch "pack $label_name -fill both -expand yes -side $label_side" \
		"Error packing label $label_name at side \"$label_side\"!"				;# pack the message
	myCatch "$label_name configure -text \{$label_text\}" \
		"Error configuring label $label_name."									;# give it text
 	return $to_return															;# return the flag
}																				;# END createLabel



proc parseSection { section frame_level } {										;# parse the next word in the rc file
	global Times Stripped_Rc Menu_Vars Toggle_Pack to_unpack_list Graph_Maxes Graph_Mins Graph_Scale
	switch -- [myCatch "lindex {$section} 0" "Error in Rc file:"] {
	    "\#" -
		comment {																;# if it starts with a comment
			Debug 1 "Comment\n"													;# generate a debug message
		}
		!group -
		group {																	;# if it is a group
			checkList $section													;# check syntax of list
			set frame_name $frame_level.[string tolower [lindex $section 1]]	;# create new frame_name
			set label_string [lindex $section 2]								;# find the label_string
			set command_string [lindex $section 3]								;# find the command string
			checkList $command_string											;# check the syntax of the list
			set refresh [lindex $section 4]										;# find the refresh rate
			set pack_side [lindex $section 5]									;# find the side to pack its children
			set extra_args [lindex $section 6]									;# find any extra config args
			checkList $extra_args												;# check the syntax of list
			set count 7															;# set pointer to next arg
			set l_length [myCatch "llength {$section}" "Error in Rc file:"]		;# find total size of this section
			set Times($frame_name) 0											;# init the refresh time
			if {[string index [lindex $section 0] 0] == "!"} {					;# if it starts with !
				lappend to_unpack_list $frame_name								;# remember it for later
			}
			if {$l_length > $count} {											;# if there are children
				Debug 1 "Entered group        -> $frame_name\n"					;# generate a debug message
				myCatch "expr $refresh + 1" "Error, update time must be a number for $frame_name!"
				myCatch "frame $frame_name" "Error creating group frame $frame_name!";# create the frame
				bind $frame_name <Button-2> "Unpack $frame_name"				;# mouse b3 unpack this label
				.pack$frame_level add cascade -label [lindex $section 1] \
					-menu .pack$frame_name										;# add the cascaded menu
				menu .pack$frame_name											;# create the next pulldown menu
				.pack$frame_name add checkbutton -label Frame -variable Toggle_Pack($frame_name) \
					-command "TogglePack $frame_name"							;# add the checkbutton
				set Toggle_Pack($frame_name) 1									;# initialize the checkbutton
				set future_label_string $label_string							;# init future_label_string
				if {$label_string != {}} {										;# if there's a label
					if {![createLabel $label_string $frame_name.label]} {		;# if it's static
						set future_label_string {}								;# set label to {} for future passes
					}
					.pack$frame_name add checkbutton -label [lindex $section 1] \
						-variable Toggle_Pack($frame_name.label) -command "TogglePack $frame_name.label"
					set Toggle_Pack($frame_name.label) 1						;# set default toggle value
				}																;# end if there's a label
				append Stripped_Rc "\{[string tolower [lrange $section 0 1]]"	;# add to the stripped Rc file
				append Stripped_Rc " {$future_label_string}"					;# add new label_string
				append Stripped_Rc " [lrange $section 3 [expr $count - 1]]\n"	;# add rest of section
				Debug 2 "\{[string tolower [lrange $section 0 1]]"				;# generate debug messages...
				Debug 2 " {$future_label_string}"								;# ...that mirror the above...
				Debug 2 " [lrange $section 3 [expr $count - 1]]\n"				;# ...appended information
				while {$count < $l_length} {									;# while there are still more of them
					set pack_list [parseSection [lindex $section $count] $frame_name] ;# recurse children
					foreach frame $pack_list {									;# go through all the returned frames
						myCatch "pack $frame -fill both -expand yes -side $pack_side" \
							"Error packing $frame on side \"$pack_side\"!"		;# pack them all
						Debug 1 "Packed group         <- $frame\n"				;# generate a debug message
						foreach arg $extra_args {								;# go through any extra args
																				;# configure them in
							set old_config [myCatch "$frame configure [lindex $arg 0]" \
								"Error configuring $frame with [lindex $arg 0] [lindex $arg 1]... skipping."]
							if {[info exists old_config] && \
								   [lindex $old_config 3] == [lindex $old_config 4]} {;# if was config'd explicitly
								myCatch "$frame configure [lindex $arg 0] [lindex $arg 1]" \
								   "Error configuring $frame with [lindex $arg 0] [lindex $arg 1]... skipping."
								unset old_config								;# forget this one
							}
						}
					}															;# end foreach returned frame
					incr count													;# go to next item in section
				}																;# end while there are more children
				append Stripped_Rc "\}\n"										;# finish appending to stripped Rc
				Debug 2 "\}\n"													;# generate mirror debug message
				return $frame_name												;# return this frame_name to parent
			} elseif {$label_string != {}} {									;# if there's a label
				if {[createLabel $label_string $frame_name]} {					;# if label's dynamic
					append Stripped_Rc "\{[string tolower [lrange $section 0 1]]";# add to the stripped Rc file
					append Stripped_Rc " {$label_string}"						;# add new label_string
					append Stripped_Rc " [lrange $section 3 [expr $count - 1]]\n\}\n";# add rest of section
					Debug 2 "\{[string tolower [lrange $section 0 1]]"			;# generate debug messages...
					Debug 2 " {$label_string}"									;# ...that mirror the above...
					Debug 2 " [lrange $section 3 [expr $count - 1]]\n\}\n"		;# ...appended information
				}																;# end if label's dynamic
				.pack$frame_level add checkbutton -label [lindex $section 1] -variable Toggle_Pack($frame_name) \
					-command "TogglePack $frame_name"							;# add the checkbutton
				set Toggle_Pack($frame_name) 1									;# initialize the checkbutton
				return $frame_name												;# return name for higher packing
			}																	;# end if there's a label
		}
		!graph -
		graph {																	;# if it's a graph
			;###### Inititialization stuff #####
			checkList $section													;# check the section for syntax
			set frame_name $frame_level.[string tolower [lindex $section 1]]	;# create new frame_name
			set label_string [lindex $section 2]								;# find the label_string
			set command_string [lindex $section 3]								;# find the command string
			checkList $command_string											;# check the syntax of the list
			set width [lindex $section 4]										;# find the width
			set height [lindex $section 5]										;# find the height
			set hash [lindex $section 6]										;# find the hash value
			set zero_color [lindex $section 7]									;# find the zero color
			set hash_color [lindex $section 8]									;# find the hash color
			foreach color "\"$zero_color\" \"$hash_color\"" {							;# check both colors
				if {$color != "" && [catch ". configure -bg \"$color\""]} {		;# if the color's not valid
					puts stderr "Error, color in $frame_name.title, $color, is invalid!";# print error message
					exit 1														;# exit everything
				}
			}																	;# end for both colors
			set refresh [lindex $section 9]										;# find the refresh rate
			set history [lindex $section 11]									;# find the history size
			myCatch "expr $width + $height + $hash + $refresh + $history" \
				"Error with options to $frame_name!"							;# check if they're all numbers
			set direction [lindex $section 10]									;# find the direction
			if {$direction != "left" && $direction != "right" && $direction != "up" && $direction != "down"} {
				puts stderr "Error in direction for $frame_name."				;# oops wrong direction
				exit 1															;# exit everything
			}																	;# end if direction is valid
			set extra_args [lindex $section 12]									;# find any extra config args
			checkList $extra_args												;# check the syntax of list
			set count 13														;# set pointer to next arg
			set l_length [myCatch "llength {$section}" "Error in Rc file:"]		;# find total size of this section
			;##### Create the frame #####
			set Times($frame_name) 0											;# init the refresh time
			if {[string index [lindex $section 0] 0] == "!"} {					;# if it starts with !
				lappend to_unpack_list $frame_name								;# remember it for later
			}
			myCatch "frame $frame_name" "Error creating graph frame $frame_name!";# create the frame
			bind $frame_name <Button-2> "Unpack $frame_name"					;# mouse b3 unpack this label
			.pack$frame_level add cascade -label [lindex $section 1] -menu .pack$frame_name;# add the cascaded menu
			menu .pack$frame_name												;# create the next pulldown menu
			.pack$frame_name add checkbutton -label Frame -variable Toggle_Pack($frame_name) \
				-command "TogglePack $frame_name"								;# add the checkbutton
			set Toggle_Pack($frame_name) 1										;# initialize the checkbutton
			set future_label_string $label_string								;# init future_label_string
			;##### Create the label #####
			if {$label_string != {}} {											;# if there's a label
				if {![createLabel $label_string $frame_name.label]} {			;# if it's static
					set future_label_string {}									;# set label to {} for future passes
				}
				.pack$frame_name add checkbutton -label [lindex $section 1] \
					-variable Toggle_Pack($frame_name.label) -command "TogglePack $frame_name.label"
				set Toggle_Pack($frame_name.label) 1							;# set default toggle to on
			}																	;# end if it's static
			;##### Create the canvas #####
			myCatch "canvas $frame_name.graph -width $width -height $height -scrollincrement 1" \
				"Error creating graph canvas $frame_name.graph!"				;# create the canvas
			bind $frame_name.graph <Button-1> \
				"[list scrollCanvas $frame_name.graph mark $direction $width $height $history %x %y]"
			bind $frame_name.graph <B1-Motion> \
				"[list scrollCanvas $frame_name.graph dragto $direction $width $height $history %x %y]"
			if {$direction == "left" || $direction == "right"} {				;# if it's horizontal
				bind $frame_name.graph <Double-1> "[list $frame_name.graph xview 0]";# set reset value
			} else {															;# else it's vertical
				bind $frame_name.graph <Double-1> "[list $frame_name.graph yview 0]";# set reset value
			}																	;# end if direction
			bind $frame_name.graph <Button-2> "Unpack $frame_name"				;# bind unpacking the canvas
			set Graph_Maxes($frame_name) 0										;# init the max value
			set Graph_Mins($frame_name) 0										;# init the min value
			set Graph_Scale($frame_name) "1.0 1.0"								;# init the scaled value
			foreach arg $extra_args {											;# for all extra args
				myCatch "$frame_name.graph configure [lindex $arg 0] [lindex $arg 1]" \
					"Error configuring graph, $frame_name.graph."				;# configure in extra arg
			}
			menu .pack$frame_name.graph											;# create the new menu
			.pack$frame_name add checkbutton -label Graph -variable Toggle_Pack($frame_name.graph) \
				-command "TogglePack $frame_name.graph"
			set Toggle_Pack($frame_name.graph) 1								;# init the toggle value to on
			pack $frame_name.graph												;# pack the canvas
			Debug 1 "Packed graph         >---< $frame_name\n"					;# generate a debug message
			append Stripped_Rc "\{[string tolower [lrange $section 0 1]]"		;# add to the stripped Rc file
			append Stripped_Rc " {$future_label_string}"						;# add new label_string
			append Stripped_Rc " [lrange $section 3 [expr $count - 1]]\n"		;# add rest of section
			Debug 2 "\{[string tolower [lrange $section 0 1]]"					;# generate debug messages...
			Debug 2 " {$future_label_string}"									;# ...that mirror the above...
			Debug 2 " [lrange $section 3 [expr $count - 1]]\n"					;# ...appended information
			;##### Check the lines to graph #####
			while {$count < $l_length} {										;# while there are still more of them
				set title [lindex [lindex $section $count] 0]					;# find the title of the line
				if {$title != "\#" && $title != "comment"} {					;# if it's not a comment
					set default 1												;# init it to on
					if {[string index $title 0] == "!"} {						;# if it starts with !
						set default 0											;# init it to off
					}
					set color [lindex [lindex $section $count] 2]				;# find the line's color
					if {[catch ". configure -bg \"$color\""]} {					;# if the color's not valid
						puts stderr "Error, color in $frame_name.title, $color, is invalid!";# print error message
						exit 1													;# exit everything
					}
					set type [lindex [lindex $section $count] 3]				;# find the type of the line
					if {$type != "solid" && $type != "lined"} {					;# if it's not valid
						puts stderr "Error, graph, $frame_name.$title, type must";# print error message
						puts stderr "be \"solid\" or \"lined\", not \"$type\"."	;# print more error message
						exit 1													;# exit everything
					}
					.pack$frame_name add checkbutton -label $title \
						-variable Toggle_Pack($frame_name.graph.$title) \
						-command "ToggleGraph \"$frame_name.graph\" \"$title\" \"$color\"";# add the checkbutton
					set Toggle_Pack($frame_name.graph.$title) $default			;# init to on or off
					append Stripped_Rc "\{[lindex $section $count]\}\n"			;# add line to stripped rc file
					Debug 2 "\{[lindex $section $count]\n"						;# generate debug message
					Debug 2 "\}\n"												;# generate more debug message
				}																;# end if not a comment for line
				incr count														;# go to next item in section
			}																	;# end while more lines
			append Stripped_Rc "\}\n"											;# finish appending to stripped Rc
			Debug 2 "\}\n"														;# generate mirror debug message
			pack $frame_name -fill both											;# pack the graph (don't expand)
		}
		configure {																;# if it's a configuration section
			configOptions [lrange $section 1 end]								;# pass the rest of the section
		}
		default {																;# it's not a ! or a group
			checkList $section													;# check the syntax of the list
			Debug 1 "Default\n"													;# generate a debug message
			if {$section == [lindex $section 0]} {								;# if this piece is a single piece
				puts stderr "Error, found a section beginning with \"$section\".";# print error message
			} else {															;# else it's a multi-piece
				set count 0														;# init item pointer to 0
				while {$count < [llength $section]} {							;# while there are more
					set temp [parseSection [lindex $section $count] $frame_level];# recurse the children
					foreach frame $temp {										;# for each child returned
						myCatch "pack $frame -fill both -expand yes" \
							"Error packing $frame!"								;# pack it
						Debug 1 "Packed default       <- $frame\n"				;# generate a debug message
					}
					append pack_list $temp										;# append to the pack_list
					incr count													;# go to next child
				}																;# end while there are more
				return $pack_list												;# return nothing
			}																	;# end else it's a multi-piece
		}
	}																			;# end switch
}																				;# END parseSection



proc evalSpecial { symbols output frame_name suffix } {							;# evaluate special symbols
	global Last_Value Times Elapsed_Seconds
	set label_name $frame_name$suffix											;# find the label name
	foreach piece $symbols {													;# for each part of the math equation
		switch -- [string index $piece 0] {
			"$" {																;# if it begins with a $
				if {[string index $piece 1] == "s"} {							;# if it is "$s"
					set piece [expr $Elapsed_Seconds - $Times($frame_name)]		;# find the last seconds delta
				} elseif {[string index $piece [expr [string length $piece] - 1]] == "\}"} {;# else if has a {...}
					set part [string trimleft [string range $piece 0 [expr [string first "\{" $piece] - 1]] "\$"]
					if {![catch "expr $part + 1"]} {							;# if it's a number
						set new_symbols [string trim [string range $piece [string first "\{" $piece] end] "\{\}"]
						set piece [evalSpecial $new_symbols [lindex $output $part] $frame_name $suffix]
					}
				} else {														;# else it's a normal $n
					set inx [string trimleft $piece \$]							;# find the index number
					if {![catch "expr $inx + 1"]} {								;# if it's a number
						set piece [lindex $output $inx]							;# find what the $number points to
					}
				}																;# end else it's a normal $n
			}
			"%" {																;# if it begins with a %
				if {[string index $piece 1] == "s"} {							;# if it is "%s"
					set piece [expr $Elapsed_Seconds - $Times($frame_name)]		;# find the last seconds delta
				} elseif {[string index $piece [expr [string length $piece] - 1]] == "\}"} {;# else if has a {...}
					set part [string trimleft [string range $piece 0 [expr [string first "\{" $piece] - 1]] "%"]
					if {![catch "expr $part + 1"]} {							;# if it's a number
						set new_symbols [string trim [string range $piece [string first "\{" $piece] end] "\{\}"]
						set piece [evalSpecial $new_symbols [lindex $output \
							[expr [llength $output] - ($part + 1)]] $frame_name $suffix]
					}
				} else {														;# else it's a normal %n
					set inx [string trimleft $piece %]							;# find the index number
					if {![catch "expr $inx + 1"]} {								;# if it's a number
						set piece [lindex $output [expr [llength $output] - ($inx + 1)]];# find field from the right
					}
				}																;# end else it's a normal %n
			}
			":" {																;# if it begins with a :
				set trim [string trimleft $piece ":"]							;# trim off the :
				set split [split [string trimleft $trim "\$%"] "\$%"]			;# split the list
				set num1 [lindex $split 0]										;# find the first number
				set num2 [lindex $split 1]										;# find the second number
				if {![catch "expr $num1 + 1"] && ![catch "expr $num2 + 1"]} {	;# if both give numbers
					if {[string index $trim 0] == "\$"} {						;# if it's a $ number
						set b $num1												;# find the beginning
					} elseif {[string index $trim 0] == "%"} {					;# else it's a %
						set b [expr [llength $output] - $num1]					;# find the beginning
					}
					if {[string first "\$" [string trimleft $trim "\$%"]] != -1} {;# if the second one's a $
						set e $num2												;# find the end
					} elseif {[string first "%" [string trimleft $trim "\$%"]] != -1} {;# else it's a %
						set e [expr [llength $output] - ($num2 + 1)]			;# find the end
					}
					if {[info exists b] && [info exists e]} {					;# if there was both a b and an e
						set piece [lrange $output $b $e]						;# return the range it gives
					}
				}																;# end if
			}
			"|" {																;# if it begins with a |
				set each_char [split $output {}]								;# split the output into characters
				set output {}													;# reinit output
				foreach char $each_char {										;# for each character
					if {$char != [string index $piece 1]} {						;# if its not the split char
						append output $char										;# put it in the list
					} else {													;# else it is the split char
						append output " "										;# append a space
					}
				}																;# end foreach char
				set piece {}													;# return {} for this piece
			}
			"=" {																;# if it begins with an =
				set trim [string trimleft $piece "="]							;# trim off the =
				set piece [evalSpecial $trim $Last_Value($label_name) $frame_name $suffix];# recurse to next piece
				set Last_Value($label_name) $output								;# remember old output
			}
		}																		;# end switch
		append math $piece														;# append it to the equation
	}																			;# end for each piece
	if {[catch "expr $math" result]} {											;# if parsing the equation fails
		set return_val $math													;# set the label_text to the string
	} else {																	;# else the parsing succeeded
		set return_val $result													;# set the label_text to the result
	}
	return $return_val															;# return the discovered value
}																				;# END evalSpecial



proc absSort { first second } {													;# compare absolute values
	set first [expr abs([lindex $first 0])]										;# find the first in a list
	set second [expr abs([lindex $second 0])]									;# find the second in a list
	if {$first == $second} {													;# if their equal
		return 0																;# return 0
	} elseif {$first > $second} {												;# if first is > second
		return 1																;# return positive
	} else {																	;# else must be < second
		return -1																;# return negative
	}																			;# end else is <
}																				;# END absSort



proc updateSection { section frame_level output } {								;# parse the next word in the rc file
	global Times Elapsed_Seconds Menu_Vars Unpacked Toggle_Pack
	global Graph_Maxes Graph_Mins Graph_Scale Graph_Last Graph_History
	switch -- [lindex $section 0] {
		!group -
		group {																	;# if it's a group
			set frame_name $frame_level.[lindex $section 1]						;# create the new frame_name
			set label_string [lindex $section 2]								;# find the label_string
			set command_string [lindex $section 3]								;# find the command_string
			set refresh [lindex $section 4]										;# find the refresh time
			set count 7															;# init where the children begin
			set l_length [llength $section]										;# find where total length
			set command_out $output												;# pass on $output if not regenerated
			if {$l_length > $count && ![info exists Unpacked($frame_name)]} {	;# if children and not unpacked
				Debug 1 "Enter  -> [lindex $section 1]\n"						;# generate a debug message
				if {$label_string != {}} {										;# if there is a label
					myCatch "$frame_name$suffix configure \
						-text \{[evalSpecial [lindex $label_string 0] $output $frame_name $suffix]\}" \
						"Error updating label text for $frame_name$suffix."		;# put the text in the message
				}
				if {$command_string != {} && ![Debug 4 ""]} {					;# if there is a command
					foreach command $command_string {							;# generate command output
						set pid [pid]											;# find the currect process id
						append command_out [myCatch "exec sh -c [list $command]" \
							"Error executing command:  $command!"] "\n"			;# execute the command
					}
				}																;# end if there is a command
				if {$Times($frame_name) < $Elapsed_Seconds} {					;# if it is update time for children
					set Times($frame_name) [expr $Elapsed_Seconds + $refresh]	;# set time for next refresh
					while {$count < $l_length} {								;# while there are more children
						updateSection [lindex $section $count] $frame_name $command_out ;# recurse through child
						incr count												;# go to next child
					}
				}																;# end if it's update time
				Debug 1 "Leave  <- [lindex $section 1]\n"						;# generate a debug message
			} elseif {$label_string != {}} {									;# else no children, but label
				if {[pack slaves $frame_name] == ""} {							;# if it's not a parent
					myCatch "$frame_name configure \
						-text \{[evalSpecial [lindex $label_string 0] $output $frame_name ""]\}" \
						"Error updating label text for $frame_name."			;# put the text in the message
				} else {														;# else it's a parent
					myCatch "$frame_name.label configure \
						-text \{[evalSpecial [lindex $label_string 0] $output $frame_name .label]\}" \
						"Error updating label text for $frame_name.label."		;# put the text in the message
				}
				Debug 1 "Update >---< [lindex $section 1]\n"					;# generate debug message
			}																	;# end else no children, but label
		}
		!graph -
		graph {																	;# if it's a graph command
			set frame_name $frame_level.[lindex $section 1]						;# find frame_name
			if {$Times($frame_name) < $Elapsed_Seconds} {						;# if it is update time
				set command_string [lindex $section 3]							;# find the command
				set width [expr double([lindex $section 4])]					;# find the width
				set height [expr double([lindex $section 5])]					;# find the height
				set hash_value [expr double([lindex $section 6])]				;# find the hash value
				set zero_color [lindex $section 7]								;# find the zero color
				set hash_color [lindex $section 8]								;# find the hash color
				set refresh [lindex $section 9]									;# find the refresh rate
				set direction [lindex $section 10]								;# find the direction
				set history [lindex $section 11]								;# find the history size
				set count 13													;# init count to next item
				set l_length [llength $section]									;# find total size of this section
				set Times($frame_name) [expr $Elapsed_Seconds + $refresh]		;# set time for next update
				Debug 1 "Graph  >---< $frame_name\n"							;# generate debug message
				set local_max 0													;# so far no max
				set local_min 0													;# so far no min
				if {![info exists Unpacked($frame_name.graph)]} {				;# if canvas not unpacked
					set old_max $Graph_Maxes($frame_name)						;# find old max
					set old_min $Graph_Mins($frame_name)						;# find old min
					eval "$frame_name.graph scale all 0 0 $Graph_Scale($frame_name)";# unscale from previous time
					while {$count < $l_length} {								;# while there are still more of them
						set current [lindex $section $count]					;# find current line
						set id [lindex $current 0]								;# find it's id
						set expression [lindex $current 1]						;# find it's expression
						set color [lindex $current 2]							;# find it's color
						if {!$Toggle_Pack($frame_name.graph.$id)} {				;# if it's unpacked
							set color ""										;# set color to clear
						}
						set type [lindex $current 3]							;# find it's type
						set value [evalSpecial $expression $output $frame_name .$id];# eval the expression
						if {![catch "expr $value + 1"]} {						;# if it's a number
							if {$value > $local_max} {							;# if it's a new local max
								set local_max $value							;# set max to it
							}
							if {$value < $local_min} {							;# if it's a new local min
								set local_min $value							;# set min to it
							}
							if {$value > $Graph_Maxes($frame_name)} {			;# it's a new global max
								set Graph_Maxes($frame_name) $value				;# set max to it
								reHash $frame_name $height $width $direction $history \
									$hash_value $zero_color $hash_color			;# and rehash given new value
							}
							if {$value < $Graph_Mins($frame_name)} {			;# it it's a new global min
								set Graph_Mins($frame_name) $value				;# set min to it
								reHash $frame_name $height $width $direction $history \
									$hash_value $zero_color $hash_color			;# and rehash given new value
							}
							if {![info exists Graph_Last] || \
								    ![info exists Graph_Last($frame_name.$id)]} {;# if there is a Graph_Last
								set Graph_Last($frame_name.$id) $value			;# find out what it was
							}
							switch $direction {
								up -
								down {											;# if it's up or down
									if {$direction == "up"} {					;# if it's up
										set y1 [expr $height - 1]				;# find the start y
										set y2_lined [expr $height - 2]			;# find the end y
										set ymove -1							;# find the dy
									} else {									;# else it's down
										set y1 0								;# find the start y
										set y2_lined 1							;# find the end y
										set ymove 1								;# find the dy
									}
									set x1 [expr -$value]						;# find start x
									if {$type == "solid"} {						;# if it's a solid line
										set y2 $y1								;# find end y
										set x2 0								;# find end x
									} else {									;# else it's lined line
										set y2 $y2_lined						;# find end y
										set x2 [expr -$Graph_Last($frame_name.$id)];# find end x
									}
									set Graph_Last($frame_name.$id) $value		;# remember this value
									set xmove 0									;# find dx
								}
								left -
								right {											;# if it's left or right
									if {$direction == "left"} {					;# if it's left
										set x1 [expr $width - 1]				;# find start x
										set x2_lined [expr $width - 2]			;# find end x
										set xmove -1							;# find dx
									} else {									;# else it's right
										set x1 0								;# find start x
										set x2_lined 1							;# find end x
										set xmove 1								;# find dx
									}
									set y1 [expr -$value]						;# find start y
									if {$type == "solid"} {						;# if it's solid line
										set x2 $x1								;# find end x
										set y2 0								;# find end y
									} else {									;# else it's lined
										set x2 $x2_lined						;# find end x
										set y2 [expr -$Graph_Last($frame_name.$id)];# find end y
									}
									set Graph_Last($frame_name.$id) $value		;# remember this value
									set ymove 0									;# find dy
								}
							}													;# end switch direction
							$frame_name.graph move $id $xmove $ymove			;# move all lines over
							set temp [$frame_name.graph create line $x1 $y1 $x2 $y2 -fill $color -tags $id]
							lappend local_sort($type) "$value $temp"			;# add to sorting array
							lappend local_group $temp							;# remember this line
						}														;# end if value's a number
					incr count													;# go to next item in section
					}															;# end while there are more
					if {[info exists local_sort(solid)]} {						;# if there were solid lines
						foreach item [lsort -command absSort $local_sort(solid)] {;# for each sorted one
							$frame_name.graph lower [lindex $item 1]			;# lower it to bottom
						}
					}															;# end if there were solid lines
					if {[info exists local_sort(lined)]} {						;# if there were lined lines
						foreach item [lsort -command absSort $local_sort(lined)] {;# fo each sorted one
							$frame_name.graph raise [lindex $item 1]			;# raise it to top
						}
					}															;# end if there were lined lines
					lappend Graph_History($frame_name) "$local_max $local_min \{$local_group\}";# remember extremes
					if {[llength $Graph_History($frame_name)] > $history} {		;# if we're over history
						set leaving_max [lindex [lindex $Graph_History($frame_name) 0] 0];# find who's leaving max
						set leaving_min [lindex [lindex $Graph_History($frame_name) 0] 1];# find who's leaving min
						set leaving_group [lindex [lindex $Graph_History($frame_name) 0] 2];# find id of who's leaving
						set Graph_History($frame_name) [lrange $Graph_History($frame_name) 1 end];# forget who leaving
						eval $frame_name.graph delete $leaving_group			;# delete everyone who's leaving
						set local_max 0											;# init local max
						set local_min 0											;# init local min
						if {$leaving_max >= $Graph_Maxes($frame_name) || \
								$leaving_min <= $Graph_Mins($frame_name)} {		;# if leaving was a max or min
							foreach old_one $Graph_History($frame_name) {		;# go through everyone still left
								if {[lindex $old_one 0] > $local_max} {			;# if it's a local max
									set local_max [lindex $old_one 0]			;# set max to it
								}
								if {[lindex $old_one 1] < $local_min} {			;# if it's a local min
									set local_min [lindex $old_one 1]			;# set min to it
								}
							}													;# end for everyone left
							set Graph_Maxes($frame_name) $local_max				;# set max to new max
							set Graph_Mins($frame_name) $local_min				;# set min to new min
						}														;# end if leaving was max or min
					}															;# end if we're over history
					switch $direction {
						up -
						down {													;# if it's up or down
							set yscale 1										;# set y scale to no change
							if {[set g_width [expr $Graph_Maxes($frame_name) - $Graph_Mins($frame_name)]] == 0} {
								set xscale 1									;# if no width then no change
							} else {											;# else if some width
								set xscale [expr ($width - 2) / $g_width]		;# find new x scale
								set Graph_Scale($frame_name) "[expr 1.0 / $xscale] 1.0";# remember new scale
							}													;# end else some width
							set xmove [expr int(($Graph_Maxes($frame_name) * -$xscale) - 1)];# find x move
							$frame_name.graph xview $xmove						;# do new move
						}
						left -
						right {													;# if it's left or right
							set xscale 1										;# set x scale to no change
							if {[set g_height [expr $Graph_Maxes($frame_name) - $Graph_Mins($frame_name)]] == 0} {
								set yscale 1									;# if no height then no change
							} else {											;# else there is height
								set yscale [expr ($height - 2) / $g_height]		;# find to y scale
								set Graph_Scale($frame_name) "1.0 [expr 1.0 / $yscale]";# remember new scale
							}													;# end else there is height
							set ymove [expr int(($Graph_Maxes($frame_name) * -$yscale) - 1)];# find y move
							$frame_name.graph yview $ymove						;# do new move
						}
					}															;# end switch direction
					$frame_name.graph scale all 0 0 $xscale $yscale				;# do new scaling
				}																;# end if canvas is not unpacked
			}																	;# end if update time
		}
		default {																;# if it's not a group
			set count 0															;# init where the children begin
			if {[llength [lindex $section 0]] == 1} {							;# if this piece is one piece
				puts stderr "Error, found a section beginning with [lindex $section 0].";# print error message
			} else {															;# else this is multi-piece
				while {$count < [llength $section]} {							;# while there are more
					updateSection [lindex $section $count] "" ""				;# update them
					incr count													;# go to next
				}
				return															;# return nothing
			}																	;# end else this is multi-piece
		}
	}																			;# end switch
}																				;# END updateSection



proc updateSeconds {} {															;# update the seconds count
	global Elapsed_Seconds Stripped_Rc Update_Delta
	set Elapsed_Seconds [expr $Elapsed_Seconds + ($Update_Delta / 1000.0)]		;# incr the seconds count
	Debug 1 "$Elapsed_Seconds Seconds\n"										;# generate a debug message
	updateSection $Stripped_Rc "" ""											;# update everything
	after $Update_Delta updateSeconds											;# wait update delta then update again
}																				;# END undateSeconds



proc initAll {} {																;# initializes everything
	global OM_title Colors OmniRcFile to_unpack_list OM_title OM_legal Stripped_Rc Update_Delta
	doGlobals																	;# do the global initialization stuff
	getENVs																		;# get and parse environmental vars
	getCLAs																		;# get and parse the CLAs
	wm title . $OM_title														;# title the window
	wm iconname . OmniMoni														;# title the icon
	wm protocol . WM_DELETE_WINDOW exit											;# tell it what to do if deleted
	message .intro -justify center -aspect 450 -text "$OM_legal\nPlease wait.  Setting up..."
	.intro configure -bg \#116 -fore \#c34										;# give it some color
	pack .intro																	;# pack the intro message
	update																		;# make sure it's displayed
	menu .pack
	set to_unpack_list {}														;# init the unpacking list
	parseSection [loadRcFile $OmniRcFile] ""									;# do first parse on .omnirc file
	foreach item $to_unpack_list {												;# go through the list
		Unpack $item															;# unpacking each
	}
	bind all <Button-3> ".pack post %X %Y"										;# post the packing menu
	bind Menu <Button-3> ".pack unpost"											;# if b3 unpost the menu
	bind all <Q> "exit"															;# bind exit to Q
	bind all <Z> "wm iconify ."													;# bind iconify to Z
	bind all <plus> {															;# bind to +
		set Update_Delta [expr $Update_Delta + 1000]							;# incr update delta by 1000
		puts "Update delta set to $Update_Delta."								;# tell them so
	}
	bind all <Control-plus> {													;# bind to ^+
		set Update_Delta [expr $Update_Delta + 60000]							;# incr update delta by 60000
		puts "Update delta set to $Update_Delta."								;# tell them so
	}
	bind all <minus> {															;# bin to -
		set Update_Delta [expr $Update_Delta - 1000]							;# decr update delta by 1000
		if {$Update_Delta < 1} {												;# if too small
			set Update_Delta 1													;# set to 1
		}
		puts "Update delta set to $Update_Delta."								;# tell them so
	}
	bind all <Control-minus> {													;# bind to ^-
		set Update_Delta [expr $Update_Delta - 60000]							;# decr update delta by 60000
		if {$Update_Delta < 1} {												;# if too small
			set Update_Delta 1													;# set to 1
		}
		puts "Update delta set to $Update_Delta."								;# tell them so
	}
	bind all <KeyPress-1> "setDebug %K"											;# bind setDebug to 1
	bind all <KeyPress-2> "setDebug %K"											;# bind setDebug to 2
	bind all <KeyPress-3> "setDebug %K"											;# bind setDebug to 3
	bind all <KeyPress-4> "setDebug %K"											;# bind setDebug to 4
	bind all <KeyPress-5> "setDebug %K"											;# bind setDebug to 5
	. config -bg \#116															;# set background color to something
	pack forget .intro															;# forget the intro message
	destroy .intro																;# destroy the intro message
	if {[info exists Stripped_Rc]} {											;# if there is a stripped rc
		updateSeconds															;# start seconds updating
	} else {																	;# else no stripped rc
		puts stderr "Error, nothing valid in configuration file!"				;# tell them problem
		exit 1																	;# exit everything
	}																			;# end else no stripped rc
}																				;# END initAll 



initAll																			;# call the procedure to start it all



### Emacs variables...
###
### Local Variables:
### mode:tcl
### tab-width:4
### comment-start: ";# "
### comment-start-skip: ";#+ *"
### comment-column:80
### minormode:line-number
### End:
