# pcd2html: package pcd2html_uti.pm
# Copyright Andreas Tille <tille@debian.org>
# License: GPL
#
# Perl utilities and names for pcd2html

## I would like to use strict but I do not how to declare the %item variable which
## will be set external to %german or %english
use strict ;

## our (%german, %english);

## Also this declearation fails unfortunately :-(((
my ( $sysconfdir,    # directory for system configuration
     $configname,    # name of configuration file in this directory
     $pcd_info,      # location of PCD info file on Kodak Photo CDs
     $pcd2html_home, # location of user configuration
     $pcd2html_source_url, # URL where to find information about pcd2html
     $config,        # configuration file
     $pcd2html_uti,  #
     $footer_string, # Create string for footer only once
     %available_keys # Dictionar with key -> directory
   );

my ($cdrom) ;


$sysconfdir    = "/etc" ;
$configname    = "pcd2html.conf" ;
$pcd_info      = "info.pcd" ;
$pcd2html_home = $ENV{"HOME"} . "/.pcd2html" ;

$pcd2html_source_url = "http://fam-tille.de/debian/pcd2html.html" ;

my $PCD2HTMLMARKER = "##PCD2HTMLMARKER##" ;

$config        = "$sysconfdir/$configname";
stat($config) || die "Missing config file $config" ; 
open(CONF, $config) || die "Error while opening config file $config" ;
while ( <CONF> ) {
  unless ( /^\s*#/ ) {
    chomp( $cdrom = $_ );   # path to cdrom (cdrom images) obtained from config file
  }
}
close(CONF) || die "Error while closing file $config" ;

my $LinkTdString = 'td class="linktype"' ; # HTML-string used for links inside <td>-tags
my $IconWidth    = 80 ;                    # width of icons
my $IconHeight   = 64 ;                    # height of icons
# Dimensions of the index icons
my $MainIndexIconWidth  = 70; 
my $MainIndexIconHeight = 54;
my $IndexIconWidth      = 82;
my $IndexIconHeight     = 64;

sub IndexLink {
    # Link to Index with width and height
    # $_[2] != 0 page index
    # $_[2] == 0 main index

    if ( $_[2] != 0 ) {
	return '   <a href="' . $_[0] . '" class="'. $_[1] . '">' . "<img src=\"index.jpg\" ".
	    "width=\"$IndexIconWidth\" height=\"$IndexIconHeight\" alt=\"index\" /></a>\n" ; ;
    } else {
	return '   <a href="../' . $_[0] . '" class="'. $_[1] . '">' . "<img src=\"../index.jpg\" ".
	    "width=\"$MainIndexIconWidth\" height=\"$MainIndexIconHeight\" alt=\"main index\" /></a>\n" ; ;
    }
}

sub GetCropSize {
    # Crop size for convert call
    if ( $_[0] == 4 ) {
	return "$MainIndexIconWidth"."x"."$MainIndexIconHeight" ;
    } else {
	return "$IndexIconWidth"."x"."$IndexIconHeight" ;
    }
}

my $internal_info_key = "pcd2html internal info";
sub GetInternalInfoKey {
  return $internal_info_key ;
}

sub GetPcd2HtmlSourceUrl {
  return $pcd2html_source_url ;
}

# some definitions for image conversion
my $JPEG_QUALITY = 70 ;
sub GetQuality {
    if ( $_[0] ne "" ) {
	return "-quality $_[0]";
    }
    return "-quality $JPEG_QUALITY";
}

my $pcd_css       = "pcd.css" ;
sub GetCSS {
  return $pcd_css ;
}

# some English translations
my %english = ( "hext",   ".html" ,
                "lang",   "en" ,
		"next",   "next" ,
		"prev",   "previous",
		"back",   "back to index page" ,
		"text",   ".eng" ,
		"index",  "index.html" ,
		"otitle", "Deutsche Version dieser Seite" ,
		"slide",  "Slide show of all these images" ,
		"back_m", "back to main page" ,
		"top",    "back" ,
		"home",   "Home page" ,
		"oicon",  "deutsch.png" ,
		"other",  "index_de.html"
	      );
