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