# !perl

# Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.

# Version Info:
# Version 001:  - specialisation of smhtml for the aleppo help compiler (much simpler)

# smhtml version info:

# Version 016:	- Able to find altable.sty in paths containing ;; and those that start with ;
# Version 015:	- now prepends EPOC32: to the title of all pages
# Version 014:  - now includes release option:
#					- turn on background
#					- turn off confidential and Samaria text
#					- delete any status comments before the first Heading 2
#				- now uses a button-bar for navlinks rather than the old text version (no change to .nav file)
# Version 013:  - now includes Javascript for displaying pop-out windows
#				- now handles <figure-picture> tags arising from Figure Directives
# Version 012:  - new translations for <figure-picture> tags
# Version 011:  - new translation <cs style="lcode" => <code> [this is needed to ensure no subsequent implicit linking of text from an explicit link]
# Version 010:	- changes for figure styles (<figure>=><dl> and </figure>=></dl>), figure anchor gets [ and ] around text
#				- changes for syntax style (now horizontal rules are put around the syntax lines)
# Version 009:	- no longer puts vertical rule before a heading 5
# Version 008:  - now checks to see if linking to top anchor in a file - if yes, links to the file, not the anchor
# Version 007:	- now converts glossary links
# Version 006:  - now searches the path for samaria.rsc and smtable.sty
#				- now handles <manual formattype> tags by highlighting them in purple
# Version 005:	- now handles file:// type as well as http:// type URL References
#			 	  (converts backslashes to forward slashes, handles local disk filing systems)
#				- also puts tab in indented code style lines
#				- also tabulates Syntax style (alteration in smtable.sty)
# Version 004:	- now takes navigation link input from .nav file (created by smnav) to produce navlinks for a cs-ptml file
# Version 003:	- now converts all special characters into ISO8859-1 or Microsoft set (according to command line switch)
#				- also displays pictures
# Version 002:	- now uses style table for many translations
# Version 001:	- converts .named-ptml to .html

# ------------------------------------- Global variables -----------------------------------
# --- path variables for finding support files ---
$path_list = "";
@path_array = ();
# ---- for handling style tables ----
$proof_document = 1;
%opening_tags = ();		# associative array of styles to opening tags
%closing_tags = ();		# associative array of styles to opening tags
# --------- for tables --------
$in_table = 0;						# whether the context is in a table or not (boolean)
$in_cell = -1;						# whether the context is in a table cell (integer)
@column_widths = "";				# the width of the columns of the current table (array of integer)
# ---- for graphics index ---
@mbm_index = ();					# index of graphics in the file to be processed
# -------- filenames --------
$without_extender = "";				# input file without extender
$log_name = "";						# filename of error file
$html_name = "";					# filename of pipeline output file
$style_table_name = "";				# filename of the style table
$input_name = "";					# filename of input file
$mbm_name = "";						# filename of .mbm file
# -------- arguments --------
$input_extension = "sgml";				# default input file extension
$input_directory = pwd()."\\";			# default input directory is current directory 
$output_extension = "html";				# default output file extension
$output_directory = pwd()."\\";			# default output directory is current directory
$stylefile = "";						# default name of stylefile is null
$console_error = 1;						# default is to display errors on the console
$log_error = 0;							# default is not to log errors in a file
$log_name = pwd()."\\aleppo.log";		# default logfile name
$resource_name = "samaria.rsc";			# default resource-file name
$release_build = 0;
# ------------------------------------------------------------------------------------------

# ------------------------------------------- Start of Main() ----------------------------------------

&handle_command_line_args();										# calculate filenames
&get_path_into_array();
&load_style_table();

open(INFILE,"$input_name") || &log_die("Cannot find $input_name");				# open input file (.linked-ptml)
open(HTMLFILE,">$html_name") || &log_die("Cannot create $html_name");			# open output file (.html)
if ($log_error == 1) {
	open(LOGFILE,">>$log_name") || &log_die("Cannot create $log_name");			# open error log for appending
}

