1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #include <pam.hxx> // GetSpaces 33 #include <txtcfg.hxx> 34 #include <frminf.hxx> // SwTxtFrminfo 35 #include <itrtxt.hxx> // SwTxtMargin 36 37 /************************************************************************* 38 * SwTxtMargin::GetTxtStart() 39 *************************************************************************/ 40 41 xub_StrLen SwTxtMargin::GetTxtStart() const 42 { 43 const XubString &rTxt = GetInfo().GetTxt(); 44 const xub_StrLen nTmpPos = nStart; 45 const xub_StrLen nEnd = nTmpPos + pCurr->GetLen(); 46 xub_StrLen i; 47 48 for( i = nTmpPos; i < nEnd; ++i ) 49 { 50 const xub_Unicode aChar = rTxt.GetChar( i ); 51 if( CH_TAB != aChar && ' ' != aChar ) 52 return i; 53 } 54 return i; 55 } 56 57 /************************************************************************* 58 * SwTxtMargin::GetTxtEnd() 59 *************************************************************************/ 60 61 xub_StrLen SwTxtMargin::GetTxtEnd() const 62 { 63 const XubString &rTxt = GetInfo().GetTxt(); 64 const xub_StrLen nTmpPos = nStart; 65 const xub_StrLen nEnd = nTmpPos + pCurr->GetLen(); 66 long i; 67 for( i = nEnd - 1; i >= nTmpPos; --i ) 68 { 69 xub_Unicode aChar = rTxt.GetChar( static_cast<xub_StrLen>(i) ); 70 if( CH_TAB != aChar && CH_BREAK != aChar && ' ' != aChar ) 71 return static_cast<xub_StrLen>(i + 1); 72 } 73 return static_cast<xub_StrLen>(i + 1); 74 } 75 76 /************************************************************************* 77 * SwTxtFrmInfo::IsOneLine() 78 *************************************************************************/ 79 80 // Passt der Absatz in eine Zeile? 81 sal_Bool SwTxtFrmInfo::IsOneLine() const 82 { 83 const SwLineLayout *pLay = pFrm->GetPara(); 84 if( !pLay ) 85 return sal_False; 86 else 87 { 88 // 6575: bei Follows natuerlich sal_False 89 if( pFrm->GetFollow() ) 90 return sal_False; 91 pLay = pLay->GetNext(); 92 while( pLay ) 93 { 94 if( pLay->GetLen() ) 95 return sal_False; 96 pLay = pLay->GetNext(); 97 } 98 return sal_True; 99 } 100 } 101 102 /************************************************************************* 103 * SwTxtFrmInfo::IsFilled() 104 *************************************************************************/ 105 106 // Ist die Zeile zu X% gefuellt? 107 sal_Bool SwTxtFrmInfo::IsFilled( const sal_uInt8 nPercent ) const 108 { 109 const SwLineLayout *pLay = pFrm->GetPara(); 110 if( !pLay ) 111 return sal_False; 112 else 113 { 114 long nWidth = pFrm->Prt().Width(); 115 nWidth *= nPercent; 116 nWidth /= 100; 117 return KSHORT(nWidth) <= pLay->Width(); 118 } 119 } 120 121 /************************************************************************* 122 * SwTxtFrmInfo::GetLineStart() 123 *************************************************************************/ 124 125 // Wo beginnt der Text (ohne whitespaces)? ( Dokument global ) 126 SwTwips SwTxtFrmInfo::GetLineStart( const SwTxtCursor &rLine ) const 127 { 128 xub_StrLen nTxtStart = rLine.GetTxtStart(); 129 SwTwips nStart; 130 if( rLine.GetStart() == nTxtStart ) 131 nStart = rLine.GetLineStart(); 132 else 133 { 134 SwRect aRect; 135 if( ((SwTxtCursor&)rLine).GetCharRect( &aRect, nTxtStart ) ) 136 nStart = aRect.Left(); 137 else 138 nStart = rLine.GetLineStart(); 139 } 140 return nStart; 141 } 142 143 144 /************************************************************************* 145 * SwTxtFrmInfo::GetLineStart() 146 *************************************************************************/ 147 148 // Wo beginnt der Text (ohne whitespaces)? (rel. im Frame) 149 SwTwips SwTxtFrmInfo::GetLineStart() const 150 { 151 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 152 SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf ); 153 return GetLineStart( aLine ) - pFrm->Frm().Left() - pFrm->Prt().Left(); 154 } 155 156 // errechne die Position des Zeichens und gebe die Mittelposition zurueck 157 SwTwips SwTxtFrmInfo::GetCharPos( xub_StrLen nChar, sal_Bool bCenter ) const 158 { 159 SWRECTFN( pFrm ) 160 SwFrmSwapper aSwapper( pFrm, sal_True ); 161 162 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 163 SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf ); 164 165 SwTwips nStt, nNext; 166 SwRect aRect; 167 if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar ) ) 168 { 169 if ( bVert ) 170 pFrm->SwitchHorizontalToVertical( aRect ); 171 172 nStt = (aRect.*fnRect->fnGetLeft)(); 173 } 174 else 175 nStt = aLine.GetLineStart(); 176 177 if( !bCenter ) 178 return nStt - (pFrm->Frm().*fnRect->fnGetLeft)(); 179 180 if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar+1 ) ) 181 { 182 if ( bVert ) 183 pFrm->SwitchHorizontalToVertical( aRect ); 184 185 nNext = (aRect.*fnRect->fnGetLeft)(); 186 } 187 else 188 nNext = aLine.GetLineStart(); 189 190 return (( nNext + nStt ) / 2 ) - (pFrm->Frm().*fnRect->fnGetLeft)(); 191 } 192 193 /************************************************************************* 194 * SwTxtFrmInfo::GetSpaces() 195 *************************************************************************/ 196 197 SwPaM *AddPam( SwPaM *pPam, const SwTxtFrm* pTxtFrm, 198 const xub_StrLen nPos, const xub_StrLen nLen ) 199 { 200 if( nLen ) 201 { 202 // Es koennte auch der erste sein. 203 if( pPam->HasMark() ) 204 { 205 // liegt die neue Position genau hinter der aktuellen, dann 206 // erweiter den Pam einfach 207 if( nPos == pPam->GetPoint()->nContent.GetIndex() ) 208 { 209 pPam->GetPoint()->nContent += nLen; 210 return pPam; 211 } 212 pPam = new SwPaM( *pPam ); 213 } 214 215 SwIndex &rContent = pPam->GetPoint()->nContent; 216 rContent.Assign( (SwTxtNode*)pTxtFrm->GetTxtNode(), nPos ); 217 pPam->SetMark(); 218 rContent += nLen; 219 } 220 return pPam; 221 } 222 223 // Sammelt die whitespaces am Zeilenbeginn und -ende im Pam 224 void SwTxtFrmInfo::GetSpaces( SwPaM &rPam, sal_Bool bWithLineBreak ) const 225 { 226 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 227 SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf ); 228 SwPaM *pPam = &rPam; 229 sal_Bool bFirstLine = sal_True; 230 do { 231 232 if( aLine.GetCurr()->GetLen() ) 233 { 234 xub_StrLen nPos = aLine.GetTxtStart(); 235 // Bug 49649: von der ersten Line die Blanks/Tabs NICHT 236 // mit selektieren 237 if( !bFirstLine && nPos > aLine.GetStart() ) 238 pPam = AddPam( pPam, pFrm, aLine.GetStart(), 239 nPos - aLine.GetStart() ); 240 241 // Bug 49649: von der letzten Line die Blanks/Tabs NICHT 242 // mit selektieren 243 if( aLine.GetNext() ) 244 { 245 nPos = aLine.GetTxtEnd(); 246 247 if( nPos < aLine.GetEnd() ) 248 { 249 MSHORT nOff = !bWithLineBreak && CH_BREAK == 250 aLine.GetInfo().GetChar( aLine.GetEnd() - 1 ) 251 ? 1 : 0; 252 pPam = AddPam( pPam, pFrm, nPos, aLine.GetEnd() - nPos - nOff ); 253 } 254 } 255 } 256 bFirstLine = sal_False; 257 } 258 while( aLine.Next() ); 259 } 260 261 /************************************************************************* 262 * SwTxtFrmInfo::IsBullet() 263 *************************************************************************/ 264 265 // Ist an der Textposition ein Bullet/Symbol etc? 266 // Fonts: CharSet, SYMBOL und DONTKNOW 267 sal_Bool SwTxtFrmInfo::IsBullet( xub_StrLen nTxtStart ) const 268 { 269 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 270 SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf ); 271 aInf.SetIdx( nTxtStart ); 272 return aLine.IsSymbol( nTxtStart ); 273 } 274 275 /************************************************************************* 276 * SwTxtFrmInfo::GetFirstIndent() 277 *************************************************************************/ 278 279 // Ermittelt Erstzeileneinzug 280 // Voraussetzung fuer pos. oder neg. EZE ist, dass alle 281 // Zeilen ausser der ersten Zeile den selben linken Rand haben. 282 // Wir wollen nicht so knauserig sein und arbeiten mit einer Toleranz 283 // von TOLERANCE Twips. 284 285 #define TOLERANCE 20 286 287 SwTwips SwTxtFrmInfo::GetFirstIndent() const 288 { 289 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 290 SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf ); 291 const SwTwips nFirst = GetLineStart( aLine ); 292 if( !aLine.Next() ) 293 return 0; 294 295 SwTwips nLeft = GetLineStart( aLine ); 296 while( aLine.Next() ) 297 { 298 if( aLine.GetCurr()->GetLen() ) 299 { 300 const SwTwips nCurrLeft = GetLineStart( aLine ); 301 if( nLeft + TOLERANCE < nCurrLeft || 302 nLeft - TOLERANCE > nCurrLeft ) 303 return 0; 304 } 305 } 306 307 // Vorerst wird nur +1, -1 und 0 returnt. 308 if( nLeft == nFirst ) 309 return 0; 310 else 311 if( nLeft > nFirst ) 312 return -1; 313 else 314 return +1; 315 } 316 317 /************************************************************************* 318 * SwTxtFrmInfo::GetBigIndent() 319 *************************************************************************/ 320 321 KSHORT SwTxtFrmInfo::GetBigIndent( xub_StrLen& rFndPos, 322 const SwTxtFrm *pNextFrm ) const 323 { 324 SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm ); 325 SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf ); 326 SwTwips nNextIndent = 0; 327 328 if( pNextFrm ) 329 { 330 // ich bin einzeilig 331 SwTxtSizeInfo aNxtInf( (SwTxtFrm*)pNextFrm ); 332 SwTxtCursor aNxtLine( (SwTxtFrm*)pNextFrm, &aNxtInf ); 333 nNextIndent = GetLineStart( aNxtLine ); 334 } 335 else 336 { 337 // ich bin mehrzeilig 338 if( aLine.Next() ) 339 { 340 nNextIndent = GetLineStart( aLine ); 341 aLine.Prev(); 342 } 343 } 344 345 if( nNextIndent <= GetLineStart( aLine ) ) 346 return 0; 347 348 const Point aPoint( nNextIndent, aLine.Y() ); 349 rFndPos = aLine.GetCrsrOfst( 0, aPoint, sal_False ); 350 if( 1 >= rFndPos ) 351 return 0; 352 353 // steht vor einem "nicht Space" 354 const XubString& rTxt = aInf.GetTxt(); 355 xub_Unicode aChar = rTxt.GetChar( rFndPos ); 356 if( CH_TAB == aChar || CH_BREAK == aChar || ' ' == aChar || 357 (( CH_TXTATR_BREAKWORD == aChar || CH_TXTATR_INWORD == aChar ) && 358 aInf.HasHint( rFndPos ) ) ) 359 return 0; 360 361 // und hinter einem "Space" 362 aChar = rTxt.GetChar( rFndPos - 1 ); 363 if( CH_TAB != aChar && CH_BREAK != aChar && 364 ( ( CH_TXTATR_BREAKWORD != aChar && CH_TXTATR_INWORD != aChar ) || 365 !aInf.HasHint( rFndPos - 1 ) ) && 366 // mehr als 2 Blanks !! 367 ( ' ' != aChar || ' ' != rTxt.GetChar( rFndPos - 2 ) ) ) 368 return 0; 369 370 SwRect aRect; 371 return aLine.GetCharRect( &aRect, rFndPos ) 372 ? KSHORT( aRect.Left() - pFrm->Frm().Left() - pFrm->Prt().Left()) 373 : 0; 374 } 375 376 377 378