#!/bin/sh
# -*-Tcl-*-
# JLdL 23Nov07.
#
# Note that up to the first exec below this is a sh script; the
# _ argument "$0" will pass argv[0] to wish, while the argument
# _ "$@", following the "--", will pass to this wish script all
# _ the command-line arguments given to this shell script; note
# _ the trailing backslash on the comment line, just before the
# _ exec line; it is needed so that wish will not interpret the
# _ exec line, but rather treat it as a continued comment.
#
# The next line restarts execution using wish. \
    exec wish "$0" -- "$@" 
#
# This is a Tcl/Tk graphical front-end program, to be used for
# _ plotting complex functions w(z) as two-dimensional vector
# _ fields over the complex plane; it executes the external
# _ Fortran plotting program "plot_func"; a data file which
# _ is written by this program, and which is monitored, read
# _ and deleted by the external program, is used to transfer
# _ the necessary information from one program to the other.
#
# Define a variable with the name of the plotting program.
set plot_func ./plot_func
#
# Record the name this script was called with.
set name [exec basename $argv0]
#
# Define the name of the default configuration file.
set init_file .complex-functions.rc
#
# Try to use the Tcl/Tk package BWidget, which implements a set
# _ of extra Tcl/Tk widgets, but only if some version of it is
# _ available in the system; the name of the Debian package is
# _ simply bwidget; we are interested in the widget of the type
# _ "balloon", which can be used for implementing a bit of
# _ active help for the interactive user of the program.
#
# Initialize a flag for the presence of the package.
set bwidget 0
#
# Check whether there is a version of the package present.
if { [package versions BWidget] != "" } {
    #
    # If there is, raise the flag.
    set bwidget 1
    #
    # Load (require) the package.
    package require BWidget
    #
    # Make an alias called "help", for the balloon-type
    # _ help widget "DynamicHelp" within BWidget.
    interp alias {} help {} DynamicHelp::register
}
#
# Detect the language in use via the LANG environment variable,
# _ so we can write balloon help in that language.
set lang [array get env LANG]
#
# Reset the variable "lang" to a simpler value.
if { $lang == "LANG pt_BR" } {
    set lang pt_BR
} else {
    set lang ""
}
#
#----------------------------------------------------------------
# Section 01: user-controllable initialization.
#
# Read an initial configuration (rc) file for this program.
#
# The expression within square brackets below is the way to
# _ test the existence of a file; the command "source" reads
# _ the contents of the file as Tcl commands and loads them
# _ into the structure of the current program.
if { [file exists $init_file] } { source $init_file }
#
# Now set the variable "init_file" to the null string.
set init_file ""
#
#----------------------------------------------------------------
# Section 02: process command-line arguments.
#
# This should go right after the reading of the configuration
# _ file, so that we may override some of the settings in the 
# _ file with the corresponding command-line arguments.
#
# Initialize a flag for the initialization file.
set init_flag 0
#
# Process the command-line arguments.
foreach arg $argv {
    #
    # Detect options.
    if { [string range $arg 0 0] == "-" } {
	#
	# If we got here with an argument flag up, there is an error.
	if { $init_flag == 1 } {
	    #
	    # Write out an error message.
	    puts -nonewline "$name: ERROR: "
	    puts "option -f requires an argument"
	    #
	    # Exit in error.
	    exit 1
	    #
	}
	#
	# Now process the options.
	#
	# Use "switch" with the "--" option, so we can deal with
	# _ the option strings starting with "-".
	switch -- $arg {
	    #
	    # The "-" as the body means: use the next body.
	    -h -
	    --help {
		puts "usage: $name \[-f|--file <file>\]"
		puts "       -f: read and load the initialization file <file>"
		puts "       show complex functions as two-dimensional vector fields;"
		puts "       to get all the details run 'man $name'"
		#
		# Exit normally.
		exit 0
		#
	    }
	    -f -
	    --file {
		#
		# Raise the initialization file flag.
		set init_flag 1
		#
	    }
	    default {
		#
		# Write out an error message.
		puts -nonewline "$name: ERROR: "
		puts "unknown option $arg; try -h to get help"
		#
		# Exit in error.
		exit 1
		#
	    }
	}
    } else {
	#
	# Process non-option arguments.
	#
	# Get the arguments of options.
	if { $init_flag == 1 } {
	    #
	    # Set the initialization file.
	    set init_file $arg
	    #
	    # Lower the flag.
	    set init_flag 0
	    #
	} else {
	    #
	    # This script takes no arguments.
	    #
	    # Write out an error message.
	    puts -nonewline "$name: ERROR: "
	    puts "this program takes no arguments; try -h to get help"
	    #
	    # Exit in error.
	    exit 1
	    #
	}
    }
}
#
# If we got here with an argument flag up, there is an error.
if { $init_flag == 1 } {
    #
    # Write out an error message.
    puts -nonewline "$name: ERROR: "
    puts "option -f requires an argument"
    #
    # Exit in error.
    exit 1
    #
}
#----------------------------------------------------------------
# Section 03: read an additional initialization file.
#
# We only do this if an additional initialization file
# _ was entered via a command-line option.
if { $init_file != "" } {
    #
    # We require that additional file to exist.
    if { [file exists $init_file] } {
	source $init_file
    } else {
	#
	# Write out an error message.
	puts -nonewline "$name: ERROR: "
	puts "file $init_file not found"
	#
	# Exit in error.
	exit 1
	#
    }
}
#----------------------------------------------------------------
# Section 04: define the main window.
#
# Define the geometry of the main window; set variables with
# _ the values of its size and position; the geometry of the
# _ plotting window will also be derived from these values;
# _ the values are given in pixels, and only the variable
# _ "mx_pos" can be negative; do not use any "+" signs; note
# _ that a correction of 10 is needed in the case of negative
# _ "mx_pos", since the value -10 will already make the main
# _ window touch the right margin of the screen.
set mx_siz 160
set my_siz 665
#
# The expression within square brackets below is how one
# _ verifies whether a variable is already defined.
#
# In the case of the variables which may be defined in the rc
# _ file we must check whether or not they in fact were.
if { [namespace which -variable mx_pos] == "" } {
    #
    # This actually corresponds to "-100".
    set mx_pos -110
} else {
    #
    # Correct the value of "mx_pos" from the rc file.
    #
    # Note the expression within square brackets, used to
    # _ compare the variable "mx_pos" with "-0" as strings;
    # _ the idea is that using "0" for the variable results
    # _ in the main window touching the left margin of the
    # _ screen, while using "-0" results in the main window
    # _ touching the right margin of the screen.
    if { $mx_pos < 0 || [string compare $mx_pos -0] == 0 } {
	set mx_pos [expr $mx_pos - 10]
    }
}
if { [namespace which -variable my_pos] == "" } {
    set my_pos  100 }
