Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/outdev.hxx>
21 : #include <SwPortionHandler.hxx>
22 :
23 : #include "porlin.hxx"
24 : #include "inftxt.hxx"
25 : #include "portxt.hxx"
26 : #include "pormulti.hxx"
27 : #include "porglue.hxx"
28 : #include "blink.hxx"
29 : #if OSL_DEBUG_LEVEL > 0
30 :
31 : bool ChkChain( SwLinePortion *pStart )
32 : {
33 : SwLinePortion *pPor = pStart->GetPortion();
34 : sal_uInt16 nCount = 0;
35 : while( pPor )
36 : {
37 : ++nCount;
38 : OSL_ENSURE( nCount < 200 && pPor != pStart,
39 : "ChkChain(): lost in chains" );
40 : if( nCount >= 200 || pPor == pStart )
41 : {
42 : // der Lebensretter
43 : pPor = pStart->GetPortion();
44 : pStart->SetPortion(0);
45 : pPor->Truncate();
46 : pStart->SetPortion( pPor );
47 : return false;
48 : }
49 : pPor = pPor->GetPortion();
50 : }
51 : return true;
52 : }
53 : #endif
54 :
55 248540 : SwLinePortion::~SwLinePortion()
56 : {
57 248540 : if( pBlink )
58 2977 : pBlink->Delete( this );
59 248540 : }
60 :
61 114058 : SwLinePortion *SwLinePortion::Compress()
62 : {
63 114058 : return GetLen() || Width() ? this : 0;
64 : }
65 :
66 8193 : sal_uInt16 SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const
67 : {
68 8193 : return 0;
69 : }
70 :
71 222564 : SwLinePortion::SwLinePortion( ) :
72 : pPortion( NULL ),
73 : nLineLength( 0 ),
74 : nAscent( 0 ),
75 : nWhichPor( POR_LIN ),
76 : m_bJoinBorderWithPrev(false),
77 222564 : m_bJoinBorderWithNext(false)
78 : {
79 222564 : }
80 :
81 10843 : void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf,
82 : const SwLinePortion* pLast ) const
83 : {
84 : OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
85 : OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
86 :
87 10843 : const sal_uInt16 nViewWidth = GetViewWidth( rInf );
88 :
89 10843 : if( ! nViewWidth )
90 20258 : return;
91 :
92 1428 : const sal_uInt16 nHalfView = nViewWidth / 2;
93 1428 : sal_uInt16 nLastWidth = pLast->Width();
94 :
95 1428 : if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
96 0 : nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
97 :
98 : sal_uInt16 nPos;
99 1428 : SwTxtPaintInfo aInf( rInf );
100 :
101 2856 : const bool bBidiPor = rInf.GetTxtFrm()->IsRightToLeft() !=
102 2856 : bool( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() );
103 :
104 : sal_uInt16 nDir = bBidiPor ?
105 : 1800 :
106 1428 : rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
107 :
108 1428 : switch ( nDir )
109 : {
110 : case 0 :
111 1428 : nPos = sal_uInt16( rInf.X() );
112 1428 : if( nLastWidth > nHalfView )
113 1144 : nPos += nLastWidth - nHalfView;
114 1428 : aInf.X( nPos );
115 1428 : break;
116 : case 900 :
117 0 : nPos = sal_uInt16( rInf.Y() );
118 0 : if( nLastWidth > nHalfView )
119 0 : nPos -= nLastWidth + nHalfView;
120 0 : aInf.Y( nPos );
121 0 : break;
122 : case 1800 :
123 0 : nPos = sal_uInt16( rInf.X() );
124 0 : if( nLastWidth > nHalfView )
125 0 : nPos -= nLastWidth + nHalfView;
126 0 : aInf.X( nPos );
127 0 : break;
128 : case 2700 :
129 0 : nPos = sal_uInt16( rInf.Y() );
130 0 : if( nLastWidth > nHalfView )
131 0 : nPos += nLastWidth - nHalfView;
132 0 : aInf.Y( nPos );
133 0 : break;
134 : }
135 :
136 1428 : SwLinePortion *pThis = (SwLinePortion*)this;
137 1428 : pThis->Width( nViewWidth );
138 1428 : Paint( aInf );
139 1428 : pThis->Width(0);
140 : }
141 :
142 2476 : void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf )
143 : {
144 2476 : if( GetLen() == rInf.GetLen() )
145 2476 : *((SwPosSize*)this) = GetTxtSize( rInf );
146 : else
147 : {
148 0 : SwTxtSizeInfo aInf( rInf );
149 0 : aInf.SetLen( GetLen() );
150 0 : *((SwPosSize*)this) = GetTxtSize( aInf );
151 : }
152 2476 : }
153 :
154 : // Es werden alle nachfolgenden Portions geloescht.
155 43512 : void SwLinePortion::_Truncate()
156 : {
157 43512 : SwLinePortion *pPos = pPortion;
158 130029 : do
159 : { OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
160 130029 : SwLinePortion *pLast = pPos;
161 130029 : pPos = pPos->GetPortion();
162 130029 : pLast->SetPortion( 0 );
163 130029 : delete pLast;
164 :
165 : } while( pPos );
166 :
167 43512 : pPortion = 0;
168 43512 : }
169 :
170 : // Es wird immer hinter uns eingefuegt.
171 92617 : SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
172 : {
173 92617 : pIns->FindLastPortion()->SetPortion( pPortion );
174 92617 : SetPortion( pIns );
175 : #if OSL_DEBUG_LEVEL > 0
176 : ChkChain( this );
177 : #endif
178 92617 : return pIns;
179 : }
180 :
181 97841 : SwLinePortion *SwLinePortion::FindLastPortion()
182 : {
183 97841 : SwLinePortion *pPos = this;
184 : // An das Ende wandern und pLinPortion an den letzten haengen ...
185 203590 : while( pPos->GetPortion() )
186 : {
187 7908 : pPos = pPos->GetPortion();
188 : }
189 97841 : return pPos;
190 : }
191 :
192 2616 : SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
193 : {
194 2616 : SwLinePortion *pPos = FindLastPortion();
195 2616 : pPos->SetPortion( pIns );
196 2616 : pIns->SetPortion( 0 );
197 : #if OSL_DEBUG_LEVEL > 0
198 : ChkChain( this );
199 : #endif
200 2616 : return pIns;
201 : }
202 :
203 10448 : SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
204 : {
205 10448 : SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
206 : OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
207 10448 : pPrev->SetPortion( pVictim->GetPortion() );
208 10448 : pVictim->SetPortion(0);
209 10448 : return pVictim;
210 : }
211 :
212 11104 : SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
213 : {
214 : OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
215 11104 : SwLinePortion *pPos = (SwLinePortion*)pRoot;
216 23072 : while( pPos->GetPortion() && pPos->GetPortion() != this )
217 : {
218 864 : pPos = pPos->GetPortion();
219 : }
220 : OSL_ENSURE( pPos->GetPortion(),
221 : "SwLinePortion::FindPrevPortion: blowing in the wind");
222 11104 : return pPos;
223 : }
224 :
225 58 : sal_Int32 SwLinePortion::GetCrsrOfst( const sal_uInt16 nOfst ) const
226 : {
227 58 : if( nOfst > ( PrtWidth() / 2 ) )
228 52 : return GetLen();
229 : else
230 6 : return 0;
231 : }
232 :
233 0 : SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const
234 : {
235 : OSL_ENSURE( false, "SwLinePortion::GetTxtSize: don't ask me about sizes, "
236 : "I'm only a stupid SwLinePortion" );
237 0 : return SwPosSize();
238 : }
239 :
240 880 : bool SwLinePortion::Format( SwTxtFormatInfo &rInf )
241 : {
242 880 : if( rInf.X() > rInf.Width() )
243 : {
244 0 : Truncate();
245 0 : rInf.SetUnderflow( this );
246 0 : return true;
247 : }
248 :
249 880 : const SwLinePortion *pLast = rInf.GetLast();
250 880 : Height( pLast->Height() );
251 880 : SetAscent( pLast->GetAscent() );
252 880 : const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
253 : // Nur Portions mit echter Breite koennen ein true zurueckliefern
254 : // Notizen beispielsweise setzen niemals bFull==true
255 880 : if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
256 : {
257 0 : Truncate();
258 0 : if( nNewWidth > rInf.Width() )
259 0 : PrtWidth( nNewWidth - rInf.Width() );
260 0 : rInf.GetLast()->FormatEOL( rInf );
261 0 : return true;
262 : }
263 880 : return false;
264 : }
265 :
266 : // Format end of line
267 :
268 196 : void SwLinePortion::FormatEOL( SwTxtFormatInfo & )
269 196 : { }
270 :
271 442287 : void SwLinePortion::Move( SwTxtPaintInfo &rInf )
272 : {
273 442287 : bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
274 442287 : const bool bFrmDir = rInf.GetTxtFrm()->IsRightToLeft();
275 442309 : bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
276 442639 : ( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
277 :
278 442287 : if ( InSpaceGrp() && rInf.GetSpaceAdd() )
279 : {
280 2096 : SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
281 2096 : if( rInf.IsRotated() )
282 0 : rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
283 2096 : else if ( bCounterDir )
284 0 : rInf.X( rInf.X() - nTmp );
285 : else
286 2096 : rInf.X( rInf.X() + nTmp );
287 : }
288 : else
289 : {
290 440191 : if( InFixMargGrp() && !IsMarginPortion() )
291 : {
292 53803 : rInf.IncSpaceIdx();
293 53803 : rInf.IncKanaIdx();
294 : }
295 440191 : if( rInf.IsRotated() )
296 2 : rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
297 440189 : else if ( bCounterDir )
298 22 : rInf.X( rInf.X() - PrtWidth() );
299 : else
300 440167 : rInf.X( rInf.X() + PrtWidth() );
301 : }
302 442287 : if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() )
303 0 : rInf.IncSpaceIdx();
304 :
305 442287 : rInf.SetIdx( rInf.GetIdx() + GetLen() );
306 442287 : }
307 :
308 0 : long SwLinePortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
309 : {
310 0 : return 0;
311 : }
312 :
313 0 : bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &, OUString & ) const
314 : {
315 0 : return false;
316 : }
317 :
318 114 : void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
319 : {
320 114 : rPH.Special( GetLen(), OUString(), GetWhichPor(), Height(), Width() );
321 384 : }
322 :
323 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|