1 --- sc/inc/global.hxx.old 2009-04-02 10:45:43.000000000 +0000
2 +++ sc/inc/global.hxx 2009-04-06 16:41:48.000000000 +0000
3 @@ -727,7 +727,11 @@ enum ScQueryOp
10 + SC_DOES_NOT_CONTAIN,
15 // -----------------------------------------------------------------------
16 --- sc/source/core/data/table3.cxx.old 2009-04-02 10:45:01.000000000 +0000
17 +++ sc/source/core/data/table3.cxx 2009-04-06 16:41:48.000000000 +0000
19 // MARKER(update_precomp.py): autogen include statement, do not remove
20 #include "precompiled_sc.hxx"
22 +#include <i18nutil/unicode.hxx>
23 #include <rtl/math.hxx>
24 #include <unotools/textsearch.hxx>
25 #include <svtools/zforlist.hxx>
26 @@ -928,6 +929,28 @@ BOOL ScTable::DoSubTotals( ScSubTotalPar
30 +static BOOL HasNonWSInRange (const String& s, int start, int end)
32 + for (int i = start; i < end; ++i) {
33 + if (!unicode::isSpace(s.GetChar(i)))
39 +static BOOL IsMatch (BOOL bMatchWholeCell, ScQueryOp eOp, const String& s, int nMatchStart, int nMatchEnd)
41 + BOOL bBegin = HasNonWSInRange(s, 0, nMatchStart);
42 + BOOL bEnd = HasNonWSInRange(s, nMatchEnd, s.Len());
44 + if (bMatchWholeCell && (bBegin || bEnd))
46 + else if (eOp == SC_BEGINS_WITH && bBegin)
48 + else if (eOp == SC_ENDS_WITH && bEnd)
53 BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
54 BOOL* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
55 @@ -1021,13 +1044,22 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
59 - else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
60 + else if ( (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
61 + rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH ||
62 + rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
63 (rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
65 static_cast<SCCOL>(rEntry.nField),
70 + // Contains and Does not contain is similar to EQUAL and NOT EQUAL
71 + // but with bMatchWholeCell set to false
72 + if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
73 + rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH )
74 + bMatchWholeCell = FALSE;
78 if (pCell->GetCellType() != CELLTYPE_NOTE)
79 @@ -1040,7 +1072,9 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
80 GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
82 BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
83 - || (rEntry.eOp == SC_NOT_EQUAL)));
84 + || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS)
85 + || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
86 + || (rEntry.eOp == SC_ENDS_WITH)));
87 BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
88 && ((rEntry.eOp == SC_LESS_EQUAL)
89 || (rEntry.eOp == SC_GREATER_EQUAL)));
90 @@ -1051,17 +1085,21 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
91 BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
92 ->SearchFrwrd( aCellStr, &nStart, &nEnd );
93 // from 614 on, nEnd is behind the found text
94 - if ( bMatch && bMatchWholeCell
95 - && (nStart != 0 || nEnd != aCellStr.Len()) )
96 - bMatch = FALSE; // RegExp must match entire cell string
99 + bMatch = IsMatch(bMatchWholeCell, rEntry.eOp, aCellStr, nStart, nEnd);
102 - bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
103 + bOk = ( ( rEntry.eOp == SC_NOT_EQUAL ||
104 + rEntry.eOp == SC_DOES_NOT_CONTAIN ) ? !bMatch : bMatch );
110 - if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL )
111 + if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ||
112 + rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
113 + rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH )
115 if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
117 @@ -1070,8 +1108,6 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
118 // don't find any string (isEqual would find empty string results in formula cells).
121 - else if ( bMatchWholeCell )
122 - bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
125 ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
126 @@ -1081,9 +1117,14 @@ BOOL ScTable::ValidQuery(SCROW nRow, con
127 String aQuer( pTransliteration->transliterate(
128 *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
130 - bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
131 + xub_StrLen nPos = aCell.Search( aQuer );
132 + bOk = ( nPos != STRING_NOTFOUND );
134 + bOk = IsMatch(bMatchWholeCell, rEntry.eOp, aCell, nPos, nPos+aQuer.Len());
137 - if ( rEntry.eOp == SC_NOT_EQUAL )
138 + if ( rEntry.eOp == SC_NOT_EQUAL ||
139 + rEntry.eOp == SC_DOES_NOT_CONTAIN )
143 --- sc/source/filter/excel/excimp8.cxx.old 2009-04-02 10:44:55.000000000 +0000
144 +++ sc/source/filter/excel/excimp8.cxx 2009-04-06 16:41:48.000000000 +0000
145 @@ -426,6 +426,66 @@ void XclImpAutoFilterData::InsertQueryPa
149 +static void ExcelQueryToOooQuery( ScQueryEntry& rEntry, ScQueryParam& rParam )
151 + if( rEntry.pStr == NULL )
153 + if( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL )
155 + xub_StrLen nLen = rEntry.pStr->Len();
158 + BOOL bRegExp = FALSE;
159 + for( int i = 0; i < nLen; ++i ) {
160 + sal_Unicode c = rEntry.pStr->GetChar( i );
162 + if( rEntry.eOp == SC_NOT_EQUAL ) {
164 + rEntry.eOp = SC_DOES_NOT_CONTAIN;
166 + else if( rEntry.eOp == SC_DOES_NOT_CONTAIN )
169 + rEntry.eOp = SC_ENDS_WITH;
170 + else if( i == nLen-1 )
171 + rEntry.eOp = rEntry.eOp == SC_ENDS_WITH ? SC_CONTAINS : SC_BEGINS_WITH;
175 + else if( c == '?' )
178 + if( rEntry.pStr->GetChar( 0 ) == '*' )
179 + rEntry.pStr->Erase( 0, 1 );
180 + nLen = rEntry.pStr->Len();
181 + if( nLen > 0 && rEntry.pStr->GetChar( nLen-1 ) == '*' ) {
182 + rEntry.pStr->Erase( nLen-1, 1 );
186 + rParam.bRegExp = TRUE;
187 + for( int i = 0; i < nLen; ++i ) {
188 + sal_Unicode c = rEntry.pStr->GetChar( i );
191 + rEntry.pStr->ReplaceAscii( i, 1, ".*" );
196 + rEntry.pStr->InsertAscii( "\\", i );
201 + rEntry.pStr->ReplaceAscii( i, 1, "." );
209 void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
212 @@ -463,14 +523,14 @@ void XclImpAutoFilterData::ReadAutoFilte
215 UINT8 nStrLen[ 2 ] = { 0, 0 };
216 - String* pEntryStr[ 2 ] = { NULL, NULL };
217 + ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
219 for( nE = 0; nE < 2; nE++ )
221 if( nFirstEmpty < nCount )
223 ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
224 - pEntryStr[ nE ] = aEntry.pStr;
225 + pQueryEntries[ nE ] = &aEntry;
228 rStrm >> nType >> nOper;
229 @@ -558,8 +618,10 @@ void XclImpAutoFilterData::ReadAutoFilte
232 for( nE = 0; nE < 2; nE++ )
233 - if( nStrLen[ nE ] && pEntryStr[ nE ] )
234 - pEntryStr[ nE ]->Assign( rStrm.ReadUniString( nStrLen[ nE ] ) );
235 + if( nStrLen[ nE ] && pQueryEntries[ nE ] ) {
236 + pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
237 + ExcelQueryToOooQuery( *pQueryEntries[ nE ], aParam );
242 --- sc/source/filter/excel/excrecds.cxx.old 2009-04-02 10:44:55.000000000 +0000
243 +++ sc/source/filter/excel/excrecds.cxx 2009-04-06 16:41:48.000000000 +0000
244 @@ -693,13 +693,50 @@ BOOL XclExpAutofilter::AddCondition( ScQ
248 -BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
249 +static String OooQueryToExcelQuery( const ScQueryEntry& rEntry, const ScQueryParam& rParam )
251 + String aStr (*rEntry.pStr);
252 + BOOL bHaveRegex = rParam.bRegExp;
254 + xub_StrLen nLen = aStr.Len();
255 + for( int i = 0; i < nLen; ++i ) {
256 + sal_Unicode c = aStr.GetChar( i );
258 + if( i+1 < nLen && aStr.GetChar( i+1 ) == '*' ) {
259 + aStr.ReplaceAscii( i, 2, "*" );
263 + aStr.ReplaceAscii( i, 1, "?" );
265 + else if( c == '\\' ) {
266 + aStr.Erase( i, 1 );
271 + if( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN )
272 + aStr.InsertAscii( "*" , 0 );
273 + if( rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN )
274 + aStr.AppendAscii( "*" );
278 +BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry, const ScQueryParam& rParam )
280 BOOL bConflict = FALSE;
284 - sText.Assign( *rEntry.pStr );
285 + ScQueryOp eOp = rEntry.eOp;
286 + if( rEntry.pStr ) {
287 + if (eOp != SC_BEGINS_WITH && eOp != SC_ENDS_WITH &&
288 + eOp != SC_CONTAINS && eOp != SC_DOES_NOT_CONTAIN)
289 + sText.Assign( *rEntry.pStr );
291 + sText.Assign( OooQueryToExcelQuery( rEntry, rParam ) );
292 + eOp = eOp == SC_DOES_NOT_CONTAIN ? SC_NOT_EQUAL : SC_EQUAL;
296 BOOL bLen = sText.Len() > 0;
298 @@ -718,7 +755,7 @@ BOOL XclExpAutofilter::AddEntry( const S
301 UINT16 nNewFlags = 0x0000;
302 - switch( rEntry.eOp )
306 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
307 @@ -751,7 +788,7 @@ BOOL XclExpAutofilter::AddEntry( const S
308 UINT8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
309 UINT8 nOper = EXC_AFOPER_NONE;
311 - switch( rEntry.eOp )
314 case SC_EQUAL: nOper = EXC_AFOPER_EQUAL; break;
315 case SC_LESS: nOper = EXC_AFOPER_LESS; break;
316 @@ -900,7 +937,7 @@ ExcAutoFilterRecs::ExcAutoFilterRecs( co
317 bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
318 (nFirstField != rEntry.nField);
320 - bConflict = pFilter->AddEntry( rEntry );
321 + bConflict = pFilter->AddEntry( rEntry, aParam );
325 --- sc/source/filter/inc/excrecds.hxx.old 2009-04-02 10:44:58.000000000 +0000
326 +++ sc/source/filter/inc/excrecds.hxx 2009-04-06 16:41:48.000000000 +0000
327 @@ -442,7 +442,7 @@ public:
328 inline BOOL HasCondition() const { return !aCond[ 0 ].IsEmpty(); }
329 inline BOOL HasTop10() const { return ::get_flag( nFlags, EXC_AFFLAG_TOP10 ); }
331 - BOOL AddEntry( const ScQueryEntry& rEntry );
332 + BOOL AddEntry( const ScQueryEntry& rEntry, const ScQueryParam& rParam );
334 virtual void SaveXml( XclExpXmlStream& rStrm );
336 --- sc/source/ui/src/filter.src.old 2009-04-02 10:45:23.000000000 +0000
337 +++ sc/source/ui/src/filter.src 2009-04-06 16:41:48.000000000 +0000
338 @@ -121,16 +121,20 @@ ModelessDialog RID_SCDLG_FILTER
340 stringlist [ en-US ] =
342 - < "=" ; Default ; > ;
343 + < "Equals" ; Default ; > ;
344 < "<" ; Default ; > ;
345 < ">" ; Default ; > ;
346 < "<=" ; Default ; > ;
347 < ">=" ; Default ; > ;
348 - < "<>" ; Default ; > ;
349 + < "Not equals" ; Default ; > ;
350 < "Largest" ; Default ; > ;
351 < "Smallest" ; Default ; > ;
352 < "Largest %" ; Default ; > ;
353 < "Smallest %" ; Default ; > ;
354 + < "Contains" ; Default ; > ;
355 + < "Does not Contain" ; Default ; > ;
356 + < "Begins with" ; Default ; > ;
357 + < "Ends with" ; Default ; > ;
361 @@ -142,16 +146,20 @@ ModelessDialog RID_SCDLG_FILTER
363 stringlist [ en-US ] =
365 - < "=" ; Default ; > ;
366 + < "Equals" ; Default ; > ;
367 < "<" ; Default ; > ;
368 < ">" ; Default ; > ;
369 < "<=" ; Default ; > ;
370 < ">=" ; Default ; > ;
371 - < "<>" ; Default ; > ;
372 + < "Not equals" ; Default ; > ;
373 < "Largest" ; Default ; > ;
374 < "Smallest" ; Default ; > ;
375 < "Largest %" ; Default ; > ;
376 < "Smallest %" ; Default ; > ;
377 + < "Contains" ; Default ; > ;
378 + < "Does not Contain" ; Default ; > ;
379 + < "Begins with" ; Default ; > ;
380 + < "Ends with" ; Default ; > ;
384 @@ -163,16 +171,20 @@ ModelessDialog RID_SCDLG_FILTER
386 stringlist [ en-US ] =
388 - < "=" ; Default ; > ;
389 + < "Equals" ; Default ; > ;
390 < "<" ; Default ; > ;
391 < ">" ; Default ; > ;
392 < "<=" ; Default ; > ;
393 < ">=" ; Default ; > ;
394 - < "<>" ; Default ; > ;
395 + < "Not equals" ; Default ; > ;
396 < "Largest" ; Default ; > ;
397 < "Smallest" ; Default ; > ;
398 < "Largest %" ; Default ; > ;
399 < "Smallest %" ; Default ; > ;
400 + < "Contains" ; Default ; > ;
401 + < "Does not Contain" ; Default ; > ;
402 + < "Begins with" ; Default ; > ;
403 + < "Ends with" ; Default ; > ;
407 --- sc/util/makefile.mk.old 2009-04-06 16:41:39.000000000 +0000
408 +++ sc/util/makefile.mk 2009-04-06 16:41:48.000000000 +0000
409 @@ -94,6 +94,7 @@ SHL1STDLIBS= \