#!/usr/bin/perl -w
#
# Anand Natrajan (www.anandnatrajan.com)
# Mon Jun 10 15:30:00 EST 2002
#
# Program to display photos in multiple ways.

use File::Basename;
use File::Path;
use POSIX ":sys_wait_h";
use Getopt::Long;
use Time::Local;
use IO::Handle;
$| = 1;

$MyName = basename($0);
$MyName =~ s/.*\\//;   # For Windows paths.
# Valid formats for pictures.
@PixForms = ("jpg", "JPG", "jpeg", "JPEG", "gif", "GIF");
# Valid formats for captions.
@TxtForms = ("txt", "TXT", "htm", "HTM", "html", "HTML", "shtml", "SHTML",
	"php", "PHP");
# Valid formats for sounds.
@SndForms = ("mid", "MID", "wav", "WAV", "mp3", "MP3");
# Default output types.
@OutForms = ("table", "thumbnail", "slideshow");

# Create a default record for displaying pictures in various formats. This
# built-in default will be overridden by defaults the user specifies from
# the command-line, which in turn will be overridden by any
# picture-specific requests in the order files.
%PixRec = (
	tableWidth        => 250,   # 250 pixels width
	tableHeight       => 'a',   # automatic height
	thumbnailWidth    => 100,   # 100 pixels width
	thumbnailHeight   => 'a',   # automatic height
	thumbnailCols     =>   5,   # 5 columns per row
	slideshowWidth    => 500,   # 500 pixels width
	slideshowHeight   => 'a',   # automatic height
	slideshowInterval =>   5    # 5 seconds before moving on
);
@BackColours = ("8fbc8f", "b5a642", "cococo", "d8bfd8", "d9d9f3",
	"ebc79e", "ffffff");
@BackImages = (
	"http://wp.netscape.com/assist/net_sites/bg/fabric/gray_fabric.gif",
	"http://wp.netscape.com/assist/net_sites/bg/fabric/pink_fabric.gif",
	"http://wp.netscape.com/assist/net_sites/bg/fabric/yellow_fabric.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/lipurple_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/blue_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/yellow_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/bluewind_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/embossed_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/weave/funkyblue_weave.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/gray_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/red_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/yellow_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/blue_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/multicolor1_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/multicolor2_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/multicolor3.gif",
	"http://wp.netscape.com/assist/net_sites/bg/rock/smblue_rock.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/blue_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/greenred_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/redgray_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/purpleblue_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/olivepink_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/purple_marble1.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/lavender_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/lavender_swirl_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/70s_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/purple_marble2.gif",
	"http://wp.netscape.com/assist/net_sites/bg/marble/tanblue_marble.gif",
	"http://wp.netscape.com/assist/net_sites/bg/metal/brushed_aluminum.gif",
	"http://wp.netscape.com/assist/net_sites/bg/metal/gray_aluminum.gif",
	"http://wp.netscape.com/assist/net_sites/bg/metal/corrugated_metal.gif",
	"http://wp.netscape.com/assist/net_sites/bg/stucco/gray_stucco.gif",
	"http://wp.netscape.com/assist/net_sites/bg/stucco/green_stucco.gif",
	"http://wp.netscape.com/assist/net_sites/bg/stucco/red_stucco.gif",
	"http://wp.netscape.com/assist/net_sites/bg/stucco/yellow_stucco.gif",
	"http://wp.netscape.com/assist/net_sites/bg/stucco/smgreen_stucco.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/blue_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/bluewhite_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/greenwhite_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/olive_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/purple_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/tan_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/teal_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/yellow_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/bluesand_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/orange_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/bright_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/lavender_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/multidot_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/olivered_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/peach_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/red_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/smblue_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/smbluewhite_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/summer_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/wind_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/paper/redwhite_paper.gif",
	"http://wp.netscape.com/assist/net_sites/bg/dots/grey_dots.gif",
	"http://wp.netscape.com/assist/net_sites/bg/dots/1960s_dots.gif",
	"http://wp.netscape.com/assist/net_sites/bg/dots/multicolor1_dots.gif",
	"http://wp.netscape.com/assist/net_sites/bg/water/raindrops_dark.gif",
	"http://wp.netscape.com/assist/net_sites/bg/water/raindrops_light.gif",
	"http://wp.netscape.com/assist/net_sites/bg/water/clouds.gif"
);

