xref: /trunk/main/sw/source/core/text/frminf.cxx (revision efeef26f)
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 
GetTxtStart() const37 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 
GetTxtEnd() const57 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?
IsOneLine() const77 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?
IsFilled(const sal_uInt8 nPercent) const103 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 )
GetLineStart(const SwTxtCursor & rLine) const122 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)
GetLineStart() const145 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
GetCharPos(xub_StrLen nChar,sal_Bool bCenter) const153 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 
AddPam(SwPaM * pPam,const SwTxtFrm * pTxtFrm,const xub_StrLen nPos,const xub_StrLen nLen)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
GetSpaces(SwPaM & rPam,sal_Bool bWithLineBreak) const220 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
IsBullet(xub_StrLen nTxtStart) const263 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 
GetFirstIndent() const283 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 
GetBigIndent(xub_StrLen & rFndPos,const SwTxtFrm * pNextFrm) const317 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