// EIKWSEL.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikwsel.h>
#include <eikwsel.hrh>
#include <eikpanic.h>
#include <e32keys.h>
#include <barsread.h>
#include <eikenv.h>
#include <eikcolor.h>

const TInt KWorldMinCursorWidth=2;
const TInt KSearchStateTextSpace=2;
#define KWorldNameTooLong _L("…")

class CEikWorldModel: public CBase
	{
public:
	enum TFindAdjacent 
		{
		EFindPrevious,
		EFindNext
		};
	enum TFindExtreme
		{
		EFindFirst,
		EFindLast
		};
private:
	struct SSearchStateText
		{
		HBufC* iSearchWithinCountry;
		HBufC* iSearchWithinWorld;
		};
public:
	CEikWorldModel();
	~CEikWorldModel();
	void ConstructL();
	TBool FindExtreme(TWorldSelectorType aSelectorType,TFindExtreme aExtreme);
	TBool FindAdjacent(TWorldSelectorType aSelectorType,TFindAdjacent aAdjacent);
	TBool FindMatching(TWorldSelectorType aSelectorType);
	void SetSearchStateTextL(TWorldSelectorType aSelector,TWldSelect aSearchExtent,const TDesC& aDes);
	const TDesC* SearchStateText(TWorldSelectorType aSelector,TWldSelect aSearchExtent) const;
	void SetSearchExtentL(TWldSelect aSearchExtent);
	inline TWldSelect SearchExtent() const;
	void ResetMatcher();
	void SetMatcherToText(TWorldSelectorType aSelectorType);
	TBool MatchAdditionalChar(TWorldSelectorType aSelectorType,TChar aChar);
	void DeleteLastChar(TWorldSelectorType aSelectorType);
	void SetMatcherTextL(const TDesC& aDes);
    void GetState(SWorldSelectorState& aState) const;
    TInt SetStateL(const SWorldSelectorState& aState);
	inline const TDesC& CurrentItemText(TWorldSelectorType aWorldType) const;
	inline TInt CursorPos() const;
	inline TBool StateChanged() const;
	inline void SetStateChanged();
	inline void ResetStateChanged();
private:
	void SetWorldItem(const TWorldId& anItem,TWorldSelectorType aSelectorType);
	inline const TWorldId& CurrentWorldItem() const;
private:
	SSearchStateText iCountrySearchStateText;
	SSearchStateText iCitySearchStateText;
	RIncrMatcherBase* iIncrMatcher;
	RWorldServer iWorldServer;
	TWorldId iCurrentItemID;
	TBool iChangeStatus;
	};

//
//	CEikWorldModel
//

inline TInt CEikWorldModel::CursorPos() const
	{
	return iIncrMatcher->MatchLength();
	}
inline const TDesC& CEikWorldModel::CurrentItemText(TWorldSelectorType aSelector) const
	{
	return((aSelector==EWorldSelectorTypeCity)? CurrentWorldItem().City() : CurrentWorldItem().Country());
	}
inline const TWorldId& CEikWorldModel::CurrentWorldItem() const
	{
	return(iCurrentItemID);
	}
inline TWldSelect CEikWorldModel::SearchExtent() const
	{
	return(iCurrentItemID.Select());
	}
inline void CEikWorldModel::SetStateChanged()
	{
	iChangeStatus=ETrue;
	}
inline void CEikWorldModel::ResetStateChanged()
	{
	iChangeStatus=EFalse;
	}
inline TBool CEikWorldModel::StateChanged() const
	{
	return(iChangeStatus);
	}

//
//	class CEikWorldSelector
//

EXPORT_C CEikWorldSelector::CEikWorldSelector()
//
// Constructor
//
	{
	__DECLARE_NAME(_S("CEikWorldSelector"));
    iBorder=TEikBorder(TEikBorder::ESingleGray);
	}

EXPORT_C CEikWorldSelector::~CEikWorldSelector()
//
//	Destructor
//
	{
	if (iOwnsController)
		delete iController;
	}

EXPORT_C void CEikWorldSelector::SetContainerWindowL(const CCoeControl& aParent)
//
//	Set the parent window
//
	{
	iParent=&aParent;
	CCoeControl::SetContainerWindowL(aParent);
	}

