filebrowser/src/FBFileEditor.cpp
branchRCL_3
changeset 20 fad26422216a
parent 0 d6fe6244b863
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filebrowser/src/FBFileEditor.cpp	Wed Sep 01 12:30:35 2010 +0100
@@ -0,0 +1,1300 @@
+/*
+* 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:  
+*
+*/
+
+
+// INCLUDE FILES
+#include "FBFileEditor.h"
+#include "FBStd.h"
+#include "FB.hrh"
+#include <filebrowser.rsg>
+
+#include <utf.h>
+#include <eikedwin.h>
+#include <eikrted.h>
+#include <txtrich.h>
+#include <eikspane.h>
+#include <avkon.hrh> 
+#include <akntitle.h>
+#include <AknUtils.h> 
+#include <AknBidiTextUtils.h>
+#include <aknnotewrappers.h>
+#include <eiksbfrm.h>
+#include <AknDef.h>
+#include <layoutmetadata.cdl.h>
+
+const TUint KLeftMargin = 2;
+const TUint KRightMargin = 2;
+const TUint KHexSeparatorMargin = 4;
+
+const TInt KEditorFontHeight = 117;
+const TInt KViewerFontHeight = 117;
+const TInt KEditorFontHeightQHD = 100;
+const TInt KViewerFontHeightQHD = 100;
+
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+CFileBrowserFileEditorDlg* CFileBrowserFileEditorDlg::NewL(const TDesC& aFileName, TInt aMode)
+    {
+    CFileBrowserFileEditorDlg* self = new(ELeave) CFileBrowserFileEditorDlg(aFileName, aMode);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;    
+    }
+
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileEditorDlg::~CFileBrowserFileEditorDlg()
+    {
+    if (iEditorPF)
+        delete iEditorPF;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileEditorDlg::CFileBrowserFileEditorDlg(const TDesC& aFileName, TInt aMode) :
+    iFileName(aFileName), iActiveMode(aMode)
+    {
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::ConstructL()
+    {
+    // construct a menu bar
+    if (iActiveMode == EFileEditorEditAsText || iActiveMode == EFileEditorEditAsHex)
+        CAknDialog::ConstructL(R_FILEBROWSER_FILEEDITOR_MENUBAR);
+    else
+        CAknDialog::ConstructL(R_FILEBROWSER_FILEVIEWER_MENUBAR);
+    
+    iTextFormat = EFileBrowserCmdFileEditorSaveFormatANSIASCII;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::PreLayoutDynInitL()
+    {
+    CAknDialog::PreLayoutDynInitL();
+    
+    // set title text
+    CEikStatusPane* sp = iEikonEnv->AppUiFactory()->StatusPane();
+    CAknTitlePane* tp = static_cast<CAknTitlePane*>( sp->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+    tp->SetTextL( _L("File editor") );
+    
+    
+    // init edwin editor component
+    if (iActiveMode == EFileEditorEditAsText || iActiveMode == EFileEditorEditAsHex)
+        {
+        CCoeControl* control = CreateLineByTypeL(KNullDesC, EFileEditorDialogId, EEikCtEdwin, NULL);
+        iTextEditor = static_cast<CEikEdwin*>(control);
+        iTextEditor->SetMopParent(this);
+        iTextEditor->ConstructL(EEikEdwinOwnsWindow|EEikEdwinNoHorizScrolling|EEikEdwinInclusiveSizeFixed|EEikEdwinNoAutoSelection, 0, 0, 0 );
+        iTextEditor->CreateTextViewL();
+        iTextEditor->SetAknEditorFlags(EAknEditorFlagEnableScrollBars);
+        iTextEditor->CreateScrollBarFrameL();
+        iTextEditor->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
+        iTextEditor->ForceScrollBarUpdateL(); 
+        iTextEditor->SetBackgroundColorL(KRgbWhite);
+        iTextEditor->SetFocus(ETrue);
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::PostLayoutDynInitL()
+    {
+    CAknDialog::PostLayoutDynInitL();
+    
+    // modify layout of the texteditor
+    if (iActiveMode == EFileEditorEditAsText || iActiveMode == EFileEditorEditAsHex)
+        {
+        CGraphicsDevice* dev = iCoeEnv->ScreenDevice();
+        const TSize screenSize = dev->SizeInPixels();
+        
+        // Set the font of the editor
+        TFontSpec fontSpec = AknLayoutUtils::FontFromId(EAknLogicalFontSecondaryFont)->FontSpecInTwips();
+        fontSpec.iHeight = IsQHD(screenSize) ? KEditorFontHeightQHD : KEditorFontHeight; // set height
+        
+        TCharFormat cf(fontSpec.iTypeface.iName, fontSpec.iHeight);
+        cf.iFontPresentation.iTextColor = KRgbBlack; 
+
+        TCharFormatMask cfm;
+        cfm.SetAll();
+
+        CCharFormatLayer *charFL = CCharFormatLayer::NewL(cf, cfm);
+        iTextEditor->SetCharFormatLayer(charFL);
+
+        if (iEditorPF)
+            {
+            delete iEditorPF;
+            iEditorPF = NULL;
+            }
+
+        iEditorPF = CParaFormat::NewL();
+        iEditorPF->iLineSpacingInTwips = IsQHD(screenSize) ? KEditorFontHeightQHD : KEditorFontHeight;
+        iEditorPF->iFillColor = KRgbWhite;
+
+        TParaFormatMask pfm;
+        pfm.SetAll();
+
+        CParaFormatLayer *paraFL = CParaFormatLayer::NewL(iEditorPF, pfm);
+        iTextEditor->SetParaFormatLayer(paraFL);
+        
+
+        // set size of the editor
+        TRect rect = Rect();
+        iTextEditor->SetRect(rect);
+        //iTextEditor->Size().iWidth - (CEikScrollBar::DefaultScrollBarBreadth());
+        }
+
+    // load the file to editor or viewer
+    LoadFileL();
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::OpenFileLC(RFile& aFile, const TDesC& aFileName)
+    {
+    TInt err = aFile.Open(CEikonEnv::Static()->FsSession(), aFileName, EFileRead|EFileShareReadersOnly);
+    
+    if (err == KErrInUse)
+        {
+        CAknErrorNote* note = new(ELeave) CAknErrorNote;
+        note->ExecuteLD(_L("The file is in use, cannot open"));
+        User::Leave(KErrNone);
+        }
+    else if (err != KErrNone)
+        {
+        CAknErrorNote* note = new(ELeave) CAknErrorNote;
+        note->ExecuteLD(_L("Cannot open the file"));
+        User::Leave(KErrNone);
+        }
+    else
+        {
+        // opened succesfully, add to cleanup stack
+        CleanupClosePushL(aFile);
+        }     
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::GetTextFileMode(RFile& aFile, TInt& aFileSize)
+    {
+    iTextFormat = EFileBrowserCmdFileEditorSaveFormatANSIASCII;
+
+    // if we are working with text files, check the type first   
+    if (iActiveMode == EFileEditorEditAsText || iActiveMode == EFileEditorViewAsText)
+        {
+        TBuf8<4> BOM;
+
+        // first check for UTF-16
+        if (aFileSize >= 2 && aFile.Read(0, BOM, 2) == KErrNone)
+            {
+            if (BOM.Length()==2 && BOM[0]==0xFF && BOM[1]==0xFE)
+                {
+                iTextFormat = EFileBrowserCmdFileEditorSaveFormatUTF16LE;
+                aFileSize -= 2;
+                return;
+                }
+            else if (BOM.Length()==2 && BOM[0]==0xFE && BOM[1]==0xFF)
+                {
+                iTextFormat = EFileBrowserCmdFileEditorSaveFormatUTF16BE;
+                aFileSize -= 2;
+                return;
+                }
+            }       
+
+        // then check for UTF-8
+        if (aFileSize >= 3 && aFile.Read(0, BOM, 3) == KErrNone)
+            {
+            if (BOM.Length()==3 && BOM[0]==0xEF && BOM[1]==0xBB && BOM[2]==0xBF)
+                {
+                iTextFormat = EFileBrowserCmdFileEditorSaveFormatUTF8;
+                aFileSize -= 3;
+                return;
+                }
+            }
+            
+        
+        // none of those, seek back to beginning
+        TInt pos(0);
+        aFile.Seek(ESeekStart, pos);
+        }    
+    }
+
+
+// --------------------------------------------------------------------------------------------
+
+HBufC16* CFileBrowserFileEditorDlg::ConvertBuf8ToBuf16L(HBufC8* aBuf8)
+    {
+    __ASSERT_ALWAYS(aBuf8 != NULL, User::Panic(_L("Emp.Buf."),942));
+
+    HBufC16* buf16 = NULL;
+    TPtr8 buf8Ptr(aBuf8->Des()); 
+
+    if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatANSIASCII)
+        {
+        // simple conversion
+        buf16 = HBufC16::NewMaxL(aBuf8->Length());
+        buf16->Des().Copy(aBuf8->Des());
+        }
+    
+    else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF8)
+        {
+        // use the conversion service
+        buf16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L(aBuf8->Des());
+        }            
+
+    else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE || iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+        {
+        buf16 = HBufC16::NewL(aBuf8->Length());
+        buf16->Des().Copy(KNullDesC);
+        
+        HBufC16* oneUniCodeChar = HBufC16::NewMaxLC(1);
+        TUint16* oneUniCodeCharPtr = &oneUniCodeChar->Des()[0];
+       
+        for (TInt i=0; i<buf8Ptr.Length(); i+=2)
+            {
+            // get two 8-bit values and pack them to one 16-bit character depending of endianess
+
+            if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE)
+                {
+                oneUniCodeCharPtr[0] = TUint16((buf8Ptr[i+1] << 8) + buf8Ptr[i]);
+                }
+            else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+                {
+                oneUniCodeCharPtr[0] = TUint16((buf8Ptr[i] << 8) + buf8Ptr[i+1]);
+                }
+            
+            // append to buffer
+            buf16->Des().Append( oneUniCodeChar->Des() );
+            }
+        
+        CleanupStack::PopAndDestroy(); // oneUniCodeChar
+        } 
+    
+    return buf16; //ownership of buf16 will transferred to the caller           
+    }
+
+// --------------------------------------------------------------------------------------------
+
+HBufC8* CFileBrowserFileEditorDlg::ConvertBuf16ToBuf8L(HBufC16* aBuf16)
+    {
+    __ASSERT_ALWAYS(aBuf16 != NULL, User::Panic(_L("Emp.Buf."),943));
+
+    HBufC8* buf8 = NULL;
+    TPtr16 buf16Ptr(aBuf16->Des()); 
+
+    if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatANSIASCII)
+        {
+        // simple conversion
+        buf8 = HBufC8::NewMaxL(aBuf16->Length());
+        buf8->Des().Copy(aBuf16->Des());
+        }
+    
+    else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF8)
+        {
+        // use the conversion service
+        buf8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(aBuf16->Des());
+        }            
+
+    else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE || iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+        {
+        buf8 = HBufC8::NewL(aBuf16->Length()*2);
+        buf8->Des().Copy(KNullDesC);
+
+        TUint16* charPtr = NULL;
+        TBuf8<2> twoChars;
+        twoChars.Copy(_L8("XX"));        
+       
+        for (TInt i=0; i<aBuf16->Length(); i++)
+            {
+            charPtr = &aBuf16->Des()[i];
+            
+            // get 16-bit character to two variables
+            if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE)
+                {
+                twoChars[0] = TUint8(charPtr[0]);
+                twoChars[1] = TUint8(charPtr[0] << 8);
+                }
+            else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+                {
+                twoChars[0] = TUint8(charPtr[0] << 8);
+                twoChars[1] = TUint8(charPtr[0]);
+                }
+
+            // append to the buffer
+            buf8->Des().Append(twoChars);
+
+            } // for
+            
+        } // else if
+    
+    return buf8; //ownership of buf8 will transferred to the caller           
+    }                
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::LoadFileL()
+    {
+    // open the file for reading
+    RFile fileP;
+    OpenFileLC(fileP, iFileName);
+    
+    // get file size
+    TInt fileSize(0);
+    User::LeaveIfError(fileP.Size(fileSize));
+
+    // read BOM from file
+    GetTextFileMode(fileP, fileSize);
+
+    
+    // editor related file loading
+    if (iActiveMode == EFileEditorEditAsText || iActiveMode == EFileEditorEditAsHex)
+        {
+        // make sure that there is currently no text in the editor 
+        iTextEditor->Text()->Reset();
+
+        // set character handling related cases for the editor
+        if (iActiveMode == EFileEditorEditAsText)
+            {
+            iTextEditor->SetOnlyASCIIChars(EFalse);
+            iTextEditor->SetAknEditorCase(EAknEditorTextCase);
+            }
+        else if (iActiveMode == EFileEditorEditAsHex)
+            {
+            iTextEditor->SetOnlyASCIIChars(ETrue);
+            iTextEditor->SetAknEditorCase(EAknEditorUpperCase);
+            }  
+            
+        const TInt KBufSize(1024);
+        TInt fileOffset(0);
+        TInt printOffset(0);
+
+        HBufC8* buf = HBufC8::NewLC(KBufSize);
+        TPtr8 bufPtr(buf->Des());
+        TChar ch;
+        _LIT(KHex, "%02x");
+        TBuf<3> hexBuf;
+
+        // read to buffer and supply the editor
+        while (fileOffset < fileSize)
+            {
+            // read to buffer
+            User::LeaveIfError( fileP.Read(bufPtr, KBufSize) );
+            
+            // handle in text format
+            if (iActiveMode == EFileEditorEditAsText)
+                {
+                HBufC16* buf16 = ConvertBuf8ToBuf16L(buf);
+                CleanupStack::PushL(buf16);
+                TPtr16 buf16Ptr(buf16->Des());
+
+                // replace any line breaks and append to the editor
+                for (TInt i=0; i<buf16Ptr.Length(); i++)
+                    {
+                    ch = buf16Ptr[i] != '\n' ? (TChar)buf16Ptr[i] : (TChar)CEditableText::ELineBreak;
+                    iTextEditor->Text()->InsertL(printOffset, ch);
+                    printOffset++;
+                    }
+                
+                CleanupStack::PopAndDestroy(); // buf16
+                }
+            
+            // or handle in hex format
+            else if (iActiveMode == EFileEditorEditAsHex)
+                {
+                for (TInt i=0; i<bufPtr.Length(); i++)
+                    {
+                    hexBuf.Format(KHex, bufPtr[i]);
+                    hexBuf.UpperCase();
+                    hexBuf.Append(_L(" "));                    
+                    iTextEditor->Text()->InsertL(printOffset, hexBuf);
+                    printOffset += 3;
+                    }
+                }
+            
+            fileOffset += bufPtr.Length();
+            }
+                
+        CleanupStack::PopAndDestroy(); // buf
+
+        // make sure that the cursor position is in the beginning 
+        iTextEditor->SetCursorPosL(0, EFalse);
+        iTextEditor->NotifyNewDocumentL();
+        iTextEditor->UpdateScrollBarsL();
+        }
+
+
+    // viewer related file loading
+    else if (iActiveMode == EFileEditorViewAsText || iActiveMode == EFileEditorViewAsHex)
+        {
+        // load the entire file to buffer
+        HBufC8* buf = HBufC8::NewLC(fileSize);
+        TPtr8 bufPtr(buf->Des());
+        
+        User::LeaveIfError( fileP.Read(bufPtr, fileSize) );
+        
+        // send the buffer to viewer
+        if (iActiveMode == EFileEditorViewAsText)
+            {
+            HBufC16* buf16 = ConvertBuf8ToBuf16L(buf);
+            CleanupStack::PopAndDestroy(); // buf
+            iViewer->FormatAsTextL(buf16);
+            }
+
+        else if (iActiveMode == EFileEditorViewAsHex)
+            {
+            iViewer->FormatAsHexL(buf);
+            CleanupStack::Pop(); // buf
+            }
+        }
+
+    CleanupStack::PopAndDestroy(); // fileP
+    }
+    
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::SaveEditorDataL(TBool aQueryNewName)
+    {
+    TBool doSave(ETrue);
+    CPlainText* docText = iTextEditor->Text();
+    TInt docLength = docText->DocumentLength();
+    
+    TFileName fileName;
+    fileName.Copy(iFileName);
+    
+    // check that format of the file is valid
+    if (iActiveMode == EFileEditorEditAsHex)
+        {
+        // check every 3rd char is a space
+        for (TInt i=2; i<docLength; i+=3)
+            {
+            TPtrC docPtr = docText->Read(i, 1);
+            if (docPtr.Length() < 1 || docPtr[0] != ' ')
+                {
+                CAknErrorNote* note = new(ELeave) CAknErrorNote;
+                note->ExecuteLD(_L("Separate hex blocks with space!"));
+                return;                
+                }
+            }
+        
+        // check for valid chars
+        for (TInt i=0; i<docLength; i+=3)
+            {
+            TPtrC docPtr = docText->Read(i, 2);
+            if (docPtr.Length() < 2 || !IsHexChar(docPtr[0]) || !IsHexChar(docPtr[1]))
+                {
+                CAknErrorNote* note = new(ELeave) CAknErrorNote;
+                note->ExecuteLD(_L("Use only hex characters!"));
+                return;                
+                }
+            }
+        }
+    
+    
+    // query new file name
+    if (aQueryNewName)
+        {
+        CAknTextQueryDialog* textQuery = CAknTextQueryDialog::NewL(fileName);
+        textQuery->SetPromptL(_L("Full path:"));
+        
+        if (textQuery->ExecuteLD(R_GENERAL_TEXT_QUERY))
+            {
+            doSave = ETrue;
+            }
+        else
+            {
+            doSave = EFalse;
+            }
+        }
+
+
+    // continue with writing
+    if (doSave)        
+        {
+        RFile fileP;
+        TInt err = fileP.Replace(CEikonEnv::Static()->FsSession(), fileName, EFileWrite);
+            
+        if (err == KErrNone)    
+            {
+            CleanupClosePushL(fileP);
+            
+            const TInt KBufSize(1002);
+            TInt fileOffset(0);        
+            TInt docOffset(0);
+            TLex converter;
+            TUint hexValue(0);
+            
+            // write BOM for text files
+            if (iActiveMode == EFileEditorEditAsText)
+                {
+                if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE)
+                    {
+                    TBuf8<2> BOM;
+                    BOM.Append(0xFF);
+                    BOM.Append(0xFE);
+                    
+                    if (fileP.Write(0, BOM, 2) == KErrNone)
+                        fileOffset += 2;
+                    }
+                
+                else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+                    {
+                    TBuf8<2> BOM;
+                    BOM.Append(0xFE);
+                    BOM.Append(0xFF);
+                    
+                    if (fileP.Write(0, BOM, 2) == KErrNone)
+                        fileOffset += 2;
+                    }
+                                  
+                else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF8)
+                    {
+                    TBuf8<3> BOM;
+                    BOM.Append(0xEF);
+                    BOM.Append(0xBB);
+                    BOM.Append(0xBF);
+                    
+                    if (fileP.Write(0, BOM, 3) == KErrNone)
+                        fileOffset += 3;
+                    }                
+                }
+            
+            
+            HBufC8* buf = HBufC8::NewLC(KBufSize * 2);
+            TPtr8 bufPtr(buf->Des());      
+          
+            while (docOffset < docLength)
+                {
+                // get text from storage
+                TPtrC docPtr = docText->Read(docOffset, KBufSize);
+                bufPtr.Copy(KNullDesC);
+
+                if (iActiveMode == EFileEditorEditAsText)
+                    {
+                    HBufC16* convBuf = HBufC16::NewLC(docPtr.Length());
+                    convBuf->Des().Copy(KNullDesC);
+                    
+                     // convert to line breaks first
+                    for (TInt i=0; i<docPtr.Length(); i++)
+                        {
+                        if (docPtr[i] == CEditableText::EParagraphDelimiter) // skip extra char from the editor
+                            continue;    
+                        else if (docPtr[i] == CEditableText::ELineBreak)
+                            convBuf->Des().Append('\n');
+                        else
+                            convBuf->Des().Append(docPtr[i]);
+                        }
+ 
+                    HBufC8* buf8 = ConvertBuf16ToBuf8L(convBuf);
+                    
+                    // make sure the sizes are correct
+                    if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatANSIASCII || iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF8)
+                        {
+                        bufPtr.Copy(buf8->Des().Left(convBuf->Length())); 
+                        }
+                    else if (iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16LE || iTextFormat == EFileBrowserCmdFileEditorSaveFormatUTF16BE)
+                        {
+                        bufPtr.Copy(buf8->Des().Left(convBuf->Length()*2)); 
+                        }
+                    
+                    delete buf8;
+                    buf8 = NULL;
+
+                    CleanupStack::PopAndDestroy(); // convBuf
+                    }
+                    
+                else if (iActiveMode == EFileEditorEditAsHex)
+                    {
+                    for (TInt i=0; i<docPtr.Length(); i+=3)
+                        {
+                        if (i+1 >= docPtr.Length() - 1)
+                            break;
+                        
+                        TBuf<3> buf2;
+                        buf2.Append(docPtr[i]);
+                        buf2.Append(docPtr[i+1]);
+
+                        // convert from hex to decimal
+                        converter.Assign(buf2);
+                        if (converter.Val(hexValue, EHex) == KErrNone)
+                            {
+                            bufPtr.Append(hexValue);
+                            }
+                        }                    
+                    }
+                
+                // write to a file
+                err = fileP.Write(fileOffset, bufPtr, bufPtr.Length());
+                if (err != KErrNone)
+                    break;
+                
+                docOffset += docPtr.Length();
+                fileOffset += bufPtr.Length();
+                }
+            
+           CleanupStack::PopAndDestroy(2); // buf, fileP
+            }
+        
+        if (err == KErrNone)
+            {
+            // remember the new file name if save was succesfull
+            iFileName.Copy(fileName);
+            
+            CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote;
+            note->ExecuteLD(_L("Saved succesfully"));
+            } 
+        else if (err == KErrInUse)
+            {
+            CAknErrorNote* note = new(ELeave) CAknErrorNote;
+            note->ExecuteLD(_L("The file is in use, cannot write"));
+            User::Leave(KErrNone);
+            }
+        else
+            {
+            CAknErrorNote* note = new(ELeave) CAknErrorNote;
+            note->ExecuteLD(_L("Cannot write to the file"));
+            User::Leave(KErrNone);
+            }
+        }
+    }
+    
+// --------------------------------------------------------------------------------------------
+
+TBool CFileBrowserFileEditorDlg::IsHexChar(TInt aCh)
+    {
+    if (aCh >= '0' && aCh <= '9')
+        return ETrue;
+    else if (aCh >= 'a' && aCh <= 'f')
+        return ETrue;
+    else if (aCh >= 'A' && aCh <= 'F')
+        return ETrue;
+    else
+        return EFalse;
+    }
+      
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::ProcessCommandL(TInt aCommandId)
+    {
+    CAknDialog::ProcessCommandL(aCommandId);
+
+    switch (aCommandId)
+        {
+        case EFileBrowserCmdFileEditorViewAsText:
+            {
+            iActiveMode = EFileEditorViewAsText;
+            LoadFileL();
+            }
+            break;
+
+        case EFileBrowserCmdFileEditorViewAsHex:
+            {
+            iActiveMode = EFileEditorViewAsHex;
+            LoadFileL();
+            }
+            break;
+
+//
+        case EFileBrowserCmdFileEditorSave:
+            {
+            SaveEditorDataL();
+            }
+            break;
+            
+        case EFileBrowserCmdFileEditorSaveAs:
+            {
+            SaveEditorDataL(ETrue);
+            }
+            break;
+
+        case EFileBrowserCmdFileEditorSaveFormatANSIASCII:
+        case EFileBrowserCmdFileEditorSaveFormatUTF8:
+        case EFileBrowserCmdFileEditorSaveFormatUTF16LE:
+        case EFileBrowserCmdFileEditorSaveFormatUTF16BE:
+            {
+            iTextFormat = aCommandId;
+            }
+            break;
+            
+        case EFileBrowserCmdFileEditorEditAsText:
+            {
+            iActiveMode = EFileEditorEditAsText;
+            LoadFileL();
+            }
+            break;
+
+        case EFileBrowserCmdFileEditorEditAsHex:
+            {
+            iActiveMode = EFileEditorEditAsHex;
+            LoadFileL();
+            }
+            break;
+
+//                        
+        case EFileBrowserCmdFileEditorExit:
+            TryExitL(EAknCmdExit);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
+    {
+    if (aResourceId == R_FILEBROWSER_FILEVIEWER_MENUPANE)
+        {
+        aMenuPane->SetItemDimmed(EFileBrowserCmdFileEditorViewAsText, iActiveMode == EFileEditorViewAsText);
+        aMenuPane->SetItemDimmed(EFileBrowserCmdFileEditorViewAsHex, iActiveMode == EFileEditorViewAsHex);
+        }
+    else if (aResourceId == R_FILEBROWSER_FILEEDITOR_MENUPANE)
+        {
+        aMenuPane->SetItemDimmed(EFileBrowserCmdFileEditorEditAsText, iActiveMode == EFileEditorEditAsText);
+        aMenuPane->SetItemDimmed(EFileBrowserCmdFileEditorEditAsHex, iActiveMode == EFileEditorEditAsHex);
+        aMenuPane->SetItemDimmed(EFileBrowserCmdFileEditorSaveFormat, iActiveMode == EFileEditorEditAsHex);
+        }
+	else if (aResourceId == R_FILEBROWSER_FILEEDITOR_SAVEFORMAT_SUBMENU)
+	    {
+        aMenuPane->SetItemButtonState(iTextFormat, EEikMenuItemSymbolOn);
+	    }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+SEikControlInfo CFileBrowserFileEditorDlg::CreateCustomControlL(TInt aControlType)
+    {
+    SEikControlInfo controlInfo;
+    controlInfo.iControl = NULL;
+    controlInfo.iTrailerTextId = 0;
+    controlInfo.iFlags = 0;
+
+    if (aControlType == EFileViewerDialogControl)
+        {
+        // create a control
+        iViewer = new(ELeave) CFileBrowserFileEditorViewControl();
+        iViewer->SetMopParent(this);
+        iViewer->ConstructL();
+
+        controlInfo.iControl = iViewer;
+        }
+        
+    return controlInfo;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorDlg::SetSizeAndPosition(const TSize& /*aSize*/)
+    {
+    // fill whole window
+    TRect mainPaneRect;
+    TRect naviPaneRect;
+
+    if (Layout_Meta_Data::IsLandscapeOrientation() ||
+        iEikonEnv->AppUiFactory()->StatusPane()->CurrentLayoutResId() != R_AVKON_STATUS_PANE_LAYOUT_SMALL)
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        }
+    else
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::ENaviPane, naviPaneRect);
+        mainPaneRect.iTl.iY = naviPaneRect.Height();   
+        }
+            
+    SetRect(mainPaneRect);
+    }
+
+// --------------------------------------------------------------------------------------------
+
+TBool CFileBrowserFileEditorDlg::RunDlgLD()
+    {
+    if (iActiveMode == EFileEditorViewAsText || iActiveMode == EFileEditorViewAsHex)
+        return ExecuteLD(R_FILEBROWSER_FILEVIEWER_DIALOG);
+    else
+        return ExecuteLD(R_FILEBROWSER_FILEEDITOR_DIALOG);
+    }
+       
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileEditorViewControl::~CFileBrowserFileEditorViewControl()
+    {
+    ResetVariables();
+    }
+
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileEditorViewControl::CFileBrowserFileEditorViewControl()
+    {
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::ConstructL()
+    {
+    CreateWindowL();
+    SetBlank();
+    SetRect(Rect());
+    ActivateL();
+    
+    iTotalNumberOfLines = 0;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+TSize CFileBrowserFileEditorViewControl::MinimumSize()
+    {
+    TRect mainPaneRect;
+    TRect naviPaneRect;
+    
+    if (Layout_Meta_Data::IsLandscapeOrientation() ||
+        iEikonEnv->AppUiFactory()->StatusPane()->CurrentLayoutResId() != R_AVKON_STATUS_PANE_LAYOUT_SMALL)
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        }
+    else
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::ENaviPane, naviPaneRect);
+        mainPaneRect.iTl.iY = naviPaneRect.Height();   
+        }
+
+    return mainPaneRect.Size();
+    }
+        
+// --------------------------------------------------------------------------------------------
+
+TKeyResponse CFileBrowserFileEditorViewControl::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
+    {
+    if(aType != EEventKey)
+        return EKeyWasNotConsumed;
+    
+    // normally scroll only one line
+    TInt scrollLines(1); 
+    
+    // with special keys scroll iNumberOfLinesFitsScreen-1 lines instead
+    if (aKeyEvent.iCode == EKeyIncVolume || aKeyEvent.iCode=='#' || aKeyEvent.iCode == EKeyDecVolume || aKeyEvent.iCode=='*')
+        scrollLines = iNumberOfLinesFitsScreen-1;
+    
+    
+    if (aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyIncVolume || aKeyEvent.iCode=='#')
+        {
+        if (iCurrentLine > 0)
+            {
+            iCurrentLine -= scrollLines;
+            
+            if (iCurrentLine < 0)
+                iCurrentLine = 0;
+            
+            UpdateScrollBarL();
+            DrawNow();
+            }
+
+        return EKeyWasConsumed;
+        }
+    
+    else if (aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyDecVolume || aKeyEvent.iCode=='*')
+        {
+        if (iActiveMode == EFileEditorViewAsText)
+            {
+            // no need to scroll text if it fits to the screen
+            if (iTotalNumberOfLines <= iNumberOfLinesFitsScreen)
+                return EKeyWasConsumed;
+
+            iCurrentLine += scrollLines;
+
+            // adjust the last line to end of the screen            
+            if (iCurrentLine > iTotalNumberOfLines - iNumberOfLinesFitsScreen)
+                iCurrentLine = iTotalNumberOfLines - iNumberOfLinesFitsScreen;            
+            }
+        else if (iActiveMode == EFileEditorViewAsHex)
+            {
+            iCurrentLine += scrollLines;
+
+            // last line can be first line on the screen            
+            if (iCurrentLine > iTotalNumberOfLines - 1)
+                iCurrentLine = iTotalNumberOfLines - 1;              
+            }
+            
+        UpdateScrollBarL();
+        DrawNow();
+        
+        return EKeyWasConsumed;
+        }
+    
+    return EKeyWasNotConsumed;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::FormatAsTextL(HBufC16* aBuf)
+    {
+    if (aBuf == NULL)    
+        ResetVariables(EFalse);
+    else
+        ResetVariables();
+    
+    InitVariables();
+    iActiveMode = EFileEditorViewAsText;
+    
+    // store the bugger
+    if (aBuf != NULL)
+        iTextBuf = aBuf;
+    
+    iWrappedTextArray = new(ELeave) CArrayFixFlat<TPtrC>(32);
+    
+    // wrap to array
+    AknTextUtils::WrapToArrayL(iTextBuf->Des(), iDrawingWidth, *iFont, *iWrappedTextArray);
+    iTotalNumberOfLines = iWrappedTextArray->Count();
+
+    // count amount of lines fits to screen
+    iNumberOfLinesFitsScreen = TInt(iViewerRect.Height() / (iFont->HeightInPixels()));
+
+    // update scroll bars
+    UpdateScrollBarL();
+
+    // update the screen
+    DrawNow();    
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::FormatAsHexL(HBufC8* aBuf)
+    {
+    if (aBuf == NULL)    
+        ResetVariables(EFalse);
+    else
+        ResetVariables();
+    
+    InitVariables();
+    iActiveMode = EFileEditorViewAsHex;
+    
+    // store the buffer
+    if (aBuf != NULL)
+        iHexesBuffer = aBuf;
+    
+    // calculate amount of hex values fits to the screen
+    TUint charWidth = iFont->CharWidthInPixels('X');
+    iHexGrougWidth = charWidth*2 + TInt (KHexSeparatorMargin*iX_factor);
+    iAmountOfHexesFitsHorizontally = TUint( iDrawingWidth / iHexGrougWidth );
+
+    // calculate total number of files
+    iTotalNumberOfLines = iHexesBuffer->Length() / iAmountOfHexesFitsHorizontally + 1;
+
+    // count amount of lines fits to screen
+    iNumberOfLinesFitsScreen = TInt(iViewerRect.Height() / iFont->HeightInPixels()) - 1;
+
+    // update scroll bars
+    UpdateScrollBarL();
+
+    // update the screen
+    DrawNow();      
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::InitVariables()
+    {
+    iCurrentLine = 0;
+
+    // calculate layout data
+    TRect mainPaneRect;
+    TRect naviPaneRect;
+    
+    if (Layout_Meta_Data::IsLandscapeOrientation() ||
+        iEikonEnv->AppUiFactory()->StatusPane()->CurrentLayoutResId() != R_AVKON_STATUS_PANE_LAYOUT_SMALL)
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        }
+    else
+        {
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
+        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::ENaviPane, naviPaneRect);
+        mainPaneRect.iTl.iY = naviPaneRect.Height();   
+        }
+
+    iViewerRect = TRect(mainPaneRect.Size());
+
+    iX_factor = TReal(iViewerRect.Width()) / 176;
+    iY_factor = TReal(iViewerRect.Height()) / 144;
+
+
+    // define drawing width, some extra space needed for double span scrolling bar
+    if (AknLayoutUtils::LayoutMirrored())  // scroll bar on 'left'
+        {
+        iLeftDrawingPosition = KLeftMargin + 12;
+        iDrawingWidth = TUint( iViewerRect.Width() - iLeftDrawingPosition*iX_factor - (KRightMargin*iX_factor)); 
+        }
+    else // scroll bar on 'right'
+        {
+        iLeftDrawingPosition = KLeftMargin;  
+        iDrawingWidth = TUint( iViewerRect.Width() - iLeftDrawingPosition*iX_factor - (KRightMargin*iX_factor + 7*iX_factor)); 
+        } 
+
+
+    // set font
+    CGraphicsDevice* dev = iCoeEnv->ScreenDevice();
+    const TSize screenSize = dev->SizeInPixels();
+    
+    TFontSpec fontSpec = AknLayoutUtils::FontFromId(EAknLogicalFontSecondaryFont)->FontSpecInTwips();
+    fontSpec.iHeight = IsQHD(screenSize) ? KViewerFontHeightQHD : KViewerFontHeight; // set height
+    dev->GetNearestFontInTwips(iFont, fontSpec);
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::ResetVariables(TBool aResetData)
+    {
+    if (iScrollBarFrame)
+        {
+        delete iScrollBarFrame;
+        iScrollBarFrame = NULL;
+        }
+        
+    if (iHexesBuffer && aResetData)
+        {
+        delete iHexesBuffer;
+        iHexesBuffer = NULL;
+        }    
+
+    if (iWrappedTextArray)
+        {
+        delete iWrappedTextArray;
+        iWrappedTextArray = NULL;
+        }
+
+    if (iTextBuf && aResetData)
+        {
+        delete iTextBuf;
+        iTextBuf = NULL;
+        }
+
+    if (iFont)
+        {
+        CGraphicsDevice* dev = iCoeEnv->ScreenDevice();
+        dev->ReleaseFont(iFont);
+        iFont = NULL;
+        }
+    }
+    
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::UpdateScrollBarL()
+    {
+    TRect rect(iViewerRect);
+    
+    // init the scroll bar    
+    if (!iScrollBarFrame)
+        {
+        iScrollBarFrame = new(ELeave) CEikScrollBarFrame(this, this, ETrue);
+        iScrollBarFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse);            
+        iScrollBarFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan);
+        iScrollBarFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
+        }       
+
+
+    // update values
+	TEikScrollBarModel horizontalBar;
+    TEikScrollBarModel verticalBar;
+
+    if (iActiveMode == EFileEditorViewAsText)
+        {    
+        verticalBar.iThumbPosition = iCurrentLine;
+        verticalBar.iScrollSpan = iTotalNumberOfLines - iNumberOfLinesFitsScreen + 1;
+        verticalBar.iThumbSpan = 1;
+        }
+    
+    else if (iActiveMode == EFileEditorViewAsHex)
+        {    
+        verticalBar.iThumbPosition = iCurrentLine;
+        verticalBar.iScrollSpan = iTotalNumberOfLines;
+        verticalBar.iThumbSpan = 1;
+        }
+        
+    TEikScrollBarFrameLayout layout;
+	layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant;
+
+    // do not let scrollbar values overflow
+    if (verticalBar.iThumbPosition + verticalBar.iThumbSpan > verticalBar.iScrollSpan)
+        verticalBar.iThumbPosition = verticalBar.iScrollSpan - verticalBar.iThumbSpan;
+	
+    TAknDoubleSpanScrollBarModel horizontalDSBar(horizontalBar);
+    TAknDoubleSpanScrollBarModel verticalDSBar(verticalBar);
+   
+    iScrollBarFrame->TileL(&horizontalDSBar, &verticalDSBar, rect, rect, layout);        
+    iScrollBarFrame->SetVFocusPosToThumbPos(verticalDSBar.FocusPosition());
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::Draw(const TRect& aRect) const
+    {
+    CWindowGc& gc = SystemGc();
+    gc.Clear(aRect);
+    gc.SetPenColor(KRgbBlack);
+    gc.UseFont(iFont);
+    
+    TInt fontHeight = iFont->HeightInPixels();
+
+    if (iActiveMode == EFileEditorViewAsText)
+        {
+        // draw the text
+        for (TInt i=0; i<iNumberOfLinesFitsScreen; i++)
+            {
+            // check for bounds and draw
+            if (iCurrentLine >= 0 && iTotalNumberOfLines > i+iCurrentLine)
+                gc.DrawText(iWrappedTextArray->At(i+iCurrentLine), TPoint(TInt(iLeftDrawingPosition*iX_factor), TInt(fontHeight*(i+1))));
+            }        
+        }
+
+    else if (iActiveMode == EFileEditorViewAsHex)
+        {
+        TInt hexesOffSet = iCurrentLine * iAmountOfHexesFitsHorizontally; 
+        TInt topLineHeight = 2*iY_factor + fontHeight;
+        
+        // draw the top line
+        gc.SetPenColor(KRgbWhite);
+        
+        gc.SetBrushColor(KRgbBlue);
+        gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+        if (AknLayoutUtils::LayoutMirrored())  // scroll bar on 'left'
+            {
+            gc.DrawRect(TRect((KLeftMargin + 12)*iX_factor, 0, aRect.iBr.iX, topLineHeight));
+            }
+        else // scroll bar on 'right'
+            {
+            gc.DrawRect(TRect(0, 0, aRect.iBr.iX-(KRightMargin*iX_factor + 7*iX_factor), topLineHeight));
+            } 
+
+        TBuf<128> topLineBuf;
+        topLineBuf.AppendNum(hexesOffSet);
+        topLineBuf.Append(_L(": "));
+        
+        for (TInt i=0; i<iAmountOfHexesFitsHorizontally; i++)
+            {
+            TInt pos = hexesOffSet + i;
+            
+            if (pos < iHexesBuffer->Des().Length())
+                {
+                topLineBuf.Append(iHexesBuffer->Des()[pos]);
+                }
+            }
+ 
+        gc.DrawText(topLineBuf, TPoint(TInt(iLeftDrawingPosition*iX_factor), TInt(fontHeight)));
+
+ 
+        // draw hex values
+        gc.SetPenColor(KRgbBlack);
+        for (TInt i=0; i<iNumberOfLinesFitsScreen; i++)
+            {
+            for (TInt j=0; j<iAmountOfHexesFitsHorizontally; j++)
+                {
+                TInt pos = hexesOffSet + i*iAmountOfHexesFitsHorizontally + j;
+                
+                if (pos >= iHexesBuffer->Des().Length())
+                    return;
+                
+                TUint8* ptr = &iHexesBuffer->Des()[pos];
+                
+                _LIT(KHex, "%02x");
+                TBuf<5> hexBuf;
+                hexBuf.Format(KHex, ptr[0]);
+                hexBuf.UpperCase();
+
+                gc.DrawText(hexBuf, TPoint(TInt(iLeftDrawingPosition*iX_factor + j*iHexGrougWidth), TInt(topLineHeight + fontHeight*(i+1))));
+                }
+            }         
+        }
+
+    gc.DiscardFont();
+    }
+  
+// --------------------------------------------------------------------------------------------
+
+CCoeControl* CFileBrowserFileEditorViewControl::ComponentControl(TInt aIndex) const
+	{
+	if (aIndex == 0 && iScrollBarFrame)
+	    return iScrollBarFrame->VerticalScrollBar();
+	else
+	    return NULL;
+	}
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileEditorViewControl::CountComponentControls() const
+	{
+	if (iScrollBarFrame)
+	    return 1;
+	else
+	    return 0;
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEventType)
+    {
+    if ((aEventType == EEikScrollPageDown) || (aEventType == EEikScrollPageUp) || 
+       (aEventType == EEikScrollThumbDragVert) || (aEventType == EEikScrollUp) ||
+       (aEventType == EEikScrollDown))
+        {
+        iCurrentLine = aScrollBar->ThumbPosition();
+        UpdateScrollBarL();
+        DrawNow();
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+ 
+TTypeUid::Ptr CFileBrowserFileEditorViewControl::MopSupplyObject(TTypeUid aId)
+    {
+    return CCoeControl::MopSupplyObject(aId);
+    }
+	   
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileEditorViewControl::HandleResourceChange(TInt aType)
+    {
+    if (aType == KEikDynamicLayoutVariantSwitch)
+        {
+        SetRect(Rect());
+        ActivateL();
+        
+        // reformat the text
+        if (iActiveMode == EFileEditorViewAsText)
+            {
+            FormatAsTextL();
+            }
+        else if (iActiveMode == EFileEditorViewAsHex)
+            {
+            FormatAsHexL();
+            }
+        }
+    else
+        {
+        CCoeControl::HandleResourceChange(aType);
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+// End of File
+