# some German translations
my %german = (  "hext",  "_de.html" ,
		"lang",  "de" ,
		"next",  "n&auml;chstes" ,
		"prev",  "vorhergehendes" ,
		"back",  "zur&uuml;ck zur Indexseite" ,
		"text",  ".deu" ,
		"index", "index_de.html" ,
		"otitle", "English copy of this page",
		"slide",  "Alle Bilder nacheinander" ,
		"back_m", "zur&uuml;ck zur Hauptseite" ,
		"top",    "zur&uuml;ck" ,
		"home",   "Hauptseite" ,
		"oicon",  "english.png" ,
		"other",  "index.html"
	     );

sub GetConvert {
    # enable alterative usage of GraphicsMagick
    return "gm convert $_[0] -verbose" ;
}

sub GetMontage {
    # enable alterative usage of GraphicsMagick

    # Du not use the "-debug" option here !!!

    # montage of ImageMagic is broken and the -borderwidth option has to be removed
    # just live without the border in icons ... especially if
    # Katrin prefers the icons without the lines ...
    return "gm montage -label \"\" -bordercolor white -background black -borderwidth 1" ;
}

sub GetIconConvert {
    return GetConvert($_[0]) . " -dither -geometry $IconWidth" . 'x' . "$IconHeight" ;
}

$pcd2html_uti = "pcd2html_uti" ;


# Return a list of potential PCD dirs
sub get_pcd_dirs {

    my @dirs = () ;
    my $check_command = "find $cdrom -follow \\( -type d -or -type l \\) -and -name photo_cd" ;
    open (FINDDIRS, "$check_command |") || die ( "Kann $check_command nicht ausführen." ) ;
    while ( <FINDDIRS> ) {
	chomp ;
	@dirs = (@dirs, $_) ;
    }
    close (FINDDIRS) ;
    return @dirs ;
}

# check whether a PCD directories are available
# try to mount if fail
# return list of directories with PCD structures
sub mounted_pcd {
  my ( $ostype, $info, @pcd_dirs );

  my @check_pcd_dirs = get_pcd_dirs ();

  if ( ! @check_pcd_dirs ) { 
    $ostype = $ENV{"OSTYPE"} ;
    if ( ! $ostype ) {
      $ostype = `uname` ;
    }
    if ( ! $ostype ) {
      $ostype = "unknown" ;
    }
    unless ( $ostype =~ /linux/i ) {
      warn "Don't know how to mount CD drive on an $ostype system\n" ;
      return 0;
    }
    print "Warning: CD not mounted at $cdrom.  Trying to mount...\n" ;
    unless ( `cat /etc/fstab` =~ /$cdrom/ ) { 
      warn "Error: $cdrom not contained in /etc/fstab.  Giving up.\n" ;
      return 0;
    }
    if ( system ( "mount $cdrom" ) ) {
      warn "Unable to mount $cdrom.  Please ask your system administrator." ;
      return 0;
    }
    @check_pcd_dirs = get_pcd_dirs ();
    if ( ! @check_pcd_dirs ) {
	return () ;
    }
  }

  foreach ( @check_pcd_dirs ) {
      if ( -e "$_/$pcd_info" ) {
	  s?^$cdrom/?? ;
	  @pcd_dirs = (@pcd_dirs, $_) ;
      } else {
	  warn "Directory in $_ doesn't seem to contain a Kodak Photo CD!\n";
      }
  }
  return @pcd_dirs;
}

