--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/consoles/vt100cons/src/vt100/vtc_controller.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,883 @@
+// vtc_controller.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 <e32base.h>
+#include <fshell/common.mmh>
+#include "vtc_controller.h"
+#include "vtc_cursor_tracker.h"
+
+
+//
+// Constants.
+//
+
+_LIT(KAttSupportAttributes, "support_attributes");
+_LIT(KAttForegroundColor, "foreground_color");
+_LIT(KAttBackgroundColor, "background_color");
+
+class TEscapeMapping
+ {
+public:
+ TUint8 iEscapeChar;
+ TKeyCode iKeyCode;
+ };
+
+class TLongerEscapeMapping
+ {
+public:
+ TUint8 iEscapeChar1;
+ TUint8 iEscapeChar2;
+ TKeyCode iKeyCode;
+ };
+
+
+const TEscapeMapping KEscapeMappings[] =
+ {
+ { 'A', EKeyUpArrow },
+ { 'B', EKeyDownArrow },
+ { 'C', EKeyRightArrow },
+ { 'D', EKeyLeftArrow },
+ { 'H', EKeyHome },
+ { 'K', EKeyEnd },
+ };
+const TInt KNumEscapeMappings(sizeof(KEscapeMappings) / sizeof(TEscapeMapping));
+
+const TEscapeMapping KFunctionKeyMappings[] =
+ {
+ { 'P', EKeyF1 },
+ { 'Q', EKeyF2 },
+ { 'R', EKeyF3 },
+ { 'S', EKeyF4 },
+ };
+const TInt KNumEscapeFunctionMappings(sizeof(KFunctionKeyMappings) / sizeof(TEscapeMapping));
+
+// The following are for VT220 support, which is needed to get function keys understood from teraterm. They use ESC [xx~ where xx is given by the below table
+// See http://aperiodic.net/phil/archives/Geekery/term-function-keys.html for the reference I used
+const TLongerEscapeMapping KExtendedEscapeMappings[] =
+ {
+ { '1', '1', EKeyF1 },
+ { '1', '2', EKeyF2 },
+ { '1', '3', EKeyF3 },
+ { '1', '4', EKeyF4 },
+ { '1', '5', EKeyF5 },
+ // '1' '6' isn't used
+ { '1', '7', EKeyF6 },
+ { '1', '8', EKeyF7 },
+ { '1', '9', EKeyF8 },
+ { '2', '0', EKeyF9 },
+ { '2', '1', EKeyF10 },
+ // '2' '2' isn't used
+ { '2', '3', EKeyF11 },
+ { '2', '4', EKeyF12 },
+
+ // ESC [1~ is Home key according to http://www.zaik.uni-koeln.de/~ftp/elfi/etc/telnet.key
+ { '1', 0, EKeyHome },
+ { '4', 0, EKeyEnd },
+ { '5', 0, EKeyPageUp },
+ { '6', 0, EKeyPageDown },
+ { '2', 0, EKeyInsert },
+ { '3', 0, EKeyDelete },
+ };
+const TInt KNumExtendedEscapeMappings = sizeof(KExtendedEscapeMappings) / sizeof(TLongerEscapeMapping);
+
+static const TUint8 KEscapeChar1 = 0x1b;
+static const TUint8 KEscapeChar2 = '[';
+static const TUint8 KEscapeChar2Func = 'O';
+
+static const TInt KEscapeTimeoutMicros = 200000; // 1/5th second
+
+
+//______________________________________________________________________________
+// TKeyPress
+EXPORT_C TKeyPress::TKeyPress()
+ : iCode(EKeyNull), iModifiers(0)
+ {
+ }
+
+EXPORT_C TKeyPress::TKeyPress(TKeyCode aCode, TUint aModifiers)
+ : iCode(aCode), iModifiers(aModifiers)
+ {
+ }
+
+//______________________________________________________________________________
+// CVtConsoleOutputController
+EXPORT_C CVtConsoleOutputController* CVtConsoleOutputController::NewL(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile, const TSize& aScreenSize)
+ {
+ CVtConsoleOutputController* self = new(ELeave)CVtConsoleOutputController(aOutput, aIniFile);
+ CleanupStack::PushL(self);
+ User::LeaveIfError(self->Construct(aScreenSize));
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CVtConsoleOutputController* CVtConsoleOutputController::New(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile, const TSize& aScreenSize)
+ {
+ CVtConsoleOutputController* self = new CVtConsoleOutputController(aOutput, aIniFile);
+ TInt err = self->Construct(aScreenSize);
+ if (err!=KErrNone)
+ {
+ delete self;
+ self = NULL;
+ }
+ return self;
+ }
+
+class TAttributeBuf : public TBuf8<64>
+ {
+public:
+ enum TColorType
+ {
+ EForeground,
+ EBackground
+ };
+public:
+ TAttributeBuf(LtkUtils::CIniFile& aIniFile);
+ void Add(TUint aAttributes);
+ void Add(ConsoleAttributes::TColor aColor, TColorType aType);
+ void Finalize();
+ TBool SomethingAdded() const;
+private:
+ void Add(const TDesC8& aAttribute);
+private:
+ LtkUtils::CIniFile& iIniFile;
+ TBool iSomethingAdded;
+ };
+
+_LIT8(KPrefix, "\x1b[");
+TAttributeBuf::TAttributeBuf(LtkUtils::CIniFile& aIniFile)
+ : TBuf8<64>(KPrefix), iIniFile(aIniFile), iSomethingAdded(EFalse)
+ {
+ }
+
+void TAttributeBuf::Add(const TDesC8& aAttribute)
+ {
+ if (iSomethingAdded)
+ {
+ Append(';');
+ }
+ Append(aAttribute);
+ iSomethingAdded = ETrue;
+ }
+
+void TAttributeBuf::Finalize()
+ {
+ ASSERT(iSomethingAdded);
+ Append('m');
+ }
+
+TBool TAttributeBuf::SomethingAdded() const
+ {
+ return iSomethingAdded;
+ }
+
+void TAttributeBuf::Add(TUint aAttributes)
+ {
+ _LIT8(KAttReset, "0");
+ _LIT8(KAttBold, "1");
+ _LIT8(KAttUnderscore, "4");
+ _LIT8(KAttBlink, "5");
+ _LIT8(KAttInverse, "7");
+ _LIT8(KAttConceal, "8");
+
+ if (aAttributes & ConsoleAttributes::ENone)
+ {
+ Add(KAttReset);
+ Add((ConsoleAttributes::TColor)iIniFile.GetInt(KAttForegroundColor), TAttributeBuf::EForeground);
+ Add((ConsoleAttributes::TColor)iIniFile.GetInt(KAttBackgroundColor), TAttributeBuf::EBackground);
+ }
+ if (aAttributes & ConsoleAttributes::EBold)
+ {
+ Add(KAttBold);
+ }
+ if (aAttributes & ConsoleAttributes::EUnderscore)
+ {
+ Add(KAttUnderscore);
+ }
+ if (aAttributes & ConsoleAttributes::EBlink)
+ {
+ Add(KAttBlink);
+ }
+ if (aAttributes & ConsoleAttributes::EInverse)
+ {
+ Add(KAttInverse);
+ }
+ if (aAttributes & ConsoleAttributes::EConceal)
+ {
+ Add(KAttConceal);
+ }
+ }
+
+void TAttributeBuf::Add(ConsoleAttributes::TColor aColor, TColorType aType)
+ {
+ _LIT8(KFgBlack, "30");
+ _LIT8(KFgRed, "31");
+ _LIT8(KFgGreen, "32");
+ _LIT8(KFgYellow, "33");
+ _LIT8(KFgBlue, "34");
+ _LIT8(KFgMagenta, "35");
+ _LIT8(KFgCyan, "36");
+ _LIT8(KFgWhite, "37");
+ _LIT8(KFgReset, "39");
+ _LIT8(KBgBlack, "40");
+ _LIT8(KBgRed, "41");
+ _LIT8(KBgGreen, "42");
+ _LIT8(KBgYellow, "43");
+ _LIT8(KBgBlue, "44");
+ _LIT8(KBgMagenta, "45");
+ _LIT8(KBgCyan, "46");
+ _LIT8(KBgWhite, "47");
+ _LIT8(KBgReset, "49");
+
+ if (aType == EForeground)
+ {
+ switch (aColor)
+ {
+ default:
+ case ConsoleAttributes::EUnchanged:
+ {
+ // Do nothing.
+ break;
+ }
+ case ConsoleAttributes::EBlack:
+ {
+ Add(KFgBlack);
+ break;
+ }
+ case ConsoleAttributes::ERed:
+ {
+ Add(KFgRed);
+ break;
+ }
+ case ConsoleAttributes::EGreen:
+ {
+ Add(KFgGreen);
+ break;
+ }
+ case ConsoleAttributes::EYellow:
+ {
+ Add(KFgYellow);
+ break;
+ }
+ case ConsoleAttributes::EBlue:
+ {
+ Add(KFgBlue);
+ break;
+ }
+ case ConsoleAttributes::EMagenta:
+ {
+ Add(KFgMagenta);
+ break;
+ }
+ case ConsoleAttributes::ECyan:
+ {
+ Add(KFgCyan);
+ break;
+ }
+ case ConsoleAttributes::EWhite:
+ {
+ Add(KFgWhite);
+ break;
+ }
+ case ConsoleAttributes::EReset:
+ {
+ Add(KFgReset);
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (aColor)
+ {
+ default:
+ case ConsoleAttributes::EUnchanged:
+ {
+ // Do nothing.
+ break;
+ }
+ case ConsoleAttributes::EBlack:
+ {
+ Add(KBgBlack);
+ break;
+ }
+ case ConsoleAttributes::ERed:
+ {
+ Add(KBgRed);
+ break;
+ }
+ case ConsoleAttributes::EGreen:
+ {
+ Add(KBgGreen);
+ break;
+ }
+ case ConsoleAttributes::EYellow:
+ {
+ Add(KBgYellow);
+ break;
+ }
+ case ConsoleAttributes::EBlue:
+ {
+ Add(KBgBlue);
+ break;
+ }
+ case ConsoleAttributes::EMagenta:
+ {
+ Add(KBgMagenta);
+ break;
+ }
+ case ConsoleAttributes::ECyan:
+ {
+ Add(KBgCyan);
+ break;
+ }
+ case ConsoleAttributes::EWhite:
+ {
+ Add(KBgWhite);
+ break;
+ }
+ case ConsoleAttributes::EReset:
+ {
+ Add(KBgReset);
+ break;
+ }
+ }
+ }
+ }
+
+EXPORT_C TInt CVtConsoleOutputController::ResetAttributes()
+ {
+ if (iIniFile.GetBool(KAttSupportAttributes))
+ {
+ TAttributeBuf buf(iIniFile);
+ buf.Add(ConsoleAttributes::ENone);
+ buf.Finalize();
+ return iOutput.Output(buf);
+ }
+
+ return KErrNone;
+ }
+
+EXPORT_C TInt CVtConsoleOutputController::SetAttributes(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor)
+ {
+ if (iIniFile.GetBool(KAttSupportAttributes))
+ {
+ TAttributeBuf buf(iIniFile);
+ buf.Add(aAttributes);
+ buf.Add(aForegroundColor, TAttributeBuf::EForeground);
+ buf.Add(aBackgroundColor, TAttributeBuf::EBackground);
+
+ if (buf.SomethingAdded())
+ {
+ buf.Finalize();
+ return iOutput.Output(buf);
+ }
+
+ return KErrNone;
+ }
+
+ return KErrNotSupported;
+ }
+
+CVtConsoleOutputController::CVtConsoleOutputController(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile)
+ : iOutput(aOutput), iIniFile(aIniFile), iMode(ConsoleMode::EText)
+ {
+ }
+
+TInt CVtConsoleOutputController::Construct(const TSize& aScreenSize)
+ {
+ iCursorTracker = new TCursorTracker(aScreenSize);
+ if (!iCursorTracker) return KErrNoMemory;
+ return KErrNone;
+ }
+
+EXPORT_C CVtConsoleOutputController::~CVtConsoleOutputController()
+ {
+ delete iCursorTracker;
+ iOutputBuf.Close();
+ }
+
+TInt CVtConsoleOutputController::GetCursorPos(TPoint& aPos) const
+ {
+ aPos = iCursorTracker->CursorPos();
+ return KErrNone;
+ }
+
+
+TInt CVtConsoleOutputController::SetCursorPosAbs(const TPoint& aPos)
+ {
+ TInt err = KErrInUse;
+ if (iMode == ConsoleMode::EText)
+ {
+ _LIT8(KEscapeSetCursorPosAbs, "\x1b[%u;%uH");
+ TBuf8<32> buf;
+ buf.Format(KEscapeSetCursorPosAbs, aPos.iY + 1, aPos.iX + 1);
+ err = iOutput.Output(buf);
+ if (err == KErrNone)
+ {
+ iCursorTracker->SetCursorPosAbs(aPos);
+ }
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::SetCursorPosRel(const TPoint& aPoint)
+ {
+ TInt err = KErrInUse;
+ if (iMode == ConsoleMode::EText)
+ {
+ TBuf8<32> buf;
+
+ if (aPoint.iY == 0)
+ {
+ // Do nothing.
+ }
+ else if (aPoint.iY < 0)
+ {
+ // Move cursor up.
+ _LIT8(KEscapeCursorUp, "\x1b[%uA");
+ buf.AppendFormat(KEscapeCursorUp, -aPoint.iY);
+ }
+ else if (aPoint.iY > 0)
+ {
+ // Move cursor down.
+ _LIT8(KEscapeCursorDown, "\x1b[%uB");
+ buf.AppendFormat(KEscapeCursorDown, aPoint.iY);
+ }
+
+ if (aPoint.iX == 0)
+ {
+ // Do nothing.
+ }
+ else if (aPoint.iX < 0)
+ {
+ // Move cursor left.
+ _LIT8(KEscapeCursorLeft, "\x1b[%uD");
+ buf.AppendFormat(KEscapeCursorLeft, -aPoint.iY);
+ }
+ else if (aPoint.iX > 0)
+ {
+ // Move cursor right.
+ _LIT8(KEscapeCursorRight, "\x1b[%uC");
+ buf.AppendFormat(KEscapeCursorRight, aPoint.iY);
+ }
+
+ err = KErrNone;
+ if (buf.Length() > 0)
+ {
+ err = iOutput.Output(buf);
+ if (err == KErrNone)
+ {
+ iCursorTracker->SetCursorPosRel(aPoint);
+ }
+ }
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::SetCursorHeight(TInt aPercentage)
+ {
+ TInt err = KErrInUse;
+ if (iMode == ConsoleMode::EText)
+ {
+ _LIT8(KEscapeHideCursor, "\x1b[?25l");
+ _LIT8(KEscapeSeeCursor, "\x1b[?25h");
+ if (aPercentage == 0)
+ {
+ err = iOutput.Output(KEscapeHideCursor);
+ }
+ else
+ {
+ err = iOutput.Output(KEscapeSeeCursor);
+ }
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::SetTitle(const TDesC&)
+ {
+ return KErrNone;
+ }
+
+TInt CVtConsoleOutputController::ClearScreen()
+ {
+ TInt err = KErrInUse;
+ if (iMode == ConsoleMode::EText)
+ {
+ _LIT8(KResetTerminal, "\x1b" "c" "\x1b" "[?7h"); // reset console, then enable line wrapping
+ err = iOutput.Output(KResetTerminal);
+ if (err == KErrNone)
+ {
+ User::After(100000); // It seems that TeraTerm doesn't like receiving attribute changes too soon after a terminal reset (tends to ignore the attributes).
+ err = ResetAttributes();
+ if (err == KErrNone)
+ {
+ _LIT8(KEscapeClearScreen, "\x1b[2J\x1b[01;01H");
+ err = iOutput.Output(KEscapeClearScreen);
+ if (err == KErrNone)
+ {
+ iCursorTracker->Reset();
+ }
+ }
+ }
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::ClearToEndOfLine()
+ {
+ TInt err = KErrInUse;
+ if (iMode == ConsoleMode::EText)
+ {
+ _LIT8(KEscapeClearToEndOfLine, "\x1b[K");
+ err = iOutput.Output(KEscapeClearToEndOfLine);
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::GetScreenSize(TSize& aSize) const
+ {
+ aSize = iCursorTracker->ConsoleSize();
+ return KErrNone;
+ }
+
+TInt CVtConsoleOutputController::Write(const TDesC& aDes)
+ {
+ TInt err = KErrNone;
+ if (iMode == ConsoleMode::EBinary)
+ {
+ // staight collapse to 8 bit, no cleverness
+ TBuf8<256> buf;
+ TInt offset = 0;
+ while ((offset < aDes.Length()) && (err == KErrNone))
+ {
+ buf.Copy(aDes.Mid(offset, Min(aDes.Length() - offset, buf.MaxLength())));
+ offset += buf.Length();
+ err = iOutput.Output(buf);
+ }
+ }
+ else
+ {
+ // In text mode we do a UTF-16 -> UTF-8 conversion
+ TRAP(err, iOutputBuf.CopyAsUtf8L(aDes));
+ if (err == KErrNone)
+ {
+ err = iOutput.Output(iOutputBuf);
+ if (err == KErrNone)
+ {
+ iCursorTracker->Write(aDes);
+ }
+ }
+ }
+ return err;
+ }
+
+TInt CVtConsoleOutputController::Write(const TDesC8& aDes)
+ {
+ TInt err = iOutput.Output(aDes);
+ if ((err == KErrNone) && (iMode == ConsoleMode::EText))
+ {
+ iCursorTracker->Write(aDes);
+ }
+ return err;
+ }
+
+void CVtConsoleOutputController::SetMode(ConsoleMode::TMode aMode)
+ {
+ iMode = aMode;
+ }
+
+//______________________________________________________________________________
+// CVtConsoleInputController
+
+EXPORT_C CVtConsoleInputController* CVtConsoleInputController::New(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
+ {
+ CVtConsoleInputController* self = NULL;
+ TRAPD(err, self = NewL(aConsoleInput, aIniFile));
+ if (err == KErrNone)
+ {
+ return self;
+ }
+ return NULL;
+ }
+
+EXPORT_C CVtConsoleInputController* CVtConsoleInputController::NewL(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
+ {
+ CVtConsoleInputController* self = NewLC(aConsoleInput, aIniFile);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CVtConsoleInputController* CVtConsoleInputController::NewLC(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
+ {
+ CVtConsoleInputController* self = new(ELeave)CVtConsoleInputController(aConsoleInput, aIniFile);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CVtConsoleInputController::CVtConsoleInputController(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
+ : CActive(CActive::EPriorityStandard), iConsoleInput(aConsoleInput), iIniFile(aIniFile), iMode(ConsoleMode::EText)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CVtConsoleInputController::ConstructL()
+ {
+ iEscapeTimer = CPeriodic::NewL(CActive::EPriorityLow);
+ }
+
+CVtConsoleInputController::~CVtConsoleInputController()
+ {
+ Reset();
+ delete iEscapeTimer;
+ }
+
+EXPORT_C void CVtConsoleInputController::GetKeyPress(TKeyPress& aKeyPress, TRequestStatus& aStatus)
+ {
+ ASSERT((iClientKeyPress == NULL) && (iClientRequestStatus == NULL));
+ iClientKeyPress = &aKeyPress;
+ iClientRequestStatus = &aStatus;
+ *iClientRequestStatus = KRequestPending;
+ if (iKeyCodePending)
+ {
+ iKeyCodePending = EFalse;
+ CompleteKeyPressRequest(iPendingKeyCode);
+ }
+ else if (iInputError)
+ {
+ CompleteKeyPressRequest(iInputError);
+ iInputError = KErrNone;
+ }
+ else
+ {
+ ReadKeyPress();
+ }
+ }
+
+EXPORT_C void CVtConsoleInputController::CancelGetKeyPress()
+ {
+ Cancel();
+ if (iClientRequestStatus)
+ {
+ CompleteKeyPressRequest(KErrCancel);
+ }
+ }
+
+EXPORT_C void CVtConsoleInputController::SetMode(ConsoleMode::TMode aMode)
+ {
+ Reset();
+ iMode = aMode;
+ }
+
+void CVtConsoleInputController::ReadKeyPress()
+ {
+ iEscapeTimer->Cancel();
+
+ while (iClientRequestStatus && (iBufPos < iBuf.Length()))
+ {
+ TUint8 c = iBuf[iBufPos++];
+ if (iMode == ConsoleMode::EBinary)
+ {
+ CompleteKeyPressRequest((TKeyCode)c);
+ }
+ else
+ {
+ switch (iState)
+ {
+ case ENormal:
+ if (c == KEscapeChar1)
+ {
+ iState = EWaitingForEscapeChar2;
+ if (iBufPos == iBuf.Length())
+ {
+ iEscapeTimer->Start(KEscapeTimeoutMicros, KEscapeTimeoutMicros, TCallBack(EscapeTimeoutS, this));
+ }
+ }
+ else
+ {
+ CompleteKeyPressRequest((TKeyCode)c);
+ }
+ break;
+ case EWaitingForEscapeChar2:
+ if (c == KEscapeChar2)
+ {
+ iState = EWaitingForEscapeChar3;
+ }
+ else if (c == KEscapeChar2Func)
+ {
+ iState = EWaitingForEscapeChar3Func;
+ }
+ else
+ {
+ CompleteKeyPressRequest(EKeyEscape, (TKeyCode)c);
+ iState = ENormal;
+ }
+ break;
+ case EWaitingForEscapeChar3:
+ if (c >= '0' && c <= '9')
+ {
+ iState = EWaitingForExtendedFunc;
+ iExtendedEscapeBuf.Zero();
+ iExtendedEscapeBuf.Append(c);
+ }
+ else
+ {
+ DoEscapeKeyL(c, KEscapeMappings, KNumEscapeMappings);
+ }
+ break;
+ case EWaitingForEscapeChar3Func:
+ DoEscapeKeyL(c, KFunctionKeyMappings, KNumEscapeFunctionMappings);
+ break;
+ case EWaitingForExtendedFunc:
+ if (iExtendedEscapeBuf.Length() < iExtendedEscapeBuf.MaxLength() && ((c >= '0' && c <= '9') || c == ';'))
+ {
+ iExtendedEscapeBuf.Append(c);
+ // Stay in this state until you see a '~'
+ }
+ else if (c == '~')
+ {
+ DoExtendedEscapeKey();
+ }
+ else
+ {
+ // Gone off the rails, bail
+ iState = ENormal;
+ CompleteKeyPressRequest((TKeyCode)c);
+ }
+ break;
+ }
+ }
+ }
+
+ ReadInput();
+ }
+
+void CVtConsoleInputController::CompleteKeyPressRequest(TInt aError)
+ {
+ ASSERT(iClientKeyPress && iClientRequestStatus);
+ iClientKeyPress = NULL;
+ User::RequestComplete(iClientRequestStatus, aError);
+ }
+
+void CVtConsoleInputController::CompleteKeyPressRequest(TKeyCode aKeyCode)
+ {
+ ASSERT(iClientKeyPress && iClientRequestStatus);
+ iClientKeyPress->iCode = (TKeyCode)aKeyCode;
+ iClientKeyPress->iModifiers = 0;
+ iClientKeyPress = NULL;
+ User::RequestComplete(iClientRequestStatus, KErrNone);
+ }
+
+void CVtConsoleInputController::CompleteKeyPressRequest(TKeyCode aKeyCode1, TKeyCode aKeyCode2)
+ {
+ ASSERT(!iKeyCodePending);
+ // Store the second key-code in a member variable to be used the next time GetKeyPress is called.
+ iKeyCodePending = ETrue;
+ iPendingKeyCode = aKeyCode2;
+ CompleteKeyPressRequest(aKeyCode1);
+ }
+
+void CVtConsoleInputController::Reset()
+ {
+ Cancel();
+ iEscapeTimer->Cancel();
+ iState = ENormal;
+ iKeyCodePending = EFalse;
+ }
+
+void CVtConsoleInputController::ReadInput()
+ {
+ if (iClientRequestStatus && !IsActive()) // Note, if the escape timer expired we could already be active.
+ {
+ ASSERT(iBufPos == iBuf.Length());
+ iBufPos = 0;
+ iBuf.Zero();
+ iConsoleInput.Input(iBuf, iStatus);
+ SetActive();
+ }
+ }
+
+void CVtConsoleInputController::RunL()
+ {
+ TInt err = iStatus.Int();
+#ifdef FSHELL_PLATFORM_OPP
+ if (err == KErrAbort)
+ {
+ ReadInput();
+ return;
+ }
+#endif
+ if (err == KErrNone)
+ {
+ ReadKeyPress();
+ }
+ else if (iClientRequestStatus)
+ {
+ CompleteKeyPressRequest(err);
+ }
+ else
+ {
+ // Report the error next time the client requests a key.
+ iInputError = err;
+ }
+ }
+
+void CVtConsoleInputController::DoCancel()
+ {
+ iConsoleInput.CancelInput(iStatus);
+ }
+
+void CVtConsoleInputController::DoEscapeKeyL(TUint8 aChar, const TEscapeMapping* aMappings, TInt aMappingCount)
+ {
+ iState = ENormal;
+ for (TInt j = 0; j < aMappingCount; ++j)
+ {
+ if (aChar == aMappings[j].iEscapeChar)
+ {
+ CompleteKeyPressRequest(aMappings[j].iKeyCode);
+ return;
+ }
+ }
+ }
+
+TInt CVtConsoleInputController::EscapeTimeout()
+ {
+ ASSERT(iState == EWaitingForEscapeChar2);
+ iState = ENormal;
+ CompleteKeyPressRequest(EKeyEscape);
+ return KErrNone;
+ }
+
+TInt CVtConsoleInputController::EscapeTimeoutS(TAny* aSelf)
+ {
+ return ((CVtConsoleInputController*)aSelf)->EscapeTimeout();
+ }
+
+
+void CVtConsoleInputController::DoExtendedEscapeKey()
+ {
+ iState = ENormal;
+ TUint8 escape1 = 0;
+ TUint8 escape2 = 0;
+ if (iExtendedEscapeBuf.Length()) escape1 = iExtendedEscapeBuf[0];
+ if (iExtendedEscapeBuf.Length() > 1) escape2 = iExtendedEscapeBuf[1];
+
+ for (TInt j = 0; j < KNumExtendedEscapeMappings; ++j)
+ {
+ const TLongerEscapeMapping& mapping = KExtendedEscapeMappings[j];
+ if (escape1 == mapping.iEscapeChar1 && escape2 == mapping.iEscapeChar2)
+ {
+ CompleteKeyPressRequest(mapping.iKeyCode);
+ return;
+ }
+ }
+ }