--- a/libraries/iosrv/client/command_base.cpp Wed Aug 25 22:17:52 2010 +0100
+++ b/libraries/iosrv/client/command_base.cpp Thu Aug 26 00:49:35 2010 +0100
@@ -14,7 +14,7 @@
#include "ioutils.h"
#include "command_base.h"
#include <fshell/ltkutils.h>
-
+#include <fshell/line_editor.h> // for definition of CTRL()
using namespace IoUtils;
#define RETURN_IF_ERROR(x) {TInt _err = (x); if (_err<0) return _err;}
@@ -1523,10 +1523,15 @@
TUint privateFlags = (iFlags & KPrivateFlagsMask);
iFlags = (aFlags & KPublicFlagsMask);
iFlags |= privateFlags;
+ // Make sure implied flags are set
if (iFlags & ECompleteOnRunL)
{
iFlags |= EManualComplete;
}
+ if (iFlags & ECaptureCtrlC)
+ {
+ iFlags |= ENotifyKeypresses;
+ }
}
EXPORT_C void CCommandBase::SetCif(const CCommandInfoFile& aCif)
@@ -1588,6 +1593,17 @@
UpdateHandlesL();
}
+ if (iFlags & ENotifyKeypresses)
+ {
+ __ASSERT_ALWAYS(iExtension && iExtension->ExtensionVersion() >= ECommandExtensionV2, IoUtils::Panic(EENotifyKeypressesSpecifiedWithoutExtensionBeingSet));
+ iKeypressWatcher = new(ELeave) CKeypressWatcher(*static_cast<MCommandExtensionsV2*>(iExtension), Stdin());
+ if (iFlags & ECaptureCtrlC)
+ {
+ User::LeaveIfError(Stdin().CaptureKey(CTRL('c'), 0, 0));
+ }
+ iKeypressWatcher->Notify();
+ }
+
TBool deleted(EFalse);
iDeleted = &deleted;
// Note, commands that manually complete may call CCommandBase::Complete from their DoRunL, which in the case
@@ -1626,7 +1642,7 @@
}
EXPORT_C CCommandBase::CCommandBase(TUint aFlags)
- : CActive(CActive::EPriorityStandard), iFlags(aFlags)
+ : CActive(CActive::EPriorityStandard)
{
CActiveScheduler::Add(this);
if (Dll::Tls() == NULL)
@@ -1635,14 +1651,15 @@
iFlags |= ETlsSet;
}
- // Ensure EManualComplete is set if ECompleteOnRunL is.
- SetFlags(Flags());
+ // Don't initialise iFlags directly - SetFlags checks that private flags aren't being set
+ SetFlags(aFlags);
}
EXPORT_C CCommandBase::~CCommandBase()
{
delete iReadChangeNotifier;
delete iCompleter;
+ delete iKeypressWatcher;
iFs.Close();
if (iFlags & EOwnsHandles)
{
@@ -1781,6 +1798,15 @@
iStdout.Write(aData); // Ignore error.
}
+EXPORT_C TUint CCommandBase::ReadKey()
+ {
+ // Make sure keypresswatcher doesn't get in the way (some commands do some synchronous ReadKeys followed by use of async ENotifyKeypresses callbacks)
+ if (iKeypressWatcher) iKeypressWatcher->Cancel();
+ TUint result = iStdin.ReadKey();
+ if (iKeypressWatcher) iKeypressWatcher->Notify();
+ return result;
+ }
+
EXPORT_C void CCommandBase::Printf(TRefByValue<const TDesC> aFmt, ...)
{
VA_LIST list;
@@ -3538,7 +3564,7 @@
// This makes them attached to the same I/O end-points (consoles, files, etc)
// as the passed in handles.
User::LeaveIfError(iStdin.Duplicate(aStdin));
- User::LeaveIfError(iStdin.SetToForeground());
+ // iStdin.SetToForeground() moved to Run() so the child doesn't steal foreground until it actually runs
User::LeaveIfError(iStdout.Duplicate(aStdout));
User::LeaveIfError(iStderr.Duplicate(aStderr));
@@ -3579,6 +3605,7 @@
EXPORT_C void RChildProcess::Run(TRequestStatus& aStatus)
{
+ iStdin.SetToForeground();
iProcess.Logon(aStatus);
if (aStatus != KRequestPending)
{
@@ -3808,8 +3835,46 @@
iReadHandle.CancelNotifyChange();
}
+//
+// CKeypressWatcher
//
+CKeypressWatcher::CKeypressWatcher(IoUtils::MCommandExtensionsV2& aCmd, RIoConsoleReadHandle& aReadHandle)
+ : CActive(CActive::EPriorityStandard), iCmd(aCmd), iReadHandle(aReadHandle)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CKeypressWatcher::~CKeypressWatcher()
+ {
+ Cancel();
+ }
+
+void CKeypressWatcher::Notify()
+ {
+ iReadHandle.WaitForKey(iStatus);
+ SetActive();
+ }
+
+void CKeypressWatcher::RunL()
+ {
+ TUint code = iReadHandle.KeyCode();
+ TUint modifiers = iReadHandle.KeyModifiers();
+ Notify();
+ iCmd.KeyPressed(code, modifiers);
+ if (code == CTRL('c'))
+ {
+ iCmd.CtrlCPressed();
+ }
+ }
+
+void CKeypressWatcher::DoCancel()
+ {
+ iReadHandle.WaitForKeyCancel();
+ }
+
+//
+
EXPORT_C TCommandExtensionVersion MCommandExtensionsV1::ExtensionVersion() const
{
return ECommandExtensionV1;
@@ -3824,3 +3889,18 @@
{
iExtension = aExtension;
}
+
+EXPORT_C TCommandExtensionVersion MCommandExtensionsV2::ExtensionVersion() const
+ {
+ return ECommandExtensionV2;
+ }
+
+EXPORT_C void MCommandExtensionsV2::KeyPressed(TUint /*aKeyCode*/, TUint /*aModifiers*/)
+ {
+ // Default is to do nothing
+ }
+
+EXPORT_C void MCommandExtensionsV2::CtrlCPressed()
+ {
+ // Default is to do nothing
+ }