#### Method: pcd_get_keys
# Obtain Kodak Photo CD keys
#
####
sub pcd_get_keys {
    my ( $key, $info, %keys, @pcd_dirs ) ;

    # do not obtain the keys more than once ...
    if ( keys(%available_keys) ) { return %available_keys ; }

    @pcd_dirs = mounted_pcd() ;
    unless ( @pcd_dirs ) {
	warn "No Kodak Photo images available at $cdrom.\n";
	return undef ;
    }

    # Search used PCD database in ${HOME}
    if ( stat( "$pcd2html_home" ) ) {
	unless ( open(HOME, "$pcd2html_home" ) ) {
	    warn "Error while opening $pcd2html_home\n" ;
	    return undef ;
	}
	while ( <HOME> ) {
	    unless ( /\s*#/ ) {
		chomp ;
		s/# .*// ;
		$a = $b = $_ ;
		$a =~ s/\s*(\w*)\s.*/$1/ ;
		$b =~ s/\s*$a\s*(\w*)\s*.*/$1/ ;
		$keys{$b} = $a ;
	    }
	}
	close(HOME);
    } else {
	# Create new database otherwise
	unless ( open(HOME, ">$pcd2html_home" ) ) {
	    warn "Error while creating $pcd2html_home\n" ;
	    return undef;
	}
	select (HOME) ;
	print "# pcd2html: keys for different Kodak Photo CDs\n" ;
	print "# <key used in rules file> <specification number of CD>\n";
	print "#   or for other images\n";
	print "# <key used in rules file> <directory where to find the image>\n";
	print "#\n" ;
	select (STDOUT) ;
	close(HOME) ;
    }  

    my $i = 0 ;
    foreach ( @pcd_dirs ) {
        my $current_pcd_info = "$cdrom/$_/$pcd_info";
	unless ( open(INFO, $current_pcd_info ) ) {
	    warn "Error while opening Kodak Photo CD information at $cdrom/$_/$pcd_info\n" ;
	    return undef ;
	}
	chomp ($info = <INFO>) ;
	close(INFO) ;
	$info =~ s/\D*(\d*)\D.*/$1/ ;
	unless ( $info ) {
	    print STDERR "$_/$pcd_info does not seem to be a valid Photo CD structure. Ignored.\n" ;
	    next ;
	}

	$key = $keys{$info} ;
	$i  += 1 ;
	if ( $key ) {
	    $available_keys{$key} = $_ ;
	}
	
	unless ( $key ) {
	    print "The Kodak Photo CD in $current_pcd_info was not used before.\n" ;
	    print "Which key should be used in the rules file? " ;
	    while ( 1 ) {
		$key = <STDIN> ;
		chomp ( $key ) ;
		unless ( $key =~ /\W/ ) { last ; }
		print "Only letters, digits and `_` are allowed in keys\n" ;
		print "Please insert valid key! " ;
	    }
	    unless ( open(HOME, ">>$pcd2html_home" ) ) {
		warn "Error while opening $pcd2html_home\n" ;
		return undef ;
	    }
	    select (HOME) ;
	    print "$key $info\n" ;
	    select (STDOUT) ;
	    close(HOME) ;
	}
    }

    return %available_keys ;
}  

#### Method: pcd_get_dirs ################################
# Obtain keys of other images which are stored on disk
#
####
sub pcd_get_dirs {
  my ( $key, %dirs ) ;

  if ( stat( "$pcd2html_home" ) ) {
    unless ( open(HOME, "$pcd2html_home" ) ) {
      warn "Error while opening $pcd2html_home\n" ;
      return undef ;
    }
    while ( <HOME> ) {
      unless ( /\s*#/ ) {
        if ( /\// ) {
          chomp ;
          s/# .*// ;
          $a = $b = $_ ;
          $a =~ s/\s*(\w*)\s.*/$1/ ;
          $b =~ s/\s*$a\s*([^\s]*)\s*.*/$1/ ;
          if ( -d $b ) { $dirs{$a} = $b ; }
	}
      }
    }
    close(HOME);
  }
  return %dirs ;
}

#######################################################
# open rules file of a subdriectory
#
sub OpenRules {
    my ( $rules, %keys ) ;

    $rules = "rules" ;

    unless ( -f $rules ) { die "There is no $rules file.\n" ; }
    unless ( open(RULES, $rules ) ) { die "Error while opening $rules. ($!)\n" ; }

    %keys = pcd_get_keys() ;
    unless ( %keys ) { print STDERR "pcd2html: Warning: No PCD inserted.\n" ; }
    return %keys ;
}

