xref: /trunk/main/sw/source/core/doc/docdraw.cxx (revision cdf0e10c)
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 #include <hintids.hxx>
32 #include <rtl/logfile.hxx>
33 #include <vcl/outdev.hxx>
34 #include <sfx2/printer.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/flditem.hxx>
37 #include <editeng/editeng.hxx>
38 #include <svx/svdoutl.hxx>
39 #include <editeng/colritem.hxx>
40 #include <svx/svdpage.hxx>
41 #include <svx/svdogrp.hxx>
42 #include <editeng/langitem.hxx>
43 #include <editeng/unolingu.hxx>
44 #include <editeng/measfld.hxx>
45 #include <svx/svdpool.hxx>
46 #include <fmtanchr.hxx>
47 #include <charatr.hxx>
48 #include <frmfmt.hxx>
49 #include <charfmt.hxx>
50 #include <viewimp.hxx>
51 #include <swhints.hxx>
52 #include <doc.hxx>
53 #include <IDocumentUndoRedo.hxx>
54 #include <docsh.hxx>
55 #include <rootfrm.hxx>	//Damit der RootDtor gerufen wird.
56 #include <poolfmt.hxx>
57 #include <viewsh.hxx>           // fuer MakeDrawView
58 #include <drawdoc.hxx>
59 #include <UndoDraw.hxx>
60 #include <swundo.hxx>			// fuer die UndoIds
61 #include <dcontact.hxx>
62 #include <dview.hxx>
63 #include <mvsave.hxx>
64 #include <flyfrm.hxx>
65 #include <dflyobj.hxx>
66 #include <svx/svdetc.hxx>
67 #include <editeng/fhgtitem.hxx>
68 #include <svx/svdpagv.hxx>
69 #include <dcontact.hxx>
70 #include <txtfrm.hxx>
71 #include <frmfmt.hxx>
72 #include <editeng/frmdiritem.hxx>
73 #include <fmtornt.hxx>
74 #include <svx/svditer.hxx>
75 #include <vector>
76 #include <switerator.hxx>
77 
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::linguistic2;
80 
81 
82 SV_IMPL_VARARR_SORT( _ZSortFlys, _ZSortFly )
83 
84 /*************************************************************************
85 |*
86 |*	SwDoc::GroupSelection / SwDoc::UnGroupSelection
87 |*
88 |*	Ersterstellung		JP 21.08.95
89 |*	Letzte Aenderung	JP 21.08.95
90 |*
91 |*************************************************************************/
92 // OD 2004-04-01 #i26791# - local method to determine positioning and
93 // alignment attributes for a drawing object, which is newly connected to
94 // the layout. Used for a newly formed group object <SwDoc::GroupSelection(..)>
95 // and the members of a destroyed group <SwDoc::UnGroupSelection(..)>
96 void lcl_AdjustPositioningAttr( SwDrawFrmFmt* _pFrmFmt,
97                                 const SdrObject& _rSdrObj )
98 {
99     const SwContact* pContact = GetUserCall( &_rSdrObj );
100     ASSERT( pContact, "<lcl_AdjustPositioningAttr(..)> - missing contact object." );
101 
102     // determine position of new group object relative to its anchor frame position
103     SwTwips nHoriRelPos = 0;
104     SwTwips nVertRelPos = 0;
105     {
106         const SwFrm* pAnchorFrm = pContact->GetAnchoredObj( &_rSdrObj )->GetAnchorFrm();
107         ASSERT( !pAnchorFrm ||
108                 !pAnchorFrm->IsTxtFrm() ||
109                 !static_cast<const SwTxtFrm*>(pAnchorFrm)->IsFollow(),
110                 "<lcl_AdjustPositioningAttr(..)> - anchor frame is a follow. Please inform OD." );
111         bool bVert = false;
112         bool bR2L = false;
113         // --> OD 2005-05-10 #i45952# - use anchor position of
114         // anchor frame, if it exist.
115         Point aAnchorPos;
116         if ( pAnchorFrm )
117         {
118             // --> OD 2005-05-10 #i45952#
119             aAnchorPos = pAnchorFrm->GetFrmAnchorPos( ::HasWrap( &_rSdrObj ) );
120             // <--
121             bVert = pAnchorFrm->IsVertical();
122             bR2L = pAnchorFrm->IsRightToLeft();
123         }
124         else
125         {
126             // --> OD 2005-05-10 #i45952#
127             aAnchorPos = _rSdrObj.GetAnchorPos();
128             // <--
129             // If no anchor frame exist - e.g. because no layout exists - the
130             // default layout direction is taken.
131             const SvxFrameDirectionItem* pDirItem =
132                 static_cast<const SvxFrameDirectionItem*>(&(_pFrmFmt->GetAttrSet().GetPool()->GetDefaultItem( RES_FRAMEDIR )));
133             switch ( pDirItem->GetValue() )
134             {
135                 case FRMDIR_VERT_TOP_LEFT:
136                 {
137                     // vertical from left-to-right - Badaa: supported now!
138                     bVert = true;
139                     bR2L = true;
140                     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
141                     //ASSERT( false, "<lcl_AdjustPositioningAttr(..)> - vertical from left-to-right not supported." );
142                     //End
143                 }
144                 break;
145                 case FRMDIR_VERT_TOP_RIGHT:
146                 {
147                     // vertical from right-to-left
148                     bVert = true;
149                     bR2L = false;
150                 }
151                 break;
152                 case FRMDIR_HORI_RIGHT_TOP:
153                 {
154                     // horizontal from right-to-left
155                     bVert = false;
156                     bR2L = true;
157                 }
158                 break;
159                 case FRMDIR_HORI_LEFT_TOP:
160                 {
161                     // horizontal from left-to-right
162                     bVert = false;
163                     bR2L = false;
164                 }
165                 break;
166             }
167 
168         }
169         // use geometry of drawing object
170         const SwRect aObjRect = _rSdrObj.GetSnapRect();
171 
172         if ( bVert )
173         {
174             if ( bR2L ) {
175 			  	//FRMDIR_VERT_TOP_LEFT
176 			  	nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
177 			  	nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
178 			} else {
179 				//FRMDIR_VERT_TOP_RIGHT
180 				nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
181             	nVertRelPos = aAnchorPos.X() - aObjRect.Right();
182 			}
183         }
184         else if ( bR2L )
185         {
186             nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
187             nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
188         }
189         else
190         {
191             nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
192             nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
193         }
194         //End of SCMS
195     }
196 
197     _pFrmFmt->SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
198     _pFrmFmt->SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
199     // --> OD 2005-03-11 #i44334#, #i44681# - positioning attributes already set
200     _pFrmFmt->PosAttrSet();
201     // <--
202     // --> OD 2004-10-01 #i34750# - keep current object rectangle for  drawing
203     // objects. The object rectangle is used on events from the drawing layer
204     // to adjust the positioning attributes - see <SwDrawContact::_Changed(..)>.
205     {
206         const SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( &_rSdrObj );
207         if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
208         {
209             const SwAnchoredDrawObject* pAnchoredDrawObj =
210                             static_cast<const SwAnchoredDrawObject*>(pAnchoredObj);
211             const SwRect aObjRect = _rSdrObj.GetSnapRect();
212             const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
213                                         ->SetLastObjRect( aObjRect.SVRect() );
214         }
215     }
216     // <--
217 }
218 
219 SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
220 {
221     // OD 30.06.2003 #108784# - replace marked 'virtual' drawing objects by
222     // the corresponding 'master' drawing objects.
223     SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
224 
225     const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
226 	SwDrawFrmFmt *pFmt = 0L;
227 	SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
228 	sal_Bool bNoGroup = ( 0 == pObj->GetUpGroup() );
229     SwDrawContact* pNewContact = 0;
230 	if( bNoGroup )
231 	{
232 		//Ankerattribut aufheben.
233 		SwDrawContact *pMyContact = (SwDrawContact*)GetUserCall(pObj);
234 		const SwFmtAnchor aAnch( pMyContact->GetFmt()->GetAnchor() );
235 
236         SwUndoDrawGroup *const pUndo = (!GetIDocumentUndoRedo().DoesUndo())
237                                  ? 0
238                                  : new SwUndoDrawGroup( (sal_uInt16)rMrkList.GetMarkCount() );
239 
240         // --> OD 2005-08-16 #i53320#
241         bool bGroupMembersNotPositioned( false );
242         {
243             SwAnchoredDrawObject* pAnchoredDrawObj =
244                 static_cast<SwAnchoredDrawObject*>(pMyContact->GetAnchoredObj( pObj ));
245             bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned();
246         }
247         // <--
248 		//ContactObjekte und Formate vernichten.
249 		for( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
250 		{
251 			pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
252 			SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
253 
254             // --> OD 2005-08-16 #i53320#
255 #ifdef DBG_UTIL
256             SwAnchoredDrawObject* pAnchoredDrawObj =
257                 static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ));
258             ASSERT( bGroupMembersNotPositioned == pAnchoredDrawObj->NotYetPositioned(),
259                     "<SwDoc::GroupSelection(..)> - group members have different positioning status!" );
260 #endif
261             // <--
262 
263             pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
264 			//loescht sich selbst!
265 			pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
266 			pObj->SetUserCall( 0 );
267 
268 			if( pUndo )
269 				pUndo->AddObj( i, pFmt, pObj );
270 			else
271 				DelFrmFmt( pFmt );
272 
273             // --> OD 2005-05-10 #i45952# - re-introduce position
274             // normalization of group member objects, because its anchor position
275             // is cleared, when they are grouped.
276             Point aAnchorPos( pObj->GetAnchorPos() );
277             pObj->NbcSetAnchorPos( Point( 0, 0 ) );
278             pObj->NbcMove( Size( aAnchorPos.X(), aAnchorPos.Y() ) );
279             // <--
280         }
281 
282 		pFmt = MakeDrawFrmFmt( String::CreateFromAscii(
283 								RTL_CONSTASCII_STRINGPARAM( "DrawObject" )),
284 								GetDfltFrmFmt() );
285         pFmt->SetFmtAttr( aAnch );
286         // --> OD 2004-10-25 #i36010# - set layout direction of the position
287         pFmt->SetPositionLayoutDir(
288             text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
289         // <--
290 
291         rDrawView.GroupMarked();
292         ASSERT( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
293 
294         SdrObject* pNewGroupObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
295         pNewContact = new SwDrawContact( pFmt, pNewGroupObj );
296         // --> OD 2004-11-22 #i35635#
297         pNewContact->MoveObjToVisibleLayer( pNewGroupObj );
298         // <--
299         pNewContact->ConnectToLayout();
300         // --> OD 2005-08-16 #i53320# - No adjustment of the positioning and
301         // alignment attributes, if group members aren't positioned yet.
302         if ( !bGroupMembersNotPositioned )
303         {
304             // OD 2004-04-01 #i26791# - Adjust positioning and alignment attributes.
305             lcl_AdjustPositioningAttr( pFmt, *pNewGroupObj );
306         }
307         // <--
308 
309         if( pUndo )
310 		{
311 			pUndo->SetGroupFmt( pFmt );
312             GetIDocumentUndoRedo().AppendUndo( pUndo );
313         }
314     }
315     else
316     {
317         if (GetIDocumentUndoRedo().DoesUndo())
318         {
319             GetIDocumentUndoRedo().ClearRedo();
320         }
321 
322         rDrawView.GroupMarked();
323         ASSERT( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
324     }
325 
326 	return pNewContact;
327 }
328 
329 
330 void SwDoc::UnGroupSelection( SdrView& rDrawView )
331 {
332     bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
333 	if( bUndo )
334     {
335         GetIDocumentUndoRedo().ClearRedo();
336     }
337 
338     // OD 30.06.2003 #108784# - replace marked 'virtual' drawing objects by
339     // the corresponding 'master' drawing objects.
340     SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
341 
342     const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
343     // --> OD 2006-11-01 #130889#
344     std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >* pFmtsAndObjs( 0L );
345     const sal_uInt32 nMarkCount( rMrkList.GetMarkCount() );
346     // <--
347     if ( nMarkCount )
348 	{
349         // --> OD 2006-11-01 #130889#
350         pFmtsAndObjs = new std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >[nMarkCount];
351         // <--
352 		SdrObject *pMyObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
353 		if( !pMyObj->GetUpGroup() )
354 		{
355 			String sDrwFmtNm( String::CreateFromAscii(
356 								RTL_CONSTASCII_STRINGPARAM("DrawObject" )));
357             for ( sal_uInt16 i = 0; i < nMarkCount; ++i )
358 			{
359 				SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
360 				if ( pObj->IsA( TYPE(SdrObjGroup) ) )
361 				{
362 					SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
363 					SwFmtAnchor aAnch( pContact->GetFmt()->GetAnchor() );
364 					SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
365 
366 					SwUndoDrawUnGroup* pUndo = 0;
367 					if( bUndo )
368 					{
369 						pUndo = new SwUndoDrawUnGroup( (SdrObjGroup*)pObj );
370                         GetIDocumentUndoRedo().AppendUndo(pUndo);
371                     }
372 
373 					for ( sal_uInt16 i2 = 0; i2 < pLst->GetObjCount(); ++i2 )
374 					{
375                         SdrObject* pSubObj = pLst->GetObj( i2 );
376 						SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( sDrwFmtNm,
377 															GetDfltFrmFmt() );
378                         pFmt->SetFmtAttr( aAnch );
379                         // --> OD 2004-10-25 #i36010# - set layout direction of the position
380                         pFmt->SetPositionLayoutDir(
381                             text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
382                         // <--
383                         // --> OD 2006-11-01 #130889#
384                         // creation of <SwDrawContact> instances for the group
385                         // members and its connection to the Writer layout is
386                         // done after intrinsic ungrouping.
387 //                        SwDrawContact* pContact = new SwDrawContact( pFmt, pSubObj );
388 //                        // --> OD 2004-11-22 #i35635#
389 //                        pContact->MoveObjToVisibleLayer( pSubObj );
390 //                        // <--
391 //                        pContact->ConnectToLayout();
392 //                        // OD 2004-04-07 #i26791# - Adjust positioning and
393 //                        // alignment attributes.
394 //                        lcl_AdjustPositioningAttr( pFmt, *pSubObj );
395                         pFmtsAndObjs[i].push_back( std::pair< SwDrawFrmFmt*, SdrObject* >( pFmt, pSubObj ) );
396                         // <--
397 
398 						if( bUndo )
399 							pUndo->AddObj( i2, pFmt );
400 					}
401 				}
402 			}
403 		}
404 	}
405 	rDrawView.UnGroupMarked();
406     // --> OD 2006-11-01 #130889#
407     // creation of <SwDrawContact> instances for the former group members and
408     // its connection to the Writer layout.
409     for ( sal_uInt32 i = 0; i < nMarkCount; ++i )
410     {
411         SwUndoDrawUnGroupConnectToLayout* pUndo = 0;
412         if( bUndo )
413         {
414             pUndo = new SwUndoDrawUnGroupConnectToLayout();
415             GetIDocumentUndoRedo().AppendUndo(pUndo);
416         }
417 
418         while ( pFmtsAndObjs[i].size() > 0 )
419         {
420             SwDrawFrmFmt* pFmt( pFmtsAndObjs[i].back().first );
421             SdrObject* pObj( pFmtsAndObjs[i].back().second );
422             pFmtsAndObjs[i].pop_back();
423 
424             SwDrawContact* pContact = new SwDrawContact( pFmt, pObj );
425             pContact->MoveObjToVisibleLayer( pObj );
426             pContact->ConnectToLayout();
427             lcl_AdjustPositioningAttr( pFmt, *pObj );
428 
429             if ( bUndo )
430             {
431                 pUndo->AddFmtAndObj( pFmt, pObj );
432             }
433         }
434     }
435     delete [] pFmtsAndObjs;
436     // <--
437 }
438 
439 /*************************************************************************
440 |*
441 |*	SwDoc::DeleteSelection()
442 |*
443 |*	Ersterstellung		MA 14. Nov. 95
444 |*	Letzte Aenderung	MA 14. Nov. 95
445 |*
446 |*************************************************************************/
447 
448 sal_Bool SwDoc::DeleteSelection( SwDrawView& rDrawView )
449 {
450 	sal_Bool bCallBase = sal_False;
451 	const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
452 	if( rMrkList.GetMarkCount() )
453 	{
454         GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
455 		sal_uInt16 i;
456 		sal_Bool bDelMarked = sal_True;
457 
458 		if( 1 == rMrkList.GetMarkCount() )
459 		{
460 			SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
461 			if( pObj->ISA(SwVirtFlyDrawObj) )
462 			{
463 				SwFlyFrmFmt* pFrmFmt = (SwFlyFrmFmt*)
464 					((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
465 				if( pFrmFmt )
466 				{
467 					DelLayoutFmt( pFrmFmt );
468 					bDelMarked = sal_False;
469 				}
470 			}
471 		}
472 
473 		for( i = 0; i < rMrkList.GetMarkCount(); ++i )
474 		{
475 			SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
476 			if( !pObj->ISA(SwVirtFlyDrawObj) )
477 			{
478 				SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
479 				SwDrawFrmFmt *pFrmFmt = (SwDrawFrmFmt*)pC->GetFmt();
480 				if( pFrmFmt &&
481                     FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
482 				{
483 					rDrawView.MarkObj( pObj, rDrawView.Imp().GetPageView(), sal_True );
484 					--i;
485 					DelLayoutFmt( pFrmFmt );
486 				}
487 			}
488 		}
489 
490 		if( rMrkList.GetMarkCount() && bDelMarked )
491 		{
492 			SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
493 			if( !pObj->GetUpGroup() )
494 			{
495                 SwUndoDrawDelete *const pUndo =
496                     (!GetIDocumentUndoRedo().DoesUndo())
497                         ? 0
498 							: new SwUndoDrawDelete(	(sal_uInt16)rMrkList.GetMarkCount() );
499 
500                 //ContactObjekte vernichten, Formate sicherstellen.
501 				for( i = 0; i < rMrkList.GetMarkCount(); ++i )
502 				{
503                     const SdrMark& rMark = *rMrkList.GetMark( i );
504 					pObj = rMark.GetMarkedSdrObj();
505 					SwDrawContact *pContact = (SwDrawContact*)pObj->GetUserCall();
506 					if( pContact ) // natuerlich nicht bei gruppierten Objekten
507 					{
508 						SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
509                         // OD 18.06.2003 #108784# - before delete of selection
510                         // is performed, marked <SwDrawVirtObj>-objects have to
511                         // be replaced by its reference objects.
512                         // Thus, assert, if a <SwDrawVirt>-object is found in the mark list.
513                         if ( pObj->ISA(SwDrawVirtObj) )
514                         {
515                             ASSERT( false,
516                                     "<SwDrawVirtObj> is still marked for delete. application will crash!" );
517                         }
518                         //loescht sich selbst!
519                         pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
520                         pObj->SetUserCall( 0 );
521 
522 						if( pUndo )
523 							pUndo->AddObj( i, pFmt, rMark );
524 						else
525 							DelFrmFmt( pFmt );
526 					}
527 				}
528 
529 				if( pUndo )
530                 {
531                     GetIDocumentUndoRedo().AppendUndo( pUndo );
532                 }
533             }
534 			bCallBase = sal_True;
535 		}
536 		SetModified();
537 
538         GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
539     }
540 
541 	return bCallBase;
542 }
543 
544 /*************************************************************************
545 |*
546 |*	SwDoc::DeleteSelection()
547 |*
548 |*	Ersterstellung		JP 11.01.96
549 |*	Letzte Aenderung	JP 11.01.96
550 |*
551 |*************************************************************************/
552 
553 _ZSortFly::_ZSortFly( const SwFrmFmt* pFrmFmt, const SwFmtAnchor* pFlyAn,
554 					  sal_uInt32 nArrOrdNum )
555 	: pFmt( pFrmFmt ), pAnchor( pFlyAn ), nOrdNum( nArrOrdNum )
556 {
557 	// #i11176#
558 	// This also needs to work when no layout exists. Thus, for
559 	// FlyFrames an alternative method is used now in that case.
560 	if( RES_FLYFRMFMT == pFmt->Which() )
561 	{
562         if( pFmt->getIDocumentLayoutAccess()->GetCurrentViewShell() )	//swmod 071107//swmod 071225
563 		{
564 			// Schauen, ob es ein SdrObject dafuer gibt
565             SwFlyFrm* pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *pFrmFmt );
566 			if( pFly )
567 				nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
568 		}
569 		else
570 		{
571 			// Schauen, ob es ein SdrObject dafuer gibt
572             SwFlyDrawContact* pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *pFrmFmt );
573 			if( pContact )
574 				nOrdNum = pContact->GetMaster()->GetOrdNum();
575 		}
576 	}
577 	else if( RES_DRAWFRMFMT == pFmt->Which() )
578 	{
579 		// Schauen, ob es ein SdrObject dafuer gibt
580             SwDrawContact* pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFrmFmt );
581 			if( pContact )
582 				nOrdNum = pContact->GetMaster()->GetOrdNum();
583 	}
584 	else {
585 		ASSERT( !this, "was ist das fuer ein Format?" );
586     }
587 }
588 
589 /*************************************************************************/
590 // Wird auch vom Sw3-Reader gerufen, wenn ein Fehler beim Einlesen
591 // des Drawing Layers auftrat. In diesem Fall wird der Layer komplett
592 // neu aufgebaut.
593 
594 // #75371#
595 #include <svx/sxenditm.hxx>
596 
597 void SwDoc::InitDrawModel()
598 {
599 	RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722",  "SwDoc::InitDrawModel" );
600 
601 	//!!Achtung im sw3-Reader (sw3imp.cxx) gibt es aehnlichen Code, der
602 	//mitgepfelgt werden muss.
603 	if ( pDrawModel )
604 		ReleaseDrawModel();
605 
606 	//DrawPool und EditEnginePool anlegen, diese gehoeren uns und werden
607 	//dem Drawing nur mitgegeben. Im ReleaseDrawModel werden die Pools wieder
608 	//zerstoert.
609 	// 17.2.99: for Bug 73110 - for loading the drawing items. This must
610 	//							be loaded without RefCounts!
611 	SfxItemPool *pSdrPool = new SdrItemPool( &GetAttrPool() );
612 	// #75371# change DefaultItems for the SdrEdgeObj distance items
613 	// to TWIPS.
614 	if(pSdrPool)
615 	{
616 		const long nDefEdgeDist = ((500 * 72) / 127); // 1/100th mm in twips
617 		pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
618 		pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
619 		pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
620 		pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
621 
622 		// #i33700#
623 		// Set shadow distance defaults as PoolDefaultItems. Details see bug.
624 		pSdrPool->SetPoolDefaultItem(SdrShadowXDistItem((300 * 72) / 127));
625 		pSdrPool->SetPoolDefaultItem(SdrShadowYDistItem((300 * 72) / 127));
626 	}
627 	SfxItemPool *pEEgPool = EditEngine::CreatePool( sal_False );
628 	pSdrPool->SetSecondaryPool( pEEgPool );
629  	if ( !GetAttrPool().GetFrozenIdRanges () )
630 		GetAttrPool().FreezeIdRanges();
631 	else
632 		pSdrPool->FreezeIdRanges();
633 
634     // SJ: #95129# set FontHeight pool defaults without changing static SdrEngineDefaults
635  	GetAttrPool().SetPoolDefaultItem(SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ));
636 
637 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create DrawDocument" );
638 	//Das SdrModel gehoert dem Dokument, wir haben immer zwei Layer und eine
639 	//Seite.
640 	pDrawModel = new SwDrawDocument( this );
641 
642     pDrawModel->EnableUndo( GetIDocumentUndoRedo().DoesUndo() );
643 
644 	String sLayerNm;
645 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Hell" ));
646 	nHell	= pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
647 
648 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Heaven" ));
649 	nHeaven	= pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
650 
651 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Controls" ));
652 	nControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
653 
654     // OD 25.06.2003 #108784# - add invisible layers corresponding to the
655     // visible ones.
656     {
657         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
658         nInvisibleHell   = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
659 
660         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
661         nInvisibleHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
662 
663         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
664         nInvisibleControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
665     }
666 
667     SdrPage* pMasterPage = pDrawModel->AllocPage( sal_False );
668 	pDrawModel->InsertPage( pMasterPage );
669 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create DrawDocument" );
670 
671 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create Spellchecker/Hyphenator" );
672 	SdrOutliner& rOutliner = pDrawModel->GetDrawOutliner();
673 	uno::Reference< XSpellChecker1 > xSpell = ::GetSpellChecker();
674 	rOutliner.SetSpeller( xSpell );
675     uno::Reference<XHyphenator> xHyphenator( ::GetHyphenator() );
676 	rOutliner.SetHyphenator( xHyphenator );
677 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create Spellchecker/Hyphenator" );
678 
679 	SetCalcFieldValueHdl(&rOutliner);
680 	SetCalcFieldValueHdl(&pDrawModel->GetHitTestOutliner());
681 
682 	//JP 16.07.98: Bug 50193 - Linkmanager am Model setzen, damit
683 	//			dort ggfs. verlinkte Grafiken eingefuegt werden koennen
684 	//JP 28.01.99: der WinWord Import benoetigt ihn auch
685 	pDrawModel->SetLinkManager( &GetLinkManager() );
686     pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
687 
688     OutputDevice* pRefDev = getReferenceDevice( false );
689     if ( pRefDev )
690         pDrawModel->SetRefDevice( pRefDev );
691 
692     pDrawModel->SetNotifyUndoActionHdl( LINK( this, SwDoc, AddDrawUndo ));
693 	if ( pCurrentView )
694 	{
695         ViewShell* pViewSh = pCurrentView;
696         do
697         {
698             SwRootFrm* pRoot =  pViewSh->GetLayout();
699             if( pRoot && !pRoot->GetDrawPage() )
700             {
701                 // Disable "multiple layout" for the moment:
702                 // use pMasterPage instead of a new created SdrPage
703                 // pDrawModel->AllocPage( FALSE );
704                 // pDrawModel->InsertPage( pDrawPage );
705                 SdrPage* pDrawPage = pMasterPage;
706                 pRoot->SetDrawPage( pDrawPage );
707                 pDrawPage->SetSize( pRoot->Frm().SSize() );
708             }
709             pViewSh = (ViewShell*)pViewSh->GetNext();
710         }while( pViewSh != pCurrentView );
711 	}
712 
713 	UpdateDrawDefaults();
714 }
715 
716 /** method to notify drawing page view about the invisible layers
717 
718     OD 26.06.2003 #108784#
719 
720     @author OD
721 */
722 void SwDoc::NotifyInvisibleLayers( SdrPageView& _rSdrPageView )
723 {
724     String sLayerNm;
725     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
726     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
727 
728     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
729     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
730 
731     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
732     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
733 }
734 
735 /** method to determine, if a layer ID belongs to the visible ones.
736 
737     OD 25.06.2003 #108784#
738     Note: If given layer ID is unknown, method asserts and returns <false>.
739 
740     @author OD
741 */
742 bool SwDoc::IsVisibleLayerId( const SdrLayerID& _nLayerId ) const
743 {
744     bool bRetVal;
745 
746     if ( _nLayerId == GetHeavenId() ||
747          _nLayerId == GetHellId() ||
748          _nLayerId == GetControlsId() )
749     {
750         bRetVal = true;
751     }
752     else if ( _nLayerId == GetInvisibleHeavenId() ||
753               _nLayerId == GetInvisibleHellId() ||
754               _nLayerId == GetInvisibleControlsId() )
755     {
756         bRetVal = false;
757     }
758     else
759     {
760         ASSERT( false, "<SwDoc::IsVisibleLayerId(..)> - unknown layer ID." );
761         bRetVal = false;
762     }
763 
764     return bRetVal;
765 }
766 
767 /** method to determine, if the corresponding visible layer ID for a invisible one.
768 
769     OD 25.06.2003 #108784#
770     Note: If given layer ID is a visible one, method returns given layer ID.
771     Note: If given layer ID is unknown, method returns given layer ID.
772 
773     @author OD
774 */
775 SdrLayerID SwDoc::GetVisibleLayerIdByInvisibleOne( const SdrLayerID& _nInvisibleLayerId )
776 {
777     SdrLayerID nVisibleLayerId;
778 
779     if ( _nInvisibleLayerId == GetInvisibleHeavenId() )
780     {
781         nVisibleLayerId = GetHeavenId();
782     }
783     else if ( _nInvisibleLayerId == GetInvisibleHellId() )
784     {
785         nVisibleLayerId = GetHellId();
786     }
787     else if ( _nInvisibleLayerId == GetInvisibleControlsId() )
788     {
789         nVisibleLayerId = GetControlsId();
790     }
791     else if ( _nInvisibleLayerId == GetHeavenId() ||
792               _nInvisibleLayerId == GetHellId() ||
793               _nInvisibleLayerId == GetControlsId() )
794     {
795         ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID already an invisible one." );
796         nVisibleLayerId = _nInvisibleLayerId;
797     }
798     else
799     {
800         ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID is unknown." );
801         nVisibleLayerId = _nInvisibleLayerId;
802     }
803 
804     return nVisibleLayerId;
805 }
806 
807 /** method to determine, if the corresponding invisible layer ID for a visible one.
808 
809     OD 25.06.2003 #108784#
810     Note: If given layer ID is a invisible one, method returns given layer ID.
811     Note: If given layer ID is unknown, method returns given layer ID.
812 
813     @author OD
814 */
815 SdrLayerID SwDoc::GetInvisibleLayerIdByVisibleOne( const SdrLayerID& _nVisibleLayerId )
816 {
817     SdrLayerID nInvisibleLayerId;
818 
819     if ( _nVisibleLayerId == GetHeavenId() )
820     {
821         nInvisibleLayerId = GetInvisibleHeavenId();
822     }
823     else if ( _nVisibleLayerId == GetHellId() )
824     {
825         nInvisibleLayerId = GetInvisibleHellId();
826     }
827     else if ( _nVisibleLayerId == GetControlsId() )
828     {
829         nInvisibleLayerId = GetInvisibleControlsId();
830     }
831     else if ( _nVisibleLayerId == GetInvisibleHeavenId() ||
832               _nVisibleLayerId == GetInvisibleHellId() ||
833               _nVisibleLayerId == GetInvisibleControlsId() )
834     {
835         ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID already an invisible one." );
836         nInvisibleLayerId = _nVisibleLayerId;
837     }
838     else
839     {
840         ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID is unknown." );
841         nInvisibleLayerId = _nVisibleLayerId;
842     }
843 
844     return nInvisibleLayerId;
845 }
846 
847 /*************************************************************************/
848 
849 
850 void SwDoc::ReleaseDrawModel()
851 {
852 	if ( pDrawModel )
853 	{
854 		//!!Den code im sw3io fuer Einfuegen Dokument mitpflegen!!
855 
856 		delete pDrawModel; pDrawModel = 0;
857 		SfxItemPool *pSdrPool = GetAttrPool().GetSecondaryPool();
858 
859 		ASSERT( pSdrPool, "missing Pool" );
860 		SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
861 		ASSERT( !pEEgPool->GetSecondaryPool(), "i don't accept additional pools");
862 		pSdrPool->Delete();					//Erst die Items vernichten lassen,
863 											//dann erst die Verkettung loesen
864 		GetAttrPool().SetSecondaryPool( 0 );	//Der ist ein muss!
865 		pSdrPool->SetSecondaryPool( 0 );	//Der ist sicherer
866 		SfxItemPool::Free(pSdrPool);
867 		SfxItemPool::Free(pEEgPool);
868 	}
869 }
870 
871 /*************************************************************************/
872 
873 
874 SdrModel* SwDoc::_MakeDrawModel()
875 {
876 	ASSERT( !pDrawModel, "_MakeDrawModel: Why?" );
877 	InitDrawModel();
878 	if ( pCurrentView )
879 	{
880 		ViewShell* pTmp = pCurrentView;
881 		do
882 		{
883 			pTmp->MakeDrawView();
884 			pTmp = (ViewShell*) pTmp->GetNext();
885 		} while ( pTmp != pCurrentView );
886 
887 		//Broadcast, damit die FormShell mit der DrawView verbunden werden kann
888 		if( GetDocShell() )
889 		{
890 			SfxSimpleHint aHnt( SW_BROADCAST_DRAWVIEWS_CREATED );
891 			GetDocShell()->Broadcast( aHnt );
892 		}
893 	}	//swmod 071029//swmod 071225
894 	return pDrawModel;
895 }
896 
897 /*************************************************************************/
898 
899 void SwDoc::DrawNotifyUndoHdl()
900 {
901 	pDrawModel->SetNotifyUndoActionHdl( Link() );
902 }
903 
904 /*************************************************************************
905 *
906 * Am Outliner Link auf Methode fuer Felddarstellung in Editobjekten setzen
907 *
908 *************************************************************************/
909 
910 void SwDoc::SetCalcFieldValueHdl(Outliner* pOutliner)
911 {
912 	pOutliner->SetCalcFieldValueHdl(LINK(this, SwDoc, CalcFieldValueHdl));
913 }
914 
915 /*************************************************************************
916 |*
917 |* Felder bzw URLs im Outliner erkennen und Darstellung festlegen
918 |*
919 \************************************************************************/
920 
921 IMPL_LINK(SwDoc, CalcFieldValueHdl, EditFieldInfo*, pInfo)
922 {
923 	if (pInfo)
924 	{
925 		const SvxFieldItem& rField = pInfo->GetField();
926 		const SvxFieldData* pField = rField.GetField();
927 
928 		if (pField && pField->ISA(SvxDateField))
929 		{
930 			/******************************************************************
931 			* Date-Field
932 			******************************************************************/
933 			pInfo->SetRepresentation(
934 				((const SvxDateField*) pField)->GetFormatted(
935 						*GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
936 		}
937 		else if (pField && pField->ISA(SvxURLField))
938 		{
939 			/******************************************************************
940 			* URL-Field
941 			******************************************************************/
942 
943 			switch ( ((const SvxURLField*) pField)->GetFormat() )
944 			{
945 				case SVXURLFORMAT_APPDEFAULT: //!!! einstellbar an App???
946 				case SVXURLFORMAT_REPR:
947 				{
948 					pInfo->SetRepresentation(
949 						((const SvxURLField*)pField)->GetRepresentation());
950 				}
951 				break;
952 
953 				case SVXURLFORMAT_URL:
954 				{
955 					pInfo->SetRepresentation(
956 						((const SvxURLField*)pField)->GetURL());
957 				}
958 				break;
959 			}
960 
961 			sal_uInt16 nChrFmt;
962 
963 			if (IsVisitedURL(((const SvxURLField*)pField)->GetURL()))
964 				nChrFmt = RES_POOLCHR_INET_VISIT;
965 			else
966 				nChrFmt = RES_POOLCHR_INET_NORMAL;
967 
968 			SwFmt *pFmt = GetCharFmtFromPool(nChrFmt);
969 
970 			Color aColor(COL_LIGHTBLUE);
971 			if (pFmt)
972 				aColor = pFmt->GetColor().GetValue();
973 
974 			pInfo->SetTxtColor(aColor);
975 		}
976 		else if (pField && pField->ISA(SdrMeasureField))
977 		{
978 			/******************************************************************
979 			* Measure-Field
980 			******************************************************************/
981 			pInfo->ClearFldColor();
982 		}
983         else if ( pField && pField->ISA(SvxExtTimeField))
984         {
985             /******************************************************************
986             * Time-Field
987             ******************************************************************/
988             pInfo->SetRepresentation(
989                 ((const SvxExtTimeField*) pField)->GetFormatted(
990                         *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
991         }
992 		else
993 		{
994 			DBG_ERROR("unbekannter Feldbefehl");
995 			pInfo->SetRepresentation( String( '?' ) );
996 		}
997 	}
998 
999 	return(0);
1000 }
1001 
1002 /* TFFDI: The functions formerly declared 'inline'
1003  */
1004 const SdrModel* SwDoc::GetDrawModel() const { return pDrawModel; }
1005 SdrModel* SwDoc::GetDrawModel() { return pDrawModel; }
1006 SdrLayerID SwDoc::GetHeavenId() const { return nHeaven; }
1007 SdrLayerID SwDoc::GetHellId() const { return nHell; }
1008 SdrLayerID SwDoc::GetControlsId() const { return nControls;   }
1009 SdrLayerID SwDoc::GetInvisibleHeavenId() const { return nInvisibleHeaven; }
1010 SdrLayerID SwDoc::GetInvisibleHellId() const { return nInvisibleHell; }
1011 SdrLayerID SwDoc::GetInvisibleControlsId() const { return nInvisibleControls; }
1012 SdrModel* SwDoc::GetOrCreateDrawModel() { return GetDrawModel() ? GetDrawModel() : _MakeDrawModel(); }
1013 
1014 // --> OD 2006-03-14 #i62875#
1015 namespace docfunc
1016 {
1017     bool ExistsDrawObjs( SwDoc& p_rDoc )
1018     {
1019         bool bExistsDrawObjs( false );
1020 
1021         if ( p_rDoc.GetDrawModel() &&
1022              p_rDoc.GetDrawModel()->GetPage( 0 ) )
1023         {
1024             const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
1025 
1026             SdrObjListIter aIter( rSdrPage, IM_FLAT );
1027             while( aIter.IsMore() )
1028             {
1029                 SdrObject* pObj( aIter.Next() );
1030                 if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
1031                      !dynamic_cast<SwFlyDrawObj*>(pObj) )
1032                 {
1033                     bExistsDrawObjs = true;
1034                     break;
1035                 }
1036             }
1037         }
1038 
1039         return bExistsDrawObjs;
1040     }
1041 
1042     bool AllDrawObjsOnPage( SwDoc& p_rDoc )
1043     {
1044         bool bAllDrawObjsOnPage( true );
1045 
1046         if ( p_rDoc.GetDrawModel() &&
1047              p_rDoc.GetDrawModel()->GetPage( 0 ) )
1048         {
1049             const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
1050 
1051             SdrObjListIter aIter( rSdrPage, IM_FLAT );
1052             while( aIter.IsMore() )
1053             {
1054                 SdrObject* pObj( aIter.Next() );
1055                 if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
1056                      !dynamic_cast<SwFlyDrawObj*>(pObj) )
1057                 {
1058                     SwDrawContact* pDrawContact =
1059                             dynamic_cast<SwDrawContact*>(::GetUserCall( pObj ));
1060                     if ( pDrawContact )
1061                     {
1062                         SwAnchoredDrawObject* pAnchoredDrawObj =
1063                             dynamic_cast<SwAnchoredDrawObject*>(pDrawContact->GetAnchoredObj( pObj ));
1064 
1065                         // error handling
1066                         {
1067                             if ( !pAnchoredDrawObj )
1068                             {
1069                                 ASSERT( false,
1070                                         "<docfunc::AllDrawObjsOnPage() - missing anchored draw object" );
1071                                 bAllDrawObjsOnPage = false;
1072                                 break;
1073                             }
1074                         }
1075 
1076                         if ( pAnchoredDrawObj->NotYetPositioned() )
1077                         {
1078                             // The drawing object isn't yet layouted.
1079                             // Thus, it isn't known, if all drawing objects are on page.
1080                             bAllDrawObjsOnPage = false;
1081                             break;
1082                         }
1083                         else if ( pAnchoredDrawObj->IsOutsidePage() )
1084                         {
1085                             bAllDrawObjsOnPage = false;
1086                             break;
1087                         }
1088                     }
1089                     else
1090                     {
1091                         // contact object of drawing object doesn't exists.
1092                         // Thus, the drawing object isn't yet positioned.
1093                         // Thus, it isn't known, if all drawing objects are on page.
1094                         bAllDrawObjsOnPage = false;
1095                         break;
1096                     }
1097                 }
1098             }
1099         }
1100 
1101         return bAllDrawObjsOnPage;
1102     }
1103 }
1104 // <--
1105 
1106 void SwDoc::SetDrawDefaults()
1107 {
1108     mbSetDrawDefaults = true;
1109     UpdateDrawDefaults();
1110 }
1111 
1112 void SwDoc::UpdateDrawDefaults()
1113 {
1114     // drawing layer defaults that are set for new documents (if InitNew was called)
1115     if ( pDrawModel && mbSetDrawDefaults )
1116 		pDrawModel->SetDrawingLayerPoolDefaults();
1117 }
1118 
1119