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