#######################################################
# open license file of a subdriectory
#
sub GetTranslationItems {
  my ( $license, $text, %item ) ;

  $license = "license.$_[0]" ;
  $text    = "" ;

  unless ( -f $license ) {
    $license = "../".$license ;
    if ( -f $license ) { 
      unless ( open(LICENSE, $license ) ) { die "Error while opening $license. ($!)\n" ; }

      while ( <LICENSE> ) {
        $text = $text . $_ ;
      }
      close(LICENSE);
    } # else {
      # print "Warning: It would be sane to apply a license to your images.\n" ;
      # }
  }

  if ( $_[0] =~ /deu/ ) {
      $german{"license"} = $text;
      %item = %german ;
  } else {
      $english{"license"} = $text;
      %item = %english ;
  }

  return %item ;
}

######################################################
# Get author from finger information
#
sub GetAuthor {
  my ( @finger ) ;

  @finger = `finger $ENV{"LOGNAME"}` ;
  foreach ( @finger ) {
    if ( /Name/ ) {
      chomp ;
      s/.*Name: *//;
      return $_ ;
    }
  }
}

sub GetDate {
  $_ = `date +%Y-%m-%d%t%T%z` ; 
  chomp ;
  return $_ ;
}

#############################################################
# Get strings for a homepage to go from main index
# These strings have to be written in index.{deu,eng}
# files as comment marked by the keywords "home" and "back"
sub GetTextHome {

  my ($back, $home);

  open(TEXTFILE, "$_[0]" ) || die "Unable to open $_[0]\n" ;
  while ( <TEXTFILE> ) {
    if ( /^# *back: *(.*)/ ) {
      $back = $1 ;
    }
    if ( /^# *home: *(.*)/ ) {
      $home = $1 ;
    }
  }
  close TEXTFILE ;
  return ($back, $home);
}

#############################################################
# For prevention of Spam mails you can provide an image
# containing your e-mail adress in index.{eng,deu}
sub GetSpamPrevention {

  my $email = '';

  open(TEXTFILE, "$_[0]" ) || return '' ;
  while ( <TEXTFILE> ) {
    if ( /^# *email: *(.*)/ ) {
      $email = $1 ;
      last ;
    }
  }
  close TEXTFILE ;
  if ( ! $email  ) { return '' ; }
  $_ = $_[0] ;
  # Add '../ ' if contained in beginning of path of $_[0]
  if ( /^([.\/]+)/ ) { $email = $1 . $email ; }
  if ( -s $email ) { return $email ; }
  return '' ;
}

#############################################################
# Get email from environment or build from loginname@host
#
sub GetEmail {
  my ( $email ) ;

  $email = $ENV{"EMAIL"} ;
  if ( defined( $email ) && $email =~ /\w/ ) { 
    return $email ; 
  }
  $_ = `hostname` ;
  $_ = `host $_` ;
  /([^\s]*)/ ;

  return $ENV{"LOGNAME"} . "\@$1" ;
}

##############################################################
# Read first line (without #) as title information
#
sub GetTitle {
  my ($title, $file, $textfile ) ;

  $file="$_[0]$_[2]" ;
  if ( -f $file ) {
    open(FILE, $file ) || die "Unable to open $file\n" ;
    while ( <FILE> ) {
      unless ( /^#/ ) {
        chomp ;
##        Iso2Html () ;
        $title = $_ ;
	last ;
      }
    }
    close FILE ;
    $textfile = $file ;
  } else {
    $title = $_[1] ;
    $textfile = "none" ;
  }
  return ( $title, $textfile ) ;
}

