--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filebrowser/src/FBFileEditor.cpp Tue Feb 02 00:17:27 2010 +0200
@@ -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
+