#
# Define the standard X11 geometry string, taking into
# _ account the sign of the x position.
if { $mx_pos < 0 } {
    set w_geom ${mx_siz}x${my_siz}${mx_pos}+${my_pos}
} else {
    set w_geom ${mx_siz}x${my_siz}+${mx_pos}+${my_pos}
}
#
# Fix the geometry of the main window.
wm geometry . $w_geom
#
# Do not let the main window be resized.
wm minsize . $mx_siz $my_siz
wm maxsize . $mx_siz $my_siz
#
# Fix the title of the main window.
wm title . "PLOT"
#
#----------------------------------------------------------------
# Section 05: define a mapping procedure.
#
# Define a procedure to map complex function numbers onto the
# _ corresponding short and long description strings; note
# _ that this functions sets a global variable, and that
# _ hence it may have side effects.
#
# The procedure takes as input a variable "i_f" holding
# _ the number corresponding to the complex function.
proc the_func i_f {
    #
    # Connect the local variable "t_f" to the global
    # _ variable "t_func" in the main program.
    upvar t_func t_f
    #
    # Here is the list of supported functions; in each case
    # _ define the long string "t_f" and the short string
    # _ "l_f", to be used for the labels of the function
    # _ menu entries.
    switch $i_f {
	1 {
	    set l_f "A z^N"
	    set t_f "w(z) = A z^N" }
	2 {
	    set l_f "A exp(B z)"
	    set t_f "w(z) = A exp(B z)" }
	3 {
	    set l_f "A sin(B z)"
	    set t_f "w(z) = A sin(B z)" }
	4 {
	    set l_f "A cos(B z)"
	    set t_f "w(z) = A cos(B z)" }
	5 {
	    set l_f "A sqrt(z)"
	    set t_f "w(z) = A sqrt(z)" }
	6 {
	    set l_f "A ln(z + C)"
	    set t_f "w(z) = A ln(z + C)" }
	7 {
	    set l_f "A / (z^N - B)"
	    set t_f "w(z) = A / (z^N - B)" }
	8 {
	    set l_f "A sqrt(z^N - B)"
	    set t_f "w(z) = A sqrt(z^N - B)" }
	9 {
	    set l_f "A / sqrt(z^N - B)"
	    set t_f "w(z) = A / sqrt(z^N - B)" }
	10 {
	    set l_f "A exp(B / z^N)"
	    set t_f "w(z) = A exp(B / z^N)" }
	11 {
	    set l_f "A / sin(B / z^N)"
	    set t_f "w(z) = A / sin(B / z^N)" }
	default {
	    set l_f "NOT DEFINED"
	    set t_f "w(z) = NOT DEFINED" }
    }
    #
    # Return the short description string as
    # _the value of the procedure.
    return $l_f
}
#----------------------------------------------------------------
# Section 06: define and place a menu widget.
#
# Get the full path to the manual page; when it is done in this
# _ way, the command "man" will automatically implement the use
# _ of the LANG environment variable; besides this, having the
# _ full path we will be able to display the manual page window
# _ with more control over its geometry.
set man_page [exec man -w complex-functions]
#
# Define a global label for the main window, which is also the
# _ label for this menu widget, and which is also an execution
# _ button that opens a separate window with the manual page
# _ of this program.
button .title -text "COMPLEX FUNCTION" -relief flat -command \
    "exec zcat $man_page | groff -man -TX100 -P-geometry -P900x600 &"
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .title balloon "MOSTRAR A PGINA DE MANUAL"
    } else {
	help .title balloon "SHOW THE MANUAL PAGE"
    }
}
#
# Place the global label.
place .title -in . -x 5 -y 5 -width 150 -height 25
#
# Define a menu button to choose the complex function.
#
# Set the default value for the variable "i_func".
if { [namespace which -variable i_func] == "" } {
    set i_func 1
}
#
# Define the menu button.
menubutton .func -menu .func.menu -textvariable t_func \
    -indicatoron 1 -relief raised -direction flush
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .func balloon \
	    "ESCOLHER O TIPO DE FUNO COMPLEXA A MOSTRAR"
    } else {
	help .func balloon \
	    "CHOOSE THE TYPE OF COMPLEX FUNCTION TO SHOW"
    }
}
#
# Place the menu button.
place .func -in . -x 5 -y 30 -width 150 -height 25
#
# Define the menu for the menu button.
menu .func.menu -tearoff 0
#
# Define the entries for the menu.
.func.menu add command -label [the_func 1] \
    -command "set i_func 1 ; the_func 1"