EXPORT_C void CEikWorldSelector::ConstructL(CCoeControl& aParent,TBool aWithBorder,TWorldSelectorType aSelectorType)
//
//	Constructs first world selector without resource and builds controller
//
	{
	SetContainerWindowL(aParent);
	if (aWithBorder==EFalse)
		iBorder.SetType(TEikBorder::ENone);
	iSelectorType=aSelectorType;
	iController=CEikWorldController::NewL(aParent,*iCoeEnv,*this,aWithBorder);
	iOwnsController=ETrue;
	}

EXPORT_C void CEikWorldSelector::ConstructSelectorPairL(CEikWorldSelector& aFirstSelector)
//
//	Links to controller of first world selector
//
	{
	CEikWorldController* controller=aFirstSelector.Controller();
	__ASSERT_ALWAYS(controller,Panic(EEikPanicNullPointer));
	iSelectorType=(aFirstSelector.Type()==EWorldSelectorTypeCity)?EWorldSelectorTypeCountry:EWorldSelectorTypeCity;
	controller->SetSecondSelector(*this);
	iController=controller;
	SetContainerWindowL(*(controller->Client()));
	if (!(iController->Border()))
		iBorder.SetType(TEikBorder::ENone);
	}

EXPORT_C void CEikWorldSelector::SetNeighbor(CCoeControl* aNeighbor)
//
//	Get pointer to dialog item above this one
//
	{
	iPrevious=aNeighbor;
	}


EXPORT_C void CEikWorldSelector::ConstructFromResourceL(TResourceReader& aReader)
//
// construct from resource for e.g dialogs
//
	{
	TInt flags=aReader.ReadInt16();
	TInt widthInChars=aReader.ReadInt16();
	CEikWorldController* controller=NULL;
	CEikWorldSelector* pair=NULL;
	if ((iPrevious)&&(flags&EEikWorldSelSecondSelector))
		{
		pair=(CEikWorldSelector* )iPrevious;
		iSelectorType=(pair->Type()==EWorldSelectorTypeCity)?EWorldSelectorTypeCountry:EWorldSelectorTypeCity;
		controller=pair->Controller();
		__ASSERT_ALWAYS(controller,Panic(EEikPanicNullPointer));
		iController=controller;
		iController->SetSecondSelector(*this);
		}
	else 	//Must be first or only selector control: build own controller
		{
		TBool withBorder=ETrue;
		if (flags&EEikWorldSelNoBorder)
			withBorder=EFalse;
		if (flags&EEikWorldSelCountrySelector)
			iSelectorType=EWorldSelectorTypeCountry;
		else
			iSelectorType=EWorldSelectorTypeCity;
		iController=CEikWorldController::NewL(*iParent,*iCoeEnv,*this,withBorder);
		if (widthInChars>0)
			iController->SetSelectorWidthInCharacters(widthInChars);
		iOwnsController=ETrue;
		}
	if (!(iController->Border()))
		iBorder.SetType(TEikBorder::ENone);
	TPtrC ptr=aReader.ReadTPtrC();
	iController->SetSearchStateTextL(Type(),EWithinCountry,ptr);
	ptr.Set(aReader.ReadTPtrC());
	iController->SetSearchStateTextL(Type(),EWithinWorld,ptr);
	}

EXPORT_C TSize CEikWorldSelector::MinimumSize()
//
// returns the minimum size needed to display
//
	{
	TInt widthInChars=iController->SelectorWidthInCharacters();
	TSize size=iBorder.SizeDelta();
	const CFont* font;
	if (iController&&iController->Font())
		font=iController->Font();
	else
		font=iCoeEnv->NormalFont();
	size.iHeight+=font->HeightInPixels();
	size.iWidth+=(font->MaxNormalCharWidthInPixels()*widthInChars); 
	return size;
	}

EXPORT_C TKeyResponse CEikWorldSelector::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode /*aType*/)
//
// Respond to key presses
//
	{
	return(iController->HandleKeyEventL(aKeyEvent,*this));
	}

EXPORT_C void CEikWorldSelector::HandleStateChangeL()
//
//	Performs necessary actions when state has changed
//
	{
	DrawNow();
	DisplayCursor();
	ReportEventL(MCoeControlObserver::EEventStateChanged);
	}