################################################################
#  Print header of HTML information with certain keywords
#
sub MyHtmlStart{
  my ( $title, $author, $date, $keywords, $css, $internal, $content ) ;
  our %item;  # = %german or %english depending from calling routine
  
  $author = GetAuthor() ;
  $date   = GetDate() ;
  $title    = $_[0];
  $keywords = $_[1];
  $content  = $_[2];
  $css      = $_[3];
  $internal = $_[4];

  print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">' ;
  if ( defined ($internal) ) {
    print $internal ;
  }
  print "\n<html>\n<head>\n" ;
  if ( $title ) {
    print "<title>$title</title>\n" ;
  } else {
    print STDOUT "Warning: No title for this page.\n";
  }

  print "<meta name=\"date\" content=\"$date\" />\n" ;
  print "<meta name=\"author\" content=\"$author\" />\n" ;
  print "<meta name=\"generator\" content=\"pcd2html\" />\n" ;
  if ( defined ( $keywords ) ) {
    print '<meta name="keywords" lang="' . $item{"lang"} . "\" content=\"$keywords\" />\n" ;
  }
  if ( defined ( $content ) ) {
    print '<meta name="content" lang="' . $item{"lang"} . "\" content=\"$content\" />\n" ;
  }
  if ( defined ( $css ) ) {
    print "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css\" />\n" ;
  }
  print "</head>\n<body>\n" ;
}

###################################################################
# Print top navigation
#
sub MyNavigation{
  my $homename   = $_[0];
  my $topname    = $_[1];
  my $otherlang  = $_[2];
  my $iconname   = $_[3];
  my $othertitle = $_[4];
  my $back       = $_[5];
  my $home       = $_[6];
  my $imgsrc     = $_[7];

  print "<table class=\"navigation\" width=\"100%\">\n <tr>\n" ;
  $imgsrc = '<img class="navigation" src="' . $imgsrc ;
  if ( defined ( $back ) || defined ( $home ) ) {
    print "  <td class=\"mainindex\">\n" ;
    my $homestring = '   <a href="' . $home . '">' . $imgsrc . 'home.png" alt="' .
                     $homename . "\"></a>\n" ;
    if ( defined ( $back ) ) {
      print '   <a href="'.$back.'">' . $imgsrc . 'pic_home.png" alt="' .
            $topname . "\"></a>\n" ;
      if ( defined ( $home ) ) {
        print "  </td>\n  <td class=\"home\">\n" ;
        print $homestring ;
      }
    } else {
      print $homestring ;
    }
    print "  </td>\n" ;
  }
  print "  <td class=\"language\">\n" ;
  print '   <a href="'.$otherlang.'">' . $imgsrc . $iconname.'" alt="' .
        $othertitle . "\"></a>\n" ;
  print "  </td>\n" ;
  print " </tr>\n</table>\n" ;
}

###################################################################
# Print end of HTML information with subscription
#
sub CreateFooterString {
  my ( $email, $using, $date, $author, $license, $nospam, $end );

  $footer_string = "" ;

  $_ = GetDate() ;
  /([\-\d]*).*/ ;
  $date = $1 ;
  $license="" ;
  if ( $_[0] eq "de" ) {
    $license=$german{"license"} 
  } else {
    $license=$english{"license"} 
  }
  if ( defined $license && $license ne "" ) {
    $footer_string = $footer_string . "<p class=\"license\">\n$license\n</p>\n" ;
  }  
  $footer_string = $footer_string . "<p class=\"footer\">\n" ;
  if ( $_[0] eq "de" ) {
    $footer_string = $footer_string . " Diese Seite wurde am " ;
    $_ = $date ;
    /(\d*)-(\d*)-(\d*)/ ;
    $footer_string = $footer_string . "$3.$2.$1 durch " ;
    $using = "mittels" ;
  } else {
    $footer_string = $footer_string . " This page was created on $date by " ;
    $using = "using" ;
  }

  $end = " $using <a href=\"$pcd2html_source_url\">pcd2html</a>" ;
  if ( $_[0] eq "de" ) { $end = $end . " erstellt" ; }
  $end = $end . ".\n</p>\n</body>\n</html>\n" ;
  $author = GetAuthor() ;
  if ( ($nospam = GetSpamPrevention($_[1]) ) ) {
    my ( $back, $home);
    ($back, $home) = GetTextHome($_[1]) ;
    if ( $home ) {
      # if $home is a relative address obtain from $nospam the relative directory
      if ( $home =~ /^([.\/]+)/ && $nospam =~ /^([.\/]+)/ ) { $home = $1 . $home ; }
      $footer_string = $footer_string .
                         "<a href=\"$PCD2HTMLMARKER$home\">$author</a> "
    }
    $footer_string = $footer_string . 
                      '<a href="mailto:this.is@not.mymail.info"><img class="emil" src="' .
                      "$PCD2HTMLMARKER$nospam\" alt=\"$author\"></a>" . $end ;
  } else {
    $footer_string = $footer_string . '<a href="mailto:' . GetEmail() . 
                      "\">$author</a>" . $end ;
  }
}

