MayaChemTools

   1 #!/usr/bin/perl -w
   2 #
   3 # $RCSfile: TextFilesToHTML.pl,v $
   4 # $Date: 2008/01/30 21:45:04 $
   5 # $Revision: 1.28 $
   6 #
   7 # Author: Manish Sud <msud@san.rr.com>
   8 #
   9 # Copyright (C) 2004-2008 Manish Sud. All rights reserved.
  10 #
  11 # This file is part of MayaChemTools.
  12 #
  13 # MayaChemTools is free software; you can redistribute it and/or modify it under
  14 # the terms of the GNU Lesser General Public License as published by the Free
  15 # Software Foundation; either version 3 of the License, or (at your option) any
  16 # later version.
  17 #
  18 # MayaChemTools is distributed in the hope that it will be useful, but without
  19 # any warranty; without even the implied warranty of merchantability of fitness
  20 # for a particular purpose.  See the GNU Lesser General Public License for more
  21 # details.
  22 #
  23 # You should have received a copy of the GNU Lesser General Public License
  24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
  25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
  26 # Boston, MA, 02111-1307, USA.
  27 #
  28 
  29 use 5.006;
  30 use strict;
  31 use FindBin; use lib "$FindBin::Bin/../lib";
  32 use Getopt::Long;
  33 use File::Basename;
  34 use Text::ParseWords;
  35 use Benchmark;
  36 use FileUtil;
  37 use TextUtil;
  38 use HTMLUtil;
  39 
  40 my($ScriptName, %Options, $StartTime, $EndTime, $TotalTime);
  41 
  42 # Autoflush STDOUT
  43 $| = 1;
  44 
  45 # Starting message...
  46 $ScriptName = basename($0);
  47 print "\n$ScriptName: Starting...\n\n";
  48 $StartTime = new Benchmark;
  49 
  50 # Get the options and setup script...
  51 SetupScriptUsage();
  52 if ($Options{help} || @ARGV < 1) {
  53   die GetUsageFromPod("$FindBin::Bin/$ScriptName");
  54 }
  55 
  56 my(@TextFilesList);
  57 @TextFilesList = ExpandFileNames(\@ARGV, "csv tsv");
  58 
  59 #Make sure appropriate mode specific option values are specified...
  60 print "Processing options...\n";
  61 my($ShadeRowsStatus, $HighlightStatus, $OddRowsShadeColor, $EvenRowsShadeColor, $ValueOkColor, $ValueNotOkColor, $TableHeaderRowColor, $RowVAlignment, $RowHAlignment, $TableHeaderRowHAlignment, $TableHeaderRowVAlignment, $TableBorder, $TableCellPadding, $TableCellSpacing, $TitleDisplay, $Footer, $NavLinksAtTop, $NavLinksAtBottom, $NavLinksTableInfo, $NavLinksLineInfo, @SpecifiedColIds, @SpecifiedColDataTypes, @SpecifiedColCriteria, @SpecifiedColValues);
  62 ProcessOptions();
  63 
  64 # Collect column information for all the text files...
  65 print "Checking input text file(s)...\n";
  66 my(@TextFilesOkay, @TextFilesColCount, @TextFilesLineCount, @TextFilesInDelim, @TextFilesHTMLRoot, @TextFilesHTMLTitle, @TextFilesMultipleHTMLTables, @TextFilesColLabels, @TextFilesColLabelToNumMap, @TextFilesTopHTMLDir, @TextFilesSubHTMLDir);
  67 RetrieveTextFilesInfo();
  68 
  69 # Setup columns to hightlight...
  70 my(@TextFilesHightlightColNumMap, @TextFilesHightlightDataMap);
  71 ProcessColumnsToHighlight();
  72 
  73 # Setup navigation link information for multiple tables...
  74 my(@TextFilesTableCount, @TextFilesTableHTMLFiles, @TextFilesTableStartLineNum, @TextFilesTableEndLineNum);
  75 SetupMultipleTablesInfo();
  76 
  77 my($Index, $TextFile, $RowHeaderTags, $RowEndTags, $BgFilledOddRowHeaderTags, $BgFilledEvenRowHeaderTags, $TableRowHeaderTags);
  78 
  79 # Setup row tags...
  80 $RowHeaderTags = ""; $RowEndTags = ""; $BgFilledOddRowHeaderTags = ""; $BgFilledEvenRowHeaderTags = ""; $TableRowHeaderTags = "";
  81 $RowHeaderTags = SetupHTMLTableRowHeader($RowHAlignment, "", $RowVAlignment);
  82 $RowEndTags = SetupHTMLTableRowEnd();
  83 if ($ShadeRowsStatus) {
  84   $BgFilledOddRowHeaderTags = SetupHTMLTableRowHeader($RowHAlignment, $OddRowsShadeColor, $RowVAlignment);
  85   $BgFilledEvenRowHeaderTags = SetupHTMLTableRowHeader($RowHAlignment, $EvenRowsShadeColor, $RowVAlignment);
  86 }
  87 $TableRowHeaderTags = SetupHTMLTableRowHeader($TableHeaderRowHAlignment, $TableHeaderRowColor, $TableHeaderRowVAlignment);
  88 
  89 if (@TextFilesList > 1) {
  90   print "Processing text files...\n";
  91 }
  92 for $Index (0 .. $#TextFilesList) {
  93   if ($TextFilesOkay[$Index]) {
  94     $TextFile = $TextFilesList[$Index];
  95     if (@TextFilesList > 1) {
  96       print "\nProcessing file $TextFile...\n";
  97     }
  98     else {
  99       print "Processing file $TextFile...\n"
 100     }
 101     if ($TextFilesMultipleHTMLTables[$Index]) {
 102       GenerateMultipleHTMLTable($Index);
 103     }
 104     else {
 105       GenerateOneHTMLTable($Index);
 106     }
 107   }
 108 }
 109 
 110 print "$ScriptName:Done...\n\n";
 111 
 112 $EndTime = new Benchmark;
 113 $TotalTime = timediff ($EndTime, $StartTime);
 114 print "Total time: ", timestr($TotalTime), "\n";
 115 
 116 ###############################################################################
 117 
 118 sub GenerateOneHTMLTable {
 119   my($Index) = @_;
 120   my($TopHTMLDir, $HTMLFile, $Line, $StartRowNum, $EndRowNum, $CSSFile, $CSSFilePath, $CSSRef);
 121 
 122   $HTMLFile = $TextFilesHTMLRoot[$Index] . ".html";
 123   $TextFile = $TextFilesList[$Index];
 124 
 125   # Setup data directories...
 126   ($TopHTMLDir) = SetupDataDirs($Index);
 127 
 128   # Setup stylesheet file...
 129   $CSSRef = "";
 130   if ($Options{stylesheet} =~ /^new$/i) {
 131     $CSSFile = $TextFilesHTMLRoot[$Index] . ".css"; $CSSRef = ".\/" . "$CSSFile";
 132     $CSSFilePath = "$TopHTMLDir" . "\/" . $CSSFile;
 133     GenerateStyleSheetFile($CSSFilePath);
 134   }
 135   elsif ($Options{stylesheet} =~ /^old$/i) {
 136     $CSSRef = $Options{stylesheetname};
 137   }
 138   # Set HTML file location...
 139   $HTMLFile = "$TopHTMLDir" . "\/" . $HTMLFile;
 140 
 141   print "Generating HTML file $HTMLFile...\n";
 142   open HTMLFILE, ">$HTMLFile" or die "Error: Can't open $HTMLFile: $! \n";
 143   open TEXTFILE, "$TextFile" or die "Error: Can't open $TextFile: $! \n";
 144 
 145   # Write out HTML page header...
 146   print HTMLFILE SetupHTMLPageHeader($TextFilesHTMLTitle[$Index], $CSSRef);
 147   if ($TitleDisplay) {
 148     print HTMLFILE SetupHTMLPageTitle($TextFilesHTMLTitle[$Index]);
 149   }
 150   else {
 151     print HTMLFILE SetupHTMLEmptyLines(1);
 152   }
 153 
 154   # Start the table...
 155   print HTMLFILE SetupHTMLAlignmentBegin("center");
 156   print HTMLFILE SetupHTMLTableHeader($TableBorder, $TableCellPadding, $TableCellSpacing);
 157 
 158   WriteColLabels($Index, \*TEXTFILE, \*HTMLFILE);
 159 
 160   # Skip the labels and write out all the other rows...
 161   $Line = <TEXTFILE>;
 162   $StartRowNum = 1;
 163   $EndRowNum = $TextFilesLineCount[$Index];
 164   WriteRowValues($Index, $StartRowNum, $EndRowNum, \*TEXTFILE, \*HTMLFILE);
 165 
 166   # Finish up the table...
 167   print HTMLFILE SetupHTMLTableEnd();
 168   print HTMLFILE SetupHTMLAlignmentEnd("center");
 169 
 170   # Write out HTML page end...
 171   print HTMLFILE SetupHTMLPageEnd($Footer);
 172 
 173   close HTMLFILE;
 174   close TEXTFILE;
 175 }
 176 
 177 # Generate multiple tables...
 178 sub GenerateMultipleHTMLTable {
 179   my($Index) = @_;
 180   my($TopHTMLDir, $SubHTMLDir, $TextFile, $HTMLFile, $TableNum, $TableCount, $TableIndex, $TableStartLineNum, $TableEndLineNum, $Line, $InSubHTMLDir, $PrintMsg, $CSSFile, $CSSFilePath, $CSSRef, $NewStyleSheet);
 181 
 182   # Open text file and skip over label line...
 183   $TextFile = $TextFilesList[$Index];
 184   open TEXTFILE, "$TextFile" or die "Error: Can't open $TextFile: $! \n";
 185   $Line = <TEXTFILE>;
 186 
 187   # Set up data directories to hold various html files...
 188   ($TopHTMLDir, $SubHTMLDir) = SetupDataDirs($Index);
 189 
 190   # Create stylesheet file...
 191   $CSSRef = "";
 192   $NewStyleSheet = 0;
 193   if ($Options{stylesheet} =~ /^new$/i) {
 194     $NewStyleSheet = 1;
 195     $CSSFile = $TextFilesHTMLRoot[$Index] . ".css";
 196     $CSSFilePath = "$TopHTMLDir" . "\/" . $CSSFile;
 197     GenerateStyleSheetFile($CSSFilePath);
 198   }
 199   elsif ($Options{stylesheet} =~ /^old$/i) {
 200     $CSSRef = $Options{stylesheetname};
 201   }
 202 
 203   $PrintMsg = 1;
 204   # Generate HTML files for all the tables...
 205   $TableCount = $TextFilesTableCount[$Index];
 206   for $TableNum (1 .. $TableCount) {
 207     $TableIndex = $TableNum - 1;
 208     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$TableIndex];
 209     $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$TableIndex];
 210     $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$TableIndex];
 211 
 212     # Setup file name...
 213     if ($TableNum == 1) {
 214       $HTMLFile = "$TopHTMLDir" . "\/" . $HTMLFile;
 215       print "Generating HTML file $HTMLFile...\n";
 216     }
 217     else {
 218       $HTMLFile = "$SubHTMLDir" . "\/" . $HTMLFile;
 219       if ($PrintMsg) {
 220 	$PrintMsg = 0;
 221 	if ($TableCount == 2) {
 222 	  print "Generating HTML file $HTMLFile...\n";
 223 	}
 224 	else {
 225 	  print "Generating ", ($TableCount - 1), " other HTML files: $SubHTMLDir\/$TextFilesHTMLRoot[$Index]\*.html...\n";
 226 	}
 227       }
 228     }
 229     # Setup stylesheet reference...
 230     if ($NewStyleSheet) {
 231       $CSSRef = ($TableNum == 1) ? ".\/" : "..\/";
 232       $CSSRef .= $CSSFile;
 233     }
 234 
 235     open HTMLFILE, ">$HTMLFile" or die "Error: Can't open $HTMLFile: $! \n";
 236     # Write out HTML page header...
 237     print HTMLFILE SetupHTMLPageHeader($TextFilesHTMLTitle[$Index], $CSSRef);
 238 
 239     # Set up the navigation links for this table...
 240     if ($NavLinksAtTop) {
 241       WriteNavigationLinks($Index, $TableNum, \*HTMLFILE);
 242     }
 243     # Setup page title...
 244     if ($TitleDisplay) {
 245       print HTMLFILE SetupHTMLPageTitle($TextFilesHTMLTitle[$Index]);
 246     }
 247     else {
 248       print HTMLFILE SetupHTMLEmptyLines(1);
 249     }
 250 
 251     # Start the table...
 252     print HTMLFILE SetupHTMLAlignmentBegin("center");
 253     print HTMLFILE SetupHTMLTableHeader($TableBorder, $TableCellPadding, $TableCellSpacing);
 254 
 255     WriteColLabels($Index, \*TEXTFILE, \*HTMLFILE);
 256 
 257     # Write out appropriate row data for this table...
 258     WriteRowValues($Index, $TableStartLineNum, $TableEndLineNum, \*TEXTFILE, \*HTMLFILE);
 259 
 260     # Finish up the table...
 261     print HTMLFILE SetupHTMLTableEnd();
 262     print HTMLFILE SetupHTMLAlignmentEnd("center");
 263 
 264     # Set up the navigation links for this table...
 265     if ($NavLinksAtBottom) {
 266       print HTMLFILE SetupHTMLEmptyLines(1);
 267       WriteNavigationLinks($Index, $TableNum, \*HTMLFILE);
 268     }
 269 
 270     # Write out HTML page end...
 271     print HTMLFILE SetupHTMLPageEnd($Footer);
 272     close HTMLFILE;
 273   }
 274   close TEXTFILE;
 275 
 276 }
 277 
 278 # Create stylesheet file...
 279 sub GenerateStyleSheetFile {
 280   my($CSSFile) = @_;
 281     print "Generating stylesheet file $CSSFile...\n";
 282     open CSSFILE, ">$CSSFile" or die "Error: Can't open $CSSFile: $! \n";
 283     print CSSFILE SetupHTMLStyleSheetTags();
 284     close CSSFILE;
 285 }
 286 
 287 # Write out table header using column labels...
 288 sub WriteColLabels {
 289   my($Index, $TextFileRef, $HTMLFileRef) = @_;
 290   my(@ColLabels, $Label);
 291 
 292   print $HTMLFileRef $TableRowHeaderTags;
 293 
 294   @ColLabels = @{$TextFilesColLabels[$Index]};
 295   for $Label (@ColLabels) {
 296     print $HTMLFileRef SetupHTMLTableRowHeaderValue($Label);
 297   }
 298   print $HTMLFileRef $RowEndTags;
 299 }
 300 
 301 #Write out the rows value...
 302 sub WriteRowValues {
 303   my($Index, $StartRowNum, $EndRowNum, $TextFileRef, $HTMLFileRef) = @_;
 304   my($ColNum, $BackgroundColor, $FontColor, $LineCount, $Line, @RowValues, $Value, $InDelim, $LastColNum);
 305 
 306   $InDelim = $TextFilesInDelim[$Index];
 307   $LastColNum = @{$TextFilesColLabels[$Index]} - 1;
 308 
 309   for $LineCount ($StartRowNum .. $EndRowNum) {
 310     $Line = GetTextLine($TextFileRef);
 311 
 312     if ($ShadeRowsStatus) {
 313       print $HTMLFileRef ($LineCount % 2) ? $BgFilledOddRowHeaderTags : $BgFilledEvenRowHeaderTags;
 314     }
 315     else {
 316       print $HTMLFileRef $RowHeaderTags;
 317     }
 318     @RowValues = quotewords($InDelim, 0, $Line);
 319     for $ColNum (0 .. $LastColNum) {
 320       $Value = ($ColNum <= $#RowValues) ? $RowValues[$ColNum] : "";
 321       $BackgroundColor = ""; $FontColor = "";
 322       if ($HighlightStatus) {
 323 	if (exists($TextFilesHightlightColNumMap[$Index]{$ColNum})) {
 324 	  ($BackgroundColor, $FontColor) = GetValueHighlightColors($Index, $ColNum, $Value);
 325 	}
 326       }
 327       print $HTMLFileRef SetupHTMLTableRowDataValue($Value, $BackgroundColor, $FontColor);
 328     }
 329     print $HTMLFileRef $RowEndTags;
 330   }
 331 }
 332 
 333 # Setup navigation link information for each table.
 334 #
 335 # All table sets besides first and last have these links: FirstTable, Previous, Current-1,Current,Current+1,  Next, and LastTable
 336 # First set: Current, Next, and LastTable
 337 # Last set: FirstTable, Previous and Current.
 338 #
 339 sub WriteNavigationLinks {
 340   my($Index, $CurTableNum, $HTMLFileRef) = @_;
 341   my($TableNum, $StartTableNum, $EndTableNum, $TableIndex, $BorderWidth, $CellPadding, $CellSpacing,$HTMLFile, $HTMLRefFile, $RelativeFileDir, $HTMLRefValue, $FirstTableNum, $FirstTableIndex, $LastTableNum, $LastTableIndex, $TableStartLineNum, $TableEndLineNum, $LastLineNum, $BGColor, $LinksOffSet);
 342 
 343   $LinksOffSet = 10;
 344 
 345   $FirstTableNum = 1; $FirstTableIndex = $FirstTableNum - 1;
 346   $LastTableNum = $TextFilesTableCount[$Index]; $LastTableIndex = $LastTableNum - 1;
 347   $LastLineNum = ${$TextFilesTableEndLineNum[$Index]}[$LastTableIndex];
 348 
 349   # Figure out which links to display for a particular table...
 350   $StartTableNum = $CurTableNum - $LinksOffSet + 1;
 351   $StartTableNum = ($StartTableNum < $FirstTableNum) ? $FirstTableNum : $StartTableNum;
 352   if ($CurTableNum < $LinksOffSet) {
 353     $EndTableNum = $LinksOffSet;
 354   }
 355   else {
 356     $EndTableNum = $CurTableNum + $LinksOffSet - 1;
 357   }
 358   $EndTableNum = ($EndTableNum > $LastTableNum) ? $LastTableNum : $EndTableNum;
 359 
 360   my($InactiveLinkNumColor, $InactiveLinkFontBold) = ("#8e2323", "1");
 361   my($LinkTextColor, $LinkBGColor, $LinkFontBold) = ("", "", "1");
 362 
 363   # Start link table...
 364   $BorderWidth = 0; $CellPadding = 2; $CellSpacing = 2;
 365   print $HTMLFileRef SetupHTMLAlignmentBegin("center");
 366   print $HTMLFileRef SetupHTMLDivBegin("tablenav");
 367   print $HTMLFileRef  SetupHTMLTableHeader($BorderWidth, $CellPadding, $CellSpacing);
 368   print $HTMLFileRef $RowHeaderTags;
 369 
 370   if ($NavLinksTableInfo && $NavLinksLineInfo) {
 371     print $HTMLFileRef SetupHTMLTableRowDataValue("Showing table $CurTableNum of $LastTableNum");
 372     print $HTMLFileRef SetupHTMLTableRowDataValue("&nbsp");
 373     print $HTMLFileRef SetupHTMLTableRowDataValue("&nbsp");
 374   }
 375 
 376   print $HTMLFileRef SetupHTMLTableRowDataValue("Tables: ");
 377   # Setup a link to first table...
 378   if ($StartTableNum != $FirstTableNum) {
 379     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$FirstTableIndex];
 380     $HTMLRefFile = GetRelativeFileDir($CurTableNum, $FirstTableNum, $FirstTableNum) . $HTMLFile;
 381     $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$FirstTableIndex];
 382     $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$FirstTableIndex];
 383     $HTMLRefValue = SetupHTMLHRef("First", $HTMLRefFile, "First Table Containing Lines $TableStartLineNum To $TableEndLineNum");
 384     print $HTMLFileRef SetupHTMLTableRowDataValue($HTMLRefValue, $LinkBGColor, $LinkTextColor, $LinkFontBold);
 385   }
 386 
 387   # Setup link to previous table...
 388   if ($CurTableNum != $FirstTableNum) {
 389     my($PreviousTableNum, $PreviousTableIndex);
 390     $PreviousTableNum = $CurTableNum - 1; $PreviousTableIndex = $PreviousTableNum - 1;
 391     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$PreviousTableIndex];
 392     $HTMLRefFile = GetRelativeFileDir($CurTableNum, $PreviousTableNum, $FirstTableNum) . $HTMLFile;
 393     $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$PreviousTableIndex];
 394     $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$PreviousTableIndex];
 395     $HTMLRefValue = SetupHTMLHRef("Previous", $HTMLRefFile, "Previous Table Containing Lines $TableStartLineNum To $TableEndLineNum");
 396     print $HTMLFileRef SetupHTMLTableRowDataValue($HTMLRefValue, $LinkBGColor, $LinkTextColor, $LinkFontBold);
 397   }
 398 
 399   for $TableNum ($StartTableNum .. $EndTableNum) {
 400     $TableIndex = $TableNum - 1;
 401     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$TableIndex];
 402     if ($TableNum == $CurTableNum) {
 403       print $HTMLFileRef SetupHTMLTableRowDataValue($TableNum, $LinkBGColor, $InactiveLinkNumColor, $InactiveLinkFontBold);
 404     }
 405     else {
 406       # Setup the link...
 407       my($RefTitle);
 408       $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$TableIndex];
 409       $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$TableIndex];
 410       $RefTitle = AddNumberSuffix($TableNum) . " Table Containing Lines $TableStartLineNum To $TableEndLineNum";
 411       $HTMLRefFile = GetRelativeFileDir($CurTableNum, $TableNum, $FirstTableNum) . $HTMLFile;
 412       $HTMLRefValue = SetupHTMLHRef($TableNum, $HTMLRefFile, $RefTitle);
 413       print $HTMLFileRef SetupHTMLTableRowDataValue($HTMLRefValue);
 414     }
 415   }
 416 
 417   # Setup link to next table...
 418   if ($CurTableNum != $LastTableNum) {
 419     my($NextTableNum, $NextTableIndex);
 420     $NextTableNum = $CurTableNum + 1; $NextTableIndex = $NextTableNum - 1;
 421     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$NextTableIndex];
 422     $HTMLRefFile = GetRelativeFileDir($CurTableNum, $NextTableNum, $FirstTableNum) . $HTMLFile;
 423     $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$NextTableIndex];
 424     $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$NextTableIndex];
 425     $HTMLRefValue = SetupHTMLHRef("Next", $HTMLRefFile, "Next Table Containing Lines $TableStartLineNum To $TableEndLineNum");
 426     print $HTMLFileRef SetupHTMLTableRowDataValue($HTMLRefValue, $LinkBGColor, $LinkTextColor, $LinkFontBold);
 427   }
 428 
 429   # Setup link to last table...
 430   if ($EndTableNum != $LastTableNum) {
 431     $HTMLFile = ${$TextFilesTableHTMLFiles[$Index]}[$LastTableIndex];
 432     $HTMLRefFile = GetRelativeFileDir($CurTableNum, $LastTableNum, $FirstTableNum) . $HTMLFile;
 433     $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$LastTableIndex];
 434     $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$LastTableIndex];
 435     $HTMLRefValue = SetupHTMLHRef("Last", $HTMLRefFile, "Last Table Containing Lines $TableStartLineNum To $TableEndLineNum");
 436     print $HTMLFileRef SetupHTMLTableRowDataValue($HTMLRefValue, $LinkBGColor, $LinkTextColor, $LinkFontBold);
 437   }
 438   # Setup current table info text....
 439   print $HTMLFileRef SetupHTMLTableRowDataValue("&nbsp");
 440   print $HTMLFileRef SetupHTMLTableRowDataValue("&nbsp");
 441   $TableStartLineNum = ${$TextFilesTableStartLineNum[$Index]}[$CurTableNum - 1];
 442   $TableEndLineNum = ${$TextFilesTableEndLineNum[$Index]}[$CurTableNum - 1];
 443   if ($NavLinksLineInfo) {
 444     print $HTMLFileRef SetupHTMLTableRowDataValue("Showing lines $TableStartLineNum to $TableEndLineNum of $LastLineNum");
 445   }
 446   else {
 447     print $HTMLFileRef SetupHTMLTableRowDataValue("Showing table $CurTableNum of $LastTableNum");
 448   }
 449 
 450   print $HTMLFileRef $RowEndTags;
 451   # End link table...
 452   print $HTMLFileRef SetupHTMLTableEnd();
 453   print $HTMLFileRef SetupHTMLDivEnd();
 454   print $HTMLFileRef SetupHTMLAlignmentEnd("center");
 455 }
 456 
 457 # Generate relative directory path...
 458 sub GetRelativeFileDir {
 459   my($FromTableNum, $ToTableNum, $FirstTableNum) = @_;
 460   my($RelativeFileDir) = "";
 461 
 462   if ($FromTableNum == $FirstTableNum) {
 463     $RelativeFileDir = ($ToTableNum == $FirstTableNum) ? ".\/" : ".\/html\/";
 464   }
 465   else {
 466     $RelativeFileDir = ($ToTableNum == $FirstTableNum) ? "..\/" : ".\/";
 467   }
 468   return $RelativeFileDir;
 469 }
 470 
 471 # Based on hightlight stype, return appropriate colors for background or text...
 472 sub GetValueHighlightColors {
 473   my($FileIndex, $ColNum, $Value) = @_;
 474   my($DataType, $Criterion, $CriterionValue, $BgColor, $FontColor, $ValueOk, $Nothing);
 475 
 476   $BgColor = ""; $FontColor = "";
 477   $DataType = ${$TextFilesHightlightDataMap[$FileIndex]{$ColNum}}[0];
 478   $Criterion = ${$TextFilesHightlightDataMap[$FileIndex]{$ColNum}}[1];
 479   $CriterionValue = ${$TextFilesHightlightDataMap[$FileIndex]{$ColNum}}[2];
 480 
 481   $ValueOk = 0;
 482   if ($DataType =~ /^numeric$/i) {
 483   NUMSWITCH: {
 484       if ($Criterion =~ /^ge$/i) { $ValueOk = ($Value >= $CriterionValue) ? 1 : 0; last NUMSWITCH; }
 485       if ($Criterion =~ /^le$/i) { $ValueOk = ($Value <= $CriterionValue) ? 1 : 0; last NUMSWITCH; }
 486       if ($Criterion =~ /^eq$/i) { $ValueOk = ($Value == $CriterionValue) ? 1 : 0; last NUMSWITCH; }
 487       $Nothing = 1;
 488     }
 489   }
 490   else {
 491   TEXTSWITCH: {
 492       if ($Criterion =~ /^ge$/i) { $ValueOk = ($Value ge $CriterionValue) ? 1 : 0; last TEXTSWITCH; }
 493       if ($Criterion =~ /^le$/i) { $ValueOk = ($Value le $CriterionValue) ? 1 : 0; last TEXTSWITCH; }
 494       if ($Criterion =~ /^eq$/i) { $ValueOk = ($Value eq $CriterionValue) ? 1 : 0; last TEXTSWITCH; }
 495       $Nothing = 1;
 496     }
 497   }
 498   $BgColor = $ValueOk ? $ValueOkColor : $ValueNotOkColor;
 499   if ($Options{highlightstyle} =~ /^text$/i) {
 500     $BgColor = "";
 501     $FontColor = $ValueOk ? $ValueOkColor : $ValueNotOkColor;
 502   }
 503   return ($BgColor, $FontColor);
 504 }
 505 
 506 sub ProcessColumnsToHighlight {
 507   my($ColID, $DataType, $Criterion, $Value, $Index, $ColNum, $ColLabel, $ColIndex);
 508 
 509   @TextFilesHightlightColNumMap = ();
 510   @TextFilesHightlightDataMap = ();
 511 
 512   for $Index (0 .. $#TextFilesList) {
 513     %{$TextFilesHightlightColNumMap[$Index]} = ();
 514     %{$TextFilesHightlightDataMap[$Index]} = ();
 515     if ($TextFilesOkay[$Index]) {
 516       SPECIFIEDCOLS: for $ColIndex (0 .. $#SpecifiedColIds) {
 517 	$ColID = $SpecifiedColIds[$ColIndex];
 518 	$DataType = $SpecifiedColDataTypes[$ColIndex];
 519 	$Criterion = $SpecifiedColCriteria[$ColIndex];
 520 	$Value = $SpecifiedColValues[$ColIndex];
 521 	if (!$HighlightStatus) {
 522 	  next SPECIFIEDCOLS;
 523 	}
 524 	if ($Options{highlightby} =~ /^colnum$/i) {
 525 	  $ColNum = $ColID;
 526 	  if ($ColNum > 0 && $ColNum <= $TextFilesColCount[$Index]) {
 527 	    $ColNum -= 1;
 528 	  }
 529 	  else {
 530 	    warn "Warning: Ignoring column number, $ColID, specifed in quartet, \"$ColID,$DataType,$Criterion,$Value\", using \"--highlight\" option for $TextFilesList[$Index]: it doesn't exists \n";
 531 	    next SPECIFIEDCOLS;
 532 	  }
 533 	}
 534 	else {
 535 	  $ColLabel = $ColID;
 536 	  if (exists($TextFilesColLabelToNumMap[$Index]{$ColLabel})) {
 537 	    $ColNum = $TextFilesColLabelToNumMap[$Index]{$ColLabel};
 538 	  } else {
 539 	    warn "Warning: Ignoring column label, $ColID, specifed in quartet, \"$ColID,$DataType,$Criterion,$Value\", using \"--highlight\" option for $TextFilesList[$Index]: it doesn't exists \n";
 540 	    next SPECIFIEDCOLS;
 541 	  }
 542 	}
 543 	$TextFilesHightlightColNumMap[$Index]{$ColNum} = $ColNum;
 544 	@{$TextFilesHightlightDataMap[$Index]{$ColNum}} =();
 545 	push @{$TextFilesHightlightDataMap[$Index]{$ColNum}}, ($DataType, $Criterion, $Value);
 546       }
 547     }
 548   }
 549 }
 550 
 551 #Make sure appropriate mode specific option values are specified...
 552 sub ProcessOptions {
 553 
 554   $RowHAlignment = "left"; $RowVAlignment = "middle";
 555   if (exists($Options{align})) {
 556     my (@AlignValues) = split ",", $Options{align};
 557     if (@AlignValues == 2) {
 558       $RowHAlignment = $AlignValues[0];
 559       $RowVAlignment = $AlignValues[1];
 560     }
 561     elsif (@AlignValues == 1) {
 562       $RowHAlignment = $AlignValues[0];
 563     }
 564     else {
 565       die "Error: Invalid number of values, ", scalar(@AlignValues) , ", specified by \"-a --align\" option.\nIt must contain only one or two value.\n";
 566     }
 567     if ($RowHAlignment !~ /^(left|center|right)$/i) {
 568       die "Error: The horizontal alignment value specified, $Options{align}, for option \"-a --align\" is not valid. Allowed values: left, center, or right\n";
 569     }
 570     if ($RowVAlignment !~ /^(top|middle|bottom)$/i) {
 571       die "Error: The horizontal alignment value specified, $Options{align}, for option \"-a --align\" is not valid. Allowed values: top, middle, or bottom\n";
 572     }
 573   }
 574 
 575   $TableHeaderRowHAlignment = "center"; $TableHeaderRowVAlignment = "middle";
 576   if (exists($Options{headeralign})) {
 577     my (@AlignValues) = split ",", $Options{headeralign};
 578     if (@AlignValues == 2) {
 579       $TableHeaderRowHAlignment = $AlignValues[0];
 580       $TableHeaderRowVAlignment = $AlignValues[1];
 581     }
 582     elsif (@AlignValues == 1) {
 583       $TableHeaderRowHAlignment = $AlignValues[0];
 584     }
 585     else {
 586       die "Error: Invalid number of values, ", scalar(@AlignValues) , ", specified by \"--headeralign\" option.\nIt must contain only one or two value.\n";
 587     }
 588     if ($TableHeaderRowHAlignment !~ /^(left|center|right)$/i) {
 589       die "Error: The horizontal alignment value specified, $Options{headeralign}, for option \"--headeralign\" is not valid. Allowed values: left, center, or right\n";
 590     }
 591     if ($TableHeaderRowVAlignment !~ /^(top|middle|bottom)$/i) {
 592       die "Error: The horizontal alignment value specified, $Options{headeralign}, for option \"-a --headeralign\" is not valid. Allowed values: top, middle, or bottom\n";
 593     }
 594   }
 595 
 596   $TitleDisplay = ($Options{titledisplay} =~ /^yes$/i) ? 1 : 0;
 597 
 598   if (exists($Options{border})) {
 599     $TableBorder = $Options{border};
 600   }
 601   else {
 602     $TableBorder = ($Options{mode} =~ /^(plain|highlight)$/i) ? 1 : 0;
 603   }
 604   $TableCellPadding = $Options{cellpadding};
 605   $TableCellSpacing = $Options{cellspacing};
 606   $Footer = $Options{footer} ? $Options{footer} : "";
 607 
 608   if ($Options{headercolor}) {
 609     $TableHeaderRowColor = $Options{headercolor};
 610   }
 611   else {
 612     $TableHeaderRowColor = ($Options{mode} =~ /^plain$/i) ? "" : "#ccccff";
 613   }
 614 
 615   $NavLinksAtBottom = 1; $NavLinksAtTop = 0;
 616   if ($Options{displaylinks} =~ /^(both|top)$/i) {
 617     $NavLinksAtTop = 1;
 618   }
 619   $NavLinksTableInfo = 1; $NavLinksLineInfo = 0;
 620   if ($Options{displaylinksinfo} =~ /^both$/i) {
 621     $NavLinksLineInfo = 1;
 622     $NavLinksTableInfo = 1;
 623   }
 624   elsif ($Options{displaylinksinfo} =~ /^line$/i) {
 625     $NavLinksLineInfo = 1;
 626     $NavLinksTableInfo = 0;
 627   }
 628 
 629   if ($Options{stylesheet} =~ /^old$/i ) {
 630     if (!$Options{stylesheetname}) {
 631       die "Error: No stylesheet name specified using \"--stylesheetname\" option: It is required for \"old\" value of \"-s --stylesheet\" option. \n";
 632     }
 633   }
 634 
 635   my(@ColorValues);
 636   $OddRowsShadeColor = ""; $EvenRowsShadeColor = ""; $ShadeRowsStatus = 0;
 637   if ($Options{mode} =~ /^(shade|shadedhighlight)$/i) {
 638     $OddRowsShadeColor = "#ffffff";
 639     $EvenRowsShadeColor = "#e0e0eb";
 640     $ShadeRowsStatus = 1;
 641     if ($Options{shadecolor}) {
 642       # Make sure only two value are specified...
 643       @ColorValues = split ",", $Options{shadecolor};
 644       if (@ColorValues == 2) {
 645 	$OddRowsShadeColor = $ColorValues[0];
 646 	$EvenRowsShadeColor = $ColorValues[1];
 647       }
 648       else {
 649 	die "Error: Invalid number of values, ", scalar(@ColorValues) , ", specified by \"--shadecolor\" option.\nIt must contain only two values.\n";
 650       }
 651     }
 652   }
 653   $ValueOkColor = ""; $ValueNotOkColor = ""; $HighlightStatus = 0;
 654   if ($Options{mode} =~ /^(highlight|shadedhighlight)$/i) {
 655     my($HighlightMode, $HighlightBy);
 656     $HighlightMode = $Options{mode}; $HighlightBy = $Options{highlightby};
 657 
 658     $HighlightStatus = 1;
 659     $ValueOkColor = "#0fff0f";
 660     $ValueNotOkColor = "#ff0f0f";
 661     if ($Options{highlightstyle} =~ /^text$/i) {
 662       $ValueOkColor = "#0fbb0f";
 663       $ValueNotOkColor = "#ff0f0f";
 664     }
 665     if ($Options{highlightcolor}) {
 666       # Make sure two values are specified...
 667       @ColorValues = split ",", $Options{highlightcolor};
 668       if (@ColorValues == 2) {
 669 	$ValueOkColor = $ColorValues[0];
 670 	$ValueNotOkColor = $ColorValues[1];
 671       }
 672       else {
 673 	die "Error: Invalid number of values, ", scalar(@ColorValues), ", specified by \"--highlightcolor\" option.\nIt must contain only two value for $HighlightMode value specified using \"-m --mode\" option.\n";
 674       }
 675     }
 676     if (!$Options{highlight}) {
 677       die "Error: Specify columns to be highlighted using \"--hightlight\" option\n";
 678     }
 679     # Retrieve quartet values from "hightlight" option...
 680     my(@HighlightValueQuartets);
 681 
 682     @HighlightValueQuartets = ();
 683     @HighlightValueQuartets = split ",", $Options{highlight};
 684     if ((@HighlightValueQuartets % 4)) {
 685       die "Error: Quartets not found in values specified using \"--highlight\" option for $HighlightMode \"-m --mode\"\n";
 686     }
 687     # Process quartets...
 688     my($Col, $DataType, $Criterion, $Value);
 689 
 690     @SpecifiedColIds = ();
 691     @SpecifiedColDataTypes = ();
 692     @SpecifiedColCriteria = ();
 693     @SpecifiedColValues = ();
 694     for ($Index = 0; $Index < @HighlightValueQuartets; $Index = $Index + 4) {
 695       $Col = $HighlightValueQuartets[$Index];
 696       $DataType = $HighlightValueQuartets[$Index + 1];
 697       $Criterion = $HighlightValueQuartets[$Index + 2];
 698       $Value = $HighlightValueQuartets[$Index + 3];
 699       if ($Options{highlightby} =~ /^colnum$/i ) {
 700 	if (!IsPositiveInteger($Col)) {
 701 	  die "Error: Invalid column id, $Col, specified in quartet, \"$Col,$DataType,$Criterion,$Value\", using \"--hightlight\" option: It must be an integer value > 0 for $HighlightMode \"-m --mode\" and $HighlightBy \"--highlightby\" option values.\n";
 702 	}
 703       }
 704       if ($DataType !~ /^(numeric|text)$/i) {
 705 	die "Error: Invalid column data type, $DataType, specified in quartet, \"$Col,$DataType,$Criterion,$Value\", using \"--hightlight\" option: Valid values: numeric or text\n";
 706       }
 707       if ($Criterion !~ /^(eq|le|ge)$/i) {
 708 	die "Error: Invalid criterion value, $Criterion, specified in quartet, \"$Col,$DataType,$Criterion,$Value\", using \"--hightlight\" option: Valid values: le, ge, or eq\n";
 709       }
 710       if ($DataType =~ /^numeric$/i) {
 711 	if (!IsFloat($Value)) {
 712 	  die "Error: Invalid criterion value, $Value, specified in quartet, \"$Col,$DataType,$Criterion,$Value\", using \"--hightlight\" option: numeric value required for numeric data type\n";
 713 	}
 714       }
 715       push @SpecifiedColIds, $Col;
 716       push @SpecifiedColDataTypes, $DataType;
 717       push @SpecifiedColCriteria, $Criterion;
 718       push @SpecifiedColValues, $Value;
 719     }
 720   }
 721 }
 722 
 723 # Retrieve information about input text files...
 724 sub RetrieveTextFilesInfo {
 725   my($LineCount, $TextFile, $FileDir, $FileName, $HTMLFile, $CSSFile, $HTMLRoot, $HTMLTitle, $FileExt, $Index, $ColIndex, $ColNum, $ColLabel, $LinesCount, $InDelim, $Line, @LineWords, @ColLabels, $TopHTMLDir);
 726 
 727   @TextFilesOkay = ();
 728   @TextFilesColCount = (); @TextFilesColLabels = ();
 729   @TextFilesColLabelToNumMap = ();
 730   @TextFilesLineCount = ();
 731   @TextFilesInDelim = ();
 732   @TextFilesHTMLRoot = ();
 733   @TextFilesHTMLTitle = ();
 734   @TextFilesMultipleHTMLTables = ();
 735 
 736   @TextFilesTopHTMLDir = (); @TextFilesSubHTMLDir = ();
 737 
 738  FILELIST: for $Index (0 .. $#TextFilesList) {
 739     $TextFile = $TextFilesList[$Index];
 740     $TextFilesOkay[$Index] = 0;
 741     $TextFilesColCount[$Index] = 0;
 742     $TextFilesLineCount[$Index] = 0;
 743     $TextFilesInDelim[$Index] = "";
 744     $TextFilesHTMLRoot[$Index] = "";
 745     $TextFilesHTMLTitle[$Index] = "";
 746     $TextFilesMultipleHTMLTables[$Index] = 0;
 747     @{$TextFilesColLabels[$Index]} = ();
 748     %{$TextFilesColLabelToNumMap[$Index]} = ();
 749     if (!(-e $TextFile)) {
 750       warn "Warning: Ignoring file $TextFile: It doesn't exist\n";
 751       next FILELIST;
 752     }
 753     if (!CheckFileType($TextFile, "csv tsv")) {
 754       warn "Warning: Ignoring file $TextFile: It's not a csv or tsv file\n";
 755       next FILELIST;
 756     }
 757     ($FileDir, $FileName, $FileExt) = ParseFileName($TextFile);
 758     if ($FileExt =~ /^tsv$/i) {
 759       $InDelim = "\t";
 760     }
 761     else {
 762       $InDelim = "\,";
 763       if ($Options{indelim} !~ /^(comma|semicolon)$/i) {
 764 	warn "Warning: Ignoring file $TextFile: The value specified, $Options{indelim}, for option \"--indelim\" is not valid for csv files\n";
 765 	next FILELIST;
 766       }
 767       if ($Options{indelim} =~ /^semicolon$/i) {
 768 	$InDelim = "\;";
 769       }
 770     }
 771 
 772     if (!open TEXTFILE, "$TextFile") {
 773       warn "Warning: Ignoring file $TextFile: Couldn't open it: $! \n";
 774       next FILELIST;
 775     }
 776 
 777     $Line = GetTextLine(\*TEXTFILE);
 778     @ColLabels = quotewords($InDelim, 0, $Line);
 779     $LineCount = 0;
 780     while (<TEXTFILE>) {
 781       $LineCount++;
 782     }
 783     close TEXTFILE;
 784 
 785     $FileDir = ""; $FileName = ""; $FileExt = "";
 786     ($FileDir, $FileName, $FileExt) = ParseFileName($TextFile);
 787     $HTMLRoot = $FileName;
 788     if ($Options{root} && (@TextFilesList == 1)) {
 789       my ($RootFileDir, $RootFileName, $RootFileExt) = ParseFileName($Options{root});
 790       if ($RootFileName && $RootFileExt) {
 791 	$HTMLRoot = $RootFileName;
 792       }
 793       else {
 794 	$HTMLRoot = $Options{root};
 795       }
 796     }
 797     $HTMLTitle = $HTMLRoot;
 798     if ($Options{title} && (@TextFilesList == 1)) {
 799       $HTMLTitle = $Options{title};
 800     }
 801     $HTMLFile = lc($HTMLRoot) . "-html";
 802     if (!$Options{overwrite}) {
 803       if (-d $HTMLFile) {
 804 	warn "Warning: Ignoring file $TextFile: The directory $HTMLFile already exists\n";
 805 	next FILELIST;
 806       }
 807     }
 808 
 809     $TextFilesOkay[$Index] = 1;
 810     $TextFilesInDelim[$Index] = $InDelim;
 811     $TextFilesHTMLRoot[$Index] = "$HTMLRoot";
 812     $TextFilesHTMLTitle[$Index] = "$HTMLTitle";
 813 
 814     $TextFilesColCount[$Index] = @ColLabels;
 815     push @{$TextFilesColLabels[$Index]}, @ColLabels;
 816     for $ColNum (0 .. $#ColLabels) {
 817       $ColLabel = $ColLabels[$ColNum];
 818       $TextFilesColLabelToNumMap[$Index]{$ColLabel} = $ColNum;
 819     }
 820     $TextFilesLineCount[$Index] = $LineCount;
 821 
 822     if ($Options{numrows} == 0 || $LineCount <= $Options{numrows}) {
 823       $TextFilesMultipleHTMLTables[$Index] = 0;
 824     }
 825     else {
 826       $TextFilesMultipleHTMLTables[$Index] = 1;
 827     }
 828     # Setup HTML data directories paths...
 829     $TopHTMLDir = lc($TextFilesHTMLRoot[$Index]) . "-html";
 830     $TextFilesTopHTMLDir[$Index] = "$TopHTMLDir";
 831     $TextFilesSubHTMLDir[$Index] = "$TopHTMLDir\/html";
 832   }
 833 }
 834 
 835 # Setup navigation link information for multiple tables...
 836 sub SetupMultipleTablesInfo {
 837   my($Index, $LinesPerTable);
 838 
 839   $LinesPerTable = $Options{numrows};
 840   @TextFilesTableCount = ();
 841   @TextFilesTableHTMLFiles = ();
 842   @TextFilesTableStartLineNum = ();
 843   @TextFilesTableEndLineNum = ();
 844 
 845   for $Index (0 .. $#TextFilesList) {
 846     $TextFilesTableCount[$Index] = 1;
 847     @{$TextFilesTableHTMLFiles[$Index]} = ();
 848     @{$TextFilesTableStartLineNum[$Index]} = ();
 849     @{$TextFilesTableEndLineNum[$Index]} = ();
 850 
 851     if ($TextFilesOkay[$Index]) {
 852       if ($TextFilesMultipleHTMLTables[$Index]) {
 853 	my($TableIndex, $TotalLines, $TableCount, $TableStartLineNum, $TableEndLineNum, $Name);
 854 
 855 	$TotalLines = $TextFilesLineCount[$Index];
 856 	$TableCount = ($TotalLines % $LinesPerTable) ? (int($TotalLines/$LinesPerTable) + 1) : ($TotalLines/$LinesPerTable);
 857 	$TextFilesTableCount[$Index] = $TableCount;
 858 	for $TableIndex (1 .. $TableCount) {
 859 	  $TableStartLineNum = ($TableIndex - 1) * $LinesPerTable + 1;
 860 	  $TableEndLineNum = ($TableIndex == $TableCount) ? $TotalLines : ($TableIndex * $LinesPerTable);
 861 	  push @{$TextFilesTableStartLineNum[$Index]}, $TableStartLineNum;
 862 	  push @{$TextFilesTableEndLineNum[$Index]}, $TableEndLineNum;
 863 
 864 	  # Setup HTML file names for all the tables...
 865 	  $Name = "Lines" . "$TableStartLineNum" . "To" . "$TableEndLineNum";
 866 	  if ($TableIndex == 1) {
 867 	    $Name = "";
 868 	  }
 869 	  $Name = $TextFilesHTMLRoot[$Index] . $Name . ".html";
 870 	  push @{$TextFilesTableHTMLFiles[$Index]}, $Name;
 871 	}
 872 	#print "$TextFilesList[$Index]: $TableCount -  @{$TextFilesTableStartLineNum[$Index]} - @{$TextFilesTableEndLineNum[$Index]} -  @{$TextFilesTableHTMLFiles[$Index]}\n";
 873       }
 874     }
 875   }
 876 }
 877 
 878 # Setup various data directories to hold HTML and other related files...
 879 sub SetupDataDirs {
 880   my($Index) = @_;
 881   my($TopHTMLDir, $SubHTMLDir, $CreateTopHTMLDir, $CreateSubHTMLDir);
 882 
 883   $TopHTMLDir = $TextFilesTopHTMLDir[$Index];
 884   $SubHTMLDir = $TextFilesSubHTMLDir[$Index];
 885 
 886   # Clean up existing directories...
 887   if (-d $TopHTMLDir) {
 888     unlink "<$TopHTMLDir/*.html>";
 889     unlink "<$TopHTMLDir/*.css>";
 890   }
 891   if (-d $SubHTMLDir) {
 892     unlink "<$SubHTMLDir/*.html>";
 893   }
 894   # What directories need to be created...
 895   $CreateTopHTMLDir = (-d $TopHTMLDir) ? 0 : 1;
 896 
 897   $CreateSubHTMLDir = 0;
 898   if ($TextFilesMultipleHTMLTables[