Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "textsearch.hxx"
31 : : #include "levdis.hxx"
32 : : #include <regexp/reclass.hxx>
33 : : #include <com/sun/star/lang/Locale.hpp>
34 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 : : #include <comphelper/processfactory.hxx>
36 : : #include <com/sun/star/i18n/UnicodeType.hpp>
37 : : #include <com/sun/star/util/SearchFlags.hpp>
38 : : #include <com/sun/star/i18n/WordType.hpp>
39 : : #include <com/sun/star/i18n/ScriptType.hpp>
40 : : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
41 : : #include <com/sun/star/i18n/KCharacterType.hpp>
42 : : #include <com/sun/star/registry/XRegistryKey.hpp>
43 : : #include <cppuhelper/factory.hxx>
44 : : #include <cppuhelper/weak.hxx>
45 : :
46 : : #ifdef _MSC_VER
47 : : // get rid of that dumb compiler warning
48 : : // identifier was truncated to '255' characters in the debug information
49 : : // for STL template usage, if .pdb files are to be created
50 : : #pragma warning( disable: 4786 )
51 : : #endif
52 : :
53 : : #include <string.h>
54 : :
55 : : using namespace ::com::sun::star::util;
56 : : using namespace ::com::sun::star::uno;
57 : : using namespace ::com::sun::star::lang;
58 : : using namespace ::com::sun::star::i18n;
59 : : using namespace ::rtl;
60 : :
61 : : static sal_Int32 COMPLEX_TRANS_MASK_TMP =
62 : : TransliterationModules_ignoreBaFa_ja_JP |
63 : : TransliterationModules_ignoreIterationMark_ja_JP |
64 : : TransliterationModules_ignoreTiJi_ja_JP |
65 : : TransliterationModules_ignoreHyuByu_ja_JP |
66 : : TransliterationModules_ignoreSeZe_ja_JP |
67 : : TransliterationModules_ignoreIandEfollowedByYa_ja_JP |
68 : : TransliterationModules_ignoreKiKuFollowedBySa_ja_JP |
69 : : TransliterationModules_ignoreProlongedSoundMark_ja_JP;
70 : 7 : static const sal_Int32 SIMPLE_TRANS_MASK = 0xffffffff ^ COMPLEX_TRANS_MASK_TMP;
71 : 7 : static const sal_Int32 COMPLEX_TRANS_MASK =
72 : : COMPLEX_TRANS_MASK_TMP |
73 : : TransliterationModules_IGNORE_KANA |
74 : : TransliterationModules_IGNORE_WIDTH;
75 : : // Above 2 transliteration is simple but need to take effect in
76 : : // complex transliteration
77 : :
78 : 61 : TextSearch::TextSearch(const Reference < XMultiServiceFactory > & rxMSF)
79 : : : xMSF( rxMSF )
80 : : , pJumpTable( 0 )
81 : : , pJumpTable2( 0 )
82 : : , pRegExp( 0 )
83 : 61 : , pWLD( 0 )
84 : : {
85 : 61 : SearchOptions aOpt;
86 : 61 : aOpt.algorithmType = SearchAlgorithms_ABSOLUTE;
87 : 61 : aOpt.searchFlag = SearchFlags::ALL_IGNORE_CASE;
88 : : //aOpt.Locale = ???;
89 [ + - ]: 61 : setOptions( aOpt );
90 : 61 : }
91 : :
92 : 54 : TextSearch::~TextSearch()
93 : : {
94 [ - + ][ # # ]: 54 : delete pRegExp;
95 [ - + ][ # # ]: 54 : delete pWLD;
96 [ + + ]: 54 : delete pJumpTable;
97 [ - + ]: 54 : delete pJumpTable2;
98 [ - + ]: 108 : }
99 : :
100 : 122 : void TextSearch::setOptions( const SearchOptions& rOptions ) throw( RuntimeException )
101 : : {
102 : 122 : aSrchPara = rOptions;
103 : :
104 [ - + ]: 122 : delete pRegExp, pRegExp = 0;
105 [ - + ]: 122 : delete pWLD, pWLD = 0;
106 [ - + ]: 122 : delete pJumpTable, pJumpTable = 0;
107 [ - + ]: 122 : delete pJumpTable2, pJumpTable2 = 0;
108 : :
109 : : // Create Transliteration class
110 [ + + ]: 122 : if( aSrchPara.transliterateFlags & SIMPLE_TRANS_MASK )
111 : : {
112 [ + - ]: 61 : if( !xTranslit.is() )
113 : : {
114 [ + - ]: 61 : Reference < XInterface > xI = xMSF->createInstance(
115 : : OUString(
116 [ + - ]: 61 : "com.sun.star.i18n.Transliteration"));
117 [ + - ]: 61 : if ( xI.is() )
118 [ + - ]: 61 : xI->queryInterface( ::getCppuType(
119 [ + - ]: 61 : (const Reference< XExtendedTransliteration >*)0))
120 [ + - ][ + - ]: 61 : >>= xTranslit;
121 : : }
122 : : // Load transliteration module
123 [ + - ]: 61 : if( xTranslit.is() )
124 : 61 : xTranslit->loadModule(
125 : : (TransliterationModules)( aSrchPara.transliterateFlags & SIMPLE_TRANS_MASK ),
126 : 61 : aSrchPara.Locale);
127 : : }
128 [ - + ]: 61 : else if( xTranslit.is() )
129 : 0 : xTranslit = 0;
130 : :
131 : : // Create Transliteration for 2<->1, 2<->2 transliteration
132 [ - + ]: 122 : if ( aSrchPara.transliterateFlags & COMPLEX_TRANS_MASK )
133 : : {
134 [ # # ]: 0 : if( !xTranslit2.is() )
135 : : {
136 [ # # ]: 0 : Reference < XInterface > xI = xMSF->createInstance(
137 : : OUString(
138 [ # # ]: 0 : "com.sun.star.i18n.Transliteration"));
139 [ # # ]: 0 : if ( xI.is() )
140 [ # # ]: 0 : xI->queryInterface( ::getCppuType(
141 [ # # ]: 0 : (const Reference< XExtendedTransliteration >*)0))
142 [ # # ][ # # ]: 0 : >>= xTranslit2;
143 : : }
144 : : // Load transliteration module
145 [ # # ]: 0 : if( xTranslit2.is() )
146 : 0 : xTranslit2->loadModule(
147 : : (TransliterationModules)( aSrchPara.transliterateFlags & COMPLEX_TRANS_MASK ),
148 : 0 : aSrchPara.Locale);
149 : : }
150 : :
151 [ + + ]: 122 : if ( !xBreak.is() )
152 : : {
153 [ + - ]: 61 : Reference < XInterface > xI = xMSF->createInstance(
154 [ + - ]: 61 : OUString("com.sun.star.i18n.BreakIterator"));
155 [ + - ]: 61 : if( xI.is() )
156 [ + - ]: 61 : xI->queryInterface( ::getCppuType(
157 [ + - ]: 61 : (const Reference< XBreakIterator >*)0))
158 [ + - ][ + - ]: 61 : >>= xBreak;
159 : : }
160 : :
161 : 122 : sSrchStr = aSrchPara.searchString;
162 : :
163 : : // use transliteration here, but only if not RegEx, which does it different
164 [ + + ][ + - ]: 122 : if ( aSrchPara.algorithmType != SearchAlgorithms_REGEXP && xTranslit.is() &&
[ + + ][ + - ]
165 : : aSrchPara.transliterateFlags & SIMPLE_TRANS_MASK )
166 : 61 : sSrchStr = xTranslit->transliterateString2String(
167 : 61 : aSrchPara.searchString, 0, aSrchPara.searchString.getLength());
168 : :
169 [ + - ][ - + ]: 122 : if ( aSrchPara.algorithmType != SearchAlgorithms_REGEXP && xTranslit2.is() &&
[ # # ][ - + ]
170 : : aSrchPara.transliterateFlags & COMPLEX_TRANS_MASK )
171 : 0 : sSrchStr2 = xTranslit2->transliterateString2String(
172 : 0 : aSrchPara.searchString, 0, aSrchPara.searchString.getLength());
173 : :
174 : : // When start or end of search string is a complex script type, we need to
175 : : // make sure the result boundary is not located in the middle of cell.
176 : 244 : checkCTLStart = (xBreak.is() && (xBreak->getScriptType(sSrchStr, 0) ==
177 [ + - - + ]: 244 : ScriptType::COMPLEX));
178 : 244 : checkCTLEnd = (xBreak.is() && (xBreak->getScriptType(sSrchStr,
179 [ + - - + ]: 244 : sSrchStr.getLength()-1) == ScriptType::COMPLEX));
180 : :
181 [ - + ]: 122 : if ( aSrchPara.algorithmType == SearchAlgorithms_REGEXP )
182 : : {
183 : 0 : fnForward = &TextSearch::RESrchFrwrd;
184 : 0 : fnBackward = &TextSearch::RESrchBkwrd;
185 : :
186 [ # # ][ # # ]: 0 : pRegExp = new Regexpr( aSrchPara, xTranslit );
187 : : }
188 : : else
189 : : {
190 [ - + ]: 122 : if ( aSrchPara.algorithmType == SearchAlgorithms_APPROXIMATE )
191 : : {
192 : 0 : fnForward = &TextSearch::ApproxSrchFrwrd;
193 : 0 : fnBackward = &TextSearch::ApproxSrchBkwrd;
194 : :
195 : 0 : pWLD = new WLevDistance( sSrchStr.getStr(), aSrchPara.changedChars,
196 : : aSrchPara.insertedChars, aSrchPara.deletedChars,
197 [ # # ]: 0 : 0 != (SearchFlags::LEV_RELAXED & aSrchPara.searchFlag ) );
198 : :
199 : 0 : nLimit = pWLD->GetLimit();
200 : : }
201 : : else
202 : : {
203 : 122 : fnForward = &TextSearch::NSrchFrwrd;
204 : 122 : fnBackward = &TextSearch::NSrchBkwrd;
205 : : }
206 : : }
207 : 122 : }
208 : :
209 : 154 : sal_Int32 FindPosInSeq_Impl( const Sequence <sal_Int32>& rOff, sal_Int32 nPos )
210 : : {
211 : 154 : sal_Int32 nRet = 0, nEnd = rOff.getLength();
212 [ + - ][ + + ]: 8444 : while( nRet < nEnd && nPos > rOff[ nRet ] ) ++nRet;
[ + + ]
213 : 154 : return nRet;
214 : : }
215 : :
216 : 0 : sal_Bool TextSearch::isCellStart(const OUString& searchStr, sal_Int32 nPos)
217 : : throw( RuntimeException )
218 : : {
219 : : sal_Int32 nDone;
220 [ # # ]: 0 : return nPos == xBreak->previousCharacters(searchStr, nPos+1,
221 [ # # ]: 0 : aSrchPara.Locale, CharacterIteratorMode::SKIPCELL, 1, nDone);
222 : : }
223 : :
224 : 648 : SearchResult TextSearch::searchForward( const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos )
225 : : throw( RuntimeException )
226 : : {
227 [ + - ]: 648 : SearchResult sres;
228 : :
229 : 648 : OUString in_str(searchStr);
230 : 648 : sal_Int32 newStartPos = startPos;
231 : 648 : sal_Int32 newEndPos = endPos;
232 : :
233 : 648 : bUsePrimarySrchStr = true;
234 : :
235 [ + - ]: 648 : if ( xTranslit.is() )
236 : : {
237 : : // apply normal transliteration (1<->1, 1<->0)
238 [ + - ]: 648 : com::sun::star::uno::Sequence <sal_Int32> offset( in_str.getLength());
239 [ + - ][ + - ]: 648 : in_str = xTranslit->transliterate( searchStr, 0, in_str.getLength(), offset );
240 : :
241 : : // JP 20.6.2001: also the start and end positions must be corrected!
242 [ + + ]: 648 : if( startPos )
243 [ + - ]: 154 : newStartPos = FindPosInSeq_Impl( offset, startPos );
244 : :
245 [ - + ]: 648 : if( endPos < searchStr.getLength() )
246 [ # # ]: 0 : newEndPos = FindPosInSeq_Impl( offset, endPos );
247 : : else
248 : 648 : newEndPos = in_str.getLength();
249 : :
250 [ + - ][ + - ]: 648 : sres = (this->*fnForward)( in_str, newStartPos, newEndPos );
[ + - ][ + - ]
251 : :
252 [ + + ]: 889 : for ( int k = 0; k < sres.startOffset.getLength(); k++ )
253 : : {
254 [ + - ][ + + ]: 241 : if (sres.startOffset[k])
255 [ + - ][ + - ]: 150 : sres.startOffset[k] = offset[sres.startOffset[k]];
[ + - ]
256 : : // JP 20.6.2001: end is ever exclusive and then don't return
257 : : // the position of the next character - return the
258 : : // next position behind the last found character!
259 : : // "a b c" find "b" must return 2,3 and not 2,4!!!
260 [ + - ][ + - ]: 241 : if (sres.endOffset[k])
261 [ + - ][ + - ]: 241 : sres.endOffset[k] = offset[sres.endOffset[k]-1] + 1;
[ + - ]
262 [ + - ]: 648 : }
263 : : }
264 : : else
265 : : {
266 [ # # ][ # # ]: 0 : sres = (this->*fnForward)( in_str, startPos, endPos );
[ # # ][ # # ]
267 : : }
268 : :
269 [ - + ][ # # ]: 648 : if ( xTranslit2.is() && aSrchPara.algorithmType != SearchAlgorithms_REGEXP)
[ - + ]
270 : : {
271 [ # # ]: 0 : SearchResult sres2;
272 : :
273 : 0 : in_str = OUString(searchStr);
274 [ # # ]: 0 : com::sun::star::uno::Sequence <sal_Int32> offset( in_str.getLength());
275 : :
276 [ # # ][ # # ]: 0 : in_str = xTranslit2->transliterate( searchStr, 0, in_str.getLength(), offset );
277 : :
278 [ # # ]: 0 : if( startPos )
279 [ # # ]: 0 : startPos = FindPosInSeq_Impl( offset, startPos );
280 : :
281 [ # # ]: 0 : if( endPos < searchStr.getLength() )
282 [ # # ]: 0 : endPos = FindPosInSeq_Impl( offset, endPos );
283 : : else
284 : 0 : endPos = in_str.getLength();
285 : :
286 : 0 : bUsePrimarySrchStr = false;
287 [ # # ][ # # ]: 0 : sres2 = (this->*fnForward)( in_str, startPos, endPos );
[ # # ][ # # ]
288 : :
289 [ # # ]: 0 : for ( int k = 0; k < sres2.startOffset.getLength(); k++ )
290 : : {
291 [ # # ][ # # ]: 0 : if (sres2.startOffset[k])
292 [ # # ][ # # ]: 0 : sres2.startOffset[k] = offset[sres2.startOffset[k]-1] + 1;
[ # # ]
293 [ # # ][ # # ]: 0 : if (sres2.endOffset[k])
294 [ # # ][ # # ]: 0 : sres2.endOffset[k] = offset[sres2.endOffset[k]-1] + 1;
[ # # ]
295 : : }
296 : :
297 : : // pick first and long one
298 [ # # ]: 0 : if ( sres.subRegExpressions == 0)
299 [ # # ]: 0 : return sres2;
300 [ # # ]: 0 : if ( sres2.subRegExpressions == 1)
301 : : {
302 [ # # ][ # # ]: 0 : if ( sres.startOffset[0] > sres2.startOffset[0])
[ # # ]
303 [ # # ]: 0 : return sres2;
304 [ # # ][ # # ]: 0 : else if ( sres.startOffset[0] == sres2.startOffset[0] &&
[ # # ][ # # ]
[ # # ]
305 [ # # ][ # # ]: 0 : sres.endOffset[0] < sres2.endOffset[0])
306 [ # # ]: 0 : return sres2;
307 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
308 : : }
309 : :
310 [ + - ][ + - ]: 648 : return sres;
311 : : }
312 : :
313 : 0 : SearchResult TextSearch::searchBackward( const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos )
314 : : throw(RuntimeException)
315 : : {
316 [ # # ]: 0 : SearchResult sres;
317 : :
318 : 0 : OUString in_str(searchStr);
319 : 0 : sal_Int32 newStartPos = startPos;
320 : 0 : sal_Int32 newEndPos = endPos;
321 : :
322 : 0 : bUsePrimarySrchStr = true;
323 : :
324 [ # # ]: 0 : if ( xTranslit.is() )
325 : : {
326 : : // apply only simple 1<->1 transliteration here
327 [ # # ]: 0 : com::sun::star::uno::Sequence <sal_Int32> offset( in_str.getLength());
328 [ # # ][ # # ]: 0 : in_str = xTranslit->transliterate( searchStr, 0, in_str.getLength(), offset );
329 : :
330 : : // JP 20.6.2001: also the start and end positions must be corrected!
331 [ # # ]: 0 : if( startPos < searchStr.getLength() )
332 [ # # ]: 0 : newStartPos = FindPosInSeq_Impl( offset, startPos );
333 : : else
334 : 0 : newStartPos = in_str.getLength();
335 : :
336 [ # # ]: 0 : if( endPos )
337 [ # # ]: 0 : newEndPos = FindPosInSeq_Impl( offset, endPos );
338 : :
339 [ # # ][ # # ]: 0 : sres = (this->*fnBackward)( in_str, newStartPos, newEndPos );
[ # # ][ # # ]
340 : :
341 [ # # ]: 0 : for ( int k = 0; k < sres.startOffset.getLength(); k++ )
342 : : {
343 [ # # ][ # # ]: 0 : if (sres.startOffset[k])
344 [ # # ][ # # ]: 0 : sres.startOffset[k] = offset[sres.startOffset[k] - 1] + 1;
[ # # ]
345 : : // JP 20.6.2001: end is ever exclusive and then don't return
346 : : // the position of the next character - return the
347 : : // next position behind the last found character!
348 : : // "a b c" find "b" must return 2,3 and not 2,4!!!
349 [ # # ][ # # ]: 0 : if (sres.endOffset[k])
350 [ # # ][ # # ]: 0 : sres.endOffset[k] = offset[sres.endOffset[k]];
[ # # ]
351 [ # # ]: 0 : }
352 : : }
353 : : else
354 : : {
355 [ # # ][ # # ]: 0 : sres = (this->*fnBackward)( in_str, startPos, endPos );
[ # # ][ # # ]
356 : : }
357 : :
358 [ # # ][ # # ]: 0 : if ( xTranslit2.is() && aSrchPara.algorithmType != SearchAlgorithms_REGEXP )
[ # # ]
359 : : {
360 [ # # ]: 0 : SearchResult sres2;
361 : :
362 : 0 : in_str = OUString(searchStr);
363 [ # # ]: 0 : com::sun::star::uno::Sequence <sal_Int32> offset( in_str.getLength());
364 : :
365 [ # # ][ # # ]: 0 : in_str = xTranslit2->transliterate(searchStr, 0, in_str.getLength(), offset);
366 : :
367 [ # # ]: 0 : if( startPos < searchStr.getLength() )
368 [ # # ]: 0 : startPos = FindPosInSeq_Impl( offset, startPos );
369 : : else
370 : 0 : startPos = in_str.getLength();
371 : :
372 [ # # ]: 0 : if( endPos )
373 [ # # ]: 0 : endPos = FindPosInSeq_Impl( offset, endPos );
374 : :
375 : 0 : bUsePrimarySrchStr = false;
376 [ # # ][ # # ]: 0 : sres2 = (this->*fnBackward)( in_str, startPos, endPos );
[ # # ][ # # ]
377 : :
378 [ # # ]: 0 : for( int k = 0; k < sres2.startOffset.getLength(); k++ )
379 : : {
380 [ # # ][ # # ]: 0 : if (sres2.startOffset[k])
381 [ # # ][ # # ]: 0 : sres2.startOffset[k] = offset[sres2.startOffset[k]-1]+1;
[ # # ]
382 [ # # ][ # # ]: 0 : if (sres2.endOffset[k])
383 [ # # ][ # # ]: 0 : sres2.endOffset[k] = offset[sres2.endOffset[k]-1]+1;
[ # # ]
384 : : }
385 : :
386 : : // pick last and long one
387 [ # # ]: 0 : if ( sres.subRegExpressions == 0 )
388 [ # # ]: 0 : return sres2;
389 [ # # ]: 0 : if ( sres2.subRegExpressions == 1 )
390 : : {
391 [ # # ][ # # ]: 0 : if ( sres.startOffset[0] < sres2.startOffset[0] )
[ # # ]
392 [ # # ]: 0 : return sres2;
393 [ # # ][ # # ]: 0 : if ( sres.startOffset[0] == sres2.startOffset[0] &&
[ # # ][ # # ]
[ # # ]
394 [ # # ][ # # ]: 0 : sres.endOffset[0] > sres2.endOffset[0] )
395 [ # # ]: 0 : return sres2;
396 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
397 : : }
398 : :
399 [ # # ][ # # ]: 0 : return sres;
400 : : }
401 : :
402 : :
403 : :
404 : : //--------------- die Wort-Trennner ----------------------------------
405 : :
406 : 0 : bool TextSearch::IsDelimiter( const OUString& rStr, sal_Int32 nPos ) const
407 : : {
408 : 0 : bool bRet = 1;
409 [ # # ]: 0 : if( '\x7f' != rStr[nPos])
410 : : {
411 [ # # ]: 0 : if ( !xCharClass.is() )
412 : : {
413 [ # # ]: 0 : Reference < XInterface > xI = xMSF->createInstance(
414 [ # # ]: 0 : OUString("com.sun.star.i18n.CharacterClassification"));
415 [ # # ]: 0 : if( xI.is() )
416 [ # # ]: 0 : xI->queryInterface( ::getCppuType(
417 [ # # ]: 0 : (const Reference< XCharacterClassification >*)0))
418 [ # # ][ # # ]: 0 : >>= xCharClass;
419 : : }
420 [ # # ]: 0 : if ( xCharClass.is() )
421 : : {
422 : 0 : sal_Int32 nCType = xCharClass->getCharacterType( rStr, nPos,
423 : 0 : aSrchPara.Locale );
424 [ # # ]: 0 : if( 0 != (( KCharacterType::DIGIT | KCharacterType::ALPHA |
425 : : KCharacterType::LETTER ) & nCType ) )
426 : 0 : bRet = 0;
427 : : }
428 : : }
429 : 0 : return bRet;
430 : : }
431 : :
432 : :
433 : :
434 : : // --------- methods for the kind of boyer-morre search ------------------
435 : :
436 : :
437 : 406 : void TextSearch::MakeForwardTab()
438 : : {
439 : : // create the jumptable for the search text
440 [ + + ]: 406 : if( pJumpTable )
441 : : {
442 [ + - ]: 349 : if( bIsForwardTab )
443 : 406 : return ; // the jumpTable is ok
444 [ # # ]: 0 : delete pJumpTable;
445 : : }
446 : 57 : bIsForwardTab = true;
447 : :
448 : 57 : sal_Int32 n, nLen = sSrchStr.getLength();
449 [ + - ]: 57 : pJumpTable = new TextSearchJumpTable;
450 : :
451 [ + + ]: 441 : for( n = 0; n < nLen - 1; ++n )
452 : : {
453 : 384 : sal_Unicode cCh = sSrchStr[n];
454 : 384 : sal_Int32 nDiff = nLen - n - 1;
455 [ + - ]: 384 : TextSearchJumpTable::value_type aEntry( cCh, nDiff );
456 : :
457 : : ::std::pair< TextSearchJumpTable::iterator, bool > aPair =
458 [ + - ]: 384 : pJumpTable->insert( aEntry );
459 [ + + ]: 384 : if ( !aPair.second )
460 [ + - ]: 129 : (*(aPair.first)).second = nDiff;
461 : : }
462 : : }
463 : :
464 : 0 : void TextSearch::MakeForwardTab2()
465 : : {
466 : : // create the jumptable for the search text
467 [ # # ]: 0 : if( pJumpTable2 )
468 : : {
469 [ # # ]: 0 : if( bIsForwardTab )
470 : 0 : return ; // the jumpTable is ok
471 [ # # ]: 0 : delete pJumpTable2;
472 : : }
473 : 0 : bIsForwardTab = true;
474 : :
475 : 0 : sal_Int32 n, nLen = sSrchStr2.getLength();
476 [ # # ]: 0 : pJumpTable2 = new TextSearchJumpTable;
477 : :
478 [ # # ]: 0 : for( n = 0; n < nLen - 1; ++n )
479 : : {
480 : 0 : sal_Unicode cCh = sSrchStr2[n];
481 : 0 : sal_Int32 nDiff = nLen - n - 1;
482 : :
483 [ # # ]: 0 : TextSearchJumpTable::value_type aEntry( cCh, nDiff );
484 : : ::std::pair< TextSearchJumpTable::iterator, bool > aPair =
485 [ # # ]: 0 : pJumpTable2->insert( aEntry );
486 [ # # ]: 0 : if ( !aPair.second )
487 [ # # ]: 0 : (*(aPair.first)).second = nDiff;
488 : : }
489 : : }
490 : :
491 : 0 : void TextSearch::MakeBackwardTab()
492 : : {
493 : : // create the jumptable for the search text
494 [ # # ]: 0 : if( pJumpTable )
495 : : {
496 [ # # ]: 0 : if( !bIsForwardTab )
497 : 0 : return ; // the jumpTable is ok
498 [ # # ]: 0 : delete pJumpTable;
499 : : }
500 : 0 : bIsForwardTab = false;
501 : :
502 : 0 : sal_Int32 n, nLen = sSrchStr.getLength();
503 [ # # ][ # # ]: 0 : pJumpTable = new TextSearchJumpTable;
504 : :
505 [ # # ]: 0 : for( n = nLen-1; n > 0; --n )
506 : : {
507 : 0 : sal_Unicode cCh = sSrchStr[n];
508 [ # # ]: 0 : TextSearchJumpTable::value_type aEntry( cCh, n );
509 : : ::std::pair< TextSearchJumpTable::iterator, bool > aPair =
510 [ # # ]: 0 : pJumpTable->insert( aEntry );
511 [ # # ]: 0 : if ( !aPair.second )
512 [ # # ]: 0 : (*(aPair.first)).second = n;
513 : : }
514 : : }
515 : :
516 : 0 : void TextSearch::MakeBackwardTab2()
517 : : {
518 : : // create the jumptable for the search text
519 [ # # ]: 0 : if( pJumpTable2 )
520 : : {
521 [ # # ]: 0 : if( !bIsForwardTab )
522 : 0 : return ; // the jumpTable is ok
523 [ # # ]: 0 : delete pJumpTable2;
524 : : }
525 : 0 : bIsForwardTab = false;
526 : :
527 : 0 : sal_Int32 n, nLen = sSrchStr2.getLength();
528 [ # # ][ # # ]: 0 : pJumpTable2 = new TextSearchJumpTable;
529 : :
530 [ # # ]: 0 : for( n = nLen-1; n > 0; --n )
531 : : {
532 : 0 : sal_Unicode cCh = sSrchStr2[n];
533 [ # # ]: 0 : TextSearchJumpTable::value_type aEntry( cCh, n );
534 : : ::std::pair< TextSearchJumpTable::iterator, bool > aPair =
535 [ # # ]: 0 : pJumpTable2->insert( aEntry );
536 [ # # ]: 0 : if ( !aPair.second )
537 [ # # ]: 0 : (*(aPair.first)).second = n;
538 : : }
539 : : }
540 : :
541 : 1740 : sal_Int32 TextSearch::GetDiff( const sal_Unicode cChr ) const
542 : : {
543 : : TextSearchJumpTable *pJump;
544 : 1740 : OUString sSearchKey;
545 : :
546 [ + - ]: 1740 : if ( bUsePrimarySrchStr ) {
547 : 1740 : pJump = pJumpTable;
548 : 1740 : sSearchKey = sSrchStr;
549 : : } else {
550 : 0 : pJump = pJumpTable2;
551 : 0 : sSearchKey = sSrchStr2;
552 : : }
553 : :
554 [ + - ][ + - ]: 1740 : TextSearchJumpTable::const_iterator iLook = pJump->find( cChr );
555 [ + - ][ + - ]: 1740 : if ( iLook == pJump->end() )
[ + + ]
556 : 1458 : return sSearchKey.getLength();
557 [ + - ]: 1740 : return (*iLook).second;
558 : : }
559 : :
560 : :
561 : : // TextSearch::NSrchFrwrd is mis-optimized on unxsoli (#i105945#)
562 : 648 : SearchResult TextSearch::NSrchFrwrd( const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos )
563 : : throw(RuntimeException)
564 : : {
565 [ + - ]: 648 : SearchResult aRet;
566 : 648 : aRet.subRegExpressions = 0;
567 : :
568 [ + - ]: 648 : OUString sSearchKey = bUsePrimarySrchStr ? sSrchStr : sSrchStr2;
569 : :
570 : 648 : OUString aStr( searchStr );
571 : 648 : sal_Int32 nSuchIdx = aStr.getLength();
572 : 648 : sal_Int32 nEnde = endPos;
573 [ + - ][ + + ]: 648 : if( !nSuchIdx || !sSearchKey.getLength() || sSearchKey.getLength() > nSuchIdx )
[ + + ][ + - ]
574 : : return aRet;
575 : :
576 : :
577 [ + - ]: 406 : if( nEnde < sSearchKey.getLength() ) // position inside the search region ?
578 : : return aRet;
579 : :
580 : 406 : nEnde -= sSearchKey.getLength();
581 : :
582 [ + - ]: 406 : if (bUsePrimarySrchStr)
583 [ + - ]: 406 : MakeForwardTab(); // create the jumptable
584 : : else
585 [ # # ]: 0 : MakeForwardTab2();
586 : :
587 [ + - ][ + + ]: 2146 : for (sal_Int32 nCmpIdx = startPos; // start position for the search
588 : : nCmpIdx <= nEnde;
589 : 1740 : nCmpIdx += GetDiff( aStr[nCmpIdx + sSearchKey.getLength()-1]))
590 : : {
591 : : // if the match would be the completed cells, skip it.
592 [ - + ][ # # ]: 1981 : if ( (checkCTLStart && !isCellStart( aStr, nCmpIdx )) || (checkCTLEnd
[ # # ][ - + ]
[ # # ][ - + ]
593 [ # # ]: 0 : && !isCellStart( aStr, nCmpIdx + sSearchKey.getLength())) )
594 : 0 : continue;
595 : :
596 : 1981 : nSuchIdx = sSearchKey.getLength() - 1;
597 [ + - ][ + + ]: 4203 : while( nSuchIdx >= 0 && sSearchKey[nSuchIdx] == aStr[nCmpIdx + nSuchIdx])
[ + + ]
598 : : {
599 [ + + ]: 2463 : if( nSuchIdx == 0 )
600 : : {
601 [ - + ]: 241 : if( SearchFlags::NORM_WORD_ONLY & aSrchPara.searchFlag )
602 : : {
603 : 0 : sal_Int32 nFndEnd = nCmpIdx + sSearchKey.getLength();
604 : 0 : bool bAtStart = !nCmpIdx;
605 : 0 : bool bAtEnd = nFndEnd == endPos;
606 [ # # ][ # # ]: 0 : bool bDelimBefore = bAtStart || IsDelimiter( aStr, nCmpIdx-1 );
[ # # ]
607 [ # # ]: 0 : bool bDelimBehind = IsDelimiter( aStr, nFndEnd );
608 : : // * 1 -> only one word in the paragraph
609 : : // * 2 -> at begin of paragraph
610 : : // * 3 -> at end of paragraph
611 : : // * 4 -> inside the paragraph
612 [ # # ]: 0 : if( !( ( bAtStart && bAtEnd ) || // 1
613 : : ( bAtStart && bDelimBehind ) || // 2
614 : : ( bAtEnd && bDelimBefore ) || // 3
615 [ # # ][ # # ]: 0 : ( bDelimBefore && bDelimBehind ))) // 4
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
616 : 0 : break;
617 : : }
618 : :
619 : 241 : aRet.subRegExpressions = 1;
620 [ + - ]: 241 : aRet.startOffset.realloc( 1 );
621 [ + - ]: 241 : aRet.startOffset[ 0 ] = nCmpIdx;
622 [ + - ]: 241 : aRet.endOffset.realloc( 1 );
623 [ + - ]: 241 : aRet.endOffset[ 0 ] = nCmpIdx + sSearchKey.getLength();
624 : :
625 : : return aRet;
626 : : }
627 : : else
628 : 2222 : nSuchIdx--;
629 : : }
630 : : }
631 : 648 : return aRet;
632 : : }
633 : :
634 : 0 : SearchResult TextSearch::NSrchBkwrd( const OUString& searchStr, sal_Int32 startPos, sal_Int32 endPos )
635 : : throw(RuntimeException)
636 : : {
637 [ # # ]: 0 : SearchResult aRet;
638 : 0 : aRet.subRegExpressions = 0;
639 : :
640 [ # # ]: 0 : OUString sSearchKey = bUsePrimarySrchStr ? sSrchStr : sSrchStr2;
641 : :
642 : 0 : OUString aStr( searchStr );
643 : 0 : sal_Int32 nSuchIdx = aStr.getLength();
644 : 0 : sal_Int32 nEnde = endPos;
645 [ # # ][ # # ]: 0 : if( nSuchIdx == 0 || sSearchKey.isEmpty() || sSearchKey.getLength() > nSuchIdx)
[ # # ][ # # ]
646 : : return aRet;
647 : :
648 [ # # ]: 0 : if (bUsePrimarySrchStr)
649 [ # # ]: 0 : MakeBackwardTab(); // create the jumptable
650 : : else
651 [ # # ]: 0 : MakeBackwardTab2();
652 : :
653 [ # # ]: 0 : if( nEnde == nSuchIdx ) // end position for the search
654 : 0 : nEnde = sSearchKey.getLength();
655 : : else
656 : 0 : nEnde += sSearchKey.getLength();
657 : :
658 : 0 : sal_Int32 nCmpIdx = startPos; // start position for the search
659 : :
660 [ # # ]: 0 : while (nCmpIdx >= nEnde)
661 : : {
662 : : // if the match would be the completed cells, skip it.
663 [ # # ][ # # ]: 0 : if ( (!checkCTLStart || isCellStart( aStr, nCmpIdx -
[ # # ][ # # ]
[ # # ]
664 [ # # ]: 0 : sSearchKey.getLength() )) && (!checkCTLEnd ||
665 [ # # ]: 0 : isCellStart( aStr, nCmpIdx)))
666 : : {
667 : 0 : nSuchIdx = 0;
668 [ # # ][ # # ]: 0 : while( nSuchIdx < sSearchKey.getLength() && sSearchKey[nSuchIdx] ==
[ # # ]
669 : 0 : aStr[nCmpIdx + nSuchIdx - sSearchKey.getLength()] )
670 : 0 : nSuchIdx++;
671 [ # # ]: 0 : if( nSuchIdx >= sSearchKey.getLength() )
672 : : {
673 [ # # ]: 0 : if( SearchFlags::NORM_WORD_ONLY & aSrchPara.searchFlag )
674 : : {
675 : 0 : sal_Int32 nFndStt = nCmpIdx - sSearchKey.getLength();
676 : 0 : bool bAtStart = !nFndStt;
677 : 0 : bool bAtEnd = nCmpIdx == startPos;
678 [ # # ]: 0 : bool bDelimBehind = IsDelimiter( aStr, nCmpIdx );
679 : : bool bDelimBefore = bAtStart || // begin of paragraph
680 [ # # ][ # # ]: 0 : IsDelimiter( aStr, nFndStt-1 );
[ # # ]
681 : : // * 1 -> only one word in the paragraph
682 : : // * 2 -> at begin of paragraph
683 : : // * 3 -> at end of paragraph
684 : : // * 4 -> inside the paragraph
685 [ # # ][ # # ]: 0 : if( ( bAtStart && bAtEnd ) || // 1
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
686 : : ( bAtStart && bDelimBehind ) || // 2
687 : : ( bAtEnd && bDelimBefore ) || // 3
688 : : ( bDelimBefore && bDelimBehind )) // 4
689 : : {
690 : 0 : aRet.subRegExpressions = 1;
691 [ # # ]: 0 : aRet.startOffset.realloc( 1 );
692 [ # # ]: 0 : aRet.startOffset[ 0 ] = nCmpIdx;
693 [ # # ]: 0 : aRet.endOffset.realloc( 1 );
694 [ # # ]: 0 : aRet.endOffset[ 0 ] = nCmpIdx - sSearchKey.getLength();
695 : : return aRet;
696 : : }
697 : : }
698 : : else
699 : : {
700 : 0 : aRet.subRegExpressions = 1;
701 [ # # ]: 0 : aRet.startOffset.realloc( 1 );
702 [ # # ]: 0 : aRet.startOffset[ 0 ] = nCmpIdx;
703 [ # # ]: 0 : aRet.endOffset.realloc( 1 );
704 [ # # ]: 0 : aRet.endOffset[ 0 ] = nCmpIdx - sSearchKey.getLength();
705 : : return aRet;
706 : : }
707 : : }
708 : : }
709 [ # # ]: 0 : nSuchIdx = GetDiff( aStr[nCmpIdx - sSearchKey.getLength()] );
710 [ # # ]: 0 : if( nCmpIdx < nSuchIdx )
711 : : return aRet;
712 : 0 : nCmpIdx -= nSuchIdx;
713 : : }
714 : 0 : return aRet;
715 : : }
716 : :
717 : :
718 : :
719 : : //---------------------------------------------------------------------------
720 : : // ------- Methoden fuer die Suche ueber Regular-Expressions --------------
721 : :
722 : 0 : SearchResult TextSearch::RESrchFrwrd( const OUString& searchStr,
723 : : sal_Int32 startPos, sal_Int32 endPos )
724 : : throw(RuntimeException)
725 : : {
726 [ # # ]: 0 : SearchResult aRet;
727 : 0 : aRet.subRegExpressions = 0;
728 : 0 : OUString aStr( searchStr );
729 : :
730 : : bool bSearchInSel = (0 != (( SearchFlags::REG_NOT_BEGINOFLINE |
731 : 0 : SearchFlags::REG_NOT_ENDOFLINE ) & aSrchPara.searchFlag ));
732 : :
733 [ # # ][ # # ]: 0 : pRegExp->set_line(aStr.getStr(), bSearchInSel ? endPos : aStr.getLength());
734 : :
735 : : struct re_registers regs;
736 : :
737 : : // Clear structure
738 : 0 : memset((void *)®s, 0, sizeof(struct re_registers));
739 [ # # ][ # # ]: 0 : if ( ! pRegExp->re_search(®s, startPos) )
740 : : {
741 [ # # ][ # # ]: 0 : if( regs.num_of_match > 0 &&
[ # # ]
742 : 0 : (regs.start[0] != -1 && regs.end[0] != -1) )
743 : : {
744 [ # # ]: 0 : aRet.startOffset.realloc(regs.num_of_match);
745 [ # # ]: 0 : aRet.endOffset.realloc(regs.num_of_match);
746 : :
747 : 0 : sal_Int32 i = 0, j = 0;
748 [ # # ]: 0 : while( j < regs.num_of_match )
749 : : {
750 [ # # ][ # # ]: 0 : if( regs.start[j] != -1 && regs.end[j] != -1 )
751 : : {
752 [ # # ]: 0 : aRet.startOffset[i] = regs.start[j];
753 [ # # ]: 0 : aRet.endOffset[i] = regs.end[j];
754 : 0 : ++i;
755 : : }
756 : 0 : ++j;
757 : : }
758 : 0 : aRet.subRegExpressions = i;
759 : : }
760 [ # # ]: 0 : if ( regs.num_regs > 0 )
761 : : {
762 [ # # ]: 0 : if ( regs.start )
763 : 0 : free(regs.start);
764 [ # # ]: 0 : if ( regs.end )
765 : 0 : free(regs.end);
766 : : }
767 : : }
768 : :
769 : 0 : return aRet;
770 : : }
771 : :
772 : : /*
773 : : * Sucht das Muster aSrchPara.sSrchStr rueckwaerts im String rStr
774 : : */
775 : 0 : SearchResult TextSearch::RESrchBkwrd( const OUString& searchStr,
776 : : sal_Int32 startPos, sal_Int32 endPos )
777 : : throw(RuntimeException)
778 : : {
779 [ # # ]: 0 : SearchResult aRet;
780 : 0 : aRet.subRegExpressions = 0;
781 : 0 : OUString aStr( searchStr );
782 : :
783 : 0 : sal_Int32 nOffset = 0;
784 [ # # ]: 0 : sal_Int32 nStrEnde = aStr.getLength() == endPos ? 0 : endPos;
785 : :
786 : : bool bSearchInSel = (0 != (( SearchFlags::REG_NOT_BEGINOFLINE |
787 : 0 : SearchFlags::REG_NOT_ENDOFLINE ) & aSrchPara.searchFlag ));
788 : :
789 [ # # ]: 0 : if( startPos )
790 : 0 : nOffset = startPos - 1;
791 : :
792 : : // search only in the subString
793 [ # # ][ # # ]: 0 : if( bSearchInSel && nStrEnde )
794 : : {
795 : 0 : aStr = aStr.copy( nStrEnde, aStr.getLength() - nStrEnde );
796 [ # # ]: 0 : if( nOffset > nStrEnde )
797 : 0 : nOffset = nOffset - nStrEnde;
798 : : else
799 : 0 : nOffset = 0;
800 : : }
801 : :
802 : : // set the length to negative for reverse search
803 [ # # ]: 0 : pRegExp->set_line( aStr.getStr(), -(aStr.getLength()) );
804 : : struct re_registers regs;
805 : :
806 : : // Clear structure
807 : 0 : memset((void *)®s, 0, sizeof(struct re_registers));
808 [ # # ][ # # ]: 0 : if ( ! pRegExp->re_search(®s, nOffset) )
809 : : {
810 [ # # ][ # # ]: 0 : if( regs.num_of_match > 0 &&
[ # # ]
811 : 0 : (regs.start[0] != -1 && regs.end[0] != -1) )
812 : : {
813 [ # # ]: 0 : nOffset = bSearchInSel ? nStrEnde : 0;
814 [ # # ]: 0 : aRet.startOffset.realloc(regs.num_of_match);
815 [ # # ]: 0 : aRet.endOffset.realloc(regs.num_of_match);
816 : :
817 : 0 : sal_Int32 i = 0, j = 0;
818 [ # # ]: 0 : while( j < regs.num_of_match )
819 : : {
820 [ # # ][ # # ]: 0 : if( regs.start[j] != -1 && regs.end[j] != -1 )
821 : : {
822 [ # # ]: 0 : aRet.startOffset[i] = regs.end[j] + nOffset;
823 [ # # ]: 0 : aRet.endOffset[i] = regs.start[j] + nOffset;
824 : 0 : ++i;
825 : : }
826 : 0 : ++j;
827 : : }
828 : 0 : aRet.subRegExpressions = i;
829 : : }
830 [ # # ]: 0 : if ( regs.num_regs > 0 )
831 : : {
832 [ # # ]: 0 : if ( regs.start )
833 : 0 : free(regs.start);
834 [ # # ]: 0 : if ( regs.end )
835 : 0 : free(regs.end);
836 : : }
837 : : }
838 : :
839 : 0 : return aRet;
840 : : }
841 : :
842 : : // Phonetische Suche von Worten
843 : 0 : SearchResult TextSearch::ApproxSrchFrwrd( const OUString& searchStr,
844 : : sal_Int32 startPos, sal_Int32 endPos )
845 : : throw(RuntimeException)
846 : : {
847 [ # # ]: 0 : SearchResult aRet;
848 : 0 : aRet.subRegExpressions = 0;
849 : :
850 [ # # ]: 0 : if( !xBreak.is() )
851 : : return aRet;
852 : :
853 : 0 : OUString aWTemp( searchStr );
854 : :
855 : : register sal_Int32 nStt, nEnd;
856 : :
857 [ # # ]: 0 : Boundary aWBnd = xBreak->getWordBoundary( aWTemp, startPos,
858 : : aSrchPara.Locale,
859 [ # # ]: 0 : WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
860 : :
861 [ # # # # ]: 0 : do
[ # # ][ # # ]
862 : : {
863 [ # # ]: 0 : if( aWBnd.startPos >= endPos )
864 : 0 : break;
865 [ # # ]: 0 : nStt = aWBnd.startPos < startPos ? startPos : aWBnd.startPos;
866 [ # # ]: 0 : nEnd = aWBnd.endPos > endPos ? endPos : aWBnd.endPos;
867 : :
868 [ # # ][ # # ]: 0 : if( nStt < nEnd &&
[ # # ]
869 [ # # ]: 0 : pWLD->WLD( aWTemp.getStr() + nStt, nEnd - nStt ) <= nLimit )
870 : : {
871 : 0 : aRet.subRegExpressions = 1;
872 [ # # ]: 0 : aRet.startOffset.realloc( 1 );
873 [ # # ]: 0 : aRet.startOffset[ 0 ] = nStt;
874 [ # # ]: 0 : aRet.endOffset.realloc( 1 );
875 [ # # ]: 0 : aRet.endOffset[ 0 ] = nEnd;
876 : 0 : break;
877 : : }
878 : :
879 : 0 : nStt = nEnd - 1;
880 [ # # ]: 0 : aWBnd = xBreak->nextWord( aWTemp, nStt, aSrchPara.Locale,
881 [ # # ]: 0 : WordType::ANYWORD_IGNOREWHITESPACES);
882 : : } while( aWBnd.startPos != aWBnd.endPos ||
883 : 0 : (aWBnd.endPos != aWTemp.getLength() && aWBnd.endPos != nEnd) );
884 : : // #i50244# aWBnd.endPos != nEnd : in case there is _no_ word (only
885 : : // whitespace) in searchStr, getWordBoundary() returned startPos,startPos
886 : : // and nextWord() does also => don't loop forever.
887 : 0 : return aRet;
888 : : }
889 : :
890 : 0 : SearchResult TextSearch::ApproxSrchBkwrd( const OUString& searchStr,
891 : : sal_Int32 startPos, sal_Int32 endPos )
892 : : throw(RuntimeException)
893 : : {
894 [ # # ]: 0 : SearchResult aRet;
895 : 0 : aRet.subRegExpressions = 0;
896 : :
897 [ # # ]: 0 : if( !xBreak.is() )
898 : : return aRet;
899 : :
900 : 0 : OUString aWTemp( searchStr );
901 : :
902 : : register sal_Int32 nStt, nEnd;
903 : :
904 [ # # ]: 0 : Boundary aWBnd = xBreak->getWordBoundary( aWTemp, startPos,
905 : : aSrchPara.Locale,
906 [ # # ]: 0 : WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
907 : :
908 [ # # # # ]: 0 : do
[ # # ]
909 : : {
910 [ # # ]: 0 : if( aWBnd.endPos <= endPos )
911 : 0 : break;
912 [ # # ]: 0 : nStt = aWBnd.startPos < endPos ? endPos : aWBnd.startPos;
913 [ # # ]: 0 : nEnd = aWBnd.endPos > startPos ? startPos : aWBnd.endPos;
914 : :
915 [ # # ][ # # ]: 0 : if( nStt < nEnd &&
[ # # ]
916 [ # # ]: 0 : pWLD->WLD( aWTemp.getStr() + nStt, nEnd - nStt ) <= nLimit )
917 : : {
918 : 0 : aRet.subRegExpressions = 1;
919 [ # # ]: 0 : aRet.startOffset.realloc( 1 );
920 [ # # ]: 0 : aRet.startOffset[ 0 ] = nEnd;
921 [ # # ]: 0 : aRet.endOffset.realloc( 1 );
922 [ # # ]: 0 : aRet.endOffset[ 0 ] = nStt;
923 : 0 : break;
924 : : }
925 [ # # ]: 0 : if( !nStt )
926 : 0 : break;
927 : :
928 [ # # ]: 0 : aWBnd = xBreak->previousWord( aWTemp, nStt, aSrchPara.Locale,
929 [ # # ]: 0 : WordType::ANYWORD_IGNOREWHITESPACES);
930 : 0 : } while( aWBnd.startPos != aWBnd.endPos || aWBnd.endPos != aWTemp.getLength() );
931 : 0 : return aRet;
932 : : }
933 : :
934 : :
935 : : static const sal_Char cSearchName[] = "com.sun.star.util.TextSearch";
936 : : static const sal_Char cSearchImpl[] = "com.sun.star.util.TextSearch_i18n";
937 : :
938 : 7 : static OUString getServiceName_Static()
939 : : {
940 : 7 : return OUString::createFromAscii( cSearchName );
941 : : }
942 : :
943 : 7 : static OUString getImplementationName_Static()
944 : : {
945 : 7 : return OUString::createFromAscii( cSearchImpl );
946 : : }
947 : :
948 : : OUString SAL_CALL
949 : 0 : TextSearch::getImplementationName()
950 : : throw( RuntimeException )
951 : : {
952 : 0 : return getImplementationName_Static();
953 : : }
954 : :
955 : : sal_Bool SAL_CALL
956 : 0 : TextSearch::supportsService(const OUString& rServiceName)
957 : : throw( RuntimeException )
958 : : {
959 : 0 : return !rServiceName.compareToAscii( cSearchName );
960 : : }
961 : :
962 : : Sequence< OUString > SAL_CALL
963 : 0 : TextSearch::getSupportedServiceNames(void) throw( RuntimeException )
964 : : {
965 : 0 : Sequence< OUString > aRet(1);
966 [ # # ]: 0 : aRet[0] = getServiceName_Static();
967 : 0 : return aRet;
968 : : }
969 : :
970 : : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
971 : 61 : SAL_CALL TextSearch_CreateInstance(
972 : : const ::com::sun::star::uno::Reference<
973 : : ::com::sun::star::lang::XMultiServiceFactory >& rxMSF )
974 : : {
975 : : return ::com::sun::star::uno::Reference<
976 : : ::com::sun::star::uno::XInterface >(
977 [ + - ]: 61 : (::cppu::OWeakObject*) new TextSearch( rxMSF ) );
978 : : }
979 : :
980 : : extern "C"
981 : : {
982 : :
983 : 7 : SAL_DLLPUBLIC_EXPORT void* SAL_CALL i18nsearch_component_getFactory( const sal_Char* sImplementationName,
984 : : void* _pServiceManager, SAL_UNUSED_PARAMETER void* /*_pRegistryKey*/ )
985 : : {
986 : 7 : void* pRet = NULL;
987 : :
988 : : ::com::sun::star::lang::XMultiServiceFactory* pServiceManager =
989 : : reinterpret_cast< ::com::sun::star::lang::XMultiServiceFactory* >
990 : 7 : ( _pServiceManager );
991 : : ::com::sun::star::uno::Reference<
992 : 7 : ::com::sun::star::lang::XSingleServiceFactory > xFactory;
993 : :
994 [ + - ]: 7 : if ( 0 == rtl_str_compare( sImplementationName, cSearchImpl) )
995 : : {
996 [ + - ]: 7 : ::com::sun::star::uno::Sequence< ::rtl::OUString > aServiceNames(1);
997 [ + - ]: 7 : aServiceNames[0] = getServiceName_Static();
998 : : xFactory = ::cppu::createSingleFactory(
999 : : pServiceManager, getImplementationName_Static(),
1000 [ + - ][ + - ]: 7 : &TextSearch_CreateInstance, aServiceNames );
[ + - ][ + - ]
1001 : : }
1002 : :
1003 [ + - ]: 7 : if ( xFactory.is() )
1004 : : {
1005 [ + - ]: 7 : xFactory->acquire();
1006 [ + - ]: 7 : pRet = xFactory.get();
1007 : : }
1008 : :
1009 : 7 : return pRet;
1010 : : }
1011 : :
1012 [ + - ][ + - ]: 21 : } // extern "C"
1013 : :
1014 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|