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
28
29 // INCLUDE ---------------------------------------------------------
30
31 #include <sfx2/app.hxx>
32 #include <sfx2/docfile.hxx>
33 #include <sfx2/fcontnr.hxx>
34 #include <sfx2/sfxsids.hrc>
35 #include <sfx2/linkmgr.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <svl/stritem.hxx>
38 #include <vcl/msgbox.hxx>
39
40 #include "arealink.hxx"
41
42 #include "tablink.hxx"
43 #include "document.hxx"
44 #include "docsh.hxx"
45 #include "rangenam.hxx"
46 #include "dbcolect.hxx"
47 #include "undoblk.hxx"
48 #include "globstr.hrc"
49 #include "markdata.hxx"
50 #include "hints.hxx"
51 #include "filter.hxx"
52 //CHINA001 #include "linkarea.hxx" // dialog
53
54 #include "attrib.hxx" // raus, wenn ResetAttrib am Dokument
55 #include "patattr.hxx" // raus, wenn ResetAttrib am Dokument
56 #include "docpool.hxx" // raus, wenn ResetAttrib am Dokument
57
58 #include "sc.hrc" //CHINA001
59 #include "scabstdlg.hxx" //CHINA001
60 #include "clipparam.hxx"
61
62 struct AreaLink_Impl
63 {
64 ScDocShell* m_pDocSh;
65 AbstractScLinkedAreaDlg* m_pDialog;
66
AreaLink_ImplAreaLink_Impl67 AreaLink_Impl() : m_pDocSh( NULL ), m_pDialog( NULL ) {}
68 };
69
70 TYPEINIT1(ScAreaLink,::sfx2::SvBaseLink);
71
72 //------------------------------------------------------------------------
73
ScAreaLink(SfxObjectShell * pShell,const String & rFile,const String & rFilter,const String & rOpt,const String & rArea,const ScRange & rDest,sal_uLong nRefresh)74 ScAreaLink::ScAreaLink( SfxObjectShell* pShell, const String& rFile,
75 const String& rFilter, const String& rOpt,
76 const String& rArea, const ScRange& rDest,
77 sal_uLong nRefresh ) :
78 ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
79 ScRefreshTimer ( nRefresh ),
80 pImpl ( new AreaLink_Impl() ),
81 aFileName (rFile),
82 aFilterName (rFilter),
83 aOptions (rOpt),
84 aSourceArea (rArea),
85 aDestArea (rDest),
86 bAddUndo (sal_True),
87 bInCreate (sal_False),
88 bDoInsert (sal_True)
89 {
90 DBG_ASSERT(pShell->ISA(ScDocShell), "ScAreaLink mit falscher ObjectShell");
91 pImpl->m_pDocSh = static_cast< ScDocShell* >( pShell );
92 SetRefreshHandler( LINK( this, ScAreaLink, RefreshHdl ) );
93 SetRefreshControl( pImpl->m_pDocSh->GetDocument()->GetRefreshTimerControlAddress() );
94 }
95
~ScAreaLink()96 __EXPORT ScAreaLink::~ScAreaLink()
97 {
98 StopRefreshTimer();
99 delete pImpl;
100 }
101
Edit(Window * pParent,const Link &)102 void __EXPORT ScAreaLink::Edit(Window* pParent, const Link& /* rEndEditHdl */ )
103 {
104 // use own dialog instead of SvBaseLink::Edit...
105 // DefModalDialogParent setzen, weil evtl. aus der DocShell beim ConvertFrom
106 // ein Optionen-Dialog kommt...
107
108 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
109 DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
110
111 AbstractScLinkedAreaDlg* pDlg = pFact->CreateScLinkedAreaDlg( pParent, RID_SCDLG_LINKAREA);
112 DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
113 pDlg->InitFromOldLink( aFileName, aFilterName, aOptions, aSourceArea, GetRefreshDelay() );
114 pImpl->m_pDialog = pDlg;
115 pDlg->StartExecuteModal( LINK( this, ScAreaLink, AreaEndEditHdl ) );
116 }
117
DataChanged(const String &,const::com::sun::star::uno::Any &)118 void __EXPORT ScAreaLink::DataChanged( const String&,
119 const ::com::sun::star::uno::Any& )
120 {
121 // bei bInCreate nichts tun, damit Update gerufen werden kann, um den Status im
122 // LinkManager zu setzen, ohne die Daten im Dokument zu aendern
123
124 if (bInCreate)
125 return;
126
127 sfx2::LinkManager* pLinkManager=pImpl->m_pDocSh->GetDocument()->GetLinkManager();
128 if (pLinkManager!=NULL)
129 {
130 String aFile;
131 String aFilter;
132 String aArea;
133 pLinkManager->GetDisplayNames( this,0,&aFile,&aArea,&aFilter);
134
135 // the file dialog returns the filter name with the application prefix
136 // -> remove prefix
137 ScDocumentLoader::RemoveAppPrefix( aFilter );
138
139 // #81155# dialog doesn't set area, so keep old one
140 if ( !aArea.Len() )
141 {
142 aArea = aSourceArea;
143
144 // adjust in dialog:
145 String aNewLinkName;
146 sfx2::MakeLnkName( aNewLinkName, NULL, aFile, aArea, &aFilter );
147 SetName( aNewLinkName );
148 }
149
150 Refresh( aFile, aFilter, aArea, GetRefreshDelay() );
151 }
152 }
153
Closed()154 void __EXPORT ScAreaLink::Closed()
155 {
156 // Verknuepfung loeschen: Undo
157
158 ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
159 sal_Bool bUndo (pDoc->IsUndoEnabled());
160 if (bAddUndo && bUndo)
161 {
162 pImpl->m_pDocSh->GetUndoManager()->AddUndoAction( new ScUndoRemoveAreaLink( pImpl->m_pDocSh,
163 aFileName, aFilterName, aOptions,
164 aSourceArea, aDestArea, GetRefreshDelay() ) );
165
166 bAddUndo = sal_False; // nur einmal
167 }
168
169 SCTAB nDestTab = aDestArea.aStart.Tab();
170 if (pDoc->IsStreamValid(nDestTab))
171 pDoc->SetStreamValid(nDestTab, sal_False);
172
173 SvBaseLink::Closed();
174 }
175
SetDestArea(const ScRange & rNew)176 void ScAreaLink::SetDestArea(const ScRange& rNew)
177 {
178 aDestArea = rNew; // fuer Undo
179 }
180
SetSource(const String & rDoc,const String & rFlt,const String & rOpt,const String & rArea)181 void ScAreaLink::SetSource(const String& rDoc, const String& rFlt, const String& rOpt,
182 const String& rArea)
183 {
184 aFileName = rDoc;
185 aFilterName = rFlt;
186 aOptions = rOpt;
187 aSourceArea = rArea;
188
189 // also update link name for dialog
190 String aNewLinkName;
191 sfx2::MakeLnkName( aNewLinkName, NULL, aFileName, aSourceArea, &aFilterName );
192 SetName( aNewLinkName );
193 }
194
IsEqual(const String & rFile,const String & rFilter,const String & rOpt,const String & rSource,const ScRange & rDest) const195 sal_Bool ScAreaLink::IsEqual( const String& rFile, const String& rFilter, const String& rOpt,
196 const String& rSource, const ScRange& rDest ) const
197 {
198 return aFileName == rFile && aFilterName == rFilter && aOptions == rOpt &&
199 aSourceArea == rSource && aDestArea.aStart == rDest.aStart;
200 }
201
202 // find a range with name >rAreaName< in >pSrcDoc<, return it in >rRange<
FindExtRange(ScRange & rRange,ScDocument * pSrcDoc,const String & rAreaName)203 sal_Bool ScAreaLink::FindExtRange( ScRange& rRange, ScDocument* pSrcDoc, const String& rAreaName )
204 {
205 sal_Bool bFound = sal_False;
206 ScRangeName* pNames = pSrcDoc->GetRangeName();
207 sal_uInt16 nPos;
208 if (pNames) // benannte Bereiche
209 {
210 if (pNames->SearchName( rAreaName, nPos ))
211 if ( (*pNames)[nPos]->IsValidReference( rRange ) )
212 bFound = sal_True;
213 }
214 if (!bFound) // Datenbankbereiche
215 {
216 ScDBCollection* pDBColl = pSrcDoc->GetDBCollection();
217 if (pDBColl)
218 if (pDBColl->SearchName( rAreaName, nPos ))
219 {
220 SCTAB nTab;
221 SCCOL nCol1, nCol2;
222 SCROW nRow1, nRow2;
223 (*pDBColl)[nPos]->GetArea(nTab,nCol1,nRow1,nCol2,nRow2);
224 rRange = ScRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
225 bFound = sal_True;
226 }
227 }
228 if (!bFound) // direct reference (range or cell)
229 {
230 ScAddress::Details aDetails(pSrcDoc->GetAddressConvention(), 0, 0);
231 if ( rRange.ParseAny( rAreaName, pSrcDoc, aDetails ) & SCA_VALID )
232 bFound = sal_True;
233 }
234 return bFound;
235 }
236
237 // ausfuehren:
238
Refresh(const String & rNewFile,const String & rNewFilter,const String & rNewArea,sal_uLong nNewRefresh)239 sal_Bool ScAreaLink::Refresh( const String& rNewFile, const String& rNewFilter,
240 const String& rNewArea, sal_uLong nNewRefresh )
241 {
242 // Dokument laden - wie TabLink
243
244 if (!rNewFile.Len() || !rNewFilter.Len())
245 return sal_False;
246
247 // Request for authorization
248 sfx2::LinkManager* pLinkMgr = pImpl->m_pDocSh->GetDocument()->GetLinkManager();
249 if ( pLinkMgr ) {
250 if ( pLinkMgr->urlIsVendor( rNewFile ) )
251 return sal_False;
252 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pImpl->m_pDocSh );
253 if ( pFrame ) {
254 Window* pWindow = &pFrame->GetWindow();
255 if ( pWindow ) {
256 if ( !pLinkMgr->GetUserAllowsLinkUpdate( pWindow ) ) {
257 return sal_False;
258 }
259 }
260 }
261 }
262
263 String aNewUrl( ScGlobal::GetAbsDocName( rNewFile, pImpl->m_pDocSh ) );
264 sal_Bool bNewUrlName = (aNewUrl != aFileName);
265
266 const SfxFilter* pFilter = pImpl->m_pDocSh->GetFactory().GetFilterContainer()->GetFilter4FilterName(rNewFilter);
267 if (!pFilter)
268 return sal_False;
269
270 ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
271
272 sal_Bool bUndo (pDoc->IsUndoEnabled());
273 pDoc->SetInLinkUpdate( sal_True );
274
275 // wenn neuer Filter ausgewaehlt wurde, Optionen vergessen
276 if ( rNewFilter != aFilterName )
277 aOptions.Erase();
278
279 // ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
280 SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
281 if ( aOptions.Len() )
282 pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
283
284 SfxMedium* pMed = new SfxMedium(aNewUrl, STREAM_STD_READ, sal_False, pFilter);
285
286 // aRef->DoClose() will be closed explicitly, but it is still more safe to use SfxObjectShellLock here
287 ScDocShell* pSrcShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
288 SfxObjectShellLock aRef = pSrcShell;
289 pSrcShell->DoLoad(pMed);
290
291 ScDocument* pSrcDoc = pSrcShell->GetDocument();
292
293 // Optionen koennten gesetzt worden sein
294 String aNewOpt = ScDocumentLoader::GetOptions(*pMed);
295 if (!aNewOpt.Len())
296 aNewOpt = aOptions;
297
298 // correct source range name list for web query import
299 String aTempArea;
300
301 if( rNewFilter == ScDocShell::GetWebQueryFilterName() )
302 aTempArea = ScFormatFilter::Get().GetHTMLRangeNameList( pSrcDoc, rNewArea );
303 else
304 aTempArea = rNewArea;
305
306 // find total size of source area
307 SCCOL nWidth = 0;
308 SCROW nHeight = 0;
309 xub_StrLen nTokenCnt = aTempArea.GetTokenCount( ';' );
310 xub_StrLen nStringIx = 0;
311 xub_StrLen nToken;
312
313 for( nToken = 0; nToken < nTokenCnt; nToken++ )
314 {
315 String aToken( aTempArea.GetToken( 0, ';', nStringIx ) );
316 ScRange aTokenRange;
317 if( FindExtRange( aTokenRange, pSrcDoc, aToken ) )
318 {
319 // columns: find maximum
320 nWidth = Max( nWidth, (SCCOL)(aTokenRange.aEnd.Col() - aTokenRange.aStart.Col() + 1) );
321 // rows: add row range + 1 empty row
322 nHeight += aTokenRange.aEnd.Row() - aTokenRange.aStart.Row() + 2;
323 }
324 }
325 // remove the last empty row
326 if( nHeight > 0 )
327 nHeight--;
328
329 // alte Daten loeschen / neue kopieren
330
331 ScAddress aDestPos = aDestArea.aStart;
332 SCTAB nDestTab = aDestPos.Tab();
333 ScRange aOldRange = aDestArea;
334 ScRange aNewRange = aDestArea; // alter Bereich, wenn Datei nicht gefunden o.ae.
335 if (nWidth > 0 && nHeight > 0)
336 {
337 aNewRange.aEnd.SetCol( aNewRange.aStart.Col() + nWidth - 1 );
338 aNewRange.aEnd.SetRow( aNewRange.aStart.Row() + nHeight - 1 );
339 }
340
341 //! check CanFitBlock only if bDoInsert is set?
342 sal_Bool bCanDo = ValidColRow( aNewRange.aEnd.Col(), aNewRange.aEnd.Row() ) &&
343 pDoc->CanFitBlock( aOldRange, aNewRange );
344 if (bCanDo)
345 {
346 ScDocShellModificator aModificator( *pImpl->m_pDocSh );
347
348 SCCOL nOldEndX = aOldRange.aEnd.Col();
349 SCROW nOldEndY = aOldRange.aEnd.Row();
350 SCCOL nNewEndX = aNewRange.aEnd.Col();
351 SCROW nNewEndY = aNewRange.aEnd.Row();
352 ScRange aMaxRange( aDestPos,
353 ScAddress(Max(nOldEndX,nNewEndX), Max(nOldEndY,nNewEndY), nDestTab) );
354
355 // Undo initialisieren
356
357 ScDocument* pUndoDoc = NULL;
358 ScDocument* pRedoDoc = NULL;
359 if ( bAddUndo && bUndo )
360 {
361 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
362 if ( bDoInsert )
363 {
364 if ( nNewEndX != nOldEndX || nNewEndY != nOldEndY ) // Bereich veraendert?
365 {
366 pUndoDoc->InitUndo( pDoc, 0, pDoc->GetTableCount()-1 );
367 pDoc->CopyToDocument( 0,0,0,MAXCOL,MAXROW,MAXTAB,
368 IDF_FORMULA, sal_False, pUndoDoc ); // alle Formeln
369 }
370 else
371 pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
372 pDoc->CopyToDocument( aOldRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
373 }
374 else // ohne Einfuegen
375 {
376 pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
377 pDoc->CopyToDocument( aMaxRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
378 }
379 }
380
381 // Zellen einfuegen / loeschen
382 // DeleteAreaTab loescht auch MERGE_FLAG Attribute
383
384 if (bDoInsert)
385 pDoc->FitBlock( aOldRange, aNewRange ); // incl. loeschen
386 else
387 pDoc->DeleteAreaTab( aMaxRange, IDF_ALL & ~IDF_NOTE );
388
389 // Daten kopieren
390
391 if (nWidth > 0 && nHeight > 0)
392 {
393 ScDocument aClipDoc( SCDOCMODE_CLIP );
394 ScRange aNewTokenRange( aNewRange.aStart );
395 nStringIx = 0;
396 for( nToken = 0; nToken < nTokenCnt; nToken++ )
397 {
398 String aToken( aTempArea.GetToken( 0, ';', nStringIx ) );
399 ScRange aTokenRange;
400 if( FindExtRange( aTokenRange, pSrcDoc, aToken ) )
401 {
402 SCTAB nSrcTab = aTokenRange.aStart.Tab();
403 ScMarkData aSourceMark;
404 aSourceMark.SelectOneTable( nSrcTab ); // selektieren fuer CopyToClip
405 aSourceMark.SetMarkArea( aTokenRange );
406
407 ScClipParam aClipParam(aTokenRange, false);
408 pSrcDoc->CopyToClip(aClipParam, &aClipDoc, &aSourceMark);
409
410 if ( aClipDoc.HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
411 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
412 {
413 //! ResetAttrib am Dokument !!!
414
415 ScPatternAttr aPattern( pSrcDoc->GetPool() );
416 aPattern.GetItemSet().Put( ScMergeAttr() ); // Defaults
417 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
418 aClipDoc.ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern );
419 }
420
421 aNewTokenRange.aEnd.SetCol( aNewTokenRange.aStart.Col() + (aTokenRange.aEnd.Col() - aTokenRange.aStart.Col()) );
422 aNewTokenRange.aEnd.SetRow( aNewTokenRange.aStart.Row() + (aTokenRange.aEnd.Row() - aTokenRange.aStart.Row()) );
423 ScMarkData aDestMark;
424 aDestMark.SelectOneTable( nDestTab );
425 aDestMark.SetMarkArea( aNewTokenRange );
426 pDoc->CopyFromClip( aNewTokenRange, aDestMark, IDF_ALL, NULL, &aClipDoc, sal_False );
427 aNewTokenRange.aStart.SetRow( aNewTokenRange.aEnd.Row() + 2 );
428 }
429 }
430 }
431 else
432 {
433 String aErr = ScGlobal::GetRscString(STR_LINKERROR);
434 pDoc->SetString( aDestPos.Col(), aDestPos.Row(), aDestPos.Tab(), aErr );
435 }
436
437 // Undo eintragen
438
439 if ( bAddUndo && bUndo)
440 {
441 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
442 pRedoDoc->InitUndo( pDoc, nDestTab, nDestTab );
443 pDoc->CopyToDocument( aNewRange, IDF_ALL & ~IDF_NOTE, sal_False, pRedoDoc );
444
445 pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
446 new ScUndoUpdateAreaLink( pImpl->m_pDocSh,
447 aFileName, aFilterName, aOptions,
448 aSourceArea, aOldRange, GetRefreshDelay(),
449 aNewUrl, rNewFilter, aNewOpt,
450 rNewArea, aNewRange, nNewRefresh,
451 pUndoDoc, pRedoDoc, bDoInsert ) );
452 }
453
454 // neue Einstellungen merken
455
456 if ( bNewUrlName )
457 aFileName = aNewUrl;
458 if ( rNewFilter != aFilterName )
459 aFilterName = rNewFilter;
460 if ( rNewArea != aSourceArea )
461 aSourceArea = rNewArea;
462 if ( aNewOpt != aOptions )
463 aOptions = aNewOpt;
464
465 if ( aNewRange != aDestArea )
466 aDestArea = aNewRange;
467
468 if ( nNewRefresh != GetRefreshDelay() )
469 SetRefreshDelay( nNewRefresh );
470
471 SCCOL nPaintEndX = Max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() );
472 SCROW nPaintEndY = Max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() );
473
474 if ( aOldRange.aEnd.Col() != aNewRange.aEnd.Col() )
475 nPaintEndX = MAXCOL;
476 if ( aOldRange.aEnd.Row() != aNewRange.aEnd.Row() )
477 nPaintEndY = MAXROW;
478
479 if ( !pImpl->m_pDocSh->AdjustRowHeight( aDestPos.Row(), nPaintEndY, nDestTab ) )
480 pImpl->m_pDocSh->PostPaint( aDestPos.Col(),aDestPos.Row(),nDestTab,
481 nPaintEndX,nPaintEndY,nDestTab, PAINT_GRID );
482 aModificator.SetDocumentModified();
483 }
484 else
485 {
486 // CanFitBlock sal_False -> Probleme mit zusammengefassten Zellen
487 // oder Tabellengrenze erreicht!
488 //! Zellschutz ???
489
490 //! Link-Dialog muss Default-Parent setzen
491 // "kann keine Zeilen einfuegen"
492 InfoBox aBox( Application::GetDefDialogParent(),
493 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_2 ) );
494 aBox.Execute();
495 }
496
497 // aufraeumen
498
499 aRef->DoClose();
500
501 pDoc->SetInLinkUpdate( sal_False );
502
503 if (bCanDo)
504 {
505 // notify Uno objects (for XRefreshListener)
506 //! also notify Uno objects if file name was changed!
507 ScLinkRefreshedHint aHint;
508 aHint.SetAreaLink( aDestPos );
509 pDoc->BroadcastUno( aHint );
510 }
511
512 return bCanDo;
513 }
514
515
IMPL_LINK(ScAreaLink,RefreshHdl,ScAreaLink *,EMPTYARG)516 IMPL_LINK( ScAreaLink, RefreshHdl, ScAreaLink*, EMPTYARG )
517 {
518 long nRes = Refresh( aFileName, aFilterName, aSourceArea,
519 GetRefreshDelay() ) != 0;
520 return nRes;
521 }
522
IMPL_LINK(ScAreaLink,AreaEndEditHdl,void *,EMPTYARG)523 IMPL_LINK( ScAreaLink, AreaEndEditHdl, void*, EMPTYARG )
524 {
525 // #i76514# can't use link argument to access the dialog,
526 // because it's the ScLinkedAreaDlg, not AbstractScLinkedAreaDlg
527
528 if ( pImpl->m_pDialog && pImpl->m_pDialog->GetResult() == RET_OK )
529 {
530 aOptions = pImpl->m_pDialog->GetOptions();
531 Refresh( pImpl->m_pDialog->GetURL(), pImpl->m_pDialog->GetFilter(),
532 pImpl->m_pDialog->GetSource(), pImpl->m_pDialog->GetRefresh() );
533
534 // copy source data from members (set in Refresh) into link name for dialog
535 String aNewLinkName;
536 sfx2::MakeLnkName( aNewLinkName, NULL, aFileName, aSourceArea, &aFilterName );
537 SetName( aNewLinkName );
538 }
539 pImpl->m_pDialog = NULL; // dialog is deleted with parent
540
541 return 0;
542 }
543
544