EXPORT_C void CEikWorldSelector::FocusChanged(TDrawNow aDrawNow)
//
// Draw or remove cursor as required depending on whether we have the focus
//
    {
	if (aDrawNow==ENoDrawNow)
		return;
	iController->ResetMatcher();
    if (IsFocused())
        DisplayCursor();
    else 
		iEikonEnv->HideCursor(this);
    }

EXPORT_C void CEikWorldSelector::Draw(const TRect& /*aRect*/) const
//
// Draw the whole selector
//
	{
	iBorder.Draw(SystemGc(),Rect());
	DrawSearchStateText();
    DrawSelector();
	DisplayCursor();
	}

void CEikWorldSelector::DrawSelector() const
//
//	Draws city/country name text in a rect.
//	Item name truncated by execess if item name and search state text
//	together exceed width of selector rect.
//
	{
	const CFont* font=iController->Font();
	TPtrC text=(iController->CurrentItemText(Type()));
	TRect rect=iBorder.InnerRect(Rect());
	TInt textWidth=font->TextWidthInPixels(text);
	TInt searchStateTextWidth=font->TextWidthInPixels(iController->SearchStateText(Type()));
	if (searchStateTextWidth&&searchStateTextWidth+KSearchStateTextSpace<rect.Width())	//Search state text not drawn if as wide or wider than selector
		rect.iBr.iX-=searchStateTextWidth+KSearchStateTextSpace;						//Narrow rect by width of search state text;
	if (textWidth>rect.Width())
		{
		TPtrC worldNameTooLong(KWorldNameTooLong);
		TInt availableTextWidth=rect.Width()-font->TextWidthInPixels(worldNameTooLong);
		TInt visibleCharacters=font->TextCount(text,availableTextWidth);
		TInt actualTextWidth=font->TextWidthInPixels(text.Left(visibleCharacters));
		TRect worldNameTooLongRect=rect;
		worldNameTooLongRect.iTl.iX+=actualTextWidth;
		DrawTextInRect(worldNameTooLong,worldNameTooLongRect,CGraphicsContext::ELeft);
		rect.iBr.iX-=worldNameTooLongRect.Width();
		}
	DrawTextInRect(text,rect,CGraphicsContext::ELeft);
	}

void CEikWorldSelector::DrawSearchStateText() const
//
//	Draws search state text in a rect.
//
	{
	TRect rect=iBorder.InnerRect(Rect());
	if (rect.Width()==0)
		return;
	const CFont* font=iController->Font();
	TPtrC text=(iController->SearchStateText(Type()));
	TInt textWidth=font->TextWidthInPixels(text);
	if (!textWidth||(textWidth+KSearchStateTextSpace>=rect.Width()))
		return;	 //Search state text not drawn if as wide or wider than selector
	TInt textOffset=rect.Width()-textWidth-KSearchStateTextSpace;
	rect.iTl.iX+=textOffset;
	DrawTextInRect(text,rect,CGraphicsContext::ELeft);
	}

void CEikWorldSelector::DrawTextInRect(TDesC& aText,TRect aRect,CGraphicsContext::TTextAlign aHoriz) const
//
// Does set up for drawing and draws
//
	{
	CWindowGc& gc=SystemGc();
	const CFont* font=iController->Font();
	TInt excessHeight=(aRect.Height()-font->HeightInPixels())/2;
	gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc.SetPenColor(iEikonEnv->ControlColor(EEikColorWindowText,*this));
	gc.SetBrushColor(iEikonEnv->ControlColor(EEikColorWindowBackground,*this)); // KEikWorldSelectorBackGroundColor
    gc.UseFont(font);
	gc.DrawText(aText,aRect,(font->AscentInPixels()+excessHeight),aHoriz,0);
	}

