bool CGUIDialogSmartPlaylistEditor::OnMessage(CGUIMessage& message)
{
  switch ( message.GetMessage() )
  {
  case GUI_MSG_CLICKED:
    {
      int iControl = message.GetSenderId();
      int iAction = message.GetParam1();
      if (iControl == CONTROL_RULE_LIST && (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK))
        OnRuleList(GetSelectedItem());
      else if (iControl == CONTROL_RULE_ADD)
        OnRuleAdd();
      else if (iControl == CONTROL_RULE_EDIT)
        OnRuleList(GetSelectedItem());
      else if (iControl == CONTROL_RULE_REMOVE)
        OnRuleRemove(GetSelectedItem());
      else if (iControl == CONTROL_NAME)
        OnEditChanged(iControl, m_playlist.m_playlistName);
      else if (iControl == CONTROL_OK)
        OnOK();
      else if (iControl == CONTROL_CANCEL)
        OnCancel();
      else if (iControl == CONTROL_MATCH)
        OnMatch();
      else if (iControl == CONTROL_LIMIT)
        OnLimit();
      else if (iControl == CONTROL_ORDER_FIELD)
        OnOrder();
      else if (iControl == CONTROL_ORDER_DIRECTION)
        OnOrderDirection();
      else if (iControl == CONTROL_TYPE)
        OnType();
      else if (iControl == CONTROL_GROUP_BY)
        OnGroupBy();
      else if (iControl == CONTROL_GROUP_MIXED)
        OnGroupMixed();
      else
        return CGUIDialog::OnMessage(message);
      return true;
    }
    break;
  case GUI_MSG_FOCUSED:
    if (message.GetControlId() == CONTROL_RULE_REMOVE ||
        message.GetControlId() == CONTROL_RULE_EDIT)
      HighlightItem(GetSelectedItem());
    else
    {
      if (message.GetControlId() == CONTROL_RULE_LIST)
        UpdateRuleControlButtons();

      HighlightItem(-1);
    }
    break;
  case GUI_MSG_WINDOW_INIT:
    {
      const std::string& startupList = message.GetStringParam(0);
      if (!startupList.empty())
      {
        int party = 0;
        if (URIUtils::PathEquals(startupList, CProfilesManager::GetInstance().GetUserDataItem("PartyMode.xsp")))
          party = 1;
        else if (URIUtils::PathEquals(startupList, CProfilesManager::GetInstance().GetUserDataItem("PartyMode-Video.xsp")))
          party = 2;

        if ((party && !XFILE::CFile::Exists(startupList)) ||
             m_playlist.Load(startupList))
        {
          m_path = startupList;

          if (party == 1)
            m_mode = "partymusic";
          else if (party == 2)
            m_mode = "partyvideo";
          else
          {
            PLAYLIST_TYPE type = ConvertType(m_playlist.GetType());
            if (type == TYPE_SONGS || type == TYPE_ALBUMS || type == TYPE_ARTISTS)
              m_mode = "music";
            else
              m_mode = "video";
          }
        }
        else
          return false;
      }
    }
    break;
  }
  return CGUIDialog::OnMessage(message);
}
//recursive function - called from
//Match. Do most of job to match text to the rule
int COXRegExpression::MatchNextTag(CString &sString, int nTag, int* pNumber)
{
	ASSERT(nTag<GetTagCount());
	
	tRegExpTag* pTag=GetTag(nTag);
	int nSuccess=FALSE;
	int nMin=pTag->nMin;
	int nMax=(pTag->nMax==-1)?
		(sString.GetLength()-1-*pNumber):pTag->nMax;


	if (!nMin)
	{
		if (nTag<GetTagCount()-1)
		{
			nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
			if (nSuccess & OX_REGEXP_CANCELED)
				return OX_REGEXP_CANCELED;
		}
		else
		{
			if (GetTagCount()==1)//no sense to do search 
				return FALSE;    // for 0 
			ASSERT((*pNumber)-m_nNumber>=0);
			m_nFound++;
			if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
				return OX_REGEXP_CANCELED;
			nSuccess=TRUE;
		}
	}

	switch (pTag->nType)
	{
	case OX_REGEXP_TAG_COMMON_CHAR:
	case OX_REGEXP_TAG_PATTERN:
		ASSERT(!pTag->sValue.IsEmpty());
	case OX_REGEXP_TAG_CHARS_AT_LEAST_MOST:
	case OX_REGEXP_TAG_CHARS_AT_LEAST:
		{

			for (int n=0;n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (sString.Right(sString.GetLength()-*pNumber).Find(
					(LPCTSTR) pTag->sValue)!=NULL)
				{
							return nSuccess;
				}
				else
				{
					*pNumber+=pTag->sValue.GetLength();
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
										return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}

					}
				}
			}
				return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_BEGINING_OF_THE_LINE:
		{
			for (int n=0;n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (sString.GetAt(*pNumber)!=TEXT('\n') && (*pNumber || n))
					return nSuccess;
				if (*pNumber) 
						(*pNumber)++;
				if (nTag==GetTagCount()-1)
					{
						ASSERT((*pNumber)-m_nNumber>=0);
						m_nFound++;
						if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
								return OX_REGEXP_CANCELED;
					}
				else
					{
						nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
						if (nSuccess & OX_REGEXP_CANCELED)
							return OX_REGEXP_CANCELED;
					}
			}
				return nSuccess;
		}
	case OX_REGEXP_TAG_END_OF_THE_LINE:
		{
			for (int n=0;n<nMax;n++)
			{
				if (*pNumber>sString.GetLength())
					return FALSE;
				if (*pNumber==sString.GetLength() ||
					((sString.GetLength()- *pNumber-1) &&
					(sString.GetAt(*pNumber+1)==TEXT('\n'))))
				{
					(*pNumber)++;
					if (nTag==GetTagCount()-1)
						{
							ASSERT((*pNumber)-m_nNumber>=0);
							m_nFound++;
							if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
								return OX_REGEXP_CANCELED;
							nSuccess=TRUE;
						}
					else
						{
							nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
							if (nSuccess & OX_REGEXP_CANCELED)
								return OX_REGEXP_CANCELED;
						}
				}
				else
					return nSuccess;
			}
		}
		break;
	case OX_REGEXP_TAG_CHAR_NOT_NEW_LINE:
		{
			for (int n=0;n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (sString.GetAt(*pNumber)==TEXT('\n'))
					return nSuccess;
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}

					}
				}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_CHARSET:
		{
			for (int n=0;n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (pTag->sValue.Find(sString.GetAt(*pNumber))==-1)
				{
					return nSuccess;
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}
					}
				}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_NON_CHARSET:
		{
			for (int n=0;n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (pTag->sValue.Find(sString.GetAt(*pNumber))!=-1)
				{
					return nSuccess;
				}
				(*pNumber)++;
				if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}

					}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_WORD_BOUNDARY:
		ASSERT(nMin==1 && nMax==1);//only one tag allowed
		if (*pNumber>=sString.GetLength())
			return FALSE;
		if ((*pNumber &&
			(((m_sSpace.Find(sString.GetAt(*pNumber)))==-1)
			^ ((m_sSpace.Find(sString.GetAt(*pNumber-1)))==-1)))
			|| (!*pNumber && 
			(m_sSpace.Find(sString.GetAt(*pNumber)))==-1 ))
		{
			if (nTag==GetTagCount()-1)
			{
				ASSERT((*pNumber)-m_nNumber>=0);
				m_nFound++;
				if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
					return OX_REGEXP_CANCELED;
				return TRUE;
			}
			else
				return MatchNextTag(sString, nTag+1, pNumber);
		}
		else
			return nSuccess;
		break;
	case OX_REGEXP_TAG_NON_WORD_BOUNDARY:
		ASSERT(nMin==1 && nMax==1);//only one tag allowed
		if (*pNumber>=sString.GetLength())
			return FALSE;
		if ((*pNumber &&
			!(((m_sSpace.Find(sString.GetAt(*pNumber)))==-1)
			^ ((m_sSpace.Find(sString.GetAt(*pNumber-1)))==-1)))
			|| (!*pNumber && 
			(m_sSpace.Find(sString.GetAt(*pNumber)))!=-1 ))

		{
			if (nTag==GetTagCount()-1)
			{
				ASSERT((*pNumber)-m_nNumber>=0);
				m_nFound++;
				if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
					return OX_REGEXP_CANCELED;
				return TRUE;
			}
			else
				return MatchNextTag(sString, nTag+1, pNumber);
		}
		else
			return nSuccess;
		break;
	case OX_REGEXP_TAG_DIGIT:
		{
			for (int n=0; n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (sString.GetAt(*pNumber)<TEXT('0') ||
					sString.GetAt(*pNumber)>TEXT('9'))
					return nSuccess;
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}

					}
				}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_NON_DIGIT:
		{
			for (int n=0; n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (sString.GetAt(*pNumber)>=TEXT('0') &&
					sString.GetAt(*pNumber)<=TEXT('9'))
				{
					return nSuccess;						
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
								
							}

					}
				}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_WHITESPACE:
		{
			for (int n=0; n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (m_sSpace.Find(sString.GetAt(*pNumber))==-1)
				{
						return nSuccess;
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
								
							}

					}
				}
			}
			return nSuccess;
		}

		break;
	case OX_REGEXP_TAG_NON_WHITESPACE:
		{
			for (int n=0; n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				if (m_sSpace.Find(sString.GetAt(*pNumber))!=-1)
				{
						return nSuccess;
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}
					}
				}
			}
			return nSuccess;
		}
		break;
	case OX_REGEXP_TAG_ANY_WORD:
		{
			if (sString.GetLength()<=*pNumber)
				return FALSE;
			for (int n=0; n<nMax;n++)
			{
				TCHAR ch=sString.GetAt(*pNumber);
				if (!(((ch>=TEXT('a') && ch<=TEXT('z')) ||
					(ch>=TEXT('A') && ch<=TEXT('Z')) ||
					(ch>=TEXT('0') && ch<=TEXT('9')) ||
					ch==TEXT('_'))))
				{
						return nSuccess;
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
								
							}

					}
				}
			}
			return nSuccess;
		}

		break;
	case OX_REGEXP_TAG_ANY_NON_WORD:
		{
			for (int n=0; n<nMax;n++)
			{
				if (sString.GetLength()<=*pNumber)
					return FALSE;
				TCHAR ch=sString.GetAt(*pNumber);
				if ((ch>=TEXT('a') && ch<=TEXT('z')) ||
					(ch>=TEXT('A') && ch<=TEXT('Z')) ||
					(ch>=TEXT('0') && ch<=TEXT('9')) ||
					ch==TEXT('_'))
				{
						return nSuccess;
				}
				else
				{
					(*pNumber)++;
					if (n+1>=nMin)
					{
							if (nTag<GetTagCount()-1)
							{
								nSuccess |=MatchNextTag(sString,nTag+1,pNumber);
								if (nSuccess & OX_REGEXP_CANCELED)
									return OX_REGEXP_CANCELED;
							}
							else
							{
								ASSERT((*pNumber)-m_nNumber>=0);
								m_nFound++;
								if (!OnMatch(m_nNumber, (*pNumber)-m_nNumber))
									return OX_REGEXP_CANCELED;
								nSuccess=TRUE;
							}
					}
				}
			}
			return nSuccess;
		}
		break;
	default:
		ASSERT(FALSE);//unexpected type
	}
	return nSuccess;

}