#!/usr/bin/perl -w

# @(#)$Id: gpsreplay,v 1.5 2004/01/18 19:37:24 ganter Exp $

# Copyright (C) 2002 - 2003 Tim Witham <twitham@surewest.net>

# (see the files README and COPYING for more details)

# replay track logs for gpsdrive by pretending to be a GPS (gpsd)

use strict;
use vars qw/*Server *Client/;	# socket handles
use Socket;
use Tk qw(MainLoop Ev DoOneEvent);
use Time::Local;
use POSIX qw(strftime);

# this should be calculated based on position but gpsdrive doesn't need it:
my $variation = 0;		# degrees magnetic deviation, negative for west
my $filter = 5.0002;		# ignore points < seconds.latlon from last
my $rate = 4;			# update rate, times per second
my $timescale = 1;		# speed up time by this factor
my $format = "%a %b %e %H:%M:%S %Y"; # strftime format for clocks
my $font = '7x13bold';		# font for the input/output text
my $port = 2947;		# port to listen on for gpsdrive (like gpsd)
my $connected = 0;		# whether gpsdrive is connected
my $paused;			# whether replay is paused
my $doc = [];			# documentation defines the bindings!
my $unit = 'nm';		# preferred units display
my $leglabel = '';		# label for the leg
my $alt = 0;			# current altitude

chdir "$ENV{HOME}/.gpsdrive" or warn "can't cd $ENV{HOME}/.gpsdrive: $!\n";
if (open FILE, "gpsdriverc") {
    while (<FILE>) {		# snag units from gpsdrive, if possible
	$unit = $1 if /units = (\S+)/;
    }
    close FILE;
}
$unit =~ s/miles/mi/;		# convert to my format
$unit =~ s/metric/km/;
$unit =~ s/nautic/nm/;

{				# listen for gpsdrive on the gpsd socket
    my $proto = getprotobyname('tcp');
    socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
    setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
	|| die "setsockopt: $!";
    bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
    listen(Server,SOMAXCONN) || die "listen: $!";
}

my $main = MainWindow->new;	# Tk window setup starts here

$main->fileevent(\*Server, 'readable', \&accept); # socket handlers
$SIG{PIPE} = \&close;

my($file, $log, $p, $time, $leg); # all reset by readfile
&readfile;			# initially with DATA below _END_, then
my $tmp = shift @ARGV;		# re-set with command-line or file-open
&readfile($tmp) if $tmp && -s $tmp;

my $top = $main->Frame->pack(qw/-fill x/);
my $canvas = $main->Canvas(qw/-width 800 -height 50 -highlightthickness 0
			   -scrollregion/, [0, 0, 800, 50])->pack;
my $scale = $main->Scale(qw/-orient horizontal -length 800 -variable/
			 => \$time)->pack;

my $bot = $main->Frame->pack(qw/-fill x/);
my $inlabel = $bot->Label(-font => $font)->pack(qw/-side left/);
my $in = $bot->Label(-font => $font)->pack(qw/-side right/);
$bot = $main->Frame->pack(qw/-fill x/);
my $outlabel = $bot->Label(-font => $font)->pack(qw/-side left/);
my $out = $bot->Label(-font => $font)->pack(qw/-side right/);

my $h = $top->Button(qw/-text Help -underline 0 -command/ => \&help
		     )->pack(qw/-side right/);
my $utctime = $top->Label->pack(qw/-side right/);
my $loctime = $top->Label(qw/-relief raised/)->pack(qw/-side right/);
my $menu = $top->Menubutton(qw/-underline 0 -relief raised
			    -text File -direction below/
			    )->pack(qw/-side left/);
$menu->command(qw/-label ~Open... -command/ => sub {
    my $tmp; &readfile($tmp) if $tmp = &fileDialog($main) });
$menu->command(qw/-label ~Filter -command/ => sub {
    &readfile('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units');
map {$rc->radiobutton(-label => "~$_", -value => $_, -variable => \$unit,
		      -command => [\&updatelabels]) } qw/nm mi km/;
$menu->command(-label => '~Run gpsdriveadf('-reload') if $file});
$menu->separator;
my $rc = $menu->cascade(-label => '~Units')