commands/fed/src/fed.cpp
changeset 0 7f656887cf89
child 78 b3ffff030d5c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/fed/src/fed.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,376 @@
+// fed.cpp
+// 
+// Copyright (c) 2009 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include <e32cons.h>
+#include <BADESCA.H>
+#include <charconv.h>
+
+#include "fed.h"
+#include "viewbase.h"
+#include "bufferbase.h"
+#include "screenmngr.h"
+#include "cmdwindow.h"
+
+#include "filebuffer.h"
+#include "lrtextview.h"
+
+const TInt KDefScreenPosX = 0;
+const TInt KDefScreenPosY = 0;
+
+CFed* CFed::NewL(CColorConsoleBase& aConsole, RFs& aFs)
+	{
+	CFed* fed = new (ELeave) CFed(aConsole, aFs);
+	CleanupStack::PushL(fed);
+	fed->ConstructL();
+	CleanupStack::Pop(fed);
+	return fed;
+	}
+
+CFed* CFed::NewL(CConsoleBase& aConsole, RFs& aFs)
+	{
+	CFed* fed = new (ELeave) CFed(aConsole, aFs);
+	CleanupStack::PushL(fed);
+	fed->ConstructL();
+	CleanupStack::Pop(fed);
+	return fed;
+	}
+
+CFed::CFed(CColorConsoleBase& aConsole, RFs& aFs)
+	: CActive(CActive::EPriorityStandard), iFs(aFs), iConsole(aConsole), iColorConsole(&aConsole), iViewIdx(-1)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CFed::CFed(CConsoleBase& aConsole, RFs& aFs)
+	: CActive(CActive::EPriorityStandard), iFs(aFs), iConsole(aConsole), iViewIdx(-1)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CFed::~CFed()
+	{
+	Cancel();
+	for (TInt i = iViewArray.Count()-1; i >= 0; i--)
+		delete iViewArray[i];
+	iViewArray.Reset();
+	delete iCmdWindow;
+	delete iCharconv;
+	}
+
+void CFed::ConstructL()
+	{
+	iFs.CreatePrivatePath(EDriveC);
+	TSize size = iConsole.ScreenSize();
+	iScreenMngr.ResizeScreenL(TWindow(KDefScreenPosX, KDefScreenPosY, size.iWidth, size.iHeight));
+	if (iColorConsole)
+		{
+		iCmdWindow = CCommandWindow::NewL(iFs, *iColorConsole);
+		}
+	else
+		{
+		iCmdWindow = CCommandWindow::NewL(iFs, iConsole);
+		}
+	iCmdWindow->SetWindow(iScreenMngr.GetCommandWindow());
+	
+	TRAPD(err, iCharconv = CCnvCharacterSetConverter::NewL());
+	if (!err)
+		{
+		// This can fail if charconv isn't properly configured in the ROM
+		ASSERT(iCharconv->PrepareToConvertToOrFromL(KCharacterSetIdentifierUtf8, iFs) == CCnvCharacterSetConverter::EAvailable);
+		}
+	}
+
+void CFed::StartL(CDesC16Array* aFiles)
+	{
+	CleanupStack::PushL(aFiles);
+	CreateViewsL(aFiles);
+	CleanupStack::PopAndDestroy(aFiles);
+
+	iConsole.Read(iStatus);
+	SetActive();
+	}
+
+//CActive
+void CFed::DoCancel()
+	{
+	iConsole.ReadCancel();
+	}
+
+void CFed::RunL()
+	{
+	if(iStatus.Int() < 0)
+		{
+		CActiveScheduler::Stop();
+		return;
+		}
+
+	TKeyCode code = iConsole.KeyCode();
+	TCmdType cmd = ProcessKeyL(code);
+
+	if(!ExecuteCommandL(cmd) && iViewIdx >= 0)
+		iViewArray[iViewIdx]->ConsumeKeyL(code);
+	if(iViewArray.Count() == 0)
+		{
+		// No more views, time to exit.
+		// Set the cursor to the bottom of the screen before we do - easier for the user to see that we've exited
+		TSize screenSize = iConsole.ScreenSize();
+		iConsole.SetPos(screenSize.iWidth-1, screenSize.iHeight-1); // Bottom right corner
+		iConsole.Write(_L(" ")); // This should cause the window to scroll and the cursor to be on the bottom line
+		CActiveScheduler::Stop();
+		return;
+		}
+
+	iConsole.Read(iStatus);
+	SetActive();
+	}
+
+TInt CFed::RunError(TInt aError)
+	{
+	if (iCmdWindow)
+		{
+		iCmdWindow->InfoPrint(_L("Leave occurred: %d"), aError);
+
+		// And rerequest further keys
+		iConsole.Read(iStatus);
+		SetActive();
+
+		return KErrNone;
+		}
+	return aError;
+	}
+
+void CFed::CreateViewsL(CDesC16Array* aFiles)
+	{
+	TInt n = aFiles->Count();
+	for (TInt i = 0; i < n; i++)
+		{
+		NewViewL((*aFiles)[i], ETrue);
+		}
+
+	if (n == 0)
+		{
+		// Create a new untitled view instead
+		NewViewL(KNullDesC);
+		}
+	if (iCharconv)
+		{
+		iCmdWindow->InfoPrint(_L("Welcome to fed. Press Ctrl-L for help."));
+		}
+	else
+		{
+		iCmdWindow->InfoPrint(_L("Warning: couldn't load charconv. UTF-8 not available."));
+		}
+	}
+
+CFed::TCmdType CFed::ProcessKeyL(const TKeyCode& aCode)
+	{
+	switch(aCode)
+		{
+	case CTRL('q'):
+		return ECmdCloseAll;
+	case EKeyF1:
+	case CTRL('l'):
+		return ECmdHelp;
+	case EKeyF2:
+	case CTRL('p'):
+		return ECmdPrevView;
+	case EKeyF3:
+	case CTRL('}'):
+		return ECmdNextView;
+	case EKeyEscape:
+	case CTRL('w'):
+		return ECmdCloseCurrent;
+	case CTRL('n'):
+		return ECmdNewDocument;
+	case CTRL('o'):
+		return ECmdOpenDocument;
+	case CTRL('r'):
+	case EKeyF5:
+		return ECmdRefresh;
+	default:
+		break;
+		}
+	return ECmdNone;
+	}
+
+TBool CFed::ExecuteCommandL(TCmdType aCmd)
+{
+	switch(aCmd)
+		{
+		case ECmdHelp:
+			::ShowHelpL();
+			break;
+		case ECmdPrevView:
+			iViewIdx--;
+			if (iViewIdx < 0) iViewIdx = iViewArray.Count()-1;
+			iScreenMngr.AttachViewL(*iViewArray[iViewIdx]);
+			break;
+		case ECmdNextView:
+			iViewIdx++;
+			if (iViewIdx >= iViewArray.Count()) iViewIdx = 0;
+			iScreenMngr.AttachViewL(*iViewArray[iViewIdx]);
+			break;
+		case ECmdCloseCurrent:
+			CloseCurrentViewL();
+			break;
+		case ECmdCloseAll:
+			CloseAllViewsL();
+			break;
+		case ECmdNewDocument:
+			NewViewL(KNullDesC);
+			break;
+		case ECmdOpenDocument:
+			OpenDocumentL();
+			break;
+		case ECmdRefresh:
+			iScreenMngr.RefreshScreenL();
+			break;
+		default:
+			return EFalse;
+		}
+	return ETrue;
+}
+
+TBool CFed::CloseCurrentViewL()
+{
+	if(iViewIdx < 0)
+		{
+		//Show a message to the user that there is nothing to close
+		return EFalse;
+		}
+
+	CFedViewBase* view = iViewArray[iViewIdx];
+	TBool okToClose = ETrue; 
+	if (view->Buffer().RefCount() == 1)
+		{
+		// We're the only view on this buffer - better ask about saving
+		okToClose = view->TryCloseL();
+		}
+
+	if (okToClose)
+		{
+		DeleteView();
+		}
+	return okToClose;
+	}
+
+void CFed::CloseAllViewsL()
+{
+	TBool ret = ETrue;
+	while(iViewIdx >=0 && ret)
+		ret = CloseCurrentViewL();
+}
+
+void CFed::DeleteView()
+	{
+	delete iViewArray[iViewIdx];
+	iViewArray.Remove(iViewIdx);
+	iScreenMngr.UnsetCurrentView();
+	if (iViewIdx >= iViewArray.Count())
+		{
+		iViewIdx = iViewArray.Count()-1;
+		}
+	if (iViewIdx >= 0)
+		{
+		// Attach the new frontmost view
+		iScreenMngr.AttachViewL(*(iViewArray[iViewIdx]));
+		}
+	}
+
+void CFed::NewViewL(const TDesC& aFileName, TBool aPromptOnNonexistantName)
+	{
+	CFileBuffer* buffer = NULL;
+	TRAPD(err, buffer = CFileBuffer::NewL(iFs, iCharconv, aFileName, EFalse));
+	if ((err == KErrNotFound || err == KErrPathNotFound) && aPromptOnNonexistantName)
+		{
+		if (iCmdWindow->Query(_L("File not found. Create? (yes/no) "), _L("yn")) == 'y')
+			{
+			buffer = CFileBuffer::NewL(iFs, iCharconv, aFileName, ETrue);
+			err = KErrNone;
+			}
+		}
+	User::LeaveIfError(err);
+
+	buffer->PushL();
+	CLRTextView* view = CLRTextView::NewL(*iCmdWindow, *buffer);
+	CleanupStack::Pop(buffer);
+	buffer->DecRef(); // view now has a ref to it
+	CleanupStack::PushL(view);
+	iViewArray.AppendL(view);
+	CleanupStack::Pop(view);
+	iViewIdx = iViewArray.Count()-1;
+	iScreenMngr.AddViewL(*view);
+	}
+
+void CFed::OpenDocumentL()
+	{
+	TFileName name;
+	TBool go = iCmdWindow->QueryFilename(_L("Open file: "), name);
+	if (go)
+		{
+		TInt prevIdx = iViewIdx;
+		TRAPD(err, NewViewL(name));
+		if (err)
+			{
+			switch (err)
+				{
+				case KErrNotFound:
+					iCmdWindow->InfoPrint(_L("File '%S' not found"), &name);
+					break;
+				case KErrPathNotFound:
+					iCmdWindow->InfoPrint(_L("KErrPathNotFound. Directory doesn't exist?"));
+					break;
+				case KErrBadName:
+					iCmdWindow->InfoPrint(_L("Bad name"));
+					break;
+				default:
+					iCmdWindow->InfoPrint(_L("Unable to open file: %d."), err);
+					break;
+				}
+			}
+		else if (!err && prevIdx >= 0)
+			{
+			CFedViewBase* prevView = iViewArray[prevIdx];
+			if (prevView->Buffer().Editable() && !prevView->Buffer().Modified() && prevView->Buffer().Title().Length() == 0)
+				{
+				// Then previous doc was an empty, untitled window, which this open should replace
+				delete prevView;
+				iViewArray.Remove(prevIdx);
+				iViewIdx = iViewArray.Count()-1;
+				}
+			}
+		}
+	}
+
+// Not usable: ^H = Bksp, ^M = CR, ^I = Tab, ^J = LF, ^Z = suspend, ^[ = Esc
+// Currently free: ^E, ^Y
+void CFed::ShowHelpL(HBufC* aHelpText)
+	{
+	_LIT(KHelpTitle, "Fed Help");
+	CleanupStack::PushL(aHelpText);
+	CConstDataBuffer* helpBuf = new(ELeave) CConstDataBuffer(KHelpTitle, aHelpText);
+	CleanupStack::Pop(aHelpText);
+	helpBuf->PushL();
+	CLRTextView* view = CLRTextView::NewL(*iCmdWindow, *helpBuf);
+	CleanupStack::Pop(helpBuf);
+	helpBuf->DecRef(); // view now has a ref to it
+	CleanupStack::PushL(view);
+	iViewArray.AppendL(view);
+	CleanupStack::Pop(view);
+	iViewIdx = iViewArray.Count()-1;
+	iScreenMngr.AddViewL(*view);
+	}
+
+void CFed::RedrawEverythingL()
+	{
+	ExecuteCommandL(ECmdRefresh);
+	}