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