eval 'exec perl -x $0 ${1+"$@"}' # -*-perl-*-
  if 0;
#!perl -w
#
# Wrapper application for XEmacs.
# Opens a new window using gnuclient or gnudoit if possible, or starts
# xemacs if necessary.
# Keeps a list of recent files opened, which is stored in the
# AppMenu file in the application directory.
#
# Diego Zamboni, January 4, 2001.

use strict;
use File::Basename;
use File::Spec;
use Cwd;
use vars qw(
	    $AppDir
	    $Fcache
	    $Fcache_xml
	    @CACHE
	    $MAXFILES
	    $USECACHE
	    $res
	   );

######################################################################
# Configuration section

# Keep a cache of recent files
# Set to undef to disable using the cache
$USECACHE = 1;

# Number of recent files to remember. They are only remembered if they
# were opened through the application wrapper (either by dragging
# files into it or as a MIME-type association), not opened directly
# from xemacs.
$MAXFILES = 5;

# End configuration section
######################################################################

# Get the directory for the application
$AppDir=dirname($0);
$Fcache="$AppDir/AppMenu.txt";
$Fcache_xml="$AppDir/AppMenu";

update_cache() if $USECACHE;

if (@ARGV) {
  $_='"'.$_.'"' foreach @ARGV;
  $res=system("gnuclient -q @ARGV 2>/dev/null");
}
else {
  $res=system("gnudoit -q '(make-frame-on-display \"$ENV{DISPLAY}\")' 2>/dev/null");
}

if ($res) {
  # The command to start a client returned in error, so we start xemacs
  exec("xemacs @ARGV");
}

exit;

sub update_cache {
  # Read the current file cache
  if (-f $Fcache) {
    local @ARGV=($Fcache);
    # Take only the second field, changing "~" to my home path.
    @CACHE=map { $_=(split)[1]; s/^~/$ENV{HOME}/; $_ } <>;
  }
  else {
    @CACHE=();
  }

  # Check if we need one of the stored files
  if ($ARGV[0] && $ARGV[0] =~ /^--(\d+)/) {
    my $nfiles=@CACHE;		# Size of cache
    my $num=$1;			# Number of file requested
    if ($num<1 || $num>$nfiles) {
      warn "$0: Invalid file number ($num) - must be between 1 and $nfiles\n";
      exit;
    }
    @ARGV=($CACHE[$num-1]);
  }
  # For now we don't update the cache if a file from the menu was
  # selected. This has the effect that the selected file does not
  # "float" to the top of the menu. I find it more intuitive that
  # way, but can just as well be made otherwise.
  elsif (@ARGV) {
    # Update the cache, making all pathnames absolute (in case the
    # wrapper was invoked from the command line with a relative path)
    # We use unshift and reverse because the cache is kept in reverse
    # chronological order, so that the most recently accessed files
    # are at the top.
    unshift @CACHE, reverse map {
      File::Spec->file_name_is_absolute($_)?
	  $_:
	  File::Spec->catfile(cwd, $_);
    } @ARGV;
    # Remove duplicate files from the cache.
    my %dup;
    my @newcache;
    foreach (@CACHE) {
      push @newcache, $_ unless $dup{$_}++;
    }
    # Cut the cache to the appropriate maximum size
    @CACHE=splice @newcache, 0, $MAXFILES;
    # Rewrite the plain-text cache to disk
    if (open CACHE, ">$Fcache.new") {
      foreach (0 .. $#CACHE) {
	# Change HOME path back to "~" for shorter menu entries.
	$CACHE[$_] =~ s/^$ENV{HOME}/~/;
	print CACHE ($_+1)."\t".$CACHE[$_]."\n";
      }
      close CACHE;
      # We write to a new file and then rename it (instead of simply
      # overwriting the cache file) because that updates the mtime in
      # the application directory, which causes Rox to re-read the
      # application menu correctly.
      rename "$Fcache.new", $Fcache
	or warn "Error generating updated cache file: $!\n";
    }
    else {
      # Warn, but continue opening the files
      warn "Could not update file cache $Fcache: $!\n";
    }

    # Rewrite the xml cache to disk.
    if (open CACHE, ">${Fcache_xml}.new") {
      print CACHE qq(<?xml version="1.0"?>\n);
      print CACHE "<AppMenu>\n";
      foreach (0 .. $#CACHE) {
	# Change HOME path back to "~" for shorter menu entries.
	$CACHE[$_] =~ s/^$ENV{HOME}/~/;
	my $num=$_+1;
	print CACHE qq(<Item label="$CACHE[$_]" option="--$num"/>\n);
      }
      print CACHE "</AppMenu>\n";
      close CACHE;
      # We write to a new file and then rename it (instead of simply
      # overwriting the cache file) because that updates the mtime in
      # the application directory, which causes Rox to re-read the
      # application menu correctly.
      rename "${Fcache_xml}.new", $Fcache_xml
	or warn "Error generating updated cache file: $!\n";
    }
    else {
      # Warn, but continue opening the files
      warn "Could not update file cache $Fcache: $!\n";
    }
  }
}
