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