1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/util/SearchFlags.hpp>
21 #include <com/sun/star/util/SearchOptions.hpp>
22 #include <com/sun/star/util/SearchAlgorithms2.hpp>
23 #include <com/sun/star/util/XTextSearch2.hpp>
24 #include <unotest/bootstrapfixturebase.hxx>
25 #include <i18nutil/transliteration.hxx>
27 #include <unicode/regex.h>
29 using namespace ::com::sun::star
;
31 class TestTextSearch
: public test::BootstrapFixtureBase
34 virtual void setUp() override
;
35 virtual void tearDown() override
;
39 void testWildcardSearch();
40 void testApostropheSearch();
43 CPPUNIT_TEST_SUITE(TestTextSearch
);
44 CPPUNIT_TEST(testICU
);
45 CPPUNIT_TEST(testSearches
);
46 CPPUNIT_TEST(testWildcardSearch
);
47 CPPUNIT_TEST(testApostropheSearch
);
48 CPPUNIT_TEST(testTdf138410
);
49 CPPUNIT_TEST_SUITE_END();
51 uno::Reference
<util::XTextSearch
> m_xSearch
;
52 uno::Reference
<util::XTextSearch2
> m_xSearch2
;
55 // Sanity check our ICU first ...
56 void TestTextSearch::testICU()
58 UErrorCode nErr
= U_ZERO_ERROR
;
59 sal_uInt32 nSearchFlags
= UREGEX_UWORD
| UREGEX_CASE_INSENSITIVE
;
61 OUString
aString( "abcdefgh" );
62 OUString
aPattern( "e" );
63 icu::UnicodeString
aSearchPat( reinterpret_cast<const UChar
*>(aPattern
.getStr()), aPattern
.getLength() );
65 std::unique_ptr
<icu::RegexMatcher
> pRegexMatcher(new icu::RegexMatcher( aSearchPat
, nSearchFlags
, nErr
));
67 icu::UnicodeString
aSource( reinterpret_cast<const UChar
*>(aString
.getStr()), aString
.getLength() );
68 pRegexMatcher
->reset( aSource
);
70 CPPUNIT_ASSERT( pRegexMatcher
->find( 0, nErr
) );
71 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
72 CPPUNIT_ASSERT_EQUAL( static_cast<int32_t>(4), pRegexMatcher
->start( nErr
) );
73 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
74 CPPUNIT_ASSERT_EQUAL( static_cast<int32_t>(5), pRegexMatcher
->end( nErr
) );
75 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
77 OUString
aString2( "acababaabcababadcdaa" );
78 OUString
aPattern2( "a" );
80 icu::UnicodeString
aSearchPat2( reinterpret_cast<const UChar
*>(aPattern2
.getStr()), aPattern2
.getLength() );
81 pRegexMatcher
.reset(new icu::RegexMatcher( aSearchPat2
, nSearchFlags
, nErr
));
83 icu::UnicodeString
aSource2( reinterpret_cast<const UChar
*>(aString2
.getStr()), aString2
.getLength() );
84 pRegexMatcher
->reset( aSource2
);
86 CPPUNIT_ASSERT( pRegexMatcher
->find( 0, nErr
) );
87 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
88 CPPUNIT_ASSERT_EQUAL( static_cast<int32_t>(0), pRegexMatcher
->start( nErr
) );
89 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
90 CPPUNIT_ASSERT_EQUAL( static_cast<int32_t>(1), pRegexMatcher
->end( nErr
) );
91 CPPUNIT_ASSERT_EQUAL( U_ZERO_ERROR
, nErr
);
94 void TestTextSearch::testSearches()
96 OUString
str( "acababaabcababadcdaa" );
97 sal_Int32 startPos
= 2, endPos
= 20 ;
98 sal_Int32
const fStartRes
= 10, fEndRes
= 18 ;
99 sal_Int32
const bStartRes
= 18, bEndRes
= 10 ;
102 util::SearchOptions aOptions
;
103 aOptions
.algorithmType
= util::SearchAlgorithms_REGEXP
;
104 aOptions
.searchFlag
= util::SearchFlags::ALL_IGNORE_CASE
;
105 aOptions
.searchString
= "(ab)*a(c|d)+";
106 m_xSearch
->setOptions( aOptions
);
108 util::SearchResult aRes
;
111 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
112 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
113 CPPUNIT_ASSERT_EQUAL( fStartRes
, aRes
.startOffset
[0] );
114 CPPUNIT_ASSERT_EQUAL( fEndRes
, aRes
.endOffset
[0] );
117 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
118 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
119 CPPUNIT_ASSERT_EQUAL( bStartRes
, aRes
.startOffset
[0] );
120 CPPUNIT_ASSERT_EQUAL( bEndRes
, aRes
.endOffset
[0] );
122 aOptions
.transliterateFlags
= static_cast<int>(TransliterationFlags::IGNORE_CASE
123 | TransliterationFlags::IGNORE_WIDTH
);
124 aOptions
.searchString
= "([^ ]*)[ ]*([^ ]*)";
125 m_xSearch
->setOptions(aOptions
);
126 aRes
= m_xSearch
->searchForward("11 22 33", 2, 7);
127 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(3), aRes
.subRegExpressions
);
128 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.startOffset
[0]);
129 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.endOffset
[0]);
130 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.startOffset
[1]);
131 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.endOffset
[1]);
132 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes
.startOffset
[2]);
133 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.endOffset
[2]);
136 void TestTextSearch::testWildcardSearch()
138 util::SearchOptions2 aOptions
;
140 util::SearchResult aRes
;
142 aOptions
.AlgorithmType2
= util::SearchAlgorithms2::WILDCARD
;
143 aOptions
.WildcardEscapeCharacter
= '~';
144 // aOptions.searchFlag = ::css::util::SearchFlags::WILD_MATCH_SELECTION;
145 // is not set, so substring match is allowed.
146 aOptions
.transliterateFlags
= sal_Int32(::css::i18n::TransliterationModules::TransliterationModules_IGNORE_CASE
);
149 aOptions
.searchString
= "a";
150 m_xSearch2
->setOptions2( aOptions
);
151 // match first "a", [0,1)
152 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
153 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
154 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
155 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.endOffset
[0]);
156 // match last "a", (5,4]
157 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
158 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
159 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.startOffset
[0]);
160 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.endOffset
[0]);
162 aOptions
.searchString
= "a?";
163 m_xSearch2
->setOptions2( aOptions
);
165 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
166 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
167 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
168 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.endOffset
[0]);
170 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
171 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
172 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.startOffset
[0]);
173 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.endOffset
[0]);
175 aOptions
.searchString
= "a*c";
176 m_xSearch2
->setOptions2( aOptions
);
177 // match "abac", [0,4) XXX NOTE: first match forward
178 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
179 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
180 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
181 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.endOffset
[0]);
182 // match "ac", (4,2] XXX NOTE: first match backward, not greedy
183 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
184 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
185 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.startOffset
[0]);
186 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRes
.endOffset
[0]);
188 aOptions
.searchString
= "b*a";
189 m_xSearch2
->setOptions2( aOptions
);
190 // match "ba", [1,3) XXX NOTE: first match forward, not greedy
191 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
192 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
193 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.startOffset
[0]);
194 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes
.endOffset
[0]);
195 // match "baca", (5,1] XXX NOTE: first match backward
196 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
197 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
198 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.startOffset
[0]);
199 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.endOffset
[0]);
203 aOptions
.searchString
= "?~??";
204 m_xSearch2
->setOptions2( aOptions
);
205 // match "b?c", [1,4)
206 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
207 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
208 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.startOffset
[0]);
209 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.endOffset
[0]);
210 // match "b?c", (4,1]
211 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
212 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
213 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.startOffset
[0]);
214 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.endOffset
[0]);
218 aOptions
.searchString
= "?~*?";
219 m_xSearch2
->setOptions2( aOptions
);
220 // match "b?c", [1,4)
221 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
222 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
223 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.startOffset
[0]);
224 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.endOffset
[0]);
225 // match "b?c", (4,1]
226 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
227 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
228 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRes
.startOffset
[0]);
229 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRes
.endOffset
[0]);
231 aOptions
.searchString
= "ca?";
232 m_xSearch2
->setOptions2( aOptions
);
234 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
235 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
237 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
238 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
240 aOptions
.searchString
= "ca*";
241 m_xSearch2
->setOptions2( aOptions
);
243 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
244 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
245 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes
.startOffset
[0]);
246 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.endOffset
[0]);
248 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
249 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
250 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.startOffset
[0]);
251 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes
.endOffset
[0]);
253 aOptions
.searchString
= "*ca*";
254 m_xSearch2
->setOptions2( aOptions
);
255 // match "abaca", [0,5)
256 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
257 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
258 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
259 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.endOffset
[0]);
260 // match "abaca", (5,0]
261 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
262 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
263 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aRes
.startOffset
[0]);
264 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.endOffset
[0]);
267 aOptions
.searchString
= "*2?";
268 m_xSearch2
->setOptions2( aOptions
);
269 // match first "123", [0,3)
270 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
271 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
272 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
273 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRes
.endOffset
[0]);
274 // match "123123", (6,0] Yes this looks odd, but it is as searching "?2*" forward.
275 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
276 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
277 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aRes
.startOffset
[0]);
278 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.endOffset
[0]);
280 aOptions
.searchFlag
|= util::SearchFlags::WILD_MATCH_SELECTION
;
281 m_xSearch2
->setOptions2( aOptions
);
282 // match "123123", [0,6) with greedy '*'
283 aRes
= m_xSearch2
->searchForward( aText
, 0, aText
.getLength());
284 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
285 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.startOffset
[0]);
286 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aRes
.endOffset
[0]);
287 // match "123123", (6,0]
288 aRes
= m_xSearch2
->searchBackward( aText
, aText
.getLength(), 0);
289 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.subRegExpressions
);
290 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aRes
.startOffset
[0]);
291 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aRes
.endOffset
[0]);
294 void TestTextSearch::testApostropheSearch()
296 // A) find typographic apostrophes also by using ASCII apostrophe in searchString
297 OUString
str( u
"It\u2019s an apostrophe." );
298 sal_Int32 startPos
= 0, endPos
= str
.getLength();
301 util::SearchOptions aOptions
;
302 aOptions
.algorithmType
= util::SearchAlgorithms_ABSOLUTE
;
303 aOptions
.searchFlag
= util::SearchFlags::ALL_IGNORE_CASE
;
304 aOptions
.searchString
= "'";
305 m_xSearch
->setOptions( aOptions
);
307 util::SearchResult aRes
;
310 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
312 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
313 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.startOffset
[0] );
314 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.endOffset
[0] );
317 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
319 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
320 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.startOffset
[0] );
321 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.endOffset
[0] );
323 // check with transliteration
324 aOptions
.transliterateFlags
= static_cast<int>(TransliterationFlags::IGNORE_CASE
325 | TransliterationFlags::IGNORE_WIDTH
);
326 m_xSearch
->setOptions(aOptions
);
329 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
331 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
332 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.startOffset
[0] );
333 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.endOffset
[0] );
336 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
338 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
339 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.startOffset
[0] );
340 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.endOffset
[0] );
342 // B) search ASCII apostrophe in a text with ASCII apostrophes
343 str
= str
.replace(u
'\u2019', '\'');
346 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
347 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
348 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.startOffset
[0] );
349 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.endOffset
[0] );
352 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
353 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
354 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.startOffset
[0] );
355 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.endOffset
[0] );
357 // C) search typographic apostrophe in a text with ASCII apostrophes (no result)
358 aOptions
.searchString
= OUString(u
"\u2019");
359 m_xSearch
->setOptions( aOptions
);
361 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
362 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
364 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
365 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
367 // D) search typographic apostrophe in a text with typographic apostrophes
368 str
= str
.replace('\'', u
'\u2019');
371 aRes
= m_xSearch
->searchForward( str
, startPos
, endPos
);
372 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
373 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.startOffset
[0] );
374 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.endOffset
[0] );
377 aRes
= m_xSearch
->searchBackward( str
, endPos
, startPos
);
378 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
379 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(3), aRes
.startOffset
[0] );
380 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(2), aRes
.endOffset
[0] );
382 // E) search mixed apostrophes in a text with mixed apostrophes:
383 aOptions
.searchString
= OUString(u
"'\u2019");
384 m_xSearch
->setOptions( aOptions
);
385 str
= u
"test: \u2019'";
388 aRes
= m_xSearch
->searchForward( str
, startPos
, str
.getLength());
389 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
392 aRes
= m_xSearch
->searchBackward( str
, str
.getLength(), startPos
);
393 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
395 // F) search mixed apostrophes in a text with ASCII apostrophes:
399 aRes
= m_xSearch
->searchForward( str
, startPos
, str
.getLength());
400 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
403 aRes
= m_xSearch
->searchBackward( str
, str
.getLength(), startPos
);
404 CPPUNIT_ASSERT( aRes
.subRegExpressions
> 0 );
407 void TestTextSearch::testTdf138410()
409 OUString
str(u
"\u0643\u064f\u062a\u064f\u0628 \u0643\u062a\u0628");
410 sal_Int32 startPos
= 0, endPos
= str
.getLength();
412 util::SearchOptions aOptions
;
413 aOptions
.algorithmType
= util::SearchAlgorithms_ABSOLUTE
;
415 util::SearchResult aRes
;
418 // The search string will be found whether it is followed by a mark in the
419 // text or not, and whether IGNORE_DIACRITICS_CTL is set or not.
422 aOptions
.searchString
= u
"\u0643";
423 aOptions
.transliterateFlags
= 0;
424 m_xSearch
->setOptions(aOptions
);
427 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
428 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
429 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.startOffset
[0]);
430 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.endOffset
[0]);
433 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
434 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
435 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(7), aRes
.startOffset
[0]);
436 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(6), aRes
.endOffset
[0]);
438 // check with transliteration
439 aOptions
.transliterateFlags
= static_cast<int>(TransliterationFlags::IGNORE_DIACRITICS_CTL
);
440 m_xSearch
->setOptions(aOptions
);
443 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
444 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
445 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.startOffset
[0]);
446 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.endOffset
[0]);
449 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
450 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
451 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(7), aRes
.startOffset
[0]);
452 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(6), aRes
.endOffset
[0]);
455 // The search string will be found when followed by a mark in the text, or
456 // when IGNORE_DIACRITICS_CTL is set whether it is followed by a mark or
460 aOptions
.searchString
= u
"\u0643\u064f";
461 aOptions
.transliterateFlags
= 0;
462 m_xSearch
->setOptions(aOptions
);
465 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
466 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
467 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.startOffset
[0]);
468 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), aRes
.endOffset
[0]);
471 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
472 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
473 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), aRes
.startOffset
[0]);
474 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.endOffset
[0]);
476 // check with transliteration
477 aOptions
.transliterateFlags
= static_cast<int>(TransliterationFlags::IGNORE_DIACRITICS_CTL
);
478 m_xSearch
->setOptions(aOptions
);
481 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
482 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
483 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.startOffset
[0]);
484 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.endOffset
[0]);
487 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
488 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
489 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(7), aRes
.startOffset
[0]);
490 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(6), aRes
.endOffset
[0]);
493 // The search string will be found only when IGNORE_DIACRITICS_CTL is not
497 aOptions
.searchString
= u
"\u064f";
498 aOptions
.transliterateFlags
= 0;
499 m_xSearch
->setOptions(aOptions
);
502 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
503 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
504 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aRes
.startOffset
[0]);
505 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), aRes
.endOffset
[0]);
508 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
509 CPPUNIT_ASSERT(aRes
.subRegExpressions
> 0);
510 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(4), aRes
.startOffset
[0]);
511 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(3), aRes
.endOffset
[0]);
513 // with ignore marks the mark will not be found
514 aOptions
.transliterateFlags
= static_cast<int>(TransliterationFlags::IGNORE_DIACRITICS_CTL
);
515 m_xSearch
->setOptions(aOptions
);
518 aRes
= m_xSearch
->searchForward(str
, startPos
, endPos
);
519 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
522 aRes
= m_xSearch
->searchBackward(str
, endPos
, startPos
);
523 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), aRes
.subRegExpressions
);
526 void TestTextSearch::setUp()
528 BootstrapFixtureBase::setUp();
529 m_xSearch
.set(m_xSFactory
->createInstance("com.sun.star.util.TextSearch"), uno::UNO_QUERY_THROW
);
530 m_xSearch2
.set(m_xSFactory
->createInstance("com.sun.star.util.TextSearch2"), uno::UNO_QUERY_THROW
);
533 void TestTextSearch::tearDown()
537 BootstrapFixtureBase::tearDown();
540 CPPUNIT_TEST_SUITE_REGISTRATION(TestTextSearch
);
542 CPPUNIT_PLUGIN_IMPLEMENT();
544 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */