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(" "); 373 print $HTMLFileRef SetupHTMLTableRowDataValue(" "); 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(" "); 440 print $HTMLFileRef SetupHTMLTableRowDataValue(" "); 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[