.func.menu add command -label [the_func 2] \
    -command "set i_func 2 ; the_func 2"
.func.menu add command -label [the_func 3] \
    -command "set i_func 3 ; the_func 3"
.func.menu add command -label [the_func 4] \
    -command "set i_func 4 ; the_func 4"
.func.menu add command -label [the_func 5] \
    -command "set i_func 5 ; the_func 5"
.func.menu add command -label [the_func 6] \
    -command "set i_func 6 ; the_func 6"
.func.menu add command -label [the_func 7] \
    -command "set i_func 7 ; the_func 7"
.func.menu add command -label [the_func 8] \
    -command "set i_func 8 ; the_func 8"
.func.menu add command -label [the_func 9] \
    -command "set i_func 9 ; the_func 9"
.func.menu add command -label [the_func 10] \
    -command "set i_func 10 ; the_func 10"
.func.menu add command -label [the_func 11] \
    -command "set i_func 11 ; the_func 11"
#
# Only now, after the procedure "the_func" has been used to
# _ set all the labels of the menu entries above, set the
# _ default value for the text variable "t_func".
the_func $i_func
#
#----------------------------------------------------------------
# Section 07: define and place some entry widgets.
#
# Define a global label for the complex-constant entries.
label .const -text "Constants"
#
# Place the global label.
place .const -in . -x 5 -y 55 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .const balloon \
	    "DEFINIR OS VALORES DAS CONSTANTES COMPLEXAS"
    } else {
	help .const balloon \
	    "SET THE VALUES OF THE COMPLEX CONSTANTS"
    }
}
#
# Define a set of entry buttons, for the complex constants.
#
# Define labels for the complex-constant entries.
label .l_a_real -text "A ="
label .l_a_imag -text "+ i"
label .l_b_real -text "B ="
label .l_b_imag -text "+ i"
label .l_c_real -text "C ="
label .l_c_imag -text "+ i"
label .l_npower -text "N ="
#
# Place the labels.
place .l_a_real -in . -x  5 -y  80 -width 25 -height 25
place .l_a_imag -in . -x 80 -y  80 -width 25 -height 25
place .l_b_real -in . -x  5 -y 105 -width 25 -height 25
place .l_b_imag -in . -x 80 -y 105 -width 25 -height 25
place .l_c_real -in . -x  5 -y 130 -width 25 -height 25
place .l_c_imag -in . -x 80 -y 130 -width 25 -height 25
place .l_npower -in . -x  5 -y 155 -width 25 -height 25
#
# Set default values for the text variables.
if { [namespace which -variable a_real] == "" } {
    set a_real 0.5
}
if { [namespace which -variable a_imag] == "" } {
    set a_imag 0.0
}
if { [namespace which -variable b_real] == "" } {
    set b_real 1.0
}
if { [namespace which -variable b_imag] == "" } {
    set b_imag 0.0
}
if { [namespace which -variable c_real] == "" } {
    set c_real 0.0
}
if { [namespace which -variable c_imag] == "" } {
    set c_imag 0.0
}
if { [namespace which -variable npower] == "" } {
    set npower 1
}
#
# Define the complex-constant entries.
entry .v_a_real -background white -textvariable a_real
entry .v_a_imag -background white -textvariable a_imag
entry .v_b_real -background white -textvariable b_real
entry .v_b_imag -background white -textvariable b_imag
entry .v_c_real -background white -textvariable c_real
entry .v_c_imag -background white -textvariable c_imag
entry .v_npower -background white -textvariable npower
#
# Place the complex-constant entries.
place .v_a_real -in . -x  30 -y  80 -width 50 -height 25
place .v_a_imag -in . -x 105 -y  80 -width 50 -height 25
place .v_b_real -in . -x  30 -y 105 -width 50 -height 25
place .v_b_imag -in . -x 105 -y 105 -width 50 -height 25
place .v_c_real -in . -x  30 -y 130 -width 50 -height 25
place .v_c_imag -in . -x 105 -y 130 -width 50 -height 25
place .v_npower -in . -x  30 -y 155 -width 50 -height 25
#
#----------------------------------------------------------------
# Section 08: define and place some entry widgets.
#
# Define a global label for the range entries.
label .ranges -text "Plotting Ranges"
#
# Place the global label.
place .ranges -in . -x 5 -y 180 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .ranges balloon \
	    "DEFINIR OS INTERVALOS DE PLOTAGEM NO PLANO COMPLEXO"
    } else {
	help .ranges balloon \
	    "SET THE PLOTTING RANGES WITHIN THE COMPLEX PLANE"
    }
}
#
# Define a set of entry buttons, for the ranges.
#
# Define labels for the range entries.
label .l_xr_min -text "Re(z)_min:" -anchor w
label .l_xr_max -text "Re(z)_max:" -anchor w
label .l_yi_min -text "Im(z)_min:" -anchor w
label .l_yi_max -text "Im(z)_max:" -anchor w
#
# Place the labels.
place .l_xr_min -in . -x 5 -y 205 -width 75 -height 25
place .l_xr_max -in . -x 5 -y 230 -width 75 -height 25
place .l_yi_min -in . -x 5 -y 255 -width 75 -height 25
place .l_yi_max -in . -x 5 -y 280 -width 75 -height 25
#
# Set default values for the text variables.
if { [namespace which -variable xr_min] == "" } {
    set xr_min -2.0
}
if { [namespace which -variable xr_max] == "" } {
    set xr_max  2.0
}
if { [namespace which -variable yi_min] == "" } {
    set yi_min -2.0
}
if { [namespace which -variable yi_max] == "" } {
    set yi_max  2.0
}
#
# Define the range entries.
entry .v_xr_min -background white -textvariable xr_min
entry .v_xr_max -background white -textvariable xr_max
entry .v_yi_min -background white -textvariable yi_min
entry .v_yi_max -background white -textvariable yi_max
#
# Place the range entries.
place .v_xr_min -in . -x 80 -y 205 -width 75 -height 25
place .v_xr_max -in . -x 80 -y 230 -width 75 -height 25
place .v_yi_min -in . -x 80 -y 255 -width 75 -height 25
place .v_yi_max -in . -x 80 -y 280 -width 75 -height 25
#
#----------------------------------------------------------------
# Section 09: define and place some entry widgets.
#
# Define a global label for the axis entries.
label .axes -text "Axis Origins"
#
# Place the global label.
place .axes -in . -x 5 -y 305 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .axes balloon \
	    "DEFINIR AS POSIES DOS EIXOS REAL E IMAGINRIO"
    } else {
	help .axes balloon \
	    "SET THE POSITION OF THE REAL AND IMAGINARY AXES"
    }
}
#
# Define a set of entry buttons, for the axis positions.
#
# Define labels for the axis-position entries.
label .l_xp_org -text "Re(z)_orig:" -anchor w
label .l_yp_org -text "Im(z)_orig:" -anchor w
#
# Place the labels.
place .l_xp_org -in . -x 5 -y 330 -width 75 -height 25
place .l_yp_org -in . -x 5 -y 355 -width 75 -height 25
#
# Set default values for the text variables.
if { [namespace which -variable xp_org] == "" } {
    set xp_org 0.0
}
if { [namespace which -variable yp_org] == "" } {
    set yp_org 0.0
}
#
# Define the axis-position entries.
entry .v_xp_org -background white -textvariable xp_org
entry .v_yp_org -background white -textvariable yp_org
#
# Place the axis-position entries.
place .v_xp_org -in . -x 80 -y 330 -width 75 -height 25
place .v_yp_org -in . -x 80 -y 355 -width 75 -height 25
#
#----------------------------------------------------------------
# Section 10: define a mapping procedure.
#
# Define a procedure to map coordinate system numbers onto the
# _ corresponding short and long description strings; note
# _ that this functions sets a global variable, and that
# _ hence it may have side effects.
#
# The procedure takes as input a variable "i_c" holding
# _ the number corresponding to the coordinate system.
proc the_cscp i_c {
    #
    # Connect the local variable "t_c" to the global
    # _ variable "t_cscp" in the main program.
    upvar t_cscp t_c
    #
    # Here is the list of supported coordinate systems; in each
    # _ case define the long string "t_c" and the short string
    # _ "l_c", to be used for the labels of the coordinate
    # _ system menu entries.
    switch $i_c {
        0 {
	    set l_c "none"
	    set t_c "Grid: none" }
	1 {
	    set l_c "cartesian"
	    set t_c "Grid: cartesian" }
	2 {
	    set l_c "polar"
	    set t_c "Grid: polar" }
	3 {
	    set l_c "random"
	    set t_c "Grid: random" }
	default {
	    set l_c "NOT DEFINED"
	    set t_c "Grid: NOT DEFINED" }
    }
    #
    # Return the short description string as
    # _the value of the procedure.
    return $l_c
}
#----------------------------------------------------------------
# Section 11: define a mapping procedure.
#
# Define a procedure to map vector function numbers onto the
# _ corresponding short and long description strings; note
# _ that this functions sets a global variable, and that
# _ hence it may have side effects.
#
# The procedure takes as input a variable "i_v" holding
# _ the number corresponding to the vector function.
proc the_vect i_v {
    #
    # Connect the local variable "t_v" to the global
    # _ variable "t_vect" in the main program.
    upvar t_vect t_v
    #
    # Here is the list of supported vector functions; in each
    # _ case define the long string "t_v" and the short string
    # _ "l_v", to be used for the labels of the vector
    # _ function menu entries.
    switch $i_v {
        0 {
	    set l_v "(u, v)"
	    set t_v "Plot: (u, v)" }
	1 {
	    set l_v "(u,-v)"
	    set t_v "Plot: (u,-v)" }
	2 {
	    set l_v "(v, u)"
	    set t_v "Plot: (v, u)" }
	3 {
	    set l_v "(u, v)/|w|"
	    set t_v "Plot: (u, v)/|w|" }
	4 {
	    set l_v "(u,-v)/|w|"
	    set t_v "Plot: (u,-v)/|w|" }
	5 {
	    set l_v "(v, u)/|w|"
	    set t_v "Plot: (v, u)/|w|" }
	default {
	    set l_v "NOT DEFINED"
	    set t_v "Plot: NOT DEFINED" }
    }
    #
    # Return the short description string as
    # _the value of the procedure.
    return $l_v
}
#----------------------------------------------------------------
# Section 12: define and place some menu and entry widgets.
#
# Define a global label for the plotting-grid entries.
label .grid -text "Plotting Grid"
#
# Place the global label.
place .grid -in . -x 5 -y 380 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .grid balloon \
	    "DEFINIR AS CARACTERSTICAS DA REDE DE PLOTAGEM"
    } else {
	help .grid balloon \
	    "SET THE CHARACTERISTICS OF THE PLOTTING GRID"
    }
}
#
# Define a menu button to choose the grid coordinate system.
#
# Set the default value for the variable "i_cscp".
if { [namespace which -variable i_cscp] == "" } {
    set i_cscp 0
}
#
# Define the menu button.
menubutton .coord -menu .coord.menu -textvariable t_cscp \
    -indicatoron 1 -relief raised -direction flush
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .coord balloon \
	    "ESCOLHER O TIPO DE REDE PARA PLOTAR OS VETORES"
    } else {
	help .coord balloon \
	    "CHOOSE THE TYPE OF GRID FOR PLOTTING THE VECTORS"
    }
}
#
# Place the menu button.
place .coord -in . -x 5 -y 405 -width 150 -height 25
#
# Define the menu for the menu button.
menu .coord.menu -tearoff 0
#
# Define the entries for the menu.
.coord.menu add command -label [the_cscp 0] \
    -command "set i_cscp 0 ; the_cscp 0"