&get_mbm_list();
&print_html_header();

$line_number = 0;
while ($_ = <INFILE>)	{							# Iterate over all lines of the linked-ptml file
	$line_number++;									# increment line count (for error logging)

	s/<topictitle>(.*)<\/topictitle>/<h2>$1<\/h2>/;	# convert topic titles to h2
	s/<synonyms>(.*)<\/synonyms>/<p>Synonyms: <i>$1<\/i><\/p>/;	# convert synonyms
	
	if (/<p style="([^"]*)">(.*)<\/p>/) {			# translate paragraph style
		&translate_paragraph_style($1,$2);
	}
	 
	while (/<graphic index=(.*)>/) {				# translate graphic
		&translate_graphic_index($1);		
	}

	while (/<cs style="([^"]*)">(.*?)<\/cs>/) {		# repeatedly, translate character styles
		&translate_character_style($1,$2);
	}

	while (/<manual formattype="([^\"]*)">(.*?)<\/manual>/) {
		&translate_manual_format();
	}
	 
	&translate_special_chars();

	# all translations done - print the line
	print HTMLFILE;
}

&print_html_footer();

close(HTMLFILE);
close(INFILE);
if ($log_error == 1) {
	close(LOGFILE);
}

# ---------------------------------------------- End of Main() ------------------------------------------

sub get_mbm_list {
	if (open(MBMLIST,"$mbm_name")) {
		$index = 0;
		while ($_ = <MBMLIST>) {
			/name=(.*?) bitmapfile=(.*?) /;
			$image_name = $1.".jpg";	
			$mbm_index[$index] = $image_name;
			$index++;
		}
		close(MBMLIST);
	}
}

sub get_path_into_array {
	$path_list = $ENV{"PATH"};
	$path_list =~ s/\;(\;*)/\;/g;
	$path_list =~ s/^;//;
	@path_array = split(/;/,$path_list);
}

# -------------------------------------- Load Style Translation Table -----------------------------------

sub load_style_table {
	# search path for style file
	$cur_path_pos = 0;
	$found_and_opened = 0;
	while ($path_array[$cur_path_pos] && $found_and_opened == 0) {
		if (open(STYLEFILE,"$path_array[$cur_path_pos]\\$style_table_name")) {	# try to open style file
			$found_and_opened = 1;
		} else {
			$cur_path_pos++;
		}
	}
	if ($found_and_opened == 0) {
		&log_die("Cannot find $style_table_name in path");
	}

	if ($first_line = <STYLEFILE>) {
		if ($first_line ne "<Aleppo Style Table>\n") {
			&log_error("File $style_table_name is not a valid Aleppo style table");
			exit;
		} else {
			while ($_ = <STYLEFILE>)	{			# Iterate over all lines of the style file
				/([^=]*)=(.*)/;
				$this_style = $1;
				$open_tag_list = $2;
				$close_tag_list = &tag_reverse($open_tag_list);
				$opening_tags{$this_style} = $open_tag_list;
				$closing_tags{$this_style} = $close_tag_list;
			}
		}
	}
	close(STYLEFILE);
}

sub tag_reverse {
	my($open_tag_list) = @_;
	$close_tag_list = "";
	while ($open_tag_list =~ /<([^>]*)>/) {			# while there are still tags
		$tag = "<\/$1>";
		$tag =~ s/<\/([^ ]*) (.*)>/<\/$1>/;
		$close_tag_list = $tag.$close_tag_list;	# append corresponding end tag to start of close tag list
		$open_tag_list = $';					# and continue with the rest of the open tag list
	}
	return $close_tag_list;
}

# ---------------------------------------- SGML to HTML Conversions -------------------------------------

sub translate_graphic_index {
	my($index) = @_;
	
	# look up the index in the mbm index file
	$graphic_location = $mbm_index[$index];

	s/<graphic index=(.*?)>/<img src=$graphic_location>/;
}