void CEikWorldSelector::DisplayCursor()	const
//
// Draw the cursor at the appropriate position
//
    {
    if (!IsFocused())
        return;
	const CFont* font=iController->Font();
    TPoint cursorTL=Position();
    TMargins margins=iBorder.Margins();
    cursorTL.iX+=margins.iLeft;
    cursorTL.iY+=margins.iTop;
	TPtrC text=(iController->CurrentItemText(Type()));
	TInt cursorPos=iController->CursorPos();
	TPtrC stringBeforeCursor=text.Left(cursorPos);
	cursorTL.iX+=font->TextWidthInPixels(stringBeforeCursor);
	TInt cursorWidth=KWorldMinCursorWidth;
	if (text.Length()>cursorPos)
		cursorWidth=font->TextWidthInPixels(text.Mid(cursorPos,1));
	TInt ascent=font->AscentInPixels();
	cursorTL.iY+=ascent;

	const TRect rect=iBorder.InnerRect(Rect());
	if ((cursorTL.iX + cursorWidth) >= rect.iBr.iX)
		{
		iController->WorldModel()->DeleteLastChar(iSelectorType);
		--cursorPos;
		TPtrC maxStringAllowed=text.Left(cursorPos);
		cursorTL.iX=Position().iX + font->TextWidthInPixels(maxStringAllowed);
		return;
		}
    iEikonEnv->DrawCursor(this,cursorTL,cursorWidth,ascent,font->HeightInPixels());
    }

//
//	CEikWorldController
//

EXPORT_C CEikWorldController* CEikWorldController::NewL(const CCoeControl& aClient,CCoeEnv& aEnv,CEikWorldSelector& aSelector,TBool aWithBorder)
//
//	Public c'tor
//
	{
	CEikWorldController* This=new(ELeave) CEikWorldController;
	CleanupStack::PushL(This);
	This->ConstructL(aClient,aEnv,aSelector,aWithBorder);
	CleanupStack::Pop();
	return(This);
	}

CEikWorldController::CEikWorldController()
//
//	Private c'tor
//
	{
	__DECLARE_NAME(_S("CEikWorldController"));
	}

EXPORT_C CEikWorldController::~CEikWorldController()
//
//	Destructor
//
	{
	delete iWorldModel;
	}

void CEikWorldController::ConstructL(const CCoeControl& aClient,CCoeEnv& aEnv,CEikWorldSelector& aSelector,TBool aWithBorder)
//
//	Initialise world controller
//
	{
	iEnv=&aEnv;
	iFont=iEnv->NormalFont();
	iSelectorWidthInCharacters=KMaxCountryName;
	iWithBorder=aWithBorder;
	__ASSERT_ALWAYS(!(iCountrySelector||iCitySelector),Panic(EEikPanicWorldControllerDuplicateSelector));
	iClient=&aClient;
	if (aSelector.Type()==EWorldSelectorTypeCountry)
		iCountrySelector=&aSelector;
	else
		iCitySelector=&aSelector;
	iWorldModel=new(ELeave)CEikWorldModel;
	iWorldModel->ConstructL();
	}

EXPORT_C void CEikWorldController::SetSecondSelector(CEikWorldSelector& aSecondSelector)
//
//	Add second selector to form coordinated pair
//
	{
	__ASSERT_ALWAYS(!(iCountrySelector&&iCitySelector),Panic(EEikPanicWorldControllerDuplicateSelector));
	if (!iCountrySelector)
		iCountrySelector=&aSecondSelector;
	else if (!iCitySelector)
		iCitySelector=&aSecondSelector;
	else
		Panic(EEikPanicWorldControllerDuplicateSelector);
	}

EXPORT_C TKeyResponse CEikWorldController::HandleKeyEventL(const TKeyEvent& aKeyEvent,CEikWorldSelector& aSelector)
//
// Handles key events
//
	{
	TKeyResponse keyConsumed=EKeyWasNotConsumed;
	TWorldSelectorType selectorType=aSelector.Type();
	if (aKeyEvent.iModifiers&EModifierCtrl)
		{
		switch (aKeyEvent.iCode)
			{
		case EKeyHome:
			iWorldModel->FindExtreme(selectorType,CEikWorldModel::EFindFirst);
			keyConsumed=EKeyWasConsumed;
			break;
		case EKeyEnd:
			iWorldModel->FindExtreme(selectorType,CEikWorldModel::EFindLast);
			keyConsumed=EKeyWasConsumed;
			break;
		default:
			break;
			}
		}
	else
		keyConsumed=DoUnmodifiedKeys(aKeyEvent,selectorType);
	if (keyConsumed)
		HandleChangesL();
	return keyConsumed;
	}

