# # This file is part of: # # gpsman --- GPS Manager: a manager for GPS receiver data # # Copyright (c) 1998-2011 Miguel Filgueiras migf@portugalmail.pt # # 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 3 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: command.tcl # Last change: 19 July 2011 # # this file is only source-ed in command-line mode (even if the graphical # interface is launched to obey the command) ### change some initial values if needs be if { $COMMAND(rec) } { # use an "accept anything from receiver" setting RecCanSendAnything $MYGPS } if { $COMMAND(log) } { set NotLogging 0 } ##### executing command proc ExecCommand {} { # execute command from command line # return 0 on success, 1 on error, "wait" to loop, "-0" to quit fast global COMMAND CMDLINE NoImgLib GSHPVersion RealTimeLogAnim PVTState \ PVTDumping RealTimeGettingFix MESS GPSProtocol if { [set prot $COMMAND(prot)] != "" } { set GPSProtocol $prot } switch $COMMAND(name) { checkconn { # "is connected" command return [ExecGPSConnectFail] } show { CmdShow $COMMAND(what) return "-0" } haslib { switch $COMMAND(what) { gpsmanshp { if { $GSHPVersion == "" } { return 1 } } Img { if { $NoImgLib } { return 1 } } default { if { [lsearch -exact [package names] $COMMAND(what)] \ == -1 } { return 1 } } } } getwrite { if { [CmdGetFails $COMMAND(rectypes)] || \ [CmdWriteFails $COMMAND(format) $COMMAND(path) \ $COMMAND(out,params) $COMMAND(filetypes)] } { return 1 } } readput { if { [CmdReadFails $COMMAND(format) $COMMAND(path) \ $COMMAND(in,params) $COMMAND(filetypes)] || \ [CmdPutFails $COMMAND(rectypes)] } { return 1 } } translate { CmdSetTranslateParams $COMMAND(params) if { [CmdReadFails $COMMAND(infmt) $COMMAND(inpath) \ $COMMAND(in,params) $COMMAND(intypes)] || \ [CmdWriteFails $COMMAND(format) $COMMAND(path) \ $COMMAND(out,params) $COMMAND(filetypes)] } { return 1 } CmdRestoreTranslation } getrtimelog { if { [CmdCantStartRTimeLog Ignore Ignore] || \ [CmdRTimeDumpFails $COMMAND(path)] } { return 1 } # force calls to SavePVTData $PVTDFile set PVTDumping 1 set PVTState on return wait } getfix { # interval for real-time log set COMMAND(interv) 2 if { [CmdCantStartRTimeLog Ignore Ignore] || \ [CmdRTimeDumpFails $COMMAND(path)] } { return 1 } set RealTimeGettingFix 1 trace variable RealTimeGettingFix w CmdRTimeGotFix if { $COMMAND(timeout) != 0 } { after [expr $COMMAND(timeout)*1000] \ { set RealTimeGettingFix -1 } } # avoid calls to SavePVTData $PVTDFile set PVTDumping 0 set PVTState on return wait } getalmanac { if { [CmdGetAlmanacFails $COMMAND(path)] } { return 1 } } starttravel { # enter graphical mode set CMDLINE 0 GMInit if { ! [CmdCantStartRTimeLog EnableGPS \ [list GMMessage $MESS(receiver)]] } { set RealTimeLogAnim 1 ToTravel } return wait } project { if { [CmdBadProjArgs] || [CmdBadProjSetup] } { return 1 } set proj $COMMAND(proj) foreach "x y" [Proj${proj}Point MPData \ $COMMAND(latd) $COMMAND(longd) $COMMAND(ptsdatum)] {} puts "$x\t$y" return "-0" } georef { if { [CmdBadGeoRefArgs] || [CmdBadGeoRefSetup] } { return 1 } CmdGenerateGeoRef return "-0" } geopicts { global Number Datum SYMBOLS DEFAULTSYMBOL set type $COMMAND(intypes) if { [CmdReadFails $COMMAND(infmt) $COMMAND(inpath) \ $COMMAND(in,params) $type] || $Number($type) == 0 } { return 1 } set fmt $COMMAND(format) set ix [expr $Number($type)-1] set mdate pict ; set dhour 0 if { $fmt == "GPX" } { set datum "WGS 84" } else { set datum $Datum } set sy scenic set prefix P foreach "lhs rhs" $COMMAND(params) { switch $lhs { id { if { [set ix [IndexNamed $type $rhs]] == -1 } { GMMessage "$MESS(notlisted): $rhs" return 1 } } date { set mdate $rhs } dh { set dhour $rhs } datum { if { [EllipsdOf $rhs] == "" } { GMMessage "$MESS(unkndatum): $rhs" return 1 } if { $fmt != "GPX" } { set datum $rhs } } sy { if { [lsearch -exact $SYMBOLS $rhs] == -1 } { GMMessage "$MESS(badSYMBOLcode): $rhs" return 1 } set sy $rhs } prefix { set prefix $rhs } __picts { set pcs $rhs } } } if { [set lts [GetFilesDates $pcs $mdate $dhour]] == "" || \ [set lts [GeoAdapt $type $ix $datum $lts]] == "" } { GMMessage $MESS(missingdata) return 1 } if { [CmdProcParamsFails $fmt $COMMAND(out,params)] || \ [CmdGPictsOutputFails $fmt $COMMAND(path) \ $lts $datum $sy $prefix] } { return 1 } } source { # file is assumed to be in system encoding if { [catch {source $COMMAND(path)}] } { return 1 } return wait } read { if { ! $COMMAND(script) } { # enter graphical mode set CMDLINE 0 GMInit if { [CmdReadFails $COMMAND(format) $COMMAND(path) \ $COMMAND(in,params) $COMMAND(filetypes)] } { GMMessage "$MESS(badfile): $COMMAND(path)" } return wait } return [CmdReadFails $COMMAND(format) $COMMAND(path) \ $COMMAND(in,params) $COMMAND(filetypes)] } exec { if { [catch {set f [open $COMMAND(path) r]}] } { return 1 } set COMMAND(script) 1 return [CmdInterpret $f] } write { return [CmdWriteFails $COMMAND(format) $COMMAND(path) \ $COMMAND(out,params) $COMMAND(filetypes)] } get { return [CmdGetFails $COMMAND(rectypes)] } put { return [CmdPutFails $COMMAND(rectypes)] } } return 0 } proc CmdProcessLine {line} { # split $line into command name and arguments taking care of quotes # return list similar to argv or ERROR on error set line [string trim $line] regsub -all "\t" $line " " line while { [regsub -all " " $line " " line] } { continue } set l "" while { [string first "\"" $line] != -1 } { if { ! [regexp {^([^"]*)"([^"]*)"(.*)$} $line m pre in rest] } { return ERROR } if { $pre != "" } { set l [concat $l [split [string trim $pre] " "]] } lappend l $in set line [string trim $rest] } if { $line != "" } { set l [concat $l [split $line " "]] } return $l } proc CmdInterpret {file} { # interpret commands from $file # return 1 on error, 0 on success global argv set prev "" while { ! [eof $file] } { gets $file line set line [string trim $line " \t"] # discards comment lines whose first non-blank is "#" if { $line == "" || [regexp {^#} $line] } { continue } # check continuation line indicator (backslash as last char) # if there is a unmatched quote this will cause error! if { [string index $line end] == "\\" } { set prev "$prev$line " continue } set line [string trim "$prev$line" " \t"] set argv [CmdProcessLine $line] if { [BadCommandLine] } { puts stderr "bad command: $line" return 1 } if { [ExecCommand] == 1 } { puts stderr "command failed: $line" return 1 } set prev "" } # continuation line not found if { $prev != "" } { return 1 } return 0 } proc ExecGPSConnectFail {args} { # $args is list with 1st and 2nd argument to proc GPSConnection # return 1 on error, 0 on success global GPSOpResult if { $args == "" } { if { [GPSConnection Ignore Ignore] == 0 } { return 1 } } elseif { [GPSConnection [lindex $args 0] [lindex $args 1]] == 0 } { return 1 } vwait GPSOpResult return $GPSOpResult } proc CmdCantStartRTimeLog {connproc errorproc} { # return 0 on success, 1 on error global COMMAND GPSProtocol # this depends on the Garmin variant... if { [string first "garmin" $GPSProtocol] == 0 && \ [ExecGPSConnectFail $connproc $errorproc] } { return 1 } if { ! [StartRealTimeLog $COMMAND(interv)] } { return 1 } return 0 } proc CmdGetFails {types} { # get items of given $types # return 0 on success global GPSOpResult if { [ExecGPSConnectFail] } { return 1 } foreach t $types { GetGPS $t vwait GPSOpResult if { $GPSOpResult } { return 1 } } return 0 } proc CmdGetAlmanacFails {path} { # get almanac and print it to file # return 0 on success global ALDataTxt if { [CmdGetFails AL] || [set f [CmdOpenFile $path out]] == -1 } { return 1 } puts $f $ALDataTxt close $f return 0 } proc CmdPutFails {types} { # put items of given $types # return 0 on success global GPSOpResult Storage if { [ExecGPSConnectFail] } { return 1 } foreach wh $types { set ids [lindex $Storage($wh) 0] global $ids PutGPS $wh [array names $ids] vwait GPSOpResult if { $GPSOpResult } { return 1 } } return 0 } proc CmdOpenFile {path mode} { # open file # $mode in {in, out, app} # if $path in {stdin, stdout} for suitable $mode return $path # otherwise return file descriptor or -1 on error if { $mode == "in" } { if { $path == "stdin" } { return stdin } set mode r } elseif { $path == "stdout" } { set mode w return stdout } elseif { $mode == "out" } { set mode w } else { set mode a } if { [catch {set f [open $path $mode]}] } { return -1 } return $f } proc CmdReadFails {fmt path pars types} { # read file in format $fmt # if $path==stdin use standard input unless $fmt is Shapefile in which # case return failure # return 0 on success global FILEFORMAT File if { [CmdProcParamsFails $fmt $pars] } { return 1 } switch -glob $fmt { GPSMan { if { [set f [CmdOpenFile $path in]] == -1 || \ [catch {set r [LoadFileFrom $f Data]}] || \ $r == 0 } { return 1 } } Shapefile { if { $path == "stdin" } { return 1 } # a single type per file return [ImportShapefileFrom $path $types] } default { if { $FILEFORMAT($fmt,filetype) != "data" } { # a single type per file set wh $types } else { set wh Data } if { $fmt == "GPStrans" } { set cr 1 } else { set cr 0 } if { [set f [CmdOpenFile $path in]] == -1 } { return 1 } InitInputFileVars $f $wh $cr 0 set File($wh) $path if { [catch {set r [ImportFileFrom $f $wh $fmt]}] || $r == 1 } { return 1 } } } return 0 } proc CmdWriteFails {fmt path pars types} { # write data to file in format $fmt # if $path==stdout use standard output unless $fmt is Shapefile # in which case return failure # return 0 on success global FILEFORMAT if { [CmdProcParamsFails $fmt $pars] } { return 1 } switch -glob $fmt { GPSMan { if { [set f [CmdOpenFile $path out]] == -1 } { return 1 } if { [catch {set fts $FILEFORMAT(GPSMan,types)}] } { set fts [lindex $FILEFORMAT(GPSMan,io_types) 1] } if { [llength $fts] == [llength $types] } { if { [catch {SaveFileTo $f all Data}] } { return 1 } } else { foreach t $types { if { [catch {SaveFileTo $f all $t}] || \ [set f [CmdOpenFile $path app]] == -1 } { return 1 } } if { $path != "stdout" } { close $f } } } Shapefile { if { $path == "stdout" } { return 1 } # a single type per file return [ExportFileTo $path all $fmt $types] } default { if { [set f [CmdOpenFile $path out]] == -1 } { return 1 } if { $FILEFORMAT($fmt,filetype) != "data" } { # a single type per file if { [catch {set r [ExportFileTo $f all $fmt $types]}] || \ $r == 1 } { return 1 } } else { set lp [AllIndicesForType Data $types] if { [catch {Export_$fmt $f $lp}] } { return 1 } } } } return 0 } proc CmdProcParamsFails {fmt pars} { # process parameters: check the given/default values, convert them, and # use them in defining global variables global FILEFORMAT MESS if { $pars == "" } { return 0 } if { [llength $pars] & 1 == 1 } { BUG Bad parameters list } set gvcsvl "" foreach "p val" $pars { foreach "gvar conversion constraint" $FILEFORMAT($fmt,param,$p) { break } if { [catch {eval $conversion}] } { GMMessage [format $MESS(badconv) $p $val] return 1 } lappend gvcsvl $p $gvar $constraint $val } foreach "p gvar constraint val" $gvcsvl { if { [catch {set r [eval $constraint]}] || $r == 0 } { GMMessage [format $MESS(badprmval) $p $val] return 1 } global $gvar set $gvar $val } return 0 } proc CmdSetTranslateParams {pars} { # set globals for the translation global CmdSAVED foreach "p val" $pars { switch -- $p { itoffset { global FromTimeOffset set CmdSAVED(FromTimeOffset) $FromTimeOffset set FromTimeOffset $val } otoffset { global TimeOffset set CmdSAVED(TimeOffset) $TimeOffset set TimeOffset $val } } } return } proc CmdRestoreTranslation {} { # restore any globals changed for the translation global CmdSAVED if { [info exists CmdSAVED] } { foreach g [array names CmdSaved] { global $g set g $CmdSaved($g) } unset CmdSAVED } return } proc CmdRTimeDumpFails {path} { # start dumping real-time log continuously # return 0 on success global PVTDFile if { [set PVTDFile [CmdOpenFile $path out]] == -1 } { return 1 } return 0 } proc CmdRTimeGotFix {args} { # global RealTimeGettingFix has been changed to either -1 for a timeout # or a list with formatted real-time position data --- see procs # UseRealTimeData and RTimeDumpLine # exit with 1 on timeout # if the fix is valid write to $PVTDFile and exit with 0, otherwise # reset RealTimeGettingFix to 1 global RealTimeGettingFix PVTDFile TXT DSCALE SPUNIT if { $RealTimeGettingFix == -1 } { exit 1 } foreach "n date lat long alt fix epe eph epv velx vely velz trk" \ $RealTimeGettingFix { break } if { $fix != $TXT(posfixerror) && $fix != $TXT(posfix_) } { puts $PVTDFile "$lat $long" puts $PVTDFile "WGS 84" puts $PVTDFile $date puts $PVTDFile $trk # horizontal speed if { $velx != "" && $vely != "" } { puts $PVTDFile [format "%.2f $SPUNIT" \ [expr sqrt($velx*$velx+$vely*$vely)*$DSCALE]] } else { puts $PVTDFile "" } if { $velz != "" } { puts $PVTDFile [format "%.1f" $velz] } else { puts $PVTDFile "" } puts $PVTDFile $epe puts $PVTDFile $eph puts $PVTDFile $epv if { $fix == $TXT(posfix3D) || $fix == $TXT(posfix3D-diff) } { puts $PVTDFile $alt } else { puts $PVTDFile "" } close $PVTDFile exit 0 } set RealTimeGettingFix 1 return } proc CmdShow {what} { # print information to stdout global VERSION FILEFORMAT RECPROTS TXT MESS MAPKNOWNPROJS MAPPROJDATA \ MAPPROJDTYPE MAPPARTPDATA MAPKNOWNTRANSFS GDATUM COMMAND SYMBOLS switch $what { help { puts $COMMAND(USAGE) } version { puts $VERSION } formats { array set mode [list \ in $TXT(fread) \ out $TXT(fwrite) \ {in out} $TXT(fread)/$TXT(fwrite)] foreach f $FILEFORMAT(names) { if { ! [catch {set dep $FILEFORMAT($f,depends)}] && \ ! [eval $dep] } { puts "$f:\t$MESS(shpwrongfile)" continue } set m $mode($FILEFORMAT($f,mode)) if { [set t $FILEFORMAT($f,filetype)] == "data" } { set suff " $TXT(nameData)" } else { set suff "" } if { [catch {set ts $FILEFORMAT($f,types)}] } { foreach "its ots" $FILEFORMAT($f,io_types) { break } puts "$f:\t$mode(in)\t $its$suff" puts "\t$mode(out)\t $ots$suff" } else { puts "$f:\t$m\t $FILEFORMAT($f,types)$suff" } set t 1 foreach how "in out" { if { ! [catch {set params $FILEFORMAT($f,$how,params)}] } { if { $t } { puts " $TXT(params)" set t 0 } puts "\t$mode($how):" if { [catch {set pds $FILEFORMAT($f,$how,pdefts)}] } { set pds "" } foreach p $params dv $pds { if { [regexp {^global:(.+)$} $dv m dvv] } { global $dvv puts "\t\t$p\t[set $dvv]" } else { puts "\t\t$p\t$dv" } } } } } } projections { set pp [array names MAPPARTPDATA] foreach p [lsort -dictionary $MAPKNOWNPROJS] { if { $p == "Schreiber" } { puts "$p:\t$TXT(PRJ$p)" } else { puts "$p:\t$TXT(PRJ$p)\n $TXT(params)" puts "\t?datum" if { [lsearch -exact $pp $p] == -1 } { if { $p == "UTM" } { puts "\t?UTMzone" continue } foreach pm $MAPPROJDATA($p) { if { [set t $MAPPROJDTYPE($pm)] != "reserved" } { regsub {^(list=)|(list:)} $t "" t puts "\t$pm\t($t)\t$TXT($pm)" } } } } } } transfs { foreach t [lsort -dictionary $MAPKNOWNTRANSFS] { puts "$t:\t$TXT(TRNSF$t)" } } datums { foreach d [lsort -dictionary [array names GDATUM]] { if { [set cmt [lindex $GDATUM($d) 5]] != "" } { puts "$d\t:$cmt" } else { puts $d } } } protocols { foreach p [lsort -dictionary [array names RECPROTS *,*]] { regexp {^(.+),(.+)$} $p x rec prot puts "$prot ($rec)" } } symbols { foreach s [lsort -dictionary $SYMBOLS] { if { [string length $s] > 7 } { set sep "\t" } else { set sep "\t\t" } puts "$s$sep$TXT(SY$s)" } } } return } proc CmdBadProjArgs {} { # check all the arguments of the project command # return 0 on success, 1 on error global COMMAND MAPKNOWNPROJS MAPPROJDATA MAPPROJDTYPE MAPPARTPROJ \ MAPPARTPDATA MPData foreach a "latd longd ptsdatum proj params" { set $a $COMMAND($a) } if { ! [CheckCoord GMMessage DDD $latd N 90] || \ ! [CheckCoord GMMessage DDD $longd E 180] || \ [EllipsdOf $ptsdatum] == "" || \ [lsearch -exact $MAPKNOWNPROJS $proj] == -1 } { return 1 } set missdat 1 if { [set pars $COMMAND(params)] != "" } { if { [llength $pars] & 1 == 1 } { BUG Bad parameters list } foreach "p val" $pars { if { $p == "datum" } { if { [EllipsdOf $val] == "" } { return 1 } set MPData(datum) $val set missdat 0 } else { if { [catch {set type MAPPROJDTYPE($p)}] || \ $type == "reserved" } { return 1 } set CMD_$p $val } } } if { $missdat } { set MPData(datum) $ptsdatum } # UTM has an optional parameter if { $proj == "UTM" && [catch {set CMD_UTMzone}] } { return 0 } if { [catch {set mp $MAPPARTPROJ($proj)}] } { foreach p $MAPPROJDATA($proj) { if { [set type $MAPPROJDTYPE($p)] != "reserved" } { if { [catch {set val [set CMD_$p]}] || \ [BadParam "" $type $val] } { return 1 } set MPData($p) $val } } } else { foreach e $MAPPROJDATA($mp) v $MAPPARTPDATA($proj) { set MPData($e) $v } set COMMAND(proj) $mp } return 0 } proc CmdBadProjSetup {} { # initialize projection # return 0 on success, 1 on error global COMMAND foreach a "latd longd ptsdatum proj" { set $a $COMMAND($a) } if { [BadProjSetup MPData $proj $latd $longd $ptsdatum] } { return 1 } return 0 } proc CmdBadGeoRefArgs {} { # check the arguments of the georef command and prepare data # return 0 on success, 1 on error global COMMAND MapLoadPos foreach a "transf ptsdatum proj params" { set $a $COMMAND($a) } # used by proc CmdBadProjArgs set COMMAND(latd) $COMMAND(0,lat) set COMMAND(longd) $COMMAND(0,long) if { [CmdBadProjArgs] } { return 1 } set npts $COMMAND(npts) for { set p 0 } { $p < $npts } { incr p } { foreach pp "lat long x y" { set $pp $COMMAND($p,$pp) } if { ! [CheckCoord GMMessage DDD $lat N 90] || \ ! [CheckCoord GMMessage DDD $long E 180] || \ ! [CheckFloat GMMessage $x] || ! [CheckFloat GMMessage $y] } { return 1 } set MapLoadPos($p,x) $x ; set MapLoadPos($p,y) $y } return 0 } proc CmdProjCoords {npts} { # return list of projected coordinates for points given in command line # $npts is number of points # assumes that the following elements are defined in array COMMAND # ptsdatum # $n,lat for $n in 0..$npts-1 # $n,long # proj projection # assumes that the projection parameters were initialized in array MPData global COMMAND set ptsdatum $COMMAND(ptsdatum) ; set proj $COMMAND(proj) set tcs "" for { set p 0 } { $p < $npts } { incr p } { lappend tcs [Proj${proj}Point MPData \ $COMMAND($p,lat) $COMMAND($p,long) $ptsdatum] } return $tcs } proc CmdBadGeoRefSetup {} { # initialize projection and transformation # return 0 on success, 1 on error global COMMAND if { [CmdBadProjSetup] } { return 1 } MapProjectionIs $COMMAND(proj) if { [set transf $COMMAND(transf)] == "NoRot" } { set proc InitNoRotTransf } else { set proc MapInit${transf}Transf } if { ! [$proc] } { return 1 } return 0 } proc CmdGenerateGeoRef {} { # output geo-ref information file global COMMAND SaveMapBack $COMMAND(image) stdout return } proc CmdGPictsOutputFails {fmt path lts datum sy prefix} { # write a waypoint for each tuple in $lts to file in format $fmt # $fmt must be GPX (for the time being) # $lts is list of tuples with the latitude and longitude (decimal # degrees, for $datum) and altitude (metre), date in seconds from # $YEAR0, file path, and date in "%Y:%m:%d %H:%M:%S" format # $sy the symbol code to use for WPs # $prefix is the name prefix to be used when generating WP names # if $path==stdout use standard output # return 0 on success if { $fmt != "GPX" } { BUG CmdGPictsOutputFails: format must be GPX } if { $path != "stdout" } { if { [catch {set file [open $path w]}] } { return 1 } } else { set file stdout } # output GPX set xml_hdr {<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <gpx version="1.0" creator="GPSMan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/2" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/2 http://www.topografix.com/GPX/Private/TopoGrafix/0/2/topografix.xsd"> <author>anonymous GPSMan user</author> <email>undefined</email> <url>undefined</url> <urlname>undefined</urlname> } set xml_footer {</gpx>} set xml_wptalt {<wpt lat="%s" lon="%s"> <name>%s</name> <ele>%s</ele> <symbol>%s</symbol> <desc>%s</desc> <extensions><picture>%s</picture></extensions> </wpt> } set xml_wpt {<wpt lat="%s" lon="%s"> <name>%s</name> <symbol>%s</symbol> <desc>%s</desc> <extensions><picture>%s</picture></extensions> </wpt> } set n 0 set dpre "Photo" puts $file $xml_hdr foreach tuple $lts { foreach "la lo alt secs fpath date" $tuple { break } set name "$prefix[format %05d $n]" incr n set fname [file tail $fpath] set dscr "$dpre $fname" if { $alt != "" } { puts $file [format $xml_wptalt $la $lo $name $alt $sy $dscr $fname] } else { puts $file [format $xml_wpt $la $lo $name $sy $dscr $fname] } } puts $file $xml_footer if { $path != "stdout" } { close $file } return 0 } ##### logo window proc ShowGPSMan {} { # create widgets for displaying information about GPSMan in root window global SmallLogo VERSION COLOUR EPOSX EPOSY TXT wm protocol . WM_DELETE_WINDOW { exit 1 } frame .fr -relief flat -borderwidth 5 -bg $COLOUR(messbg) if { $SmallLogo != "" } { label .fr.im -image $SmallLogo -relief sunken pack .fr.im } label .fr.title -text "$TXT(GMtit) $VERSION" -relief sunken bind . <Button-1> About pack .fr.title -side top -pady 5 pack .fr -side top update idletasks return }