update credits
[LibreOffice.git] / vcl / source / edit / xtextedt.cxx
blobace53c7de387eaf1fddfd36a23fbca45a20d7041
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
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>
27 using namespace ::com::sun::star;
30 ExtTextEngine::ExtTextEngine() : maGroupChars(OUString("(){}[]"))
34 ExtTextEngine::~ExtTextEngine()
38 TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const
40 TextSelection aSel( rCursor );
41 sal_uInt16 nPos = rCursor.GetIndex();
42 sal_uLong nPara = rCursor.GetPara();
43 sal_uLong nParas = GetParagraphCount();
44 if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) )
46 sal_uInt16 nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) );
47 if ( nMatchChar != STRING_NOTFOUND )
49 if ( ( nMatchChar % 2 ) == 0 )
51 // search forwards
52 sal_Unicode nSC = maGroupChars.GetChar( nMatchChar );
53 sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 );
55 sal_uInt16 nCur = nPos+1;
56 sal_uInt16 nLevel = 1;
57 while ( nLevel && ( nPara < nParas ) )
59 XubString aStr = GetText( nPara );
60 while ( nCur < aStr.Len() )
62 if ( aStr.GetChar( nCur ) == nSC )
63 nLevel++;
64 else if ( aStr.GetChar( nCur ) == nEC )
66 nLevel--;
67 if ( !nLevel )
68 break; // while nCur...
70 nCur++;
73 if ( nLevel )
75 nPara++;
76 nCur = 0;
79 if ( nLevel == 0 ) // found
81 aSel.GetStart() = rCursor;
82 aSel.GetEnd() = TextPaM( nPara, nCur+1 );
85 else
87 // search backwards
88 sal_Unicode nEC = maGroupChars.GetChar( nMatchChar );
89 sal_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 );
91 sal_uInt16 nCur = rCursor.GetIndex()-1;
92 sal_uInt16 nLevel = 1;
93 while ( nLevel )
95 if ( GetTextLen( nPara ) )
97 XubString aStr = GetText( nPara );
98 while ( nCur )
100 if ( aStr.GetChar( nCur ) == nSC )
102 nLevel--;
103 if ( !nLevel )
104 break; // while nCur...
106 else if ( aStr.GetChar( nCur ) == nEC )
107 nLevel++;
109 nCur--;
113 if ( nLevel )
115 if ( nPara )
117 nPara--;
118 nCur = GetTextLen( nPara )-1; // no matter if negativ, as if Len()
120 else
121 break;
125 if ( nLevel == 0 ) // found
127 aSel.GetStart() = rCursor;
128 aSel.GetStart().GetIndex()++; // behind the char
129 aSel.GetEnd() = TextPaM( nPara, nCur );
134 return aSel;
137 sal_Bool ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, sal_Bool bForward )
139 TextSelection aSel( rSel );
140 aSel.Justify();
142 bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
144 TextPaM aStartPaM( aSel.GetEnd() );
145 if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) )
147 aStartPaM = aSel.GetStart();
150 bool bFound = false;
151 sal_uLong nStartNode, nEndNode;
153 if ( bSearchInSelection )
154 nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara();
155 else
156 nEndNode = bForward ? (GetParagraphCount()-1) : 0;
158 nStartNode = aStartPaM.GetPara();
160 util::SearchOptions aOptions( rSearchOptions );
161 aOptions.Locale = Application::GetSettings().GetLanguageTag().getLocale();
162 utl::TextSearch aSearcher( rSearchOptions );
164 // iterate over the paragraphs
165 for ( sal_uLong nNode = nStartNode;
166 bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode );
167 bForward ? nNode++ : nNode-- )
169 String aText = GetText( nNode );
170 sal_uInt16 nStartPos = 0;
171 sal_uInt16 nEndPos = aText.Len();
172 if ( nNode == nStartNode )
174 if ( bForward )
175 nStartPos = aStartPaM.GetIndex();
176 else
177 nEndPos = aStartPaM.GetIndex();
179 if ( ( nNode == nEndNode ) && bSearchInSelection )
181 if ( bForward )
182 nEndPos = aSel.GetEnd().GetIndex();
183 else
184 nStartPos = aSel.GetStart().GetIndex();
187 if ( bForward )
188 bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos );
189 else
190 bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos );
192 if ( bFound )
194 rSel.GetStart().GetPara() = nNode;
195 rSel.GetStart().GetIndex() = nStartPos;
196 rSel.GetEnd().GetPara() = nNode;
197 rSel.GetEnd().GetIndex() = nEndPos;
198 // Select over the paragraph?
199 // FIXME This should be max long...
200 if( nEndPos == sal::static_int_cast<sal_uInt16>(-1) ) // sal_uInt16 for 0 and -1 !
202 if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() )
204 rSel.GetEnd().GetPara()++;
205 rSel.GetEnd().GetIndex() = 0;
207 else
209 rSel.GetEnd().GetIndex() = nStartPos;
210 bFound = false;
214 break;
217 if ( !bForward && !nNode ) // if searching backwards, if nEndNode == 0:
218 break;
221 return bFound;
225 // -------------------------------------------------------------------------
226 // class ExtTextView
227 // -------------------------------------------------------------------------
228 ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow )
229 : TextView( pEng, pWindow )
233 ExtTextView::~ExtTextView()
237 sal_Bool ExtTextView::MatchGroup()
239 TextSelection aTmpSel( GetSelection() );
240 aTmpSel.Justify();
241 if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) ||
242 ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) )
244 return sal_False;
247 TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() );
248 if ( aMatchSel.HasRange() )
249 SetSelection( aMatchSel );
251 return aMatchSel.HasRange() ? sal_True : sal_False;
254 sal_Bool ExtTextView::Search( const util::SearchOptions& rSearchOptions, sal_Bool bForward )
256 sal_Bool bFound = sal_False;
257 TextSelection aSel( GetSelection() );
258 if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) )
260 bFound = sal_True;
261 // First add the beginning of the word to the selection,
262 // so that the whole word is in the visible region.
263 SetSelection( aSel.GetStart() );
264 ShowCursor( sal_True, sal_False );
266 else
268 aSel = GetSelection().GetEnd();
271 SetSelection( aSel );
272 ShowCursor();
274 return bFound;
277 sal_uInt16 ExtTextView::Replace( const util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward )
279 sal_uInt16 nFound = 0;
281 if ( !bAll )
283 if ( GetSelection().HasRange() )
285 InsertText( rSearchOptions.replaceString );
286 nFound = 1;
287 Search( rSearchOptions, bForward ); // right away to the next
289 else
291 if( Search( rSearchOptions, bForward ) )
292 nFound = 1;
295 else
297 // the writer replaces all, from beginning to end
299 ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine();
301 // HideSelection();
302 TextSelection aSel;
304 bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
305 if ( bSearchInSelection )
307 aSel = GetSelection();
308 aSel.Justify();
311 TextSelection aSearchSel( aSel );
313 sal_Bool bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True );
314 if ( bFound )
315 pTextEngine->UndoActionStart();
316 while ( bFound )
318 nFound++;
320 TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString );
321 aSel = aSearchSel;
322 aSel.GetStart() = aNewStart;
323 bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True );
325 if ( nFound )
327 SetSelection( aSel.GetStart() );
328 pTextEngine->FormatAndUpdate( this );
329 pTextEngine->UndoActionEnd();
332 return nFound;
335 sal_Bool ExtTextView::ImpIndentBlock( sal_Bool bRight )
337 sal_Bool bDone = sal_False;
339 TextSelection aSel = GetSelection();
340 aSel.Justify();
342 HideSelection();
343 GetTextEngine()->UndoActionStart();
345 sal_uLong nStartPara = aSel.GetStart().GetPara();
346 sal_uLong nEndPara = aSel.GetEnd().GetPara();
347 if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() )
349 nEndPara--; // do not indent
352 for ( sal_uLong nPara = nStartPara; nPara <= nEndPara; nPara++ )
354 if ( bRight )
356 // add tabs
357 GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' );
358 bDone = sal_True;
360 else
362 // remove Tabs/Blanks
363 String aText = GetTextEngine()->GetText( nPara );
364 if ( aText.Len() && (
365 ( aText.GetChar( 0 ) == '\t' ) ||
366 ( aText.GetChar( 0 ) == ' ' ) ) )
368 GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) );
369 bDone = sal_True;
374 GetTextEngine()->UndoActionEnd();
376 sal_Bool bRange = aSel.HasRange();
377 if ( bRight )
379 aSel.GetStart().GetIndex()++;
380 if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) )
381 aSel.GetEnd().GetIndex()++;
383 else
385 if ( aSel.GetStart().GetIndex() )
386 aSel.GetStart().GetIndex()--;
387 if ( bRange && aSel.GetEnd().GetIndex() )
388 aSel.GetEnd().GetIndex()--;
391 ImpSetSelection( aSel );
392 GetTextEngine()->FormatAndUpdate( this );
394 return bDone;
397 sal_Bool ExtTextView::IndentBlock()
399 return ImpIndentBlock( sal_True );
402 sal_Bool ExtTextView::UnindentBlock()
404 return ImpIndentBlock( sal_False );
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */