
######################################################################
#
#  ICEWM.PL - IceWM-specific code file for wmtheme
#
#  Documentation:
#
#    http://www.stu.uea.ac.uk/~markj/manual/
#    http://icewmfaq.cjb.net/

$tosite = 'icewm.themes.org';
$wm_executable = 'icewm';
$badnamechars .= '"\\';

my $icewm_version = 0;
my $icewm_userinstalled = 0;

checkuserinstall_icewm();

  ###
  #
  #  WM_GETDEFAULTDIRS
  #
  ###

sub wm_getdefaultdirs {
  verify_themedirs(0,
    "$home/.icewm/themes",
    '/usr/local/lib/X11/icewm/themes',   #  DEFAULT
    '/usr/lib/X11/icewm/themes',         #  Debian
    '/usr/X11R6/lib/X11/icewm/themes',   #  Red Hat
    '/usr/local/share/icewm/themes',     #  A guess
    '/usr/X11R6/lib/icewm/themes',       #  What Slackware would probably do
    '/usr/X11R6/share/icewm/themes'      #  Or this
    );
}

  ###
  #
  #  WM_SCANDIR
  #
  ###

sub wm_scandir {
  my $dir = shift;
  my (%scandirs, $rdir, $mtime);

  dbugout("scanning directory $dir") if $debug;
  opendir DH, $dir or choke("can't opendir $dir: $!");

    # Directories coming from the cache may not be the global/local
    # theme dir (a "main" theme dir), and a "main" theme dir must
    # be handled differently from an individual theme's dir; thus
    # this if/else.

  if (($localthemedir and $dir eq $localthemedir)
      or $dir eq $globalthemedir) {

    $scandirs{$dir} = (stat $dir)[9];
    while (defined($entry = readdir DH)) {
       ## IceWM won't recognize a theme dir if there's no default.theme

      if ($entry !~ /^\.\.?$/ and
          -d "$dir/$entry" and
          -f "$dir/$entry/default.theme") {
        ($rdir, $mtime) = registerthemedir_icewm("$dir/$entry");
        $scandirs{$rdir} = $mtime;
      }
    }
    closedir DH;

  } elsif (-f "$dir/default.theme") {

       # Since this is an individual theme's dir, one doesn't look into
       # it for individual theme dirs, but rather use it if it's valid
       # ( == has the default.theme file).

      ($rdir, $mtime) = registerthemedir_icewm($dir);
      $scandirs{$rdir} = $mtime;

  }
  %scandirs;
}

sub registerthemedir_icewm {
  my ($dir, $isnew) = @_;
  my $oid = (stat $dir)[4];
  my $mtime = (stat _)[9];
  my ($entry, $name);

  choke("can't grok directory $dir") unless ($name) = $dir =~ /([^\/]+)$/;

   ##   notes
   #
   #  - icewm won't recurse into subdirs
   #  - the name of the directory is the name of the theme
   #  - themes are required to be in a subdirectory (no name.theme
   #    plopped into the themes dir)
   #

  dbugout("scanning directory $dir") if $debug;
  opendir STD, $dir or choke("can't opendir $dir: $!");
  while (defined($entry = readdir STD)) {
    if (!-d "$dir/$entry" and $entry =~ /(.+)\.theme$/) {
      if ($1 eq 'default') {
        dbugout("keeping default of \"$name\"") if $debug;
        createthemerec($name, $dir, $oid);
      } else {
        dbugout("keeping \"$name/$1\"") if $debug;
        createthemerec("$name/$1", "$dir/$entry", $oid);
        cache_themedir("$name/$1"), $isnew = 0 if $isnew;
      }
    }
  }
  closedir STD;
  ($dir, $mtime);
}


  ###
  #
  #  WM_INSTALLTHEME
  #
  ###

