# HG changeset patch # User Tom Sutcliffe # Date 1282583431 -3600 # Node ID cfabd0207208bac78af3908a2795a978fab7a067 # Parent 50af04b02d7dd2a5943da7ba36fa664a78decbf0 Added terminalkeyboard console (terminalkeyboardcons.dll) diff -r 50af04b02d7d -r cfabd0207208 build/ncp/platform.mmh --- a/build/ncp/platform.mmh Fri Aug 13 16:18:06 2010 +0100 +++ b/build/ncp/platform.mmh Mon Aug 23 18:10:31 2010 +0100 @@ -20,5 +20,6 @@ #define FSHELL_NO_APPARC_SUPPORT #define FSHELL_FLEXIBLEMM_AWARE #define FSHELL_ARM11XX_SUPPORT +#define FSHELL_TRACECORE_SUPPORT #endif // FSHELL_PLATFORM_MMH diff -r 50af04b02d7d -r cfabd0207208 build/s60/tb92/platform.mmh --- a/build/s60/tb92/platform.mmh Fri Aug 13 16:18:06 2010 +0100 +++ b/build/s60/tb92/platform.mmh Mon Aug 23 18:10:31 2010 +0100 @@ -29,5 +29,6 @@ #define FSHELL_DYNAMICSTARTUP_SUPPORT #define FSHELL_TESTEXECUTE_SUPPORT +#define FSHELL_TRACECORE_SUPPORT #endif // FSHELL_PLATFORM_MMH diff -r 50af04b02d7d -r cfabd0207208 documentation/common_mmh.pod --- a/documentation/common_mmh.pod Fri Aug 13 16:18:06 2010 +0100 +++ b/documentation/common_mmh.pod Mon Aug 23 18:10:31 2010 +0100 @@ -218,6 +218,10 @@ The TestExecute APIs are available. +=item FSHELL_TRACECORE_SUPPORT + +The TraceCore APIs are available. + =back A couple of further macros follow - these are specifically for platforms that provide an custom implementation of the relevant command rather than using fshell's built-in version. diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/common/bld.inf --- a/plugins/consoles/common/bld.inf Fri Aug 13 16:18:06 2010 +0100 +++ b/plugins/consoles/common/bld.inf Mon Aug 23 18:10:31 2010 +0100 @@ -49,3 +49,7 @@ PRJ_MMPFILES ..\tefcons\tefcons.mmp #endif + +#ifdef FSHELL_TRACECORE_SUPPORT +..\terminalkeyboardcons\terminalkeyboardcons.mmp +#endif diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.cpp Mon Aug 23 18:10:31 2010 +0100 @@ -0,0 +1,393 @@ +// terminalkeyboardcons.cpp +// +// Copyright (c) 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 "terminalkeyboardcons.h" +#include +#include +#include + +const TInt KTkbdMessageId = 0xD6; +// These are the defaults unless overridden by --console-size +const TInt KWidth = 80; +const TInt KHeight = 24; + +class CMessageWatcher : public CActive + { +public: + CMessageWatcher(CTerminalKeyboardCons& aConsole) + : CActive(CActive::EPriorityStandard), iConsole(aConsole) + { + CActiveScheduler::Add(this); + iConsole.iDriver.RequestMessage(iStatus); + SetActive(); + } + + void DoCancel() + { + iConsole.iDriver.CancelMessage(); + } + + void RunL() + { + iConsole.MessageReceived(iStatus.Int()); + if (iStatus.Int() == KErrNone) + { + iConsole.iDriver.RequestMessage(iStatus); + SetActive(); + } + } + + ~CMessageWatcher() + { + Cancel(); + } + +private: + CTerminalKeyboardCons& iConsole; + }; + + +CTerminalKeyboardCons::CTerminalKeyboardCons() + : iTracker(TSize(KWidth, KHeight), this) + { + } + +CTerminalKeyboardCons::~CTerminalKeyboardCons() + { + CleanupUnderlyingConsole(); + delete iWatcher; + iDriver.Close(); + iTextBuffer.Close(); + iMungedTextBuffer.Close(); + } + +TInt CTerminalKeyboardCons::Create(const TDesC& aTitle, TSize aSize) + { + TRAPD(err, ConstructL(aTitle, aSize)); + HandleConsoleCreationError(_L("TerminalKeyboard"), err); + return err; + } + +void CTerminalKeyboardCons::ConstructL(const TDesC& aTitle, const TSize& aSize) + { + if (aTitle == _L("debug")) SetDebug(ETrue); + if (aSize.iWidth > 10 && aSize.iHeight > 10) + { + // Override size now we know it, checking that it's sane-ish - be sure to do this before anything that uses the console size! + new (&iTracker) TCursorTracker(aSize, this); + } + + iTextBuffer.CreateMaxL(ScreenSize().iWidth * ScreenSize().iHeight); +#ifdef SHOW_TEXTSHELL_BORDERS + iMungedTextBuffer.CreateL((ScreenSize().iWidth + 2) * (ScreenSize().iHeight + 2)); +#endif + + TInt err = User::LoadLogicalDevice(KTcLddDriverName); + if (err && err != KErrAlreadyExists) + { + Message(EError, _L("Couldn't load LDD %S: %d"), &KTcLddDriverName, err); + User::Leave(err); + } + + // Idiotic driver only accepts connections from processes with nokia vid - like that will stop us + TUint originalVid = RProcess().VendorId(); + RMemoryAccess memAccess; + User::LeaveIfError(memAccess.Open()); + TProcessProperties props; + props.iVid = 0x101FB657; + RProcess me; me.Open(RProcess().Id()); + memAccess.SetProcessProperties(me, props); + + err = iDriver.Open(); + + props.iVid = originalVid; + memAccess.SetProcessProperties(me, props); + me.Close(); + memAccess.Close(); + + if (err) + { + Message(EError, _L("Couldn't open RTcDriver: %d"), err); + User::Leave(err); + } + + err = iDriver.Subscribe(KTkbdMessageId); + if (err) + { + Message(EError, _L("Couldn't subscribe: %d"), err); + User::Leave(err); + } + + iWatcher = new(ELeave) CMessageWatcher(*this); + CleanupUnderlyingConsole(); + + ClearScreen(); + } + + +TInt CTerminalKeyboardCons::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1) + { + /*if (aExtensionId == ConsoleMode::KSetConsoleModeExtension) + { + ConsoleMode::TMode mode = (ConsoleMode::TMode)(TInt)a1; + iInputController->SetMode(mode); + iOutputController->SetMode(mode); + return KErrNone; + } + else*/ + /*else if (aExtensionId == ConsoleAttributes::KSetConsoleAttributesExtension) + { + ConsoleAttributes::TAttributes* attributes = (ConsoleAttributes::TAttributes*)a1; + return iOutputController->SetAttributes(attributes->iAttributes, attributes->iForegroundColor, attributes->iBackgroundColor); + }*/ + + TInt ret = MIosrvConsoleHelper_Extension(aExtensionId, a0, a1); + if (ret == KErrExtensionNotSupported) ret = CConsoleBase::Extension_(aExtensionId, a0, a1); + return ret; + } + +void CTerminalKeyboardCons::MessageReceived(TInt aError) + { + Message(EDebug, _L("MessageReceived err=%d"), aError); + TInt err = aError; + if (err == KErrNone) + { + TPtrC8 data; + err = iDriver.GetMessageData(data); + if (!err && data.Length() < 1) err = KErrCorrupt; + if (!err && !iGotKey) + { + TUint16 rawkey = data[0]; + Message(EDebug, _L("CTerminalKeyboardCons got key %d"), (TInt)rawkey); + + // Terminal keyboard doesn't support control keys or cursor keys so we use our own two-stage sticky modifier (like unix meta key I think?) + if (iBacktickModifierDown) + { + // Terminal keyboard sends 2,4,6,8 for cursors, so we translate backtick-2 (ie backtick-leftarrow) as meaning left arrow + if (rawkey == '2') rawkey = (TUint16)EKeyUpArrow; + else if (rawkey == '4') rawkey = (TUint16)EKeyLeftArrow; + else if (rawkey == '6') rawkey = (TUint16)EKeyRightArrow; + else if (rawkey == '8') rawkey = (TUint16)EKeyDownArrow; + else if (rawkey >= 'a' && rawkey <= 'z') + { + // backtick-c means CTRL-C + rawkey = rawkey - 'a'+1; + } + else if (rawkey == ' ') rawkey = '`'; // backtick-space is how you do a backtick + else if (rawkey == '`') rawkey = (TUint16)EKeyEscape; // backtick-backtick is 'escape' + else if (rawkey == '1') rawkey = (TUint16)EKeyTab; // backtick-1 is 'tab' + iBacktickModifierDown = EFalse; + Message(EDebug, _L("Backtick escape converted to %d"), (TInt)rawkey); + } + else if (rawkey == '`') + { + iBacktickModifierDown = ETrue; + return; + } + + iKeyCode = (TKeyCode)rawkey; // Close enough for now! + iGotKey = ETrue; + } + } + if (iClientStatus) + { + User::RequestComplete(iClientStatus, err); + if (err == KErrNone) iGotKey = EFalse; + } + } + +void CTerminalKeyboardCons::Read(TRequestStatus& aStatus) + { + /*if (iClientStatus) + { + TRequestStatus* stat = &aStatus; + User::RequestComplete(stat, KErrInUse); + } + else*/ + { + aStatus = KRequestPending; + iClientStatus = &aStatus; + if (iGotKey) + { + iGotKey = EFalse; + User::RequestComplete(iClientStatus, KErrNone); + } + } + } + +void CTerminalKeyboardCons::ReadCancel() + { + if (iClientStatus) + { + User::RequestComplete(iClientStatus, KErrCancel); + } + } + +void CTerminalKeyboardCons::Write(const TDesC& aDes) + { + for (TInt i = 0; i < aDes.Length(); i++) + { + TInt textBufPos = CursorPos().iY * ScreenSize().iWidth + CursorPos().iX; + TChar ch(aDes[i]); + iTracker.WriteChar(ch); + if (ch.IsPrint()) iTextBuffer[textBufPos] = aDes[i]; + } + + Update(); + } + +TPoint CTerminalKeyboardCons::CursorPos() const + { + return iTracker.CursorPos(); + } + +void CTerminalKeyboardCons::SetCursorPosAbs(const TPoint& aPoint) + { + iTracker.SetCursorPosAbs(aPoint); + } + +void CTerminalKeyboardCons::SetCursorPosRel(const TPoint& aPoint) + { + iTracker.SetCursorPosRel(aPoint); + } + +void CTerminalKeyboardCons::SetCursorHeight(TInt /*aPercentage*/) + { + //iOutputController->SetCursorHeight(aPercentage); + } + +void CTerminalKeyboardCons::SetTitle(const TDesC& /*aDes*/) + { + //iOutputController->SetTitle(aDes); + } + +void CTerminalKeyboardCons::ClearScreen() + { + SetCursorPosAbs(TPoint(0,0)); + iTextBuffer.Fill(' '); + Update(); + } + +void CTerminalKeyboardCons::ClearToEndOfLine() + { + iTextBuffer.MidTPtr(CursorPos().iY * ScreenSize().iWidth + CursorPos().iX, ScreenSize().iWidth - CursorPos().iX).Fill(' '); + Update(); + } + +TSize CTerminalKeyboardCons::ScreenSize() const + { + return iTracker.ConsoleSize(); + } + +TKeyCode CTerminalKeyboardCons::KeyCode() const + { + return iKeyCode; + } + +TUint CTerminalKeyboardCons::KeyModifiers() const + { + return iKeyModifiers; + } + +// All these magic vals are as per the DOS 437 codepage http://en.wikipedia.org/wiki/CP437 and not Windows-1252 like the ws_win.cpp source incorrectly states +// See also http://en.wikipedia.org/wiki/Box_drawing_characters +enum + { + EBoxHorizontalBar = 0xCD, + EBoxVerticalBar = 0xBA, + EBoxTopLeft = 0xC9, + EBoxTopRight = 0xBB, + EBoxBottomLeft = 0xC8, + EBoxBottomRight = 0xBC, + }; + +void CTerminalKeyboardCons::Update() + { +#ifdef SHOW_TEXTSHELL_BORDERS + // Update munged buffer + const TInt contentWidth = ScreenSize().iWidth; + const TInt width = contentWidth + 2; + iMungedTextBuffer.SetLength(width); + iMungedTextBuffer.Fill(TChar(EBoxHorizontalBar)); + iMungedTextBuffer[0] = EBoxTopLeft; + iMungedTextBuffer[width-1] = EBoxTopRight; + + for (TInt i = 0; i < ScreenSize().iHeight; i++) + { + TPtrC line(iTextBuffer.Mid(i*contentWidth, contentWidth)); + iMungedTextBuffer.AppendFormat(_L("%c%S%c"), EBoxVerticalBar, &line, EBoxVerticalBar); + } + + iMungedTextBuffer.Append(EBoxBottomLeft); + iMungedTextBuffer.SetLength(iMungedTextBuffer.Length() + contentWidth); + iMungedTextBuffer.RightTPtr(contentWidth).Fill(EBoxHorizontalBar); + iMungedTextBuffer.Append(EBoxBottomRight); + + // And send the munged buffer + Transmit(iMungedTextBuffer, width, ScreenSize().iHeight + 2); +#else + // Just send it straight + Transmit(iTextBuffer, ScreenSize().iWidth, ScreenSize().iHeight); +#endif + } + +void CTerminalKeyboardCons::Transmit(const TDesC& aBuf, TInt aWidth, TInt aHeight) + { + // This is how terminal keyboard does it - pretty horrible really + + static const TInt KMaxLen = 200; // This is what terminal keyboard uses - technically you could go as far as a total of 256 + TInt numLinesPerPrint = KMaxLen / aWidth; + + TBuf<256> line; + TInt startLine = 0; + while (startLine < aHeight) + { + if (startLine == 0) + { + // First line has extra info + line.Format(_L("#$STIConsole#$%02d%02X%02X"), startLine, aWidth, aHeight); + } + else + { + line.Format(_L("#$STIConsole#$%02d"), startLine); + } + + for (TInt i = 0; i < numLinesPerPrint; i++) + { + TPtrC theContents(aBuf.Mid((startLine+i)*aWidth, aWidth)); + //RDebug::Printf("line len=%d theContents len=%d", line.Length(), theContents.Length()); + line.Append(theContents); + } + + RDebug::Print(line); + startLine += numLinesPerPrint; + } + } + +void CTerminalKeyboardCons::ConsoleScrolled(TInt aNumberOfLines) + { + TInt numChars = Abs(aNumberOfLines) * ScreenSize().iWidth; + if (aNumberOfLines > 0) + { + iTextBuffer.Delete(0, numChars); + iTextBuffer.AppendFill(' ', numChars); + } + else if (aNumberOfLines < 0) + { + iTextBuffer.SetLength(iTextBuffer.Length() - numChars); + while (numChars--) iTextBuffer.Insert(0, _L(" ")); + } + } + +extern "C" EXPORT_C TAny* NewConsole() + { + return new CTerminalKeyboardCons; + } diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.h Mon Aug 23 18:10:31 2010 +0100 @@ -0,0 +1,72 @@ +// terminalkeyboardcons.h +// +// Copyright (c) 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 +// +#ifndef TERMINALKEYBOARDCONS_H +#define TERMINALKEYBOARDCONS_H + +#include +#include +#include +#include +#include "vtc_cursor_tracker.h" +class CMessageWatcher; + +//#define SHOW_TEXTSHELL_BORDERS + +NONSHARABLE_CLASS(CTerminalKeyboardCons) : public CConsoleBase, public MIosrvConsoleHelper, public MConsoleScrollHandler + { +public: + CTerminalKeyboardCons(); + virtual ~CTerminalKeyboardCons(); + +public: // From CConsoleBase + virtual TInt Create(const TDesC& aTitle, TSize aSize); + virtual void Read(TRequestStatus& aStatus); + virtual void ReadCancel(); + virtual void Write(const TDesC& aDes); + virtual TPoint CursorPos() const; + virtual void SetCursorPosAbs(const TPoint& aPoint); + virtual void SetCursorPosRel(const TPoint& aPoint); + virtual void SetCursorHeight(TInt aPercentage); + virtual void SetTitle(const TDesC& aTitle); + virtual void ClearScreen(); + virtual void ClearToEndOfLine(); + virtual TSize ScreenSize() const; + virtual TKeyCode KeyCode() const; + virtual TUint KeyModifiers() const; + virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1); + +private: // From MConsoleScrollHandler + void ConsoleScrolled(TInt aNumberOfLines); + +private: + virtual void ConstructL(const TDesC& aTitle, const TSize& aSize); + void Update(); + void MessageReceived(TInt aError); + void Transmit(const TDesC& aBuf, TInt aWidth, TInt aHeight); + +protected: + TRequestStatus* iClientStatus; + TBool iGotKey; + TKeyCode iKeyCode; + TUint iKeyModifiers; + CConsoleBase* iUnderlyingConsole; + RTcDriver iDriver; + + RBuf iTextBuffer; + RBuf iMungedTextBuffer; // With the borders + TCursorTracker iTracker; + CMessageWatcher* iWatcher; + friend class CMessageWatcher; + TBool iBacktickModifierDown; + }; + +#endif // TERMINALKEYBOARDCONS_H diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/consoles/terminalkeyboardcons/terminalkeyboardcons.mmp Mon Aug 23 18:10:31 2010 +0100 @@ -0,0 +1,33 @@ +// terminalkeyboardcons.mmp +// +// Copyright (c) 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 + +target terminalkeyboardcons.dll +targettype DLL +uid 0x1000008d 0x100039e7 // Note this MUST be set to 0x100039e7 +capability FSHELL_CAP_MMP_NORMAL + +sourcepath . +userinclude . +userinclude ..\vt100cons\src\vt100 // For vtc_cursor_tracker.h +#include + +source terminalkeyboardcons.cpp +sourcepath ..\vt100cons\src\vt100 +source vtc_cursor_tracker.cpp + +library euser.lib +library econs.lib +library consoleextensions.lib + +nostrictdef +deffile ..\common\~\console.def diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.cpp --- a/plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.cpp Fri Aug 13 16:18:06 2010 +0100 +++ b/plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.cpp Mon Aug 23 18:10:31 2010 +0100 @@ -17,15 +17,15 @@ // Constants. // -const TInt KTabSize = 8; +const TInt KTabSize = 4; // // TCursorTracker. // -TCursorTracker::TCursorTracker(TSize aConsoleSize) - : iConsoleSize(aConsoleSize), iCursorPos(TPoint(0, 0)) +TCursorTracker::TCursorTracker(TSize aConsoleSize, MConsoleScrollHandler* aScrollHander) + : iConsoleSize(aConsoleSize), iCursorPos(TPoint(0, 0)), iScrollHandler(aScrollHander) { } @@ -135,6 +135,7 @@ { // Reached the end of the line and there's no space below - console will scroll up a line and jump to the beginning of the newly exposed line. iCursorPos.iX = 0; + if (iScrollHandler) iScrollHandler->ConsoleScrolled(1); } } @@ -148,6 +149,7 @@ else { iCursorPos.iX = 0; + if (iScrollHandler) iScrollHandler->ConsoleScrolled(1); } } diff -r 50af04b02d7d -r cfabd0207208 plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.h --- a/plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.h Fri Aug 13 16:18:06 2010 +0100 +++ b/plugins/consoles/vt100cons/src/vt100/vtc_cursor_tracker.h Mon Aug 23 18:10:31 2010 +0100 @@ -16,6 +16,12 @@ #include +class MConsoleScrollHandler + { +public: + virtual void ConsoleScrolled(TInt aNumberOfLines) = 0; // Positive aNumberOfLines means scrolled off the bottom. Negative means scrolled up + }; + /** * This class is responsible for tracking the cursor position within the console * window based on the data that is written to it. The cursor position is tracked @@ -26,9 +32,10 @@ class TCursorTracker { public: - TCursorTracker(TSize aConsoleSize); + TCursorTracker(TSize aConsoleSize, MConsoleScrollHandler* aScrollHander = NULL); void Write(const TDesC& aDes); void Write(const TDesC8& aDes); + void WriteChar(TChar aChar); void SetCursorPosAbs(const TPoint& aPoint); void SetCursorPosRel(const TPoint& aPoint); void Reset(); @@ -39,11 +46,10 @@ void CursorRight(); void LineFeed(); void CarriageReturn(); - void WriteChar(TChar aChar); private: const TSize iConsoleSize; TPoint iCursorPos; + MConsoleScrollHandler* iScrollHandler; }; - #endif // VTC_CURSOR_TRACKER_H