Index: sc/inc/global.hxx
===================================================================
RCS file: /cvs/sc/sc/inc/global.hxx,v
retrieving revision 1.49
diff -u -p -r1.49 global.hxx
--- sc/inc/global.hxx	6 Jul 2007 12:30:02 -0000	1.49
+++ sc/inc/global.hxx	9 Aug 2007 18:29:24 -0000
@@ -817,7 +817,11 @@ enum ScQueryOp
 		SC_TOPVAL,
 		SC_BOTVAL,
 		SC_TOPPERC,
-		SC_BOTPERC
+		SC_BOTPERC,
+		SC_CONTAINS,
+		SC_DOES_NOT_CONTAIN,
+		SC_BEGINS_WITH,
+		SC_ENDS_WITH
 	};
 
 // -----------------------------------------------------------------------
Index: sc/source/core/data/table3.cxx
===================================================================
RCS file: /cvs/sc/sc/source/core/data/table3.cxx,v
retrieving revision 1.28
diff -u -p -r1.28 table3.cxx
--- sc/source/core/data/table3.cxx	5 Mar 2007 14:40:30 -0000	1.28
+++ sc/source/core/data/table3.cxx	9 Aug 2007 18:29:24 -0000
@@ -40,6 +40,7 @@
 
 // INCLUDE ---------------------------------------------------------------
 
+#include <i18nutil/unicode.hxx>
 #include <rtl/math.hxx>
 #include <unotools/textsearch.hxx>
 #include <svtools/zforlist.hxx>
@@ -925,6 +926,28 @@ BOOL ScTable::DoSubTotals( ScSubTotalPar
 	return bSpaceLeft;
 }
 
+static BOOL HasNonWSInRange (const String& s, int start, int end)
+{
+	for (int i = start; i < end; ++i) {
+		if (!unicode::isSpace(s.GetChar(i)))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static BOOL IsMatch (BOOL bMatchWholeCell, ScQueryOp eOp, const String& s, int nMatchStart, int nMatchEnd)
+{
+	BOOL bBegin = HasNonWSInRange(s, 0, nMatchStart);
+	BOOL bEnd   = HasNonWSInRange(s, nMatchEnd, s.Len());
+
+	if (bMatchWholeCell && (bBegin || bEnd))
+		return FALSE;
+	else if (eOp == SC_BEGINS_WITH && bBegin)
+		return FALSE;
+	else if (eOp == SC_ENDS_WITH && bEnd)
+		return FALSE;
+	return TRUE;
+}
 
 BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
         BOOL* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
@@ -1018,13 +1041,22 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
                 }
 			}
 		}
-        else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
+        else if ( (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN || 
+		rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH || 
+		rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
                 (rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
                                            HasStringData(
                                                static_cast<SCCOL>(rEntry.nField),
                                                nRow))))
 		{	// by String
 			String	aCellStr;
+
+			// Contains and Does not contain is similar to EQUAL and NOT EQUAL
+			// but with bMatchWholeCell set to false
+			if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
+				rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH )
+				bMatchWholeCell = FALSE;
+
             if ( pCell )
             {
                 if (pCell->GetCellType() != CELLTYPE_NOTE)
@@ -1037,7 +1069,9 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
                 GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
 
             BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
-                || (rEntry.eOp == SC_NOT_EQUAL)));
+                || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS) 
+				|| (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
+				|| (rEntry.eOp == SC_ENDS_WITH)));
             BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
                 && ((rEntry.eOp == SC_LESS_EQUAL)
                     || (rEntry.eOp == SC_GREATER_EQUAL)));
@@ -1048,17 +1082,21 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
                 BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
 					->SearchFrwrd( aCellStr, &nStart, &nEnd );
 				// from 614 on, nEnd is behind the found text
-                if ( bMatch && bMatchWholeCell
-						&& (nStart != 0 || nEnd != aCellStr.Len()) )
-                    bMatch = FALSE;    // RegExp must match entire cell string
+                if ( bMatch )
+				{
+					bMatch = IsMatch(bMatchWholeCell, rEntry.eOp, aCellStr, nStart, nEnd);
+				}
                 if ( bRealRegExp )
