tsrc/testing/tools/testdoc.pl
changeset 0 96612d01cf9f
child 23 8f0df5c82986
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tsrc/testing/tools/testdoc.pl	Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,5437 @@
+#
+# Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description: 
+#
+
+#-----------------------------------------------
+# Sequence
+#-----------------------------------------------
+# Reads parameters -> [if !ok params] ShowHelp
+# ReadConfigFiles
+#	-> ParseCfg
+#	-> ReadCase
+#
+#    for all testreports:
+#       ReadTestRunInfoFromStifReport
+#           GetReportLogFileNames
+#       ParseResultsAndLogs
+#
+#    ParseResultsAndLogs
+#        WriteCaseLog
+#			LogLineTimeMatchesForCase
+#			FormatLogLine
+#        UpdateCase
+#        CheckCaseEntriesInLog
+#
+# OLD:
+#	-> ParseReportFile
+#		-> ReadReportLogs
+#		-> WriteCaseLog
+#			-> LogLineTimeMatchesForCase
+#			-> FormatLogLine
+#		-> CheckCaseEntriesInLog
+#
+# ReportNotDocumentedCases
+# SortCases
+# CalculateStats
+# WriteOfficeXml -> XmlReadyText
+# exit()
+
+#-----------------------------------------------
+# Other functions:
+#-----------------------------------------------
+# RemoveWhiteSpaces
+# SpecialChars
+# ReplaceChar
+# GetCaseField
+# GetCase (id or name)
+# GetCaseDesc (id or name)
+# PrintCases
+# JustFormatLogFile
+
+#
+#
+#
+# STIF CFG:
+#************************************************************************************
+#[IptvETDescription]
+# Testname: <insert text here>
+#
+# Purpose: <insert text here>
+#
+# Means: <insert text here>
+#
+# Required environment settings: <insert text here>
+#
+# Verification: <insert text here>
+#
+# Note: <insert text here>
+#
+# Related requirements: <reqid> <reqid> <reqid> ..
+#
+#[EndIptvETDescription]
+#------------------------------------------------------------------------------------
+#[Test]
+# do stuff here
+#[Endtest]
+
+#------------------------------------------------------------------------------------
+# Includes
+#------------------------------------------------------------------------------------
+#use strict;
+use warnings;
+use Cwd; # for cwd
+use FindBin; # for FindBin:Bin
+use File::Path; # for mkpath
+use File::Copy;
+use Date::Calc;
+
+#------------------------------------------------------------------------------------
+# Globals
+#------------------------------------------------------------------------------------
+
+my $lastCaseLogLine = 0;
+
+my $ALT_RESULTCOUNT = 10; # maximum number of runs in alternative report
+
+my @cases; #references to case arrays
+my @gCfgFiles; # list of cfg files.
+my @caseDescs; # case description and the case itself in text
+my @notDocumentedCases; #array to hold information about the cases without documentation
+
+$regexpCaseName = '[\x3C\x3E\(\)\w.,\/:_\-&\' ]+';
+
+my $caseDefaultStatus = 			"NOT RUN";
+
+#
+# Case field numerations
+#
+
+my $CASE_NAME = 					0;
+my $CASE_ID = 						1;
+my $CASE_RUN_TIMES = 				2;
+my $CASE_CRASHED = 					3;
+my $CASE_FAILED = 					4;
+my $CASE_PASSED = 					5;
+my $CASE_STATUS = 					6;
+my $CASE_PURPOSE = 					7;
+my $CASE_MEANS = 					8;
+my $CASE_REQUIRED_SETTINGS = 		9;
+my $CASE_RELATED_REQUIREMENTS = 	10;
+my $CASE_VERIFICATION = 			11;
+my $CASE_NOTE = 					12;
+my $CASE_REASON = 					13; # where crashed or what returned the error code
+my $CASE_RESULT = 					14; # error code
+my $CASE_LOG_FILE = 				15; # test case specific log file.
+my $CASE_LOG_FILE_SCRIPTER = 	    16; # test case specific log from STIF testscripter logs.
+my $CASE_CHECK_RESULT_LOG_FILE = 	17; # set if the case is in the log files, if next line is found: >>>Case start: ETxxxxx CaseName
+									# or STIF own trace: Starting testcase [ET1000 Add multiple Iaps] (usually from fasttrace or emulator log)
+my $CASE_CFG_FILE = 				18;
+my $CASE_RUN_TIME_SECONDS = 		19; # how many seconds it took to run the case
+my $CASE_REPORTLINE1 =              20;
+my $CASE_REPORTLINE2 =              21;
+my $CASE_REPORTLINE3 =              22;
+my $CASE_ENTRY_LOG_START =          23;
+
+my $TDTOOLRESULTFILE = ".\\text_file.txt";
+my $XML_OUTPUT_FILE = ".\\test_cases.xml";
+my $XML_BRIEF_OUTPUT_FILE = ".\\test_cases_brief.xml";
+my $NOT_DOCUMENTED_CASES_FILE = ".\\test_cases_notdocumented.txt";
+
+my @globalTempFiles;
+
+#
+# Tags inside the xml, will be replaced by case data when writing the xml file
+#
+
+my $CaseCountMul8 = "CASE_COUNT_MUL8";
+
+my $STYLE_ID_STATUS_TAG = "STYLE_ID_STATUS"; # must be in the xml data
+
+my $STYLE_ID_STATUS_FAILED = "s36";
+my $STYLE_ID_STATUS_PASSED = "s37";
+my $STYLE_ID_STATUS_CRASHED = "s38";
+my $STYLE_ID_STATUS_UNKNOWN = "s401";
+my $STYLE_ID_STATUS_NA = "s39";
+
+my $STYLE_ID_STATUS_FAILED_CENTERED = "s36centered";
+my $STYLE_ID_STATUS_PASSED_CENTERED = "s37centered";
+my $STYLE_ID_STATUS_CRASHED_CENTERED = "s38centered";
+my $STYLE_ID_STATUS_UNKNOWN_CENTERED = "s401centered";
+my $STYLE_ID_STATUS_NA_CENTERED = "s39centered";
+
+# these must be in the xml data to get the results inserted into xml
+my $xmlDataCaseName = "XML_DATA_CASE_NAME";
+my $xmlDataCaseRunTimes = "XML_DATA_CASE_RUN_TIMES";
+my $xmlDataCaseFailed = "XML_DATA_CASE_FAILED";
+my $xmlDataCaseCrashed = "XML_DATA_CASE_CRASHED";
+my $xmlDataCasePassed = "XML_DATA_CASE_PASSED";
+my $xmlDataCaseStatus = "XML_DATA_CASE_STATUS";
+my $xmlDataCasePurpose = "XML_DATA_CASE_PURPOSE";
+my $xmlDataCaseMeans = "XML_DATA_CASE_MEANS";
+my $xmlDataCaseRequiredSettings = "XML_DATA_CASE_REQUIRED_SETTINGS";
+my $xmlDataCaseRelatedRequirements = "XML_DATA_CASE_RELATED_REQUIREMENTS";
+my $xmlDataCaseVerification = "XML_DATA_CASE_VERIFICATION";
+my $xmlDataCaseNote = "XML_DATA_CASE_NOTE";
+my $xmlDataCaseReason = "XML_DATA_CASE_REASON";
+my $xmlDataCaseResult = "XML_DATA_CASE_RESULT";
+my $xmlDataCaseLink1 = "XML_DATA_CASE_LINK1";
+my $xmlDataCaseLink2 = "XML_DATA_CASE_LINK2";
+
+my $xmlDataSummaryCaseCount = "XML_DATA_SUMMARY_TOTAL_CASES";
+my $xmlDataSummaryPassed = "XML_DATA_SUMMARY_PASSED";
+my $xmlDataSummaryFailed = "XML_DATA_SUMMARY_FAILED";
+my $xmlDataSummaryCrashed = "XML_DATA_SUMMARY_CRASHED";
+my $xmlDataSummaryTimeout = "XML_DATA_SUMMARY_TIMEOUT";
+my $xmlDataSummaryPassRateTotal = "XML_DATA_SUMMARY_PASS_RATE_TOTAL";
+my $xmlDataSummaryPassRateRun = "XML_DATA_SUMMARY_PASS_RATE_RUN";
+my $xmlDataSummaryRunRate = "XML_DATA_SUMMARY_RUN_RATE";
+
+my $xmlDataAltDateX = "XML_DATA_ALTDATE";
+
+my $xmlDataAltResultX = "XML_DATA_ALTRESULT";
+
+my $xmlDataCfgFile = "XML_DATA_CFG_FILE";
+
+#
+# Statistics
+#
+
+my $summaryCaseCount = 0;
+my $summaryPassedCases = 0;
+my $summaryFailedCases = 0;
+my $summaryCrashedCases = 0;
+my $summaryTimeoutCases = 0;
+my $summaryPassRateTotal = 0;
+my $summaryPassRateRun = 0;
+my $summaryRunRate = 0;
+
+#
+# Xml data
+#
+
+my $xmlHeader;
+my $xmlHeaderTableColumns;
+my $xmlHeaderTableColumnsBrief;
+my $xmlFooter;
+my $xmlDataEmptyRow;
+my $xmlSummaryData;
+my $xmlData;
+my $xmlDataCaseStatusDisabled;
+my $xmlData2;
+my $xmlDataBriefHeader;
+my $xmlDataBrief;
+my $xmlCfgFileBrief;
+my $xmlHeaderTableColumnsAlt;
+my $xmlCfgFileAltHeader;
+my $xmlCfgFileAltData;
+
+InitXmlData();
+
+#------------------------------------------------------------------------------------
+# GLOBAL CODE
+#------------------------------------------------------------------------------------
+
+my $argcount = scalar(@ARGV);
+
+my $optionSortCases = 0;
+my $optionShowMessages = 0;
+my $optionHtml = 0;
+my $optionLogAllCases = 1;
+my $optionNoLogs = 0;
+my $optionNoSecurityTests = 0;
+my $optionNoLiveTvTests = 0;
+my $optionCaseIncludedInLog = 0;
+my $optionGoodIsBetter = 1;
+my $optionPrintCfgSummaries = 0;
+my $optionCaseRunTimes = 0;
+my $optionFinalDoc = 1;
+my $optionFixFilename = "";
+my $optionDebug = 0;
+my $optionCaseList = "";
+my $optionAltResults = 0;
+my $optionLogFileName = "fusion";
+
+while(scalar(@ARGV) >= 1)
+{
+	my $argument = shift(@ARGV);
+
+	if($argument eq "-h")
+	{
+		ShowHelp();
+	}
+
+	elsif($argument eq "-e")
+	{
+		$optionShowMessages = 1;
+	}
+
+	elsif($argument eq "-s")
+	{
+		$optionSortCases = 1;
+	}
+
+	elsif($argument eq "-html")
+	{
+		$optionHtml = 1;
+	}
+
+	elsif($argument eq "-logall")
+	{
+		$optionLogAllCases = 1;
+	}
+
+	elsif($argument eq "-nologs")
+	{
+		$optionNoLogs = 1;
+	}
+
+	elsif($argument eq "-nosecuritytests")
+	{
+		$optionNoSecurityTests = 1;
+	}
+
+	elsif($argument eq "-nolivetvtests")
+	{
+		$optionNoLiveTvTests = 1;
+	}
+
+	elsif($argument eq "-i")
+	{
+		$optionCaseIncludedInLog = 1;
+	}
+
+	elsif($argument eq "-file")
+	{
+		$file = shift(@ARGV);
+
+		JustFormatLogFile($file);
+		exit;
+	}
+	elsif($argument eq "-runtimes")
+	{
+		$optionCaseRunTimes = 1;
+	}
+
+	elsif($argument eq "-xxx")
+	{
+		$optionCaseIncludedInLog = 1;
+		$optionNoLiveTvTests = 1;
+		$optionNoSecurityTests = 1;
+		$optionHtml = 1;
+	}
+	elsif($argument eq "-good")
+	{
+		$optionGoodIsBetter = 1;
+	}
+	elsif($argument eq "-cfgsum")
+	{
+		$optionPrintCfgSummaries = 1;
+	}
+	elsif($argument eq "-finalize")
+	{
+		$optionFinalDoc = 1;
+	}
+	elsif($argument eq "-fix") {
+		$optionFixFilename = shift(@ARGV);
+		FixExcelLogPaths();
+        exit();
+	}
+	elsif($argument eq "-debug") {
+	    $optionShowMessages = 1;
+	    $optionDebug = 1;
+	}
+	elsif($argument eq "-caselist") {
+	    $optionCaseList = shift(@ARGV);
+	}
+	elsif($argument eq "-alt") {
+	    $optionAltResults = 1;
+	}
+	elsif( $argument eq "-logfile") {
+		$optionLogFileName = shift(@ARGV);
+	}
+	else
+	{
+	    ShowHelp();
+	}
+}
+
+UnzipAndCopyFiles();
+
+my $totalExecutionTime = 0;
+
+my $caseLogOutDir = "testcase_logs\\testcase_logs\\";
+
+my @caseList;
+
+if($optionCaseList ne "")
+{
+    ReadCaseList(\@caseList, $optionCaseList);
+}
+
+# Find cfg files.
+FindCfgFiles( ".", \@gCfgFiles );
+
+# None found from current dir, see one dir lower.
+FindCfgFiles( "..", \@gCfgFiles ) if( scalar( @gCfgFiles ) < 1 );
+
+# Parse results
+if($optionPrintCfgSummaries)
+{
+	PrintCfgSummaries();
+}
+elsif( !$optionAltResults )
+{
+    my $res = ReadTestReports();
+
+	if( $res == 0 )
+	{
+        foreach my $file ( @globalTempFiles )
+        {
+            unlink $file if( -e $file );
+        }
+		print("No reports to read.\n");
+		exit;
+	}
+
+    #ReportNotDocumentedCases($NOT_DOCUMENTED_CASES_FILE);
+
+    if($optionSortCases)
+    {
+	    @cases = sort SortCases @cases;
+    }
+
+    CalculateStats();
+
+    #WriteOfficeXml($XML_OUTPUT_FILE, 0);
+    WriteOfficeXml($XML_BRIEF_OUTPUT_FILE, 1);
+}
+else
+{
+    my @runs;
+    ReadTestReportsAlt(\@runs);
+
+    WriteOfficeXmlAlt($XML_BRIEF_OUTPUT_FILE, \@runs);
+}
+
+#print("Total run time: " . $totalExecutionTime . "\n") if( $optionCaseRunTimes );
+
+foreach my $file ( @globalTempFiles )
+{
+    unlink $file if( defined( $file ) && -e $file );
+}
+
+exit();
+
+#------------------------------------------------------------------------------------
+# UnzipAndCopyFiles
+#------------------------------------------------------------------------------------
+sub UnzipAndCopyFiles
+{
+	my @files;
+	system("rmdir ziptemp /s /q>NUL") if( -e "ziptemp" );
+	
+	# Unzip zips in current directory and one level of subdirectories. -> ATS results.
+	GetAllFiles( ".", \@files, 1 );
+	
+	foreach my $file ( @files )
+	{
+		if( $file =~ m/\.zip/i )
+		{
+			my $fileName = GetPathFileName( $file );
+			
+			mkdir ("ziptemp");
+			my $cmd = "unzip -o \"$file\" -d ziptemp\\$fileName >NUL";
+			print("Unzipping $file\n") if( $optionShowMessages );
+			system( $cmd );
+		}
+	}
+
+	undef( @files );
+	GetAllFiles( ".", \@files, -1 );
+
+	# Copy files to current dir.
+
+	my $currDir = cwd;
+	
+	foreach my $file ( @files )
+	{
+	    next if( -d $file );
+	    
+	    $file =~ s/\//\\/g;
+	    
+    	# Do nothing for files which are in current dir.
+    	my $srcDir = GetPathDir( $file );
+    	my $currpath = cwd;
+    	$currpath =~ s/\//\\/g;
+    	next if( $srcDir eq $currpath );
+	    
+	    my $filename = GetPathFileName( $file );
+	    
+	    # LOOP all testreport*.txt testscripter*.txt
+	    # if file is testreport.txt
+	    #   lastFolder = last folder from the path
+	    #     LOOP all fusion*.txt
+	    #       LOOP remove tailing text from lastFolder starting from last index of '.' until it matches with folder of fusion*.txt
+	    #          pair fusion*.txt with testreport
+	    
+	    
+		if( ( $filename =~ m/testreport/i || $filename =~ m/testscripter/i ) && $filename =~ m/\.txt/i )
+		#if( ( $filename =~ m/$optionLogFileName/i || $filename =~ m/testreport/i || $filename =~ m/testscripter/i ) && $filename =~ m/\.txt/i )
+		{
+		    my $dst = "";
+		    
+		    if( $filename =~ m/testreport/i )
+		    {
+		        # Pair testreports and logs.
+		        CopyTestReportWithLog( $file, \@files );
+		    }
+		    else
+		    {
+		        print("Copying file $file\n") if( $optionDebug );
+		        # For other files we just need unique filename and copy them.
+            	$dst = $filename;
+            	
+            	if( -e $filename )
+            	{
+                	# Separate file's name and extension.
+                	my $name = "";
+                	my $ext = "";
+                	my $pos = index($filename, ".");
+                	if( $pos != -1) 
+                	{
+                		$ext = substr( $filename, $pos );
+                		$name = substr( $filename, 0, $pos );
+                		
+                		my $count = 0;
+                		while( 1 )
+                		{
+                		    $dst = "$name" . "_" . $count . $ext;
+                		    last if( ! -e "$dst" );
+                		    $count++;
+                		    if( $count > 1000 )
+                		    {
+                		        $dst = "";
+                		        last;
+                		    }
+                		}
+                	}
+                }
+    			push @globalTempFiles, $dst;
+    			
+    			print("Dest: $dst\n") if( $optionDebug );
+    			
+    			copy( $file, $dst ) or die "Could not copy '$file' to '$dst'\n";
+		    }
+		}
+	}
+
+	system("rmdir ziptemp /s /q>NUL") if( -e "ziptemp" );
+}
+
+sub CopyTestReportWithLog
+{
+    my ( $reportFileName, $refFiles ) = @_;
+    
+    print("\nTrying to pair: $reportFileName\n") if( $optionDebug );
+    
+    my $reportPath = GetPathDir( $reportFileName );
+    
+    my $logFileName = "";
+    
+#\ResultAndLogFiles_vod\22507.23325.1.4.25129-lab.net\TestReport.txt
+#\ResultAndLogFiles_vod\22507.23325.1.4.25130-lab.net\Fusion.txt
+#                       ^^^^^^^^^^^^^^^ matching part    
+    # Find log file with about same path with the report.
+    while( 1 )
+    {    
+        # Check the log files.
+        foreach $file ( @$refFiles )
+        {
+            $file =~ s/\//\\/g;
+            my $filename = GetPathFileName( $file );
+            
+            if( $filename =~ m/$optionLogFileName/i )
+            {
+                if( index( $file, $reportPath ) == 0 )
+                {
+                    $logFileName = $file;
+                    
+                    print("PAIRED: \n") if( $optionDebug );
+                    print("reportPath: $reportPath\n") if( $optionDebug );
+                    print("report: $reportFileName\n") if( $optionDebug );
+                    print("log   : $logFileName\n") if( $optionDebug );
+                    
+                    print("Report log pair: $logFileName\n") if( $optionShowMessages && !$optionDebug );
+                    last;
+                }
+            }
+        }
+        
+        last if( $logFileName ne "" );
+        
+        # Remove all from last dot in the path.            
+        my $pos = rindex( $reportPath, "." );
+        last if( $pos == -1 );
+        $reportPath = substr( $reportPath, 0, $pos );
+        
+        # The first 4 numbers might be same with multiple reports and logs. Ignore file if match is not found before.
+        last if( rindex( $reportPath, "\\" ) == -1 );
+        my $dotstr = substr( $reportPath, rindex( $reportPath, "\\" )+1 );
+        last if( ! ( $dotstr =~ m/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ ) );
+        print( "DOT: $dotstr\n" ) if( $optionDebug );
+    }
+
+    if( $logFileName eq "" )
+    {
+        print("Could not find log file for: $reportFileName\n") if( $optionShowMessages );
+    }
+    
+    my $dstReportFileName = "";
+    my $dstReportLogName = "";
+
+    # Find first available name for the report in current directory.
+    my $fileNum = 0;
+
+    my $filename = GetPathFileName( $reportFileName );
+    
+	# Separate file's name and extension.
+	my $name = "";
+	my $ext = "";
+
+	my $pos = index($filename, ".");
+	return if( $pos == -1);
+	
+	$ext = substr( $filename, $pos );
+	$name = substr( $filename, 0, $pos );
+	
+	# Find free filename.
+	while( 1 )
+	{
+	    $dstReportFileName = "$name" . "_" . $fileNum . $ext;
+	    last if( ! -e "$dstReportFileName" );
+	    $fileNum++;
+	    if( $fileNum > 1000 )
+	    {
+	        die("Too many files to copy.");
+	    }
+	}
+	
+	if( $logFileName ne "" )
+	{
+    	# Get new name for the log with same numbering.
+    	
+    	$filename = GetPathFileName( $logFileName );
+    	
+        $pos = index($filename, ".");
+    	return if( $pos == -1);
+    	
+    	$ext = substr( $filename, $pos );
+    	$name = substr( $filename, 0, $pos );
+    	
+    	$dstLogFileName = "$name" . "_" . $fileNum . $ext;
+    	die("Log filename already exists.") if( -e "$dstLogFileName" ); # Shouldn't happen.
+    }
+    
+	# Copy the files.
+	
+    push @globalTempFiles, $dstReportFileName;
+    push @globalTempFiles, $dstLogFileName;
+
+	print("Copying $reportFileName\n") if( $optionShowMessages );
+	print("Dest: $dstReportFileName\n") if( $optionShowMessages );
+	
+	copy( $reportFileName, $dstReportFileName ) or die "Could not copy '$reportFileName' to '$dstReportFileName'\n";	
+	
+	if( $logFileName ne "" )
+	{	
+	    print("Copying $logFileName\n") if( $optionShowMessages );
+	    print("Dest: $dstLogFileName\n") if( $optionShowMessages );
+	    copy( $logFileName, $dstLogFileName ) or die "Could not copy '$logFileName' to '$dstLogFileName'\n";	
+    }
+}
+
+#------------------------------------------------------------------------------------
+# ReadCaseList
+#
+#------------------------------------------------------------------------------------
+sub ReadCaseList
+{
+    my ($refList, $filename) = @_;
+
+	if( open(FILE_HANDLE, ".\\" . $filename) )
+	{
+		my @lines = <FILE_HANDLE>;
+		close(FILE_HANDLE);
+	    foreach $line (@lines)
+	    {
+	        my $caseId;
+
+            if($line =~ m/^case /i)
+            {
+                if($line =~ m/^case ET([0-9]+) /i)
+                {
+                    $caseId = "ET" . $1;
+                }
+                else
+                {
+                    $caseId = substr($line, 4);
+                }
+                RemoveWhiteSpaces(\$caseId);
+                push @$refList, $caseId;
+            }
+	    }
+	}
+}
+
+#------------------------------------------------------------------------------------
+# IsCaseInCaseList
+#
+#------------------------------------------------------------------------------------
+sub IsCaseInCaseList
+{
+    my ($caseNameOrId) = @_;
+
+     return 1 if(scalar(@caseList) <= 0);
+
+    my $caseIdFromName = GetCaseIdFromName($caseNameOrId);
+
+    foreach $caseId (@caseList)
+    {
+        if($caseId eq $caseNameOrId)
+        {
+            return 1;
+        }
+    }
+
+    foreach $caseId (@caseList)
+    {
+        if($caseId eq $caseIdFromName)
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+#------------------------------------------------------------------------------------
+# FixExcelLogPaths
+#
+# Changes the paths on lines:
+#<Cell ss:StyleID="s60" ss:HRef="C:\Documents and Settings\senbom\Desktop\testcase_logs\testcase_logs\ET17099_4371843802.txt"><Data>
+# To:
+#<Cell ss:StyleID="s60" ss:HRef="testcase_logs\ET17099_4371843802.txt"><Data>
+#
+# Because the absolute path does not work in Excel.
+#
+#------------------------------------------------------------------------------------
+sub FixExcelLogPaths
+{
+	if( open(FILE_HANDLE, ".\\" . $optionFixFilename) )
+	{
+		my @lines = <FILE_HANDLE>;
+		close(FILE_HANDLE);
+
+		if(!open(FILE_HANDLE, ">" . $optionFixFilename) )
+		{
+			die("Could not write to file $file\n");
+		}
+
+		foreach my $line(@lines)
+		{
+			my $pos = index($line, "\\testcase_logs\\testcase_logs\\");
+			if($pos != -1)
+			{
+				my $start = rindex($line, "\"", $pos);
+				my $remstr = substr($line, $start+1, $pos-$start + length("\\testcase_logs") );
+
+				$line = substr( $line, 0, index($line, $remstr) ) .
+						   substr( $line, index($line, $remstr) + length($remstr) );
+
+			}
+
+			print FILE_HANDLE ($line);
+
+		}
+		close(FILE_HANDLE);
+
+		print("Fixed paths in $optionFixFilename\n");
+	}
+	else
+	{
+	    die("Coult not open file $optionFixFilename\n");
+	}
+}
+
+#------------------------------------------------------------------------------------
+# CalculateStats
+#------------------------------------------------------------------------------------
+sub CalculateStats
+{
+	$summaryCaseCount = scalar( @cases );
+	$summaryPassedCases = 0;
+	$summaryFailedCases = 0;
+	$summaryCrashedCases = 0;
+	$summaryTimeoutCases = 0;
+	$summaryPassRateTotal = 0;
+	$summaryPassRateRun = 0;
+	$summaryRunRate = 0;
+
+	foreach $case(@cases)
+	{
+		if(defined(@{$case}[$CASE_STATUS]))
+		{
+			my $status = @{$case}[$CASE_STATUS];
+
+			$summaryPassedCases++ if($status eq "PASSED");
+			$summaryFailedCases++ if($status eq "FAILED");
+			$summaryCrashedCases++ if($status eq "CRASHED");
+		}
+	}
+	
+	my $runCases = $summaryPassedCases + $summaryFailedCases + $summaryCrashedCases;
+	
+	$summaryPassRateTotal = $summaryPassedCases / $summaryCaseCount * 100;
+	$summaryPassRateRun = $summaryPassedCases / $runCases * 100;
+	$summaryRunRate = $runCases / $summaryCaseCount * 100;
+}
+
+#------------------------------------------------------------------------------------
+# SortCases
+#------------------------------------------------------------------------------------
+sub SortCases()
+{
+	$aprio = 0;
+	$bprio = 0;
+
+	#print @{$a}[$CASE_STATUS] . " - " . $a . " vs " . $b . " - " . @{$b}[$CASE_STATUS] . "\n";
+
+	if(@{$a}[$CASE_STATUS] eq "CRASHED") { $aprio = 5; }
+	elsif(@{$a}[$CASE_STATUS] eq "FAILED") { $aprio = 4; }
+	elsif(@{$a}[$CASE_STATUS] eq "PASSED") { $aprio = 3; }
+
+	if(@{$b}[$CASE_STATUS] eq "CRASHED") { $bprio = 5; }
+	elsif(@{$b}[$CASE_STATUS] eq "FAILED") { $bprio = 4; }
+	elsif(@{$b}[$CASE_STATUS] eq "PASSED") { $bprio = 3; }
+
+	if($aprio == $bprio)
+	{
+		return lc(@{$a}[$CASE_NAME]) cmp lc(@{$b}[$CASE_NAME]);
+	}
+
+	return $bprio cmp $aprio;
+}
+
+
+#------------------------------------------------------------------------------------
+# ShowHelp
+#------------------------------------------------------------------------------------
+sub ShowHelp {
+
+print <<USAGE_EOF;
+testdoc.pl
+
+Create folder to VaDo root folder for STIF results and copy this script and 
+the results there. STIF CFG files are searched from . and .. from the script 
+run folder. The STIF results can be either ATS results zips or multiple 
+TestReport*.txt and fusion*.txt files as long as they have the same ending 
+in the name. Script also parses the STIF testscripter logs it finds.
+
+Options:
+-i: STIF case will be included in the start of the case log
+-s: cases will be sorted by status
+-e: Shows extra information during the tool run
+-html: Case logs are generated in html format instead of text
+-logall: Logs are created for passed cases too.
+-nologs: Logs are not processed.
+-nosecuritytests: Security tests are not included in the reports.
+-nolivetvttests: Live TV tests are not included in the reports.
+-i: Test case from the CFG is included in the log file
+-file <file>: Only formats defined log file into html
+-runtimes: Result of the case will contain the case execution time in seconds.
+-good: If case has passed once it will be marked as passed no matter how many 
+ times it has failed.
+-cfgsum: Prints summary info for cfgs: how many cases and how long the cfg did 
+ take to execute.
+-finalize
+-fix if you save the file in Excel the log paths will come absolute and don't 
+ work if moved to another directory. use this fix it.
+-caselist <file>: Only reports the cases in caselist.txt, see genrerun.pl for 
+ file format.
+-logfile <file>: Sets filter for log filenames. Default is fusion.
+-slogs: Reads STIF testscripter logs instead of custom logs.
+These files will be generated:
+	test_cases.xml
+	test_cases_brief.xml
+	test_cases_notdocumented.txt
+
+Case specific log files are generated in testcase_logs directory and result 
+file has links to them.
+
+USAGE_EOF
+
+	exit();
+
+};
+
+#------------------------------------------------------------------------------------
+# ReadReportLogs
+#
+# Parameters:
+#	$fileName
+#	$refLogLines
+#
+# Reads log file of specific TestReport.
+#
+# The function has two different behaviours:
+#
+# Filenames for test report and log must match. For example
+# if test report file is TestReport_XXX.txt then fusion_XXX.txt is read if found.
+#
+# If fileName is * then *fusion*.txt files will be read one by one and processed by function CheckCaseEntriesInLog()
+#------------------------------------------------------------------------------------
+sub ReadReportLogs
+{
+	my ($fileName, $refLogLines) = @_;
+
+	return if($optionNoLogs || $optionPrintCfgSummaries);
+
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	#default mask for logs
+	my $filemask = "^$optionLogFileName\.TXT";
+
+	#create file mask for logs if testreport.txt is in format: testreport_*.txt
+	if(index($fileName, "_") != -1)
+	{
+		my $spos = index($fileName, "_");
+		my $epos = rindex($fileName, ".");
+
+		$filemask = substr($fileName, $spos, $epos - $spos);
+		#print("filemask: $filemask\n");
+
+		#$filemask = "$optionLogFileName" . $filemask . "[a-z\-0-9_]*\.txt"; # this finds $optionLogFileName_xxx*.txt
+		$filemask = "$optionLogFileName" . $filemask . "\.txt"; # this finds only $optionLogFileName_xxx.txt
+		#print("filemask: $filemask\n");
+		#die();
+	}
+
+	my $processLogsHere = 0;
+
+	if($fileName eq "*")
+	{
+		$processLogsHere = 1;
+		$filemask = $optionLogFileName . "[a-z\-0-9_]*\.txt"
+	}
+
+	my $i;
+
+	#read the files into refLogLines array
+	foreach $file(@filelist)
+	{
+		#if($file =~ m/^$optionLogFileName[a-z0-9_]+\.TXT$/i or $file =~ m/^$optionLogFileName\.TXT$/i )
+		if($file =~ m/$filemask/i )
+		{
+			print("Reading log file: " . $file . ".");
+
+			if( open(FILE_HANDLE, ".\\" . $file) )
+			{
+				my @tempArray = <FILE_HANDLE>;
+				close(FILE_HANDLE);
+
+				FormatFasttraceTraces(\@tempArray);
+
+				if($processLogsHere)
+				{
+					FindAndMarkCaseEntriesInLog(\@tempArray, \@cases);
+
+					CheckCaseEntriesInLog(\@tempArray);
+				}
+				else
+				{
+					while(scalar(@tempArray) > 0)
+					{
+						push @$refLogLines, (shift(@tempArray));
+					}
+				}
+			}
+		}
+	}
+
+	FindAndMarkCaseEntriesInLog($refLogLines, \@cases);
+}
+
+#------------------------------------------------------------------------------------
+# GetReportLogFileNames
+#
+# Parameters:
+#	$fileName
+#	$refLogFiles
+#
+# Gets log filenames for specific testreport.
+#
+# The function has two different behaviours:
+#
+# Filenames for test report and log must match. For example
+# if test report file is TestReport_XXX.txt then $optionLogFileName_XXX.txt is read if found.
+#
+# If fileName is * then *$optionLogFileName*.txt files will be read one by one and processed by function CheckCaseEntriesInLog()
+#------------------------------------------------------------------------------------
+sub GetReportLogFileNames
+{
+	my ($fileName, $refLogFiles) = @_;
+
+	return if($optionNoLogs || $optionPrintCfgSummaries);
+
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	#default mask for logs
+	my $filemask = "^$optionLogFileName\.TXT";
+
+	#create file mask for logs if testreport.txt is in format: testreport_*.txt
+	if(index($fileName, "_") != -1)
+	{
+		my $spos = index($fileName, "_");
+		my $epos = rindex($fileName, ".");
+
+		$filemask = substr($fileName, $spos, $epos - $spos);
+		$filemask = "$optionLogFileName" . $filemask . "\.txt"; # this finds only $optionLogFileName_xxx.txt
+	}
+
+	if($fileName eq "*")
+	{
+		$filemask = $optionLogFileName . "[a-z0-9_]*\.txt"
+	}
+
+	foreach $file(@filelist)
+	{
+		if($file =~ m/$filemask/i )
+		{
+			push @$refLogFiles, $file;
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# FindAndMarkCaseEntriesInLog
+#
+# Parameters:
+#	$refLogLines
+#
+# Searches for case entries in the log and if found then marks the case in @cases array
+#------------------------------------------------------------------------------------
+sub FindAndMarkCaseEntriesInLog
+{
+	my ($refLogLines, $refCases) = @_;
+
+	my $line;
+
+	print(" - Searching case start entries from log\n") if($optionShowMessages);
+
+    my $startLineIndex = 0;
+
+	# scan the log thru and mark if there's log start entries
+	for( my $i = 0; $i < scalar(@$refLogLines); $i++ )
+	{
+	    my $line = @$refLogLines[$i];
+
+		my $caseStartInLog = 0;
+
+		my $caseId = "";
+
+		if($line =~ m/>>> Case start:/i)
+		{
+			$startLineIndex = $i;
+			$caseStartInLog = 1;
+			$caseId = substr($line, index($line, ">>> Case start:") + length(">>> Case start:"));
+			print("Found case start: $caseId\n") if($optionShowMessages);
+		}
+
+		if($caseStartInLog)
+		{
+			RemoveWhiteSpaces(\$caseId);
+
+			my $refCase = GetCase($caseId, $refCases);
+
+			if(defined($refCase))
+			{
+				@$refCase[$CASE_CHECK_RESULT_LOG_FILE] = 1;
+				@$refCase[$CASE_ENTRY_LOG_START] = $startLineIndex;
+			}
+			else
+			{
+				print("Case start in log found: $caseId\n") if($optionShowMessages);
+				print("ERROR! The start in log found but case is not found from report or cfg.\n");
+			}
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# FormatFasttraceTraces
+#
+# Parameters:
+#	$refLogArray
+#------------------------------------------------------------------------------------
+sub FormatFasttraceTraces
+{
+	my ($refLogArray) = @_;
+
+	my $ftDebug = 0;
+
+	# strip fasttrace logging text from the start of lines
+	#[13:58:17.234] sti: MCU_ASCII_PRINTF; channel:0xE0; msg:$optionLogFileName.TXT 09/10/2006¿1:57:08¿C$optionLogFileName::CheckIsPluginRunning
+
+	my $stripFasttrace = 0;
+	# find first occurance of Musti message, remove anything before that
+	my $i;
+
+	for($i= 0; $i<100; $i++)
+	{
+		if(defined(@$refLogArray[$i]))
+		{
+			if(@$refLogArray[$i] =~ m/MCU_ASCII_PRINTF/i)
+			{
+				$stripFasttrace = 1;
+				last;
+			}
+		}
+	}
+
+	print("fasttrace: end $i, strip: $stripFasttrace\n") if($ftDebug);
+
+	#remove the fasttrace specific lines
+	print("fasttrace: lines before: " . scalar(@$refLogArray) . "\n") if($ftDebug);
+
+	splice(@$refLogArray, 0, $i) if($stripFasttrace);
+
+	return if(!$stripFasttrace);
+
+	print("fasttrace: lines " . scalar(@$refLogArray) . "\n") if($ftDebug);
+
+	#remove the fasttrace line startings and change format of STIF messages
+
+	for($i = 0; $i<scalar(@$refLogArray); $i++)
+	{
+		#before: [14:38:40.641] sti: MCU_ASCII_PRINTF; channel:0xE0; msg:TestCase [ET1024 Sort IapList when it has no IAPs] finished with verdict[0]
+		#after:  [14:38:40.641] sti: MCU_ASCII_PRINTF; channel:0xE0; msg:$optionLogFileName.TXT 18/10/2006¿2:37:37¿TestCase [ET1024 Sort IapList when it has no IAPs] finished with verdict[0]
+		if(@$refLogArray[$i] =~ m/TestCase \[([[a-z0-9_]+) ($regexpCaseName)\] finished with verdict\[[-]?([0-9]+)/i)
+		{
+			#die(@$refLogArray[$i]);
+
+			my $startStr = substr(@$refLogArray[$i], 0, index(@$refLogArray[$i], "TestCase"));
+			my $endStr = substr(@$refLogArray[$i], index(@$refLogArray[$i], "TestCase"));
+
+			my $timeStr = FasttraceLogFindIptvTraceTime($refLogArray, $i);
+
+			@$refLogArray[$i] = $startStr . "$optionLogFileName.TXT " . $timeStr . "\t" . $endStr;
+
+			print("fasttrace: " . @$refLogArray[$i] . "\n") if($ftDebug);
+
+			#print("\n\n" . $startStr . "'\n$optionLogFileName.TXT \n" . $timeStr . "'\n" . $endStr . "'\n" );
+			#die();
+		}
+
+		#change the lines where is STIF message saying starting testcase to "$optionLogFileName.TXT <TIME> >>> Case start: <CASEID>" format, otherwise it will be not be recognized later
+		if(@$refLogArray[$i] =~ m/Starting testcase \[([[a-z0-9_]+) ($regexpCaseName)\]/i)
+		{
+			print("debug: " . @$refLogArray[$i] . "\n");
+			@$refLogArray[$i] = substr(@$refLogArray[$i], 0, index(@$refLogArray[$i], "Starting testcase"));
+
+			my $timeStr = FasttraceLogFindIptvTraceTime($refLogArray, $i);
+
+			@$refLogArray[$i] .= "$optionLogFileName.TXT $timeStr\t>>> Case start: $1" . "\r\n";
+
+			print("fasttrace: '" . @$refLogArray[$i] . "'\n") if($ftDebug);
+
+			#@$refLogArray[$i] = "[14:38:37.953] sti: MCU_ASCII_PRINTF; channel:0xE0; msg:$optionLogFileName.TXT 18/10/2006\t2:37:34\t>>> Case start: $1";
+		}
+
+		if(@$refLogArray[$i] =~ m/channel\:[0-9a-z]+; msg:$optionLogFileName.TXT [0-9]+\/[0-9]+\/[0-9]+/i)
+		{
+			@$refLogArray[$i] = substr(@$refLogArray[$i], index(@$refLogArray[$i], "msg:$optionLogFileName.TXT") + length("msg:$optionLogFileName.TXT") + 1);
+
+			#replace fasttrace tab chars
+			@$refLogArray[$i] =~ s/¿/\t/g;
+			#print(@$refLogArray[$i]);
+
+		}
+		else
+		{
+			# if there's no match then this is not a trace for $optionLogFileName
+			splice(@$refLogArray, $i, 1);
+			$i--;
+		}
+	}
+}
+
+
+#------------------------------------------------------------------------------------
+# FastTraceLogFindIptvTraceTime
+#
+# Parameters:
+#	$refLines: reference to array of the log line
+# 	$startLine: line where to start looking for
+#
+# Finds next time stamp of Iptvengine from Fasttrace log
+#------------------------------------------------------------------------------------
+sub FasttraceLogFindIptvTraceTime
+{
+	my ($refLines, $startLine) = @_;
+
+	#find next trace of iptvengine and get the time and date
+	my $timeStr = "";
+	for(my $e = $startLine+1; $e < scalar(@$refLines); $e++)
+	{
+		if(@$refLines[$e] =~m/msg:$optionLogFileName.TXT/)
+		{
+			my $line = @$refLines[$e];
+			#remove the fasttrace trace from line start, we don't want it's time
+			$line = substr($line, index($line, "msg:$optionLogFileName.TXT"));
+
+			if($line =~ m/([0-9]+\/[0-9]+\/[0-9]+)/i)
+			{
+				$timeStr .= $1 . "\t";
+			}
+
+			if($line =~ m/([0-9]+:[0-9]+:[0-9]+)/i)
+			{
+				$timeStr .= $1;
+			}
+			last if($timeStr ne "");
+		}
+	}
+
+	return $timeStr;
+}
+
+#------------------------------------------------------------------------------------
+# ReportNotDocumentedCases
+#
+# Parameters:
+#	$file
+#
+# Writes the @notDocumentedCases array into a file
+#------------------------------------------------------------------------------------
+sub ReportNotDocumentedCases
+{
+	my ($file) = @_;
+
+	if(scalar(@notDocumentedCases) > 0)
+	{
+		if(!open(FILE_HANDLE, ">" . $file) )
+		{
+			print("ERROR! Could not open file '" . $file . "'\n");
+		} else {
+			print FILE_HANDLE ( @notDocumentedCases );
+			close(FILE_HANDLE);
+			print("Report " . $NOT_DOCUMENTED_CASES_FILE . " written.\n");
+		}
+	} else
+	{
+		print("All cases are documented.");
+	}
+}
+
+#------------------------------------------------------------------------------------
+# ReadTestReports
+#
+# Reads TestReportXX.txt files from the current directory and updates the cases with the results.
+# Reads also logs for the report and creates case specific logs.
+#------------------------------------------------------------------------------------
+sub ReadTestReports
+{
+	# Read filelist of current directory
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	my $readSomething = 0;
+
+    my @testScripterLogLines;
+    ReadTestScripterLogs( \@testScripterLogLines );
+    
+    # Read reports and logs in the current directory
+	foreach $file(@filelist)
+	{
+		next if( -d $file or $file eq "." or $file eq "..");
+
+        # Read results STIF testreport
+		if($file =~ m/^TestReport[a-z\-0-9_]+\.txt$/i or $file =~ m/^TestReport\.txt$/i )
+		{
+			if($optionShowMessages) { print("***************************\n"); };
+			print("Report file: " . $file . "\n");
+
+			my @logFiles;
+			my @caseResults;
+
+			ReadTestRunInfoFromStifReport( $file, \@caseResults, \@logFiles );
+			ParseResultsAndLogs( \@caseResults, \@logFiles, \@testScripterLogLines );
+
+			undef(@logFiles);
+			undef(@caseResults);
+
+			$readSomething++;
+		}
+	}
+
+	return if($optionPrintCfgSummaries);
+
+	# No testreports found. Read all logs and parse them.
+	if($readSomething == 0)
+	{
+		print("\nNo test reports found in the current directory. Trying to read all the logs.\n");
+
+		my @logFileLines;
+
+		ReadReportLogs("*", \@logFileLines);
+		
+		if( scalar( @logFileLines ) > 0 )
+		{
+			$readSomething = 1;
+		}
+
+		undef(@logFileLines);
+	}
+
+	return $readSomething;
+}
+
+#------------------------------------------------------------------------------------
+# ReadTestReportsAlt
+#
+# Every test report is one run and those should have as much same cases as possible.
+#------------------------------------------------------------------------------------
+sub ReadTestReportsAlt
+{
+    my ($refRuns) = @_;
+
+	# Read filelist of current directory
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+    my @runs;
+
+    # Read reports and logs in the current directory
+	foreach $file(@filelist)
+	{
+		if($file eq "." or $file eq "..") {next};
+
+        # Read results STIF testreport
+		if($file =~ m/^TestReport[a-z0-9_]+\.txt$/i or $file =~ m/^TestReport\.txt$/i )
+		{
+			if($optionShowMessages) { print("***************************\n"); };
+			print("Report file: " . $file . "\n");
+
+            # Store report filename, run date and then cases into array
+
+        	# Read date from report
+        	if( !open(FILE_HANDLE, $file) ) {
+        		print("ERROR! Could not open file '" . $file . "'\n");
+        		return;
+        	}
+        	my @array = <FILE_HANDLE>;
+        	close(FILE_HANDLE);
+
+        	#Monday 25th August 2008
+        	my @pieces = split(' ', $array[1]);
+
+            $pieces[1] =~ s/st//;
+            $pieces[1] =~ s/nd//;
+            $pieces[1] =~ s/rd//;
+            $pieces[1] =~ s/th//;
+
+            undef(@array);
+
+            my @runInfo;
+			$runInfo[0] = $file;
+			$runInfo[1] = substr( $pieces[0], 0, 3 ) . " " . $pieces[1] . " " . substr( $pieces[2], 0, 3 );
+
+			my @runResults;
+			my @logFiles;
+			ReadTestRunInfoFromStifReport($file, \@runResults, \@logFiles );
+            $runInfo[2] = \@runResults;
+
+	        push @$refRuns, \@runInfo;
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# ReadTestScripterLogs
+#------------------------------------------------------------------------------------
+sub ReadTestScripterLogs
+{
+    my ( $refLogLines ) = @_;
+    
+    return if($optionNoLogs || $optionPrintCfgSummaries);
+    
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+	
+	foreach $file(@filelist)
+	{
+		if($file =~ m/^testscripter[a-z0-9_]+.txt/i )
+		{
+		    print("Reading scripter log: $file\n") if( $optionDebug );
+		    if( open(FILE_HANDLE, $file) )
+    		{
+    			my @tempArray = <FILE_HANDLE>;
+    			close(FILE_HANDLE);
+    
+    			while(scalar(@tempArray) > 0)
+    			{
+    				push @$refLogLines, ( shift( @tempArray ) );
+    			}
+    			undef(@tempArray);
+    		}
+    		else
+    		{
+    		    print("ERROR: Could not open the log file: $file!\n");
+    		}			
+		}
+		else
+		{
+		    print("Not a scripter log: $file\n") if( $optionDebug );
+		}
+	}
+}
+
+
+#------------------------------------------------------------------------------------
+# ReadTestReportDates
+#
+# Reads the date from each testreport in current directory
+#------------------------------------------------------------------------------------
+sub ReadTestReportDates
+{
+    my ($refDates) = @_;
+
+	# Read filelist of current directory
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+    my @runs;
+
+    # Read reports and logs in the current directory
+	foreach $file(@filelist)
+	{
+		if($file eq "." or $file eq "..") {next};
+
+        # Read results STIF testreport
+		if($file =~ m/^TestReport[a-z0-9_]+\.txt$/i or $file =~ m/^TestReport\.txt$/i )
+		{
+			my @fileDate;
+			$fileDate[0] = $file;
+
+        	if( !open(FILE_HANDLE, $file) ) {
+        		print("ERROR! Could not open file '" . $file . "'\n");
+        		return;
+        	}
+        	my @array = <FILE_HANDLE>;
+        	close(FILE_HANDLE);
+
+        	#Monday 25th August 2008
+        	my @pieces = split(' ', $array[1]);
+
+            $pieces[1] =~ s/st//;
+            $pieces[1] =~ s/nd//;
+            $pieces[1] =~ s/rd//;
+            $pieces[1] =~ s/th//;
+
+        	$fileDate[1] = substr( $pieces[0], 0, 3 ) . " " . $pieces[1] . " " . substr( $pieces[2], 0, 3 );
+
+            undef(@array);
+
+	        push @$refDates, \@fileDate;
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# ParseTimeFromLine
+#
+#------------------------------------------------------------------------------------
+sub ParseTimeFromLine
+{
+    my ($line) = @_;
+
+    my $timestr = "";
+
+    if($line =~ m/([0-9]+)(:[0-9]+:[0-9]+\,[0-9]*)/i || $line =~ m/([0-9]+)(:[0-9]+:[0-9]+\.[0-9]*)/i)
+    {
+        $timestr = "" . $1 . $2;
+        if($1 > 12)
+        {
+            $timestr = "" . ($1-12) . $2;
+        }
+    }
+
+    return $timestr;
+}
+
+#------------------------------------------------------------------------------------
+# ReadTestRunInfoFromStifReport
+#
+# Parameters:
+#	$file, the testreport
+#   $refCaseResults, results for all cases of the testreport
+#   $refLogFiles, filenames for the log files of the testreport
+#------------------------------------------------------------------------------------
+sub ReadTestRunInfoFromStifReport
+{
+	my ($file, $refCaseResults, $refLogFiles) = @_;
+
+	if( !open(FILE_HANDLE, $file) ) {
+		print("ERROR! Could not open file '" . $file . "'\n");
+		return;
+	}
+	my @array = <FILE_HANDLE>;
+	close(FILE_HANDLE);
+
+    # Get log files for the report
+    GetReportLogFileNames($file, $refLogFiles);
+
+	my $index = 0;
+	my $line = "";
+
+	for(my $i = 0; $i < scalar(@array); $i++)
+	{
+		$line = $array[$i];
+		RemoveWhiteSpaces(\$line);
+
+#[testscripter_iptvservicetest][C:\TestFramework\IptvServiceTest.cfg][10] Title:[ET9009 Set id]
+#[testscripter][c:\testframework\iptvvoddlapitest2.cfg][2] Title:[ET12100 Purchase]
+#	StartTime: 8:54:23.5565 PM, EndTime: 8:54:24.3471 PM
+#	Result: 0 [] ==> PASSED
+#	Info: xxx
+
+		# found a start of a result
+		#[1] Title:[ET1000 Add multiple Iaps]
+		my $cfgFile = "";
+
+		if($line =~ m/([a-z_0-9.]+)\]\[[0-9]+\][ ]+Title:\[/i)
+		{
+			$cfgFile = $1;
+			if($optionShowMessages) { print(" - Cfg: $cfgFile\n"); };
+			
+			for( my $e = 0; $e < scalar( @gCfgFiles ); $e++ )
+			{
+			    if( $gCfgFiles[$e] =~ m/$cfgFile/i )
+			    {
+			        my $caseCount = ParseCfg( $gCfgFiles[$e] );
+			        $gCfgFiles[$e] = ""; # We don't want to read it again.
+			    }
+			}
+		}
+
+		if($line =~ m/\[[0-9]+\][ ]+Title:\[($regexpCaseName)\]$/i)
+		{
+			if($optionShowMessages) { print(" - Case: " . $1 . "\n"); };
+
+			#get the case name
+			my $caseName = $1;
+			my $caseId = GetCaseIdFromName($caseName);
+			my $caseRunTime = CountCaseRunTime($array[$i+1]);
+
+            # Save case report lines for later use
+            my $caseLine1 = $array[$i];
+            my $caseLine2 = $array[$i+1];
+            my $caseLine3 = $array[$i+2];
+
+			# Read the case result
+
+			#	StartTime: 3:54:10.1670 PM, EndTime: 3:54:23.8226 PM
+			$line = $array[$i+2];
+			RemoveWhiteSpaces(\$line);
+
+			my $info = "";
+			my $result = "N/A";
+			my $status = "$caseDefaultStatus";
+			my $reason = "";
+
+			# Result: 0 [] ==> PASSED / something
+			if($line =~ m/^Result:[ ]([-]*[0-9]+)[ ]\[[\w]*\][ ]==>[ ]([\w ]+)$/i)
+			{
+				$result = $1;
+				$status = $2;
+			}
+            # Result: -2 [CTestRunner::RunError [CTestRunner::ExecuteCommandL returned error]] ==> FAILED
+			# Result: -2 [CTestRunner::ExecuteCommandL returned error] ==> FAILED
+			elsif($line =~ m/^Result:[ ]([-]*[0-9]+)[ ]\[([\w: ]+)\][ ]==>[ ]([\w]+)$/i or
+			      $line =~ m/^Result:[ ]([-]*[0-9]+)[ ]\[[\w: ]+\[([\w: ]+)\]\][ ]==>[ ]([\w]+)$/i )
+			{
+				$result = $1;
+				$status = $3;
+				$reason = $2;
+			}
+
+			#CaseExecutionResult: Test case execution fails with -15
+			elsif($line =~ m/^CaseExecutionResult:[ ]Test case execution fails with ([-]*[0-9]+)$/i)
+			{
+				$result = $1;
+				$status = "FAILED";
+				$reason = "Test case execution failed.";
+			}
+
+			# CaseExecutionResult: Leave during case: with -4
+			elsif($line =~ m/^CaseExecutionResult:[ ]Leave during case: with ([-]*[0-9]+)$/i)
+			{
+				$result = $1;
+				$status = "FAILED";
+				$reason = "Leave during case";
+			}
+			#CaseExecutionResult: Crash reason:Error in test ca with 69
+			#CaseExecutionResult: Crash reason:IptvEngineServer with 13
+			elsif($line =~ m/^CaseExecutionResult:[ ]Crash reason:([\w_ \-]+)[ ]with[ ]([-]*[0-9]+)$/i)
+			{
+				$result = $2;
+				$status = "CRASHED";
+				$reason = $1;
+			}
+
+			# Result: -2 [Crash reason:KERN-EXEC] ==> FAILED
+			elsif($line =~ m/^Result:[ ]([-]*[0-9]+)[ ]\[Crash reason:([\w\-:\. ]+)\] ==> ([\w]+)/i)
+			{
+				$result = $1;
+				$status = "CRASHED";
+				$reason = $2;
+			}
+
+			# CaseExecutionResult: TestModule loading fails, cannot connect to the TestModule with -2
+			elsif($line =~ m/^CaseExecutionResult: TestModule loading fails, cannot connect to the TestModule with ([-]*[0-9]+)/i)
+			{
+				$result = $1;
+				$status = "FAILED";
+				$reason = "Test module loading failed.";
+			}
+			else
+			{
+				print("Error while parsing case result line: " . $line . "\n");
+			}
+
+			$line = $array[$i+3];
+			RemoveWhiteSpaces(\$line);
+
+			#	Info: xxx
+			if($line =~ m/^Info:/i)
+			{
+				$info = substr($line, 5) . " / ";
+				RemoveWhiteSpaces(\$info);
+				$info .= " ";
+			}
+
+            my @caseResult;
+
+            $caseResult[$CASE_CFG_FILE] = $cfgFile;
+            $caseResult[$CASE_NAME] = $caseName;
+            $caseResult[$CASE_ID] = $caseId;
+            $caseResult[$CASE_RUN_TIME_SECONDS] = $caseRunTime;
+        	$caseResult[$CASE_NOTE] = $info;
+        	$caseResult[$CASE_RESULT] = $result;
+        	$caseResult[$CASE_STATUS] = $status;
+        	$caseResult[$CASE_REASON] = $reason;
+        	$caseResult[$CASE_REPORTLINE1] = $caseLine1;
+        	$caseResult[$CASE_REPORTLINE2] = $caseLine2;
+        	$caseResult[$CASE_REPORTLINE3] = $caseLine3;
+
+            push @$refCaseResults, \@caseResult;
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# ParseResultsAndLogs
+#
+# Parameters:
+#   $refCaseResults
+#	$refLogFiles
+#   $refTestScripterLogLines
+#------------------------------------------------------------------------------------
+sub ParseResultsAndLogs
+{
+	my ($refCaseResults, $refLogFiles, $refTestScripterLogLines) = @_;
+
+    my @logLines;
+
+    # Read log files
+	foreach $file (@$refLogFiles)
+	{
+        $file =~ s/\//\\/g;
+
+    	print("Reading log file: " . $file . " .. ");
+
+		if( open(FILE_HANDLE, $file) )
+		{
+			my @tempArray = <FILE_HANDLE>;
+			close(FILE_HANDLE);
+
+			FormatFasttraceTraces(\@tempArray);
+			print " .. ";
+
+			while(scalar(@tempArray) > 0)
+			{
+				push @logLines, (shift(@tempArray));
+			}
+			print " done.\n";
+
+			undef(@tempArray);
+		}
+		else
+		{
+		    print("ERROR: Could not open the log file: $file!\n");
+		}
+	}
+	
+	FindAndMarkCaseEntriesInLog( \@logLines, $refCaseResults );
+
+    my @caseSpecificLogs;
+
+    foreach $refCaseResult (@$refCaseResults)
+    {
+        my $cfgFile = @$refCaseResult[$CASE_CFG_FILE];
+        my $caseName = @$refCaseResult[$CASE_NAME];
+        my $caseId = @$refCaseResult[$CASE_ID];
+        my $caseRunTime = @$refCaseResult[$CASE_RUN_TIME_SECONDS];
+    	my $info = @$refCaseResult[$CASE_NOTE];
+    	my $result = @$refCaseResult[$CASE_RESULT];
+    	my $status = @$refCaseResult[$CASE_STATUS];
+    	my $reason = @$refCaseResult[$CASE_REASON];
+    	my $reportLine1 = @$refCaseResult[$CASE_REPORTLINE1];
+    	my $reportLine2 = @$refCaseResult[$CASE_REPORTLINE2];
+    	my $reportLine3 = @$refCaseResult[$CASE_REPORTLINE3];
+
+        if($optionShowMessages) { print(" - Case: " . $caseName . "\n"); };
+
+		# Create case specific log into the log directory
+		my $caseLogFile = GetCaseField($caseId, $CASE_LOG_FILE);
+		my $caseScripterLogFile = GetCaseField($caseId, $CASE_LOG_FILE_SCRIPTER);
+        my $refCaseDesc = GetCaseDesc($caseId);
+
+        $caseLogFile = GetFileNameForCaseLog(  $reportLine1, $reportLine2, $reportLine3 );
+        $caseScripterLogFile = GetFileNameForCaseLog(  $reportLine1, $reportLine2, $reportLine3, "_scripter" );
+
+        if( -e $caseLogFile )
+        {
+            unlink ( $caseLogFile );
+        }
+
+        if( -e $caseScripterLogFile )
+        {
+            unlink ( $caseScripterLogFile );
+        }
+
+        my @logInfo;
+        $logInfo[0] = $caseLogFile;
+        if( defined( @$refCaseResult[$CASE_CHECK_RESULT_LOG_FILE] ) )
+        {
+            # Case start entry trace was found from log.
+            $logInfo[1] = @$refCaseResult[$CASE_ENTRY_LOG_START];
+        }
+        else
+        {
+            $logInfo[1] = -1;
+        }
+        $logInfo[2] = $reportLine1;
+        $logInfo[3] = $reportLine2;
+        $logInfo[4] = $reportLine3;
+        $logInfo[5] = $refCaseDesc;
+        $logInfo[6] = $caseScripterLogFile;
+        push @caseSpecificLogs, \@logInfo;
+
+		# Update case
+		my $refCase = GetCase($caseId, \@cases);
+		if(!defined($refCase))
+		{
+			$refCase = GetCaseByNameOnly($caseName);
+		}
+
+		if(defined($refCase))
+		{
+			UpdateCase($refCase, $caseLogFile, $caseScripterLogFile, $result, $status, $info, $reason, $caseRunTime);
+		}
+		else
+		{
+		    # Case doesn't exist yet, add it.		    
+			my @case;
+			$case[$CASE_NAME] = $caseName;
+			$case[$CASE_ID] = $caseId;
+			$case[$CASE_RUN_TIMES] = 0;
+			$case[$CASE_CRASHED] = 0;
+			$case[$CASE_FAILED] = 0;
+			$case[$CASE_PASSED] = 0;
+			$case[$CASE_STATUS] = "$caseDefaultStatus";
+			$case[$CASE_PURPOSE] = "N/A";
+			$case[$CASE_MEANS] = "N/A";
+			$case[$CASE_REQUIRED_SETTINGS] = "N/A";
+			$case[$CASE_RELATED_REQUIREMENTS] = "N/A";
+			$case[$CASE_VERIFICATION] = "N/A";
+			$case[$CASE_NOTE] = "N/A";
+			$case[$CASE_REASON] = "";
+			$case[$CASE_RESULT] = "";
+			$case[$CASE_LOG_FILE] = "";
+			$case[$CASE_LOG_FILE_SCRIPTER] = "";
+			$case[$CASE_CHECK_RESULT_LOG_FILE] = 0;
+			$case[$CASE_CFG_FILE] = $cfgFile;
+			$case[$CASE_RUN_TIME_SECONDS] = 0;
+
+			$refCase = GetCaseByNameOnly($caseName);
+
+			UpdateCase(\@case, $caseLogFile, $caseScripterLogFile, $result, $status, $info, $reason, $caseRunTime);
+
+            # Insert case after other cases from same CFG, if any.
+
+            my $indexToInsert = -1;
+            
+            for( my $i = 0; $i < scalar(@cases); $i++ )
+        	{
+        		my $case = $cases[$i];
+        		
+        		if( defined(@$case[$CASE_CFG_FILE]) )
+		        {
+		            if( @$case[$CASE_CFG_FILE] eq $cfgFile )
+		            {
+		                $indexToInsert = $i;
+		            }
+		        }
+		    }
+		    
+		    if( $indexToInsert == -1 )
+		    {
+		        push @cases, [ @case ];
+		    }
+		    else
+		    {
+		        splice @cases, $indexToInsert+1, 0, [ @case ];
+		    }
+		}
+    }
+
+    my $caseCount = scalar( @$refCaseResults );
+
+    my @testScripterLogCaseLocations;
+    PrepareTestScripterLogs( $refTestScripterLogLines, \@testScripterLogCaseLocations );
+    WriteCaseSpecificScripterLogs( \@caseSpecificLogs, $refTestScripterLogLines, \@testScripterLogCaseLocations );
+    WriteCaseSpecificLogs( \@caseSpecificLogs, $caseCount, \@logLines );    
+
+	if($caseCount >= 10 && $optionShowMessages == 0)
+	{
+	     print("\n"); #line break for the progress bar
+	}
+	elsif($optionShowMessages == 0)
+	{
+	    print("##########\n"); # fake it
+	}
+
+	undef(@logLines);
+}
+
+#------------------------------------------------------------------------------------
+# WriteCaseSpecificLogs
+#
+# Parameters:
+#   $refCaseSpecificLogs 
+#	$caseCount
+#   $refLogLines
+#------------------------------------------------------------------------------------
+sub WriteCaseSpecificLogs
+{
+    my ($refCaseSpecificLogs, $caseCount, $refLogLines ) = @_;
+
+    my $caseLogProgress = 0;
+
+    foreach my $refLogInfo ( @$refCaseSpecificLogs )
+    {
+        #@logInfo[1] = @$refCaseResult[$CASE_ENTRY_LOG_START];
+
+        my $caseLogFile = @$refLogInfo[0];
+        my $reportLine1 = @$refLogInfo[2];
+        my $reportLine2 = @$refLogInfo[3];
+        my $reportLine3 = @$refLogInfo[4];
+        my $refCaseDesc = @$refLogInfo[5];
+
+        my $logWritten = 0;
+        if( @$refLogInfo[1] != -1 )
+        {
+            # Case start entry trace found from log files.
+            $logWritten = WriteCaseLogFromEntry($caseLogFile, $refLogLines, @$refLogInfo[1], $reportLine1, $reportLine2, $reportLine3);
+        }
+
+        if( !$logWritten )
+        {
+		    # Use case start and end times to write case specific log.
+		    WriteCaseLog($caseLogFile, $refLogLines, $refCaseDesc, $reportLine1, $reportLine2, $reportLine3);
+		}
+
+		# Show simple progress bar
+		if($caseCount >= 10 && $optionShowMessages == 0)
+		{
+			$caseLogProgress++;
+			if($caseLogProgress > $caseCount/10)
+			{
+				$caseLogProgress = 0;
+				print("#");
+			}
+		}
+    }
+
+	if($caseCount >= 10 && $optionShowMessages == 0)
+	{
+	     print("\n"); #line break for the progress bar
+	}
+	elsif($optionShowMessages == 0)
+	{
+	    print("##########\n"); # fake it
+	}   
+}
+
+#------------------------------------------------------------------------------------
+# PrepareTestScripterLogs
+#
+# Parameters:
+#	$refTestScripterLogLines
+#   $refTestScripterLogCaseLocations
+#------------------------------------------------------------------------------------
+sub PrepareTestScripterLogs
+{
+    my ($refTestScripterLogLines, $refTestScripterLogCaseLocations ) = @_;
+
+    for( my $i = 0; $i < scalar(@$refTestScripterLogLines); $i++ )
+    {
+        my $line = @$refTestScripterLogLines[$i];
+        
+        if( $line =~ m/RunTest:/ )
+        {
+            push @$refTestScripterLogCaseLocations, ( $i );
+        }
+    }
+}
+
+#------------------------------------------------------------------------------------
+# WriteCaseSpecificScripterLogs
+#
+# Parameters:
+#	$refLogFiles
+#   $refCaseResults
+#   $refTestScripterLogCaseLocations
+#------------------------------------------------------------------------------------
+sub WriteCaseSpecificScripterLogs
+{
+    my ($refCaseSpecificLogs, $refScripterLogLines, $refTestScripterLogCaseLocations ) = @_;
+
+    foreach my $refLogInfo ( @$refCaseSpecificLogs )
+    {        
+        my $caseLogFile = @$refLogInfo[6];
+        my $reportLine1 = @$refLogInfo[2];
+        my $reportLine2 = @$refLogInfo[3];
+        my $reportLine3 = @$refLogInfo[4];
+        my $refCaseDesc = @$refLogInfo[5];
+
+        WriteCaseLogFromTestScripterLogs( $caseLogFile, $refScripterLogLines, $refTestScripterLogCaseLocations, $refCaseDesc, $reportLine1, $reportLine2, $reportLine3);
+    }
+}
+
+#------------------------------------------------------------------------------------
+# WriteCaseLogFromTestScripterLogs
+#
+#------------------------------------------------------------------------------------
+sub WriteCaseLogFromTestScripterLogs
+{ 
+    my ( $caseLogFile, $refLogLines, $refTestScripterLogCaseLocations, $refCaseDesc, $line1, $line2, $line3 ) = @_;
+
+    print("### WriteCaseLogFromTestScripterLogs") if( $optionDebug );
+
+	# Don't generate log files if we only print summary
+	if($optionPrintCfgSummaries)
+	{
+		return;
+	}
+
+	RemoveWhiteSpaces(\$line1);
+	RemoveWhiteSpaces(\$line2);
+	RemoveWhiteSpaces(\$line3);
+
+	my $lineBreak = "\n";
+	$lineBreak = "<br>\n" if($optionHtml);
+
+	my $caseName = "";
+
+	if($line1 =~ m/\[[0-9]+\][ ]+Title:\[([a-z0-9]+$regexpCaseName)\]$/i)
+	{
+		#"' ultraedit
+		$caseName = $1;
+		print(" Writing scripter log for: $caseName.\n") if($optionShowMessages);
+	}
+	else
+	{
+	    return;
+	}
+
+	# Write header for case
+
+	my @writeArray;
+
+	# split the first line
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+	push @writeArray, ( substr($line1, 0, index($line1, "Title:")) . $lineBreak );
+	push @writeArray, ( substr($line1, index($line1, "Title:")) . $lineBreak );
+	my $title = substr($line1, index($line1, "Title:"));
+
+	#($line1 . "\n");
+	push @writeArray, ($line2 . $lineBreak);
+	push @writeArray, ($line3 . $lineBreak);
+	push @writeArray, ("\n");
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+
+	# Include the script for the case in the file?
+
+	if($optionCaseIncludedInLog)
+	{
+		foreach $linexxx (@{$refCaseDesc})
+		{
+			push @writeArray, ("$linexxx");
+			push @writeArray, ($lineBreak) if($optionHtml);
+		}
+		push @writeArray, ( "<hr>" ) if($optionHtml);
+		push @writeArray, ("\n");
+	}
+	
+	# Create log directory
+
+	if ( !(-e "testcase_logs") )
+	{
+  		mkdir("testcase_logs");
+	}
+
+	if ( !(-e "$caseLogOutDir") )
+	{
+		mkdir($caseLogOutDir, 0755);
+	}
+
+    # Find start and end lines for the case.
+    my $startLine = -1;
+    my $endLine = -1;
+
+    my $caseNameRegexp = $caseName;
+    $caseNameRegexp =~s/\)/\\\)/;
+    $caseNameRegexp =~s/\(/\\\(/;
+
+    # Try to find case start from cached locations.
+    foreach my $lineNum ( @$refTestScripterLogCaseLocations )
+    {
+        if( @$refLogLines[$lineNum] =~ m/RunTest: $caseNameRegexp/ )
+        {
+            print("  - found cached start: $lineNum") if( $optionDebug );
+            $startLine = $lineNum;
+            last;
+        }
+    }    
+
+    for( my $i = $startLine; $i < scalar(@$refLogLines); $i++ )
+    {
+        $i++ if( $i < 0 );
+        
+        my $line = @$refLogLines[$i];
+
+        next if( !defined $line );
+        
+        # Case start was not found from cached locations, find it as we go thru the lines.
+        if( $startLine == -1 )
+        {   
+            if( $line =~ m/RunTest: $caseNameRegexp/ )
+            {
+                print("  - found start: $line") if( $optionDebug );
+                $startLine = $i;
+            }
+        }
+        else
+        {
+            if( $line =~ m/\*\*\*Testcase [a-z]+\*\*\*/i )
+            {
+                print("  - found end: $line") if( $optionDebug );
+                $endLine = $i + 1;
+                last;
+            }
+        }
+    }
+
+    if( $startLine == -1 || $endLine == -1 )
+    {
+        return;
+    }
+
+	# Write the log file
+
+	my $fileMode = ">>";
+
+	print(" - Case log file: " . $caseLogFile ."\n") if($optionShowMessages);
+
+	if(	open(FILE_HANDLE, $fileMode . $caseLogFile) )
+	{
+		if($optionHtml)
+		{
+			print FILE_HANDLE (
+			"<html>\n" .
+			"<head>\n" .
+			"<title>$title</title>\n" .
+			"</head>\n" .
+			"<body>\n" .
+			"<basefont color=\"black\" face=\"arial\" size=\"4\">\n"
+			);
+		}
+
+		foreach $line(@writeArray)
+		{
+			print FILE_HANDLE ($line);
+		}
+
+		for( my $i = $startLine; $i < $endLine; $i++ )
+		{
+			my $line = @$refLogLines[$i];
+			FormatLogLine(\$line) if($optionHtml);
+
+			print FILE_HANDLE ($line);
+		}
+
+		if($optionHtml)
+		{
+		print FILE_HANDLE (
+			"</body>\n" .
+			"</html>"
+			);
+		}
+
+        print FILE_HANDLE ( $lineBreak );
+		print FILE_HANDLE ( $lineBreak );
+
+		close FILE_HANDLE;
+
+	} else
+	{
+		print("ERROR: Could not write to file: " . $caseLogFile . "\n");
+	}
+}
+
+#------------------------------------------------------------------------------------
+# CheckCaseEntriesInLog
+#
+# Parameters:
+#	$refLogLines: reference to array of log lines
+#
+# Finds if there's log entries for cases that are not reported in the testreport files
+# and create case specific logs for them
+#------------------------------------------------------------------------------------
+sub CheckCaseEntriesInLog
+{
+	my ($refLogLines) = @_;
+
+	foreach $case(@cases)
+	{
+		if(@{$case}[$CASE_CHECK_RESULT_LOG_FILE] == 1)
+		{
+			@{$case}[$CASE_CHECK_RESULT_LOG_FILE] = 0;
+
+#create the next lines for WriteCaseLog function
+
+#line1: [testscripter_iptvservicemanagementapitestasync][c:\TestFramework\IptvServiceManagementApiTestAsync.cfg][2] Title:[ET08203 Add valid hardcoded service_0 ASYNC]
+#line2:	StartTime: 3:06:14.2212 PM, EndTime: 3:06:18.1037 PM
+#line3:	Result: 0 [] ==> PASSED
+
+			#starttime = case startline
+			#endttime = next case starttline | lastline
+
+			my $line1 = "[unknown.cfg][0] Title:[" . @{$case}[$CASE_NAME] . "]";
+			my $line2 = "";
+			my $line3 = "Result: 0 [] ==> UNKNOWN";
+
+			my $startTime = "";
+			my $endTime = "";
+			my $status = "UNKNOWN";
+			my $caseLogFile = "";
+			my $result = "0";
+			my $info = "";
+			my $reason = "";
+
+			my $caseId = "";
+			foreach $line(@$refLogLines)
+			{
+				# take the times from lines where is case start text
+
+				if($startTime eq "" && $line =~ m/>>> Case start:/i)
+				{
+					$caseId = substr($line, index($line, ">>> Case start:") + length(">>> Case start:"));
+
+					RemoveWhiteSpaces(\$caseId);
+
+					# set start time if case matches
+					#02/08/2006	12:15:42	>>> Case start: ET00000 caseId
+					if($caseId eq @{$case}[$CASE_ID])
+					{
+						#print("*** Reading case name\n\n");
+						if($line =~ m/([0-9]+):([0-9]+):([0-9]+)/)
+						{
+							#print("CASESTART: $line\n");
+							$startTime = "$1:$2:$3.0000";
+							#print("*** READ TIME $startTime\n\n");
+							next; # skip the rest of loop otherwise endtime will be same
+						}
+					}
+				}
+
+				# find endtime for case if starttime is set
+				if($startTime ne "")
+				{
+					#[14:38:40.641] sti: MCU_ASCII_PRINTF; channel:0xE0; msg:TestCase [ET1024 Sort IapList when it has no IAPs] finished with verdict[0]
+
+					#die("$line") if($line =~m/$caseId/i);
+					#die("line: $line\n") if($line =~ m/finished with verdict/);
+
+					if($line =~ m/$caseId/i and $line =~ m/finished with verdict\[([-]*[0-9]+)\]/)
+					{
+
+						$result = $1;
+
+						if($1 eq "0")
+						{
+							$status = "PASSED";
+							$line3 = "Result: $1 [] ==> PASSED";
+						}
+						else
+						{
+							$status = "FAILED";
+							$line3 = "Result: $1 [] ==> FAILED";
+						}
+					}
+
+					#if line has time then grab it
+					if($line =~ m/([0-9]+):([0-9]+):([0-9]+)/)
+					{
+						$endTime = "$1:$2:$3.9999";
+						# stop searching when next case is starting
+						if( ($line =~ m/>>> Case start:/i || $line =~ m/>>> Case end./i) and !($line =~ m/$caseId/) )
+						{
+							#print("CASEEND: $line\n");
+							last;
+						}
+					}
+				}
+
+			}
+
+			$line2 = "StartTime: $startTime PM, EndTime: $endTime PM";
+
+			#print("l1: $line1\nl2: $line2\nl3: $line3\n\n");
+
+			my $refCaseDesc = GetCaseDesc($caseId);
+
+			$caseLogFile = GetFileNameForCaseLog( $line1, $line2, $line3 );
+
+			WriteCaseLog($caseLogFile, $refLogLines, $refCaseDesc, $line1, $line2, $line3);
+
+			my $refCase = GetCase($caseId, \@cases);
+
+			UpdateCase($refCase, $caseLogFile, "", $result, $status, $info, $reason, 0);
+		}
+	}
+}
+
+sub UpdateCase
+{
+	my ($refCase, $caseLogFile, $caseScripterLogFile, $result, $status, $info, $reason, $caseRunTimeSeconds) = @_;
+
+	if($optionShowMessages) { print(" - Case update: $result, $status, $reason, $caseRunTimeSeconds\n\n"); };
+
+	die("Result not defined. Cannot update.\n") if(!defined($result)  );
+	die("Status not defined. Cannot update.\n") if(!defined($status) );
+	die("Info not defined. Cannot update.\n") if( !defined($info) );
+	die("Reason not defined. Cannot update.\n") if( !defined($reason) );
+
+	$caseRunTimeSeconds = 0 if($caseRunTimeSeconds < 0);
+
+	# we have actual result, no need for this anymore
+	@$refCase[$CASE_CHECK_RESULT_LOG_FILE] = 0;
+
+	if(!$optionFinalDoc)
+	{
+		@$refCase[$CASE_RUN_TIMES]++;
+
+		@$refCase[$CASE_RUN_TIME_SECONDS] = $caseRunTimeSeconds;
+
+		if($status eq "CRASHED") {
+			@$refCase[$CASE_CRASHED]++;
+		}
+		elsif($status eq "FAILED") {
+			@$refCase[$CASE_FAILED]++;
+		}
+		elsif($status eq "PASSED") {
+			@$refCase[$CASE_PASSED]++;
+		}
+	}
+	else
+	{
+		if($status eq "PASSED") {
+			@$refCase[$CASE_PASSED] = 1;
+			@$refCase[$CASE_CRASHED] = 0;
+			@$refCase[$CASE_FAILED] = 0;
+		}
+		elsif($status eq "CRASHED" && @$refCase[$CASE_STATUS] ne "PASSED") {
+			@$refCase[$CASE_PASSED] = 0;
+			@$refCase[$CASE_CRASHED] = 1;
+			@$refCase[$CASE_FAILED] = 0;
+		}
+		elsif($status eq "FAILED" && @$refCase[$CASE_STATUS] ne "PASSED" && @$refCase[$CASE_STATUS] ne "CRASHED") {
+			@$refCase[$CASE_PASSED] = 0;
+			@$refCase[$CASE_CRASHED] = 0;
+			@$refCase[$CASE_FAILED] = 1;
+		}
+	}
+
+	my $updateCase = 0;
+
+	if(!$optionGoodIsBetter and !$optionFinalDoc)
+	{
+		# Only update case status if it's more fatal than the current, CRASHED > FAILED > UNKNOWN > PASSED
+		if($status ne "$caseDefaultStatus")
+		{
+			if (@$refCase[$CASE_STATUS] eq "$caseDefaultStatus") {
+				$updateCase = 1;
+			}
+			elsif (@$refCase[$CASE_STATUS] eq "CRASHED" ) {
+
+			}
+			elsif (@$refCase[$CASE_STATUS] eq "FAILED") {
+				$updateCase = 1 if($status eq "CRASHED");
+			}
+			elsif(@$refCase[$CASE_STATUS] eq "PASSED") {
+				$updateCase = 1;
+			}
+		}
+	}
+	else
+	{
+		# Only update case status if it's less fatal than the current, PASSED > FAILED > CRASHED > UNKNOWN
+		if($status ne "$caseDefaultStatus")
+		{
+			if (@$refCase[$CASE_STATUS] eq "$caseDefaultStatus") {
+				$updateCase = 1;
+			}
+			elsif(@$refCase[$CASE_STATUS] eq "UNKNOWN") {
+				$updateCase = 1;
+			}
+			elsif($status eq "PASSED")
+			{
+				$updateCase = 1;
+			}
+			elsif (@$refCase[$CASE_STATUS] eq "CRASHED" ) {
+				$updateCase = 1 if($status eq "FAILED");
+			}
+			elsif (@$refCase[$CASE_STATUS] eq "FAILED") {
+
+			}
+		}
+	}
+
+	if($updateCase)
+	{
+		@$refCase[$CASE_REASON] = $info . $reason;
+		@$refCase[$CASE_RESULT] = $result;
+		@$refCase[$CASE_STATUS] = $status;
+		@$refCase[$CASE_LOG_FILE] = $caseLogFile;
+		@$refCase[$CASE_LOG_FILE_SCRIPTER] = $caseScripterLogFile;
+	}
+	else
+	{
+	    # -1112 overrides other error codes because the case succeeded but verifying has failed.
+	    if(@$refCase[$CASE_RESULT] ne "-1112" and $result eq "-1112")
+	    {
+	        @$refCase[$CASE_RESULT] = $result;
+	    }
+	}
+	#print "case: " . @{$case}[$CASE_NAME] . "\n" . "run: " . @{$case}[$CASE_RUN_TIMES] . ", crash: " . @{$case}[$CASE_CRASHED] . ", fail " . @{$case}[$CASE_FAILED] . ", passed: " . 	@{$case}[$CASE_PASSED] . "\n";
+}
+
+sub CountCaseRunTime
+{
+	my ($line) = @_;
+	my $found = 0;
+	RemoveWhiteSpaces(\$line);
+	#StartTime: 16:12:10,2440, EndTime: 16:12:34,3880
+	#StartTime: 12:02:49.9302 pm, EndTime: 12:03:04.5781 pm
+	if($line =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*$/i)
+	{
+		$found = 1;
+	}
+	elsif($line =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*$/i)
+	{
+		$found = 1;
+	}
+
+    my $caseRunTime = 0;
+
+	if($found)
+	{
+		my $startSeconds = ($1 * 60 * 60) + $2 * 60 + $3;
+		my $endSeconds = ($4 * 60 * 60) + $5 * 60 + $6;
+
+		$caseRunTime = $endSeconds - $startSeconds;
+	}
+	$caseRunTime = 0 if($caseRunTime < 0);
+
+    $totalExecutionTime += $caseRunTime;
+	return $caseRunTime;
+}
+
+sub GetFileNameForCaseLog
+{
+    my ($line1, $line2, $line3, $extra) = @_;
+
+	RemoveWhiteSpaces(\$line1);
+	RemoveWhiteSpaces(\$line2);
+	RemoveWhiteSpaces(\$line3);
+
+	my $caseId = "";
+
+	if($line1 =~ m/\[[0-9]+\][ ]+Title:\[([a-z0-9]+)$regexpCaseName\]$/i)
+	{
+		#"' ultraedit
+		$caseId = $1;
+	}
+
+	my $caseTimeStr = "";
+
+	#StartTime: 16:12:10,2440, EndTime: 16:12:34,3880
+	if($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*$/i)
+	{
+		$found = 1;
+	}
+	elsif($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*$/i)
+	{
+		$found = 1;
+	}
+
+	if( $found )
+	{
+		$caseTimeStr = $1 . $2 . $3 . $4 . $5 . $6;
+	}
+
+	my $fileext = ".txt";
+	$fileext = ".html" if($optionHtml);
+
+    my $caseLogFile;
+    
+     if( !defined( $extra ) )
+     {
+        $caseLogFile = $caseLogOutDir . $caseId . "_" . $caseTimeStr . $fileext;
+    }
+    else
+    {
+        $caseLogFile = $caseLogOutDir . $caseId . "_" . $caseTimeStr . $extra . $fileext;
+    }
+
+	print(" - Case log file: " . $caseLogFile ."\n") if($optionShowMessages);
+	return $caseLogFile;
+}
+
+#------------------------------------------------------------------------------------
+# WriteCaseLog
+#
+# Parameters:
+# 	$caseLogFile: filename to write
+# 	$refLogLines: input where log lines are stored
+# 	$caseDesc: optional text description of case which will be written into the log file
+# 	$line1: [testscripter_iptvservicemanagementapitestasync][c:\TestFramework\IptvServiceManagementApiTestAsync.cfg][2] Title:[ET08203 Add valid hardcoded service_0 ASYNC]
+# 	$line2:	StartTime: 3:06:14.2212 PM, EndTime: 3:06:18.1037 PM
+# 	$line3:	Result: 0 [] ==> PASSED
+#
+# Writes case specific log file into testcase_logs/testcase_logs directory. Reads the lines from @caseLogLines array
+#------------------------------------------------------------------------------------
+sub WriteCaseLog
+{
+#[testscripter_iptvservicemanagementapitestasync][c:\TestFramework\IptvServiceManagementApiTestAsync.cfg][2] Title:[ET08203 Add valid hardcoded service_0 ASYNC]
+#	StartTime: 3:06:14.2212 PM, EndTime: 3:06:18.1037 PM
+#	StartTime: 12:34:41.5407, EndTime: 12:34:41.9687
+#	Result: 0 [] ==> PASSED
+
+	my ($caseLogFile, $refLogLines, $refCaseDesc, $line1, $line2, $line3) = @_;
+
+	# Don't generate log files if we only print summary
+	if($optionPrintCfgSummaries)
+	{
+		return;
+	}
+
+	#print("1: $line1");	print("2: $line2");	print("3: $line3");
+
+	RemoveWhiteSpaces(\$line1);
+	RemoveWhiteSpaces(\$line2);
+	RemoveWhiteSpaces(\$line3);
+
+	my $lineBreak = "\n";
+	$lineBreak = "<br>\n" if($optionHtml);
+
+	my $caseId = "";
+
+	if($line1 =~ m/\[[0-9]+\][ ]+Title:\[([a-z0-9]+)$regexpCaseName\]$/i)
+	{
+		#"' ultraedit
+		$caseId = $1;
+		print("Writing log for: $caseId.\n") if($optionShowMessages);
+	}
+
+	# Write header for case
+
+	my @writeArray;
+
+	# split the first line
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+	push @writeArray, ( substr($line1, 0, index($line1, "Title:")) . $lineBreak );
+	push @writeArray, ( substr($line1, index($line1, "Title:")) . $lineBreak );
+	my $title = substr($line1, index($line1, "Title:"));
+
+	#($line1 . "\n");
+	push @writeArray, ($line2 . $lineBreak);
+	push @writeArray, ($line3 . $lineBreak);
+	push @writeArray, ("\n");
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+
+	# Include the script for the case in the file?
+
+	if($optionCaseIncludedInLog)
+	{
+		foreach $linexxx (@{$refCaseDesc})
+		{
+			push @writeArray, ("$linexxx");
+			push @writeArray, ($lineBreak) if($optionHtml);
+		}
+		push @writeArray, ( "<hr>" ) if($optionHtml);
+		push @writeArray, ("\n");
+	}
+
+	my $passed = 0;
+	$passed = 1 if($line3 =~ m/==> PASSED/);
+
+	# Get the log for the case
+
+	my $startLine = 0;
+	my $endLine = 0;
+
+	my $logLineCount = scalar(@$refLogLines);
+
+	if($logLineCount > 0 && ($optionLogAllCases || !$passed) )
+	{
+		if($lastCaseLogLine >= $logLineCount)
+		{
+			$lastCaseLogLine = 0;
+		}
+
+		# Get the start and end time for the case
+
+		my $found = 0;
+		#StartTime: 16:12:10,2440, EndTime: 16:12:34,3880
+		if($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*$/i)
+		{
+			$found = 1;
+		}
+		elsif($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*$/i)
+		{
+			$found = 1;
+		}
+		else
+		{
+			print(" *ERROR* Could not parse case run time for case $caseId.  Can not write case log note. Returning.\n");
+			return;
+		}
+
+		my $startSeconds = 0;
+		my $endSeconds = 0;
+
+		if($found)
+		{
+			$startSeconds = ($1 * 60 * 60) + $2 * 60 + $3;
+			$endSeconds = ($4 * 60 * 60) + $5 * 60 + $6;
+
+			my $caseRunTime = $endSeconds - $startSeconds;
+
+			if($caseRunTime < 0)
+			{
+				# It's possible to code solution but it'd slow down the script.
+				print(" *ERROR* Case $caseId has probably passed midnight/midday. Giving up writing case specific log.\n");
+				return;
+			}
+
+			#print " - start:"  . $1 . ":" . $2 . ":" . $3 . " = " . $startSeconds . "\n";
+			#print " - end: " . $4 . ":" . $5 . ":" . $6 . " = " . $endSeconds . "\n";
+		}
+
+		# Find indexes for start and end lines
+
+		$startLine = -1;
+		# If the line at $lastCaseLogLine matches then find backwards the first matching line,
+		# otherwise some lines might be missed from the log note.
+		if(LogLineTimeMatchesForCase(\@$refLogLines[$lastCaseLogLine], $startSeconds, $startSeconds))
+		{
+			#print("find back\n");
+			for(my $i=$lastCaseLogLine; $i > 0; $i--)
+			{
+				if(!LogLineTimeMatchesForCase(\@$refLogLines[$i], $startSeconds, $startSeconds))
+				{
+					$startLine = $i+1;
+					last;
+				}
+			}
+		}
+		# Otherwise try to find match forward.
+		else
+		{
+			$startLine = FindLogLineMatch($refLogLines, $startSeconds, $endSeconds, $lastCaseLogLine, 1);
+		}
+		# If that doesn't succeed then lets go at start of the log. SLOW for huge logs.
+		if($startLine == -1)
+		{
+			$startLine = FindLogLineMatch($refLogLines, $startSeconds, $endSeconds, 0, 1);
+			$lastCaseLogLine = 0;
+		}
+		if($startLine == -1)
+		{
+			print(" *ERROR* startLine not found!\n");
+			return;
+		}
+
+		print(" - StartLine: $startLine\n") if($optionShowMessages);
+
+		# Find forward the last line which does not match.
+		$endLine = FindLogLineMatch($refLogLines, $startSeconds, $endSeconds, $startLine+1, 0);
+
+		if($endLine == -1 || $endLine < $startLine)
+		{
+		    print(" - End line not found, trying alternative method.\n") if($optionShowMessages);
+			# Find first not matching line forward from the case start.
+			$endLine = FindLogLineMatch($refLogLines, $startSeconds, $endSeconds, scalar(@$refLogLines)-1, 0);
+			if( $endLine == -1 || $endLine < $startLine )
+			{
+				# Just take the rest of the log
+				$endLine = scalar(@$refLogLines)-1;
+			}
+		}
+
+		print(" - EndLine: $endLine\n") if($optionShowMessages);
+
+		$lastCaseLogLine = $endLine-1;
+	}
+
+	# Create log directory
+
+	if ( !(-e "testcase_logs") )
+	{
+  		mkdir("testcase_logs");
+	}
+
+	if ( !(-e "$caseLogOutDir") )
+	{
+		mkdir($caseLogOutDir, 0755);
+	}
+
+	# Write the log file
+
+	my $fileMode = ">>";
+
+	print(" - Case log file: " . $caseLogFile ."\n") if($optionShowMessages);
+
+	if(	open(FILE_HANDLE, $fileMode . $caseLogFile) )
+	{
+		if($optionHtml)
+		{
+			print FILE_HANDLE (
+			"<html>\n" .
+			"<head>\n" .
+			"<title>$title</title>\n" .
+			"</head>\n" .
+			"<body>\n" .
+			"<basefont color=\"black\" face=\"arial\" size=\"4\">\n"
+			);
+		}
+
+		foreach $line(@writeArray)
+		{
+			print FILE_HANDLE ($line);
+		}
+
+		for(my $i=$startLine;$i<$endLine;$i++)
+		{
+			my $line = @$refLogLines[$i];
+			FormatLogLine(\$line) if($optionHtml);
+
+			print FILE_HANDLE ($line);
+		}
+
+		if($optionHtml)
+		{
+		print FILE_HANDLE (
+			"</body>\n" .
+			"</html>"
+			);
+		}
+
+        print FILE_HANDLE ( $lineBreak );
+		print FILE_HANDLE ( $lineBreak );
+
+		close FILE_HANDLE;
+
+	} else
+	{
+		print("ERROR: Could not write to file: " . $caseLogFile . "\n");
+	}
+}
+
+# There's case start entry in the log, write case log from there onwards.
+sub WriteCaseLogFromEntry
+{
+ 	my ($caseLogFile, $refLogLines, $caseEntryLogStartLine, $line1, $line2, $line3) = @_;
+
+	# Don't generate log files if we only print summary
+	if($optionPrintCfgSummaries)
+	{
+		return 0;
+	}
+
+	RemoveWhiteSpaces(\$line1);
+	RemoveWhiteSpaces(\$line2);
+	RemoveWhiteSpaces(\$line3);
+
+	my $lineBreak = "\n";
+	$lineBreak = "<br>\n" if($optionHtml);
+
+	my $caseId = "";
+
+	if($line1 =~ m/\[[0-9]+\][ ]+Title:\[([a-z0-9]+)$regexpCaseName\]$/i)
+	{
+		#"' ultraedit
+		$caseId = $1;
+	}
+
+	# Write header for case
+
+	my @writeArray;
+
+	# split the first line
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+	push @writeArray, ( substr($line1, 0, index($line1, "Title:")) . $lineBreak );
+	push @writeArray, ( substr($line1, index($line1, "Title:")) . $lineBreak );
+	my $title = substr($line1, index($line1, "Title:"));
+
+	#($line1 . "\n");
+	push @writeArray, ($line2 . $lineBreak);
+	push @writeArray, ($line3 . $lineBreak);
+	push @writeArray, ("\n");
+	push @writeArray, ( "<hr>" ) if($optionHtml);
+
+	my $passed = 0;
+	$passed = 1 if($line3 =~ m/==> PASSED/);
+
+	# Get the log for the case
+
+	my $logLineCount = scalar(@$refLogLines);
+
+	if($logLineCount > 0 && ($optionLogAllCases || !$passed) )
+	{
+		# Get the start and end time for the case
+
+		my $found = 0;
+		#StartTime: 16:12:10,2440, EndTime: 16:12:34,3880
+		if($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\,[0-9]*$/i)
+		{
+			$found = 1;
+		}
+		elsif($line2 =~ m/^StartTime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*, Endtime: ([0-9]+):([0-9]+):([0-9]+)\.[0-9]*[ A-Z]*$/i)
+		{
+			$found = 1;
+		}
+		else
+		{
+			print(" *ERROR* Could not parse case run time for case $caseId.  Can not write case log note. Returning.\n");
+			return 0;
+		}
+
+		my $startSeconds = 0;
+		my $endSeconds = 0;
+
+		if($found)
+		{
+			$startSeconds = ($1 * 60 * 60) + $2 * 60 + $3;
+			$endSeconds = ($4 * 60 * 60) + $5 * 60 + $6;
+
+			my $caseRunTime = $endSeconds - $startSeconds;
+
+			if($caseRunTime < 0)
+			{
+				# It's possible to code solution but it'd slow down the script.
+				#print(" *ERROR* Case has probably passed midnight/midday. Giving up writing case specific log.\n");
+				#return;
+			}
+		}
+	}
+
+	# Create log directory
+
+	if ( !(-e "testcase_logs") )
+	{
+  		mkdir("testcase_logs");
+	}
+
+	if ( !(-e "$caseLogOutDir") )
+	{
+		mkdir($caseLogOutDir, 0755);
+	}
+
+	# Write the log file
+
+	my $fileMode = ">>";
+
+	print(" - Case log file: " . $caseLogFile ."\n") if($optionShowMessages);
+
+    my $caseEntryLogEndLine = -1;
+    for(my $i=$caseEntryLogStartLine; $i<scalar(@$refLogLines); $i++ )
+    {
+        if(@$refLogLines[$i] =~ m/<<< Case end/i)
+        {
+            $caseEntryLogEndLine = $i;
+            last;
+        }
+    }
+    if( $caseEntryLogEndLine == -1 )
+    {
+        print("ERROR: $caseId is missing case end command in the script?\n");
+        return 0;
+    }
+
+	if(	open(FILE_HANDLE, $fileMode . $caseLogFile) )
+	{
+		if($optionHtml)
+		{
+			print FILE_HANDLE (
+			"<html>\n" .
+			"<head>\n" .
+			"<title>$title</title>\n" .
+			"</head>\n" .
+			"<body>\n" .
+			"<basefont color=\"black\" face=\"arial\" size=\"4\">\n"
+			);
+		}
+
+		for( my $i = $caseEntryLogStartLine; $i < $caseEntryLogEndLine; $i++ )
+		{
+            my $line = @$refLogLines[$i];
+            FormatLogLine(\$line) if($optionHtml);
+            print FILE_HANDLE ($line);
+		}
+
+		if($optionHtml)
+		{
+		    print FILE_HANDLE (
+			    "</body>\n" .
+			    "</html>"
+			    );
+		}
+        print FILE_HANDLE ( $lineBreak );
+		print FILE_HANDLE ( $lineBreak );
+
+		close FILE_HANDLE;
+
+	} else
+	{
+		print("ERROR: Could not write to file: " . $caseLogFile . "\n");
+		return 0;
+	}
+	
+	return 1;
+}
+
+#------------------------------------------------------------------------------------
+# FindLogLineMatchRecurse
+#
+# Parameters:
+# 	$startsSeconds		the min time the log line will match
+# 	$endSeconds			the max time the log line will match
+# 	$refStartLine		index of line to start searching
+# 	$refLogLines		reference to array of the log
+# 	$boolOp				1 = first line with match is returned, 0 = first line with no match is returned
+# 	$inc				increment in the search loop
+#	$recurse			can the function call itself, if yes this will be passed to the new call too
+#	$maxLine			the last line to search
+#
+#------------------------------------------------------------------------------------
+sub FindLogLineMatchRecurse
+{
+	my ($startSeconds, $endSeconds, $refStartLine, $refLogLines, $boolOp, $inc, $recurse, $maxLine) = @_;
+
+    print("IN FindLogLineMatchRecurse\n") if($optionDebug);
+	my $spacer = "";
+	for(my $i = 0;$i<$recurse; $i++)
+	{
+		$spacer .= "-";
+	}
+
+	$maxLine = scalar(@$refLogLines) if(!defined($maxLine) or $maxLine > scalar(@$refLogLines));
+	print("s: $startSeconds, e: $endSeconds, sl: $$refStartLine, b: $boolOp, i: $inc, r: $recurse, ml: $maxLine\n") if($optionDebug);
+	print("$spacer ENTER: range: $$refStartLine - $maxLine, $inc\n") if($optionDebug);
+	print("$spacer rec: $recurse\n") if($optionDebug);
+	print("$spacer prev: $$refStartLine\n") if($optionDebug);
+	print("$spacer inc: $inc\n") if($optionDebug);
+
+	# First try to find the start line without recursion.
+	for(my $i = $$refStartLine; $i < $maxLine; $i += $inc)
+	{
+		if(LogLineTimeMatchesForCase(\@$refLogLines[$i], $startSeconds, $endSeconds) == $boolOp)
+		{
+			# We have exact match.
+			if($inc == 1)
+			{
+				$$refStartLine = $i;
+			}
+			# Not exatch match. Return start of previous block.
+			elsif($i >= $$refStartLine + $inc)
+			{
+				$$refStartLine = $i - $inc;
+			}
+
+			print("MATCH LINE: $i: " . @$refLogLines[$i] . "\n") if($optionDebug);
+			print("return line: " . $$refStartLine . "\n") if($optionDebug);
+			print("EXIT FindLogLineMatchRecurse. return 1\n") if($optionDebug);
+			return 1;
+		}
+	}
+
+	if($recurse && $inc > 500)
+	{
+		# Split the current search block to smaller blocks and do search to them
+		for(my $i = $$refStartLine; $i < $maxLine; $i += $inc)
+		{
+			print("$spacer $i\n") if($inc != 1 && $optionDebug);
+			print("...RECURSING!\n") if($optionDebug);
+
+			# Start search from the start of current block.
+			my $prevPos = $i;
+
+			# New last line to search
+			my $end = $i + $inc;
+			$end = scalar(@$refLogLines)-1 if($end > scalar(@$refLogLines)-1);
+
+			# New increment, twice smaller than now
+			my $newInc = int($inc / 2 + 0.5);
+			$newInc = 200 if($newInc < 200);
+
+			if(FindLogLineMatchRecurse($startSeconds, $endSeconds, \$prevPos, $refLogLines, $boolOp, $newInc, $recurse-1, $end) == 1)
+			{
+				$$refStartLine = $prevPos;
+				print("EXIT FindLogLineMatchRecurse. return 1\n") if($optionDebug);
+				return 1;
+			}
+		}
+	}
+
+	print("EXIT FindLogLineMatchRecurse. return 0\n") if($optionDebug);
+	return 0;
+}
+
+#------------------------------------------------------------------------------------
+# FindLogLineMatch
+#
+# Searches for log line with time between the startSeconds and endSeconds.
+#
+# Parameters:
+# 	$refLogLines		reference to array of the log
+# 	$startsSeconds		the min time the log line will match
+# 	$endSeconds			the max time the log line will match
+# 	$startLine			index of line to start searching
+# 	$boolOp				1 = first line with match is returned, 0 = first line with no match is returned
+#------------------------------------------------------------------------------------
+sub FindLogLineMatch
+{
+	my ($refLogLines, $startSeconds, $endSeconds, $startLine, $boolOp) = @_;
+    print("IN FindLogLineMatch\n") if($optionDebug);
+	my $prevPos = $startLine;
+
+	#print("\n\nSTART: $startLine, boolop: $boolOp \n");
+
+	my $match = 0;
+	$match = FindLogLineMatchRecurse($startSeconds, $endSeconds, \$prevPos, $refLogLines, $boolOp, 6000, 5);
+	$prevPos = 0 if(!$match);
+	# Refine the search to be exact line
+	$match = FindLogLineMatchRecurse($startSeconds, $endSeconds, \$prevPos, $refLogLines, $boolOp, 1, 0);
+
+    print("EXIT FindLogLineMatch\n") if($optionDebug);
+	# Not found.
+	return -1 if(!$match);
+
+	return $prevPos;
+}
+
+#------------------------------------------------------------------------------------
+# JustFormatLogFile
+#
+# Parameters:
+#	$fileName
+#------------------------------------------------------------------------------------
+sub JustFormatLogFile
+{
+	my ($fileName) = @_;
+
+	if( !open(FILE_HANDLE, $fileName) )
+	{
+		die("ERROR! Could not open file '" . $fileName . "'\n");
+	}
+	my @array = <FILE_HANDLE>;
+	close(FILE_HANDLE);
+
+	$fileName = substr($fileName, 0, index($fileName, ".txt")) . ".html";
+
+	if(	open(FILE_HANDLE, ">" . $fileName) )
+	{
+
+		print FILE_HANDLE (
+		"<html>\n" .
+		"<head>\n" .
+		"<title>$fileName</title>\n" .
+		"</head>\n" .
+		"<body>\n" .
+		"<basefont color=\"black\" face=\"arial\" size=\"4\">\n"
+		);
+
+
+		my $i;
+		for($i = 0;$i<scalar(@array); $i++)
+		{
+			my $line = $array[$i];
+			$line =~ s/\t/ /; #remove tabs
+			FormatLogLine(\$line);
+
+			print FILE_HANDLE ($line);
+		}
+
+		print FILE_HANDLE (
+		"</body>\n" .
+		"</html>"
+		);
+
+		close FILE_HANDLE;
+	} else
+	{
+		print("ERROR: Could not write to file: " . $fileName . "\n");
+	}
+
+}
+
+#------------------------------------------------------------------------------------
+# LogLineTimeMatchesForCase
+#
+# Parameters:
+#	$refLine
+#	$startSeconds
+#	$endSeconds
+#------------------------------------------------------------------------------------
+sub LogLineTimeMatchesForCase
+{
+	my ($refLine, $startSeconds, $endSeconds) = @_;
+
+	return 0 if(!defined($$refLine));
+
+	$$refLine =~ s/\t/ /; #remove tabs
+
+	#print($$refLine . "\n");
+	#print(" - $startSeconds, $endSeconds\n");
+
+	if(${$refLine} =~ m/[0-9\/]+ ([0-9]+):([0-9]+):([0-9]+)/i)
+	{
+#			print("YES " . $1 . "\n");
+
+		my $currSeconds = $1 * 60 * 60 + $2 * 60 + $3;
+		#print(" - curr: $currSeconds\n");
+
+		#print("curr: $currSeconds, start: $startSeconds, end: $endSeconds\n");
+
+		if($currSeconds >= $startSeconds and $currSeconds <= $endSeconds)
+		{
+			#print("MATCH curr: " . $1 . ":" . $2 . ":" . $3 . " = " . $currSeconds . "\n");
+			return 1;
+		}
+	}
+	#print("NO MATCH\n");
+	return 0;
+}
+
+#------------------------------------------------------------------------------------
+# FormatLogLine
+# Parameters:
+# 	$line
+#------------------------------------------------------------------------------------
+sub FormatLogLine
+{
+	my ($line) = @_;
+
+#Color
+
+# sisään
+#27/06/2006	9:37:52	>>>*									royalblue #2B60DE
+# pois
+#27/06/2006	9:37:52	<<<*									lightblue #0000FF
+#27/06/2006	9:23:57	* exit
+# destructor
+#27/06/2006	9:23:58	~*										#FF0000
+#27/06/2006	9:23:58	>>>~*
+
+#27/06/2006	9:37:52	CIptv*Test *							GREY #808080
+#27/06/2006	9:37:52	*error/fail								RED #FF0000
+#27/06/2006	9:23:41	CreateServerProcess() 					GREEN #00FF00
+
+#!!	TTestObject::~TTestObject								#800080
+
+my $color = "#000000";
+
+
+if(${$line} =~ m/([0-9\/]+ [0-9]+:[0-9]+:[0-9]+)/i)
+{
+	$date = $1;
+	${$line} = substr(${$line}, length($date));
+
+	$color = "#808080" if(${$line} =~ m/CIptvTest[a-z0-9]+Test/i);
+
+	$color = "#2B60DE" if(${$line} =~ m/^[\t ]*>>>/i);
+	$color = "#2B60DE" if(${$line} =~ m/\(\)$/i);
+	$color = "#2B60DE" if(${$line} =~ m/enter$/i);
+
+	$color = "#0000FF" if(${$line} =~ m/^[\t ]*<<<*/i);
+	$color = "#0000FF" if(${$line} =~ m/ exit$/i);
+
+	$color = "#800080" if(${$line} =~ m/^[\t ]*~/i);
+	$color = "#800080" if(${$line} =~ m/^[\t ]*>>>~/i);
+	$color = "#800080" if(${$line} =~ m/::~/i);
+
+	$color = "#FF0000" if(${$line} =~ m/error|fail/i);
+	
+	$color = "#00AA00" if(${$line} =~ m/passed/i);
+	$color = "#FF0000" if(${$line} =~ m/\*\*\*Testcase[a-z ]+\*\*\*/i);
+	$color = "#00AA00" if(${$line} =~ m/\*\*\*Testcase PASSED+\*\*\*/i);
+	$color = "#0000FF" if(${$line} =~ m/Executing line/i);
+	
+	my $formatStart = "", $formatEnd = "";
+
+	if(${$line} =~ m/Client created semaphore, init/i) { $formatStart = "<b>"; $formatEnd = "</b>"; }
+	if(${$line} =~ m/CIptvEngineServer:: ->Starting server shutdown/i) { $formatStart = "<b>"; $formatEnd = "</b>"; }
+
+	SpecialChars($line);
+
+	$date = "<font color=\"black\" face=\"arial\" size=\"2\">" . $date . "</font>";
+	${$line} = $date . "$formatStart<font color=\"$color\" face=\"arial\" size=\"2\">" . ${$line} . "</font>$formatEnd<br>";
+}
+
+
+#$line = "<font color=\"$color\" face=\"arial\" size=\"2\"> . $line
+
+#$color = "#2B60DE" if($line =~ m/([0-9\/]+ [0-9]+:[0-9]+:[0-9]+) >>>/i)
+
+
+}
+
+sub PrintCfgSummaries
+{
+	my $caseCfgFileName = "";
+	my %cfgCaseCount;
+	my %cfgCaseTotalTime;
+
+	foreach $case(@cases)
+	{
+		$caseCfgFileName = @{$case}[$CASE_CFG_FILE];
+
+		if(!defined($cfgCaseCount{$caseCfgFileName}))
+		{
+			$cfgCaseCount{$caseCfgFileName} = 0;
+			$cfgCaseTotalTime{$caseCfgFileName} = 0;
+		}
+
+		if(defined(@{$case}[$CASE_RUN_TIME_SECONDS]))
+		{
+			$cfgCaseTotalTime{$caseCfgFileName} +=  @{$case}[$CASE_RUN_TIME_SECONDS];
+		}
+
+
+		$cfgCaseCount{$caseCfgFileName}++ if(@{$case}[$CASE_STATUS] ne "$caseDefaultStatus") ;
+	}
+
+	my $totalTime = 0;
+	printf("\n%-50s %10s %10s\n", "CFG", "Case count", "Case run time");
+	foreach $caseCfgFileName (sort keys(%cfgCaseCount))
+	{
+		if($cfgCaseCount{$caseCfgFileName} > 0)
+		{
+			my $mins = ($cfgCaseTotalTime{$caseCfgFileName}/60);
+			$totalTime += $mins;
+			printf("%-50s %10d %10.1f\n", $caseCfgFileName, $cfgCaseCount{$caseCfgFileName}, $mins);
+		}
+	}
+	printf("Total time: %.2f hours\n\n", $totalTime/60 );
+
+	print("No cases run for:\n");
+	foreach $caseCfgFileName (sort keys(%cfgCaseCount))
+	{
+		if($cfgCaseCount{$caseCfgFileName} == 0)
+		{
+			print("$caseCfgFileName\n");
+		}
+	}
+}
+
+#------------------------------------------------------------------------------------
+# WriteOfficeXml
+#
+# Parameters:
+#	$outputFile
+#	$briefSummary
+#
+# Writes the cases into a word formatted xml file.
+#------------------------------------------------------------------------------------
+sub WriteOfficeXml
+{
+	my ($outputFile, $briefSummary) = @_;
+
+	if(	!open(FILE_HANDLE, ">" . $outputFile) )
+	{
+		print("ERROR! Could not open file '" . $outputFile . "'\n");
+		return;
+	}
+
+	my $writeData = $xmlHeader;
+	my $replacement;
+
+	if($briefSummary == 0) {
+		$writeData .= $xmlHeaderTableColumns;
+	}
+	else {
+		$writeData .= $xmlHeaderTableColumnsBrief;
+	}
+
+	$excelRowCount = scalar(@cases) * 9 + 100;
+	$writeData =~ s/$CaseCountMul8/$excelRowCount/;
+
+	print FILE_HANDLE ( $writeData );
+
+	if($briefSummary) {
+		$writeData = $xmlSummaryData;
+
+		$writeData =~ s/$xmlDataSummaryCaseCount/$summaryCaseCount/;
+		$writeData =~ s/$xmlDataSummaryPassed/$summaryPassedCases/;
+		$writeData =~ s/$xmlDataSummaryFailed/$summaryFailedCases/;
+		$writeData =~ s/$xmlDataSummaryCrashed/$summaryCrashedCases/;
+		$writeData =~ s/$xmlDataSummaryTimeout/$summaryTimeoutCases/;
+		$writeData =~ s/$xmlDataSummaryRunRate/$summaryRunRate/;
+		$writeData =~ s/$xmlDataSummaryPassRateTotal/$summaryPassRateTotal/;
+		$writeData =~ s/$xmlDataSummaryPassRateRun/$summaryPassRateRun/;
+
+		print FILE_HANDLE ( $writeData );
+	}
+
+	my $caseCfgFileName = "";
+
+	my %cfgCaseCount;
+
+	# Sort the cases by the config files, cfg's which have no run cases come last
+
+	if(!$optionSortCases)
+	{
+		#print("HASH CREATE\n");
+		#create hash of cfg case counts
+		foreach $case(@cases)
+		{
+			$caseCfgFileName = @{$case}[$CASE_CFG_FILE];
+
+			if(!defined($cfgCaseCount{$caseCfgFileName}))
+			{
+				$cfgCaseCount{$caseCfgFileName} = 0;
+			}
+
+			$cfgCaseCount{$caseCfgFileName}++ if(@{$case}[$CASE_STATUS] ne "$caseDefaultStatus") ;
+		}
+
+		#print("THRU CASES\n");
+
+		foreach $caseCfgFileName (keys(%cfgCaseCount))
+		{
+			# if cfg has zero cases run then it's cases are put back of the array
+			if($cfgCaseCount{$caseCfgFileName} == 0)
+			{
+				#print("ZERO CASES RUN: $caseCfgFileName\n");
+				my @moveCases;
+
+				my $i;
+				for($i=0; $i< scalar(@cases); $i++)
+				{
+					if($cases[$i][$CASE_CFG_FILE] eq $caseCfgFileName)
+					{
+						push @moveCases, splice(@cases, $i, 1);
+						$i--;
+					}
+				}
+
+				push @cases, @moveCases;
+			}
+		}
+	}
+
+	# Write the xml file
+
+	$caseCfgFileName = "";
+
+	foreach $case(@cases)
+	{
+	    if($optionShowMessages || $optionDebug) 
+		{
+			print(" - Case Xml : " . @{$case}[$CASE_NAME]  . ", status: " . @{$case}[$CASE_STATUS] . "\n") if( $optionDebug || @{$case}[$CASE_STATUS] ne "Not planned" );
+		}
+		
+		if($briefSummary == 0)
+		{
+			$writeData = $xmlData;
+			$writeData .= $xmlData2;
+			$writeData .= $xmlDataEmptyRow;
+		}
+		else
+		{
+			$writeData = "";
+
+			# Write cfg file to the brief xml if it has changed for the case
+			if($optionSortCases == 0 && $caseCfgFileName ne @{$case}[$CASE_CFG_FILE])
+			{
+				$caseCfgFileName = @{$case}[$CASE_CFG_FILE];
+
+				$writeData .= $xmlDataEmptyRow;
+				$writeData .= $xmlCfgFileBrief;
+				$writeData .= $xmlDataBriefHeader;
+
+				$replacement = @{$case}[$CASE_CFG_FILE];
+				XmlReadyText(\$replacement);
+				$writeData =~ s/$xmlDataCfgFile/$replacement/;
+			}
+			
+			# Write log file links to xml.
+
+			my $caseHasLog = ( defined(@{$case}[$CASE_LOG_FILE]) and @{$case}[$CASE_LOG_FILE] ne "" );
+			my $caseHasScripterLog = ( defined(@{$case}[$CASE_LOG_FILE_SCRIPTER]) and @{$case}[$CASE_LOG_FILE_SCRIPTER] ne "" );
+			my $caseLogLink1 = "";
+			my $caseLogLink2 = "";
+			
+			if( $caseHasLog && $caseHasScripterLog )
+			{
+			    print("   - Case has both log files\n") if ($optionDebug );
+			    $writeData .= $xmlDataBrief2Links;
+			    $caseLogLink1 = @{$case}[$CASE_LOG_FILE];
+			    $caseLogLink2 = @{$case}[$CASE_LOG_FILE_SCRIPTER];
+			}
+			elsif( $caseHasLog )
+			{
+			    print("   - Case has log file\n") if ($optionDebug );
+			    $writeData .= $xmlDataBrief1Link;
+			    $caseLogLink1 = @{$case}[$CASE_LOG_FILE];
+			}
+			elsif( $caseHasScripterLog )
+			{
+			    print("   - Case has scripter log file\n") if ($optionDebug );
+			    $writeData .= $xmlDataBrief1Link;
+			    $caseLogLink1 = @{$case}[$CASE_LOG_FILE_SCRIPTER];
+		    }
+			else
+			{
+			    print("   - Case has no log files\n") if ($optionDebug );
+			    $writeData .= $xmlDataBriefNoLinks;
+			}
+			
+			if( $caseLogLink1 ne "" )
+			{
+                print("   - Log file 1: $caseLogLink1\n") if ($optionDebug );
+                $replacement = $caseLogLink1;
+				XmlReadyText(\$replacement);
+				
+				#print("wordxml log file 1: $replacement\n";
+
+				#print("repl: " . $replacement . "\n");
+				$replacement = substr($replacement, index($replacement, "\\") + 1);
+				#$replacement = ".\\testcase_logs\\..\\" . $replacement;
+				#print("repl: " . $replacement . "\n");
+
+				$writeData =~ s/$xmlDataCaseLink1/$replacement/;
+			}
+
+			if( $caseLogLink2 ne "" )
+			{
+			    print("   - Log file 2: $caseLogLink2\n") if ($optionDebug );
+                $replacement = $caseLogLink2;
+				XmlReadyText(\$replacement);
+				
+				#print("wordxml log file 2: $replacement\n";
+
+				#print("repl: " . $replacement . "\n");
+				$replacement = substr($replacement, index($replacement, "\\") + 1);
+				#$replacement = ".\\testcase_logs\\..\\" . $replacement;
+				#print("repl: " . $replacement . "\n");
+
+				$writeData =~ s/$xmlDataCaseLink2/$replacement/;
+			}
+			
+			# Write case fail reason to xml.
+			
+			$replacement = @{$case}[$CASE_REASON];
+			XmlReadyText(\$replacement);
+			$writeData =~ s/$xmlDataCaseReason/$replacement/;
+
+            # Write case run time or result to xml.
+
+			if(!$optionCaseRunTimes)
+			{
+				$replacement = @{$case}[$CASE_RESULT];
+			}
+			else
+			{
+				$replacement = @{$case}[$CASE_RUN_TIME_SECONDS];
+			}
+
+			# Write result to xml.
+			
+			XmlReadyText(\$replacement);
+			$writeData =~ s/$xmlDataCaseResult/$replacement/;
+		}
+
+		#$writeData = $xmlData;
+		#if($option_brief_summary == 0) { $writeData .= $xmlData2; }
+		#$writeData .= $xmlDataEmptyRow;
+
+		$replacement = @{$case}[$CASE_NAME];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseName/$replacement/;
+
+		$replacement = @{$case}[$CASE_RUN_TIMES];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseRunTimes/$replacement/;
+
+		$replacement = @{$case}[$CASE_FAILED];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseFailed/$replacement/;
+
+		$replacement = @{$case}[$CASE_CRASHED];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseCrashed/$replacement/;
+
+		$replacement = @{$case}[$CASE_PASSED];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCasePassed/$replacement/;
+
+		$replacement = @{$case}[$CASE_STATUS];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseStatus/$replacement/;
+
+		$replacement = @{$case}[$CASE_PURPOSE];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCasePurpose/$replacement/;
+
+		$replacement = @{$case}[$CASE_MEANS];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseMeans/$replacement/;
+
+		$replacement = @{$case}[$CASE_REQUIRED_SETTINGS];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseRequiredSettings/$replacement/;
+
+		$replacement = @{$case}[$CASE_RELATED_REQUIREMENTS];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseRelatedRequirements/$replacement/;
+
+		$replacement = @{$case}[$CASE_VERIFICATION];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseVerification/$replacement/;
+
+		$replacement = @{$case}[$CASE_NOTE];
+		XmlReadyText(\$replacement);
+		$writeData =~ s/$xmlDataCaseNote/$replacement/;
+
+		if(@{$case}[$CASE_STATUS] eq "UNKNOWN") {
+			$replacement = $STYLE_ID_STATUS_UNKNOWN;
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "CRASHED") {
+			$replacement = $STYLE_ID_STATUS_CRASHED;
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "FAILED") {
+			$replacement = $STYLE_ID_STATUS_FAILED;
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "PASSED") {
+			$replacement = $STYLE_ID_STATUS_PASSED;
+		}
+		else {
+			$replacement = $STYLE_ID_STATUS_NA;
+		}
+
+		$writeData =~ s/$STYLE_ID_STATUS_TAG/$replacement/;
+
+		print FILE_HANDLE ( $writeData );
+	}
+
+	print FILE_HANDLE ( $xmlFooter );
+
+	close(FILE_HANDLE);
+
+	print("Report " . $outputFile . " written.\n");
+}
+
+#------------------------------------------------------------------------------------
+# WriteOfficeXmlAlt
+#
+# Parameters:
+#	$outputFile
+#
+# Writes the cases into a word formatted xml file.
+#------------------------------------------------------------------------------------
+sub WriteOfficeXmlAlt
+{
+	my ($outputFile, $refRuns) = @_;
+
+	CalculateStats();
+
+	if(	!open(FILE_HANDLE, ">" . $outputFile) )
+	{
+		print("ERROR! Could not open file '" . $outputFile . "'\n");
+		return;
+	}
+
+	my $writeData = $xmlHeader;
+	my $replacement;
+
+    $writeData .= $xmlHeaderTableColumnsAlt;
+
+    my $xRefRunInfo = @$refRuns[0];
+    my $xRefCases = @$xRefRunInfo[2];
+    my $caseCount = scalar( @$xRefCases ) + 1000;
+
+	$excelRowCount = $caseCount * 9 + 100;
+	$writeData =~ s/$CaseCountMul8/$excelRowCount/;
+
+	print FILE_HANDLE ( $writeData );
+
+	my $caseCfgFileName = "";
+
+	my %cfgCaseCount;
+
+	# Sort the cases by the config files, cfg's which have no run cases come last
+
+	if(!$optionSortCases)
+	{
+		#print("HASH CREATE\n");
+		#create hash of cfg case counts
+		foreach $case(@cases)
+		{
+			$caseCfgFileName = @{$case}[$CASE_CFG_FILE];
+
+			if(!defined($cfgCaseCount{$caseCfgFileName}))
+			{
+				$cfgCaseCount{$caseCfgFileName} = 0;
+			}
+
+			$cfgCaseCount{$caseCfgFileName}++ if(@{$case}[$CASE_STATUS] ne "$caseDefaultStatus") ;
+		}
+
+		#print("THRU CASES\n");
+
+		foreach $caseCfgFileName (keys(%cfgCaseCount))
+		{
+			# if cfg has zero cases run then it's cases are put back of the array
+			if($cfgCaseCount{$caseCfgFileName} == 0)
+			{
+				#print("ZERO CASES RUN: $caseCfgFileName\n");
+				my @moveCases;
+
+				my $i;
+				for($i=0; $i< scalar(@cases); $i++)
+				{
+					if($cases[$i][$CASE_CFG_FILE] eq $caseCfgFileName)
+					{
+						push @moveCases, splice(@cases, $i, 1);
+						$i--;
+					}
+				}
+
+				push @cases, @moveCases;
+			}
+		}
+	}
+
+    my @sortedRuns;
+
+    #Monday 25th August 2008
+    while( 1 )
+    {
+        my $maxTotal = 0;
+        my $refWinner;
+        for( my $i=0; $i<scalar(@$refRuns); $i++ )
+        {
+            my $refRunInfo = @$refRuns[$i];
+            my $date = @$refRunInfo[1];
+            my @parts = split(" ", $date);
+            my $total = 0 + $parts[1];
+
+            if( $parts[2] eq "Jan" )
+            {
+                $total += 1 * 30;
+            }
+            elsif( $parts[2] eq "Feb" )
+            {
+                $total += 2 * 30;
+            }
+            elsif( $parts[2] eq "Mar" )
+            {
+                $total += 3 * 30;
+            }
+            elsif( $parts[2] eq "Apr" )
+            {
+                $total += 4 * 30;
+            }
+            elsif( $parts[2] eq "May" )
+            {
+                $total += 5 * 30;
+            }
+            elsif( $parts[2] eq "Jun" )
+            {
+                $total += 6 * 30;
+            }
+            elsif( $parts[2] eq "Jul" )
+            {
+                $total += 7 * 30;
+            }
+            elsif( $parts[2] eq "Aug" )
+            {
+                $total += 8 * 30;
+            }
+            elsif( $parts[2] eq "Sep" )
+            {
+                $total += 9 * 30;
+            }
+            elsif( $parts[2] eq "Oct" )
+            {
+                $total += 10 * 30;
+            }
+            elsif( $parts[2] eq "Nov" )
+            {
+                $total += 11 * 30;
+            }
+            elsif( $parts[2] eq "Dec" )
+            {
+                $total += 12 * 30;
+            }
+
+            if( $maxTotal < $total )
+            {
+                my $foundAlready = 0;
+                foreach my $xrun ( @sortedRuns )
+                {
+                    if( $xrun == @$refRuns[$i] )
+                    {
+                        $foundAlready = 1;
+                    }
+
+                }
+
+                if( !$foundAlready )
+                {
+                    $maxTotal = $total;
+                    $winner = @$refRuns[$i];
+                }
+            }
+        }
+        push @sortedRuns, $winner;
+        if( scalar(@sortedRuns) == scalar(@$refRuns) )
+        {
+            last;
+        }
+    }
+
+    foreach $run ( @sortedRuns )
+    {
+        #print("sorted: " . @$run[1] . "\n");
+    }
+    foreach $run ( @$refRuns )
+    {
+        #print("orig: " . @$run[1] . "\n");
+    }
+
+    my $refMainRunInfo = $sortedRuns[0];
+    my $refMainCases = @$refMainRunInfo[2];
+
+	$caseCfgFileName = "";
+    $replacement = "";
+
+    # This prints only cases which are in first run. Build list of cases in all runs and use that.
+    foreach $mainCase ( @$refMainCases )
+    {
+        $writeData = "";
+
+        # Status of the current case in different runs
+        my @statuses;
+        my @results;
+        for( my $i = 0; $i<100; $i++ )
+        {
+            $statuses[$i] = "UNKNOWN";
+            $results[$i] = "";
+        }
+
+        for( my $i = 0; $i<scalar( @sortedRuns ); $i++ )
+        {
+            my $refRunInfo = $sortedRuns[$i];
+
+            my $refCases = @$refRunInfo[2];
+
+            foreach $case ( @$refCases )
+            {
+                if( @$case[$CASE_ID] eq @$mainCase[$CASE_ID] )
+                {
+                    $statuses[$i] = @$case[$CASE_STATUS];
+                    $results[$i] = @$case[$CASE_RESULT];
+                }
+            }
+        }
+
+		# If cfg changes, write xml header for it
+		if($caseCfgFileName ne @$mainCase[$CASE_CFG_FILE])
+		{
+			$caseCfgFileName = @$mainCase[$CASE_CFG_FILE];
+
+			$writeData .= $xmlDataEmptyRow;
+			$writeData .= $xmlCfgFileBrief;
+			$writeData .= $xmlCfgFileAltHeader;
+
+			$replacement = @$mainCase[$CASE_CFG_FILE];
+			XmlReadyText(\$replacement);
+			$writeData =~ s/$xmlDataCfgFile/$replacement/;
+
+
+            for( $i = 0; $i<$ALT_RESULTCOUNT; $i++ )
+            {
+                $replacement = "";
+                if( defined( $sortedRuns[$i] ) )
+                {
+                    $refRunInfo = $sortedRuns[$i];
+                    $replacement = @$refRunInfo[1];
+                }
+                my $field = $xmlDataAltDateX . ($i+1);
+                $writeData =~ s/$field/$replacement/;
+            }
+		}
+
+        # Write xml for X cases
+
+        $writeData .= $xmlCfgFileAltData;
+
+	    $replacement = @$mainCase[$CASE_NAME];
+	    XmlReadyText(\$replacement);
+	    $writeData =~ s/$xmlDataCaseName/$replacement/;
+
+        # Replace the X fields for runs
+        for( my $i = 0; $i<$ALT_RESULTCOUNT; $i++ )
+        {
+            $replacement = $statuses[$i];
+            $replacement = $results[$i];
+            my $field = $xmlDataAltResultX . ($i+1);
+            $writeData =~ s/$field/$replacement/;
+
+    		$replacement = $STYLE_ID_STATUS_NA_CENTERED;
+    		if($statuses[$i] eq "CRASHED") {
+    			$replacement = $STYLE_ID_STATUS_CRASHED_CENTERED;
+    		}
+    		elsif($statuses[$i] eq "FAILED") {
+    			$replacement = $STYLE_ID_STATUS_FAILED_CENTERED;
+    		}
+    		elsif($statuses[$i] eq "PASSED") {
+    			$replacement = $STYLE_ID_STATUS_PASSED_CENTERED;
+    		}
+    		else {
+    			$replacement = $STYLE_ID_STATUS_NA_CENTERED;
+    		}
+
+    		$writeData =~ s/$STYLE_ID_STATUS_TAG/$replacement/;
+        }
+        print FILE_HANDLE ( $writeData );
+    }
+
+	print FILE_HANDLE ( $xmlFooter );
+	close(FILE_HANDLE);
+	print("Alternative report " . $outputFile . " written.\n");
+	return;
+}
+
+#------------------------------------------------------------------------------------
+# WriteTDToolResultFile
+#
+# Parameters:
+#	$outputFile
+#
+# Writes the cases into TDTool formatted file which can be exported into Quality Center
+#------------------------------------------------------------------------------------
+sub WriteTDToolResultFile
+{
+	my ($outputFile) = @_;
+
+	if(	!open(FILE_HANDLE, ">" . $outputFile) )
+	{
+		print("ERROR! Could not open file '" . $outputFile . "'\n");
+		return;
+	}
+
+	my $writeData;
+	my $replacement;
+
+	my %cfgCaseCount;
+
+	# sort the cases by the config files, cfg's which have no run cases come last
+	if(!$optionSortCases)
+	{
+		foreach $case(@cases)
+		{
+			$caseCfgFileName = @{$case}[$CASE_CFG_FILE];
+
+			if(!defined($cfgCaseCount{$caseCfgFileName}))
+			{
+				$cfgCaseCount{$caseCfgFileName} = 0;
+			}
+
+			$cfgCaseCount{$caseCfgFileName}++ if(@{$case}[$CASE_STATUS] ne "$caseDefaultStatus") ;
+		}
+
+		#print("THRU CASES\n");
+
+		foreach $caseCfgFileName (keys(%cfgCaseCount))
+		{
+			# if cfg has zero cases run then it's cases are put back of the array
+			if($cfgCaseCount{$caseCfgFileName} == 0)
+			{
+				#print("ZERO CASES RUN: $caseCfgFileName\n");
+				my @moveCases;
+
+				my $i;
+				for($i=0; $i< scalar(@cases); $i++)
+				{
+					if($cases[$i][$CASE_CFG_FILE] eq $caseCfgFileName)
+					{
+						push @moveCases, splice(@cases, $i, 1);
+						$i--;
+					}
+				}
+
+				push @cases, @moveCases;
+			}
+		}
+	}
+
+#test_set_name_here
+#[1]APES PTSW_WBA_TS -1.1. - Server Version - (01) - COMM_SERVER_VERSION_GET_REQ
+#Passed&Actual result:  Info: 0
+
+	print FILE_HANDLE ( "IPTV_Engine test set\n" );
+
+	foreach $case(@cases)
+	{
+		$writeData = "[1]";
+
+		my $caseName = @{$case}[$CASE_NAME];
+		$writeData .= $caseName;
+
+		$writeData .= "\n";
+
+		my $result;
+
+		if(@{$case}[$CASE_STATUS] eq "UNKNOWN") {
+			$result = "N/A";
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "CRASHED") {
+			$result = "Failed";
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "FAILED") {
+			$result = "Failed";
+		}
+		elsif(@{$case}[$CASE_STATUS] eq "PASSED") {
+			$result = "Passed";
+		}
+		else {
+			$result = "No Run";
+		}
+
+		$writeData .= $result;
+
+
+
+		my $comments = "&Info";
+
+		#$comments = "CFG file: @{$case}[$CASE_CFG_FILE];
+
+		#$comments .= "Actual result = " . @{$case}[$CASE_RESULT] . ", Info = " . @{$case}[$CASE_REASON];
+
+		$writeData .= $comments;
+
+		$writeData .= "\n";
+
+		# Replace bad characters for QC
+		$writeData =~ s/\\/-/g;
+		$writeData =~ s/\//-/g;
+		$writeData =~ s/:/-/g;
+		$writeData =~ s/\"/-/g;
+		$writeData =~ s/\?/-/g;
+		$writeData =~ s/\'/-/g;
+		$writeData =~ s/\|/-/g;
+		$writeData =~ s/\*/-/g;
+		$writeData =~ s/\%/-/g;
+		$writeData =~ s/ä/a/g;
+		$writeData =~ s/ö/o/g;
+		$writeData =~ s/\å/a/g;
+		$writeData =~ s/</(/g;
+		$writeData =~ s/>/)/g;
+
+		if($result eq "Passed" or $result eq "Failed")
+		{
+			print FILE_HANDLE ( $writeData );
+		}
+	}
+
+	close(FILE_HANDLE);
+
+	print("Report " . $outputFile . " written.\n");
+}
+
+
+#------------------------------------------------------------------------------------
+# FindCfgFiles
+# Parameters:
+#	$godir, $refFiles
+#
+# Finds cfg files from the the specified directory and it's sub directories.
+#------------------------------------------------------------------------------------
+sub FindCfgFiles
+{
+	my ($godir, $refFiles) = @_;
+	
+    my $startDir = cwd;
+
+	chdir($godir) or die("Could not change dir to $godir");
+	
+	opendir(DIR, ".");
+	my @files = sort(readdir(DIR));
+	closedir(DIR);
+	
+	foreach $file(@files)
+	{
+		if($file eq "." or $file eq "..") {next};
+
+		if (-d $file)
+		{
+		 	FindCfgFiles( $file, $refFiles );
+		} else {
+			if($file =~ m/\.cfg$/i)
+			{
+				next if($file =~ m/livetv/i and $optionNoLiveTvTests);
+
+				next if(
+						($file =~ m/IptvSecurityServicesTest/i or
+						 $file =~ m/IptvRssSecurityTest/i or
+						 $file =~ m/IptvLiveTvSep/i or
+						 $file =~ m/IptvRssDownloadSecurityTest/i)
+
+						 and $optionNoSecurityTests
+						);
+
+				next if($file =~ m/example.cfg/i);
+
+				push @$refFiles, ( cwd . "/" . $file );
+			}
+		}
+	}
+
+	chdir("$startDir") or die("Could not change dir to $startDir");
+}
+
+#------------------------------------------------------------------------------------
+# ParseCfg
+# Parameters:
+#	$file
+#------------------------------------------------------------------------------------
+sub ParseCfg
+{
+	my ($file) = @_;
+
+	my $fileCaseCount = 0;
+
+	if( !open(FILE_HANDLE, $file) )
+	{
+		print("ERROR! Could not open file '" . $file . "'\n");
+		return 0;
+	}
+	my @array = <FILE_HANDLE>;
+	close(FILE_HANDLE);
+
+	my $lineCount = scalar(@array);
+	my $i;
+	my $cfgFileWritten = 0;
+	my $caseDocumentationStart = -1;
+	my $line;
+
+	my @caseDesc; # lines for case desc and case itself
+
+	for($i=0; $i<$lineCount; $i++ ) {
+		$line = $array[$i];
+
+		RemoveWhiteSpaces(\$line);
+
+		#print("           $line\n");
+
+		if($line =~ m/^\#\[IptvETDescription\]/)
+		{
+			$caseDocumentationStart = $i;
+		}
+
+		if($line =~ m/\[Test\]/)
+		{
+			if($caseDocumentationStart >= 0)
+			{
+				ReadCaseAndDescText(\@array, \@caseDesc, $caseDocumentationStart-1)
+			}
+			else
+			{
+				ReadCaseAndDescText(\@array, \@caseDesc, $i);
+			}
+
+			#print("readcase desc: " . scalar(@caseDesc) . "\n");
+		}
+		else
+		{
+		    #print("NOT READ readcase desc: " . scalar(@caseDesc) . "\n");
+		}
+
+	    #test case starts here
+	    if($line =~ m/^title /)
+	    {
+	    	#print("COUNT: " . scalar(@caseDesc) . "\n\n");
+
+			if($caseDocumentationStart >= 0)
+			{
+				#print(">>> Case start: " . $line . "\n");
+				#$i +=
+				ReadCase(\@array, $caseDocumentationStart, $file);
+				$caseDocumentationStart = -1;
+			}
+
+	    	my $caseName = substr($line, length("title "));
+	    	my $caseId = GetCaseIdFromName($caseName);
+
+	    	RemoveWhiteSpaces(\$caseName);
+	    	#SpecialChars(\$caseName);
+
+	    	my $documentationExists = GetCase($caseId, \@cases);
+
+			$caseDesc[0] = $caseName;
+			push @caseDescs, [ @caseDesc ];
+			@caseDesc = (); #new case starts
+
+	    	# create empty array for case
+	    	if(!$documentationExists)
+	    	{
+	    		if($cfgFileWritten == 0)
+	    		{
+	    			$cfgFileWritten = 1;
+	    			push @notDocumentedCases, ("\n\n" . $file .
+"\n************************************************************************************************\n"
+						);
+
+	    		}
+	    		push @notDocumentedCases, ($caseName . "\n");
+
+				#create dummy case
+				my @case;
+				$case[$CASE_NAME] = $caseName;
+
+				$case[$CASE_ID] = $caseId;
+
+				$case[$CASE_RUN_TIMES] = 0;
+				$case[$CASE_CRASHED] = 0;
+				$case[$CASE_FAILED] = 0;
+				$case[$CASE_PASSED] = 0;
+				$case[$CASE_STATUS] = "$caseDefaultStatus";
+				$case[$CASE_PURPOSE] = "N/A";
+				$case[$CASE_MEANS] = "N/A";
+				$case[$CASE_REQUIRED_SETTINGS] = "N/A";
+				$case[$CASE_RELATED_REQUIREMENTS] = "N/A";
+				$case[$CASE_VERIFICATION] = "N/A";
+				$case[$CASE_NOTE] = "N/A";
+				$case[$CASE_REASON] = "";
+				$case[$CASE_RESULT] = "";
+				$case[$CASE_LOG_FILE] = "";
+				$case[$CASE_LOG_FILE_SCRIPTER] = "";
+				$case[$CASE_CHECK_RESULT_LOG_FILE] = 0;
+				$case[$CASE_CFG_FILE] = lc( GetPathFileName($file) );
+				$case[$CASE_RUN_TIME_SECONDS] = 0;
+
+                if( IsCaseInCaseList( $case[$CASE_ID] ) )
+    			{
+        			push @cases, [ @case ];
+    		    }
+	    	}
+
+	    	$fileCaseCount++;
+	    	if($optionShowMessages) { print(" - Case: " . $caseName . "\n"); };
+	    }
+	}
+
+	return $fileCaseCount;
+}
+
+
+#------------------------------------------------------------------------------------
+# ReadCaseAndDescText
+#
+# Parameters:
+#	$lines
+#	$caseInfo
+#	$startIndex
+#------------------------------------------------------------------------------------
+sub ReadCaseAndDescText
+{
+	my ($lines, $caseInfo, $startIndex) = @_;
+	my $lineCount = @{$lines};
+
+	my $readLines = 0;
+	my $i = 0;
+
+	@{$caseInfo}[0] = "N/A";
+
+	for($i=$startIndex; $i<$lineCount; $i++)
+	{
+		my $line = @{$lines}[$i];
+
+		@{$caseInfo}[ scalar(@{$caseInfo}) ] = $line;
+
+		#print($line . "\n");
+
+		if($line =~ m/\[Endtest\]/i)
+		{
+#				push @cases, [ @case ];
+
+			#foreach $xxx (@{$caseInfo})	{		print("XXX: " . $xxx . "");	}
+
+			return $readLines;
+		}
+
+		$readLines++;
+	}
+
+	return $readLines;
+}
+
+#------------------------------------------------------------------------------------
+# ReadCase
+#
+# Parameters:
+#	$lines
+#	$startIndex
+#	$file
+#------------------------------------------------------------------------------------
+sub ReadCase
+{
+	my ($lines, $startIndex, $file) = @_;
+	my $lineCount = @{$lines};
+
+	my $readLines = 0;
+	my $i = 0;
+
+	my $caseName = "";
+	my $casePurpose = "";
+	my $caseMeans = "";
+	my $caseRequiredSettings = "";
+	my $caseRelatedRequirements = "";
+	my $caseVerification = "";
+	my $caseNote = "";
+
+	#this is where text is appended if it's on a line which has no description tag
+	# -> multiline descriptions can be specified
+	my $refAppend = 0;
+
+	for($i=$startIndex; $i<$lineCount; $i++)
+	{
+		my $line = @{$lines}[$i];
+
+		#print($line . "\n");
+
+		RemoveWhiteSpaces(\$line);
+		#$line =~ s/\s+$//; #whitespaces in the end
+		#$line =~ s/^\s+//; #whitespaces at the start
+
+		if($line =~ m/^\#\[EndIptvETDescription\]/)
+		{
+			#print(" ***** End case\n");
+
+			my @case;
+
+			$case[$CASE_NAME] = $caseName;
+			$case[$CASE_ID] = GetCaseIdFromName($caseName);
+
+			$case[$CASE_RUN_TIMES] = 0;
+			$case[$CASE_CRASHED] = 0;
+			$case[$CASE_FAILED] = 0;
+			$case[$CASE_PASSED] = 0;
+			$case[$CASE_STATUS] = "$caseDefaultStatus";
+			$case[$CASE_PURPOSE] = $casePurpose;
+			$case[$CASE_MEANS] = $caseMeans;
+			$case[$CASE_REQUIRED_SETTINGS] = $caseRequiredSettings;
+			$case[$CASE_RELATED_REQUIREMENTS] = $caseRelatedRequirements;
+			$case[$CASE_VERIFICATION] = $caseVerification;
+			$case[$CASE_NOTE] = $caseNote;
+			$case[$CASE_REASON] = "";
+			$case[$CASE_RESULT] = "";
+			$case[$CASE_LOG_FILE] = "";
+			$case[$CASE_LOG_FILE_SCRIPTER] = "";
+			$case[$CASE_CHECK_RESULT_LOG_FILE] = 0;
+			$case[$CASE_CFG_FILE] = $file;
+			$case[$CASE_RUN_TIME_SECONDS] = 0;
+
+            if( IsCaseInCaseList( $case[$CASE_ID] ) )
+			{
+    			push @cases, [ @case ];
+			}
+
+			return $readLines;
+		}
+
+		elsif($line =~ m/^\# Testname:/)
+		{
+			$caseName = substr($line, length("# Testname:"));
+			RemoveWhiteSpaces(\$caseName);
+			#SpecialChars(\$caseName);
+			$refAppend = \$caseName;
+		}
+
+		elsif($line =~ m/^\# Purpose:/)
+		{
+			$casePurpose = substr($line, length("# Purpose:"));
+			RemoveWhiteSpaces(\$casePurpose);
+			#SpecialChars(\$casePurpose);
+			$refAppend = \$casePurpose;
+		}
+
+		elsif($line =~ m/^\# Means:/)
+		{
+			$caseMeans = substr($line, length("# Means:"));
+			RemoveWhiteSpaces(\$caseMeans);
+			#SpecialChars(\$caseMeans);
+			$refAppend = \$caseMeans;
+		}
+
+		elsif($line =~ m/^\# Required environment settings:/)
+		{
+			$caseRequiredSettings = substr($line, length("# Required environment settings:"));
+			RemoveWhiteSpaces(\$caseRequiredSettings);
+			#SpecialChars(\$caseRequiredSettings);
+			$refAppend = \$caseRequiredSettings;
+		}
+
+		elsif($line =~ m/^\# Related requirements:/)
+		{
+			$caseRelatedRequirements = substr($line, length("# Related requirements:"));
+			RemoveWhiteSpaces(\$caseRelatedRequirements);
+			$refAppend = \$caseRelatedRequirements;
+		}
+
+		elsif($line =~ m/^\# Verification:/)
+		{
+			$caseVerification = substr($line, length("# Verification:"));
+			RemoveWhiteSpaces(\$caseVerification);
+			$refAppend = \$caseVerification;
+		}
+
+		elsif($line =~ m/^\# Note:/)
+		{
+			$caseNote = substr($line, length("# Note:"));
+			RemoveWhiteSpaces(\$caseNote);
+			$refAppend = \$caseNote;
+		}
+
+		elsif($line =~ m/^\#/)
+		{
+			my $text = substr($line, length("#"));
+			RemoveWhiteSpaces(\$text);
+			#print(" ***** JOTTAI MUuTA: " . $text. "\n");
+			${$refAppend} .= " " . $text;
+
+			RemoveWhiteSpaces($refAppend);
+
+		}
+
+		$readLines++;
+	}
+
+	return $readLines;
+}
+
+#------------------------------------------------------------------------------------
+# GetCaseIdFromName
+#
+# Parameters:
+#	$caseName
+#------------------------------------------------------------------------------------
+sub GetCaseIdFromName
+{
+	my ($caseName) = @_;
+
+	return "NOID" if(!defined($caseName) || $caseName eq "");
+
+	RemoveWhiteSpaces(\$caseName);
+	#SpecialChars(\$caseName);
+
+	if($caseName =~ m/(ET[0-9]+)[ ]+/)
+	{
+		return $1;
+	}
+
+	return $caseName;
+}
+
+#------------------------------------------------------------------------------------
+# GetCaseField
+#
+# Parameters:
+#	$caseName
+#	$caseField
+#------------------------------------------------------------------------------------
+sub GetCaseField
+{
+	my ($caseNameOrId, $caseField) = @_;
+
+	my $ret = "";
+
+	foreach my $case(@cases)
+	{
+		if(@{$case}[$CASE_NAME] eq $caseNameOrId or @{$case}[$CASE_ID] eq $caseNameOrId)
+		{
+			if( defined(@{$case}[$caseField]) )
+			{
+				$ret = @{$case}[$caseField];
+			}
+		}
+	}
+
+	return $ret;
+}
+
+#------------------------------------------------------------------------------------
+# GetCaseByNameOnly
+#
+# Parameters:
+#	$caseName
+#
+# Removes the case IDs from case names and tries to find case from @cases array
+#------------------------------------------------------------------------------------
+sub GetCaseByNameOnly
+{
+	my ($caseName) = @_;
+
+	my $startPos = index($caseName, " ");
+	$caseName  = substr($caseName, $startPos) if($startPos != -1);
+
+	RemoveWhiteSpaces(\$caseName);
+
+	for(my $i = 0; $i<scalar(@cases); $i++)
+	{
+		my $name = $cases[$i][$CASE_NAME];
+		$startPos = index($name, " ");
+		return if($startPos == -1);
+		$name  = substr($name, $startPos);
+		RemoveWhiteSpaces(\$name);
+
+		return $cases[$i] if($name eq $caseName);
+	}
+	return;
+}
+
+#------------------------------------------------------------------------------------
+# GetCase
+#
+# Parameters:
+#	$caseNameOrID
+#
+# Returns reference to case
+#------------------------------------------------------------------------------------
+sub GetCase
+{
+	my ($caseNameOrID, $refCases) = @_;
+
+	for(my $i = 0; $i<scalar(@$refCases); $i++)
+	{
+        $case = @$refCases[$i];
+		if(@$case[$CASE_NAME] eq $caseNameOrID or @$case[$CASE_ID] eq $caseNameOrID)
+		{
+			return $case;
+		}
+	}
+	return;
+}
+
+#------------------------------------------------------------------------------------
+# GetCaseDesc
+#
+# Parameters:
+#	$caseNameOrID
+#
+# Returns reference to casedesc
+#------------------------------------------------------------------------------------
+sub GetCaseDesc
+{
+	my ($caseNameOrID) = @_;
+
+	for(my $i=0; $i<scalar(@caseDescs); $i++)
+	{
+		if($caseDescs[$i][0] eq $caseNameOrID || $caseDescs[$i][0] eq $caseNameOrID)
+		{
+			return $caseDescs[$i];
+		}
+	}
+	return;
+}
+
+#------------------------------------------------------------------------------------
+# RemoveWhiteSpaces
+#
+# Parameters:
+# 	$text
+#------------------------------------------------------------------------------------
+sub RemoveWhiteSpaces()
+{
+	my ($text) = @_;
+	${$text} =~ s/\s+$//; #whitespaces in the end
+	${$text} =~ s/^\s+//; #whitespaces at the start
+}
+
+#------------------------------------------------------------------------------------
+# XmlReadyText
+#
+# Parameters:
+# 	$text
+#------------------------------------------------------------------------------------
+sub XmlReadyText
+{
+	my ($text) = @_;
+
+	$txtlt = "&lt;";
+	$txtgt = "&gt;";
+	${$text} =~ s/</$txtlt/g;
+	${$text} =~ s/>/$txtgt/g;
+
+	${$text} =~ s/Ä/&Auml/g;
+	${$text} =~ s/ä/&auml/g;
+	${$text} =~ s/Ö/&Ouml/g;
+	${$text} =~ s/ö/&ouml/g;
+
+	#ä &auml;
+
+#	Ö &Ouml;
+
+#	ö &ouml;
+
+}
+
+#------------------------------------------------------------------------------------
+# SpecialChars
+#
+# Parameters:
+# 	$text
+#------------------------------------------------------------------------------------
+sub SpecialChars
+{
+	my ($text) = @_;
+
+
+	ReplaceChar($text, "etmerkki#39;", "'" );
+	ReplaceChar($text, "etmerkkiamp;", "&" );
+	ReplaceChar($text, "etmerkkiacute;", "´" );
+
+	ReplaceChar($text, "etmerkkilsquo;", "‘" );
+	ReplaceChar($text, "etmerkkirsquo;", "’" );
+	ReplaceChar($text, "etmerkkisbquo;", "‚" );
+	ReplaceChar($text, "etmerkkildquo;", "“" );
+	ReplaceChar($text, "etmerkkirdquo;", "”" );
+	ReplaceChar($text, "etmerkkibdquo;", "„" );
+	ReplaceChar($text, "etmerkki#34;", "\"" );
+
+	ReplaceChar($text, "etmerkki#40;", "(" );
+	ReplaceChar($text, "etmerkki#41;", ")" );
+
+	ReplaceChar($text, "etmerkkifrasl;", "/" );
+	ReplaceChar($text, "etmerkkilt;", "<" );
+	ReplaceChar($text, "etmerkkigt;", ">" );
+	ReplaceChar($text, "etmerkki#166;" , "¦" );
+
+	ReplaceChar($text, "etmerkkipara;", "¶" );
+	ReplaceChar($text, "etmerkkimiddot;", "·" );
+	ReplaceChar($text, "etmerkkifrac14;", "¼" );
+	ReplaceChar($text, "etmerkkifrac12;", "½" );
+	ReplaceChar($text, "etmerkkifrac34;" , "¾" );
+
+
+	${$text} =~ s/etmerkki/&/g;
+
+	#	print("TEXT: " . ${$text} . "\n");
+}
+
+#------------------------------------------------------------------------------------
+# ReplaceChar
+#
+# Parameters:
+# 	$text
+#	$replacement
+#	$char
+#------------------------------------------------------------------------------------
+sub ReplaceChar
+{
+	my ($text, $replacement, $char) = @_;
+
+#	print("txt: " . ${$text} . "char: " . $char . ", repl: " . $replacement . "\n");
+
+	while(index(${$text}, $char)  != -1)
+	{
+		my $pos = index(${$text}, $char);
+		if($pos < 0) { $pos = 0 };
+
+		$str1 = substr(${$text}, 0, $pos);
+		$str2 = substr(${$text}, $pos+1);
+
+#		print "STR: '" .  $str1 . "' - '" . $str2 . "'\n";
+
+#		print "XXX: " . $str1 . $replacement .  $str2 . "\n";
+
+		${$text} = $str1 . $replacement . $str2;;
+	}
+}
+
+#------------------------------------------------------------------------------------
+# PrintCases
+#------------------------------------------------------------------------------------
+sub PrintCases
+{
+
+	my ($fileName) = @_;
+
+	my @buff;
+
+	push @buff, ("Name, Status, LogFile\n");
+
+	my $i;
+
+	push @buff, ("----------------------------------------\nCASES\n--------------------------------------\n");
+	foreach $case(@cases)
+	{
+
+		#	my $case = $cases[$i];
+		if(0 or @{$case}[$CASE_STATUS] ne "$caseDefaultStatus")
+			{
+
+			push @buff, (@{$case}[$CASE_NAME] . " ");
+			#@{$case}[$CASE_RUN_TIMES]
+			#@{$case}[$CASE_CRASHED]
+			#@{$case}[$CASE_FAILED]
+			#@{$case}[$CASE_PASSED]
+			push @buff, (@{$case}[$CASE_STATUS] . " ");
+			#@{$case}[$CASE_PURPOSE]
+			#@{$case}[$CASE_MEANS]
+			#@{$case}[$CASE_REQUIRED_SETTINGS]
+			#@{$case}[$CASE_RELATED_REQUIREMENTS]
+			#@{$case}[$CASE_VERIFICATION]
+			#@{$case}[$CASE_NOTE]
+			#@{$case}[$CASE_REASON]
+			#@{$case}[$CASE_RESULT]
+			push @buff, ("file: " . @{$case}[$CASE_LOG_FILE]  . " ");
+
+			push @buff, ("check log: " . @{$case}[$CASE_CHECK_RESULT_LOG_FILE]  . " ");
+
+			push @buff, ("\n");
+
+			}
+	}
+
+	open(XXX, ">" . $fileName);
+	print XXX ( @buff );
+	close(XXX);
+
+}
+
+#------------------------------------------------------------------------------------
+# FindFiles
+# Parameters:
+#	$goDir, where to start finding
+#	$fileSearch, filename search
+#	$searchType, 0 = fullname search, 1 = filetype search
+#	$refIncfiles, reference to array which will hold found files
+#------------------------------------------------------------------------------------
+sub FindFiles
+{
+	my ($godir, $fileSearch, $searchType, $refIncfiles) = @_;
+
+	my $startDir = cwd;
+
+	chdir($godir) or die("Could not change dir to $godir");
+
+	#print("Now in: " . cwd . "\n");
+
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	foreach my $file(@filelist)
+	{
+		if($file eq "." or $file eq "..") {next};
+
+		if (-d $file)
+		{
+		 	FindFiles( $file, $fileSearch, $searchType, $refIncfiles);
+		} else
+		{
+			if( ($file =~ m/$fileSearch/i and $searchType == 0 ) or ($file =~ m/$fileSearch$/i and $searchType == 1 ) )
+			{
+                $file = cwd . "/" . $file;
+				push @$refIncfiles, $file;
+				#print("$file\n");
+			}
+		}
+	}
+
+	chdir ($startDir) or die("Could not change dir to $startDir");
+}
+
+
+#------------------------------------------------------------------------------------
+# GetAllFiles
+# Parameters:
+#	$goDir, where to start finding
+#	$refIncfiles, reference to array which will hold found files
+#   $subDirLevel, how deep in the directories we go to search files. < 0 is no limit.
+#------------------------------------------------------------------------------------
+sub GetAllFiles
+{
+	my ($godir, $refIncfiles, $subDirLevel) = @_;
+
+	my $startDir = cwd;
+
+	chdir($godir) or die("Could not change dir to $godir");
+
+	#print("Now in: " . cwd . "\n");
+
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	foreach my $file(@filelist)
+	{
+		if($file eq "." or $file eq "..") {next};
+		
+		if (! (-d $file) )
+		{
+		 	my $path = $startDir . "/" . $file;
+		 	push @$refIncfiles, $path;		 	
+		} elsif( $subDirLevel > 0 || $subDirLevel < 0 )
+		{
+			my $backupDir = cwd;
+			chdir( $file ) or die("Could not change dir to $file");
+			GetAllFiles( $godir, $refIncfiles, $subDirLevel-1 );
+			chdir( $backupDir ) or die("Could not change dir to $backupDir");
+		}
+	}
+
+	chdir ($startDir) or die("Could not change dir to $startDir");
+}
+
+#------------------------------------------------------------------------------------
+# FindDirs
+# Parameters:
+#	$goDir, where to start finding
+#	$fileSearch, filename search
+#	$refIncfiles, reference to array which will hold found files
+#------------------------------------------------------------------------------------
+sub FindDirs
+{
+	my ($godir, $fileSearch, $refIncfiles) = @_;
+
+	my $startDir = cwd;
+
+	chdir($godir) or die("Could not change dir to $godir");
+
+	#print("Now in: " . cwd . "\n");
+
+	opendir(DIR, ".");
+	my @filelist = sort(readdir(DIR));
+	closedir(DIR);
+
+	foreach my $file(@filelist)
+	{
+		if($file eq "." or $file eq "..") {next};
+
+		if (-d $file)
+		{
+		    if( $file =~ m/$fileSearch/i )
+		    {
+		        push @$refIncfiles, (cwd . "/" . $file);
+		    }
+		 	FindDirs( $file, $fileSearch, $refIncfiles );
+		}
+	}
+
+	chdir ($startDir) or die("Could not change dir to $startDir");
+}
+
+#------------------------------------------------------------------------------------
+# GetPathFileName
+#
+# Parameters:
+# 	$str
+#------------------------------------------------------------------------------------
+sub GetPathFileName
+{
+    my ($str) = @_;
+
+    my $startPos = rindex($str, "\\");
+    if($startPos == -1)
+    {
+        $startPos = rindex($str, "/");
+        return $str if($startPos == -1);
+    }
+
+    my $filename = substr($str, $startPos+1);
+
+    return $filename;
+}
+
+#------------------------------------------------------------------------------------
+# GetPathDir
+#
+# Parameters:
+# 	$str
+#------------------------------------------------------------------------------------
+sub GetPathDir
+{
+    my ($str) = @_;
+
+    my $startPos = rindex($str, "\\");
+    if($startPos == -1)
+    {
+        $startPos = rindex($str, "/");
+        return $str if($startPos == -1);
+    }
+
+    my $filename = substr($str, 0, $startPos);
+
+    return $filename;
+}
+
+sub InitXmlData
+{
+
+$xmlHeader =
+"<?xml version='1.0'?>" .
+"<?mso-application progid='Excel.Sheet'?>" .
+"<Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet'" .
+" xmlns:o='urn:schemas-microsoft-com:office:office'" .
+" xmlns:x='urn:schemas-microsoft-com:office:excel'" .
+" xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet'" .
+" xmlns:html='http://www.w3.org/TR/REC-html40'>" .
+" <DocumentProperties xmlns='urn:schemas-microsoft-com:office:office'>" .
+"  <Author>Senbom Petri</Author>" .
+"  <LastAuthor>Senbom Petri</LastAuthor>" .
+"  <Created>2006-06-09T11:08:05Z</Created>" .
+"  <Company>Nokia Oyj</Company>" .
+"  <Version>11.6568</Version>" .
+" </DocumentProperties>" .
+" <ExcelWorkbook xmlns='urn:schemas-microsoft-com:office:excel'>" .
+"  <WindowHeight>12210</WindowHeight>" .
+"  <WindowWidth>18780</WindowWidth>" .
+"  <WindowTopX>360</WindowTopX>" .
+"  <WindowTopY>255</WindowTopY>" .
+"  <ProtectStructure>False</ProtectStructure>" .
+"  <ProtectWindows>False</ProtectWindows>" .
+" </ExcelWorkbook>" .
+" <Styles>" .
+"  <Style ss:ID='Default' ss:Name='Normal'>" .
+"   <Alignment ss:Vertical='Bottom'/>" .
+"   <Borders/>" .
+"   <Font/>" .
+"   <Interior/>" .
+"   <NumberFormat/>" .
+"   <Protection/>" .
+"  </Style>" .
+"  <Style ss:ID='m155260432'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='m155260442'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='m155266416'>" .
+"   <Alignment ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Font x:Family='Swiss' ss:Bold='1'/>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='m155266426'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='m155266436'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='m155266446'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s21'>" .
+"   <Alignment ss:Horizontal='Right' ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s25'>" .
+"   <Alignment ss:Horizontal='Right' ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s26'>" .
+"   <Borders>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s27'>" .
+"   <Alignment ss:Horizontal='Center' ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s28'>" .
+"   <Borders>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s29'>" .
+"   <Borders>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s30'>" .
+"   <Alignment ss:Horizontal='Right' ss:Vertical='Top'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s34'>" .
+"   <Alignment ss:Horizontal='Right' ss:Vertical='Top'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+"  <Style ss:ID='s35'>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#failed
+
+"  <Style ss:ID='s36'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFF00' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#passed style
+
+"  <Style ss:ID='s37'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#CCFFCC' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#crashed style
+
+"  <Style ss:ID='s38'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FF6600' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+# UNKNOWN style
+
+"  <Style ss:ID='s401'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FF6600' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+
+#NA style
+"  <Style ss:ID='s39'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"  </Style>" .
+
+
+#failed centered
+
+"  <Style ss:ID='s36centered'>" .
+"   <Alignment ss:Horizontal=\"Center\" ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFF00' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#passed style centered
+
+"  <Style ss:ID='s37centered'>" .
+"   <Alignment ss:Horizontal=\"Center\" ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#CCFFCC' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#crashed style centered
+
+"  <Style ss:ID='s38centered'>" .
+"   <Alignment ss:Horizontal=\"Center\" ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FF6600' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+# UNKNOWN style centered
+
+"  <Style ss:ID='s401centered'>" .
+"   <Alignment ss:Horizontal=\"Center\" ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FF6600' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+
+#NA style centered
+"  <Style ss:ID='s39centered'>" .
+"   <Alignment ss:Horizontal=\"Center\" ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"  </Style>" .
+
+#summary style
+"  <Style ss:ID='summary'>" .
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#summary real number style
+"  <Style ss:ID='summaryreal'>" .
+"   <NumberFormat ss:Format='Fixed'/> ".
+"   <Alignment ss:Vertical='Top' ss:WrapText='1'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#summary header
+"  <Style ss:ID='summary_header'>" .
+"   <Alignment ss:Horizontal='Left' ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Font x:Family='Swiss' ss:Bold='1'/>" .
+"  </Style>" .
+
+#brief header
+"  <Style ss:ID='brief_header'>" .
+"   <Alignment ss:Horizontal='Center' ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Interior ss:Color='#99CCFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+"  <Style ss:ID='brief_heading_cfgfilename'>" .
+"   <Alignment ss:Vertical='Bottom'/>" .
+"   <Borders>" .
+"    <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"    <Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>" .
+"   </Borders>" .
+"   <Font x:Family='Swiss' ss:Bold='1'/>" .
+"   <Interior ss:Color='#CCFFCC' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+#link
+"  <Style ss:ID='urlparent' ss:Name='Hyperlink'>" .
+"   <Font ss:Color='#0000FF' ss:Underline='Single'/>" .
+"  </Style>" .
+
+"  <Style ss:ID='url' ss:Parent='urlparent'>" .
+"   <Interior ss:Color='#FFFFFF' ss:Pattern='Solid'/>" .
+"  </Style>" .
+
+" </Styles>" .
+" <Worksheet ss:Name='Sheet1'>";
+
+$xmlHeaderTableColumns =
+"  <Table ss:ExpandedColumnCount='18' ss:ExpandedRowCount='CASE_COUNT_MUL8' x:FullColumns='1'" .
+"   x:FullRows='1'>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='138.75'/>" .
+"   <Column ss:Index='3' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='5' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='7' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='16' ss:AutoFitWidth='0' ss:Width='26.25'/>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='15'/>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='525.75'/>\n\n";
+
+$xmlHeaderTableColumnsBrief =
+"  <Table ss:ExpandedColumnCount='25' ss:ExpandedRowCount='CASE_COUNT_MUL8' x:FullColumns='1'" .
+"   x:FullRows='1'>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='138.75'/>" .
+"   <Column ss:Index='2' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='3' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='4' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='5' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='6' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='7' ss:AutoFitWidth='0' ss:Width='65'/>" . #status
+"   <Column ss:Index='8' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='9' ss:AutoFitWidth='0' ss:Width='39'/>" .
+"   <Column ss:Index='12' ss:AutoFitWidth='0' ss:Width='260'/>" . # info
+"   <Column ss:Index='13' ss:AutoFitWidth='0' ss:Width='26.25'/>" . # link1
+"   <Column ss:Index='14' ss:AutoFitWidth='0' ss:Width='26.25'/>" . # link2
+"   <Column ss:Index='16' ss:AutoFitWidth='0' ss:Width='26.25'/>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='15'/>" .
+"   <Column ss:AutoFitWidth='0' ss:Width='525.75'/>\n\n";
+
+$xmlHeaderTableColumnsAlt =
+"  <Table ss:ExpandedColumnCount='25' ss:ExpandedRowCount='CASE_COUNT_MUL8' x:FullColumns='1'" .
+"   x:FullRows='1'>" .
+"   <Column ss:AutoFitWidth=\"0\" ss:Width=\"138.75\"/>" .
+"   <Column ss:AutoFitWidth=\"0\" ss:Width=\"30\" ss:Span=\"4\"/>" .
+"   <Column ss:Index=\"7\" ss:AutoFitWidth=\"0\" ss:Width=\"60.00\" ss:Span=\"9\"/>" .
+"   <Column ss:Index=\"17\" ss:AutoFitWidth=\"0\" ss:Width=\"15\"/>" .
+"   <Column ss:AutoFitWidth=\"0\" ss:Width=\"525.75\"/>";
+
+$xmlFooter =
+
+"  </Table>" .
+"  <WorksheetOptions xmlns='urn:schemas-microsoft-com:office:excel'>" .
+
+#splitted panes
+#"  <Selected/>" .
+#"   <SplitHorizontal>3060</SplitHorizontal>" .
+#"   <TopRowBottomPane>11</TopRowBottomPane>" .
+#"   <ActivePane>2</ActivePane>" .
+#"   <Panes>" .
+#"    <Pane>" .
+#"     <Number>3</Number>" .
+#"    </Pane>" .
+#"    <Pane>" .
+#"     <Number>2</Number>" .
+#"     <RangeSelection>R12C1:R12C8</RangeSelection>" .
+#"    </Pane>" .
+#"   </Panes>" .
+
+#not splitted
+"   <Selected/>" .
+"   <Panes>" .
+"    <Pane>" .
+"     <Number>3</Number>" .
+"     <ActiveRow>7</ActiveRow>" .
+"     <ActiveCol>2</ActiveCol>" .
+"    </Pane>" .
+"   </Panes>" .
+
+"   <ProtectObjects>False</ProtectObjects>" .
+"   <ProtectScenarios>False</ProtectScenarios>" .
+"  </WorksheetOptions>" .
+" </Worksheet>" .
+" <Worksheet ss:Name='Sheet2'>" .
+"  <WorksheetOptions xmlns='urn:schemas-microsoft-com:office:excel'>" .
+"   <ProtectObjects>False</ProtectObjects>" .
+"   <ProtectScenarios>False</ProtectScenarios>" .
+"  </WorksheetOptions>" .
+" </Worksheet>" .
+" <Worksheet ss:Name='Sheet3'>" .
+"  <WorksheetOptions xmlns='urn:schemas-microsoft-com:office:excel'>" .
+"   <ProtectObjects>False</ProtectObjects>" .
+"   <ProtectScenarios>False</ProtectScenarios>" .
+"  </WorksheetOptions>" .
+" </Worksheet>" .
+"</Workbook>\n\n";
+
+$xmlDataEmptyRow =
+"   <Row>" .
+"    <Cell ss:StyleID='s35'><Data ss:Type='String'></Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+$xmlSummaryData =
+
+$xmlDataEmptyRow .
+
+"   <Row>" .
+"    <Cell ss:StyleID='s35' ss:MergeAcross='20'>" . "<Data ss:Type='String'>INSERT TEST SOFTWARE HERE</Data></Cell>" .
+"   </Row>\n\n" .
+
+"   <Row>" .
+"    <Cell ss:StyleID='s35' ss:MergeAcross='20'>" . "<Data ss:Type='String'>INSERT TEST DEVICE HERE</Data></Cell>" .
+"   </Row>\n\n" .
+
+$xmlDataEmptyRow .
+
+"   <Row>\n" .
+"    <Cell ss:MergeAcross='4' ss:StyleID='summary_header'><Data ss:Type='String'>Test Execution Metrics</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Total cases:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summary'><Data ss:Type='Number'>$xmlDataSummaryCaseCount</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Passed:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summary'><Data ss:Type='Number'>$xmlDataSummaryPassed</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Failed:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summary'><Data ss:Type='Number'>$xmlDataSummaryFailed</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Crashed:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summary'><Data ss:Type='Number'>$xmlDataSummaryCrashed</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Timeout:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summary'><Data ss:Type='Number'>$xmlDataSummaryTimeout</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Pass rate % (total cases):</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summaryreal'><Data ss:Type='Number'>$xmlDataSummaryPassRateTotal</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Pass rate % (run cases):</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summaryreal'><Data ss:Type='Number'>$xmlDataSummaryPassRateRun</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+"   <Row>\n" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Run rate %:</Data></Cell>" .
+"    <Cell ss:MergeAcross='3' ss:StyleID='summaryreal'><Data ss:Type='Number'>$xmlDataSummaryRunRate</Data></Cell>" .
+"    <Cell ss:MergeAcross='12' ss:StyleID='s35'/>\n" .
+"   </Row>\n" .
+ $xmlDataEmptyRow;
+
+$xmlData =
+"   <Row>" .
+"    <Cell ss:StyleID='s21'><Data ss:Type='String'>Name:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155266416'><Data ss:Type='String'>XML_DATA_CASE_NAME</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>";
+
+# not included in the case documentation report
+$xmlDataCaseStatusDisabled =
+"   <Row>" .
+"    <Cell ss:StyleID='s25'><Data ss:Type='String'>Run times:</Data></Cell>" .
+"    <Cell ss:StyleID='s26'><Data ss:Type='Number'>XML_DATA_CASE_RUN_TIMES</Data></Cell>" .
+#
+"    <Cell ss:StyleID='s27'><Data ss:Type='String'>Crashed</Data></Cell>" .
+"    <Cell ss:StyleID='s28'><Data ss:Type='Number'>XML_DATA_CASE_CRASHED</Data></Cell>" .
+
+"    <Cell ss:StyleID='s27'><Data ss:Type='String'>Failed</Data></Cell>" .
+"    <Cell ss:StyleID='s28'><Data ss:Type='Number'>XML_DATA_CASE_FAILED</Data></Cell>" .
+"    <Cell ss:StyleID='s27'><Data ss:Type='String'>Passed</Data></Cell>" .
+"    <Cell ss:StyleID='s28'><Data ss:Type='Number'>XML_DATA_CASE_PASSED</Data></Cell>" .
+"    <Cell ss:StyleID='s27'><Data ss:Type='String'>Status</Data></Cell>" .
+#orig status style id s28
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='String'>XML_DATA_CASE_STATUS</Data></Cell>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+"    <Cell ss:StyleID='s28'/>" .
+#"    <Cell ss:StyleID='s28'/>" .
+#"    <Cell ss:StyleID='s29'/>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+$xmlDataCaseStatusDisabled .= "";
+
+$xmlData2 =
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s30'><Data ss:Type='String'>Purpose:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155266426'><Data ss:Type='String'>XML_DATA_CASE_PURPOSE</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>" .
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s30'><Data ss:Type='String'>Means:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155266436'><Data ss:Type='String'>XML_DATA_CASE_MEANS</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>" .
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s30'><Data ss:Type='String'>Required environment settings:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155266446'><Data ss:Type='String'>XML_DATA_CASE_REQUIRED_SETTINGS</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>" .
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s30'><Data ss:Type='String'>Related requirements:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155266446'><Data ss:Type='String'>XML_DATA_CASE_RELATED_REQUIREMENTS</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>" .
+
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s30'><Data ss:Type='String'>Verification:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155260432'><Data ss:Type='String'>XML_DATA_CASE_VERIFICATION</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>" .
+"   <Row ss:AutoFitHeight='0' ss:Height='30'>" .
+"    <Cell ss:StyleID='s34'><Data ss:Type='String'>Note:</Data></Cell>" .
+"    <Cell ss:MergeAcross='15' ss:StyleID='m155260442'><Data ss:Type='String'>XML_DATA_CASE_NOTE</Data></Cell>" .
+"    <Cell ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+
+$xmlDataBriefHeader =
+"   <Row>" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='brief_header'><Data ss:Type='String'>Name</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Status</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Passes</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Fails</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Crashes</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Result</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>Info</Data></Cell>" .
+"    <Cell ss:MergeAcross='6' ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+$xmlDataBriefNoLinks =
+"   <Row>\n" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='m155266416'><Data ss:Type='String'>XML_DATA_CASE_NAME</Data></Cell>\n" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='String'>XML_DATA_CASE_STATUS</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_PASSED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_FAILED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_CRASHED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_RESULT</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='String'>XML_DATA_CASE_REASON</Data></Cell>\n" .
+"    <Cell ss:MergeAcross='7' ss:StyleID='s35'/>\n" .
+"   </Row>\n\n";
+
+$xmlDataBrief1Link =
+"   <Row>\n" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='m155266416'><Data ss:Type='String'>XML_DATA_CASE_NAME</Data></Cell>\n" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='String'>XML_DATA_CASE_STATUS</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_PASSED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_FAILED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_CRASHED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_RESULT</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='String'>XML_DATA_CASE_REASON</Data></Cell>\n" .
+"    <Cell ss:StyleID='url' ss:HRef='XML_DATA_CASE_LINK1'><Data ss:Type='String'>Link</Data></Cell>\n" .
+"    <Cell ss:MergeAcross='6' ss:StyleID='s35'/>\n" .
+"   </Row>\n\n";
+
+$xmlDataBrief2Links =
+"   <Row>\n" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='m155266416'><Data ss:Type='String'>XML_DATA_CASE_NAME</Data></Cell>\n" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='String'>XML_DATA_CASE_STATUS</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_PASSED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_FAILED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_CRASHED</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='Number'>XML_DATA_CASE_RESULT</Data></Cell>\n" .
+"    <Cell ss:StyleID='s39'><Data ss:Type='String'>XML_DATA_CASE_REASON</Data></Cell>\n" .
+"    <Cell ss:StyleID='url' ss:HRef='XML_DATA_CASE_LINK1'><Data ss:Type='String'>Link</Data></Cell>\n" .
+"    <Cell ss:StyleID='url' ss:HRef='XML_DATA_CASE_LINK2'><Data ss:Type='String'>Link</Data></Cell>\n" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='s35'/>\n" .
+"   </Row>\n\n";
+
+$xmlCfgFileBrief =
+"   <Row>" .
+"    <Cell ss:MergeAcross='11' ss:StyleID='brief_heading_cfgfilename'><Data ss:Type='String'>XML_DATA_CFG_FILE</Data></Cell>" .
+"    <Cell ss:MergeAcross='6' ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+
+$xmlCfgFileAltHeader =
+"   <Row>" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='brief_header'><Data ss:Type='String'>Name</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE1</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE2</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE3</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE4</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE5</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE6</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE7</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE8</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE9</Data></Cell>" .
+"    <Cell ss:StyleID='brief_header'><Data ss:Type='String'>XML_DATA_ALTDATE10</Data></Cell>" .
+"    <Cell ss:MergeAcross='6' ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+
+$xmlCfgFileAltData =
+"   <Row>" .
+"    <Cell ss:MergeAcross='5' ss:StyleID='m155266416'><Data ss:Type='String'>XML_DATA_CASE_NAME</Data></Cell>\n" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT1</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT2</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT3</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT4</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT5</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT6</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT7</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT8</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT9</Data></Cell>" .
+"    <Cell ss:StyleID='STYLE_ID_STATUS'><Data ss:Type='Number'>XML_DATA_ALTRESULT10</Data></Cell>" .
+"    <Cell ss:MergeAcross='6' ss:StyleID='s35'/>" .
+"   </Row>\n\n";
+
+} # sub InitXml
+