xref: /AOO41X/main/cui/source/options/optjava.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 ---------------------------------------------------------------
32 
33 #include "optjava.hxx"
34 #include <dialmgr.hxx>
35 
36 #include "optjava.hrc"
37 #include <cuires.hrc>
38 #include "helpid.hrc"
39 #include <vcl/svapp.hxx>
40 #include <vcl/help.hxx>
41 #include <tools/urlobj.hxx>
42 #include <vcl/msgbox.hxx>
43 #include <vcl/waitobj.hxx>
44 #include <unotools/pathoptions.hxx>
45 #include <svtools/imagemgr.hxx>
46 #include <sfx2/filedlghelper.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <ucbhelper/contentbroker.hxx>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
51 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
52 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
53 #include <com/sun/star/ucb/XContentProvider.hpp>
54 #include <jvmfwk/framework.h>
55 
56 // define ----------------------------------------------------------------
57 
58 #define CLASSPATH_DELIMITER	SAL_PATHSEPARATOR
59 #define STRIM( s )			s.EraseLeadingChars().EraseTrailingChars()
60 #define BUTTON_BORDER		2
61 #define	RESET_TIMEOUT		300
62 
63 using namespace ::com::sun::star::lang;
64 using namespace ::com::sun::star::ucb;
65 using namespace ::com::sun::star::ui::dialogs;
66 using namespace ::com::sun::star::uno;
67 
68 // -----------------------------------------------------------------------
69 
70 bool areListsEqual( const Sequence< ::rtl::OUString >& rListA, const Sequence< ::rtl::OUString >& rListB )
71 {
72 	bool bRet = true;
73 	const sal_Int32 nLen = rListA.getLength();
74 
75 	if (  rListB.getLength() != nLen )
76 		bRet = false;
77 	else
78 	{
79 		const ::rtl::OUString* pStringA = rListA.getConstArray();
80 		const ::rtl::OUString* pStringB = rListB.getConstArray();
81 
82 		for ( sal_Int32 i = 0; i < nLen; ++i )
83 		{
84 			if ( *pStringA++ != *pStringB++ )
85 			{
86 				bRet = false;
87 				break;
88 			}
89 		}
90 	}
91 
92 	return bRet;
93 }
94 
95 // class SvxJavaOptionsPage ----------------------------------------------
96 
97 SvxJavaOptionsPage::SvxJavaOptionsPage( Window* pParent, const SfxItemSet& rSet ) :
98 
99 	SfxTabPage( pParent, CUI_RES( RID_SVXPAGE_OPTIONS_JAVA ), rSet ),
100 
101 	m_aJavaLine			( this, CUI_RES( FL_JAVA ) ),
102 	m_aJavaEnableCB		( this, CUI_RES( CB_JAVA_ENABLE ) ),
103 	m_aJavaFoundLabel	( this, CUI_RES( FT_JAVA_FOUND ) ),
104 	m_aJavaList			( this, CUI_RES( LB_JAVA ) ),
105 	m_aJavaPathText		( this, CUI_RES( FT_JAVA_PATH ) ),
106 	m_aAddBtn			( this, CUI_RES( PB_ADD ) ),
107 	m_aParameterBtn		( this, CUI_RES( PB_PARAMETER ) ),
108 	m_aClassPathBtn		( this, CUI_RES( PB_CLASSPATH ) ),
109 
110 	m_pParamDlg			( NULL ),
111 	m_pPathDlg			( NULL ),
112 	m_parJavaInfo		( NULL ),
113 	m_parParameters		( NULL ),
114 	m_pClassPath		( NULL ),
115 	m_nInfoSize			( 0 ),
116 	m_nParamSize		( 0 ),
117 	m_sInstallText		( 		CUI_RES( STR_INSTALLED_IN ) ),
118 	m_sAccessibilityText(		CUI_RES( STR_ACCESSIBILITY ) ),
119     m_sAddDialogText    (       CUI_RES( STR_ADDDLGTEXT ) ),
120 
121     xDialogListener     ( new ::svt::DialogClosedListener() )
122 
123 {
124 	m_aJavaEnableCB.SetClickHdl( LINK( this, SvxJavaOptionsPage, EnableHdl_Impl ) );
125 	m_aJavaList.SetCheckButtonHdl( LINK( this, SvxJavaOptionsPage, CheckHdl_Impl ) );
126 	m_aJavaList.SetSelectHdl( LINK( this, SvxJavaOptionsPage, SelectHdl_Impl ) );
127 	m_aAddBtn.SetClickHdl( LINK( this, SvxJavaOptionsPage, AddHdl_Impl ) );
128 	m_aParameterBtn.SetClickHdl( LINK( this, SvxJavaOptionsPage, ParameterHdl_Impl ) );
129 	m_aClassPathBtn.SetClickHdl( LINK( this, SvxJavaOptionsPage, ClassPathHdl_Impl ) );
130 	m_aResetTimer.SetTimeoutHdl( LINK( this, SvxJavaOptionsPage, ResetHdl_Impl ) );
131 	m_aResetTimer.SetTimeout( RESET_TIMEOUT );
132 
133 //!   m_aJavaList.EnableCheckButton( new SvLBoxButtonData( &m_aJavaList, true ) );
134 
135 	static long aStaticTabs[]=
136 	{
137 		5, 0, 15, 90, 130, 300
138 	};
139 
140 	m_aJavaList.SvxSimpleTable::SetTabs( aStaticTabs );
141 	String sHeader( '\t' );
142 	sHeader += String( CUI_RES( STR_HEADER_VENDOR ) );
143 	sHeader += '\t';
144 	sHeader += String( CUI_RES( STR_HEADER_VERSION ) );
145 	sHeader += '\t';
146 	sHeader += String( CUI_RES( STR_HEADER_FEATURES ) );
147 	sHeader += '\t';
148 	m_aJavaList.InsertHeaderEntry( sHeader, HEADERBAR_APPEND, HIB_LEFT );
149 
150     m_aJavaList.SetHelpId( HID_OPTIONS_JAVA_LIST );
151 
152 	FreeResource();
153 
154     xDialogListener->SetDialogClosedLink( LINK( this, SvxJavaOptionsPage, DialogClosedHdl ) );
155 
156     EnableHdl_Impl( &m_aJavaEnableCB );
157 	jfw_lock();
158 
159 	//check if the text fits into the class path button
160     Size aButtonSize = m_aClassPathBtn.GetOutputSizePixel();
161     sal_Int32 nTextWidth = m_aClassPathBtn.GetTextWidth(m_aClassPathBtn.GetText());
162     //add some additional space
163     sal_Int32 nDiff = nTextWidth + 4 - aButtonSize.Width();
164     if( nDiff > 0)
165     {
166         Point aPos(m_aClassPathBtn.GetPosPixel());
167         aPos.X() -= nDiff;
168         aButtonSize.Width() += nDiff;
169         m_aClassPathBtn.SetPosSizePixel(aPos, aButtonSize);
170         aPos = m_aAddBtn.GetPosPixel();
171         aPos.X() -= nDiff;
172         m_aAddBtn.SetPosSizePixel(aPos, aButtonSize);
173         aPos = m_aParameterBtn.GetPosPixel();
174         aPos.X() -= nDiff;
175         m_aParameterBtn.SetPosSizePixel(aPos, aButtonSize);
176         Size aSize = m_aJavaList.GetSizePixel();
177         aSize.Width() -= nDiff;
178         m_aJavaList.SetSizePixel(aSize);
179     }
180 }
181 
182 // -----------------------------------------------------------------------
183 
184 SvxJavaOptionsPage::~SvxJavaOptionsPage()
185 {
186 	delete m_pParamDlg;
187 	delete m_pPathDlg;
188 	ClearJavaInfo();
189 	std::vector< JavaInfo* >::iterator pIter;
190 	for ( pIter = m_aAddedInfos.begin(); pIter != m_aAddedInfos.end(); ++pIter )
191 	{
192 		JavaInfo* pInfo = *pIter;
193 		jfw_freeJavaInfo( pInfo );
194 	}
195 /*
196 	rtl_uString** pParamArr = m_parParameters;
197 	for ( sal_Int32 i = 0; i < m_nParamSize; ++i )
198 		rtl_uString_release( *pParamArr++ );
199 	rtl_freeMemory( m_parParameters );
200 	rtl_uString_release( m_pClassPath );
201 */
202 	jfw_unlock();
203 }
204 
205 // -----------------------------------------------------------------------
206 
207 IMPL_LINK( SvxJavaOptionsPage, EnableHdl_Impl, CheckBox *, EMPTYARG )
208 {
209 	sal_Bool bEnable = m_aJavaEnableCB.IsChecked();
210 	m_aJavaFoundLabel.Enable( bEnable );
211 	m_aJavaPathText.Enable( bEnable );
212 	m_aAddBtn.Enable( bEnable );
213 	m_aParameterBtn.Enable( bEnable );
214 	m_aClassPathBtn.Enable( bEnable );
215 
216     bEnable ? m_aJavaList.EnableTable() : m_aJavaList.DisableTable();
217 
218 	return 0;
219 }
220 
221 // -----------------------------------------------------------------------
222 
223 IMPL_LINK( SvxJavaOptionsPage, CheckHdl_Impl, SvxSimpleTable *, pList )
224 {
225 	SvLBoxEntry* pEntry = pList ? m_aJavaList.GetEntry( m_aJavaList.GetCurMousePoint() )
226 								: m_aJavaList.FirstSelected();
227     if ( pEntry )
228         m_aJavaList.HandleEntryChecked( pEntry );
229 	return 0;
230 }
231 
232 // -----------------------------------------------------------------------
233 
234 IMPL_LINK( SvxJavaOptionsPage, SelectHdl_Impl, SvxSimpleTable *, EMPTYARG )
235 {
236 	// set installation directory info
237 	SvLBoxEntry* pEntry = m_aJavaList.FirstSelected();
238 	DBG_ASSERT( pEntry, "SvxJavaOptionsPage::SelectHdl_Impl(): no entry" );
239 	String* pLocation = static_cast< String* >( pEntry->GetUserData() );
240 	DBG_ASSERT( pLocation, "invalid location string" );
241 	String sInfo = m_sInstallText;
242     if ( pLocation )
243         sInfo += *pLocation;
244 	m_aJavaPathText.SetText( sInfo );
245 	return 0;
246 }
247 
248 // -----------------------------------------------------------------------
249 
250 IMPL_LINK( SvxJavaOptionsPage, AddHdl_Impl, PushButton *, EMPTYARG )
251 {
252     try
253     {
254         Reference < XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
255         xFolderPicker = Reference< XFolderPicker >(
256             xMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FolderPicker" ) ), UNO_QUERY );
257 
258         String sWorkFolder = SvtPathOptions().GetWorkPath();
259         xFolderPicker->setDisplayDirectory( sWorkFolder );
260         xFolderPicker->setDescription( m_sAddDialogText );
261 
262         Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY );
263         if ( xAsyncDlg.is() )
264             xAsyncDlg->startExecuteModal( xDialogListener.get() );
265         else if ( xFolderPicker.is() && xFolderPicker->execute() == ExecutableDialogResults::OK )
266             AddFolder( xFolderPicker->getDirectory() );
267     }
268     catch ( Exception& )
269     {
270 #ifdef DBG_UTIL
271         DBG_ERRORFILE( "SvxJavaOptionsPage::AddHdl_Impl(): caught exception" );
272 #endif
273     }
274 
275     return 0;
276 }
277 
278 // -----------------------------------------------------------------------
279 
280 IMPL_LINK( SvxJavaOptionsPage, ParameterHdl_Impl, PushButton *, EMPTYARG )
281 {
282 	Sequence< ::rtl::OUString > aParameterList;
283 	if ( !m_pParamDlg )
284 	{
285 		m_pParamDlg = new SvxJavaParameterDlg( this );
286 		javaFrameworkError eErr = jfw_getVMParameters( &m_parParameters, &m_nParamSize );
287 		if ( JFW_E_NONE == eErr && m_parParameters && m_nParamSize > 0 )
288 		{
289 			rtl_uString** pParamArr = m_parParameters;
290 			aParameterList.realloc( m_nParamSize );
291 			::rtl::OUString* pParams = aParameterList.getArray();
292 			for ( sal_Int32 i = 0; i < m_nParamSize; ++i )
293 			{
294 				rtl_uString* pParam = *pParamArr++;
295 				pParams[i] = ::rtl::OUString( pParam );
296 			}
297 			m_pParamDlg->SetParameters( aParameterList );
298 		}
299 	}
300 	else
301 		aParameterList = m_pParamDlg->GetParameters();
302 
303 	if ( m_pParamDlg->Execute() == RET_OK )
304 	{
305 		if ( !areListsEqual( aParameterList, m_pParamDlg->GetParameters() ) )
306 		{
307 			aParameterList = m_pParamDlg->GetParameters();
308 			sal_Bool bRunning = sal_False;
309 			javaFrameworkError eErr = jfw_isVMRunning( &bRunning );
310 			DBG_ASSERT( JFW_E_NONE == eErr,
311 						"SvxJavaOptionsPage::ParameterHdl_Impl(): error in jfw_isVMRunning" );
312 			(void)eErr;
313 			if ( bRunning )
314 			{
315 				WarningBox aWarnBox( this, CUI_RES( RID_SVX_MSGBOX_JAVA_RESTART2 ) );
316 				aWarnBox.Execute();
317 			}
318 		}
319 	}
320 	else
321 		m_pParamDlg->SetParameters( aParameterList );
322 
323 	return 0;
324 }
325 
326 // -----------------------------------------------------------------------
327 
328 IMPL_LINK( SvxJavaOptionsPage, ClassPathHdl_Impl, PushButton *, EMPTYARG )
329 {
330 	String sClassPath;
331 
332 	if ( !m_pPathDlg )
333 	{
334   		m_pPathDlg = new SvxJavaClassPathDlg( this );
335 		javaFrameworkError eErr = jfw_getUserClassPath( &m_pClassPath );
336 		if ( JFW_E_NONE == eErr && m_pClassPath )
337 		{
338 			sClassPath = String( ::rtl::OUString( m_pClassPath ) );
339 			m_pPathDlg->SetClassPath( sClassPath );
340 		}
341 	}
342 	else
343 		sClassPath = m_pPathDlg->GetClassPath();
344 
345 	m_pPathDlg->SetFocus();
346 	if ( m_pPathDlg->Execute() == RET_OK )
347 	{
348 
349 		if ( m_pPathDlg->GetClassPath() != sClassPath )
350 		{
351 			sClassPath = m_pPathDlg->GetClassPath();
352 			sal_Bool bRunning = sal_False;
353 			javaFrameworkError eErr = jfw_isVMRunning( &bRunning );
354 			DBG_ASSERT( JFW_E_NONE == eErr,
355 						"SvxJavaOptionsPage::ParameterHdl_Impl(): error in jfw_isVMRunning" );
356 			(void)eErr;
357 			if ( bRunning )
358 			{
359 				WarningBox aWarnBox( this, CUI_RES( RID_SVX_MSGBOX_JAVA_RESTART2 ) );
360 				aWarnBox.Execute();
361 			}
362 		}
363 	}
364 	else
365 		m_pPathDlg->SetClassPath( sClassPath );
366 
367 	return 0;
368 }
369 
370 // -----------------------------------------------------------------------
371 
372 IMPL_LINK( SvxJavaOptionsPage, ResetHdl_Impl, Timer *, EMPTYARG )
373 {
374 	LoadJREs();
375 	return 0;
376 }
377 
378 // -----------------------------------------------------------------------
379 
380 IMPL_LINK( SvxJavaOptionsPage, StartFolderPickerHdl, void*, EMPTYARG )
381 {
382     try
383     {
384         Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY );
385         if ( xAsyncDlg.is() )
386             xAsyncDlg->startExecuteModal( xDialogListener.get() );
387         else if ( xFolderPicker.is() && xFolderPicker->execute() == ExecutableDialogResults::OK )
388             AddFolder( xFolderPicker->getDirectory() );
389     }
390     catch ( Exception& )
391     {
392 #ifdef DBG_UTIL
393         DBG_ERRORFILE( "SvxJavaOptionsPage::StartFolderPickerHdl(): caught exception" );
394 #endif
395     }
396 
397     return 0L;
398 }
399 
400 // -----------------------------------------------------------------------
401 
402 IMPL_LINK( SvxJavaOptionsPage, DialogClosedHdl, DialogClosedEvent*, pEvt )
403 {
404     if ( RET_OK == pEvt->DialogResult )
405     {
406         DBG_ASSERT( xFolderPicker.is() == sal_True, "SvxJavaOptionsPage::DialogClosedHdl(): no folder picker" );
407 
408         AddFolder( xFolderPicker->getDirectory() );
409     }
410     return 0L;
411 }
412 
413 // -----------------------------------------------------------------------
414 
415 void SvxJavaOptionsPage::ClearJavaInfo()
416 {
417 	if ( m_parJavaInfo )
418 	{
419 		JavaInfo** parInfo = m_parJavaInfo;
420 		for ( sal_Int32 i = 0; i < m_nInfoSize; ++i )
421 		{
422 			JavaInfo* pInfo = *parInfo++;
423 			jfw_freeJavaInfo( pInfo );
424 		}
425 
426 		rtl_freeMemory( m_parJavaInfo );
427 		m_parJavaInfo = NULL;
428 		m_nInfoSize = 0;
429 	}
430 }
431 
432 // -----------------------------------------------------------------------
433 
434 void SvxJavaOptionsPage::ClearJavaList()
435 {
436 	SvLBoxEntry* pEntry = m_aJavaList.First();
437 	while ( pEntry )
438 	{
439 		String* pLocation = static_cast< String* >( pEntry->GetUserData() );
440 		delete pLocation;
441 		pEntry = m_aJavaList.Next( pEntry );
442 	}
443 	m_aJavaList.Clear();
444 }
445 
446 // -----------------------------------------------------------------------
447 
448 void SvxJavaOptionsPage::LoadJREs()
449 {
450 	WaitObject aWaitObj( &m_aJavaList );
451 	javaFrameworkError eErr = jfw_findAllJREs( &m_parJavaInfo, &m_nInfoSize );
452 	if ( JFW_E_NONE == eErr && m_parJavaInfo )
453 	{
454 		JavaInfo** parInfo = m_parJavaInfo;
455 		for ( sal_Int32 i = 0; i < m_nInfoSize; ++i )
456 		{
457 			JavaInfo* pInfo = *parInfo++;
458 			AddJRE( pInfo );
459 		}
460 	}
461 
462     std::vector< JavaInfo* >::iterator pIter;
463 	for ( pIter = m_aAddedInfos.begin(); pIter != m_aAddedInfos.end(); ++pIter )
464 	{
465 		JavaInfo* pInfo = *pIter;
466 		AddJRE( pInfo );
467 	}
468 
469 	JavaInfo* pSelectedJava = NULL;
470 	eErr = jfw_getSelectedJRE( &pSelectedJava );
471 	if ( JFW_E_NONE == eErr && pSelectedJava )
472 	{
473 		JavaInfo** parInfo = m_parJavaInfo;
474 		for ( sal_Int32 i = 0; i < m_nInfoSize; ++i )
475 		{
476 			JavaInfo* pCmpInfo = *parInfo++;
477 			if ( jfw_areEqualJavaInfo( pCmpInfo, pSelectedJava ) )
478 			{
479 				SvLBoxEntry* pEntry = m_aJavaList.GetEntry(i);
480                 if ( pEntry )
481                     m_aJavaList.HandleEntryChecked( pEntry );
482 				break;
483 			}
484 		}
485 	}
486 
487 	jfw_freeJavaInfo( pSelectedJava );
488 }
489 
490 // -----------------------------------------------------------------------
491 
492 void SvxJavaOptionsPage::AddJRE( JavaInfo* _pInfo )
493 {
494 	String sEntry( '\t' );
495 	sEntry += String( ::rtl::OUString( _pInfo->sVendor ) );
496 	sEntry += '\t';
497 	sEntry += String( ::rtl::OUString( _pInfo->sVersion ) );
498 	sEntry += '\t';
499 	if ( ( _pInfo->nFeatures & JFW_FEATURE_ACCESSBRIDGE ) == JFW_FEATURE_ACCESSBRIDGE )
500 		sEntry += m_sAccessibilityText;
501 	SvLBoxEntry* pEntry = m_aJavaList.InsertEntry( sEntry );
502 	INetURLObject aLocObj( ::rtl::OUString( _pInfo->sLocation ) );
503 	String* pLocation = new String( aLocObj.getFSysPath( INetURLObject::FSYS_DETECT ) );
504 	pEntry->SetUserData( pLocation );
505 }
506 
507 // -----------------------------------------------------------------------
508 
509 void SvxJavaOptionsPage::HandleCheckEntry( SvLBoxEntry* _pEntry )
510 {
511 	m_aJavaList.Select( _pEntry, sal_True );
512 	SvButtonState eState = m_aJavaList.GetCheckButtonState( _pEntry );
513 
514 	if ( SV_BUTTON_CHECKED == eState )
515 	{
516 		// we have radio button behavior -> so uncheck the other entries
517 		SvLBoxEntry* pEntry = m_aJavaList.First();
518 		while ( pEntry )
519 		{
520 			if ( pEntry != _pEntry )
521 				m_aJavaList.SetCheckButtonState( pEntry, SV_BUTTON_UNCHECKED );
522 			pEntry = m_aJavaList.Next( pEntry );
523 		}
524 	}
525 	else
526 		m_aJavaList.SetCheckButtonState( _pEntry, SV_BUTTON_CHECKED );
527 }
528 
529 // -----------------------------------------------------------------------
530 
531 void SvxJavaOptionsPage::AddFolder( const ::rtl::OUString& _rFolder )
532 {
533     bool bStartAgain = true;
534     sal_Int32 nPos = 0;
535     JavaInfo* pInfo = NULL;
536     javaFrameworkError eErr = jfw_getJavaInfoByPath( _rFolder.pData, &pInfo );
537     if ( JFW_E_NONE == eErr && pInfo )
538     {
539         bool bFound = false;
540         JavaInfo** parInfo = m_parJavaInfo;
541         for ( sal_Int32 i = 0; i < m_nInfoSize; ++i )
542         {
543             JavaInfo* pCmpInfo = *parInfo++;
544             if ( jfw_areEqualJavaInfo( pCmpInfo, pInfo ) )
545             {
546                 bFound = true;
547                 nPos = i;
548                 break;
549             }
550         }
551 
552         if ( !bFound )
553         {
554             std::vector< JavaInfo* >::iterator pIter;
555             for ( pIter = m_aAddedInfos.begin(); pIter != m_aAddedInfos.end(); ++pIter )
556             {
557                 JavaInfo* pCmpInfo = *pIter;
558                 if ( jfw_areEqualJavaInfo( pCmpInfo, pInfo ) )
559                 {
560                     bFound = true;
561                     break;
562                 }
563             }
564         }
565 
566         if ( !bFound )
567         {
568             jfw_addJRELocation( pInfo->sLocation );
569             AddJRE( pInfo );
570             m_aAddedInfos.push_back( pInfo );
571             nPos = m_aJavaList.GetEntryCount() - 1;
572         }
573         else
574             jfw_freeJavaInfo( pInfo );
575 
576         SvLBoxEntry* pEntry = m_aJavaList.GetEntry( nPos );
577         m_aJavaList.Select( pEntry );
578         m_aJavaList.SetCheckButtonState( pEntry, SV_BUTTON_CHECKED );
579         HandleCheckEntry( pEntry );
580         bStartAgain = false;
581     }
582     else if ( JFW_E_NOT_RECOGNIZED == eErr )
583     {
584         ErrorBox aErrBox( this, CUI_RES( RID_SVXERR_JRE_NOT_RECOGNIZED ) );
585         aErrBox.Execute();
586     }
587     else if ( JFW_E_FAILED_VERSION == eErr )
588     {
589         ErrorBox aErrBox( this, CUI_RES( RID_SVXERR_JRE_FAILED_VERSION ) );
590         aErrBox.Execute();
591     }
592 
593     if ( bStartAgain )
594     {
595         xFolderPicker->setDisplayDirectory( _rFolder );
596         Application::PostUserEvent( LINK( this, SvxJavaOptionsPage, StartFolderPickerHdl ) );
597     }
598 }
599 
600 // -----------------------------------------------------------------------
601 
602 SfxTabPage*	SvxJavaOptionsPage::Create( Window* pParent, const SfxItemSet& rAttrSet )
603 {
604 	return ( new SvxJavaOptionsPage( pParent, rAttrSet ) );
605 }
606 
607 // -----------------------------------------------------------------------
608 
609 sal_Bool SvxJavaOptionsPage::FillItemSet( SfxItemSet& /*rCoreSet*/ )
610 {
611 	sal_Bool bModified = sal_False;
612 	javaFrameworkError eErr = JFW_E_NONE;
613 	if ( m_pParamDlg )
614 	{
615 	    Sequence< ::rtl::OUString > aParamList = m_pParamDlg->GetParameters();
616 		sal_Int32 i, nSize = aParamList.getLength();
617 	    rtl_uString** pParamArr = (rtl_uString**)rtl_allocateMemory( sizeof(rtl_uString*) * nSize );
618 	    rtl_uString** pParamArrIter = pParamArr;
619 	    const ::rtl::OUString* pList = aParamList.getConstArray();
620 	    for ( i = 0; i < nSize; ++i )
621 			pParamArr[i] = pList[i].pData;
622 		eErr = jfw_setVMParameters( pParamArrIter, nSize );
623 		DBG_ASSERT( JFW_E_NONE == eErr,
624 					"SvxJavaOptionsPage::FillItemSet(): error in jfw_setVMParameters" );
625 	    pParamArrIter = pParamArr;
626 		rtl_freeMemory( pParamArr );
627 		bModified = sal_True;
628 	}
629 
630 	if ( m_pPathDlg	)
631 	{
632 	    ::rtl::OUString sPath( m_pPathDlg->GetClassPath() );
633 		if ( m_pPathDlg->GetOldPath() != String( sPath ) )
634 		{
635 			eErr = jfw_setUserClassPath( sPath.pData );
636 			DBG_ASSERT( JFW_E_NONE == eErr,
637 						"SvxJavaOptionsPage::FillItemSet(): error in jfw_setUserClassPath" );
638 			bModified = sal_True;
639 		}
640 	}
641 
642 	sal_uLong nCount = m_aJavaList.GetEntryCount();
643 	for ( sal_uLong i = 0; i < nCount; ++i )
644 	{
645 		if ( m_aJavaList.GetCheckButtonState( m_aJavaList.GetEntry(i) ) == SV_BUTTON_CHECKED )
646 		{
647             JavaInfo* pInfo = NULL;
648             if ( i < static_cast< sal_uLong >( m_nInfoSize ) )
649                 pInfo = m_parJavaInfo[i];
650             else
651                 pInfo = m_aAddedInfos[ i - m_nInfoSize ];
652 
653 			JavaInfo* pSelectedJava = NULL;
654 			eErr = jfw_getSelectedJRE( &pSelectedJava );
655 			if ( JFW_E_NONE == eErr || JFW_E_INVALID_SETTINGS == eErr )
656 			{
657 				if (pSelectedJava == NULL || !jfw_areEqualJavaInfo( pInfo, pSelectedJava ) )
658 				{
659 					sal_Bool bRunning = sal_False;
660 					eErr = jfw_isVMRunning( &bRunning );
661 					DBG_ASSERT( JFW_E_NONE == eErr,
662 								"SvxJavaOptionsPage::FillItemSet(): error in jfw_isVMRunning" );
663 					if ( bRunning ||
664 						( ( pInfo->nRequirements & JFW_REQUIRE_NEEDRESTART ) == JFW_REQUIRE_NEEDRESTART ) )
665 					{
666 						WarningBox aWarnBox( this, CUI_RES( RID_SVX_MSGBOX_JAVA_RESTART ) );
667 						aWarnBox.Execute();
668 					}
669 
670 					eErr = jfw_setSelectedJRE( pInfo );
671 					DBG_ASSERT( JFW_E_NONE == eErr,
672 								"SvxJavaOptionsPage::FillItemSet(): error in jfw_setSelectedJRE" );
673 					bModified = sal_True;
674 				}
675 			}
676 			jfw_freeJavaInfo( pSelectedJava );
677 			break;
678 		}
679 	}
680 
681 	sal_Bool bEnabled = sal_False;
682 	eErr = jfw_getEnabled( &bEnabled );
683 	DBG_ASSERT( JFW_E_NONE == eErr,
684 				"SvxJavaOptionsPage::FillItemSet(): error in jfw_getEnabled" );
685 	if ( bEnabled != m_aJavaEnableCB.IsChecked() )
686 	{
687 		eErr = jfw_setEnabled( m_aJavaEnableCB.IsChecked() );
688 		DBG_ASSERT( JFW_E_NONE == eErr,
689 					"SvxJavaOptionsPage::FillItemSet(): error in jfw_setEnabled" );
690 		bModified = sal_True;
691 	}
692 
693 	return bModified;
694 }
695 
696 // -----------------------------------------------------------------------
697 
698 void SvxJavaOptionsPage::Reset( const SfxItemSet& /*rSet*/ )
699 {
700 	ClearJavaInfo();
701 	ClearJavaList();
702 
703 	sal_Bool bEnabled = sal_False;
704 	javaFrameworkError eErr = jfw_getEnabled( &bEnabled );
705 	if ( eErr != JFW_E_NONE )
706 		bEnabled = sal_False;
707 	m_aJavaEnableCB.Check( bEnabled );
708 	EnableHdl_Impl( &m_aJavaEnableCB );
709 
710 	m_aResetTimer.Start();
711 }
712 
713 // -----------------------------------------------------------------------
714 
715 void SvxJavaOptionsPage::FillUserData()
716 {
717 	String aUserData;
718 	SetUserData( aUserData );
719 }
720 
721 // class SvxJavaParameterDlg ---------------------------------------------
722 
723 SvxJavaParameterDlg::SvxJavaParameterDlg( Window* pParent ) :
724 
725 	ModalDialog( pParent, CUI_RES( RID_SVXDLG_JAVA_PARAMETER ) ),
726 
727 	m_aParameterLabel	( this, CUI_RES( FT_PARAMETER ) ),
728 	m_aParameterEdit	( this, CUI_RES( ED_PARAMETER ) ),
729 	m_aAssignBtn		( this, CUI_RES( PB_ASSIGN ) ),
730 	m_aAssignedLabel	( this, CUI_RES( FT_ASSIGNED ) ),
731 	m_aAssignedList		( this, CUI_RES( LB_ASSIGNED ) ),
732 	m_aExampleText		( this, CUI_RES( FT_EXAMPLE ) ),
733 	m_aRemoveBtn		( this, CUI_RES( PB_REMOVE ) ),
734 	m_aButtonsLine		( this, CUI_RES( FL_BUTTONS ) ),
735 	m_aOKBtn			( this, CUI_RES( PB_PARAMETER_OK ) ),
736 	m_aCancelBtn		( this, CUI_RES( PB_PARAMETER_ESC ) ),
737 	m_aHelpBtn			( this, CUI_RES( PB_PARAMETER_HLP ) )
738 
739 {
740 	FreeResource();
741 
742 	m_aParameterEdit.SetModifyHdl( LINK( this, SvxJavaParameterDlg, ModifyHdl_Impl ) );
743 	m_aAssignBtn.SetClickHdl( LINK( this, SvxJavaParameterDlg, AssignHdl_Impl ) );
744 	m_aRemoveBtn.SetClickHdl( LINK( this, SvxJavaParameterDlg, RemoveHdl_Impl ) );
745 	m_aAssignedList.SetSelectHdl( LINK( this, SvxJavaParameterDlg, SelectHdl_Impl ) );
746 	m_aAssignedList.SetDoubleClickHdl( LINK( this, SvxJavaParameterDlg, DblClickHdl_Impl ) );
747 
748 	ModifyHdl_Impl( &m_aParameterEdit );
749 	EnableRemoveButton();
750 }
751 
752 // -----------------------------------------------------------------------
753 
754 SvxJavaParameterDlg::~SvxJavaParameterDlg()
755 {
756 }
757 
758 // -----------------------------------------------------------------------
759 
760 IMPL_LINK( SvxJavaParameterDlg, ModifyHdl_Impl, Edit *, EMPTYARG )
761 {
762 	String sParam = STRIM( m_aParameterEdit.GetText() );
763 	m_aAssignBtn.Enable( sParam.Len() > 0 );
764 
765 	return 0;
766 }
767 
768 // -----------------------------------------------------------------------
769 
770 IMPL_LINK( SvxJavaParameterDlg, AssignHdl_Impl, PushButton *, EMPTYARG )
771 {
772 	String sParam = STRIM( m_aParameterEdit.GetText() );
773 	if ( sParam.Len() > 0 )
774 	{
775 		sal_uInt16 nPos = m_aAssignedList.GetEntryPos( sParam );
776 		if ( LISTBOX_ENTRY_NOTFOUND == nPos )
777 			nPos = m_aAssignedList.InsertEntry( sParam );
778 		m_aAssignedList.SelectEntryPos( nPos );
779 		m_aParameterEdit.SetText( String() );
780 		ModifyHdl_Impl( &m_aParameterEdit );
781 		EnableRemoveButton();
782 	}
783 
784 	return 0;
785 }
786 
787 // -----------------------------------------------------------------------
788 
789 IMPL_LINK( SvxJavaParameterDlg, SelectHdl_Impl, ListBox *, EMPTYARG )
790 {
791 	EnableRemoveButton();
792 	return 0;
793 }
794 
795 // -----------------------------------------------------------------------
796 
797 IMPL_LINK( SvxJavaParameterDlg, DblClickHdl_Impl, ListBox *, EMPTYARG )
798 {
799 	sal_uInt16 nPos = m_aAssignedList.GetSelectEntryPos();
800 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
801 		m_aParameterEdit.SetText( m_aAssignedList.GetEntry( nPos ) );
802 	return 0;
803 }
804 
805 // -----------------------------------------------------------------------
806 
807 IMPL_LINK( SvxJavaParameterDlg, RemoveHdl_Impl, PushButton *, EMPTYARG )
808 {
809 	sal_uInt16 nPos = m_aAssignedList.GetSelectEntryPos();
810 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
811 	{
812 		m_aAssignedList.RemoveEntry( nPos );
813 		sal_uInt16 nCount = m_aAssignedList.GetEntryCount();
814 		if ( nCount )
815 		{
816 			if ( nPos >= nCount )
817 				nPos = ( nCount - 1 );
818 			m_aAssignedList.SelectEntryPos( nPos );
819 		}
820 	}
821 	EnableRemoveButton();
822 
823 	return 0;
824 }
825 
826 // -----------------------------------------------------------------------
827 
828 short SvxJavaParameterDlg::Execute()
829 {
830 	m_aParameterEdit.GrabFocus();
831 	m_aAssignedList.SetNoSelection();
832 	return ModalDialog::Execute();
833 }
834 
835 // -----------------------------------------------------------------------
836 
837 Sequence< ::rtl::OUString >	SvxJavaParameterDlg::GetParameters() const
838 {
839 	sal_uInt16 nCount = m_aAssignedList.GetEntryCount();
840 	Sequence< ::rtl::OUString > aParamList( nCount );
841 	::rtl::OUString* pArray = aParamList.getArray();
842  	for ( sal_uInt16 i = 0; i < nCount; ++i )
843  	    pArray[i] = ::rtl::OUString( m_aAssignedList.GetEntry(i) );
844 	return aParamList;
845 }
846 
847 // -----------------------------------------------------------------------
848 
849 void SvxJavaParameterDlg::SetParameters( Sequence< ::rtl::OUString >& rParams )
850 {
851 	m_aAssignedList.Clear();
852 	sal_uLong i, nCount = rParams.getLength();
853 	const ::rtl::OUString* pArray = rParams.getConstArray();
854 	for ( i = 0; i < nCount; ++i )
855 	{
856 		String sParam = String( *pArray++ );
857 		m_aAssignedList.InsertEntry( sParam );
858 	}
859 }
860 
861 // class SvxJavaClassPathDlg ---------------------------------------------
862 
863 SvxJavaClassPathDlg::SvxJavaClassPathDlg( Window* pParent ) :
864 
865 	ModalDialog( pParent, CUI_RES( RID_SVXDLG_JAVA_CLASSPATH ) ),
866 
867 	m_aPathLabel		( this, CUI_RES( FT_PATH ) ),
868 	m_aPathList			( this, CUI_RES( LB_PATH ) ),
869 	m_aAddArchiveBtn	( this, CUI_RES( PB_ADDARCHIVE ) ),
870 	m_aAddPathBtn		( this, CUI_RES( PB_ADDPATH ) ),
871 	m_aRemoveBtn		( this, CUI_RES( PB_REMOVE_PATH ) ),
872 	m_aButtonsLine		( this, CUI_RES( FL_PATH_BUTTONS ) ),
873 	m_aOKBtn			( this, CUI_RES( PB_PATH_OK ) ),
874 	m_aCancelBtn		( this, CUI_RES( PB_PATH_ESC ) ),
875 	m_aHelpBtn			( this, CUI_RES( PB_PATH_HLP ) )
876 
877 {
878 	FreeResource();
879 
880 	m_aAddArchiveBtn.SetClickHdl( LINK( this, SvxJavaClassPathDlg, AddArchiveHdl_Impl ) );
881 	m_aAddPathBtn.SetClickHdl( LINK( this, SvxJavaClassPathDlg, AddPathHdl_Impl ) );
882 	m_aRemoveBtn.SetClickHdl( LINK( this, SvxJavaClassPathDlg, RemoveHdl_Impl ) );
883 	m_aPathList.SetSelectHdl( LINK( this, SvxJavaClassPathDlg, SelectHdl_Impl ) );
884 
885 	// check if the buttons text are not too wide otherwise we have to stretch the buttons
886 	// and shrink the listbox
887 	long nTxtWidth1 = m_aAddArchiveBtn.GetTextWidth( m_aAddArchiveBtn.GetText() );
888 	long nTxtWidth2 = m_aAddPathBtn.GetTextWidth( m_aAddPathBtn.GetText() );
889 	Size aBtnSz = m_aAddArchiveBtn.GetSizePixel();
890 	if ( nTxtWidth1 > aBtnSz.Width() || nTxtWidth2 > aBtnSz.Width() )
891 	{
892 		long nW = ( nTxtWidth1 > aBtnSz.Width() ) ? nTxtWidth1 : nTxtWidth2;
893 		long nDelta = nW - aBtnSz.Width() + 2 * BUTTON_BORDER;
894 		aBtnSz.Width() += nDelta;
895 		Point aBtnPnt = m_aAddArchiveBtn.GetPosPixel();
896 		aBtnPnt.X() -= nDelta;
897 		m_aAddArchiveBtn.SetPosSizePixel( aBtnPnt, aBtnSz );
898 		aBtnPnt = m_aAddPathBtn.GetPosPixel();
899 		aBtnPnt.X() -= nDelta;
900 		m_aAddPathBtn.SetPosSizePixel( aBtnPnt, aBtnSz );
901 		aBtnPnt = m_aRemoveBtn.GetPosPixel();
902 		aBtnPnt.X() -= nDelta;
903 		m_aRemoveBtn.SetPosSizePixel( aBtnPnt, aBtnSz );
904 		Size aBoxSz = m_aPathList.GetSizePixel();
905 		aBoxSz.Width() -= nDelta;
906 		m_aPathList.SetSizePixel( aBoxSz );
907 	}
908 
909 	// set initial focus to path list
910 	m_aPathList.GrabFocus();
911 }
912 
913 // -----------------------------------------------------------------------
914 
915 SvxJavaClassPathDlg::~SvxJavaClassPathDlg()
916 {
917 	sal_uInt16 i, nCount = m_aPathList.GetEntryCount();
918 	for ( i = 0; i < nCount; ++i )
919 		delete static_cast< String* >( m_aPathList.GetEntryData(i) );
920 }
921 
922 // -----------------------------------------------------------------------
923 
924 IMPL_LINK( SvxJavaClassPathDlg, AddArchiveHdl_Impl, PushButton *, EMPTYARG )
925 {
926     sfx2::FileDialogHelper aDlg( TemplateDescription::FILEOPEN_SIMPLE, 0 );
927 	aDlg.SetTitle( CUI_RES( RID_SVXSTR_ARCHIVE_TITLE ) );
928 	aDlg.AddFilter( CUI_RES( RID_SVXSTR_ARCHIVE_HEADLINE ), String::CreateFromAscii("*.jar;*.zip") );
929 	String sFolder;
930 	if ( m_aPathList.GetSelectEntryCount() > 0 )
931 	{
932 		INetURLObject aObj( m_aPathList.GetSelectEntry(), INetURLObject::FSYS_DETECT );
933 		sFolder = aObj.GetMainURL( INetURLObject::NO_DECODE );
934 	}
935 	else
936 	 	sFolder = SvtPathOptions().GetWorkPath();
937     aDlg.SetDisplayDirectory( sFolder );
938 	if ( aDlg.Execute() == ERRCODE_NONE )
939     {
940 		String sURL = aDlg.GetPath();
941 		INetURLObject aURL( sURL );
942 		String sFile = aURL.getFSysPath( INetURLObject::FSYS_DETECT );
943 		if ( !IsPathDuplicate( sURL ) )
944         {
945             sal_uInt16 nPos = m_aPathList.InsertEntry( sFile, SvFileInformationManager::GetImage( aURL ) );
946             m_aPathList.SelectEntryPos( nPos );
947         }
948         else
949 		{
950 			String sMsg( CUI_RES( RID_SVXSTR_MULTIFILE_DBL_ERR ) );
951 			sMsg.SearchAndReplaceAscii( "%1", sFile );
952 			ErrorBox( this, WB_OK, sMsg ).Execute();
953 		}
954 	}
955     EnableRemoveButton();
956 	return 0;
957 }
958 
959 // -----------------------------------------------------------------------
960 
961 IMPL_LINK( SvxJavaClassPathDlg, AddPathHdl_Impl, PushButton *, EMPTYARG )
962 {
963     rtl::OUString sService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FolderPicker" ) );
964     Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
965 	Reference < XFolderPicker > xFolderPicker( xFactory->createInstance( sService ), UNO_QUERY );
966 
967     String sOldFolder;
968 	if ( m_aPathList.GetSelectEntryCount() > 0 )
969 	{
970 		INetURLObject aObj( m_aPathList.GetSelectEntry(), INetURLObject::FSYS_DETECT );
971         sOldFolder = aObj.GetMainURL( INetURLObject::NO_DECODE );
972 	}
973 	else
974         sOldFolder = SvtPathOptions().GetWorkPath();
975     xFolderPicker->setDisplayDirectory( sOldFolder );
976 	if ( xFolderPicker->execute() == ExecutableDialogResults::OK )
977 	{
978 		String sFolderURL( xFolderPicker->getDirectory() );
979 		INetURLObject aURL( sFolderURL );
980         String sNewFolder = aURL.getFSysPath( INetURLObject::FSYS_DETECT );
981 		if ( !IsPathDuplicate( sFolderURL ) )
982         {
983             sal_uInt16 nPos = m_aPathList.InsertEntry( sNewFolder, SvFileInformationManager::GetImage( aURL ) );
984             m_aPathList.SelectEntryPos( nPos );
985         }
986 		else
987 		{
988 			String sMsg( CUI_RES( RID_SVXSTR_MULTIFILE_DBL_ERR ) );
989             sMsg.SearchAndReplaceAscii( "%1", sNewFolder );
990 			ErrorBox( this, WB_OK, sMsg ).Execute();
991 		}
992 	}
993     EnableRemoveButton();
994 	return 0;
995 }
996 
997 // -----------------------------------------------------------------------
998 
999 IMPL_LINK( SvxJavaClassPathDlg, RemoveHdl_Impl, PushButton *, EMPTYARG )
1000 {
1001 	sal_uInt16 nPos = m_aPathList.GetSelectEntryPos();
1002 	if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1003 	{
1004 		m_aPathList.RemoveEntry( nPos );
1005 		sal_uInt16 nCount = m_aPathList.GetEntryCount();
1006 		if ( nCount )
1007 		{
1008 			if ( nPos >= nCount )
1009 				nPos = ( nCount - 1 );
1010 			m_aPathList.SelectEntryPos( nPos );
1011 		}
1012 	}
1013 
1014     EnableRemoveButton();
1015 	return 0;
1016 }
1017 
1018 // -----------------------------------------------------------------------
1019 
1020 IMPL_LINK( SvxJavaClassPathDlg, SelectHdl_Impl, ListBox *, EMPTYARG )
1021 {
1022 	EnableRemoveButton();
1023 	return 0;
1024 }
1025 
1026 // -----------------------------------------------------------------------
1027 
1028 bool SvxJavaClassPathDlg::IsPathDuplicate( const String& _rPath )
1029 {
1030 	bool bRet = false;
1031 	INetURLObject aFileObj( _rPath );
1032 	sal_uInt16 nCount = m_aPathList.GetEntryCount();
1033 	for ( sal_uInt16 i = 0; i < nCount; ++i )
1034 	{
1035 		INetURLObject aOtherObj( m_aPathList.GetEntry(i), INetURLObject::FSYS_DETECT );
1036 		if ( aOtherObj == aFileObj )
1037 		{
1038 			bRet = true;
1039 			break;
1040 		}
1041 	}
1042 
1043 	return bRet;
1044 }
1045 
1046 // -----------------------------------------------------------------------
1047 
1048 String SvxJavaClassPathDlg::GetClassPath() const
1049 {
1050 	String sPath;
1051 	sal_uInt16 nCount = m_aPathList.GetEntryCount();
1052 	for ( sal_uInt16 i = 0; i < nCount; ++i )
1053 	{
1054 		if ( sPath.Len() > 0 )
1055 			sPath += CLASSPATH_DELIMITER;
1056 		String* pFullPath = static_cast< String* >( m_aPathList.GetEntryData(i) );
1057 		if ( pFullPath )
1058 			sPath += *pFullPath;
1059 		else
1060 			sPath += m_aPathList.GetEntry(i);
1061 	}
1062 	return sPath;
1063 }
1064 
1065 // -----------------------------------------------------------------------
1066 
1067 void SvxJavaClassPathDlg::SetClassPath( const String& _rPath )
1068 {
1069 	if ( m_sOldPath.Len() == 0 )
1070 		m_sOldPath = _rPath;
1071 	m_aPathList.Clear();
1072 	xub_StrLen i, nIdx = 0;
1073 	xub_StrLen nCount = _rPath.GetTokenCount( CLASSPATH_DELIMITER );
1074 	for ( i = 0; i < nCount; ++i )
1075 	{
1076 		String sToken = _rPath.GetToken( 0, CLASSPATH_DELIMITER, nIdx );
1077 		INetURLObject aURL( sToken, INetURLObject::FSYS_DETECT );
1078 		String sPath = aURL.getFSysPath( INetURLObject::FSYS_DETECT );
1079 		m_aPathList.InsertEntry( sPath, SvFileInformationManager::GetImage( aURL ) );
1080 	}
1081 	// select first entry
1082 	m_aPathList.SelectEntryPos(0);
1083 	SelectHdl_Impl( NULL );
1084 }
1085 
1086