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