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 : MSHORT 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 :
56 1443 : SwLinePortion::~SwLinePortion()
57 : {
58 1443 : if( pBlink )
59 0 : pBlink->Delete( this );
60 1443 : }
61 :
62 649 : SwLinePortion *SwLinePortion::Compress()
63 : {
64 649 : return GetLen() || Width() ? this : 0;
65 : }
66 :
67 66 : KSHORT SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const
68 : {
69 66 : return 0;
70 : }
71 :
72 : /*************************************************************************
73 : * SwLinePortion::SwLinePortion( )
74 : *************************************************************************/
75 :
76 1382 : SwLinePortion::SwLinePortion( ) :
77 : pPortion( NULL ),
78 : nLineLength( 0 ),
79 1382 : nAscent( 0 )
80 : {
81 1382 : }
82 :
83 : /*************************************************************************
84 : * SwLinePortion::PrePaint()
85 : *************************************************************************/
86 :
87 73 : void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf,
88 : const SwLinePortion* pLast ) const
89 : {
90 : OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
91 : OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
92 :
93 73 : const KSHORT nViewWidth = GetViewWidth( rInf );
94 :
95 73 : if( ! nViewWidth )
96 73 : return;
97 :
98 7 : const KSHORT nHalfView = nViewWidth / 2;
99 7 : sal_uInt16 nLastWidth = pLast->Width();
100 :
101 7 : if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
102 0 : nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
103 :
104 : KSHORT nPos;
105 7 : SwTxtPaintInfo aInf( rInf );
106 :
107 7 : const bool bBidiPor = ( rInf.GetTxtFrm()->IsRightToLeft() ) !=
108 7 : ( 0 != ( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() ) );
109 :
110 : sal_uInt16 nDir = bBidiPor ?
111 : 1800 :
112 7 : rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
113 :
114 7 : switch ( nDir )
115 : {
116 : case 0 :
117 7 : nPos = KSHORT( rInf.X() );
118 7 : if( nLastWidth > nHalfView )
119 4 : nPos += nLastWidth - nHalfView;
120 7 : aInf.X( nPos );
121 7 : break;
122 : case 900 :
123 0 : nPos = KSHORT( rInf.Y() );
124 0 : if( nLastWidth > nHalfView )
125 0 : nPos -= nLastWidth + nHalfView;
126 0 : aInf.Y( nPos );
127 0 : break;
128 : case 1800 :
129 0 : nPos = KSHORT( rInf.X() );
130 0 : if( nLastWidth > nHalfView )
131 0 : nPos -= nLastWidth + nHalfView;
132 0 : aInf.X( nPos );
133 0 : break;
134 : case 2700 :
135 0 : nPos = KSHORT( rInf.Y() );
136 0 : if( nLastWidth > nHalfView )
137 0 : nPos += nLastWidth - nHalfView;
138 0 : aInf.Y( nPos );
139 0 : break;
140 : }
141 :
142 7 : SwLinePortion *pThis = (SwLinePortion*)this;
143 7 : pThis->Width( nViewWidth );
144 7 : Paint( aInf );
145 7 : pThis->Width(0);
146 : }
147 :
148 : /*************************************************************************
149 : * SwLinePortion::CalcTxtSize()
150 : *************************************************************************/
151 :
152 6 : void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf )
153 : {
154 6 : if( GetLen() == rInf.GetLen() )
155 6 : *((SwPosSize*)this) = GetTxtSize( rInf );
156 : else
157 : {
158 0 : SwTxtSizeInfo aInf( rInf );
159 0 : aInf.SetLen( GetLen() );
160 0 : *((SwPosSize*)this) = GetTxtSize( aInf );
161 : }
162 6 : }
163 :
164 : /*************************************************************************
165 : * SwLinePortion::Truncate()
166 : *
167 : * Es werden alle nachfolgenden Portions geloescht.
168 : *************************************************************************/
169 :
170 266 : void SwLinePortion::_Truncate()
171 : {
172 266 : SwLinePortion *pPos = pPortion;
173 571 : do
174 : { OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
175 571 : SwLinePortion *pLast = pPos;
176 571 : pPos = pPos->GetPortion();
177 571 : pLast->SetPortion( 0 );
178 571 : delete pLast;
179 :
180 : } while( pPos );
181 :
182 266 : pPortion = 0;
183 266 : }
184 :
185 : /*************************************************************************
186 : * virtual SwLinePortion::Insert()
187 : *
188 : * Es wird immer hinter uns eingefuegt.
189 : *************************************************************************/
190 :
191 326 : SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
192 : {
193 326 : pIns->FindLastPortion()->SetPortion( pPortion );
194 326 : SetPortion( pIns );
195 : #if OSL_DEBUG_LEVEL > 0
196 : ChkChain( this );
197 : #endif
198 326 : return pIns;
199 : }
200 :
201 : /*************************************************************************
202 : * SwLinePortion::FindLastPortion()
203 : *************************************************************************/
204 :
205 368 : SwLinePortion *SwLinePortion::FindLastPortion()
206 : {
207 368 : SwLinePortion *pPos = this;
208 : // An das Ende wandern und pLinPortion an den letzten haengen ...
209 779 : while( pPos->GetPortion() )
210 : {
211 43 : pPos = pPos->GetPortion();
212 : }
213 368 : return pPos;
214 : }
215 :
216 : /*************************************************************************
217 : * virtual SwLinePortion::Append()
218 : *************************************************************************/
219 :
220 21 : SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
221 : {
222 21 : SwLinePortion *pPos = FindLastPortion();
223 21 : pPos->SetPortion( pIns );
224 21 : pIns->SetPortion( 0 );
225 : #if OSL_DEBUG_LEVEL > 0
226 : ChkChain( this );
227 : #endif
228 21 : return pIns;
229 : }
230 :
231 : /*************************************************************************
232 : * virtual SwLinePortion::Cut()
233 : *************************************************************************/
234 :
235 61 : SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
236 : {
237 61 : SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
238 : OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
239 61 : pPrev->SetPortion( pVictim->GetPortion() );
240 61 : pVictim->SetPortion(0);
241 61 : return pVictim;
242 : }
243 :
244 : /*************************************************************************
245 : * SwLinePortion::FindPrevPortion()
246 : *************************************************************************/
247 :
248 94 : SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
249 : {
250 : OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
251 94 : SwLinePortion *pPos = (SwLinePortion*)pRoot;
252 221 : while( pPos->GetPortion() && pPos->GetPortion() != this )
253 : {
254 33 : pPos = pPos->GetPortion();
255 : }
256 : OSL_ENSURE( pPos->GetPortion(),
257 : "SwLinePortion::FindPrevPortion: blowing in the wind");
258 94 : return pPos;
259 : }
260 :
261 : /*************************************************************************
262 : * virtual SwLinePortion::GetCrsrOfst()
263 : *************************************************************************/
264 :
265 0 : xub_StrLen SwLinePortion::GetCrsrOfst( const KSHORT nOfst ) const
266 : {
267 0 : if( nOfst > ( PrtWidth() / 2 ) )
268 0 : return GetLen();
269 : else
270 0 : return 0;
271 : }
272 :
273 : /*************************************************************************
274 : * virtual SwLinePortion::GetTxtSize()
275 : *************************************************************************/
276 :
277 0 : SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const
278 : {
279 : OSL_ENSURE( !this, "SwLinePortion::GetTxtSize: don't ask me about sizes, "
280 : "I'm only a stupid SwLinePortion" );
281 0 : return SwPosSize();
282 : }
283 :
284 : /*************************************************************************
285 : * virtual SwLinePortion::Format()
286 : *************************************************************************/
287 :
288 6 : sal_Bool SwLinePortion::Format( SwTxtFormatInfo &rInf )
289 : {
290 6 : if( rInf.X() > rInf.Width() )
291 : {
292 0 : Truncate();
293 0 : rInf.SetUnderFlow( this );
294 0 : return sal_True;
295 : }
296 :
297 6 : const SwLinePortion *pLast = rInf.GetLast();
298 6 : Height( pLast->Height() );
299 6 : SetAscent( pLast->GetAscent() );
300 6 : const KSHORT nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
301 : // Nur Portions mit echter Breite koennen ein sal_True zurueckliefern
302 : // Notizen beispielsweise setzen niemals bFull==sal_True
303 6 : if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
304 : {
305 0 : Truncate();
306 0 : if( nNewWidth > rInf.Width() )
307 0 : PrtWidth( nNewWidth - rInf.Width() );
308 0 : rInf.GetLast()->FormatEOL( rInf );
309 0 : return sal_True;
310 : }
311 6 : return sal_False;
312 : }
313 :
314 : /*************************************************************************
315 : * virtual SwLinePortion::FormatEOL()
316 : *************************************************************************/
317 :
318 : // Format end of line
319 :
320 1 : void SwLinePortion::FormatEOL( SwTxtFormatInfo & )
321 1 : { }
322 :
323 : /*************************************************************************
324 : * SwLinePortion::Move()
325 : *************************************************************************/
326 :
327 2681 : void SwLinePortion::Move( SwTxtPaintInfo &rInf )
328 : {
329 2681 : bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
330 2681 : const bool bFrmDir = rInf.GetTxtFrm()->IsRightToLeft();
331 5362 : bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
332 5362 : ( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
333 :
334 2681 : if ( InSpaceGrp() && rInf.GetSpaceAdd() )
335 : {
336 4 : SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
337 4 : if( rInf.IsRotated() )
338 0 : rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
339 4 : else if ( bCounterDir )
340 0 : rInf.X( rInf.X() - nTmp );
341 : else
342 4 : rInf.X( rInf.X() + nTmp );
343 : }
344 : else
345 : {
346 2677 : if( InFixMargGrp() && !IsMarginPortion() )
347 : {
348 177 : rInf.IncSpaceIdx();
349 177 : rInf.IncKanaIdx();
350 : }
351 2677 : if( rInf.IsRotated() )
352 0 : rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
353 2677 : else if ( bCounterDir )
354 2 : rInf.X( rInf.X() - PrtWidth() );
355 : else
356 2675 : rInf.X( rInf.X() + PrtWidth() );
357 : }
358 2681 : if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() )
359 0 : rInf.IncSpaceIdx();
360 :
361 2681 : rInf.SetIdx( rInf.GetIdx() + GetLen() );
362 2681 : }
363 :
364 : /*************************************************************************
365 : * virtual SwLinePortion::CalcSpacing()
366 : *************************************************************************/
367 :
368 0 : long SwLinePortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
369 : {
370 0 : return 0;
371 : }
372 :
373 : /*************************************************************************
374 : * virtual SwLinePortion::GetExpTxt()
375 : *************************************************************************/
376 :
377 0 : sal_Bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
378 : {
379 0 : return sal_False;
380 : }
381 :
382 : /*************************************************************************
383 : * virtual SwLinePortion::HandlePortion()
384 : *************************************************************************/
385 :
386 1 : void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
387 : {
388 1 : String aString;
389 1 : rPH.Special( GetLen(), aString, GetWhichPor(), Height(), Width() );
390 1 : }
391 :
392 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|