.coord.menu add command -label [the_cscp 1] \
    -command "set i_cscp 1 ; the_cscp 1"
.coord.menu add command -label [the_cscp 2] \
    -command "set i_cscp 2 ; the_cscp 2"
.coord.menu add command -label [the_cscp 3] \
    -command "set i_cscp 3 ; the_cscp 3"
#
# Only now, after the procedure "the_cscp" has been used to
# _ set all the labels of the menu entries above, set the
# _ default value for the text variable "t_cscp".
the_cscp $i_cscp
#
# Define a menu button to choose the vector function.
#
# Set the default value for the variable "i_vect".
if { [namespace which -variable i_vect] == "" } {
    set i_vect 0
}
#
# Define the menu button.
menubutton .vect -menu .vect.menu -textvariable t_vect \
    -indicatoron 1 -relief raised -direction flush
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .vect balloon \
	    "ESCOLHER O TIPO DE CAMPO VETORIAL A PLOTAR"
    } else {
	help .vect balloon \
	    "CHOOSE THE TYPE OF VECTOR FIELD TO PLOT"
    }
}
#
# Place the menu button.
place .vect -in . -x 5 -y 430 -width 150 -height 25
#
# Define the menu for the menu button.
menu .vect.menu -tearoff 0
#
# Define the entries for the menu.
.vect.menu add command -label [the_vect 0] \
    -command "set i_vect 0 ; the_vect 0"