sub MyHtmlEnd {
  my $subdir = '' ;
  if ( $_[0] ) { $subdir = $_[0] ; }
  $_ = $footer_string ;
  s/$PCD2HTMLMARKER/$subdir/g ;
  print ;
}

###################################################################
#  Read complete file information into a single string
#
sub File2String {
  my ( $string ) ;

  if ( -f $_[0] ) {
    open(FILE, $_[0] ) || die "Unable to open $$_[0] file\n" ;
    $string = "" ;
    while ( <FILE> ) {
      unless ( /[ \t]*#/ ) {
        chomp ;
        $string = "$string $_" ;
      }
    }
    close FILE ;
  }
  return $string ;
}

############################################################################
#  Convert file contents to HTML
#  blank lines  -> <br>
#  8 bit ISO -> HTML
#  --- Parameters: ---
#  $filename
#  optional flag, if first valid line (== title) should be printed as
#  heading line (default) or should be suppressed on the page if (flag == 0)
#
sub File2HTML {
  my ( $filename, $print_headline, $i, $title );

  $filename    = $_[0] ;
  $print_headline = 0;
  if ( defined ( $_[1] ) && $_[1] == 0 ) {
      $print_headline = 1 ;
  }
  
  $i = 0;
  unless ( open(TEXT, "$filename" ) ) {
    warn "Error while opening $filename.\n" ;
  } else {
    if ( defined $_[2] ) {
      $title = $_[2] ;
    } else {
      $title = "" ;
    }
    while ( <TEXT> ) { 
      unless ( /^#/ ) {
        if ( $print_headline && $i == 0 && /$title/ ) { next ; }
        $i++ ;
        Iso2Html () ;
        if ( /^\s*$/ ) { print "<br />\n" ; } 
	print ; 
      }
    }
    close TEXT ;
  }
}

###################################################################
#  Search for file with <name>.<ext> where <name> is the argument
#  of this function and <ext> some known extensions of image file
#  formats.  Returns first valid image name found.
#
sub ExistingPicWithName {
  my ( $name, $ext, @extensions ) ;
  @extensions = ( "jpg", "gif", "png", "tif" ) ;

  $name = $_[0] ;
  unless ( defined($name) ) { return undef ; }

  foreach $ext (@extensions) {
    if ( -f "$name.$ext" ) {
      return "$name.$ext" ;
    }
  }
  return undef ;
}

