xref: /AOO41X/main/sw/source/core/text/frminf.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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