sub wm_installtheme {
  my ($location, $filename, $defname) = @_;

  unless (-d $location) {
    choke("can't use $location as a theme archive");
  }

  my ($themename, $possiblename, $destthemedir, $answer, $cdir);

  if ($> == 0) {
    if (!$globalthemedir) {
      choke("no global theme directory could be identified",
        "perhaps IceWM is not installed on this system?");
    }
    $destthemedir = $globalthemedir;
  } else {
    userinstall_icewm();
    $destthemedir = $localthemedir;
  }

  $cdir = findsubdirwithfile($location, 'default.theme') or
    choke('bad theme - no "default.theme" found');

  if ($defname) {
    $possiblename = $defname;
  } elsif ($cdir =~ /\/([^\/]+)$/) {
    $possiblename = $1;
  } else {
    choke("internal error: can't grok $cdir");
  }
  $themename = checkname($possiblename);

  syscmd('mv', $cdir, "$destthemedir/$themename");
  registerthemedir_icewm("$destthemedir/$themename", 1);

  $themename;
}

  ###
  #
  #  WM_ACTIVATETHEME
  #
  ###

sub wm_activatetheme {
  my ($themename, $explicit) = @_;
  my ($themefile, $prefs);
  my $path = $themes{$themename}{path};

  if (!$icewm_userinstalled) {
    if ($explicit) {
      userinstall_icewm();
    } else {
      return;
    }
  }

  if (-d $path) {
    if ($path =~ /\/([^\/]+)$/) {
      $themefile = "$1/default.theme";
    } else {
      choke("internal error: can't grok theme dir $path");
    }
  } elsif ($path =~ m|/([^/]+/[^/]+)$|) {
    $themefile = $1;
  } else {
    choke("internal error: can't grok theme file $path");
  }

  $prefs = slurpfile("$home/.icewm/preferences");
  if ($prefs =~ s/^\s*Theme\s*=.*$/Theme=\"$themefile\"/m) {
  } else {
    $prefs .= "\nTheme=\"$themefile\"\n";
  }
  stowfile("$home/.icewm/preferences", $prefs);
  sigbyname(HUP, $wm_executable);
}

  ###
  #
  #  WM_UNINSTALLTHEME
  #
  ###

sub wm_uninstalltheme {
  my $themename = shift;

  if (dirwipe($themes{$themename}{path}, 1)) {
    if ($themename !~ /\//) {
      ## A base theme: dirwipe() has erased its subthemes, so
      ## forget those explicitly here.
      foreach (keys %themes) {
        if (/^\Q$themename\E\/./) {
          delete $themes{$_};
        }
      }
    }
    1;
  } else {
    0;
  }
}

  ###
  #
  #  WM_RENAME
  #
  ###

sub wm_rename {
  my ($old, $new) = @_;
  my ($newpath, $base, $sub);

   # 0. too many slashes: error

  if ($new =~ /\/.*\//) {
    choke("can't handle \"$new\": too many /s");

   # 1. "main/oldname" -> "main/newname"

  } elsif (($base, $sub) = $new =~ m!([^/]+)/([^/]+)!) {
    if ($old !~ /\//) {
      choke("can't rename a base theme to a subtheme");
    } elsif ($old !~ /^\Q$base\E\/[^\/]+\.theme$/) {
      choke("can't shift one subtheme to another base theme");
    }
    $newpath = $themes{$old}{path};
    $newpath =~ s!/\Q$old\E\.theme$!/$base/$sub.theme! or
      choke("internal error: can't find \"$old.theme\" in $themes{$old}{path}");
    rename $themes{$old}{path}, $newpath or
      choke("can't rename \"$themes{$old}{path}\" to \"$newpath\": $!");
    return $newpath;
  } else {
    $new =~ s/\///;

   # 2. "main/oldname" -> "newname"

    if (($base, $sub) = $old =~ m!([^/]+)/([^/]+)!) {
      $newpath = $themes{$old}{path};
      $newpath =~ s/\/\Q$old\E\.theme$/\/$base\/$new.theme/ or
        choke("internal error: can't find \"$old.theme\" in $themes{$old}{path}");
      rename $themes{$old}{path}, $newpath or
        choke("can't rename \"$themes{$old}{path}\" to \"$newpath\": $!");
      return $newpath, "$base/$new";

   # 3. "oldmain" -> "newmain"

    } else {
      my %subthemes = ();
      $base = $themes{$old}{path};
      $base =~ s!/\Q$old\E$!! or
        choke("internal error: can't find \"$old\" in \"$base\"");
      rename $themes{$old}{path}, "$base/$new" or
        choke("can't rename \"$themes{$old}{path}\" to \"$base/$new\": $!");

        # 3a. All subthemes of "oldmain" must become "newmain/name"

        # note that the temporary list created by 'foreach' is critical here
      foreach (keys %themes) {
        if ($themes{$_}{path} =~ m!/\Q$old\E/([^/]+)\.theme$! and
            $1 ne 'default') {
          $subtheme = $1;
          $themes{"$new/$subtheme"} = $themes{$_};
          $themes{"$new/$subtheme"}{path} = "$base/$new/$subtheme.theme";
          delete $themes{$_};
          cache_themedir("$new/$subtheme");
        }
      }

      return "$base/$new";
    }
  }
}

  ###
  #
  #  WM_VERSIONOK
  #
  ###

