commonuisupport/grid/src/GRDIMG.CPP
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commonuisupport/grid/src/GRDIMG.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,2910 @@
+// Copyright (c) 1997-2009 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:
+// The member variables of the class CGridImg are as follows:-
+// iGridRect - the coordinates of the rectangle containing the grid.
+// iTitlePoint - The point at the top left of the grid not including the labels
+// iMainPoint - The point at which the visible range starts (usually == iTitlePoint)
+// iCursorPos - the cell reference of the current cursor position.
+// iNewCursorPos - the proposed cell reference of the position that
+// the cursor would occupy after a keypress.
+// iAnchorPos - the cell reference of the position that the cursor must
+// return to after a series of selected movements have been made.
+// iGcPtr - a pointer to the current graphics context.
+// iGc - the internal grid image Gc
+// *iWin - a pointer to the current active window.
+// *iGridLay, *iGridCellImg, *iGridLabelImg - allow access to the data in these
+// other classes.
+// *iSelected - allows access to the class that stores the array of selected ranges
+// *iCursorMoveCallBack - a pointer to call back to an app after a cursor move
+// iDragLabel - store the index of the label currently being dragged
+// iCurrentDragPos - Stores the position of the label prior to it being dragged
+// iDragDiff - Stores the distance between the second drag label and the pointer while a label drag is in progress
+// iDragDim - Simply stores the dimension in which a label drag is in (X,Y or none)
+// iDragBmp - Stores the bitmap of the dragged labels during a drag.
+// iXRefPoint,iYRefPoint - Remembers which part of the grid the last pointer event was in. This is used in the
+// SetCursorWithPointer() function logic.
+// 
+//
+
+#include "GRDSTD.H"
+#include "GRDPANIC.H"
+
+#if !defined(__WINC__)
+#include <w32std.h>
+#endif
+
+const TInt KArrowLength = 11;
+const TInt KArrowBreadth = 11;
+const TInt KArrowSeparation = 11;
+
+GLDEF_C void Panic(TGridPanic aPanic)
+	{
+	_LIT(KGridPanic,"GRIDIMG");
+	User::Panic(KGridPanic,aPanic);
+	}
+
+EXPORT_C void TGridUtils::FillRect(CGraphicsContext* aGc,TRgb aColor,const TRect &aRect)
+/** Fills the specified rectangle with the specified colour.
+
+@param aGc The graphics context to be used.
+@param aColor The colour which is to fill the rectangle.
+@param aRect The rectangle to be filled.
+@panic GRIDIMG 0 In debug mode only, if the pointer to the graphics context 
+is Null. */
+	{
+	__ASSERT_DEBUG(aGc!=NULL,Panic(EGridImgInvalidGC));
+	aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+	aGc->SetPenStyle(CGraphicsContext::ENullPen);
+	aGc->SetBrushColor(aColor);
+	aGc->DrawRect(aRect);
+	aGc->SetPenStyle(CGraphicsContext::ESolidPen);
+	aGc->SetBrushStyle(CGraphicsContext::ENullBrush);
+	}
+
+//
+
+EXPORT_C CGridCellImg::CGridCellImg()
+	: iBurstColOffset(0),
+	iBurstLeft(0),
+	iBurstRight(0),
+	iGridLineFlags(EIsHorizontalGridLines|EIsVerticalGridLines)
+/** Default constructor. */
+	{
+	}
+
+EXPORT_C CGridCellImg::~CGridCellImg()
+/** Destructor. */
+	{
+	}
+
+
+EXPORT_C TInt CGridCellImg::DataWidthInPixelsL(const TCellRef& /*aCell*/) const
+/**	Gets the width of the data contained in the specified cell.
+@publishedAll 
+@released
+@param aCell The cell to be tested.
+@return The width of the data, in pixels. The default implementation returns zero.*/
+	{
+	return 0;
+	}
+
+EXPORT_C TBool CGridCellImg::DoesCellContainDataL(const TCellRef& /*aCell*/) const
+/**	Tests whether the specified cell contains data.
+@publishedAll 
+@released
+@param aCell The cell to be tested.
+@return True, if the cell contains data; false, otherwise. The default implementation returns true.*/
+	{
+	return ETrue;
+	}
+
+EXPORT_C void CGridCellImg::Reserved_1()
+	{
+// No implementation yet
+	}
+
+void CGridCellImg::SetBurstingData(TInt aBurstColOffset,TInt aBurstLeft,TInt aBurstRight)
+	{
+	iBurstColOffset=aBurstColOffset;
+	iBurstLeft=aBurstLeft;
+	iBurstRight=aBurstRight;
+	}
+
+//
+
+EXPORT_C CGridLabelImg::CGridLabelImg(const TFontSpec& aFontSpec,MGraphicsDeviceMap* aGraphicsDeviceMap)
+	: iFontSpec(aFontSpec),
+	iGraphicsDeviceMap(aGraphicsDeviceMap)
+/** Constructor taking specified parameters.
+
+@param aFontSpec A font specification in device independent terms.
+@param aGraphicsDeviceMap An interface for mapping between twips and device-specific 
+units. */
+	{
+	}
+
+EXPORT_C CGridLabelImg::~CGridLabelImg()
+/** Destructor.
+
+Releases resources before the object is destroyed. Specifically, it releases 
+the font acquired when the object was constructed. */
+	{
+	if (iGraphicsDeviceMap && iFont)
+		iGraphicsDeviceMap->ReleaseFont(iFont);
+	}
+
+EXPORT_C void CGridLabelImg::ConstructL()
+/** Implements the second phase of two-phase construction.
+
+Specifically, it gets the nearest font to that specified in the font specification 
+passed to the constructor. */
+	{
+	NotifyGraphicsDeviceMapChangeL();
+	}
+
+
+EXPORT_C void CGridLabelImg::DrawTopLeftLabelL(CGraphicsContext* aGc,const TRect& aRect) const
+/** Fills the specified rectangle with a colour.
+
+The default implementation fills the specified rectangle with the background 
+colour value as defined by the grid colour specification in iGridColors.
+@publishedAll 
+@released 
+@param aGc The graphics context to be used.
+@param aRect The rectangle to be filled.
+@see TGridColors */
+	{
+//	TGridUtils::FillRect(aGc,KGridBackgroundColor,aRect);
+//->
+	TGridUtils::FillRect(aGc, iGridColors.iBackground, aRect);
+	}
+
+EXPORT_C void CGridLabelImg::DrawTopLeftLabelL(CGraphicsContext* aGc,const TRect& aRect, TRgb aColor) const
+/** Fills the specified rectangle with the specified colour.
+
+@param aGc The graphics context to be used.
+@param aRect The rectangle to be filled.
+@param aColor The colour which is to fill the rectangle. */
+	{
+	TGridUtils::FillRect(aGc, aColor, aRect);
+	}
+//->
+
+
+EXPORT_C TInt CGridLabelImg::SideLabelWidthInPixels(TInt /*aStartRow*/,TInt /*aEndRow*/) const
+/** Gets the width of the side labels.
+@publishedAll 
+@released 
+@param aStartRow A start row. The default implementation does not use this value, 
+but a derived class can use this to define the start of a range of rows, 
+which may be useful if side labels have variable widths.
+@param aEndRow An end row. The default implementation does not use this value, 
+but a derived class can use this to define the end of a range of rows, 
+which may be useful if side labels have variable widths.
+@return The width value, in pixels. The default implementation returns the 
+pixel value corresponding to the twips value EDefaultSideLabelWidthInTwips, 
+as converted by the graphics device map function MGraphicsDeviceMap::HorizontalTwipsToPixels(). */
+	{
+	__ASSERT_DEBUG(iGraphicsDeviceMap!=NULL,Panic(EGridNullGraphicsDeviceMap));
+	return iGraphicsDeviceMap->HorizontalTwipsToPixels(EDefaultSideLabelWidthInTwips);
+	}
+
+EXPORT_C TInt CGridLabelImg::TopLabelHeightInPixels() const
+/** Gets the height of the top labels.
+@publishedAll 
+@released 
+@return The height value, in pixels. The default implementation returns the 
+pixel value corresponding to the twips value EDefaultTopLabelHeightInTwips, 
+as converted by the graphics device map function MGraphicsDeviceMap::VerticalTwipsToPixels(). */
+	{
+	__ASSERT_DEBUG(iGraphicsDeviceMap!=NULL,Panic(EGridNullGraphicsDeviceMap));
+	return iGraphicsDeviceMap->VerticalTwipsToPixels(EDefaultTopLabelHeightInTwips);
+	}
+
+EXPORT_C void CGridLabelImg::DrawRowCursorL(CGraphicsContext* /*aGc*/,const TRect& /*aRect*/) const
+/** Draws a cursor to identify a row.
+
+The default implementation is empty.
+@publishedAll 
+@released 
+@param aGc The graphics context to be used.
+@param aRect The rectangle in which the cursor is to be drawn. */
+//
+// To be overridden from if used
+//
+	{}
+
+EXPORT_C void CGridLabelImg::ReleaseFont()
+//
+// Should be called before any change in the zoom factor device
+/** Releases the font.
+
+This is called by the destructor, and should be called before calling SetGraphicsDeviceMap().
+
+@see ConstructL() */
+	{
+	__ASSERT_DEBUG(iGraphicsDeviceMap!=NULL,Panic(EGridNullGraphicsDeviceMap));
+	iGraphicsDeviceMap->ReleaseFont(iFont);
+	iFont=NULL;
+	}
+
+EXPORT_C void CGridLabelImg::NotifyGraphicsDeviceMapChangeL()
+/** Deals with the result of changing the graphics device map, i.e. the interface 
+for mapping between twips and device-specific units.
+
+The function releases the existing font, and then tries to get the nearest 
+font to that specified in the font specification.
+
+@see ConstructL()
+@see SetGraphicsDeviceMap() */
+	{
+	ReleaseFont();
+	User::LeaveIfError(iGraphicsDeviceMap->GetNearestFontInTwips(iFont,iFontSpec));
+	}
+
+//
+
+EXPORT_C CGridImg* CGridImg::NewL(CGridCellImg* aGridCellImg,CGridLay* aGridLay)
+/** Creates a new grid image object suitable for printing.
+
+@param aGridCellImg A pointer to an object that draws the contents of a 
+single cell.
+@param aGridLay A pointer to the object that controls the layout of rows and 
+columns.
+@return A pointer to the new grid image object. */
+	{
+//->
+	CGridImg* self = new(ELeave) CGridImg(aGridCellImg,aGridLay);
+	if (aGridLay && aGridCellImg)
+		aGridCellImg->SetGridColors(aGridLay->GridColors());
+	return self;
+//->
+//	return new(ELeave) CGridImg(aGridCellImg,aGridLay);
+	}
+
+CGridImg::CGridImg(CGridCellImg* aGridCellImg,CGridLay* aGridLay)
+//
+// Construct a partial gridImg object for printing with the same data as the passed gridImg
+// and a handle to the passed gridLay
+	: iGridCellImg(aGridCellImg),
+	iGridLay(aGridLay)
+	{
+	}
+
+EXPORT_C CGridImg* CGridImg::NewL(CGraphicsDevice* aGraphicsDevice,CGridCellImg* aGridCellImg,CGridLay* aGridLay)
+/** Creates a new grid image object.
+
+@param aGraphicsDevice The graphics device to be used for drawing.
+@param aGridCellImg A pointer to an object that draws the contents of a single 
+cell.
+@param aGridLay A pointer to the object that controls the layout of rows and 
+columns.
+@return A pointer to the new grid image object. */
+	{
+	CGridImg* self=new(ELeave) CGridImg(aGraphicsDevice,aGridCellImg,aGridLay);
+	CleanupStack::PushL(self);
+//->
+	if (aGridLay && aGridCellImg)
+		aGridCellImg->SetGridColors(aGridLay->GridColors());
+//->
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+CGridImg::CGridImg(CGraphicsDevice *aGraphicsDevice,CGridCellImg *aGridCellImg,CGridLay* aGridLay)
+	: iGraphicsDevice(aGraphicsDevice),
+	iGridCellImg(aGridCellImg),
+	iGridLay(aGridLay),
+	iDragLabel(0),
+	iCurrentDragPos(0),
+	iDragDiff(0),
+	iDragFlags(0),
+	iDragDim(ENoDrag),
+	iXRefPoint(EMainRef),
+	iYRefPoint(EMainRef)
+	{
+	}
+
+void CGridImg::ConstructL()
+	{
+#if !defined(__WINC__)
+	if (iGraphicsDevice)
+		User::LeaveIfError(iGraphicsDevice->CreateContext((CGraphicsContext*&)iGc));
+#endif
+	}
+
+EXPORT_C CGridImg::~CGridImg()
+/** Destructor.
+
+Frees resources before destruction of the object. */
+	{
+#if !defined(__WINC__)
+	delete iGc;
+	delete iDragBmp;
+#endif
+	delete iSelected;
+	}
+
+void CGridImg::ConstructSelectedL(const TRangeRef& aGridRange)
+	{
+    delete iSelected;
+    iSelected=NULL; // in case next line fails
+	iSelected = CGridCellRegion::NewL(aGridRange);
+	}
+
+void CGridImg::CreateGc(CGraphicsContext* aGc)
+	{
+	__ASSERT_DEBUG(iGcPtr==NULL,Panic(EGridImgInvalidGC));
+	iGcPtr=aGc;
+#if !defined(__WINC__)
+    if (iGcPtr==iGc)
+    	iGc->Activate(*iWin);
+#endif
+	}
+
+void CGridImg::DeleteGc()
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+#if !defined(__WINC__)
+	if (iGcPtr==iGc)
+    	iGc->Deactivate();
+#endif
+	iGcPtr=NULL;
+	}
+
+void CGridImg::DrawAllGridLabelsL() const
+// Draw all the grid labels
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	DrawTopLeftGridLabelL();
+	TRangeRef titleRange=iGridLay->TitleRange();
+	if (iGridLay->IsHorizontalTitleLine())
+		DrawSideGridLabelsL(titleRange.iFrom.iRow,titleRange.iTo.iRow-1,ETitleRef);
+	if (iGridLay->IsVerticalTitleLine())
+		DrawTopGridLabelsL(titleRange.iFrom.iCol,titleRange.iTo.iCol-1,ETitleRef);
+	TRangeRef visRange=iGridLay->VisibleRange();
+	DrawTopGridLabelsL(visRange.iFrom.iCol,visRange.iTo.iCol);
+	DrawSideGridLabelsL(visRange.iFrom.iRow,visRange.iTo.iRow);
+	}
+
+void CGridImg::DrawTopLeftGridLabelL() const
+// Draw top left corner label
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	if (iGridLay->IsTopLabels() && iGridLay->IsSideLabels())
+		{
+		TRect rect(iGridRect.iTl,iTitlePoint);
+		if (iGridLay->IsGridLabelSeparators())
+			{
+		    rect.Resize(-1,-1);
+//->
+		    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//		    iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+		    TPoint start(rect.iTl.iX,rect.iBr.iY);
+		    TPoint finish(rect.iBr.iX+1,rect.iBr.iY);
+		    iGcPtr->DrawLine(start,finish);
+		    start.SetXY(rect.iBr.iX,rect.iTl.iY);
+		    iGcPtr->DrawLine(start,rect.iBr);
+            }
+//->
+//		iGridLabelImg->DrawTopLeftLabelL(iGcPtr,rect);
+		iGridLabelImg->DrawTopLeftLabelL(iGcPtr, rect, iGridLay->GridColors().iBackground);
+//->
+		}
+	}
+
+void CGridImg::DrawTopGridLabelsL(TInt aStartCol,TInt aEndCol,TRefPoint aXRef) const
+// Draws all the top grid labels within the specified column range
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	if (!iGridLay->IsTopLabels() || iGridLabelImg==NULL)
+		return;
+	TInt separatorCorr=(iGridLay->IsGridLabelSeparators()) ? 1 : 0;
+	TRect rect;
+	rect.iTl.iY=iGridRect.iTl.iY;
+	rect.iBr.iY=iTitlePoint.iY-separatorCorr;
+	rect.iTl.iX=((aXRef==ETitleRef) ? iGridLay->TitleColumnToXVal(aStartCol) :
+		iGridLay->ColumnToXVal(aStartCol));
+	rect.iBr.iX=rect.iTl.iX-separatorCorr;
+	TBool doGrayFill=EFalse;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (aEndCol>=visRange.iTo.iCol)
+		{
+		aEndCol=visRange.iTo.iCol;
+		if (aEndCol>iGridLay->GridRange().iTo.iCol)
+			{
+			aEndCol--;
+			doGrayFill=ETrue;
+			}
+		}
+	iGcPtr->SetClippingRect(TRect(iTitlePoint.iX,iGridRect.iTl.iY,iGridRect.iBr.iX,iTitlePoint.iY));
+	if (iGridLay->IsGridLabelSeparators())
+		{
+		for (TInt ii=aStartCol;ii<=aEndCol;ii++)
+			{
+			rect.iBr.iX+=iGridLay->ColumnWidthInPixels(ii);
+			iGridLabelImg->DrawColLabelL(iGcPtr,ii,rect);
+			rect.iTl.iX=rect.iBr.iX;
+//->
+		    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+			iGcPtr->DrawLine(rect.iTl,rect.iBr);
+			rect.iTl.iX++;
+			}
+		}
+	else
+		{
+		for (TInt ii=aStartCol;ii<=aEndCol;ii++)
+			{
+			rect.iBr.iX+=iGridLay->ColumnWidthInPixels(ii);
+			iGridLabelImg->DrawColLabelL(iGcPtr,ii,rect);
+			rect.iTl.iX=rect.iBr.iX;
+			}
+		}
+	if (doGrayFill)	
+		{
+		TGridUtils::FillRect(iGcPtr,iGridLay->iGridEdgeColor,
+			TRect(rect.iTl.iX,rect.iTl.iY,iGridRect.iBr.iX,rect.iBr.iY+separatorCorr));
+		}
+	if (iGridLay->IsGridLabelSeparators())
+		{
+	    rect.iBr.iX++;
+//->
+	    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//	    iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+	    iGcPtr->DrawLine(TPoint(iTitlePoint.iX,rect.iBr.iY),rect.iBr);
+//->
+        }
+	iGcPtr->CancelClippingRect();
+	}
+
+void CGridImg::DrawSideGridLabelsL(TInt aStartRow,TInt aEndRow,TRefPoint aYRef) const
+	{
+	//
+	// Draw all the side grid labels within the specified row range
+	//
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	if (!iGridLay->IsSideLabels() || iGridLabelImg==NULL)
+		return;
+	TInt separatorCorr=(iGridLay->IsGridLabelSeparators()) ? 1 : 0;
+	TRect rect;
+	rect.iTl.iX=iGridRect.iTl.iX;
+	rect.iBr.iX=iTitlePoint.iX-separatorCorr;
+	rect.iTl.iY=((aYRef==ETitleRef) ? iGridLay->TitleRowToYVal(aStartRow) :
+		iGridLay->RowToYVal(aStartRow));
+	TInt startY=rect.iTl.iY;
+	rect.iBr.iY=rect.iTl.iY-separatorCorr;
+	TBool doGrayFill=EFalse;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (aEndRow>=visRange.iTo.iRow)
+		{
+		aEndRow=visRange.iTo.iRow;
+		TInt reqRow;
+		if (iGridLay->RequestRow(aEndRow,reqRow))
+			{
+			if (aEndRow!=reqRow)
+				{
+				aEndRow--;
+				doGrayFill=ETrue;
+				}
+			}
+		else
+			{
+			aEndRow=aStartRow-1;	// guarantees not to go into loop
+			doGrayFill=ETrue;
+			}
+		}
+	iGcPtr->SetClippingRect(TRect(iGridRect.iTl.iX,iTitlePoint.iY,iTitlePoint.iX,iGridRect.iBr.iY));
+	if (iGridLay->IsGridLabelSeparators())
+		{
+		for (TInt ii=aStartRow;ii<=aEndRow;ii++)
+			{
+			rect.iBr.iY+=iGridLay->RowHeightInPixels(ii);
+			iGridLabelImg->DrawRowLabelL(iGcPtr,ii,rect);
+			if (ii==iCursorPos.iRow)
+				iGridLabelImg->DrawRowCursorL(iGcPtr,rect);
+			rect.iTl.iY=rect.iBr.iY;
+//->
+		    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+			iGcPtr->DrawLine(rect.iTl,rect.iBr);
+			rect.iTl.iY++;
+			}
+		}
+	else
+		{
+		for (TInt ii=aStartRow;ii<=aEndRow;ii++)
+			{
+			rect.iBr.iY+=iGridLay->RowHeightInPixels(ii);
+			iGridLabelImg->DrawRowLabelL(iGcPtr,ii,rect);
+			if (ii==iCursorPos.iRow)
+				iGridLabelImg->DrawRowCursorL(iGcPtr,rect);
+			rect.iTl.iY=rect.iBr.iY;
+			}
+		}
+	if (doGrayFill)
+		{
+		TGridUtils::FillRect(iGcPtr,iGridLay->iGridEdgeColor,
+			TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX+separatorCorr,iGridRect.iBr.iY));
+		}
+	if (iGridLay->IsGridLabelSeparators())
+		{
+		rect.iBr.iY++;
+//->
+	    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//		iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+		iGcPtr->DrawLine(TPoint(rect.iBr.iX,startY),rect.iBr);
+		}
+	iGcPtr->CancelClippingRect();
+	}
+
+void CGridImg::DrawSideGridLabelIfOnScreenL(TInt aRow) const
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	TBool doDraw=EFalse;
+	TRefPoint refPoint=EMainRef;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (aRow>=visRange.iFrom.iRow && aRow<=visRange.iTo.iRow)
+		doDraw=ETrue;
+	else if (iGridLay->IsHorizontalTitleLine())
+		{
+		TRangeRef titleRange=iGridLay->TitleRange();
+		if (aRow>=titleRange.iFrom.iRow && aRow<titleRange.iTo.iRow)
+			{
+			doDraw=ETrue;
+			refPoint=ETitleRef;
+			}
+		}
+	if (doDraw)
+		DrawSideGridLabelsL(aRow,aRow,refPoint);
+	}
+
+EXPORT_C void CGridImg::DrawTitleLines() const
+/** Draws the title lines. */
+	{
+#if !defined(__WINC__)
+	((CGridImg*)this)->CreateGc(iGc);
+	DrawVerticalTitleLine();
+	DrawHorizontalTitleLine();
+	((CGridImg*)this)->DeleteGc();
+#endif
+	}
+
+EXPORT_C void CGridImg::ClearTitleLineRegionL(const TPoint& aCrossPoint) const
+/** Clears the region where the the title lines are.
+
+@param aCrossPoint Any point within the title region. */
+	{
+	TRect rect(Max(aCrossPoint.iX-1,iTitlePoint.iX),iTitlePoint.iY,
+		aCrossPoint.iX,iGridRect.iBr.iY);
+	BeginRedrawAndDrawL(rect);
+	rect.SetRect(iTitlePoint.iX,Max(aCrossPoint.iY-1,iTitlePoint.iY),
+		iGridRect.iBr.iX,aCrossPoint.iY);
+	BeginRedrawAndDrawL(rect);
+	}
+
+void CGridImg::DrawVerticalTitleLine() const
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	if (iMainPoint.iX>iTitlePoint.iX)
+		{
+//->
+	    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//		iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+		iGcPtr->DrawLine(TPoint(iMainPoint.iX-1,iTitlePoint.iY-1),
+			TPoint(iMainPoint.iX-1,iGridRect.iBr.iY));
+		}
+	}
+
+void CGridImg::DrawHorizontalTitleLine() const
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	if (iMainPoint.iY>iTitlePoint.iY)
+		{
+//->
+	    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//		iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+		iGcPtr->DrawLine(TPoint(iTitlePoint.iX-1,iMainPoint.iY-1),
+			TPoint(iGridRect.iBr.iX,iMainPoint.iY-1));
+		}
+	}
+
+void CGridImg::DrawAllGridLinesAndCellsL() const
+	// Draws all the grid lines and cells
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (iGridLay->IsEncroachingCellBorders())
+		{
+		if (iGridLay->IsVisibleToRowFullyVisible())
+			visRange.iTo.iRow++;
+		if (iGridLay->IsVisibleToColumnFullyVisible())
+			visRange.iTo.iCol++;
+		}
+	TRect clippingRect;
+	TRangeRef titleRange=iGridLay->TitleRange();
+	TBool isHorizontalTitleLine=iGridLay->IsHorizontalTitleLine();
+	TBool isVerticalTitleLine=iGridLay->IsVerticalTitleLine();
+	TRangeRef range;
+	if (isHorizontalTitleLine && isVerticalTitleLine)
+		{
+		clippingRect.SetRect(iTitlePoint,iMainPoint);
+		DrawGridLinesAndCellsInRangeL(titleRange,clippingRect,ETitleRef,ETitleRef);
+		}
+	if (isHorizontalTitleLine)
+		{
+		clippingRect.SetRect(iMainPoint.iX,iTitlePoint.iY,iGridRect.iBr.iX,iMainPoint.iY);
+		range.SetRange(titleRange.iFrom.iRow,visRange.iFrom.iCol,
+			titleRange.iTo.iRow,visRange.iTo.iCol);
+		DrawGridLinesAndCellsInRangeL(range,clippingRect,EMainRef,ETitleRef);
+		}
+	if (isVerticalTitleLine)
+		{
+		clippingRect.SetRect(iTitlePoint.iX,iMainPoint.iY,iMainPoint.iX,iGridRect.iBr.iY);
+		range.SetRange(visRange.iFrom.iRow,titleRange.iFrom.iCol,
+			visRange.iTo.iRow,titleRange.iTo.iCol);
+		DrawGridLinesAndCellsInRangeL(range,clippingRect,ETitleRef,EMainRef);
+		}
+	clippingRect.SetRect(iMainPoint,iGridRect.iBr);
+	DrawGridLinesAndCellsInRangeL(visRange,clippingRect);
+	}
+
+void CGridImg::DrawGridLinesAndCellsInRangeL(const TRangeRef& aRange,const TRect& aClipRect,
+	TRefPoint aXRef,TRefPoint aYRef) const
+// Draws the grid cells for the given cell range
+	{
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	TRect rangeRect;
+	if (aYRef==ETitleRef)
+		{
+		rangeRect.iTl.iY=iGridLay->TitleRowToYVal(aRange.iFrom.iRow);
+		rangeRect.iBr.iY=iMainPoint.iY-1;
+		}
+	else
+		{
+		rangeRect.iTl.iY=iGridLay->RowToYVal(aRange.iFrom.iRow);
+		rangeRect.iBr.iY=iGridRect.iBr.iY;
+		}
+	if (aXRef==ETitleRef)
+		{
+		rangeRect.iTl.iX=iGridLay->TitleColumnToXVal(aRange.iFrom.iCol);
+		rangeRect.iBr.iX=iMainPoint.iX-1;
+		}
+	else
+		{
+		rangeRect.iTl.iX=iGridLay->ColumnToXVal(aRange.iFrom.iCol);
+		rangeRect.iBr.iX=iGridRect.iBr.iX;
+		}
+	
+	TInt endCol=aRange.iTo.iCol;
+	TBool doRightFill=EFalse;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (endCol>=visRange.iTo.iCol)
+		{
+		endCol=visRange.iTo.iCol;
+		if (endCol>iGridLay->GridRange().iTo.iCol)
+			{
+			endCol--;
+			doRightFill=ETrue;
+			}
+		}
+	TInt endRow=aRange.iTo.iRow;
+	TBool doBottomFill=EFalse;
+	if (endRow>=visRange.iTo.iRow)
+		{
+		endRow=visRange.iTo.iRow;
+		TInt reqRow;
+		if (iGridLay->RequestRow(endRow,reqRow))
+			{
+			if (endRow!=reqRow)
+				{
+				endRow--;
+				doBottomFill=ETrue;
+				}
+			}
+		else
+			{
+			endRow=aRange.iFrom.iRow-1;
+			doBottomFill=ETrue;
+			}
+		}
+//->
+	iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : iGridLay->GridColors().iLines);		// To workaround a problem when printing gray lines
+//	iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : KRgbGridLines);		// To workaround a problem when printing gray lines
+//->
+	TRect rect;
+	rect.iTl.iX=rect.iBr.iX=rangeRect.iTl.iX-1;
+	if (iGridLay->IsVerticalGridLines())
+		{
+		rect.iTl.iY=rangeRect.iTl.iY;
+		rect.iBr.iY=(doBottomFill) ? iGridLay->RowToYVal(endRow+1) : rangeRect.iBr.iY;
+		}
+	TInt startCol=aRange.iFrom.iCol;
+	TInt pageCol=KMaxTInt;
+	if (!iGridLay->IsPageBreakLinesHidden())
+		iGridLay->FindNextColumnPageBreak(startCol,pageCol);
+	iGcPtr->SetClippingRect(aClipRect);
+	for (;startCol<=endCol;startCol++)
+		{
+		rect.Move(iGridLay->ColumnWidthInPixels(startCol),0);
+		if (startCol==pageCol)
+			{
+			TPoint start(rect.iTl.iX,iTitlePoint.iY);
+			TPoint end(rect.iBr.iX,rangeRect.iBr.iY);
+//->
+			iGcPtr->SetPenColor(iGridLay->GridColors().iBackground);
+//			iGcPtr->SetPenColor(KRgbGridBackground);
+//->
+			iGcPtr->DrawLine(start,end);
+//->
+		    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+			iGcPtr->SetPenStyle((iGridLay->IsHardColumnPageBreak(pageCol+1))
+				? CGraphicsContext::EDotDashPen : CGraphicsContext::EDashedPen);
+			iGcPtr->DrawLine(start,end);
+			iGcPtr->SetPenStyle(CGraphicsContext::ESolidPen);
+//->
+			iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : iGridLay->GridColors().iLines);
+//			iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : KRgbGridLines);
+//->
+			iGridLay->FindNextColumnPageBreak(startCol+1,pageCol);
+			}
+		else
+			iGcPtr->DrawLine(rect.iTl,rect.iBr);
+		}
+	if (doRightFill)
+		{
+		TGridUtils::FillRect(iGcPtr,iGridLay->iGridEdgeColor,
+			TRect(rect.iTl.iX+1,rangeRect.iTl.iY,iGridRect.iBr.iX,rangeRect.iBr.iY));
+		}
+
+	rect.iTl.iY=rect.iBr.iY=rangeRect.iTl.iY-1;
+	if (iGridLay->IsHorizontalGridLines())
+		{
+		rect.iTl.iX=rangeRect.iTl.iX;
+		rect.iBr.iX=(doRightFill) ? iGridLay->ColumnToXVal(endCol+1) : rangeRect.iBr.iX;
+		}
+	TInt startRow=aRange.iFrom.iRow;
+	TInt pageRow=KMaxTInt;
+	if (!iGridLay->IsPageBreakLinesHidden())
+		iGridLay->FindNextRowPageBreak(startRow,pageRow);
+	for (;startRow<=endRow;startRow++)
+		{
+		rect.Move(0,iGridLay->RowHeightInPixels(startRow));
+		if (startRow==pageRow)
+			{
+			TPoint start(iTitlePoint.iX,rect.iTl.iY);
+			TPoint end(rangeRect.iBr.iX,rect.iBr.iY);
+//->
+			iGcPtr->SetPenColor(iGridLay->GridColors().iBackground);
+//			iGcPtr->SetPenColor(KRgbGridBackground);
+//->
+			iGcPtr->DrawLine(start,end);
+//->
+		    iGcPtr->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			iGcPtr->SetPenColor(KRgbGridLabelSeparators);
+//->
+			iGcPtr->SetPenStyle((iGridLay->IsHardRowPageBreak(pageRow+1))
+				? CGraphicsContext::EDotDashPen : CGraphicsContext::EDashedPen);
+			iGcPtr->DrawLine(start,end);
+			iGcPtr->SetPenStyle(CGraphicsContext::ESolidPen);
+//->
+			iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : iGridLay->GridColors().iLines);
+//			iGcPtr->SetPenColor((iGcPtr->Device()->DisplayMode()==EGray2) ? KRgbBlack : KRgbGridLines);
+//->
+			iGridLay->FindNextRowPageBreak(startRow+1,pageRow);
+			}
+		else
+			iGcPtr->DrawLine(rect.iTl,rect.iBr);
+		}
+	if (doBottomFill)
+		{
+		TGridUtils::FillRect(iGcPtr,iGridLay->iGridEdgeColor,
+			TRect(rangeRect.iTl.iX,rect.iTl.iY+1,rangeRect.iBr.iX,iGridRect.iBr.iY));
+		}
+	iGcPtr->CancelClippingRect();
+	DrawCellsToGcL(iGcPtr,aRange,aClipRect,rangeRect.iTl);
+	}
+
+void CGridImg::DrawCellsToGcL(CGraphicsContext* aGc,const TRangeRef& aRange,const TRect& aClipRect,
+	const TPoint& aStartPoint,TInt aScaleFactor) const
+	{
+	TCellRef startCell=aRange.iFrom;
+	if (!iGridLay->LimitCell(startCell))
+		return;	// Nothing to draw
+	TCellRef endCell = aRange.iTo;
+	iGridLay->LimitCell(endCell);
+	TRect rect;
+	TInt yPos=aStartPoint.iY;
+	rect.iTl.iY = yPos*EScaleOneToOne/aScaleFactor;
+	TCellRef cell = aRange.iFrom;
+	TInt horzLineCorr=(iGridLay->IsHorizontalGridLines()) ? 1 : 0;
+	TInt vertLineCorr=(iGridLay->IsVerticalGridLines()) ? 1 : 0;
+	iGridCellImg->iGridLineFlags=0;
+	if (horzLineCorr)
+		iGridCellImg->iGridLineFlags|=CGridCellImg::EIsHorizontalGridLines;
+	if (vertLineCorr)
+		iGridCellImg->iGridLineFlags|=CGridCellImg::EIsVerticalGridLines;
+	for (;cell.iRow<=endCell.iRow;cell.iRow++)
+		{
+		TInt xPos=aStartPoint.iX;
+		rect.iTl.iX=xPos*EScaleOneToOne/aScaleFactor;
+		yPos+=iGridLay->RowHeightInPixels(cell.iRow);
+		rect.iBr.iY = yPos*EScaleOneToOne/aScaleFactor-vertLineCorr;
+		cell.iCol=aRange.iFrom.iCol;
+		if (iGridLay->IsColumnBursting())
+			{
+			if (cell.iCol<=endCell.iCol)
+				{
+				xPos+=iGridLay->ColumnWidthInPixels(cell.iCol);
+				rect.iBr.iX = xPos*EScaleOneToOne/aScaleFactor-horzLineCorr;
+				TCellRef burstCell=cell;
+				TInt burstLeft=CalcBurstLeftL(burstCell,aScaleFactor);
+				DrawBurstingCellL(aGc,cell,rect,aClipRect,aScaleFactor,burstLeft,burstCell);
+				burstLeft+=rect.Width()+horzLineCorr;
+				rect.iTl.iX=rect.iBr.iX+horzLineCorr;
+				for (cell.iCol++;cell.iCol<=endCell.iCol;cell.iCol++)
+					{
+					xPos+=iGridLay->ColumnWidthInPixels(cell.iCol);
+					rect.iBr.iX = xPos*EScaleOneToOne/aScaleFactor-horzLineCorr;
+					if (iGridCellImg->DoesCellContainDataL(cell))
+						{
+						burstLeft=0;
+						burstCell.iCol=cell.iCol;
+						}
+					DrawBurstingCellL(aGc,cell,rect,aClipRect,aScaleFactor,burstLeft,burstCell);
+					burstLeft+=rect.Width()+horzLineCorr;
+					rect.iTl.iX=rect.iBr.iX+horzLineCorr;
+					}
+				}
+			}
+		else
+			{
+			for (;cell.iCol<=endCell.iCol;cell.iCol++)
+				{
+				xPos+=iGridLay->ColumnWidthInPixels(cell.iCol);
+				rect.iBr.iX = xPos*EScaleOneToOne/aScaleFactor-horzLineCorr;
+				iGridCellImg->DrawL(aGc,cell,rect,aClipRect);
+				rect.iTl.iX=rect.iBr.iX+horzLineCorr;
+				}
+			}
+		rect.iTl.iY=rect.iBr.iY+vertLineCorr;
+		}
+	ResetGcToDefault(aGc);
+	}
+
+void CGridImg::DrawBurstingCellL(CGraphicsContext* aGc,const TCellRef& aCell,const TRect& aRect,const TRect& aClipRect,
+	TInt aScaleFactor,TInt aBurstLeft,const TCellRef& aBurstCell) const
+	{
+	TInt burstDataWidth=iGridCellImg->DataWidthInPixelsL(aBurstCell);
+	if (burstDataWidth<=aBurstLeft)
+		iGridCellImg->DrawL(aGc,aCell,aRect,aClipRect);
+	else
+		{
+		TInt excessRight=burstDataWidth-aBurstLeft-aRect.Width();
+		iGridCellImg->SetBurstingData(aCell.iCol-aBurstCell.iCol,aBurstLeft,
+			CalcBurstRightL(aCell,excessRight,aScaleFactor));
+		iGridCellImg->DrawL(aGc,aCell,aRect,aClipRect);
+		iGridCellImg->SetBurstingData();
+		}
+	}
+
+TInt CGridImg::CalcBurstLeftL(TCellRef& aBurstCell,TInt aScaleFactor) const
+	{
+	enum { EMaxNumberChecked = 20 };
+	const TInt limit=Max(aBurstCell.iCol-EMaxNumberChecked,iGridLay->GridRange().iFrom.iCol);
+	TInt burstLeft=0;
+	while (aBurstCell.iCol>limit && !iGridCellImg->DoesCellContainDataL(aBurstCell))
+		{
+		burstLeft+=iGridLay->ColumnWidthInPixels(--aBurstCell.iCol);
+		}
+	return burstLeft*EScaleOneToOne/aScaleFactor;
+	}
+
+TInt CGridImg::CalcBurstRightL(const TCellRef& aCell,TInt aExcessRight,TInt aScaleFactor) const
+	{
+	TInt limit=iGridLay->GridRange().iTo.iCol;
+	TInt burstRight=0;
+	TInt scaledBurstRight=0;
+	for (TCellRef forwardCell(aCell.iRow,aCell.iCol+1);forwardCell.iCol<=limit;forwardCell.iCol++)
+		{
+		TInt width=iGridLay->ColumnWidthInPixels(forwardCell.iCol);
+		if (iGridCellImg->DoesCellContainDataL(forwardCell) || scaledBurstRight>aExcessRight)
+			{
+			break;
+			}
+		burstRight+=width;
+		scaledBurstRight=burstRight*EScaleOneToOne/aScaleFactor;
+		}
+	return scaledBurstRight;
+	}
+
+EXPORT_C void CGridImg::DrawCellL(const TCellRef &aCell) const
+/** Draws the content of the specified cell.
+
+@param aCell The cell to be drawn. */
+	{
+	TRect rect=PartialCellRectL(aCell,MainRect());
+	TRect clipRect;
+	TBool isHorizontalTitleLine=iGridLay->IsHorizontalTitleLine();
+	TBool isVerticalTitleLine=iGridLay->IsVerticalTitleLine();
+	if (isHorizontalTitleLine && isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint,iMainPoint);
+		rect.BoundingRect(PartialCellRectL(aCell,clipRect,ETitleRef,ETitleRef));
+		}
+	if (isHorizontalTitleLine)
+		{
+		clipRect.SetRect(iMainPoint.iX,iTitlePoint.iY,iGridRect.iBr.iX,iMainPoint.iY);
+		rect.BoundingRect(PartialCellRectL(aCell,clipRect,EMainRef,ETitleRef));
+		}
+	if (isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint.iX,iMainPoint.iY,iMainPoint.iX,iGridRect.iBr.iY);
+		rect.BoundingRect(PartialCellRectL(aCell,clipRect,ETitleRef,EMainRef));
+		}
+	BeginRedrawAndDrawL(rect);
+	}
+
+TRect CGridImg::PartialCellRectL(const TCellRef& aCell,const TRect& aClipRect,
+	TRefPoint aXRef,TRefPoint aYRef) const
+	{
+	TRect rect;
+	rect.iTl=RelativeCellToPoint(aCell,aXRef,aYRef);
+	rect.iBr=rect.iTl+iGridLay->CellToPoint(aCell,aCell+TCellRef(1,1));
+	if (iGridLay->IsColumnBursting())
+		{
+		TInt limit=iGridLay->GridRange().iTo.iCol;
+		for (TCellRef forwardCell(aCell.iRow,aCell.iCol+1);rect.iBr.iX<iGridRect.iBr.iX && forwardCell.iCol<=limit;forwardCell.iCol++)
+			{
+			if (iGridCellImg->DoesCellContainDataL(forwardCell))
+				break;
+			rect.iBr.iX+=iGridLay->ColumnWidthInPixels(forwardCell.iCol);
+			}
+		}
+	rect.iTl-=TPoint(2,2);	//For cell borders
+	rect.Intersection(aClipRect);
+	return rect;
+	}
+
+EXPORT_C void CGridImg::DrawRangeL(const TRangeRef& aRange) const
+/** Draws the rectangle corresponding to the specified range.
+
+@param aRange The range to be drawn. */
+	{
+	TRect rect=PartialRangeRect(aRange,MainRect());
+	TRect clipRect;
+	TBool isHorizontalTitleLine=iGridLay->IsHorizontalTitleLine();
+	TBool isVerticalTitleLine=iGridLay->IsVerticalTitleLine();
+	if (isHorizontalTitleLine && isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint,iMainPoint);
+		rect.BoundingRect(PartialRangeRect(aRange,clipRect,ETitleRef,ETitleRef));
+		}
+	if (isHorizontalTitleLine)
+		{
+		clipRect.SetRect(iMainPoint.iX,iTitlePoint.iY,iGridRect.iBr.iX,iMainPoint.iY);
+		rect.BoundingRect(PartialRangeRect(aRange,clipRect,EMainRef,ETitleRef));
+		}
+	if (isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint.iX,iMainPoint.iY,iMainPoint.iX,iGridRect.iBr.iY);
+		rect.BoundingRect(PartialRangeRect(aRange,clipRect,ETitleRef,EMainRef));
+		}
+	BeginRedrawAndDrawL(rect);
+	}
+
+TRect CGridImg::PartialRangeRect(const TRangeRef& aRange,const TRect& aClipRect,
+	TRefPoint aXRef,TRefPoint aYRef) const
+	{
+	TRect rect;
+	rect.iTl=RelativeCellToPoint(aRange.iFrom,aXRef,aYRef);
+	rect.iBr=rect.iTl+iGridLay->CellToPoint(aRange.iFrom,aRange.iTo+TCellRef(1,1));
+	if (iGridLay->IsColumnBursting())
+		rect.iBr.iX=iGridRect.iBr.iX;
+	rect.iTl-=TPoint(2,2);	//For cell borders
+	rect.Intersection(aClipRect);
+	return rect;
+	}
+
+EXPORT_C void CGridImg::DrawSelectedL() const
+/** Draws the currently selected region. */
+	{
+	TInt count=iSelected->Count();
+	if (count==0)
+		DrawCellL(iCursorPos);
+	else if (count==1)
+		DrawRangeL((*iSelected)[0]);
+	else
+		BeginRedrawAndDrawL();
+	}
+	
+#if defined(__WINC__)
+void CGridImg::HighlightMinRegionL(const TRegion& /*aOldRegion*/,const TRegion& /*aNewRegion*/)
+	{}
+#else
+
+void CGridImg::HighlightMinRegionL(const TRegion& aOldRegion,const TRegion& aNewRegion)
+// 
+// Highlights the minimum necessary region to get from the old to the new region
+//
+	{
+	RRegion unionRegion;
+	unionRegion.Copy(aOldRegion);
+	unionRegion.Union(aNewRegion);
+	RRegion tempRegion;
+	tempRegion.Copy(aOldRegion);
+	tempRegion.Intersect(aNewRegion);
+	unionRegion.SubRegion(tempRegion);
+	tempRegion.Close();
+	unionRegion.Tidy();
+	if (unionRegion.CheckError())
+		{
+		unionRegion.Close();
+		User::Leave(KErrNoMemory);
+		}
+	CreateGc(iGc);
+	HighlightRegion(unionRegion);
+	DeleteGc();
+	unionRegion.Close();
+	}
+#endif
+
+void CGridImg::HighlightRegion(const TRegion &aRegion) const
+	{
+	//
+	// Fills each of the rectangles in the passed region one by one
+	//
+	__ASSERT_DEBUG(iGcPtr!=NULL,Panic(EGridImgInvalidGC));
+	TInt count=aRegion.Count();
+	if (count)
+		{
+		iGcPtr->SetDrawMode(CGraphicsContext::EDrawModeNOTSCREEN);
+		iGcPtr->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		for (TInt ii=0;ii<count;ii++)
+			iGcPtr->DrawRect(aRegion[ii]);
+		iGcPtr->SetBrushStyle(CGraphicsContext::ENullBrush);
+		iGcPtr->SetDrawMode(CGraphicsContext::EDrawModePEN);
+		}
+	}
+
+TPoint CGridImg::RelativeCellToPoint(const TCellRef& aCell,
+	TRefPoint aXRef,TRefPoint aYRef) const
+	{
+	TPoint ret;
+	ret.iX=(aXRef==ETitleRef) ? iGridLay->TitleColumnToXVal(aCell.iCol) :
+		iGridLay->ColumnToXVal(aCell.iCol);
+	ret.iY=(aYRef==ETitleRef) ? iGridLay->TitleRowToYVal(aCell.iRow) :
+		iGridLay->RowToYVal(aCell.iRow);
+	return ret;
+	}
+
+TCellRef CGridImg::RelativePointToCell(const TPoint& aPoint,
+	TRefPoint aXRef,TRefPoint aYRef) const
+	{
+	TCellRef ret;
+	ret.iCol=(aXRef==ETitleRef) ? iGridLay->XValToTitleColumn(aPoint.iX) :
+		iGridLay->XValToColumn(aPoint.iX);
+	ret.iRow=(aYRef==ETitleRef) ? iGridLay->YValToTitleRow(aPoint.iY) :
+		iGridLay->YValToRow(aPoint.iY);
+	return ret;
+	}
+
+void CGridImg::AppendPartialHighlightRegionL(TRegion& aRegion,const TRect& aClipRect,
+	TRefPoint aXRef,TRefPoint aYRef) const
+//
+// returns ETrue if there's an error in the region manipulation
+	{
+	TInt count=iSelected->Count();
+	if (!count)
+		{
+		if (iGridLay->IsCursorVisible())
+			{
+            if (iGridLay->IsCellOutOfGridRange(iCursorPos))
+                return;
+			TRect cursor(RelativeCellToPoint(iCursorPos,aXRef,aYRef),TSize(0,0));
+			cursor.iBr.iX+=iGridLay->ColumnWidthInPixels(iCursorPos.iCol);
+			cursor.iBr.iY+=iGridLay->RowHeightInPixels(iCursorPos.iRow);
+		
+			TRegionFix<4> region;
+			region.AddRect(TRect(cursor.iTl.iX-2,cursor.iTl.iY-2,cursor.iBr.iX+1,cursor.iTl.iY+1));
+			region.AddRect(TRect(cursor.iTl.iX-2,cursor.iBr.iY-2,cursor.iBr.iX+1,cursor.iBr.iY+1));
+			region.AddRect(TRect(cursor.iTl.iX-2,cursor.iTl.iY+1,cursor.iTl.iX+1,cursor.iBr.iY-2));
+			region.AddRect(TRect(cursor.iBr.iX-2,cursor.iTl.iY+1,cursor.iBr.iX+1,cursor.iBr.iY-2));
+			region.ClipRect(aClipRect);
+			aRegion.Union(region);
+			}
+		}
+    else if (iGridLay->IsHighlightVisible())
+		{
+		for (TInt ii=0;ii<count;ii++)
+			{
+			TRangeRef range=(*iSelected)[ii];
+			if (!iGridLay->LimitCell(range.iFrom))
+				continue;
+			iGridLay->LimitCell(range.iTo);
+			TRect rect;
+			rect.iTl=RelativeCellToPoint(range.iFrom,aXRef,aYRef);
+			rect.iBr=RelativeCellToPoint(range.iTo+TCellRef(1,1),aXRef,aYRef);
+			rect.Resize(-1,-1);
+			rect.Shrink(1,1);
+			rect.Intersection(aClipRect);
+			if (iSelected->IsColSelected(range.iFrom.iCol,ii) && 
+				(iTitlePoint.iY==iMainPoint.iY || aYRef==ETitleRef) &&
+				!iGridLay->IsColumnSelectionDisabled())
+				{
+				rect.iTl.iY=Min(rect.iTl.iY,iGridRect.iTl.iY+1);
+				}
+			if (iSelected->IsRowSelected(range.iFrom.iRow,ii) &&
+				(iTitlePoint.iX==iMainPoint.iX || aXRef==ETitleRef) &&
+				!iGridLay->IsRowSelectionDisabled())
+				{
+				rect.iTl.iX=Min(rect.iTl.iX,iGridRect.iTl.iX+1);
+				}
+			aRegion.AddRect(rect);
+			}
+		if (iGridLay->IsCursorVisible())
+			{
+			if (!iGridLay->IsCellOutOfGridRange(iAnchorPos))
+				{
+				TRect anchorRect=(TRect(RelativeCellToPoint(iAnchorPos,aXRef,aYRef),TSize(0,0)));
+				anchorRect.iBr.iX+=iGridLay->ColumnWidthInPixels(iAnchorPos.iCol);
+				anchorRect.iBr.iY+=iGridLay->RowHeightInPixels(iAnchorPos.iRow);
+				anchorRect.Resize(-1,-1);
+				anchorRect.Shrink(2,2);
+				anchorRect.Intersection(aClipRect);
+				aRegion.SubRect(anchorRect);
+				}
+			}
+		}
+	if (aRegion.CheckError())
+		User::Leave(KErrNoMemory);
+	}
+
+void CGridImg::AppendTotalHighlightRegionL(TRegion &aRegion) const
+	{
+	//
+	// Creates the total selected region by summing all the rectangles
+	// of the cursor or the highlighted regions (including the anchor)
+	//
+	TRect clipRect=MainRect();
+	AppendPartialHighlightRegionL(aRegion,clipRect);
+	TBool isHorizontalTitleLine=iGridLay->IsHorizontalTitleLine();
+	TBool isVerticalTitleLine=iGridLay->IsVerticalTitleLine();
+	if (isHorizontalTitleLine && isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint,iMainPoint-TPoint(1,1));
+		if (clipRect.IsNormalized())
+			AppendPartialHighlightRegionL(aRegion,clipRect,ETitleRef,ETitleRef);
+		}
+	if (isHorizontalTitleLine)
+		{
+		clipRect.SetRect(iMainPoint.iX,iTitlePoint.iY,iGridRect.iBr.iX,iMainPoint.iY-1);
+		if (clipRect.IsNormalized())
+			AppendPartialHighlightRegionL(aRegion,clipRect,EMainRef,ETitleRef);
+		}
+	if (isVerticalTitleLine)
+		{
+		clipRect.SetRect(iTitlePoint.iX,iMainPoint.iY,iMainPoint.iX-1,iGridRect.iBr.iY);
+		if (clipRect.IsNormalized())
+			AppendPartialHighlightRegionL(aRegion,clipRect,ETitleRef,EMainRef);
+		}
+	}
+
+void CGridImg::RemoveRowLabelFromRegionL(TInt aRow,TRegion& aRegion) const
+//
+// Returns ETrue if error
+	{
+	TInt tlY=iGridLay->VisibleRowToYVal(aRow);
+	if (tlY<0)
+		return;	// Not on screen
+	TRect rect(iGridRect.iTl.iX,tlY,iTitlePoint.iX,tlY+iGridLay->RowHeightInPixels(aRow));
+	aRegion.SubRect(rect);
+	if (aRegion.CheckError())
+		User::Leave(KErrNoMemory);
+	}
+
+void CGridImg::CleanupGc(TAny* aObject)
+	{
+	((CGridImg*)aObject)->DeleteGc();
+	}
+
+EXPORT_C void CGridImg::DrawL(CGraphicsContext* aGc) const
+/** Draws the entire grid and its contents.
+
+@param aGc The graphics context to be used for drawing. */
+	{
+	((CGridImg*)this)->CreateGc(aGc);
+	iGcPtr->SetClippingRect(iGridRect);	//Needed because of border round grid
+	ResetGcToDefault(iGcPtr);
+	CleanupStack::PushL(TCleanupItem(CleanupGc,(CGridImg*)this));
+	DrawAllGridLabelsL();
+	iGcPtr->Reset();
+	if (iGridLay->IsAutoClearGridCells())
+//->
+		TGridUtils::FillRect(iGcPtr, iGridLay->GridColors().iBackground, TRect(iTitlePoint,iGridRect.iBr));
+//		TGridUtils::FillRect(iGcPtr,KRgbGridBackground,TRect(iTitlePoint,iGridRect.iBr));
+//->
+	DrawAllGridLinesAndCellsL();	//Handles its own clipping
+	RRegion region;
+	CleanupClose<RRegion>::PushL(region);
+	AppendTotalHighlightRegionL(region);
+	CleanupStack::Pop(2);	// region + gc cleanup
+	HighlightRegion(region);
+	region.Close();
+	DrawVerticalTitleLine();
+	DrawHorizontalTitleLine();
+	((CGridImg*)this)->DeleteGc();
+	CONST_CAST(CGridImg*,this)->DrawResizingDragHiglights(iGridRect);
+	}
+
+#if !defined(__WINC__)
+LOCAL_C void EndRedraw(TAny* aObject)
+	{
+	((RWindow*)aObject)->EndRedraw();
+	}
+#endif
+
+void CGridImg::BeginRedrawAndDrawL() const
+	{
+#if !defined(__WINC__)
+	iWin->Invalidate();
+	iWin->BeginRedraw();
+	CleanupStack::PushL(TCleanupItem(EndRedraw,iWin));
+	DrawL(iGc);
+	CleanupStack::PopAndDestroy();
+#endif
+	}
+
+EXPORT_C void CGridImg::DrawL(CGraphicsContext* aGc,const TRect& aRect) const
+/** Draws the grid and its contents that are visible within the specified 
+rectangle.
+
+@param aGc The graphics context to be used for drawing.
+@param aRect Drawing of the grid is restricted to this rectangle. */
+	{
+	if (aRect.Contains(iGridRect.iTl) && aRect.Contains(iGridRect.iBr))
+		{
+		DrawL(aGc);
+		return;
+		}
+	((CGridImg*)this)->CreateGc(aGc);
+	ResetGcToDefault(iGcPtr);
+
+	TRangeRef titleRange=iGridLay->TitleRange();
+	TBool isHorizontalTitleLine=iGridLay->IsHorizontalTitleLine();
+	TBool isVerticalTitleLine=iGridLay->IsVerticalTitleLine();
+	TRect clippingRect(iGridRect.iTl,iMainPoint);	//Top left quarter of grid
+	CleanupStack::PushL(TCleanupItem(CleanupGc,(CGridImg*)this));
+	if (aRect.Intersects(clippingRect))
+		{
+		clippingRect.Intersection(aRect);
+		iGcPtr->SetClippingRect(clippingRect);
+		DrawTopLeftGridLabelL();
+		if (isVerticalTitleLine)
+			DrawTopGridLabelsL(titleRange.iFrom.iCol,titleRange.iTo.iCol-1,ETitleRef);
+		if (isHorizontalTitleLine)
+			{
+			DrawSideGridLabelsL(titleRange.iFrom.iRow,titleRange.iTo.iRow,ETitleRef);
+			}
+		iGcPtr->Reset();
+		if (isVerticalTitleLine && isHorizontalTitleLine)
+			{
+			clippingRect.SetRect(iTitlePoint,iMainPoint);
+			clippingRect.Intersection(aRect);
+			if (iGridLay->IsAutoClearGridCells())
+//->
+				TGridUtils::FillRect(iGcPtr, iGridLay->GridColors().iBackground, clippingRect);
+//				TGridUtils::FillRect(iGcPtr,KRgbGridBackground,clippingRect);
+//->
+			DrawGridLinesAndCellsInRangeL(titleRange,clippingRect,ETitleRef,ETitleRef);
+			}
+		}
+
+	TInt borderCorr=(iGridLay->IsEncroachingCellBorders()) ? 1 : 0;
+	TRangeRef range;
+	clippingRect.SetRect(iMainPoint.iX,iGridRect.iTl.iY,iGridRect.iBr.iX,iMainPoint.iY);//Top right quarter
+	if (aRect.Intersects(clippingRect))
+		{
+		clippingRect.Intersection(aRect);
+		iGcPtr->SetClippingRect(clippingRect);
+		range.iFrom.iCol=iGridLay->XValToColumn(clippingRect.iTl.iX);
+		range.iTo.iCol=iGridLay->XValToColumn(clippingRect.iBr.iX+borderCorr);
+		DrawTopGridLabelsL(range.iFrom.iCol,range.iTo.iCol);
+		iGcPtr->Reset();
+		if (isHorizontalTitleLine)
+			{
+			range.iFrom.iRow=titleRange.iFrom.iRow;
+			range.iTo.iRow=titleRange.iTo.iRow;
+			clippingRect.SetRect(iMainPoint.iX,iTitlePoint.iY,iGridRect.iBr.iX,iMainPoint.iY);
+			clippingRect.Intersection(aRect);
+			if (iGridLay->IsAutoClearGridCells())
+//->
+				TGridUtils::FillRect(iGcPtr,iGridLay->GridColors().iBackground,clippingRect);
+//				TGridUtils::FillRect(iGcPtr,KRgbGridBackground,clippingRect);
+//->
+			DrawGridLinesAndCellsInRangeL(range,clippingRect,EMainRef,ETitleRef);
+			}
+		}
+
+	clippingRect.SetRect(iGridRect.iTl.iX,iMainPoint.iY,iMainPoint.iX,iGridRect.iBr.iY);//Bottom left quarter
+	if (aRect.Intersects(clippingRect))
+		{
+		clippingRect.Intersection(aRect);
+		iGcPtr->SetClippingRect(clippingRect);
+		range.iFrom.iRow=iGridLay->YValToRow(clippingRect.iTl.iY);
+		range.iTo.iRow=iGridLay->YValToRow(clippingRect.iBr.iY+borderCorr);
+		DrawSideGridLabelsL(range.iFrom.iRow,range.iTo.iRow);
+		iGcPtr->Reset();
+		if (isVerticalTitleLine)
+			{
+			range.iFrom.iCol=titleRange.iFrom.iCol;
+			range.iTo.iCol=titleRange.iTo.iCol;
+			clippingRect.SetRect(iTitlePoint.iX,iMainPoint.iY,iMainPoint.iX,iGridRect.iBr.iY);
+			clippingRect.Intersection(aRect);
+			if (iGridLay->IsAutoClearGridCells())
+//->
+				TGridUtils::FillRect(iGcPtr,iGridLay->GridColors().iBackground,clippingRect);
+//				TGridUtils::FillRect(iGcPtr,KRgbGridBackground,clippingRect);
+//->
+			DrawGridLinesAndCellsInRangeL(range,clippingRect,ETitleRef,EMainRef);
+			}
+		}
+
+	clippingRect.SetRect(iMainPoint,iGridRect.iBr);	//Bottom right(main) quarter of grid
+	if (aRect.Intersects(clippingRect))
+		{
+		clippingRect.Intersection(aRect);
+		range.iFrom = iGridLay->PointToCell(clippingRect.iTl);
+		range.iTo = iGridLay->PointToCell(clippingRect.iBr+TPoint(borderCorr,borderCorr));
+		if (iGridLay->IsAutoClearGridCells())
+//->
+			TGridUtils::FillRect(iGcPtr,iGridLay->GridColors().iBackground,clippingRect);
+//			TGridUtils::FillRect(iGcPtr,KRgbGridBackground,clippingRect);
+//->
+		DrawGridLinesAndCellsInRangeL(range,clippingRect);
+		}
+	clippingRect=iGridRect;
+	clippingRect.Intersection(aRect);
+	iGcPtr->SetClippingRect(clippingRect);
+	RRegion region;
+	CleanupClose<RRegion>::PushL(region);
+	AppendTotalHighlightRegionL(region);
+	CleanupStack::Pop(2);	// region + gc cleanup
+	HighlightRegion(region);
+	region.Close();
+	DrawVerticalTitleLine();
+	DrawHorizontalTitleLine();
+	iGcPtr->CancelClippingRect();
+	((CGridImg*)this)->DeleteGc();
+	CONST_CAST(CGridImg*,this)->DrawResizingDragHiglights(aRect);
+	}
+
+#if defined(__WINC__)
+void CGridImg::BeginRedrawAndDrawL(const TRect& /*aRect*/) const
+	{}	// shouldn't be called under WINC
+#else
+
+void CGridImg::BeginRedrawAndDrawL(const TRect& aRect) const
+	{
+	iWin->Invalidate(aRect);
+	iWin->BeginRedraw(aRect);
+	CleanupStack::PushL(TCleanupItem(EndRedraw,iWin));
+	DrawL(iGc,aRect);
+	CleanupStack::PopAndDestroy();
+	}
+#endif
+
+EXPORT_C void CGridImg::PrintGridLinesAndCellsInRangeL(CGraphicsContext* aPrinterGc,const TRangeRef& aRange,
+	TInt aScaleFactor) const
+//
+// Assumes aPrinterGc is active for drawing to
+/** Prints the grid lines and cells in the specified range.
+
+@param aPrinterGc The printer graphics context.
+@param aRange The cell range.
+@param aScaleFactor The scale factor. A value of: 2, scales down by a half; 
+4, scales down by a quarter, etc. */
+	{
+	__ASSERT_DEBUG(aPrinterGc!=NULL,Panic(EGridImgInvalidGC));
+
+	TRangeRef visRange=iGridLay->VisibleRange();
+	TPoint endPoint=iGridLay->CellToPoint(visRange.iTo+TCellRef(1,1));
+	TRect borderRect(iGridRect.iTl,endPoint);
+	TPoint titlePoint=iTitlePoint;
+	if (aScaleFactor!=EScaleOneToOne)
+		{
+		ScaleDown(borderRect.iTl,aScaleFactor);
+		ScaleDown(borderRect.iBr,aScaleFactor);
+		ScaleDown(titlePoint,aScaleFactor);
+		}
+	borderRect.iTl-=TPoint(1,1);
+	TPoint realTlPoint=iGridLay->CellToPoint(aRange.iFrom);
+	TBool doColumns=aRange.iTo.iCol>=aRange.iFrom.iCol;
+	TBool doRows=aRange.iTo.iRow>=aRange.iFrom.iRow;
+	TBool printBorderRect=EFalse;
+	if (iGridLay->IsPrintedLabels())
+		{
+		TBool isSideLabels=iGridLay->IsSideLabels();
+		TBool isTopLabels=iGridLay->IsTopLabels();
+		if (isSideLabels && isTopLabels && aRange.iFrom==visRange.iFrom)	// i.e. is top band
+			{
+			TRect rect(iGridRect.iTl,iTitlePoint);
+			ScaleDown(rect.iTl,aScaleFactor);
+			ScaleDown(rect.iBr,aScaleFactor);
+			rect.Resize(-1,-1);
+//->
+//			iGridLabelImg->DrawTopLeftLabelL(aPrinterGc,rect);
+			iGridLabelImg->DrawTopLeftLabelL(aPrinterGc, rect, iGridLay->GridColors().iBackground);
+//->
+			printBorderRect=ETrue;
+			}
+		if (isTopLabels && doColumns)
+			{
+			TInt realPos=realTlPoint.iX;
+			TRect line(realPos*EScaleOneToOne/aScaleFactor,borderRect.iTl.iY+1,0,titlePoint.iY-1);
+			for (TInt ii=aRange.iFrom.iCol;ii<aRange.iTo.iCol;ii++)
+				{
+				realPos+=iGridLay->ColumnWidthInPixels(ii);
+				line.iBr.iX=realPos*EScaleOneToOne/aScaleFactor-1;
+				iGridLabelImg->DrawColLabelL(aPrinterGc,ii,line);
+				line.iTl.iX=line.iBr.iX;
+//->
+			    aPrinterGc->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//				aPrinterGc->SetPenColor(KRgbGridLabelSeparators);
+//->
+				aPrinterGc->DrawLine(line.iTl,line.iBr);
+				line.iTl.iX++;
+				}
+			realPos+=iGridLay->ColumnWidthInPixels(aRange.iTo.iCol);
+			line.iBr.iX=realPos*EScaleOneToOne/aScaleFactor-1;
+			iGridLabelImg->DrawColLabelL(aPrinterGc,aRange.iTo.iCol,line);
+//->
+		    aPrinterGc->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			aPrinterGc->SetPenColor(KRgbGridLabelSeparators);
+//->
+			aPrinterGc->DrawLine(TPoint(borderRect.iTl.iX,titlePoint.iY-1),
+				TPoint(borderRect.iBr.iX,titlePoint.iY-1));
+			printBorderRect=ETrue;
+			}
+		if (isSideLabels && doRows)
+			{
+			TInt realPos=realTlPoint.iY;
+			TRect line(borderRect.iTl.iX+1,realPos*EScaleOneToOne/aScaleFactor,titlePoint.iX-1,0);
+			for (TInt ii=aRange.iFrom.iRow;ii<aRange.iTo.iRow;ii++)
+				{
+				realPos+=iGridLay->RowHeightInPixels(ii);
+				line.iBr.iY=realPos*EScaleOneToOne/aScaleFactor-1;
+				iGridLabelImg->DrawRowLabelL(aPrinterGc,ii,line);
+				line.iTl.iY=line.iBr.iY;
+//->
+			    aPrinterGc->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//				aPrinterGc->SetPenColor(KRgbGridLabelSeparators);
+//->
+				aPrinterGc->DrawLine(line.iTl,line.iBr);
+				line.iTl.iY++;
+				}
+			realPos+=iGridLay->RowHeightInPixels(aRange.iTo.iRow);
+			line.iBr.iY=realPos*EScaleOneToOne/aScaleFactor-1;
+			iGridLabelImg->DrawRowLabelL(aPrinterGc,aRange.iTo.iRow,line);
+//->
+		    aPrinterGc->SetPenColor(iGridLay->GridColors().iLabelSeparators);
+//			aPrinterGc->SetPenColor(KRgbGridLabelSeparators);
+//->
+			aPrinterGc->DrawLine(TPoint(titlePoint.iX-1,borderRect.iTl.iY),
+				TPoint(titlePoint.iX-1,borderRect.iBr.iY));
+			printBorderRect=ETrue;
+			}
+		}
+
+	if (iGridLay->IsPrintedGridLines())
+		{	
+//->
+//		aPrinterGc->SetPenColor(KRgbGridForeground);	// prints black not gray as on screen
+		aPrinterGc->SetPenColor(iGridLay->GridColors().iForeground);	// prints black not gray as on screen
+//->
+		if (iGridLay->IsVerticalGridLines() && doColumns)
+			{
+			TInt realPos=realTlPoint.iX;
+			TRect line(0,titlePoint.iY,0,borderRect.iBr.iY-1);
+			for (TInt ii=aRange.iFrom.iCol;ii<aRange.iTo.iCol;ii++)
+				{
+				realPos+=iGridLay->ColumnWidthInPixels(ii);
+				line.iTl.iX=line.iBr.iX=realPos*EScaleOneToOne/aScaleFactor-1;
+				aPrinterGc->DrawLine(line.iTl,line.iBr);
+				}
+			printBorderRect=ETrue;
+			}
+		if (iGridLay->IsHorizontalGridLines() && doRows)
+			{
+			TInt realPos=realTlPoint.iY;
+			TRect line(titlePoint.iX,0,borderRect.iBr.iX-1,0);
+			for (TInt ii=aRange.iFrom.iRow;ii<aRange.iTo.iRow;ii++)
+				{
+				realPos+=iGridLay->RowHeightInPixels(ii);
+				line.iTl.iY=line.iBr.iY=realPos*EScaleOneToOne/aScaleFactor-1;
+				aPrinterGc->DrawLine(line.iTl,line.iBr);
+				}
+			printBorderRect=ETrue;
+			}
+		}
+	if (printBorderRect)
+		{
+//->
+//		aPrinterGc->SetPenColor(KRgbGridForeground);
+		aPrinterGc->SetPenColor(iGridLay->GridColors().iForeground);
+//->
+		
+		aPrinterGc->DrawRect(borderRect);
+		}
+	if (doRows && doColumns)
+		DrawCellsToGcL(aPrinterGc,aRange,TRect(titlePoint,borderRect.iBr),realTlPoint,aScaleFactor);
+	}
+
+void CGridImg::ScaleDown(TPoint& aPoint,TInt aScaleFactor) const
+	{
+	aPoint.iX=aPoint.iX*EScaleOneToOne/aScaleFactor;
+	aPoint.iY=aPoint.iY*EScaleOneToOne/aScaleFactor;
+	}
+
+void CGridImg::ResetGcToDefault(CGraphicsContext* aGc) const
+//
+// Should be called if the gc may have changed outside CGridImg since the private
+// functions assume these settings.
+	{
+	aGc->SetPenStyle(CGraphicsContext::ESolidPen);
+	aGc->SetPenSize(TSize(1,1));
+	aGc->SetBrushStyle(CGraphicsContext::ENullBrush);
+	}
+
+EXPORT_C void CGridImg::SetCursorPosL(const TCellRef& aCursorPos)	
+/** Sets the new position of the cursor.
+
+This is the proposed position that the cursor would occupy after a keypress.
+
+@param aCursorPos The cell reference of the new cursor position. */
+	{
+	iNewCursorPos=aCursorPos;
+	if (!iGridLay->LimitCell(iNewCursorPos))
+		{
+		iNewCursorPos=iCursorPos;
+		return;
+		}
+	DrawCursorOrRegionL(EIsAbsoluteMove);
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::SetAnchorPosL(const TCellRef& aAnchorPos)
+/** Sets the cursor's anchor position.
+
+Note that the cursor's anchor position is unchanged if the specified position 
+lies outside the currently selected region.
+
+@param aAnchorPos The cell reference of the cursor's anchor position. */
+	{
+	if (!iSelected->IsCellSelected(iAnchorPos))
+		return;	//Can't have the anchor outside the selection region
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	iAnchorPos=aAnchorPos;
+	if (!iGridLay->LimitCell(iAnchorPos))
+		{
+		oldRegion.Close();
+		CleanupStack::Pop();
+		return;
+		}
+	iNewCursorPos=iCursorPos=iAnchorPos;
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::MoveCursorL(TMoveDirectionAndAmount aCursorMove,TUint aSelectState)
+/** Moves the cursor to the specified position.
+
+The screen is scrolled as necessary.
+
+@param aCursorMove Defines the direction and the amount by which the cursor 
+is to be moved.
+@param aSelectState Flag. If set to EIsWithSelect, then the cursor may become 
+part of the selected region. */
+	{
+	TUint flagList=aSelectState&EIsWithSelect;	//Filters out any other components
+	if (!flagList && iSelected->Count())
+		iNewCursorPos = iAnchorPos;
+	TCellRef oldPos=iNewCursorPos;
+	TMoveDirectionAndAmount pageScroll=EMoveNone;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	TCellRef cellToExpose=visRange.iFrom;
+	TBool doExposeCol=EFalse;
+	TInt relCursorPos;
+	TInt amount;
+	switch (aCursorMove)
+		{
+	case EMoveRowUp:
+		iGridLay->StepRowBackward(--iNewCursorPos.iRow);
+		break;
+	case EMoveRowDown:
+		iGridLay->StepRowForward(++iNewCursorPos.iRow);
+		break;
+	case EMoveColumnLeft:
+		if (iGridLay->IsRowPermanentlySelected())
+			{
+			--cellToExpose.iCol;
+			doExposeCol=ETrue;
+			}
+		else
+			iGridLay->StepColumnBackward(--iNewCursorPos.iCol);
+		break;
+	case EMoveColumnRight:
+		if (iGridLay->IsRowPermanentlySelected())
+			{
+			cellToExpose.iCol=visRange.iTo.iCol;
+			if (iGridLay->IsVisibleToColumnFullyVisible() || visRange.iFrom.iCol==visRange.iTo.iCol)
+				cellToExpose.iCol++;
+			doExposeCol=ETrue;
+			}
+		else
+			iGridLay->StepColumnForward(++iNewCursorPos.iCol);
+		break;
+	case EMovePageUp:
+		relCursorPos=iGridLay->RowToYVal(visRange.iFrom.iRow,iNewCursorPos.iRow);
+		pageScroll=EMovePageDown;
+		amount=iGridLay->CalcVisibleFromRowAfterPageScroll(pageScroll);
+		if (amount!=visRange.iFrom.iRow)
+			{
+			TInt newCursorRow=iGridLay->YValToNearestRow(amount,relCursorPos);
+			if (newCursorRow>=iNewCursorPos.iRow)
+				iGridLay->StepRowBackward(--iNewCursorPos.iRow);
+			else
+				iNewCursorPos.iRow=newCursorRow;
+			}
+		else
+			iNewCursorPos.iRow=Min(visRange.iFrom.iRow,iNewCursorPos.iRow-1);
+		iGridLay->LimitRowToVisible(iNewCursorPos.iRow);
+		break;
+	case EMovePageDown:
+		relCursorPos=iGridLay->RowToYVal(visRange.iFrom.iRow,iNewCursorPos.iRow);
+		pageScroll=EMovePageUp;
+		amount=iGridLay->CalcVisibleFromRowAfterPageScroll(pageScroll);
+		if (amount!=visRange.iFrom.iRow)
+			{
+			TInt newCursorRow=iGridLay->YValToNearestRow(amount,relCursorPos);
+			if (newCursorRow<=iNewCursorPos.iRow)
+				iGridLay->StepRowForward(++iNewCursorPos.iRow);
+			else
+				iNewCursorPos.iRow=newCursorRow;
+			}
+		else
+			{
+			TInt corr=iGridLay->IsVisibleToRowFullyVisible() ? 0 : 1;
+			iNewCursorPos.iRow=Max(visRange.iTo.iRow-corr,iNewCursorPos.iRow+1);
+			}
+		break;
+	case EMovePageLeft:
+		relCursorPos=iGridLay->ColumnToXVal(visRange.iFrom.iCol,iNewCursorPos.iCol);
+		pageScroll=EMovePageRight;
+		amount=iGridLay->CalcVisibleFromColumnAfterPageScroll(pageScroll);
+		if (amount!=visRange.iFrom.iCol)
+			{
+			TInt newCursorColumn=iGridLay->XValToNearestColumn(amount,relCursorPos);
+			if (newCursorColumn>=iNewCursorPos.iCol)
+				iGridLay->StepColumnBackward(--iNewCursorPos.iCol);
+			else
+				iNewCursorPos.iCol=newCursorColumn;
+			}
+		else
+			iNewCursorPos.iCol=Min(visRange.iFrom.iCol,iNewCursorPos.iCol-1);
+		iGridLay->LimitColumnToVisible(iNewCursorPos.iCol);
+		break;
+	case EMovePageRight:
+		relCursorPos=iGridLay->ColumnToXVal(visRange.iFrom.iCol,iNewCursorPos.iCol);
+		pageScroll=EMovePageLeft;
+		amount=iGridLay->CalcVisibleFromColumnAfterPageScroll(pageScroll);
+		if (amount!=visRange.iFrom.iCol)
+			{
+			TInt newCursorColumn=iGridLay->XValToNearestColumn(amount,relCursorPos);
+			if (newCursorColumn<=iNewCursorPos.iCol)
+				iGridLay->StepColumnForward(++iNewCursorPos.iCol);
+			else
+				iNewCursorPos.iCol=newCursorColumn;
+			}
+		else
+			{
+			TInt corr=iGridLay->IsVisibleToColumnFullyVisible() ? 0 : 1;
+			iNewCursorPos.iCol=Max(visRange.iTo.iCol-corr,iNewCursorPos.iCol+1);
+			}
+		break;
+	case EMoveRowStart:
+	case EMoveColumnStart:
+	case EMoveHome:
+		if (aCursorMove!=EMoveColumnStart)
+			{
+			if (iGridLay->IsRowPermanentlySelected())
+				{
+				cellToExpose.iCol=iGridLay->MinVisibleFromColumn();
+				doExposeCol=ETrue;
+				}
+			else
+				{
+				iNewCursorPos.iCol=iGridLay->MinVisibleFromColumn();
+				iGridLay->StepColumnForward(iNewCursorPos.iCol);
+				}
+			}
+		if (aCursorMove!=EMoveRowStart)
+			{
+			iNewCursorPos.iRow=(iGridLay->IsIndefiniteRowBoundaries())
+				? -KMaxTInt : iGridLay->MinVisibleFromRow();
+			iGridLay->StepRowForward(iNewCursorPos.iRow);
+			}
+		break;
+	case EMoveRowEnd:
+	case EMoveColumnEnd:
+	case EMoveEnd:
+		{
+		TCellRef fromCell=iGridLay->GridRange().iFrom;
+		if (aCursorMove!=EMoveColumnEnd)
+			{
+			TInt lastCol=fromCell.iCol+iGridLay->ColumnExtent()-1;
+			if (iGridLay->IsRowPermanentlySelected())
+				{
+				cellToExpose.iCol=lastCol;
+				doExposeCol=ETrue;
+				}
+			else
+				{
+				iNewCursorPos.iCol=lastCol;
+				iGridLay->StepColumnBackward(iNewCursorPos.iCol);
+				}
+			}
+		if (aCursorMove!=EMoveRowEnd)
+			{
+			iNewCursorPos.iRow=(iGridLay->IsIndefiniteRowBoundaries())
+				? KMaxTInt : fromCell.iRow+iGridLay->RowExtent()-1;
+			iGridLay->StepRowBackward(iNewCursorPos.iRow);
+			}
+		}
+		break;
+	default:
+		break;
+		}
+	iGridLay->LimitCell(iNewCursorPos);
+	if (oldPos==iNewCursorPos)
+		flagList|=EIsAtBoundary;
+	oldPos=iNewCursorPos;
+	DrawCursorOrRegionL(flagList);
+	TPoint offset;
+	if (pageScroll!=EMoveNone)
+		offset=iGridLay->PageScroll(pageScroll);
+	cellToExpose.iRow=iCursorPos.iRow;
+	if (!doExposeCol)
+		cellToExpose.iCol=iCursorPos.iCol;
+	if (iGridLay->IsCellOutOfVisibleRange(cellToExpose))
+		{
+		visRange=iGridLay->VisibleRange();
+		visRange.iTo.Offset(-1,-1);
+		iGridLay->StepRowBackward(visRange.iTo.iRow);
+		iGridLay->StepColumnBackward(visRange.iTo.iCol);
+		if (iSelected->IsColSelectedLastIndex(cellToExpose.iCol) && 
+			!iGridLay->IsColumnSelectionDisabled())
+			{
+			cellToExpose.iRow=visRange.iFrom.iRow;
+			}
+		if ((iSelected->IsRowSelectedLastIndex(cellToExpose.iRow) || iGridLay->IsRowPermanentlySelected())
+			&& !doExposeCol && !iGridLay->IsRowSelectionDisabled())
+			{
+			cellToExpose.iCol=visRange.iFrom.iCol;
+			}
+		offset+=iGridLay->ExposeCell(cellToExpose);
+		}
+	ScrollL(offset);
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::SetCursorWithPointerL(const TPoint &aPoint,TUint aFlagList)
+/** Moves the cursor to an absolute position.
+
+@param aPoint The absolute position.
+@param aFlagList Flag. Can be set to EIsWithDrag. */
+	{
+	TRangeRef visRange(iGridLay->VisibleRange());
+	TCellRef cellToExpose = visRange.iFrom;
+	if (iGridLay->IsVerticalTitleLine())
+		{
+		if (aPoint.iX<iMainPoint.iX)
+			{
+			if (!(aFlagList&EIsWithDrag))
+		 		iXRefPoint=ETitleRef;
+			}
+		else
+			{
+			if (iXRefPoint==ETitleRef && !iSelected->IsRowSelectedLastIndex(iCursorPos.iRow)
+				&& (aFlagList&EIsWithDrag))
+				{
+				cellToExpose.iCol=iGridLay->TitleRange().iTo.iCol;
+				}
+			iXRefPoint=EMainRef;
+			}
+		}
+	else
+		iXRefPoint=EMainRef;
+	if (iGridLay->IsHorizontalTitleLine())
+		{
+		if (aPoint.iY<iMainPoint.iY)
+			{
+			if (!(aFlagList&EIsWithDrag))
+				iYRefPoint=ETitleRef;
+			}
+		else
+			{
+			if (iYRefPoint==ETitleRef && !iSelected->IsColSelectedLastIndex(iCursorPos.iCol)
+				&& (aFlagList&EIsWithDrag))
+				{
+				cellToExpose.iRow=iGridLay->TitleRange().iTo.iRow;
+				}
+			iYRefPoint=EMainRef;
+			}
+		}
+	else
+		iYRefPoint=EMainRef;
+	TPoint offset=iGridLay->ExposeCellToTopLeft(cellToExpose);
+	ScrollL(offset);
+
+	if (aPoint.iY<iTitlePoint.iY)
+		{
+		if (iDragFlags&EIsLabelDraggingIgnored && aFlagList&EIsWithDrag)
+			return;
+		if (!(aFlagList&EIsWithDrag) || iSelected->IsColSelectedLastIndex(iCursorPos.iCol))
+			{
+			if (iGridLay->IsColumnSelectionDisabled())
+				{
+				iDragFlags|=EIsLabelDraggingIgnored;
+				return;
+				}
+			aFlagList|=EIsColumnSelected;
+			iDragFlags=iDragFlags&~EIsLabelDraggingIgnored;
+			}
+		}
+	if (aPoint.iX<iTitlePoint.iX)
+		{
+		if (iDragFlags&EIsLabelDraggingIgnored && aFlagList&EIsWithDrag)
+			return;
+		if (!(aFlagList&EIsWithDrag) ||	iSelected->IsRowSelectedLastIndex(iCursorPos.iRow))
+			{
+			if (iGridLay->IsRowPermanentlySelected() && !(aFlagList&EIsWithDrag))
+				iDragFlags|=EIsSidewaysScrollIgnored;
+			else if (iGridLay->IsRowSelectionDisabled())
+				{
+				iDragFlags|=EIsLabelDraggingIgnored;
+				return;
+				}
+			else
+				aFlagList|=EIsRowSelected;
+			iDragFlags=iDragFlags&~EIsLabelDraggingIgnored;
+			}
+		}
+	else
+		{
+		iDragFlags=iDragFlags&~EIsSidewaysScrollIgnored;
+		if (aPoint.iY>=iTitlePoint.iY)		//ie not on the labels
+			iDragFlags=iDragFlags&~EIsLabelDraggingIgnored;
+		}
+	iNewCursorPos=RelativePointToCell(aPoint,iXRefPoint,iYRefPoint);	
+	iGridLay->LimitCell(iNewCursorPos);
+	if (iCursorPos==iNewCursorPos && !iSelected->Count() && 
+		!(aFlagList&(EIsRowSelected|EIsColumnSelected|EIsWithControl)))
+		{
+		return;	// Don't need to do anything in this case
+		}
+
+	cellToExpose = iNewCursorPos;
+	if (iSelected->IsColSelectedLastIndex(iCursorPos.iCol) && (aFlagList&EIsWithDrag))
+		cellToExpose.iRow = visRange.iFrom.iRow;
+	if ((iSelected->IsRowSelectedLastIndex(iCursorPos.iRow) && (aFlagList&EIsWithDrag)
+		&& !iGridLay->IsRowPermanentlySelected()) || iDragFlags&EIsSidewaysScrollIgnored)
+		{
+		cellToExpose.iCol = visRange.iFrom.iCol;
+		}
+	TBool expose = EFalse;
+	if (aFlagList&EIsWithDrag)
+		{
+		if ((aPoint.iX<iMainPoint.iX && iXRefPoint==EMainRef) || aPoint.iX>iGridRect.iBr.iX)
+			expose=ETrue;
+		else
+			cellToExpose.iCol=visRange.iFrom.iCol;
+		if ((aPoint.iY<iMainPoint.iY && iYRefPoint==EMainRef) || aPoint.iY>iGridRect.iBr.iY)
+			expose=ETrue;
+		else
+			cellToExpose.iRow=visRange.iFrom.iRow;
+		}
+
+	aFlagList|=EIsAbsoluteMove;
+	DrawCursorOrRegionL(aFlagList);
+	if (expose)
+		{
+		offset=iGridLay->ExposeCell(cellToExpose);
+		ScrollL(offset);
+		}
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::ResetSelectedL()
+/** Clears the selected region. */
+	{
+	if (!iSelected->Count())
+		return;
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	iNewCursorPos=iCursorPos=iAnchorPos;
+	iSelected->Reset();
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::AddRangeToSelectedL(const TRangeRef& aRange,TSelectType aType)
+/** Adds the specified range to, or replaces, the currently selected region.
+
+The range can be added to the existing selected region or it can replace the 
+existing selected region.
+
+@param aRange The range to be added.
+@param aType Indicates whether the existing selected region is to be reset 
+(i.e. emptied) before adding the new range. */
+	{
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	if (aType==ESelectOverwrite)
+		iSelected->Reset();
+	iNewCursorPos=iCursorPos=aRange.iTo;
+	iAnchorPos=aRange.iFrom;
+	iSelected->AddCellRangeL(aRange);
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::AddRegionToSelectedL(const CArrayFix<TRangeRef>* aCellRegion,TSelectType aType)
+/** Adds the specified region to, or replaces, the currently selected region.
+
+The region can be added to the existing selected region, or it can replace 
+the existing selected region.
+
+@param aCellRegion A set of ranges that form the region to be added.
+@param aType Indicates whether the existing selected region is to be reset 
+(i.e. emptied) before adding the new region. */
+	{
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	if (aType==ESelectOverwrite)
+		iSelected->Reset();
+	TInt count=aCellRegion->Count();
+	if (!count)
+		iNewCursorPos=iCursorPos=iAnchorPos=iGridLay->GridRange().iFrom;
+	else
+		{
+		TRangeRef lastRange=(*aCellRegion)[count-1];
+		iNewCursorPos=iCursorPos=lastRange.iTo;
+		iAnchorPos=lastRange.iFrom;
+		for (TInt ii=0;ii<count;ii++)
+			iSelected->AddCellRangeL((*aCellRegion)[ii]);
+		}
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::AddRowToSelectedL(TInt aRow,TSelectType aType)
+/** Adds a row to, or replaces, the currently selected region.
+
+The row can be added to the existing selected region, or it can replace the 
+existing selected region.
+
+@param aRow The row to be added.
+@param aType Indicates whether the existing selected region is to be reset 
+(i.e. emptied) before adding the new region. */
+	{
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	if (aType==ESelectOverwrite)
+		iSelected->Reset();
+	iAnchorPos.iRow=iCursorPos.iRow=iNewCursorPos.iRow=aRow;
+	iAnchorPos.iCol=iGridLay->VisibleRange().iFrom.iCol;
+	iNewCursorPos.iCol=iCursorPos.iCol=iGridLay->GridRange().iTo.iCol;
+	iSelected->AddRowL(aRow);
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+EXPORT_C void CGridImg::AddColToSelectedL(TInt aCol,TSelectType aType)
+/** Adds a column to, or replaces, the currently selected region.
+
+The column can be added to the existing selected region, or it can replace 
+the existing selected region.
+
+@param aCol The column to be added.
+@param aType Indicates whether the existing selected region is to be reset 
+(i.e. emptied) before adding the new region. */
+	{
+	RRegion oldRegion;
+	CleanupClose<RRegion>::PushL(oldRegion);
+	AppendTotalHighlightRegionL(oldRegion);
+	if (aType==ESelectOverwrite)
+		iSelected->Reset();
+	iAnchorPos.iCol=iCursorPos.iCol=iNewCursorPos.iCol=aCol;
+	iAnchorPos.iRow=iGridLay->VisibleRange().iFrom.iRow;
+	iNewCursorPos.iRow=iCursorPos.iRow=iGridLay->GridRange().iTo.iRow;
+	iSelected->AddColL(aCol);
+	HighlightNewRegionFromOldL(oldRegion);
+	oldRegion.Close();
+	CleanupStack::Pop();
+	if (iCursorMoveCallBack)
+		iCursorMoveCallBack->HandleCursorMoveL();
+	}
+
+void CGridImg::HighlightNewRegionFromOldL(const TRegion& aOldRegion)
+//
+// returns ETrue if there's an error
+	{
+	RRegion newRegion;
+	CleanupClose<RRegion>::PushL(newRegion);
+	AppendTotalHighlightRegionL(newRegion);
+	HighlightMinRegionL(aOldRegion,newRegion);
+	CleanupStack::Pop();
+	newRegion.Close();
+	}
+
+EXPORT_C void CGridImg::CheckSideLabelWidthAndScrollL()
+/** Checks the side label width and, if changed, scrolls the screen. */
+	{
+	TInt offset=CheckSideLabelWidth();
+#if !defined(__WINC__)
+	if (offset)
+		{
+		TRect rect(iGridRect.iTl.iX,iGridRect.iTl.iY,iTitlePoint.iX-1,iGridRect.iBr.iY);
+		iWin->Scroll(iGridRect,TPoint(offset,0));
+		BeginRedrawAndDrawL(rect);
+		if (offset<0)
+			{
+			rect.SetRect(iGridRect.iBr.iX+offset,iGridRect.iTl.iY,iGridRect.iBr.iX,iGridRect.iBr.iY);
+			BeginRedrawAndDrawL(rect);
+			}
+		}
+#endif
+	}
+
+EXPORT_C TInt CGridImg::CheckSideLabelWidth()
+/** Checks whether there has been a change in the width of the side label.
+
+@return The difference between the new width and the old width (new width 
+- old width). */
+	{
+	if (iGridLay->IsSideLabels())
+		{
+		TInt oldWidth=iTitlePoint.iX-iGridRect.iTl.iX;
+		TInt newWidth=SideLabelWidthInPixels();
+		if (oldWidth!=newWidth)
+			{
+			ResetReferencePoints();
+			iGridLay->ResetVisibleToCell();
+			return (newWidth-oldWidth);
+			}
+		}
+	return 0;
+	}
+
+EXPORT_C TInt CGridImg::SideLabelWidthInPixels() const
+/** Gets the width of the side label.
+
+@return The width of the side label, in pixels. */
+	{
+	if (iGridLabelImg==NULL)
+		return 0;
+	TRangeRef visRange=iGridLay->VisibleRange();
+	if (!iGridLay->LimitRow(visRange.iFrom.iRow))
+		return 0;
+	return iGridLabelImg->SideLabelWidthInPixels(visRange.iFrom.iRow,visRange.iTo.iRow);
+	}
+
+EXPORT_C TInt CGridImg::MaxSideLabelWidthInPixels() const
+/** Gets the maximum width of the side label.
+
+@return The maximum width of the side label, in pixels. */
+	{
+	if (iGridLabelImg==NULL)
+		return 0;
+	TInt firstRow;
+	if (!iGridLay->RequestRow(-KMaxTInt,firstRow))
+		return 0;
+	return iGridLabelImg->SideLabelWidthInPixels(firstRow,firstRow+iGridLay->RowExtent()-1);
+	}
+
+EXPORT_C TInt CGridImg::TopLabelHeightInPixels() const
+/** Gets the height of the top labels.
+
+@return The height of the top labels, in pixels. */
+	{
+	if (iGridLabelImg==NULL)
+		return 0;
+	return iGridLabelImg->TopLabelHeightInPixels();
+	}
+
+#if defined(__WINC__)
+
+// All these functions are inappropriate under WINC
+EXPORT_C void CGridImg::FinishLabelDragL()
+	{}
+
+EXPORT_C TBool CGridImg::StartLabelDrag(const TPoint& /*aPoint*/)
+	{ return EFalse; }
+
+TBool CGridImg::ScanColumnsForDrag(TInt /*aFromColumn*/,TInt /*aToColumn*/,TInt /*aPointerPos*/,TInt& /*aPrevious*/,TInt& /*aCurrent*/)
+	{ return EFalse; }
+
+TBool CGridImg::ScanRowsForDrag(TInt /*aFromRow*/,TInt /*aToRow*/,TInt /*aPointerPos*/,TInt& /*aPrevious*/,TInt& /*aCurrent*/)
+	{ return EFalse; }
+
+EXPORT_C TBool CGridImg::UpdateLabelDrag(const TPoint& /*aPoint*/)
+	{ return EFalse; }
+
+void CGridImg::DrawArrowsToInMemoryBitmap(TArrows /*aArrows*/)
+	{}
+
+void CGridImg::DrawDraggingHighlight(const TRect /*aLine*/,TDragDraw /*aDragDraw*/)
+	{}
+
+EXPORT_C void CGridImg::ScrollL(const TPoint& /*aOffset*/)
+	{}
+#else
+
+EXPORT_C void CGridImg::FinishLabelDragL()
+/** Deals with the end of a drag operation.
+
+Typically, the function is called whan handling a pointer event in a control.
+
+The function removes the dotted drag line indicating a drag operation, and, 
+if necessary, updates the column width/row height, and then scrolls and redraws 
+the necessary regions.
+
+@see StartLabelDrag() */
+	{	   
+	//
+	// Erases the two dotted drag lines if necessary, updates the column/row width/height then scrolls
+	// and redraws the necessary regions. The relevant member variables are also set to zero.
+	//
+	if (iDragDim == ENoDrag)
+		return;
+	TRect line1 = iGridRect;
+	TRect line2 = iGridRect;
+	TInt oldValue;
+	TInt prevDragPos;
+	TRangeRef titleRange=iGridLay->TitleRange();
+	if (iDragDim == EXDrag)
+		{
+		prevDragPos = ((iGridLay->IsVerticalTitleLine() && iDragLabel<=titleRange.iTo.iCol)
+			? iGridLay->TitleColumnToXVal(iDragLabel) : iGridLay->ColumnToXVal(iDragLabel))-1;
+		line1.iTl.iX = line1.iBr.iX = prevDragPos;
+		line2.iTl.iX = line2.iBr.iX = iCurrentDragPos;
+		oldValue = iGridLay->ColumnWidthInPixels(iDragLabel);
+		}
+	else
+		{
+		prevDragPos = ((iGridLay->IsHorizontalTitleLine() && iDragLabel<=titleRange.iTo.iRow)
+			? iGridLay->TitleRowToYVal(iDragLabel) : iGridLay->RowToYVal(iDragLabel))-1;
+		line1.iTl.iY = line1.iBr.iY = prevDragPos;
+		line2.iTl.iY = line2.iBr.iY = iCurrentDragPos;
+		oldValue = iGridLay->RowHeightInPixels(iDragLabel);
+		}
+	CreateGc(iGc);
+	iGc->SetClippingRect(iGridRect);
+	DrawDraggingHighlight(line1,EDragDrawWithoutBitmap);
+	DrawDraggingHighlight(line2,EDragDrawWithBitmap);
+	delete iDragBmp;
+	iDragBmp=NULL;
+	DeleteGc();
+	iCurrentDragPos = Max(iCurrentDragPos,prevDragPos);
+	TInt newValue = iCurrentDragPos-prevDragPos;
+	TInt minValue=(iDragDim==EXDrag) ? iGridLay->MinColumnWidthInPixels() : iGridLay->MinRowHeightInPixels();
+	newValue=Max(newValue,minValue);
+	if (oldValue!=newValue)
+		{
+		TRect validRect=iGridRect;
+		TRect scrollRect=iGridRect;
+		TPoint offset;
+		TBool doScroll=EFalse;
+		TBool newPagination=EFalse;
+		TBool clearPagination=EFalse;
+		if (iGridLay->IsPaginated())
+			{
+			if (!iGridLay->IsAutoPagination())
+				clearPagination=ETrue;
+			newPagination=ETrue;
+			}
+		if (iDragDim==EXDrag)
+			{
+			if (iGridLay->IsUniformColumnWidth() || (iSelected->IsRangeSelected(iGridLay->GridRange())
+				&& !iGridLay->IsColumnSelectionDisabled()))
+				{
+				if (newValue==0)
+					goto DragEnd;
+				validRect.iTl.iX=iTitlePoint.iX;
+				iGridLay->SetDefaultColumnWidthInPixels(newValue);
+				iGridLay->SetColumnWidthsToDefault();
+				}
+			else if (iSelected->IsColSelected(iDragLabel) && !iGridLay->IsColumnSelectionDisabled())
+				{
+				validRect.iTl.iX=iTitlePoint.iX;
+				TInt count=iSelected->Count();
+				for (TInt ii=0;ii<count;ii++)
+					{
+					TRangeRef range=(*iSelected)[ii];
+					if (iSelected->IsColSelected(range.iFrom.iCol,ii))
+						{
+						if ((range.iTo.iCol-range.iFrom.iCol)>CGridLay::EMaxArrayChanges)
+							continue;
+						for (;range.iFrom.iCol<=range.iTo.iCol;range.iFrom.iCol++)
+							iGridLay->SetColumnWidthInPixelsL(range.iFrom.iCol,newValue);
+						}
+					}
+				}
+			else
+				{
+				validRect.iTl.iX = (clearPagination) ? iTitlePoint.iX :
+					Max(prevDragPos-1,iTitlePoint.iX);
+				if (!iGridLay->IsColumnBursting() && !newPagination)
+					{
+					doScroll=ETrue;
+					validRect.iBr.iX = iCurrentDragPos+2;
+					scrollRect.iTl.iX=Max(Min(prevDragPos+oldValue+2,iCurrentDragPos+1),iTitlePoint.iX);
+					offset.iX = newValue-oldValue;
+					}
+				iGridLay->SetColumnWidthInPixelsL(iDragLabel,newValue);
+				}
+			}
+		else
+			{
+			if (iGridLay->IsUniformRowHeight() || (iSelected->IsRangeSelected(iGridLay->GridRange())
+				&& !iGridLay->IsRowSelectionDisabled()))
+				{
+				if (newValue==0)
+					goto DragEnd;
+				validRect.iTl.iY=iTitlePoint.iY;
+				iGridLay->SetDefaultRowHeightInPixels(newValue);
+				iGridLay->SetRowHeightsToDefault();
+				}
+			else if (iSelected->IsRowSelected(iDragLabel) && !iGridLay->IsRowSelectionDisabled())
+				{
+				validRect.iTl.iY=iTitlePoint.iY;
+				TInt count=iSelected->Count();
+				for (TInt ii=0;ii<count;ii++)
+					{
+					TRangeRef range=(*iSelected)[ii];
+					if (iSelected->IsRowSelected(range.iFrom.iRow,ii))
+						{
+						if ((range.iTo.iRow-range.iFrom.iRow)>CGridLay::EMaxArrayChanges)
+							continue;
+						for (;range.iFrom.iRow<=range.iTo.iRow;range.iFrom.iRow++)
+							iGridLay->SetRowHeightInPixelsL(range.iFrom.iRow,newValue);
+						}
+					}
+				}
+			else
+				{
+				validRect.iTl.iY = (clearPagination) ? iTitlePoint.iY :
+					Max(prevDragPos-1,iTitlePoint.iY);
+				if (!newPagination)
+					{
+					doScroll=ETrue;
+					validRect.iBr.iY = iCurrentDragPos+2;
+					scrollRect.iTl.iY=Max(Min(prevDragPos+oldValue+2,iCurrentDragPos+1),iTitlePoint.iY);
+					offset.iY = newValue-oldValue;
+					}
+				iGridLay->SetRowHeightInPixelsL(iDragLabel,newValue);
+				}
+			}
+		iGridLay->NotifyPaginationOutOfDateL();
+		if (doScroll)
+	   		iWin->Scroll(scrollRect,offset);
+		validRect.Intersection(iGridRect);
+		BeginRedrawAndDrawL(validRect);
+		if ((offset.iX<0 && !iGridLay->IsColumnBursting()) || offset.iY<0)
+			{
+			if (offset.iX<0)
+				{
+				validRect.iBr.iX = iGridRect.iBr.iX;
+				validRect.iTl.iX = validRect.iBr.iX+offset.iX;
+				}
+			else
+				{
+				validRect.iBr.iY = iGridRect.iBr.iY;
+				validRect.iTl.iY = validRect.iBr.iY+offset.iY;
+				}
+			BeginRedrawAndDrawL(validRect);
+			}
+		CheckSideLabelWidthAndScrollL();
+		if (!newValue && !iSelected->Count())
+			{
+			if (iDragDim==EXDrag)
+				{
+				if (iDragLabel==iCursorPos.iCol)
+					MoveCursorL(EMoveColumnRight,!EIsWithSelect);	//2nd param=0
+				}
+			else
+				{
+				if (iDragLabel==iCursorPos.iRow)
+					MoveCursorL(EMoveRowDown,!EIsWithSelect);
+				}
+			}
+		}
+DragEnd:
+	iCurrentDragPos = iDragLabel = iDragDiff = 0;
+	iDragDim = ENoDrag;
+	}
+
+EXPORT_C TBool CGridImg::StartLabelResize(TBool aIsColumnLabel, TInt aIndex)
+/** Begins the resizing of a column or a row.
+
+@param aIsColumnLabel Indicates whether a column or row is to be resized: 
+specify ETrue for a column; specify EFalse for a row.
+@param aIndex Identifes the row or column to be resized. This value increases 
+from left to right for a column, and from top to bottom for a row.
+@return True, if resizing has begun; false otherwise. */
+	{
+	TInt widthOrHeight=0;
+	TRect line1 = iGridRect;
+	TRect line2 = iGridRect;
+	TRangeRef visibleRange=iGridLay->VisibleRange();
+	iDragDim=ENoDrag;
+	if(aIsColumnLabel && aIndex>=visibleRange.iFrom.iCol && aIndex<visibleRange.iTo.iCol 
+		&& !iGridLay->IsTopLabelDragDisabled())
+		{
+		iDragLabel=aIndex;
+		iDragDim = EXDrag;
+		line1.iTl.iX=line1.iBr.iX=iGridLay->ColumnToXVal(aIndex)-1;
+		widthOrHeight=iGridLay->ColumnWidthInPixels(aIndex);
+		iCurrentDragPos=line2.iTl.iX=line2.iBr.iX=line1.iTl.iX+widthOrHeight;
+		}
+	else if(!aIsColumnLabel && aIndex>=visibleRange.iFrom.iRow && 
+		aIndex<visibleRange.iTo.iRow && !iGridLay->IsSideLabelDragDisabled())
+		{
+		iDragLabel=aIndex;
+		iDragDim = EYDrag;
+		line1.iTl.iY=line1.iBr.iY=iGridLay->RowToYVal(aIndex)-1;
+		widthOrHeight=iGridLay->RowHeightInPixels(aIndex);
+		iCurrentDragPos=line2.iTl.iY=line2.iBr.iY=line1.iTl.iY+widthOrHeight;
+		}
+	if(iDragDim!=ENoDrag)
+		{
+		TArrows arrows=(widthOrHeight==0? ESecondArrowOnly : EBothArrows);
+		DrawArrowsToInMemoryBitmap(arrows);
+		TRect invalid = TRect(line1.iTl,line2.iBr);
+		if(iDragDim==EXDrag)
+			{
+			invalid.iTl.iX-=2;
+			invalid.iBr.iX+=KArrowLength+KArrowSeparation;
+			}
+		else
+			{
+			invalid.iTl.iY-=2;
+			invalid.iBr.iY+=KArrowLength+KArrowSeparation;
+			}
+		iWin->Invalidate(invalid);
+		iDrawResizeLines=ETrue;
+		return ETrue;
+		}
+	else
+		return EFalse;
+	}
+
+void CGridImg::DrawResizingDragHiglights(const TRect& aRect)
+	{
+	if(iDrawResizeLines)
+		{
+		TRect line1 = iGridRect;
+		TRect line2 = iGridRect;
+		if(iDragDim==EXDrag)
+			{
+			line1.iTl.iX=line1.iBr.iX=iGridLay->ColumnToXVal(iDragLabel)-1;
+			line2.iTl.iX=line2.iBr.iX=iCurrentDragPos;
+			}
+		else if(iDragDim==EYDrag)
+			{
+			line1.iTl.iY=line1.iBr.iY=iGridLay->RowToYVal(iDragLabel)-1;
+			line2.iTl.iY=line2.iBr.iY=iCurrentDragPos;
+			}
+		CreateGc(iGc);
+		TRect clip=aRect;
+		clip.Intersection(iGridRect);
+		iGc->SetClippingRect(clip);
+		DrawDraggingHighlight(line1,EDragDrawWithoutBitmap);
+		DrawDraggingHighlight(line2,EDragDrawWithBitmap);
+		DeleteGc();
+		}
+	}
+
+EXPORT_C TBool CGridImg::UpdateLabelResize(TInt aDelta)
+/** Changes the size of the row or column currently being resized.
+
+@param aDelta The amount, in pixels, by which the size of the row or column 
+is being changed.
+@return True, if a row or column is being resized; false, otherwise. */
+	{
+	if(iDragDim==ENoDrag)
+		return EFalse;
+	TRect line1 = iGridRect;
+	TRect line2 = iGridRect;
+	if (iDragDim == EXDrag)
+		{
+		TInt left=iGridLay->ColumnToXVal(iDragLabel);
+		line1.iTl.iX = line1.iBr.iX = iCurrentDragPos;
+		line2.iTl.iX = line2.iBr.iX = iCurrentDragPos =
+			Max(left,Min(iCurrentDragPos+aDelta,iGridRect.iBr.iX));
+		}
+	else
+		{
+		TInt top=iGridLay->RowToYVal(iDragLabel);
+		line1.iTl.iY = line1.iBr.iY = iCurrentDragPos;
+		line2.iTl.iY = line2.iBr.iY = iCurrentDragPos =
+			Max(top,Min(iCurrentDragPos+aDelta,iGridRect.iBr.iY));
+		}
+	if (line1!=line2)
+		{
+		CreateGc(iGc);
+		iGc->SetClippingRect(iGridRect);
+		DrawDraggingHighlight(line1,EDragDrawWithBitmap);
+		DrawDraggingHighlight(line2,EDragDrawWithBitmap);
+		DeleteGc();
+		}
+	return ETrue;
+	}
+
+EXPORT_C void CGridImg::FinishLabelResizeL(TBool aResize)
+/** Completes the resizing of a row or column.
+
+@param aResize ETrue, to complete the resizing of the row or column; EFalse, 
+if the row or column is to retain its original size. */
+	{
+	iDrawResizeLines=EFalse;
+	if(iDragDim!=ENoDrag && aResize)
+		{
+		FinishLabelDragL();
+		}
+	else if (iDragDim!=ENoDrag && !aResize)
+		{
+		TRect line1 = iGridRect;
+		TRect line2 = iGridRect;
+		if (iDragDim == EXDrag)
+			{
+			line1.iTl.iX = line1.iBr.iX = iCurrentDragPos;
+			line2.iTl.iX = line2.iBr.iX = iGridLay->ColumnToXVal(iDragLabel)-1;
+			}
+		else
+			{
+			line1.iTl.iY = line1.iBr.iY = iCurrentDragPos;
+			line2.iTl.iY = line2.iBr.iY = iGridLay->RowToYVal(iDragLabel)-1;
+			}
+		CreateGc(iGc);
+		iGc->SetClippingRect(iGridRect);
+		DrawDraggingHighlight(line1,EDragDrawWithBitmap);
+		DrawDraggingHighlight(line2,EDragDrawWithoutBitmap);
+		DeleteGc();
+		}
+	}
+
+EXPORT_C TBool CGridImg::StartLabelDrag(const TPoint& aPoint)
+/** Deals with the start of a drag operation.
+
+Typically, the function is called whan handling a pointer event in a control.
+
+The function checks that the pointer event is within 10 pixels of the boundary 
+between label cells, and draws a dotted line along the row or column boundary 
+together with pairs of arrows on either side of that line, and prepares for 
+the continuation or end of a drag operation on the boundary separating a row 
+or a column (to expand or contract that row or column).
+
+The dotted line is a visual indication that a drag operation is in progress.
+
+@param aPoint The position of the pointer event.
+@return True, if the pointer event marks the start of a drag operation, and 
+dragging is permitted; false otherwise. */
+	{
+	TBool action = EFalse;
+	TRect line1 = iGridRect;
+	TRect line2 = iGridRect;
+	TRangeRef titleRange=iGridLay->TitleRange();
+	TRangeRef visibleRange=iGridLay->VisibleRange();
+	TArrows arrows = EBothArrows;
+	if (aPoint.iY<iTitlePoint.iY-1 && !iGridLay->IsTopLabelDragDisabled())
+		{
+		TInt previous = iTitlePoint.iX-1;
+        TInt current=0;
+		if (iGridLay->IsVerticalTitleLine())
+			action = ScanColumnsForDrag(titleRange.iFrom.iCol,titleRange.iTo.iCol,aPoint.iX,previous,current);
+		if (!action)
+			action = ScanColumnsForDrag(visibleRange.iFrom.iCol,visibleRange.iTo.iCol,aPoint.iX,previous,current);
+		if (action)
+			{
+			line1.iTl.iX = line1.iBr.iX = previous;
+			line2.iTl.iX = line2.iBr.iX = iCurrentDragPos = current;
+			if (previous==current)
+				arrows=ESecondArrowOnly;
+			iDragDiff = aPoint.iX - current;
+			iDragDim = EXDrag;
+			}
+		}
+	else if (aPoint.iX<iTitlePoint.iX-1 && !iGridLay->IsSideLabelDragDisabled())
+		{
+		TInt previous = iTitlePoint.iY-1;
+		TInt current=0;
+		if (iGridLay->IsHorizontalTitleLine())
+			action = ScanRowsForDrag(titleRange.iFrom.iRow,titleRange.iTo.iRow,aPoint.iY,previous,current);
+		if (!action)
+			action = ScanRowsForDrag(visibleRange.iFrom.iRow,visibleRange.iTo.iRow,aPoint.iY,previous,current);
+		if (action)
+			{
+			line1.iTl.iY = line1.iBr.iY = previous;
+			line2.iTl.iY = line2.iBr.iY = iCurrentDragPos = current;
+			if (previous==current)
+				arrows=ESecondArrowOnly;
+			iDragDiff = aPoint.iY - current;
+			iDragDim = EYDrag;
+			}
+		}
+	if (action)
+		{
+		DrawArrowsToInMemoryBitmap(arrows);
+		CreateGc(iGc);
+		iGc->SetClippingRect(iGridRect);
+		DrawDraggingHighlight(line1,EDragDrawWithoutBitmap);
+		DrawDraggingHighlight(line2,EDragDrawWithBitmap);
+		DeleteGc();
+		}
+	return action;
+	}
+
+const TInt KDragFactor = 5;
+const TInt KMaxPenToLabel = 10;
+const TInt KMinDraggingLength = 10;
+
+TBool CGridImg::ScanColumnsForDrag(TInt aFromColumn,TInt aToColumn,TInt aPointerPos,TInt& aPrevious,TInt& aCurrent)
+	{
+	TInt ii=aFromColumn;
+	if (!iGridLay->ColumnWidthInPixels(ii-1))
+		--ii;
+	TInt width=iGridLay->ColumnWidthInPixels(ii++);
+	aCurrent=aPrevious+width;
+	TInt currentPenToLabel=(width>=KMinDraggingLength) ? Min(width/KDragFactor,(TInt)KMaxPenToLabel) : 0;
+	for (;ii<=aToColumn && aCurrent<iGridRect.iBr.iX;ii++)
+		{
+		iGridLay->StepColumnForward(ii);
+		width=iGridLay->ColumnWidthInPixels(ii);
+		TInt next=aCurrent+width;
+		TInt nextPenToLabel=(width>=KMinDraggingLength) ? Min(width/KDragFactor,(TInt)KMaxPenToLabel) : 0;
+		if (aPointerPos>aCurrent-currentPenToLabel && aPointerPos>Min(aPrevious+currentPenToLabel,aCurrent-1)
+			&& aPointerPos<aCurrent+nextPenToLabel && aPointerPos<Max(next-nextPenToLabel,aCurrent))
+			{
+			iDragLabel=ii-1;
+			if (aPointerPos<aCurrent)
+				iGridLay->StepColumnBackward(iDragLabel);
+			else if (iGridLay->ColumnWidthInPixels(iDragLabel)==0)
+				aPrevious=aCurrent;	// reopen zero width column
+			return ETrue;
+			}
+		aPrevious=aCurrent;
+		aCurrent=next;
+		currentPenToLabel=nextPenToLabel;
+		}
+	return EFalse;
+	}
+
+TBool CGridImg::ScanRowsForDrag(TInt aFromRow,TInt aToRow,TInt aPointerPos,TInt& aPrevious,TInt& aCurrent)
+	{
+	TInt ii=aFromRow;
+	if (!iGridLay->RowHeightInPixels(ii-1))
+		--ii;
+	TInt height=iGridLay->RowHeightInPixels(ii++);
+	aCurrent=aPrevious+height;
+	TInt currentPenToLabel=(height>=KMinDraggingLength) ? Min(height/KDragFactor,(TInt)KMaxPenToLabel) : 0;
+	for (;ii<=aToRow && aCurrent<iGridRect.iBr.iY;ii++)
+		{
+		iGridLay->StepRowForward(ii);
+		height=iGridLay->RowHeightInPixels(ii);
+		TInt next=aCurrent+height;
+		TInt nextPenToLabel=(height>=KMinDraggingLength) ? Min(height/KDragFactor,(TInt)KMaxPenToLabel) : 0;
+		if (aPointerPos>aCurrent-currentPenToLabel && aPointerPos>Min(aPrevious+currentPenToLabel,aCurrent-1)
+			&& aPointerPos<aCurrent+nextPenToLabel && aPointerPos<Max(next-nextPenToLabel,aCurrent))
+			{
+			iDragLabel=ii-1;
+			if (aPointerPos<aCurrent)
+				iGridLay->StepRowBackward(iDragLabel);
+			else if (iGridLay->RowHeightInPixels(iDragLabel)==0)
+				aPrevious=aCurrent;	// reopen zero height row
+			return ETrue;
+			}
+		aPrevious=aCurrent;
+		aCurrent=next;
+		currentPenToLabel=nextPenToLabel;
+		}
+	return EFalse;
+	}
+
+EXPORT_C TBool CGridImg::UpdateLabelDrag(const TPoint& aPoint)
+/** Deletes the dotted drag line and and redraws it at the new pointer position.
+
+Typically, the function is called whan handling a pointer event in a control.
+
+@param aPoint The position of the pointer event.
+@return True, if a drag operation was in progress; false, otherwise. */
+	{
+	if (iDragDim == ENoDrag)
+		return EFalse;
+	TRect line1 = iGridRect;
+	TRect line2 = iGridRect;
+	if (iDragDim == EXDrag)
+		{
+		line1.iTl.iX = line1.iBr.iX = iCurrentDragPos;
+		line2.iTl.iX = line2.iBr.iX = iCurrentDragPos = Min(aPoint.iX-iDragDiff,iGridRect.iBr.iX-1);
+		}
+	else
+		{
+		line1.iTl.iY = line1.iBr.iY = iCurrentDragPos;
+		line2.iTl.iY = line2.iBr.iY = iCurrentDragPos = Min(aPoint.iY-iDragDiff,iGridRect.iBr.iY-1);
+		}
+	if (line1!=line2)
+		{
+		CreateGc(iGc);
+		iGc->SetClippingRect(iGridRect);
+		DrawDraggingHighlight(line1,EDragDrawWithBitmap);
+		DrawDraggingHighlight(line2,EDragDrawWithBitmap);
+		DeleteGc();
+		}
+	return ETrue;
+	}
+
+void CGridImg::DrawArrowsToInMemoryBitmap(TArrows aArrows)
+	{
+	const TInt KNoOfPoints = 3;
+	CFbsBitmapDevice* bmpDevice=NULL;
+	CGraphicsContext* bmpGc=NULL;
+	delete iDragBmp;
+	iDragBmp=NULL;
+	TRAPD(err,
+		iDragBmp = new(ELeave) CFbsBitmap;
+		TSize bmpSize;
+		if (iDragDim==EXDrag)
+			bmpSize.SetSize(2*KArrowLength+KArrowSeparation,KArrowBreadth);
+		else
+			bmpSize.SetSize(KArrowBreadth,2*KArrowLength+KArrowSeparation);
+		iDragBmp->Create(bmpSize,EGray2);
+		bmpDevice = CFbsBitmapDevice::NewL(iDragBmp);
+		CleanupStack::PushL(bmpDevice);
+		User::LeaveIfError(bmpDevice->CreateContext(bmpGc));
+		CleanupStack::Pop();	// bmpDevice
+		);
+	if (err!=KErrNone)
+		{
+		delete iDragBmp;
+		iDragBmp=NULL;
+		return;		// No big deal - we just don't draw the arrows in low memory conditions
+		}
+	bmpGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+	bmpGc->SetBrushColor(KRgbBlack);
+	TPoint arrow[KNoOfPoints];
+	if (iDragDim==EXDrag)
+		{
+		if (aArrows==EBothArrows)
+			{
+			arrow[0].SetXY(KArrowLength-1,0);
+			arrow[1].SetXY(KArrowLength-1,KArrowBreadth-1);
+			arrow[2].SetXY(0,KArrowBreadth/2);
+			bmpGc->DrawPolygon(arrow,KNoOfPoints);
+			}
+		arrow[0].SetXY(KArrowLength+KArrowSeparation,0);
+		arrow[1].SetXY(arrow[0].iX,KArrowBreadth-1);
+		arrow[2].SetXY(arrow[1].iX+KArrowLength,KArrowBreadth/2);
+		bmpGc->DrawPolygon(arrow,KNoOfPoints);
+		}
+	else
+		{
+		if (aArrows==EBothArrows)
+			{
+			arrow[0].SetXY(KArrowBreadth/2,0);
+			arrow[1].SetXY(0,KArrowLength-1);
+			arrow[2].SetXY(KArrowBreadth-1,KArrowLength-1);
+			bmpGc->DrawPolygon(arrow,KNoOfPoints);
+			}
+		arrow[0].SetXY(0,KArrowLength+KArrowSeparation);
+		arrow[1].SetXY(KArrowBreadth-1,arrow[0].iY);
+		arrow[2].SetXY(KArrowBreadth/2,arrow[1].iY+KArrowLength);
+		bmpGc->DrawPolygon(arrow,KNoOfPoints);
+		}
+	delete bmpGc;
+	delete bmpDevice;
+	}
+
+void CGridImg::DrawDraggingHighlight(const TRect aLine,TDragDraw aDragDraw)
+	{
+	__ASSERT_DEBUG(iGcPtr==iGc,Panic(EGridImgInvalidGC));	// Can only call this using internal GC
+	iGc->SetDrawMode(CGraphicsContext::EDrawModeNOTXOR);
+	iGc->SetPenStyle(CGraphicsContext::EDottedPen);
+	iGc->DrawLine(aLine.iTl,aLine.iBr);
+	if (aDragDraw==EDragDrawWithoutBitmap || !iDragBmp)
+		return;
+	
+	const TInt KNoOfArrowsToDisplay = 4;
+	const TInt KMinArrowSeparation = 25;
+	TSize bmpSize=iDragBmp->SizeInPixels();
+	if (iDragDim==EXDrag)
+		{
+		TInt separation=Max((aLine.iBr.iY-iTitlePoint.iY)/KNoOfArrowsToDisplay,KMinArrowSeparation);
+		TPoint point(aLine.iTl.iX-bmpSize.iWidth/2,iTitlePoint.iY+(separation-bmpSize.iHeight)/2);
+		while (point.iY<aLine.iBr.iY-separation/2)
+			{
+			iGc->BitBlt(point,iDragBmp);
+			point.iY+=separation;
+			}
+		}
+	else
+		{
+		TInt separation=Max((aLine.iBr.iX-iTitlePoint.iX)/KNoOfArrowsToDisplay,KMinArrowSeparation);
+		TPoint point(iTitlePoint.iX+(separation-bmpSize.iWidth)/2,aLine.iTl.iY-bmpSize.iHeight/2);
+		while (point.iX<aLine.iBr.iX-separation/2)
+			{
+			iGc->BitBlt(point,iDragBmp);
+			point.iX+=separation;
+			}
+		}
+	}
+
+EXPORT_C void CGridImg::ScrollL(const TPoint &aOffset)
+/** Scrolls the grid by the specified number of pixels.
+
+Draws the minimum necessary, i.e. grid labels, grid lines, grid cells, selected 
+regions and the cursor.
+
+@param aOffset Scroll offset, in pixels. */
+	{
+	if (!aOffset.iY && !aOffset.iX)
+		return;
+	TRect scrollRect;
+	TRect validRect;
+	TRegionFix<4> region;
+	if (aOffset.iX)
+		{
+		scrollRect=iGridRect;
+		scrollRect.iTl.iX=iMainPoint.iX;
+		validRect=scrollRect;
+		if (aOffset.iX>0)
+			validRect.iBr.iX = Min(validRect.iBr.iX,validRect.iTl.iX+aOffset.iX);
+		else
+			validRect.iTl.iX = Max(validRect.iTl.iX,validRect.iBr.iX+aOffset.iX);
+		iWin->Scroll(scrollRect, TPoint(aOffset.iX,0));
+		region.AddRect(validRect);
+		}
+	if (aOffset.iY)
+		{
+		scrollRect=iGridRect;
+		scrollRect.iTl.iY=iMainPoint.iY;
+		validRect=scrollRect;
+		if (aOffset.iY>0)
+			validRect.iBr.iY = Min(validRect.iBr.iY,validRect.iTl.iY+aOffset.iY);
+		else
+			validRect.iTl.iY = Max(validRect.iTl.iY,validRect.iBr.iY+aOffset.iY);
+		iWin->Scroll(scrollRect, TPoint(0,aOffset.iY));
+		region.AddRect(validRect);
+		}
+	region.Tidy();
+	TInt end=region.Count();
+	for (TInt ii=0;ii<end;ii++)
+		{
+		TRect rect=region[ii];
+		BeginRedrawAndDrawL(rect);
+		}
+	CheckSideLabelWidthAndScrollL();
+	}
+#endif
+
+EXPORT_C void CGridImg::SetGridRect(const TRect& aNewRect)
+/** Sets the rectangle that is to contain the grid.
+
+@param aNewRect The rectangle that is to contain the grid. */
+	{
+	iGridRect = aNewRect;
+	ResetReferencePoints();
+	}
+
+EXPORT_C void CGridImg::SetPrintGridRect(const TRect& aPrintGridRect)
+/** Sets the rectangle that is to contain the grid for the purpose of printing.
+
+@param aPrintRect The rectangle that is to contain the grid. */
+	{
+	iGridRect=aPrintGridRect;
+	iTitlePoint=iGridRect.iTl;
+	if (iGridLay->IsPrintedLabels())
+		{
+		if (iGridLay->IsSideLabels())
+			iTitlePoint.iX+=MaxSideLabelWidthInPixels();
+		if (iGridLay->IsTopLabels())
+			iTitlePoint.iY+=TopLabelHeightInPixels();
+		}
+	iMainPoint=iTitlePoint;
+	}
+
+EXPORT_C void CGridImg::ResetReferencePoints()
+/** Resets the reference points.
+
+The reference points are the mainpoint and the titlepoint, i.e the point at 
+which the visible range starts, and the point at the top left of the grid 
+not including the labels. */
+	{
+	iTitlePoint=iGridRect.iTl;
+	if (iGridLay->IsSideLabels())
+		iTitlePoint.iX+=SideLabelWidthInPixels();
+	if (iGridLay->IsTopLabels())
+		iTitlePoint.iY+=TopLabelHeightInPixels();
+	iMainPoint=iTitlePoint+iGridLay->TopLeftTitleRangeSize();
+	}
+
+EXPORT_C void CGridImg::NotifyGridRangeResize()
+/** Resets the region boundary to the grid boundary. */
+	{
+	iGridLay->LimitCell(iCursorPos);
+	iGridLay->LimitCell(iAnchorPos);
+	iSelected->ResizeBounds(iGridLay->iGridRange.iTo);
+	}
+
+//->
+EXPORT_C void CGridImg::SetGridLabelImg(CGridLabelImg* aGridLabelImg)
+/** Sets an object that draws a cell label.
+
+@param aGridLabelImg A pointer to an object that draws a cell label. */
+	{
+	iGridLabelImg =  aGridLabelImg;
+	if (aGridLabelImg && iGridLay)
+		aGridLabelImg->SetGridColors(iGridLay->GridColors());
+	}
+
+void CGridImg::SetGridColors(const TGridColors& aGridColors)
+	{
+	iGridLabelImg->SetGridColors(aGridColors);
+	iGridCellImg->SetGridColors(aGridColors);
+	}
+//->