##################################################################
#  Convert 8 bit ISO characters into HTML syntax
#
##  s/&/\&amp;/;  you have to care for right &amp; in your texts ...
sub Iso2Html {
  s/Å/\&Aring;/ ;
  s/Æ/\&AElig;/ ;
  s/Ç/\&Ccedil;/ ;
  s/È/\&Egrave;/ ;
  s/É/\&Eacute;/ ;
  s/Ê/\&Ecirc;/ ;
  s/Ë/\&Euml;/ ;
  s/Ì/\&Igrave;/ ;
  s/Í/\&Iacute;/ ;
  s/Î/\&Icirc;/ ;
  s/Ï/\&Iuml;/ ;
  s/Ð/\&ETH;/ ;
  s/Ñ/\&Ntilde;/ ;
  s/Ò/\&Ograve;/ ;
  s/Ó/\&Oacute;/ ;
  s/Ô/\&Ocirc;/ ;
  s/Õ/\&Otilde;/ ;
  s/Ö/\&Ouml;/ ;
  s/×/\&times;/ ;
  s/Ø/\&Oslash;/ ;
  s/Ù/\&Ugrave;/ ;
  s/Ú/\&Uacute;/ ;
  s/Û/\&Ucirc;/ ;
  s/Ü/\&Uuml;/ ;
  s/Ý/\&Yacute;/ ;
  s/Þ/\&THORN;/ ;
  s/ß/\&szlig;/ ;
  s/à/\&agrave;/ ;
  s/á/\&aacute;/ ;
  s/â/\&acirc;/ ;
  s/ã/\&atilde;/ ;
  s/ä/\&auml;/ ;
  s/å/\&aring;/ ;
  s/æ/\&aelig;/ ;
  s/ç/\&ccedil;/ ;
  s/è/\&egrave;/ ;
  s/é/\&eacute;/ ;
  s/ê/\&ecirc;/ ;
  s/ë/\&euml;/ ;
  s/ì/\&igrave;/ ;
  s/í/\&iacute;/ ;
  s/î/\&icirc;/ ;
  s/ï/\&iuml;/ ;
  s/ð/\&eth;/ ;
  s/ñ/\&ntilde;/ ;
  s/ò/\&ograve;/ ;
  s/ó/\&oacute;/ ;
  s/ô/\&ocirc;/ ;
  s/õ/\&otilde;/ ;
  s/ö/\&ouml;/ ;
  s/÷/\&divide;/ ;
  s/ø/\&oslash;/ ;
  s/ù/\&ugrave;/ ;
  s/ú/\&uacute;/ ;
  s/û/\&ucirc;/ ;
  s/ü/\&uuml;/ ;
  s/ý/\&yacute;/ ;
  s/þ/\&thorn;/ ;
  s/ÿ/\&yuml;/ ;
  s/Ô/\&Ocirc;/ ;
  s/Õ/\&Otilde;/ ;
}

##################################################################
#  Find out size of an image
#
sub ImageSize {
  # If $_[1] > 0 the size of icon
  my $img = $_[0] ;

  if ( ! -e $img ) {
    if ( defined ( $_[1] ) && $_[1] > 0 ) {
      return ( $IconWidth, $IconHeight );
    } else {
      return;
    }
  }
  $_ = `identify -ping $img | head -n1`;
  ## identify-output file name with optional '[n]' for multiimage
  ## files and JPEG or GIF before dimeansions [FG] catches this 
  /$img[\sA-Z0-9\[\]]*[FG] ([0-9]*)x([0-9]*)/ ;
  return ($1, $2);
}

##################################################################
# Check existing Kodak photo cd with key $pickey and valid image
# width $picnum
sub GetKeyAndSource {

  my (  $pickey,  ## internal key of the cd in question 
        $picnum,  ## number of the picture
        $imgfile, ## *.img file for this image
        %dirs, $dir, $source, %keys, $pcddir
     );

  $pickey  = $_[0];
  $picnum  = $_[1];
  $imgfile = $_[2];

  %keys   = pcd_get_keys() ;
  $pcddir = $keys{$pickey} ;

  unless ( $pcddir ) {
    %dirs = pcd_get_dirs() ;
    unless ( %dirs ) { 
      print STDERR "Can't obtain Kodak Photo-CD key \"$pickey\" or any valid image directory\n";
      return ( $pickey, undef );
    }
    $dir  = $dirs{$pickey};
    unless ( defined($dir) ) {
      unless ( open(IMG, ">$imgfile" ) ) { die "Unable to open $imgfile\n" ; }
      print IMG "Wrong PCD inserted and no valid image directory available.\n" ;
      close (IMG) ;
      exit 0 ;
    }
    $source = ExistingPicWithName ( "$dir/$picnum" ) ;
    unless ( $source ) { 
      unless ( open(IMG, ">$imgfile" ) ) { die "Unable to open $imgfile\n" ; }
      print IMG "There is no image $dir/$picnum.\n" ;
      close (IMG) ;
      exit 0 ;
    }
  } else {
    unless ( $picnum =~ /extra/ ) {
      $source = "$cdrom/$pcddir/images/img0" . $picnum . ".pcd";
    }
  }
  return ($pickey, $source) ;
}

