Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <vcl/xtextedt.hxx>
22 : #include <vcl/svapp.hxx> // International
23 : #include <unotools/textsearch.hxx>
24 : #include <com/sun/star/util/SearchOptions.hpp>
25 : #include <com/sun/star/util/SearchFlags.hpp>
26 :
27 : using namespace ::com::sun::star;
28 :
29 :
30 :
31 : // -------------------------------------------------------------------------
32 : // class ExtTextEngine
33 : // -------------------------------------------------------------------------
34 0 : ExtTextEngine::ExtTextEngine() : maGroupChars(rtl::OUString("(){}[]"))
35 : {
36 0 : }
37 :
38 0 : ExtTextEngine::~ExtTextEngine()
39 : {
40 0 : }
41 :
42 0 : TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const
43 : {
44 0 : TextSelection aSel( rCursor );
45 0 : sal_uInt16 nPos = rCursor.GetIndex();
46 0 : sal_uLong nPara = rCursor.GetPara();
47 0 : sal_uLong nParas = GetParagraphCount();
48 0 : if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) )
49 : {
50 0 : sal_uInt16 nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) );
51 0 : if ( nMatchChar != STRING_NOTFOUND )
52 : {
53 0 : if ( ( nMatchChar % 2 ) == 0 )
54 : {
55 : // Vorwaerts suchen...
56 0 : sal_Unicode nSC = maGroupChars.GetChar( nMatchChar );
57 0 : sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 );
58 :
59 0 : sal_uInt16 nCur = nPos+1;
60 0 : sal_uInt16 nLevel = 1;
61 0 : while ( nLevel && ( nPara < nParas ) )
62 : {
63 0 : XubString aStr = GetText( nPara );
64 0 : while ( nCur < aStr.Len() )
65 : {
66 0 : if ( aStr.GetChar( nCur ) == nSC )
67 0 : nLevel++;
68 0 : else if ( aStr.GetChar( nCur ) == nEC )
69 : {
70 0 : nLevel--;
71 0 : if ( !nLevel )
72 0 : break; // while nCur...
73 : }
74 0 : nCur++;
75 : }
76 :
77 0 : if ( nLevel )
78 : {
79 0 : nPara++;
80 0 : nCur = 0;
81 : }
82 0 : }
83 0 : if ( nLevel == 0 ) // gefunden
84 : {
85 0 : aSel.GetStart() = rCursor;
86 0 : aSel.GetEnd() = TextPaM( nPara, nCur+1 );
87 : }
88 : }
89 : else
90 : {
91 : // Rueckwaerts suchen...
92 0 : sal_Unicode nEC = maGroupChars.GetChar( nMatchChar );
93 0 : sal_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 );
94 :
95 0 : sal_uInt16 nCur = rCursor.GetIndex()-1;
96 0 : sal_uInt16 nLevel = 1;
97 0 : while ( nLevel )
98 : {
99 0 : if ( GetTextLen( nPara ) )
100 : {
101 0 : XubString aStr = GetText( nPara );
102 0 : while ( nCur )
103 : {
104 0 : if ( aStr.GetChar( nCur ) == nSC )
105 : {
106 0 : nLevel--;
107 0 : if ( !nLevel )
108 0 : break; // while nCur...
109 : }
110 0 : else if ( aStr.GetChar( nCur ) == nEC )
111 0 : nLevel++;
112 :
113 0 : nCur--;
114 0 : }
115 : }
116 :
117 0 : if ( nLevel )
118 : {
119 0 : if ( nPara )
120 : {
121 0 : nPara--;
122 0 : nCur = GetTextLen( nPara )-1; // egal ob negativ, weil if Len()
123 : }
124 : else
125 0 : break;
126 : }
127 : }
128 :
129 0 : if ( nLevel == 0 ) // gefunden
130 : {
131 0 : aSel.GetStart() = rCursor;
132 0 : aSel.GetStart().GetIndex()++; // hinter das Zeichen
133 0 : aSel.GetEnd() = TextPaM( nPara, nCur );
134 : }
135 : }
136 : }
137 : }
138 0 : return aSel;
139 : }
140 :
141 0 : sal_Bool ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, sal_Bool bForward )
142 : {
143 0 : TextSelection aSel( rSel );
144 0 : aSel.Justify();
145 :
146 0 : sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
147 :
148 0 : TextPaM aStartPaM( aSel.GetEnd() );
149 0 : if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) )
150 : {
151 0 : aStartPaM = aSel.GetStart();
152 : }
153 :
154 0 : bool bFound = false;
155 : sal_uLong nStartNode, nEndNode;
156 :
157 0 : if ( bSearchInSelection )
158 0 : nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara();
159 : else
160 0 : nEndNode = bForward ? (GetParagraphCount()-1) : 0;
161 :
162 0 : nStartNode = aStartPaM.GetPara();
163 :
164 0 : util::SearchOptions aOptions( rSearchOptions );
165 0 : aOptions.Locale = Application::GetSettings().GetLanguageTag().getLocale();
166 0 : utl::TextSearch aSearcher( rSearchOptions );
167 :
168 : // ueber die Absaetze iterieren...
169 0 : for ( sal_uLong nNode = nStartNode;
170 : bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode );
171 : bForward ? nNode++ : nNode-- )
172 : {
173 0 : String aText = GetText( nNode );
174 0 : sal_uInt16 nStartPos = 0;
175 0 : sal_uInt16 nEndPos = aText.Len();
176 0 : if ( nNode == nStartNode )
177 : {
178 0 : if ( bForward )
179 0 : nStartPos = aStartPaM.GetIndex();
180 : else
181 0 : nEndPos = aStartPaM.GetIndex();
182 : }
183 0 : if ( ( nNode == nEndNode ) && bSearchInSelection )
184 : {
185 0 : if ( bForward )
186 0 : nEndPos = aSel.GetEnd().GetIndex();
187 : else
188 0 : nStartPos = aSel.GetStart().GetIndex();
189 : }
190 :
191 0 : if ( bForward )
192 0 : bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos );
193 : else
194 0 : bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos );
195 :
196 0 : if ( bFound )
197 : {
198 0 : rSel.GetStart().GetPara() = nNode;
199 0 : rSel.GetStart().GetIndex() = nStartPos;
200 0 : rSel.GetEnd().GetPara() = nNode;
201 0 : rSel.GetEnd().GetIndex() = nEndPos;
202 : // Ueber den Absatz selektieren?
203 : // Select over the paragraph?
204 : // FIXME This should be max long...
205 0 : if( nEndPos == sal::static_int_cast<sal_uInt16>(-1) ) // sal_uInt16 for 0 and -1 !
206 : {
207 0 : if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() )
208 : {
209 0 : rSel.GetEnd().GetPara()++;
210 0 : rSel.GetEnd().GetIndex() = 0;
211 : }
212 : else
213 : {
214 0 : rSel.GetEnd().GetIndex() = nStartPos;
215 0 : bFound = false;
216 : }
217 : }
218 :
219 : break;
220 : }
221 :
222 0 : if ( !bForward && !nNode ) // Bei rueckwaertsuche, wenn nEndNode = 0:
223 : break;
224 0 : }
225 :
226 0 : return bFound;
227 : }
228 :
229 :
230 : // -------------------------------------------------------------------------
231 : // class ExtTextView
232 : // -------------------------------------------------------------------------
233 0 : ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow )
234 0 : : TextView( pEng, pWindow )
235 : {
236 0 : }
237 :
238 0 : ExtTextView::~ExtTextView()
239 : {
240 0 : }
241 :
242 0 : sal_Bool ExtTextView::MatchGroup()
243 : {
244 0 : TextSelection aTmpSel( GetSelection() );
245 0 : aTmpSel.Justify();
246 0 : if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) ||
247 0 : ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) )
248 : {
249 0 : return sal_False;
250 : }
251 :
252 0 : TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() );
253 0 : if ( aMatchSel.HasRange() )
254 0 : SetSelection( aMatchSel );
255 :
256 0 : return aMatchSel.HasRange() ? sal_True : sal_False;
257 : }
258 :
259 0 : sal_Bool ExtTextView::Search( const util::SearchOptions& rSearchOptions, sal_Bool bForward )
260 : {
261 0 : sal_Bool bFound = sal_False;
262 0 : TextSelection aSel( GetSelection() );
263 0 : if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) )
264 : {
265 0 : bFound = sal_True;
266 : // Erstmal den Anfang des Wortes als Selektion einstellen,
267 : // damit das ganze Wort in den sichtbaren Bereich kommt.
268 0 : SetSelection( aSel.GetStart() );
269 0 : ShowCursor( sal_True, sal_False );
270 : }
271 : else
272 : {
273 0 : aSel = GetSelection().GetEnd();
274 : }
275 :
276 0 : SetSelection( aSel );
277 0 : ShowCursor();
278 :
279 0 : return bFound;
280 : }
281 :
282 0 : sal_uInt16 ExtTextView::Replace( const util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward )
283 : {
284 0 : sal_uInt16 nFound = 0;
285 :
286 0 : if ( !bAll )
287 : {
288 0 : if ( GetSelection().HasRange() )
289 : {
290 0 : InsertText( rSearchOptions.replaceString );
291 0 : nFound = 1;
292 0 : Search( rSearchOptions, bForward ); // gleich zum naechsten
293 : }
294 : else
295 : {
296 0 : if( Search( rSearchOptions, bForward ) )
297 0 : nFound = 1;
298 : }
299 : }
300 : else
301 : {
302 : // Der Writer ersetzt alle, vom Anfang bis Ende...
303 :
304 0 : ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine();
305 :
306 : // HideSelection();
307 0 : TextSelection aSel;
308 :
309 0 : sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
310 0 : if ( bSearchInSelection )
311 : {
312 0 : aSel = GetSelection();
313 0 : aSel.Justify();
314 : }
315 :
316 0 : TextSelection aSearchSel( aSel );
317 :
318 0 : sal_Bool bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True );
319 0 : if ( bFound )
320 0 : pTextEngine->UndoActionStart();
321 0 : while ( bFound )
322 : {
323 0 : nFound++;
324 :
325 0 : TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString );
326 0 : aSel = aSearchSel;
327 0 : aSel.GetStart() = aNewStart;
328 0 : bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True );
329 : }
330 0 : if ( nFound )
331 : {
332 0 : SetSelection( aSel.GetStart() );
333 0 : pTextEngine->FormatAndUpdate( this );
334 0 : pTextEngine->UndoActionEnd();
335 : }
336 : }
337 0 : return nFound;
338 : }
339 :
340 0 : sal_Bool ExtTextView::ImpIndentBlock( sal_Bool bRight )
341 : {
342 0 : sal_Bool bDone = sal_False;
343 :
344 0 : TextSelection aSel = GetSelection();
345 0 : aSel.Justify();
346 :
347 0 : HideSelection();
348 0 : GetTextEngine()->UndoActionStart();
349 :
350 0 : sal_uLong nStartPara = aSel.GetStart().GetPara();
351 0 : sal_uLong nEndPara = aSel.GetEnd().GetPara();
352 0 : if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() )
353 : {
354 0 : nEndPara--; // den dann nicht einruecken...
355 : }
356 :
357 0 : for ( sal_uLong nPara = nStartPara; nPara <= nEndPara; nPara++ )
358 : {
359 0 : if ( bRight )
360 : {
361 : // Tabs hinzufuegen
362 0 : GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' );
363 0 : bDone = sal_True;
364 : }
365 : else
366 : {
367 : // Tabs/Blanks entfernen
368 0 : String aText = GetTextEngine()->GetText( nPara );
369 0 : if ( aText.Len() && (
370 0 : ( aText.GetChar( 0 ) == '\t' ) ||
371 0 : ( aText.GetChar( 0 ) == ' ' ) ) )
372 : {
373 0 : GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) );
374 0 : bDone = sal_True;
375 0 : }
376 : }
377 : }
378 :
379 0 : GetTextEngine()->UndoActionEnd();
380 :
381 0 : sal_Bool bRange = aSel.HasRange();
382 0 : if ( bRight )
383 : {
384 0 : aSel.GetStart().GetIndex()++;
385 0 : if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) )
386 0 : aSel.GetEnd().GetIndex()++;
387 : }
388 : else
389 : {
390 0 : if ( aSel.GetStart().GetIndex() )
391 0 : aSel.GetStart().GetIndex()--;
392 0 : if ( bRange && aSel.GetEnd().GetIndex() )
393 0 : aSel.GetEnd().GetIndex()--;
394 : }
395 :
396 0 : ImpSetSelection( aSel );
397 0 : GetTextEngine()->FormatAndUpdate( this );
398 :
399 0 : return bDone;
400 : }
401 :
402 0 : sal_Bool ExtTextView::IndentBlock()
403 : {
404 0 : return ImpIndentBlock( sal_True );
405 : }
406 :
407 0 : sal_Bool ExtTextView::UnindentBlock()
408 : {
409 0 : return ImpIndentBlock( sal_False );
410 : }
411 :
412 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|