os/graphics/windowing/windowserver/minigui/src/econswserv.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/windowing/windowserver/minigui/src/econswserv.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,693 @@
     1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <e32cons.h>
    1.20 +#include <e32keys.h>
    1.21 +#include <e32base.h>
    1.22 +#include <w32std.h>
    1.23 +#include <gdi.h>
    1.24 +#include <bitstd.h>
    1.25 +#include <bitdev.h>
    1.26 +
    1.27 +const TInt KGroupId = 0x100039e7;
    1.28 +
    1.29 +class CWsConsoleMux;
    1.30 +class CWsConsole;
    1.31 +
    1.32 +// Active object to listen to Wserv events. Only used when
    1.33 +// application thread has installed an active scheduler
    1.34 +//
    1.35 +NONSHARABLE_CLASS(CWsKeyReader): public CActive
    1.36 +	{
    1.37 +public:
    1.38 +	CWsKeyReader(CWsConsoleMux* aMux);
    1.39 +	void MakeRequest();
    1.40 +
    1.41 +protected:
    1.42 +	void RunL();
    1.43 +	void DoCancel();
    1.44 +
    1.45 +private:
    1.46 +	CWsConsoleMux* iMux; //uses
    1.47 +	};
    1.48 +
    1.49 +// Master console to dispatch key events to relevant console in situation where 
    1.50 +// a single application thread owns multiple instances of console (CConsoleBase).
    1.51 +// Reference counted as only a single instance of this class will be created
    1.52 +// for each thread.
    1.53 +//
    1.54 +NONSHARABLE_CLASS(CWsConsoleMux): public CBase
    1.55 +	{
    1.56 +public:
    1.57 +	static TInt Open();
    1.58 +	static void Close();
    1.59 +	static CWsConsoleMux* Static();
    1.60 +	~CWsConsoleMux();
    1.61 +	
    1.62 +	void MakeRequest(CWsConsole* aConsole);
    1.63 +	void CancelRequest(CWsConsole* aConsole);
    1.64 +	void RequestComplete();
    1.65 +
    1.66 +	inline RWsSession& Session();
    1.67 +	inline RWindowGroup& Group();
    1.68 +	inline CWindowGc& Gc();
    1.69 +	inline CWsScreenDevice& Screen();
    1.70 +
    1.71 +private:
    1.72 +	static CWsConsoleMux* NewL();
    1.73 +	CWsConsoleMux();
    1.74 +	void ConstructL();
    1.75 +
    1.76 +private:
    1.77 +	TInt iRefCount;
    1.78 +	RWsSession iWs;
    1.79 +	RWindowGroup iGroup;
    1.80 +	CWsScreenDevice* iScr;
    1.81 +	CWindowGc* iGc;
    1.82 +
    1.83 +	CWsConsole* iConsole;
    1.84 +	CWsKeyReader* iReader;
    1.85 +	};
    1.86 +
    1.87 +// Console that uses direct Wserv API. Each console will own a window and 
    1.88 +// a bitmap for its backing store, but will be sharing Wserv session, window group,
    1.89 +// screen device and window drawing context
    1.90 +//
    1.91 +NONSHARABLE_CLASS(CWsConsole): public CConsoleBase
    1.92 +	{
    1.93 +	friend class CWsConsoleMux;
    1.94 +
    1.95 +public:
    1.96 +	CWsConsole();
    1.97 +	virtual ~CWsConsole();
    1.98 +	
    1.99 +	//from CConsoleBase 
   1.100 +	virtual TInt Create(const TDesC &aTitle,TSize aSize);
   1.101 +	virtual void Read(TRequestStatus &aStatus);
   1.102 +	virtual void ReadCancel();
   1.103 +	virtual void Write(const TDesC &aDes);
   1.104 +	virtual TPoint CursorPos() const;
   1.105 +	virtual void SetCursorPosAbs(const TPoint &aPoint);
   1.106 +	virtual void SetCursorPosRel(const TPoint &aPoint);
   1.107 +	virtual void SetCursorHeight(TInt aPercentage);
   1.108 +	virtual void SetTitle(const TDesC &aTitle);
   1.109 +	virtual void ClearScreen();
   1.110 +	virtual void ClearToEndOfLine();
   1.111 +	virtual TSize ScreenSize() const;
   1.112 +	virtual TKeyCode KeyCode() const;
   1.113 +	virtual TUint KeyModifiers() const;
   1.114 +
   1.115 +private:	
   1.116 +	// for CWsConsoleMux
   1.117 +	TRequestStatus* ReadStatus();
   1.118 +	void SetKey(TUint aCode, TUint aModifier);
   1.119 +
   1.120 +	// internal
   1.121 +	void ConstructL();
   1.122 +	void DrawNow();
   1.123 +	void Scroll();
   1.124 +	TPoint WritePos();
   1.125 +	void CarriageReturn();
   1.126 +	void LineFeed();
   1.127 +	void Left();
   1.128 +	void Right();
   1.129 +	void WriteChar(TText);
   1.130 +	
   1.131 +private:
   1.132 +	// window stuff
   1.133 +	RWindow iWin;
   1.134 +	TSize iWindowSize;
   1.135 +
   1.136 +	// back buffer
   1.137 +	CFbsBitmap* iBitmap;
   1.138 +	CFbsBitGc* iBitGc;
   1.139 +	CFbsBitmapDevice* iBitDev;
   1.140 +
   1.141 +	// console stuff in chars dimension
   1.142 +	TPoint iCursorPos; //The position of the cursor is on the baseline
   1.143 +	TSize iSizeInChars;
   1.144 +
   1.145 +	// font stuff
   1.146 +	CFont* iFont;
   1.147 +	TSize iCharSize;
   1.148 +	TInt iFontAscent;
   1.149 +	TInt iFontDescent;
   1.150 +	
   1.151 +	TKeyCode iKeyCode;
   1.152 +	TUint iModifiers;
   1.153 +	TTextCursor iTextCursor;
   1.154 +	
   1.155 +	// master console
   1.156 +	CWsConsoleMux* iMux;
   1.157 +	TRequestStatus* iReadStatus;
   1.158 +	};
   1.159 +
   1.160 +//
   1.161 +// CWsKeyReader implementation
   1.162 +//
   1.163 +//
   1.164 +//
   1.165 +CWsKeyReader::CWsKeyReader(CWsConsoleMux* aMux):
   1.166 +	CActive(CActive::EPriorityStandard),
   1.167 +	iMux(aMux)	
   1.168 +	{
   1.169 +	CActiveScheduler::Add(this);
   1.170 +	}
   1.171 +
   1.172 +void CWsKeyReader::MakeRequest()
   1.173 +	{
   1.174 +	SetActive();
   1.175 +	iMux->Session().EventReady(&iStatus);
   1.176 +	}
   1.177 +
   1.178 +void CWsKeyReader::RunL()
   1.179 +	{
   1.180 +	// let master console decide what to do
   1.181 +	iMux->RequestComplete();
   1.182 +	}
   1.183 +
   1.184 +void CWsKeyReader::DoCancel()
   1.185 +	{
   1.186 +	iMux->Session().EventReadyCancel();
   1.187 +	}
   1.188 +
   1.189 +//
   1.190 +// CWsConsoleMux implementation
   1.191 +//
   1.192 +//
   1.193 +//
   1.194 +TInt CWsConsoleMux::Open()
   1.195 +	{
   1.196 +	CWsConsoleMux* mux = (CWsConsoleMux*)Dll::Tls();
   1.197 +	
   1.198 +	// not the first time, simply increment refcount
   1.199 +	if (mux)
   1.200 +		{
   1.201 +		++mux->iRefCount;
   1.202 +		return KErrNone;
   1.203 +		}
   1.204 +
   1.205 +	// first time, let's create master console and
   1.206 +	// stick it to TLS
   1.207 +	TRAPD(err, mux = CWsConsoleMux::NewL());
   1.208 +	if (err != KErrNone)
   1.209 +		{
   1.210 +		return err;
   1.211 +		}
   1.212 +
   1.213 +	err = Dll::SetTls(mux);
   1.214 +	if (err != KErrNone)
   1.215 +		{
   1.216 +		delete mux;
   1.217 +		return err;
   1.218 +		}
   1.219 +
   1.220 +	++mux->iRefCount;			
   1.221 +	return KErrNone;
   1.222 +	}
   1.223 +
   1.224 +void CWsConsoleMux::Close()
   1.225 +	{
   1.226 +	CWsConsoleMux* mux = (CWsConsoleMux*)Dll::Tls();
   1.227 +	if (!mux)
   1.228 +		{
   1.229 +		return;
   1.230 +		}
   1.231 +		
   1.232 +	// destroy master console if this is the last use from
   1.233 +	// this thread and reset TLS
   1.234 +	if (--mux->iRefCount == 0)
   1.235 +		{
   1.236 +		delete mux;
   1.237 +		Dll::FreeTls();
   1.238 +		}
   1.239 +	}
   1.240 +
   1.241 +CWsConsoleMux* CWsConsoleMux::Static()
   1.242 +	{
   1.243 +	return (CWsConsoleMux*)Dll::Tls();
   1.244 +	}
   1.245 +
   1.246 +CWsConsoleMux::CWsConsoleMux()
   1.247 +	{
   1.248 +	}
   1.249 +	
   1.250 +CWsConsoleMux::~CWsConsoleMux()
   1.251 +	{
   1.252 +	delete iReader;
   1.253 +	delete iGc;
   1.254 +	delete iScr;
   1.255 +	iGroup.Close();
   1.256 +	iWs.Close();
   1.257 +	}
   1.258 +
   1.259 +CWsConsoleMux* CWsConsoleMux::NewL()
   1.260 +	{
   1.261 +	CWsConsoleMux* mux = new(ELeave) CWsConsoleMux;
   1.262 +	CleanupStack::PushL(mux);
   1.263 +	mux->ConstructL();
   1.264 +	CleanupStack::Pop(mux);
   1.265 +	
   1.266 +	return mux;
   1.267 +	}
   1.268 +	
   1.269 +void CWsConsoleMux::ConstructL()
   1.270 +	{
   1.271 +	TInt err = iWs.Connect();
   1.272 +	User::LeaveIfError(err);
   1.273 +	
   1.274 +	iScr = new(ELeave) CWsScreenDevice(iWs);
   1.275 +	err = iScr->Construct();
   1.276 +	User::LeaveIfError(err);
   1.277 +	
   1.278 +	iGc = new(ELeave) CWindowGc(iScr);
   1.279 +	err = iGc->Construct();
   1.280 +	User::LeaveIfError(err);
   1.281 +	
   1.282 +	iGroup = RWindowGroup(iWs);
   1.283 +	err = iGroup.Construct(KGroupId, ETrue);
   1.284 +	User::LeaveIfError(err);
   1.285 +	
   1.286 +	// we will be using active object to listen to Wserv events
   1.287 +	// only if this thread already has active scheduler
   1.288 +	//
   1.289 +	if (CActiveScheduler::Current())
   1.290 +		{
   1.291 +		iReader = new(ELeave) CWsKeyReader(this);
   1.292 +		}
   1.293 +	}
   1.294 +
   1.295 +RWsSession& CWsConsoleMux::Session()
   1.296 + 	{
   1.297 + 	return iWs;
   1.298 + 	}
   1.299 + 	
   1.300 +RWindowGroup& CWsConsoleMux::Group()
   1.301 +	{
   1.302 +	return iGroup;
   1.303 +	}
   1.304 +	
   1.305 +CWindowGc& CWsConsoleMux::Gc()
   1.306 +	{
   1.307 +	return *iGc;
   1.308 +	}
   1.309 +	
   1.310 +CWsScreenDevice& CWsConsoleMux::Screen()
   1.311 +	{
   1.312 +	return *iScr;
   1.313 +	}
   1.314 +
   1.315 +void CWsConsoleMux::MakeRequest(CWsConsole* aConsole)
   1.316 +	{
   1.317 +	if (!iReader)
   1.318 +		{
   1.319 +		// client does not have scheduler, ideally we should use
   1.320 +		// secondary thread to make this asynchronous.
   1.321 +		//
   1.322 +		// however, we can get away with this because application 
   1.323 +		// that doesn't use active scheduler will be calling asynchronous console read 
   1.324 +		// and immediately followed by WaitForRequest e.g.
   1.325 +		//
   1.326 +		// while (1)
   1.327 +		//	{
   1.328 +		//	...
   1.329 +		//	console->Read(status);
   1.330 +		//	User::WaitForRequest(status);
   1.331 +		//	...
   1.332 +		//	}
   1.333 +		//
   1.334 +		TWsEvent event;
   1.335 +
   1.336 +		// keep going until we got key event
   1.337 +		do
   1.338 +			{
   1.339 +			TRequestStatus s;
   1.340 +			s = KRequestPending;
   1.341 +			iWs.EventReady(&s);
   1.342 +			User::WaitForRequest(s);
   1.343 +			
   1.344 +			iWs.GetEvent(event);
   1.345 +			}
   1.346 +		while (event.Type() != EEventKey);
   1.347 +		
   1.348 +		aConsole->SetKey(event.Key()->iCode, event.Key()->iModifiers);
   1.349 +		TRequestStatus* pS = aConsole->ReadStatus();
   1.350 +		User::RequestComplete(pS, KErrNone);
   1.351 +		}
   1.352 +	else
   1.353 +		{
   1.354 +		iConsole = aConsole;
   1.355 +		iReader->MakeRequest();
   1.356 +		}
   1.357 +	}
   1.358 +
   1.359 +// called from key listener RunL
   1.360 +//
   1.361 +void CWsConsoleMux::RequestComplete()
   1.362 +	{
   1.363 +	TWsEvent event;
   1.364 +	iWs.GetEvent(event);
   1.365 +
   1.366 +	if (event.Type() == EEventKey)
   1.367 +		{
   1.368 +		iConsole->SetKey(event.Key()->iCode, event.Key()->iModifiers);
   1.369 +		TRequestStatus* pS = iConsole->ReadStatus();
   1.370 +		User::RequestComplete(pS, KErrNone);
   1.371 +		iConsole = NULL;
   1.372 +		}
   1.373 +	else
   1.374 +		{
   1.375 +		// keep going until we got key event
   1.376 +		//
   1.377 +		iReader->MakeRequest();
   1.378 +		}
   1.379 +	}
   1.380 +
   1.381 +void CWsConsoleMux::CancelRequest(CWsConsole* aConsole)
   1.382 +	{
   1.383 +	if (iReader && iConsole == aConsole)
   1.384 +		{
   1.385 +		iReader->Cancel();
   1.386 +		}
   1.387 +	}
   1.388 +	
   1.389 +//
   1.390 +// CWsConsole implementation
   1.391 +//
   1.392 +//
   1.393 +//
   1.394 +CWsConsole::CWsConsole()
   1.395 +	{
   1.396 +	}
   1.397 +
   1.398 +CWsConsole::~CWsConsole()
   1.399 +	{
   1.400 +	if(iBitGc)
   1.401 +		{
   1.402 +		iBitGc->DiscardFont();
   1.403 +		}
   1.404 +	if(iBitDev)
   1.405 +		{
   1.406 +		iBitDev->ReleaseFont(iFont);
   1.407 +		}
   1.408 +
   1.409 +	delete iBitGc;
   1.410 +	delete iBitDev;
   1.411 +	delete iBitmap;	
   1.412 +	iWin.Close();
   1.413 +	iMux->Session().Flush();
   1.414 +
   1.415 +	CWsConsoleMux::Close();
   1.416 +	}
   1.417 +
   1.418 +TInt CWsConsole::Create(const TDesC& /*aTitle*/, TSize /*aSize*/)
   1.419 +	{
   1.420 +	// we must not push this object to cleanup stack during construction because
   1.421 +	// caller will explicitly call delete on this object when Create() returns error
   1.422 +	//
   1.423 +	TRAPD(err, ConstructL());
   1.424 +	return err;
   1.425 +	}
   1.426 +	
   1.427 +void CWsConsole::ConstructL()
   1.428 +	{
   1.429 +	TInt err = CWsConsoleMux::Open();
   1.430 +	User::LeaveIfError(err);
   1.431 +
   1.432 +	iMux = CWsConsoleMux::Static();
   1.433 +	
   1.434 +	iWindowSize = iMux->Screen().SizeInPixels();
   1.435 +	
   1.436 +	iBitmap = new(ELeave) CFbsBitmap;
   1.437 +	err = iBitmap->Create(iWindowSize, EGray2);
   1.438 +	User::LeaveIfError(err);
   1.439 +
   1.440 +	iBitDev = CFbsBitmapDevice::NewL(iBitmap);
   1.441 +	err = iBitDev->CreateContext(iBitGc);
   1.442 +	User::LeaveIfError(err);
   1.443 +
   1.444 +	iBitGc->SetPenColor(KRgbBlack);
   1.445 +	iBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
   1.446 +	iBitGc->SetBrushColor(KRgbWhite);
   1.447 +	iBitGc->Clear();
   1.448 +
   1.449 +	TFontSpec fs(_L("DejaVu Sans Mono"), 12);
   1.450 +	err = iBitDev->GetNearestFontToDesignHeightInPixels(iFont, fs);
   1.451 +	User::LeaveIfError(err);
   1.452 +
   1.453 +	iBitGc->UseFont(iFont);
   1.454 +
   1.455 +	// uses monospace font to get uniform glpyh size
   1.456 +	iCharSize.iHeight = iFont->FontMaxAscent() + iFont->FontMaxDescent();
   1.457 +	iCharSize.iWidth = iFont->MaxCharWidthInPixels();
   1.458 +	iFontAscent = iFont->FontMaxAscent();
   1.459 +	iFontDescent= iFont->FontMaxDescent();
   1.460 +
   1.461 +	// cursor represent char position in character-based area
   1.462 +	// eshell is using 0,0 based
   1.463 +	iCursorPos = TPoint(1,1);
   1.464 +	// console size in number of characters and lines
   1.465 +	iSizeInChars.iWidth = iWindowSize.iWidth / iCharSize.iWidth;
   1.466 +	iSizeInChars.iHeight = iWindowSize.iHeight / iCharSize.iHeight;
   1.467 +	
   1.468 +	iTextCursor.iType = TTextCursor::ETypeRectangle;
   1.469 +	iTextCursor.iHeight = iCharSize.iHeight;
   1.470 +	iTextCursor.iAscent = iFontAscent;
   1.471 +	iTextCursor.iWidth = iCharSize.iWidth;
   1.472 +	iTextCursor.iFlags = 0;
   1.473 +	iTextCursor.iColor = KRgbWhite;
   1.474 +
   1.475 +
   1.476 +	iWin = RWindow(iMux->Session());
   1.477 +	err = iWin.Construct(iMux->Group(), (TInt)this);
   1.478 +	User::LeaveIfError(err);
   1.479 +		
   1.480 +	iWin.Activate();
   1.481 +	iMux->Session().Flush();
   1.482 +	}
   1.483 +
   1.484 +TRequestStatus* CWsConsole::ReadStatus()
   1.485 +	{
   1.486 +	return iReadStatus;
   1.487 +	}
   1.488 +
   1.489 +void CWsConsole::SetKey(TUint aCode, TUint aModifier) 
   1.490 +	{
   1.491 +	iKeyCode = (TKeyCode)aCode;
   1.492 +	iModifiers = aModifier;
   1.493 +	}
   1.494 +
   1.495 +TPoint CWsConsole::WritePos()
   1.496 +	{
   1.497 +	return TPoint((iCursorPos.iX - 1) * iCharSize.iWidth, (iCursorPos.iY - 1) * iCharSize.iHeight + iFontAscent);
   1.498 +	}
   1.499 +	
   1.500 +void CWsConsole::Read(TRequestStatus &aStatus)
   1.501 +	{
   1.502 +	iReadStatus = &aStatus;
   1.503 +	*iReadStatus = KRequestPending;
   1.504 +	iMux->MakeRequest(this);
   1.505 +	}
   1.506 +
   1.507 +void CWsConsole::ReadCancel()
   1.508 +	{
   1.509 +	iMux->CancelRequest(this);
   1.510 +	iReadStatus = NULL;
   1.511 +	}
   1.512 +
   1.513 +void CWsConsole::CarriageReturn()
   1.514 +	{
   1.515 +	iCursorPos.iX = 1;
   1.516 +	}
   1.517 +
   1.518 +void CWsConsole::LineFeed()
   1.519 +	{
   1.520 +	CarriageReturn();
   1.521 +	if (iCursorPos.iY < iSizeInChars.iHeight)
   1.522 +		{
   1.523 +		++iCursorPos.iY;
   1.524 +		}
   1.525 +	else
   1.526 +		{
   1.527 +		Scroll();
   1.528 +		}
   1.529 +	}
   1.530 +
   1.531 +void CWsConsole::Left()
   1.532 +	{
   1.533 +	if (iCursorPos != TPoint(1,1))
   1.534 +		{
   1.535 +		if (iCursorPos.iX == 1)
   1.536 +			{
   1.537 +			iCursorPos.iX += iSizeInChars.iWidth;
   1.538 +			--iCursorPos.iY;
   1.539 +			}
   1.540 +		--iCursorPos.iX;
   1.541 +		}
   1.542 +	}
   1.543 +
   1.544 +void CWsConsole::Right()
   1.545 +	{
   1.546 +	++iCursorPos.iX;
   1.547 +	if (iCursorPos.iX > iSizeInChars.iWidth)
   1.548 +		{
   1.549 +		LineFeed();
   1.550 +		}
   1.551 +	}
   1.552 +
   1.553 +void CWsConsole::Write(const TDesC& aDes)
   1.554 +	{
   1.555 +	const TInt length = aDes.Length();
   1.556 +	if (length == 0)
   1.557 +		{
   1.558 +		return;
   1.559 +		}
   1.560 +	
   1.561 +	for (TInt i=0; i<length; ++i)
   1.562 +		{
   1.563 +		switch (aDes[i])
   1.564 +			{
   1.565 +			case 0x07:
   1.566 +				RDebug::Print(_L("WSCON: End of command line!"));
   1.567 +				break;
   1.568 +			case 0x0a:
   1.569 +				LineFeed();
   1.570 +				break;
   1.571 +			case 0x0d:
   1.572 +				CarriageReturn();
   1.573 +				break;
   1.574 +			default:
   1.575 +				WriteChar(aDes[i]);
   1.576 +				break;
   1.577 +			}
   1.578 +		}
   1.579 +	
   1.580 +	DrawNow();
   1.581 +	}
   1.582 +
   1.583 +void CWsConsole::WriteChar(TText aChar)
   1.584 +	{
   1.585 +	TBuf<1> s;
   1.586 +	s.Append(aChar);
   1.587 +	// use draw text box to clear the glpyh box
   1.588 +	TPoint writePos = WritePos();
   1.589 +	TRect r(writePos.iX, writePos.iY-iFontAscent,writePos.iX+iCharSize.iWidth, writePos.iY+iFontDescent);
   1.590 +	iBitGc->DrawText(s, r, iFontAscent);
   1.591 +	Right();
   1.592 +	}
   1.593 +
   1.594 +TPoint CWsConsole::CursorPos() const
   1.595 +	{
   1.596 +	// eshell is using 0,0 based
   1.597 +	return iCursorPos - TPoint(1,1);
   1.598 +	}
   1.599 +
   1.600 +void CWsConsole::SetCursorPosAbs(const TPoint& aPoint)
   1.601 +	{
   1.602 +	// eshell is using 0,0 based
   1.603 +	iCursorPos = aPoint + TPoint(1,1);
   1.604 +	iMux->Group().SetTextCursor(iWin, WritePos(), iTextCursor);
   1.605 +	}
   1.606 +
   1.607 +void CWsConsole::SetCursorPosRel(const TPoint& aPoint)
   1.608 +	{
   1.609 +	iCursorPos += aPoint;
   1.610 +	iMux->Group().SetTextCursor(iWin, WritePos(), iTextCursor);
   1.611 +	}
   1.612 +
   1.613 +void CWsConsole::SetCursorHeight(TInt aPercentage)
   1.614 +	{
   1.615 +	if (aPercentage == 0)
   1.616 +		{
   1.617 +		// none
   1.618 +		iTextCursor.iHeight = 0;
   1.619 +		}
   1.620 +	else if (aPercentage == 100)
   1.621 +		{
   1.622 +		// insert
   1.623 +		iTextCursor.iHeight = iCharSize.iHeight;
   1.624 +		iTextCursor.iAscent = iFontAscent;
   1.625 +		}
   1.626 +	else
   1.627 +		{
   1.628 +		// normal
   1.629 +		iTextCursor.iHeight = 1;
   1.630 +		iTextCursor.iAscent = 0;
   1.631 +		}
   1.632 +
   1.633 +	iMux->Group().SetTextCursor(iWin, WritePos(), iTextCursor);
   1.634 +	}
   1.635 +
   1.636 +void CWsConsole::SetTitle(const TDesC& /*aTitle*/)
   1.637 +	{
   1.638 +	}
   1.639 +
   1.640 +void CWsConsole::ClearScreen()
   1.641 +	{
   1.642 +	iBitGc->Clear();
   1.643 +	iCursorPos.iX = iCursorPos.iY = 1;
   1.644 +	DrawNow();
   1.645 +	}
   1.646 +
   1.647 +void CWsConsole::ClearToEndOfLine()
   1.648 +	{
   1.649 +	iMux->Group().CancelTextCursor();
   1.650 +	TPoint writePos = WritePos();
   1.651 +	TRect r(writePos.iX, writePos.iY-iFontAscent, iWindowSize.iWidth, writePos.iY+iFontDescent);
   1.652 +	iBitGc->Clear(r);
   1.653 +	DrawNow();
   1.654 +	iMux->Group().SetTextCursor(iWin, WritePos(), iTextCursor);
   1.655 +	}
   1.656 +
   1.657 +TSize CWsConsole::ScreenSize() const
   1.658 +	{
   1.659 +	return iSizeInChars;
   1.660 +	}
   1.661 +
   1.662 +TKeyCode CWsConsole::KeyCode() const
   1.663 +	{
   1.664 +	return iKeyCode;
   1.665 +	}
   1.666 +
   1.667 +TUint CWsConsole::KeyModifiers() const
   1.668 +	{
   1.669 +	return iModifiers;
   1.670 +	}
   1.671 +
   1.672 +void CWsConsole::DrawNow()
   1.673 +	{
   1.674 +	iWin.Invalidate();
   1.675 +	iWin.BeginRedraw();
   1.676 +	iMux->Gc().Activate(iWin);
   1.677 +	iMux->Gc().BitBlt(TPoint(0,0), iBitmap);
   1.678 +	iMux->Gc().Deactivate();
   1.679 +	iWin.EndRedraw();
   1.680 +	iMux->Session().Flush();
   1.681 +	}
   1.682 +
   1.683 +void CWsConsole::Scroll()
   1.684 +	{
   1.685 +	TRect r(0, iCharSize.iHeight, iWindowSize.iWidth, iSizeInChars.iHeight * iCharSize.iHeight);
   1.686 +
   1.687 +	iBitGc->CopyRect(TPoint(0, -iCharSize.iHeight), r);
   1.688 +	// clear last line
   1.689 +	TRect rect(0, WritePos().iY-iFontAscent, iWindowSize.iWidth, iWindowSize.iHeight);
   1.690 +	iBitGc->Clear(rect);
   1.691 +	}
   1.692 +
   1.693 +extern "C" EXPORT_C TAny *NewConsole()
   1.694 +	{
   1.695 +	return new CWsConsole;
   1.696 +	}