-                    bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
+                    bOk = ( ( rEntry.eOp == SC_NOT_EQUAL || 
+							rEntry.eOp == SC_DOES_NOT_CONTAIN ) ? !bMatch : bMatch );
                 else
                     bTestEqual = bMatch;
             }
             if ( !bRealRegExp )
 			{
-				if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL )
+				if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL || 
+					 rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
+					 rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH )
 				{
                     if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
                     {
@@ -1067,8 +1105,6 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
                         // don't find any string (isEqual would find empty string results in formula cells).
                         bOk = FALSE;
                     }
-                    else if ( bMatchWholeCell )
-                        bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
 					else
 					{
                         ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
@@ -1078,9 +1114,14 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
                         String aQuer( pTransliteration->transliterate(
                             *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
                             &xOff ) );
-                        bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+						xub_StrLen nPos = aCell.Search( aQuer );
+                        bOk = ( nPos != STRING_NOTFOUND );
+						if ( bOk ) {
+							bOk = IsMatch(bMatchWholeCell, rEntry.eOp, aCell, nPos, nPos+aQuer.Len());
+						}
 					}
-					if ( rEntry.eOp == SC_NOT_EQUAL )
+					if ( rEntry.eOp == SC_NOT_EQUAL || 
+						 rEntry.eOp == SC_DOES_NOT_CONTAIN )
 						bOk = !bOk;
 				}
 				else
Index: sc/source/filter/excel/excimp8.cxx
===================================================================
RCS file: /cvs/sc/sc/source/filter/excel/excimp8.cxx,v
retrieving revision 1.120
diff -u -p -r1.120 excimp8.cxx
--- sc/source/filter/excel/excimp8.cxx	17 Jul 2007 13:33:21 -0000	1.120
+++ sc/source/filter/excel/excimp8.cxx	10 Aug 2007 13:27:58 -0000
@@ -454,6 +454,66 @@ void XclImpAutoFilterData::InsertQueryPa
 	}
 }
 
+static void ExcelQueryToOooQuery( ScQueryEntry& rEntry, ScQueryParam& rParam )
+{
+	if( rEntry.pStr == NULL )
+		return;
+	if( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL )
+		return;
+	xub_StrLen nLen = rEntry.pStr->Len();
+	if( nLen == 0 )
+		return;
+	BOOL bRegExp = FALSE;
+	for( int i = 0; i < nLen; ++i ) {
+		sal_Unicode c = rEntry.pStr->GetChar( i );
+		if( c == '*' ) {
+			if( rEntry.eOp == SC_NOT_EQUAL ) {
+				bRegExp = TRUE;
+				rEntry.eOp = SC_DOES_NOT_CONTAIN;
+			}
+			else if( rEntry.eOp == SC_DOES_NOT_CONTAIN )
+				; // ignore
+			else if( i == 0 )
+				rEntry.eOp = SC_ENDS_WITH;
+			else if( i == nLen-1 )
+				rEntry.eOp = rEntry.eOp == SC_ENDS_WITH ? SC_CONTAINS : SC_BEGINS_WITH;
+			else
+				bRegExp = TRUE;
+		}
+		else if( c == '?' )
+			bRegExp = TRUE;
+	}
+	if( rEntry.pStr->GetChar( 0 ) == '*' )
+		rEntry.pStr->Erase( 0, 1 );
+	nLen = rEntry.pStr->Len();
+	if( nLen > 0 && rEntry.pStr->GetChar( nLen-1 ) == '*' ) {
+		rEntry.pStr->Erase( nLen-1, 1 );
+		--nLen;
+	}
+	if( bRegExp ) {
+		rParam.bRegExp = TRUE;
+		for( int i = 0; i < nLen; ++i ) {
+			sal_Unicode c = rEntry.pStr->GetChar( i );
+			switch( c ) {
+				case '*':
+					rEntry.pStr->ReplaceAscii( i, 1, ".*" );
+					++i;
+					++nLen;
+					break;
+				case '.':
+					rEntry.pStr->InsertAscii( "\\", i );
+					++i;
+					++nLen;
+					break;
+				case '?':
+					rEntry.pStr->ReplaceAscii( i, 1, "." );
+					break;
+				default: break;
+			}
+		}
+	}
+}
+
 void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
 {
 	UINT16 nCol, nFlags;
@@ -491,14 +551,14 @@ void XclImpAutoFilterData::ReadAutoFilte
 		BOOL	bIgnore;
 
 		UINT8	nStrLen[ 2 ]	= { 0, 0 };
-		String*	pEntryStr[ 2 ]	= { NULL, NULL };
+		ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
 
 		for( nE = 0; nE < 2; nE++ )
 		{
 			if( nFirstEmpty < nCount )
 			{
 				ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
-				pEntryStr[ nE ] = aEntry.pStr;
+				pQueryEntries[ nE ] = &aEntry;
 				bIgnore = FALSE;
 
 				rStrm >> nType >> nOper;
@@ -586,8 +646,10 @@ void XclImpAutoFilterData::ReadAutoFilte
 		}
 
 		for( nE = 0; nE < 2; nE++ )
-			if( nStrLen[ nE ] && pEntryStr[ nE ] )
-                pEntryStr[ nE ]->Assign( rStrm.ReadUniString( nStrLen[ nE ] ) );
+			if( nStrLen[ nE ] && pQueryEntries[ nE ] ) {
+				pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
+				ExcelQueryToOooQuery( *pQueryEntries[ nE ], aParam );
+			}
 	}
 }
 
