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 // ------------------------------------------------------------------------- 40 ExtTextEngine::ExtTextEngine() : maGroupChars( String::CreateFromAscii( "(){}[]", 6 ) ) 41 { 42 } 43 44 ExtTextEngine::~ExtTextEngine() 45 { 46 } 47 48 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 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 // ------------------------------------------------------------------------- 239 ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow ) 240 : TextView( pEng, pWindow ) 241 { 242 } 243 244 ExtTextView::~ExtTextView() 245 { 246 } 247 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 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 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 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 408 sal_Bool ExtTextView::IndentBlock() 409 { 410 return ImpIndentBlock( sal_True ); 411 } 412 413 sal_Bool ExtTextView::UnindentBlock() 414 { 415 return ImpIndentBlock( sal_False ); 416 } 417 418