--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/iosrv/server/persistentconsole.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,1189 @@
+// persistentconsole.cpp
+//
+// Copyright (c) 2008 - 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 "persistentconsole.h"
+#include <e32hashtab.h>
+
+
+static void CleanupNullPointer(TAny* aPtrPtr)
+ {
+ *((TAny**)aPtrPtr) = NULL;
+ }
+
+static void CleanupNullPointerPushL(TAny** aPtr)
+ {
+ CleanupStack::PushL(TCleanupItem(CleanupNullPointer, aPtr));
+ }
+
+_LIT(KProxySuffix, "_proxy");
+
+//______________________________________________________________________________
+// CIoPersistentConsole
+CIoPersistentConsole* CIoPersistentConsole::NewLC(const TDesC& aName, const TDesC& aTitle, CIoServer& aServer, const RMsg& aMessage)
+ {
+ CIoPersistentConsole* self = new(ELeave)CIoPersistentConsole(aServer);
+ CleanupClosePushL(*self);
+ self->ConstructL(aName, aTitle, aMessage);
+ return self;
+ }
+
+TBool CIoPersistentConsole::CanConnectReaderL(const MIoReadEndPoint& aReader) const
+ {
+ // check that the candidate end point will not result in a circular connection of
+ // persistent consoles if it's connected to this one.
+
+ RHashSet<TInt> chained; // addresses of CIoPersistentConsole's in any chain
+ CleanupClosePushL(chained);
+ chained.InsertL((TInt)this);
+ const MIoReadEndPoint* nextReader = &aReader;
+ while (nextReader && nextReader->IoepIsType(RIoHandle::EPersistentConsole))
+ {
+ const CIoPersistentConsole* next = (const CIoPersistentConsole*)nextReader;
+ if (chained.Find((TInt)next))
+ {
+ CleanupStack::PopAndDestroy();
+ return EFalse;
+ }
+ chained.InsertL((TInt)next);
+ nextReader = next->TransientReader();
+ }
+ CleanupStack::PopAndDestroy();
+ return ETrue;
+ }
+
+void CIoPersistentConsole::AttachTransientReaderL(MIoReadEndPoint& aReader, CIoSession* aDetachOnClose)
+ {
+ if (!CanConnectReaderL(aReader)) User::Leave(KErrCouldNotConnect);
+
+ if (iTransientReadEndPoint)
+ {
+ User::Leave(KErrInUse);
+ }
+
+
+ iTransientReadEndPoint = &aReader;
+ CleanupNullPointerPushL((TAny**)&iTransientReadEndPoint);
+
+ TInt fgProxyPos = ReaderProxyIndex(AttachedReader());
+ if (fgProxyPos != KErrNotFound)
+ {
+ iTransientReadEndPoint->IorepAttachL(*iReaderProxies[fgProxyPos], RIoEndPoint::EForeground);
+ }
+
+ TInt i = 0;
+ TRAPD(err,
+ for (i=0; i<iReaderProxies.Count(); ++i)
+ {
+ if (i != fgProxyPos)
+ {
+ iTransientReadEndPoint->IorepAttachL(*iReaderProxies[i], RIoEndPoint::EBackground);
+ }
+ }
+ );
+
+ if (err)
+ {
+ // deatch the readers the we successfully attached before failure
+ for (TInt j=0; j<i; ++j)
+ {
+ iTransientReadEndPoint->IorepDetach(*iReaderProxies[j]);
+ }
+ // also make sure that the foreground reader is deatched
+ if (fgProxyPos >= i)
+ {
+ iTransientReadEndPoint->IorepDetach(*iReaderProxies[fgProxyPos]);
+ }
+ User::Leave(err);
+ }
+ CleanupStack::Pop();
+
+ iReadEndPointDetachOnClose = aDetachOnClose;
+
+ // now foreward any outstanding read requests
+ for (TInt i=0; i<iReaderProxies.Count(); ++i)
+ {
+ iReaderProxies[i]->TransientReaderAttached(*iTransientReadEndPoint);
+ }
+
+ MIoReader* fg = AttachedReader();
+ if (fg)
+ {
+ fg->IorReaderChange(RIoReadHandle::EGainedForeground | RIoReadHandle::EConsoleSizeChanged);
+ }
+ }
+
+void CIoPersistentConsole::DetachTransientReader()
+ {
+ if (!iTransientReadEndPoint)
+ {
+ return;
+ }
+ MIoReadEndPoint* detaching = iTransientReadEndPoint;
+ iTransientReadEndPoint = NULL;
+
+ TInt fgReaderPos = ReaderProxyIndex(AttachedReader());
+ for (TInt i=0; i<iReaderProxies.Count(); ++i)
+ {
+ if (i!=fgReaderPos)
+ {
+ detaching->IorepDetach(*iReaderProxies[i]);
+ }
+ }
+ if (fgReaderPos!=KErrNotFound)
+ {
+ detaching->IorepDetach(*iReaderProxies[fgReaderPos]);
+ }
+ iReadEndPointDetachOnClose = NULL;
+
+ SendReadDetachNotifications();
+ }
+
+const MIoReadEndPoint* CIoPersistentConsole::TransientReader() const
+ {
+ return iTransientReadEndPoint;
+ }
+
+TBool CIoPersistentConsole::CanConnectWriterL(const MIoWriteEndPoint& aWriter) const
+ {
+ // check that the candidate end point will not result in a circular connection of
+ // persistent consoles if it's connected to this one.
+
+ RHashSet<TInt> chained; // addresses of CIoPersistentConsole's in any chain
+ CleanupClosePushL(chained);
+ chained.InsertL((TInt)this);
+ const MIoWriteEndPoint* nextWriter = &aWriter;
+ while (nextWriter && nextWriter->IoepIsType(RIoHandle::EPersistentConsole))
+ {
+ const CIoPersistentConsole* next = (const CIoPersistentConsole*)nextWriter;
+ if (chained.Find((TInt)next))
+ {
+ CleanupStack::PopAndDestroy();
+ return EFalse;
+ }
+ chained.InsertL((TInt)next);
+ nextWriter = next->TransientWriter();
+ }
+ CleanupStack::PopAndDestroy();
+ return ETrue;
+ }
+
+void CIoPersistentConsole::AttachTransientWriterL(MIoWriteEndPoint& aWriter, CIoSession* aDetachOnClose)
+ {
+ if (!CanConnectWriterL(aWriter)) User::Leave(KErrCouldNotConnect);
+
+ if (iTransientWriteEndPoint)
+ {
+ User::Leave(KErrInUse);
+ }
+ iTransientWriteEndPoint = &aWriter;
+ CleanupNullPointerPushL((TAny**)&iTransientWriteEndPoint);
+
+ TInt i = 0;
+ TRAPD(err,
+ for (i=0; i<iWriterProxies.Count(); ++i)
+ {
+ iTransientWriteEndPoint->IowepAttachL(*iWriterProxies[i]);
+ }
+ );
+ if (err)
+ {
+ // deatch the writers the we successfully attached before failure
+ for (TInt j=0; j<i; ++j)
+ {
+ iWriterProxies[j]->TransientWriterDetach(*iTransientWriteEndPoint);
+ }
+ User::Leave(err);
+ }
+ CleanupStack::Pop();
+
+ iWriteEndPointDetachOnClose = aDetachOnClose;
+
+ TRAP_IGNORE(iTransientWriteEndPoint->IowepSetTitleL(iTitleSetter));
+
+ for (TInt i=0; i<iWriterProxies.Count(); ++i)
+ {
+ iWriterProxies[i]->TransientWriterAttached(*iTransientWriteEndPoint);
+ }
+ }
+
+void CIoPersistentConsole::DetachTransientWriter()
+ {
+ if (!iTransientWriteEndPoint)
+ {
+ return;
+ }
+ MIoWriteEndPoint* detaching = iTransientWriteEndPoint;
+ iTransientWriteEndPoint = NULL;
+ for (TInt i=0; i<iWriterProxies.Count(); ++i)
+ {
+ iWriterProxies[i]->TransientWriterDetach(*detaching);
+ }
+ iWriteEndPointDetachOnClose = NULL;
+
+ SendWriteDetachNotifications();
+ }
+
+const MIoWriteEndPoint* CIoPersistentConsole::TransientWriter() const
+ {
+ return iTransientWriteEndPoint;
+ }
+
+MIoWriteEndPoint* CIoPersistentConsole::TransientWriter()
+ {
+ return iTransientWriteEndPoint;
+ }
+
+void CIoPersistentConsole::NotifyReadDetachL(const RMsg& aMessage)
+ {
+ if ((iReaderProxies.Count()==0) || !iTransientReadEndPoint)
+ {
+ Complete(aMessage, KErrNone);
+ }
+ else
+ {
+ iReadDetachNotifications.AppendL(aMessage);
+ }
+ }
+
+void CIoPersistentConsole::CancelNotifyReadDetach(TRequestStatus* aClientStatus)
+ {
+ for (TInt i=0; i<iReadDetachNotifications.Count(); ++i)
+ {
+ if (iReadDetachNotifications[i].ClientStatus() == aClientStatus)
+ {
+ Complete(iReadDetachNotifications[i], KErrCancel);
+ iReadDetachNotifications.Remove(i);
+ return;
+ }
+ }
+ }
+
+void CIoPersistentConsole::NotifyWriteDetachL(const RMsg& aMessage)
+ {
+ if ((iWriterProxies.Count()==0) || !iTransientWriteEndPoint)
+ {
+ Complete(aMessage, KErrNone);
+ }
+ else
+ {
+ iWriteDetachNotifications.AppendL(aMessage);
+ }
+ }
+
+void CIoPersistentConsole::CancelNotifyWriteDetach(TRequestStatus* aClientStatus)
+ {
+ for (TInt i=0; i<iWriteDetachNotifications.Count(); ++i)
+ {
+ if (iWriteDetachNotifications[i].ClientStatus() == aClientStatus)
+ {
+ Complete(iWriteDetachNotifications[i], KErrCancel);
+ iWriteDetachNotifications.Remove(i);
+ return;
+ }
+ }
+ }
+
+TName CIoPersistentConsole::TransientReaderName()
+ {
+ if (iTransientReadEndPoint)
+ {
+ return iTransientReadEndPoint->IoepName();
+ }
+ else
+ {
+ return KNullDesC();
+ }
+ }
+
+TName CIoPersistentConsole::TransientWriterName()
+ {
+ if (iTransientWriteEndPoint)
+ {
+ return iTransientWriteEndPoint->IoepName();
+ }
+ else
+ {
+ return KNullDesC();
+ }
+ }
+
+TThreadId CIoPersistentConsole::Creator()
+ {
+ return iCreator.Id();
+ }
+
+TName CIoPersistentConsole::Name() const
+ {
+ return iName;
+ }
+
+TBool CIoPersistentConsole::IsType(RIoHandle::TType aType) const
+ {
+ if (aType == RIoHandle::EPersistentConsole)
+ {
+ return ETrue;
+ }
+ else
+ {
+ return CIoConsole::IsType(aType);
+ }
+ }
+
+void CIoPersistentConsole::SessionClosed(const CIoSession& aSession)
+ {
+ if (&aSession == iReadEndPointDetachOnClose)
+ {
+ DetachTransientReader();
+ }
+ if (&aSession == iWriteEndPointDetachOnClose)
+ {
+ DetachTransientWriter();
+ }
+ }
+
+void CIoPersistentConsole::ClosedBy(const CIoSession& aSession)
+ {
+ SessionClosed(aSession);
+ }
+
+void CIoPersistentConsole::SendReadDetachNotifications()
+ {
+ for (TInt i=0; i<iReadDetachNotifications.Count(); ++i)
+ {
+ Complete(iReadDetachNotifications[i], KErrNone);
+ }
+ iReadDetachNotifications.Reset();
+ }
+
+void CIoPersistentConsole::SendWriteDetachNotifications()
+ {
+ for (TInt i=0; i<iWriteDetachNotifications.Count(); ++i)
+ {
+ Complete(iWriteDetachNotifications[i], KErrNone);
+ }
+ iWriteDetachNotifications.Reset();
+ }
+
+//______________________________________________________________________________
+// MIoReadEndPoint implementation - to handle reads from persistent side
+TInt CIoPersistentConsole::HandleReaderAttached(MIoReader& aReader)
+ {
+ TIoReaderProxy* proxy = new TIoReaderProxy(aReader, *this);
+ TInt err = proxy ? KErrNone : KErrNoMemory;
+ if (err==KErrNone)
+ {
+ err = iReaderProxies.Append(proxy);
+ }
+
+ if ((err == KErrNone) && iTransientReadEndPoint)
+ {
+ TRAP(err, iTransientReadEndPoint->IorepAttachL(*proxy, RIoEndPoint::EBackground));
+ }
+
+ if (err != KErrNone)
+ {
+ TInt pos = ReaderProxyIndex(proxy);
+ if (pos!=KErrNotFound)
+ {
+ iReaderProxies.Remove(pos);
+ }
+ delete proxy;
+ }
+ return err;
+ }
+
+void CIoPersistentConsole::HandleReaderDetached(MIoReader& aReader)
+ {
+ TInt pos = ReaderProxyIndex(&aReader);
+ if (pos!=KErrNotFound)
+ {
+ if (iTransientReadEndPoint)
+ {
+ iTransientReadEndPoint->IorepDetach(*iReaderProxies[pos]);
+ }
+ delete iReaderProxies[pos];
+ iReaderProxies.Remove(pos);
+
+ if (iReaderProxies.Count()==0)
+ {
+ SendReadDetachNotifications();
+ }
+ }
+ }
+
+void CIoPersistentConsole::HandleForegroundReaderChanged()
+ {
+ if (iTransientReadEndPoint)
+ {
+ CIoEndPoint::HandleForegroundReaderChanged();
+ }
+ else
+ {
+ ForegroundReaderChanged();
+ }
+ }
+
+void CIoPersistentConsole::ForegroundReaderChanged()
+ {
+ MIoReader* fgReader = AttachedReader();
+ if (iTransientReadEndPoint && fgReader)
+ {
+ TInt fgPos = ReaderProxyIndex(fgReader);
+ ASSERT(fgPos != KErrNotFound);
+ TRAPD(err, iTransientReadEndPoint->IorepSetForegroundReaderL(*iReaderProxies[fgPos]));
+ __ASSERT_ALWAYS(err == KErrNone, User::Invariant());
+ // this would only fail if this endpoints list of readers differs from the transient
+ // endpoints list; the two should always be kept in sync.
+ }
+ }
+
+TInt CIoPersistentConsole::ReaderProxyIndex(MIoReader* aReader) const
+ {
+ for (TInt i=0; i<iReaderProxies.Count(); ++i)
+ {
+ if (&iReaderProxies[i]->ClientReader() == aReader)
+ {
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+void CIoPersistentConsole::IorepReadL(MIoReader& aReader)
+ {
+ TInt pos = ReaderProxyIndex(&aReader);
+ ASSERT(pos!=KErrNotFound);
+ iReaderProxies[pos]->ReadL(iTransientReadEndPoint);
+ }
+
+void CIoPersistentConsole::IorepReadKeyL(MIoReader& aReader)
+ {
+ TInt pos = ReaderProxyIndex(&aReader);
+ ASSERT(pos!=KErrNotFound);
+ iReaderProxies[pos]->ReadKeyL(iTransientReadEndPoint);
+ }
+
+void CIoPersistentConsole::IorepSetConsoleModeL(RIoReadWriteHandle::TMode aMode, MIoReader& aReader)
+ {
+ iPersistentConsoleMode = aMode;
+ GetReaderProxy(&aReader).SetConsoleModeL(iTransientReadEndPoint, aMode);
+ }
+
+//______________________________________________________________________________
+// MIoWriteEndPoint implementation - to handles writes from persistent side
+TInt CIoPersistentConsole::HandleWriterAttached(MIoWriter& aWriter)
+ {
+ // call from CIoEndPoint
+ TIoWriterProxy* proxy = new TIoWriterProxy(aWriter, *this);
+ TInt err = proxy ? KErrNone : KErrNoMemory;
+ if (err==KErrNone)
+ {
+ err = iWriterProxies.Append(proxy);
+ }
+
+ if ((err == KErrNone) && iTransientWriteEndPoint)
+ {
+ TRAP(err, iTransientWriteEndPoint->IowepAttachL(*proxy));
+ }
+
+ if (err != KErrNone)
+ {
+ TInt pos = WriterProxyIndex(proxy);
+ if (pos!=KErrNotFound)
+ {
+ iWriterProxies.Remove(pos);
+ }
+ delete proxy;
+ }
+ return err;
+ }
+
+void CIoPersistentConsole::HandleWriterDetached(MIoWriter& aWriter)
+ {
+ TInt pos = WriterProxyIndex(&aWriter);
+ if (pos!=KErrNotFound)
+ {
+ if (iTransientWriteEndPoint)
+ {
+ iWriterProxies[pos]->TransientWriterDetach(*iTransientWriteEndPoint);
+ }
+ delete iWriterProxies[pos];
+ iWriterProxies.Remove(pos);
+
+ if (iWriterProxies.Count()==0)
+ {
+ SendWriteDetachNotifications();
+ }
+ }
+
+ }
+
+TInt CIoPersistentConsole::WriterProxyIndex(MIoWriter* aWriter) const
+ {
+ for (TInt i=0; i<iWriterProxies.Count(); ++i)
+ {
+ if (&iWriterProxies[i]->ClientWriter() == aWriter)
+ {
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+CIoPersistentConsole::TIoWriterProxy& CIoPersistentConsole::GetWriterProxy(MIoWriter* aWriter) const
+ {
+ TInt pos = WriterProxyIndex(aWriter);
+ ASSERT(pos!=KErrNotFound);
+ return *iWriterProxies[pos];
+ }
+
+CIoPersistentConsole::TIoReaderProxy& CIoPersistentConsole::GetReaderProxy(MIoReader* aWriter) const
+ {
+ TInt pos = ReaderProxyIndex(aWriter);
+ ASSERT(pos!=KErrNotFound);
+ return *iReaderProxies[pos];
+ }
+
+void CIoPersistentConsole::IowepWriteL(MIoWriter& aWriter)
+ {
+ TInt pos = WriterProxyIndex(&aWriter);
+ ASSERT(pos!=KErrNotFound);
+ iWriterProxies[pos]->WriteL(iTransientWriteEndPoint);
+
+ // move the proxy to the end of the array so that we service the writes
+ // in the correct order when we get a write end point, or when the end
+ // point goes away and comes back
+ TIoWriterProxy* proxy(iWriterProxies[pos]);
+ iWriterProxies.Remove(pos);
+ iWriterProxies.Append(proxy);
+ }
+
+void CIoPersistentConsole::IowepWriteCancel(MIoWriter& aWriter)
+ {
+ TInt pos = WriterProxyIndex(&aWriter);
+ ASSERT(pos!=KErrNotFound);
+ iWriterProxies[pos]->WriteCancel(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepCursorPosL(MIoWriter& aWriter) const
+ {
+ GetWriterProxy(&aWriter).GetCursorPosL(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepSetCursorPosAbsL(const TPoint& aPoint, MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).SetCursorPosAbsL(aPoint, iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepSetCursorPosRelL(const TPoint& aPoint, MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).SetCursorPosRelL(aPoint, iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepSetCursorHeightL(TInt aPercentage, MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).SetCursorHeightL(aPercentage, iTransientWriteEndPoint);
+ // TODO cache cursor height
+ }
+
+void CIoPersistentConsole::IowepSetTitleL(MIoWriter& aWriter)
+ {
+ delete iTitle;
+ iTitle = NULL;
+ TRAP_IGNORE(iTitle = aWriter.IowTitleLC(); CleanupStack::Pop(iTitle)); // not much we can do if this fails
+ GetWriterProxy(&aWriter).SetTitleL(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepClearScreenL(MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).ClearScreenL(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepClearToEndOfLineL(MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).ClearToEndOfLineL(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepScreenSizeL(MIoWriter& aWriter) const
+ {
+ GetWriterProxy(&aWriter).GetScreenSizeL(iTransientWriteEndPoint);
+ }
+
+void CIoPersistentConsole::IowepSetAttributesL(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor, MIoWriter& aWriter)
+ {
+ GetWriterProxy(&aWriter).SetAttributesL(aAttributes, aForegroundColor, aBackgroundColor, iTransientWriteEndPoint);
+ }
+
+CIoPersistentConsole::CIoPersistentConsole(CIoServer& aServer)
+ : CIoConsole(aServer.Config()), iServer(aServer), iTitleSetter(iTitle)
+ {
+ }
+
+CIoPersistentConsole::~CIoPersistentConsole()
+ {
+ iServer.PersistentConsoleRemove(iName, *this);
+ SendReadDetachNotifications();
+ iReadDetachNotifications.Close();
+ SendWriteDetachNotifications();
+ iWriteDetachNotifications.Close();
+
+ delete iTitle;
+ iWriterProxies.ResetAndDestroy();
+ iReaderProxies.ResetAndDestroy();
+
+ iCreator.Close();
+ }
+
+_LIT(KPersistentConsoleImplementation, "<persistent console>");
+
+void CIoPersistentConsole::ConstructL(const TDesC& aName, const TDesC& aTitle, const RMsg& aMessage)
+ {
+ LOG(CIoLog::Printf(_L("Persistent console %S @ 0x%08x created"), &aName, this));
+ iName = aName.Left(KMaxName);
+ iServer.PersistentConsoleAddL(iName, *this);
+ iImplementation = KPersistentConsoleImplementation().AllocL();
+ iTitle = aTitle.AllocL();
+ aMessage.ClientL(iCreator);
+ }
+
+//______________________________________________________________________________
+// TIoWriterProxy
+// MIoWriter proxy to service write requests from the transient side
+CIoPersistentConsole::TIoWriterProxy::TIoWriterProxy(MIoWriter& aWriter, CIoPersistentConsole& aOwner)
+ : iWriter(aWriter)
+ , iOwner(aOwner)
+ , iFlags(0)
+ {
+ }
+
+TBool CIoPersistentConsole::TIoWriterProxy::GetFlag(TFlags aFlag)
+ {
+ return iFlags & aFlag;
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetFlag(TFlags aFlag)
+ {
+ iFlags |= aFlag;
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::ClearFlag(TFlags aFlag)
+ {
+ iFlags &= (~aFlag);
+ }
+
+#define TRAP_OR(x, y) {TRAPD(err, x); if (err!=KErrNone) {y;} }
+
+
+void CIoPersistentConsole::TIoWriterProxy::TransientWriterAttached(MIoWriteEndPoint& aEndPoint)
+ {
+ if (GetFlag(EWritePending))
+ {
+ TRAP_OR(aEndPoint.IowepWriteL(*this), IowComplete(err));
+ }
+ if (GetFlag(EGetCursorPosPending))
+ {
+ TRAP_OR(aEndPoint.IowepCursorPosL(*this), IowCursorPos(err, TPoint(0,0)));
+ }
+ if (GetFlag(ESetCursorPosAbsPending))
+ {
+ TRAP_OR(aEndPoint.IowepSetCursorPosAbsL(iSetCursPosAbsPoint, *this), IowSetCursorPosAbsComplete(err));
+ }
+ if (GetFlag(ESetCursorPosRelPending))
+ {
+ TRAP_OR(aEndPoint.IowepSetCursorPosRelL(iSetCursPosRelPoint, *this), IowSetCursorPosRelComplete(err));
+ }
+ if (GetFlag(ESetCursorHeightPending))
+ {
+ TRAP_OR(aEndPoint.IowepSetCursorHeightL(iSetCursorHeight, *this), IowSetCursorHeightComplete(err));
+ }
+ if (GetFlag(ESetTitlePending))
+ {
+ TRAP_OR(aEndPoint.IowepSetTitleL(*this), IowSetTitleComplete(err));
+ }
+ if (GetFlag(EClearScreenPending))
+ {
+ TRAP_OR(aEndPoint.IowepClearScreenL(*this), IowClearScreenComplete(err));
+ }
+ if (GetFlag(EClearToEndOfLinePending))
+ {
+ TRAP_OR(aEndPoint.IowepClearToEndOfLineL(*this), IowClearToEndOfLineComplete(err));
+ }
+ if (GetFlag(EGetScreenSizePending))
+ {
+ TRAP_OR(aEndPoint.IowepScreenSizeL(*this), IowScreenSize(err, TSize(0,0)));
+ }
+ if (GetFlag(ESetAttributesPending))
+ {
+ TRAP_OR(aEndPoint.IowepSetAttributesL(iAttributes, iForegroundColor, iBackgroundColor, *this), IowSetAttributesComplete(err));
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::TransientWriterDetach(MIoWriteEndPoint& aEndPoint)
+ {
+ if (GetFlag(EDetaching)) return;
+ if (GetFlag(EWritePending))
+ {
+ aEndPoint.IowepWriteCancel(*this);
+ // leave the write pending so it is serviced when we get a new transient end point
+ }
+ aEndPoint.IowepDetach(*this);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::WriteL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(EWritePending);
+ if (aEndPoint)
+ {
+ TRAPD(err, aEndPoint->IowepWriteL(*this));
+ if (err)
+ {
+ ClearFlag(EWritePending);
+ User::Leave(err);
+ }
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::WriteCancel(MIoWriteEndPoint* aEndPoint)
+ {
+ if (aEndPoint)
+ {
+ aEndPoint->IowepWriteCancel(*this);
+ }
+ ClearFlag(EWritePending);
+ }
+
+
+MIoWriter& CIoPersistentConsole::TIoWriterProxy::ClientWriter() const
+ {
+ return iWriter;
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::GetCursorPosL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(EGetCursorPosPending);
+ if (aEndPoint)
+ {
+ aEndPoint->IowepCursorPosL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetCursorPosAbsL(const TPoint& aPos, MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(ESetCursorPosAbsPending);
+ iSetCursPosAbsPoint = aPos;
+ if (aEndPoint)
+ {
+ aEndPoint->IowepSetCursorPosAbsL(iSetCursPosAbsPoint, *this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetCursorPosRelL(const TPoint& aPos, MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(ESetCursorPosRelPending);
+ iSetCursPosRelPoint = aPos;
+ if (aEndPoint)
+ {
+ aEndPoint->IowepSetCursorPosRelL(iSetCursPosRelPoint, *this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetCursorHeightL(TInt aPercentage, MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(ESetCursorHeightPending);
+ iSetCursorHeight = aPercentage;
+ if (aEndPoint)
+ {
+ aEndPoint->IowepSetCursorHeightL(iSetCursorHeight, *this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetTitleL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(ESetTitlePending);
+ if (aEndPoint)
+ {
+ aEndPoint->IowepSetTitleL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::ClearScreenL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(EClearScreenPending);
+ if (aEndPoint)
+ {
+ aEndPoint->IowepClearScreenL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::ClearToEndOfLineL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(EClearToEndOfLinePending);
+ if (aEndPoint)
+ {
+ aEndPoint->IowepClearToEndOfLineL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::GetScreenSizeL(MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(EGetScreenSizePending);
+ if (aEndPoint)
+ {
+ aEndPoint->IowepScreenSizeL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::SetAttributesL(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor, MIoWriteEndPoint* aEndPoint)
+ {
+ SetFlag(ESetAttributesPending);
+ iAttributes = aAttributes;
+ iForegroundColor = aForegroundColor;
+ iBackgroundColor = aBackgroundColor;
+ if (aEndPoint)
+ {
+ aEndPoint->IowepSetAttributesL(iAttributes, iForegroundColor, iBackgroundColor, *this);
+ }
+ }
+
+TInt CIoPersistentConsole::TIoWriterProxy::IowWriteLength() const
+ {
+ return iWriter.IowWriteLength();
+ }
+
+TInt CIoPersistentConsole::TIoWriterProxy::IowWrite(TDes& aBuf)
+ {
+ return iWriter.IowWrite(aBuf);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowComplete(TInt aError)
+ {
+ if (aError == KErrNone)
+ {
+ iWriter.IowComplete(KErrNone);
+ ClearFlag(EWritePending);
+ }
+ else
+ {
+ SetFlag(EDetaching);
+ iOwner.DetachTransientWriter();
+ ClearFlag(EDetaching);
+ }
+ }
+
+TName CIoPersistentConsole::TIoWriterProxy::IowName()
+ {
+ TName name(iWriter.IowName());
+ if (name.Length() + KProxySuffix().Length() > name.MaxLength())
+ {
+ name.SetLength(name.MaxLength() - KProxySuffix().Length());
+ }
+ name.Append(KProxySuffix);
+ return name;
+ }
+
+RIoReadWriteHandle::TMode CIoPersistentConsole::TIoWriterProxy::IorwMode() const
+ {
+ return iWriter.IorwMode();
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowCursorPos(TInt aError, TPoint aPos)
+ {
+ ClearFlag(EGetCursorPosPending);
+ iWriter.IowCursorPos(aError, aPos);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowSetCursorPosAbsComplete(TInt aError)
+ {
+ ClearFlag(ESetCursorPosAbsPending);
+ iWriter.IowSetCursorPosAbsComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowSetCursorPosRelComplete(TInt aError)
+ {
+ ClearFlag(ESetCursorPosRelPending);
+ iWriter.IowSetCursorPosRelComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowSetCursorHeightComplete(TInt aError)
+ {
+ ClearFlag(ESetCursorHeightPending);
+ iWriter.IowSetCursorHeightComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowSetTitleComplete(TInt aError)
+ {
+ ClearFlag(ESetTitlePending);
+ iWriter.IowSetTitleComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowClearScreenComplete(TInt aError)
+ {
+ ClearFlag(EClearScreenPending);
+ iWriter.IowClearScreenComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowClearToEndOfLineComplete(TInt aError)
+ {
+ ClearFlag(EClearToEndOfLinePending);
+ iWriter.IowClearToEndOfLineComplete(aError);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowScreenSize(TInt aError, TSize aSize)
+ {
+ ClearFlag(EGetScreenSizePending);
+ iWriter.IowScreenSize(aError, aSize);
+ }
+
+void CIoPersistentConsole::TIoWriterProxy::IowSetAttributesComplete(TInt aError)
+ {
+ ClearFlag(ESetAttributesPending);
+ iWriter.IowSetAttributesComplete(aError);
+ }
+
+HBufC* CIoPersistentConsole::TIoWriterProxy::IowTitleLC()
+ {
+ return iWriter.IowTitleLC();
+ }
+
+//______________________________________________________________________________
+// TIoReaderProxy
+// MIoReader proxy - to service read requests from transient side
+CIoPersistentConsole::TIoReaderProxy::TIoReaderProxy(MIoReader& aReader, CIoPersistentConsole& aOwner)
+ : iReader(aReader), iOwner(aOwner), iDetaching(EFalse), iSetConsoleModePending(EFalse)
+ {
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::TransientReaderAttached(MIoReadEndPoint& aReader)
+ {
+ if (iReader.IorReadPending())
+ {
+ TRAPD(err, aReader.IorepReadL(*this));
+ if (err)
+ {
+ IorReadComplete(err);
+ }
+ }
+ if (iReader.IorReadKeyPending())
+ {
+ TRAPD(err, aReader.IorepReadKeyL(*this));
+ if (err)
+ {
+ IorReadKeyComplete(err, EKeyNull, 0);
+ }
+ }
+ if (iSetConsoleModePending)
+ {
+ TRAP_OR(aReader.IorepSetConsoleModeL(iSetConsoleMode, *this), IorSetConsoleModeComplete(err));
+ }
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::ReadL(MIoReadEndPoint* aEndPoint)
+ {
+ if (aEndPoint)
+ {
+ aEndPoint->IorepReadL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::ReadKeyL(MIoReadEndPoint* aEndPoint)
+ {
+ if (aEndPoint)
+ {
+ aEndPoint->IorepReadKeyL(*this);
+ }
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::SetConsoleModeL(MIoReadEndPoint* aEndPoint, RIoReadWriteHandle::TMode aMode)
+ {
+ iSetConsoleModePending = ETrue;
+ iSetConsoleMode = aMode;
+ if (aEndPoint)
+ {
+ CleanupNullPointerPushL((TAny**)&iSetConsoleModePending);
+ aEndPoint->IorepSetConsoleModeL(iSetConsoleMode, *this);
+ CleanupStack::Pop();
+ }
+ }
+
+MIoReader& CIoPersistentConsole::TIoReaderProxy::ClientReader() const
+ {
+ return iReader;
+ }
+
+RIoReadWriteHandle::TMode CIoPersistentConsole::TIoReaderProxy::IorwMode() const
+ {
+ return iReader.IorwMode();
+ }
+
+TBool CIoPersistentConsole::TIoReaderProxy::IorReadPending() const
+ {
+ return iReader.IorReadPending();
+ }
+
+TBool CIoPersistentConsole::TIoReaderProxy::IorReadKeyPending() const
+ {
+ return iReader.IorReadKeyPending();
+ }
+
+
+TDes& CIoPersistentConsole::TIoReaderProxy::IorReadBuf()
+ {
+ return iReader.IorReadBuf();
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::IorDataBuffered(TInt aLength)
+ {
+ iReader.IorDataBuffered(aLength);
+ }
+
+TBool CIoPersistentConsole::TIoReaderProxy::IorDataIsBuffered() const
+ {
+ return iReader.IorDataIsBuffered();
+ }
+
+
+TBool CIoPersistentConsole::TIoReaderProxy::IorIsKeyCaptured(TUint aKeyCode, TUint aModifiers)
+ {
+ return iReader.IorIsKeyCaptured(aKeyCode, aModifiers);
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::IorReadComplete(TInt /*aError*/)
+ {
+ // indicates that the read end point will be providing no more data
+ // so detatch it
+ iDetaching = ETrue;
+ iOwner.DetachTransientReader();
+ iDetaching = EFalse;
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::IorReadKeyComplete(TInt aError, TUint aKeyCode, TUint aModifiers)
+ {
+ if (aError == KErrEof)
+ {
+ // indicates that the read end point will be providing no more data
+ // so detatch it
+ iOwner.DetachTransientReader();
+ }
+ else
+ {
+ iReader.IorReadKeyComplete(aError, aKeyCode, aModifiers);
+ }
+ }
+
+TName CIoPersistentConsole::TIoReaderProxy::IorName()
+ {
+ TName name(iReader.IorName());
+ if (name.Length() + KProxySuffix().Length() > name.MaxLength())
+ {
+ name.SetLength(name.MaxLength() - KProxySuffix().Length());
+ }
+ name.Append(KProxySuffix);
+ return name;
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::IorReaderChange(TUint aChange)
+ {
+ iReader.IorReaderChange(aChange);
+ }
+
+void CIoPersistentConsole::TIoReaderProxy::IorSetConsoleModeComplete(TInt aError)
+ {
+ iSetConsoleModePending = EFalse;
+ iReader.IorSetConsoleModeComplete(aError);
+ }
+
+//______________________________________________________________________________
+// TConsoleTitleSetter
+TConsoleTitleSetter::TConsoleTitleSetter(HBufC*& aTitle)
+ : iTitle(aTitle)
+ {
+ }
+
+TInt TConsoleTitleSetter::IowWriteLength() const
+ {
+ ASSERT(0);
+ return 0;
+ }
+
+TInt TConsoleTitleSetter::IowWrite(TDes&)
+ {
+ ASSERT(0);
+ return 0;
+ }
+
+void TConsoleTitleSetter::IowComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+TName TConsoleTitleSetter::IowName()
+ {
+ ASSERT(0);
+ return TName();
+ }
+
+RIoReadWriteHandle::TMode TConsoleTitleSetter::IorwMode() const
+ {
+ ASSERT(0);
+ return RIoReadWriteHandle::EText;
+ }
+
+void TConsoleTitleSetter::IowCursorPos(TInt, TPoint)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowSetCursorPosAbsComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowSetCursorPosRelComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowSetCursorHeightComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowSetTitleComplete(TInt)
+ {
+ }
+
+void TConsoleTitleSetter::IowClearScreenComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowClearToEndOfLineComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowScreenSize(TInt, TSize)
+ {
+ ASSERT(0);
+ }
+
+void TConsoleTitleSetter::IowSetAttributesComplete(TInt)
+ {
+ ASSERT(0);
+ }
+
+HBufC* TConsoleTitleSetter::IowTitleLC()
+ {
+ return iTitle->AllocLC();
+ }
+
+