diff -r 000000000000 -r 2f259fa3e83a uifw/EikStd/console/EIKCONCL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/EikStd/console/EIKCONCL.CPP Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1005 @@ +/* +* Copyright (c) 1997-1999 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 "EIKCONCL.H" +#include "EIKCONCL.PAN" +#include +#include +#include +#include +#include +#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include + +GLDEF_C void Panic(TEikConClPanic aPanic) + { + _LIT(KPanicCat,"EIKON-CONCL"); + User::Panic(KPanicCat,aPanic); + } + +class CEikConsMessager; + +class CCommsKeyReader : public CActive + { +public: + CCommsKeyReader(RComm& aComm, CEikConsMessager* aMessager); + ~CCommsKeyReader(); + +private: + void RunL(); + void DoCancel(); + void Start(); + +private: + RComm& iComm; + CEikConsMessager* iMessager; + TBuf8<1> iBuf; + TBuf8<4> iMatch; + }; + + +class CCommsKeyWriter : public CActive + { +public: + CCommsKeyWriter(RComm& aComm); + ~CCommsKeyWriter(); + + void Write(const TDesC& aDes); + +private: + void WriteIfReady(); + void RunL(); + void DoCancel(); + void AppendBlocking(TText8 aChar); + +private: + RComm& iComm; + TBuf8<256> iBuf; + TBuf8<256> iWrite; + TBool iInFakeCancel; + }; + + +enum + { + EExit, + ERead, + EReadCancel, + EWrite, + ESetCursorPosAbs, + ESetCursorPosRel, + ESetCursorHeight, + ESetTitle, + EClearScreen, + EClearToEndOfLine + }; + + +struct TFepKey + { + TText iLong; + const TText* iLower; + const TText* iUpper; + }; + +const TFepKey KFepKeyTable[] = + { + { '0', _S(" 0\r"), _S(" 0\r") }, + { '1', _S("\\.:1#*/-+=\"',()|`!$%^&_[]{};@~<>?"), _S("\\.:1#*/-+=\"',()|`!$%^&_[]{};@~<>?") }, + { '2', _S("abc2"), _S("ABC2") }, + { '3', _S("def3"), _S("DEF3") }, + { '4', _S("ghi4"), _S("GHI4") }, + { '5', _S("jkl5"), _S("JKL5") }, + { '6', _S("mno6"), _S("MNO6") }, + { '7', _S("pqrs7"), _S("PQRS7") }, + { '8', _S("tuv8"), _S("TUV8") }, + { '9', _S("wxyz9"), _S("WXYZ9") } + }; + +const TText* const KModeNames[] = + { + _S("Lower"), + _S("Caps"), + _S("Numeric") + }; + +const TText* const KIOModeNames[] = + { + _S("Screen"), + _S("Serial"), + _S("Ansi-Serial") + }; + +_LIT(KCommModule, "IRCOMM"); +_LIT(KCommPort, "IRCOMM::0"); + +// +// class CEikConsMessager +// + +class CEikConsMessager : public CActive + { +public: + enum TMyFlags + { + EShift, + EDigitPressed + }; + enum TKeyMode + { + ELower, + ECaps, + ENumeric, + ENumModes + }; + enum TIOMode + { + EScreen, + ESerial, + EAnsi, + ENumIOModes + }; +public: + CEikConsMessager(CEikConsoleScreen* aScreen,RThread aParentThread); + ~CEikConsMessager(); + void ConstructL(CEikConsoleClient* aClient); + void HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType); + void AddKeyEvent(const TKeyEvent& aKeyEvent); +private: // overridden + void RunL(); + void DoCancel(); +private: // internal + void CompleteReadRequest(); +private: // fep like stuff + void StartTimer(); + static TInt TimerCallBack(TAny* aThis); + void DoTimer(); + void LaunchSCTL(); + void HandleDigit(const TKeyEvent& aKeyEvent, TEventCode aType); + void StartCommsL(); + void StopComms(); + void WriteComms(const TDesC& aMsg); + +private: + CEikConsoleScreen* iScreen; + RThread iParentThread; + TRequestStatus* iReadStatus; + TKeyEvent* iKeyEvent; + TInt iMessage; + const TAny* iParam; + TRequestStatus* iReplyStatus; + CCirBuf* iKeyQ; + + // fep like stuff + TKeyEvent iLastKey; + CPeriodic* iTimer; + TBitFlags iFlags; + TInt iMultiStep; + TKeyMode iKeyMode; + TIOMode iIOMode; + RCommServ iCommServ; + RComm iComm; + CCommsKeyReader* iReader; + CCommsKeyWriter* iWriter; + }; + +CEikConsMessager::CEikConsMessager(CEikConsoleScreen* aScreen,RThread aParentThread) + : CActive(EActivePriorityIpcEventsHigh), + iParentThread(aParentThread) + { + iScreen=aScreen; + } + +CEikConsMessager::~CEikConsMessager() + { + StopComms(); + delete iTimer; + iParentThread.Close(); + delete iKeyQ; + } + +void CEikConsMessager::ConstructL(CEikConsoleClient* aClient) + { + iTimer = CPeriodic::NewL(EPriorityStandard); + iKeyQ=new(ELeave) CCirBuf; + iKeyQ->SetLengthL(40); // buffer length, too high? too low? + iKeyEvent=(&aClient->iKeyEvent); + aClient->iThreadStatus=(&iStatus); + aClient->iMessage=(&iMessage); + aClient->iParam=(&iParam); + aClient->iReplyStatus=(&iReplyStatus); + aClient->iScreen=iScreen; + CActiveScheduler::Add(this); + iStatus=KRequestPending; + SetActive(); + } + +void CEikConsMessager::DoCancel() + { + } + +void CEikConsMessager::RunL() + { + switch (iMessage) + { + case EExit: + CBaActiveScheduler::Exit(); + break; + case ERead: + if (iReadStatus) + Panic(EEikConClPanicReadAlreadyOutstanding); + iReadStatus=(TRequestStatus*)iParam; + if (iKeyQ->Count()>0) // already a buffered event + CompleteReadRequest(); + break; + case EReadCancel: + if (iReadStatus) + iParentThread.RequestComplete(iReadStatus,KErrCancel); + break; + case EWrite: + iScreen->Write(*(const TDesC*)iParam); + if (iIOMode != EScreen) + WriteComms(*(const TDesC*)iParam); + break; + case ESetCursorPosAbs: + iScreen->SetCursorPosAbs(*(const TPoint*)iParam); + if (iIOMode == EAnsi) + { + TPoint point = iScreen->CursorPos(); + TBuf<10> buf; + buf.Format(_L("\033[%d;%dH"), point.iY, point.iX); + WriteComms(buf); + } + break; + case ESetCursorPosRel: + iScreen->SetCursorPosRel(*(const TPoint*)iParam); + if (iIOMode == EAnsi) + { + TPoint point = iScreen->CursorPos(); + TBuf<10> buf; + buf.Format(_L("\033[%d;%dH"), point.iY, point.iX); + WriteComms(buf); + } + break; + case ESetCursorHeight: + iScreen->SetCursorHeight((TInt)iParam); + break; + case EClearScreen: + iScreen->ClearScreen(); + if (iIOMode == EAnsi) + { + WriteComms(_L("\033[2J")); + } + break; + case EClearToEndOfLine: + iScreen->ClearToEndOfLine(); + if (iIOMode == EAnsi) + { + WriteComms(_L("\033[K")); + } + break; + } + iStatus=KRequestPending; + SetActive(); + iParentThread.RequestComplete(iReplyStatus,0); + } + +void CEikConsMessager::CompleteReadRequest() + { + if (iReadStatus) + { + iKeyQ->Remove(iKeyEvent);; + iParentThread.RequestComplete(iReadStatus,0); + } + } + +void CEikConsMessager::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType) + { + iFlags.Assign(EShift, aKeyEvent.iModifiers & EModifierShift); + + if ('0' <= aKeyEvent.iScanCode && aKeyEvent.iScanCode <= '9') + { + HandleDigit(aKeyEvent, aType); + } + else if (aKeyEvent.iScanCode == EStdKeyHash) + { + if (aType == EEventKeyDown) + { + if (iFlags[EShift]) + { + iIOMode = TIOMode((iIOMode+1)%ENumIOModes); + User::InfoPrint(TPtrC(KIOModeNames[iIOMode])); + if (iIOMode == ESerial) + { + StartCommsL(); + } + else if (iIOMode == EScreen) + StopComms(); + } + else + { + iKeyMode = TKeyMode((iKeyMode+1)%ENumModes); + User::InfoPrint(TPtrC(KModeNames[iKeyMode])); + } + iTimer->Cancel(); + } + } + else if (aType == EEventKey) + { + if (aKeyEvent.iCode == '*') + { + LaunchSCTL(); + iTimer->Cancel(); + } + else if (aKeyEvent.iCode != EKeyF21) + { + AddKeyEvent(aKeyEvent); + iTimer->Cancel(); + } + } + } + +void CEikConsMessager::AddKeyEvent(const TKeyEvent& aKeyEvent) + { + TInt ret=iKeyQ->Add(&aKeyEvent); + if (ret==0) + CEikonEnv::Beep(); + if (iKeyQ->Count()==1) // client may be waiting on this key event + CompleteReadRequest(); + } + +void CEikConsMessager::LaunchSCTL() + { + TBuf<8> specialChars; + TBool shift = !COMPARE_BOOLS(iFlags[EShift], (iKeyMode==ECaps)); + TInt sctCase = (shift ? EAknSCTUpperCase : EAknSCTLowerCase); + CAknCharMapDialog* dialog=new(ELeave) CAknCharMapDialog(sctCase, specialChars); + if (dialog->ExecuteLD(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG)) + { + TKeyEvent event = { 0, 0, 0, 0 }; + for ( TInt ii = 0; ii < specialChars.Length(); ii++) + { + if ( specialChars[ii] == 0x000A ) // 0x000A is line feed + { + event.iCode = EKeyEnter; + event.iScanCode = EKeyEnter; + } + else + { + event.iCode = specialChars[ii]; + event.iScanCode = specialChars[ii]; + } + AddKeyEvent(event); + } + } + } + +void CEikConsMessager::HandleDigit(const TKeyEvent& aKeyEvent, TEventCode aType) + { + TText digit = TText(aKeyEvent.iScanCode); + __ASSERT_DEBUG('0' <= digit && digit <= '9', Panic(EEikConClPanicIllegalFepChar)); + TBool shift = !COMPARE_BOOLS(iFlags[EShift], (iKeyMode==ECaps)); + const TFepKey& fepKey = KFepKeyTable[digit - '0']; + TPtrC keys(shift ? fepKey.iUpper : fepKey.iLower); + + if (iKeyMode == ENumeric) + { + if (aType == EEventKey) + { + AddKeyEvent(aKeyEvent); + iTimer->Cancel(); + } + } + else + { + if (aType == EEventKeyDown) + { + iFlags.Set(EDigitPressed); + if (digit == iLastKey.iScanCode) + { + iMultiStep = (iMultiStep + 1) % keys.Length(); + TKeyEvent del = {EKeyBackspace, EStdKeyBackspace, 0, 0}; + AddKeyEvent(del); + TKeyEvent event = {keys[iMultiStep], keys[iMultiStep], 0, 0}; + AddKeyEvent(event); + } + else + { + iMultiStep = 0; + TKeyEvent event = {keys[iMultiStep], keys[iMultiStep], 0, 0}; + AddKeyEvent(event); + } + + StartTimer(); + iLastKey = aKeyEvent; + } + else if (aType == EEventKeyUp) + { + iFlags.Clear(EDigitPressed); + } + } + } + +void CEikConsMessager::StartTimer() + { + iTimer->Cancel(); + iTimer->Start(800000, 1000000, TCallBack(TimerCallBack, this)); + } + +TInt CEikConsMessager::TimerCallBack(TAny* aThis) + { + ((CEikConsMessager*)aThis)->DoTimer(); + return 0; + } + +void CEikConsMessager::DoTimer() + { + if (iFlags[EDigitPressed]) + { + TText digit = TText(iLastKey.iScanCode); + __ASSERT_DEBUG('0' <= digit && digit <= '9', Panic(EEikConClPanicIllegalFepChar)); + TText key = KFepKeyTable[digit - '0'].iLong; + TKeyEvent del = {EKeyBackspace, EStdKeyBackspace, 0, 0}; + AddKeyEvent(del); + TKeyEvent event = {key, key, 0, 0}; + AddKeyEvent(event); + iFlags.Clear(EDigitPressed); + } + + iLastKey.iScanCode = 0; + iMultiStep = 0; + } + +void CEikConsMessager::StartCommsL() + { + User::LeaveIfError(iCommServ.Connect()); + User::LeaveIfError(iCommServ.LoadCommModule(KCommModule)); + User::LeaveIfError(iComm.Open(iCommServ, KCommPort, ECommExclusive)); + TCommConfig cBuf; + iComm.Config(cBuf); + TCommConfigV01& c=cBuf(); + c.iRate=EBps115200; + c.iDataBits=EData8; + c.iStopBits=EStop1; + c.iParity=EParityNone; + User::LeaveIfError(iComm.SetConfig(cBuf)); + delete iReader; + iReader=0; + iReader = new(ELeave) CCommsKeyReader(iComm, this); + delete iWriter; + iWriter=0; + iWriter = new(ELeave) CCommsKeyWriter(iComm); + } + +void CEikConsMessager::StopComms() + { + delete iWriter; + iWriter=0; + delete iReader; + iReader=0; + iComm.Close(); + iCommServ.Close(); + } + +void CEikConsMessager::WriteComms(const TDesC& aMsg) + { + if (iWriter) + { + iWriter->Write(aMsg); + } + } + + +struct TEscSeq + { + TText8 iText[4]; + TKeyCode iCode; + TStdScanCode iScanCode; + }; + +const TEscSeq KEscSeqs[] = + { + {"[?D", EKeyLeftArrow, EStdKeyLeftArrow}, + {"[?C", EKeyRightArrow, EStdKeyRightArrow}, + {"[?A", EKeyUpArrow, EStdKeyUpArrow}, + {"[?B", EKeyDownArrow, EStdKeyDownArrow} + }; + + +CCommsKeyReader::CCommsKeyReader(RComm& aComm, CEikConsMessager* aMessager) +: CActive(EPriorityHigh), iComm(aComm), iMessager(aMessager) + { + CActiveScheduler::Add(this); + Start(); + } + +CCommsKeyReader::~CCommsKeyReader() + { + Cancel(); + } + +void CCommsKeyReader::RunL() + { + if (iStatus == KErrNone) + { + Start(); + if (iMatch.Length() || iBuf[0]=='[') + { + iMatch.Append(iBuf[0]); + for (TInt i=0; i<4; i++) + { + if (iMatch.Match(TPtrC8(KEscSeqs[i].iText)) == 0) + { + TKeyEvent event = {KEscSeqs[i].iCode, KEscSeqs[i].iScanCode, 0, 0}; + iMessager->AddKeyEvent(event); + iMatch.Zero(); + return; + } + } + if (iMatch.Length() >= 3) + iMatch.Zero(); + else + return; + } + TKeyEvent event = {iBuf[0], iBuf[0], 0, 0}; + iMessager->AddKeyEvent(event); + } + } + +void CCommsKeyReader::DoCancel() + { + iComm.ReadCancel(); + } + +void CCommsKeyReader::Start() + { + iComm.ReadOneOrMore(iStatus, iBuf); + SetActive(); + } + + +CCommsKeyWriter::CCommsKeyWriter(RComm& aComm) +: CActive(EPriorityStandard), iComm(aComm), iInFakeCancel(EFalse) + { + CActiveScheduler::Add(this); + } + +CCommsKeyWriter::~CCommsKeyWriter() + { + Cancel(); + } + +void CCommsKeyWriter::Write(const TDesC& aDes) + { + for (TInt i=0; i0) + { + iWrite=iBuf; + iBuf.Zero(); + iComm.Write(iStatus, iWrite); + SetActive(); + } + } + +void CCommsKeyWriter::AppendBlocking(TText8 aChar) + { + if (iBuf.Length() >= iBuf.MaxLength()) + { + RTimer t; + t.CreateLocal(); + TRequestStatus tR; + t.After(tR, 2000000); // 2 second timeout + User::WaitForRequest(iStatus, tR); + if (iStatus != KRequestPending) + { + // write completed + t.Cancel(); + User::WaitForRequest(tR); + + if (IsActive()) + { + iInFakeCancel = ETrue; + Cancel(); + } + + iWrite.Zero(); + WriteIfReady(); + + } + else + { + // timeout, throw away the buffered data - sorry! + iBuf.Zero(); + } + t.Close(); + } + + iBuf.Append(aChar); + } + +void CCommsKeyWriter::RunL() + { + iWrite.Zero(); + WriteIfReady(); + } + +void CCommsKeyWriter::DoCancel() + { + if (iInFakeCancel == EFalse) + iComm.WriteCancel(); + + iInFakeCancel = EFalse; + } + + + +// +// class CEikConsAppUi +// + +struct SCommandLine + { + RThread iParentThread; + TRequestStatus* iStatus; + CEikConsoleClient* iClient; + TSize iSize; + const TDesC* iTitle; + }; + +class CEikConsAppUi : public CAknAppUi //CEikAppUi + { +public: + DECLARE_TYPE_ID(0x2001b26a) +public: + void ConstructL(const SCommandLine* aComLine); + ~CEikConsAppUi(); +private: // overridden + TKeyResponse HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType); + void HandleForegroundEventL(TBool aForeground); + void SetAndDrawFocus(TBool aFocus); +protected: // from MObjectProvider + virtual TTypeUid::Ptr MopSupplyObject(TTypeUid aId); + virtual MObjectProvider* MopNext(); +private: + CEikConsoleScreen* iScreen; + CEikConsoleControl* iControl; + CEikConsMessager* iMessager; + }; + +CEikConsAppUi::~CEikConsAppUi() + { + delete(iScreen); + delete(iMessager); + } + +void CEikConsAppUi::ConstructL(const SCommandLine* aComLine) + { + // CEikAppUi::BaseConstructL(ENoAppResourceFile); + CAknAppUi::BaseConstructL(ENoAppResourceFile | ENoScreenFurniture | EAknEnableMSK); + iScreen=new(ELeave) CEikConsoleScreen; + iScreen->ConstructL(*(aComLine->iTitle),0); + iControl=iScreen->ConsoleControl(); + iControl->SetFocus(ETrue,EDrawNow); + iMessager=new(ELeave) CEikConsMessager(iScreen,aComLine->iParentThread); + iMessager->ConstructL(aComLine->iClient); + RThread().SetPriority(EPriorityMore); + } + +void CEikConsAppUi::HandleForegroundEventL(TBool aForeground) + { + if (aForeground) + RThread().SetPriority(EPriorityMore); + CEikAppUi::HandleForegroundEventL(aForeground); + } + +void CEikConsAppUi::SetAndDrawFocus(TBool aFocus) + { + if (iControl) + iControl->SetFocus(aFocus,EDrawNow); + } + +TKeyResponse CEikConsAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) + { + iMessager->HandleKeyEventL(aKeyEvent, aType); + return EKeyWasConsumed; + } + +TTypeUid::Ptr CEikConsAppUi::MopSupplyObject(TTypeUid aId) +/** Retrieves an object of the same type as that encapsulated in aId. + +This function is used to allow to ask owners for access to +other objects that they own. + +Other than in the case where NULL is returned, the object returned must be +of the same object type - that is, the ETypeId member of the object pointed +to by the pointer returned by this function must be equal to the iUid member +of aId. + +@param aId An encapsulated object type ID. +@return Encapsulates the pointer to the object provided. Note that the encapsulated +pointer may be NULL. */ + { + if (aId.iUid == ETypeId) + { + // Touch compatibility mode uses this to detect console application + return aId.MakePtr(this); + } + return TTypeUid::Null(); + } + +MObjectProvider* CEikConsAppUi::MopNext() +/** Retrieves the parent. + +@return A pointer to an object provider, or NULL if none is defined. +@publishedAll +@released */ + { + CEikonEnv* env=(CEikonEnv*)iCoeEnv; + return env->AppUiFactory(); + } + +// +// class CConsEikonEnv +// + +class CConsEikonEnv : public CEikonEnv + { +public: + void ConstructConsoleEnvironmentL(const SCommandLine* aComLine); + +#if defined(SYMBIAN_UI_FRAMEWORKS_CONTROL_API_V2) +private: + IMPORT_C virtual void CEikonEnv_Reserved_1(); + IMPORT_C virtual void CEikonEnv_Reserved_2(); + IMPORT_C virtual void CEikonEnv_Reserved_3(); + IMPORT_C virtual void CEikonEnv_Reserved_4(); + IMPORT_C virtual void CEikonEnv_Reserved_5(); + IMPORT_C virtual void CEikonEnv_Reserved_6(); + IMPORT_C virtual void CEikonEnv_Reserved_7(); + IMPORT_C virtual void CEikonEnv_Reserved_8(); + IMPORT_C virtual void CEikonEnv_Reserved_9(); + IMPORT_C virtual void CEikonEnv_Reserved_10(); +#endif + }; + +void CConsEikonEnv::ConstructConsoleEnvironmentL(const SCommandLine* aComLine) + { + ConstructL(); + CEikConsAppUi* appUi=new(ELeave) CEikConsAppUi; + appUi->ConstructL(aComLine); + CApaWindowGroupName* wgName=CApaWindowGroupName::NewLC(iWsSession); + TPtrC caption=*(aComLine->iTitle); + wgName->SetCaptionL(caption); + wgName->SetRespondsToShutdownEvent(EFalse); + wgName->SetRespondsToSwitchFilesEvent(EFalse); + wgName->SetWindowGroupName(iRootWin); + CleanupStack::PopAndDestroy(); // wgName + + User::RenameProcess(caption); + User::RenameThread(caption); + } + +#if defined(SYMBIAN_UI_FRAMEWORKS_CONTROL_API_V2) +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_1() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_2() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_3() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_4() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_5() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_6() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_7() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_8() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_9() + { + } + +EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_10() + { + } +#endif + +TInt ConsoleClientStartFunction(TAny* aParam) + { + const SCommandLine* comLine=(const SCommandLine*)aParam; + TInt err=KErrNoMemory; + CConsEikonEnv* coe=new CConsEikonEnv; + if (coe) + { + TRAP(err,coe->ConstructConsoleEnvironmentL(comLine)); + } + TRequestStatus* pS=(comLine->iStatus); + comLine->iParentThread.RequestComplete(pS,err); + if (!err) + coe->ExecuteD(); + return(0); + } + +// +// class CEikConsoleClient +// + +CEikConsoleClient::~CEikConsoleClient() + { + if (iLogonStatus.Int()==KRequestPending && iReplyStatus) + SendReceive(EExit,NULL); + iThread.Close(); + } + +CEikConsoleClient::CEikConsoleClient() + { + } + +const TInt KMaxHeapSize=0x1000*254; // chunks are a megabyte anyway + +TInt CEikConsoleClient::Create(const TDesC& aTitle,TSize aSize) + { + TInt err; + TRequestStatus status=KRequestPending; + SCommandLine comLine; + comLine.iStatus=(&status); + comLine.iClient=this; + comLine.iSize=aSize; + comLine.iTitle=&aTitle; + TBuf<20> threadName; + TInt num=0; + do + { + _LIT(KTemp,"UI%02d"); + threadName.Format(KTemp,num++); // !! review the title + err=iThread.Create(threadName,ConsoleClientStartFunction,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&comLine,EOwnerThread); + } while(err==KErrAlreadyExists); + if (!err) + { + iThread.Logon(iLogonStatus); + comLine.iParentThread.Duplicate(iThread); + iThread.Resume(); + User::WaitForRequest(status,iLogonStatus); + err=status.Int(); + } + return(err); + } + +void CEikConsoleClient::SendReceive(TInt aMessage,const TAny* aParam) + { + if (iLogonStatus.Int()!=KRequestPending) + User::Exit(KErrCancel); + *iMessage=aMessage; + *iParam=aParam; + TRequestStatus replyStatus=KRequestPending; + *iReplyStatus=(&replyStatus); + TRequestStatus* pS=iThreadStatus; + iThread.RequestComplete(pS,0); + User::WaitForRequest(replyStatus,iLogonStatus); + } + +void CEikConsoleClient::Read(TRequestStatus& aStatus) + { + aStatus=KRequestPending; + SendReceive(ERead,&aStatus); + } + +void CEikConsoleClient::ReadCancel() + { + SendReceive(EReadCancel,NULL); + } + +void CEikConsoleClient::Write(const TDesC& aDes) + { + SendReceive(EWrite,&aDes); + } + +TPoint CEikConsoleClient::CursorPos() const + { + return(iScreen->CursorPos()); + } + +void CEikConsoleClient::SetCursorPosAbs(const TPoint& aPosition) + { + SendReceive(ESetCursorPosAbs,&aPosition); + } + +void CEikConsoleClient::SetCursorPosRel(const TPoint &aVector) + { + SendReceive(ESetCursorPosRel,&aVector); + } + +void CEikConsoleClient::SetCursorHeight(TInt aPercentage) + { + SendReceive(ESetCursorHeight,aPercentage); + } + +void CEikConsoleClient::SetTitle(const TDesC& aTitle) + { + SendReceive(ESetTitle,&aTitle); + } + +void CEikConsoleClient::ClearScreen() + { + SendReceive(EClearScreen,NULL); + } + +void CEikConsoleClient::ClearToEndOfLine() + { + SendReceive(EClearToEndOfLine,NULL); + } + +TSize CEikConsoleClient::ScreenSize() const + { + return(iScreen->ScreenSize() ); + } + +TKeyCode CEikConsoleClient::KeyCode() const + { + return((TKeyCode)iKeyEvent.iCode); + } + +TUint CEikConsoleClient::KeyModifiers() const + { + return(iKeyEvent.iModifiers); + } + +extern "C" { +EXPORT_C TAny* NewConsole() + { + return(new CEikConsoleClient); + } +}