.vect.menu add command -label [the_vect 1] \
    -command "set i_vect 1 ; the_vect 1"
.vect.menu add command -label [the_vect 2] \
    -command "set i_vect 2 ; the_vect 2"
.vect.menu add command -label [the_vect 3] \
    -command "set i_vect 3 ; the_vect 3"
.vect.menu add command -label [the_vect 4] \
    -command "set i_vect 4 ; the_vect 4"
.vect.menu add command -label [the_vect 5] \
    -command "set i_vect 5 ; the_vect 5"
#
# Only now, after the procedure "the_vect" has been used to
# _ set all the labels of the menu entries above, set the
# _ default value for the text variable "t_vect".
the_vect $i_vect
#
# Define an entry button for the grid spacing.
#
# Define a label for the grid-spacing entry.
label .l_gr_siz -text "Spacing:"
#
# Place the label.
place .l_gr_siz -in . -x 5 -y 455 -width 75 -height 25
#
# Set a default value for the text variable.
if { [namespace which -variable gr_siz] == "" } {
    set gr_siz 0.2
}
#
# Define the grid-spacing entry.
entry .v_gr_siz -background white -textvariable gr_siz
#
# Place the grid-spacing entry.
place .v_gr_siz -in . -x 80 -y 455 -width 75 -height 25
#
#----------------------------------------------------------------
# Section 13: define and place an entry widget.
#
# Define a global label for the singularity-handling entry.
label .sing -text "Singularity Handling"
#
# Place the global label.
place .sing -in . -x 5 -y 480 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .sing balloon \
	    "DEFINIR O TAMANHO DOS MARCADORES DE SINGULARIDADES E RAZES"
    } else {
	help .sing balloon \
	    "SET THE SIZE OF THE SINGULARITY AND ROOT MARKERS"
    }
}
#
# Define an entry button, for the singularity-marker radius.
#
# Define a label for the singularity-marker entry.
label .l_sm_rad -text "Mark radius:"
#
# Place the label.
place .l_sm_rad -in . -x 5 -y 505 -width 75 -height 25
#
# Set a default value for the text variable.
if { [namespace which -variable sm_rad] == "" } {
    set sm_rad 0.01
}
#
# Define the singularity-marker entry.
entry .v_sm_rad -background white -textvariable sm_rad
#
# Place the singularity-marker entries.
place .v_sm_rad -in . -x 80 -y 505 -width 75 -height 25
#
#----------------------------------------------------------------
# Section 14: define and place some entry widgets.
#
# Define a global label for the plotting-window entries.
label .wind -text "Plotting Window"
#
# Place the global label.
place .wind -in . -x 5 -y 530 -width 150 -height 25
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .wind balloon \
	    "DEFINIR O TAMANHO E A POSIO DA JANELA GRFICA"
    } else {
	help .wind balloon \
	    "SET THE SIZE AND POSITION OF THE PLOTTING WINDOW"
    }
}
#
# Define a set of entry buttons, for the window position.
#
# Define labels for the window-position entries.
label .l_ix_pos -text "X position:"
label .l_iy_pos -text "Y position:"
#
# Place the labels.
place .l_ix_pos -in . -x 5 -y 555 -width 75 -height 25
place .l_iy_pos -in . -x 5 -y 580 -width 75 -height 25
#
# Set default values for the text variables; this will in fact
# _ determine the position of the plotting window with respect
# _ to the position of the main window.
#
# This will acquire the width of the root window; we need it
# _ so we can pass it to the external plotting program.
set i_w_rw [exec xwininfo -root -shape \
		| grep Width \
		| tr -s \  \
		| cut -d\  -f3]
