
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;

#
# PilotDrop - Version 0.9 alpha
#  -- Alan Harder, 4/97
#     Alan.Harder@Sun.COM
#
# PilotDrop lets you drag & drop files into your PilotManager SyncMemo
# folders so they will be transferred to your pilot on your next HotSync.
# You can drag files or text from Mailtool, File Manager or Text Editor.
# Simply drop into the folder for the Memo category you want.
#
# Usage: PilotDrop [-e]
#    -e = Run text editor on results after catching drop
#
# NOTE: doesn't work with Tk400.202 due to a bug in Tk.  The bug is actually
# easy to fix from the error message when you run PilotDrop (you just need
# to add some quotes around a string).
#

use Tk;
use Tk::DropSite qw(Sun);

my (%GoodTarget);		# List of D&D targets we care about
my (@Category, $tmp);		# List of Pilot Categories
my ($dir1, $dir2, $dir3);	# Icon bitmaps for GUI
my ($top);			# Main window
my ($errdlg, $errtext);		# Dialog, text widget for reporting errors
my ($gEditOnDrop) = (0);	# Whether to run textedit after drop

die "Error reading SyncMemo preferences file:\n\
~/.pilotmgr/SyncMemo/SyncMemo.prefs\n"
    if (! -f "$ENV{HOME}/.pilotmgr/SyncMemo/SyncMemo.prefs");

eval `cat $ENV{HOME}/.pilotmgr/SyncMemo/SyncMemo.prefs`;
$PREFS;
die "No setting for Memo Directory found in SyncMemo preferences.\n"
    unless(defined($PREFS->{gHomeDirectory}));

$tmp = $PREFS->{gHomeDirectory};
die "Memo directory from SyncMemo preferences doesn't exist:\n$tmp\n"
    unless(-d $tmp);

$tmp =~ s|/|\\/|g;
@Category = split("\n",
    `find $PREFS->{gHomeDirectory} -type d -print | \
     sed -e 's/^$tmp//' -e '/^\$/ d' -e 's/^\\///'`);

%GoodTarget = (
	"TEXT" => {},
	"STRING" => {},
	"NAME" => {},
	"FILE_NAME" => {},
	"TIMESTAMP" => {},
);

die "usage: $0 [-e]\n -e = Run text editor on results after catching drop\n"
    if ($ARGV[0] eq "-h");
$gEditOnDrop = 1 if ($ARGV[0] eq "-e");

&CreateGui;
MainLoop;
exit;

#########################################################################

sub CreateGui
{
    my ($btn, $cat);

    $top = MainWindow->new();
    $top->title("Pilot Drop");

    $dir1 = $top->Bitmap("dir1", -data => &icondata1, -maskdata => &iconmask);
    $dir2 = $top->Bitmap("dir2", -data => &icondata2, -maskdata => &iconmask);
    $dir3 = $top->Bitmap("dir3", -data => &icondata3, -maskdata => &iconmask);

    foreach $cat (@Category)
    {
	&AddDir($top, $cat);
    }

    # Create error dialog
    $errdlg = $top->Toplevel(-title => "Drop Error");
    $errdlg->withdraw;
    $errdlg->transient($errdlg->toplevel); # get rid of minimize box

    $errtext = $errdlg->Label(-wraplength => '3i', -justify => 'left');
    $errtext->pack(-side => "top", -fill => "x", -expand => 1);

    $btn = $errdlg->Button(-text => "Ok",
			   -command => sub{ $errdlg->withdraw });
    $btn->pack;
}

sub AddDir
{
    my ($win, $text) = @_;
    my ($frame, $textlabel, $imagelabel) = $win->Frame;

    $imagelabel = $frame->Label(-image => $dir1);
    $imagelabel->pack(-side => "top");
    $textlabel = $frame->Label(-text => $text);
    $textlabel->pack;

    $frame->DropSite(-dropcommand => [\&Drop, $frame, $imagelabel, $text],
		     -entercommand => [\&Select, $imagelabel]);
    $frame->pack(-side => "left");
}

sub Select
{
    my ($label, $enter) = @_;

    if ($enter == 1)
    {
	$label->configure(-image => $dir2);
    } elsif ($enter == 2) {
	$label->configure(-image => $dir3);
	$label->after(1500, [\&Select, $label, 0]);
    } elsif ($enter == 3) {
	$label->configure(-image => $dir2);
	$label->after(3000, [\&Select, $label, 0]);
    } else {
	$label->configure(-image => $dir1);
    }
}

