plugins/consoles/vt100cons/src/vt100/vtc_controller.cpp
changeset 0 7f656887cf89
child 83 706c7a69e448
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // vtc_controller.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <e32base.h>
       
    14 #include <fshell/common.mmh>
       
    15 #include "vtc_controller.h"
       
    16 #include "vtc_cursor_tracker.h"
       
    17 
       
    18 
       
    19 //
       
    20 // Constants.
       
    21 //
       
    22 
       
    23 _LIT(KAttSupportAttributes, "support_attributes");
       
    24 _LIT(KAttForegroundColor, "foreground_color");
       
    25 _LIT(KAttBackgroundColor, "background_color");
       
    26 
       
    27 class TEscapeMapping
       
    28 	{
       
    29 public:
       
    30 	TUint8 iEscapeChar;
       
    31 	TKeyCode iKeyCode;
       
    32 	};
       
    33 
       
    34 class TLongerEscapeMapping
       
    35 	{
       
    36 public:
       
    37 	TUint8 iEscapeChar1;
       
    38 	TUint8 iEscapeChar2;
       
    39 	TKeyCode iKeyCode;
       
    40 	};
       
    41 
       
    42 
       
    43 const TEscapeMapping KEscapeMappings[] = 
       
    44 	{
       
    45 		{ 'A', EKeyUpArrow },
       
    46 		{ 'B', EKeyDownArrow },
       
    47 		{ 'C', EKeyRightArrow },
       
    48 		{ 'D', EKeyLeftArrow },
       
    49 		{ 'H', EKeyHome },
       
    50 		{ 'K', EKeyEnd },
       
    51 	};
       
    52 const TInt KNumEscapeMappings(sizeof(KEscapeMappings) / sizeof(TEscapeMapping));
       
    53 
       
    54 const TEscapeMapping KFunctionKeyMappings[] =
       
    55 	{
       
    56 		{ 'P', EKeyF1 },
       
    57 		{ 'Q', EKeyF2 },
       
    58 		{ 'R', EKeyF3 },
       
    59 		{ 'S', EKeyF4 },
       
    60 	};
       
    61 const TInt KNumEscapeFunctionMappings(sizeof(KFunctionKeyMappings) / sizeof(TEscapeMapping));
       
    62 
       
    63 // 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
       
    64 // See http://aperiodic.net/phil/archives/Geekery/term-function-keys.html for the reference I used
       
    65 const TLongerEscapeMapping KExtendedEscapeMappings[] = 
       
    66 	{
       
    67 		{ '1', '1', EKeyF1 },
       
    68 		{ '1', '2', EKeyF2 },
       
    69 		{ '1', '3', EKeyF3 },
       
    70 		{ '1', '4', EKeyF4 },
       
    71 		{ '1', '5', EKeyF5 },
       
    72 		// '1' '6' isn't used
       
    73 		{ '1', '7', EKeyF6 },
       
    74 		{ '1', '8', EKeyF7 },
       
    75 		{ '1', '9', EKeyF8 },
       
    76 		{ '2', '0', EKeyF9 },
       
    77 		{ '2', '1', EKeyF10 },
       
    78 		// '2' '2' isn't used
       
    79 		{ '2', '3', EKeyF11 },
       
    80 		{ '2', '4', EKeyF12 },
       
    81 
       
    82 		// ESC [1~ is Home key according to http://www.zaik.uni-koeln.de/~ftp/elfi/etc/telnet.key
       
    83 		{ '1', 0, EKeyHome },
       
    84 		{ '4', 0, EKeyEnd },
       
    85 		{ '5', 0, EKeyPageUp },
       
    86 		{ '6', 0, EKeyPageDown },
       
    87 		{ '2', 0, EKeyInsert },
       
    88 		{ '3', 0, EKeyDelete },
       
    89 	};
       
    90 const TInt KNumExtendedEscapeMappings = sizeof(KExtendedEscapeMappings) / sizeof(TLongerEscapeMapping);
       
    91 
       
    92 static const TUint8 KEscapeChar1 = 0x1b;
       
    93 static const TUint8 KEscapeChar2 = '[';
       
    94 static const TUint8 KEscapeChar2Func = 'O';
       
    95 
       
    96 static const TInt KEscapeTimeoutMicros = 200000; // 1/5th second
       
    97 
       
    98 
       
    99 //______________________________________________________________________________
       
   100 //						TKeyPress
       
   101 EXPORT_C TKeyPress::TKeyPress()
       
   102 	: iCode(EKeyNull), iModifiers(0)
       
   103 	{
       
   104 	}
       
   105 
       
   106 EXPORT_C TKeyPress::TKeyPress(TKeyCode aCode, TUint aModifiers)
       
   107 	: iCode(aCode), iModifiers(aModifiers)
       
   108 	{
       
   109 	}
       
   110 
       
   111 //______________________________________________________________________________
       
   112 //						CVtConsoleOutputController
       
   113 EXPORT_C CVtConsoleOutputController* CVtConsoleOutputController::NewL(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile, const TSize& aScreenSize)
       
   114 	{
       
   115 	CVtConsoleOutputController* self = new(ELeave)CVtConsoleOutputController(aOutput, aIniFile);
       
   116 	CleanupStack::PushL(self);
       
   117 	User::LeaveIfError(self->Construct(aScreenSize));
       
   118 	CleanupStack::Pop(self);
       
   119 	return self;
       
   120 	}
       
   121 	
       
   122 EXPORT_C CVtConsoleOutputController* CVtConsoleOutputController::New(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile, const TSize& aScreenSize)
       
   123 	{
       
   124 	CVtConsoleOutputController* self = new CVtConsoleOutputController(aOutput, aIniFile);
       
   125 	TInt err = self->Construct(aScreenSize);
       
   126 	if (err!=KErrNone)
       
   127 		{
       
   128 		delete self;
       
   129 		self = NULL;
       
   130 		}
       
   131 	return self;
       
   132 	}
       
   133 
       
   134 class TAttributeBuf : public TBuf8<64>
       
   135 	{
       
   136 public:
       
   137 	enum TColorType
       
   138 		{
       
   139 		EForeground,
       
   140 		EBackground
       
   141 		};
       
   142 public:
       
   143 	TAttributeBuf(LtkUtils::CIniFile& aIniFile);
       
   144 	void Add(TUint aAttributes);
       
   145 	void Add(ConsoleAttributes::TColor aColor, TColorType aType);
       
   146 	void Finalize();
       
   147 	TBool SomethingAdded() const;
       
   148 private:
       
   149 	void Add(const TDesC8& aAttribute);
       
   150 private:
       
   151 	LtkUtils::CIniFile& iIniFile;
       
   152 	TBool iSomethingAdded;
       
   153 	};
       
   154 
       
   155 _LIT8(KPrefix, "\x1b[");
       
   156 TAttributeBuf::TAttributeBuf(LtkUtils::CIniFile& aIniFile)
       
   157 	: TBuf8<64>(KPrefix), iIniFile(aIniFile), iSomethingAdded(EFalse)
       
   158 	{
       
   159 	}
       
   160 
       
   161 void TAttributeBuf::Add(const TDesC8& aAttribute)
       
   162 	{
       
   163 	if (iSomethingAdded)
       
   164 		{
       
   165 		Append(';');
       
   166 		}
       
   167 	Append(aAttribute);
       
   168 	iSomethingAdded = ETrue;
       
   169 	}
       
   170 
       
   171 void TAttributeBuf::Finalize()
       
   172 	{
       
   173 	ASSERT(iSomethingAdded);
       
   174 	Append('m');
       
   175 	}
       
   176 
       
   177 TBool TAttributeBuf::SomethingAdded() const
       
   178 	{
       
   179 	return iSomethingAdded;
       
   180 	}
       
   181 
       
   182 void TAttributeBuf::Add(TUint aAttributes)
       
   183 	{
       
   184 	_LIT8(KAttReset,		"0");
       
   185 	_LIT8(KAttBold,			"1");
       
   186 	_LIT8(KAttUnderscore,	"4");
       
   187 	_LIT8(KAttBlink,		"5");
       
   188 	_LIT8(KAttInverse,		"7");
       
   189 	_LIT8(KAttConceal,		"8");
       
   190 
       
   191 	if (aAttributes & ConsoleAttributes::ENone)
       
   192 		{
       
   193 		Add(KAttReset);
       
   194 		Add((ConsoleAttributes::TColor)iIniFile.GetInt(KAttForegroundColor), TAttributeBuf::EForeground);
       
   195 		Add((ConsoleAttributes::TColor)iIniFile.GetInt(KAttBackgroundColor), TAttributeBuf::EBackground);
       
   196 		}
       
   197 	if (aAttributes & ConsoleAttributes::EBold)
       
   198 		{
       
   199 		Add(KAttBold);
       
   200 		}
       
   201 	if (aAttributes & ConsoleAttributes::EUnderscore)
       
   202 		{
       
   203 		Add(KAttUnderscore);
       
   204 		}
       
   205 	if (aAttributes & ConsoleAttributes::EBlink)
       
   206 		{
       
   207 		Add(KAttBlink);
       
   208 		}
       
   209 	if (aAttributes & ConsoleAttributes::EInverse)
       
   210 		{
       
   211 		Add(KAttInverse);
       
   212 		}
       
   213 	if (aAttributes & ConsoleAttributes::EConceal)
       
   214 		{
       
   215 		Add(KAttConceal);
       
   216 		}
       
   217 	}
       
   218 
       
   219 void TAttributeBuf::Add(ConsoleAttributes::TColor aColor, TColorType aType)
       
   220 	{
       
   221 	_LIT8(KFgBlack,			"30");
       
   222 	_LIT8(KFgRed,			"31");
       
   223 	_LIT8(KFgGreen,			"32");
       
   224 	_LIT8(KFgYellow,		"33");
       
   225 	_LIT8(KFgBlue,			"34");
       
   226 	_LIT8(KFgMagenta,		"35");
       
   227 	_LIT8(KFgCyan,			"36");
       
   228 	_LIT8(KFgWhite,			"37");
       
   229 	_LIT8(KFgReset,			"39");
       
   230 	_LIT8(KBgBlack,			"40");
       
   231 	_LIT8(KBgRed,			"41");
       
   232 	_LIT8(KBgGreen,			"42");
       
   233 	_LIT8(KBgYellow,		"43");
       
   234 	_LIT8(KBgBlue,			"44");
       
   235 	_LIT8(KBgMagenta,		"45");
       
   236 	_LIT8(KBgCyan,			"46");
       
   237 	_LIT8(KBgWhite,			"47");
       
   238 	_LIT8(KBgReset,			"49");
       
   239 
       
   240 	if (aType == EForeground)
       
   241 		{
       
   242 		switch (aColor)
       
   243 			{
       
   244 			default:
       
   245 			case ConsoleAttributes::EUnchanged:
       
   246 				{
       
   247 				// Do nothing.
       
   248 				break;
       
   249 				}
       
   250 			case ConsoleAttributes::EBlack:
       
   251 				{
       
   252 				Add(KFgBlack);
       
   253 				break;
       
   254 				}
       
   255 			case ConsoleAttributes::ERed:
       
   256 				{
       
   257 				Add(KFgRed);
       
   258 				break;
       
   259 				}
       
   260 			case ConsoleAttributes::EGreen:
       
   261 				{
       
   262 				Add(KFgGreen);
       
   263 				break;
       
   264 				}
       
   265 			case ConsoleAttributes::EYellow:
       
   266 				{
       
   267 				Add(KFgYellow);
       
   268 				break;
       
   269 				}
       
   270 			case ConsoleAttributes::EBlue:
       
   271 				{
       
   272 				Add(KFgBlue);
       
   273 				break;
       
   274 				}
       
   275 			case ConsoleAttributes::EMagenta:
       
   276 				{
       
   277 				Add(KFgMagenta);
       
   278 				break;
       
   279 				}
       
   280 			case ConsoleAttributes::ECyan:
       
   281 				{
       
   282 				Add(KFgCyan);
       
   283 				break;
       
   284 				}
       
   285 			case ConsoleAttributes::EWhite:
       
   286 				{
       
   287 				Add(KFgWhite);
       
   288 				break;
       
   289 				}
       
   290 			case ConsoleAttributes::EReset:
       
   291 				{
       
   292 				Add(KFgReset);
       
   293 				break;
       
   294 				}
       
   295 			}
       
   296 		}
       
   297 	else
       
   298 		{
       
   299 		switch (aColor)
       
   300 			{
       
   301 			default:
       
   302 			case ConsoleAttributes::EUnchanged:
       
   303 				{
       
   304 				// Do nothing.
       
   305 				break;
       
   306 				}
       
   307 			case ConsoleAttributes::EBlack:
       
   308 				{
       
   309 				Add(KBgBlack);
       
   310 				break;
       
   311 				}
       
   312 			case ConsoleAttributes::ERed:
       
   313 				{
       
   314 				Add(KBgRed);
       
   315 				break;
       
   316 				}
       
   317 			case ConsoleAttributes::EGreen:
       
   318 				{
       
   319 				Add(KBgGreen);
       
   320 				break;
       
   321 				}
       
   322 			case ConsoleAttributes::EYellow:
       
   323 				{
       
   324 				Add(KBgYellow);
       
   325 				break;
       
   326 				}
       
   327 			case ConsoleAttributes::EBlue:
       
   328 				{
       
   329 				Add(KBgBlue);
       
   330 				break;
       
   331 				}
       
   332 			case ConsoleAttributes::EMagenta:
       
   333 				{
       
   334 				Add(KBgMagenta);
       
   335 				break;
       
   336 				}
       
   337 			case ConsoleAttributes::ECyan:
       
   338 				{
       
   339 				Add(KBgCyan);
       
   340 				break;
       
   341 				}
       
   342 			case ConsoleAttributes::EWhite:
       
   343 				{
       
   344 				Add(KBgWhite);
       
   345 				break;
       
   346 				}
       
   347 			case ConsoleAttributes::EReset:
       
   348 				{
       
   349 				Add(KBgReset);
       
   350 				break;
       
   351 				}
       
   352 			}
       
   353 		}
       
   354 	}
       
   355 
       
   356 EXPORT_C TInt CVtConsoleOutputController::ResetAttributes()
       
   357 	{
       
   358 	if (iIniFile.GetBool(KAttSupportAttributes))
       
   359 		{
       
   360 		TAttributeBuf buf(iIniFile);
       
   361 		buf.Add(ConsoleAttributes::ENone);
       
   362 		buf.Finalize();
       
   363 		return iOutput.Output(buf);
       
   364 		}
       
   365 
       
   366 	return KErrNone;
       
   367 	}
       
   368 
       
   369 EXPORT_C TInt CVtConsoleOutputController::SetAttributes(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor)
       
   370 	{
       
   371 	if (iIniFile.GetBool(KAttSupportAttributes))
       
   372 		{
       
   373 		TAttributeBuf buf(iIniFile);
       
   374 		buf.Add(aAttributes);
       
   375 		buf.Add(aForegroundColor, TAttributeBuf::EForeground);
       
   376 		buf.Add(aBackgroundColor, TAttributeBuf::EBackground);
       
   377 
       
   378 		if (buf.SomethingAdded())
       
   379 			{
       
   380 			buf.Finalize();
       
   381 			return iOutput.Output(buf);
       
   382 			}
       
   383 
       
   384 		return KErrNone;
       
   385 		}
       
   386 
       
   387 	return KErrNotSupported;
       
   388 	}
       
   389 	
       
   390 CVtConsoleOutputController::CVtConsoleOutputController(MConsoleOutput& aOutput, LtkUtils::CIniFile& aIniFile)
       
   391 	: iOutput(aOutput), iIniFile(aIniFile), iMode(ConsoleMode::EText)
       
   392 	{
       
   393 	}
       
   394 
       
   395 TInt CVtConsoleOutputController::Construct(const TSize& aScreenSize)
       
   396 	{
       
   397 	iCursorTracker = new TCursorTracker(aScreenSize);
       
   398 	if (!iCursorTracker) return KErrNoMemory;
       
   399 	return KErrNone;
       
   400 	}
       
   401 
       
   402 EXPORT_C CVtConsoleOutputController::~CVtConsoleOutputController()
       
   403 	{
       
   404 	delete iCursorTracker;
       
   405 	iOutputBuf.Close();
       
   406 	}
       
   407 
       
   408 TInt CVtConsoleOutputController::GetCursorPos(TPoint& aPos) const
       
   409 	{
       
   410 	aPos = iCursorTracker->CursorPos();
       
   411 	return KErrNone;
       
   412 	}
       
   413 
       
   414 
       
   415 TInt CVtConsoleOutputController::SetCursorPosAbs(const TPoint& aPos)
       
   416 	{
       
   417 	TInt err = KErrInUse;
       
   418 	if (iMode == ConsoleMode::EText)
       
   419 		{
       
   420 		_LIT8(KEscapeSetCursorPosAbs, "\x1b[%u;%uH");
       
   421 		TBuf8<32> buf;
       
   422 		buf.Format(KEscapeSetCursorPosAbs, aPos.iY + 1, aPos.iX + 1);
       
   423 		err = iOutput.Output(buf);
       
   424 		if (err == KErrNone)
       
   425 			{
       
   426 			iCursorTracker->SetCursorPosAbs(aPos);
       
   427 			}
       
   428 		}
       
   429 	return err;
       
   430 	}
       
   431 
       
   432 TInt CVtConsoleOutputController::SetCursorPosRel(const TPoint& aPoint)
       
   433 	{
       
   434 	TInt err = KErrInUse;
       
   435 	if (iMode == ConsoleMode::EText)
       
   436 		{
       
   437 		TBuf8<32> buf;
       
   438 
       
   439 		if (aPoint.iY == 0)
       
   440 			{
       
   441 			// Do nothing.
       
   442 			}
       
   443 		else if (aPoint.iY < 0)
       
   444 			{
       
   445 			// Move cursor up.
       
   446 			_LIT8(KEscapeCursorUp, "\x1b[%uA");
       
   447 			buf.AppendFormat(KEscapeCursorUp, -aPoint.iY);
       
   448 			}
       
   449 		else if (aPoint.iY > 0)
       
   450 			{
       
   451 			// Move cursor down.
       
   452 			_LIT8(KEscapeCursorDown, "\x1b[%uB");
       
   453 			buf.AppendFormat(KEscapeCursorDown, aPoint.iY);
       
   454 			}
       
   455 
       
   456 		if (aPoint.iX == 0)
       
   457 			{
       
   458 			// Do nothing.
       
   459 			}
       
   460 		else if (aPoint.iX < 0)
       
   461 			{
       
   462 			// Move cursor left.
       
   463 			_LIT8(KEscapeCursorLeft, "\x1b[%uD");
       
   464 			buf.AppendFormat(KEscapeCursorLeft, -aPoint.iY);
       
   465 			}
       
   466 		else if (aPoint.iX > 0)
       
   467 			{
       
   468 			// Move cursor right.
       
   469 			_LIT8(KEscapeCursorRight, "\x1b[%uC");
       
   470 			buf.AppendFormat(KEscapeCursorRight, aPoint.iY);
       
   471 			}
       
   472 		
       
   473 		err = KErrNone;
       
   474 		if (buf.Length() > 0)
       
   475 			{
       
   476 			err = iOutput.Output(buf);
       
   477 			if (err == KErrNone)
       
   478 				{
       
   479 				iCursorTracker->SetCursorPosRel(aPoint);
       
   480 				}
       
   481 			}
       
   482 		}
       
   483 	return err;
       
   484 	}
       
   485 
       
   486 TInt CVtConsoleOutputController::SetCursorHeight(TInt aPercentage)
       
   487 	{
       
   488 	TInt err = KErrInUse;
       
   489 	if (iMode == ConsoleMode::EText)
       
   490 		{
       
   491 		_LIT8(KEscapeHideCursor, "\x1b[?25l");
       
   492 		_LIT8(KEscapeSeeCursor, "\x1b[?25h");
       
   493 		if (aPercentage == 0)
       
   494 			{
       
   495 			err = iOutput.Output(KEscapeHideCursor);
       
   496 			}
       
   497 		else
       
   498 			{
       
   499 			err = iOutput.Output(KEscapeSeeCursor);
       
   500 			}
       
   501 		}
       
   502 	return err;
       
   503 	}
       
   504 
       
   505 TInt CVtConsoleOutputController::SetTitle(const TDesC&)
       
   506 	{
       
   507 	return KErrNone;
       
   508 	}
       
   509 
       
   510 TInt CVtConsoleOutputController::ClearScreen()
       
   511 	{
       
   512 	TInt err = KErrInUse;
       
   513 	if (iMode == ConsoleMode::EText)
       
   514 		{
       
   515 		_LIT8(KResetTerminal, "\x1b" "c" "\x1b" "[?7h"); // reset console, then enable line wrapping
       
   516 		err = iOutput.Output(KResetTerminal);
       
   517 		if (err == KErrNone)
       
   518 			{
       
   519 			User::After(100000); // It seems that TeraTerm doesn't like receiving attribute changes too soon after a terminal reset (tends to ignore the attributes).
       
   520 			err = ResetAttributes();
       
   521 			if (err == KErrNone)
       
   522 				{
       
   523 				_LIT8(KEscapeClearScreen, "\x1b[2J\x1b[01;01H");
       
   524 				err = iOutput.Output(KEscapeClearScreen);
       
   525 				if (err == KErrNone)
       
   526 					{
       
   527 					iCursorTracker->Reset();
       
   528 					}
       
   529 				}
       
   530 			}
       
   531 		}
       
   532 	return err;
       
   533 	}
       
   534 
       
   535 TInt CVtConsoleOutputController::ClearToEndOfLine()
       
   536 	{
       
   537 	TInt err = KErrInUse;
       
   538 	if (iMode == ConsoleMode::EText)
       
   539 		{
       
   540 		_LIT8(KEscapeClearToEndOfLine, "\x1b[K");
       
   541 		err = iOutput.Output(KEscapeClearToEndOfLine);
       
   542 		}
       
   543 	return err;
       
   544 	}
       
   545 
       
   546 TInt CVtConsoleOutputController::GetScreenSize(TSize& aSize) const
       
   547 	{
       
   548 	aSize = iCursorTracker->ConsoleSize();
       
   549 	return KErrNone;
       
   550 	}
       
   551 
       
   552 TInt CVtConsoleOutputController::Write(const TDesC& aDes)
       
   553 	{
       
   554 	TInt err = KErrNone;
       
   555 	if (iMode == ConsoleMode::EBinary)
       
   556 		{
       
   557 		// staight collapse to 8 bit, no cleverness
       
   558 		TBuf8<256> buf;
       
   559 		TInt offset = 0;
       
   560 		while ((offset < aDes.Length()) && (err == KErrNone))
       
   561 			{
       
   562 			buf.Copy(aDes.Mid(offset, Min(aDes.Length() - offset, buf.MaxLength())));
       
   563 			offset += buf.Length();
       
   564 			err = iOutput.Output(buf);
       
   565 			}
       
   566 		}
       
   567 	else
       
   568 		{
       
   569 		// In text mode we do a UTF-16 -> UTF-8 conversion
       
   570 		TRAP(err, iOutputBuf.CopyAsUtf8L(aDes));
       
   571 		if (err == KErrNone)
       
   572 			{
       
   573 			err = iOutput.Output(iOutputBuf);
       
   574 			if (err == KErrNone)
       
   575 				{
       
   576 				iCursorTracker->Write(aDes);
       
   577 				}
       
   578 			}
       
   579 		}
       
   580 	return err;
       
   581 	}
       
   582 	
       
   583 TInt CVtConsoleOutputController::Write(const TDesC8& aDes)
       
   584 	{
       
   585 	TInt err = iOutput.Output(aDes);
       
   586 	if ((err == KErrNone) && (iMode == ConsoleMode::EText))
       
   587 		{
       
   588 		iCursorTracker->Write(aDes);
       
   589 		}
       
   590 	return err;
       
   591 	}
       
   592 
       
   593 void CVtConsoleOutputController::SetMode(ConsoleMode::TMode aMode)
       
   594 	{
       
   595 	iMode = aMode;
       
   596 	}
       
   597 
       
   598 //______________________________________________________________________________
       
   599 //						CVtConsoleInputController
       
   600 
       
   601 EXPORT_C CVtConsoleInputController* CVtConsoleInputController::New(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
       
   602 	{
       
   603 	CVtConsoleInputController* self = NULL;
       
   604 	TRAPD(err, self = NewL(aConsoleInput, aIniFile));
       
   605 	if (err == KErrNone)
       
   606 		{
       
   607 		return self;
       
   608 		}
       
   609 	return NULL;
       
   610 	}
       
   611 
       
   612 EXPORT_C  CVtConsoleInputController* CVtConsoleInputController::NewL(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
       
   613 	{
       
   614 	CVtConsoleInputController* self = NewLC(aConsoleInput, aIniFile);
       
   615 	CleanupStack::Pop(self);
       
   616 	return self;
       
   617 	}
       
   618 	
       
   619 EXPORT_C  CVtConsoleInputController* CVtConsoleInputController::NewLC(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
       
   620 	{
       
   621 	CVtConsoleInputController* self = new(ELeave)CVtConsoleInputController(aConsoleInput, aIniFile);
       
   622 	CleanupStack::PushL(self);
       
   623 	self->ConstructL();
       
   624 	return self;
       
   625 	}
       
   626 
       
   627 CVtConsoleInputController::CVtConsoleInputController(MConsoleInput& aConsoleInput, LtkUtils::CIniFile& aIniFile)
       
   628 	: CActive(CActive::EPriorityStandard), iConsoleInput(aConsoleInput), iIniFile(aIniFile), iMode(ConsoleMode::EText)
       
   629 	{
       
   630 	CActiveScheduler::Add(this);
       
   631 	}
       
   632 	
       
   633 void CVtConsoleInputController::ConstructL()
       
   634 	{
       
   635 	iEscapeTimer = CPeriodic::NewL(CActive::EPriorityLow);
       
   636 	}
       
   637 	
       
   638 CVtConsoleInputController::~CVtConsoleInputController()
       
   639 	{
       
   640 	Reset();
       
   641 	delete iEscapeTimer;
       
   642 	}
       
   643 
       
   644 EXPORT_C void CVtConsoleInputController::GetKeyPress(TKeyPress& aKeyPress, TRequestStatus& aStatus)
       
   645 	{
       
   646 	ASSERT((iClientKeyPress == NULL) && (iClientRequestStatus == NULL));
       
   647 	iClientKeyPress = &aKeyPress;
       
   648 	iClientRequestStatus = &aStatus;
       
   649 	*iClientRequestStatus = KRequestPending;
       
   650 	if (iKeyCodePending)
       
   651 		{
       
   652 		iKeyCodePending = EFalse;
       
   653 		CompleteKeyPressRequest(iPendingKeyCode);
       
   654 		}
       
   655 	else if (iInputError)
       
   656 		{
       
   657 		CompleteKeyPressRequest(iInputError);
       
   658 		iInputError = KErrNone;
       
   659 		}
       
   660 	else
       
   661 		{
       
   662 		ReadKeyPress();
       
   663 		}
       
   664 	}
       
   665 
       
   666 EXPORT_C void CVtConsoleInputController::CancelGetKeyPress()
       
   667 	{
       
   668 	Cancel();
       
   669 	if (iClientRequestStatus)
       
   670 		{
       
   671 		CompleteKeyPressRequest(KErrCancel);
       
   672 		}
       
   673 	}
       
   674 
       
   675 EXPORT_C void CVtConsoleInputController::SetMode(ConsoleMode::TMode aMode)
       
   676 	{
       
   677 	Reset();
       
   678 	iMode = aMode;
       
   679 	}
       
   680 
       
   681 void CVtConsoleInputController::ReadKeyPress()
       
   682 	{
       
   683 	iEscapeTimer->Cancel();
       
   684 
       
   685 	while (iClientRequestStatus && (iBufPos < iBuf.Length()))
       
   686 		{
       
   687 		TUint8 c = iBuf[iBufPos++];
       
   688 		if (iMode == ConsoleMode::EBinary)
       
   689 			{
       
   690 			CompleteKeyPressRequest((TKeyCode)c);
       
   691 			}
       
   692 		else
       
   693 			{
       
   694 			switch (iState)
       
   695 				{
       
   696 			case ENormal:
       
   697 				if (c == KEscapeChar1)
       
   698 					{
       
   699 					iState = EWaitingForEscapeChar2;
       
   700 					if (iBufPos == iBuf.Length())
       
   701 						{
       
   702 						iEscapeTimer->Start(KEscapeTimeoutMicros, KEscapeTimeoutMicros, TCallBack(EscapeTimeoutS, this));
       
   703 						}
       
   704 					}
       
   705 				else
       
   706 					{
       
   707 					CompleteKeyPressRequest((TKeyCode)c);
       
   708 					}
       
   709 				break;
       
   710 			case EWaitingForEscapeChar2:
       
   711 				if (c == KEscapeChar2)
       
   712 					{
       
   713 					iState = EWaitingForEscapeChar3;
       
   714 					}
       
   715 				else if (c == KEscapeChar2Func)
       
   716 					{
       
   717 					iState = EWaitingForEscapeChar3Func;
       
   718 					}
       
   719 				else
       
   720 					{
       
   721 					CompleteKeyPressRequest(EKeyEscape, (TKeyCode)c);
       
   722 					iState = ENormal;
       
   723 					}
       
   724 				break;
       
   725 			case EWaitingForEscapeChar3:
       
   726 				if (c >= '0' && c <= '9')
       
   727 					{
       
   728 					iState = EWaitingForExtendedFunc;
       
   729 					iExtendedEscapeBuf.Zero();
       
   730 					iExtendedEscapeBuf.Append(c);
       
   731 					}
       
   732 				else
       
   733 					{
       
   734 					DoEscapeKeyL(c, KEscapeMappings, KNumEscapeMappings);
       
   735 					}
       
   736 				break;
       
   737 			case EWaitingForEscapeChar3Func:
       
   738 				DoEscapeKeyL(c, KFunctionKeyMappings, KNumEscapeFunctionMappings);
       
   739 				break;
       
   740 			case EWaitingForExtendedFunc:
       
   741 				if (iExtendedEscapeBuf.Length() < iExtendedEscapeBuf.MaxLength() && ((c >= '0' && c <= '9') || c == ';'))
       
   742 					{
       
   743 					iExtendedEscapeBuf.Append(c);
       
   744 					// Stay in this state until you see a '~'
       
   745 					}
       
   746 				else if (c == '~')
       
   747 					{
       
   748 					DoExtendedEscapeKey();
       
   749 					}
       
   750 				else
       
   751 					{
       
   752 					// Gone off the rails, bail
       
   753 					iState = ENormal;
       
   754 					CompleteKeyPressRequest((TKeyCode)c);
       
   755 					}
       
   756 				break;
       
   757 				}
       
   758 			}
       
   759 		}
       
   760 
       
   761 	ReadInput();
       
   762 	}
       
   763 
       
   764 void CVtConsoleInputController::CompleteKeyPressRequest(TInt aError)
       
   765 	{
       
   766 	ASSERT(iClientKeyPress && iClientRequestStatus);
       
   767 	iClientKeyPress = NULL;
       
   768 	User::RequestComplete(iClientRequestStatus, aError);
       
   769 	}
       
   770 
       
   771 void CVtConsoleInputController::CompleteKeyPressRequest(TKeyCode aKeyCode)
       
   772 	{
       
   773 	ASSERT(iClientKeyPress && iClientRequestStatus);
       
   774 	iClientKeyPress->iCode = (TKeyCode)aKeyCode;
       
   775 	iClientKeyPress->iModifiers = 0;
       
   776 	iClientKeyPress = NULL;
       
   777 	User::RequestComplete(iClientRequestStatus, KErrNone);
       
   778 	}
       
   779 
       
   780 void CVtConsoleInputController::CompleteKeyPressRequest(TKeyCode aKeyCode1, TKeyCode aKeyCode2)
       
   781 	{
       
   782 	ASSERT(!iKeyCodePending);
       
   783 	// Store the second key-code in a member variable to be used the next time GetKeyPress is called.
       
   784 	iKeyCodePending = ETrue;
       
   785 	iPendingKeyCode = aKeyCode2;
       
   786 	CompleteKeyPressRequest(aKeyCode1);
       
   787 	}
       
   788 
       
   789 void CVtConsoleInputController::Reset()
       
   790 	{
       
   791 	Cancel();
       
   792 	iEscapeTimer->Cancel();
       
   793 	iState = ENormal;
       
   794 	iKeyCodePending = EFalse;
       
   795 	}
       
   796 
       
   797 void CVtConsoleInputController::ReadInput()
       
   798 	{
       
   799 	if (iClientRequestStatus && !IsActive()) // Note, if the escape timer expired we could already be active.
       
   800 		{
       
   801 		ASSERT(iBufPos == iBuf.Length());
       
   802 		iBufPos = 0;
       
   803 		iBuf.Zero();
       
   804 		iConsoleInput.Input(iBuf, iStatus);
       
   805 		SetActive();
       
   806 		}
       
   807 	}
       
   808 
       
   809 void CVtConsoleInputController::RunL()
       
   810 	{
       
   811 	TInt err = iStatus.Int();
       
   812 #ifdef FSHELL_PLATFORM_OPP
       
   813 	if (err == KErrAbort)
       
   814 		{
       
   815 		ReadInput();
       
   816 		return;
       
   817 		}
       
   818 #endif
       
   819 	if (err == KErrNone)
       
   820 		{
       
   821 		ReadKeyPress();
       
   822 		}
       
   823 	else if (iClientRequestStatus)
       
   824 		{
       
   825 		CompleteKeyPressRequest(err);
       
   826 		}
       
   827 	else
       
   828 		{
       
   829 		// Report the error next time the client requests a key.
       
   830 		iInputError = err;
       
   831 		}
       
   832 	}
       
   833 
       
   834 void CVtConsoleInputController::DoCancel()
       
   835 	{
       
   836 	iConsoleInput.CancelInput(iStatus);
       
   837 	}
       
   838 
       
   839 void CVtConsoleInputController::DoEscapeKeyL(TUint8 aChar, const TEscapeMapping* aMappings, TInt aMappingCount)
       
   840 	{
       
   841 	iState = ENormal;
       
   842 	for (TInt j = 0; j < aMappingCount; ++j)
       
   843 		{
       
   844 		if (aChar == aMappings[j].iEscapeChar)
       
   845 			{
       
   846 			CompleteKeyPressRequest(aMappings[j].iKeyCode);
       
   847 			return;
       
   848 			}
       
   849 		}
       
   850 	}
       
   851 	
       
   852 TInt CVtConsoleInputController::EscapeTimeout()
       
   853 	{
       
   854 	ASSERT(iState == EWaitingForEscapeChar2);
       
   855 	iState = ENormal;
       
   856 	CompleteKeyPressRequest(EKeyEscape);
       
   857 	return KErrNone;
       
   858 	}
       
   859 
       
   860 TInt CVtConsoleInputController::EscapeTimeoutS(TAny* aSelf)
       
   861 	{
       
   862 	return ((CVtConsoleInputController*)aSelf)->EscapeTimeout();
       
   863 	}
       
   864 
       
   865 	
       
   866 void CVtConsoleInputController::DoExtendedEscapeKey()
       
   867 	{
       
   868 	iState = ENormal;
       
   869 	TUint8 escape1 = 0;
       
   870 	TUint8 escape2 = 0;
       
   871 	if (iExtendedEscapeBuf.Length()) escape1 = iExtendedEscapeBuf[0];
       
   872 	if (iExtendedEscapeBuf.Length() > 1) escape2 = iExtendedEscapeBuf[1];
       
   873 
       
   874 	for (TInt j = 0; j < KNumExtendedEscapeMappings; ++j)
       
   875 		{
       
   876 		const TLongerEscapeMapping& mapping = KExtendedEscapeMappings[j];
       
   877 		if (escape1 == mapping.iEscapeChar1 && escape2 == mapping.iEscapeChar2)
       
   878 			{
       
   879 			CompleteKeyPressRequest(mapping.iKeyCode);
       
   880 			return;
       
   881 			}
       
   882 		}
       
   883 	}