text: /**************************************************************
   * 
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   * 
   *   http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   * 
   *************************************************************/
  
  
  
  // MARKER(update_precomp.py): autogen include statement, do not remove
  #include "precompiled_editeng.hxx"
  
  #include <com/sun/star/uno/Any.hxx>
  #include <com/sun/star/uno/Reference.hxx>
  #include <comphelper/accessiblekeybindinghelper.hxx>
  
  #include "AccessibleHyperlink.hxx"
  #include "editeng/unoedprx.hxx"
  #include <editeng/flditem.hxx>
  #include <vcl/keycodes.hxx>
  
  using namespace ::com::sun::star;
  
  
  //------------------------------------------------------------------------
  //
  // AccessibleHyperlink implementation
  //
  //------------------------------------------------------------------------
  
  namespace accessibility
  {
  
      AccessibleHyperlink::AccessibleHyperlink( SvxAccessibleTextAdapter& r, SvxFieldItem* p, sal_uInt16 nP, sal_uInt16 nR, sal_Int32 nStt, sal_Int32 nEnd, const ::rtl::OUString& rD ) 
      : rTA( r )
      { 
          pFld = p; 
          nPara = nP; 
          nRealIdx = nR; 
          nStartIdx = nStt; 
          nEndIdx = nEnd; 
          aDescription = rD;
      }
      
      AccessibleHyperlink::~AccessibleHyperlink()
      {
          delete pFld;
      }
  
      // XAccessibleAction
      sal_Int32 SAL_CALL AccessibleHyperlink::getAccessibleActionCount() throw (uno::RuntimeException)
      {
      	 return isValid() ? 1 : 0;
      }
      
      sal_Bool SAL_CALL AccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex  ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
      {
      	sal_Bool bRet = sal_False;
      	if ( isValid() && ( nIndex == 0 ) )
      	{
      	    rTA.FieldClicked( *pFld, nPara, nRealIdx );
      	    bRet = sal_True;
      	}
      	return bRet;
      }
      
      ::rtl::OUString  SAL_CALL AccessibleHyperlink::getAccessibleActionDescription( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
      {
      	::rtl::OUString aDesc;
  
      	if ( isValid() && ( nIndex == 0 ) )
      	    aDesc = aDescription;
      
      	return aDesc;
      }
      
      uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL AccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
      {
      	uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > xKeyBinding;
      
      	if( isValid() && ( nIndex == 0 ) )
      	{
      		::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper = new ::comphelper::OAccessibleKeyBindingHelper();
      		xKeyBinding = pKeyBindingHelper;
      
              awt::KeyStroke aKeyStroke;
      		aKeyStroke.Modifiers = 0;
      		aKeyStroke.KeyCode = KEY_RETURN;
      		aKeyStroke.KeyChar = 0;
      		aKeyStroke.KeyFunc = 0;
      		pKeyBindingHelper->AddKeyBinding( aKeyStroke );
      	}
      
      	return xKeyBinding;
      }
  
      // XAccessibleHyperlink
      uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionAnchor( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
      {
      	return uno::Any();
      }
      
      uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionObject( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
      {
      	return uno::Any();
      }
      
      sal_Int32 SAL_CALL AccessibleHyperlink::getStartIndex() throw (uno::RuntimeException)
      {
      	return nStartIdx;
      }
      
      sal_Int32 SAL_CALL AccessibleHyperlink::getEndIndex() throw (uno::RuntimeException)
      {
      	return nEndIdx;
      }
      
      sal_Bool SAL_CALL AccessibleHyperlink::isValid(  ) throw (uno::RuntimeException)
      {
      	return rTA.IsValid();
      }
  
  }  // end of namespace accessibility
  
  //------------------------------------------------------------------------
  
  // MT IA2: Accessiblehyperlink.hxx from IA2 CWS - meanwhile we also introduced one in DEV300 (above)
  // Keeping this for reference - we probably should get support for image maps in our implementation...
  
  
  /*
  
  class SVX_DLLPUBLIC SvxAccessibleHyperlink : 
  		public ::cppu::WeakImplHelper1<
  		::com::sun::star::accessibility::XAccessibleHyperlink >
  {
  	SvxURLField* mpField;
  	sal_Int32 nStartIdx;
  	sal_Int32 nEndIdx;
  
  	ImageMap* mpImageMap;
  	SdrObject* m_pShape;
  	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >  shapeParent;
  
  public:
  
  	SvxAccessibleHyperlink(){};
  	//SvxAccessibleHyperlink(::rtl::OUString name, const Imagemap* pImageMap);
  	SvxAccessibleHyperlink(const SvxURLField* p, sal_Int32 nStt, sal_Int32 nEnd);
  	SvxAccessibleHyperlink(SdrObject* p, ::accessibility::AccessibleShape* pAcc);
  	virtual ~SvxAccessibleHyperlink();
  	//void setImageMap(ImageMap* pMap);
  	//void setXAccessibleImage(::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > parent);
  	::rtl::OUString GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException);
  	sal_Bool IsValidHyperlink();
  
  	// XAccessibleAction
      virtual sal_Int32 SAL_CALL getAccessibleActionCount() 
  		throw (::com::sun::star::uno::RuntimeException);
      virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex ) 
  		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
  				::com::sun::star::uno::RuntimeException);
      virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription( 
  				sal_Int32 nIndex ) 
  		throw (::com::sun::star::lang::IndexOutOfBoundsException,
  				::com::sun::star::uno::RuntimeException);
      virtual ::com::sun::star::uno::Reference< 
  			::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL
  		   	getAccessibleActionKeyBinding( sal_Int32 nIndex ) 
  		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
  				::com::sun::star::uno::RuntimeException);
  
  	// XAccessibleHyperlink
      virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor( 
  				sal_Int32 nIndex ) 
  		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
  				::com::sun::star::uno::RuntimeException);
      virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject( 
  			sal_Int32 nIndex ) 
  		throw (::com::sun::star::lang::IndexOutOfBoundsException, 
  				::com::sun::star::uno::RuntimeException);
      virtual sal_Int32 SAL_CALL getStartIndex() 
  		throw (::com::sun::star::uno::RuntimeException);
      virtual sal_Int32 SAL_CALL getEndIndex() 
  		throw (::com::sun::star::uno::RuntimeException);
      virtual sal_Bool SAL_CALL isValid(  ) 
  		throw (::com::sun::star::uno::RuntimeException);
  };
  
  
  SvxAccessibleHyperlink::SvxAccessibleHyperlink( const SvxURLField *p,
  										  sal_Int32 nStt, sal_Int32 nEnd ) :
  	nStartIdx( nStt ),
  	nEndIdx( nEnd ),
  	m_pShape(NULL),
  	shapeParent(NULL)
  {
  	if(p)
  		mpField = (SvxURLField*)p->Clone();
  	else
  		mpField = NULL;
  }
  	
  SvxAccessibleHyperlink::SvxAccessibleHyperlink(SdrObject* p, 
  											::accessibility::AccessibleShape* pAcc) :
  	nStartIdx( -1 ),
  	nEndIdx( -1 ),
  	mpField(NULL),
  	m_pShape(p)
  {
  	mpImageMap = m_pShape->GetModel()->GetImageMapForObject(m_pShape);
  	shapeParent = dynamic_cast< XAccessible* >(pAcc);
  }
  
  SvxAccessibleHyperlink::~SvxAccessibleHyperlink()
  {
  	if(mpField)
  		delete mpField;
  }
  
  ::rtl::OUString SvxAccessibleHyperlink::GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException)
  {
  	if( mpField )
  	{
  		if (nIndex != 0)
  	        throw ::com::sun::star::lang::IndexOutOfBoundsException();
  		return ::rtl::OUString( mpField->GetURL() );
  	}
  	else if (mpImageMap)
  	{
  		if (nIndex < 0 || nIndex >=mpImageMap->GetIMapObjectCount())
  			throw IndexOutOfBoundsException();
  		
  		IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
  		if (pMapObj->GetURL().Len())
  			return ::rtl::OUString( pMapObj->GetURL() );
  	}
  	else
  	{
  		if (nIndex != 0)
  	        throw ::com::sun::star::lang::IndexOutOfBoundsException();
  		
  		SdrUnoObj* pUnoCtrl = dynamic_cast< SdrUnoObj* >( m_pShape );
  	
  		if(pUnoCtrl) 
  		{
  			try
  			{
  				uno::Reference< awt::XControlModel > xControlModel( pUnoCtrl->GetUnoControlModel(), uno::UNO_QUERY_THROW );
  				uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
  				uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo(), uno::UNO_QUERY_THROW );
  		
  				form::FormButtonType eButtonType = form::FormButtonType_URL;
  				const ::rtl::OUString sButtonType( RTL_CONSTASCII_USTRINGPARAM( "ButtonType" ) );
  				if(xPropInfo->hasPropertyByName( sButtonType ) && (xPropSet->getPropertyValue( sButtonType ) >>= eButtonType ) )
  				{
  					::rtl::OUString aString;
  
  					// URL
  					const ::rtl::OUString sTargetURL(RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ));
  					if(xPropInfo->hasPropertyByName(sTargetURL))
  					{
  						if( xPropSet->getPropertyValue(sTargetURL) >>= aString )
  							return aString;
  					}
  				}
  			}
  			catch( uno::Exception& )
  			{
  			}
  		}
  		// If hyperlink can't be got from sdrobject, query the corresponding document to retrieve the link info
  		uno::Reference< XAccessibleGroupPosition > xGroupPosition (shapeParent, uno::UNO_QUERY);
  		if (xGroupPosition.is())
  			return xGroupPosition->getObjectLink( uno::makeAny( shapeParent ) );
  	}
  	return ::rtl::OUString();
  }
  
  // Just check whether the first hyperlink is valid
  sal_Bool SvxAccessibleHyperlink::IsValidHyperlink()
  {
  	::rtl::OUString url = GetHyperlinkURL(0);
  	if (url.getLength() > 0)
  		return sal_True;
  	else
  		return sal_False;
  }
  // XAccessibleAction
  sal_Int32 SAL_CALL SvxAccessibleHyperlink::getAccessibleActionCount() 
  		throw (RuntimeException)
  {
  	if (mpImageMap)
  		return mpImageMap->GetIMapObjectCount();
  	else
  		return 1;	// only shape link or url field
  		
  	//return mpField ? 1 : (mpImageMap ? mpImageMap->GetIMapObjectCount() : 0);
  }
  
  sal_Bool SAL_CALL SvxAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex ) 
  		throw (IndexOutOfBoundsException, RuntimeException)
  {
  	vos::OGuard aGuard(Application::GetSolarMutex());
  
  	sal_Bool bRet = sal_False;
  
  	OUString url = GetHyperlinkURL(nIndex);
  	
  	if( url.getLength() > 0 ) 
  	{
  		SfxStringItem aStrItem(SID_FILE_NAME, url);
  		const SfxObjectShell* pDocSh = SfxObjectShell::Current();
  		if( pDocSh )
  		{
  			SfxMedium* pSfxMedium = pDocSh->GetMedium();
  			if( pSfxMedium)
  			{
  				SfxStringItem aReferer(SID_REFERER, pSfxMedium->GetName());
  				SfxBoolItem aBrowseItem( SID_BROWSE, TRUE );
  				SfxViewFrame* pFrame = SfxViewFrame::Current();
  				if( pFrame )
  				{
  					pFrame->GetDispatcher()->Execute(SID_OPENDOC, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
  						    	&aStrItem, &aBrowseItem, &aReferer, 0L);
  					bRet = sal_True;
  				}
  			}
  		}
  	}
  
  	return bRet;
  }
  		
  OUString SAL_CALL SvxAccessibleHyperlink::getAccessibleActionDescription(
  		sal_Int32 nIndex ) 
  		throw (IndexOutOfBoundsException, RuntimeException)
  {
  	return GetHyperlinkURL(nIndex);
  }
  
  ::com::sun::star::uno::Reference< XAccessibleKeyBinding > SAL_CALL
  	SvxAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 ) 
  	throw (IndexOutOfBoundsException, RuntimeException)
  {
  	::com::sun::star::uno::Reference< XAccessibleKeyBinding > xKeyBinding;
  
  	if( mpField || m_pShape)
  	{
  		::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper =
  		   	new ::comphelper::OAccessibleKeyBindingHelper();
  		xKeyBinding = pKeyBindingHelper;
  
  		::com::sun::star::awt::KeyStroke aKeyStroke;
  		aKeyStroke.Modifiers = 0;
  		aKeyStroke.KeyCode = KEY_RETURN;
  		aKeyStroke.KeyChar = 0;
  		aKeyStroke.KeyFunc = 0;
  		pKeyBindingHelper->AddKeyBinding( aKeyStroke );
  	}
  
  	return xKeyBinding;
  }
  
  // XAccessibleHyperlink
  Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionAnchor(
  		sal_Int32 nIndex ) 
  		throw (IndexOutOfBoundsException, RuntimeException)
  {
  	Any aRet;
  
  	::rtl::OUString retText;
  	if(mpField && nIndex == 0)
  	{
  		retText = mpField->GetRepresentation();		
  		aRet <<= retText;
  		return aRet;
  	}
  	else if(mpImageMap)
  	{
  		IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
  		if(pMapObj && pMapObj->GetURL().Len())
  			aRet <<= shapeParent;
  			return aRet;
  	}
  	else if (nIndex == 0)
  	{
  		aRet <<= shapeParent;
  		return aRet;
  	}
  	return aRet;
  }
  
  Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionObject( 
  			sal_Int32 nIndex ) 
  	throw (IndexOutOfBoundsException, RuntimeException)
  {
  	::rtl::OUString retText = GetHyperlinkURL(nIndex);
  	Any aRet;
  	aRet <<= retText;
  	return aRet;
  }
  
  sal_Int32 SAL_CALL SvxAccessibleHyperlink::getStartIndex() 
  		throw (RuntimeException)
  {
  	return nStartIdx;
  }
  
  sal_Int32 SAL_CALL SvxAccessibleHyperlink::getEndIndex() 
  		throw (RuntimeException)
  {
  	return nEndIdx;
  }
  
  sal_Bool SAL_CALL SvxAccessibleHyperlink::isValid(  ) 
  		throw (RuntimeException)
  {
  	vos::OGuard aGuard(Application::GetSolarMutex());
  	//return mpField ? sal_True: ( mpImageMap ? sal_True : sal_False );
  	if (mpField || m_pShape)
  		return sal_True;
  	else 
  		return sal_False;
  }
  
  */
  
  
  
  