uifw/EikStd/coctlsrc/EIKCONSO.CPP
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/coctlsrc/EIKCONSO.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1003 @@
+/*
+* Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <eikconso.h>
+#include <gdi.h>
+#include <coecntrl.h>
+#include <coemain.h>
+
+EXPORT_C TSize CEikConsoleScreen::ScreenSize() const
+    {
+    return iConsoleSize;
+    }
+
+EXPORT_C TInt CEikConsoleScreen::Create(const TDesC& aTitle,TSize aSize)
+    {
+    TRAPD(err,ConstructL(aTitle,aSize,EUseBackedUpWindow));
+    if (!err)
+        DrawCursor();
+    return(err);
+    }
+
+EXPORT_C void CEikConsoleScreen::Read(TRequestStatus& /*aStatus*/)
+    { // not implemented - this part of base abstraction deliberately broken
+    }
+
+EXPORT_C void CEikConsoleScreen::ReadCancel()
+    { // not implemented - this part of base abstraction deliberately broken
+    }
+
+EXPORT_C TKeyCode CEikConsoleScreen::KeyCode() const
+    { // not implemented - this part of base abstraction deliberately broken
+    return(EKeyNull);
+    }
+
+EXPORT_C TUint CEikConsoleScreen::KeyModifiers() const
+    { // not implemented - this part of base abstraction deliberately broken
+    return(0);
+    }
+
+EXPORT_C void CEikConsoleScreen::FlushChars() 
+	{
+	if (!iWriteNow && iWriteBuffer.Length())
+		{
+		iWriteNow=1;
+		Write(iWriteBuffer);
+		iWriteBuffer.SetLength(0);
+		iWriteNow=0;
+		}
+	}
+	    
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  UTILITY FUNCTIONS
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+void cutmax(TInt &x,TInt max) {if (x>max) x=max;}
+void cutmin(TInt &x,TInt min) {if (x<min) x=min;}
+
+TUint SmallerPoint(TPoint a,TPoint b)
+	{ 
+	return ( a.iY < b.iY || (a.iY==b.iY && a.iX<=b.iX ) ); 
+	}
+
+TRect Clip(const TRect &aRect,const TRect &anOtherRect)
+// return aRect clipped to anOtherRect (i.e. true intersection) 
+	{
+	TRect theRect = aRect;
+	theRect.Intersection(anOtherRect);
+	cutmax(theRect.iTl.iX,theRect.iBr.iX);
+	cutmax(theRect.iTl.iY,theRect.iBr.iY);
+	return theRect;
+	}
+
+void CopyNormalisedRange(TRect &dstRange,const TRect &srcRange)
+// Make dstRange a normalized RANGE version of srcRange 
+	{
+	dstRange=srcRange;
+	if (SmallerPoint(dstRange.iBr,dstRange.iTl))
+		{ dstRange.iTl=srcRange.iBr; dstRange.iBr=srcRange.iTl; }
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  HISTORY ACCESS (LOW LEVEL)
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+TPtr8	CEikConsoleScreen::MemAttPtr(TPoint aScrPos,TUint aLength) // aScrPos = SCREEN coordinates
+// returns TPtr8 within attribute history at given position for aLength 'characters'
+	{
+	return TPtr8(&iAttBuf[aScrPos.iX+((aScrPos.iY+iMaxAttExtra)*iConsoleSize.iWidth)],aLength,aLength);
+	}
+
+TPtr	CEikConsoleScreen::MemChrPtr(TPoint aScrPos,TUint aLength) // aScrPos = SCREEN coordinates
+// returns TPtr within character history at given position for aLength 'characters'
+	{
+	return TPtr(&iChrBuf[aScrPos.iX+((aScrPos.iY+iMaxChrExtra)*iConsoleSize.iWidth)],aLength,aLength);
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  SCROLLBAR STUFF 
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C TBool CEikConsoleScreen::UpdateScrollBars() 
+// should be called whenever datasize and/or topleft changes
+// Return ETrue if, as a result, the visible window has changed
+	{
+	if (iConsoleControl)
+		{
+		TBool updatedScrollbars = EFalse;
+		TRAP_IGNORE(updatedScrollbars = iConsoleControl->UpdateScrollbarsL(iConsoleSize+TSize(0,iNoChrExtra),iConsoleSize,iTopLeft-TPoint(0,iMaxChrExtra-iNoChrExtra)));
+		if (updatedScrollbars)
+			return RecalculateSize(); // datasize change may have resulted in a different visible window (due to scrollbars)
+		}
+	return EFalse;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  HISTORY STORAGE (HIGH LEVEL)
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+// aPos = SCREEN coordinates
+void CEikConsoleScreen::MemScrPut(const TDesC &aString,TPoint aPos,TUint8 anAtt)
+ 	{
+	MemChrPtr(aPos,aString.Length()).Copy(aString);
+	MemAttPtr(aPos,aString.Length()).Fill(anAtt);
+	}
+
+
+// aRect = SCREEN coordinates
+void CEikConsoleScreen::MemScrClr(const TRect &aRect,TUint8 anAtt)
+	{
+	TUint8 clrAtt = anAtt;
+	if ((clrAtt & ATT_COLORMASK) == 0) 
+		clrAtt &= (ATT_BOLD|ATT_INVERSE); // when clearing, only BOLD and INVERSE properties are relevant
+	for (TInt y=aRect.iTl.iY;y<aRect.iBr.iY;y++)
+		{
+		TInt width = aRect.iBr.iX - aRect.iTl.iX;
+		MemChrPtr(TPoint(aRect.iTl.iX,y),width).Fill(TChar(' '));
+		MemAttPtr(TPoint(aRect.iTl.iX,y),width).Fill(clrAtt);
+		}
+	}
+
+// anOldPt/aNewPt = SCREEN coordinates
+void CEikConsoleScreen::MemScrMove(TPoint anOldPt,TPoint aNewPt,TUint aLen)
+	{
+	MemChrPtr(aNewPt,aLen).Copy(MemChrPtr(anOldPt,aLen));
+	MemAttPtr(aNewPt,aLen).Copy(MemAttPtr(anOldPt,aLen));
+	}
+
+// aRect = SCREEN coordinates 
+void CEikConsoleScreen::MemScrScroll(const TRect &aRect,TPoint aVector)
+	{
+	// determine the destination rectangle
+	TRect normRect = aRect;
+	normRect.Normalize();
+	TRect newRect = normRect;
+	newRect.Move(aVector);
+	newRect.Intersection(normRect); 
+	newRect.Intersection(TRect(iConsoleSize));
+	// now move from old rectangle to new rectangle...
+	TInt width = newRect.iBr.iX - newRect.iTl.iX;
+	if (width>0)
+		{
+		TInt height= newRect.iBr.iY - newRect.iTl.iY;
+		if ( aVector.iY <= 0 )
+			{
+			for ( TInt y=0;y<height;y++ )
+				MemScrMove(newRect.iTl-aVector+TPoint(0,y),newRect.iTl+TPoint(0,y),TUint(width));
+			}
+		else
+			{
+			for ( TInt y=height-1;y>=0;y-- )
+				MemScrMove(newRect.iTl-aVector+TPoint(0,y),newRect.iTl+TPoint(0,y),TUint(width));
+			}	
+		}
+	// now, all characters that are in normRect but not in newRect must become spaces, but WE KEEP THE ATTRIBUTES!
+	for(TInt y=normRect.iTl.iY;y<normRect.iBr.iY;y++)
+		for(TInt x=normRect.iTl.iX;x<normRect.iBr.iX;x++)
+			if (!newRect.Contains(TPoint(x,y)))
+				MemChrPtr(TPoint(x,y),1).Fill(TChar(' '));
+	}
+
+void CEikConsoleScreen::MemScrScrollUp(TUint aLines)
+	{
+	TInt toMove = iConsoleSize.iWidth * (iConsoleSize.iHeight + iMaxChrExtra - aLines);
+	if (toMove>0)
+		MemChrPtr(TPoint(0,-iMaxChrExtra),toMove).Copy(MemChrPtr(TPoint(0,aLines-iMaxChrExtra),toMove));
+	toMove = iConsoleSize.iWidth * (iConsoleSize.iHeight + iMaxAttExtra - aLines);
+	if (toMove>0)
+		MemAttPtr(TPoint(0,-iMaxAttExtra),toMove).Copy(MemAttPtr(TPoint(0,aLines-iMaxAttExtra),toMove));
+	// update nr of lines stored
+	iNoChrExtra+=aLines; 
+	cutmax(iNoChrExtra,iMaxChrExtra); 
+	}
+
+EXPORT_C void CEikConsoleScreen::SetHistorySizeL(TUint aMaxChrExtra,TUint aMaxAttExtra)
+	{
+	FlushChars();
+	TText* chrBuf = (TText  *) User::AllocL(iConsoleSize.iWidth * (aMaxChrExtra + iConsoleSize.iHeight) * sizeof(TText));
+	CleanupStack::PushL(chrBuf);
+	TUint8* attBuf = (TUint8 *) User::AllocL(iConsoleSize.iWidth * (aMaxAttExtra + iConsoleSize.iHeight) * sizeof(TUint8));
+	CleanupStack::Pop(); // chrBuf
+	iMaxChrExtra=aMaxChrExtra;
+	iMaxAttExtra=aMaxAttExtra;
+	User::Free(iChrBuf);
+	iChrBuf=chrBuf;
+	User::Free(iAttBuf);
+	iAttBuf=attBuf;
+	// clear on-screen buffers and set top left to top of screen
+	iNoChrExtra=0; 
+	MemScrClr(TRect(iConsoleSize),0);
+	iTopLeft.SetXY(0,iMaxChrExtra);
+	// datasize + topleft have changed:
+	UpdateScrollBars(); 
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  SETTINGS
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C void CEikConsoleScreen::SetKeepCursorInSight(TUint aFlag)
+	{
+	FlushChars();
+	iKeepCursorInSight=aFlag;
+	}
+
+EXPORT_C void CEikConsoleScreen::SetPureCRLF(TUint aFlag)
+	{
+	FlushChars();
+	iPureCRLF=aFlag;
+	}
+
+EXPORT_C void CEikConsoleScreen::SetAllPrintable(TUint aFlag)
+	{
+	FlushChars();
+	iAllPrintable=aFlag;
+	}
+
+EXPORT_C void CEikConsoleScreen::SetScrollLock(TUint aFlag)
+	{
+	FlushChars();
+	iScrollLock=aFlag;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  CURSOR DISPLAY
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C TInt CEikConsoleScreen::HideCursor()
+	{
+	FlushChars();
+	if (iCursorBlinking) 
+		{
+		if (iConsoleControl->IsFocused())
+			iConsoleControl->HideCursor();
+		iCursorBlinking=FALSE;
+		return 1;
+		}
+	return 0;
+	}
+
+EXPORT_C void CEikConsoleScreen::DrawCursorInSight()
+	{
+	DrawInSight(iCursor);
+	DrawCursor();
+	}
+
+EXPORT_C void CEikConsoleScreen::DrawCursor()
+	{
+	if (iConsFlags&ENoInitialCursor)
+		{
+		iConsFlags&=(~ENoInitialCursor);
+		return;
+		}
+	FlushChars();
+	if(iConsoleControl->IsFocused())
+		{
+		TPoint theCursor = ScrToVis(iCursor);
+		iConsoleControl->DrawCursor(theCursor);
+		iCursorBlinking=TRUE;
+		}
+	}
+
+void CEikConsoleScreen::DrawCursorWhereNeeded()
+	{
+	// FlushChars() by one of the DrawCursor's
+	if (iKeepCursorInSight) 
+		DrawCursorInSight(); 
+	else  
+		DrawCursor();
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  MoveTopLeft() and Redraw()
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C void CEikConsoleScreen::SetScrollBarVisibilityL(CEikScrollBarFrame::TScrollBarVisibility aHBarVisibility, CEikScrollBarFrame::TScrollBarVisibility aVBarVisibility)
+	{
+	if (iConsoleControl->SetScrollBarVisibilityL(aHBarVisibility,aVBarVisibility))
+		{
+		if (UpdateScrollBars())
+			iConsoleControl->UpdateArea();
+		}
+	}
+
+EXPORT_C void CEikConsoleScreen::MoveTopLeft(TPoint aVector)
+	{
+	TInt cursorHidden=HideCursor(); //FlushChars(); by hidecursor
+
+	TPoint newTL = iTopLeft + aVector; 
+	cutmax(newTL.iX, iConsoleSize.iWidth - iVisSize.iWidth);
+	cutmin(newTL.iX, 0);
+	cutmax(newTL.iY, iMaxChrExtra + iConsoleSize.iHeight - iVisSize.iHeight);
+	cutmin(newTL.iY, iMaxChrExtra - iNoChrExtra);
+
+	TPoint vector = iTopLeft-newTL;
+	iConsoleControl->ScrollChars(iVisWin,vector);	
+	iTopLeft=newTL;
+	// topleft has changed:
+	UpdateScrollBars(); 
+
+	// Following lines added for smooth redrawing: (@@@ are these really needed? @@@)
+	if (vector.iX==0)
+		{
+		if (vector.iY>0)
+			Redraw(TRect(0,0,iVisSize.iWidth,vector.iY)); 
+		else if (vector.iY<0)
+			Redraw(TRect(0,iVisSize.iHeight+vector.iY,iVisSize.iWidth,iVisSize.iHeight)); 
+		}
+	else if (vector.iY==0)
+		{
+		if (vector.iX>0)
+			Redraw(TRect(0,0,vector.iX,iVisSize.iHeight)); 
+		else // if (vector.iX<0)
+			Redraw(TRect(iVisSize.iWidth+vector.iX,0,iVisSize.iWidth,iVisSize.iHeight)); 
+		}
+
+	if (cursorHidden) 
+		DrawCursor();
+	}
+
+// Redraw of a set of same-attribute characters (knows about double LEFT/RIGHT)
+void CEikConsoleScreen::RedrawChars(TInt anX,TInt anY,TInt aLength,TUint anAtt)
+	{
+	TUint att=anAtt;
+	if ( (anX&1) && !(anAtt & ATT_COLORMASK) && (anAtt & ATT_DOUBLEMASK) )
+		att |= ATT_RIGHTMASK; // set RIGHT flag for any doublewidth non-color character in an odd column
+	iConsoleControl->DrawChars(MemChrPtr(TPoint(anX,anY-iMaxChrExtra),aLength),TPoint(anX,anY)-iTopLeft,att);
+	TRect sel; CopyNormalisedRange(sel,iSelection); sel.Move(0,iMaxChrExtra);
+	InvertOverlap(sel.iTl,sel.iBr,TPoint(anX,anY),TPoint(anX+aLength,anY)); //}}}
+	}
+
+// aRect = VISIBLE coordinates!!!
+EXPORT_C void CEikConsoleScreen::Redraw(const TRect &aRect)
+	{
+	TInt oldnow=iWriteNow; iWriteNow=1; 
+
+	TRect todoRect = Clip(aRect,iVisWin);
+	if (RecalculateSize())
+		{
+		iTopLeft = GetAnInSightPosition(iCursor);
+		// topleft has changed
+		if (UpdateScrollBars())
+			{
+			iTopLeft = GetAnInSightPosition(iCursor);
+			UpdateScrollBars();
+			}
+		// might as well redraw the whole screen now...
+		todoRect = iVisWin;
+		}
+
+	// convert visible to clipped absolute coordinates
+	todoRect.Move(iTopLeft);
+	cutmax(todoRect.iBr.iX,iConsoleSize.iWidth);
+	cutmax(todoRect.iBr.iY,iMaxChrExtra + iConsoleSize.iHeight);
+	
+	// hide cursor while redarwing...
+	TInt cursorHidden = HideCursor();
+	
+	for( TInt y=todoRect.iTl.iY; y<todoRect.iBr.iY; y++) 
+		{
+		TInt yAtt = y+iMaxAttExtra-iMaxChrExtra; // line within attribute buffer
+		TInt x,start;
+		TInt len=0;
+		TUint att=ATT_MAXVALUE+1;	// impossible value
+		TUint attXY=ATT_NORMAL;    	// default attribute (in case there is no attribute history)
+	  	for( x=start=todoRect.iTl.iX; x<todoRect.iBr.iX; x++)
+			{
+			if (yAtt>=0) 
+				attXY=iAttBuf[x+yAtt*iConsoleSize.iWidth]; 
+			if ( att != attXY )
+				{
+				if (len)  
+					RedrawChars(start,y,len,att);
+				start=x; att=attXY; len=0;
+				}
+			len++;
+			}
+		if (len)
+			RedrawChars(start,y,len,att);
+		}
+
+	if (cursorHidden) 
+		DrawCursor();
+	iWriteNow=oldnow;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  Constructors/Destructors/Initializers
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C void CEikConsoleScreen::SetTitle(const TDesC& aTitle)
+    {
+    TRAP_IGNORE(SetTitleL(aTitle));
+    // !! what to do if err ??
+    }
+
+EXPORT_C void CEikConsoleScreen::SetTitleL(const TDesC& aTitle)
+	{
+    HBufC* oldTitle=iConsoleTitle;
+	iConsoleTitle=aTitle.AllocL();
+    delete(oldTitle);
+	}
+
+EXPORT_C void CEikConsoleScreen::ConstructL(const TDesC &aTitle,TInt aFlags)// use full screen 
+	{
+	// if no CEikConsoleControl set yet, claim one 
+	iConsFlags=aFlags;
+	if (!iConsoleControl)
+		{
+		CEikConsoleControl* consWin = new(ELeave) CEikConsoleControl;
+		CleanupStack::PushL(consWin);
+		consWin->ConstructL(aFlags);
+		SetConsWin(consWin);
+		CleanupStack::Pop();	// consWin
+		}
+	SetTitleL(aTitle);
+	iConsoleSize=TSize(iConsoleControl->Size().iWidth/iConsoleControl->CharSize().iWidth,
+		iConsoleControl->Size().iHeight/iConsoleControl->CharSize().iHeight);
+	iKeepCursorInSight=TRUE;
+	iWriteBuffer.SetLength(0); 
+	SetHistorySizeL(0,0);
+	}
+
+EXPORT_C void CEikConsoleScreen::ConstructL(const TDesC &aTitle,TPoint aTopLeft,const TSize &aSize,
+				TInt aFlags,TEikConsWinUnits aUnit)
+	{
+	// if no CEikConsoleControl set yet, claim one 
+	iConsFlags=aFlags;
+	if (!iConsoleControl)
+		{
+		CEikConsoleControl* consWin = new(ELeave) CEikConsoleControl;
+		CleanupStack::PushL(consWin);
+		consWin->ConstructL(aTopLeft,aSize,aFlags,aUnit);
+		SetConsWin(consWin);
+		CleanupStack::Pop();	// consWin
+		}
+	SetTitleL(aTitle);
+	if (aUnit==EEikConsWinInChars)
+		iConsoleSize=aSize;
+	else
+		iConsoleSize=TSize(aSize.iWidth/iConsoleControl->CharSize().iWidth,
+			aSize.iHeight/iConsoleControl->CharSize().iHeight);
+	iKeepCursorInSight=TRUE;
+	iWriteBuffer.SetLength(0); 
+	SetHistorySizeL(0,0);
+	}
+
+EXPORT_C void CEikConsoleScreen::ConstructL(const TDesC &aTitle,const TSize &aSize,TInt aFlags,TEikConsWinUnits aUnit)
+ // place the screen at TPoint(0,0)
+	{
+	ConstructL(aTitle,TPoint(0,0),aSize,aFlags,aUnit);
+	}
+
+EXPORT_C CEikConsoleScreen::CEikConsoleScreen()
+    {
+    }
+
+EXPORT_C CEikConsoleScreen::~CEikConsoleScreen()
+	{
+    delete(iConsoleControl);
+	User::Free(iChrBuf);
+	User::Free(iAttBuf);
+	User::Free(iConsoleTitle);
+	}
+
+TBool CEikConsoleScreen::RecalculateSize()
+// returns ETrue if visible window has changed
+	{
+	TRect oldwin=iVisWin;
+	iVisSize = iConsoleControl->VisibleSize();
+	cutmax(iVisSize.iWidth ,iConsoleSize.iWidth);
+	cutmax(iVisSize.iHeight ,iConsoleSize.iHeight);
+	iVisWin = TRect(iVisSize);
+	return oldwin!=iVisWin;
+	}
+
+EXPORT_C const TFontSpec& CEikConsoleScreen::Font() const
+	{
+	return iConsoleControl->Font();
+	}
+
+EXPORT_C void CEikConsoleScreen::SetFontL(const TFontSpec &aFontSpec)
+	{
+	FlushChars();
+	iConsoleControl->SetFontL(aFontSpec,NULL);
+	}
+
+EXPORT_C void CEikConsoleScreen::SetConsWin(CEikConsoleControl *aConsWin)
+	{
+	FlushChars();
+	TBool calledBefore=EFalse;
+	TInt cursorHidden=EFalse;
+	if (iConsoleControl)
+		{
+		calledBefore=ETrue;
+		cursorHidden=HideCursor();
+		delete(iConsoleControl);
+		}
+	iConsoleControl=aConsWin;
+	iConsoleControl->SetRedrawer(this);
+	if (RecalculateSize())
+		iTopLeft = GetAnInSightPosition(iCursor);
+	if (calledBefore) // no need to update scrollbars the very first time
+		UpdateScrollBars();
+	if (cursorHidden)
+		DrawCursorWhereNeeded();
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  Cursor Stuff
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+// clip cursor to SCREEN, allows X coordinate of LAST line to be 1 past the right marging!
+void CEikConsoleScreen::ClipCursor()
+	{
+	cutmin(iCursor.iX,0);
+	cutmin(iCursor.iY, -iNoChrExtra);
+	if (iCursor.iY<iConsoleSize.iHeight-1)
+		cutmax(iCursor.iX,iConsoleSize.iWidth-1);
+	else
+		cutmax(iCursor.iX,iConsoleSize.iWidth);
+	cutmax(iCursor.iY,iConsoleSize.iHeight-1);
+	}
+
+// return SCREEN coordinates
+EXPORT_C TPoint CEikConsoleScreen::CursorPos() const
+	{
+	((CEikConsoleScreen*)this)->FlushChars();
+	return iCursor;
+	}
+
+// aPoint = SCREEN coordinates
+EXPORT_C void CEikConsoleScreen::SetCursorPosAbs(const TPoint &aPoint)
+	{
+	FlushChars();
+	iCursor = aPoint;
+	ClipCursor(); 
+	if (iCursorBlinking)
+		DrawCursorWhereNeeded();
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+EXPORT_C void CEikConsoleScreen::SetCursorPosRel(const TPoint &aPoint)
+	{
+	FlushChars();
+	iCursor+=aPoint;
+	ClipCursor();
+	if (iCursorBlinking)
+		DrawCursorWhereNeeded();
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+EXPORT_C void CEikConsoleScreen::SetCursorHeight(TInt aPercentage)
+// set cursor height to aPercentage, and redraw cursor (if it is blinking)
+	{
+	iConsoleControl->SetCursorHeight(aPercentage);
+	if (iCursorBlinking)
+		DrawCursorWhereNeeded();
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+TPoint CEikConsoleScreen::GetAnInSightPosition(TPoint aPosition) const
+	{
+	TPoint newTL = iTopLeft;
+	// past right margin: move so that cursor is at 3/4th of visible line screen
+	if ( aPosition.iX >= newTL.iX + iVisSize.iWidth )
+		newTL.iX = aPosition.iX - (3*iVisSize.iWidth)/4;
+	// past left margin: move so that cursor is at 1/4th of visible line screen
+	if ( aPosition.iX < newTL.iX )
+		newTL.iX = aPosition.iX - iVisSize.iWidth/4;
+	// keep within visible limits
+	cutmax(newTL.iX,iConsoleSize.iWidth - iVisSize.iWidth);
+	cutmin(newTL.iX,0);
+	cutmax(newTL.iY,iMaxChrExtra + iConsoleSize.iHeight - iVisSize.iHeight);
+	cutmax(newTL.iY,aPosition.iY + iMaxChrExtra);
+	cutmin(newTL.iY,iMaxChrExtra + aPosition.iY - (iVisSize.iHeight-1));
+	cutmin(newTL.iY,0); 
+	return newTL;
+	}
+
+EXPORT_C void CEikConsoleScreen::DrawInSight(TPoint aPosition)
+	{
+	FlushChars();
+	TPoint vector = GetAnInSightPosition(aPosition);
+	if ( vector != iTopLeft )
+		MoveTopLeft(vector-iTopLeft); // FlushChars() by MoveTopLeft
+	}
+
+EXPORT_C void CEikConsoleScreen::Up(TUint aCount)
+	{
+	FlushChars();
+	iCursor.iY-=aCount;
+	ClipCursor();
+	DrawCursorWhereNeeded();
+	}
+
+EXPORT_C void CEikConsoleScreen::Down(TUint aCount)
+	{
+	FlushChars();
+	iCursor.iY+=aCount;
+	ClipCursor();
+	DrawCursorWhereNeeded();
+	}
+
+EXPORT_C void CEikConsoleScreen::Left(TUint aCount)
+	{
+	FlushChars();
+	iCursor.iY-=(aCount / iConsoleSize.iWidth );
+	iCursor.iX-=(aCount % iConsoleSize.iWidth );
+	while (iCursor.iX<0) 
+		{ iCursor.iY--; iCursor.iX+=iConsoleSize.iWidth; } 
+	if (iCursor.iY<(-iNoChrExtra)) 
+		iCursor.SetXY(0,-iNoChrExtra);
+	ClipCursor();
+	DrawCursorWhereNeeded();
+	}
+
+EXPORT_C void CEikConsoleScreen::Right(TUint aCount)
+	{
+	FlushChars();
+	iCursor.iX += aCount;
+	iCursor.iY += (iCursor.iX / iConsoleSize.iWidth);
+	iCursor.iX %= iConsoleSize.iWidth;
+	if (iCursor.iY>=iConsoleSize.iHeight)
+		iCursor.iX=iConsoleSize.iWidth;
+	ClipCursor();
+	DrawCursorWhereNeeded();
+	}
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  GRAPHICS
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+EXPORT_C HBufC *CEikConsoleScreen::RetrieveL(const TRect &aSelection)
+	{
+	FlushChars();
+	TRect sel=aSelection; 
+	TInt len = (sel.iBr.iX-sel.iTl.iX)+iConsoleSize.iWidth*(sel.iBr.iY-sel.iTl.iY);
+	if (len==0)
+		return NULL;
+	if (len<0) 
+		return 	MemChrPtr(sel.iBr,-len).AllocL();
+	return 		MemChrPtr(sel.iTl, len).AllocL();
+	}
+
+// aRect = SCREEN coordinates
+EXPORT_C void CEikConsoleScreen::ClearChars(const TRect &aRect,TUint anAtt) 
+	{
+	FlushChars();
+	MemScrClr(aRect,TUint8(anAtt));
+	iConsoleControl->ClearChars(Clip(ScrToVis(aRect),TRect(iConsoleSize)),anAtt);
+	}
+
+EXPORT_C void CEikConsoleScreen::ScrollChars(const TRect &anArea,const TPoint &aVector)
+	{
+	FlushChars();
+	MemScrScroll(anArea,aVector);
+	iConsoleControl->ScrollChars(Clip(ScrToVis(anArea),TRect(iConsoleSize)),aVector);
+	}
+
+EXPORT_C void CEikConsoleScreen::ClearScreen()
+	{
+	TInt cursorHidden = HideCursor(); //FlushChars(); by hidecursor
+	iCursor.SetXY(0,0);
+	SelectCursor();
+	iTopLeft.SetXY(0,iMaxChrExtra); 
+	ClearChars(TRect(iConsoleSize),iAtt);
+	// datasize + topleft changed
+	UpdateScrollBars();  // wont ever actually leave
+	if (cursorHidden) 
+		DrawCursorWhereNeeded();
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+EXPORT_C void CEikConsoleScreen::SetAtt(TUint anAtt)
+	{
+	// never store the LEFT/RIGHT flag
+	TUint newAtt = anAtt;
+	if (!(anAtt & ATT_COLORMASK))
+		newAtt &= ATT_IGNORE_RIGHTLEFT;
+	if (newAtt!=iAtt)
+		{
+		FlushChars();
+		iAtt = newAtt;
+		}
+	}
+
+EXPORT_C void CEikConsoleScreen::SetAtt(TUint aForegroundGrey16,TUint aBackgroundGrey16)
+	{
+	SetAtt( ATT_COLORMASK | (aForegroundGrey16 & 0x0F) | ((((aBackgroundGrey16/2) & 0x0F)<<4)) );
+	}
+
+EXPORT_C void CEikConsoleScreen::ClearToEndOfLine()
+	{
+	FlushChars(); //needed before using iCursor!
+	ClearChars(TRect(iCursor.iX,iCursor.iY,iConsoleSize.iWidth,iCursor.iY+1),iAtt);
+	}
+
+
+EXPORT_C void CEikConsoleScreen::Cr()
+	{
+	// !! removed by DavidW, to match E32 console behaviour -- ClearToEndOfLine(); //FlushChars(); by clreol
+	iCursor.iX=0;
+	}
+
+
+EXPORT_C void CEikConsoleScreen::Lf()
+	{
+	TInt cursorHidden=HideCursor(); //FlushChars(); by hidecursor
+	iCursor.iY++;
+	if (iCursor.iY >= iConsoleSize.iHeight)
+		{
+		iCursor.iY--;
+		if (!iScrollLock)
+			{
+			//move selection along too!
+			iSelection.iTl.iY--; cutmin(iSelection.iTl.iY,-iNoChrExtra);
+			iSelection.iBr.iY--; cutmin(iSelection.iBr.iY,-iNoChrExtra);
+			// scroll in memory and clear new bottom line
+			MemScrScrollUp();
+			UpdateScrollBars();
+			MemScrClr(TRect(0,iConsoleSize.iHeight-1,iConsoleSize.iWidth,iConsoleSize.iHeight),TUint8(iAtt));
+			iConsoleControl->ScrollChars(iVisWin, TPoint(0,-1));  
+			Redraw(TRect(0,iVisSize.iHeight-1,iVisSize.iWidth,iVisSize.iHeight)); 
+			}
+		// restore cursor
+		}
+	if (cursorHidden) 
+		DrawCursorWhereNeeded();	
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+EXPORT_C void CEikConsoleScreen::Write(const TDesC &aText)
+	{
+
+	if (aText.Length()==0)
+	  return;
+
+	// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+	// consecutive write handling: save characters until
+	//  - any OTHER command is called that MUST come AFTER this write
+	//  - we got more than we can buffer
+	//	- we encounter a CR/LF as last character (?)
+	retry:
+	if (iWriteNow==0)
+		{
+		if (iWriteBuffer.Length() + aText.Length() < 256)
+			{
+			iWriteBuffer.Append(aText);
+/* !! Prevents eg EShell from flushing when using Up arrow (prev command coz no trailing CR/LF
+			// check for CR/LF as last character @@@ should we?
+			TInt c = iWriteBuffer[ iWriteBuffer.Length()-1 ];
+			if ( c==EKeyLineFeed || c==EKeyEnter )
+*/ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+					FlushChars();
+			return;
+			}
+		else 
+			{ 
+			FlushChars(); 
+			if ( aText.Length() < 256 )
+				goto retry;
+			// ELSE: write iWriteNow!
+			}
+		}
+
+	// no cursor while we draw, and forget selection
+	TInt cursorHidden=HideCursor();
+	InvertRange(iSelection); 
+
+	for ( TInt i=0; i<aText.Length(); )
+		{
+		// current line full?
+		if (iCursor.iX>=iConsoleSize.iWidth)
+			{
+			iCursor.iX=0; // instead of Cr()
+			Lf();
+			continue;
+			}
+		// there are characters to be printed...
+		TChar c = aText[i]; 
+		if ( c<32 && iAllPrintable==FALSE )
+			{
+			switch (c)
+				{	
+				// next char is a FF?
+			case  EKeyBell:	
+						// BELL @@@
+						break;
+			case  EKeyBackspace:    
+						Left(); // BS
+						break;
+			case  EKeyTab:	//TAB
+						FlushChars();
+						for(;;)
+							{
+							// move character forward (stop at right margin)
+							if (iCursor.iX<iConsoleSize.iWidth)
+								iCursor.iX++;
+                            else
+                                break;  
+							// break at the first tab that is encountered
+							if ( iCursor.iX%8==0) 
+								break;
+							}
+						break;
+			case EKeyLineFeed:	
+						if (!iPureCRLF) 
+							Cr();
+						Lf(); // LF
+						break;
+			case EKeyFormFeed:	
+						ClearScreen(); // FF
+						break;
+			case EKeyEnter:	
+						if (iPureCRLF) 	
+							Cr(); // CR
+						break;
+				}
+			i++;
+			}
+		else
+			{
+			// Determine how many characters can be output at once
+			TUint8 att = TUint8(iAtt);
+			TInt avail = ( iConsoleSize.iWidth - iCursor.iX );
+			TInt outnow=0; 
+			if (iAllPrintable) outnow=1;
+			while ( outnow<avail && i+outnow < aText.Length() && aText[i+outnow]>=32 ) 
+				outnow++;
+			MemScrPut(aText.Mid(i,outnow),iCursor,att);
+		
+			// now let's see how many characters need actually be drawn...
+			TPoint pos=ScrToVis(iCursor);
+			if (pos.iY>=0 && pos.iY<iVisSize.iHeight)
+				{
+				TUint start=i;
+				TInt len=outnow;
+				if (pos.iX<0) 
+					{ 
+					start-=pos.iX; len+=pos.iX; pos.iX=0; 
+					} 
+				cutmax(len,iVisSize.iWidth-pos.iX);
+				if (len>0)
+					{
+					TUint drawAtt = att;
+					if ( !(drawAtt & ATT_COLORMASK) && (drawAtt & ATT_DOUBLEMASK) && ((pos.iX+iTopLeft.iX) &1) )
+						drawAtt |= ATT_RIGHTMASK; // set RIGHT flag for any doublewidth non-color character in an odd column					
+					iConsoleControl->DrawChars(aText.Mid(start,len),pos,drawAtt);
+					}
+				}
+
+			iCursor.iX += outnow;
+			i+=outnow;
+			}
+		}
+
+	InvertRange(iSelection);
+	if (iCursor.iX==iConsoleSize.iWidth)
+		if (iCursor.iY<iConsoleSize.iHeight-1)
+			{ iCursor.iX=0; iCursor.iY++; }
+	if (cursorHidden)
+		DrawCursorWhereNeeded();
+	else if (iKeepCursorInSight) 
+		DrawInSight(iCursor);
+	}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//
+//  SELECTION ROUTINES (LOW LEVEL)
+//
+////////////////////////////////////////////////////////////////////////////////////////
+TPoint CEikConsoleScreen::ScrToVis(TPoint aPoint) // ^screen -> ^visible (unclipped)
+	{
+	return aPoint + TPoint(0,iMaxChrExtra) - iTopLeft; 
+	}
+
+TRect CEikConsoleScreen::ScrToVis(const TRect &aRect) // ^screen -> ^visible (clip iVisWin) 
+	{
+	return Clip(TRect(ScrToVis(aRect.iTl),ScrToVis(aRect.iBr)),iVisWin);
+	}
+
+void CEikConsoleScreen::InvertRange(const TRect &aRange) // ^screen
+	{
+	TRect aRect; CopyNormalisedRange(aRect,aRange);
+	for ( TInt y=aRect.iTl.iY; y<=aRect.iBr.iY; y++ )
+		{
+		TInt from = (y==aRect.iTl.iY) ? aRect.iTl.iX : 0;
+		TInt upto = (y==aRect.iBr.iY)   ? aRect.iBr.iX : iConsoleSize.iWidth;
+		if (from<upto) 
+			iConsoleControl->InvertChars(ScrToVis(TRect(from,y,upto,y+1))); 
+		}
+	}
+
+void CEikConsoleScreen::InvertOverlap(TPoint aStart,TPoint aEnd,TPoint bStart,TPoint bEnd) // ^absolute
+	{
+	if (SmallerPoint(aEnd,aStart))
+		return;
+	if (SmallerPoint(bEnd,bStart)) 
+		return;
+	TPoint start = SmallerPoint(aStart,bStart) ? bStart : aStart;  
+	TPoint end   = SmallerPoint(aEnd  ,bEnd  ) ? aEnd   : bEnd;  	
+	if (SmallerPoint(end,start)) 
+		return;
+	TRect rect(start,end);
+	rect.Move(0,-iMaxChrExtra);
+	InvertRange(rect); // ^absolute -> ^screen
+	}
+
+
+EXPORT_C void CEikConsoleScreen::SetSelection(const TRect &aSelection) // ^screen
+	{
+	FlushChars();
+	TRect oldRange,newRange;
+	CopyNormalisedRange(oldRange,iSelection);		// normalise previous selection
+	CopyNormalisedRange(newRange,aSelection);		// normalise new selection
+	iSelection=aSelection;
+
+	oldRange.iTl.iY+=iMaxChrExtra; 
+	oldRange.iBr.iY+=iMaxChrExtra; 
+	newRange.iTl.iY+=iMaxChrExtra; 
+	newRange.iBr.iY+=iMaxChrExtra; 
+
+	InvertOverlap(TPoint(0,0), newRange.iTl,oldRange.iTl,oldRange.iBr ); 						// devert beforenew
+	InvertOverlap(newRange.iTl,newRange.iBr,TPoint(0,0),oldRange.iTl);							// invert beforeold
+	InvertOverlap(newRange.iTl,newRange.iBr,oldRange.iBr,TPoint(0,iMaxChrExtra)+iConsoleSize );	// invert afterold
+	InvertOverlap(newRange.iBr,TPoint(0,iMaxChrExtra)+iConsoleSize,oldRange.iTl,oldRange.iBr);	// devert afternew
+	}
+
+EXPORT_C void CEikConsoleScreen::SelectCursor()
+	{
+	FlushChars();
+	SetSelection(TRect(iCursor,iCursor)); 
+	}
+
+EXPORT_C TRect CEikConsoleScreen::Selection() // ^screen
+	{
+	FlushChars();
+	return iSelection;
+	}
+
+