#
#  gpsman --- GPS Manager: a manager for GPS receiver data
#
#  Copyright (c) 2001 Miguel Filgueiras (mig@ncc.up.pt) / Universidade do Porto
#
#    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.
#
#  File: main.tcl
#  Last change:  20 November 2001
#
# Includes contributions by Brian Baulch (baulchb@onthenet.com.au)
#  marked "BSB contribution"
#

set VERSIONDATE(day) 20
set VERSIONDATE(month) 11
set VERSIONDATE(year) 2001

      # this test here prevents errors in the lang*.tcl files
if { [lsearch -exact "KM NAUTMILE STATMILE" $DISTUNIT] == -1 } {
    puts "Bad value in variable DISTUNIT: $DISTUNIT (see file gpsman.tcl)"
    exit 1
}

array set DSCALEFOR {
    KM             1
    sub,KM         0.001
    NAUTMILE       0.5399568
    sub,NAUTMILE   0.00016457916
    STATMILE       0.6213882
    sub,STATMILE   0.00018939432
}

array set ASCALEFOR {
    KM             1
    NAUTMILE       1
    STATMILE       2.5899881
}

      # MAPDISTS must have a single value of 1 (for the main distance unit)
      #  all values before taken to be in sub-unit
set MAPDISTSFOR(KM) [list "50 m" "100 m" "200 m" "500 m" "1 km" "2 km" \
	"4 km" "8 km" "16 km" "32 km" "64 km" "128 km" "512 km"]
set MAPDISTSFOR(NAUTMILE) [list "150 ft" "300 ft" "600 ft" "1200 ft" \
	"2400 ft" "1 n ml" "2 n ml" "4 n ml" "8 n ml" "16 n ml" "32 n ml" \
	"64 n ml" "128 n ml" "512 n ml"]
set MAPDISTSFOR(STATMILE) [list "150 ft" "300 ft" "600 ft" "1200 ft" \
	"2400 ft" "1 st ml" "2 st ml" "4 st ml" "8 st ml" "16 st ml" \
	"32 st ml" "64 st ml" "128 st ml" "512 st ml"]

      # default denotations for units; can be overriden by lang*.tcl
set MAPDISTUNITS(KM) [list km m]
set MAPDISTUNITS(NAUTMILE) [list "n ml" ft]
set MAPDISTUNITS(STATMILE) [list "st ml" ft]

set DSCALE $DSCALEFOR($DISTUNIT)
set SUBDSCALE $DSCALEFOR(sub,$DISTUNIT)
set ASCALE $ASCALEFOR($DISTUNIT)

set MAPDISTS $MAPDISTSFOR($DISTUNIT)

set KNOWNLANGS {engl fr deutsch it port}

# names of known languages in their own language
array set TXT {
    deutsch  Deutsch
    engl   English
    fr     Français
    it     Italiano
    port   Português
}

# other source files

  # source the English messages; other language files can omit translations
source [file join $SRCDIR langengl.tcl]

foreach f $SRCFILESBEGIN {
       source [file join $SRCDIR $f.tcl]
}

# other tests

         # year from which seconds are reckoned; MUST BE A LEAP YEAR < 1990
         #     dates with years less than YEAR0 will not be accepted
         #     NB: Garmin protocol dates start at 1990 January 1st
         #         Lowrance dates start at 1992 January 1st
set YEAR0 1988

if { $YEAR0%4!=0 || ($YEAR0%100==0 && $YEAR0%400!=0) } {
    GMMessage [format $MESS(notleap) $YEAR0]
    exit 1
}

if { int($TimeOffset) != $TimeOffset } {
    GMMessage $MESS(timeoffnotint)
    exit 1
}

set VERSION 5.4.1

set UDatums "" ; set UEllipsoids ""
set WindowStack ""

proc AboutInfo {w} {
    # create widgets for displaying information about GPSMan in window $w
    # all widgets will be inside frame $w.fr and are packed
    global Logo VERSION VERSIONDATE DateFormat COLOUR EPOSX EPOSY TXT

    frame $w.fr -relief flat -borderwidth 5 -bg $COLOUR(messbg)
    if { "$Logo" != "" } {
	label $w.fr.im -image $Logo -relief sunken
	pack $w.fr.im
    }
    set d [lindex [FormatDate $DateFormat $VERSIONDATE(year) \
	               $VERSIONDATE(month) $VERSIONDATE(day) 0 0 0] 0]
    label $w.fr.title -text "$TXT(GMtit) $VERSION / $d" -relief sunken
    message $w.fr.text -aspect 800 \
	    -text "Copyright (c) $VERSIONDATE(year) \
Miguel Filgueiras / DCC-FC & LIACC / Universidade do Porto\n\
$TXT(contrib) Brian Baulch (baulchb@onthenet.com.au)\n\
$TXT(contrib) Andreas Lange (andreas.lange@rhein-main.de)\n\
$TXT(contrib) Alessandro Palmas (alpalmas@tin.it)\n\n\
$TXT(errorsto) mig@ncc.up.pt"

    pack $w.fr -side top
    pack $w.fr.title $w.fr.text -side top -pady 5
    return
}

proc MakeDir {path} {
    # make directory under Unix(-like) system
    # take care of "~" replacement
    # return 0 on failure

    if { [string first ~ $path] == 0 } {
	set e [exec env]
	if { [set i [lsearch -glob $e HOME*]] == -1 } { return 0 }
	regsub HOME= [lindex $e $i] "" h
	set path ${h}[string range $path 1 end]
    }
    set a [exec mkdir $path]
    if { "$a" == "" } { return 1 }
    return 0
}

### images needed for start up
InitSymbolImages

if { [catch "set Logo [image create photo \
	-file [file join $SRCDIR gmicons gpsman-logo.gif]]"] } {
    set Logo ""
}

### if no user data directory force one being created
if { $InitDir } {
    if { "$tcl_platform(platform)" != "unix" || \
	    ! [GMConfirm [format $MESS(oktomkdir) $USERDIR]] || \
	    ! [MakeDir $USERDIR] } {
	GMMessage [format $MESS(createdir) $USERDIR]
	exit 1
    }
}

### if no preferences file force one being written
if { $InitOpts || [OutDatedOptions] } {
    if { [SetOptions] } {
	GMMessage $MESS(goingdown)
	exit 0
    }
    exit 1
}

### read source files

  # files setting receiver parameters
foreach f $SRCFILESREC {
    source [file join $SRCDIR $f.tcl]
}

  # files that depend on receiver trade mark
foreach f $SRCFILESFOR($MYGPS) {
    source [file join $SRCDIR $f.tcl]
}

  # conditional files
foreach p $SRCFILESCOND {
    if { [set [lindex $p 0]] } {
	source [file join $SRCDIR [lindex $p 1].tcl]
    }
}

  # files that may depend on the preferences file
foreach f $SRCFILESEND {
    source [file join $SRCDIR $f.tcl]
}

##### initialize interface

set NAMEWIDTH [expr $NAMELENGTH+2]
set COMMENTWIDTH [expr $COMMENTLENGTH+2]

