#!/usr/bin/perl

################################################################################
# HTMLxWords                                                                   #
# Version 1                                                                    #
# Author: Denis NICOLAS                                                        #
################################################################################


# These are the roman numbers known to the program.
# If you need to build grids with more lines than that, you just have to
# complete the array.
%romans = (
	 1 => "I",
	 2 => "II",
	 3 => "III",
	 4 => "IV",
	 5 => "V",
	 6 => "VI",
	 7 => "VII",
	 8 => "VIII",
	 9 => "IX",
	10 => "X",
	11 => "XI",
	12 => "XII",
	13 => "XIII",
	14 => "XIV",
	15 => "XV",
	16 => "XVI",
	17 => "XVII",
	18 => "XVIII",
	19 => "XIX",
	20 => "XX"
);

$fileNb = &openInputFile;

$gridFileName = "grid" . $fileNb . ".html";
$definitionsFileName = "definitions" . $fileNb . ".html";
$xWordsFileName = "xWords" . $fileNb . ".html";
$solutionFileName = "solution" . $fileNb . ".html";

&generateXWORDS_FILE;
$nbLines = &generateGrids;
&generateDEFINITIONS_FILE;

close(INPUT_FILE);


################################################################################
# Prompts the user for the name of the data file to be read.                   #
# Returns the number contained in that name.                                   #
################################################################################
sub openInputFile {

	my($fileName);
	
	print("Name of input file: ");
	$fileName = <STDIN>;	
	chop($fileName);
	open(INPUT_FILE, $fileName) || die("Can't open file $fileName...\n");
	
	$fileName =~ /[0-9]+/;
	return ($&);
}


################################################################################
# Opens a file for output.                                                     #
# If the file already exists, prompts the user.                                #
################################################################################
sub openOutputFile {
	my($file, $fileName) = @_;

	my($answer);
	
	if (-e $fileName) {
		print("File $fileName already exists. Overwrite (y/n)? ");
		$answer = <STDIN>;
		chop($answer);
		$answer =~ tr/A-Z/a-z/;
		die() if ($answer eq "n");
	}
	
	open($file, ">$fileName");
}


################################################################################
# XWORDS_FILE is the HTML file defining the FRAMESET.                          #
################################################################################
sub generateXWORDS_FILE {
	
	my($line);

	&openOutputFile("XWORDS_FILE", $xWordsFileName);
	select(XWORDS_FILE);
	# Copy of the contents of "xWords.html.base" into XWORDS_FILE.
	# "xWords.html.base" contains the static beginning of the file we want to
	# generate.
	open(XWORDS_HTML_BASE, "xWords.html.base") ||
		die("Can't open file xWords.html.base...\n");
	while ($line = <XWORDS_HTML_BASE>) {
		print($line);
	}
	close(XWORDS_HTML_BASE);

	# Now we need to generate the end of the file.
	print("  <FRAME SRC=\"$gridFileName\">\n");
  print("  <FRAME SRC=\"$definitionsFileName\" NAME=\"definitions\">\n");

	print("\n</FRAMESET>\n");
	print("\n</HTML>");
	
	close(XWORDS_FILE);
	select(STDOUT);

}