TKeyResponse CEikWorldController::DoUnmodifiedKeys(const TKeyEvent& aKeyEvent,TWorldSelectorType aSelectorType)
//
// Deals with unmodified keys
//
	{
	TKeyResponse keyConsumed=EKeyWasNotConsumed;
	TBool retVal=ETrue;
	switch (aKeyEvent.iCode)
		{
	case EKeyLeftArrow:
		retVal=iWorldModel->FindAdjacent(aSelectorType,CEikWorldModel::EFindPrevious);
		if (!retVal)
			retVal=iWorldModel->FindExtreme(aSelectorType,CEikWorldModel::EFindLast);
		keyConsumed=EKeyWasConsumed;
		break;
	case EKeyRightArrow:
		retVal=iWorldModel->FindAdjacent(aSelectorType,CEikWorldModel::EFindNext);
		if (!retVal)
			retVal=iWorldModel->FindExtreme(aSelectorType,CEikWorldModel::EFindFirst);
		keyConsumed=EKeyWasConsumed;
		break;
	case EKeyBackspace:
		iWorldModel->DeleteLastChar(aSelectorType);
		keyConsumed=EKeyWasConsumed;
		break;
	case EKeyHome:
		iWorldModel->ResetMatcher();
		keyConsumed=EKeyWasConsumed;
		break;
	case EKeyEnd:
		iWorldModel->SetMatcherToText(aSelectorType);
		keyConsumed=EKeyWasConsumed;
		break;
	default:
		if (!(aKeyEvent.iModifiers&EModifierCtrl)&&TChar(aKeyEvent.iCode).IsPrint())
			{
			if(iWorldModel->MatchAdditionalChar(aSelectorType,aKeyEvent.iCode))
				keyConsumed=EKeyWasConsumed;
			}
		break;
		}
	return keyConsumed;
	}

void CEikWorldController::HandleChangesL()
//
//	Initiates drawing if changes have occurred
//
	{
	if (!(iWorldModel->StateChanged()))
		return;
	if (iCitySelector)
		iCitySelector->HandleStateChangeL();
	if (iCountrySelector)
		iCountrySelector->HandleStateChangeL();
	iWorldModel->ResetStateChanged();
	}

EXPORT_C TPtrC CEikWorldController::SearchStateText(TWorldSelectorType aSelectorType) const
//
//	Returns search state text according to current search extent and type of selector
//
	{
	TPtrC retPtr;
	const TDesC* text=iWorldModel->SearchStateText(aSelectorType,(iWorldModel->SearchExtent()));
	if (text)
		retPtr.Set(*text);
	return (retPtr);
	}

EXPORT_C void CEikWorldController::SetFontL(const CFont* aFont)
//
//	Store font. If pointer is null use the normal font
//
	{
	if (aFont)
		{
		iFont=aFont;
		iWorldModel->SetStateChanged();
		HandleChangesL();
		}
	else 
		iFont=iEnv->NormalFont();
	}

EXPORT_C void CEikWorldController::SetSearchExtentL(TWldSelect aSearchExtent)
//
//	Set current search extent
//
	{
	iWorldModel->SetSearchExtentL(aSearchExtent);
	HandleChangesL();
	}

EXPORT_C TInt CEikWorldController::SetStateL(const SWorldSelectorState& aState)
//
//	Set selector state
//
	{
	TInt ret=iWorldModel->SetStateL(aState);
	if (ret==KErrNone)
		HandleChangesL();
	return ret;
	}
	 
EXPORT_C TWldSelect CEikWorldController::SearchExtent() const
	{
	return iWorldModel->SearchExtent();
	}

EXPORT_C TInt CEikWorldController::CursorPos() const
	{
	return iWorldModel->CursorPos();
	}

EXPORT_C void CEikWorldController::ResetMatcher()
	{
	iWorldModel->ResetMatcher();
	}

EXPORT_C void CEikWorldController::GetState(SWorldSelectorState& aState) const
	{
	iWorldModel->GetState(aState);
	}

EXPORT_C TPtrC CEikWorldController::CurrentItemText(TWorldSelectorType aSelectorType) const
	{
	return (iWorldModel->CurrentItemText(aSelectorType));
	}

EXPORT_C void CEikWorldController::SetSearchStateTextL(TWorldSelectorType aSelectorType,TWldSelect aSearchExtent,const TDesC& aDes)
	{
	iWorldModel->SetSearchStateTextL(aSelectorType,aSearchExtent,aDes);
	}