set OBSWIDTH 40
set OBSHEIGHT 3

set DATEW(YYYYMMDD) 19
set DATEW(MMDDYYYY) 19
set DATEW(DDMMMYYYY) 20

set DATEWIDTH $DATEW($DateFormat)

set SUBDTUNIT $DLUNIT($DISTUNIT,subdist)

  # crosshair cursor centre in pixels from lower right corner
set CRHAIRx 5
set CRHAIRy 5

proc GlobalOptionsBindings {} {
    # change some of the default options and bindings of Tcl widgets
    global COLOUR

    option add *Frame.borderWidth 0
    option add *Frame.relief flat
    option add *Menubutton.relief raised
    option add *Menubutton.direction below
    option add *Menu.tearOff 0
    option add *Entry.exportSelection 1
    option add *Checkbutton.selectColor $COLOUR(check)
    option add *Radiobutton.selectColor $COLOUR(check)
    option add *Text.wrap word
    option add *Text.exportSelection 1

    bind Listbox <B1-Leave> { break }
    bind Listbox <Button-2> { break }
    bind Listbox <B2-Motion> { break }
    return
}

proc GMInit {} {
    # set up main window(s)
    global MAPHEIGHT MAPWIDTH LISTWIDTH LISTHEIGHT COLOUR MAPCOLOUR \
	    VERSION SRCDIR LPOSX LPOSY MPOSX MPOSY RPOSX RPOSY \
	    MAPSCALE MAPDISTS MAPSCLENGTH MWINDOWSCONF TYPES RECTYPES MYGPS \
	    Title Temp1 List ListInds EdWindow GPSLabel PositionFormat \
	    Datum GPSState Map MapBounds TXT MESS DISTUNIT DTUNIT DSCALE \
	    SUBDTUNIT SUBDSCALE DLUNIT MAPDISTUNITS MapScale \
	    MpW LsW RcW LsWTit MpWTit RcWTit WConf OVx OVy XCoord YCoord \
	    MapZone MapProjTitle MapTransfTitle MapPFormat MapRange \
	    MapWPMoving MapMakingRT MapLoading MapScInitVal MapImageItems \
	    GetDispl MAPKNOWNTRANSFS RECPROTOCOLS SYMBOLIMAGE RcMenu \
	    GPSProtocol GPSProtocolExt RealTimeLogAnim PVTState USvState

    GlobalOptionsBindings

    foreach type $TYPES {
	global GM${type}Show 
	set EdWindow($type) .gm$type ; set ListInds($type) ""
	set GM${type}Show 0
    }

    set Title "GPS Manager"
    set MapBounds "0 0 $MAPWIDTH $MAPHEIGHT"
    set MapRange(x) $MAPWIDTH ; set MapRange(y) $MAPHEIGHT
    set MapRange(x0) 0 ; set MapRange(y0) 0
    set OVx 0 ; set OVy 0 ; set XCoord "" ; set YCoord "" ; set MapZone ""
    set MapWPMoving -1 ; set MapMakingRT 0 ; set MapLoading 0
    set MapImageItems ""
    set GetDispl 0

    option add *Foreground $COLOUR(fg)
    option add *Background $COLOUR(bg)

    wm protocol . WM_DELETE_WINDOW { QuitNow }
    wm title . "$TXT(GMtit) $VERSION"
    bind . <Control-c> QuitNow

    set mt [Measure "GPS Manager"]

    set WConf(datastate) ""

    switch $MWINDOWSCONF {
	lists {
	    set gtit .title
	    wm geometry . +$LPOSX+$LPOSY
	    set MpW .mpw.fr ; set LsW .lsw.frls ; set RcW .rcw.fr
	    frame .lsw
	    frame $LsW

	    foreach w ".mpw .rcw" t "MpW RcW" p "M R" z "nameMap GPSrec" {
		set ${t}Tit "GPS Manager"
		toplevel $w
		wm protocol $w WM_DELETE_WINDOW "lower $w"
		wm title $w "GPS Manager: $TXT($z)"
		# because of some window managers do not iconify windows
		# wm geometry $w +[set ${p}POSX]+[set ${p}POSY]
		# wm iconify $w
		# ... and some other do not like this
		# wm geometry $w +-10000+-10000
		wm geometry $w +[set ${p}POSX]+[set ${p}POSY]
		lower $w .
		frame [set $t] -borderwidth 10
		button $w.tit -textvariable ${t}Tit -width $mt \
			-command "Raise . ; $w.tit configure -state normal"
		bind $w.tit <Enter> "set ${t}Tit {$TXT(mainwd)}"
		bind $w.tit <Leave> "set ${t}Tit {GPS Manager}"
	    }

	    frame .lsw.frmb -borderwidth 2
	    menubutton .lsw.frmb.dtitle -text Datum -menu .lsw.frmb.dtitle.m
	    menu .lsw.frmb.dtitle.m \
		 -postcommand "FillDatumMenu .lsw.frmb.dtitle.m ChangeMapDatum"
	    label .lsw.frmb.datum -textvariable Datum \
		    -width [Measure "Astro B4 Sorol Atoll"]

	    set t [Measure $TXT(GPSrec)]
	    frame .lsw.frmb.frb
	    frame .lsw.frmb.frb.sep -height 6 -bg $COLOUR(dialbg) -width $t
	    button .lsw.frmb.frb.load -text $TXT(load) \
		    -command { LoadFile Data ; \
		    .lsw.frmb.frb.load configure -state normal }
	    button .lsw.frmb.frb.save -text $TXT(save) -state disabled \
		    -command { SaveFile all Data ; \
		    .lsw.frmb.frb.save configure -state normal }
	    button .lsw.frmb.frb.search -text $TXT(search) -state disabled \
		    -command { Search ; \
		    .lsw.frmb.frb.search configure -state normal }
	    frame .lsw.frmb.frb.sep2 -height 6 -bg $COLOUR(dialbg) -width $t
	    set WConf(datastate) [list [list \
		    button [list .lsw.frmb.frb.save .lsw.frmb.frb.search]]]
	    button .lsw.frmb.mpw -text $TXT(nameMap) -width $t \
		    -command "ToggleWindow .mpw $MPOSX $MPOSY ; \
		    .lsw.frmb.mpw configure -state normal"
	    set RcMenu .lsw.frmb.rcw.m
	    menubutton .lsw.frmb.rcw -text $TXT(GPSrec) -width $t -menu $RcMenu
	    frame .lsw.frmb.sep -height 6 -bg $COLOUR(dialbg) -width $t
	    button .lsw.frmb.opt -text $TXT(options) -width $t \
		    -command { SetOptions ; \
	                       .lsw.frmb.opt configure -state normal }
	}
	map {
	    wm geometry . +$MPOSX+$MPOSY
	    set MpW .fr ; set LsW .lsw.frbl.frls ; set RcW .rcw.fr
	    frame $MpW -borderwidth 5

	    foreach w ".lsw .rcw" t "LsW RcW" p "L R" z "nameLists GPSrec" {
		set ${t}Tit "GPS Manager"
		toplevel $w
		wm protocol $w WM_DELETE_WINDOW "lower $w"
		wm title $w "GPS Manager: $TXT($z)"
		# because of some window managers do not iconify windows
		# wm geometry $w +[set ${p}POSX]+[set ${p}POSY]
		# wm iconify $w
		# ... and some others do not accept this
		# wm geometry $w +-10000+-10000
		wm geometry $w +[set ${p}POSX]+[set ${p}POSY]
		lower $w .
		button $w.tit -textvariable ${t}Tit -width $mt \
			-command "Raise . ; $w.tit configure -state normal"
		bind $w.tit <Enter> "set ${t}Tit {$TXT(mainwd)}"
		bind $w.tit <Leave> "set ${t}Tit {GPS Manager}"
	    }

	    frame .rcw.fr -borderwidth 10

	    frame .lsw.frbl
	    frame .lsw.frbl.frls -borderwidth 10
	    frame .lsw.frbl.frb
	    button .lsw.frbl.frb.load -text $TXT(load) \
		    -command { LoadFile Data ; \
		    .lsw.frbl.frb.load configure -state normal }
	    button .lsw.frbl.frb.save -text $TXT(save) -state disabled \
		    -command { SaveFile all Data ; \
		    .lsw.frbl.frb.save configure -state normal }
	    button .lsw.frbl.frb.search -text $TXT(search) -state disabled \
		    -command { Search ; \
		    .lsw.frbl.frb.search configure -state normal }
	}
    }

    frame $MpW.frm
    frame $MpW.frm.frmap1
    set Map $MpW.frm.frmap1.map
    canvas $Map -borderwidth 5 -relief groove -confine true \
	    -scrollregion $MapBounds \
	    -width $MAPWIDTH -height $MAPHEIGHT \
	    -xscrollincrement 1 -yscrollincrement 1 \
	    -xscrollcommand "$MpW.frm.frmap2.mhscr set" \
	    -yscrollcommand "$MpW.frm.frmap1.mvscr set"
    scrollbar $MpW.frm.frmap1.mvscr -command "ScrollMap y"

    frame $MpW.frm.frmap2
    scrollbar $MpW.frm.frmap2.mhscr -command "ScrollMap x" -orient horizontal
    canvas $MpW.frm.frmap2.fill -height 1 -relief flat \
	    -width [expr [$MpW.frm.frmap1.mvscr cget -width]+4]

    frame $MpW.frm.frmap3
    canvas $MpW.frm.frmap3.cv -width $MAPSCLENGTH -height 15 -relief flat
    label $MpW.frm.frmap3.cv.val -width 10 -font fixed
    $MpW.frm.frmap3.cv create line 0 7.5 $MAPSCLENGTH 7.5 -arrow both \
	    -fill $MAPCOLOUR(mapsel)
    $MpW.frm.frmap3.cv create line 1 0 1 15 -fill $MAPCOLOUR(mapsel)
    set l [expr $MAPSCLENGTH-1]
    $MpW.frm.frmap3.cv create line $l 0 $l 15 -fill $MAPCOLOUR(mapsel)
    $MpW.frm.frmap3.cv create window [expr $MAPSCLENGTH/2] 7.5 \
	    -window $MpW.frm.frmap3.cv.val
    menubutton $MpW.frm.frmap3.mn -text $TXT(change) -menu $MpW.frm.frmap3.mn.m
    menu $MpW.frm.frmap3.mn.m
    set nf 1 ; set nmd ""
    set u $SUBDTUNIT ; set f $SUBDSCALE ; set ims [lindex $MAPSCALE 0]
    set imsu [lreplace $MAPSCALE 0 0]
    # map scale in meters/pixel
    if { "$imsu" == "[lindex $MAPDISTUNITS($DISTUNIT) 0]" } {
	set ds $DSCALE
    } else { set ds $SUBDSCALE }
    set MapScale [expr $ims*$ds*1000.0/$MAPSCLENGTH]
    foreach d $MAPDISTS {
	set v [lindex $d 0]
	if { $v == 1 } {
	    set u $DTUNIT ; set f 1
	}
	set ad [expr $v*$f] ; set t "$v $u"
	lappend nmd $t
	$MpW.frm.frmap3.mn.m add radiobutton -label $t \
		-selectcolor $COLOUR(check) -command "MapScaleSet $ad"
	if { $v == $ims } {
	    # cannot call MapScaleSet yet!
	    set nf 0 ; set MapScInitVal $ad
	    $MpW.frm.frmap3.cv.val configure -text $t
	}
    }
    if { $nf } {
	if { "$imsu" != "$DTUNIT" && "$imsu" != "$SUBDTUNIT" && \
		[lsearch -exact $MAPDISTUNITS($DISTUNIT) $imsu] == -1 } {
	    GMMessage "$MESS(baddistunit): $imsu"
	} else {
	    GMMessage "$MESS(badscale): $MAPSCALE"
	}
	set MapScInitVal 1
	$MpW.frm.frmap3.cv.val configure -text "1 $DTUNIT"
    }
    set MAPDISTS $nmd

    frame $MpW.frm.frmap3.sep -height 6 -bg $COLOUR(dialbg) -width 5
    foreach op "loc disp clr" lb "locate displ clear" exc "GR _ GR" \
	    fp "FillMappedMenus FillDispMenus FillMappedMenus" \
	    cm "Locate {} UnMap" {
	set mn $MpW.frm.frmap3.$op.m
	menubutton $MpW.frm.frmap3.$op -text $TXT($lb) -menu $mn \
		-state disabled
	menu $mn
	foreach wh $TYPES {
	    if { "$wh" != "$exc" } {
		set m $mn.w$wh
		$mn add cascade -label $TXT(name$wh) -menu $m
		menu $m
	    }
	}
	if { "$cm" != "" } {
	    bind $MpW.frm.frmap3.$op <Button-1> \
		    "$fp $MpW.frm.frmap3.$op.m $cm"
	} else {
	    bind $MpW.frm.frmap3.$op <Button-1> \
		    "$fp $MpW.frm.frmap3.$op.m"
	}
    }
    set WConf(mapstate) "$MpW.frm.frmap3.loc $MpW.frm.frmap3.clr"
    set WConf(mapstatetype) "menubutton menubutton"
    lappend WConf(datastate) [list menubutton $MpW.frm.frmap3.disp]

    frame $MpW.frmi

    switch $MWINDOWSCONF {
	lists {
	    set WConf(mapdatum) "$MpW.frmi.frcoords.dtitle \
		    $MpW.frmi.frcoords.ptitle"
	    lappend WConf(mapstate) $MpW.frmi.frmbs.msave \
		    $MpW.frmi.frmbs.mclear
	    lappend WConf(mapstatetype) button button
	    set WConf(mapstateback) $MpW.frmi.frmbs.mback.m
	    set WConf(additemstate) ""

	    set bl [Measure $TXT(backgrnd)]
	    frame $MpW.frmi.frmbs -borderwidth 2
	    label $MpW.frmi.frmbs.mtitle -text $TXT(map)
	    # assuming for each $grid, $grid==$TXT($grid)
	    menubutton $MpW.frmi.frmbs.grid -textvariable MapPFormat \
		    -width 8 -menu $MpW.frmi.frmbs.grid.m
	    menu $MpW.frmi.frmbs.grid.m
	    bind $MpW.frmi.frmbs.grid <Button-1> \
		    "FillPFormtMenu $MpW.frmi.frmbs.grid.m ChangeMapPFormat"

	    label $MpW.frmi.frmbs.zone -textvariable MapZone -width 4 \
		    -relief sunken
	    label $MpW.frmi.frmbs.xcoord -textvariable XCoord -width 11 \
		    -relief sunken
	    label $MpW.frmi.frmbs.ycoord -textvariable YCoord -width 11 \
		    -relief sunken
	    button $MpW.frmi.frmbs.msave -text "$TXT(saveto) PS" \
		    -command "SaveMap ; \
		              $MpW.frmi.frmbs.msave configure -state normal" \
		    -state disabled -width $bl
	    menubutton $MpW.frmi.frmbs.mback -text $TXT(backgrnd) -width $bl \
		    -menu $MpW.frmi.frmbs.mback.m
	    menu $MpW.frmi.frmbs.mback.m
	    # order of entries used in file map.tcl
	    foreach f [list $TXT(loadmback) $TXT(savemback) $TXT(chgmback) \
		            $TXT(clearmback)] \
		    c "LoadMapBack SaveMapBack ChangeMapBack ClearMapBack" \
		    s "normal disabled disabled disabled" {
		$MpW.frmi.frmbs.mback.m add command -label $f \
			-command $c -state $s
	    }
	    button $MpW.frmi.frmbs.mclear -text $TXT(clear) -state disabled \
		    -width $bl \
		    -command "ClearMap ; \
		    $MpW.frmi.frmbs.mclear configure -state normal"
	    frame $MpW.frmi.frcoords -borderwidth 2
	    menubutton $MpW.frmi.frcoords.dtitle -text Datum \
		    -menu $MpW.frmi.frcoords.dtitle.m
	    set dm $MpW.frmi.frcoords.dtitle.m
	    menu $dm -postcommand "FillDatumMenu $dm ChangeMapDatum"
	    label $MpW.frmi.frcoords.datum -textvariable Datum \
		    -width [Measure "Astro B4 Sorol Atoll"]
	    menubutton $MpW.frmi.frcoords.ptitle -text $TXT(projection) \
		    -menu $MpW.frmi.frcoords.ptitle.m
	    menu $MpW.frmi.frcoords.ptitle.m \
		    -postcommand "FillProjsMenu $MpW.frmi.frcoords.ptitle.m \
		                   MAPKNOWNPROJS MapProjectionIs"
	    label $MpW.frmi.frcoords.proj -textvariable MapProjTitle \
		    -width 20
	    label $MpW.frmi.frcoords.ttitle -relief raised -text $TXT(transf)
	    label $MpW.frmi.frcoords.transf -textvariable MapTransfTitle \
		     -width 20

	    set defsmnbt $MpW.frmi.frcoords.udefs
	}
	map {
	    frame $MpW.frm.frmap0 -borderwidth 2
	    set fr0 $MpW.frm.frmap0
	    set gtit $fr0.title

	    menubutton $fr0.db -text $TXT(nameData) -width $mt -menu $fr0.db.m
	    menu $fr0.db.m
	    $fr0.db.m add command -label "$TXT(load) ..." \
		    -command "LoadFile Data"
	    $fr0.db.m add command -label "$TXT(save) ..." \
		    -command "SaveFile all Data" -state disabled
	    $fr0.db.m add command -label $TXT(nameLists) \
		    -command "ToggleWindow .lsw $LPOSX $LPOSY"
	    $fr0.db.m add command -label "$TXT(search) ..." -command Search \
		    -state disabled
	    foreach i $TYPES {
		set m $fr0.db.m.e$i
		$fr0.db.m add cascade -label $TXT(name$i) -menu $m
		menu $m
		switch $i {
		    GR {
			set tits [list $TXT(newGR) $TXT(clearall) \
			       "$TXT(loadgrels) ..." $TXT(count)]
			set coms "NewItem ClearList LoadGREls Count"
			set sts "normal disabled disabled normal"
			set im 3
			set imp importgrels ; set impst disabled
			set imppr ImportGREls ; set fmts "GPStrans Fugawi"
			set acts "save saveels exportels"
			set prs "SaveFile SaveGREls ExportGREls"
		    }
		    WP {
			set tits [list $TXT(new$i) $TXT(clearall) $TXT(count)]
			set coms "NewItem ClearList Count"
			set sts "normal disabled normal"
			set im 2
			set imp import ; set impst normal
			set imppr ImportFile ; set fmts "GPStrans Fugawi"
			set acts "save export" ; set prs "SaveFile ExportFile"
		    }
		    default {
			set tits [list $TXT(new$i) $TXT(clearall) $TXT(count)]
			set coms "NewItem ClearList Count"
			set sts "normal disabled normal"
			set im 2
			set imp import ; set impst normal
			set imppr ImportFile ; set fmts "GPStrans"
			set acts "save export" ; set prs "SaveFile ExportFile"
		    }
		}
		foreach l $tits c $coms s $sts {
		    $m add command -label $l -command "$c $i" -state $s
		}
		foreach ip $imp s $impst p $imppr {
		    $m insert $im cascade -label "$TXT($ip) ..." \
			    -menu $m.$ip -state $s
		    menu $m.$ip
		    foreach fmt $fmts {
			$m.$ip add command -label $fmt -command "$p $i $fmt"
		    }
		    incr im
		}
		foreach a $acts p $prs {
		    $m insert $im cascade -label "$TXT($a) ..." \
			    -menu $m.$a -state disabled
		    menu $m.$a
		    $m.$a add command -label $TXT(all) -command "$p all $i"
		    $m.$a add command -label "$TXT(select) ..." \
			    -command "$p select $i"
		    incr im
		}
	    }

	    set RcMenu $fr0.rcw.m
	    menubutton $fr0.rcw -text $TXT(GPSrec) -width $mt -menu $RcMenu
	    menubutton $fr0.map -text $TXT(nameMap) -width $mt -menu $fr0.map.m
	    menu $fr0.map.m
	    # order of entries used in file map.tcl
	    $fr0.map.m add command -label "$TXT(saveto) PS" -command SaveMap \
		    -state disabled
	    $fr0.map.m add cascade -label $TXT(backgrnd) -menu $fr0.map.mback
	    menu $fr0.map.mback
	    foreach f [list $TXT(loadmback) $TXT(savemback) $TXT(chgmback) \
		            $TXT(clearmback)] \
		    c "LoadMapBack SaveMapBack ChangeMapBack ClearMapBack" \
		    s "normal disabled disabled disabled" {
		$fr0.map.mback add command -label $f -command $c -state $s
	    }
	    $fr0.map.m add command -label $TXT(clear) -command ClearMap \
		    -state disabled

	    set defsmnbt $fr0.udefs

	    button $fr0.options -text $TXT(options) -width $mt \
		    -command "SetOptions ; \
		    $fr0.options configure -state normal"

	    frame $MpW.frm.frmap4 -borderwidth 2
	    set fr4 $MpW.frm.frmap4

	    menubutton $fr4.datum -textvariable Datum -menu $fr4.datum.m \
		    -width [Measure "Astro B4 Sorol Atoll"]
	    menu $fr4.datum.m \
		    -postcommand "FillDatumMenu $fr4.datum.m ChangeMapDatum"
	    menubutton $fr4.proj -textvariable MapProjTitle -width 20 \
		    -menu $fr4.proj.m
	    menu $fr4.proj.m \
		    -postcommand "FillProjsMenu $fr4.proj.m \
		                     MAPKNOWNPROJS MapProjectionIs"
	    label $fr4.transf -textvariable MapTransfTitle -relief raised \
		    -width 20

	    frame $fr4.sep -height 6 -bg $COLOUR(dialbg) -width 5
	    menubutton $fr4.grid -textvariable MapPFormat -width 8 \
		    -menu $fr4.grid.m
	    menu $fr4.grid.m
	    bind $fr4.grid <Button-1> \
		    "FillPFormtMenu $fr4.grid.m ChangeMapPFormat"
	    label $fr4.zone -textvariable MapZone -width 4 -relief sunken
	    label $fr4.xcoord -textvariable XCoord -width 11 -relief sunken
	    label $fr4.ycoord -textvariable YCoord -width 11 -relief sunken

	    set WConf(mapdatum) "$fr4.datum $fr4.proj"
	    set WConf(mapposition) $fr4 ; set WConf(mapposprev) sep
	    set WConf(mapposside) left
	    lappend WConf(mapstate) $fr0.map.m
	    lappend WConf(mapstatetype) menu
	    set WConf(mapstateback) $fr0.map.mback
	    set WConf(additemstate) $fr0.db.m.e
	    lappend WConf(datastate) \
		    [list menu [list [list $fr0.db.m [list 1 3]]]] \
		    [list button [list .lsw.frbl.frb.save \
		                       .lsw.frbl.frb.search]]
	}
    }

    set mn $defsmnbt.mn
    menubutton $defsmnbt -text $TXT(defs) -menu $mn
    menu $mn
    $mn add cascade -label $TXT(projection) -menu $mn.proj
    menu $mn.proj
    $mn.proj add command -label $TXT(define) -command DefineProjection
    menu $mn.proj.mn \
	    -postcommand "FillProjsMenu $mn.proj.mn UProjs OpenUserProjection"
    $mn.proj add cascade -label "$TXT(open)..." -menu $mn.proj.mn
    $mn add separator
    $mn add cascade -label Datum -menu $mn.dat
    menu $mn.dat
    $mn.dat add command -label $TXT(define) -command DefineDatum
    menu $mn.dat.mn \
	    -postcommand "FillDatumMenu $mn.dat.mn OpenDatum"
    $mn.dat add cascade -label "$TXT(open)..." -menu $mn.dat.mn
    $mn add cascade -label $TXT(ellpsd) -menu $mn.ell
    menu $mn.ell
    $mn.ell add command -label $TXT(define) -command DefineEllipsoid
    menu $mn.ell.mn \
	    -postcommand "FillEllipsoidMenu $mn.ell.mn OpenEllipsoid"
    $mn.ell add cascade -label "$TXT(open)..." -menu $mn.ell.mn

    if { [catch "set gim [image create photo \
	    -file [file join $SRCDIR gmicons gpsman-logo-small.gif]]"] } {
	set Title "GPS Manager"
	button $gtit -textvariable Title -width $mt \
		-command "QuitNow ; $gtit configure -state normal"
	bind $gtit <Enter> "set Title $TXT(exit)"
	bind $gtit <Leave> { set Title "GPS Manager" }
    } else {
	menubutton $gtit -image $gim -menu $gtit.m
	menu $gtit.m
	$gtit.m add command -label $TXT(about) -command About
	$gtit.m add command -label $TXT(exit) -command QuitNow
    }

    set tw [Measure $TXT(nameWP)]
    set bw [Measure $TXT(clear)]
    foreach i $TYPES {
	set n $TXT(name$i)
	set List($i) $LsW.frl$i.frl.box
	frame $LsW.frl$i -borderwidth 2
	frame $LsW.frl$i.frb
	menubutton $LsW.frl$i.frb.file -text $n -width $tw \
		-menu $LsW.frl$i.frb.file.m
	menu $LsW.frl$i.frb.file.m
	frame $LsW.frl$i.frl
	listbox $LsW.frl$i.frl.box -height $LISTHEIGHT -width $LISTWIDTH \
 	    -yscrollcommand "$LsW.frl$i.frl.bscr set" \
 	    -selectmode single -exportselection 1
	bind $LsW.frl$i.frl.box <Enter> { focus %W }
	bind $LsW.frl$i.frl.box <Leave> "focus $LsW"
	bind $LsW.frl$i.frl.box <Double-1> "OpenListItem $i"
	bind $LsW.frl$i.frl.box <Key> { ScrollListIndex %W %A }
	scrollbar $LsW.frl$i.frl.bscr -command "$LsW.frl$i.frl.box yview"
	# BSB contribution: wheelmouse scrolling
	Mscroll $LsW.frl$i.frl.box

	# order of menu entries is used elsewhere!
	switch $i {
	    GR {
		set tits [list $TXT(newGR) $TXT(clearall) "$TXT(load) ..." \
			       "$TXT(loadgrels) ..." $TXT(count)]
		set coms "NewItem ClearList LoadFile LoadGREls Count"
		set sts "normal disabled normal disabled normal"
		set im 4
		set imp importgrels ; set impst disabled
		set imppr ImportGREls ; set fmts "GPStrans Fugawi"
		set acts "save saveels exportels"
		set prs "SaveFile SaveGREls ExportGREls"
	    }
	    WP {
		set tits [list $TXT(new$i) $TXT(clearall) "$TXT(load) ..." \
		               $TXT(count)]
		set coms "NewItem ClearList LoadFile Count"
		set sts "normal disabled normal normal"
		set im 3
		set imp import ; set impst normal
		set imppr ImportFile ; set fmts "GPStrans Fugawi"
		set acts "save export" ; set prs "SaveFile ExportFile"
	    }
	    default {
		set tits [list $TXT(new$i) $TXT(clearall) "$TXT(load) ..." \
		               $TXT(count)]
		set coms "NewItem ClearList LoadFile Count"
		set sts "normal disabled normal normal"
		set im 3
		set imp import ; set impst normal
		set imppr ImportFile ; set fmts "GPStrans"
		set acts "save export" ; set prs "SaveFile ExportFile"
	    }
	}
	set m $LsW.frl$i.frb.file.m
	foreach l $tits c $coms s $sts {
	    $m add command -label $l -command "$c $i" -state $s
	}
	foreach ip $imp s $impst p $imppr {
	    $m insert $im cascade -label "$TXT($ip) ..." -menu $m.$ip -state $s
	    menu $m.$ip
	    foreach fmt $fmts {
		$m.$ip add command -label $fmt -command "$p $i $fmt"
	    }
	    incr im
	}
	foreach a $acts p $prs {
	    $m insert $im cascade -label "$TXT($a) ..." \
		    -menu $m.$a -state disabled
	    menu $m.$a
	    $m.$a add command -label $TXT(all) -command "$p all $i"
	    $m.$a add command -label "$TXT(select) ..." -command "$p select $i"
	    incr im
	}
    }
    # cannot use $TYPES here!!!
    bind $LsW.frlWP.frl.box <Button-3> {
	ToggleDisplayItem WP [%W nearest %y]
    }
    bind $LsW.frlRT.frl.box <Button-3> {
	ToggleDisplayItem RT [%W nearest %y]
    }
    bind $LsW.frlTR.frl.box <Button-3> {
	ToggleDisplayItem TR [%W nearest %y]
    }
    bind $LsW.frlGR.frl.box <Button-3> {
	ToggleDisplayItem GR [%W nearest %y]
    }
    
    frame $RcW.frgps -borderwidth 2
    if { "$MYGPS" == "Garmin" } {
	global MyProdDescr

	set MyProdDescr $TXT(GPSrec)
	label $RcW.frgps.title -width 40 -textvariable MyProdDescr
    } else {
	label $RcW.frgps.title -text $TXT(GPSrec)
    }

    # receiver window; create and fill also receiver menu
    menu $RcMenu
    $RcMenu add command -label $TXT(recwindow) \
	    -command "ToggleWindow .rcw $RPOSX $RPOSY"
    $RcMenu add separator
    menu $RcMenu.pm
    $RcMenu add cascade -label $TXT(protcl) -menu $RcMenu.pm

    frame $RcW.frgps.prt -borderwidth 2 -bg $COLOUR(messbg)
    set fprt $RcW.frgps.prt
    menubutton $fprt.title -text $TXT(protcl) -menu $fprt.title.m
    menu $fprt.title.m
    set GPSProtocolExt $TXT([set GPSProtocol [lindex $RECPROTOCOLS 0]])
    foreach p $RECPROTOCOLS {
	$fprt.title.m add command -label $TXT($p) \
		-command "GPSChangeProtocol $p"
	$RcMenu.pm add radiobutton -label $TXT($p) \
		-selectcolor $COLOUR(check) -command "GPSChangeProtocol $p"
    }
    $RcMenu.pm invoke 0
    label $fprt.prot -textvariable GPSProtocolExt -width 12

    frame $RcW.frgps.rlt -borderwidth 2 -bg $COLOUR(messbg)
    set frlt $RcW.frgps.rlt
    label $frlt.title -text $TXT(realtimelog)
    menu $RcMenu.rtm
    $RcMenu add cascade -label $TXT(realtimelog) -menu $RcMenu.rtm
    $RcMenu.rtm add command -label $TXT(getlog) -command GPSRealTimeLogOnOff
    $RcMenu.rtm add command -label $TXT(dolog) -command { set PVTState on }
    $RcMenu.rtm add command -label $TXT(animation) \
	    -command { set RealTimeLogAnim 1 }
    button $frlt.onoff -text $TXT(getlog) -width 10 \
	    -command "GPSRealTimeLogOnOff ; \
	    $frlt.onoff configure -state normal"
    button $frlt.show -text $TXT(dolog) \
	    -command "set PVTState on ; $frlt.show configure -state normal"
    button $frlt.anim -text $TXT(animation) \
	    -command "set RealTimeLogAnim 1 ; \
	    $frlt.anim configure -state normal"
    set WConf(realtime) [list $frlt.onoff [list $RcMenu.rtm 0]]
    set WConf(realtimetype) "button menuentry"
    grid configure $frlt.title -row 0 -column 0 -columnspan 2 -sticky news
    grid configure $frlt.onoff -row 1 -column 0 -rowspan 2 -sticky ew
    grid configure $frlt.show -row 1 -column 1 -sticky news
    grid configure $frlt.anim -row 2 -column 1 -sticky news

    frame $RcW.frgps.bs -borderwidth 2
    set GPSState offline ; set GPSLabel $TXT(offline)
    set r [Measure "Turn Off"]
    button $RcW.frgps.bs.state -textvariable GPSLabel -fg $COLOUR(offline) \
	    -width $r \
	    -command { CheckGPS ; $RcW.frgps.bs.state configure -state normal }
    bind $RcW.frgps.bs.state <Enter> { set GPSLabel $TXT(check) }
    bind $RcW.frgps.bs.state <Leave> { set GPSLabel $TXT($GPSState) }
    $RcMenu add command -accelerator $TXT(check) \
	    -image $SYMBOLIMAGE(diamond_red) -command CheckGPS
    button $RcW.frgps.bs.off -text $TXT(turnoff) -state disabled -width $r \
	    -command "TurnOff ; \
	    $RcW.frgps.bs.off configure -state normal"
    $RcMenu add command -label $TXT(turnoff) -state disabled \
	    -command TurnOff
    set r [Measure $TXT(nameWP)]
    frame $RcW.frget -borderwidth 2
    frame $RcW.frget.frget1
    frame $RcW.frget.frget2
    label $RcW.frget.frget1.title -text $TXT(get)
    menu $RcMenu.gm
    $RcMenu add cascade -label $TXT(get) -state disabled -menu $RcMenu.gm
    checkbutton $RcW.frget.frget1.displ -text $TXT(mapitems) \
	    -variable GetDispl -onvalue 1 -offvalue 0 \
	    -selectcolor $COLOUR(check)

    frame $RcW.frput -borderwidth 2
    label $RcW.frput.title -text $TXT(put)
    menu $RcMenu.ptm
    $RcMenu add cascade -label $TXT(put) -state disabled -menu $RcMenu.ptm
    foreach i $RECTYPES {
	set n $TXT(name$i)
	button $RcW.frget.frget2.get$i -text $n -width $r -state disabled \
	       -command "GetFromGPS $i ; \
	                 $RcW.frget.frget2.get$i configure -state normal"
	$RcMenu.gm add command -label $n -command "GetFromGPS $i"
	# BSB contribution: no IC put button
	if { "$i" != "IC" } {
	    menubutton $RcW.frput.put$i -text $n -width $r -state disabled \
		    -menu $RcW.frput.put$i.m
	    menu $RcW.frput.put$i.m
	    $RcW.frput.put$i.m add command -label $TXT(all) \
		    -command "PutOnGPS all $i"
	    $RcW.frput.put$i.m add command -label "$TXT(select) ..." \
		    -command "PutOnGPS select $i"
	    menu $RcMenu.ptm.m$i
	    $RcMenu.ptm add cascade -label $n -menu $RcMenu.ptm.m$i
	    $RcMenu.ptm.m$i add command -label $TXT(all) \
		    -command "PutOnGPS all $i"
	    $RcMenu.ptm.m$i add command -label "$TXT(select) ..." \
		    -command "PutOnGPS select $i"
	}
    }
    # BSB contribution
    if { "$MYGPS" == "Lowrance" } {
	frame $RcW.frinfo -borderwidth 2
	frame $RcW.frinfo1 -borderwidth 2
	label $RcW.frinfo.tprod -relief raised -width 10 -text $TXT(prod)
	label $RcW.frinfo.prod -width 16 -textvariable Prod
	label $RcW.frinfo.twp -relief raised -width 19 -text $TXT(WPCapac)
	label $RcW.frinfo.wp -width 6 -textvariable MAX(WP)
	label $RcW.frinfo.trt -relief raised -width 16 -text $TXT(RTCapac)
	label $RcW.frinfo.rt -width 6 -textvariable MAX(RT)
	label $RcW.frinfo.tic -relief raised -width 16 -text $TXT(ICCapac)
	label $RcW.frinfo.ic -width 6 -textvariable MAX(IC)
	label $RcW.frinfo1.tprt -relief raised -width 10 -text $TXT(protcl)
	label $RcW.frinfo1.prt -width 16 -textvariable Protv
	label $RcW.frinfo1.ticg -relief raised -width 16 -text $TXT(ICGraph)
	label $RcW.frinfo1.icg -width 6 -textvariable MAXICG
	label $RcW.frinfo1.ttr -relief raised -width 16 -text $TXT(TRCapac)
	label $RcW.frinfo1.tr -width 6 -textvariable MAX(TR)
	label $RcW.frinfo1.twr -relief raised -width 19 -text $TXT(WPperRT)
	label $RcW.frinfo1.wr -width 6 -textvariable MAXWPINROUTE
    }
    # end of BSB contribution

    # packing
    if { "$MWINDOWSCONF" == "map" } {
	pack $gtit $fr0.db $fr0.rcw $fr0.map $defsmnbt $fr0.options \
		-side left -padx 3
	pack $fr0
    }
    pack $MpW.frm.frmap1.mvscr -side right -fill y
    pack $Map -side left -expand yes -fill both
    pack $MpW.frm.frmap1 -expand yes -fill both
    pack $MpW.frm.frmap2.mhscr -padx 2 -side left -fill x -expand true
    pack $MpW.frm.frmap2.fill -side left
    pack $MpW.frm.frmap2 -pady 0 -fill x -expand true
    pack $MpW.frm.frmap3.cv $MpW.frm.frmap3.mn -side left -padx 2
    pack $MpW.frm.frmap3.sep $MpW.frm.frmap3.loc -side left -padx 10
    pack $MpW.frm.frmap3.disp $MpW.frm.frmap3.clr -side left -padx 2
    pack $MpW.frm.frmap3 -pady 2

    foreach i $TYPES {
	pack $LsW.frl$i.frl.box $LsW.frl$i.frl.bscr -side left \
		-fill y -expand true
	pack $LsW.frl$i.frb.file -side top -pady 5
	pack $LsW.frl$i.frb $LsW.frl$i.frl -side top \
		-fill y -expand true
	pack $LsW.frl$i -side left -fill y
    }

    switch $MWINDOWSCONF {
	lists {
	    pack $defsmnbt $MpW.frmi.frcoords.transf \
		    $MpW.frmi.frcoords.ttitle $MpW.frmi.frcoords.proj \
		    $MpW.frmi.frcoords.ptitle $MpW.frmi.frcoords.datum \
		    $MpW.frmi.frcoords.dtitle -pady 2 -side bottom
	    pack $MpW.frmi.frmbs.mtitle $MpW.frmi.frmbs.grid \
		    $MpW.frmi.frmbs.zone $MpW.frmi.frmbs.xcoord \
		    $MpW.frmi.frmbs.ycoord $MpW.frmi.frmbs.msave \
		    $MpW.frmi.frmbs.mback $MpW.frmi.frmbs.mclear -pady 5

	    pack $MpW.frmi.frcoords -side top
	    pack $MpW.frmi.frmbs -side bottom

	    pack $MpW.frm $MpW.frmi -side left -fill y
	}
	map {
	    pack $fr4.datum $fr4.proj $fr4.transf $fr4.sep $fr4.grid \
		    $fr4.zone $fr4.xcoord $fr4.ycoord -side left -padx 3
	    pack $fr4 -pady 2
	    pack $MpW.frm
	    pack $MpW
	    pack .lsw.frbl.frb.load .lsw.frbl.frb.save .lsw.frbl.frb.search \
		    -side left -padx 3
	    pack .lsw.frbl.frb $LsW -side top -pady 3
	    pack .lsw.tit .lsw.frbl -side top -pady 5
	}
    }

    pack $RcW.frgps.prt.title $RcW.frgps.prt.prot -side left
    pack $RcW.frgps.bs.state $RcW.frgps.bs.off -side left -pady 2
    pack $RcW.frgps.title $RcW.frgps.prt $RcW.frgps.rlt $RcW.frgps.bs \
	    -side top -pady 5
    pack $RcW.frget.frget1.title $RcW.frget.frget1.displ -side left -padx 5
    foreach i $RECTYPES {
	pack $RcW.frget.frget2.get$i -side left -pady 2
    }
    pack $RcW.frget.frget1 $RcW.frget.frget2 -side top
    pack $RcW.frput.title -side top
    # BSB contribution: no IC put button
    foreach i $RECTYPES {
	if { "$i" != "IC" } { 
	    pack $RcW.frput.put$i -side left -pady 2
	}
    }

    switch $MWINDOWSCONF {
	lists {
	    pack .lsw.frmb.dtitle .lsw.frmb.datum -pady 2 -side top
	    pack .lsw.frmb.frb.sep .lsw.frmb.frb.load  .lsw.frmb.frb.save \
		    .lsw.frmb.frb.search .lsw.frmb.frb.sep2 -side top -pady 3 \
		    -fill x
	    pack .lsw.frmb.frb -pady 20 -side top
	    pack .lsw.frmb.opt -pady 5 -side bottom
	    pack .lsw.frmb.sep -pady 5 -side bottom -fill x
	    pack .lsw.frmb.rcw .lsw.frmb.mpw -pady 5 -side bottom
	    pack $LsW .lsw.frmb -side left -fill y
	    pack $gtit .lsw -side top -pady 3

	    pack .mpw.tit $MpW -side top -pady 3
	}
	map {
	    pack $RcW.frgps $RcW.frget $RcW.frput -side top -pady 5
	    pack .rcw.tit $RcW -side top -pady 3

	    # BSB contribution
	    if { "$MYGPS" == "Lowrance" } {
		pack $RcW.frinfo1 -side bottom -pady 5
		pack $RcW.frinfo1.tprt $RcW.frinfo1.prt $RcW.frinfo1.twr \
			$RcW.frinfo1.wr $RcW.frinfo1.ticg $RcW.frinfo1.icg \
			$RcW.frinfo1.ttr $RcW.frinfo1.tr -side left -pady 2
		pack $RcW.frinfo -side bottom -pady 5
		pack $RcW.frinfo.tprod $RcW.frinfo.prod $RcW.frinfo.twp \
			$RcW.frinfo.wp $RcW.frinfo.trt $RcW.frinfo.rt \
			$RcW.frinfo.tic $RcW.frinfo.ic -side left -pady 2
	    }
	    # end of BSB contribution
	}
    }

    SetMapBindings

    # saved state
    if { [file readable $USvState] } {
	RestoreState
    }
    return
}