my $Now = localtime;

sub Usage
{
    print STDERR <<EOF;
Usage: $MyName [-help] [-about] [-v[erbose]] [-debug] <dir>
	[-o[ut] <format>]+ [-order <file>] [-clean]
EOF

	if ($#_ > -1)
	{
		print STDERR <<EOF;

$MyName enables displays of pictures in directories (called albums).
A picture is any file with one of the extensions:
EOF
		print STDERR "\t" . join(" ", @PixForms) . "\n";
		print STDERR <<EOF;
A caption is any file with one of the extensions:
EOF
		print STDERR "\t" . join(" ", @TxtForms) . "\n";
		print STDERR <<EOF;
A tune is any file with one of the extensions:
EOF
		print STDERR "\t" . join(" ", @SndForms) . "\n";
		print STDERR <<EOF;

Pictures are displayed in one or more of the following forms (default, all):
EOF
		print STDERR "\t" . join(" ", @OutForms) . "\n";
		print STDERR <<EOF;

The simplest way to display an album is:
    $MyName <dir>
where <dir> is an album containing pictures and captions. The above line
will create <dir>/index.html. Browsing that file will show your pictures.

    -help                   : Print this help screen.
    -about                  : Print information about the author.
    -v[erbose]              : Turn verbose mode on.
    -debug                  : Turn debug mode on. Warning! Copious output.
    <dir>                   : Find picture files in <dir>. Can be specified
                              multiply. Will recurse through sub-directories.
    -o[ut] <format>         : Display results in <format> form only.
                              Default is all formats. Formats can be
                              appended with colon-separated parameters, e.g.,
                                  table:<width>:<height>
                                  thumbnail:<width>:<height>:<cols>
                                  slideshow:<width>:<height>:<interval>
                              where
                                  <width> can be a number, a percentage,
                                      'a' for automatic or empty for default
                                  <height> can be a number, a percentage,
                                      'a' for automatic or empty for default
                                  <cols> can be a number, 'a' or empty
                                      for default
                                  <interval> can be a number, 'a' or empty
                                      for default
    -order <file>           : Sort pictures in the order in <file> in each
                              album. Default is alphanumerical. <file> should
                              contain a list of names, one per line, with
                              optional formats after spaces. Format is same
                              as in -out flag.
    -clean                  : Cleans specified albums of previous run of
                              $MyName and terminates.
    -cd                     : Makes the specified albums "CD-ready", i.e.,
                              creates a <dir>/../autorun.inf file.

EOF
	}
    exit(1);
}

sub About
{
    print STDERR <<EOF;

$MyName enables displays of pictures.

$MyName is authored by Anand Natrajan.
URL: www.anandnatrajan.com.

$MyName is freeware. Please use it as you wish.
Naturally, the author is not liable if it breaks.
Send suggestions, comments and criticism to author.

EOF
	exit(0);
}

# Print only if verbose mode is on.
sub Vprint
{
	foreach my $line (@_) { print STDERR $line if ($opt_v); }
}

# Print only if debug mode is on.
sub Dprint
{
	foreach my $line (@_) { print STDERR $line if ($opt_debug); }
}

@Primes = (); $Primes[0] = 2;
# Check if integer is prime.
sub prime
{
	my $num = shift;
	return 1 if ($num == 0 or $num == 1);  # Pretend 0 and 1 are prime.
	foreach my $div (@Primes)
	{
		return 1 if ($num == $div);
		return 0 if (int($num / $div) * $div == $num);
	}
	push(@Primes, $num);  # Add this number as a prime.
	return 1;
}

# Write a string to a named file.
sub write
{
	my $file = shift;
	my $str = shift;
	open(FILE, ">$file") or die "Couldn't open $file: $!\n";
	&Dprint("Writing $file.\n");
	print FILE $str;
	close FILE;
}

### MAIN ###

&GetOptions("help" => \$opt_help, "about" => \$opt_about, "debug",
	"v|verbose", "o|out=s@", "order=s", "clean" => \$opt_clean,
	"cd" => \$opt_cd) or &Usage;
&Usage(1) if ($opt_help);
&About if ($opt_about);
$opt_v = 1 if (defined($opt_debug));
@opt_d = @ARGV;

if (defined($opt_clean))
{
	my @ProbeDirs = @opt_d;
	# Start with the specified directories, then spiral in and remove junk
	# as we go through. The logic to add directories to traverse is used
	# below as well for actual work.
	while ($#ProbeDirs >= 0)
	{
		my $end = ($#ProbeDirs == 0) ? "" : "s";
		&Dprint("Cleaning " . ($#ProbeDirs + 1) . " album$end.\n");
		my $dir = shift(@ProbeDirs);
		&Vprint("Cleaning $dir.\n");
		# Remove all the files for auto-running on a CD.
		unlink("$dir/../autorun.inf");
		&Dprint("\tCleaning $dir/../autorun.inf.\n");
		unlink("$dir/$MyName.bat");
		&Dprint("\tCleaning $dir/$MyName.bat.\n");
		opendir(DIR, $dir) or die "Can't open album $dir!\n";
		foreach my $file (readdir(DIR))
		{
			next if ($file eq "." or $file eq "..");  # Skip the obvious.
			# All our files are .html files prefixed with a '.'. Except
			# for index.html, which we'll overwrite.
			if ($file eq "index.html" or $file =~ /\.[a-zA-Z0-9]*\.html/)
			{
				unlink("$dir/$file");
				&Dprint("\tCleaning $dir/$file.\n");
			}
			# Add sub-directories to the list of directories we should probe.
			push(@ProbeDirs, "$dir/$file") if (-d "$dir/$file");
		}
		closedir DIR;    # ... and that's that.
	}
	exit(0);
}

my $opt_table = undef;
my $opt_thumbnail = undef;
my $opt_slideshow = undef;
if (defined(@opt_o))
{
	foreach my $outform (@opt_o)
	{
		# The output formats may contain ':'-separated format suggestions.
		# For example, "-o table:34:57%"... says that for the table format,
		# widths should be 34 and heights should be 57%. If present, these
		# requests override the default table style.
		if ($outform =~ /^table/)
		{
			$opt_table = 1;
			# See if ':'-separated parameters are added to this parameter.
			my ($option, $width, $height) = split(/:/, $outform);
			# if not defined, stick with defaults.
			if (defined($width) and $width !~ /^\s*$/)
			{
				if ($width =~ /^a/)
				{
					$PixRec{'tableWidth'} = 'a';  # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'tableWidth'} = $width;
				}
			}
			# if not defined, stick with defaults.
			if (defined($height) and $height !~ /^\s*$/)
			{
				if ($height =~ /^a/)
				{
					$PixRec{'tableHeight'} = 'a';   # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'tableHeight'} = $height;
				}
			}
		}
		elsif ($outform =~ /^thumbnail/)
		{
			$opt_thumbnail = 1;
			# See if ':'-separated parameters are added to this parameter.
			my ($option, $width, $height, $cols) = split(/:/, $outform);
			# if not defined, stick with defaults.
			if (defined($width) and $width !~ /^\s*$/)
			{
				if ($width =~ /^a/)
				{
					$PixRec{'thumbnailWidth'} = 'a';  # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'thumbnailWidth'} = $width;
				}
			}
			# if not defined, stick with defaults.
			if (defined($height) and $height !~ /^\s*$/)
			{
				if ($height =~ /^a/)
				{
					$PixRec{'thumbnailHeight'} = 'a';   # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'thumbnailHeight'} = $height;
				}
			}
			# if not defined, stick with defaults.
			if (defined($cols) and $cols !~ /^\s*$/)
			{
				if ($cols !~ /^a/) # else stick with defaults.
				{
					# Hope that's a number.
					$PixRec{'thumbnailCols'} = $cols;
				}
			}
		}
		elsif ($outform =~ /^slideshow/)
		{
			$opt_slideshow = 1;
			# See if ':'-separated parameters are added to this parameter.
			my ($option, $width, $height, $secs) = split(/:/, $outform);
			# if not defined, stick with defaults.
			if (defined($width) and $width !~ /^\s*$/)
			{
				if ($width =~ /^a/)
				{
					$PixRec{'slideshowWidth'} = 'a';  # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'slideshowWidth'} = $width;
				}
			}
			# if not defined, stick with defaults.
			if (defined($height) and $height !~ /^\s*$/)
			{
				if ($height =~ /^a/)
				{
					$PixRec{'slideshowHeight'} = 'a';   # automatic width selection.
				}
				else
				{
					# Hope that's a number or percentage.
					$PixRec{'slideshowHeight'} = $height;
				}
			}
			# if not defined, stick with defaults.
			if (defined($secs) and $secs !~ /^\s*$/)
			{
				if ($secs !~ /^a/) # else stick with defaults.
				{
					# Hope that's a number.
					$PixRec{'slideshowInterval'} = $secs;
				}
			}
		}
		else
		{
			print STDERR "\"$outform\" is an invalid output format.\n\n"
				and &Usage;
		}
	}
}
else
{
	$opt_table = $opt_thumbnail = $opt_slideshow = 1;
}

$TotalPictures = 0;
@ProbeDirs = @opt_d;
push(@ProbeDirs, undef);
# This sentinel value indicates we should start putting parent dir links.
$Uplink = 0;

# The style below is put on each HTML page generated.
$Style = <<EOF;
<style type="text/css">
	<!-- /* old-style browsers can ignore this */
	body { text: black }
	a:link { color: blue; }
	a:visited { color: red; }
	a:hover { color: green; }
	a:active { background: yellow; }
	/* end old-style browser's ignorance */ -->
</style>
EOF

# The signature below is put on each HTML page generated.
$Signature = <<EOF;
<hr align=left width=30%>
<i>$Now</i>
<!-- Created by Anand Natrajan (www.anandnatrajan.com). -->
EOF

# Figure out all the directories we need to probe.
# Search each of those directories to make up the HTML pages.
$PixPattern = "(" . join("|", @PixForms) . ")";
while ($#ProbeDirs >= 0)
{
	# Set initial values for each section in each kind of output.
	my $MainPreHTML = "";
	my $MainHTML = "";
	my $MainNavHTML = "";
	my $TableHTML = "";
	my $ThumbnailHTML = "";
	my $SlideShowHTML = "";
	my $SlideShowNavHTML = "";

	# Set the initial style for each kind of picture.
	my %Rec = %PixRec;

	my $CurrentPictures = 0;
	my $end = ($#ProbeDirs == 0) ? "" : "s";
	&Dprint("Checking " . ($#ProbeDirs + 1) . " album$end.\n");
	my $dir = shift(@ProbeDirs);
	if (!defined($dir))
	{
		$Uplink = 1;
		next;
	}
	&Vprint("Checking $dir for pictures and albums.\n");

	my $bgcolour = $BackColours[rand(@BackColours)];
	$MainPreHTML .= <<EOF;
<html>
<head>
	<title>$dir</title>
	$Style
</head>
<body bgcolor=$bgcolour>
<center>
<h1>Display of $dir</h1>
<hr>
EOF

	if (defined($opt_slideshow))
	{
		$MainNavHTML .= <<EOF;
&nbsp;&nbsp;&nbsp;[<a href=.slideshow.html>Slide&nbsp;Show&nbsp;View</a>]
EOF
	}

	if (defined($opt_table))
	{
		$MainNavHTML .= <<EOF;
&nbsp;&nbsp;&nbsp;[<a href=.table.html>Table&nbsp;View</a>]
EOF
	}
	$bgcolour = $BackColours[rand(@BackColours)];
	$TableHTML .= <<EOF;
<html>
<head>
	<title>Table View of $dir</title>
	$Style
</head>
<body bgcolor=$bgcolour>
<center>
<h1>Table View of $dir</h1>
<hr>
<table border=1>
EOF

	if (defined($opt_thumbnail))
	{
		$MainNavHTML .= <<EOF;
&nbsp;&nbsp;&nbsp;[<a href=.thumbnail.html>Thumbnail&nbsp;View</a>]
EOF
	}
	$bgcolour = $BackColours[rand(@BackColours)];
	$ThumbnailHTML .= <<EOF;
<html>
<head>
	<title>Thumbnail View of $dir</title>
	$Style
</head>
<body bgcolor=$bgcolour>
<center>
<h1>Thumbnail View of $dir</h1>
<hr>
<table>
	<tr>
EOF

	$MainNavHTML .= "<hr>\n";
	if ($Uplink)
	{
		$MainHTML .= <<EOF;
<i><a href=../index.html>&lt;up one level&gt;</a></i><br>
EOF
	}

	# If an order file is specified, look for it in each directory. Else,
	# just assume user wants alphanumeric sorting of entries.
	my @entries = (); my $found = 0;
	if (defined($opt_order))
	{
		&Vprint("\tOrdering files in $dir.\n");
		if (-e "$dir/$opt_order")
		{
			&Dprint("\t\tFound order file $dir/$opt_order.\n");
			$found = 1;
			open(ORDER, "$dir/$opt_order") or
				die "Can't open order file $dir/$opt_order!\n";
			foreach (<ORDER>)
			{
				chomp; s/^\s+//; s/\s+$//;
				my ($entry, $rest) = split;
				# Right here, we need to parse "rest" and look at them for
				# stylistic hints. Also, we need to create an associative
				# array to store the hints for each file.
				push (@entries, $entry);
			}
			close ORDER;
		}
		else
		{
			warn "\t\tCouldn't find order file $dir/$opt_order!\n";
		}
	}
	if (!$found)
	{
		&Dprint("\t\tNo ordering for $dir.\n");
		opendir(DIR, $dir) or die "Can't open album $dir!\n";
		foreach my $file (readdir(DIR))
		{
			push(@entries, $file);
		}
		closedir DIR;
		@entries = sort @entries;
	}

	foreach my $file (@entries)
	{
		next if ($file eq "." or $file eq "..");  # Skip the obvious.
		# Need the existence check below if order is specified, really.
		if (!-e "$dir/$file")
		{
			warn "Couldn't find file $dir/$file in $dir/$opt_order!\n";
			next;
		}
		# Add sub-directories to the list of directories we should probe.
		if (-d "$dir/$file")
		{
			&Dprint("\tFound album $dir/$file.\n");
			push(@ProbeDirs, "$dir/$file");
			$MainHTML .= <<EOF;
<a href=$file/index.html>$file</a><br>
EOF
			next;
		}
		next if (!-f "$dir/$file");  # Neither a directory, nor a file...

		# Pick an image for the slideshow.
		my $bgimage = $BackImages[rand(@BackImages)];

		# Consider only those pictures that fit the proper extension pattern.
		next if ($file !~ /\.$PixPattern$/);
		&Dprint("\tFound picture $dir/$file.\n");
		# Check if those pictures have corresponding captions.
		my $caption = undef;
		$file =~ m/(.*)\.(.*)/;
		my ($fname, $fext) = ($1, $2);
		foreach my $ext (@TxtForms)
		{
			if (-f "$dir/$fname.$ext")
			{
				$caption = "$fname.$ext";
				&Dprint("\t\tFound caption $dir/$caption.\n");
				last;
			}
		}
		&Dprint("\t\tFound no caption for $dir/$file.\n")
			if (!defined($caption));
		$caption = (defined($caption) ? "src=$caption" : "");

		my $width = "";
		my $height = "";

		# If width is specified, use it, else trust the browser.
		if ($Rec{'tableWidth'} ne 'a')
		{
			$width = "width=$Rec{'tableWidth'}";
			&Dprint("\t\t\tSet table width to $width for $dir/$file.\n");
		}
		# If height is specified, use it, else trust the browser.
		if ($Rec{'tableHeight'} ne 'a')
		{
			$height = "height=$Rec{'tableHeight'}";
			&Dprint("\t\t\tSet table height to $height for $dir/$file.\n");
		}
		if ($CurrentPictures % 2 == 0)
		{
			$TableHTML .= <<EOF;
	<tr>
		<td align=center valign=middle>
			<a href=$file target=popup>
				<img $width $height src=$file border=0>
			</a>
		</td>
		<td align=left valign=middle>
			<iframe frameborder=0 $caption width=100% height=100%>
			</iframe>
		</td>
	</tr>
EOF
		}
		else
		{
			$TableHTML .= <<EOF;
	<tr>
		<td align=left valign=middle>
			<iframe frameborder=0 $caption width=100% height=100%>
			</iframe>
		</td>
		<td align=center valign=middle>
			<a href=$file target=popup>
				<img $width $height src=$file border=0>
			</a>
		</td>
	</tr>
EOF
		}

		$width = "";
		$height = "";
		# If width is specified, use it, else trust the browser.
		if ($Rec{'thumbnailWidth'} ne 'a')
		{
			$width = "width=$Rec{'thumbnailWidth'}";
			&Dprint("\t\t\tSet thumbnail width to $width for $dir/$file.\n");
		}
		# If height is specified, use it, else trust the browser.
		if ($Rec{'thumbnailHeight'} ne 'a')
		{
			$height = "height=$Rec{'thumbnailHeight'}";
			&Dprint("\t\t\tSet thumbnail height to $height for $dir/$file.\n");
		}
		# cols cannot be specified here - it is ignored. Can't have the
		# number of cols changing with every picture.
		$ThumbnailHTML .= <<EOF;
		<td align=center valign=middle>
			<a href=$file target=popup>
				<img $width $height src=$file border=0>
			</a>
		</td>
EOF
		if ($CurrentPictures % $Rec{'thumbnailCols'} == $Rec{'thumbnailCols'} - 1)
		{
			$ThumbnailHTML .= <<EOF;
	</tr>
	<tr>
EOF
		}

		my $PrevPicture = $CurrentPictures - 1;
		$PrevPicture = "slideshow" if ($PrevPicture == -1);
		$NextPicture = $CurrentPictures + 1;
		my $SlideShowHTML = "";   # This is the per-picture page.
		$width = "";
		$height = "";
		$interval = $Rec{'slideshowInterval'};
		# If width is specified, use it, else trust the browser.
		if ($Rec{'slideshowWidth'} ne 'a')
		{
			$width = "width=$Rec{'slideshowWidth'}";
			&Dprint("\t\t\tSet slideshow width to $width for $dir/$file.\n");
		}
		# If height is specified, use it, else trust the browser.
		if ($Rec{'slideshowHeight'} ne 'a')
		{
			$height = "height=$Rec{'slideshowHeight'}";
			&Dprint("\t\t\tSet slideshow height to $height for $dir/$file.\n");
		}
		# If interval is specified, use it, else use the default.
		if ($Rec{'slideshowInterval'} ne 'a')
		{
			$interval = $Rec{'slideshowInterval'};
			&Dprint("\t\t\tSet slideshow interval to $interval for $dir/$file.\n");
		}
		$bgcolour = $BackColours[rand(@BackColours)];
		$SlideShowHTML .= <<EOF;
<html>
<head>
	<title>Slide Show View of $dir</title>
	<meta http-equiv=refresh content="$interval; url=.$NextPicture.html">
	<meta http-equiv="Page-Enter" content="revealTrans(Duration=2.0,Transition=23)">
	<meta http-equiv="Page-Exit" content="revealTrans(Duration=2.0,Transition=23)">
	$Style
</head>
<body bgcolor=$bgcolour>
<center>
<h1>Slide Show View of $dir, #$CurrentPictures</h1>
<hr>
<table>
	<tr>
		<td rowspan=3 align=center valign=middle background=$bgimage>
			<table cellpadding=5 cellspacing=5>
				<tr>
					<td align=center valign=middle>
						<a href=$file target=popup>
							<img $width $height src=$file border=0>
						</a>
					</td>
				</tr>
			</table>
		</td>
		<td align=center valign=top>
			<font size=+3>
				<a href=.$PrevPicture.html>&larr;</a>
			</font>
			&nbsp;&nbsp;&nbsp;
			<font size=+3>
				<a href=index.html>&uarr;</a>
			</font>
			&nbsp;&nbsp;&nbsp;
			<font size=+3>
				<a href=.$NextPicture.html>&rarr;</a>
			</font>
		</td>
	</tr>
	<tr>
		<td align=center valign=top>
			<iframe frameborder=0 $caption width=100% height=100%>
			</iframe>
		</td>
	</tr>
	<tr>
		<td align=center valign=bottom>
			<iframe bgcolor=$bgcolour frameborder=0 src=.slideshownav.html width=100% height=50>
			</iframe>
		</td>
	</tr>
</table>
</center>
$Signature
</body>
</html>
EOF
		&write("$dir/.$CurrentPictures.html", $SlideShowHTML)
			if (defined($opt_slideshow));

		$CurrentPictures++;
	}
	$end = ($CurrentPictures == 1) ? "" : "s";
	&Vprint("\tFound $CurrentPictures picture$end in $dir.\n");
	$TotalPictures += $CurrentPictures;

	$MainPreHTML .= $MainNavHTML if ($CurrentPictures > 0);
	$MainHTML = $MainPreHTML . $MainHTML;
	$MainHTML .= <<EOF;
<hr>
$CurrentPictures picture$end in $dir.
EOF
	# If an index.txt file already exists, then include it in as a frame.
	if (-e "$dir/index.txt")
	{
		&Dprint("\t\tFound caption $dir/index.txt.\n");
		$MainHTML .= <<EOF;
<iframe frameborder=0 src=index.txt width=100% height=100%>
</iframe>
EOF
	}
	elsif (-e "$dir/index.TXT")
	{
		&Dprint("\t\tFound caption $dir/index.TXT.\n");
		$MainHTML .= <<EOF;
<iframe frameborder=0 src=index.TXT width=100% height=100%>
</iframe>
EOF
	}
	$MainHTML .= <<EOF;
</center>
$Signature
</body>
</html>
EOF

	$TableHTML .= <<EOF;
</table>
</center>
$Signature
</body>
</html>
EOF

	$ThumbnailHTML .= <<EOF;
	</tr>
</table>
</center>
$Signature
</body>
</html>
EOF

	$bgcolour = $BackColours[rand(@BackColours)];
	# Check if a sound file is present for this directory. If it is, then
	# start playing sound with the first slide show page.
	my $sound = undef;
	foreach my $ext (@SndForms)
	{
		if (-f "$dir.$ext")
		{
			$sound = basename($dir);
			$sound = "$sound.$ext";
			&Dprint("\t\tFound tune $sound in dir $dir.\n");
			last;
		}
	}
	&Dprint("\t\tFound no tune for $dir.\n") if (!defined($sound));
	if (defined($sound))
	{
		my $soundfile = "." . $sound . ".html";
		&Dprint("\t\tGenerating tune file $soundfile for tune $sound.\n");
		my $SlideShowSoundHTML = "";
		$SlideShowSoundHTML .= <<EOF;
<html>
<head>
	<title>Slide Show Sound for $dir</title>
</head>
<body bgcolor=$bgcolour text=black link=blue vlink=red>
<center>
<embed src=../$sound width=144 height=15 autostart=true loop=true controls=smallconsole>
<noembed>
<bgsound src=../$sound loop=infinite controls=smallconsole>
</noembed>
</center>
<!-- Created by Anand Natrajan (www.anandnatrajan.com). -->
</body>
</html>
EOF
		&write("$dir/$soundfile", $SlideShowSoundHTML)
			if (defined($opt_slideshow));
		$sound = <<EOF;
	<script language=JavaScript>
		sound = window.open('$soundfile', 'sound', 'height=5,width=175,menubar=no,location=no,resizable=yes,scrollbars=no,alwaysRaised=yes');
	</script>
EOF
	}
	else
	{
		$sound = '';
	}

	$SlideShowHTML .= <<EOF;
<html>
<head>
	<title>Slide Show View of $dir</title>
	<meta http-equiv=refresh content="$Rec{'slideshowInterval'}; url=.0.html">
	$Style
	$sound
</head>
<body bgcolor=$bgcolour>
<center>
<h1>Slide Show View of $dir</h1>
<i>Beginning now...</i>
<hr>
<table>
	<tr>
		<td colspan=2>
			<em>On any page, click on...</em>
		<td>
	</td>
	<tr>
		<td>
			The left arrow to see the previous picture.<br>
			The right arrow to see the next picture.<br>
			The up arrow to exit the slide show.
		</td>
		<td align=center valign=top>
			<font size=+3>
				<a href=index.html>&uarr;</a>
			</font>
			&nbsp;&nbsp;&nbsp;
			<font size=+3>
				<a href=.0.html>&rarr;</a>
			</font>
		</td>
	</tr>
	<tr>
		<td>
			A number in the navigation box to see the corresponding picture.<br>
		</td>
		<td align=center valign=bottom>
			<iframe bgcolor=$bgcolour frameborder=0 src=.slideshownav.html width=100% height=50>
			</iframe>
		</td>
	</tr>
</table>
</center>
$Signature
</body>
</html>
EOF

	$SlideShowNavHTML .= <<EOF;
<html>
<head>
	<title>Slide Show Navigation Bar of $dir</title>
	$Style
</head>
<body bgcolor=white>
<center>
<font size=-1>
EOF
	for (my $i = 0; $i < $CurrentPictures; $i++)
	{
		my $text = &prime($i) ? $i : "&bull;";
		$SlideShowNavHTML .= <<EOF;
	&nbsp;&nbsp;<a target=_parent href=.$i.html>$text</a>
EOF
	}
	$SlideShowNavHTML .= <<EOF;
</font>
</center>
<!-- Created by Anand Natrajan (www.anandnatrajan.com). -->
</body>
</html>
EOF

	# Write out all the output files except the intermediate ones for the
	# slide show, which should have been written out already.
	&write("$dir/index.html", $MainHTML);
	&write("$dir/.table.html", $TableHTML) if (defined($opt_table));
	&write("$dir/.thumbnail.html", $ThumbnailHTML) if (defined($opt_thumbnail));
	if (defined($opt_slideshow))
	{
		&write("$dir/.slideshow.html", $SlideShowHTML);
		link("$dir/.slideshow.html", "$dir/.$CurrentPictures.html");
			# or warn "Couldn't write to $dir/.$CurrentPictures.html: $!\n";
		&Dprint("Linking $dir/.$CurrentPictures.html to start.\n");
		&write("$dir/.slideshownav.html", $SlideShowNavHTML);
	}

	# Write out the files to make this directory "CD-ready". Notice we're
	# going to write autorun.inf and batch files in each subdirectory as
	# well, though it's only the root directory that needs it. That's all
	# right... it makes the logic simpler and it allows for people to tear
	# out pieces of their pictures and put only those on a CD... provided
	# they remember to copy the relevant autorun.inf files as well.
	if (defined($opt_cd))
	{
		my $base = basename($dir);
		&write("$dir/../autorun.inf", "[autorun]\nopen=$base\\$MyName.bat\n");
		&write("$dir/$MyName.bat", "\@echo off\n$base\\index.html\n");
	}
}
my $end = ($TotalPictures == 1) ? "" : "s";
&Vprint("Found $TotalPictures picture$end totally.\n");
