Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "dcontact.hxx" // SwDrawContact
30 : : #include "dflyobj.hxx" // SwVirtFlyDrawObj
31 : : #include "pam.hxx" // SwPosition
32 : : #include "flyfrm.hxx" // SwFlyInCntFrm
33 : : #include "rootfrm.hxx"
34 : : #include "frmfmt.hxx" // SwFrmFmt
35 : : #include "viewsh.hxx"
36 : :
37 : : #include <vcl/outdev.hxx>
38 : : #include <editeng/lrspitem.hxx>
39 : : #include <editeng/ulspitem.hxx>
40 : : #include <fmtanchr.hxx>
41 : : #include <fmtflcnt.hxx>
42 : : #include <fmtornt.hxx>
43 : : #include <frmatr.hxx>
44 : : #include "flyfrms.hxx"
45 : : #include "txatbase.hxx" // SwTxtAttr
46 : : #include "porfly.hxx"
47 : : #include "porlay.hxx" // SetFly
48 : : #include "inftxt.hxx" // SwTxtPaintInfo
49 : :
50 : : // OD 2004-05-24 #i28701#
51 : : #include <sortedobjs.hxx>
52 : :
53 : :
54 : : /*************************************************************************
55 : : * class SwFlyPortion
56 : : *
57 : : * Wir erwarten ein framelokales SwRect !
58 : : *************************************************************************/
59 : :
60 : 106 : void SwFlyPortion::Paint( const SwTxtPaintInfo& ) const
61 : : {
62 : 106 : }
63 : :
64 : : /*************************************************************************
65 : : * virtual SwFlyPortion::Format()
66 : : *************************************************************************/
67 : 119 : sal_Bool SwFlyPortion::Format( SwTxtFormatInfo &rInf )
68 : : {
69 : : OSL_ENSURE( Fix() >= rInf.X(), "SwFlyPortion::Format: rush hour" );
70 : : // 8537: Tabs muessen expandiert werden.
71 [ - + ]: 119 : if( rInf.GetLastTab() )
72 : 0 : ((SwLinePortion*)rInf.GetLastTab())->FormatEOL( rInf );
73 : :
74 : : // Der Glue wird aufgespannt.
75 : 119 : rInf.GetLast()->FormatEOL( rInf );
76 : 119 : PrtWidth( static_cast<sal_uInt16>(Fix() - rInf.X() + PrtWidth()) );
77 [ - + ]: 119 : if( !Width() )
78 : : {
79 : : OSL_ENSURE( Width(), "+SwFlyPortion::Format: a fly is a fly is a fly" );
80 : 0 : Width(1);
81 : : }
82 : :
83 : : // Restaurierung
84 : 119 : rInf.SetFly( 0 );
85 : 119 : rInf.Width( rInf.RealWidth() );
86 : 119 : rInf.GetParaPortion()->SetFly( sal_True );
87 : :
88 : : // trailing blank:
89 [ + + + - : 263 : if( rInf.GetIdx() < rInf.GetTxt().Len() && 1 < rInf.GetIdx()
- + # # #
# # # ]
[ - + ][ + + ]
90 : 72 : && !rInf.GetRest()
91 : 72 : && ' ' == rInf.GetChar( rInf.GetIdx() )
92 : 0 : && ' ' != rInf.GetChar( rInf.GetIdx() - 1 )
93 : 0 : && ( !rInf.GetLast() || !rInf.GetLast()->IsBreakPortion() ) )
94 : : {
95 [ # # ][ # # ]: 0 : SetBlankWidth( rInf.GetTxtSize(rtl::OUString(' ')).Width() );
[ # # ]
96 : 0 : SetLen( 1 );
97 : : }
98 : :
99 : 119 : const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
100 [ + + ]: 119 : if( rInf.Width() <= nNewWidth )
101 : : {
102 : 70 : Truncate();
103 [ - + ]: 70 : if( nNewWidth > rInf.Width() )
104 : : {
105 : 0 : PrtWidth( nNewWidth - rInf.Width() );
106 : 0 : SetFixWidth( PrtWidth() );
107 : : }
108 : 70 : return sal_True;
109 : : }
110 : 119 : return sal_False;
111 : : }
112 : :
113 : : /*************************************************************************
114 : : * virtual SwFlyCntPortion::Format()
115 : : *************************************************************************/
116 : 1290 : sal_Bool SwFlyCntPortion::Format( SwTxtFormatInfo &rInf )
117 : : {
118 : 1290 : sal_Bool bFull = rInf.Width() < rInf.X() + PrtWidth();
119 : :
120 [ + + ]: 1290 : if( bFull )
121 : : {
122 : : // 3924: wenn die Zeile voll ist und der zeichengebundene Frame am
123 : : // Anfang der Zeile steht.
124 : : // 5157: nicht wenn einem Fly ausgewichen werden kann!
125 : : // "Begin of line" criteria ( ! rInf.X() ) has to be extended.
126 : : // KerningPortions at beginning of line, e.g., for grid layout
127 : : // must be considered.
128 : 30 : const SwLinePortion* pLastPor = rInf.GetLast();
129 : : const sal_uInt16 nLeft = ( pLastPor &&
130 : 30 : ( pLastPor->IsKernPortion() ||
131 : 30 : pLastPor->IsErgoSumPortion() ) ) ?
132 : 0 : pLastPor->Width() :
133 [ + - + - : 90 : 0;
- + ]
134 : :
135 [ + + ][ + + ]: 30 : if( nLeft == rInf.X() && ! rInf.GetFly() )
[ + + ]
136 : : {
137 : 6 : Width( rInf.Width() );
138 : 6 : bFull = sal_False; // Damit Notizen noch in dieser Zeile landen
139 : : }
140 : : else
141 : : {
142 [ + + ]: 24 : if( !rInf.GetFly() )
143 : 15 : rInf.SetNewLine( sal_True );
144 : 24 : Width(0);
145 : 24 : SetAscent(0);
146 : 24 : SetLen(0);
147 [ + - ]: 24 : if( rInf.GetLast() )
148 : 24 : rInf.GetLast()->FormatEOL( rInf );
149 : :
150 : 24 : return bFull;
151 : : }
152 : : }
153 : :
154 : 1266 : rInf.GetParaPortion()->SetFly( sal_True );
155 : 1290 : return bFull;
156 : : }
157 : :
158 : : /*************************************************************************
159 : : * SwTxtFrm::MoveFlyInCnt() haengt jetzt die zeichengebundenen Objekte
160 : : * innerhalb des angegebenen Bereichs um, damit koennen diese vom Master
161 : : * zum Follow oder umgekehrt wandern.
162 : : *************************************************************************/
163 : 712 : void SwTxtFrm::MoveFlyInCnt( SwTxtFrm *pNew, xub_StrLen nStart, xub_StrLen nEnd )
164 : : {
165 : 712 : SwSortedObjs *pObjs = 0L;
166 [ + + ]: 712 : if ( 0 != (pObjs = GetDrawObjs()) )
167 : : {
168 [ + + ][ + + ]: 24 : for ( sal_uInt32 i = 0; GetDrawObjs() && i < pObjs->Count(); ++i )
[ + + ]
169 : : {
170 : : // OD 2004-03-29 #i26791#
171 : : // #i28701# - consider changed type of
172 : : // <SwSortedList> entries
173 : 18 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
174 : 18 : const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
175 [ + - ]: 18 : if (rAnch.GetAnchorId() == FLY_AS_CHAR)
176 : : {
177 : 18 : const SwPosition* pPos = rAnch.GetCntntAnchor();
178 : 18 : xub_StrLen nIdx = pPos->nContent.GetIndex();
179 [ + - ][ + + ]: 18 : if ( nIdx >= nStart && nEnd > nIdx )
180 : : {
181 [ - + ]: 14 : if ( pAnchoredObj->ISA(SwFlyFrm) )
182 : : {
183 [ # # ]: 0 : RemoveFly( static_cast<SwFlyFrm*>(pAnchoredObj) );
184 [ # # ]: 0 : pNew->AppendFly( static_cast<SwFlyFrm*>(pAnchoredObj) );
185 : : }
186 [ + - ]: 14 : else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
187 : : {
188 : 14 : RemoveDrawObj( *pAnchoredObj );
189 : 14 : pNew->AppendDrawObj( *pAnchoredObj );
190 : : }
191 : 14 : --i;
192 : : }
193 : : }
194 : : }
195 : : }
196 : 712 : }
197 : :
198 : : /*************************************************************************
199 : : * SwTxtFrm::CalcFlyPos()
200 : : *************************************************************************/
201 : 84 : xub_StrLen SwTxtFrm::CalcFlyPos( SwFrmFmt* pSearch )
202 : : {
203 : 84 : SwpHints* pHints = GetTxtNode()->GetpSwpHints();
204 : : OSL_ENSURE( pHints, "CalcFlyPos: Why me?" );
205 [ - + ]: 84 : if( !pHints )
206 : 0 : return STRING_LEN;
207 : 84 : SwTxtAttr* pFound = NULL;
208 [ + + ]: 226 : for ( sal_uInt16 i = 0; i < pHints->Count(); i++)
209 : : {
210 : 142 : SwTxtAttr *pHt = pHints->GetTextHint( i );
211 [ + - ]: 142 : if( RES_TXTATR_FLYCNT == pHt->Which() )
212 : : {
213 : 142 : SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
214 [ + + ]: 142 : if( pFrmFmt == pSearch )
215 : 84 : pFound = pHt;
216 : : }
217 : : }
218 : : OSL_ENSURE( pHints, "CalcFlyPos: Not Found!" );
219 [ - + ]: 84 : if( !pFound )
220 : 0 : return STRING_LEN;
221 : 84 : return *pFound->GetStart();
222 : : }
223 : :
224 : : /*************************************************************************
225 : : * virtual SwFlyCntPortion::Paint()
226 : : *************************************************************************/
227 : 7256 : void SwFlyCntPortion::Paint( const SwTxtPaintInfo &rInf ) const
228 : : {
229 [ + + ]: 7256 : if( bDraw )
230 : : {
231 [ - + ]: 7015 : if( !((SwDrawContact*)pContact)->GetAnchorFrm() )
232 : : {
233 : : // OD 2004-04-01 #i26791# - no direct positioning of the drawing
234 : : // object is needed.
235 : 0 : SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pContact);
236 : 0 : pDrawContact->ConnectToLayout();
237 : : }
238 : : }
239 : : else
240 : : {
241 : : // Baseline-Ausgabe !
242 : : // 7922: Bei CompletePaint alles painten
243 : 241 : SwRect aRepaintRect( rInf.GetPaintRect() );
244 : :
245 [ - + ][ + - ]: 241 : if ( rInf.GetTxtFrm()->IsRightToLeft() )
246 [ # # ]: 0 : rInf.GetTxtFrm()->SwitchLTRtoRTL( aRepaintRect );
247 : :
248 [ + - ][ - + ]: 241 : if ( rInf.GetTxtFrm()->IsVertical() )
249 [ # # ]: 0 : rInf.GetTxtFrm()->SwitchHorizontalToVertical( aRepaintRect );
250 : :
251 [ + - ][ + + ]: 715 : if( (GetFlyFrm()->IsCompletePaint() ||
[ + - ][ + + ]
252 [ + - ]: 241 : GetFlyFrm()->Frm().IsOver( aRepaintRect )) &&
253 [ + - ]: 233 : SwFlyFrm::IsPaint( (SdrObject*)GetFlyFrm()->GetVirtDrawObj(),
254 [ + - ]: 466 : GetFlyFrm()->getRootFrm()->GetCurrShell() ))
255 : : {
256 : 233 : SwRect aRect( GetFlyFrm()->Frm() );
257 [ + - ]: 233 : if( !GetFlyFrm()->IsCompletePaint() )
258 [ + - ]: 233 : aRect._Intersection( aRepaintRect );
259 : :
260 : :
261 : : // GetFlyFrm() may change the layout mode at the output device.
262 : : {
263 [ + - ]: 233 : SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
264 [ + - ][ + - ]: 233 : GetFlyFrm()->Paint( aRect );
265 : : }
266 : : ((SwTxtPaintInfo&)rInf).GetRefDev()->SetLayoutMode(
267 [ + - ]: 233 : rInf.GetOut()->GetLayoutMode() );
268 : :
269 : : // Es hilft alles nichts, im zeichengebundenen Frame kann wer weiss
270 : : // was am OutputDevice eingestellt sein, wir muessen unseren Font
271 : : // wieder hineinselektieren. Dass wir im const stehen, soll uns
272 : : // daran nicht hindern:
273 [ + - ]: 233 : ((SwTxtPaintInfo&)rInf).SelectFont();
274 : :
275 : : // I want to know if this can really happen. So here comes a new
276 : : OSL_ENSURE( ! rInf.GetVsh() || rInf.GetVsh()->GetOut() == rInf.GetOut(),
277 : : "SwFlyCntPortion::Paint: Outdev has changed" );
278 [ + - ]: 233 : if( rInf.GetVsh() )
279 : 241 : ((SwTxtPaintInfo&)rInf).SetOut( rInf.GetVsh()->GetOut() );
280 : : }
281 : : }
282 : 7256 : }
283 : :
284 : : /*************************************************************************
285 : : * SwFlyCntPortion::SwFlyCntPortion()
286 : : *
287 : : * Es werden die Masze vom pFly->OutRect() eingestellt.
288 : : * Es erfolgt ein SetBase() !
289 : : *************************************************************************/
290 : : // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
291 : 562 : SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm,
292 : : SwFlyInCntFrm *pFly, const Point &rBase,
293 : : long nLnAscent, long nLnDescent,
294 : : long nFlyAsc, long nFlyDesc,
295 : : objectpositioning::AsCharFlags nFlags ) :
296 : : pContact( pFly ),
297 : : bDraw( sal_False ),
298 : : bMax( sal_False ),
299 : 562 : nAlign( 0 )
300 : : {
301 : : OSL_ENSURE( pFly, "SwFlyCntPortion::SwFlyCntPortion: no SwFlyInCntFrm!" );
302 : 562 : nLineLength = 1;
303 : 562 : nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT;
304 [ + - ]: 562 : SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags );
305 : 562 : SetWhichPor( POR_FLYCNT );
306 : 562 : }
307 : :
308 : : // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
309 : 728 : SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm,
310 : : SwDrawContact *pDrawContact, const Point &rBase,
311 : : long nLnAscent, long nLnDescent,
312 : : long nFlyAsc, long nFlyDesc,
313 : : objectpositioning::AsCharFlags nFlags ) :
314 : : pContact( pDrawContact ),
315 : : bDraw( sal_True ),
316 : : bMax( sal_False ),
317 : 728 : nAlign( 0 )
318 : : {
319 : : OSL_ENSURE( pDrawContact, "SwFlyCntPortion::SwFlyCntPortion: no SwDrawContact!" );
320 [ + + ][ + - ]: 728 : if( !pDrawContact->GetAnchorFrm() )
321 : : {
322 : : // OD 2004-04-01 #i26791# - no direct positioning needed any more
323 [ + - ]: 12 : pDrawContact->ConnectToLayout();
324 : : // #i40333# - follow-up of #i35635#
325 : : // move object to visible layer
326 [ + - ][ + - ]: 12 : pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
327 : : }
328 : 728 : nLineLength = 1;
329 : 728 : nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT;
330 : :
331 [ + - ]: 728 : SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags );
332 : :
333 : 728 : SetWhichPor( POR_FLYCNT );
334 : 728 : }
335 : :
336 : :
337 : : /*************************************************************************
338 : : * SwFlyCntPortion::SetBase()
339 : : *
340 : : * Nach dem Setzen des RefPoints muss der Ascent neu berechnet werden,
341 : : * da er von der RelPos abhaengt.
342 : : * pFly->GetRelPos().Y() bezeichnet die relative Position zur Baseline.
343 : : * Bei 0 liegt der obere Rand des FlyCnt auf der Baseline der Zeile.
344 : : *************************************************************************/
345 : : // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
346 : 4187 : void SwFlyCntPortion::SetBase( const SwTxtFrm& rFrm, const Point &rBase,
347 : : long nLnAscent, long nLnDescent,
348 : : long nFlyAsc, long nFlyDesc,
349 : : objectpositioning::AsCharFlags nFlags )
350 : : {
351 : : // Note: rBase have to be an absolute value
352 : :
353 : : // OD 28.10.2003 #113049# - use new class to position object
354 : : // determine drawing object
355 : 4187 : SdrObject* pSdrObj = 0L;
356 [ + + ]: 4187 : if( bDraw )
357 : : {
358 : : // OD 20.06.2003 #108784# - determine drawing object ('master' or 'virtual')
359 : : // by frame.
360 [ + - ]: 2175 : pSdrObj = GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm );
361 [ - + ]: 2175 : if ( !pSdrObj )
362 : : {
363 : : OSL_FAIL( "SwFlyCntPortion::SetBase(..) - No drawing object found by <GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm )>" );
364 [ # # ]: 0 : pSdrObj = GetDrawContact()->GetMaster();
365 : : }
366 : : // #i65798#
367 : : // call <SwAnchoredDrawObject::MakeObjPos()> to assure that flag at
368 : : // the <DrawFrmFmt> and at the <SwAnchoredDrawObject> instance are
369 : : // correctly set.
370 [ + - ]: 2175 : if ( pSdrObj )
371 : : {
372 [ + - ][ + - ]: 2175 : GetDrawContact()->GetAnchoredObj( pSdrObj )->MakeObjPos();
373 : : }
374 : : }
375 : : else
376 : : {
377 [ + - ]: 2012 : pSdrObj = GetFlyFrm()->GetVirtDrawObj();
378 : : }
379 : :
380 : : // position object
381 : : objectpositioning::SwAsCharAnchoredObjectPosition aObjPositioning(
382 : : *pSdrObj,
383 : : rBase, nFlags,
384 [ + - ]: 4187 : nLnAscent, nLnDescent, nFlyAsc, nFlyDesc );
385 : :
386 : : // OD 2004-04-13 #i26791# - scope of local variable <aObjPosInProgress>
387 : : {
388 : : // OD 2004-04-13 #i26791#
389 [ + - ]: 4187 : SwObjPositioningInProgress aObjPosInProgress( *pSdrObj );
390 [ + - ][ + - ]: 4187 : aObjPositioning.CalcPosition();
391 : : }
392 : :
393 [ + - ]: 4187 : SetAlign( aObjPositioning.GetLineAlignment() );
394 : :
395 [ + - ]: 4187 : aRef = aObjPositioning.GetAnchorPos();
396 [ - + ]: 4187 : if( nFlags & AS_CHAR_ROTATE )
397 [ # # ]: 0 : SvXSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
398 : : else
399 [ + - ]: 4187 : SvLSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
400 [ + - ]: 4187 : if( Height() )
401 : : {
402 [ + - ]: 4187 : SwTwips nRelPos = aObjPositioning.GetRelPosY();
403 [ + + ]: 4187 : if ( nRelPos < 0 )
404 : : {
405 : 2048 : nAscent = static_cast<sal_uInt16>(-nRelPos);
406 [ - + ]: 2048 : if( nAscent > Height() )
407 : 0 : Height( nAscent );
408 : : }
409 : : else
410 : : {
411 : 2139 : nAscent = 0;
412 : 2139 : Height( Height() + static_cast<sal_uInt16>(nRelPos) );
413 : : }
414 : : }
415 : : else
416 : : {
417 : 0 : Height( 1 );
418 : 0 : nAscent = 0;
419 [ + - ]: 4187 : }
420 : 4187 : }
421 : :
422 : : /*************************************************************************
423 : : * virtual SwFlyCntPortion::GetFlyCrsrOfst()
424 : : *************************************************************************/
425 : :
426 : 0 : xub_StrLen SwFlyCntPortion::GetFlyCrsrOfst( const KSHORT nOfst,
427 : : const Point &rPoint, SwPosition *pPos, SwCrsrMoveState* pCMS ) const
428 : : {
429 : : // Da die FlyCnt nicht an der Seite haengen, wird ihr
430 : : // GetCrsrOfst() nicht gerufen. Um die Layoutseite
431 : : // von unnoetiger Verwaltung zu entlasten, ruft der Absatz
432 : : // das GetCrsrOfst des FlyFrm, wenn es erforderlich ist.
433 : 0 : Point aPoint( rPoint );
434 [ # # ][ # # ]: 0 : if( !pPos || bDraw || !( GetFlyFrm()->GetCrsrOfst( pPos, aPoint, pCMS ) ) )
[ # # ][ # # ]
[ # # ]
435 [ # # ]: 0 : return SwLinePortion::GetCrsrOfst( nOfst );
436 : : else
437 : 0 : return 0;
438 : : }
439 : :
440 : : /*************************************************************************
441 : : * virtual SwFlyCntPortion::GetCrsrOfst()
442 : : *************************************************************************/
443 : :
444 : 62 : xub_StrLen SwFlyCntPortion::GetCrsrOfst( const KSHORT nOfst ) const
445 : : {
446 : : // OSL_ENSURE( !this, "SwFlyCntPortion::GetCrsrOfst: use GetFlyCrsrOfst()" );
447 : 62 : return SwLinePortion::GetCrsrOfst( nOfst );
448 : : }
449 : :
450 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|