################################################################################
# Generates 2 HTML files:                                                      #
# 	* GRID_FILE: defines the blank grid.                                       #
# 	* SOLUTION_FILE: defines the completed grid.                               #
#                                                                              #
# Returns the number of lines in the crosswords.                               #
################################################################################
sub generateGrids {

	my($line, @characters, $character, $nbCols, $nbLines, $i);
	
	&openOutputFile("GRID_FILE", $gridFileName);
	&openOutputFile("SOLUTION_FILE", $solutionFileName);
	
	$line = <INPUT_FILE>;
	chop($line);
	@characters = split(//, $line);
	$nbCols = @characters;

	print GRID_FILE ('
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>

<HEAD>
  <TITLE>Grille</TITLE>
  
  <META NAME="GENERATOR" CONTENT="HTMLxWords (Perl)">
  <META NAME="Author" CONTENT="Denis NICOLAS">
  <META NAME="Description" CONTENT="Une grille de mots croisés qu\'il est possible de compléter à l\'écran. Ce document a été conçu pour s\'afficher dans un Frame, l\'autre Frame contenant les définitions.">
</HEAD>


<BODY TEXT="#FFCC00" BGCOLOR="#7E79AF" LINK="#FFFF00" VLINK="#FFCC00" ALINK="#FF0000"
  BACKGROUND="../../images/Background.jpg">

<BASE TARGET="definitions">

<CENTER>

<FORM>

<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=0 BGCOLOR="#000000">

<CAPTION>
  ');
	
	print GRID_FILE ("<H1>Grille n&deg; $fileNb</H1>");
	
	print GRID_FILE ('
</CAPTION>

<TBODY>

<TR ALIGN=CENTER BGCOLOR="#7E79AF">
  <TD></TD>
');

	# Column headers:
	for ($i = 1 ; $i <= $nbCols ; $i++) {
		print GRID_FILE ("  <TH><A HREF=\"$definitionsFileName#$i\">$i</A></TH>\n");
	}
	
	print GRID_FILE ("</TR>\n");


	print SOLUTION_FILE ('
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>

<HEAD>
  <TITLE>Solution</TITLE>
  
  <META NAME="GENERATOR" CONTENT="HTMLxWords (Perl)">
  <META NAME="Author" CONTENT="Denis NICOLAS">
  <META NAME="Description" CONTENT="Solution d\'une grille de mots croisés. Ce document a été conçu pour être affiché dans un Frame, l\'autre Frame affichant les définitions.">
</HEAD>


<BODY TEXT="#000000" BGCOLOR="#7E79AF" LINK="#FFFF00" VLINK="#FFCC00" ALINK="#FF0000"
  BACKGROUND="../../images/Background.jpg">

<BASE TARGET="definitions">

<CENTER>

<TABLE BORDER=1 CELLSPACING=0 BGCOLOR="#FFFFFF">

<CAPTION>
  <H1>
    <FONT COLOR="#FFCC00">
  ');
	
	print SOLUTION_FILE ("    Solution de la Grille n&deg; $fileNb");
	
	print SOLUTION_FILE ('
    </FONT>
  </H1>
</CAPTION>

<TBODY>

<TR ALIGN=CENTER BGCOLOR="#7E79AF">
  <TD></TD>
');
	
	# Column headers:
	for ($i = 1 ; $i <= $nbCols ; $i++) {
		print SOLUTION_FILE ("  <TH WIDTH = 20>",
												 "<A HREF=\"$definitionsFileName#$i\">$i</A></TH>\n");
	}
	
	print SOLUTION_FILE ("</TR>\n");
	
	
	# Grid lines:
	$nbLines = 0;
	while ($line ne "") {
		$nbLines++;
		print GRID_FILE ("\n<TR>\n");
		# Row header:
		print GRID_FILE ('  <TH ALIGN=RIGHT BGCOLOR="#7E79AF">');
		print GRID_FILE ("<A HREF=\"$definitionsFileName#$romans{$nbLines}\">",
										 "$romans{$nbLines}</A></TH>\n");
		
		print SOLUTION_FILE ("\n<TR ALIGN=CENTER>\n");
		# Row header:
		print SOLUTION_FILE ('  <TH ALIGN=RIGHT BGCOLOR="#7E79AF">');
		print SOLUTION_FILE ("<A HREF=\"$definitionsFileName#$romans{$nbLines}\">",
												 "$romans{$nbLines}</A></TH>\n");

		# One grid line:
		foreach $character (@characters) {
			print GRID_FILE ('  <TD>');
			
			if ($character eq "_") {
				print GRID_FILE ('<FONT COLOR="#000000">b</FONT>');
				print SOLUTION_FILE ("  <TD BGCOLOR=\"#000000\">",
														 "<FONT COLOR=\"#000000\">b</FONT></TD>\n");
			} else {
				print GRID_FILE ('<INPUT SIZE="2" MAXLENGTH=1>');
				print SOLUTION_FILE ("  <TD>$character</TD>\n");
			}
			
			print GRID_FILE ("</TD>\n");
		}
		
		print GRID_FILE ("</TR>\n");
		print SOLUTION_FILE ("</TR>\n");
		
		$line = <INPUT_FILE>;
		chop($line);
		@characters = split(//, $line);
	}
	
	# Generate the end of GRID_FILE.
	print GRID_FILE ('
</TBODY>

</TABLE>

</FORM>

<P>
');
	
	print GRID_FILE ("<A HREF=\"$solutionFileName\" TARGET=\"_self\">");
	
	print GRID_FILE ('Je donne ma langue au chat !</A>
</P>

</CENTER>

</BODY>

</HTML>
	');
	
	
	# Generate the end of SOLUTION_FILE.
	print SOLUTION_FILE ('	
</TBODY>

</TABLE>

</CENTER>

</BODY>

</HTML>
	');
	
	
	close(GRID_FILE);
	close(SOLUTION_FILE);
	
	return($nbLines);
}


################################################################################
# DEFINITIONS_FILE is the HTML file containing the definitions.                #
################################################################################
sub generateDEFINITIONS_FILE {

	my($line, $lineCounter, $nb);
	
	&openOutputFile("DEFINITIONS_FILE", $definitionsFileName);
	select(DEFINITIONS_FILE);
	
	# Beginning of the file.
	print('
<HTML>

<HEAD>
  <TITLE>D&eacute;finitions</TITLE>
  
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
  <META NAME="GENERATOR" CONTENT="HTMLxWords (Perl)">
  <META NAME="Author" CONTENT="Denis NICOLAS">
  <META NAME="Description" CONTENT="Définitions d\'une grille de mots croisés. Ce document a été conçu pour s\'afficher dans un Frame, l\'autre Frame contenant la grille.">
</HEAD>


<BODY TEXT="#FFCC00" BGCOLOR="#7E79AF" LINK="#FFFF00" VLINK="#FFCC00" ALINK="#FF0000"
  BACKGROUND="../../images/Background.jpg">

<CENTER>

<TABLE BORDER CELLPADDING=5>

<CAPTION>
  <H2>HORIZONTALEMENT</H2>
</CAPTION>

<TBODY>
	');
	
	$lineCounter = 1;
	# Read all the definitions.
	while ($line = <INPUT_FILE>) {
		print("\n<TR VALIGN=TOP>\n");
		# Definition number:
		print("  <TH ALIGN=RIGHT>");
				
		if ($lineCounter <= $nbLines) {
			# Number for a horizontal definition:
			$nb = $romans{$lineCounter};
		} else {
			# Number for a vertical definition:
			$nb = $lineCounter - $nbLines;
		}
		print("<A NAME=\"$nb\">$nb</A></TH>\n  <TD>\n");
		
		# All the definitions for this number:
		do {
			chop($line);
			$line = &charEntities($line);
			print("    $line<BR>\n");
			$line = <INPUT_FILE>;
		} until ($line eq "\n");
		
		print("  </TD>\n</TR>\n");
		
		if ($lineCounter == $nbLines) {
			# End of horizontal definitions and beginning of vertical ones.
			print('
</TBODY>

</TABLE>

</CENTER>

<P>
<HR>
</P>

<CENTER>

<TABLE BORDER CELLPADDING=5>

<CAPTION>
  <H2>VERTICALEMENT</H2>
</CAPTION>

<TBODY>
			');
		}
		
		$lineCounter++;
	}
	
	# Generate end of file.
	print('
</TBODY>

</TABLE>

</CENTER>

<P>
<HR>
</P>

<CENTER>
<FONT SIZE=+1>
  <A HREF="../../HomePage.html" TARGET="_top">Home Page</A>
</FONT>
</CENTER>

<P>
  <HR>
  ');
  
  print("Derni&egrave;re mise &agrave; jour le ", &getDate, ".<BR>");
  
  print('
  Commentaires et suggestions bienvenus !
</P>

<ADDRESS>
  Denis NICOLAS, <A HREF="mailto:denicola@worldnet.fr">denicola@worldnet.fr</A>
</ADDRESS>

</BODY>

</HTML>
	');

	close(DEFINITIONS_FILE);
	select(STDOUT);
}


################################################################################
# Returns the date as a string.                                                #
# Example: "11 Juillet 97".                                                    #
################################################################################
sub getDate {

	my(@months, @time, $date, $month, $year);
	
	@months = (
		"Janvier",
		"Février",
		"Mars",
		"Avril",
		"Mai",
		"Juin",
		"Juillet",
		"Août",
		"Septembre",
		"Octobre",
		"Novembre",
		"Décembre"
	);

	@time = localtime(time());
	$date = $time[3];
	$month = $months[$time[4]];
	$year = $time[5];
	
	return ("$date $month $year");
}


################################################################################
# Receives a string.                                                           #
# Replaces special characters with the corresponding HTML character entities.  #
# Returns the resulting string.                                                #
################################################################################
sub charEntities {
	my($string) = @_;

	$string =~ s/&/&amp;/g;
	$string =~ s/</&lt;/g;
	$string =~ s/>/&gt;/g;
	$string =~ s/\xE0/&agrave;/g;	# à
	$string =~ s/\xE2/&acirc;/g;	# â
	$string =~ s/\xE4/&auml;/g;		# ä
	$string =~ s/\xE7/&ccedil;/g;	# ç
	$string =~ s/\xE8/&egrave;/g;	# è
	$string =~ s/\xE9/&eacute;/g;	# é
	$string =~ s/\xEA/&ecirc;/g;	# ê
	$string =~ s/\xEB/&euml;/g;		# ë
	$string =~ s/\xEE/&icirc;/g;	# î
	$string =~ s/\xEF/&iuml;/g;		# ï
	$string =~ s/\xF4/&ocirc;/g;	# ô
	$string =~ s/\xF6/&ouml;/g;		# ö
	$string =~ s/\xF9/&ugrave;/g;	# ù
	$string =~ s/\xFB/&ucirc;/g;	# û
	$string =~ s/\xFC/&uuml;/g;		# ü
	
	return ($string);
}