sub ReadDrop
{
    my ($drop, $seln) = @_;
    my (@targets, $targ, %vals);

    @targets = $drop->SelectionGet(-selection => $seln, "TARGETS");
#print "TARGETS: "; my ($b); foreach $b (@targets) { print "$b "; } print "\n";
    foreach $targ (@targets)
    {
	$vals{$targ} = $drop->SelectionGet(-selection => $seln, $targ)
	    if (defined($GoodTarget{$targ}));
    }

    return(%vals);
}

sub Drop
{
    my ($drop, $image, $category ,$seln, $x, $y) = @_;
    my (%DND, $text, $app, $dir, $fname);

    %DND = &ReadDrop($drop, $seln);

    $app = defined($DND{NAME}) ? $DND{NAME} : "";
    $dir = $PREFS->{gHomeDirectory} . "/" . $category;
    mkdir($dir, 0755) unless (-d $dir);
    if (defined($DND{FILE_NAME}))
    {
	$fname = $DND{FILE_NAME};
	$fname =~ s|^.*/([^/]+)$|$1|;
	$fname = $dir . "/" . $fname;
    } else {
	$fname = &mktemp($dir);
    }

    $text = defined($DND{TEXT}) ? $DND{TEXT} : "";
    $text = $DND{STRING} unless ($text || !defined($DND{STRING}));

    if ($app eq "mailtool")
    {
	my ($oldtext, $body, $in, $newin, $line) = ($text, 0, 0);
	$text = "";

	foreach $line (split("\n", $oldtext))
	{
	    $in = $newin;
	    $newin = 0;
	    next unless ($body				||
			 $line =~ /^[Ff]rom/		||
			 $line =~ /^[Tt]o: /		||
			 $line =~ /^[Dd]ate: /		||
			 $line =~ /^[Ss]ubject: /	||
			 $line =~ /^[Rr]eply-[Tt]o: /	||
			 $line =~ /^[Bb]?[Cc][Cc]: /	||
			 $line =~ /^[Ss]ender: /	||
			 ($line =~ /^\s/ && $in)	||
			 $line =~ /^$/			);

	    $body++ if ($line =~ /^$/);
	    $newin = 1;

	    $text .= "$line\n";
	}
    }

    unless ($text)
    {
	$errtext->configure(-text => "No text caught from drop.");
	$errdlg->Popup(-popanchor => 'c',-popover => $top,-overanchor => 'c');
	&Select($image, 3);
	return;
    }

    unless (open(FD, ">$fname"))
    {
	$errtext->configure(-text => "Error opening $fname for write.");
	$errdlg->Popup(-popanchor => 'c',-popover => $top,-overanchor => 'c');
	&Select($image, 3);
	return;
    }

    print FD $text;
    close(FD);

    &Select($image, 2);

    exec "textedit $fname ; rm -f $fname%" if ($gEditOnDrop && !fork);
}

sub mktemp
{
    my ($dir) = @_;
    my ($fname) = "memo0000";

    while (1)
    {
	return ("$dir/$fname.txt") if (! -e "$dir/$fname.txt");
	$fname++;
    }
}

######## ICON DATA ########

sub iconmask
{
    return <<'EOF';
#define nfm_dir.mask_width 32
#define nfm_dir.mask_height 32
#define nfm_dir.mask_x_hot 16
#define nfm_dir.mask_y_hot 16
static char nfm_dir.mask_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x3f,
   0xfe, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff};
EOF
}

sub icondata1
{
    return <<'EOF';
#define nfm_dir.icon_width 32
#define nfm_dir.icon_height 32
#define nfm_dir.icon_x_hot 16
#define nfm_dir.icon_y_hot 16
static char nfm_dir.icon_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x20,
   0xfe, 0xff, 0x07, 0x40, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff};
EOF
}

sub icondata2
{
    return <<'EOF';
#define dir2_width 32
#define dir2_height 32
#define dir2_x_hot 16
#define dir2_y_hot 16
static char dir2_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x3f,
   0xfe, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff};
EOF
}

sub icondata3
{
    return <<'EOF';
#define dir3_width 32
#define dir3_height 32
#define dir3_x_hot 16
#define dir3_y_hot 16
static char dir3_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x20,
   0xfe, 0xff, 0x07, 0x40, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x20, 0x02, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x04, 0x10, 0xc0, 0x01, 0x04, 0x10, 0xc0,
   0x01, 0x08, 0x08, 0xc0, 0x01, 0xf0, 0x07, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
   0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff};
EOF
}