#################################################################################
#
# Read rules file for use in pcd2html_create_{jpg,html}
#
sub GetParametersFromRules {
  my ( $pickey, $picnum, $num, $name, $image, $source, $O, $E, $Q, $line, $WikiPediaLink );

  $pickey = $_[0];
  $picnum = $_[1];

  while ( <RULES> ) {
    if ( /^$pickey:$picnum/ ) {
      chomp ;
      $line = $_ ;
      if ( /extra/ ) {
        /(\w*):extra *([^ ]*)/ ;
        $num   = "$1_extra" ;
        $name  = "$2" ;
        $image = $1 . "_extra" . $name ;
        $O = $Q = $E = $WikiPediaLink = "" ; # we need defined values for these variables
      } else {
        /(\w*):(\w*) *([^ ]*).*/ ;
        $num   = "$1_$2" ;
        $name  = "$3" ;
        $image = "$num$name.jpg" ;
        $O = GetOperationParameter($line, '\[.*\]', '[^ ]* *\[(.*)\]' ) ;
        $E = GetOperationParameter($line, "!", "[^\\!]*!([1-5])") ;

##      if ( defined ($Q = GetOperationParameter($line, "Q", "[^\\Q]*Q([0-9]*)" )) ) { 
##  Hmmm, I'm not really sure why I once placed the '\\' here, but now it is not good any more
        $Q = GetOperationParameter($line, "Q", "[^Q]*Q([0-9]*)" ) ;
	if ( /{([^{}]*\.jpe?g)}/ ) {
	    $WikiPediaLink = $1 ;
	} else {
	    $WikiPediaLink = "" ;
	}
        last ;
      }
    }
  }
  close RULES ;

  return ($num, $name, $image, $O, $Q, $E, $WikiPediaLink);
}

sub CheckChanges {
  my ( $html_target, $img_file, $O, $E, $Q, $checkfile ) ;

  $html_target = $_[0] ;
  $img_file    = $_[1] ;
  $O           = $_[2] ;
  $E           = $_[3] ;
  $Q           = $_[4] ;

  if ( -f $html_target ) { $checkfile = $html_target ; }
  else                   { $checkfile = $img_file ; }
  unless ( -f $checkfile ) { return -1 ; }
  if ( open(HTML, "$checkfile" ) ) {
    my ($HO, $HE, $HQ) ;
    while ( <HTML> ) {
      if ( /<!-- $internal_info_key: O=([^,]*), E=(\d*), Q=(\d*) -->/ ) {
        $HO = $1;
        $HE = $2;
        $HQ = $3;
        last ;
      }
    }
    close HTML ;
    # in case of completely new img file
    if ( ! defined($HO) || ! defined($HE) || ! defined($HQ) ) {
      return 1;
    }    
    if ( defined($HO) && defined($HE) && defined($HQ) &&
         $O eq $HO && $E eq $HE && $Q eq $HQ ) {
      unless ( open(IMG, ">>$img_file" ) ) { die "Unable to open $img_file\n" ; }
      print IMG "rules according to this image not changed\n" ;
      close IMG ;
      return 0;        
    }
  }
  return 1 ;
}

sub GetOperationParameter {
  $_ = $_[0] ;
  our $key ; # set in calling routine
  my $currkey;
  if ( /$_[1]/ ) {
    if ( ! $key ) { $currkey = "" ; }
    else          { $currkey = $key ; }
    /$currkey:(\w*)\s*$_[2].*/ ;
    if ( defined ( $2 ) ) { return $2 ; }
  }
  return "" ;
}
