xref: /aoo42x/main/sw/source/core/doc/docdraw.cxx (revision 26ea3662)
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     // SJ: #95129# set FontHeight pool defaults without changing static SdrEngineDefaults
603  	GetAttrPool().SetPoolDefaultItem(SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ));
604 
605 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create DrawDocument" );
606 	//Das SdrModel gehoert dem Dokument, wir haben immer zwei Layer und eine
607 	//Seite.
608 	pDrawModel = new SwDrawModel( this );
609 
610     pDrawModel->EnableUndo( GetIDocumentUndoRedo().DoesUndo() );
611 
612 	String sLayerNm;
613 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Hell" ));
614 	nHell	= pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
615 
616 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Heaven" ));
617 	nHeaven	= pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
618 
619 	sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Controls" ));
620 	nControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
621 
622     // OD 25.06.2003 #108784# - add invisible layers corresponding to the
623     // visible ones.
624     {
625         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
626         nInvisibleHell   = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
627 
628         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
629         nInvisibleHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
630 
631         sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
632         nInvisibleControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
633     }
634 
635     SdrPage* pMasterPage = pDrawModel->AllocPage( sal_False );
636 	pDrawModel->InsertPage( pMasterPage );
637 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create DrawDocument" );
638 
639 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create Spellchecker/Hyphenator" );
640 	SdrOutliner& rOutliner = pDrawModel->GetDrawOutliner();
641 	uno::Reference< XSpellChecker1 > xSpell = ::GetSpellChecker();
642 	rOutliner.SetSpeller( xSpell );
643     uno::Reference<XHyphenator> xHyphenator( ::GetHyphenator() );
644 	rOutliner.SetHyphenator( xHyphenator );
645 	RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create Spellchecker/Hyphenator" );
646 
647 	SetCalcFieldValueHdl(&rOutliner);
648 	SetCalcFieldValueHdl(&pDrawModel->GetHitTestOutliner());
649 
650 	//JP 16.07.98: Bug 50193 - Linkmanager am Model setzen, damit
651 	//			dort ggfs. verlinkte Grafiken eingefuegt werden koennen
652 	//JP 28.01.99: der WinWord Import benoetigt ihn auch
653 	pDrawModel->SetLinkManager( &GetLinkManager() );
654     pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
655 
656     OutputDevice* pRefDev = getReferenceDevice( false );
657     if ( pRefDev )
658         pDrawModel->SetRefDevice( pRefDev );
659 
660     pDrawModel->SetNotifyUndoActionHdl( LINK( this, SwDoc, AddDrawUndo ));
661 	if ( pCurrentView )
662 	{
663         ViewShell* pViewSh = pCurrentView;
664         do
665         {
666             SwRootFrm* pRoot =  pViewSh->GetLayout();
667             if( pRoot && !pRoot->GetDrawPage() )
668             {
669                 // Disable "multiple layout" for the moment:
670                 // use pMasterPage instead of a new created SdrPage
671                 // pDrawModel->AllocPage( FALSE );
672                 // pDrawModel->InsertPage( pDrawPage );
673                 SdrPage* pDrawPage = pMasterPage;
674                 pRoot->SetDrawPage( pDrawPage );
675                 pDrawPage->SetSize( pRoot->Frm().SSize() );
676             }
677             pViewSh = (ViewShell*)pViewSh->GetNext();
678         }while( pViewSh != pCurrentView );
679 	}
680 }
681 
682 /** method to notify drawing page view about the invisible layers
683 
684     OD 26.06.2003 #108784#
685 
686     @author OD
687 */
688 void SwDoc::NotifyInvisibleLayers( SdrPageView& _rSdrPageView )
689 {
690     String sLayerNm;
691     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
692     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
693 
694     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
695     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
696 
697     sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
698     _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
699 }
700 
701 /** method to determine, if a layer ID belongs to the visible ones.
702 
703     OD 25.06.2003 #108784#
704     Note: If given layer ID is unknown, method asserts and returns <false>.
705 
706     @author OD
707 */
708 bool SwDoc::IsVisibleLayerId( const SdrLayerID& _nLayerId ) const
709 {
710     bool bRetVal;
711 
712     if ( _nLayerId == GetHeavenId() ||
713          _nLayerId == GetHellId() ||
714          _nLayerId == GetControlsId() )
715     {
716         bRetVal = true;
717     }
718     else if ( _nLayerId == GetInvisibleHeavenId() ||
719               _nLayerId == GetInvisibleHellId() ||
720               _nLayerId == GetInvisibleControlsId() )
721     {
722         bRetVal = false;
723     }
724     else
725     {
726         ASSERT( false, "<SwDoc::IsVisibleLayerId(..)> - unknown layer ID." );
727         bRetVal = false;
728     }
729 
730     return bRetVal;
731 }
732 
733 /** method to determine, if the corresponding visible layer ID for a invisible one.
734 
735     OD 25.06.2003 #108784#
736     Note: If given layer ID is a visible one, method returns given layer ID.
737     Note: If given layer ID is unknown, method returns given layer ID.
738 
739     @author OD
740 */
741 SdrLayerID SwDoc::GetVisibleLayerIdByInvisibleOne( const SdrLayerID& _nInvisibleLayerId )
742 {
743     SdrLayerID nVisibleLayerId;
744 
745     if ( _nInvisibleLayerId == GetInvisibleHeavenId() )
746     {
747         nVisibleLayerId = GetHeavenId();
748     }
749     else if ( _nInvisibleLayerId == GetInvisibleHellId() )
750     {
751         nVisibleLayerId = GetHellId();
752     }
753     else if ( _nInvisibleLayerId == GetInvisibleControlsId() )
754     {
755         nVisibleLayerId = GetControlsId();
756     }
757     else if ( _nInvisibleLayerId == GetHeavenId() ||
758               _nInvisibleLayerId == GetHellId() ||
759               _nInvisibleLayerId == GetControlsId() )
760     {
761         ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID already an invisible one." );
762         nVisibleLayerId = _nInvisibleLayerId;
763     }
764     else
765     {
766         ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID is unknown." );
767         nVisibleLayerId = _nInvisibleLayerId;
768     }
769 
770     return nVisibleLayerId;
771 }
772 
773 /** method to determine, if the corresponding invisible layer ID for a visible one.
774 
775     OD 25.06.2003 #108784#
776     Note: If given layer ID is a invisible one, method returns given layer ID.
777     Note: If given layer ID is unknown, method returns given layer ID.
778 
779     @author OD
780 */
781 SdrLayerID SwDoc::GetInvisibleLayerIdByVisibleOne( const SdrLayerID& _nVisibleLayerId )
782 {
783     SdrLayerID nInvisibleLayerId;
784 
785     if ( _nVisibleLayerId == GetHeavenId() )
786     {
787         nInvisibleLayerId = GetInvisibleHeavenId();
788     }
789     else if ( _nVisibleLayerId == GetHellId() )
790     {
791         nInvisibleLayerId = GetInvisibleHellId();
792     }
793     else if ( _nVisibleLayerId == GetControlsId() )
794     {
795         nInvisibleLayerId = GetInvisibleControlsId();
796     }
797     else if ( _nVisibleLayerId == GetInvisibleHeavenId() ||
798               _nVisibleLayerId == GetInvisibleHellId() ||
799               _nVisibleLayerId == GetInvisibleControlsId() )
800     {
801         ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID already an invisible one." );
802         nInvisibleLayerId = _nVisibleLayerId;
803     }
804     else
805     {
806         ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID is unknown." );
807         nInvisibleLayerId = _nVisibleLayerId;
808     }
809 
810     return nInvisibleLayerId;
811 }
812 
813 /*************************************************************************/
814 
815 
816 void SwDoc::ReleaseDrawModel()
817 {
818 	if ( pDrawModel )
819 	{
820 		//!!Den code im sw3io fuer Einfuegen Dokument mitpflegen!!
821 		delete pDrawModel; pDrawModel = 0;
822 	}
823 }
824 
825 /*************************************************************************/
826 
827 
828 SwDrawModel* SwDoc::_MakeDrawModel()
829 {
830 	ASSERT( !pDrawModel, "_MakeDrawModel: Why?" );
831 	InitDrawModel();
832 	if ( pCurrentView )
833 	{
834 		ViewShell* pTmp = pCurrentView;
835 		do
836 		{
837 			pTmp->MakeDrawView();
838 			pTmp = (ViewShell*) pTmp->GetNext();
839 		} while ( pTmp != pCurrentView );
840 
841 		//Broadcast, damit die FormShell mit der DrawView verbunden werden kann
842 		if( GetDocShell() )
843 		{
844 			SfxSimpleHint aHnt( SW_BROADCAST_DRAWVIEWS_CREATED );
845 			GetDocShell()->Broadcast( aHnt );
846 		}
847 	}	//swmod 071029//swmod 071225
848 	return pDrawModel;
849 }
850 
851 /*************************************************************************/
852 
853 void SwDoc::DrawNotifyUndoHdl()
854 {
855 	pDrawModel->SetNotifyUndoActionHdl( Link() );
856 }
857 
858 /*************************************************************************
859 *
860 * Am Outliner Link auf Methode fuer Felddarstellung in Editobjekten setzen
861 *
862 *************************************************************************/
863 
864 void SwDoc::SetCalcFieldValueHdl(Outliner* pOutliner)
865 {
866 	pOutliner->SetCalcFieldValueHdl(LINK(this, SwDoc, CalcFieldValueHdl));
867 }
868 
869 /*************************************************************************
870 |*
871 |* Felder bzw URLs im Outliner erkennen und Darstellung festlegen
872 |*
873 \************************************************************************/
874 
875 IMPL_LINK(SwDoc, CalcFieldValueHdl, EditFieldInfo*, pInfo)
876 {
877 	if (pInfo)
878 	{
879 		const SvxFieldItem& rField = pInfo->GetField();
880 		const SvxFieldData* pField = rField.GetField();
881 
882 		if (pField && pField->ISA(SvxDateField))
883 		{
884 			/******************************************************************
885 			* Date-Field
886 			******************************************************************/
887 			pInfo->SetRepresentation(
888 				((const SvxDateField*) pField)->GetFormatted(
889 						*GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
890 		}
891 		else if (pField && pField->ISA(SvxURLField))
892 		{
893 			/******************************************************************
894 			* URL-Field
895 			******************************************************************/
896 
897 			switch ( ((const SvxURLField*) pField)->GetFormat() )
898 			{
899 				case SVXURLFORMAT_APPDEFAULT: //!!! einstellbar an App???
900 				case SVXURLFORMAT_REPR:
901 				{
902 					pInfo->SetRepresentation(
903 						((const SvxURLField*)pField)->GetRepresentation());
904 				}
905 				break;
906 
907 				case SVXURLFORMAT_URL:
908 				{
909 					pInfo->SetRepresentation(
910 						((const SvxURLField*)pField)->GetURL());
911 				}
912 				break;
913 			}
914 
915 			sal_uInt16 nChrFmt;
916 
917 			if (IsVisitedURL(((const SvxURLField*)pField)->GetURL()))
918 				nChrFmt = RES_POOLCHR_INET_VISIT;
919 			else
920 				nChrFmt = RES_POOLCHR_INET_NORMAL;
921 
922 			SwFmt *pFmt = GetCharFmtFromPool(nChrFmt);
923 
924 			Color aColor(COL_LIGHTBLUE);
925 			if (pFmt)
926 				aColor = pFmt->GetColor().GetValue();
927 
928 			pInfo->SetTxtColor(aColor);
929 		}
930 		else if (pField && pField->ISA(SdrMeasureField))
931 		{
932 			/******************************************************************
933 			* Measure-Field
934 			******************************************************************/
935 			pInfo->ClearFldColor();
936 		}
937         else if ( pField && pField->ISA(SvxExtTimeField))
938         {
939             /******************************************************************
940             * Time-Field
941             ******************************************************************/
942             pInfo->SetRepresentation(
943                 ((const SvxExtTimeField*) pField)->GetFormatted(
944                         *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
945         }
946 		else
947 		{
948 			DBG_ERROR("unbekannter Feldbefehl");
949 			pInfo->SetRepresentation( String( '?' ) );
950 		}
951 	}
952 
953 	return(0);
954 }
955 
956 /* TFFDI: The functions formerly declared 'inline'
957  */
958 const SwDrawModel* SwDoc::GetDrawModel() const { return pDrawModel; }
959 SwDrawModel* SwDoc::GetDrawModel() { return pDrawModel; }
960 SdrLayerID SwDoc::GetHeavenId() const { return nHeaven; }
961 SdrLayerID SwDoc::GetHellId() const { return nHell; }
962 SdrLayerID SwDoc::GetControlsId() const { return nControls;   }
963 SdrLayerID SwDoc::GetInvisibleHeavenId() const { return nInvisibleHeaven; }
964 SdrLayerID SwDoc::GetInvisibleHellId() const { return nInvisibleHell; }
965 SdrLayerID SwDoc::GetInvisibleControlsId() const { return nInvisibleControls; }
966 SwDrawModel* SwDoc::GetOrCreateDrawModel() { return GetDrawModel() ? GetDrawModel() : _MakeDrawModel(); }
967 
968 // --> OD 2006-03-14 #i62875#
969 namespace docfunc
970 {
971     bool ExistsDrawObjs( SwDoc& p_rDoc )
972     {
973         bool bExistsDrawObjs( false );
974 
975         if ( p_rDoc.GetDrawModel() &&
976              p_rDoc.GetDrawModel()->GetPage( 0 ) )
977         {
978             const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
979 
980             SdrObjListIter aIter( rSdrPage, IM_FLAT );
981             while( aIter.IsMore() )
982             {
983                 SdrObject* pObj( aIter.Next() );
984                 if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
985                      !dynamic_cast<SwFlyDrawObj*>(pObj) )
986                 {
987                     bExistsDrawObjs = true;
988                     break;
989                 }
990             }
991         }
992 
993         return bExistsDrawObjs;
994     }
995 
996     bool AllDrawObjsOnPage( SwDoc& p_rDoc )
997     {
998         bool bAllDrawObjsOnPage( true );
999 
1000         if ( p_rDoc.GetDrawModel() &&
1001              p_rDoc.GetDrawModel()->GetPage( 0 ) )
1002         {
1003             const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
1004 
1005             SdrObjListIter aIter( rSdrPage, IM_FLAT );
1006             while( aIter.IsMore() )
1007             {
1008                 SdrObject* pObj( aIter.Next() );
1009                 if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
1010                      !dynamic_cast<SwFlyDrawObj*>(pObj) )
1011                 {
1012                     SwDrawContact* pDrawContact =
1013                             dynamic_cast<SwDrawContact*>(::GetUserCall( pObj ));
1014                     if ( pDrawContact )
1015                     {
1016                         SwAnchoredDrawObject* pAnchoredDrawObj =
1017                             dynamic_cast<SwAnchoredDrawObject*>(pDrawContact->GetAnchoredObj( pObj ));
1018 
1019                         // error handling
1020                         {
1021                             if ( !pAnchoredDrawObj )
1022                             {
1023                                 ASSERT( false,
1024                                         "<docfunc::AllDrawObjsOnPage() - missing anchored draw object" );
1025                                 bAllDrawObjsOnPage = false;
1026                                 break;
1027                             }
1028                         }
1029 
1030                         if ( pAnchoredDrawObj->NotYetPositioned() )
1031                         {
1032                             // The drawing object isn't yet layouted.
1033                             // Thus, it isn't known, if all drawing objects are on page.
1034                             bAllDrawObjsOnPage = false;
1035                             break;
1036                         }
1037                         else if ( pAnchoredDrawObj->IsOutsidePage() )
1038                         {
1039                             bAllDrawObjsOnPage = false;
1040                             break;
1041                         }
1042                     }
1043                     else
1044                     {
1045                         // contact object of drawing object doesn't exists.
1046                         // Thus, the drawing object isn't yet positioned.
1047                         // Thus, it isn't known, if all drawing objects are on page.
1048                         bAllDrawObjsOnPage = false;
1049                         break;
1050                     }
1051                 }
1052             }
1053         }
1054 
1055         return bAllDrawObjsOnPage;
1056     }
1057 }
1058 // <--
1059 
1060 // eof
1061