stif/ConsoleUI/src/ConsoleUI.cpp
branchRCL_3
changeset 59 8ad140f3dd41
parent 0 a03f92240627
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/ConsoleUI/src/ConsoleUI.cpp	Wed Oct 13 16:17:58 2010 +0300
@@ -0,0 +1,2132 @@
+/*
+* Copyright (c) 2009 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: This module contains implementation of CConsoleMain 
+* and CModule class member functions.
+*
+*/
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <e32cons.h>
+#include <e32svr.h>
+#include <f32file.h>
+
+#include <stifinternal/UIStoreIf.h>
+
+#include "ConsoleUI.h"
+#include "ConsoleMenus.h"
+
+#include "StifTestInterface.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+_LIT(KNameTxt,"STIF");
+_LIT( KConsoleMain, "CConsoleMain" );
+
+// Commandline params
+_LIT( KTestModule,      "-testmodule" );
+_LIT( KTestModuleIni,   "-testmoduleini" );
+_LIT( KTestCaseFile,    "-testcasefile" );
+_LIT( KTestSet,         "-testset" );
+_LIT( KTestRun,         "-run" );
+_LIT( KTestRunAll,      "all" );
+_LIT( KTestRunSeq,      "sequential" );
+_LIT( KTestRunPar,      "parallel" );
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+LOCAL_C void MainL();
+
+
+
+// ==================== LOCAL FUNCTIONS =======================================
+
+// None
+
+
+// ================= MEMBER FUNCTIONS =========================================
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: NewL
+
+    Description: Construct the console main class
+
+    Parameters: None
+
+    Return Values: CConsoleMain*                    New object
+
+    Errors/Exceptions: Leaves if memory allocation fails or
+                       ConstructL leaves.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleMain* CConsoleMain::NewL( )
+    {
+
+    CConsoleMain* self = new ( ELeave ) CConsoleMain();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Construct the console
+    Construct module and case containers
+    Retrieve command line parameters
+    Connect to test engine
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if memory allocation fails or fileserver or
+                       test engine can't be connected.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::ConstructL( )
+    {
+    
+    CUIStoreIf::ConstructL();
+
+    // Construct the console
+    iConsole = Console::NewL( KNameTxt,
+                             TSize( KConsFullScreen, KConsFullScreen ) );
+
+    RDebug::Print(_L("Creating module list object"));
+    TRAPD(err, iModuleList = CTestModuleList::NewL(NULL));
+    if(err != KErrNone)
+        {
+        RDebug::Print(_L("Could not create module list (%d)"), err);
+        UiError(_L("Could not create module list (err)"));
+        User::Leave(err);
+        }
+    if(!iModuleList)
+        {
+        RDebug::Print(_L("Could not create module list (NULL)"));
+        UiError(_L("Could not create module list (NULL)"));
+        User::Leave(KErrGeneral);
+        }
+
+    // Get command line parameters
+    TFileName iniFile; // TestFramework initialization file
+                    
+    ProcessCommandlineL( iniFile );
+
+    if(iTestModule)
+        {
+        // Add to module list info about module taken from command line
+        RDebug::Print(_L("Adding command line module to list"));
+        TName moduleName;
+        moduleName.Copy(iTestModule->Des());
+        moduleName.LowerCase();
+        err = iModuleList->AddTestModule(moduleName);
+        if(err != KErrNone && err != KErrAlreadyExists)
+            {
+            RDebug::Print(_L("Could not add module to list of modules (%d)"), err);
+            UiError(_L("Could not add module to list of modules (err)"));
+            User::Leave(err);
+            }
+
+        //Get added module
+        CTestModuleInfo* moduleInfo = iModuleList->GetModule(moduleName);
+        if(!moduleInfo)
+            {
+            RDebug::Print(_L("Could not add get module info from list"));
+            UiError(_L("Could not add get module info from list"));
+            User::Leave(KErrGeneral);
+            }
+
+        //Add ini file if given
+        if(iTestModuleIni && iTestModuleIni->Length() > 0)
+            {
+            TFileName filename;
+            filename.Copy(iTestModuleIni->Des());
+            filename.LowerCase();
+            moduleInfo->SetIniFile(filename);
+            }
+
+        //Add config file if given
+        if(iTestCaseFile && iTestCaseFile->Length() > 0)
+            {
+            TFileName filename;
+            filename.Copy(iTestCaseFile->Des());
+            filename.LowerCase();
+            moduleInfo->AddCfgFile(filename);
+            }
+
+        //Now check all config files if there are included modules
+        _LIT(KIncludeModuleStart, "[New_Include_Module]");
+        _LIT(KIncludeModuleEnd, "[End_Include_Module]");
+
+        RDebug::Print(_L("Start parsing included modules"));
+        CTestCaseFileInfo* finfo = iModuleList->GetUncheckedCfgFile();
+        while(finfo)
+            {
+            TFileName fname;
+            finfo->GetCfgFileName(fname);
+
+            RDebug::Print(_L("Checking file: '%S'"), &fname);
+            finfo->SetChecked();
+
+            CStifParser* parser = NULL;
+ 
+            TRAP(err, parser = CStifParser::NewL(_L(""), fname));
+            if(err != KErrNone)
+                {
+                RDebug::Print(_L("Could not create parser to read content of config file (%d)"), err);
+                UiError(_L("Could not create parser to read content of config file (err)"));
+                User::Leave(err);
+                }
+            CleanupStack::PushL(parser);
+
+            ParseTestModulesL(parser, iModuleList, KIncludeModuleStart, KIncludeModuleEnd);
+
+            CleanupStack::PopAndDestroy(parser);
+            finfo = iModuleList->GetUncheckedCfgFile();
+            }
+        RDebug::Print(_L("End parsing included modules"));
+        }
+
+    iConsole->Printf(_L("\nTest Framework starting\n"));
+
+    // CUIStore open
+    User::LeaveIfError( UIStore().Open( iniFile ) );
+    
+    }
+        
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: CConsoleMain
+
+    Description: Constructor.
+    Initialize non-zero member variables.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleMain::CConsoleMain( ):iStartCases( EStartCaseNo )
+    {
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: ~CConsoleMain
+
+    Description: Destructor
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleMain::~CConsoleMain( )
+    {	
+
+    iDialogs.ResetAndDestroy();
+    iDialogs.Close();
+ 
+    // CUIStore close
+    UIStore().Close();
+    
+    delete iReader;
+    iReader = NULL;
+    
+	delete iScroller;
+	iScroller = NULL;
+    
+    delete iConsole;
+    iConsole = NULL;
+
+    delete iMainMenu;
+    iMainMenu = NULL;
+
+    delete iTestModule;
+    iTestModule = 0;
+    
+    delete iTestModuleIni;
+    iTestModuleIni = 0;
+    
+    delete iTestCaseFile;
+    iTestCaseFile = 0;
+    
+    delete iTestSetName;
+    iTestSetName = 0;
+
+    delete iModuleList;
+    iModuleList = 0;
+    
+    iFilters.ResetAndDestroy();
+    iFilters.Close();
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: ProcessCommandlineL
+
+    Description: Process commandline parameters.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves on error.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::ProcessCommandlineL( TFileName& aIniFile )
+    {
+
+	User me;
+    TInt lineLength = me.CommandLineLength();
+    HBufC* lineBuf = HBufC::NewLC( lineLength );
+    TPtr line( lineBuf->Des() );
+    TBool firstTime = ETrue;
+    TInt offset = 0;
+    TPtrC param;
+    TChar c;
+    
+    me.CommandLine( line );
+    TLex lex( line );
+    
+    while( offset < lineLength )
+        {    
+        // Get first charecter of the parameter
+        lex.SkipSpace();
+        c = lex.Peek();
+        if( c == 0 )
+            {
+            // End of line
+            break;
+            }
+        
+        // Get the whole parameter 
+        param.Set( lex.NextToken() );
+        if( firstTime )
+            {
+            // Filebrowser workaround. It gives the exe name as command line param
+            // verify that it is not the same as the executable name
+            //@spe TFileName exePath = me.FileName();
+			TFileName exePath = RProcess().FileName();
+            if ( param == exePath )
+                {
+                // Discard command line parameters when using filebrowser
+                break;
+                }
+
+            firstTime = EFalse;
+            }
+        // Check if -param option
+        if( c == '-' )
+            {
+            // This is option
+            if( param == KTestModule )
+                {
+                // Get test module name
+                param.Set( lex.NextToken() );
+                if( param.Length() == 0 )
+                    {
+                    UiError( _L("Test module name not given"));
+                    break;
+                    }
+                if( param.Length() > KMaxName )
+                    {
+                    UiError( _L("Test module name too long"));
+                    break;
+                    }
+                iTestModule = param.AllocL();
+                }
+            else if( param == KTestModuleIni )
+                {
+                // Get test module initialization file
+                param.Set( lex.NextToken() );
+                if( param.Length() == 0 )
+                    {
+                    UiError( _L("Test module initialization file name not given"));
+                    break;
+                    }
+                if( param.Length() > KMaxFileName )
+                    {
+                    UiError( _L("Test module initialization file name too long"));
+                    break;
+                    }
+                TFileName tmpTestModuleIni( param );
+                TStifUtil::CorrectFilePathL( tmpTestModuleIni );
+                iTestModuleIni = tmpTestModuleIni.AllocL();
+                }
+            else if( param == KTestCaseFile )
+                {
+                // Get test case file name
+                param.Set( lex.NextToken() );
+                if( param.Length() == 0 )
+                    {
+                    UiError( _L("Test case file name not given"));
+                    break;
+                    }
+                if( param.Length() > KMaxFileName )
+                    {
+                    UiError( _L("Test case file name too long"));
+                    break;
+                    }
+                TFileName tmpTestCaseFile( param );
+                TStifUtil::CorrectFilePathL( tmpTestCaseFile );
+                iTestCaseFile = tmpTestCaseFile.AllocL();
+                }
+            else if( param == KTestSet )
+                {
+                // Get test set name
+                param.Set( lex.NextToken() );
+                if( param.Length() == 0 )
+                    {
+                    UiError( _L("Test set name not given"));
+                    break;
+                    }
+                if( param.Length() > KMaxFileName )
+                    {
+                    UiError( _L("Test set name too long"));
+                    
+                    break;
+                    }
+                iTestSetName = param.AllocL();
+                }
+            else if( param == KTestRun )
+                {
+                if( iStartCases )
+                    {
+                    UiError( _L("Only one -run option allowed") );
+                    // Do not start anything
+                    iStartCases = EStartCaseNo;
+                    break;
+                    }
+                // Get run type
+                lex.Mark();
+                param.Set( lex.NextToken() );
+                if( param.Length() == 0 )
+                    {
+                    UiError( _L("Test set name not given"));
+                    break;
+                    }
+                if( ( param == KTestRunAll ) ||
+                    ( param == KTestRunSeq ) )
+                    {
+                    iStartCases = EStartCasesSeq;
+                    }
+                else if( param == KTestRunPar )
+                    {
+                    iStartCases = EStartCasesPar;
+                    }
+                else
+                    {
+                    lex.UnGetToMark();
+                    lex.SkipSpace();
+                    if( lex.Val( iTestCaseNum ) != KErrNone )
+                        { 
+                        UiError( _L("Unknown run type given, valid values are all/sequential/parallel/test case number"));
+                        }
+                    else
+                        {
+                        iStartCases = EStartSingleCase;
+                        }    
+                    break;
+                    }
+                }            
+            }
+        else 
+            {
+            // This is Test Framework ini file
+            aIniFile = param;
+            TStifUtil::CorrectFilePathL( aIniFile );
+            // ini file is last option
+            break;
+            }
+        
+        }
+      
+    CleanupStack::PopAndDestroy( lineBuf );
+
+    }
+    
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: Panic
+
+    Description: Console UI panic function
+
+    Parameters: TInt
+
+    Return Values: 
+
+    Errors/Exceptions: Does not return.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::Panic(TConsoleUIPanic aPanic )
+    {
+        
+    User::Panic (_L("STIF TestFramework Console UI panic"), aPanic );
+    
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: StartL
+
+    Description: Construct menu objects and start the menu handling
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions:
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+TInt CConsoleMain::StartL()
+    {
+    
+    // Construct keystroke reader
+    iReader           = CConsoleReader::NewL( this, iConsole );
+
+    // Construct the main menu
+    TInt majorV;
+    TInt minorV;
+    TInt buildV;
+    TBuf<30> relDate;
+    TStifUtil::STIFVersion(majorV, minorV, buildV, relDate);
+    
+    TBuf<128> version;
+    version.Format(_L("STIF v%d.%d.%d - "), majorV, minorV, buildV);
+    version.Append(relDate);
+    version.Append(_L("\n"));
+    iMainMenu = CMainMenu::NewL( this, NULL, _L("Main menu"), version );
+
+    // Add the case menu
+    CMenu* caseMenu   = CMenu::NewL( this, iMainMenu, _L("Case menu") );
+    iMainMenu->AddItemL ( caseMenu );
+
+    // Add the module menu
+    CMenu* moduleMenu = CModuleListView::NewL( this, iMainMenu, _L("Module menu") );
+    iMainMenu->AddItemL ( moduleMenu );
+
+    // Add test set menu
+    CTestSetMenu* testSetMenu = CTestSetMenu::NewL( this, iMainMenu, _L("Test set menu") );
+    iMainMenu->AddItemL ( testSetMenu );
+ 
+    // Construct the case menus
+    CMenu* casestart  = NULL;
+    CMenu* casestartshow  = NULL;
+    
+    // Load filters
+    UIStore().ReadFiltersL(iFilters);
+    
+    // If there are no filters defined, then construct menu without filter's menu
+    if(iFilters.Count() == 0)
+        {
+        casestart = CCaseStartMenu::NewL(this, caseMenu, _L("Start new case"));
+        caseMenu->AddItemL(casestart);
+    CMenu* casestartshow  = NULL;
+        casestartshow = CCaseStartMenu::NewL(this, caseMenu, _L("Start & show output"), ETrue);
+        caseMenu->AddItemL(casestartshow);
+        }
+    else // if there are filters defined, create also filter's menu
+        {
+        CFilterMenu* filtercasestart = NULL;
+        CFilterMenu* filtercasestartshow = NULL;
+        
+        filtercasestart = CFilterMenu::NewL(this, caseMenu, _L("Start new case (filter)"));
+        caseMenu->AddItemL(filtercasestart);
+        casestart = CCaseStartMenu::NewL(this, caseMenu, _L("Start new case"));
+        filtercasestart->SetTestCaseMenu(casestart);
+        
+        filtercasestartshow = CFilterMenu::NewL(this, caseMenu, _L("Start & show output (filter)"));
+        caseMenu->AddItemL(filtercasestartshow);
+        casestartshow = CCaseStartMenu::NewL(this, caseMenu, _L("Start & show output"), ETrue);
+        filtercasestartshow->SetTestCaseMenu(casestartshow);
+        }
+
+	CMultipleCaseMenu* multicasestart =
+	    CMultipleCaseMenu::NewL (this, caseMenu, _L("Run multiple tests") );
+    caseMenu->AddItemL( multicasestart );
+    casestart = CCaseMenu::NewL ( this, caseMenu, _L("Ongoing cases"), 
+        CUIStoreIf::EStatusRunning );
+    caseMenu->AddItemL( casestart );
+    casestart = CCaseMenu::NewL ( this, caseMenu, _L("Executed cases"), 
+        CUIStoreIf::EStatusExecuted );
+    caseMenu->AddItemL( casestart );
+    casestart = CCaseMenu::NewL ( this, caseMenu, _L("Passed cases"), 
+        CUIStoreIf::EStatusPassed );
+    caseMenu->AddItemL( casestart );
+    casestart = CCaseMenu::NewL ( this, caseMenu, _L("Failed cases"), 
+        CUIStoreIf::EStatusFailed );
+    caseMenu->AddItemL( casestart );
+    casestart = CCaseMenu::NewL ( this, caseMenu, _L("Aborted/Crashed cases"), 
+        ( CUIStoreIf::EStatusAborted | CUIStoreIf::EStatusCrashed) );
+    caseMenu->AddItemL( casestart );
+    //Add "test set choice" menu
+    CTestSetChoiceMenu* testChoiceMenu = CTestSetChoiceMenu::NewL( this, testSetMenu, _L("Load test set") );
+ 	testSetMenu->AddItemL( testChoiceMenu );
+
+    // Start stuff according to command line parameters
+    if( iTestSetName )
+        { 
+        // Set test set name
+        testSetMenu->SetTestSetFileName( iTestSetName->Des() );
+        
+        // Load test set
+        if( UIStore().LoadTestSet( iTestSetName->Des() ) != KErrNone )
+ 	       {
+           UiError( _L("Test set loading failed"));
+           }
+        else 
+           {
+           // Inform test set menu that set is loaded
+           testSetMenu->SetCreated();
+    
+            // Check if test set should be started
+    	    if( ( iStartCases == EStartCasesPar ) || 
+    	    	( iStartCases == EStartCasesSeq ))         	
+            	{
+            
+	            // Check set starting type
+    	    	CStartedTestSet::TSetType setType = 
+       	        CStartedTestSet::ESetSequential;
+       	        
+                if( iStartCases == EStartCasesPar )
+                    {
+                    setType = 
+                        CStartedTestSet::ESetParallel;
+                    }
+                    
+                // Start test set
+                RRefArray<CTestSetInfo> setInfos;
+                TInt ret = UIStore().TestSets( setInfos );
+                if( (  ret != KErrNone ) ||
+                    ( setInfos.Count() != 1 ) )
+                    {
+                    // Should never ever happen
+                    User::Panic( KConsoleMain, KErrGeneral );
+                    }
+                
+                const CTestSetInfo& set = setInfos[0];
+                setInfos.Reset();
+                setInfos.Close();
+                
+                TInt index;
+                ret = UIStore().StartTestSet( set, index, setType );
+                if( ret != KErrNone )
+                    {
+                    UiError( _L("Test set starting failed") );
+                    }
+                } 
+            }
+        delete iTestSetName;
+        iTestSetName = 0;     
+        }
+    if( iTestModule )
+        {
+        TPtrC module( iTestModule->Des() ); 
+
+        // Add all test modules and config files
+        RDebug::Print(_L("Start creating test modules"));
+        CTestModuleInfo* moduleInfo = NULL;
+        TInt i;
+        TInt modCnt = iModuleList->Count();
+        TInt ret;
+
+        for(i = 0; i < modCnt; i++)
+            {
+            RDebug::Print(_L("Processing module"));
+            // Get module
+            moduleInfo = iModuleList->GetModule(i);
+            if(!moduleInfo)
+                {
+                RDebug::Print(_L("Could not get module info at index %d"), i);
+                continue;
+                }
+
+            // Get module name
+            TName moduleName;
+            moduleInfo->GetModuleName(moduleName);
+            RDebug::Print(_L("module name: '%S'"), &moduleName);
+
+            // Get ini file, if exists
+            TFileName ini;
+            moduleInfo->GetIniFileName(ini);
+            if(ini.Length() == 0)
+                {
+                RDebug::Print(_L("ini file not found"));
+                }
+            else
+                {
+                RDebug::Print(_L("ini file: '%S'"), &ini);
+                }
+
+            // Create test module
+            RDebug::Print(_L("Adding module to UI store"));
+            ret = UIStore().AddTestModule(moduleName, ini);
+            if(ret != KErrNone && ret != KErrAlreadyExists)
+                {
+                RDebug::Print(_L("Test module adding failed (%d)"), ret);
+                UiError(_L("Test module adding failed"));
+                continue;
+                }
+
+            //Add test case files
+            TInt cfgCnt = moduleInfo->CountCfgFiles();
+            TInt j;
+            TFileName cfgFile;
+            for(j = 0; j < cfgCnt; j++)
+                {
+                moduleInfo->GetCfgFileName(j, cfgFile);
+                if(cfgFile.Length() > 0)
+                    {
+                    RDebug::Print(_L("config file: '%S'"), &cfgFile);
+
+                    ret = UIStore().AddTestCaseFile(moduleName, cfgFile);
+                    if(ret != KErrNone)
+                        {
+                        // Log error
+                        RDebug::Print(_L("Test case file adding failed (%d)"), ret);
+                        UiError(_L("Test case file adding failed"));
+                        continue;
+                        }
+                    }
+                else
+                    {
+                    RDebug::Print(_L("Got empty cfg file"));
+                    }
+                }
+            if(cfgCnt == 0)
+                {
+                RDebug::Print(_L("cfg file not found"));
+                }
+
+            RDebug::Print(_L("Module '%S' processed correctly"), &moduleName);
+            }
+
+        RDebug::Print(_L("End creating test modules"));
+
+        if( ( iStartCases == EStartCasesPar ) ||
+            ( iStartCases == EStartCasesSeq ) )
+            {
+            // Start running
+            CMultipleBaseMenu::TRunType runType = 
+                CMultipleBaseMenu::ERunSequential;
+            if( iStartCases == EStartCasesPar )
+                {
+                runType = CMultipleBaseMenu::ERunParallel;
+                }
+            TRAPD( err,
+                //multicasestart->StartRunningL( runType, module, file );
+                multicasestart->StartRunningL(runType, KNullDesC, KNullDesC);
+                );
+            if( err != KErrNone )
+                {
+                UiError( _L("Stating test cases failed") );
+                }
+            }
+        else if( iStartCases == EStartSingleCase )
+            {
+            // Get test case
+            RRefArray<CTestInfo> testCases;
+            //ret = UIStore().TestCases( testCases, module, file );
+            ret = UIStore().TestCases(testCases, KNullDesC, KNullDesC);
+            if( ret == KErrNone )
+                {
+                if( ( iTestCaseNum < 0 ) ||
+                    ( iTestCaseNum >= testCases.Count() ) )
+                    {
+                    ret = KErrNotFound;
+                    }
+                else
+                    {         
+                    TInt index;           
+                    // Start single test case
+                    ret = UIStore().StartTestCase( testCases[iTestCaseNum], index );
+                    }                                       
+                }
+            testCases.Reset();       
+            testCases.Close();
+            if( ret != KErrNone )
+                {
+                UiError( _L("Starting test case failed"));        
+                }
+            }
+
+        delete iTestCaseFile;
+        iTestCaseFile = 0;
+        delete iTestModuleIni;
+        iTestModuleIni = 0;
+        delete iTestModule;
+        iTestModule = 0;
+        }
+        
+    iStartCases = EStartCaseNo;
+    
+    // Load testcase if some stored 
+    UIStore().LoadSavedTestCases();
+           
+	iScroller = CScrollerTimer::NewL ( this );
+	iScroller->StartL();	
+
+    // Print the main menu
+    iCurrentMenu = iMainMenu;
+    iCurrentMenu->PrintMenuL( CMenu::EMenuPrint );
+
+    // Start to process keyboard events
+    iReader->StartL();
+    
+    return KErrNone;
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: KeyPressed
+
+    Description: Process keyboard events. Print new menu
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if SelectL leaves
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::KeyPressed()
+    {
+
+    TBool cont = ETrue;
+
+    // Read the key
+    TKeyCode key = iConsole->KeyCode();
+    CMenu* tmp = iCurrentMenu;
+
+    // Let the menu handle the key press
+    TRAPD( err, 
+        iCurrentMenu = iCurrentMenu->SelectL( key, cont );
+        );
+    if( err != KErrNone )
+        {
+        User::InfoPrint( 
+            _L("Processing keystroke failed") );  
+        }
+            
+    if ( iCurrentMenu == NULL )
+        {
+        iCurrentMenu = tmp;
+        }
+
+   // If "not-exit" key pressed, continue
+    if ( cont )
+        {
+
+        // Either only update old menu or new menu.
+        if ( tmp == iCurrentMenu )
+            {
+            TRAP( err, iCurrentMenu->PrintMenuL( CMenu::EMenuRefresh ); );
+            }
+        else
+            {
+            TRAP( err, iCurrentMenu->PrintMenuL( CMenu::EMenuPrint ); )
+            }
+        
+        if( err != KErrNone )
+            {
+            if ( err == KErrNoMemory )
+            	{            	
+            	ExitWithNoMemoryErrorMessage();                
+            	}
+            else
+            	{
+	            User::InfoPrint( 
+	                _L("Printing menu failed") );
+            	}
+            }
+
+        // Enable keystrokes
+        iReader->StartL();
+
+        }
+    else
+        {
+        // "Exit", stop scheduler and exit
+        CActiveScheduler::Stop();
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: ExitWithNoMemoryErrorMessage
+
+    Description: Displays no memory error message and closes ConsoleUI
+    
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::ExitWithNoMemoryErrorMessage()
+	{
+    // "Exit", stop scheduler and exit
+    CActiveScheduler::Stop();
+
+    _LIT( KErrorTitle, "Error:\n" );
+    _LIT( KErrorMessage, "Test cases execution have been stopped. ConsoleUI does not have enough memory to store information about executed test cases.  Results of executed test cases can be found in TestReport file. ConsoleUI will be closed now." );
+    _LIT( KErrorPressAnyKey, "\n\nPress any key" );
+    
+    TSize size = GetConsole()->ScreenSize();
+    size.iWidth = Min( size.iWidth - KMenuOverhead, 
+                       KErrorMessage().Length() );
+    size.iHeight = ( KErrorTitle().Length() + KErrorMessage().Length() + 
+    				 KErrorPressAnyKey().Length() ) / size.iWidth + 3;
+    
+    CConsoleBase* console = NULL;
+    TRAPD( err, console = Console::NewL( _L("Error note"), size ) );
+    if ( err != KErrNone )
+    	{
+    	// We can't create console, exit without displaying error message
+    	return;
+    	}
+    
+    console->Printf( KErrorTitle );    
+    console->Printf( KErrorMessage ); 
+    console->Printf( KErrorPressAnyKey );
+        
+    console->Getch();
+    
+    delete console;    
+	}
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: UiError
+
+    Description: Function is called when UI hit an error.
+    
+    Parameters: const TDesC& aInfo: in: information
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+
+void CConsoleMain::UiError( const TDesC& aInfo )
+    {
+    
+    // Error note deletes itself when it completes
+    CMenuNotifier::NewL( aInfo, this );
+    
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: Update
+
+    Description: Receives output update notification from CUIStore.
+    
+    Parameters: CStartedTestCase* aTestCase: in: Test case information
+                TInt aFlags: in: Update reason flags
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::Update( CStartedTestCase* aTestCase, TInt aFlags )
+    {
+    
+   	TInt err( KErrNone );
+    
+    // First check if some menu should be signaled 
+    if( ( aFlags & CUIStoreIf::EStatusExecuted ) &&
+        ( aTestCase->iBackPtr ) )
+        {
+        CMenu* menu = ( CMenu* )aTestCase->iBackPtr;
+        TRAP( err, 
+            menu->SignalL( aTestCase ); 
+            );            
+        }
+
+    // Update console if needed
+    if( iCurrentMenu && ( iCurrentMenu->Type() & aFlags ) )
+        {
+        if( aFlags & CUIStoreIf::EPrintUpdate )
+            {
+            CCaseExecutionView* view = 
+                ( CCaseExecutionView* )iCurrentMenu;
+            if( view->TestCase() == aTestCase )
+                {
+                TRAP( err, iCurrentMenu->PrintMenuL( CMenu::EMenuRefresh ) );
+                }
+            }
+        else
+            {
+            TRAP( err, iCurrentMenu->PrintMenuL( CMenu::EMenuRefresh ); )
+            }
+        }
+    
+    	if ( err != KErrNone )
+    		{
+    		if ( err == KErrNoMemory )
+    			{
+    			ExitWithNoMemoryErrorMessage();
+    			}
+    		}
+    
+    }
+                                                              
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: Error
+
+    Description: Function is called when test framework prints error.
+    
+    Parameters: TErrorNotification& aError: in: Error description
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+
+void CConsoleMain::Error( TErrorNotification& aError )
+    {
+    
+    // Error note deletes itself when it completes
+    CMenuNotifier::NewL( aError.iText, this );
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: PopupMsg
+
+    Description: Function is called when testframework 
+        wants to print a popup window.
+    
+    Parameters: TDesC& aMsg: in: message
+                
+
+    Return Values: Symbian OS error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+
+TInt CConsoleMain::PopupMsg( const TDesC& aLine1, 
+                             const TDesC& aLine2, 
+                             TInt aTimeInSecs )
+    {
+    
+    TInt ret = KErrNone;
+    
+    CMenuDialog* dialog = NULL;
+
+    TRAP( ret, dialog = CMenuDialog::NewL( this, aLine1, aLine2, aTimeInSecs ); );
+
+    if( ret == KErrNone )
+        {
+        iDialogs.Append( dialog ); 
+        return (TInt)dialog;
+        }
+
+    return ret;
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: PopupMsg
+
+    Description: Function is called when testframework 
+        wants to print a popup window.
+    
+    Parameters: TDesC& aMsg: in: message
+                
+
+    Return Values: Symbian OS error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+
+TInt CConsoleMain::PopupMsg( const TDesC& aLine1, 
+                             const TDesC& aLine2, 
+                             TInt aTimeInSecs,
+                             TKeyCode& aKey,
+                             TRequestStatus& aStatus )
+    {
+    
+    TInt ret = PopupMsg( aLine1, aLine2, aTimeInSecs );
+    if( ret < 0 )
+        {
+        return ret;
+        }    
+        
+    CMenuDialog* dialog = (CMenuDialog*) ret; 
+    ret = dialog->WaitForKeypress( aKey, aStatus );
+
+    return (TInt) dialog;
+    
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: Close
+
+    Description: Close instance.
+    
+    Parameters: TInt aHandle: in: handle to open instance.                
+
+    Return Values: Symbian OS error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::Close( TInt aHandle )
+    {
+    
+    if( aHandle < 0 )
+        {
+        return;
+        }
+    CMenuDialog* dialog = (CMenuDialog*) aHandle;
+    TInt index = iDialogs.Find( dialog );
+    if( index >= 0 )
+        {
+        delete dialog;
+        iDialogs.Remove( index );
+        }
+        
+    }
+           
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: GetConsole
+
+    Description: Returns the console
+
+    Parameters: None
+
+    Return Values: CConsoleBase*                    Console
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleBase* CConsoleMain::GetConsole()
+    {
+
+    return iConsole;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: TimerUpdate
+
+    Description: Updates current menu from timer
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::TimerUpdate()
+    {
+
+	iCurrentMenu->TimerUpdate();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: ParseTestModulesL
+
+    Description: Parse and search for module info and fill list of modules.
+
+    Parameters: CStifParser*     aParser:       in: CStifParser object
+                CTestModuleList* aModuleList:   in: list of modules
+                TPtrC&           aSectionStart: in: descriptor with start of section string
+                TPTrC&           aSectionEnd:   in: descriptor with end of section string
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if some of called leaving methods leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::ParseTestModulesL(CStifParser* aParser, CTestModuleList* aModuleList, const TDesC& aSectionStart, const TDesC& aSectionEnd)
+    {
+    //First let's find all modules given in Stif's ini file and store that info in CTestModuleList object
+    CStifSectionParser* sectionParser = NULL;
+    CStifItemParser* item = NULL;
+
+    sectionParser = aParser->SectionL(aSectionStart, aSectionEnd);
+
+    while(sectionParser)
+        {
+        RDebug::Print(_L("Found '%S' and '%S' sections"), &aSectionStart, &aSectionEnd);
+        CleanupStack::PushL(sectionParser);
+        RDebug::Print(_L("Starting to read module information"));
+
+        // Get name of module
+        _LIT(KModuleName, "ModuleName=");
+        item = sectionParser->GetItemLineL(KModuleName);
+        CleanupStack::PushL(item);
+        if(!item)
+            {
+            CleanupStack::PopAndDestroy(item);
+            UiError(_L("Line not found from module section"));
+            User::Leave(KErrGeneral);
+            }
+        else
+            {
+            RDebug::Print(_L("'%S' found"), &KModuleName);
+            }
+
+        TPtrC name;
+        TName moduleName;
+        TInt ret(KErrNone);
+        ret = item->GetString(KModuleName, name);
+        if(ret != KErrNone)
+            {
+            CleanupStack::PopAndDestroy(item);
+            RDebug::Print(_L("Module name parsing left with error (%d)"), ret);
+            UiError(_L("Module name parsing left with error (err)"));
+            User::Leave(ret);
+            }
+        else
+            {
+            RDebug::Print(_L("Module '%S' found from ini-file"), &name);
+            moduleName.Copy(name);
+            moduleName.LowerCase();
+            ret = aModuleList->AddTestModule(moduleName);
+            if(ret != KErrNone && ret != KErrAlreadyExists)
+                {
+                RDebug::Print(_L("Could not add module to list of modules (%d)"), ret);
+                UiError(_L("Could not add module to list of modules (err)"));
+                User::Leave(ret);
+                }
+            }
+        CleanupStack::PopAndDestroy(item);
+
+        //Get pointer to added module
+        CTestModuleInfo* moduleInfo = aModuleList->GetModule(moduleName);
+        if(!moduleInfo)
+            {
+                RDebug::Print(_L("Could not add get module info from list"));
+                UiError(_L("Could not add get module info from list"));
+                User::Leave(KErrNotFound);
+            }
+
+        // Get ini file, if it exists
+        RDebug::Print(_L("Start parsing ini file"));
+        _LIT(KIniFile, "IniFile=");
+        item = sectionParser->GetItemLineL(KIniFile);
+        if(item)
+            {
+            RDebug::Print(_L("'%S' found"), &KIniFile);
+            CleanupStack::PushL(item);
+            TPtrC iniFile;
+            ret = item->GetString(KIniFile, iniFile);
+            if(ret == KErrNone)
+                {
+                RDebug::Print(_L("Initialization file '%S' found, file can be empty"), &iniFile);
+                TFileName filename;
+                filename.Copy(iniFile);
+				TStifUtil::CorrectFilePathL(filename);
+                filename.LowerCase();
+                moduleInfo->SetIniFile(filename);
+                }
+            else
+                {
+                RDebug::Print(_L("Initialization file not found"));
+                }
+            CleanupStack::PopAndDestroy(item);
+            }
+        else
+            {
+            RDebug::Print(_L("'%S' not found"), &KIniFile);
+            }
+
+        // Get config (testcase) file
+        RDebug::Print(_L("Start parsing cfg files"));
+        TPtrC cfgTag;
+        for(TInt i = 0; i < 2; i++)
+            {
+            //Set tag for config files
+            if(i == 0)
+                {
+                cfgTag.Set(_L("ConfigFile="));
+                }
+                else
+                {
+                cfgTag.Set(_L("TestCaseFile="));
+                }
+            //Read data
+            item = sectionParser->GetItemLineL(cfgTag);
+            while(item)
+                {
+                CleanupStack::PushL(item);
+                RDebug::Print(_L("Item '%S' found"), &cfgTag);
+                TPtrC cfgFile;
+                ret = item->GetString(cfgTag, cfgFile);
+                if(ret == KErrNone)
+                    {
+                    RDebug::Print(_L("Configuration file '%S' found"), &cfgFile);
+                    TFileName ifile;
+                    ifile.Copy(cfgFile);
+					TStifUtil::CorrectFilePathL(ifile);
+                    ifile.LowerCase();
+                    moduleInfo->AddCfgFile(ifile);
+                    }
+                else
+                    {
+                    RDebug::Print(_L("Configuration file not found"));
+                    }
+                CleanupStack::PopAndDestroy(item);
+                item = sectionParser->GetNextItemLineL(cfgTag);
+                }
+            }
+
+        RDebug::Print(_L("Module '%S' information read correctly"), &moduleName);
+
+        // Get next section
+        CleanupStack::PopAndDestroy(sectionParser);
+        sectionParser = aParser->NextSectionL(aSectionStart, aSectionEnd);
+        }
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: GetMainMenu
+
+    Description: Return main menu of console.
+
+    Parameters: None
+
+    Return Values: CMainMenu*  pointer to main menu
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CMainMenu* CConsoleMain::GetMainMenu()
+    {
+    return dynamic_cast<CMainMenu*>(iMainMenu);
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: GetFilterArray
+
+    Description: Get filter array for reading purposes
+
+    Parameters: None
+
+    Return Values: const RPointerArray<TDesC>&  array with filters
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+const RPointerArray<TDesC>& CConsoleMain::GetFilterArray(void) const
+    {
+    return iFilters;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: SetFilterIndex
+
+    Description: Set info about which index filter is used
+
+    Parameters: TInt aFilterIndex: filter index selected by user
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleMain::SetFilterIndex(TInt aFilterIndex)
+    {
+    iChosenFilterIndex = aFilterIndex;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleMain
+
+    Method: GetFilterIndex
+
+    Description: Get info about which index filter is used
+
+    Parameters: None
+
+    Return Values: TInt: filter index selected by user
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CConsoleMain::GetFilterIndex(void)
+    {
+    return iChosenFilterIndex;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: NewL
+
+    Description: Construct a new CScrollerTimer object
+
+    Parameters: CConsoleMain*             :in:      Pointer to main console               
+
+    Return Values: CScrollerTimer*                         New CScrollerTimer object
+
+    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CScrollerTimer* CScrollerTimer::NewL( CConsoleMain* aMain )
+    {
+
+    CScrollerTimer* self = new ( ELeave ) CScrollerTimer();
+    CleanupStack::PushL( self );
+    self->ConstructL( aMain );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: ConstructL
+
+    Description: Second level constructor
+
+    Parameters: CConsoleMain*             :in:      Pointer to main console
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CScrollerTimer::ConstructL( CConsoleMain* aMain )
+    {
+
+    // Store module information
+    iMain = aMain;
+	iTimer.CreateLocal();
+
+	CActiveScheduler::Add ( this );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: CScrollerTimer
+
+    Description: Constructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+CScrollerTimer::CScrollerTimer() : CActive (CActive::EPriorityStandard)
+    {
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: ~CScrollerTimer
+
+    Description: None
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+CScrollerTimer::~CScrollerTimer( )
+    {
+
+	Cancel();
+	iTimer.Close();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: StartL
+
+    Description: None
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+void CScrollerTimer::StartL( )
+    {
+
+	SetActive();
+	iTimer.After ( iStatus, KScrollPeriod );	
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: RunL
+
+    Description: None
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+void CScrollerTimer::RunL( )
+    {
+
+	iMain->TimerUpdate();
+
+	// Restart request
+	SetActive();
+	iTimer.After ( iStatus, KScrollPeriod );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: DoCancel
+
+    Description: None
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+void CScrollerTimer::DoCancel( )
+    {
+
+	iTimer.Cancel();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CScrollerTimer
+
+    Method: RunError
+
+    Description: None
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/
+TInt CScrollerTimer::RunError( TInt aError)
+    {
+    if ( aError == KErrNoMemory )
+    	{
+    	iMain->ExitWithNoMemoryErrorMessage();
+    	}
+  
+	return aError;
+    }    
+
+/*
+-------------------------------------------------------------------------------
+
+    DESCRIPTION
+
+    This module contains implementation of CConsoleReader class.
+
+-------------------------------------------------------------------------------
+*/
+
+// ================= MEMBER FUNCTIONS =========================================
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: NewL
+
+    Description: Construct the console main class
+
+    Parameters: CConsoleMain* aMain: in: Pointer to main console
+                CConsoleBase* aConsole: in: Console pointer
+
+    Return Values: CConsoleReader*                    New object
+
+    Errors/Exceptions: Leaves if memory allocation fails or
+                       ConstructL leaves.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleReader* CConsoleReader::NewL( CConsoleMain* aMain, 
+                                      CConsoleBase* aConsole )
+    {
+
+    CConsoleReader* self = 
+        new ( ELeave ) CConsoleReader( aMain, aConsole );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+    
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: 
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleReader::ConstructL( )
+    {
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: CConsoleReader
+
+    Description: Constructor.
+
+    Parameters: CConsoleMain* aMain: in: Pointer to main console
+                CConsoleBase* aConsole: in: Console pointer
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleReader::CConsoleReader( CConsoleMain* aMain, 
+                                CConsoleBase* aConsole ): 
+    CActive( EPriorityStandard )
+    {
+    
+    iMain = aMain;
+    iConsole = aConsole;
+    
+    CActiveScheduler::Add( this );
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: ~CConsoleReader
+
+    Description: Destructor
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+CConsoleReader::~CConsoleReader( )
+    {	
+    
+    Cancel();    
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: StartL
+
+    Description: Construct menu objects and start the menu handling
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions:
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleReader::StartL( )
+    {
+
+    // Start to process keyboard events
+    SetActive();
+    iConsole->Read(iStatus);
+
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: RunError
+
+    Description: None
+
+    Parameters: TInt aError
+
+    Return Values: Error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+    
+-------------------------------------------------------------------------------
+*/    
+TInt CConsoleReader::RunError(TInt aError)
+    {
+    return aError;
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: RunL
+
+    Description: Process keyboard events. Print new menu
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if SelectL leaves
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleReader::RunL()
+    {
+
+    iMain->KeyPressed();
+    
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CConsoleReader
+
+    Method: DoCancel
+
+    Description: Cancel request
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+void CConsoleReader::DoCancel()
+    {
+    
+    iConsole->ReadCancel();
+    
+    }
+
+
+// ================= OTHER EXPORTED FUNCTIONS =================================
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: MainL
+
+    Description: The main function that can leave.
+    Create the CMainConsole object and create, initialise and 
+    start active scheduler.
+
+    When active scheduler is stopped, clean up memory and exit.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if memory allocation or CConsoleMain construction
+                       leaves.
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+LOCAL_C void MainL()
+    {
+
+    // Construct and install active scheduler
+    CActiveScheduler* scheduler=new ( ELeave ) CActiveScheduler;
+    CleanupStack::PushL( scheduler );
+    CActiveScheduler::Install( scheduler );
+
+    // Construct the console
+    CConsoleMain* mainConsole = CConsoleMain::NewL();
+    CleanupStack::PushL( mainConsole );
+
+    // Start the console
+    mainConsole->StartL();
+
+    // Start handling requests
+    CActiveScheduler::Start();
+    // Execution continues from here after CActiveScheduler::Stop()
+
+    // Clean-up
+    CleanupStack::PopAndDestroy( mainConsole );
+    CleanupStack::PopAndDestroy( scheduler );
+
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: E32Main
+
+    Description: The main function. Execution starts from here.
+    Create clean-up stack and trap the MainL function which does the
+    real work.
+
+    Parameters: None
+
+    Return Values: TInt                             Error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+GLDEF_C TInt E32Main()
+    {
+
+    __UHEAP_MARK;
+
+    // Get clean-up stack
+    CTrapCleanup* cleanup=CTrapCleanup::New();
+
+    // Call the main function
+    TRAPD( error, MainL() );
+
+    // Clean-up
+    delete cleanup; 
+    cleanup = NULL;
+
+    __UHEAP_MARKEND;
+
+    return error;
+
+    }
+
+#if defined(__WINS__)
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: WinsMain
+
+    Description: The WinsMain function.
+
+    Parameters: None
+
+    Return Values: TInt                             Error code
+
+    Errors/Exceptions: None
+
+    Status: Draft
+
+-------------------------------------------------------------------------------
+*/
+EXPORT_C TInt WinsMain()
+	{
+	E32Main();
+	return KErrNone;
+	}
+
+#endif // __WINS__
+
+// End of File