sub wm_versionok {
  my $rqver = shift;
  my $iver;

  dbugout("judging version \"$rqver\"") if $debug;
  $rqver =~ /(\d+(\.\d+))/ and $rqver = $1;
  if ($iver = getversion_icewm()) {
    if ($iver < 0.9) {
      return $rqver < 0.9;
    } elsif ($iver < 1.1) {
      return $rqver < 1.1;
    } else {
      return minorvermatch($rqver, $iver);
    }
  } else {
    return 1;
  }
}

sub getversion_icewm {
  if (!defined $icewm_version) {
    my $icever = `icewm -v 2>&1`;
    if ($icever =~ /icewm\s+(\d+\.\d+)/i) {
      $icewm_version = $1;
      dbugout("dealing with IceWM version $icewm_version")
        if $debug;
    } else {
      dbugout("got incomprehensible \"$icever\" from icewm -v")
        if $debug;
    }
  }
  $icewm_version;
}

sub checkuserinstall_icewm {
  return if $icewm_userinstalled;

  if (-d "$home/.icewm" and
      -f "$home/.icewm/preferences" and
      -d "$home/.icewm/themes") {
    $icewm_userinstalled = 1;
  }
}

sub userinstall_icewm {
  return if $icewm_userinstalled;

  my ($answer, $preffile);

  print "Local IceWM configuration files in ~/.icewm are required. Shall I create this\n";
  print "directory and copy files into it? [Y/n] ";
  $answer = <STDIN>;

  if ($answer =~ /^([yY]|\s*$)/) {

    print "$programname: setting up ~/.icewm\n";

    if (! -d "$home/.icewm") {
      mkdir "$home/.icewm", 0755 or
        choke("can't mkdir $home/.icewm: $!");
    }

    if (! -d "$home/.icewm/themes") {
      mkdir "$home/.icewm/themes", 0755 or
        choke("can't mkdir $home/.icewm/themes: $!");
    }

    if (! -f "$home/.icewm/preferences") {

      if ($globalthemedir and
          $globalthemedir =~ m|(.+)/[^/]+$|
          and -f "$1/preferences") {
        $preffile = "$1/preferences";

      } elsif (-f '/etc/X11/icewm/preferences') {
         ##  - Debian puts preferences here, separate from the global themes dir
        $preffile = '/etc/X11/icewm/preferences';

      } else {
        choke("can't find the system-wide preferences file!");
      }

      copyfile($preffile, "$home/.icewm/preferences");
    }

    $localthemedir = "$home/.icewm/themes";
    $icewm_userinstalled = 1;

  } else {
    choke("cancelled.");
  }
}

1;

