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