xref: /trunk/main/cui/source/dialogs/linkdlg.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cui.hxx"
30 
31 #include <linkdlg.hxx>
32 #include <vcl/svapp.hxx>
33 #include "helpid.hrc"
34 
35 #include <tools/urlobj.hxx>
36 #include <svtools/svmedit.hxx>
37 #include <svtools/filedlg.hxx>
38 #include <vcl/dialog.hxx>
39 #include <vcl/button.hxx>
40 #include <vcl/fixed.hxx>
41 #include <vcl/group.hxx>
42 #include <vcl/lstbox.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <vcl/timer.hxx>
45 #include <svtools/svtabbx.hxx>
46 
47 #include <svuidlg.hrc>
48 #include <sfx2/linkmgr.hxx>
49 #include <sfx2/linksrc.hxx>
50 #include <svtools/soerr.hxx>
51 #include <sfx2/lnkbase.hxx>
52 #include <sfx2/objsh.hxx>
53 
54 #include <dialmgr.hxx>
55 
56 #define _SVSTDARR_USHORTS
57 #include <svl/svstdarr.hxx>
58 
59 #define MAX_FILENAME	18
60 #define MAX_LINKNAME	18
61 #define MAX_TYPENAME	15
62 #define MAX_UPDATENAME	10
63 
64 #define FILEOBJECT ( OBJECT_CLIENT_FILE & ~OBJECT_CLIENT_SO )
65 
66 using namespace sfx2;
67 
68 SV_DECL_IMPL_REF_LIST(SvBaseLink,SvBaseLink*)
69 
70 // Achtung im Code wird dieses Array direkt (0, 1, ...) indiziert
71 static long nTabs[] =
72 	{	4, // Number of Tabs
73 		0, 77, 144, 209
74 	};
75 
76 
77 SvBaseLinksDlg::SvBaseLinksDlg( Window * pParent, LinkManager* pMgr, sal_Bool bHtml )
78     : ModalDialog( pParent, CUI_RES( MD_UPDATE_BASELINKS ) ),
79     aFtFiles( this, CUI_RES( FT_FILES ) ),
80     aFtLinks( this, CUI_RES( FT_LINKS ) ),
81     aFtType( this, CUI_RES( FT_TYPE ) ),
82     aFtStatus( this, CUI_RES( FT_STATUS ) ),
83     aTbLinks( this, CUI_RES(TB_LINKS ) ),
84     aFtFiles2( this, CUI_RES( FT_FILES2 ) ),
85     aFtFullFileName( this, CUI_RES( FT_FULL_FILE_NAME ) ),
86     aFtSource2( this, CUI_RES( FT_SOURCE2 ) ),
87     aFtFullSourceName( this, CUI_RES( FT_FULL_SOURCE_NAME ) ),
88     aFtType2( this, CUI_RES( FT_TYPE2 ) ),
89     aFtFullTypeName( this, CUI_RES( FT_FULL_TYPE_NAME ) ),
90     aFtUpdate( this, CUI_RES( FT_UPDATE ) ),
91     aRbAutomatic( this, CUI_RES( RB_AUTOMATIC ) ),
92     aRbManual( this, CUI_RES( RB_MANUAL ) ),
93     aCancelButton1( this, CUI_RES( 1 ) ),
94     aHelpButton1( this, CUI_RES( 1 ) ),
95     aPbUpdateNow( this, CUI_RES( PB_UPDATE_NOW ) ),
96     aPbOpenSource( this, CUI_RES( PB_OPEN_SOURCE ) ),
97     aPbChangeSource( this, CUI_RES( PB_CHANGE_SOURCE ) ),
98     aPbBreakLink( this, CUI_RES( PB_BREAK_LINK ) ),
99     aStrAutolink( CUI_RES( STR_AUTOLINK ) ),
100     aStrManuallink( CUI_RES( STR_MANUALLINK ) ),
101     aStrBrokenlink( CUI_RES( STR_BROKENLINK ) ),
102     aStrGraphiclink( CUI_RES( STR_GRAPHICLINK ) ),
103     aStrButtonclose( CUI_RES( STR_BUTTONCLOSE ) ),
104     aStrCloselinkmsg( CUI_RES( STR_CLOSELINKMSG ) ),
105     aStrCloselinkmsgMulti( CUI_RES( STR_CLOSELINKMSG_MULTI ) ),
106     aStrWaitinglink( CUI_RES( STR_WAITINGLINK ) ),
107     pLinkMgr( NULL ),
108 	bHtmlMode(bHtml)
109 {
110     FreeResource();
111 
112     aTbLinks.SetHelpId(HID_LINKDLG_TABLB);
113     aTbLinks.SetSelectionMode( MULTIPLE_SELECTION );
114     aTbLinks.SetTabs( &nTabs[0], MAP_APPFONT );
115     aTbLinks.Resize();  // OS: Hack fuer richtige Selektion
116 
117     //JP 24.02.99: UpdateTimer fuer DDE-/Grf-Links, auf die gewarted wird
118     aUpdateTimer.SetTimeoutHdl( LINK( this, SvBaseLinksDlg, UpdateWaitingHdl ) );
119     aUpdateTimer.SetTimeout( 1000 );
120 	//IAccessibility2 Implementation 2009-----
121 	// Set the ZOrder, and accessible name to the dialog's title
122 	aTbLinks.SetZOrder(0, WINDOW_ZORDER_FIRST);
123 	aTbLinks.SetAccessibleName(this->GetText());
124 	aTbLinks.SetAccessibleRelationLabeledBy(&aFtFiles);
125 	//-----IAccessibility2 Implementation 2009
126 
127     OpenSource().Hide();
128 
129     Links().SetSelectHdl( LINK( this, SvBaseLinksDlg, LinksSelectHdl ) );
130     Links().SetDoubleClickHdl( LINK( this, SvBaseLinksDlg, LinksDoubleClickHdl ) );
131     Automatic().SetClickHdl( LINK( this, SvBaseLinksDlg, AutomaticClickHdl ) );
132     Manual().SetClickHdl( LINK( this, SvBaseLinksDlg, ManualClickHdl ) );
133     UpdateNow().SetClickHdl( LINK( this, SvBaseLinksDlg, UpdateNowClickHdl ) );
134 //  OpenSource().SetClickHdl( LINK( this, SvBaseLinksDlg, OpenSourceClickHdl ) );
135     ChangeSource().SetClickHdl( LINK( this, SvBaseLinksDlg, ChangeSourceClickHdl ) );
136 	if(!bHtmlMode)
137         BreakLink().SetClickHdl( LINK( this, SvBaseLinksDlg, BreakLinkClickHdl ) );
138 	else
139         BreakLink().Hide();
140 
141 	SetManager( pMgr );
142 }
143 
144 SvBaseLinksDlg::~SvBaseLinksDlg()
145 {
146 }
147 
148 /*************************************************************************
149 |*    SvBaseLinksDlg::Handler()
150 |*
151 |*	  Beschreibung
152 |*	  Ersterstellung	MM 14.06.94
153 |*	  Letzte Aenderung	JP 30.05.95
154 *************************************************************************/
155 IMPL_LINK( SvBaseLinksDlg, LinksSelectHdl, SvTabListBox *, pSvTabListBox )
156 {
157 	sal_uInt16 nSelectionCount = pSvTabListBox ?
158 		(sal_uInt16)pSvTabListBox->GetSelectionCount() : 0;
159 	if(nSelectionCount > 1)
160 	{
161 		//bei Mehrfachselektion ggf. alte Eintraege deselektieren
162 		SvLBoxEntry* pEntry = 0;
163 		SvBaseLink* pLink = 0;
164 		pEntry = pSvTabListBox->GetHdlEntry();
165 		pLink = (SvBaseLink*)pEntry->GetUserData();
166 		sal_uInt16 nObjectType = pLink->GetObjType();
167 		if((OBJECT_CLIENT_FILE & nObjectType) != OBJECT_CLIENT_FILE)
168 		{
169 			pSvTabListBox->SelectAll(sal_False);
170 			pSvTabListBox->Select(pEntry);
171 			nSelectionCount = 1;
172 		}
173 		else
174 		{
175 			for( sal_uInt16 i = 0; i < nSelectionCount; i++)
176 			{
177 				pEntry = i == 0 ? pSvTabListBox->FirstSelected() :
178 									pSvTabListBox->NextSelected(pEntry);
179 				DBG_ASSERT(pEntry, "Wo ist der Entry?");
180 				pLink = (SvBaseLink*)pEntry->GetUserData();
181 				DBG_ASSERT(pLink, "Wo ist der Link?");
182 				if( (OBJECT_CLIENT_FILE & pLink->GetObjType()) != OBJECT_CLIENT_FILE )
183 					pSvTabListBox->Select( pEntry, sal_False );
184 
185 			}
186 		}
187 
188         UpdateNow().Enable();
189 
190         Automatic().Disable();
191         Manual().Check();
192         Manual().Disable();
193 	}
194 	else
195 	{
196 		sal_uInt16 nPos;
197 		SvBaseLink* pLink = GetSelEntry( &nPos );
198 		if( !pLink )
199 			return 0;
200 
201         UpdateNow().Enable();
202 
203 		String sType, sLink;
204 		String *pLinkNm = &sLink, *pFilter = 0;
205 
206 		if( FILEOBJECT & pLink->GetObjType() )
207 		{
208             Automatic().Disable();
209             Manual().Check();
210             Manual().Disable();
211 			if( OBJECT_CLIENT_GRF == pLink->GetObjType() )
212 				pLinkNm = 0, pFilter = &sLink;
213 		}
214 		else
215 		{
216             Automatic().Enable();
217             Manual().Enable();
218 
219 			if( LINKUPDATE_ALWAYS == pLink->GetUpdateMode() )
220                 Automatic().Check();
221 			else
222                 Manual().Check();
223 		}
224 
225 		String aFileName;
226 		pLinkMgr->GetDisplayNames( pLink, &sType, &aFileName, pLinkNm, pFilter );
227         aFileName = INetURLObject::decode(aFileName, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
228         FileName().SetText( aFileName );
229         SourceName().SetText( sLink );
230         TypeName().SetText( sType );
231 	}
232 	return 0;
233 }
234 
235 IMPL_LINK_INLINE_START( SvBaseLinksDlg, LinksDoubleClickHdl, SvTabListBox *, pSvTabListBox )
236 {
237 	(void)pSvTabListBox;
238 
239 	ChangeSourceClickHdl( 0 );
240 	return 0;
241 }
242 IMPL_LINK_INLINE_END( SvBaseLinksDlg, LinksDoubleClickHdl, SvTabListBox *, pSvTabListBox )
243 
244 IMPL_LINK_INLINE_START( SvBaseLinksDlg, AutomaticClickHdl, RadioButton *, pRadioButton )
245 {
246 	(void)pRadioButton;
247 
248 	sal_uInt16 nPos;
249 	SvBaseLink* pLink = GetSelEntry( &nPos );
250 	if( pLink && !( FILEOBJECT & pLink->GetObjType() ) &&
251 		LINKUPDATE_ALWAYS != pLink->GetUpdateMode() )
252 		SetType( *pLink, nPos, LINKUPDATE_ALWAYS );
253 	return 0;
254 }
255 IMPL_LINK_INLINE_END( SvBaseLinksDlg, AutomaticClickHdl, RadioButton *, pRadioButton )
256 
257 IMPL_LINK_INLINE_START( SvBaseLinksDlg, ManualClickHdl, RadioButton *, pRadioButton )
258 {
259 	(void)pRadioButton;
260 
261 	sal_uInt16 nPos;
262 	SvBaseLink* pLink = GetSelEntry( &nPos );
263 	if( pLink && !( FILEOBJECT & pLink->GetObjType() ) &&
264 		LINKUPDATE_ONCALL != pLink->GetUpdateMode())
265 		SetType( *pLink, nPos, LINKUPDATE_ONCALL );
266 	return 0;
267 }
268 IMPL_LINK_INLINE_END( SvBaseLinksDlg, ManualClickHdl, RadioButton *, pRadioButton )
269 
270 IMPL_LINK( SvBaseLinksDlg, UpdateNowClickHdl, PushButton *, EMPTYARG )
271 {
272     SvTabListBox& rListBox = Links();
273 	sal_uInt16 nSelCnt = (sal_uInt16)rListBox.GetSelectionCount();
274 	if( 255 < nSelCnt )
275 		nSelCnt = 255;
276 
277 	std::vector< SvBaseLink* > aLnkArr;
278 	std::vector< sal_uInt16 > aPosArr;
279 
280 	SvLBoxEntry* pE = rListBox.FirstSelected();
281 	while( pE )
282 	{
283 		sal_uInt16 nFndPos = (sal_uInt16)rListBox.GetModel()->GetAbsPos( pE );
284 		if( LISTBOX_ENTRY_NOTFOUND != nFndPos )
285 		{
286 			aLnkArr.push_back( static_cast< SvBaseLink* >( pE->GetUserData() ) );
287 			aPosArr.push_back( nFndPos );
288 		}
289 		pE = rListBox.NextSelected( pE );
290 	}
291 
292 	if( !aLnkArr.empty() )
293 	{
294 		for( sal_uInt16 n = 0; n < aLnkArr.size(); ++n )
295 		{
296 			SvBaseLinkRef xLink = aLnkArr[ n ];
297 
298 			// suche erstmal im Array nach dem Eintrag
299 			for( sal_uInt16 i = 0; i < pLinkMgr->GetLinks().Count(); ++i )
300 				if( &xLink == *pLinkMgr->GetLinks()[ i ] )
301 				{
302 					xLink->SetUseCache( sal_False );
303 					SetType( *xLink, aPosArr[ n ], xLink->GetUpdateMode() );
304 					xLink->SetUseCache( sal_True );
305 					break;
306 				}
307 		}
308 
309 		// falls jemand der Meinung ist, seine Links auszutauschen (SD)
310 		LinkManager* pNewMgr = pLinkMgr;
311 		pLinkMgr = 0;
312 		SetManager( pNewMgr );
313 
314 
315 		if( 0 == (pE = rListBox.GetEntry( aPosArr[ 0 ] )) ||
316 			pE->GetUserData() != aLnkArr[ 0 ] )
317 		{
318 			// suche mal den Link
319 			pE = rListBox.First();
320 			while( pE )
321 			{
322 				if( pE->GetUserData() == aLnkArr[ 0 ] )
323 					break;
324 				pE = rListBox.Next( pE );
325 			}
326 
327 			if( !pE )
328 				pE = rListBox.FirstSelected();
329 		}
330 
331 		if( pE )
332 		{
333 			SvLBoxEntry* pSelEntry = rListBox.FirstSelected();
334 			if( pE != pSelEntry )
335 				rListBox.Select( pSelEntry, sal_False );
336 			rListBox.Select( pE );
337 			rListBox.MakeVisible( pE );
338 		}
339 	}
340 	return 0;
341 }
342 
343 /*
344 IMPL_LINK_INLINE_START( SvBaseLinksDlg, OpenSourceClickHdl, PushButton *, pPushButton )
345 {
346 	DBG_ASSERT( !this, "Open noch nicht impl." );
347 	return 0;
348 }
349 IMPL_LINK_INLINE_END( SvBaseLinksDlg, OpenSourceClickHdl, PushButton *, pPushButton )
350 */
351 
352 IMPL_LINK( SvBaseLinksDlg, ChangeSourceClickHdl, PushButton *, pPushButton )
353 {
354 	(void)pPushButton;
355 
356     sal_uInt16 nSelectionCount = (sal_uInt16)Links().GetSelectionCount();
357 	if(nSelectionCount > 1)
358 	{
359         PathDialog aPathDlg( this );
360 		String sType, sFile, sLinkName;
361 		String  sFilter;
362         SvLBoxEntry* pEntry = Links().FirstSelected();
363 		SvBaseLink* pLink = (SvBaseLink*)pEntry->GetUserData();
364 		pLinkMgr->GetDisplayNames( pLink, &sType, &sFile, 0, 0 );
365 		INetURLObject aUrl(sFile);
366 		if(aUrl.GetProtocol() == INET_PROT_FILE)
367 		{
368 			rtl::OUString sOldPath(aUrl.PathToFileName());
369 			sal_Int32 nLen = aUrl.GetName().getLength();
370 			sOldPath = sOldPath.copy(0, sOldPath.getLength() - nLen);
371 			aPathDlg.SetPath(sOldPath);
372 		}
373 		if(aPathDlg.Execute() == RET_OK)
374 		{
375 			String aPath = aPathDlg.GetPath();
376 
377 			for( sal_uInt16 i = 0; i < nSelectionCount; i++)
378 			{
379 				pEntry = i==0 ?
380                         Links().FirstSelected() :
381                             Links().NextSelected( pEntry );
382 				DBG_ASSERT(pEntry,"Wo ist der Entry");
383 				pLink = (SvBaseLink*)pEntry->GetUserData();
384 				DBG_ASSERT(pLink,"Wo ist der Link");
385 				pLinkMgr->GetDisplayNames( pLink, &sType, &sFile, &sLinkName, &sFilter );
386 				INetURLObject aUrl_(sFile);
387 				INetURLObject aUrl2(aPath, INET_PROT_FILE);
388 				aUrl2.insertName( aUrl_.getName() );
389 				String sNewLinkName;
390                 MakeLnkName( sNewLinkName, 0 ,
391 						aUrl2.GetMainURL(INetURLObject::DECODE_TO_IURI), sLinkName, &sFilter);
392 				pLink->SetLinkSourceName( sNewLinkName );
393 				pLink->Update();
394 			}
395 			if( pLinkMgr->GetPersist() )
396 				pLinkMgr->GetPersist()->SetModified();
397 			LinkManager* pNewMgr = pLinkMgr;
398 			pLinkMgr = 0;
399 			SetManager( pNewMgr );
400 		}
401 	}
402 	else
403 	{
404 		sal_uInt16 nPos;
405 		SvBaseLink* pLink = GetSelEntry( &nPos );
406         if ( pLink && (pLink->GetLinkSourceName().Len() != 0) )
407             pLink->Edit( this, LINK( this, SvBaseLinksDlg, EndEditHdl ) );
408 	}
409 	return 0;
410 }
411 
412 IMPL_LINK( SvBaseLinksDlg, BreakLinkClickHdl, PushButton *, pPushButton )
413 {
414 	(void)pPushButton;
415 
416 	sal_Bool bModified = sal_False;
417     if(Links().GetSelectionCount() <= 1)
418 	{
419 		sal_uInt16 nPos;
420 		SvBaseLinkRef xLink = GetSelEntry( &nPos );
421 		if( !xLink.Is() )
422 			return 0;
423 
424         QueryBox aBox( this, WB_YES_NO | WB_DEF_YES, Closelinkmsg() );
425 
426 		if( RET_YES == aBox.Execute() )
427 		{
428             Links().GetModel()->Remove( Links().GetEntry( nPos ) );
429 
430 			// falls Object noch vorhanden, dann das schliessen
431 			sal_Bool bNewLnkMgr = OBJECT_CLIENT_FILE == xLink->GetObjType();
432 
433 			// dem Link sagen, das er aufgeloest wird!
434 			xLink->Closed();
435 
436 			// falls einer vergessen hat sich auszutragen
437 			if( xLink.Is() )
438 				pLinkMgr->Remove( &xLink );
439 
440 			if( bNewLnkMgr )
441 			{
442 				LinkManager* pNewMgr = pLinkMgr;
443 				pLinkMgr = 0;
444 				SetManager( pNewMgr );
445 
446                 SvLBoxEntry* pEntry = Links().GetEntry( nPos ? --nPos : 0 );
447 				if( pEntry )
448                     Links().SetCurEntry( pEntry );
449 			}
450 			bModified = sal_True;
451 		}
452 	}
453 	else
454 	{
455         QueryBox aBox( this, WB_YES_NO | WB_DEF_YES, CloselinkmsgMulti() );
456 
457 		if( RET_YES == aBox.Execute() )
458 		{
459 
460 			SvBaseLinkMemberList aLinkList;
461             SvLBoxEntry* pEntry = Links().FirstSelected();
462 			while ( pEntry )
463 			{
464 				void * pUD = pEntry->GetUserData();
465 				if( pUD )
466 					aLinkList.Append( (SvBaseLink*)pUD );
467                 pEntry = Links().NextSelected(pEntry);
468 			}
469             Links().RemoveSelection();
470 			for( sal_uLong i = 0; i < aLinkList.Count(); i++ )
471 			{
472 				SvBaseLinkRef xLink = aLinkList.GetObject( i );
473 				// dem Link sagen, das er aufgeloest wird!
474 				xLink->Closed();
475 
476 				// falls einer vergessen hat sich auszutragen
477 				pLinkMgr->Remove( &xLink );
478 				bModified = sal_True;
479 			}
480 			//Danach alle selektierten Eintraege entfernen
481 		}
482 	}
483 	if(bModified)
484 	{
485         if( !Links().GetEntryCount() )
486 		{
487 			// Der letzte macht das Licht aus
488             Automatic().Disable();
489             Manual().Disable();
490             UpdateNow().Disable();
491 //            OpenSource().Disable();
492             ChangeSource().Disable();
493             BreakLink().Disable();
494 
495 			String aEmpty;
496             SourceName().SetText( aEmpty );
497             TypeName().SetText( aEmpty );
498 		}
499 		if( pLinkMgr->GetPersist() )
500 			pLinkMgr->GetPersist()->SetModified();
501 	}
502 	return 0;
503 }
504 
505 IMPL_LINK( SvBaseLinksDlg, UpdateWaitingHdl, Timer*, pTimer )
506 {
507 	(void)pTimer;
508 //    for( SvLBoxEntry* pBox = Links().First(); pBox;
509 //          pBox = Links().Next( pBox ))
510 
511     Links().SetUpdateMode(sal_False);
512     for( sal_uLong nPos = Links().GetEntryCount(); nPos; )
513 	{
514         SvLBoxEntry* pBox = Links().GetEntry( --nPos );
515 		SvBaseLinkRef xLink( (SvBaseLink*)pBox->GetUserData() );
516 		if( xLink.Is() )
517 		{
518 			String sCur( ImplGetStateStr( *xLink ) ),
519                     sOld( Links().GetEntryText( pBox, 3 ) );
520 			if( sCur != sOld )
521                 Links().SetEntryText( sCur, pBox, 3 );
522 		}
523 	}
524     Links().SetUpdateMode(sal_True);
525 	return 0;
526 }
527 
528 IMPL_LINK( SvBaseLinksDlg, EndEditHdl, sfx2::SvBaseLink*, _pLink )
529 {
530     sal_uInt16 nPos;
531     GetSelEntry( &nPos );
532 
533     if( _pLink && _pLink->WasLastEditOK() )
534     {
535         // JP 09.01.98:
536         // StarImpress/Draw tauschen die LinkObjecte selbst aus!
537         // also suche den Link im Manager, wenn der nicht mehr existiert,
538         // dann setze fuelle die Liste komplett neu. Ansonsten braucht
539         // nur der editierte Linkt aktualisiert werden.
540         sal_Bool bLinkFnd = sal_False;
541         for( sal_uInt16 n = pLinkMgr->GetLinks().Count(); n;  )
542             if( _pLink == &(*pLinkMgr->GetLinks()[ --n ]) )
543             {
544                 bLinkFnd = sal_True;
545                 break;
546             }
547 
548         if( bLinkFnd )
549         {
550             Links().SetUpdateMode(sal_False);
551             Links().GetModel()->Remove( Links().GetEntry( nPos ) );
552             SvLBoxEntry* pToUnselect = Links().FirstSelected();
553             InsertEntry( *_pLink, nPos, sal_True );
554             if(pToUnselect)
555                 Links().Select(pToUnselect, sal_False);
556             Links().SetUpdateMode(sal_True);
557         }
558         else
559         {
560             LinkManager* pNewMgr = pLinkMgr;
561             pLinkMgr = 0;
562             SetManager( pNewMgr );
563         }
564         if( pLinkMgr->GetPersist() )
565             pLinkMgr->GetPersist()->SetModified();
566     }
567     return 0;
568 }
569 
570 String SvBaseLinksDlg::ImplGetStateStr( const SvBaseLink& rLnk )
571 {
572 	String sRet;
573 	if( !rLnk.GetObj() )
574         sRet = Brokenlink();
575 	else if( rLnk.GetObj()->IsPending() )
576 	{
577         sRet = Waitinglink();
578         StartUpdateTimer();
579 	}
580 	else if( LINKUPDATE_ALWAYS == rLnk.GetUpdateMode() )
581         sRet = Autolink();
582 	else
583         sRet = Manuallink();
584 
585 	return sRet;
586 }
587 
588 void SvBaseLinksDlg::SetManager( LinkManager* pNewMgr )
589 {
590 	if( pLinkMgr == pNewMgr )
591 		return;
592 
593 	if( pNewMgr )
594 		// Update muss vor Clear gestoppt werden
595         Links().SetUpdateMode( sal_False );
596 
597     Links().Clear();
598 	pLinkMgr = pNewMgr;
599 
600 	if( pLinkMgr )
601 	{
602 		SvBaseLinks& rLnks = (SvBaseLinks&)pLinkMgr->GetLinks();
603 		for( sal_uInt16 n = 0; n < rLnks.Count(); ++n )
604 		{
605 			SvBaseLinkRef* pLinkRef = rLnks[ n ];
606 			if( !pLinkRef->Is() )
607 			{
608 				rLnks.Remove( n, 1 );
609 				--n;
610 				continue;
611 			}
612 			if( (*pLinkRef)->IsVisible() )
613 				InsertEntry( **pLinkRef );
614 		}
615 
616 		if( rLnks.Count() )
617 		{
618             SvLBoxEntry* pEntry = Links().GetEntry( 0 );
619             Links().SetCurEntry( pEntry );
620             Links().Select( pEntry );
621 			LinksSelectHdl( 0 );
622 		}
623         Links().SetUpdateMode( sal_True );
624         Links().Invalidate();
625 	}
626 }
627 
628 
629 void SvBaseLinksDlg::InsertEntry( const SvBaseLink& rLink, sal_uInt16 nPos, sal_Bool bSelect )
630 {
631 	String aEntry, sFileNm, sLinkNm, sTypeNm, sFilter;
632 
633 	pLinkMgr->GetDisplayNames( (SvBaseLink*)&rLink, &sTypeNm, &sFileNm, &sLinkNm, &sFilter );
634 
635 	// GetTab(0) gibt die Position der von der TabListBox automatisch eingefuegten
636 	// Bitmap. Die Breite der ersten Textspalte ergibt sich deshalb aus Tab(2)-Tab(1)
637     long nWidthPixel = Links().GetLogicTab( 2 ) - Links().GetLogicTab( 1 );
638 	nWidthPixel -= SV_TAB_BORDER;
639     XubString aTxt = Links().GetEllipsisString( sFileNm, nWidthPixel, TEXT_DRAW_PATHELLIPSIS );
640 	INetURLObject aPath( sFileNm, INET_PROT_FILE );
641 	String aFileName = aPath.getName();
642     aFileName = INetURLObject::decode(aFileName, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
643 
644     if( aFileName.Len() > aTxt.Len() )
645 		aTxt = aFileName;
646 	else if( aTxt.Search( aFileName, aTxt.Len() - aFileName.Len() ) == STRING_NOTFOUND )
647 		// filename not in string
648 		aTxt = aFileName;
649 
650 	aEntry = aTxt;
651 	aEntry += '\t';
652 	if( OBJECT_CLIENT_GRF == rLink.GetObjType() )
653 		aEntry += sFilter;
654 	else
655 		aEntry += sLinkNm;
656 	aEntry += '\t';
657 	aEntry += sTypeNm;
658 	aEntry += '\t';
659 	aEntry += ImplGetStateStr( rLink );
660 
661     SvLBoxEntry * pE = Links().InsertEntryToColumn( aEntry, nPos );
662 	pE->SetUserData( (void*)&rLink );
663     if(bSelect)
664         Links().Select(pE);
665 }
666 
667 SvBaseLink* SvBaseLinksDlg::GetSelEntry( sal_uInt16* pPos )
668 {
669     SvLBoxEntry* pE = Links().FirstSelected();
670 	sal_uInt16 nPos;
671 	if( pE && LISTBOX_ENTRY_NOTFOUND !=
672         ( nPos = (sal_uInt16)Links().GetModel()->GetAbsPos( pE ) ) )
673 	{
674 		DBG_ASSERT( pE, "wo kommt der leere Eintrag her?" );
675 
676 		if( pPos )
677 			*pPos = nPos;
678 		return (SvBaseLink*)pE->GetUserData();
679 	}
680 	return 0;
681 }
682 
683 void SvBaseLinksDlg::SetType( SvBaseLink& rLink,
684 									sal_uInt16 nSelPos,
685 									sal_uInt16 nType )
686 {
687 	rLink.SetUpdateMode( nType );
688 	rLink.Update();
689     SvLBoxEntry* pBox = Links().GetEntry( nSelPos );
690     Links().SetEntryText( ImplGetStateStr( rLink ), pBox, 3 );
691 	if( pLinkMgr->GetPersist() )
692 		pLinkMgr->GetPersist()->SetModified();
693 }
694 
695 void SvBaseLinksDlg::SetActLink( SvBaseLink * pLink )
696 {
697 	if( pLinkMgr )
698 	{
699 		const SvBaseLinks& rLnks = pLinkMgr->GetLinks();
700         sal_uInt16 nSelect = 0;
701         for( sal_uInt16 n = 0; n < rLnks.Count(); ++n )
702         {
703             SvBaseLinkRef* pLinkRef = rLnks[ n ];
704             // #109573# only visible links have been inserted into the TreeListBox,
705             // invisible ones have to be skipped here
706             if( (*pLinkRef)->IsVisible() )
707             {
708                 if( pLink == *pLinkRef )
709                 {
710                     Links().Select( Links().GetEntry( nSelect ) );
711                     LinksSelectHdl( 0 );
712                     return ;
713                 }
714                 nSelect++;
715             }
716         }
717 	}
718 }
719 
720