EXPORT_C void CEikWorldController::SetSelectorWidthInCharacters(TInt aWidthInChars)
	{
	iSelectorWidthInCharacters=aWidthInChars;
	}

//
// class CEikWorldModel: public CBase
//

CEikWorldModel::CEikWorldModel()
//
//	Constructor
//
	{
	__DECLARE_NAME(_S("CEikWorldModel"));
	}

CEikWorldModel::~CEikWorldModel()
//
//	Destructor
//
	{
	iWorldServer.Close();
	delete iIncrMatcher;
	delete iCitySearchStateText.iSearchWithinCountry;
	delete iCitySearchStateText.iSearchWithinWorld;
	delete iCountrySearchStateText.iSearchWithinCountry;
	delete iCountrySearchStateText.iSearchWithinWorld;
	}

void CEikWorldModel::ConstructL()
//
//	Connects to world server and sets initial data
//
	{
	User::LeaveIfError(iWorldServer.Connect());
	iCurrentItemID.SetSelect(EWithinWorld);
	iWorldServer.FirstCity(iCurrentItemID);
	iIncrMatcher=new(ELeave) RIncrMatcherTextBuf;
	((RIncrMatcherTextBuf*)iIncrMatcher)->SetMatcherLengthL(Max(KMaxCityName,KMaxCountryName)+1);
	// the +1 allows for the cursor to go past the last character
	iIncrMatcher->Clear();
	}

TBool CEikWorldModel::FindExtreme(TWorldSelectorType aSelectorType,TFindExtreme aExtreme)
//
//	Find the first/last city/country
//
	{
	TWorldId id;
	id=CurrentWorldItem();
	id.SetSelect(SearchExtent());
	TInt find=KErrGeneral;
	if (aSelectorType==EWorldSelectorTypeCountry)
		find=(aExtreme==EFindFirst)? iWorldServer.FirstCountry(id) : iWorldServer.LastCountry(id);
	else
		find=(aExtreme==EFindFirst)? iWorldServer.FirstCity(id) : iWorldServer.LastCity(id);
	if (find==KErrNone)
		{
		ResetMatcher();
		SetWorldItem(id,aSelectorType);
		return(ETrue);
		}
	return(EFalse);
	}

TBool CEikWorldModel::FindAdjacent(TWorldSelectorType aSelectorType,TFindAdjacent aAdjacent)
//
//	Find the previous or the next city/country
//
	{
	TWorldId id;
	id=CurrentWorldItem();
	id.SetSelect(SearchExtent());
	TInt find=KErrGeneral;
	if (aSelectorType==EWorldSelectorTypeCountry)
		find=(aAdjacent==EFindNext)? iWorldServer.NextCountry(id) : iWorldServer.PrevCountry(id);
	else
		find=(aAdjacent==EFindNext)? iWorldServer.NextCity(id) : iWorldServer.PrevCity(id);
	if (find==KErrNone)
		{
		ResetMatcher();
		SetWorldItem(id,aSelectorType);
		return(ETrue);
		}
	return(EFalse);
	}

TBool CEikWorldModel::FindMatching(TWorldSelectorType aSelectorType)
//
//	Find the first city that matches the incremental buffer
//
	{
	TInt find=KErrGeneral;
	TWorldId id;
	id=CurrentWorldItem();
	id.SetSelect(SearchExtent());
	if (aSelectorType==EWorldSelectorTypeCountry)
		find=iWorldServer.FindCountry(id,iIncrMatcher->MatchText());
	else
		{
		if (SearchExtent()==EWithinWorld)
			find=iWorldServer.FindCity(id,iIncrMatcher->MatchText());  
		else
			{
			find=iWorldServer.FirstCity(id);
			while (find==KErrNone)
				{
				if (iIncrMatcher->IsMatchF(id.City()))
					break;
				else
					find=iWorldServer.NextCity(id);
				}
			}
		}
	if (find==KErrNone)
		{
		SetWorldItem(id,aSelectorType);
		return(ETrue);
		}
	SetStateChanged();
	iIncrMatcher->DeleteLastChar();
	iIncrMatcher->SetBestMatchF(CurrentItemText(aSelectorType));
	return(EFalse);
	}