sub translate_paragraph_style {
	my($this_style,$this_content) = @_;

	if ($open_tags = $opening_tags{$this_style}) {			# if this style has a tag defined in the stylefile
		if ($open_tags eq "[NULL]") {
			$_ = "";				# NULL style - delete this line
		} else {
			$close_tags = $closing_tags{$this_style};		# find the style's corresponding closing tag
			$_ = $open_tags.$this_content.$close_tags."\n";
		}
	} elsif ($this_style eq "note" || $this_style eq "tip") {
		if ($this_style eq "note") {
			$style = "Note:";
		} else {
			$style = "Tip:";
		}
		$_ = "<dl>\n<dt>$style</dt>\n<dd>$this_content</dd>\n</dl>\n";
	} else {
		&translate_unknown_paragraph_style();
	}
}

sub translate_character_style {
	my($this_style,$this_content) = @_;

	if ($open_tags = $opening_tags{$this_style}) {
		if ($open_tags eq "[NULL]") {
			s/<cs style="([^"]*)">(.*?)<\/cs>//; # NULL style - delete this content
		} else {
			$close_tags = $closing_tags{$this_style};
			$replace = $open_tags.$this_content.$close_tags;
			s/<cs style="([^"]*)">(.*?)<\/cs>/$replace/;
		}
	} else {
		&translate_unknown_character_style();
	}
}

sub translate_manual_format {
	# color the manually formatted section in purple for easy identification
	s/<manual formattype="([^"]*)">(.*?)<\/manual>/<font color=#FF00FF>&lt;manual formattype=&quot;$1&quot;&gt;$2&lt;\/manual&gt;<\/font>/i;
}

sub translate_special_chars {
	s/&tab;/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/g;		# default translation of tabs to six non-blanking spaces
														# NB. &amp; &gt; &lt; are already in the correct format

	if ($use_iso_latin1 == 0) {		# if Microsoft char set should be used
		s/&lquote;/&#145;/g;
		s/&rquote;/&#146;/g;
		s/&ldquote;/&#147;/g;
		s/&rdquote;/&#148;/g;
		s/&mdash;/&#151;/g;
		s/&ndash;/&#150;/g;
	} else {						# if ISO-LATIN-1 char set should be used
		s/&lquote;/'/g;
		s/&rquote;/'/g;
		s/&ldquote;/"/g;
		s/&rdquote;/"/g;
		s/&mdash;/-/g;
		s/&ndash;/-/g;
	}

	if (/<pre>(.*)<\/pre>/) {
		s/<pre>(.*)<\/pre>/<pre>    $1<\/pre>/;		# do first line indent (four spaces)
		s/&break;/\n    /g;		# within an Indented/Reduced Code paragraph line break => \n
	} else {
		s/&break;/<br>/g;		# if not do normal translation of line breaks => <br>
	}
}

# ----------- Paragraph style translations -----------

sub translate_unknown_paragraph_style {
	# report unknown style to error log
	$style = $_;	
	$style =~ s/<p style="([^"]*)">(.*)<\/p>/$1/;
	$style =~ s/(.*)\n/$1/;
	&log_error("Unknown paragraph style '$style'");

	# unknown style so present it raw, colored red
	s/<p style="([^"]*)">(.*)<\/p>/<p><font color=#FF0000>&lt;p style=&quot;$1&quot;&gt;$2&lt;\/p&gt;<\/font><\/p>/i;
}

# ----------- Character style translations -----------

sub translate_unknown_character_style {
	# report unknown style to error log
	/<cs style="([^"]*)">(.*?)<\/cs>/;
	&log_error("Unknown character style '$1'");

	# unknown style so present it raw, colored red
	s/<cs style="([^"]*)">(.*?)<\/cs>/<font color=#FF0000>&lt;cs style=&quot;$1&quot;&gt;$2&lt;\/cs&gt;<\/font>/i;
}

# ------------------------------- HTML Header and Footer functions ------------------------------------