proc About {} {
    # create modal dialog for displaying information about GPSMan
    #  single button: OK; binding: return
    global EPOSX EPOSY TXT

    set wait 1
    toplevel .about
    wm protocol .about WM_DELETE_WINDOW { set wait 0 }
    wm title .about "GPS Manager: $TXT(message)"
    wm transient .about
    wm geometry .about +$EPOSX+$EPOSY
    bind .about <Key-Return> { set wait 0 }

    AboutInfo .about

    frame .about.fr.bt
    button .about.fr.ok -text Ok -command { set wait 0 }
    pack .about.fr.ok
    pack .about.fr -side top -pady 5
    update idletasks
    grab .about
    RaiseWindow .about
    tkwait variable wait
    destroy .about
    update idletasks
    return
}

##### initializing variables and quitting

proc GMStart {} {
    # initialize (most) global variables
    global Index Number Storage File Proc WorkDir FileTypes FDDatum GFLegend \
	    TYPES PROCTYPES CursorsChanged MAPWIDTH MAPHEIGHT MAPW2 MAPH2 \
	    AzimuthDegrees MapEmpty DataDefault DataIndex PositionFormat \
	    DEFAULTSYMBOL DEFAULTDISPOPT Datum EMPTYSTR AnimNo \
	    BalloonX BalloonY MAPKNOWNPROJS MAPKNOWNTRANSFS USERDIR \
	    UProjs UPrGrFile RealTimeLogOn RealTimeLogAnim PVTState \
	    UDtElFile USvState USvData USvMap BITMAPS SERIALPORT DEFSPORT \
	    tcl_platform
	    
    # BSB contribution: globals needed for Lowrance receivers
    global UnusedICInx UnusedWPInx MAX MYGPS

    # serial port
    if { "$tcl_platform(platform)" == "unix" && "$SERIALPORT" == "" } {
	set SERIALPORT $DEFSPORT
    }

    # projections, datums and ellipsoids
    if { [file readable [set UDtElFile [file join $USERDIR datums]]] } {
	SetUpUserDatums
    }
    set MAPKNOWNPROJS \
	    {UTM TM BNG BWI CMP GKK ITM KKJY KKJP SEG
             LCC1 LCC2 Merc1 Merc2 CS APOLY}
    set MAPKNOWNTRANSFS {Affine AffineConf NoRot}
    SetUpNZGrids
    set UProjs {}
    if { [file readable [set UPrGrFile [file join $USERDIR projs]]] } {
	SetupUserProjs
    }

    # map
    set MapEmpty 1
    set MAPW2 [expr $MAPWIDTH/2.0] ; set MAPH2 [expr $MAPHEIGHT/2.0]
    set AnimNo 0

    MapProjectionIs UTM

    # data-base
    set Number(Data) 0
           # the first element in Storage(_) must be identifier storage
           #  and the last one the display state
           # WPNum needed only for Lowrance receivers
           # WPRoute is set separately because cannot be edited
    set Storage(WP) {WPName WPNum WPCommt WPObs WPPFrmt WPPosn WPDatum \
	             WPDate WPSymbol WPDispOpt WPAlt WPHidden WPDispl}
    set DataDefault(WP) [list "" -1 "" "" $PositionFormat "" $Datum \
	    "" $DEFAULTSYMBOL $DEFAULTDISPOPT "" "" 0]
    set Storage(RT) {RTIdNumber RTCommt RTObs RTWPoints RTStages RTDispl}
    set DataDefault(RT) [list "" "" "" "" "" 0]
    set stRS {RScommt RSlabel RShidden}
    set DataDefault(RS) [list "" "" ""]
    set Storage(TR) {TRName TRObs TRDatum TRTPoints TRHidden TRDispl}
    set DataDefault(TR) [list "" "" $Datum "" "" 0]
    set stTP {TPlatd TPlongd TPlatDMS TPlongDMS TPdate TPsecs TPalt TPdepth}
    set DataDefault(TP) [list "" "" "" "" "01-Jan-1988 00:00:00" 0 "" ""]
    set Storage(GR) {GRName GRObs GRConts GRDispl}
    set DataDefault(GR) [list "" "" "" 0]
    foreach wh $TYPES proc $PROCTYPES {
	set Index($wh) 0 ; set Number($wh) 0 ; set Proc($wh) $proc
	set k 0
	foreach da $Storage($wh) {
	    set DataIndex($da) $k ; incr k
	}
    }
    foreach d "RS TP" {
	set k 0
	foreach da [set st$d] {
	    set DataIndex($da) $k ; incr k
	}
    }

    # files
    set FileTypes {WP RT TR GR Data WPDistBear WPNearest RTComp TRComp
                   Map Plot MapBkInfo Image PVTData}
    foreach t $FileTypes { set File($t) "" }
    set FDDatum ""
    set GFLegend ""
    set WorkDir [pwd]
    set USvState [file join $USERDIR sstate]
    set USvData [file join $USERDIR sdata]
    set USvMap [file join $USERDIR smap]

    # real-time log
    set RealTimeLogOn 0 ; set RealTimeLogAnim 0
    set PVTState abort

    # varia
    set CursorsChanged 0
    set BalloonX 0 ; set BalloonY 0
    set EMPTYSTR ""
    set a 0
    foreach b "N NE E SE S SW W NW" {
	set AzimuthDegrees($b) $a ; incr a 45
    }
    set BITMAPS {brokenline}
    InitBitmaps

    # initializations depending on receiver brand
    # BSB contribution
    if { "$MYGPS" != "Lowrance" } {
	StartGPS
    } else {
	set UnusedWPInx 0
	for {set i 1} {$i < $MAX(WP)} {incr i} {
	   lappend UnusedWPInx $i
	}
	set UnusedICInx 0
	for {set i 1} {$i < $MAX(WP)} {incr i} {
	   lappend UnusedICInx $i
	}
    }

    return
}

proc QuitNow {} {
    global MESS TXT SAVESTATE

    switch $SAVESTATE {
	never {
	    if { ! [GMConfirm $MESS(oktoexit)] } { return }
	}
	ask {
	    switch [GMSelect $MESS(savestate) \
		    [list Ok $TXT(no) $TXT(cancel)] "ok no cancel"] {
		ok { SaveState }
		cancel { return }
	    }
	}
	always {
	    SaveState
	}
    }
    GPSBye
    exit 0
}