Index: sc/source/filter/excel/excrecds.cxx
===================================================================
RCS file: /cvs/sc/sc/source/filter/excel/excrecds.cxx,v
retrieving revision 1.87
diff -u -p -r1.87 excrecds.cxx
--- sc/source/filter/excel/excrecds.cxx	22 May 2007 19:45:31 -0000	1.87
+++ sc/source/filter/excel/excrecds.cxx	9 Aug 2007 18:29:24 -0000
@@ -630,13 +630,50 @@ BOOL XclExpAutofilter::AddCondition( ScQ
 	return TRUE;
 }
 
-BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
+static String OooQueryToExcelQuery( const ScQueryEntry& rEntry, const ScQueryParam& rParam )
+{
+	String aStr (*rEntry.pStr);
+	BOOL bHaveRegex = rParam.bRegExp;
+	if( bHaveRegex ) {
+		xub_StrLen nLen = aStr.Len();
+		for( int i = 0; i < nLen; ++i ) {
+			sal_Unicode c = aStr.GetChar( i );
+			if( c == '.' ) {
+				if( i+1 < nLen && aStr.GetChar( i+1 ) == '*' ) {
+					aStr.ReplaceAscii( i, 2, "*" );
+					--nLen;
+				}
+				else
+					aStr.ReplaceAscii( i, 1, "?" );
+			}
+			else if( c == '\\' ) {
+				aStr.Erase( i, 1 );
+				--nLen;
+			}
+		}
+	}
+	if( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN )
+		aStr.InsertAscii( "*" , 0 );
+	if( rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN )
+		aStr.AppendAscii( "*" );
+	return aStr;
+}
+
+BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry, const ScQueryParam& rParam )
 {
 	BOOL	bConflict = FALSE;
 	String	sText;
 
-	if( rEntry.pStr )
-		sText.Assign( *rEntry.pStr );
+	ScQueryOp eOp = rEntry.eOp;
+	if( rEntry.pStr ) {
+		if (eOp != SC_BEGINS_WITH && eOp != SC_ENDS_WITH && 
+				eOp != SC_CONTAINS && eOp != SC_DOES_NOT_CONTAIN)
+			sText.Assign( *rEntry.pStr );
+		else {
+			sText.Assign( OooQueryToExcelQuery( rEntry, rParam ) );
+			eOp = eOp == SC_DOES_NOT_CONTAIN ? SC_NOT_EQUAL : SC_EQUAL;
+		}
+	}
 
     BOOL bLen = sText.Len() > 0;
 
@@ -655,7 +692,7 @@ BOOL XclExpAutofilter::AddEntry( const S
 
 		// top10 flags
 		UINT16 nNewFlags = 0x0000;
-		switch( rEntry.eOp )
+		switch( eOp )
 		{
 			case SC_TOPVAL:
 				nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
@@ -688,7 +725,7 @@ BOOL XclExpAutofilter::AddEntry( const S
 				UINT8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
 				UINT8 nOper = EXC_AFOPER_NONE;
 
-				switch( rEntry.eOp )
+				switch( eOp )
 				{
 					case SC_EQUAL:			nOper = EXC_AFOPER_EQUAL;			break;
 					case SC_LESS:			nOper = EXC_AFOPER_LESS;			break;
@@ -801,7 +838,7 @@ ExcAutoFilterRecs::ExcAutoFilterRecs( co
 						bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
 									(nFirstField != rEntry.nField);
 					if( !bConflict )
-                        bConflict = pFilter->AddEntry( rEntry );
+                        bConflict = pFilter->AddEntry( rEntry, aParam );
 				}
 			}
 
Index: sc/source/filter/inc/excrecds.hxx
===================================================================
RCS file: /cvs/sc/sc/source/filter/inc/excrecds.hxx,v
retrieving revision 1.49
diff -u -p -r1.49 excrecds.hxx
--- sc/source/filter/inc/excrecds.hxx	27 Feb 2007 12:32:42 -0000	1.49
+++ sc/source/filter/inc/excrecds.hxx	9 Aug 2007 18:29:25 -0000
@@ -469,7 +469,7 @@ public:
 	inline BOOL				HasCondition() const	{ return !aCond[ 0 ].IsEmpty(); }
     inline BOOL             HasTop10() const        { return ::get_flag( nFlags, EXC_AFFLAG_TOP10 ); }
 
-    BOOL                    AddEntry( const ScQueryEntry& rEntry );
+    BOOL                    AddEntry( const ScQueryEntry& rEntry, const ScQueryParam& rParam );
 };
 
 // ----------------------------------------------------------------------------
Index: sc/source/ui/src/filter.src
===================================================================
RCS file: /cvs/sc/sc/source/ui/src/filter.src,v
retrieving revision 1.57
diff -u -p -r1.57 filter.src
--- sc/source/ui/src/filter.src	19 Apr 2007 16:37:30 -0000	1.57
+++ sc/source/ui/src/filter.src	9 Aug 2007 18:29:26 -0000
@@ -126,16 +126,20 @@ ModelessDialog RID_SCDLG_FILTER
 		DropDown = TRUE ;
 		stringlist [ en-US ] =
 		{
-			< "=" ; Default ; > ;
+                        < "Equals" ; Default ; > ;
 			< "<" ; Default ; > ;
 			< ">" ; Default ; > ;
 			< "<=" ; Default ; > ;
 			< ">=" ; Default ; > ;
-			< "<>" ; Default ; > ;
+                        < "Not equals" ; Default ; > ;
 			< "Largest" ; Default ; > ;
 			< "Smallest" ; Default ; > ;
 			< "Largest %" ; Default ; > ;
 			< "Smallest %" ; Default ; > ;
+			< "Contains" ; Default ; > ;
+			< "Does not Contain" ; Default ; > ;
+                        < "Begins with" ; Default ; > ;
+                        < "Ends with" ; Default ; > ;
 		};
 	};
 	ListBox LB_COND2
@@ -147,16 +151,20 @@ ModelessDialog RID_SCDLG_FILTER
 		DropDown = TRUE ;
 		stringlist [ en-US ] =
 		{
-			< "=" ; Default ; > ;
+                        < "Equals" ; Default ; > ;
 			< "<" ; Default ; > ;
 			< ">" ; Default ; > ;
 			< "<=" ; Default ; > ;
 			< ">=" ; Default ; > ;
-			< "<>" ; Default ; > ;
+			< "Not equals" ; Default ; > ;
 			< "Largest" ; Default ; > ;
 			< "Smallest" ; Default ; > ;
 			< "Largest %" ; Default ; > ;
 			< "Smallest %" ; Default ; > ;
+			< "Contains" ; Default ; > ;
+			< "Does not Contain" ; Default ; > ;
+                        < "Begins with" ; Default ; > ;
+                        < "Ends with" ; Default ; > ;
 		};
 	};
 	ListBox LB_COND3
@@ -168,16 +176,20 @@ ModelessDialog RID_SCDLG_FILTER
 		DropDown = TRUE ;
 		stringlist [ en-US ] =
 		{
-			< "=" ; Default ; > ;
+                        < "Equals" ; Default ; > ;
 			< "<" ; Default ; > ;
 			< ">" ; Default ; > ;
 			< "<=" ; Default ; > ;
 			< ">=" ; Default ; > ;
-			< "<>" ; Default ; > ;
+			< "Not equals" ; Default ; > ;
 			< "Largest" ; Default ; > ;
 			< "Smallest" ; Default ; > ;
 			< "Largest %" ; Default ; > ;
 			< "Smallest %" ; Default ; > ;
+			< "Contains" ; Default ; > ;
+			< "Does not Contain" ; Default ; > ;
+                        < "Begins with" ; Default ; > ;
+                        < "Ends with" ; Default ; > ;
 		};
 	};
 	ComboBox ED_VAL1
Index: sc/util/makefile.mk
===================================================================
RCS file: /cvs/sc/sc/util/makefile.mk,v
retrieving revision 1.41
diff -u -p -r1.41 makefile.mk
--- sc/util/makefile.mk	22 May 2007 20:15:40 -0000	1.41
+++ sc/util/makefile.mk	9 Aug 2007 18:29:27 -0000
@@ -98,6 +98,7 @@ SHL1STDLIBS=       \
 	$(VOSLIB)		\
 	$(SALLIB)		\
 	$(TOOLSLIB)	\
+	$(I18NUTILLIB) \
 	$(I18NISOLANGLIB) \
 	$(UNOTOOLSLIB) \
 	$(SOTLIB)		\