sub print_html_header {
	print HTMLFILE "<!DOCTYPE  HTML    PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
	print HTMLFILE "<html>\n<body>\n";
}

sub print_html_footer {
	print HTMLFILE "</body>\n";
	print HTMLFILE "</html>\n";
}

# --------------------------------- Start of command-line parse stuff ---------------------------------

sub handle_command_line_args {
	&extract_command_line_args("alhtml");
	$input_name = $input_directory.$without_extender.".".$input_extension;
	$html_name = $output_directory.$without_extender.".".$output_extension;
	$mbm_name = $input_directory.$without_extender.".mbm-list";
	$this_book = what_book();
}

# ----------------------------------------- Misc functions --------------------------------------------

sub strip_all_styles {
	my($input_string) = @_;
	$input_string =~ s/<cs([^>]*)>(.*?)<\/cs>/$2/g;		# strip character styles
	$input_string =~ s/<([^>]*)>(.*?)<\/\1>/$2/g;		# strip simple styles: italic, bold, etc.
	return $input_string;
}

sub extract_command_line_args {
	my($program_title) = @_;
	if ($this_arg = pop(@ARGV)) {
		$without_extender = $this_arg;		# filename (without extender) is always the last argument

		while ($this_arg = pop(@ARGV)) {
			if ($this_arg =~ /-ie/) {
				$input_extension = $this_arg;
				$input_extension =~ s/-ie(.*)/$1/;
			} elsif ($this_arg =~ /-oe/) {
				$output_extension = $this_arg;
				$output_extension =~ s/-oe(.*)/$1/;
			} elsif ($this_arg =~ /-id/) {
				$input_directory = $this_arg;
				$input_directory =~ s/-id(.*)/$1/;
			} elsif ($this_arg =~ /-od/) {
				$output_directory = $this_arg;
				$output_directory =~ s/-od(.*)/$1/;
			} elsif ($this_arg =~ /-sf/) {
				$style_table_name = $this_arg;
				$style_table_name =~ s/-sf(.*)/$1/;
			} elsif ($this_arg =~ /-mc-/) {
				$console_error = 0;
			} elsif ($this_arg =~ /-ml/) {
				$log_error = 1;
				if ($this_arg ne "-ml") {			# if a logfile name is specified...
					$log_name = $this_arg;
					$log_name =~ s/-ml(.*)/$1/;
				}
			} else {
				print "Illegal argument: $this_arg";
				exit;
			}
		}
	} else {								# no arguments - print message and exit
		print "Use of $program_title:\n\t$program_title [options] filename\n\noptions:\n\t-ie(input extension)\n".
				"\t-oe(output extension)\n\t-id(input directory)\n\t-od(output directory)\n".
				"\t-sf(style-table filename)\n\t-mc-\n\t-ml(logfile)";
		exit;
	}
}

sub log_error {
	$error_string = $_[0];
	if ($log_error == 1) {
		print LOGFILE "ERROR - $without_extender: $error_string (line $line_number)\n";
	}
	if ($console_error == 1) {
		print "ERROR - $without_extender: $error_string (line $line_number)\n";
	}
}

sub log_die {
	$error_string = $_[0];
	if ($log_error == 1) {
		print LOGFILE "ERROR - $error_string\n";
	}
	die "ERROR - $error_string";
}

# ---------------------------------------- Directory handling fns -----------------------------------

sub pwd {
	$dir = `cd`;								# find current directory
	chop($dir);									# remove the eoln
	return $dir;								# and return it
}

sub what_book {					
	$start_dir = pwd();							# get the current directory string
	chdir($input_directory);					# go to the directory of the input file

	$full_dir = pwd();							# get that directory
	@dir_list = split(/\\/,$full_dir);			# split directory string into sub-dir list

	chdir("$start_dir");						# revert back to the start directory

	return pop(@dir_list);						# return the last item in the list - ie. the input file's book
}

__END__
