diff -r 000000000000 -r d6fe6244b863 filebrowser/src/FBFileEditor.cpp --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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( 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(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; iDes().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; iLength(); 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; iText()->InsertL(printOffset, ch); + printOffset++; + } + + CleanupStack::PopAndDestroy(); // buf16 + } + + // or handle in hex format + else if (iActiveMode == EFileEditorEditAsHex) + { + for (TInt i=0; iText()->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; iRead(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; iRead(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; iDes().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() - 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(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= 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; iDes().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= 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 +