void CEikWorldModel::SetSearchStateTextL(TWorldSelectorType aSelector,TWldSelect aSearchExtent,const TDesC& aDes)
//
//	Set the text to be displayed under specific search conditions
//
	{
	SSearchStateText& search=(aSelector==EWorldSelectorTypeCity)?iCitySearchStateText:iCountrySearchStateText;
	HBufC*& buf=(aSearchExtent==EWithinWorld)? search.iSearchWithinWorld:search.iSearchWithinCountry;
	delete buf;
	buf=NULL;
	if (aDes.Length()>0)
		buf=aDes.AllocL();
	}

const TDesC* CEikWorldModel::SearchStateText(TWorldSelectorType aSelector,TWldSelect aSearchExtent) const
//
//	Get the specified search text
//
	{
	const SSearchStateText& search=(aSelector==EWorldSelectorTypeCity)? iCitySearchStateText : iCountrySearchStateText;
	return((aSearchExtent==EWithinWorld)? search.iSearchWithinWorld : search.iSearchWithinCountry);
	}

void CEikWorldModel::SetSearchExtentL(TWldSelect aSearchExtent)
//
//	Set the search method for the control
//
	{
	TWldSelect search=SearchExtent();
	if (search!=aSearchExtent)
		{
		iCurrentItemID.SetSelect(aSearchExtent);
		SetStateChanged();
		}
	}

void CEikWorldModel::ResetMatcher()
//
//	Clear the text in the incremental matcher
//
	{
	SetStateChanged();
	iIncrMatcher->Clear();
	}

void CEikWorldModel::SetWorldItem(const TWorldId &anItem,TWorldSelectorType aSelectorType)
//
//	Set the current item
//
	{
	TBool changed=EFalse;
	if (anItem.City()!=CurrentWorldItem().City())
		changed=ETrue;
	if (anItem.Country()!=CurrentWorldItem().Country())
		changed=ETrue;
	if (anItem.Select()!=CurrentWorldItem().Select())
		changed=ETrue;
	if (changed)
		{
		iCurrentItemID=anItem;
		iIncrMatcher->SetBestMatchF(CurrentItemText(aSelectorType));
		SetStateChanged();
		}
	}

void CEikWorldModel::GetState(SWorldSelectorState& aState) const
//
//	Get the current state
//
	{
	aState.iCity=CurrentWorldItem().City();
	aState.iCountry=CurrentWorldItem().Country();
	aState.iSearch=CurrentWorldItem().Select();
	}

TInt CEikWorldModel::SetStateL(const SWorldSelectorState& aState)
//
//	Set the current state
//
	{
	//Check that the new seletor state is valid
	TInt ret=0;
	TWorldId newID;
	if (iWorldServer.Find(newID,aState.iCity,aState.iCountry)!=KErrNone)
		return KErrGeneral;
	newID.SetSelect(aState.iSearch);
	//Change current selector state to new selector state
	iIncrMatcher->Clear();
	SetWorldItem(newID,EWorldSelectorTypeCity);
	return ret;
	}
	  
void CEikWorldModel::SetMatcherToText(TWorldSelectorType aSelectorType)
//
//	Sets text in the incremental matcher to whole of current item
//
	{
	iIncrMatcher->SetMatchText(CurrentItemText(aSelectorType));
	SetStateChanged();
	}

void CEikWorldModel::SetMatcherTextL(const TDesC& aDes)
//
//	Set the text to be displayed under specific search conditions
//
	{
	iIncrMatcher->SetMatchText(aDes);
	}

TBool CEikWorldModel::MatchAdditionalChar(TWorldSelectorType aSelectorType,TChar aChar)
//
//	Interpret a key stroke for incremental matching
//
	{
	aChar.Fold();
	if (iIncrMatcher->MatchLength()>iIncrMatcher->MaxLength()-2)
		return(ETrue); // !! may want to Alert() the user here
	iIncrMatcher->AppendChar(aChar);
	SetStateChanged();
	if (iIncrMatcher->IsMatchF(CurrentItemText(aSelectorType)))
		return(ETrue);
	return(FindMatching(aSelectorType));
	}

void CEikWorldModel::DeleteLastChar(TWorldSelectorType aSelectorType)
//
//	Unwind selection by one character
//
	{
	SetStateChanged();
	iIncrMatcher->DeleteLastChar();
	FindMatching(aSelectorType);
	}