#
# Set the x position; this is for applications which understand
# _ negative X11 window positions in the usual way, that is, as
# _ distances from the right margin of the root window.
set ix_pos [expr $mx_pos \
		- $mx_siz]
#
# Set the y position.
set iy_pos $my_pos
#
# Define the window-position entries.
entry .v_ix_pos -background white -textvariable ix_pos
entry .v_iy_pos -background white -textvariable iy_pos
#
# Place the window-position entries.
place .v_ix_pos -in . -x 80 -y 555 -width 75 -height 25
place .v_iy_pos -in . -x 80 -y 580 -width 75 -height 25
#
# Define an entry button, for the overall window scale.
#
# Define a label for the window-scale entry.
label .l_iw_scl -text "Win. scale:"
#
# Place the label.
place .l_iw_scl -in . -x 5 -y 605 -width 75 -height 25
#
# Set a default value for the text variable.
if { [namespace which -variable iw_scl] == "" } {
    set iw_scl $my_siz
}
#
# Define the window-scale entry.
entry .v_iw_scl -background white -textvariable iw_scl
#
# Place the window-scale entry.
place .v_iw_scl -in . -x 80 -y 605 -width 75 -height 25
#
#----------------------------------------------------------------
# Section 15: define a procedure to write the data file.
#
# Define a procedure that writes the output data file; the
# _ arguments are the strings to be written into the file,
# _ one per line; please note that the first line written
# _ to this file should contain either a "0" or a "1", and
# _ is used as a flag to tell the plotting program to either
# _ stop (case "0") or continue running (case "1").
proc write_params args {
    #
    # Open the file, in create/overwrite mode; the variable
    # _ "cfp_fd" will hold the local file descriptor.
    set cfp_fd [open complex-functions-params.tmp w+]
    #
    # Loop over the arguments and write lines to the file.
    foreach arg $args {
	puts $cfp_fd $arg
    }
    #
    # Close the file.
    close $cfp_fd
}
#----------------------------------------------------------------
# Section 16: define and place some execution-button widgets.
#
# Define an execution button to exit; note that before exiting
# _ this program we overwrite the output file with a single
# _ "0", in order to stop the plotting program as well.
button .exit -text "EXIT" -command "write_params 0 ; exit"
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .exit balloon "TERMINAR O PROGRAMA"
    } else {
	help .exit balloon "TERMINATE THE PROGRAM"
    }
}
#
# Define a button to let the external plotting program loop
# _ and hence refresh the graph; set the event variable to
# _ any arbitrary value, for only the writing action to
# _ the variable matters, the value itself does not.
button .plot -text "PLOT" -command "set ievent 1"
#
# Add a help balloon to it, if BWidget is available.
if { $bwidget } {
    if { $lang == "pt_BR" } {
	help .plot balloon "ATUALIZAR A JANELA GRFICA"
    } else {
	help .plot balloon "REFRESH THE GRAPHICS WINDOW"
    }
}
#
# Place the execution buttons.
place .exit -in . -x  5 -y 635 -width 70 -height 25
place .plot -in . -x 85 -y 635 -width 70 -height 25
#
#----------------------------------------------------------------
# Section 17: write data file and start the external program.
#
# Write all the relevant data to the output file, for the
# _ first time; note the initial "1", which tells the
# _ plotting program to continue running.
write_params 1 \
    $i_func $a_real $a_imag $b_real $b_imag $c_real $c_imag \
    $npower $xr_min $xr_max $yi_min $yi_max $xp_org $yp_org \
    $i_cscp $i_vect $gr_siz $sm_rad $i_w_rw $ix_pos $iy_pos \
    $iw_scl
