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_sc.hxx"
26
27 // System - Includes -----------------------------------------------------
28
29
30
31 #ifndef PCH
32 #include "scitems.hxx"
33
34 #include <svx/pageitem.hxx>
35 #include <vcl/virdev.hxx>
36 #include <sfx2/linkmgr.hxx>
37 #endif
38
39 // INCLUDE ---------------------------------------------------------------
40
41 //#include <svxlink.hxx>
42
43 #include "docsh.hxx"
44
45 #include "stlsheet.hxx"
46 #include "stlpool.hxx"
47 #include "global.hxx"
48 #include "viewdata.hxx"
49 #include "tabvwsh.hxx"
50 #include "tablink.hxx"
51 #include "collect.hxx"
52
53 struct ScStylePair
54 {
55 SfxStyleSheetBase *pSource;
56 SfxStyleSheetBase *pDest;
57 };
58
59
60 // STATIC DATA -----------------------------------------------------------
61
62 //----------------------------------------------------------------------
63
64 //
65 // Ole
66 //
67
SetVisArea(const Rectangle & rVisArea)68 void __EXPORT ScDocShell::SetVisArea( const Rectangle & rVisArea )
69 {
70 // with the SnapVisArea call in SetVisAreaOrSize, it's safe to always
71 // use both the size and position of the VisArea
72 SetVisAreaOrSize( rVisArea, sal_True );
73 }
74
lcl_SetTopRight(Rectangle & rRect,const Point & rPos)75 void lcl_SetTopRight( Rectangle& rRect, const Point& rPos )
76 {
77 Size aSize = rRect.GetSize();
78 rRect.Right() = rPos.X();
79 rRect.Left() = rPos.X() - aSize.Width() + 1;
80 rRect.Top() = rPos.Y();
81 rRect.Bottom() = rPos.Y() + aSize.Height() - 1;
82 }
83
SetVisAreaOrSize(const Rectangle & rVisArea,sal_Bool bModifyStart)84 void ScDocShell::SetVisAreaOrSize( const Rectangle& rVisArea, sal_Bool bModifyStart )
85 {
86 sal_Bool bNegativePage = aDocument.IsNegativePage( aDocument.GetVisibleTab() );
87
88 Rectangle aArea = rVisArea;
89 if (bModifyStart)
90 {
91 // when loading, don't check for negative values, because the sheet orientation
92 // might be set later
93 if ( !aDocument.IsImportingXML() )
94 {
95 if ( ( bNegativePage ? (aArea.Right() > 0) : (aArea.Left() < 0) ) || aArea.Top() < 0 )
96 {
97 // VisArea start position can't be negative.
98 // Move the VisArea, otherwise only the upper left position would
99 // be changed in SnapVisArea, and the size would be wrong.
100
101 Point aNewPos( 0, Max( aArea.Top(), (long) 0 ) );
102 if ( bNegativePage )
103 {
104 aNewPos.X() = Min( aArea.Right(), (long) 0 );
105 lcl_SetTopRight( aArea, aNewPos );
106 }
107 else
108 {
109 aNewPos.X() = Max( aArea.Left(), (long) 0 );
110 aArea.SetPos( aNewPos );
111 }
112 }
113 }
114 }
115 else
116 {
117 Rectangle aOldVisArea = SfxObjectShell::GetVisArea();
118 if ( bNegativePage )
119 lcl_SetTopRight( aArea, aOldVisArea.TopRight() );
120 else
121 aArea.SetPos( aOldVisArea.TopLeft() );
122 }
123
124 // hier Position anpassen!
125
126 // #92248# when loading an ole object, the VisArea is set from the document's
127 // view settings and must be used as-is (document content may not be complete yet).
128 if ( !aDocument.IsImportingXML() )
129 aDocument.SnapVisArea( aArea );
130
131 //TODO/LATER: it's unclear which IPEnv is used here
132 /*
133 SvInPlaceEnvironment* pEnv = GetIPEnv();
134 if (pEnv)
135 {
136 Window* pWin = pEnv->GetEditWin();
137 pEnv->MakeScale( aArea.GetSize(), MAP_100TH_MM,
138 pWin->LogicToPixel( aArea.GetSize() ) );
139 } */
140
141 //TODO/LATER: formerly in SvInplaceObject
142 SfxObjectShell::SetVisArea( aArea );
143
144 if (bIsInplace) // Zoom in der InPlace View einstellen
145 {
146 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
147 if (pViewSh)
148 {
149 if (pViewSh->GetViewData()->GetDocShell() == this)
150 pViewSh->UpdateOleZoom();
151 }
152 //else
153 // DataChanged( SvDataType() ); // fuer Zuppeln wenn nicht IP-aktiv
154 }
155
156 if (aDocument.IsEmbedded())
157 {
158 ScRange aOld;
159 aDocument.GetEmbedded( aOld);
160 aDocument.SetEmbedded( aArea );
161 ScRange aNew;
162 aDocument.GetEmbedded( aNew);
163 if (aOld != aNew)
164 PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_GRID);
165
166 //TODO/LATER: currently not implemented
167 //ViewChanged( ASPECT_CONTENT ); // auch im Container anzeigen
168 }
169 }
170
IsOle()171 sal_Bool ScDocShell::IsOle()
172 {
173 return (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
174 }
175
UpdateOle(const ScViewData * pViewData,sal_Bool bSnapSize)176 void ScDocShell::UpdateOle( const ScViewData* pViewData, sal_Bool bSnapSize )
177 {
178 // wenn's gar nicht Ole ist, kann man sich die Berechnungen sparen
179 // (VisArea wird dann beim Save wieder zurueckgesetzt)
180
181 if (GetCreateMode() == SFX_CREATE_MODE_STANDARD)
182 return;
183
184 DBG_ASSERT(pViewData,"pViewData==0 bei ScDocShell::UpdateOle");
185
186 Rectangle aOldArea = SfxObjectShell::GetVisArea();
187 Rectangle aNewArea = aOldArea;
188
189 sal_Bool bChange = sal_False;
190 sal_Bool bEmbedded = aDocument.IsEmbedded();
191 if (bEmbedded)
192 aNewArea = aDocument.GetEmbeddedRect();
193 else
194 {
195 SCTAB nTab = pViewData->GetTabNo();
196 if ( nTab != aDocument.GetVisibleTab() )
197 {
198 aDocument.SetVisibleTab( nTab );
199 bChange = sal_True;
200 }
201
202 sal_Bool bNegativePage = aDocument.IsNegativePage( nTab );
203 SCCOL nX = pViewData->GetPosX(SC_SPLIT_LEFT);
204 SCROW nY = pViewData->GetPosY(SC_SPLIT_BOTTOM);
205 Rectangle aMMRect = aDocument.GetMMRect( nX,nY, nX,nY, nTab );
206 if (bNegativePage)
207 lcl_SetTopRight( aNewArea, aMMRect.TopRight() );
208 else
209 aNewArea.SetPos( aMMRect.TopLeft() );
210 if (bSnapSize)
211 aDocument.SnapVisArea(aNewArea); // uses the new VisibleTab
212 }
213
214 if (aNewArea != aOldArea)
215 {
216 SetVisAreaOrSize( aNewArea, sal_True ); // hier muss auch der Start angepasst werden
217 bChange = sal_True;
218 }
219
220 // if (bChange)
221 // DataChanged( SvDataType() ); //! passiert auch bei SetModified
222 }
223
224 //
225 // Style-Krempel fuer Organizer etc.
226 //
227
GetStyleSheetPool()228 SfxStyleSheetBasePool* __EXPORT ScDocShell::GetStyleSheetPool()
229 {
230 return (SfxStyleSheetBasePool*)aDocument.GetStyleSheetPool();
231 }
232
233
234 // nach dem Laden von Vorlagen aus einem anderen Dokment (LoadStyles, Insert)
235 // muessen die SetItems (ATTR_PAGE_HEADERSET, ATTR_PAGE_FOOTERSET) auf den richtigen
236 // Pool umgesetzt werden, bevor der Quell-Pool geloescht wird.
237
lcl_AdjustPool(SfxStyleSheetBasePool * pStylePool)238 void lcl_AdjustPool( SfxStyleSheetBasePool* pStylePool )
239 {
240 pStylePool->SetSearchMask(SFX_STYLE_FAMILY_PAGE, 0xffff);
241 SfxStyleSheetBase *pStyle = pStylePool->First();
242 while ( pStyle )
243 {
244 SfxItemSet& rStyleSet = pStyle->GetItemSet();
245
246 const SfxPoolItem* pItem;
247 if (rStyleSet.GetItemState(ATTR_PAGE_HEADERSET,sal_False,&pItem) == SFX_ITEM_SET)
248 {
249 SfxItemSet& rSrcSet = ((SvxSetItem*)pItem)->GetItemSet();
250 SfxItemSet* pDestSet = new SfxItemSet(*rStyleSet.GetPool(),rSrcSet.GetRanges());
251 pDestSet->Put(rSrcSet);
252 rStyleSet.Put(SvxSetItem(ATTR_PAGE_HEADERSET,pDestSet));
253 }
254 if (rStyleSet.GetItemState(ATTR_PAGE_FOOTERSET,sal_False,&pItem) == SFX_ITEM_SET)
255 {
256 SfxItemSet& rSrcSet = ((SvxSetItem*)pItem)->GetItemSet();
257 SfxItemSet* pDestSet = new SfxItemSet(*rStyleSet.GetPool(),rSrcSet.GetRanges());
258 pDestSet->Put(rSrcSet);
259 rStyleSet.Put(SvxSetItem(ATTR_PAGE_FOOTERSET,pDestSet));
260 }
261
262 pStyle = pStylePool->Next();
263 }
264 }
265
LoadStyles(SfxObjectShell & rSource)266 void __EXPORT ScDocShell::LoadStyles( SfxObjectShell &rSource )
267 {
268 aDocument.StylesToNames();
269
270 SfxObjectShell::LoadStyles(rSource);
271 lcl_AdjustPool( GetStyleSheetPool() ); // SetItems anpassen
272
273 aDocument.UpdStlShtPtrsFrmNms();
274
275 UpdateAllRowHeights();
276
277 // Paint
278
279 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID | PAINT_LEFT );
280 }
281
LoadStylesArgs(ScDocShell & rSource,sal_Bool bReplace,sal_Bool bCellStyles,sal_Bool bPageStyles)282 void ScDocShell::LoadStylesArgs( ScDocShell& rSource, sal_Bool bReplace, sal_Bool bCellStyles, sal_Bool bPageStyles )
283 {
284 // similar to LoadStyles, but with selectable behavior for XStyleLoader::loadStylesFromURL call
285
286 if ( !bCellStyles && !bPageStyles ) // nothing to do
287 return;
288
289 ScStyleSheetPool* pSourcePool = rSource.GetDocument()->GetStyleSheetPool();
290 ScStyleSheetPool* pDestPool = aDocument.GetStyleSheetPool();
291
292 SfxStyleFamily eFamily = bCellStyles ?
293 ( bPageStyles ? SFX_STYLE_FAMILY_ALL : SFX_STYLE_FAMILY_PARA ) :
294 SFX_STYLE_FAMILY_PAGE;
295 SfxStyleSheetIterator aIter( pSourcePool, eFamily );
296 sal_uInt16 nSourceCount = aIter.Count();
297 if ( nSourceCount == 0 )
298 return; // no source styles
299
300 ScStylePair* pStyles = new ScStylePair[ nSourceCount ];
301 sal_uInt16 nFound = 0;
302
303 // first create all new styles
304
305 SfxStyleSheetBase* pSourceStyle = aIter.First();
306 while (pSourceStyle)
307 {
308 String aName = pSourceStyle->GetName();
309 SfxStyleSheetBase* pDestStyle = pDestPool->Find( pSourceStyle->GetName(), pSourceStyle->GetFamily() );
310 if ( pDestStyle )
311 {
312 // touch existing styles only if replace flag is set
313 if ( bReplace )
314 {
315 pStyles[nFound].pSource = pSourceStyle;
316 pStyles[nFound].pDest = pDestStyle;
317 ++nFound;
318 }
319 }
320 else
321 {
322 pStyles[nFound].pSource = pSourceStyle;
323 pStyles[nFound].pDest = &pDestPool->Make( aName, pSourceStyle->GetFamily(), pSourceStyle->GetMask() );
324 ++nFound;
325 }
326
327 pSourceStyle = aIter.Next();
328 }
329
330 // then copy contents (after inserting all styles, for parent etc.)
331
332 for ( sal_uInt16 i = 0; i < nFound; ++i )
333 {
334 pStyles[i].pDest->GetItemSet().PutExtended(
335 pStyles[i].pSource->GetItemSet(), SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT);
336 if(pStyles[i].pSource->HasParentSupport())
337 pStyles[i].pDest->SetParent(pStyles[i].pSource->GetParent());
338 // follow is never used
339 }
340
341 lcl_AdjustPool( GetStyleSheetPool() ); // adjust SetItems
342 UpdateAllRowHeights();
343 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID | PAINT_LEFT ); // Paint
344
345 delete[] pStyles;
346 }
347
348
Insert(SfxObjectShell & rSource,sal_uInt16 nSourceIdx1,sal_uInt16 nSourceIdx2,sal_uInt16 nSourceIdx3,sal_uInt16 & nIdx1,sal_uInt16 & nIdx2,sal_uInt16 & nIdx3,sal_uInt16 & rIdxDeleted)349 sal_Bool __EXPORT ScDocShell::Insert( SfxObjectShell &rSource,
350 sal_uInt16 nSourceIdx1, sal_uInt16 nSourceIdx2, sal_uInt16 nSourceIdx3,
351 sal_uInt16 &nIdx1, sal_uInt16 &nIdx2, sal_uInt16 &nIdx3, sal_uInt16 &rIdxDeleted )
352 {
353 sal_Bool bRet = SfxObjectShell::Insert( rSource, nSourceIdx1, nSourceIdx2, nSourceIdx3,
354 nIdx1, nIdx2, nIdx3, rIdxDeleted );
355 if (bRet)
356 lcl_AdjustPool( GetStyleSheetPool() ); // SetItems anpassen
357
358 return bRet;
359 }
360
UpdateLinks()361 void ScDocShell::UpdateLinks()
362 {
363 sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
364 ScStrCollection aNames;
365
366 // nicht mehr benutzte Links raus
367
368 sal_uInt16 nCount = pLinkManager->GetLinks().Count();
369 for (sal_uInt16 k=nCount; k>0; )
370 {
371 --k;
372 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[k];
373 if (pBase->ISA(ScTableLink))
374 {
375 ScTableLink* pTabLink = (ScTableLink*)pBase;
376 if (pTabLink->IsUsed())
377 {
378 StrData* pData = new StrData(pTabLink->GetFileName());
379 if (!aNames.Insert(pData))
380 delete pData;
381 }
382 else // nicht mehr benutzt -> loeschen
383 {
384 pTabLink->SetAddUndo(sal_True);
385 pLinkManager->Remove(k);
386 }
387 }
388 }
389
390
391 // neue Links eintragen
392
393 SCTAB nTabCount = aDocument.GetTableCount();
394 for (SCTAB i=0; i<nTabCount; i++)
395 if (aDocument.IsLinked(i))
396 {
397 String aDocName = aDocument.GetLinkDoc(i);
398 String aFltName = aDocument.GetLinkFlt(i);
399 String aOptions = aDocument.GetLinkOpt(i);
400 sal_uLong nRefresh = aDocument.GetLinkRefreshDelay(i);
401 sal_Bool bThere = sal_False;
402 for (SCTAB j=0; j<i && !bThere; j++) // im Dokument mehrfach?
403 if (aDocument.IsLinked(j)
404 && aDocument.GetLinkDoc(j) == aDocName
405 && aDocument.GetLinkFlt(j) == aFltName
406 && aDocument.GetLinkOpt(j) == aOptions)
407 // Ignore refresh delay in compare, it should be the
408 // same for identical links and we don't want dupes
409 // if it ain't.
410 bThere = sal_True;
411
412 if (!bThere) // schon als Filter eingetragen?
413 {
414 StrData* pData = new StrData(aDocName);
415 if (!aNames.Insert(pData))
416 {
417 delete pData;
418 bThere = sal_True;
419 }
420 }
421 if (!bThere)
422 {
423 ScTableLink* pLink = new ScTableLink( this, aDocName, aFltName, aOptions, nRefresh );
424 pLink->SetInCreate( sal_True );
425 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aDocName, &aFltName );
426 pLink->Update();
427 pLink->SetInCreate( sal_False );
428 }
429 }
430 }
431
ReloadTabLinks()432 sal_Bool ScDocShell::ReloadTabLinks()
433 {
434 sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
435
436 sal_Bool bAny = sal_False;
437 sal_uInt16 nCount = pLinkManager->GetLinks().Count();
438 for (sal_uInt16 i=0; i<nCount; i++ )
439 {
440 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i];
441 if (pBase->ISA(ScTableLink))
442 {
443 ScTableLink* pTabLink = (ScTableLink*)pBase;
444 // pTabLink->SetAddUndo(sal_False); //! Undo's zusammenfassen
445 // Painting only after Update() makes no sense:
446 // ScTableLink::Refresh() will post a Paint only is bDoPaint is true
447 //pTabLink->SetPaint(sal_False); // Paint nur einmal am Ende
448 pTabLink->Update();
449 //pTabLink->SetPaint(sal_True);
450 // pTabLink->SetAddUndo(sal_True);
451 bAny = sal_True;
452 }
453 }
454
455 if ( bAny )
456 {
457 // Paint nur einmal
458 PostPaint( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB),
459 PAINT_GRID | PAINT_TOP | PAINT_LEFT );
460
461 SetDocumentModified();
462 }
463
464 return sal_True; //! Fehler erkennen
465 }
466
467
468