#
# Test for the existence of the plotting program; if it is there,
# _ then run it; otherwise, issue a warning, clean up and exit.
if { [file exists $plot_func] } {
    #
    # Open the plotting window; the plotting program below will read
    # _ and delete the file written above; the execution must be in
    # _ the background, so that the main window will remain active.
    exec $plot_func &
    #
} else {
    #
    # Delete the data-transfer file.
    exec rm -f complex-functions-params.tmp
    #
    # Write out an error message.
    puts -nonewline "$name: ERROR: "
    puts "cannot find executable $plot_func"
    #
    # Exit in error.
    exit 1
    #
}
#----------------------------------------------------------------
# Section 18: loop to keep passing data to the external program.
#
# The variable "ievent" is used for detecting changes within the
# _ main X11 event loop, in order to allow the refreshing of the
# _ output file, which is read by the plotting program; this is
# _ done within the infinite while loop that follows; it seems
# _ that the variable does not have to be initialized.
#
# Enter an infinite loop waiting for the variable "ievent"
# _ to be written to within the main X11 event loop.
while {1} {
    #
    # Monitor a variable in the main X11 event loop; any
    # _ writing action to this variable will fire this
    # _ loop, regardless of whether or not the value
    # _ of the variable is actually changed.
    vwait ievent
    #
    # Write all the relevant data to the output file, every
    # _ time there is write action to the variable; note
    # _ the initial "1", which tells the plotting
    # _ program to continue running.
    write_params 1 \
	$i_func $a_real $a_imag $b_real $b_imag $c_real $c_imag \
	$npower $xr_min $xr_max $yi_min $yi_max $xp_org $yp_org \
	$i_cscp $i_vect $gr_siz $sm_rad $i_w_rw $ix_pos $iy_pos \
	$iw_scl
}
