diff options
Diffstat (limited to 'editeng/source')
121 files changed, 85763 insertions, 0 deletions
diff --git a/editeng/source/accessibility/AccessibleComponentBase.cxx b/editeng/source/accessibility/AccessibleComponentBase.cxx new file mode 100644 index 0000000000..7d6d5205e0 --- /dev/null +++ b/editeng/source/accessibility/AccessibleComponentBase.cxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleComponentBase.cxx,v $ + * $Revision: 1.17 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + + +#include <editeng/AccessibleComponentBase.hxx> + +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/XAccessibleSelection.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/drawing/XShapeDescriptor.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +#include <tools/color.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility { + +//===== internal ============================================================ + +AccessibleComponentBase::AccessibleComponentBase (void) +{ +} + + + + +AccessibleComponentBase::~AccessibleComponentBase (void) +{ +} + + + + +//===== XAccessibleComponent ================================================ + +sal_Bool SAL_CALL AccessibleComponentBase::containsPoint ( + const ::com::sun::star::awt::Point& aPoint) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Size aSize (getSize()); + return (aPoint.X >= 0) + && (aPoint.X < aSize.Width) + && (aPoint.Y >= 0) + && (aPoint.Y < aSize.Height); +} + + + + +uno::Reference<XAccessible > SAL_CALL + AccessibleComponentBase::getAccessibleAtPoint ( + const awt::Point& /*aPoint*/) + throw (uno::RuntimeException) +{ + return uno::Reference<XAccessible>(); +} + + + + +awt::Rectangle SAL_CALL AccessibleComponentBase::getBounds (void) + throw (uno::RuntimeException) +{ + return awt::Rectangle(); +} + + + + +awt::Point SAL_CALL AccessibleComponentBase::getLocation (void) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Rectangle aBBox (getBounds()); + return awt::Point (aBBox.X, aBBox.Y); +} + + + + +awt::Point SAL_CALL AccessibleComponentBase::getLocationOnScreen (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return awt::Point(); +} + + + + +::com::sun::star::awt::Size SAL_CALL AccessibleComponentBase::getSize (void) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Rectangle aBBox (getBounds()); + return awt::Size (aBBox.Width, aBBox.Height); +} + + + + +void SAL_CALL AccessibleComponentBase::addFocusListener ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& /*xListener*/) + throw (::com::sun::star::uno::RuntimeException) +{ + // Ignored +} + + + + +void SAL_CALL AccessibleComponentBase::removeFocusListener (const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& /*xListener*/ ) + throw (::com::sun::star::uno::RuntimeException) +{ + // Ignored +} + + + + +void SAL_CALL AccessibleComponentBase::grabFocus (void) + throw (::com::sun::star::uno::RuntimeException) +{ + uno::Reference<XAccessibleContext> xContext (this, uno::UNO_QUERY); + uno::Reference<XAccessibleSelection> xSelection ( + xContext->getAccessibleParent(), uno::UNO_QUERY); + if (xSelection.is()) + { + // Do a single selection on this object. + xSelection->clearAccessibleSelection(); + xSelection->selectAccessibleChild (xContext->getAccessibleIndexInParent()); + } +} + + + + +sal_Int32 SAL_CALL AccessibleComponentBase::getForeground (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return Color(COL_BLACK).GetColor(); +} + + + + +sal_Int32 SAL_CALL AccessibleComponentBase::getBackground (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return Color(COL_WHITE).GetColor(); +} + + + + +//===== XAccessibleExtendedComponent ======================================== + +::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > SAL_CALL + AccessibleComponentBase::getFont (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return uno::Reference<awt::XFont>(); +} + + + + +::rtl::OUString SAL_CALL AccessibleComponentBase::getTitledBorderText (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii (""); +} + + + + +::rtl::OUString SAL_CALL AccessibleComponentBase::getToolTipText (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii (""); +} + + + + +//===== XTypeProvider =================================================== + +uno::Sequence<uno::Type> SAL_CALL + AccessibleComponentBase::getTypes (void) + throw (uno::RuntimeException) +{ + // Get list of types from the context base implementation... + uno::Sequence<uno::Type> aTypeList (2); + // ...and add the additional type for the component. + const uno::Type aComponentType = + ::getCppuType((const uno::Reference<XAccessibleComponent>*)0); + const uno::Type aExtendedComponentType = + ::getCppuType((const uno::Reference<XAccessibleExtendedComponent>*)0); + aTypeList[0] = aComponentType; + aTypeList[1] = aExtendedComponentType; + + return aTypeList; +} + + +} // end of namespace accessibility diff --git a/editeng/source/accessibility/AccessibleContextBase.cxx b/editeng/source/accessibility/AccessibleContextBase.cxx new file mode 100644 index 0000000000..d3671624f4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleContextBase.cxx @@ -0,0 +1,718 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleContextBase.cxx,v $ + * $Revision: 1.28.144.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + + +#include <editeng/AccessibleContextBase.hxx> + +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/accessibility/XAccessibleEventListener.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> + +#include <unotools/accessiblestatesethelper.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#include <comphelper/accessibleeventnotifier.hxx> +#include <rtl/uuid.h> +#include <vos/mutex.hxx> +//#include <vcl/svapp.hxx> + +#include <utility> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using ::com::sun::star::uno::Reference; + +namespace accessibility { + +//===== internal ============================================================ + +// Define a shortcut for the somewhot longish base class name. +typedef ::cppu::WeakComponentImplHelper4< + ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::lang::XServiceInfo> BaseClass; + +AccessibleContextBase::AccessibleContextBase ( + const uno::Reference<XAccessible>& rxParent, + const sal_Int16 aRole) + : BaseClass (MutexOwner::maMutex), + mxStateSet (NULL), + mxRelationSet (NULL), + mxParent(rxParent), + msDescription(), + meDescriptionOrigin(NotSet), + msName(), + meNameOrigin(NotSet), + mnClientId(0), + maRole(aRole) +{ + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // Set some states. Don't use the SetState method because no events + // shall be broadcastet (that is not yet initialized anyway). + if (pStateSet != NULL) + { + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::FOCUSABLE); + pStateSet->AddState (AccessibleStateType::SELECTABLE); + } + + // Create the relation set. + ::utl::AccessibleRelationSetHelper* pRelationSet = new ::utl::AccessibleRelationSetHelper (); + mxRelationSet = pRelationSet; +} + + + + +AccessibleContextBase::~AccessibleContextBase(void) +{ +} + + + + +sal_Bool AccessibleContextBase::SetState (sal_Int16 aState) +{ + ::osl::ClearableMutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if ((pStateSet != NULL) && !pStateSet->contains(aState)) + { + pStateSet->AddState (aState); + // Clear the mutex guard so that it is not locked during calls to + // listeners. + aGuard.clear(); + + // Send event for all states except the DEFUNC state. + if (aState != AccessibleStateType::DEFUNC) + { + uno::Any aNewValue; + aNewValue <<= aState; + CommitChange( + AccessibleEventId::STATE_CHANGED, + aNewValue, + uno::Any()); + } + return sal_True; + } + else + return sal_False; +} + + + + +sal_Bool AccessibleContextBase::ResetState (sal_Int16 aState) +{ + ::osl::ClearableMutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if ((pStateSet != NULL) && pStateSet->contains(aState)) + { + pStateSet->RemoveState (aState); + // Clear the mutex guard so that it is not locked during calls to listeners. + aGuard.clear(); + + uno::Any aOldValue; + aOldValue <<= aState; + CommitChange( + AccessibleEventId::STATE_CHANGED, + uno::Any(), + aOldValue); + return sal_True; + } + else + return sal_False; +} + + + + +sal_Bool AccessibleContextBase::GetState (sal_Int16 aState) +{ + ::osl::MutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if (pStateSet != NULL) + return pStateSet->contains(aState); + else + // If there is no state set then return false as a default value. + return sal_False; +} + + + + +void AccessibleContextBase::SetRelationSet ( + const uno::Reference<XAccessibleRelationSet>& rxNewRelationSet) + throw (::com::sun::star::uno::RuntimeException) +{ + OSL_TRACE ("setting relation set"); + + // Try to emit some meaningfull events indicating differing relations in + // both sets. + typedef std::pair<short int,short int> RD; + const RD aRelationDescriptors[] = { + RD(AccessibleRelationType::CONTROLLED_BY, AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED), + RD(AccessibleRelationType::CONTROLLER_FOR, AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED), + RD(AccessibleRelationType::LABELED_BY, AccessibleEventId::LABELED_BY_RELATION_CHANGED), + RD(AccessibleRelationType::LABEL_FOR, AccessibleEventId::LABEL_FOR_RELATION_CHANGED), + RD(AccessibleRelationType::MEMBER_OF, AccessibleEventId::MEMBER_OF_RELATION_CHANGED), + RD(AccessibleRelationType::INVALID, -1), + }; + for (int i=0; aRelationDescriptors[i].first!=AccessibleRelationType::INVALID; i++) + if (mxRelationSet->containsRelation(aRelationDescriptors[i].first) + != rxNewRelationSet->containsRelation(aRelationDescriptors[i].first)) + CommitChange (aRelationDescriptors[i].second, uno::Any(), uno::Any()); + + mxRelationSet = rxNewRelationSet; +} + + + + +//===== XAccessible ========================================================= + +uno::Reference< XAccessibleContext> SAL_CALL + AccessibleContextBase::getAccessibleContext (void) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + return this; +} + + + + +//===== XAccessibleContext ================================================== + +/** No children. +*/ +sal_Int32 SAL_CALL + AccessibleContextBase::getAccessibleChildCount (void) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + return 0; +} + + + + +/** Forward the request to the shape. Return the requested shape or throw + an exception for a wrong index. +*/ +uno::Reference<XAccessible> SAL_CALL + AccessibleContextBase::getAccessibleChild (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + throw lang::IndexOutOfBoundsException ( + ::rtl::OUString::createFromAscii ("no child with index " + nIndex), + NULL); +} + + + + +uno::Reference<XAccessible> SAL_CALL + AccessibleContextBase::getAccessibleParent (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return mxParent; +} + + + + +sal_Int32 SAL_CALL + AccessibleContextBase::getAccessibleIndexInParent (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Use a simple but slow solution for now. Optimize later. + + // Iterate over all the parent's children and search for this object. + if (mxParent.is()) + { + uno::Reference<XAccessibleContext> xParentContext ( + mxParent->getAccessibleContext()); + if (xParentContext.is()) + { + sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); + for (sal_Int32 i=0; i<nChildCount; i++) + { + uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i)); + if (xChild.is()) + { + uno::Reference<XAccessibleContext> xChildContext = xChild->getAccessibleContext(); + if (xChildContext == (XAccessibleContext*)this) + return i; + } + } + } + } + + // Return -1 to indicate that this object's parent does not know about the + // object. + return -1; +} + + + + +sal_Int16 SAL_CALL + AccessibleContextBase::getAccessibleRole (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return maRole; +} + + + + +::rtl::OUString SAL_CALL + AccessibleContextBase::getAccessibleDescription (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + return msDescription; +} + + + + +OUString SAL_CALL + AccessibleContextBase::getAccessibleName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + if (meNameOrigin == NotSet) + { + // Do not send an event because this is the first time it has been + // requested. + msName = CreateAccessibleName(); + meNameOrigin = AutomaticallyCreated; + } + + return msName; +} + + + + +/** Return a copy of the relation set. +*/ +uno::Reference<XAccessibleRelationSet> SAL_CALL + AccessibleContextBase::getAccessibleRelationSet (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + // Create a copy of the relation set and return it. + ::utl::AccessibleRelationSetHelper* pRelationSet = + static_cast< ::utl::AccessibleRelationSetHelper*>(mxRelationSet.get()); + if (pRelationSet != NULL) + { + return uno::Reference<XAccessibleRelationSet> ( + new ::utl::AccessibleRelationSetHelper (*pRelationSet)); + } + else + return uno::Reference<XAccessibleRelationSet>(NULL); +} + + + + +/** Return a copy of the state set. + Possible states are: + ENABLED + SHOWING + VISIBLE +*/ +uno::Reference<XAccessibleStateSet> SAL_CALL + AccessibleContextBase::getAccessibleStateSet (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ::utl::AccessibleStateSetHelper* pStateSet = NULL; + + if (rBHelper.bDisposed) + { + // We are already disposed! + // Create a new state set that has only set the DEFUNC state. + pStateSet = new ::utl::AccessibleStateSetHelper (); + if (pStateSet != NULL) + pStateSet->AddState (AccessibleStateType::DEFUNC); + } + else + { + // Create a copy of the state set and return it. + pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + // Merge current focused state from edit engine. +#if 0 + if (aState == AccessibleStateType::FOCUSED + && pStateSet != NULL + && mpText != NULL) + { + if (mpText->GetFocusedState ()) + pStateSet->AddState (aState); + else + pStateSet->RemoveState (aState); + } +#endif + if (pStateSet != NULL) + pStateSet = new ::utl::AccessibleStateSetHelper (*pStateSet); + } + + return uno::Reference<XAccessibleStateSet>(pStateSet); +} + + + + +lang::Locale SAL_CALL + AccessibleContextBase::getLocale (void) + throw (IllegalAccessibleComponentStateException, + ::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Delegate request to parent. + if (mxParent.is()) + { + uno::Reference<XAccessibleContext> xParentContext ( + mxParent->getAccessibleContext()); + if (xParentContext.is()) + return xParentContext->getLocale (); + } + + // No locale and no parent. Therefore throw exception to indicate this + // cluelessness. + throw IllegalAccessibleComponentStateException (); +} + + + + +//===== XAccessibleEventListener ============================================ + +void SAL_CALL + AccessibleContextBase::addEventListener ( + const uno::Reference<XAccessibleEventListener >& rxListener) + throw (uno::RuntimeException) +{ + if (rxListener.is()) + { + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY); + rxListener->disposing (lang::EventObject (x)); + } + else + { + if (!mnClientId) + mnClientId = comphelper::AccessibleEventNotifier::registerClient( ); + comphelper::AccessibleEventNotifier::addEventListener( mnClientId, rxListener ); + } + } +} + + + + +void SAL_CALL + AccessibleContextBase::removeEventListener ( + const uno::Reference<XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + if (rxListener.is()) + { + sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + comphelper::AccessibleEventNotifier::revokeClient( mnClientId ); + mnClientId = 0; + } + } +} + + + + +//===== XServiceInfo ======================================================== + +::rtl::OUString SAL_CALL + AccessibleContextBase::getImplementationName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleContextBase")); +} + + + + +sal_Bool SAL_CALL + AccessibleContextBase::supportsService (const OUString& sServiceName) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; +} + + + + +uno::Sequence< ::rtl::OUString> SAL_CALL + AccessibleContextBase::getSupportedServiceNames (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + static const OUString sServiceNames[2] = { + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.accessibility.Accessible")), + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.accessibility.AccessibleContext")) + }; + return uno::Sequence<OUString> (sServiceNames, 2); +} + + + + +//===== XTypeProvider ======================================================= + +uno::Sequence< ::com::sun::star::uno::Type> + AccessibleContextBase::getTypes (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + // This class supports no interfaces on its own. Just return those + // supported by the base class. + return BaseClass::getTypes(); +} + + + + +uno::Sequence<sal_Int8> SAL_CALL + AccessibleContextBase::getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + static uno::Sequence<sal_Int8> aId; + if (aId.getLength() == 0) + { + ::osl::MutexGuard aGuard (maMutex); + aId.realloc (16); + rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True); + } + return aId; +} + + + + +//===== internal ============================================================ + +void SAL_CALL AccessibleContextBase::disposing (void) +{ + SetState (AccessibleStateType::DEFUNC); + + ::osl::MutexGuard aGuard (maMutex); + + // Send a disposing to all listeners. + if ( mnClientId ) + { + comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this ); + mnClientId = 0; + } +} + + + + +void AccessibleContextBase::SetAccessibleDescription ( + const ::rtl::OUString& rDescription, + StringOrigin eDescriptionOrigin) + throw (uno::RuntimeException) +{ + if (eDescriptionOrigin < meDescriptionOrigin + || (eDescriptionOrigin == meDescriptionOrigin && msDescription != rDescription)) + { + uno::Any aOldValue, aNewValue; + aOldValue <<= msDescription; + aNewValue <<= rDescription; + + msDescription = rDescription; + meDescriptionOrigin = eDescriptionOrigin; + + CommitChange( + AccessibleEventId::DESCRIPTION_CHANGED, + aNewValue, + aOldValue); + } +} + + + + +void AccessibleContextBase::SetAccessibleName ( + const ::rtl::OUString& rName, + StringOrigin eNameOrigin) + throw (uno::RuntimeException) +{ + if (eNameOrigin < meNameOrigin + || (eNameOrigin == meNameOrigin && msName != rName)) + { + uno::Any aOldValue, aNewValue; + aOldValue <<= msName; + aNewValue <<= rName; + + msName = rName; + meNameOrigin = eNameOrigin; + + CommitChange( + AccessibleEventId::NAME_CHANGED, + aNewValue, + aOldValue); + } +} + + + + +::rtl::OUString AccessibleContextBase::CreateAccessibleDescription (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii ("Empty Description"); +} + + + + +::rtl::OUString AccessibleContextBase::CreateAccessibleName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii ("Empty Name"); +} + + + + +void AccessibleContextBase::CommitChange ( + sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue) +{ + // Do not call FireEvent and do not even create the event object when no + // listener has been registered yet. Creating the event object can + // otherwise lead to a crash. See issue 93419 for details. + if (mnClientId != 0) + { + AccessibleEventObject aEvent ( + static_cast<XAccessibleContext*>(this), + nEventId, + rNewValue, + rOldValue); + + FireEvent (aEvent); + } +} + + + + +void AccessibleContextBase::FireEvent (const AccessibleEventObject& aEvent) +{ + if (mnClientId) + comphelper::AccessibleEventNotifier::addEvent( mnClientId, aEvent ); +} + + + + +void AccessibleContextBase::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + OSL_TRACE ("Calling disposed object. Throwing exception:"); + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + +sal_Bool AccessibleContextBase::IsDisposed (void) +{ + return (rBHelper.bDisposed || rBHelper.bInDispose); +} + + + +void AccessibleContextBase::SetAccessibleRole( sal_Int16 _nRole ) +{ + maRole = _nRole; +} + + +} // end of namespace accessibility diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.cxx b/editeng/source/accessibility/AccessibleEditableTextPara.cxx new file mode 100644 index 0000000000..7b32e6fe58 --- /dev/null +++ b/editeng/source/accessibility/AccessibleEditableTextPara.cxx @@ -0,0 +1,2204 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleEditableTextPara.cxx,v $ + * $Revision: 1.53 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ + +#include <limits.h> +#include <vector> +#include <algorithm> +#include <vos/mutex.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <unotools/accessiblestatesethelper.hxx> + +// --> OD 2006-01-11 #i27138# +#include <unotools/accessiblerelationsethelper.hxx> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +// <-- +#include <vcl/unohelp.hxx> +#include <editeng/editeng.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unoipset.hxx> +#include <editeng/outliner.hxx> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <com/sun/star/beans/PropertyState.hpp> +#include <editeng/unolingu.hxx> +#include <editeng/unopracc.hxx> +#include "AccessibleEditableTextPara.hxx" +#include <svtools/colorcfg.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::accessibility; + + +//------------------------------------------------------------------------ +// +// AccessibleEditableTextPara implementation +// +//------------------------------------------------------------------------ + +namespace accessibility +{ + + const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet() + { + // PropertyMap for character and paragraph properties + static const SfxItemPropertyMapEntry aPropMap[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTIE, + {MAP_CHAR_LEN("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0}, + {MAP_CHAR_LEN("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0}, + {0,0,0,0,0,0} + }; + static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() ); + return &aPropSet; + } + + + DBG_NAME( AccessibleEditableTextPara ) + + // --> OD 2006-01-11 #i27138# - add parameter <_pParaManager> + AccessibleEditableTextPara::AccessibleEditableTextPara( + const uno::Reference< XAccessible >& rParent, + const AccessibleParaManager* _pParaManager ) + : AccessibleTextParaInterfaceBase( m_aMutex ), + mnParagraphIndex( 0 ), + mnIndexInParent( 0 ), + mpEditSource( NULL ), + maEEOffset( 0, 0 ), + mxParent( rParent ), + // well, that's strictly (UNO) exception safe, though not + // really robust. We rely on the fact that this member is + // constructed last, and that the constructor body catches + // exceptions, thus no chance for exceptions once the Id is + // fetched. Nevertheless, normally should employ RAII here... + mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient()), + // --> OD 2006-01-11 #i27138# + mpParaManager( _pParaManager ) + // <-- + { +#ifdef DBG_UTIL + DBG_CTOR( AccessibleEditableTextPara, NULL ); + OSL_TRACE( "AccessibleEditableTextPara received ID: %d\n", mnNotifierClientId ); +#endif + + try + { + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // these are always on + pStateSet->AddState( AccessibleStateType::MULTI_LINE ); + pStateSet->AddState( AccessibleStateType::FOCUSABLE ); + pStateSet->AddState( AccessibleStateType::VISIBLE ); + pStateSet->AddState( AccessibleStateType::SHOWING ); + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::SENSITIVE ); + } + catch( const uno::Exception& ) {} + } + + AccessibleEditableTextPara::~AccessibleEditableTextPara() + { + DBG_DTOR( AccessibleEditableTextPara, NULL ); + + // sign off from event notifier + if( getNotifierClientId() != -1 ) + { + try + { + ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleEditableTextPara revoked ID: %d\n", mnNotifierClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + ::rtl::OUString AccessibleEditableTextPara::implGetText() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextRange( 0, GetTextLen() ); + } + + ::com::sun::star::lang::Locale AccessibleEditableTextPara::implGetLocale() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + lang::Locale aLocale; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); + + // return locale of first character in the paragraph + return SvxLanguageToLocale(aLocale, GetTextForwarder().GetLanguage( static_cast< USHORT >( GetParagraphIndex() ), 0 )); + } + + void AccessibleEditableTextPara::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + USHORT nStart, nEnd; + + if( GetSelection( nStart, nEnd ) ) + { + nStartIndex = nStart; + nEndIndex = nEnd; + } + else + { + // #102234# No exception, just set to 'invalid' + nStartIndex = -1; + nEndIndex = -1; + } + } + + void AccessibleEditableTextPara::implGetParagraphBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 /*nIndex*/ ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + DBG_WARNING( "AccessibleEditableTextPara::implGetParagraphBoundary: only a base implementation, ignoring the index" ); + + rBoundary.startPos = 0; + rBoundary.endPos = GetTextLen(); + } + + void AccessibleEditableTextPara::implGetLineBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + const sal_Int32 nParaIndex = GetParagraphIndex(); + + DBG_ASSERT(nParaIndex >= 0 && nParaIndex <= USHRT_MAX, + "AccessibleEditableTextPara::implGetLineBoundary: paragraph index value overflow"); + + const sal_Int32 nTextLen = rCacheTF.GetTextLen( static_cast< USHORT >( nParaIndex ) ); + + CheckPosition(nIndex); + + rBoundary.startPos = rBoundary.endPos = -1; + + const USHORT nLineCount=rCacheTF.GetLineCount( static_cast< USHORT >( nParaIndex ) ); + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + if( nLineCount <= 1 ) + rBoundary.startPos = 0; + else + rBoundary.startPos = nTextLen - rCacheTF.GetLineLen( static_cast< USHORT >( nParaIndex ), + nLineCount-1 ); + + rBoundary.endPos = nTextLen; + } + else + { + // normal line search + USHORT nLine; + sal_Int32 nCurIndex; + for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) + { + nCurIndex += rCacheTF.GetLineLen( static_cast< USHORT >( nParaIndex ), nLine); + + if( nCurIndex > nIndex ) + { + rBoundary.startPos = nCurIndex - rCacheTF.GetLineLen(static_cast< USHORT >( nParaIndex ), nLine); + rBoundary.endPos = nCurIndex; + break; + } + } + } + } + + int AccessibleEditableTextPara::getNotifierClientId() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnNotifierClientId; + } + + void AccessibleEditableTextPara::SetIndexInParent( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + mnIndexInParent = nIndex; + } + + sal_Int32 AccessibleEditableTextPara::GetIndexInParent() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnIndexInParent; + } + + void AccessibleEditableTextPara::SetParagraphIndex( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nOldIndex = mnParagraphIndex; + + mnParagraphIndex = nIndex; + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetParagraphIndex(mnParagraphIndex); + + try + { + if( nOldIndex != nIndex ) + { + uno::Any aOldDesc; + uno::Any aOldName; + + try + { + aOldDesc <<= getAccessibleDescription(); + aOldName <<= getAccessibleName(); + } + catch( const uno::Exception& ) {} // optional behaviour + // index and therefore description changed + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + } + } + catch( const uno::Exception& ) {} // optional behaviour + } + + sal_Int32 AccessibleEditableTextPara::GetParagraphIndex() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnParagraphIndex; + } + + void AccessibleEditableTextPara::Dispose() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + int nClientId( getNotifierClientId() ); + + // #108212# drop all references before notifying dispose + mxParent = NULL; + mnNotifierClientId = -1; + mpEditSource = NULL; + + // notify listeners + if( nClientId != -1 ) + { + try + { + uno::Reference < XAccessibleContext > xThis = getAccessibleContext(); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, xThis ); +#ifdef DBG_UTIL + OSL_TRACE( "Disposed ID: %d\n", nClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + void AccessibleEditableTextPara::SetEditSource( SvxEditSourceAdapter* pEditSource ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + mpEditSource = pEditSource; + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetEditSource(pEditSource); + + if( !mpEditSource ) + { + // going defunc + UnSetState( AccessibleStateType::SHOWING ); + UnSetState( AccessibleStateType::VISIBLE ); + SetState( AccessibleStateType::INVALID ); + SetState( AccessibleStateType::DEFUNC ); + + Dispose(); + } + + // #108900# Init last text content + try + { + TextChanged(); + } + catch( const uno::RuntimeException& ) {} + } + + ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // check overflow + DBG_ASSERT(nStartEEIndex >= 0 && nStartEEIndex <= USHRT_MAX && + nEndEEIndex >= 0 && nEndEEIndex <= USHRT_MAX && + GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::MakeSelection: index value overflow"); + + USHORT nParaIndex = static_cast< USHORT >( GetParagraphIndex() ); + return ESelection( nParaIndex, static_cast< USHORT >( nStartEEIndex ), + nParaIndex, static_cast< USHORT >( nEndEEIndex ) ); + } + + ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return MakeSelection( nEEIndex, nEEIndex+1 ); + } + + ESelection AccessibleEditableTextPara::MakeCursor( sal_Int32 nEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return MakeSelection( nEEIndex, nEEIndex ); + } + + void AccessibleEditableTextPara::CheckIndex( sal_Int32 nIndex ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( nIndex < 0 || nIndex >= getCharacterCount() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleEditableTextPara: character index out of bounds")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + } + + void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( nIndex < 0 || nIndex > getCharacterCount() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleEditableTextPara: character position out of bounds")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + } + + void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + CheckPosition( nStart ); + CheckPosition( nEnd ); + } + + sal_Bool AccessibleEditableTextPara::GetSelection( USHORT& nStartPos, USHORT& nEndPos ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ESelection aSelection; + USHORT nPara = static_cast< USHORT > ( GetParagraphIndex() ); + if( !GetEditViewForwarder().GetSelection( aSelection ) ) + return sal_False; + + if( aSelection.nStartPara < aSelection.nEndPara ) + { + if( aSelection.nStartPara > nPara || + aSelection.nEndPara < nPara ) + return sal_False; + + if( nPara == aSelection.nStartPara ) + nStartPos = aSelection.nStartPos; + else + nStartPos = 0; + + if( nPara == aSelection.nEndPara ) + nEndPos = aSelection.nEndPos; + else + nEndPos = GetTextLen(); + } + else + { + if( aSelection.nStartPara < nPara || + aSelection.nEndPara > nPara ) + return sal_False; + + if( nPara == aSelection.nStartPara ) + nStartPos = aSelection.nStartPos; + else + nStartPos = GetTextLen(); + + if( nPara == aSelection.nEndPara ) + nEndPos = aSelection.nEndPos; + else + nEndPos = 0; + } + + return sal_True; + } + + String AccessibleEditableTextPara::GetText( sal_Int32 nIndex ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetText( MakeSelection(nIndex) ); + } + + String AccessibleEditableTextPara::GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetText( MakeSelection(nStartIndex, nEndIndex) ); + } + + USHORT AccessibleEditableTextPara::GetTextLen() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + } + + sal_Bool AccessibleEditableTextPara::IsVisible() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mpEditSource ? sal_True : sal_False ; + } + + uno::Reference< XAccessibleText > AccessibleEditableTextPara::GetParaInterface( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleContext > xParentContext = xParent->getAccessibleContext(); + if( xParentContext.is() ) + { + uno::Reference< XAccessible > xPara = xParentContext->getAccessibleChild( nIndex ); + if( xPara.is() ) + return uno::Reference< XAccessibleText > ( xPara, uno::UNO_QUERY ); + } + } + + return uno::Reference< XAccessibleText >(); + } + + SvxEditSourceAdapter& AccessibleEditableTextPara::GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( mpEditSource ) + return *mpEditSource; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit source, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxAccessibleTextAdapter& AccessibleEditableTextPara::GetTextForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSourceAdapter& rEditSource = GetEditSource(); + SvxAccessibleTextAdapter* pTextForwarder = rEditSource.GetTextForwarderAdapter(); + + if( !pTextForwarder ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + + if( pTextForwarder->IsValid() ) + return *pTextForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxViewForwarder& AccessibleEditableTextPara::GetViewForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder(); + + if( !pViewForwarder ) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + if( pViewForwarder->IsValid() ) + return *pViewForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxAccessibleTextEditViewAdapter& AccessibleEditableTextPara::GetEditViewForwarder( sal_Bool bCreate ) const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSourceAdapter& rEditSource = GetEditSource(); + SvxAccessibleTextEditViewAdapter* pTextEditViewForwarder = rEditSource.GetEditViewForwarderAdapter( bCreate ); + + if( !pTextEditViewForwarder ) + { + if( bCreate ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No view forwarder, object not in edit mode")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + if( pTextEditViewForwarder->IsValid() ) + return *pTextEditViewForwarder; + else + { + if( bCreate ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object not in edit mode")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + } + + sal_Bool AccessibleEditableTextPara::HaveEditView() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder(); + + if( !pViewForwarder ) + return sal_False; + + if( !pViewForwarder->IsValid() ) + return sal_False; + + return sal_True; + } + + sal_Bool AccessibleEditableTextPara::HaveChildren() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::HaveChildren: paragraph index value overflow"); + + return GetTextForwarder().HaveImageBullet( static_cast< USHORT >(GetParagraphIndex()) ); + } + + sal_Bool AccessibleEditableTextPara::IsActive() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder(); + + if( !pViewForwarder ) + return sal_False; + + if( pViewForwarder->IsValid() ) + return sal_False; + else + return sal_True; + } + + Rectangle AccessibleEditableTextPara::LogicToPixel( const Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder& rForwarder ) + { + // convert to screen coordinates + return Rectangle( rForwarder.LogicToPixel( rRect.TopLeft(), rMapMode ), + rForwarder.LogicToPixel( rRect.BottomRight(), rMapMode ) ); + } + + const Point& AccessibleEditableTextPara::GetEEOffset() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return maEEOffset; + } + + void AccessibleEditableTextPara::SetEEOffset( const Point& rOffset ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetEEOffset(rOffset); + + maEEOffset = rOffset; + } + + void AccessibleEditableTextPara::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleEditableTextPara* > (this)->getAccessibleContext() ); + + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); + + // #102261# Call global queue for focus events + if( nEventId == AccessibleEventId::STATE_CHANGED ) + vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); + + // #106234# Delegate to EventNotifier + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(), + aEvent ); + } + + void AccessibleEditableTextPara::GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + FireEvent( nEventId, rNewValue ); + } + + void AccessibleEditableTextPara::LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + FireEvent( nEventId, uno::Any(), rOldValue ); + } + + bool AccessibleEditableTextPara::HasState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL ) + return pStateSet->contains(nStateId) ? true : false; + + return false; + } + + void AccessibleEditableTextPara::SetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + !pStateSet->contains(nStateId) ) + { + pStateSet->AddState( nStateId ); + GotPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleEditableTextPara::UnSetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + pStateSet->contains(nStateId) ) + { + pStateSet->RemoveState( nStateId ); + LostPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleEditableTextPara::TextChanged() + { + ::rtl::OUString aCurrentString( OCommonAccessibleText::getText() ); + uno::Any aDeleted; + uno::Any aInserted; + if( OCommonAccessibleText::implInitTextChangedEvent( maLastTextString, aCurrentString, + aDeleted, aInserted) ) + { + FireEvent( AccessibleEventId::TEXT_CHANGED, aInserted, aDeleted ); + maLastTextString = aCurrentString; + } + } + + sal_Bool AccessibleEditableTextPara::GetAttributeRun( USHORT& nStartIndex, USHORT& nEndIndex, sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + DBG_ASSERT(nIndex >= 0 && nIndex <= USHRT_MAX, + "AccessibleEditableTextPara::GetAttributeRun: index value overflow"); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); + + return GetTextForwarder().GetAttributeRun( nStartIndex, + nEndIndex, + static_cast< USHORT >(GetParagraphIndex()), + static_cast< USHORT >(nIndex) ); + } + + uno::Any SAL_CALL AccessibleEditableTextPara::queryInterface (const uno::Type & rType) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Any aRet; + + // must provide XAccesibleText by hand, since it comes publicly inherited by XAccessibleEditableText + if ( rType == ::getCppuType((uno::Reference< XAccessibleText > *)0) ) + { + uno::Reference< XAccessibleText > aAccText = static_cast< XAccessibleEditableText * >(this); + aRet <<= aAccText; + } + else if ( rType == ::getCppuType((uno::Reference< XAccessibleEditableText > *)0) ) + { + uno::Reference< XAccessibleEditableText > aAccEditText = this; + aRet <<= aAccEditText; + } + else + { + aRet = AccessibleTextParaInterfaceBase::queryInterface(rType); + } + + return aRet; + } + + // XAccessible + uno::Reference< XAccessibleContext > SAL_CALL AccessibleEditableTextPara::getAccessibleContext() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // We implement the XAccessibleContext interface in the same object + return uno::Reference< XAccessibleContext > ( this ); + } + + // XAccessibleContext + sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return HaveChildren() ? 1 : 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( !HaveChildren() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No childs available")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + + if( i != 0 ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid child index")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + + if( !aChild.is() ) + { + // there is no hard reference available, create object then + AccessibleImageBullet* pChild = new AccessibleImageBullet( uno::Reference< XAccessible >( this ) ); + uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY ); + + if( !xChild.is() ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); + + aChild = WeakBullet::HardRefType( xChild, pChild ); + + aChild->SetEditSource( &GetEditSource() ); + aChild->SetParagraphIndex( GetParagraphIndex() ); + aChild->SetIndexInParent( i ); + + maImageBullet = aChild; + } + + return aChild.getRef(); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +#ifdef DBG_UTIL + if( !mxParent.is() ) + DBG_TRACE( "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?"); +#endif + + return mxParent; + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnIndexInParent; + } + + sal_Int16 SAL_CALL AccessibleEditableTextPara::getAccessibleRole() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return AccessibleRole::PARAGRAPH; + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getAccessibleDescription() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +// ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return ::rtl::OUString(); + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getAccessibleName() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +// ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return ::rtl::OUString(); + } + + uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleEditableTextPara::getAccessibleRelationSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // --> OD 2006-01-11 #i27138# - provide relations CONTENT_FLOWS_FROM + // and CONTENT_FLOWS_TO + if ( mpParaManager ) + { + utl::AccessibleRelationSetHelper* pAccRelSetHelper = + new utl::AccessibleRelationSetHelper(); + sal_Int32 nMyParaIndex( GetParagraphIndex() ); + // relation CONTENT_FLOWS_FROM + if ( nMyParaIndex > 0 && + mpParaManager->IsReferencable( nMyParaIndex - 1 ) ) + { + uno::Sequence<uno::Reference<XInterface> > aSequence(1); + aSequence[0] = + mpParaManager->GetChild( nMyParaIndex - 1 ).first.get().getRef(); + AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM, + aSequence ); + pAccRelSetHelper->AddRelation( aAccRel ); + } + + // relation CONTENT_FLOWS_TO + if ( (nMyParaIndex + 1) < (sal_Int32)mpParaManager->GetNum() && + mpParaManager->IsReferencable( nMyParaIndex + 1 ) ) + { + uno::Sequence<uno::Reference<XInterface> > aSequence(1); + aSequence[0] = + mpParaManager->GetChild( nMyParaIndex + 1 ).first.get().getRef(); + AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO, + aSequence ); + pAccRelSetHelper->AddRelation( aAccRel ); + } + + return pAccRelSetHelper; + } + else + { + // no relations, therefore empty + return uno::Reference< XAccessibleRelationSet >(); + } + // <-- + } + + uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Create a copy of the state set and return it. + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + if( !pStateSet ) + return uno::Reference<XAccessibleStateSet>(); + + return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + } + + lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale() throw (IllegalAccessibleComponentStateException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return implGetLocale(); + } + + void SAL_CALL AccessibleEditableTextPara::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener ); + } + + void SAL_CALL AccessibleEditableTextPara::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener ); + } + + // XAccessibleComponent + sal_Bool SAL_CALL AccessibleEditableTextPara::containsPoint( const awt::Point& aTmpPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::contains: index value overflow"); + + awt::Rectangle aTmpRect = getBounds(); + Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); + Point aPoint( aTmpPoint.X, aTmpPoint.Y ); + + return aRect.IsInside( aPoint ); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( HaveChildren() ) + { + // #103862# No longer need to make given position relative + Point aPoint( _aPoint.X, _aPoint.Y ); + + // respect EditEngine offset to surrounding shape/cell + aPoint -= GetEEOffset(); + + // convert to EditEngine coordinate system + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); + + EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( static_cast< USHORT > (GetParagraphIndex()) ); + + if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && + aBulletInfo.bVisible && + aBulletInfo.nType == SVX_NUM_BITMAP ) + { + Rectangle aRect = aBulletInfo.aBounds; + + if( aRect.IsInside( aLogPoint ) ) + return getAccessibleChild(0); + } + } + + // no children at all, or none at given position + return uno::Reference< XAccessible >(); + } + + awt::Rectangle SAL_CALL AccessibleEditableTextPara::getBounds() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getBounds: index value overflow"); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Rectangle aRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + + // convert to screen coordinates + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + awt::Point SAL_CALL AccessibleEditableTextPara::getLocation( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Point( aRect.X, aRect.Y ); + } + + awt::Point SAL_CALL AccessibleEditableTextPara::getLocationOnScreen( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // relate us to parent + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY ); + if( xParentComponent.is() ) + { + awt::Point aRefPoint = xParentComponent->getLocationOnScreen(); + awt::Point aPoint = getLocation(); + aPoint.X += aRefPoint.X; + aPoint.Y += aRefPoint.Y; + + return aPoint; + } + } + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot access parent")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + awt::Size SAL_CALL AccessibleEditableTextPara::getSize( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Size( aRect.Width, aRect.Height ); + } + + void SAL_CALL AccessibleEditableTextPara::grabFocus( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // set cursor to this paragraph + setSelection(0,0); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getForeground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #104444# Added to XAccessibleComponent interface + svtools::ColorConfig aColorConfig; + UINT32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + return static_cast<sal_Int32>(nColor); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getBackground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #104444# Added to XAccessibleComponent interface + Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() ); + + // the background is transparent + aColor.SetTransparency( 0xFF); + + return static_cast<sal_Int32>( aColor.GetColor() ); + } + + // XAccessibleText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getCaretPosition() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( !HaveEditView() ) + return -1; + + ESelection aSelection; + if( GetEditViewForwarder().GetSelection( aSelection ) && + GetParagraphIndex() == aSelection.nEndPara ) + { + // caret is always nEndPara,nEndPos + return aSelection.nEndPos; + } + + // not within this paragraph + return -1; + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return setSelection(nIndex, nIndex); + } + + sal_Unicode SAL_CALL AccessibleEditableTextPara::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacter: index value overflow"); + + return OCommonAccessibleText::getCharacter( nIndex ); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + CheckIndex(nIndex); // may throw IndexOutOfBoundsException + + // get default attribues... + ::comphelper::SequenceAsHashMap aPropHashMap( getDefaultAttributes( rRequestedAttributes ) ); + + // ... and override them with the direct attributes from the specific position + uno::Sequence< beans::PropertyValue > aRunAttribs( getRunAttributes( nIndex, rRequestedAttributes ) ); + sal_Int32 nRunAttribs = aRunAttribs.getLength(); + const beans::PropertyValue *pRunAttrib = aRunAttribs.getConstArray(); + for (sal_Int32 k = 0; k < nRunAttribs; ++k) + { + const beans::PropertyValue &rRunAttrib = pRunAttrib[k]; + aPropHashMap[ rRunAttrib.Name ] = rRunAttrib.Value; //!! should not only be the value !! + } +#ifdef TL_DEBUG + { + uno::Sequence< rtl::OUString > aNames(1); + aNames.getArray()[0] = rtl::OUString::createFromAscii("CharHeight"); + const rtl::OUString *pNames = aNames.getConstArray(); + const uno::Sequence< beans::PropertyValue > aAttribs( getRunAttributes( nIndex, aNames ) ); + const beans::PropertyValue *pAttribs = aAttribs.getConstArray(); + double d1 = -1.0; + float f1 = -1.0; + if (aAttribs.getLength()) + { + uno::Any aAny( pAttribs[0].Value ); + aAny >>= d1; + aAny >>= f1; + } + int i = 3; + } +#endif + + // get resulting sequence + uno::Sequence< beans::PropertyValue > aRes; + aPropHashMap >> aRes; + + // since SequenceAsHashMap ignores property handles and property state + // we have to restore the property state here (property handles are + // of no use to the accessibility API). + sal_Int32 nRes = aRes.getLength(); + beans::PropertyValue *pRes = aRes.getArray(); + for (sal_Int32 i = 0; i < nRes; ++i) + { + beans::PropertyValue &rRes = pRes[i]; + sal_Bool bIsDirectVal = sal_False; + for (sal_Int32 k = 0; k < nRunAttribs && !bIsDirectVal; ++k) + { + if (rRes.Name == pRunAttrib[k].Name) + bIsDirectVal = sal_True; + } + rRes.Handle = -1; + rRes.State = bIsDirectVal ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + } + + return aRes; + } + + awt::Rectangle SAL_CALL AccessibleEditableTextPara::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterBounds: index value overflow"); + + // #108900# Have position semantics now for nIndex, as + // one-past-the-end values are legal, too. + CheckPosition( nIndex ); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Rectangle aRect = rCacheTF.GetCharBounds( static_cast< USHORT >( GetParagraphIndex() ), static_cast< USHORT >( nIndex ) ); + + // convert to screen + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + // #109864# offset from parent (paragraph), but in screen + // coordinates. This makes sure the internal text offset in + // the outline view forwarder gets cancelled out here + awt::Rectangle aParaRect( getBounds() ); + aScreenRect.Move( -aParaRect.X, -aParaRect.Y ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getCharacterCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterCount: index value overflow"); + + return OCommonAccessibleText::getCharacterCount(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + USHORT nPara, nIndex; + + // offset from surrounding cell/shape + Point aOffset( GetEEOffset() ); + Point aPoint( rPoint.X - aOffset.X(), rPoint.Y - aOffset.Y() ); + + // convert to logical coordinates + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); + + // re-offset to parent (paragraph) + Rectangle aParaRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + aLogPoint.Move( aParaRect.Left(), aParaRect.Top() ); + + if( rCacheTF.GetIndexAtPoint( aLogPoint, nPara, nIndex ) && + GetParagraphIndex() == nPara ) + { + // #102259# Double-check if we're _really_ on the given character + try + { + awt::Rectangle aRect1( getCharacterBounds(nIndex) ); + Rectangle aRect2( aRect1.X, aRect1.Y, + aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y ); + if( aRect2.IsInside( Point( rPoint.X, rPoint.Y ) ) ) + return nIndex; + else + return -1; + } + catch( const lang::IndexOutOfBoundsException& ) + { + // #103927# Don't throw for invalid nIndex values + return -1; + } + } + else + { + // not within our paragraph + return -1; + } + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getSelectedText() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectedText: index value overflow"); + + if( !HaveEditView() ) + return ::rtl::OUString(); + + return OCommonAccessibleText::getSelectedText(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionStart() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectionStart: index value overflow"); + + if( !HaveEditView() ) + return -1; + + return OCommonAccessibleText::getSelectionStart(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionEnd() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectionEnd: index value overflow"); + + if( !HaveEditView() ) + return -1; + + return OCommonAccessibleText::getSelectionEnd(); + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::setSelection: paragraph index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + return rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getText() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getText: paragraph index value overflow"); + + return OCommonAccessibleText::getText(); + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextRange: paragraph index value overflow"); + + return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex); + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextAtIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + // Not yet handled by OCommonAccessibleText. Missing + // implGetAttributeRunBoundary() method there + case AccessibleTextType::ATTRIBUTE_RUN: + { + const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + aResult.SegmentStart = aResult.SegmentEnd = nTextLen; + } + else + { + USHORT nStartIndex, nEndIndex; + + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextBeforeIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + // Not yet handled by OCommonAccessibleText. Missing + // implGetAttributeRunBoundary() method there + case AccessibleTextType::ATTRIBUTE_RUN: + { + const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + USHORT nStartIndex, nEndIndex; + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + if( nIndex > 0 && + GetAttributeRun(nStartIndex, nEndIndex, nIndex-1) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + else + { + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + // already at the left border? If not, query + // one index further left + if( nStartIndex > 0 && + GetAttributeRun(nStartIndex, nEndIndex, nStartIndex-1) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextBehindIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + case AccessibleTextType::ATTRIBUTE_RUN: + { + USHORT nStartIndex, nEndIndex; + + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + // already at the right border? + if( nEndIndex < GetTextLen() ) + { + if( GetAttributeRun(nStartIndex, nEndIndex, nEndIndex) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + (void)rCacheTF; + #else + GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + #endif + + sal_Bool aRetVal; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::copyText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + // save current selection + ESelection aOldSelection; + + rCacheVF.GetSelection( aOldSelection ); + rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + aRetVal = rCacheVF.Copy(); + rCacheVF.SetSelection( aOldSelection ); // restore + + return aRetVal; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + // XAccessibleEditableText + sal_Bool SAL_CALL AccessibleEditableTextPara::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::cutText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // don't save selection, might become invalid after cut! + rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + + return rCacheVF.Cut(); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::pasteText( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::pasteText: index value overflow"); + + CheckPosition(nIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nIndex) ) ) + return sal_False; // non-editable area selected + + // #104400# set empty selection (=> cursor) to given index + rCacheVF.SetSelection( MakeCursor(nIndex) ); + + return rCacheVF.Paste(); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::deleteText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + sal_Bool bRet = rCacheTF.Delete( MakeSelection(nStartIndex, nEndIndex) ); + + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::insertText: index value overflow"); + + CheckPosition(nIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nIndex) ) ) + return sal_False; // non-editable area selected + + // #104400# insert given text at empty selection (=> cursor) + sal_Bool bRet = rCacheTF.InsertText( sText, MakeCursor(nIndex) ); + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::replaceText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // insert given text into given range => replace + sal_Bool bRet = rCacheTF.InsertText( sReplacement, MakeSelection(nStartIndex, nEndIndex) ); + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const uno::Sequence< beans::PropertyValue >& aAttributeSet ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + USHORT nPara = static_cast< USHORT >( GetParagraphIndex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::setAttributes: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // do the indices span the whole paragraph? Then use the outliner map + // TODO: hold it as a member? + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + 0 == nStartIndex && + rCacheTF.GetTextLen(nPara) == nEndIndex ? + ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() : + ImplGetSvxTextPortionSvxPropertySet() ); + + aPropSet.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + + // convert from PropertyValue to Any + sal_Int32 i, nLength( aAttributeSet.getLength() ); + const beans::PropertyValue* pPropArray = aAttributeSet.getConstArray(); + for(i=0; i<nLength; ++i) + { + try + { + aPropSet.setPropertyValue(pPropArray->Name, pPropArray->Value); + } + catch( const uno::Exception& ) + { + DBG_ERROR("AccessibleEditableTextPara::setAttributes exception in setPropertyValue"); + } + + ++pPropArray; + } + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return sal_True; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setText( const ::rtl::OUString& sText ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return replaceText(0, getCharacterCount(), sText); + } + + // XAccessibleTextAttributes + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDefaultAttributes( + const uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) + throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = + #endif + GetTextForwarder(); + + #if OSL_DEBUG_LEVEL > 0 + (void)rCacheTF; + #endif + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); + + // get XPropertySetInfo for paragraph attributes and + // character attributes that span all the paragraphs text. + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + ImplGetSvxCharAndParaPropertiesSet() ); + aPropSet.SetSelection( MakeSelection( 0, GetTextLen() ) ); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo(); + if (!xPropSetInfo.is()) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot query XPropertySetInfo")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + + // build sequence of available properties to check + sal_Int32 nLenReqAttr = rRequestedAttributes.getLength(); + uno::Sequence< beans::Property > aProperties; + if (nLenReqAttr) + { + const rtl::OUString *pRequestedAttributes = rRequestedAttributes.getConstArray(); + + aProperties.realloc( nLenReqAttr ); + beans::Property *pProperties = aProperties.getArray(); + sal_Int32 nCurLen = 0; + for (sal_Int32 i = 0; i < nLenReqAttr; ++i) + { + beans::Property aProp; + try + { + aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] ); + } + catch (beans::UnknownPropertyException &) + { + continue; + } + pProperties[ nCurLen++ ] = aProp; + } + aProperties.realloc( nCurLen ); + } + else + aProperties = xPropSetInfo->getProperties(); + + sal_Int32 nLength = aProperties.getLength(); + const beans::Property *pProperties = aProperties.getConstArray(); + + // build resulting sequence + uno::Sequence< beans::PropertyValue > aOutSequence( nLength ); + beans::PropertyValue* pOutSequence = aOutSequence.getArray(); + sal_Int32 nOutLen = 0; + for (sal_Int32 i = 0; i < nLength; ++i) + { + // calling implementation functions: + // _getPropertyState and _getPropertyValue (see below) to provide + // the proper paragraph number when retrieving paragraph attributes + PropertyState eState = aPropSet._getPropertyState( pProperties->Name, mnParagraphIndex ); + if ( eState == PropertyState_AMBIGUOUS_VALUE ) + { + OSL_ENSURE( false, "ambiguous property value encountered" ); + } + + //if (eState == PropertyState_DIRECT_VALUE) + // per definition all paragraph properties and all character + // properties spanning the whole paragraph should be returned + // and declared as default value + { + pOutSequence->Name = pProperties->Name; + pOutSequence->Handle = pProperties->Handle; + pOutSequence->Value = aPropSet._getPropertyValue( pProperties->Name, mnParagraphIndex ); + pOutSequence->State = PropertyState_DEFAULT_VALUE; + + ++pOutSequence; + ++nOutLen; + } + ++pProperties; + } + aOutSequence.realloc( nOutLen ); + + return aOutSequence; + } + + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRunAttributes( + sal_Int32 nIndex, + const uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = + #endif + GetTextForwarder(); + + #if OSL_DEBUG_LEVEL > 0 + (void)rCacheTF; + #endif + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); + + CheckIndex(nIndex); + + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + ImplGetSvxCharAndParaPropertiesSet() ); + aPropSet.SetSelection( MakeSelection( nIndex ) ); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo(); + if (!xPropSetInfo.is()) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot query XPropertySetInfo")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + + // build sequence of available properties to check + sal_Int32 nLenReqAttr = rRequestedAttributes.getLength(); + uno::Sequence< beans::Property > aProperties; + if (nLenReqAttr) + { + const rtl::OUString *pRequestedAttributes = rRequestedAttributes.getConstArray(); + + aProperties.realloc( nLenReqAttr ); + beans::Property *pProperties = aProperties.getArray(); + sal_Int32 nCurLen = 0; + for (sal_Int32 i = 0; i < nLenReqAttr; ++i) + { + beans::Property aProp; + try + { + aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] ); + } + catch (beans::UnknownPropertyException &) + { + continue; + } + pProperties[ nCurLen++ ] = aProp; + } + aProperties.realloc( nCurLen ); + } + else + aProperties = xPropSetInfo->getProperties(); + + sal_Int32 nLength = aProperties.getLength(); + const beans::Property *pProperties = aProperties.getConstArray(); + + // build resulting sequence + uno::Sequence< beans::PropertyValue > aOutSequence( nLength ); + beans::PropertyValue* pOutSequence = aOutSequence.getArray(); + sal_Int32 nOutLen = 0; + for (sal_Int32 i = 0; i < nLength; ++i) + { + // calling 'regular' functions that will operate on the selection + PropertyState eState = aPropSet.getPropertyState( pProperties->Name ); + if (eState == PropertyState_DIRECT_VALUE) + { + pOutSequence->Name = pProperties->Name; + pOutSequence->Handle = pProperties->Handle; + pOutSequence->Value = aPropSet.getPropertyValue( pProperties->Name ); + pOutSequence->State = eState; + + ++pOutSequence; + ++nOutLen; + } + ++pProperties; + } + aOutSequence.realloc( nOutLen ); + + return aOutSequence; + } + + // XAccessibleMultiLineText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getLineNumberAtIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nRes = -1; + sal_Int32 nPara = GetParagraphIndex(); + + SvxTextForwarder &rCacheTF = GetTextForwarder(); + const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); + DBG_ASSERT( bValidPara, "getLineNumberAtIndex: current paragraph index out of range" ); + if (bValidPara) + { + // we explicitly allow for the index to point at the character right behind the text + if (0 <= nIndex && nIndex <= rCacheTF.GetTextLen( static_cast< USHORT >(nPara) )) + nRes = rCacheTF.GetLineNumberAtIndex( static_cast< USHORT >(nPara), static_cast< USHORT >(nIndex) ); + else + throw lang::IndexOutOfBoundsException(); + } + return nRes; + } + + // XAccessibleMultiLineText + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineNumber( sal_Int32 nLineNo ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::com::sun::star::accessibility::TextSegment aResult; + sal_Int32 nPara = GetParagraphIndex(); + SvxTextForwarder &rCacheTF = GetTextForwarder(); + const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); + DBG_ASSERT( bValidPara, "getTextAtLineNumber: current paragraph index out of range" ); + if (bValidPara) + { + if (0 <= nLineNo && nLineNo < rCacheTF.GetLineCount( static_cast< USHORT >(nPara) )) + { + USHORT nStart = 0, nEnd = 0; + rCacheTF.GetLineBoundaries( nStart, nEnd, static_cast< USHORT >(nPara), static_cast< USHORT >(nLineNo) ); + if (nStart != 0xFFFF && nEnd != 0xFFFF) + { + try + { + aResult.SegmentText = getTextRange( nStart, nEnd ); + aResult.SegmentStart = nStart; + aResult.SegmentEnd = nEnd; + } + catch (lang::IndexOutOfBoundsException) + { + // this is not the exception that should be raised in this function ... + DBG_ASSERT( 0, "unexpected exception" ); + } + } + } + else + throw lang::IndexOutOfBoundsException(); + } + return aResult; + } + + // XAccessibleMultiLineText + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineWithCaret( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::com::sun::star::accessibility::TextSegment aResult; + try + { + aResult = getTextAtLineNumber( getNumberOfLineWithCaret() ); + } + catch (lang::IndexOutOfBoundsException &) + { + // this one needs to be catched since this interface does not allow for it. + } + return aResult; + } + + // XAccessibleMultiLineText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getNumberOfLineWithCaret( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nRes = -1; + try + { + nRes = getLineNumberAtIndex( getCaretPosition() ); + } + catch (lang::IndexOutOfBoundsException &) + { + // this one needs to be catched since this interface does not allow for it. + } + return nRes; + } + + + // XServiceInfo + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getImplementationName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("AccessibleEditableTextPara")); + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::supportsService (const ::rtl::OUString& sServiceName) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; + } + + uno::Sequence< ::rtl::OUString> SAL_CALL AccessibleEditableTextPara::getSupportedServiceNames (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + const ::rtl::OUString sServiceName( getServiceName() ); + return uno::Sequence< ::rtl::OUString > (&sServiceName, 1); + } + + // XServiceName + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getServiceName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #105185# Using correct service now + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.AccessibleParagraphView")); + } + +} // end of namespace accessibility + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.hxx b/editeng/source/accessibility/AccessibleEditableTextPara.hxx new file mode 100644 index 0000000000..f78cbd4ad4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleEditableTextPara.hxx @@ -0,0 +1,414 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleEditableTextPara.hxx,v $ + * $Revision: 1.22 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_EDITABLE_TEXT_PARA_HXX +#define _SVX_ACCESSIBLE_EDITABLE_TEXT_PARA_HXX + +#include <tools/gen.hxx> +#include <tools/string.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/compbase8.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleEditableText.hpp> +#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp> +#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp> + +#include <comphelper/accessibletexthelper.hxx> +#include <comphelper/broadcasthelper.hxx> +#include "AccessibleParaManager.hxx" +#include "AccessibleImageBullet.hxx" +#include "unoedprx.hxx" + +namespace accessibility +{ + typedef ::cppu::WeakComponentImplHelper8< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleEditableText, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleTextAttributes, + ::com::sun::star::accessibility::XAccessibleMultiLineText, + ::com::sun::star::lang::XServiceInfo > AccessibleTextParaInterfaceBase; + + /** This class implements the actual text paragraphs for the EditEngine/Outliner UAA + */ + class AccessibleEditableTextPara : public ::comphelper::OBaseMutex, public AccessibleTextParaInterfaceBase, public ::comphelper::OCommonAccessibleText + { + + protected: + // override OCommonAccessibleText methods + virtual ::rtl::OUString implGetText(); + virtual ::com::sun::star::lang::Locale implGetLocale(); + virtual void implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ); + virtual void implGetParagraphBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ); + virtual void implGetLineBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ); + + public: + /// Create accessible object for given parent + // --> OD 2006-01-11 #i27138# + // - add parameter <_pParaManager> (default value NULL) + // This has to be the the instance of <AccessibleParaManager>, which + // created and manages this accessible paragraph. + AccessibleEditableTextPara ( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rParent, + const AccessibleParaManager* _pParaManager = NULL ); + // <-- + + virtual ~AccessibleEditableTextPara (); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface (const ::com::sun::star::uno::Type & rType) throw (::com::sun::star::uno::RuntimeException); + + // XComponent + + using WeakComponentImplHelperBase::addEventListener; + using WeakComponentImplHelperBase::removeEventListener; + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole() throw (::com::sun::star::uno::RuntimeException); + /// Maximal length of text returned by getAccessibleDescription() + enum { MaxDescriptionLen = 40 }; + virtual ::rtl::OUString SAL_CALL getAccessibleDescription() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale() throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleText (this comes implicitely inherited by XAccessibleEditableText AND by XAccessibleMultiLineText) + virtual sal_Int32 SAL_CALL getCaretPosition() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getCharacterCount() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getIndexAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSelectedText() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionStart() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionEnd() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getText() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEditableText + virtual sal_Bool SAL_CALL cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL pasteText( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aAttributeSet ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setText( const ::rtl::OUString& sText ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleTextAttributes + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getDefaultAttributes( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getRunAttributes( ::sal_Int32 Index, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleMultiLineText + virtual ::sal_Int32 SAL_CALL getLineNumberAtIndex( ::sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtLineNumber( ::sal_Int32 nLineNo ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtLineWithCaret( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getNumberOfLineWithCaret( ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName (void) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService (const ::rtl::OUString& sServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames (void) throw (::com::sun::star::uno::RuntimeException); + + // XServiceName + virtual ::rtl::OUString SAL_CALL getServiceName (void) throw (::com::sun::star::uno::RuntimeException); + + /** Set the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetIndexInParent( sal_Int32 nIndex ); + + /** Get the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetIndexInParent() const; + + /** Set the current paragraph number + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetParagraphIndex( sal_Int32 nIndex ); + + /** Query the current paragraph number (0 - nParas-1) + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetParagraphIndex() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Set the edit engine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEEOffset( const Point& rOffset ); + + /** Set the EditEngine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEditSource( SvxEditSourceAdapter* pEditSource ); + + /** Dispose this object + + Notifies and deregisters the listeners, drops all references. + */ + void Dispose(); + + /// Calls all Listener objects to tell them the change. Don't hold locks when calling this! + virtual void FireEvent(const sal_Int16 nEventId, const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + /// Queries the given state on the internal state set + bool HasState( const sal_Int16 nStateId ); + /// Sets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this! + void SetState( const sal_Int16 nStateId ); + /// Unsets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this! + void UnSetState( const sal_Int16 nStateId ); + + static Rectangle LogicToPixel( const Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder& rForwarder ); + + SvxEditSourceAdapter& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxTextForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxAccessibleTextAdapter& GetTextForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxViewForwarder& GetViewForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query whether a GetEditViewForwarder( sal_False ) will return a forwarder + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Bool HaveEditView() const; + + /** Query the SvxEditViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxAccessibleTextEditViewAdapter& GetEditViewForwarder( sal_Bool bCreate = sal_False ) const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Send a TEXT_CHANGED event for this paragraph + + This method internally caters for calculating text + differences, and sends the appropriate Anys in the + Accessibility::TEXT_CHANGED event + */ + void TextChanged(); + + private: + + // declared, but not defined + AccessibleEditableTextPara( const AccessibleEditableTextPara& ); + AccessibleEditableTextPara& operator= ( const AccessibleEditableTextPara& ); + + /** Calculate character range of similar attributes + + @param nStartIndex + Therein, the start of the character range with the same attributes is returned + + @param nEndIndex + Therein, the end (exclusively) of the character range with the same attributes is returned + + @param nIndex + The character index at where to look for similar character attributes + + @return sal_False, if the method was not able to determine the range + */ + sal_Bool GetAttributeRun( USHORT& nStartIndex, USHORT& nEndIndex, sal_Int32 nIndex ); + + // syntactic sugar for FireEvent + void GotPropertyEvent( const ::com::sun::star::uno::Any& rNewValue, const sal_Int16 nEventId ) const; + void LostPropertyEvent( const ::com::sun::star::uno::Any& rOldValue, const sal_Int16 nEventId ) const; + + /** Query the visibility state + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + + @return the visibility state. Per definition, a defunc object is no longer visible + */ + sal_Bool IsVisible() const; + + int getNotifierClientId() const; + + // retrieve text interface for given paragraph index + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleText > GetParaInterface( sal_Int32 nIndex ); + + /// Do we have children? This is the case for image bullets + sal_Bool HaveChildren(); + + /// Is the underlying object in edit mode + sal_Bool IsActive() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + const Point& GetEEOffset() const; + + // Get text from forwarder + String GetText( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + String GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + USHORT GetTextLen() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Get the current selection of this paragraph + + @return sal_False, if nothing in this paragraph is selected + */ + sal_Bool GetSelection( USHORT& nStartPos, USHORT& nEndPos ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** create selection from Accessible selection. + + */ + ESelection MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex ); + ESelection MakeSelection( sal_Int32 nEEIndex ); + ESelection MakeCursor( sal_Int32 nEEIndex ); + + // check whether index value is within permitted range + + /// Check whether 0<=nIndex<=n-1 + void CheckIndex( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + /// Check whether 0<=nIndex<=n + void CheckPosition( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + /// Check whether 0<=nStart<=n and 0<=nEnd<=n + void CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + + // the paragraph index in the edit engine (guarded by solar mutex) + sal_Int32 mnParagraphIndex; + + // our current index in the parent (guarded by solar mutex) + sal_Int32 mnIndexInParent; + + // the current edit source (guarded by solar mutex) + SvxEditSourceAdapter* mpEditSource; + + // the possible child (for image bullets, guarded by solar mutex) + typedef WeakCppRef < ::com::sun::star::accessibility::XAccessible, AccessibleImageBullet > WeakBullet; + WeakBullet maImageBullet; + + // the last string used for an Accessibility::TEXT_CHANGED event (guarded by solar mutex) + ::rtl::OUString maLastTextString; + + // the offset of the underlying EditEngine from the shape/cell (guarded by solar mutex) + Point maEEOffset; + + // the current state set (updated from SetState/UnSetState and guarded by solar mutex) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > mxStateSet; + + /// The shape we're the accessible for (unguarded) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxParent; + + /// Our listeners (guarded by maMutex) + int mnNotifierClientId; + + // --> OD 2006-01-11 #i27138# + // the paragraph manager, which created this instance - is NULL, if + // instance isn't created by AccessibleParaManager. + // Needed for method <getAccessibleRelationSet()> to retrieve predecessor + // paragraph and the successor paragraph. + const AccessibleParaManager* mpParaManager; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleImageBullet.cxx b/editeng/source/accessibility/AccessibleImageBullet.cxx new file mode 100644 index 0000000000..064f196049 --- /dev/null +++ b/editeng/source/accessibility/AccessibleImageBullet.cxx @@ -0,0 +1,654 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleImageBullet.cxx,v $ + * $Revision: 1.22 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" +#include <tools/gen.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <editeng/unolingu.hxx> +#include "AccessibleEditableTextPara.hxx" +#include "AccessibleImageBullet.hxx" +#include <editeng/eerdll.hxx> + +#include <editeng/editdata.hxx> +#include <editeng/editeng.hxx> +#include <editeng/outliner.hxx> +#include "editeng.hrc" +#include <svtools/colorcfg.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility +{ + DBG_NAME( AccessibleImageBullet ) + + AccessibleImageBullet::AccessibleImageBullet ( const uno::Reference< XAccessible >& rParent ) : + mnParagraphIndex( 0 ), + mnIndexInParent( 0 ), + mpEditSource( NULL ), + maEEOffset( 0, 0 ), + mxParent( rParent ), + // well, that's strictly (UNO) exception safe, though not + // really robust. We rely on the fact that this member is + // constructed last, and that the constructor body catches + // exceptions, thus no chance for exceptions once the Id is + // fetched. Nevertheless, normally should employ RAII here... + mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient()) + { +#ifdef DBG_UTIL + DBG_CTOR( AccessibleImageBullet, NULL ); + OSL_TRACE( "Received ID: %d", mnNotifierClientId ); +#endif + + try + { + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // these are always on + pStateSet->AddState( AccessibleStateType::VISIBLE ); + pStateSet->AddState( AccessibleStateType::SHOWING ); + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::SENSITIVE ); + } + catch( const uno::Exception& ) {} + } + + AccessibleImageBullet::~AccessibleImageBullet() + { + DBG_DTOR( AccessibleImageBullet, NULL ); + + // sign off from event notifier + if( getNotifierClientId() != -1 ) + { + try + { + ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleImageBullet revoked ID: %d\n", mnNotifierClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + uno::Any SAL_CALL AccessibleImageBullet::queryInterface (const uno::Type & rType) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return AccessibleImageBulletInterfaceBase::queryInterface(rType); + } + + uno::Reference< XAccessibleContext > SAL_CALL AccessibleImageBullet::getAccessibleContext( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // We implement the XAccessibleContext interface in the same object + return uno::Reference< XAccessibleContext > ( this ); + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleChildCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + (void)i; + + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No childs available")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mxParent; + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleIndexInParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnIndexInParent; + } + + sal_Int16 SAL_CALL AccessibleImageBullet::getAccessibleRole() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return AccessibleRole::GRAPHIC; + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getAccessibleDescription() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Get the string from the resource for the specified id. + return ::rtl::OUString( String( EditResId (RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION) ) ); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getAccessibleName() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Get the string from the resource for the specified id. + return ::rtl::OUString( String ( EditResId (RID_SVXSTR_A11Y_IMAGEBULLET_NAME) ) ); + } + + uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleImageBullet::getAccessibleRelationSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // no relations, therefore empty + return uno::Reference< XAccessibleRelationSet >(); + } + + uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleImageBullet::getAccessibleStateSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Create a copy of the state set and return it. + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + if( !pStateSet ) + return uno::Reference<XAccessibleStateSet>(); + + return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + } + + lang::Locale SAL_CALL AccessibleImageBullet::getLocale() throw (IllegalAccessibleComponentStateException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + lang::Locale aLocale; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleImageBullet::getLocale: paragraph index value overflow"); + + // return locale of first character in the paragraph + return SvxLanguageToLocale(aLocale, GetTextForwarder().GetLanguage( static_cast< USHORT >( GetParagraphIndex() ), 0 )); + } + + void SAL_CALL AccessibleImageBullet::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener ); + } + + void SAL_CALL AccessibleImageBullet::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener ); + } + + sal_Bool SAL_CALL AccessibleImageBullet::containsPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::contains: index value overflow"); + + awt::Rectangle aTmpRect = getBounds(); + Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); + Point aPoint( rPoint.X, rPoint.Y ); + + return aRect.IsInside( aPoint ); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleAtPoint( const awt::Point& /*aPoint*/ ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // as we have no children, empty reference + return uno::Reference< XAccessible >(); + } + + awt::Rectangle SAL_CALL AccessibleImageBullet::getBounds( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getBounds: index value overflow"); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( static_cast< USHORT > (GetParagraphIndex()) ); + Rectangle aParentRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + + if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && + aBulletInfo.bVisible && + aBulletInfo.nType == SVX_NUM_BITMAP ) + { + Rectangle aRect = aBulletInfo.aBounds; + + // subtract paragraph position (bullet pos is absolute in EditEngine/Outliner) + aRect.Move( -aParentRect.Left(), -aParentRect.Top() ); + + // convert to screen coordinates + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + return awt::Rectangle(); + } + + awt::Point SAL_CALL AccessibleImageBullet::getLocation( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Point( aRect.X, aRect.Y ); + } + + awt::Point SAL_CALL AccessibleImageBullet::getLocationOnScreen( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // relate us to parent + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY ); + if( xParentComponent.is() ) + { + awt::Point aRefPoint = xParentComponent->getLocationOnScreen(); + awt::Point aPoint = getLocation(); + aPoint.X += aRefPoint.X; + aPoint.Y += aRefPoint.Y; + + return aPoint; + } + } + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot access parent")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + awt::Size SAL_CALL AccessibleImageBullet::getSize( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Size( aRect.Width, aRect.Height ); + } + + void SAL_CALL AccessibleImageBullet::grabFocus( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Not focusable")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getForeground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // #104444# Added to XAccessibleComponent interface + svtools::ColorConfig aColorConfig; + UINT32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + return static_cast<sal_Int32>(nColor); + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getBackground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // #104444# Added to XAccessibleComponent interface + Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() ); + + // the background is transparent + aColor.SetTransparency( 0xFF); + + return static_cast<sal_Int32>( aColor.GetColor() ); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getImplementationName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("AccessibleImageBullet")); + } + + sal_Bool SAL_CALL AccessibleImageBullet::supportsService (const ::rtl::OUString& sServiceName) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; + } + + uno::Sequence< ::rtl::OUString> SAL_CALL AccessibleImageBullet::getSupportedServiceNames (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + const ::rtl::OUString sServiceName (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.accessibility.AccessibleContext")); + return uno::Sequence< ::rtl::OUString > (&sServiceName, 1); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getServiceName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext")); + } + + void AccessibleImageBullet::SetIndexInParent( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + mnIndexInParent = nIndex; + } + + sal_Int32 AccessibleImageBullet::GetIndexInParent() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnIndexInParent; + } + + void AccessibleImageBullet::SetEEOffset( const Point& rOffset ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + maEEOffset = rOffset; + } + + void AccessibleImageBullet::Dispose() + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + int nClientId( getNotifierClientId() ); + + // #108212# drop all references before notifying dispose + mxParent = NULL; + mnNotifierClientId = -1; + mpEditSource = NULL; + + // notify listeners + if( nClientId != -1 ) + { + try + { + uno::Reference < XAccessibleContext > xThis = getAccessibleContext(); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, xThis ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleImageBullet disposed ID: %d", nClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + void AccessibleImageBullet::SetEditSource( SvxEditSource* pEditSource ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + mpEditSource = pEditSource; + + if( !mpEditSource ) + { + // going defunc + UnSetState( AccessibleStateType::SHOWING ); + UnSetState( AccessibleStateType::VISIBLE ); + SetState( AccessibleStateType::INVALID ); + SetState( AccessibleStateType::DEFUNC ); + + Dispose(); + } + } + + void AccessibleImageBullet::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleImageBullet* > (this)->getAccessibleContext() ); + + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(), + aEvent ); + } + + void AccessibleImageBullet::GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + FireEvent( nEventId, rNewValue ); + } + + void AccessibleImageBullet::LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + FireEvent( nEventId, uno::Any(), rOldValue ); + } + + void AccessibleImageBullet::SetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + !pStateSet->contains(nStateId) ) + { + pStateSet->AddState( nStateId ); + GotPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleImageBullet::UnSetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + pStateSet->contains(nStateId) ) + { + pStateSet->RemoveState( nStateId ); + LostPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + int AccessibleImageBullet::getNotifierClientId() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnNotifierClientId; + } + + void AccessibleImageBullet::SetParagraphIndex( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + uno::Any aOldDesc; + uno::Any aOldName; + + try + { + aOldDesc <<= getAccessibleDescription(); + aOldName <<= getAccessibleName(); + } + catch( const uno::Exception& ) {} // optional behaviour + + sal_Int32 nOldIndex = mnParagraphIndex; + + mnParagraphIndex = nIndex; + + try + { + if( nOldIndex != nIndex ) + { + // index and therefore description changed + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + } + } + catch( const uno::Exception& ) {} // optional behaviour + } + + sal_Int32 AccessibleImageBullet::GetParagraphIndex() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnParagraphIndex; + } + + SvxEditSource& AccessibleImageBullet::GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( mpEditSource ) + return *mpEditSource; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit source, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + SvxTextForwarder& AccessibleImageBullet::GetTextForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxTextForwarder* pTextForwarder = rEditSource.GetTextForwarder(); + + if( !pTextForwarder ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + + if( pTextForwarder->IsValid() ) + return *pTextForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + SvxViewForwarder& AccessibleImageBullet::GetViewForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder(); + + if( !pViewForwarder ) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + if( pViewForwarder->IsValid() ) + return *pViewForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + const Point& AccessibleImageBullet::GetEEOffset() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return maEEOffset; + } + +} // end of namespace accessibility + diff --git a/editeng/source/accessibility/AccessibleImageBullet.hxx b/editeng/source/accessibility/AccessibleImageBullet.hxx new file mode 100644 index 0000000000..b1dc462021 --- /dev/null +++ b/editeng/source/accessibility/AccessibleImageBullet.hxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleImageBullet.hxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_IMAGE_BULLET_HXX +#define _SVX_ACCESSIBLE_IMAGE_BULLET_HXX + +#include <tools/gen.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/implbase5.hxx> + +#ifndef _CPPUHELPER_INTERFACECONTAINER_H_ +#include <cppuhelper/interfacecontainer.hxx> +#endif +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include "AccessibleParaManager.hxx" +#include <editeng/unoedsrc.hxx> + +namespace accessibility +{ + typedef ::cppu::WeakImplHelper5< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::lang::XServiceInfo > AccessibleImageBulletInterfaceBase; + + /** This class implements the image bullets for the EditEngine/Outliner UAA + */ + class AccessibleImageBullet : public AccessibleImageBulletInterfaceBase + { + + public: + /// Create accessible object for given parent + AccessibleImageBullet ( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rParent ); + + virtual ~AccessibleImageBullet (); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface (const ::com::sun::star::uno::Type & rType) throw (::com::sun::star::uno::RuntimeException); + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole() throw (::com::sun::star::uno::RuntimeException); + /// Maximal length of text returned by getAccessibleDescription() + enum { MaxDescriptionLen = 40 }; + virtual ::rtl::OUString SAL_CALL getAccessibleDescription() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale() throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName (void) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService (const ::rtl::OUString& sServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames (void) throw (::com::sun::star::uno::RuntimeException); + + // XServiceName + virtual ::rtl::OUString SAL_CALL getServiceName (void) throw (::com::sun::star::uno::RuntimeException); + + /** Set the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetIndexInParent( sal_Int32 nIndex ); + + /** Get the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetIndexInParent() const; + + /** Set the edit engine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEEOffset( const Point& rOffset ); + + /** Set the EditEngine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEditSource( SvxEditSource* pEditSource ); + + /** Dispose this object + + Notifies and deregisters the listeners, drops all references. + */ + void Dispose(); + + /** Set the current paragraph number + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetParagraphIndex( sal_Int32 nIndex ); + + /** Query the current paragraph number (0 - nParas-1) + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetParagraphIndex() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /// Calls all Listener objects to tell them the change. Don't hold locks when calling this! + virtual void FireEvent(const sal_Int16 nEventId, const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + private: + + // declared, but not defined + AccessibleImageBullet( const AccessibleImageBullet& ); + AccessibleImageBullet& operator= ( const AccessibleImageBullet& ); + + // syntactic sugar for FireEvent + void GotPropertyEvent( const ::com::sun::star::uno::Any& rNewValue, const sal_Int16 nEventId ) const; + void LostPropertyEvent( const ::com::sun::star::uno::Any& rOldValue, const sal_Int16 nEventId ) const; + + // maintain state set and send STATE_CHANGE events + void SetState( const sal_Int16 nStateId ); + void UnSetState( const sal_Int16 nStateId ); + + SvxEditSource& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + int getNotifierClientId() const; + + /** Query the SvxTextForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxTextForwarder& GetTextForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxViewForwarder& GetViewForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + const Point& GetEEOffset() const; + + // the paragraph index in the edit engine (guarded by solar mutex) + sal_Int32 mnParagraphIndex; + + // our current index in the parent (guarded by solar mutex) + sal_Int32 mnIndexInParent; + + // the current edit source (guarded by solar mutex) + SvxEditSource* mpEditSource; + + // the offset of the underlying EditEngine from the shape/cell (guarded by solar mutex) + Point maEEOffset; + + // the current state set (updated from SetState/UnSetState and guarded by solar mutex) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > mxStateSet; + + mutable osl::Mutex maMutex; + + /// The shape we're the accessible for (unguarded) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxParent; + + /// Our listeners (guarded by maMutex) + int mnNotifierClientId; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleParaManager.cxx b/editeng/source/accessibility/AccessibleParaManager.cxx new file mode 100644 index 0000000000..0d8e75020c --- /dev/null +++ b/editeng/source/accessibility/AccessibleParaManager.cxx @@ -0,0 +1,423 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleParaManager.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weakref.hxx> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <editeng/unoedhlp.hxx> +#include <editeng/unopracc.hxx> +#include <editeng/unoedsrc.hxx> +#include "AccessibleParaManager.hxx" +#include "AccessibleEditableTextPara.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + + + +namespace accessibility +{ + AccessibleParaManager::AccessibleParaManager() : + maChildren(1), + maEEOffset( 0, 0 ), + mnFocusedChild( -1 ), + mbActive( sal_False ) + { + } + + AccessibleParaManager::~AccessibleParaManager() + { + // owner is responsible for possible child defuncs + } + + void AccessibleParaManager::SetAdditionalChildStates( const VectorOfStates& rChildStates ) + { + maChildStates = rChildStates; + } + + const AccessibleParaManager::VectorOfStates& AccessibleParaManager::GetAdditionalChildStates() const + { + return maChildStates; + } + + void AccessibleParaManager::SetNum( sal_Int32 nNumParas ) + { + if( (size_t)nNumParas < maChildren.size() ) + Release( nNumParas, maChildren.size() ); + + maChildren.resize( nNumParas ); + + if( mnFocusedChild >= nNumParas ) + mnFocusedChild = -1; + } + + sal_uInt32 AccessibleParaManager::GetNum() const + { + return maChildren.size(); + } + + AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin() + { + return maChildren.begin(); + } + + AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end() + { + return maChildren.end(); + } + + AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::begin() const + { + return maChildren.begin(); + } + + AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::end() const + { + return maChildren.end(); + } + + void AccessibleParaManager::Release( sal_uInt32 nPara ) + { + DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::Release: invalid index" ); + + if( maChildren.size() > nPara ) + { + ShutdownPara( GetChild( nPara ) ); + + // clear reference and rect + maChildren[ nPara ] = WeakChild(); + } + } + + void AccessibleParaManager::FireEvent( sal_uInt32 nPara, + const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) const + { + DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::FireEvent: invalid index" ); + + if( maChildren.size() > nPara ) + { + WeakPara::HardRefType maChild( GetChild( nPara ).first.get() ); + if( maChild.is() ) + maChild->FireEvent( nEventId, rNewValue, rOldValue ); + } + } + + sal_Bool AccessibleParaManager::IsReferencable( WeakPara::HardRefType aChild ) + { + return aChild.is(); + } + + sal_Bool AccessibleParaManager::IsReferencable( sal_uInt32 nChild ) const + { + DBG_ASSERT( maChildren.size() > nChild, "AccessibleParaManager::IsReferencable: invalid index" ); + + if( maChildren.size() > nChild ) + { + // retrieve hard reference from weak one + return IsReferencable( GetChild( nChild ).first.get() ); + } + else + { + return sal_False; + } + } + + AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_uInt32 nParagraphIndex ) const + { + DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::GetChild: invalid index" ); + + if( maChildren.size() > nParagraphIndex ) + { + return maChildren[ nParagraphIndex ]; + } + else + { + return WeakChild(); + } + } + + AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild, + const uno::Reference< XAccessible >& xFrontEnd, + SvxEditSourceAdapter& rEditSource, + sal_uInt32 nParagraphIndex ) + { + DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::CreateChild: invalid index" ); + + if( maChildren.size() > nParagraphIndex ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aChild( GetChild( nParagraphIndex ).first.get() ); + + if( !IsReferencable( nParagraphIndex ) ) + { + // there is no hard reference available, create object then + // --> OD 2006-01-11 #i27138# + AccessibleEditableTextPara* pChild = new AccessibleEditableTextPara( xFrontEnd, this ); + // <-- + uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY ); + + if( !xChild.is() ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), xFrontEnd); + + aChild = WeakPara::HardRefType( xChild, pChild ); + + InitChild( *aChild, rEditSource, nChild, nParagraphIndex ); + + maChildren[ nParagraphIndex ] = WeakChild( aChild, pChild->getBounds() ); + } + + return Child( aChild.getRef(), GetChild( nParagraphIndex ).second ); + } + else + { + return Child(); + } + } + + void AccessibleParaManager::SetEEOffset( const Point& rOffset ) + { + maEEOffset = rOffset; + + MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset ); + ::std::for_each( begin(), end(), aAdapter ); + } + + void AccessibleParaManager::SetActive( sal_Bool bActive ) + { + mbActive = bActive; + + if( bActive ) + { + SetState( AccessibleStateType::ACTIVE ); + SetState( AccessibleStateType::EDITABLE ); + } + else + { + UnSetState( AccessibleStateType::ACTIVE ); + UnSetState( AccessibleStateType::EDITABLE ); + } + } + + void AccessibleParaManager::SetFocus( sal_Int32 nChild ) + { + if( mnFocusedChild != -1 ) + UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED ); + + mnFocusedChild = nChild; + + if( mnFocusedChild != -1 ) + SetState( mnFocusedChild, AccessibleStateType::FOCUSED ); + } + + void AccessibleParaManager::InitChild( AccessibleEditableTextPara& rChild, + SvxEditSourceAdapter& rEditSource, + sal_Int32 nChild, + sal_uInt32 nParagraphIndex ) const + { + rChild.SetEditSource( &rEditSource ); + rChild.SetIndexInParent( nChild ); + rChild.SetParagraphIndex( nParagraphIndex ); + + rChild.SetEEOffset( maEEOffset ); + + if( mbActive ) + { + rChild.SetState( AccessibleStateType::ACTIVE ); + rChild.SetState( AccessibleStateType::EDITABLE ); + } + + if( mnFocusedChild == static_cast<sal_Int32>(nParagraphIndex) ) + rChild.SetState( AccessibleStateType::FOCUSED ); + + // add states passed from outside + for( VectorOfStates::const_iterator aIt = maChildStates.begin(), aEnd = maChildStates.end(); aIt != aEnd; ++aIt ) + rChild.SetState( *aIt ); + } + + void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int16 nStateId ) + { + MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::SetState, + nStateId ); + aFunc( GetChild(nChild) ); + } + + void AccessibleParaManager::SetState( const sal_Int16 nStateId ) + { + ::std::for_each( begin(), end(), + MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::SetState, + nStateId ) ); + } + + void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ) + { + MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::UnSetState, + nStateId ); + aFunc( GetChild(nChild) ); + } + + void AccessibleParaManager::UnSetState( const sal_Int16 nStateId ) + { + ::std::for_each( begin(), end(), + MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::UnSetState, + nStateId ) ); + } + + void AccessibleParaManager::SetEditSource( SvxEditSourceAdapter* pEditSource ) + { + MemFunAdapter< SvxEditSourceAdapter* > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEditSource, pEditSource ); + ::std::for_each( begin(), end(), aAdapter ); + } + + // not generic yet, no arguments... + class AccessibleParaManager_DisposeChildren : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > + { + public: + AccessibleParaManager_DisposeChildren() {} + void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) + { + rPara.Dispose(); + } + }; + + void AccessibleParaManager::Dispose() + { + AccessibleParaManager_DisposeChildren aFunctor; + + ::std::for_each( begin(), end(), + WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) ); + } + + // not generic yet, too many method arguments... + class StateChangeEvent : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > + { + public: + typedef void return_type; + StateChangeEvent( const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) : + mnEventId( nEventId ), + mrNewValue( rNewValue ), + mrOldValue( rOldValue ) {} + void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) + { + rPara.FireEvent( mnEventId, mrNewValue, mrOldValue ); + } + + private: + const sal_Int16 mnEventId; + const uno::Any& mrNewValue; + const uno::Any& mrOldValue; + }; + + void AccessibleParaManager::FireEvent( sal_uInt32 nStartPara, + sal_uInt32 nEndPara, + const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) const + { + DBG_ASSERT( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara , "AccessibleParaManager::FireEvent: invalid index" ); + + if( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara ) + { + VectorOfChildren::const_iterator front = maChildren.begin(); + VectorOfChildren::const_iterator back = front; + + ::std::advance( front, nStartPara ); + ::std::advance( back, nEndPara ); + + StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue ); + + ::std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) ); + } + } + + class ReleaseChild : public ::std::unary_function< const AccessibleParaManager::WeakChild&, AccessibleParaManager::WeakChild > + { + public: + AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara ) + { + AccessibleParaManager::ShutdownPara( rPara ); + + // clear reference + return AccessibleParaManager::WeakChild(); + } + }; + + void AccessibleParaManager::Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara ) + { + DBG_ASSERT( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara, "AccessibleParaManager::Release: invalid index" ); + + if( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara ) + { + VectorOfChildren::iterator front = maChildren.begin(); + VectorOfChildren::iterator back = front; + + ::std::advance( front, nStartPara ); + ::std::advance( back, nEndPara ); + + ::std::transform( front, back, front, ReleaseChild() ); + } + } + + void AccessibleParaManager::ShutdownPara( const WeakChild& rChild ) + { + WeakPara::HardRefType aChild( rChild.first.get() ); + + if( IsReferencable( aChild ) ) + aChild->SetEditSource( NULL ); + } + +} + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleParaManager.hxx b/editeng/source/accessibility/AccessibleParaManager.hxx new file mode 100644 index 0000000000..17644c2b7a --- /dev/null +++ b/editeng/source/accessibility/AccessibleParaManager.hxx @@ -0,0 +1,349 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleParaManager.hxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_PARA_MANAGER_HXX +#define _SVX_ACCESSIBLE_PARA_MANAGER_HXX + +#include <vector> +#include <algorithm> +#include <functional> +#include <utility> +#include <tools/gen.hxx> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weakref.hxx> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> + +class SvxEditSourceAdapter; + +namespace accessibility +{ + class AccessibleEditableTextPara; + + /** Helper class for WeakCppRef + + This class is returned by WeakChild::get() and contains a hard + reference and a reference to the c++ object. This combination + prevents the c++ object from destruction during usage. Hold + this object only as long as absolutely necessary, prevents + referenced object from vanishing otherwise + */ + template < class UnoType, class CppType > class HardCppRef + { + public: + + typedef UnoType UnoInterfaceType; + typedef CppType InterfaceType; + + HardCppRef( const ::com::sun::star::uno::WeakReference< UnoInterfaceType >& xRef, InterfaceType* rImpl ) : + mxRef( xRef ), + mpImpl( rImpl ) + { + } + + /** Query whether the reference is still valid. + + Hands off also from the implementation pointer if this + returns sal_False! + */ + sal_Bool is() const { return mxRef.is(); } + InterfaceType* operator->() const { return mpImpl; } + InterfaceType& operator*() const { return *mpImpl; } + ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() { return mxRef; } + const ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() const { return mxRef; } + + // default copy constructor and assignment will do + // HardCppRef( const HardCppRef& ); + // HardCppRef& operator= ( const HardCppRef& ); + + private: + + // the interface, hard reference to prevent object from vanishing + ::com::sun::star::uno::Reference< UnoInterfaceType > mxRef; + + // the c++ object, for our internal stuff + InterfaceType* mpImpl; + + }; + + /** Helper class for weak object references plus implementation + + This class combines a weak reference (to facilitate automatic + object disposal if user drops last reference) and hard + reference to the c++ class (for fast access and bypassing of + the UNO interface) + */ + template < class UnoType, class CppType > class WeakCppRef + { + public: + + typedef UnoType UnoInterfaceType; + typedef CppType InterfaceType; + typedef HardCppRef< UnoInterfaceType, InterfaceType > HardRefType; + + WeakCppRef() : maWeakRef(), maUnsafeRef( NULL ) {} + WeakCppRef( InterfaceType& rImpl ) : + maWeakRef( ::com::sun::star::uno::Reference< UnoInterfaceType >( rImpl, ::com::sun::star::uno::UNO_QUERY ) ), + maUnsafeRef( &rImpl ) + { + } + + WeakCppRef( HardRefType& rImpl ) : + maWeakRef( rImpl.getRef() ), + maUnsafeRef( rImpl.operator->() ) + { + } + + // get object with c++ object and hard reference (which + // prevents the c++ object from destruction during use) + HardRefType get() const { return HardRefType( maWeakRef, maUnsafeRef ); } + + // default copy constructor and assignment will do + // WeakCppRef( const WeakCppRef& ); + // WeakCppRef& operator= ( const WeakCppRef& ); + + private: + + // the interface, hold weakly + ::com::sun::star::uno::WeakReference< UnoInterfaceType > maWeakRef; + + // hard ref to c++ class, _only_ valid if maWeakRef.is() is true + InterfaceType* maUnsafeRef; + }; + + + /** This class manages the paragraphs of an AccessibleTextHelper + + To facilitate automatic deletion of paragraphs no longer used, + this class uses the WeakCppRef helper to hold the objects weakly. + */ + class AccessibleParaManager + { + public: + typedef WeakCppRef < ::com::sun::star::accessibility::XAccessible, AccessibleEditableTextPara > WeakPara; + typedef ::std::pair< WeakPara, ::com::sun::star::awt::Rectangle > WeakChild; + typedef ::std::pair< ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > , ::com::sun::star::awt::Rectangle > Child; + typedef ::std::vector< WeakChild > VectorOfChildren; + typedef ::std::vector< sal_Int16 > VectorOfStates; + + AccessibleParaManager(); + ~AccessibleParaManager(); + + /** Sets a vector of additional accessible states. + + The states are passed to every created child object + (text paragraph). The state values are defined in + com::sun::star::accessibility::AccessibleStateType. + */ + void SetAdditionalChildStates( const VectorOfStates& rChildStates ); + + /** Returns the additional accessible states for children. + */ + const VectorOfStates& GetAdditionalChildStates() const; + + /** Set the number of paragraphs + + @param nNumPara + The total number of paragraphs the EditEngine currently + has (_not_ the number of currently visible children) + */ + void SetNum( sal_Int32 nNumParas ); + + /** Get the number of paragraphs currently possible */ + sal_uInt32 GetNum() const; + + // iterators + VectorOfChildren::iterator begin(); + VectorOfChildren::iterator end(); + VectorOfChildren::const_iterator begin() const; + VectorOfChildren::const_iterator end() const; + + // dealing with single paragraphs (release reference, return reference etc) + void Release( sal_uInt32 nPara ); + /// Set focus to given child + void SetFocus( sal_Int32 nChild ); + + void FireEvent( sal_uInt32 nPara, + const sal_Int16 nEventId, + const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), + const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + static sal_Bool IsReferencable( WeakPara::HardRefType aChild ); + sal_Bool IsReferencable( sal_uInt32 nChild ) const; + static void ShutdownPara( const WeakChild& rChild ); + + Child CreateChild( sal_Int32 nChild, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xFrontEnd, + SvxEditSourceAdapter& rEditSource, + sal_uInt32 nParagraphIndex ); + + WeakChild GetChild( sal_uInt32 nParagraphIndex ) const; + + // forwarder to all paragraphs + /// Make all children active and editable (or off) + void SetActive( sal_Bool bActive = sal_True ); + /// Set state of all children + void SetState( const sal_Int16 nStateId ); + /// Unset state of all children + void UnSetState( const sal_Int16 nStateId ); + /// Set offset to edit engine for all children + void SetEEOffset ( const Point& rOffset ); + /// Change edit source on all living children + void SetEditSource ( SvxEditSourceAdapter* pEditSource ); + /// Dispose all living children + void Dispose (); + + // forwarder to given paragraphs + //------------------------------------------------------------------------ + /** Release the given range of paragraphs + + All ranges have the meaning [start,end), similar to STL + + @param nStartPara + Index of paragraph to start with releasing + + @param nEndPara + Index of first paragraph to stop with releasing + */ + void Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara ); + + /** Fire event for the given range of paragraphs + + All ranges have the meaning [start,end), similar to STL + + @param nStartPara + Index of paragraph to start with event firing + + @param nEndPara + Index of first paragraph to stop with event firing + */ + void FireEvent( sal_uInt32 nStartPara, + sal_uInt32 nEndPara, + const sal_Int16 nEventId, + const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), + const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + /** Functor adapter for ForEach template + + Adapts giving functor such that only the paragraph objects + are accessed and the fact that our children are held + weakly is hidden + + The functor must provide the following method: + void operator() ( AccessibleEditablePara& ) + + */ + template < typename Functor > class WeakChildAdapter : public ::std::unary_function< const WeakChild&, void > + { + public: + WeakChildAdapter( Functor& rFunctor ) : mrFunctor(rFunctor) {} + void operator()( const WeakChild& rPara ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aHardRef( rPara.first.get() ); + + if( aHardRef.is() ) + mrFunctor( *aHardRef ); + } + + private: + Functor& mrFunctor; + }; + + /** Adapter for unary member functions + + Since STL's binder don't work with const& arguments (and + BOOST's neither, at least on MSVC), have to provide our + own adapter for unary member functions. + + Create with pointer to member function of + AccessibleEditableTextPara and the corresponding argument. + */ + template < typename Argument > class MemFunAdapter : public ::std::unary_function< const WeakChild&, void > + { + public: + typedef void (::accessibility::AccessibleEditableTextPara::*FunctionPointer)( Argument ); + + MemFunAdapter( FunctionPointer aFunPtr, Argument aArg ) : maFunPtr(aFunPtr), maArg(aArg) {} + void operator()( const WeakChild& rPara ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aHardRef( rPara.first.get() ); + + if( aHardRef.is() ) + (*aHardRef.*maFunPtr)( maArg ); + } + + private: + FunctionPointer maFunPtr; + Argument maArg; + }; + + /** Generic algorithm on given paragraphs + + Convenience method, that already adapts the given functor with WeakChildAdapter + */ + template < typename Functor > void ForEach( Functor& rFunctor ) + { + ::std::for_each( begin(), end(), WeakChildAdapter< Functor >(rFunctor) ); + } + + private: + /// Set state on given child + void SetState( sal_Int32 nChild, const sal_Int16 nStateId ); + /// Unset state on given child + void UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ); + /// Init child with default state (as stored in previous SetFocus and SetActive calls) + void InitChild( AccessibleEditableTextPara& rChild, + SvxEditSourceAdapter& rEditSource, + sal_Int32 nChild, + sal_uInt32 nParagraphIndex ) const; + + // vector the size of the paragraph number of the underlying EditEngine + VectorOfChildren maChildren; + + /// Additional states that will be set at every created child object. + VectorOfStates maChildStates; + + // cache EE offset for child creation + Point maEEOffset; + + // which child currently has the focus (-1 for none) + sal_Int32 mnFocusedChild; + + // whether children are active and editable + sal_Bool mbActive; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleSelectionBase.cxx b/editeng/source/accessibility/AccessibleSelectionBase.cxx new file mode 100644 index 0000000000..56054da0a8 --- /dev/null +++ b/editeng/source/accessibility/AccessibleSelectionBase.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleSelectionBase.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <editeng/AccessibleSelectionBase.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility +{ + // --------------------------- + // - AccessibleSelectionBase - + // --------------------------- + + AccessibleSelectionBase::AccessibleSelectionBase() + { + } + + //-------------------------------------------------------------------- + + AccessibleSelectionBase::~AccessibleSelectionBase() + { + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::selectAccessibleChild( sal_Int32 nChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); + } + + //-------------------------------------------------------------------- + + sal_Bool SAL_CALL AccessibleSelectionBase::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ) ); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::clearAccessibleSelection( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::clearAccessibleSelection(); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::selectAllAccessibleChildren( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::selectAllAccessibleChildren(); + } + + //-------------------------------------------------------------------- + + sal_Int32 SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChildCount( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::getSelectedAccessibleChildCount() ); + } + + //-------------------------------------------------------------------- + + uno::Reference< XAccessible > SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ) ); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); + } +} diff --git a/editeng/source/accessibility/AccessibleStaticTextBase.cxx b/editeng/source/accessibility/AccessibleStaticTextBase.cxx new file mode 100644 index 0000000000..1caa0e7392 --- /dev/null +++ b/editeng/source/accessibility/AccessibleStaticTextBase.cxx @@ -0,0 +1,1050 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleStaticTextBase.cxx,v $ + * $Revision: 1.27 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ + +#include <limits.h> +#include <vector> +#include <algorithm> +#include <boost/bind.hpp> +#include <vos/mutex.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/sequenceasvector.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <editeng/editdata.hxx> +#include <editeng/unopracc.hxx> +#include "unoedprx.hxx" +#include <editeng/AccessibleStaticTextBase.hxx> +#include "AccessibleEditableTextPara.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +/* TODO: + ===== + + - separate adapter functionality from AccessibleStaticText class + + - refactor common loops into templates, using mem_fun + + */ + +namespace accessibility +{ + typedef ::comphelper::SequenceAsVector< beans::PropertyValue > PropertyValueVector; + + class PropertyValueEqualFunctor : public ::std::binary_function< beans::PropertyValue, beans::PropertyValue, bool > + { + public: + PropertyValueEqualFunctor() + {} + bool operator() ( const beans::PropertyValue& lhs, const beans::PropertyValue& rhs ) const + { + return ( lhs.Name == rhs.Name && lhs.Value == rhs.Value ); + } + }; + + //------------------------------------------------------------------------ + // + // Static Helper + // + //------------------------------------------------------------------------ + ESelection MakeSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_ASSERT(nStartPara >= 0 && nStartPara <= USHRT_MAX && + nStartIndex >= 0 && nStartIndex <= USHRT_MAX && + nEndPara >= 0 && nEndPara <= USHRT_MAX && + nEndIndex >= 0 && nEndIndex <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::MakeSelection: index value overflow"); + + return ESelection( static_cast< USHORT >(nStartPara), static_cast< USHORT >(nStartIndex), + static_cast< USHORT >(nEndPara), static_cast< USHORT >(nEndIndex) ); + } + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase_Impl declaration + // + //------------------------------------------------------------------------ + + DBG_NAME( AccessibleStaticTextBase_Impl ); + + /** AccessibleStaticTextBase_Impl + + This class implements the AccessibleStaticTextBase + functionality, mainly by forwarding the calls to an aggregated + AccessibleEditableTextPara. As this is a therefore non-trivial + adapter, factoring out the common functionality from + AccessibleEditableTextPara might be a profitable future task. + */ + class AccessibleStaticTextBase_Impl + { + + public: + + // receive pointer to our frontend class and view window + AccessibleStaticTextBase_Impl(); + ~AccessibleStaticTextBase_Impl(); + + SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return maEditSource; + } + void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)); + + void SetEventSource( const uno::Reference< XAccessible >& rInterface ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + mxThis = rInterface; + } + uno::Reference< XAccessible > GetEventSource() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return mxThis; + } + + void SetOffset( const Point& ); + Point GetOffset() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset ); + return aPoint; + } + + void UpdateChildren(); + void Dispose(); + +#ifdef DBG_UTIL + void CheckInvariants() const; +#endif + + AccessibleEditableTextPara& GetParagraph( sal_Int32 nPara ) const; + sal_Int32 GetParagraphCount() const; + sal_Int32 GetParagraphIndex() const; + sal_Int32 GetLineCount( sal_Int32 nParagraph ) const; + + EPosition Index2Internal( sal_Int32 nFlatIndex ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return ImpCalcInternal( nFlatIndex, false ); + } + + EPosition Range2Internal( sal_Int32 nFlatIndex ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return ImpCalcInternal( nFlatIndex, true ); + } + + sal_Int32 Internal2Index( EPosition nEEIndex ) const; + + void CorrectTextSegment( TextSegment& aTextSegment, + int nPara ) const; + + sal_Bool SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ); + sal_Bool CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ); + + Rectangle GetParagraphBoundingBox() const; + + private: + + EPosition ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const; + + // our frontend class (the one implementing the actual + // interface). That's not necessarily the one containing the impl + // pointer + uno::Reference< XAccessible > mxThis; + + // implements our functionality, we're just an adapter (guarded by solar mutex) + mutable AccessibleEditableTextPara* mpTextParagraph; + + uno::Reference< XAccessible > mxParagraph; + + // a wrapper for the text forwarders (guarded by solar mutex) + mutable SvxEditSourceAdapter maEditSource; + + // guard for maOffset + mutable ::osl::Mutex maMutex; + + /// our current offset to the containing shape/cell (guarded by maMutex) + Point maOffset; + + }; + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase_Impl implementation + // + //------------------------------------------------------------------------ + + AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() : + mxThis( NULL ), + mpTextParagraph( new AccessibleEditableTextPara(NULL) ), + mxParagraph( mpTextParagraph ), + maEditSource(), + maMutex(), + maOffset(0,0) + { + DBG_CTOR( AccessibleStaticTextBase_Impl, NULL ); + + // TODO: this is still somewhat of a hack, all the more since + // now the maTextParagraph has an empty parent reference set + } + + AccessibleStaticTextBase_Impl::~AccessibleStaticTextBase_Impl() + { + DBG_DTOR( AccessibleStaticTextBase_Impl, NULL ); + } + + void AccessibleStaticTextBase_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + maEditSource.SetEditSource( pEditSource ); + if( mpTextParagraph ) + mpTextParagraph->SetEditSource( &maEditSource ); + } + + void AccessibleStaticTextBase_Impl::SetOffset( const Point& rPoint ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // guard against non-atomic access to maOffset data structure + { + ::osl::MutexGuard aGuard( maMutex ); + maOffset = rPoint; + } + + if( mpTextParagraph ) + mpTextParagraph->SetEEOffset( rPoint ); + + // in all cases, check visibility afterwards. + UpdateChildren(); + } + + void AccessibleStaticTextBase_Impl::UpdateChildren() + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // currently no children + } + + void AccessibleStaticTextBase_Impl::Dispose() + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // we're the owner of the paragraph, so destroy it, too + if( mpTextParagraph ) + mpTextParagraph->Dispose(); + + // drop references + mxParagraph = NULL; + mxThis = NULL; + mpTextParagraph = NULL; + } + +#ifdef DBG_UTIL + void AccessibleStaticTextBase_Impl::CheckInvariants() const + { + // TODO + } +#endif + + AccessibleEditableTextPara& AccessibleStaticTextBase_Impl::GetParagraph( sal_Int32 nPara ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), mxThis ); + + // TODO: Have a differnt method on AccessibleEditableTextPara + // that does not care about state changes + mpTextParagraph->SetParagraphIndex( nPara ); + + return *mpTextParagraph; + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphCount() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return 0; + else + return mpTextParagraph->GetTextForwarder().GetParagraphCount(); + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphIndex() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + sal_Int32 nIndex = -1; + if( mpTextParagraph ) + nIndex = mpTextParagraph->GetParagraphIndex(); + return nIndex; + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetLineCount( sal_Int32 nParagraph ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + sal_Int32 nIndex = 0; + if( mpTextParagraph ) + nIndex = mpTextParagraph->GetTextForwarder().GetLineCount( static_cast< USHORT >(nParagraph) ); + return nIndex; + } + + sal_Int32 AccessibleStaticTextBase_Impl::Internal2Index( EPosition nEEIndex ) const + { + sal_Int32 aRes(0); + int i; + for(i=0; i<nEEIndex.nPara; ++i) + aRes += GetParagraph(i).getCharacterCount(); + + return aRes + nEEIndex.nIndex; + } + + void AccessibleStaticTextBase_Impl::CorrectTextSegment( TextSegment& aTextSegment, + int nPara ) const + { + // Keep 'invalid' values at the TextSegment + if( aTextSegment.SegmentStart != -1 && + aTextSegment.SegmentStart != -1 ) + { + // #112814# Correct TextSegment by paragraph offset + sal_Int32 nOffset(0); + int i; + for(i=0; i<nPara; ++i) + nOffset += GetParagraph(i).getCharacterCount(); + + aTextSegment.SegmentStart += nOffset; + aTextSegment.SegmentEnd += nOffset; + } + } + + EPosition AccessibleStaticTextBase_Impl::ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( nFlatIndex < 0 ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), + mxThis); + // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually + + sal_Int32 nCurrPara, nCurrIndex, nParas, nCurrCount; + for( nCurrPara=0, nParas=GetParagraphCount(), nCurrCount=0, nCurrIndex=0; nCurrPara<nParas; ++nCurrPara ) + { + nCurrCount = GetParagraph( nCurrPara ).getCharacterCount(); + nCurrIndex += nCurrCount; + + if( nCurrIndex > nFlatIndex ) + { + // check overflow + DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && + nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); + + return EPosition( static_cast< USHORT >(nCurrPara), static_cast< USHORT >(nFlatIndex - nCurrIndex + nCurrCount) ); + } + } + + // #102170# Allow one-past the end for ranges + if( bExclusive && nCurrIndex == nFlatIndex ) + { + // check overflow + DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && + nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); + + return EPosition( static_cast< USHORT >(nCurrPara-1), static_cast< USHORT >(nFlatIndex - nCurrIndex + nCurrCount) ); + } + + // not found? Out of bounds + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), + mxThis); + } + + sal_Bool AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return sal_False; + + try + { + SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); + return rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool AccessibleStaticTextBase_Impl::CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return sal_False; + + try + { + SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); + mpTextParagraph->GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + sal_Bool aRetVal; + + // save current selection + ESelection aOldSelection; + + rCacheVF.GetSelection( aOldSelection ); + rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); + aRetVal = rCacheVF.Copy(); + rCacheVF.SetSelection( aOldSelection ); // restore + + return aRetVal; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + Rectangle AccessibleStaticTextBase_Impl::GetParagraphBoundingBox() const + { + Rectangle aRect; + if( mpTextParagraph ) + { + awt::Rectangle aAwtRect = mpTextParagraph->getBounds(); + aRect = Rectangle( Point( aAwtRect.X, aAwtRect.Y ), Size( aAwtRect.Width, aAwtRect.Height ) ); + } + else + { + aRect.SetEmpty(); + } + return aRect; + } + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase implementation + // + //------------------------------------------------------------------------ + + AccessibleStaticTextBase::AccessibleStaticTextBase( ::std::auto_ptr< SvxEditSource > pEditSource ) : + mpImpl( new AccessibleStaticTextBase_Impl() ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + SetEditSource( pEditSource ); + } + + AccessibleStaticTextBase::~AccessibleStaticTextBase() + { + } + + const SvxEditSource& AccessibleStaticTextBase::GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + const SvxEditSource& aEditSource = mpImpl->GetEditSource(); + + mpImpl->CheckInvariants(); + + return aEditSource; +#else + return mpImpl->GetEditSource(); +#endif + } + + void AccessibleStaticTextBase::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->SetEditSource( pEditSource ); + + mpImpl->CheckInvariants(); +#else + mpImpl->SetEditSource( pEditSource ); +#endif + } + + void AccessibleStaticTextBase::SetEventSource( const uno::Reference< XAccessible >& rInterface ) + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + + mpImpl->SetEventSource( rInterface ); + +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + } + + uno::Reference< XAccessible > AccessibleStaticTextBase::GetEventSource() const + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() ); + + mpImpl->CheckInvariants(); + + return xRet; +#else + return mpImpl->GetEventSource(); +#endif + } + + void AccessibleStaticTextBase::SetOffset( const Point& rPoint ) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->SetOffset( rPoint ); + + mpImpl->CheckInvariants(); +#else + mpImpl->SetOffset( rPoint ); +#endif + } + + Point AccessibleStaticTextBase::GetOffset() const + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + Point aPoint( mpImpl->GetOffset() ); + + mpImpl->CheckInvariants(); + + return aPoint; +#else + return mpImpl->GetOffset(); +#endif + } + + void AccessibleStaticTextBase::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->UpdateChildren(); + + mpImpl->CheckInvariants(); +#else + mpImpl->UpdateChildren(); +#endif + } + + void AccessibleStaticTextBase::Dispose() + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + + mpImpl->Dispose(); + +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + } + + // XAccessibleContext + sal_Int32 SAL_CALL AccessibleStaticTextBase::getAccessibleChildCount() throw (uno::RuntimeException) + { + // no children at all + return 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleChild( sal_Int32 /*i*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + // no children at all + return uno::Reference< XAccessible >(); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ ) throw (uno::RuntimeException) + { + // no children at all + return uno::Reference< XAccessible >(); + } + + // XAccessibleText + sal_Int32 SAL_CALL AccessibleStaticTextBase::getCaretPosition() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getCaretPosition()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + return setSelection(nIndex, nIndex); + } + + sal_Unicode SAL_CALL AccessibleStaticTextBase::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal(nIndex) ); + + return mpImpl->GetParagraph( aPos.nPara ).getCharacter( aPos.nIndex ); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal(nIndex) ); + + return mpImpl->GetParagraph( aPos.nPara ).getCharacterAttributes( aPos.nIndex, aRequestedAttributes ); + } + + awt::Rectangle SAL_CALL AccessibleStaticTextBase::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // #108900# Allow ranges for nIndex, as one-past-the-end + // values are now legal, too. + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + // #i70916# Text in spread sheet cells return the wrong extents + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); + awt::Rectangle aParaBounds( rPara.getBounds() ); + awt::Rectangle aBounds( rPara.getCharacterBounds( aPos.nIndex ) ); + aBounds.X += aParaBounds.X; + aBounds.Y += aParaBounds.Y; + + return aBounds; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getCharacterCount() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nCount, nParas; + for( i=0, nCount=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + nCount += mpImpl->GetParagraph(i).getCharacterCount(); + + return nCount; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Int32 nParas( mpImpl->GetParagraphCount() ); + sal_Int32 nIndex; + int i; + for( i=0; i<nParas; ++i ) + { + // TODO: maybe exploit the fact that paragraphs are + // ordered vertically for early exit + + // #i70916# Text in spread sheet cells return the wrong extents + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( i ); + awt::Rectangle aParaBounds( rPara.getBounds() ); + awt::Point aPoint( rPoint ); + aPoint.X -= aParaBounds.X; + aPoint.Y -= aParaBounds.Y; + + // #112814# Use correct index offset + if ( ( nIndex = rPara.getIndexAtPoint( aPoint ) ) != -1 ) + return mpImpl->Internal2Index( EPosition(sal::static_int_cast<USHORT>(i), + sal::static_int_cast<USHORT>(nIndex)) ); + } + + return -1; + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getSelectedText() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 nStart( getSelectionStart() ); + sal_Int32 nEnd( getSelectionEnd() ); + + // #104481# Return the empty string for 'no selection' + if( nStart < 0 || nEnd < 0 ) + return ::rtl::OUString(); + + return getTextRange( nStart, nEnd ); + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionStart() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getSelectionStart()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionEnd() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getSelectionEnd()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + return mpImpl->SetSelection( aStartIndex.nPara, aStartIndex.nIndex, + aEndIndex.nPara, aEndIndex.nIndex ); + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getText() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nParas; + ::rtl::OUString aRes; + for( i=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + aRes += mpImpl->GetParagraph(i).getText(); + + return aRes; + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( nStartIndex > nEndIndex ) + ::std::swap(nStartIndex, nEndIndex); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + // #102170# Special case: start and end paragraph are identical + if( aStartIndex.nPara == aEndIndex.nPara ) + { + return mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex ); + } + else + { + sal_Int32 i( aStartIndex.nPara ); + ::rtl::OUString aRes( mpImpl->GetParagraph(i).getTextRange( aStartIndex.nIndex, + mpImpl->GetParagraph(i).getCharacterCount()-1) ); + ++i; + + // paragraphs inbetween are fully included + for( ; i<aEndIndex.nPara; ++i ) + aRes += mpImpl->GetParagraph(i).getText(); + + if( i<=aEndIndex.nPara ) + aRes += mpImpl->GetParagraph(i).getTextRange( 0, aEndIndex.nIndex ); + + return aRes; + } + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + // #106393# Special casing one behind last paragraph is + // not necessary, since then, we return the content and + // boundary of that last paragraph. Range2Internal is + // tolerant against that, and returns the last paragraph + // in aPos.nPara. + + // retrieve full text of the paragraph + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextAtIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + if( aPos.nIndex == mpImpl->GetParagraph( aPos.nPara ).getCharacterCount() ) + { + // #103589# Special casing one behind the last paragraph + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); + } + else if( aPos.nPara > 0 ) + { + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara - 1 ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara - 1, 0 ) ); + } + + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBeforeIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + // Special casing one behind the last paragraph is not + // necessary, this case is invalid here for + // getTextBehindIndex + if( aPos.nPara + 1 < mpImpl->GetParagraphCount() ) + { + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara + 1 ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara + 1, 0 ) ); + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBehindIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( nStartIndex > nEndIndex ) + ::std::swap(nStartIndex, nEndIndex); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + return mpImpl->CopyText( aStartIndex.nPara, aStartIndex.nIndex, + aEndIndex.nPara, aEndIndex.nIndex ); + } + + // XAccessibleTextAttributes + uno::Sequence< beans::PropertyValue > AccessibleStaticTextBase::getDefaultAttributes( const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (uno::RuntimeException) + { + // get the intersection of the default attributes of all paragraphs + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + PropertyValueVector aDefAttrVec( mpImpl->GetParagraph( 0 ).getDefaultAttributes( RequestedAttributes ) ); + + const sal_Int32 nParaCount = mpImpl->GetParagraphCount(); + for ( sal_Int32 nPara = 1; nPara < nParaCount; ++nPara ) + { + uno::Sequence< beans::PropertyValue > aSeq = mpImpl->GetParagraph( nPara ).getDefaultAttributes( RequestedAttributes ); + PropertyValueVector aIntersectionVec; + + PropertyValueVector::const_iterator aEnd = aDefAttrVec.end(); + for ( PropertyValueVector::const_iterator aItr = aDefAttrVec.begin(); aItr != aEnd; ++aItr ) + { + const beans::PropertyValue* pItr = aSeq.getConstArray(); + const beans::PropertyValue* pEnd = pItr + aSeq.getLength(); + const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( *aItr ) ) ); + if ( pFind != pEnd ) + { + aIntersectionVec.push_back( *pFind ); + } + } + + aDefAttrVec.swap( aIntersectionVec ); + + if ( aDefAttrVec.empty() ) + { + break; + } + } + + return aDefAttrVec.getAsConstList(); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getRunAttributes( sal_Int32 nIndex, const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + // get those default attributes of the paragraph, which are not part + // of the intersection of all paragraphs and add them to the run attributes + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal( nIndex ) ); + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); + uno::Sequence< beans::PropertyValue > aDefAttrSeq = rPara.getDefaultAttributes( RequestedAttributes ); + uno::Sequence< beans::PropertyValue > aRunAttrSeq = rPara.getRunAttributes( aPos.nIndex, RequestedAttributes ); + uno::Sequence< beans::PropertyValue > aIntersectionSeq = getDefaultAttributes( RequestedAttributes ); + PropertyValueVector aDiffVec; + + const beans::PropertyValue* pDefAttr = aDefAttrSeq.getConstArray(); + const sal_Int32 nLength = aDefAttrSeq.getLength(); + for ( sal_Int32 i = 0; i < nLength; ++i ) + { + const beans::PropertyValue* pItr = aIntersectionSeq.getConstArray(); + const beans::PropertyValue* pEnd = pItr + aIntersectionSeq.getLength(); + const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( pDefAttr[i] ) ) ); + if ( pFind == pEnd && pDefAttr[i].Handle != 0) + { + aDiffVec.push_back( pDefAttr[i] ); + } + } + + return ::comphelper::concatSequences( aRunAttrSeq, aDiffVec.getAsConstList() ); + } + + Rectangle AccessibleStaticTextBase::GetParagraphBoundingBox() const + { + return mpImpl->GetParagraphBoundingBox(); + } + + sal_Int32 AccessibleStaticTextBase::GetParagraphIndex() const + { + return mpImpl->GetParagraphIndex(); + } + + sal_Int32 AccessibleStaticTextBase::GetParagraphCount() const + { + return mpImpl->GetParagraphCount(); + } + + sal_Int32 AccessibleStaticTextBase::GetLineCount( sal_Int32 nParagraph ) const + { + return mpImpl->GetLineCount( nParagraph ); + } + +} // end of namespace accessibility + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleStringWrap.cxx b/editeng/source/accessibility/AccessibleStringWrap.cxx new file mode 100644 index 0000000000..22cd0e1cf4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleStringWrap.cxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleStringWrap.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <algorithm> +#include <tools/debug.hxx> +#include <vcl/outdev.hxx> + +#include <editeng/svxfont.hxx> +#include <editeng/AccessibleStringWrap.hxx> + +//------------------------------------------------------------------------ +// +// AccessibleStringWrap implementation +// +//------------------------------------------------------------------------ + +AccessibleStringWrap::AccessibleStringWrap( OutputDevice& rDev, SvxFont& rFont, const String& rText ) : + mrDev( rDev ), + mrFont( rFont ), + maText( rText ) +{ +} + +sal_Bool AccessibleStringWrap::GetCharacterBounds( sal_Int32 nIndex, Rectangle& rRect ) +{ + DBG_ASSERT(nIndex >= 0 && nIndex <= USHRT_MAX, + "SvxAccessibleStringWrap::GetCharacterBounds: index value overflow"); + + mrFont.SetPhysFont( &mrDev ); + + // #108900# Handle virtual position one-past-the end of the string + if( nIndex >= maText.Len() ) + { + // create a caret bounding rect that has the height of the + // current font and is one pixel wide. + rRect.Left() = mrDev.GetTextWidth(maText); + rRect.Top() = 0; + rRect.SetSize( Size(mrDev.GetTextHeight(), 1) ); + } + else + { + sal_Int32 aXArray[2]; + mrDev.GetCaretPositions( maText, aXArray, static_cast< USHORT >(nIndex), 1 ); + rRect.Left() = 0; + rRect.Top() = 0; + rRect.SetSize( Size(mrDev.GetTextHeight(), labs(aXArray[0] - aXArray[1])) ); + rRect.Move( ::std::min(aXArray[0], aXArray[1]), 0 ); + } + + if( mrFont.IsVertical() ) + { + // #101701# Rotate to vertical + rRect = Rectangle( Point(-rRect.Top(), rRect.Left()), + Point(-rRect.Bottom(), rRect.Right())); + } + + return sal_True; +} + +sal_Int32 AccessibleStringWrap::GetIndexAtPoint( const Point& rPoint ) +{ + // search for character bounding box containing given point + Rectangle aRect; + sal_Int32 i, nLen = maText.Len(); + for( i=0; i<nLen; ++i ) + { + GetCharacterBounds(i, aRect); + if( aRect.IsInside(rPoint) ) + return i; + } + + return -1; +} diff --git a/editeng/source/accessibility/accessibility.src b/editeng/source/accessibility/accessibility.src new file mode 100644 index 0000000000..51d2a49e6e --- /dev/null +++ b/editeng/source/accessibility/accessibility.src @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: accessibility.src,v $ + * $Revision: 1.34 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "editeng.hrc" + +String RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION +{ + Text [ en-US ] = "Image bullet in paragraph" ; +}; + +String RID_SVXSTR_A11Y_IMAGEBULLET_NAME +{ + Text [ en-US ] = "Image bullet" ; +}; + + diff --git a/editeng/source/accessibility/makefile.mk b/editeng/source/accessibility/makefile.mk new file mode 100755 index 0000000000..e29b6477f6 --- /dev/null +++ b/editeng/source/accessibility/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.25 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=editeng +TARGET=accessibility +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/AccessibleStringWrap.obj \ + $(SLO)$/AccessibleContextBase.obj \ + $(SLO)$/AccessibleComponentBase.obj \ + $(SLO)$/AccessibleSelectionBase.obj \ + $(SLO)$/AccessibleStaticTextBase.obj \ + $(SLO)$/AccessibleParaManager.obj \ + $(SLO)$/AccessibleEditableTextPara.obj \ + $(SLO)$/AccessibleImageBullet.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx new file mode 100644 index 0000000000..12b91d8f2d --- /dev/null +++ b/editeng/source/editeng/editattr.cxx @@ -0,0 +1,457 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editattr.cxx,v $ + * $Revision: 1.16.212.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//#include <eeng_pch.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#include <editeng/svxfont.hxx> +#include <editeng/flditem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/cscoitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/akrnitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/emphitem.hxx> +#include <editeng/charscaleitem.hxx> +#include <editeng/charreliefitem.hxx> + +#include "editattr.hxx" + +DBG_NAME( EE_EditAttrib ) + +// ------------------------------------------------------------------------- +// class EditAttrib +// ------------------------------------------------------------------------- +EditAttrib::EditAttrib( const SfxPoolItem& rAttr ) +{ + DBG_CTOR( EE_EditAttrib, 0 ); + pItem = &rAttr; +} + +EditAttrib::~EditAttrib() +{ + DBG_DTOR( EE_EditAttrib, 0 ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttrib +// ------------------------------------------------------------------------- +EditCharAttrib::EditCharAttrib( const SfxPoolItem& rAttr, USHORT nS, USHORT nE ) + : EditAttrib( rAttr ) +{ + nStart = nS; + nEnd = nE; + bFeature = FALSE; + bEdge = FALSE; + + DBG_ASSERT( ( rAttr.Which() >= EE_ITEMS_START ) && ( rAttr.Which() <= EE_ITEMS_END ), "EditCharAttrib CTOR: Invalid id!" ); + DBG_ASSERT( ( rAttr.Which() < EE_FEATURE_START ) || ( rAttr.Which() > EE_FEATURE_END ) || ( nE == (nS+1) ), "EditCharAttrib CTOR: Invalid feature!" ); +} + +void EditCharAttrib::SetFont( SvxFont&, OutputDevice* ) +{ +} + + +// ------------------------------------------------------------------------- +// class EditCharAttribFont +// ------------------------------------------------------------------------- +EditCharAttribFont::EditCharAttribFont( const SvxFontItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTINFO || rAttr.Which() == EE_CHAR_FONTINFO_CJK || rAttr.Which() == EE_CHAR_FONTINFO_CTL, "Kein Fontattribut!" ); +} + +void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) +{ + const SvxFontItem& rAttr = (const SvxFontItem&)(*GetItem()); + + rFont.SetName( rAttr.GetFamilyName() ); + rFont.SetFamily( rAttr.GetFamily() ); + rFont.SetPitch( rAttr.GetPitch() ); + rFont.SetCharSet( rAttr.GetCharSet() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribItalic +// ------------------------------------------------------------------------- +EditCharAttribItalic::EditCharAttribItalic( const SvxPostureItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_ITALIC || rAttr.Which() == EE_CHAR_ITALIC_CJK || rAttr.Which() == EE_CHAR_ITALIC_CTL, "Kein Italicattribut!" ); +} + +void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetItalic( ((const SvxPostureItem*)GetItem())->GetPosture() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribWeight +// ------------------------------------------------------------------------- +EditCharAttribWeight::EditCharAttribWeight( const SvxWeightItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_WEIGHT || rAttr.Which() == EE_CHAR_WEIGHT_CJK || rAttr.Which() == EE_CHAR_WEIGHT_CTL, "Kein Weightttribut!" ); +} + +void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetWeight( (FontWeight)((const SvxWeightItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribUnderline +// ------------------------------------------------------------------------- +EditCharAttribUnderline::EditCharAttribUnderline( const SvxUnderlineItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_UNDERLINE, "Kein Underlineattribut!" ); +} + +void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) +{ + rFont.SetUnderline( (FontUnderline)((const SvxUnderlineItem*)GetItem())->GetValue() ); + if ( pOutDev ) + pOutDev->SetTextLineColor( ((const SvxUnderlineItem*)GetItem())->GetColor() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribOverline +// ------------------------------------------------------------------------- +EditCharAttribOverline::EditCharAttribOverline( const SvxOverlineItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_OVERLINE, "Kein Overlineattribut!" ); +} + +void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) +{ + rFont.SetOverline( (FontUnderline)((const SvxOverlineItem*)GetItem())->GetValue() ); + if ( pOutDev ) + pOutDev->SetOverlineColor( ((const SvxOverlineItem*)GetItem())->GetColor() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribFontHeight +// ------------------------------------------------------------------------- +EditCharAttribFontHeight::EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTHEIGHT || rAttr.Which() == EE_CHAR_FONTHEIGHT_CJK || rAttr.Which() == EE_CHAR_FONTHEIGHT_CTL, "Kein Heightattribut!" ); +} + +void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* ) +{ + // Prop wird ignoriert + rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem*)GetItem())->GetHeight() ) ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribFontWidth +// ------------------------------------------------------------------------- +EditCharAttribFontWidth::EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTWIDTH, "Kein Widthattribut!" ); +} + +void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* ) +{ + // must be calculated outside, because f(device)... +} + +// ------------------------------------------------------------------------- +// class EditCharAttribStrikeout +// ------------------------------------------------------------------------- +EditCharAttribStrikeout::EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_STRIKEOUT, "Kein Sizeattribut!" ); +} + +void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetStrikeout( (FontStrikeout)((const SvxCrossedOutItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribColor +// ------------------------------------------------------------------------- +EditCharAttribColor::EditCharAttribColor( const SvxColorItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_COLOR, "Kein Colorattribut!" ); +} + +void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetColor( ((const SvxColorItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribLanguage +// ------------------------------------------------------------------------- +EditCharAttribLanguage::EditCharAttribLanguage( const SvxLanguageItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( ( rAttr.Which() == EE_CHAR_LANGUAGE ) || ( rAttr.Which() == EE_CHAR_LANGUAGE_CJK ) || ( rAttr.Which() == EE_CHAR_LANGUAGE_CTL ), "Kein Languageattribut!" ); +} + +void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetLanguage( ((const SvxLanguageItem*)GetItem())->GetLanguage() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribShadow +// ------------------------------------------------------------------------- +EditCharAttribShadow::EditCharAttribShadow( const SvxShadowedItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_SHADOW, "Kein Shadowattribut!" ); +} + +void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetShadow( (BOOL)((const SvxShadowedItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribEscapement +// ------------------------------------------------------------------------- +EditCharAttribEscapement::EditCharAttribEscapement( const SvxEscapementItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_ESCAPEMENT, "Kein Escapementattribut!" ); +} + +#if defined( WIN ) && !defined( WNT ) +#pragma optimize ("", off) +#endif + +void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* ) +{ + USHORT nProp = ((const SvxEscapementItem*)GetItem())->GetProp(); + rFont.SetPropr( (BYTE)nProp ); + + short nEsc = ((const SvxEscapementItem*)GetItem())->GetEsc(); + if ( nEsc == DFLT_ESC_AUTO_SUPER ) + nEsc = 100 - nProp; + else if ( nEsc == DFLT_ESC_AUTO_SUB ) + nEsc = sal::static_int_cast< short >( -( 100 - nProp ) ); + rFont.SetEscapement( nEsc ); +} + +#if defined( WIN ) && !defined( WNT ) +#pragma optimize ("", on) +#endif + + +// ------------------------------------------------------------------------- +// class EditCharAttribOutline +// ------------------------------------------------------------------------- +EditCharAttribOutline::EditCharAttribOutline( const SvxContourItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_OUTLINE, "Kein Outlineattribut!" ); +} + +void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetOutline( (BOOL)((const SvxContourItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribTab +// ------------------------------------------------------------------------- +EditCharAttribTab::EditCharAttribTab( const SfxVoidItem& rAttr, USHORT nPos ) + : EditCharAttrib( rAttr, nPos, nPos+1 ) +{ + SetFeature( TRUE ); +} + +void EditCharAttribTab::SetFont( SvxFont&, OutputDevice* ) +{ +} + +// ------------------------------------------------------------------------- +// class EditCharAttribLineBreak +// ------------------------------------------------------------------------- +EditCharAttribLineBreak::EditCharAttribLineBreak( const SfxVoidItem& rAttr, USHORT nPos ) + : EditCharAttrib( rAttr, nPos, nPos+1 ) +{ + SetFeature( TRUE ); +} + +void EditCharAttribLineBreak::SetFont( SvxFont&, OutputDevice* ) +{ +} + +// ------------------------------------------------------------------------- +// class EditCharAttribField +// ------------------------------------------------------------------------- +EditCharAttribField::EditCharAttribField( const SvxFieldItem& rAttr, USHORT nPos ) + : EditCharAttrib( rAttr, nPos, nPos+1 ) +{ + SetFeature( TRUE ); // !!! + pTxtColor = 0; + pFldColor = 0; +} + +void EditCharAttribField::SetFont( SvxFont& rFont, OutputDevice* ) +{ + if ( pFldColor ) + { + rFont.SetFillColor( *pFldColor ); + rFont.SetTransparent( FALSE ); + } + if ( pTxtColor ) + rFont.SetColor( *pTxtColor ); +} + +EditCharAttribField::EditCharAttribField( const EditCharAttribField& rAttr ) + : EditCharAttrib( *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd() ), + aFieldValue( rAttr.aFieldValue ) +{ + // Diesen CCTOR nur fuer temporaeres Object verwenden, + // Item wird nicht gepoolt. + pTxtColor = rAttr.pTxtColor ? new Color( *rAttr.pTxtColor ) : 0; + pFldColor = rAttr.pFldColor ? new Color( *rAttr.pFldColor ) : 0; +} + +EditCharAttribField::~EditCharAttribField() +{ + Reset(); +} + +BOOL EditCharAttribField::operator == ( const EditCharAttribField& rAttr ) const +{ + if ( aFieldValue != rAttr.aFieldValue ) + return FALSE; + + if ( ( pTxtColor && !rAttr.pTxtColor ) || ( !pTxtColor && rAttr.pTxtColor ) ) + return FALSE; + if ( ( pTxtColor && rAttr.pTxtColor ) && ( *pTxtColor != *rAttr.pTxtColor ) ) + return FALSE; + + if ( ( pFldColor && !rAttr.pFldColor ) || ( !pFldColor && rAttr.pFldColor ) ) + return FALSE; + if ( ( pFldColor && rAttr.pFldColor ) && ( *pFldColor != *rAttr.pFldColor ) ) + return FALSE; + + return TRUE; +} + +// ------------------------------------------------------------------------- +// class EditCharAttribPairKerning +// ------------------------------------------------------------------------- +EditCharAttribPairKerning::EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, USHORT _nStart, USHORT _nEnd ) +: EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_PAIRKERNING, "Kein PairKerning!" ); +} + +void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetKerning( ((const SvxAutoKernItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribKerning +// ------------------------------------------------------------------------- +EditCharAttribKerning::EditCharAttribKerning( const SvxKerningItem& rAttr, USHORT _nStart, USHORT _nEnd ) +: EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_KERNING, "Kein Kerning!" ); +} + +void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetFixKerning( ((const SvxKerningItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribWordLineMode +// ------------------------------------------------------------------------- +EditCharAttribWordLineMode::EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, USHORT _nStart, USHORT _nEnd ) +: EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_WLM, "Kein Kerning!" ); +} + +void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetWordLineMode( ((const SvxWordLineModeItem*)GetItem())->GetValue() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribEmphasisMark +// ------------------------------------------------------------------------- +EditCharAttribEmphasisMark::EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_EMPHASISMARK, "Kein Emphasisattribut!" ); +} + +void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem*)GetItem())->GetEmphasisMark() ); +} + +// ------------------------------------------------------------------------- +// class EditCharAttribRelief +// ------------------------------------------------------------------------- +EditCharAttribRelief::EditCharAttribRelief( const SvxCharReliefItem& rAttr, USHORT _nStart, USHORT _nEnd ) + : EditCharAttrib( rAttr, _nStart, _nEnd ) +{ + DBG_ASSERT( rAttr.Which() == EE_CHAR_RELIEF, "Not a relief attribute!" ); +} + +void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* ) +{ + rFont.SetRelief( (FontRelief)((const SvxCharReliefItem*)GetItem())->GetValue() ); +} diff --git a/editeng/source/editeng/editattr.hxx b/editeng/source/editeng/editattr.hxx new file mode 100644 index 0000000000..4d1673653c --- /dev/null +++ b/editeng/source/editeng/editattr.hxx @@ -0,0 +1,429 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editattr.hxx,v $ + * $Revision: 1.13.212.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EDITATTR_HXX +#define _EDITATTR_HXX + +#include <editeng/eeitem.hxx> + +class SvxFont; +class SvxFontItem; +class SvxWeightItem; +class SvxPostureItem; +class SvxShadowedItem; +class SvxEscapementItem; +class SvxContourItem; +class SvxCrossedOutItem; +class SvxUnderlineItem; +class SvxOverlineItem; +class SvxFontHeightItem; +class SvxCharScaleWidthItem; +class SvxColorItem; +class SvxAutoKernItem; +class SvxKerningItem; +class SvxCharSetColorItem; +class SvxWordLineModeItem; +class SvxFieldItem; +class SvxLanguageItem; +class SvxEmphasisMarkItem; +class SvxCharReliefItem; +#include <svl/poolitem.hxx> + + +class SfxVoidItem; + +#define CH_FEATURE_OLD (BYTE) 0xFF +#define CH_FEATURE (sal_Unicode) 0x01 + +// DEF_METRIC: Bei meinem Pool sollte immer die DefMetric bei +// GetMetric( nWhich ) ankommen! +// => Zum ermitteln der DefMetrik einfach ein GetMetric( 0 ) +#define DEF_METRIC 0 + +// ------------------------------------------------------------------------- +// class EditAttrib +// ------------------------------------------------------------------------- +class EditAttrib +{ +private: + EditAttrib() {;} + EditAttrib( const EditAttrib & ) {;} + +protected: + const SfxPoolItem* pItem; + + EditAttrib( const SfxPoolItem& rAttr ); + virtual ~EditAttrib(); + +public: + // RemoveFromPool muss immer vorm DTOR Aufruf erfolgen!! + void RemoveFromPool( SfxItemPool& rPool ); + + USHORT Which() const { return pItem->Which(); } + const SfxPoolItem* GetItem() const { return pItem; } +}; + +// ------------------------------------------------------------------------- +// class EditCharAttrib +// ------------------------------------------------------------------------- +// bFeature: Attribut darf nicht expandieren/schrumfen, Laenge immer 1 +// bEdge: Attribut expandiert nicht, wenn genau an der Kante expandiert werden soll +class EditCharAttrib : public EditAttrib +{ +protected: + + USHORT nStart; + USHORT nEnd; + BOOL bFeature :1; + BOOL bEdge :1; + +public: + EditCharAttrib( const SfxPoolItem& rAttr, USHORT nStart, USHORT nEnd ); + + USHORT& GetStart() { return nStart; } + USHORT& GetEnd() { return nEnd; } + + USHORT GetStart() const { return nStart; } + USHORT GetEnd() const { return nEnd; } + + inline USHORT GetLen() const; + + inline void MoveForward( USHORT nDiff ); + inline void MoveBackward( USHORT nDiff ); + + inline void Expand( USHORT nDiff ); + inline void Collaps( USHORT nDiff ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); + + BOOL IsIn( USHORT nIndex ) + { return ( ( nStart <= nIndex ) && ( nEnd >= nIndex ) ); } + BOOL IsInside( USHORT nIndex ) + { return ( ( nStart < nIndex ) && ( nEnd > nIndex ) ); } + BOOL IsEmpty() + { return nStart == nEnd; } + + BOOL IsFeature() const { return bFeature; } + void SetFeature( BOOL b) { bFeature = b; } + + BOOL IsEdge() const { return bEdge; } + void SetEdge( BOOL b ) { bEdge = b; } +}; + +inline USHORT EditCharAttrib::GetLen() const +{ + DBG_ASSERT( nEnd >= nStart, "EditCharAttrib: nEnd < nStart!" ); + return nEnd-nStart; +} + +inline void EditCharAttrib::MoveForward( USHORT nDiff ) +{ + DBG_ASSERT( ((long)nEnd + nDiff) <= 0xFFFF, "EditCharAttrib: MoveForward?!" ); + nStart = nStart + nDiff; + nEnd = nEnd + nDiff; +} + +inline void EditCharAttrib::MoveBackward( USHORT nDiff ) +{ + DBG_ASSERT( ((long)nStart - nDiff) >= 0, "EditCharAttrib: MoveBackward?!" ); + nStart = nStart - nDiff; + nEnd = nEnd - nDiff; +} + +inline void EditCharAttrib::Expand( USHORT nDiff ) +{ + DBG_ASSERT( ( ((long)nEnd + nDiff) <= (long)0xFFFF ), "EditCharAttrib: Expand?!" ); + DBG_ASSERT( !bFeature, "Bitte keine Features expandieren!" ); + nEnd = nEnd + nDiff; +} + +inline void EditCharAttrib::Collaps( USHORT nDiff ) +{ + DBG_ASSERT( (long)nEnd - nDiff >= (long)nStart, "EditCharAttrib: Collaps?!" ); + DBG_ASSERT( !bFeature, "Bitte keine Features schrumpfen!" ); + nEnd = nEnd - nDiff; +} + +// ------------------------------------------------------------------------- +// class EditCharAttribFont +// ------------------------------------------------------------------------- +class EditCharAttribFont: public EditCharAttrib +{ +public: + EditCharAttribFont( const SvxFontItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribWeight +// ------------------------------------------------------------------------- +class EditCharAttribWeight : public EditCharAttrib +{ +public: + EditCharAttribWeight( const SvxWeightItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; +// ------------------------------------------------------------------------- +// class EditCharAttribItalic +// ------------------------------------------------------------------------- +class EditCharAttribItalic : public EditCharAttrib +{ +public: + EditCharAttribItalic( const SvxPostureItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribShadow +// ------------------------------------------------------------------------- +class EditCharAttribShadow : public EditCharAttrib +{ +public: + EditCharAttribShadow( const SvxShadowedItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribEscapement +// ------------------------------------------------------------------------- +class EditCharAttribEscapement : public EditCharAttrib +{ +public: + EditCharAttribEscapement( const SvxEscapementItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribOutline +// ------------------------------------------------------------------------- +class EditCharAttribOutline : public EditCharAttrib +{ +public: + EditCharAttribOutline( const SvxContourItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribStrikeout +// ------------------------------------------------------------------------- +class EditCharAttribStrikeout : public EditCharAttrib +{ +public: + EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribUnderline +// ------------------------------------------------------------------------- +class EditCharAttribUnderline : public EditCharAttrib +{ +public: + EditCharAttribUnderline( const SvxUnderlineItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribOverline +// ------------------------------------------------------------------------- +class EditCharAttribOverline : public EditCharAttrib +{ +public: + EditCharAttribOverline( const SvxOverlineItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribEmphasisMark +// ------------------------------------------------------------------------- +class EditCharAttribEmphasisMark : public EditCharAttrib +{ +public: + EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribRelief +// ------------------------------------------------------------------------- +class EditCharAttribRelief : public EditCharAttrib +{ +public: + EditCharAttribRelief( const SvxCharReliefItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribFontHeight +// ------------------------------------------------------------------------- +class EditCharAttribFontHeight : public EditCharAttrib +{ +public: + EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribFontWidth +// ------------------------------------------------------------------------- +class EditCharAttribFontWidth : public EditCharAttrib +{ +public: + EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribColor +// ------------------------------------------------------------------------- +class EditCharAttribColor : public EditCharAttrib +{ +public: + EditCharAttribColor( const SvxColorItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribLanguage +// ------------------------------------------------------------------------- +class EditCharAttribLanguage : public EditCharAttrib +{ +public: + EditCharAttribLanguage( const SvxLanguageItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribTab +// ------------------------------------------------------------------------- +class EditCharAttribTab : public EditCharAttrib +{ +public: + EditCharAttribTab( const SfxVoidItem& rAttr, USHORT nPos ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribLineBreak +// ------------------------------------------------------------------------- +class EditCharAttribLineBreak : public EditCharAttrib +{ +public: + EditCharAttribLineBreak( const SfxVoidItem& rAttr, USHORT nPos ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribField +// ------------------------------------------------------------------------- +class EditCharAttribField: public EditCharAttrib +{ + XubString aFieldValue; + Color* pTxtColor; + Color* pFldColor; + + EditCharAttribField& operator = ( const EditCharAttribField& rAttr ) const; + +public: + EditCharAttribField( const SvxFieldItem& rAttr, USHORT nPos ); + EditCharAttribField( const EditCharAttribField& rAttr ); + ~EditCharAttribField(); + + BOOL operator == ( const EditCharAttribField& rAttr ) const; + BOOL operator != ( const EditCharAttribField& rAttr ) const + { return !(operator == ( rAttr ) ); } + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); + Color*& GetTxtColor() { return pTxtColor; } + Color*& GetFldColor() { return pFldColor; } + + const XubString& GetFieldValue() const { return aFieldValue; } + XubString& GetFieldValue() { return aFieldValue; } + + void Reset() + { + aFieldValue.Erase(); + delete pTxtColor; pTxtColor = 0; + delete pFldColor; pFldColor = 0; + } +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribPairKerning +// ------------------------------------------------------------------------- +class EditCharAttribPairKerning : public EditCharAttrib +{ +public: + EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribKerning +// ------------------------------------------------------------------------- +class EditCharAttribKerning : public EditCharAttrib +{ +public: + EditCharAttribKerning( const SvxKerningItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + +// ------------------------------------------------------------------------- +// class EditCharAttribWordLineMode +// ------------------------------------------------------------------------- +class EditCharAttribWordLineMode: public EditCharAttrib +{ +public: + EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, USHORT nStart, USHORT nEnd ); + + virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev ); +}; + + +#endif // _EDITATTR_HXX diff --git a/editeng/source/editeng/editdbg.cxx b/editeng/source/editeng/editdbg.cxx new file mode 100644 index 0000000000..bb29ef46ee --- /dev/null +++ b/editeng/source/editeng/editdbg.cxx @@ -0,0 +1,589 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editdbg.cxx,v $ + * $Revision: 1.22.148.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#include <editeng/lspcitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/adjitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/akrnitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/emphitem.hxx> +#include <editeng/numitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/charscaleitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/frmdiritem.hxx> + +#include <impedit.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editdoc.hxx> +#include <editdbg.hxx> + +#if defined( DBG_UTIL ) || ( OSL_DEBUG_LEVEL > 1 ) + +ByteString DbgOutItem( const SfxItemPool& rPool, const SfxPoolItem& rItem ) +{ + ByteString aDebStr; + switch ( rItem.Which() ) + { + case EE_PARA_WRITINGDIR: + aDebStr += "WritingDir="; + aDebStr += ByteString::CreateFromInt32( ((SvxFrameDirectionItem&)rItem).GetValue() ); + break; + case EE_PARA_OUTLLRSPACE: + case EE_PARA_LRSPACE: + aDebStr += "FI="; + aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetTxtFirstLineOfst() ); + aDebStr += ", LI="; + aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetTxtLeft() ); + aDebStr += ", RI="; + aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetRight() ); + break; + case EE_PARA_NUMBULLET: + { + aDebStr += "NumItem "; + for ( USHORT nLevel = 0; nLevel < 3; nLevel++ ) + { + aDebStr += "Level"; + aDebStr += ByteString::CreateFromInt32( nLevel ); + aDebStr += "="; + const SvxNumberFormat* pFmt = ((const SvxNumBulletItem&)rItem).GetNumRule()->Get( nLevel ); + if ( pFmt ) + { + aDebStr += "("; + aDebStr += ByteString::CreateFromInt32( pFmt->GetFirstLineOffset() ); + aDebStr += ","; + aDebStr += ByteString::CreateFromInt32( pFmt->GetAbsLSpace() ); + aDebStr += ","; + if ( pFmt->GetNumberingType() == SVX_NUM_BITMAP ) + { + aDebStr += "Bitmap"; + } + else if( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) + { + aDebStr += "Number"; + } + else + { + aDebStr += "Char=["; + aDebStr += ByteString::CreateFromInt32( pFmt->GetBulletChar() ); + aDebStr += "]"; + } + aDebStr += ") "; + } + } + } + break; + case EE_PARA_BULLETSTATE: + aDebStr += "ShowBullet="; + aDebStr += ByteString::CreateFromInt32( ((SfxBoolItem&)rItem).GetValue() ); + break; + case EE_PARA_HYPHENATE: + aDebStr += "Hyphenate="; + aDebStr += ByteString::CreateFromInt32( ((SfxBoolItem&)rItem).GetValue() ); + break; + case EE_PARA_OUTLLEVEL: + aDebStr += "Level="; + aDebStr += ByteString::CreateFromInt32( ((SfxInt16Item&)rItem).GetValue() ); + break; + case EE_PARA_ULSPACE: + aDebStr += "SB="; + aDebStr += ByteString::CreateFromInt32( ((SvxULSpaceItem&)rItem).GetUpper() ); + aDebStr += ", SA="; + aDebStr += ByteString::CreateFromInt32( ((SvxULSpaceItem&)rItem).GetLower() ); + break; + case EE_PARA_SBL: + aDebStr += "SBL="; + if ( ((SvxLineSpacingItem&)rItem).GetLineSpaceRule() == SVX_LINE_SPACE_MIN ) + { + aDebStr += "Min: "; + aDebStr += ByteString::CreateFromInt32( ((SvxLineSpacingItem&)rItem).GetInterLineSpace() ); + } + else if ( ((SvxLineSpacingItem&)rItem).GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) + { + aDebStr += "Prop: "; + aDebStr += ByteString::CreateFromInt32( (ULONG)((SvxLineSpacingItem&)rItem).GetPropLineSpace() ); + } + else + aDebStr += "Unsupported Type!"; + break; + case EE_PARA_JUST: + aDebStr += "SvxAdust="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxAdjustItem&)rItem).GetAdjust() ); + break; + case EE_PARA_TABS: + { + aDebStr += "Tabs: "; + const SvxTabStopItem& rTabs = (const SvxTabStopItem&) rItem; + aDebStr += ByteString::CreateFromInt32( rTabs.Count() ); + if ( rTabs.Count() ) + { + aDebStr += "( "; + for ( USHORT i = 0; i < rTabs.Count(); i++ ) + { + const SvxTabStop& rTab = rTabs[i]; + aDebStr += ByteString::CreateFromInt32( rTab.GetTabPos() ); + aDebStr += " "; + } + aDebStr += ")"; + } + } + break; + case EE_CHAR_LANGUAGE: + case EE_CHAR_LANGUAGE_CJK: + case EE_CHAR_LANGUAGE_CTL: + aDebStr += "Language="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxLanguageItem&)rItem).GetLanguage() ); + break; + case EE_CHAR_COLOR: + { + aDebStr += "Color= "; + Color aColor( ((SvxColorItem&)rItem).GetValue() ); + aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetRed() ); + aDebStr += ", "; + aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetGreen() ); + aDebStr += ", "; + aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetBlue() ); + } + break; + case EE_CHAR_FONTINFO: + case EE_CHAR_FONTINFO_CJK: + case EE_CHAR_FONTINFO_CTL: + { + aDebStr += "Font="; + aDebStr += ByteString( ((SvxFontItem&)rItem).GetFamilyName(), RTL_TEXTENCODING_ASCII_US ); + aDebStr += " (CharSet: "; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxFontItem&)rItem).GetCharSet() ); + aDebStr += ')'; + } + break; + case EE_CHAR_FONTHEIGHT: + case EE_CHAR_FONTHEIGHT_CJK: + case EE_CHAR_FONTHEIGHT_CTL: + { + aDebStr += "Groesse="; + aDebStr += ByteString::CreateFromInt32( ((SvxFontHeightItem&)rItem).GetHeight() ); + Size aSz( 0, ((SvxFontHeightItem&)rItem).GetHeight() ); + SfxMapUnit eUnit = rPool.GetMetric( rItem.Which() ); + MapMode aItemMapMode( (MapUnit) eUnit ); + MapMode aPntMap( MAP_POINT ); + aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); + aDebStr += " Points="; + aDebStr += ByteString::CreateFromInt32( aSz.Height() ); + } + break; + case EE_CHAR_FONTWIDTH: + { + aDebStr += "Breite="; + aDebStr += ByteString::CreateFromInt32( ((SvxCharScaleWidthItem&)rItem).GetValue() ); + aDebStr += "%"; + } + break; + case EE_CHAR_WEIGHT: + case EE_CHAR_WEIGHT_CJK: + case EE_CHAR_WEIGHT_CTL: + aDebStr += "FontWeight="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxWeightItem&)rItem).GetWeight() ); + break; + case EE_CHAR_UNDERLINE: + aDebStr += "FontUnderline="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxUnderlineItem&)rItem).GetLineStyle() ); + break; + case EE_CHAR_OVERLINE: + aDebStr += "FontOverline="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxOverlineItem&)rItem).GetLineStyle() ); + break; + case EE_CHAR_EMPHASISMARK: + aDebStr += "FontUnderline="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxEmphasisMarkItem&)rItem).GetEmphasisMark() ); + break; + case EE_CHAR_RELIEF: + aDebStr += "FontRelief="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxCharReliefItem&)rItem).GetValue() ); + break; + case EE_CHAR_STRIKEOUT: + aDebStr += "FontStrikeout="; + aDebStr +=ByteString::CreateFromInt32( (USHORT)((SvxCrossedOutItem&)rItem).GetStrikeout() ); + break; + case EE_CHAR_ITALIC: + case EE_CHAR_ITALIC_CJK: + case EE_CHAR_ITALIC_CTL: + aDebStr += "FontPosture="; + aDebStr +=ByteString::CreateFromInt32( (USHORT)((SvxPostureItem&)rItem).GetPosture() ); + break; + case EE_CHAR_OUTLINE: + aDebStr += "FontOutline="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxContourItem&)rItem).GetValue() ); + break; + case EE_CHAR_SHADOW: + aDebStr += "FontShadowed="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxShadowedItem&)rItem).GetValue() ); + break; + case EE_CHAR_ESCAPEMENT: + aDebStr += "Escape="; + aDebStr += ByteString::CreateFromInt32( (short)((SvxEscapementItem&)rItem).GetEsc() ); + aDebStr += ", "; + aDebStr += ByteString::CreateFromInt32( (short)((SvxEscapementItem&)rItem).GetProp() ); + break; + case EE_CHAR_PAIRKERNING: + aDebStr += "PairKerning="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxAutoKernItem&)rItem).GetValue() ); + break; + case EE_CHAR_KERNING: + { + aDebStr += "Kerning="; + aDebStr += ByteString::CreateFromInt32( (short)((SvxKerningItem&)rItem).GetValue() ); + Size aSz( 0, (short)((SvxKerningItem&)rItem).GetValue() ); + SfxMapUnit eUnit = rPool.GetMetric( rItem.Which() ); + MapMode aItemMapMode( (MapUnit) eUnit ); + MapMode aPntMap( MAP_POINT ); + aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); + aDebStr += " Points="; + aDebStr += ByteString::CreateFromInt32( aSz.Height() ); + } + break; + case EE_CHAR_WLM: + aDebStr += "WordLineMode="; + aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxWordLineModeItem&)rItem).GetValue() ); + break; + case EE_CHAR_XMLATTRIBS: + aDebStr += "XMLAttribs=..."; + break; + } + return aDebStr; +} + +void DbgOutItemSet( FILE* fp, const SfxItemSet& rSet, BOOL bSearchInParent, BOOL bShowALL ) +{ + for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) + { + fprintf( fp, "\nWhich: %i\t", nWhich ); + if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_OFF ) + fprintf( fp, "ITEM_OFF " ); + else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_DONTCARE ) + fprintf( fp, "ITEM_DC " ); + else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_ON ) + fprintf( fp, "ITEM_ON *" ); + + if ( !bShowALL && ( rSet.GetItemState( nWhich, bSearchInParent ) != SFX_ITEM_ON ) ) + continue; + + const SfxPoolItem& rItem = rSet.Get( nWhich, bSearchInParent ); + ByteString aDebStr = DbgOutItem( *rSet.GetPool(), rItem ); + fprintf( fp, "%s", aDebStr.GetBuffer() ); + } +} + +void EditDbg::ShowEditEngineData( EditEngine* pEE, BOOL bInfoBox ) +{ +#if defined UNX + FILE* fp = fopen( "/tmp/debug.log", "w" ); +#else + FILE* fp = fopen( "d:\\debug.log", "w" ); +#endif + if ( fp == 0 ) + { + DBG_ERROR( "Log-File konnte nicht angelegt werden!" ); + return; + } + + const SfxItemPool& rPool = *pEE->GetEmptyItemSet().GetPool(); + + fprintf( fp, "================================================================================" ); + fprintf( fp, "\n================== Dokument ================================================" ); + fprintf( fp, "\n================================================================================" ); + for ( USHORT nPortion = 0; nPortion < pEE->pImpEditEngine->GetParaPortions(). Count(); nPortion++) + { + + ParaPortion* pPPortion = pEE->pImpEditEngine->GetParaPortions().GetObject(nPortion ); + fprintf( fp, "\nAbsatz %i: Laenge = %i, Invalid = %i\nText = '%s'", nPortion, pPPortion->GetNode()->Len(), pPPortion->IsInvalid(), ByteString( *pPPortion->GetNode(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + fprintf( fp, "\nVorlage:" ); + SfxStyleSheet* pStyle = pPPortion->GetNode()->GetStyleSheet(); + if ( pStyle ) + fprintf( fp, " %s", ByteString( pStyle->GetName(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + fprintf( fp, "\nAbsatzattribute:" ); + DbgOutItemSet( fp, pPPortion->GetNode()->GetContentAttribs().GetItems(), FALSE, FALSE ); + + fprintf( fp, "\nZeichenattribute:" ); + BOOL bZeroAttr = FALSE; + USHORT z; + for ( z = 0; z < pPPortion->GetNode()->GetCharAttribs().Count(); z++ ) + { + EditCharAttrib* pAttr = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( z ); + ByteString aCharAttribs; + aCharAttribs += "\nA"; + aCharAttribs += ByteString::CreateFromInt32( nPortion ); + aCharAttribs += ": "; + aCharAttribs += ByteString::CreateFromInt32( pAttr->GetItem()->Which() ); + aCharAttribs += '\t'; + aCharAttribs += ByteString::CreateFromInt32( pAttr->GetStart() ); + aCharAttribs += '\t'; + aCharAttribs += ByteString::CreateFromInt32( pAttr->GetEnd() ); + if ( pAttr->IsEmpty() ) + bZeroAttr = TRUE; + fprintf( fp, "%s => ", aCharAttribs.GetBuffer() ); + + ByteString aDebStr = DbgOutItem( rPool, *pAttr->GetItem() ); + fprintf( fp, "%s", aDebStr.GetBuffer() ); + } + if ( bZeroAttr ) + fprintf( fp, "\nNULL-Attribute!" ); + + USHORT nTextPortions = pPPortion->GetTextPortions().Count(); + ByteString aPortionStr("\nTextportions: #"); + aPortionStr += ByteString::CreateFromInt32( nTextPortions ); + aPortionStr += " \nA"; + aPortionStr += ByteString::CreateFromInt32( nPortion ); + aPortionStr += ": Absatzlaenge = "; + aPortionStr += ByteString::CreateFromInt32( pPPortion->GetNode()->Len() ); + aPortionStr += "\nA"; + aPortionStr += ByteString::CreateFromInt32( nPortion ); + aPortionStr += ": "; + ULONG n = 0; + for ( z = 0; z < nTextPortions; z++ ) + { + TextPortion* pPortion = pPPortion->GetTextPortions().GetObject( z ); + aPortionStr += " "; + aPortionStr += ByteString::CreateFromInt32( pPortion->GetLen() ); + aPortionStr += "("; + aPortionStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() ); + aPortionStr += ")"; + aPortionStr += "["; + aPortionStr += ByteString::CreateFromInt32( (USHORT)pPortion->GetKind() ); + aPortionStr += "]"; + aPortionStr += ";"; + n += pPortion->GetLen(); + } + aPortionStr += "\nA"; + aPortionStr += ByteString::CreateFromInt32( nPortion ); + aPortionStr += ": Gesamtlaenge: "; + aPortionStr += ByteString::CreateFromInt32( n ); + if ( pPPortion->GetNode()->Len() != n ) + aPortionStr += " => Fehler !!!"; + fprintf( fp, "%s", aPortionStr.GetBuffer() ); + + + fprintf( fp, "\n\nZeilen:" ); + // Erstmal die Inhalte... + USHORT nLine; + for ( nLine = 0; nLine < pPPortion->GetLines().Count(); nLine++ ) + { + EditLine* pLine = pPPortion->GetLines().GetObject( nLine ); + + ByteString aLine( *(pPPortion->GetNode()), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart(), RTL_TEXTENCODING_ASCII_US ); + fprintf( fp, "\nZeile %i\t>%s<", nLine, aLine.GetBuffer() ); + } + // dann die internen Daten... + for ( nLine = 0; nLine < pPPortion->GetLines().Count(); nLine++ ) + { + EditLine* pLine = pPPortion->GetLines().GetObject( nLine ); + fprintf( fp, "\nZeile %i:\tStart: %i,\tEnd: %i", nLine, pLine->GetStart(), pLine->GetEnd() ); + fprintf( fp, "\t\tPortions: %i - %i.\tHoehe: %i, Ascent=%i", pLine->GetStartPortion(), pLine->GetEndPortion(), pLine->GetHeight(), pLine->GetMaxAscent() ); + } + + fprintf( fp, "\n-----------------------------------------------------------------------------" ); + } + + if ( pEE->pImpEditEngine->GetStyleSheetPool() ) + { + ULONG nStyles = pEE->pImpEditEngine->GetStyleSheetPool() ? pEE->pImpEditEngine->GetStyleSheetPool()->Count() : 0; + fprintf( fp, "\n\n================================================================================" ); + fprintf( fp, "\n================== Stylesheets =============================================" ); + fprintf( fp, "\n================================================================================" ); + fprintf( fp, "\n#Vorlagen: %lu\n", nStyles ); + SfxStyleSheetIterator aIter( pEE->pImpEditEngine->GetStyleSheetPool(), SFX_STYLE_FAMILY_ALL ); + SfxStyleSheetBase* pStyle = aIter.First(); + while ( pStyle ) + { + fprintf( fp, "\nVorlage: %s", ByteString( pStyle->GetName(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + fprintf( fp, "\nParent: %s", ByteString( pStyle->GetParent(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + fprintf( fp, "\nFollow: %s", ByteString( pStyle->GetFollow(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() ); + DbgOutItemSet( fp, pStyle->GetItemSet(), FALSE, FALSE ); + fprintf( fp, "\n----------------------------------" ); + + pStyle = aIter.Next(); + } + } + + fprintf( fp, "\n\n================================================================================" ); + fprintf( fp, "\n================== Defaults ================================================" ); + fprintf( fp, "\n================================================================================" ); + DbgOutItemSet( fp, pEE->pImpEditEngine->GetEmptyItemSet(), TRUE, TRUE ); + + fprintf( fp, "\n\n================================================================================" ); + fprintf( fp, "\n================== EditEngine & Views ======================================" ); + fprintf( fp, "\n================================================================================" ); + fprintf( fp, "\nControl: %lx", pEE->GetControlWord() ); + fprintf( fp, "\nRefMapMode: %i", pEE->pImpEditEngine->pRefDev->GetMapMode().GetMapUnit() ); + fprintf( fp, "\nPaperSize: %li x %li", pEE->GetPaperSize().Width(), pEE->GetPaperSize().Height() ); + fprintf( fp, "\nMaxAutoPaperSize: %li x %li", pEE->GetMaxAutoPaperSize().Width(), pEE->GetMaxAutoPaperSize().Height() ); + fprintf( fp, "\nMinAutoPaperSize: %li x %li", pEE->GetMinAutoPaperSize().Width(), pEE->GetMinAutoPaperSize().Height() ); + fprintf( fp, "\nUpdate: %i", pEE->GetUpdateMode() ); + fprintf( fp, "\nAnzahl der Views: %i", pEE->GetViewCount() ); + for ( USHORT nView = 0; nView < pEE->GetViewCount(); nView++ ) + { + EditView* pV = pEE->GetView( nView ); + DBG_ASSERT( pV, "View nicht gefunden!" ); + fprintf( fp, "\nView %i: Focus=%i", nView, pV->GetWindow()->HasFocus() ); + Rectangle aR( pV->GetOutputArea() ); + fprintf( fp, "\n OutputArea: nX=%li, nY=%li, dX=%li, dY=%li, MapMode = %i", aR.TopLeft().X(), aR.TopLeft().Y(), aR.GetSize().Width(), aR.GetSize().Height() , pV->GetWindow()->GetMapMode().GetMapUnit() ); + aR = pV->GetVisArea(); + fprintf( fp, "\n VisArea: nX=%li, nY=%li, dX=%li, dY=%li", aR.TopLeft().X(), aR.TopLeft().Y(), aR.GetSize().Width(), aR.GetSize().Height() ); + ESelection aSel = pV->GetSelection(); + fprintf( fp, "\n Selektion: Start=%u,%u, End=%u,%u", aSel.nStartPara, aSel.nStartPos, aSel.nEndPara, aSel.nEndPos ); + } + if ( pEE->GetActiveView() ) + { + fprintf( fp, "\n\n================================================================================" ); + fprintf( fp, "\n================== Aktuelle View ===========================================" ); + fprintf( fp, "\n================================================================================" ); + DbgOutItemSet( fp, pEE->GetActiveView()->GetAttribs(), TRUE, FALSE ); + } + fclose( fp ); + if ( bInfoBox ) + InfoBox(0, String( RTL_CONSTASCII_USTRINGPARAM( "D:\\DEBUG.LOG !" ) ) ).Execute(); +} + +ByteString EditDbg::GetPortionInfo( ParaPortion* pPPortion ) +{ + USHORT z; + + ByteString aDebStr( "Absatzlaenge = " ); + aDebStr += ByteString::CreateFromInt32( pPPortion->GetNode()->Len() ); + + aDebStr += "\nZeichenattribute:"; + for ( z = 0; z < pPPortion->GetNode()->GetCharAttribs().Count(); z++ ) + { + EditCharAttrib* pAttr = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( z ); + aDebStr += "\n "; + aDebStr += ByteString::CreateFromInt32( pAttr->GetItem()->Which() ); + aDebStr += '\t'; + aDebStr += ByteString::CreateFromInt32( pAttr->GetStart() ); + aDebStr += '\t'; + aDebStr += ByteString::CreateFromInt32( pAttr->GetEnd() ); + } + + aDebStr += "\nTextportions:"; + USHORT n = 0; + for ( z = 0; z < pPPortion->GetTextPortions().Count(); z++ ) + { + TextPortion* pPortion = pPPortion->GetTextPortions().GetObject( z ); + aDebStr += " "; + aDebStr += ByteString::CreateFromInt32( pPortion->GetLen() ); + aDebStr += "("; + aDebStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() ); + aDebStr += ")"; + aDebStr += ";"; + n = n + pPortion->GetLen(); + } + aDebStr += "\nGesamtlaenge: "; + aDebStr += ByteString::CreateFromInt32( n ); + aDebStr += "\nSortiert nach Start:"; + for ( USHORT x = 0; x < pPPortion->GetNode()->GetCharAttribs().Count(); x++ ) + { + EditCharAttrib* pCurAttrib = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( x ); + aDebStr += "\nStart: "; + aDebStr += ByteString::CreateFromInt32( pCurAttrib->GetStart() ); + aDebStr += "\tEnde: "; + aDebStr += ByteString::CreateFromInt32( pCurAttrib->GetEnd() ); + } + return aDebStr; +} + +ByteString EditDbg::GetTextPortionInfo( TextPortionList& rPortions ) +{ + ByteString aDebStr; + for ( USHORT z = 0; z < rPortions.Count(); z++ ) + { + TextPortion* pPortion = rPortions.GetObject( z ); + aDebStr += " "; + aDebStr += ByteString::CreateFromInt32( pPortion->GetLen() ); + aDebStr += "("; + aDebStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() ); + aDebStr += ")"; + aDebStr += ";"; + } + return aDebStr; +} + +void EditDbg::ShowPortionData( ParaPortion* pPortion ) +{ + ByteString aDebStr( GetPortionInfo( pPortion ) ); + InfoBox( 0, String( aDebStr, RTL_TEXTENCODING_ASCII_US ) ).Execute(); +} + + +BOOL ParaPortion::DbgCheckTextPortions() +{ + // pruefen, ob Portionlaenge ok: + USHORT nXLen = 0; + for ( USHORT nPortion = 0; nPortion < aTextPortionList.Count(); nPortion++ ) + nXLen = nXLen + aTextPortionList[nPortion]->GetLen(); + return nXLen == pNode->Len() ? TRUE : FALSE; +} + +BOOL CheckOrderedList( CharAttribArray& rAttribs, BOOL bStart ) +{ + USHORT nPrev = 0; + for ( USHORT nAttr = 0; nAttr < rAttribs.Count(); nAttr++ ) + { + EditCharAttrib* pAttr = rAttribs[nAttr]; + USHORT nCur = bStart ? pAttr->GetStart() : pAttr->GetEnd(); + if ( nCur < nPrev ) + return FALSE; + + nPrev = nCur; + } + return TRUE; +} + +#endif + diff --git a/editeng/source/editeng/editdbg.hxx b/editeng/source/editeng/editdbg.hxx new file mode 100644 index 0000000000..ceb0bad2b0 --- /dev/null +++ b/editeng/source/editeng/editdbg.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editdbg.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EDITDBG_HXX +#define _EDITDBG_HXX + +#include <svl/solar.hrc> +#include <tools/string.hxx> +#include <stdio.h> + +class EditEngine; +class ParaPortion; +class EditUndoList; +class TextPortionList; +class SfxItemSet; +class SfxItemPool; +class SfxPoolItem; + +ByteString DbgOutItem( const SfxItemPool& rPool, const SfxPoolItem& rItem ); +void DbgOutItemSet( FILE* fp, const SfxItemSet& rSet, BOOL bSearchInParent, BOOL bShowALL ); + +class EditDbg +{ +public: + static void ShowEditEngineData( EditEngine* pEditEngine, BOOL bInfoBox = TRUE ); + static void ShowPortionData( ParaPortion* pPortion ); + static ByteString GetPortionInfo( ParaPortion* pPPortion ); + static ByteString GetTextPortionInfo( TextPortionList& rPortions ); + static ByteString GetUndoDebStr( EditUndoList* pUndoList ); +}; + + +#endif // _EDITDBG_HXX diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx new file mode 100644 index 0000000000..a5d58b9c6b --- /dev/null +++ b/editeng/source/editeng/editdoc.cxx @@ -0,0 +1,2317 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editdoc.cxx,v $ + * $Revision: 1.48.148.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#include <editeng/tstpitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/akrnitem.hxx> +#include <editeng/cscoitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/emphitem.hxx> +#include <editeng/charscaleitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/xmlcnitm.hxx> +#include <editeng/editids.hrc> + +#include <editdoc.hxx> +#include <editdbg.hxx> +#include <editeng/eerdll.hxx> +#include <eerdll2.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> +#include <tools/shl.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <stdlib.h> // qsort + +using namespace ::com::sun::star; + + +// ------------------------------------------------------------ + +USHORT GetScriptItemId( USHORT nItemId, short nScriptType ) +{ + USHORT nId = nItemId; + + if ( ( nScriptType == i18n::ScriptType::ASIAN ) || + ( nScriptType == i18n::ScriptType::COMPLEX ) ) + { + switch ( nItemId ) + { + case EE_CHAR_LANGUAGE: + nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL; + break; + case EE_CHAR_FONTINFO: + nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL; + break; + case EE_CHAR_FONTHEIGHT: + nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL; + break; + case EE_CHAR_WEIGHT: + nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL; + break; + case EE_CHAR_ITALIC: + nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL; + break; + } + } + + return nId; +} + +BOOL IsScriptItemValid( USHORT nItemId, short nScriptType ) +{ + BOOL bValid = TRUE; + + switch ( nItemId ) + { + case EE_CHAR_LANGUAGE: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_LANGUAGE_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_LANGUAGE_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; + case EE_CHAR_FONTINFO: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_FONTINFO_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_FONTINFO_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; + case EE_CHAR_FONTHEIGHT: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_FONTHEIGHT_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_FONTHEIGHT_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; + case EE_CHAR_WEIGHT: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_WEIGHT_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_WEIGHT_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; + case EE_CHAR_ITALIC: + bValid = nScriptType == i18n::ScriptType::LATIN; + break; + case EE_CHAR_ITALIC_CJK: + bValid = nScriptType == i18n::ScriptType::ASIAN; + break; + case EE_CHAR_ITALIC_CTL: + bValid = nScriptType == i18n::ScriptType::COMPLEX; + break; + } + + return bValid; +} + + +// ------------------------------------------------------------ + +// Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303) +// fuer Grep: WS_TARGET + +DBG_NAME( EE_TextPortion ); +DBG_NAME( EE_EditLine ); +DBG_NAME( EE_ContentNode ); +DBG_NAME( EE_CharAttribList ); + +SfxItemInfo aItemInfos[EDITITEMCOUNT] = { + { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR + { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS + { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION + { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE }, + { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING + { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL + { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE + { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE + { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE + { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE }, + { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE }, + { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE }, + { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE }, + { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE }, + { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE }, + { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE }, + { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE }, + { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY + { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS + { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE }, + { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB + { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR + { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV + { SID_FIELD, SFX_ITEM_POOLABLE } +}; + +USHORT aV1Map[] = { + 3999, 4001, 4002, 4003, 4004, 4005, 4006, + 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019? +}; + +USHORT aV2Map[] = { + 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, + 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020 +}; + +USHORT aV3Map[] = { + 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, + 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, + 4020, 4021 +}; + +USHORT aV4Map[] = { + 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, + 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, + 4014, 4015, 4016, 4017, 4018, + /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */ + 4034, 4035, 4036, 4037 +}; + +USHORT aV5Map[] = { + 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, + 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, + 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, + 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, + /* EE_CHAR_OVERLINE inserted here */ + 4035, 4036, 4037, 4038 +}; + +SV_IMPL_PTRARR( DummyContentList, ContentNode* ); +SV_IMPL_VARARR( ScriptTypePosInfos, ScriptTypePosInfo ); +SV_IMPL_VARARR( WritingDirectionInfos, WritingDirectionInfo ); +// SV_IMPL_VARARR( ExtraCharInfos, ExtraCharInfo ); + + +int SAL_CALL CompareStart( const void* pFirst, const void* pSecond ) +{ + if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() ) + return (-1); + else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() ) + return (1); + return 0; +} + +EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, USHORT nS, USHORT nE ) +{ + // das neue Attribut im Pool anlegen + const SfxPoolItem& rNew = rPool.Put( rAttr ); + + EditCharAttrib* pNew = 0; + switch( rNew.Which() ) + { + case EE_CHAR_LANGUAGE: + case EE_CHAR_LANGUAGE_CJK: + case EE_CHAR_LANGUAGE_CTL: + { + pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_COLOR: + { + pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_FONTINFO: + case EE_CHAR_FONTINFO_CJK: + case EE_CHAR_FONTINFO_CTL: + { + pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_FONTHEIGHT: + case EE_CHAR_FONTHEIGHT_CJK: + case EE_CHAR_FONTHEIGHT_CTL: + { + pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_FONTWIDTH: + { + pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_WEIGHT: + case EE_CHAR_WEIGHT_CJK: + case EE_CHAR_WEIGHT_CTL: + { + pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_UNDERLINE: + { + pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_OVERLINE: + { + pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_EMPHASISMARK: + { + pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_RELIEF: + { + pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_STRIKEOUT: + { + pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_ITALIC: + case EE_CHAR_ITALIC_CJK: + case EE_CHAR_ITALIC_CTL: + { + pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_OUTLINE: + { + pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_SHADOW: + { + pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_ESCAPEMENT: + { + pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_PAIRKERNING: + { + pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_KERNING: + { + pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_WLM: + { + pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE ); + } + break; + case EE_CHAR_XMLATTRIBS: + { + pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information... + } + break; + case EE_FEATURE_TAB: + { + pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS ); + } + break; + case EE_FEATURE_LINEBR: + { + pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS ); + } + break; + case EE_FEATURE_FIELD: + { + pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS ); + } + break; + default: + { + DBG_ERROR( "Ungueltiges Attribut!" ); + } + } + return pNew; +} + +// ------------------------------------------------------------------------- +// class EditLine +// ------------------------------------------------------------------------- + +EditLine::EditLine() +{ + DBG_CTOR( EE_EditLine, 0 ); + + nStart = nEnd = 0; + nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann. + nEndPortion = 0; + nHeight = 0; + nStartPosX = 0; + nTxtHeight = 0; + nTxtWidth = 0; + nCrsrHeight = 0; + nMaxAscent = 0; + bHangingPunctuation = FALSE; + bInvalid = TRUE; +} + +EditLine::EditLine( const EditLine& r ) +{ + DBG_CTOR( EE_EditLine, 0 ); + + nEnd = r.nEnd; + nStart = r.nStart; + nStartPortion = r.nStartPortion; + nEndPortion = r.nEndPortion; + bHangingPunctuation = r.bHangingPunctuation; + + nHeight = 0; + nStartPosX = 0; + nTxtHeight = 0; + nTxtWidth = 0; + nCrsrHeight = 0; + nMaxAscent = 0; + bInvalid = TRUE; +} + +EditLine::~EditLine() +{ + DBG_DTOR( EE_EditLine, 0 ); +} + +EditLine* EditLine::Clone() const +{ + EditLine* pL = new EditLine; + if ( aPositions.Count() ) + { + pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0); + } + pL->nStartPosX = nStartPosX; + pL->nStart = nStart; + pL->nEnd = nEnd; + pL->nStartPortion = nStartPortion; + pL->nEndPortion = nEndPortion; + pL->nHeight = nHeight; + pL->nTxtWidth = nTxtWidth; + pL->nTxtHeight = nTxtHeight; + pL->nCrsrHeight = nCrsrHeight; + pL->nMaxAscent = nMaxAscent; + + return pL; +} + +BOOL operator == ( const EditLine& r1, const EditLine& r2 ) +{ + if ( r1.nStart != r2.nStart ) + return FALSE; + + if ( r1.nEnd != r2.nEnd ) + return FALSE; + + if ( r1.nStartPortion != r2.nStartPortion ) + return FALSE; + + if ( r1.nEndPortion != r2.nEndPortion ) + return FALSE; + + return TRUE; +} + +EditLine& EditLine::operator = ( const EditLine& r ) +{ + nEnd = r.nEnd; + nStart = r.nStart; + nEndPortion = r.nEndPortion; + nStartPortion = r.nStartPortion; + return *this; +} + + +BOOL operator != ( const EditLine& r1, const EditLine& r2 ) +{ + return !( r1 == r2 ); +} + +Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) +{ + Size aSz; + Size aTmpSz; + TextPortion* pPortion; + + USHORT nIndex = GetStart(); + + DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" ); + + for ( USHORT n = nStartPortion; n <= nEndPortion; n++ ) + { + pPortion = rParaPortion.GetTextPortions().GetObject(n); + switch ( pPortion->GetKind() ) + { + case PORTIONKIND_TEXT: + case PORTIONKIND_FIELD: + case PORTIONKIND_HYPHENATOR: + { + aTmpSz = pPortion->GetSize(); + aSz.Width() += aTmpSz.Width(); + if ( aSz.Height() < aTmpSz.Height() ) + aSz.Height() = aTmpSz.Height(); + } + break; + case PORTIONKIND_TAB: +// case PORTIONKIND_EXTRASPACE: + { + aSz.Width() += pPortion->GetSize().Width(); + } + break; + } + nIndex = nIndex + pPortion->GetLen(); + } + + SetHeight( (USHORT)aSz.Height() ); + return aSz; +} + +// ------------------------------------------------------------------------- +// class EditLineList +// ------------------------------------------------------------------------- +EditLineList::EditLineList() +{ +} + +EditLineList::~EditLineList() +{ + Reset(); +} + +void EditLineList::Reset() +{ + for ( USHORT nLine = 0; nLine < Count(); nLine++ ) + delete GetObject(nLine); + Remove( 0, Count() ); +} + +void EditLineList::DeleteFromLine( USHORT nDelFrom ) +{ + DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" ); + for ( USHORT nL = nDelFrom; nL < Count(); nL++ ) + delete GetObject(nL); + Remove( nDelFrom, Count()-nDelFrom ); +} + +USHORT EditLineList::FindLine( USHORT nChar, BOOL bInclEnd ) +{ + for ( USHORT nLine = 0; nLine < Count(); nLine++ ) + { + EditLine* pLine = GetObject( nLine ); + if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) || + ( pLine->GetEnd() > nChar ) ) + { + return nLine; + } + } + + DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" ); + return ( Count() - 1 ); +} + +// ------------------------------------------------------------------------- +// class EditSelection +// ------------------------------------------------------------------------- +BOOL EditPaM::DbgIsBuggy( EditDoc& rDoc ) +{ + if ( !pNode ) + return TRUE; + if ( rDoc.GetPos( pNode ) >= rDoc.Count() ) + return TRUE; + if ( nIndex > pNode->Len() ) + return TRUE; + + return FALSE; +} + +BOOL EditSelection::DbgIsBuggy( EditDoc& rDoc ) +{ + if ( aStartPaM.DbgIsBuggy( rDoc ) ) + return TRUE; + if ( aEndPaM.DbgIsBuggy( rDoc ) ) + return TRUE; + + return FALSE; +} + +EditSelection::EditSelection() +{ +} + +EditSelection::EditSelection( const EditPaM& rStartAndAnd ) +{ + // koennte noch optimiert werden! + // nicht erst Def-CTOR vom PaM rufen! + aStartPaM = rStartAndAnd; + aEndPaM = rStartAndAnd; +} + +EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) +{ + // koennte noch optimiert werden! + aStartPaM = rStart; + aEndPaM = rEnd; +} + +EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) +{ + aStartPaM = rPaM; + aEndPaM = rPaM; + return *this; +} + +BOOL EditSelection::IsInvalid() const +{ + EditPaM aEmptyPaM; + + if ( aStartPaM == aEmptyPaM ) + return TRUE; + + if ( aEndPaM == aEmptyPaM ) + return TRUE; + + return FALSE; +} + +BOOL EditSelection::Adjust( const ContentList& rNodes ) +{ + DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" ); + DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" ); + + ContentNode* pStartNode = aStartPaM.GetNode(); + ContentNode* pEndNode = aEndPaM.GetNode(); + + USHORT nStartNode = rNodes.GetPos( pStartNode ); + USHORT nEndNode = rNodes.GetPos( pEndNode ); + + DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" ); + DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" ); + + BOOL bSwap = FALSE; + if ( nStartNode > nEndNode ) + bSwap = TRUE; + else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) ) + bSwap = TRUE; + + if ( bSwap ) + { + EditPaM aTmpPaM( aStartPaM ); + aStartPaM = aEndPaM; + aEndPaM = aTmpPaM; + } + + return bSwap; +} + + +// ------------------------------------------------------------------------- +// class EditPaM +// ------------------------------------------------------------------------- +BOOL operator == ( const EditPaM& r1, const EditPaM& r2 ) +{ + if ( r1.GetNode() != r2.GetNode() ) + return FALSE; + + if ( r1.GetIndex() != r2.GetIndex() ) + return FALSE; + + return TRUE; +} + +EditPaM& EditPaM::operator = ( const EditPaM& rPaM ) +{ + nIndex = rPaM.nIndex; + pNode = rPaM.pNode; + return *this; +} + +BOOL operator != ( const EditPaM& r1, const EditPaM& r2 ) +{ + return !( r1 == r2 ); +} + + +// ------------------------------------------------------------------------- +// class ContentNode +// ------------------------------------------------------------------------- +ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) +{ + DBG_CTOR( EE_ContentNode, 0 ); + pWrongList = NULL; +} + +ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) : + XubString( rStr ), aContentAttribs( rContentAttribs ) +{ + DBG_CTOR( EE_ContentNode, 0 ); + pWrongList = NULL; +} + +ContentNode::~ContentNode() +{ + DBG_DTOR( EE_ContentNode, 0 ); +#ifndef SVX_LIGHT + delete pWrongList; +#endif +} + +void ContentNode::ExpandAttribs( USHORT nIndex, USHORT nNew, SfxItemPool& rItemPool ) +{ + if ( !nNew ) + return; + + // Da Features anders behandelt werden als normale Zeichenattribute, + // kann sich hier auch die Sortierung der Start-Liste aendern! + // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von + // bFeature oder Spezialfall existieren, + // muessen (n-1) Moeglichkeiten mit bResort versehen werden. + // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort, + // so dass nicht neu sortiert wird, wenn sich alle Attribute + // gleich verhalten. + BOOL bResort = FALSE; + BOOL bExpandedEmptyAtIndexNull = FALSE; + + USHORT nAttr = 0; + EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() >= nIndex ) + { + // Alle Attribute hinter der Einfuegeposition verschieben... + if ( pAttrib->GetStart() > nIndex ) + { + pAttrib->MoveForward( nNew ); + } + // 0: Leeres Attribut expandieren, wenn an Einfuegestelle + else if ( pAttrib->IsEmpty() ) + { + // Index nicht pruefen, leeres durfte nur dort liegen. + // Wenn spaeter doch Ueberpruefung: + // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch! + // Start <= nIndex, End >= nIndex => Start=End=nIndex! +// if ( pAttrib->GetStart() == nIndex ) + pAttrib->Expand( nNew ); + if ( pAttrib->GetStart() == 0 ) + bExpandedEmptyAtIndexNull = TRUE; + } + // 1: Attribut startet davor, geht bis Index... + else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen + { + // Nur expandieren, wenn kein Feature, + // und wenn nicht in ExcludeListe! + // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren +// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) + if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) + { + if ( !pAttrib->IsEdge() ) + pAttrib->Expand( nNew ); + } + else + bResort = TRUE; + } + // 2: Attribut startet davor, geht hinter Index... + else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" ); + pAttrib->Expand( nNew ); + } + // 3: Attribut startet auf Index... + else if ( pAttrib->GetStart() == nIndex ) + { + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveForward( nNew ); + bResort = TRUE; + } + else + { + BOOL bExpand = FALSE; + if ( nIndex == 0 ) + { + bExpand = TRUE; + if( bExpandedEmptyAtIndexNull ) + { + // Check if this kind of attribut was empty and expanded here... + USHORT nW = pAttrib->GetItem()->Which(); + for ( USHORT nA = 0; nA < nAttr; nA++ ) + { + EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA]; + if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) ) + { + bExpand = FALSE; + break; + } + } + + } + } + if ( bExpand ) + { + pAttrib->Expand( nNew ); + bResort = TRUE; + } + else + { + pAttrib->MoveForward( nNew ); + } + } + } + } + + if ( pAttrib->IsEdge() ) + pAttrib->SetEdge( FALSE ); + + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" ); + if ( pAttrib->IsEmpty() ) + { + DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" ); + bResort = TRUE; + aCharAttribList.GetAttribs().Remove( nAttr ); + rItemPool.Remove( *pAttrib->GetItem() ); + delete pAttrib; + nAttr--; + } + nAttr++; + pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); + } + + if ( bResort ) + aCharAttribList.ResortAttribs(); + +#ifndef SVX_LIGHT + if ( pWrongList ) + { + BOOL bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex ); + pWrongList->TextInserted( nIndex, nNew, bSep ); + } +#endif // !SVX_LIGHT + +#ifdef EDITDEBUG + DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Expand: Start-Liste verdreht" ); +#endif +} + +void ContentNode::CollapsAttribs( USHORT nIndex, USHORT nDeleted, SfxItemPool& rItemPool ) +{ + if ( !nDeleted ) + return; + + // Da Features anders behandelt werden als normale Zeichenattribute, + // kann sich hier auch die Sortierung der Start-Liste aendern! + BOOL bResort = FALSE; + BOOL bDelAttr = FALSE; + USHORT nEndChanges = nIndex+nDeleted; + + USHORT nAttr = 0; + EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); + while ( pAttrib ) + { + bDelAttr = FALSE; + if ( pAttrib->GetEnd() >= nIndex ) + { + // Alles Attribute hinter der Einfuegeposition verschieben... + if ( pAttrib->GetStart() >= nEndChanges ) + { + pAttrib->MoveBackward( nDeleted ); + } + // 1. Innenliegende Attribute loeschen... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) + { + // Spezialfall: Attrubt deckt genau den Bereich ab + // => als leeres Attribut behalten. + if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) + pAttrib->GetEnd() = nIndex; // leer + else + bDelAttr = TRUE; + } + // 2. Attribut beginnt davor, endet drinnen oder dahinter... + else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); + if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen + pAttrib->GetEnd() = nIndex; + else + pAttrib->Collaps( nDeleted ); // endet dahinter + } + // 3. Attribut beginnt drinnen, endet dahinter... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) + { + // Features duerfen nicht expandieren! + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveBackward( nDeleted ); + bResort = TRUE; + } + else + { + pAttrib->GetStart() = nEndChanges; + pAttrib->MoveBackward( nDeleted ); + } + } + } + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); + if ( bDelAttr /* || pAttrib->IsEmpty() */ ) + { + bResort = TRUE; + aCharAttribList.GetAttribs().Remove( nAttr ); + rItemPool.Remove( *pAttrib->GetItem() ); + delete pAttrib; + nAttr--; + } + else if ( pAttrib->IsEmpty() ) + aCharAttribList.HasEmptyAttribs() = TRUE; + + nAttr++; + pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); + } + + if ( bResort ) + aCharAttribList.ResortAttribs(); + +#ifndef SVX_LIGHT + if ( pWrongList ) + pWrongList->TextDeleted( nIndex, nDeleted ); +#endif // !SVX_LIGHT + +#ifdef EDITDEBUG + DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Collaps: Start-Liste verdreht" ); +#endif +} + +void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, BOOL bKeepEndingAttribs ) +{ + DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" ); + + xub_StrLen nCut = pPrevNode->Len(); + + USHORT nAttr = 0; + EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() < nCut ) + { + // bleiben unveraendert.... + ; + } + else if ( pAttrib->GetEnd() == nCut ) + { + // muessen als leeres Attribut kopiert werden. + if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) + { + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); + DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); + aCharAttribList.InsertAttrib( pNewAttrib ); + } + } + else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) + { + // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! + // muessen kopiert und geaendert werden + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); + DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); + aCharAttribList.InsertAttrib( pNewAttrib ); + // stutzen: + pAttrib->GetEnd() = nCut; + } + else + { + // alle dahinter verschieben in den neuen Node (this) +// pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib ); + pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr ); + aCharAttribList.InsertAttrib( pAttrib ); + DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" ); + DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" ); + pAttrib->GetStart() = pAttrib->GetStart() - nCut; + pAttrib->GetEnd() = pAttrib->GetEnd() - nCut; + nAttr--; + } + nAttr++; + pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); + } +} + +void ContentNode::AppendAttribs( ContentNode* pNextNode ) +{ + DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" ); + + USHORT nNewStart = Len(); + +#ifdef EDITDEBUG + DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" ); +#endif + + USHORT nAttr = 0; + EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); + while ( pAttrib ) + { + // alle Attribute verschieben in den aktuellen Node (this) + BOOL bMelted = FALSE; + if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) + { + // Evtl koennen Attribute zusammengefasst werden: + USHORT nTmpAttr = 0; + EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); + while ( !bMelted && pTmpAttrib ) + { + if ( pTmpAttrib->GetEnd() == nNewStart ) + { + if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && + ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) ) + { + pTmpAttrib->GetEnd() = + pTmpAttrib->GetEnd() + pAttrib->GetLen(); + pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr ); + // Vom Pool abmelden ?! + delete pAttrib; + bMelted = TRUE; + } + } + ++nTmpAttr; + pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); + } + } + + if ( !bMelted ) + { + pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; + pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; + aCharAttribList.InsertAttrib( pAttrib ); + ++nAttr; + } + pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); + } + // Fuer die Attribute, die nur ruebergewandert sind: + pNextNode->GetCharAttribs().Clear(); + +#ifdef EDITDEBUG + DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" ); +#endif +} + +void ContentNode::CreateDefFont() +{ + // Erst alle Informationen aus dem Style verwenden... + SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); + if ( pS ) + CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); + + // ... dann die harte Absatzformatierung rueberbuegeln... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == NULL ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) +{ + aContentAttribs.SetStyleSheet( pS ); + + // Erst alle Informationen aus dem Style verwenden... + GetCharAttribs().GetDefFont() = rFontFromStyle; + // ... dann die harte Absatzformatierung rueberbuegeln... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == NULL ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, BOOL bRecalcFont ) +{ + aContentAttribs.SetStyleSheet( pS ); + if ( bRecalcFont ) + CreateDefFont(); +} + +void ContentNode::DestroyWrongList() +{ +#ifndef SVX_LIGHT + delete pWrongList; +#endif + pWrongList = NULL; +} + +void ContentNode::CreateWrongList() +{ + DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); +#ifndef SVX_LIGHT + pWrongList = new WrongList; +#endif +} + +void ContentNode::SetWrongList( WrongList* p ) +{ + DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); + pWrongList = p; +} + +// ------------------------------------------------------------------------- +// class ContentAttribs +// ------------------------------------------------------------------------- +ContentAttribs::ContentAttribs( SfxItemPool& rPool ) : + aAttribSet( rPool, EE_PARA_START, EE_CHAR_END ) +{ + pStyle = 0; +} + +ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) : + aAttribSet( rRef.aAttribSet ) +{ + pStyle = rRef.pStyle; +} + +ContentAttribs::~ContentAttribs() +{ +} + +SvxTabStop ContentAttribs::FindTabStop( long nCurPos, USHORT nDefTab ) +{ + const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS ); + for ( USHORT i = 0; i < rTabs.Count(); i++ ) + { + const SvxTabStop& rTab = rTabs[i]; + if ( rTab.GetTabPos() > nCurPos ) + return rTab; + } + + // DefTab ermitteln... + SvxTabStop aTabStop; + long x = nCurPos / nDefTab + 1; + aTabStop.GetTabPos() = nDefTab * x; + return aTabStop; +} + +void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) +{ + BOOL bStyleChanged = ( pStyle != pS ); + pStyle = pS; + // #104799# Only when other style sheet, not when current style sheet modified + if ( pStyle && bStyleChanged ) + { + // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style + // spezifiziert sind, damit die Attribute des Styles wirken koennen. + const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); + for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) + { + // #99635# Don't change bullet on/off + if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) ) + aAttribSet.ClearItem( nWhich ); + } + } +} + +const SfxPoolItem& ContentAttribs::GetItem( USHORT nWhich ) +{ + // Harte Absatzattribute haben Vorrang! + SfxItemSet* pTakeFrom = &aAttribSet; + if ( pStyle && ( aAttribSet.GetItemState( nWhich, FALSE ) != SFX_ITEM_ON ) ) + pTakeFrom = &pStyle->GetItemSet(); + + return pTakeFrom->Get( nWhich ); +} + +BOOL ContentAttribs::HasItem( USHORT nWhich ) +{ + BOOL bHasItem = FALSE; + if ( aAttribSet.GetItemState( nWhich, FALSE ) == SFX_ITEM_ON ) + bHasItem = TRUE; + else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON ) + bHasItem = TRUE; + + return bHasItem; +} + + + +// ---------------------------------------------------------------------- +// class ItemList +// ---------------------------------------------------------------------- +const SfxPoolItem* ItemList::FindAttrib( USHORT nWhich ) +{ + const SfxPoolItem* pItem = First(); + while ( pItem && ( pItem->Which() != nWhich ) ) + pItem = Next(); + + return pItem; +} + +// ------------------------------------------------------------------------- +// class EditDoc +// ------------------------------------------------------------------------- +EditDoc::EditDoc( SfxItemPool* pPool ) +{ + if ( pPool ) + { + pItemPool = pPool; + bOwnerOfPool = FALSE; + } + else + { + pItemPool = new EditEngineItemPool( FALSE ); + bOwnerOfPool = TRUE; + } + + nDefTab = DEFTAB; + bIsVertical = FALSE; + bIsFixedCellHeight = FALSE; + + // Don't create a empty node, Clear() will be called in EditEngine-CTOR + + SetModified( FALSE ); +}; + +EditDoc::~EditDoc() +{ + ImplDestroyContents(); + if ( bOwnerOfPool ) + SfxItemPool::Free(pItemPool); +} + +void EditDoc::ImplDestroyContents() +{ + for ( USHORT nNode = Count(); nNode; ) + RemoveItemsFromPool( GetObject( --nNode ) ); + DeleteAndDestroy( 0, Count() ); +} + +void EditDoc::RemoveItemsFromPool( ContentNode* pNode ) +{ + for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ ) + { + EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr]; + GetItemPool().Remove( *pAttr->GetItem() ); + } +} + +void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType ) +{ + Font aPrevFont( rFont ); + rFont.SetAlign( ALIGN_BASELINE ); + rFont.SetTransparent( TRUE ); + + USHORT nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); + USHORT nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); + USHORT nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ); + USHORT nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ); + USHORT nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType ); + + if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) ) + { + const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo ); + rFont.SetName( rFontItem.GetFamilyName() ); + rFont.SetFamily( rFontItem.GetFamily() ); + rFont.SetPitch( rFontItem.GetPitch() ); + rFont.SetCharSet( rFontItem.GetCharSet() ); + } + if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) ) + rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) ) + rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) ) + rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); + if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) ) + rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) ) + rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) ) + rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) ) + rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() ); + if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) ) + rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) ) + rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) ) + rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) ) + { + const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT ); + + USHORT nProp = rEsc.GetProp(); + rFont.SetPropr( (BYTE)nProp ); + + short nEsc = rEsc.GetEsc(); + if ( nEsc == DFLT_ESC_AUTO_SUPER ) + nEsc = 100 - nProp; + else if ( nEsc == DFLT_ESC_AUTO_SUB ) + nEsc = sal::static_int_cast< short >( -( 100 - nProp ) ); + rFont.SetEscapement( nEsc ); + } + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) ) + rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) ) + rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) ) + rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) ) + rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() ); + if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) ) + rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() ); + + // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung + // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich. + // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer + // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen. + if ( rFont == aPrevFont ) + rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance +} + +void EditDoc::CreateDefFont( BOOL bUseStyles ) +{ + SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END ); + CreateFont( aDefFont, aTmpSet ); + aDefFont.SetVertical( IsVertical() ); + aDefFont.SetOrientation( IsVertical() ? 2700 : 0 ); + + for ( USHORT nNode = 0; nNode < Count(); nNode++ ) + { + ContentNode* pNode = GetObject( nNode ); + pNode->GetCharAttribs().GetDefFont() = aDefFont; + if ( bUseStyles ) + pNode->CreateDefFont(); + } +} + +static const sal_Unicode aCR[] = { 0x0d, 0x00 }; +static const sal_Unicode aLF[] = { 0x0a, 0x00 }; +static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 }; + +XubString EditDoc::GetSepStr( LineEnd eEnd ) +{ + XubString aSep; + if ( eEnd == LINEEND_CR ) + aSep = aCR; + else if ( eEnd == LINEEND_LF ) + aSep = aLF; + else + aSep = aCRLF; + return aSep; +} + +XubString EditDoc::GetText( LineEnd eEnd ) const +{ + ULONG nLen = GetTextLen(); + USHORT nNodes = Count(); + + String aSep = EditDoc::GetSepStr( eEnd ); + USHORT nSepSize = aSep.Len(); + + if ( nSepSize ) + nLen += nNodes * nSepSize; + if ( nLen > 0xFFFb / sizeof(xub_Unicode) ) + { + DBG_ERROR( "Text zu gross fuer String" ); + return XubString(); + } + xub_Unicode* pStr = new xub_Unicode[nLen+1]; + xub_Unicode* pCur = pStr; + USHORT nLastNode = nNodes-1; + for ( USHORT nNode = 0; nNode < nNodes; nNode++ ) + { + XubString aTmp( GetParaAsString( GetObject(nNode) ) ); + memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) ); + pCur += aTmp.Len(); + if ( nSepSize && ( nNode != nLastNode ) ) + { + memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) ); + pCur += nSepSize; + } + } + *pCur = '\0'; + XubString aASCIIText( pStr ); + delete[] pStr; + return aASCIIText; +} + +XubString EditDoc::GetParaAsString( USHORT nNode ) const +{ + return GetParaAsString( SaveGetObject( nNode ) ); +} + +XubString EditDoc::GetParaAsString( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, BOOL bResolveFields ) const +{ + if ( nEndPos > pNode->Len() ) + nEndPos = pNode->Len(); + + DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" ); + + USHORT nIndex = nStartPos; + XubString aStr; + EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex ); + while ( nIndex < nEndPos ) + { + USHORT nEnd = nEndPos; + if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) + nEnd = pNextFeature->GetStart(); + else + pNextFeature = 0; // Feature interessiert unten nicht + + DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" ); + //!! beware of sub string length of -1 which is also defined as STRING_LEN and + //!! thus would result in adding the whole sub string up to the end of the node !! + if (nEnd > nIndex) + aStr += XubString( *pNode, nIndex, nEnd - nIndex ); + + if ( pNextFeature ) + { + switch ( pNextFeature->GetItem()->Which() ) + { + case EE_FEATURE_TAB: aStr += '\t'; + break; + case EE_FEATURE_LINEBR: aStr += '\x0A'; + break; + case EE_FEATURE_FIELD: if ( bResolveFields ) + aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue(); + break; + default: DBG_ERROR( "Was fuer ein Feature ?" ); + } + pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd ); + } + nIndex = nEnd; + } + return aStr; +} + +ULONG EditDoc::GetTextLen() const +{ + ULONG nLen = 0; + for ( USHORT nNode = 0; nNode < Count(); nNode++ ) + { + ContentNode* pNode = GetObject( nNode ); + nLen += pNode->Len(); + // Felder k”nnen laenger sein als der Platzhalter im Node. + const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); + for ( USHORT nAttr = rAttrs.Count(); nAttr; ) + { + EditCharAttrib* pAttr = rAttrs[--nAttr]; + if ( pAttr->Which() == EE_FEATURE_FIELD ) + { + USHORT nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len(); + if ( !nFieldLen ) + nLen--; + else + nLen += nFieldLen-1; + } + } + } + return nLen; +} + +EditPaM EditDoc::Clear() +{ + ImplDestroyContents(); + + ContentNode* pNode = new ContentNode( GetItemPool() ); + Insert( pNode, 0 ); + + CreateDefFont( FALSE ); + + SetModified( FALSE ); + + EditPaM aPaM( pNode, 0 ); + return aPaM; +} + +void EditDoc::SetModified( BOOL b ) +{ + bModified = b; + if ( bModified ) + { + aModifyHdl.Call( NULL ); + } +} + +EditPaM EditDoc::RemoveText() +{ + // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt + ContentNode* pPrevFirstNode = GetObject(0); + SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet(); + SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); + Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); + + ImplDestroyContents(); + + ContentNode* pNode = new ContentNode( GetItemPool() ); + Insert( pNode, 0 ); + + pNode->SetStyleSheet( pPrevStyle, FALSE ); + pNode->GetContentAttribs().GetItems().Set( aPrevSet ); + pNode->GetCharAttribs().GetDefFont() = aPrevFont; + + SetModified( TRUE ); + + EditPaM aPaM( pNode, 0 ); + return aPaM; +} + +void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c ) +{ + DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + + rPaM.GetNode()->Insert( c, rPaM.GetIndex() ); + rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() ); + + SetModified( TRUE ); +} + +EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr ) +{ + DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); + DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" ); + + aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() ); + aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len(); + + SetModified( TRUE ); + + return aPaM; +} + +EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, BOOL bKeepEndingAttribs ) +{ + DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" ); + ContentNode* pCurNode = aPaM.GetNode(); + USHORT nPos = GetPos( pCurNode ); + XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() ); + aPaM.GetNode()->Erase( aPaM.GetIndex() ); + + // the paragraph attributes... + ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() ); + + // for a new paragraph we like to have the bullet/numbering visible by default + aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, TRUE), EE_PARA_BULLETSTATE ); + + // ContenNode-CTOR kopiert auch die Absatzattribute + ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); + + // Den Default-Font kopieren + pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); + SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet(); + if ( pStyle ) + { + XubString aFollow( pStyle->GetFollow() ); + if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) ) + { + SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() ); + pNode->SetStyleSheet( (SfxStyleSheet*)pNext ); + } + } + + // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden: + pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); + + Insert( pNode, nPos+1 ); + + SetModified( TRUE ); + + aPaM.SetNode( pNode ); + aPaM.SetIndex( 0 ); + return aPaM; +} + +EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) +{ + DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" ); + + aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); + + // Fuer das Feature ein Feature-Attribut anlegen... + EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); + DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" ); + aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib ); + + SetModified( TRUE ); + + aPaM.GetIndex()++; + return aPaM; +} + +EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) +{ + const EditPaM aPaM( pLeft, pLeft->Len() ); + + // Erst die Attribute, da sonst nLen nicht stimmt! + pLeft->AppendAttribs( pRight ); + // Dann den Text... + *pLeft += *pRight; + + // der rechte verschwindet. + RemoveItemsFromPool( pRight ); + USHORT nRight = GetPos( pRight ); + Remove( nRight ); + delete pRight; + + SetModified( TRUE ); + + return aPaM; +} + +EditPaM EditDoc::RemoveChars( EditPaM aPaM, USHORT nChars ) +{ + // Evtl. Features entfernen! + aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); + aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); + + SetModified( TRUE ); + + return aPaM; +} + +void EditDoc::InsertAttribInSelection( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem ) +{ + DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); + DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); + + // fuer Optimierung: + // dieses endet am Anfang der Selektion => kann erweitert werden + EditCharAttrib* pEndingAttrib = 0; + // dieses startet am Ende der Selektion => kann erweitert werden + EditCharAttrib* pStartingAttrib = 0; + + DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); + + RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() ); + + if ( pStartingAttrib && pEndingAttrib && + ( *(pStartingAttrib->GetItem()) == rPoolItem ) && + ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) + { + // wird ein groesses Attribut. + pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); + GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); + pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) ); + delete pStartingAttrib; + } + else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) + pStartingAttrib->GetStart() = nStart; + else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) + pEndingAttrib->GetEnd() = nEnd; + else + InsertAttrib( rPoolItem, pNode, nStart, nEnd ); + + if ( pStartingAttrib ) + pNode->GetCharAttribs().ResortAttribs(); + + SetModified( TRUE ); +} + +BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, USHORT nWhich ) +{ + EditCharAttrib* pStarting; + EditCharAttrib* pEnding; + return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich ); +} + +BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, USHORT nWhich ) +{ + DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); + DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); + + // dieses endet am Anfang der Selektion => kann erweitert werden + rpEnding = 0; + // dieses startet am Ende der Selektion => kann erweitert werden + rpStarting = 0; + + BOOL bChanged = FALSE; + + DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); + + // ueber die Attribute iterieren... + USHORT nAttr = 0; + EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + while ( pAttr ) + { + BOOL bRemoveAttrib = FALSE; + // MT 11.9.97: + // Ich denke dass in dieser Methode generell keine Features geloescht + // werden sollen. + // => Dann koennen die Feature-Abfragen weiter unten entfallen + USHORT nAttrWhich = pAttr->Which(); + if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) ) + { + // Attribut beginnt in Selection + if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) ) + { + bChanged = TRUE; + if ( pAttr->GetEnd() > nEnd ) + { + pAttr->GetStart() = nEnd; // dann faengt es dahinter an + rpStarting = pAttr; + if ( nWhich ) + break; // es kann kein weiteres Attrib hier liegen + } + else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) + { + // Feature nur loeschen, wenn genau an der Stelle + bRemoveAttrib = TRUE; + } + } + + // Attribut endet in Selection + else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) ) + { + bChanged = TRUE; + if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() ) + { + pAttr->GetEnd() = nStart; // dann hoert es hier auf + rpEnding = pAttr; + } + else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) + { + // Feature nur loeschen, wenn genau an der Stelle + bRemoveAttrib = TRUE; + } + } + // Attribut ueberlappt die Selektion + else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) ) + { + bChanged = TRUE; + if ( pAttr->GetStart() == nStart ) + { + pAttr->GetStart() = nEnd; + rpStarting = pAttr; + if ( nWhich ) + break; // es kann weitere Attribute geben! + } + else if ( pAttr->GetEnd() == nEnd ) + { + pAttr->GetEnd() = nStart; + rpEnding = pAttr; + if ( nWhich ) + break; // es kann weitere Attribute geben! + } + else // Attribut muss gesplittet werden... + { + USHORT nOldEnd = pAttr->GetEnd(); + pAttr->GetEnd() = nStart; + rpEnding = pAttr; + InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd ); + if ( nWhich ) + break; // es kann weitere Attribute geben! + } + } + } + if ( bRemoveAttrib ) + { + DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" ); + DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); + pNode->GetCharAttribs().GetAttribs().Remove(nAttr); + GetItemPool().Remove( *pAttr->GetItem() ); + delete pAttr; + nAttr--; + } + nAttr++; + pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + } + + if ( bChanged ) + { + // char attributes need to be sorted by start again + pNode->GetCharAttribs().ResortAttribs(); + + SetModified( TRUE ); + } + + return bChanged; +} + +void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, USHORT nStart, USHORT nEnd ) +{ + // Diese Methode prueft nicht mehr, ob ein entspr. Attribut + // schon an der Stelle existiert! + + EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd ); + DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" ); + pNode->GetCharAttribs().InsertAttrib( pAttrib ); + + SetModified( TRUE ); +} + +void EditDoc::InsertAttrib( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem ) +{ + if ( nStart != nEnd ) + { + InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem ); + } + else + { + // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle: + EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart ); + if ( pAttr ) + { + // Attribut entfernen.... + pNode->GetCharAttribs().GetAttribs().Remove( + pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) ); + } + + // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt. + pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart ); + if ( pAttr ) + { + if ( pAttr->IsInside( nStart ) ) // splitten + { + // ??????????????????????????????? + // eigentlich noch pruefen, ob wirklich splittet, oder return ! + // ??????????????????????????????? + USHORT nOldEnd = pAttr->GetEnd(); + pAttr->GetEnd() = nStart; + pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd ); + pNode->GetCharAttribs().InsertAttrib( pAttr ); + } + else if ( pAttr->GetEnd() == nStart ) + { + DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" ); + // pruefen, ob genau das gleiche Attribut + if ( *(pAttr->GetItem()) == rPoolItem ) + return; + } + } + InsertAttrib( rPoolItem, pNode, nStart, nStart ); + } + + SetModified( TRUE ); +} + +void EditDoc::FindAttribs( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet ) +{ + DBG_ASSERT( pNode, "Wo soll ich suchen ?" ); + DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" ); + + USHORT nAttr = 0; + EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + // keine Selection... + if ( nStartPos == nEndPos ) + { + while ( pAttr && ( pAttr->GetStart() <= nEndPos) ) + { + const SfxPoolItem* pItem = 0; + // Attribut liegt dadrueber... + if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) + pItem = pAttr->GetItem(); + // Attribut endet hier, ist nicht leer + else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) + { + if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) ) + pItem = pAttr->GetItem(); + } + // Attribut endet hier, ist leer + else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) + { + pItem = pAttr->GetItem(); + } + // Attribut beginnt hier + else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) + { + if ( nStartPos == 0 ) // Sonderfall + pItem = pAttr->GetItem(); + } + + if ( pItem ) + { + USHORT nWhich = pItem->Which(); + if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) + { + rCurSet.Put( *pItem ); + } + else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) + { + const SfxPoolItem& rItem = rCurSet.Get( nWhich ); + if ( rItem != *pItem ) + { + rCurSet.InvalidateItem( nWhich ); + } + } + } + nAttr++; + pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + } + } + else // Selektion + { + while ( pAttr && ( pAttr->GetStart() < nEndPos) ) + { + const SfxPoolItem* pItem = 0; + // Attribut liegt dadrueber... + if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) ) + pItem = pAttr->GetItem(); + // Attribut startet mitten drin... + else if ( pAttr->GetStart() >= nStartPos ) + { + // !!! pItem = pAttr->GetItem(); + // einfach nur pItem reicht nicht, da ich z.B. bei Shadow + // niemals ein ungleiches Item finden wuerde, da ein solche + // seine Anwesenheit durch Abwesenheit repraesentiert! + // if ( ... ) + // Es muesste geprueft werden, on genau das gleiche Attribut + // an der Bruchstelle aufsetzt, was recht aufwendig ist. + // Da ich beim Einfuegen von Attributen aber etwas optimiere + // tritt der Fall nicht so schnell auf... + // Also aus Geschwindigkeitsgruenden: + rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); + + } + // Attribut endet mitten drin... + else if ( pAttr->GetEnd() > nStartPos ) + { + // pItem = pAttr->GetItem(); + // s.o. + /*-----------------31.05.95 16:01------------------- + Ist falsch, wenn das gleiche Attribut sofort wieder + eingestellt wird! + => Sollte am besten nicht vorkommen, also gleich beim + Setzen von Attributen richtig machen! + --------------------------------------------------*/ + rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); + } + + if ( pItem ) + { + USHORT nWhich = pItem->Which(); + if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) + { + rCurSet.Put( *pItem ); + } + else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) + { + const SfxPoolItem& rItem = rCurSet.Get( nWhich ); + if ( rItem != *pItem ) + { + rCurSet.InvalidateItem( nWhich ); + } + } + } + nAttr++; + pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + } + } +} + + +// ------------------------------------------------------------------------- +// class EditCharAttribList +// ------------------------------------------------------------------------- + +CharAttribList::CharAttribList() +{ + DBG_CTOR( EE_CharAttribList, 0 ); + bHasEmptyAttribs = FALSE; +} + +CharAttribList::~CharAttribList() +{ + DBG_DTOR( EE_CharAttribList, 0 ); + + USHORT nAttr = 0; + EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); + while ( pAttr ) + { + delete pAttr; + ++nAttr; + pAttr = GetAttrib( aAttribs, nAttr ); + } + Clear(); +} + +void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) +{ +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// optimieren: binaere Suche ? ! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // MT: 26.11.98 + // Vielleicht aber auch einfach nur rueckwaerts iterieren: + // Der haeufigste und kritischste Fall: Attribute kommen bereits + // sortiert an (InsertBinTextObject!) + // Hier waere auch binaere Suche nicht optimal. + // => Wuerde einiges bringen! + + const USHORT nCount = Count(); + const USHORT nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. + + if ( pAttrib->IsEmpty() ) + bHasEmptyAttribs = TRUE; + + BOOL bInserted = FALSE; + for ( USHORT x = 0; x < nCount; x++ ) + { + EditCharAttribPtr pCurAttrib = aAttribs[x]; + if ( pCurAttrib->GetStart() > nStart ) + { + aAttribs.Insert( pAttrib, x ); + bInserted = TRUE; + break; + } + } + if ( !bInserted ) + aAttribs.Insert( pAttrib, nCount ); +} + +void CharAttribList::ResortAttribs() +{ + if ( Count() ) + { +#if defined __SUNPRO_CC +#pragma disable_warn +#endif + qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart ); +#if defined __SUNPRO_CC +#pragma enable_warn +#endif + } +} + +void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) +{ + for ( USHORT n = 0; n < aAttribs.Count(); n++ ) + { + EditCharAttrib* pAttr = aAttribs.GetObject( n ); + for ( USHORT nNext = n+1; nNext < aAttribs.Count(); nNext++ ) + { + EditCharAttrib* p = aAttribs.GetObject( nNext ); + if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) ) + { + if ( *p->GetItem() == *pAttr->GetItem() ) + { + pAttr->GetEnd() = p->GetEnd(); + aAttribs.Remove( nNext ); + rItemPool.Remove( *p->GetItem() ); + delete p; + } + break; // only 1 attr with same which can start here. + } + else if ( p->GetStart() > pAttr->GetEnd() ) + { + break; + } + } + } +} + +EditCharAttrib* CharAttribList::FindAttrib( USHORT nWhich, USHORT nPos ) +{ + // Rueckwaerts, falls eins dort endet, das naechste startet. + // => Das startende gilt... + USHORT nAttr = aAttribs.Count()-1; + EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); + while ( pAttr ) + { + if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) + return pAttr; + pAttr = GetAttrib( aAttribs, --nAttr ); + } + return 0; +} + +EditCharAttrib* CharAttribList::FindNextAttrib( USHORT nWhich, USHORT nFromPos ) const +{ + DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); + const USHORT nAttribs = aAttribs.Count(); + for ( USHORT nAttr = 0; nAttr < nAttribs; nAttr++ ) + { + EditCharAttrib* pAttr = aAttribs[ nAttr ]; + if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) ) + return pAttr; + } + return 0; +} + +BOOL CharAttribList::HasAttrib( USHORT nWhich ) const +{ + for ( USHORT nAttr = aAttribs.Count(); nAttr; ) + { + const EditCharAttrib* pAttr = aAttribs[--nAttr]; + if ( pAttr->Which() == nWhich ) + return TRUE; + } + return FALSE; +} + +BOOL CharAttribList::HasAttrib( USHORT nStartPos, USHORT nEndPos ) const +{ + BOOL bAttr = FALSE; + for ( USHORT nAttr = aAttribs.Count(); nAttr && !bAttr; ) + { + const EditCharAttrib* pAttr = aAttribs[--nAttr]; + if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) ) + return bAttr = TRUE; + } + return bAttr; +} + + +BOOL CharAttribList::HasBoundingAttrib( USHORT nBound ) +{ + // Rueckwaerts, falls eins dort endet, das naechste startet. + // => Das startende gilt... + USHORT nAttr = aAttribs.Count()-1; + EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); + while ( pAttr && ( pAttr->GetEnd() >= nBound ) ) + { + if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) + return TRUE; + pAttr = GetAttrib( aAttribs, --nAttr ); + } + return FALSE; +} + +EditCharAttrib* CharAttribList::FindEmptyAttrib( USHORT nWhich, USHORT nPos ) +{ + if ( !bHasEmptyAttribs ) + return 0; + USHORT nAttr = 0; + EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); + while ( pAttr && ( pAttr->GetStart() <= nPos ) ) + { + if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) + return pAttr; + nAttr++; + pAttr = GetAttrib( aAttribs, nAttr ); + } + return 0; +} + +EditCharAttrib* CharAttribList::FindFeature( USHORT nPos ) const +{ + + USHORT nAttr = 0; + EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr ); + + // erstmal zur gewuenschten Position... + while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) ) + { + nAttr++; + pNextAttrib = GetAttrib( aAttribs, nAttr ); + } + + // jetzt das Feature suchen... + while ( pNextAttrib && !pNextAttrib->IsFeature() ) + { + nAttr++; + pNextAttrib = GetAttrib( aAttribs, nAttr ); + } + + return pNextAttrib; +} + + +void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) +{ + for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) + { + EditCharAttrib* pAttr = aAttribs[nAttr]; + if ( pAttr->IsEmpty() ) + { + rItemPool.Remove( *pAttr->GetItem() ); + aAttribs.Remove( nAttr ); + delete pAttr; + nAttr--; + } + } + bHasEmptyAttribs = FALSE; +} + +BOOL CharAttribList::DbgCheckAttribs() +{ +#ifdef DBG_UTIL + BOOL bOK = TRUE; + for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) + { + EditCharAttrib* pAttr = aAttribs[nAttr]; + if ( pAttr->GetStart() > pAttr->GetEnd() ) + { + bOK = FALSE; + DBG_ERROR( "Attr verdreht" ); + } + else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) ) + { + bOK = FALSE; + DBG_ERROR( "Feature, Len != 1" ); + } + } + return bOK; +#else + return TRUE; +#endif +} + + + +SvxFontTable::SvxFontTable() +{ +} + +SvxFontTable::~SvxFontTable() +{ + SvxFontItem* pItem = First(); + while( pItem ) + { + delete pItem; + pItem = Next(); + } +} + +ULONG SvxFontTable::GetId( const SvxFontItem& rFontItem ) +{ + SvxFontItem* pItem = First(); + while ( pItem ) + { + if ( *pItem == rFontItem ) + return GetCurKey(); + pItem = Next(); + } + DBG_WARNING( "Font nicht gefunden: GetId()" ); + return 0; +} + +SvxColorList::SvxColorList() +{ +} + +SvxColorList::~SvxColorList() +{ + SvxColorItem* pItem = First(); + while( pItem ) + { + delete pItem; + pItem = Next(); + } +} + +ULONG SvxColorList::GetId( const SvxColorItem& rColorItem ) +{ + SvxColorItem* pItem = First(); + while ( pItem ) + { + if ( *pItem == rColorItem ) + return GetCurPos(); + pItem = Next(); + } + DBG_WARNING( "Color nicht gefunden: GetId()" ); + return 0; +} + +EditEngineItemPool::EditEngineItemPool( BOOL bPersistenRefCounts ) + : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END, + aItemInfos, 0, bPersistenRefCounts ) +{ + SetVersionMap( 1, 3999, 4015, aV1Map ); + SetVersionMap( 2, 3999, 4019, aV2Map ); + SetVersionMap( 3, 3997, 4020, aV3Map ); + SetVersionMap( 4, 3994, 4022, aV4Map ); + SetVersionMap( 5, 3994, 4037, aV5Map ); + + DBG_ASSERT( EE_DLL(), "EditDLL?!" ); + SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems(); + SetDefaults( ppDefItems ); +} + +EditEngineItemPool::~EditEngineItemPool() +{ +} + +SvStream& EditEngineItemPool::Store( SvStream& rStream ) const +{ + // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im + // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar. + + // Der eingestellte Range muss nach Store erhalten bleiben, weil dann + // erst die ItemSets gespeichert werden... + + long nVersion = rStream.GetVersion(); + BOOL b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) ) + ? TRUE : FALSE; + + EditEngineItemPool* pThis = (EditEngineItemPool*)this; + if ( b31Format ) + pThis->SetStoringRange( 3997, 4022 ); + else + pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END ); + + return SfxItemPool::Store( rStream ); +} diff --git a/editeng/source/editeng/editdoc.hxx b/editeng/source/editeng/editdoc.hxx new file mode 100644 index 0000000000..e95e08063e --- /dev/null +++ b/editeng/source/editeng/editdoc.hxx @@ -0,0 +1,805 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editdoc.hxx,v $ + * $Revision: 1.29 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EDITDOC_HXX +#define _EDITDOC_HXX + +#ifndef _COM_SUN_STAR_I18N_XEXTENDEDINPUTSEQUENCECHECKER_HDL_ +#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp> +#endif + +#include <editattr.hxx> +#include <edtspell.hxx> +#include <editeng/svxfont.hxx> +#include <svl/itemset.hxx> +#include <svl/style.hxx> +#include <svl/itempool.hxx> +#include <tools/table.hxx> + +class ImpEditEngine; +class SvxTabStop; +class SvtCTLOptions; + +DBG_NAMEEX( EE_TextPortion ) + +#define CHARPOSGROW 16 +#define DEFTAB 720 + +void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent = true, short nScriptType = 0 ); +USHORT GetScriptItemId( USHORT nItemId, short nScriptType ); +BOOL IsScriptItemValid( USHORT nItemId, short nScriptType ); + +EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, USHORT nS, USHORT nE ); + +class ContentNode; +class EditDoc; + +struct EPaM +{ + USHORT nPara; + USHORT nIndex; + + EPaM() { nPara = 0; nIndex = 0; } + EPaM( USHORT nP, USHORT nI ) { nPara = nP; nIndex = nI; } + EPaM( const EPaM& r) { nPara = r.nPara; nIndex = r.nIndex; } + EPaM& operator = ( const EPaM& r ) { nPara = r.nPara; nIndex = r.nIndex; return *this; } + inline BOOL operator == ( const EPaM& r ) const; + inline BOOL operator < ( const EPaM& r ) const; +}; + +inline BOOL EPaM::operator < ( const EPaM& r ) const +{ + return ( ( nPara < r.nPara ) || + ( ( nPara == r.nPara ) && nIndex < r.nIndex ) ) ? TRUE : FALSE; +} + +inline BOOL EPaM::operator == ( const EPaM& r ) const +{ + return ( ( nPara == r.nPara ) && ( nIndex == r.nIndex ) ) ? TRUE : FALSE; +} + +struct ScriptTypePosInfo +{ + short nScriptType; + USHORT nStartPos; + USHORT nEndPos; + + ScriptTypePosInfo( short _Type, USHORT _Start, USHORT _End ) + { + nScriptType = _Type; + nStartPos = _Start; + nEndPos = _End; + } +}; + +SV_DECL_VARARR( ScriptTypePosInfos, ScriptTypePosInfo, 0, 4 ) + +struct WritingDirectionInfo +{ + BYTE nType; + USHORT nStartPos; + USHORT nEndPos; + + WritingDirectionInfo( BYTE _Type, USHORT _Start, USHORT _End ) + { + nType = _Type; + nStartPos = _Start; + nEndPos = _End; + } +}; + +SV_DECL_VARARR( WritingDirectionInfos, WritingDirectionInfo, 0, 4 ) + +typedef EditCharAttrib* EditCharAttribPtr; +SV_DECL_PTRARR( CharAttribArray, EditCharAttribPtr, 0, 4 ) + +class ContentAttribsInfo +{ +private: + SfxItemSet aPrevParaAttribs; + CharAttribArray aPrevCharAttribs; + +public: + ContentAttribsInfo( const SfxItemSet& rParaAttribs ); + + const SfxItemSet& GetPrevParaAttribs() const { return aPrevParaAttribs; } + const CharAttribArray& GetPrevCharAttribs() const { return aPrevCharAttribs; } + + CharAttribArray& GetPrevCharAttribs() { return aPrevCharAttribs; } +}; + +typedef ContentAttribsInfo* ContentAttribsInfoPtr; +SV_DECL_PTRARR( ContentInfoArray, ContentAttribsInfoPtr, 1, 1 ) + +// ---------------------------------------------------------------------- +// class SvxFontTable +// ---------------------------------------------------------------------- +DECLARE_TABLE( DummyFontTable, SvxFontItem* ) +class SvxFontTable : public DummyFontTable +{ +public: + SvxFontTable(); + ~SvxFontTable(); + + ULONG GetId( const SvxFontItem& rFont ); +}; + +// ---------------------------------------------------------------------- +// class SvxColorList +// ---------------------------------------------------------------------- +typedef ContentNode* ContentNodePtr; +DECLARE_LIST( DummyColorList, SvxColorItem* ) +class SvxColorList : public DummyColorList +{ +public: + SvxColorList(); + ~SvxColorList(); + + ULONG GetId( const SvxColorItem& rColor ); +}; + +// ---------------------------------------------------------------------- +// class ItemList +// ---------------------------------------------------------------------- +typedef const SfxPoolItem* ConstPoolItemPtr; +DECLARE_LIST( DummyItemList, ConstPoolItemPtr ) +class ItemList : public DummyItemList +{ +public: + const SfxPoolItem* FindAttrib( USHORT nWhich ); +}; + +// ------------------------------------------------------------------------- +// class ContentAttribs +// ------------------------------------------------------------------------- +class ContentAttribs +{ +private: + SfxStyleSheet* pStyle; + SfxItemSet aAttribSet; + +public: + ContentAttribs( SfxItemPool& rItemPool ); + ContentAttribs( const ContentAttribs& ); + ~ContentAttribs(); // erst bei umfangreicheren Tabs + + SvxTabStop FindTabStop( long nCurPos, USHORT nDefTab ); + SfxItemSet& GetItems() { return aAttribSet; } + SfxStyleSheet* GetStyleSheet() const { return pStyle; } + void SetStyleSheet( SfxStyleSheet* pS ); + + const SfxPoolItem& GetItem( USHORT nWhich ); + BOOL HasItem( USHORT nWhich ); +}; + +// ------------------------------------------------------------------------- +// class CharAttribList +// ------------------------------------------------------------------------- +class CharAttribList +{ +private: + CharAttribArray aAttribs; + SvxFont aDefFont; // schneller, als jedesmal vom Pool! + BOOL bHasEmptyAttribs; + + CharAttribList( const CharAttribList& ) {;} + +public: + CharAttribList(); + ~CharAttribList(); + + void DeleteEmptyAttribs( SfxItemPool& rItemPool ); + void RemoveItemsFromPool( SfxItemPool* pItemPool ); + + EditCharAttrib* FindAttrib( USHORT nWhich, USHORT nPos ); + EditCharAttrib* FindNextAttrib( USHORT nWhich, USHORT nFromPos ) const; + EditCharAttrib* FindEmptyAttrib( USHORT nWhich, USHORT nPos ); + EditCharAttrib* FindFeature( USHORT nPos ) const; + + + void ResortAttribs(); + void OptimizeRanges( SfxItemPool& rItemPool ); + + USHORT Count() { return aAttribs.Count(); } + void Clear() { aAttribs.Remove( 0, aAttribs.Count()); } + void InsertAttrib( EditCharAttrib* pAttrib ); + + SvxFont& GetDefFont() { return aDefFont; } + + BOOL HasEmptyAttribs() const { return bHasEmptyAttribs; } + BOOL& HasEmptyAttribs() { return bHasEmptyAttribs; } + BOOL HasBoundingAttrib( USHORT nBound ); + BOOL HasAttrib( USHORT nWhich ) const; + BOOL HasAttrib( USHORT nStartPos, USHORT nEndPos ) const; + + CharAttribArray& GetAttribs() { return aAttribs; } + const CharAttribArray& GetAttribs() const { return aAttribs; } + + // Debug: + BOOL DbgCheckAttribs(); +}; + +// ------------------------------------------------------------------------- +// class ContentNode +// ------------------------------------------------------------------------- +class ContentNode : public XubString +{ +private: + ContentAttribs aContentAttribs; + CharAttribList aCharAttribList; + WrongList* pWrongList; + +public: + ContentNode( SfxItemPool& rItemPool ); + ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ); + ~ContentNode(); + + ContentAttribs& GetContentAttribs() { return aContentAttribs; } + CharAttribList& GetCharAttribs() { return aCharAttribList; } + + void ExpandAttribs( USHORT nIndex, USHORT nNewChars, SfxItemPool& rItemPool ); + void CollapsAttribs( USHORT nIndex, USHORT nDelChars, SfxItemPool& rItemPool ); + void AppendAttribs( ContentNode* pNextNode ); + void CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, BOOL bKeepEndingAttribs ); + + void SetStyleSheet( SfxStyleSheet* pS, BOOL bRecalcFont = TRUE ); + void SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ); + SfxStyleSheet* GetStyleSheet() { return aContentAttribs.GetStyleSheet(); } + + void CreateDefFont(); + + WrongList* GetWrongList() { return pWrongList; } + void SetWrongList( WrongList* p ); + + void CreateWrongList(); + void DestroyWrongList(); + + BOOL IsFeature( USHORT nPos ) const { return ( GetChar( nPos ) == CH_FEATURE ); } +}; + +typedef ContentNode* ContentNodePtr; +SV_DECL_PTRARR( DummyContentList, ContentNodePtr, 0, 4 ) + +class ContentList : public DummyContentList +{ + USHORT nLastCache; +public: + ContentList() : DummyContentList( 0, 4 ), nLastCache(0) {} + USHORT GetPos( const ContentNodePtr &rPtr ) const; +}; + +// ------------------------------------------------------------------------- +// class EditPaM +// ------------------------------------------------------------------------- +class EditPaM +{ +private: + ContentNode* pNode; + USHORT nIndex; + +public: + EditPaM() { pNode = NULL; nIndex = 0; } + EditPaM( ContentNode* p, USHORT n ) { pNode = p; nIndex = n; } + + ContentNode* GetNode() const { return pNode; } + void SetNode( ContentNode* p) { pNode = p; } + + USHORT GetIndex() const { return nIndex; } + USHORT& GetIndex() { return nIndex; } + void SetIndex( USHORT n ) { nIndex = n; } + + BOOL IsParaStart() const { return nIndex == 0; } + BOOL IsParaEnd() const { return nIndex == pNode->Len(); } + + BOOL DbgIsBuggy( EditDoc& rDoc ); + + EditPaM& operator = ( const EditPaM& rPaM ); + friend BOOL operator == ( const EditPaM& r1, const EditPaM& r2 ); + friend BOOL operator != ( const EditPaM& r1, const EditPaM& r2 ); +}; + +#define PORTIONKIND_TEXT 0 +#define PORTIONKIND_TAB 1 +#define PORTIONKIND_LINEBREAK 2 +#define PORTIONKIND_FIELD 3 +#define PORTIONKIND_HYPHENATOR 4 +// #define PORTIONKIND_EXTRASPACE 5 + +#define DELMODE_SIMPLE 0 +#define DELMODE_RESTOFWORD 1 +#define DELMODE_RESTOFCONTENT 2 + +#define CHAR_NORMAL 0x00 +#define CHAR_KANA 0x01 +#define CHAR_PUNCTUATIONLEFT 0x02 +#define CHAR_PUNCTUATIONRIGHT 0x04 + +// ------------------------------------------------------------------------- +// struct ExtraPortionInfos +// ------------------------------------------------------------------------- +struct ExtraPortionInfo +{ + long nOrgWidth; + long nWidthFullCompression; + + long nPortionOffsetX; + + USHORT nMaxCompression100thPercent; + + BYTE nAsianCompressionTypes; + BOOL bFirstCharIsRightPunktuation; + BOOL bCompressed; + + sal_Int32* pOrgDXArray; + + + ExtraPortionInfo(); + ~ExtraPortionInfo(); + + void SaveOrgDXArray( const sal_Int32* pDXArray, USHORT nLen ); + void DestroyOrgDXArray(); +}; + + +// ------------------------------------------------------------------------- +// class TextPortion +// ------------------------------------------------------------------------- +class TextPortion +{ +private: + ExtraPortionInfo* pExtraInfos; + USHORT nLen; + Size aOutSz; + BYTE nKind; + BYTE nRightToLeft; + sal_Unicode nExtraValue; + + + TextPortion() { DBG_CTOR( EE_TextPortion, 0 ); + pExtraInfos = NULL; nLen = 0; nKind = PORTIONKIND_TEXT; nExtraValue = 0; nRightToLeft = FALSE;} + +public: + TextPortion( USHORT nL ) : aOutSz( -1, -1 ) + { DBG_CTOR( EE_TextPortion, 0 ); + pExtraInfos = NULL; nLen = nL; nKind = PORTIONKIND_TEXT; nExtraValue = 0; nRightToLeft = FALSE;} + TextPortion( const TextPortion& r ) : aOutSz( r.aOutSz ) + { DBG_CTOR( EE_TextPortion, 0 ); + pExtraInfos = NULL; nLen = r.nLen; nKind = r.nKind; nExtraValue = r.nExtraValue; nRightToLeft = r.nRightToLeft; } + + ~TextPortion() { DBG_DTOR( EE_TextPortion, 0 ); delete pExtraInfos; } + + USHORT GetLen() const { return nLen; } + USHORT& GetLen() { return nLen; } + void SetLen( USHORT nL ) { nLen = nL; } + + Size& GetSize() { return aOutSz; } + Size GetSize() const { return aOutSz; } + + BYTE& GetKind() { return nKind; } + BYTE GetKind() const { return nKind; } + + void SetRightToLeft( BYTE b ) { nRightToLeft = b; } + BYTE GetRightToLeft() const { return nRightToLeft; } + BOOL IsRightToLeft() const { return (nRightToLeft&1); } + + sal_Unicode GetExtraValue() const { return nExtraValue; } + void SetExtraValue( sal_Unicode n ) { nExtraValue = n; } + + BOOL HasValidSize() const { return aOutSz.Width() != (-1); } + + ExtraPortionInfo* GetExtraInfos() const { return pExtraInfos; } + void SetExtraInfos( ExtraPortionInfo* p ) { delete pExtraInfos; pExtraInfos = p; } +}; + +// ------------------------------------------------------------------------- +// class TextPortionList +// ------------------------------------------------------------------------- +typedef TextPortion* TextPortionPtr; +SV_DECL_PTRARR( TextPortionArray, TextPortionPtr, 0, 8 ) + +class TextPortionList : public TextPortionArray +{ +public: + TextPortionList(); + ~TextPortionList(); + + void Reset(); + USHORT FindPortion( USHORT nCharPos, USHORT& rPortionStart, BOOL bPreferStartingPortion = FALSE ); + USHORT GetStartPos( USHORT nPortion ); + void DeleteFromPortion( USHORT nDelFrom ); +}; + +class ParaPortion; + +SV_DECL_VARARR( CharPosArray, sal_Int32, 0, CHARPOSGROW ) + +// ------------------------------------------------------------------------ +// class EditLine +// ------------------------------------------------------------------------- +class EditLine +{ +private: + CharPosArray aPositions; + long nTxtWidth; + USHORT nStartPosX; + USHORT nStart; // koennte durch nStartPortion ersetzt werden + USHORT nEnd; // koennte durch nEndPortion ersetzt werden + USHORT nStartPortion; + USHORT nEndPortion; + USHORT nHeight; // Gesamthoehe der Zeile + USHORT nTxtHeight; // Reine Texthoehe + USHORT nCrsrHeight; // Bei Konturfluss hohe Zeilen => Cursor zu groá. + USHORT nMaxAscent; + BOOL bHangingPunctuation; + BOOL bInvalid; // fuer geschickte Formatierung + +public: + EditLine(); + EditLine( const EditLine& ); + ~EditLine(); + + BOOL IsIn( USHORT nIndex ) const + { return ( (nIndex >= nStart ) && ( nIndex < nEnd ) ); } + + BOOL IsIn( USHORT nIndex, BOOL bInclEnd ) const + { return ( ( nIndex >= nStart ) && ( bInclEnd ? ( nIndex <= nEnd ) : ( nIndex < nEnd ) ) ); } + + void SetStart( USHORT n ) { nStart = n; } + USHORT GetStart() const { return nStart; } + USHORT& GetStart() { return nStart; } + + void SetEnd( USHORT n ) { nEnd = n; } + USHORT GetEnd() const { return nEnd; } + USHORT& GetEnd() { return nEnd; } + + void SetStartPortion( USHORT n ) { nStartPortion = n; } + USHORT GetStartPortion() const { return nStartPortion; } + USHORT& GetStartPortion() { return nStartPortion; } + + void SetEndPortion( USHORT n ) { nEndPortion = n; } + USHORT GetEndPortion() const { return nEndPortion; } + USHORT& GetEndPortion() { return nEndPortion; } + + void SetHeight( USHORT nH, USHORT nTxtH = 0, USHORT nCrsrH = 0 ) + { nHeight = nH; + nTxtHeight = ( nTxtH ? nTxtH : nH ); + nCrsrHeight = ( nCrsrH ? nCrsrH : nTxtHeight ); + } + USHORT GetHeight() const { return nHeight; } + USHORT GetTxtHeight() const { return nTxtHeight; } + USHORT GetCrsrHeight() const { return nCrsrHeight; } + + void SetTextWidth( long n ) { nTxtWidth = n; } + long GetTextWidth() const { return nTxtWidth; } + + void SetMaxAscent( USHORT n ) { nMaxAscent = n; } + USHORT GetMaxAscent() const { return nMaxAscent; } + + void SetHangingPunctuation( BOOL b ) { bHangingPunctuation = b; } + BOOL IsHangingPunctuation() const { return bHangingPunctuation; } + + USHORT GetLen() const { return nEnd - nStart; } + + USHORT GetStartPosX() const { return nStartPosX; } + void SetStartPosX( USHORT start ) { nStartPosX = start; } + + Size CalcTextSize( ParaPortion& rParaPortion ); + + BOOL IsInvalid() const { return bInvalid; } + BOOL IsValid() const { return !bInvalid; } + void SetInvalid() { bInvalid = TRUE; } + void SetValid() { bInvalid = FALSE; } + + BOOL IsEmpty() const { return (nEnd > nStart) ? FALSE : TRUE; } + + CharPosArray& GetCharPosArray() { return aPositions; } + + EditLine* Clone() const; + + EditLine& operator = ( const EditLine& rLine ); + friend BOOL operator == ( const EditLine& r1, const EditLine& r2 ); + friend BOOL operator != ( const EditLine& r1, const EditLine& r2 ); +}; + + +// ------------------------------------------------------------------------- +// class LineList +// ------------------------------------------------------------------------- +typedef EditLine* EditLinePtr; +SV_DECL_PTRARR( LineArray, EditLinePtr, 0, 4 ) + +class EditLineList : public LineArray +{ +public: + EditLineList(); + ~EditLineList(); + + void Reset(); + void DeleteFromLine( USHORT nDelFrom ); + USHORT FindLine( USHORT nChar, BOOL bInclEnd ); +}; + +// ------------------------------------------------------------------------- +// class ParaPortion +// ------------------------------------------------------------------------- +class ParaPortion +{ + friend class ImpEditEngine; // zum Einstellen der Hoehe +private: + EditLineList aLineList; + TextPortionList aTextPortionList; + ContentNode* pNode; + long nHeight; + + ScriptTypePosInfos aScriptInfos; + WritingDirectionInfos aWritingDirectionInfos; + + USHORT nInvalidPosStart; + USHORT nFirstLineOffset; // Fuer Writer-LineSpacing-Interpretation + USHORT nBulletX; + short nInvalidDiff; + + BOOL bInvalid : 1; + BOOL bSimple : 1; // nur lineares Tippen + BOOL bVisible : 1; // MT 05/00: Gehoert an den Node!!! + BOOL bForceRepaint : 1; + + ParaPortion( const ParaPortion& ); + +public: + ParaPortion( ContentNode* pNode ); + ~ParaPortion(); + + USHORT GetLineNumber( USHORT nIndex ); + + EditLineList& GetLines() { return aLineList; } + + BOOL IsInvalid() const { return bInvalid; } + BOOL IsSimpleInvalid() const { return bSimple; } + void SetValid() { bInvalid = FALSE; bSimple = TRUE;} + + BOOL MustRepaint() const { return bForceRepaint; } + void SetMustRepaint( BOOL bRP ) { bForceRepaint = bRP; } + + USHORT GetBulletX() const { return nBulletX; } + void SetBulletX( USHORT n ) { nBulletX = n; } + + void MarkInvalid( USHORT nStart, short nDiff); + void MarkSelectionInvalid( USHORT nStart, USHORT nEnd ); + + void SetVisible( BOOL bVisible ); + BOOL IsVisible() { return bVisible; } + + long GetHeight() const { return ( bVisible ? nHeight : 0 ); } + USHORT GetFirstLineOffset() const { return ( bVisible ? nFirstLineOffset : 0 ); } + void ResetHeight() { nHeight = 0; nFirstLineOffset = 0; } + + ContentNode* GetNode() const { return pNode; } + TextPortionList& GetTextPortions() { return aTextPortionList; } + + USHORT GetInvalidPosStart() const { return nInvalidPosStart; } + short GetInvalidDiff() const { return nInvalidDiff; } + + void CorrectValuesBehindLastFormattedLine( USHORT nLastFormattedLine ); + + BOOL DbgCheckTextPortions(); +}; + +typedef ParaPortion* ParaPortionPtr; +SV_DECL_PTRARR( DummyParaPortionList, ParaPortionPtr, 0, 4 ) + +// ------------------------------------------------------------------------- +// class ParaPortionList +// ------------------------------------------------------------------------- +class ParaPortionList : public DummyParaPortionList +{ + USHORT nLastCache; +public: + ParaPortionList(); + ~ParaPortionList(); + + void Reset(); + long GetYOffset( ParaPortion* pPPortion ); + USHORT FindParagraph( long nYOffset ); + + inline ParaPortion* SaveGetObject( USHORT nPos ) const + { return ( nPos < Count() ) ? GetObject( nPos ) : 0; } + + USHORT GetPos( const ParaPortionPtr &rPtr ) const; + + // temporaer: + void DbgCheck( EditDoc& rDoc ); +}; + +// ------------------------------------------------------------------------- +// class EditSelection +// ------------------------------------------------------------------------- +class EditSelection +{ +private: + EditPaM aStartPaM; + EditPaM aEndPaM; + +public: + EditSelection(); // kein CCTOR und DTOR, geht autom. richtig! + EditSelection( const EditPaM& rStartAndAnd ); + EditSelection( const EditPaM& rStart, const EditPaM& rEnd ); + + EditPaM& Min() { return aStartPaM; } + EditPaM& Max() { return aEndPaM; } + + const EditPaM& Min() const { return aStartPaM; } + const EditPaM& Max() const { return aEndPaM; } + + BOOL HasRange() const { return aStartPaM != aEndPaM; } + BOOL IsInvalid() const; + BOOL DbgIsBuggy( EditDoc& rDoc ); + + BOOL Adjust( const ContentList& rNodes ); + + EditSelection& operator = ( const EditPaM& r ); + BOOL operator == ( const EditSelection& r ) const + { return ( ( aStartPaM == r.aStartPaM ) && ( aEndPaM == r.aEndPaM ) ) + ? TRUE : FALSE; } + BOOL operator != ( const EditSelection& r ) const { return !( r == *this ); } +}; + +// ------------------------------------------------------------------------- +// class DeletedNodeInfo +// ------------------------------------------------------------------------- +class DeletedNodeInfo +{ +private: + ULONG nInvalidAdressPtr; + USHORT nInvalidParagraph; + +public: + DeletedNodeInfo( ULONG nInvAdr, USHORT nPos ) + { nInvalidAdressPtr = nInvAdr; + nInvalidParagraph = nPos; } + + ULONG GetInvalidAdress() { return nInvalidAdressPtr; } + USHORT GetPosition() { return nInvalidParagraph; } +}; + +typedef DeletedNodeInfo* DeletedNodeInfoPtr; +SV_DECL_PTRARR( DeletedNodesList, DeletedNodeInfoPtr, 0, 4 ) + +// ------------------------------------------------------------------------- +// class EditDoc +// ------------------------------------------------------------------------- +class EditDoc : public ContentList +{ +private: + SfxItemPool* pItemPool; + Link aModifyHdl; + + SvxFont aDefFont; //schneller, als jedesmal vom Pool! + USHORT nDefTab; + BOOL bIsVertical; + BOOL bIsFixedCellHeight; + + BOOL bOwnerOfPool; + BOOL bModified; + +protected: + void ImplDestroyContents(); + +public: + EditDoc( SfxItemPool* pItemPool ); + ~EditDoc(); + + BOOL IsModified() const { return bModified; } + void SetModified( BOOL b ); + + void SetModifyHdl( const Link& rLink ) { aModifyHdl = rLink; } + Link GetModifyHdl() const { return aModifyHdl; } + + void CreateDefFont( BOOL bUseStyles ); + const SvxFont& GetDefFont() { return aDefFont; } + + void SetDefTab( USHORT nTab ) { nDefTab = nTab ? nTab : DEFTAB; } + USHORT GetDefTab() const { return nDefTab; } + + void SetVertical( BOOL bVertical ) { bIsVertical = bVertical; } + BOOL IsVertical() const { return bIsVertical; } + + void SetFixedCellHeight( BOOL bUseFixedCellHeight ) { bIsFixedCellHeight = bUseFixedCellHeight; } + BOOL IsFixedCellHeight() const { return bIsFixedCellHeight; } + + EditPaM Clear(); + EditPaM RemoveText(); + EditPaM RemoveChars( EditPaM aPaM, USHORT nChars ); + void InsertText( const EditPaM& rPaM, xub_Unicode c ); + EditPaM InsertText( EditPaM aPaM, const XubString& rStr ); + EditPaM InsertParaBreak( EditPaM aPaM, BOOL bKeepEndingAttribs ); + EditPaM InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ); + EditPaM ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ); + + String GetText( LineEnd eEnd ) const; + ULONG GetTextLen() const; + + XubString GetParaAsString( USHORT nNode ) const; + XubString GetParaAsString( ContentNode* pNode, USHORT nStartPos = 0, USHORT nEndPos = 0xFFFF, BOOL bResolveFields = TRUE ) const; + + inline EditPaM GetStartPaM() const; + inline EditPaM GetEndPaM() const; + + SfxItemPool& GetItemPool() { return *pItemPool; } + const SfxItemPool& GetItemPool() const { return *pItemPool; } + + void RemoveItemsFromPool( ContentNode* pNode ); + + void InsertAttrib( const SfxPoolItem& rItem, ContentNode* pNode, USHORT nStart, USHORT nEnd ); + void InsertAttrib( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem ); + void InsertAttribInSelection( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem ); + BOOL RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, USHORT nWhich = 0 ); + BOOL RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, USHORT nWhich = 0 ); + void FindAttribs( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet ); + + USHORT GetPos( ContentNode* pNode ) const { return ContentList::GetPos(pNode); } + ContentNode* SaveGetObject( USHORT nPos ) const { return ( nPos < Count() ) ? GetObject( nPos ) : 0; } + + static XubString GetSepStr( LineEnd eEnd ); +}; + +inline EditPaM EditDoc::GetStartPaM() const +{ + return EditPaM( GetObject( 0 ), 0 ); +} + +inline EditPaM EditDoc::GetEndPaM() const +{ + ContentNode* pLastNode = GetObject( Count()-1 ); + return EditPaM( pLastNode, pLastNode->Len() ); +} + +inline EditCharAttrib* GetAttrib( const CharAttribArray& rAttribs, USHORT nAttr ) +{ + return ( nAttr < rAttribs.Count() ) ? rAttribs[nAttr] : 0; +} + +BOOL CheckOrderedList( CharAttribArray& rAttribs, BOOL bStart ); + +// ------------------------------------------------------------------------- +// class EditEngineItemPool +// ------------------------------------------------------------------------- +class EditEngineItemPool : public SfxItemPool +{ +public: + EditEngineItemPool( BOOL bPersistenRefCounts ); +protected: + virtual ~EditEngineItemPool(); +public: + + virtual SvStream& Store( SvStream& rStream ) const; +}; + +#endif // _EDITDOC_HXX diff --git a/editeng/source/editeng/editdoc2.cxx b/editeng/source/editeng/editdoc2.cxx new file mode 100644 index 0000000000..00fe509a19 --- /dev/null +++ b/editeng/source/editeng/editdoc2.cxx @@ -0,0 +1,547 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editdoc2.cxx,v $ + * $Revision: 1.19 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <svl/smplhint.hxx> + +#include <tools/rtti.hxx> +#include <editeng/lspcitem.hxx> +#include <editeng/adjitem.hxx> +#include <editeng/tstpitem.hxx> + +#include <editdoc.hxx> +#include <impedit.hxx> +#include <editdbg.hxx> + +#include <editeng/numitem.hxx> + +#include <editeng/akrnitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/charscaleitem.hxx> + +#include <vcl/svapp.hxx> // Fuer AppWindow... + +DBG_NAME( EE_ParaPortion ) + +SV_IMPL_VARARR( CharPosArray, sal_Int32 ); + +/* + +BOOL EditStyleSheet::HasStyleAsAnyParent( SfxStyleSheet& rStyle ) +{ + if ( GetParent() == rStyle.GetName() ) + return TRUE; + + if ( GetParent().Len() && ( GetParent() != GetName() ) ) + { + EditStyleSheet* pS = (EditStyleSheet*)GetPool().Find( GetParent(), rStyle.GetFamily() ); + if ( pS ) + return pS->HasStyleAsAnyParent( rStyle ); + } + return FALSE; +} + +*/ + +// ------------------------------------------------------------------------- +// class TextPortionList +// ------------------------------------------------------------------------- +TextPortionList::TextPortionList() +{ +} + +TextPortionList::~TextPortionList() +{ + Reset(); +} + +void TextPortionList::Reset() +{ + for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ ) + delete GetObject( nPortion ); + Remove( 0, Count() ); +} + +void TextPortionList::DeleteFromPortion( USHORT nDelFrom ) +{ + DBG_ASSERT( ( nDelFrom < Count() ) || ( (nDelFrom == 0) && (Count() == 0) ), "DeleteFromPortion: Out of range" ); + for ( USHORT nP = nDelFrom; nP < Count(); nP++ ) + delete GetObject( nP ); + Remove( nDelFrom, Count()-nDelFrom ); +} + +USHORT TextPortionList::FindPortion( USHORT nCharPos, USHORT& nPortionStart, BOOL bPreferStartingPortion ) +{ + // Bei nCharPos an Portion-Grenze wird die linke Portion gefunden + USHORT nTmpPos = 0; + for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ ) + { + TextPortion* pPortion = GetObject( nPortion ); + nTmpPos = nTmpPos + pPortion->GetLen(); + if ( nTmpPos >= nCharPos ) + { + // take this one if we don't prefer the starting portion, or if it's the last one + if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( nPortion == Count() - 1 ) ) + { + nPortionStart = nTmpPos - pPortion->GetLen(); + return nPortion; + } + } + } + DBG_ERROR( "FindPortion: Nicht gefunden!" ); + return ( Count() - 1 ); +} + +USHORT TextPortionList::GetStartPos( USHORT nPortion ) +{ + USHORT nPos = 0; + for ( USHORT n = 0; n < nPortion; n++ ) + { + TextPortion* pPortion = GetObject( n ); + nPos = nPos + pPortion->GetLen(); + } + return nPos; +} + + +// ------------------------------------------------------------------------- +// class ExtraPortionInfo +// ------------------------------------------------------------------------- + +ExtraPortionInfo::ExtraPortionInfo() +{ + nOrgWidth = 0; + nWidthFullCompression = 0; + nMaxCompression100thPercent = 0; + nAsianCompressionTypes = 0; + nPortionOffsetX = 0; + bFirstCharIsRightPunktuation = FALSE; + bCompressed = FALSE; + pOrgDXArray = NULL; +} + +ExtraPortionInfo::~ExtraPortionInfo() +{ + delete[] pOrgDXArray; +} + +void ExtraPortionInfo::SaveOrgDXArray( const sal_Int32* pDXArray, USHORT nLen ) +{ + delete[] pOrgDXArray; + pOrgDXArray = new sal_Int32[nLen]; + memcpy( pOrgDXArray, pDXArray, nLen*sizeof(sal_Int32) ); +} + +void ExtraPortionInfo::DestroyOrgDXArray() +{ + delete[] pOrgDXArray; + pOrgDXArray = NULL; +} + + +// ------------------------------------------------------------------------- +// class ParaPortion +// ------------------------------------------------------------------------- +ParaPortion::ParaPortion( ContentNode* pN ) +{ + DBG_CTOR( EE_ParaPortion, 0 ); + + pNode = pN; + bInvalid = TRUE; + bVisible = TRUE; + bSimple = FALSE; + bForceRepaint = FALSE; + nInvalidPosStart = 0; + nInvalidDiff = 0; + nHeight = 0; + nFirstLineOffset = 0; + nBulletX = 0; +} + +ParaPortion::~ParaPortion() +{ + DBG_DTOR( EE_ParaPortion, 0 ); +} + +void ParaPortion::MarkInvalid( USHORT nStart, short nDiff ) +{ + if ( bInvalid == FALSE ) + { +// nInvalidPosEnd = nStart; // ??? => CreateLines + nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); + nInvalidDiff = nDiff; + } + else + { + // Einfaches hintereinander tippen + if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) && + ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) ) + { + nInvalidDiff = nInvalidDiff + nDiff; + } + // Einfaches hintereinander loeschen + else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) ) + { + nInvalidPosStart = nInvalidPosStart + nDiff; + nInvalidDiff = nInvalidDiff + nDiff; + } + else + { +// nInvalidPosEnd = pNode->Len(); + DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); + nInvalidPosStart = Min( nInvalidPosStart, (USHORT) ( nDiff < 0 ? nStart+nDiff : nDiff ) ); + nInvalidDiff = 0; + bSimple = FALSE; + } + } + bInvalid = TRUE; + aScriptInfos.Remove( 0, aScriptInfos.Count() ); + aWritingDirectionInfos.Remove( 0, aWritingDirectionInfos.Count() ); +// aExtraCharInfos.Remove( 0, aExtraCharInfos.Count() ); +} + +void ParaPortion::MarkSelectionInvalid( USHORT nStart, USHORT /* nEnd */ ) +{ + if ( bInvalid == FALSE ) + { + nInvalidPosStart = nStart; +// nInvalidPosEnd = nEnd; + } + else + { + nInvalidPosStart = Min( nInvalidPosStart, nStart ); +// nInvalidPosEnd = pNode->Len(); + } + nInvalidDiff = 0; + bInvalid = TRUE; + bSimple = FALSE; + aScriptInfos.Remove( 0, aScriptInfos.Count() ); + aWritingDirectionInfos.Remove( 0, aWritingDirectionInfos.Count() ); +// aExtraCharInfos.Remove( 0, aExtraCharInfos.Count() ); +} + +USHORT ParaPortion::GetLineNumber( USHORT nIndex ) +{ + DBG_ASSERTWARNING( aLineList.Count(), "Leere ParaPortion in GetLine!" ); + DBG_ASSERT( bVisible, "Wozu GetLine() bei einem unsichtbaren Absatz?" ); + + for ( USHORT nLine = 0; nLine < aLineList.Count(); nLine++ ) + { + if ( aLineList[nLine]->IsIn( nIndex ) ) + return nLine; + } + + // Dann sollte es am Ende der letzten Zeile sein! + DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ]->GetEnd(), "Index voll daneben!" ); + return (aLineList.Count()-1); +} + +void ParaPortion::SetVisible( BOOL bMakeVisible ) +{ + bVisible = bMakeVisible; +} + +void ParaPortion::CorrectValuesBehindLastFormattedLine( USHORT nLastFormattedLine ) +{ + USHORT nLines = aLineList.Count(); + DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Leere Portion?" ); + if ( nLastFormattedLine < ( nLines - 1 ) ) + { + const EditLine* pLastFormatted = aLineList[ nLastFormattedLine ]; + const EditLine* pUnformatted = aLineList[ nLastFormattedLine+1 ]; + short nPortionDiff = pUnformatted->GetStartPortion() - pLastFormatted->GetEndPortion(); + short nTextDiff = pUnformatted->GetStart() - pLastFormatted->GetEnd(); + nTextDiff++; // LastFormatted->GetEnd() war incl. => 1 zuviel abgezogen! + + // Die erste unformatierte muss genau eine Portion hinter der letzten der + // formatierten beginnen: + // Wenn in der geaenderten Zeile eine Portion gesplittet wurde, + // kann nLastEnd > nNextStart sein! + int nPDiff = -( nPortionDiff-1 ); + int nTDiff = -( nTextDiff-1 ); + if ( nPDiff || nTDiff ) + { + for ( USHORT nL = nLastFormattedLine+1; nL < nLines; nL++ ) + { + EditLine* pLine = aLineList[ nL ]; + + pLine->GetStartPortion() = sal::static_int_cast< USHORT >( + pLine->GetStartPortion() + nPDiff); + pLine->GetEndPortion() = sal::static_int_cast< USHORT >( + pLine->GetEndPortion() + nPDiff); + + pLine->GetStart() = sal::static_int_cast< USHORT >( + pLine->GetStart() + nTDiff); + pLine->GetEnd() = sal::static_int_cast< USHORT >( + pLine->GetEnd() + nTDiff); + + pLine->SetValid(); + } + } + } + DBG_ASSERT( aLineList[ aLineList.Count()-1 ]->GetEnd() == pNode->Len(), "CorrectLines: Ende stimmt nicht!" ); +} + +// Shared reverse lookup acceleration pieces ... + +static USHORT FastGetPos( const VoidPtr *pPtrArray, USHORT nPtrArrayLen, + VoidPtr pPtr, USHORT &rLastPos ) +{ + // Through certain filter code-paths we do a lot of appends, which in + // turn call GetPos - creating some N^2 nightmares. If we have a + // non-trivially large list, do a few checks from the end first. + if( rLastPos > 16 ) + { + USHORT nEnd; + if (rLastPos > nPtrArrayLen - 2) + nEnd = nPtrArrayLen; + else + nEnd = rLastPos + 2; + + for( USHORT nIdx = rLastPos - 2; nIdx < nEnd; nIdx++ ) + { + if( pPtrArray[ nIdx ] == pPtr ) + { + rLastPos = nIdx; + return nIdx; + } + } + } + // The world's lamest linear search from svarray ... + for( USHORT nIdx = 0; nIdx < nPtrArrayLen; nIdx++ ) + if (pPtrArray[ nIdx ] == pPtr ) + return rLastPos = nIdx; + return USHRT_MAX; +} + +// ------------------------------------------------------------------------- +// class ParaPortionList +// ------------------------------------------------------------------------- +ParaPortionList::ParaPortionList() : nLastCache( 0 ) +{ +} + +ParaPortionList::~ParaPortionList() +{ + Reset(); +} + +USHORT ParaPortionList::GetPos( const ParaPortionPtr &rPtr ) const +{ + return FastGetPos( reinterpret_cast<const VoidPtr *>( GetData() ), + Count(), static_cast<VoidPtr>( rPtr ), + ((ParaPortionList *)this)->nLastCache ); +} + +USHORT ContentList::GetPos( const ContentNodePtr &rPtr ) const +{ + return FastGetPos( reinterpret_cast<const VoidPtr *>( GetData() ), + Count(), static_cast<VoidPtr>( rPtr ), + ((ContentList *)this)->nLastCache ); +} + +void ParaPortionList::Reset() +{ + for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ ) + delete GetObject( nPortion ); + Remove( 0, Count() ); +} + +long ParaPortionList::GetYOffset( ParaPortion* pPPortion ) +{ + long nHeight = 0; + for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ ) + { + ParaPortion* pTmpPortion = GetObject(nPortion); + if ( pTmpPortion == pPPortion ) + return nHeight; + nHeight += pTmpPortion->GetHeight(); + } + DBG_ERROR( "GetYOffset: Portion nicht gefunden" ); + return nHeight; +} + +USHORT ParaPortionList::FindParagraph( long nYOffset ) +{ + long nY = 0; + for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ ) + { + nY += GetObject(nPortion)->GetHeight(); // sollte auch bei !bVisible richtig sein! + if ( nY > nYOffset ) + return nPortion; + } + return 0xFFFF; // solte mal ueber EE_PARA_NOT_FOUND erreicht werden! +} + +void ParaPortionList::DbgCheck( EditDoc& +#ifdef DBG_UTIL + rDoc +#endif + ) +{ +#ifdef DBG_UTIL + DBG_ASSERT( Count() == rDoc.Count(), "ParaPortionList::DbgCheck() - Count() ungleich!" ); + for ( USHORT i = 0; i < Count(); i++ ) + { + DBG_ASSERT( SaveGetObject(i), "ParaPortionList::DbgCheck() - Null-Pointer in Liste!" ); + DBG_ASSERT( GetObject(i)->GetNode(), "ParaPortionList::DbgCheck() - Null-Pointer in Liste(2)!" ); + DBG_ASSERT( GetObject(i)->GetNode() == rDoc.GetObject(i), "ParaPortionList::DbgCheck() - Eintraege kreuzen sich!" ); + } +#endif +} + + +ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) : + aPrevParaAttribs( rParaAttribs) +{ +} + + +void ConvertItem( SfxPoolItem& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit ) +{ + DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" ); + + switch ( rPoolItem.Which() ) + { + case EE_PARA_LRSPACE: + { + DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLRSpaceItem ) ), "ConvertItem: Ungueltiges Item!" ); + SvxLRSpaceItem& rItem = (SvxLRSpaceItem&)rPoolItem; + rItem.SetTxtFirstLineOfst( sal::static_int_cast< short >( OutputDevice::LogicToLogic( rItem.GetTxtFirstLineOfst(), eSourceUnit, eDestUnit ) ) ); + rItem.SetTxtLeft( OutputDevice::LogicToLogic( rItem.GetTxtLeft(), eSourceUnit, eDestUnit ) ); +// rItem.SetLeft( OutputDevice::LogicToLogic( rItem.GetLeft(), eSourceUnit, eDestUnit ) ); // #96298# SetLeft manipulates nTxtLeft! + rItem.SetRight( OutputDevice::LogicToLogic( rItem.GetRight(), eSourceUnit, eDestUnit ) ); + } + break; + case EE_PARA_ULSPACE: + { + DBG_ASSERT( rPoolItem.IsA( TYPE( SvxULSpaceItem ) ), "ConvertItem: Ungueltiges Item!" ); + SvxULSpaceItem& rItem = (SvxULSpaceItem&)rPoolItem; + rItem.SetUpper( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) ); + rItem.SetLower( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) ); + } + break; + case EE_PARA_SBL: + { + DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLineSpacingItem ) ), "ConvertItem: Ungueltiges Item!" ); + SvxLineSpacingItem& rItem = (SvxLineSpacingItem&)rPoolItem; + // #96298# SetLineHeight changes also eLineSpace! + if ( rItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN ) + rItem.SetLineHeight( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) ); + } + break; + case EE_PARA_TABS: + { + DBG_ASSERT( rPoolItem.IsA( TYPE( SvxTabStopItem ) ), "ConvertItem: Ungueltiges Item!" ); + SvxTabStopItem& rItem = (SvxTabStopItem&)rPoolItem; + SvxTabStopItem aNewItem( EE_PARA_TABS ); + for ( USHORT i = 0; i < rItem.Count(); i++ ) + { + const SvxTabStop& rTab = rItem[i]; + SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() ); + aNewItem.Insert( aNewStop ); + } + rItem = aNewItem; + } + break; + case EE_CHAR_FONTHEIGHT: + case EE_CHAR_FONTHEIGHT_CJK: + case EE_CHAR_FONTHEIGHT_CTL: + { + DBG_ASSERT( rPoolItem.IsA( TYPE( SvxFontHeightItem ) ), "ConvertItem: Ungueltiges Item!" ); + SvxFontHeightItem& rItem = (SvxFontHeightItem&)rPoolItem; + rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) ); + } + break; + } +} + +void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit ) +{ + const SfxItemPool* pSourcePool = rSource.GetPool(); + const SfxItemPool* pDestPool = rDest.GetPool(); + + for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) + { + // Wenn moeglich ueber SlotID gehen... + + USHORT nSourceWhich = nWhich; + USHORT nSlot = pDestPool->GetTrueSlotId( nWhich ); + if ( nSlot ) + { + USHORT nW = pSourcePool->GetTrueWhich( nSlot ); + if ( nW ) + nSourceWhich = nW; + } + + if ( rSource.GetItemState( nSourceWhich, FALSE ) == SFX_ITEM_ON ) + { + MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : (MapUnit)pSourcePool->GetMetric( nSourceWhich ); + MapUnit eDestUnit = pDestUnit ? *pDestUnit : (MapUnit)pDestPool->GetMetric( nWhich ); + if ( eSourceUnit != eDestUnit ) + { + SfxPoolItem* pItem = rSource.Get( nSourceWhich ).Clone(); +// pItem->SetWhich( nWhich ); + ConvertItem( *pItem, eSourceUnit, eDestUnit ); + rDest.Put( *pItem, nWhich ); + delete pItem; + } + else + { + rDest.Put( rSource.Get( nSourceWhich ), nWhich ); + } + } + else + { + // MT 3.3.99: Waere so eigentlich richtig, aber schon seit Jahren nicht so... +// rDest.ClearItem( nWhich ); + } + } +} + diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx new file mode 100644 index 0000000000..9efdc6b2fe --- /dev/null +++ b/editeng/source/editeng/editeng.cxx @@ -0,0 +1,2944 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editeng.cxx,v $ + * $Revision: 1.117.12.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#define USE_SVXFONT + +#define _SVSTDARR_USHORTS +#include <svl/svstdarr.hxx> +#include <svl/ctloptions.hxx> +#include <svtools/ctrltool.hxx> + +#include <editeng/svxfont.hxx> +#include <impedit.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editstat.hxx> +#include <editdbg.hxx> +#include <eerdll2.hxx> +#include <editeng/eerdll.hxx> +#include <editeng.hrc> +#include <editeng/flditem.hxx> +#include <editeng/txtrange.hxx> +#include <vcl/graph.hxx> + +#include <editeng/akrnitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/cscoitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/emphitem.hxx> +#include <editeng/charscaleitem.hxx> +#include <editeng/charreliefitem.hxx> + +#include <sot/exchange.hxx> +#include <sot/formats.hxx> + +#include <editeng/numitem.hxx> +#include <editeng/bulitem.hxx> +#include <editeng/unolingu.hxx> +#include <linguistic/lngprops.hxx> +#include <i18npool/mslangid.hxx> +#include <vcl/help.hxx> +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <com/sun/star/i18n/InputSequenceCheckMode.hpp> + +#include <svl/srchdefs.hxx> + +#if OSL_DEBUG_LEVEL > 1 +#include <editeng/frmdiritem.hxx> +#endif +#include <basegfx/polygon/b2dpolygon.hxx> + +// Spaeter -> TOOLS\STRING.H (fuer Grep: WS_TARGET) + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::linguistic2; + + +DBG_NAME( EditEngine ) +DBG_NAMEEX( EditView ) + +#if (OSL_DEBUG_LEVEL > 1) || defined ( DBG_UTIL ) +static sal_Bool bDebugPaint = sal_False; +#endif + +SV_IMPL_VARARR( EECharAttribArray, EECharAttrib ); + +static SfxItemPool* pGlobalPool=0; + +// ---------------------------------------------------------------------- +// EditEngine +// ---------------------------------------------------------------------- +EditEngine::EditEngine( SfxItemPool* pItemPool ) +{ + DBG_CTOR( EditEngine, 0 ); + pImpEditEngine = new ImpEditEngine( this, pItemPool ); +} + +EditEngine::~EditEngine() +{ + DBG_DTOR( EditEngine, 0 ); + delete pImpEditEngine; +} + +void EditEngine::EnableUndo( sal_Bool bEnable ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->EnableUndo( bEnable ); +} + +sal_Bool EditEngine::IsUndoEnabled() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsUndoEnabled(); +} + +sal_Bool EditEngine::IsInUndo() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsInUndo(); +} + +SfxUndoManager& EditEngine::GetUndoManager() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetUndoManager(); +} + +void EditEngine::UndoActionStart( sal_uInt16 nId ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Aufruf von UndoActionStart im Undomodus!" ); + if ( !pImpEditEngine->IsInUndo() ) + pImpEditEngine->UndoActionStart( nId ); +} + +void EditEngine::UndoActionEnd( sal_uInt16 nId ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Aufruf von UndoActionEnd im Undomodus!" ); + if ( !pImpEditEngine->IsInUndo() ) + pImpEditEngine->UndoActionEnd( nId ); +} + +BOOL EditEngine::HasTriedMergeOnLastAddUndo() const +{ + return pImpEditEngine->mbLastTryMerge; +} + +void EditEngine::SetRefDevice( OutputDevice* pRefDev ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetRefDevice( pRefDev ); +} + +OutputDevice* EditEngine::GetRefDevice() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetRefDevice(); +} + +void EditEngine::SetRefMapMode( const MapMode& rMapMode ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetRefMapMode( rMapMode ); +} + +MapMode EditEngine::GetRefMapMode() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetRefMapMode(); +} + +void EditEngine::SetBackgroundColor( const Color& rColor ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetBackgroundColor( rColor ); +} + +Color EditEngine::GetBackgroundColor() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetBackgroundColor(); +} + +Color EditEngine::GetAutoColor() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetAutoColor(); +} + +void EditEngine::EnableAutoColor( BOOL b ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->EnableAutoColor( b ); +} + +BOOL EditEngine::IsAutoColorEnabled() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsAutoColorEnabled(); +} + +void EditEngine::ForceAutoColor( BOOL b ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->ForceAutoColor( b ); +} + +BOOL EditEngine::IsForceAutoColor() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsForceAutoColor(); +} + +const SfxItemSet& EditEngine::GetEmptyItemSet() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEmptyItemSet(); +} + +void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + Draw( pOutDev, rOutRect, Point( 0, 0 ) ); +} + +void EditEngine::Draw( OutputDevice* pOutDev, const Point& rStartPos, short nOrientation ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + // Mit 2 Punkten erzeugen, da bei Positivem Punkt, LONGMAX als Size + // Bottom und Right im Bereich > LONGMAX landen. + Rectangle aBigRec( -0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF ); + if( pOutDev->GetConnectMetaFile() ) + pOutDev->Push(); + Point aStartPos( rStartPos ); + if ( IsVertical() ) + { + aStartPos.X() += GetPaperSize().Width(); + aStartPos = Rotate( aStartPos, nOrientation, rStartPos ); + } + pImpEditEngine->Paint( pOutDev, aBigRec, aStartPos, sal_False, nOrientation ); + if( pOutDev->GetConnectMetaFile() ) + pOutDev->Pop(); +} + +void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect, const Point& rStartDocPos ) +{ + Draw( pOutDev, rOutRect, rStartDocPos, sal_True ); +} + +void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect, const Point& rStartDocPos, sal_Bool bClip ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + +#if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1) + if ( bDebugPaint ) + EditDbg::ShowEditEngineData( this, sal_False ); +#endif + + // Auf Pixelgrenze ausrichten, damit genau das gleiche + // wie bei Paint(). + Rectangle aOutRect( pOutDev->LogicToPixel( rOutRect ) ); + aOutRect = pOutDev->PixelToLogic( aOutRect ); + + Point aStartPos; + if ( !IsVertical() ) + { + aStartPos.X() = aOutRect.Left() - rStartDocPos.X(); + aStartPos.Y() = aOutRect.Top() - rStartDocPos.Y(); + } + else + { + aStartPos.X() = aOutRect.Right() + rStartDocPos.Y(); + aStartPos.Y() = aOutRect.Top() - rStartDocPos.X(); + } + + sal_Bool bClipRegion = pOutDev->IsClipRegion(); + sal_Bool bMetafile = pOutDev->GetConnectMetaFile() ? sal_True : sal_False; + Region aOldRegion = pOutDev->GetClipRegion(); + +#ifdef EDIT_PRINTER_LOG + if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER ) + { + SvFileStream aLog( "d:\\editprn.log", STREAM_WRITE ); + aLog.Seek( STREAM_SEEK_TO_END ); + aLog << '' << endl << "Printing: "; + aLog << GetText( "\n\r" ).GetStr(); + aLog << endl << endl; + aLog << "Ref-Device: " << String( (sal_uInt32)GetRefDevice() ).GetStr() << " Type=" << String( (sal_uInt16)GetRefDevice()->GetOutDevType() ).GetStr() << ", MapX=" << String( GetRefDevice()->GetMapMode().GetScaleX().GetNumerator() ).GetStr() << "/" << String( GetRefDevice()->GetMapMode().GetScaleX().GetDenominator() ).GetStr() <<endl; + aLog << "Paper-Width: " << String( GetPaperSize().Width() ).GetStr() << ",\tOut-Width: " << String( rOutRect.GetWidth() ).GetStr() << ",\tCalculated: " << String( CalcTextWidth() ).GetStr() << endl; + aLog << "Paper-Height: " << String( GetPaperSize().Height() ).GetStr() << ",\tOut-Height: " << String( rOutRect.GetHeight() ).GetStr() << ",\tCalculated: " << String( GetTextHeight() ).GetStr() << endl; + + aLog << endl; + } +#endif + + // Wenn es eine gab => Schnittmenge ! + // Bei der Metafileaufzeichnung Push/Pop verwenden. + if ( bMetafile ) + pOutDev->Push(); + + // Immer die Intersect-Methode, weil beim Metafile ein Muss! + if ( bClip ) + { + // Clip only if neccesary... + if ( !rStartDocPos.X() && !rStartDocPos.Y() && + ( rOutRect.GetHeight() >= (long)GetTextHeight() ) && + ( rOutRect.GetWidth() >= (long)CalcTextWidth() ) ) + { + bClip = FALSE; + } + else + { + // Einige Druckertreiber bereiten Probleme, wenn Buchstaben die + // ClipRegion streifen, deshalb lieber ein Pixel mehr... + Rectangle aClipRect( aOutRect ); + if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER ) + { + Size aPixSz( 1, 0 ); + aPixSz = pOutDev->PixelToLogic( aPixSz ); + aClipRect.Right() += aPixSz.Width(); + aClipRect.Bottom() += aPixSz.Width(); + } + pOutDev->IntersectClipRegion( aClipRect ); + } + } + + pImpEditEngine->Paint( pOutDev, aOutRect, aStartPos ); + + if ( bMetafile ) + pOutDev->Pop(); + else if ( bClipRegion ) + pOutDev->SetClipRegion( aOldRegion ); + else + pOutDev->SetClipRegion(); +} + +void EditEngine::InsertView( EditView* pEditView, sal_uInt16 nIndex ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_CHKOBJ( pEditView, EditView, 0 ); + + if ( nIndex > pImpEditEngine->GetEditViews().Count() ) + nIndex = pImpEditEngine->GetEditViews().Count(); + + pImpEditEngine->GetEditViews().Insert( pEditView, nIndex ); + EditSelection aStartSel; + aStartSel = pImpEditEngine->GetEditDoc().GetStartPaM(); + pEditView->pImpEditView->SetEditSelection( aStartSel ); + if ( !pImpEditEngine->GetActiveView() ) + pImpEditEngine->SetActiveView( pEditView ); + + pEditView->pImpEditView->AddDragAndDropListeners(); +} + +EditView* EditEngine::RemoveView( EditView* pView ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_CHKOBJ( pView, EditView, 0 ); + + pView->HideCursor(); + EditView* pRemoved = 0; + sal_uInt16 nPos = pImpEditEngine->GetEditViews().GetPos( pView ); + DBG_ASSERT( nPos != USHRT_MAX, "RemoveView mit ungueltigem Index" ); + if ( nPos != USHRT_MAX ) + { + pRemoved = pImpEditEngine->GetEditViews().GetObject( nPos ); + pImpEditEngine->GetEditViews().Remove( nPos ); + if ( pImpEditEngine->GetActiveView() == pView ) + { + pImpEditEngine->SetActiveView( 0 ); + pImpEditEngine->GetSelEngine().SetCurView( 0 ); + } + pView->pImpEditView->RemoveDragAndDropListeners(); + + } + return pRemoved; +} + +EditView* EditEngine::RemoveView( sal_uInt16 nIndex ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditView* pView = pImpEditEngine->GetEditViews().GetObject( nIndex ); + if ( pView ) + return RemoveView( pView ); + return NULL; +} + +EditView* EditEngine::GetView( sal_uInt16 nIndex ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditViews().GetObject( nIndex ); +} + +sal_uInt16 EditEngine::GetViewCount() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditViews().Count(); +} + +sal_Bool EditEngine::HasView( EditView* pView ) const +{ + return pImpEditEngine->GetEditViews().GetPos( pView ) != USHRT_MAX; +} + +EditView* EditEngine::GetActiveView() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetActiveView(); +} + +void EditEngine::SetActiveView( EditView* pView ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( pView ) + { + DBG_CHKOBJ( pView, EditView, 0 ); + } + pImpEditEngine->SetActiveView( pView ); +} + +void EditEngine::SetDefTab( sal_uInt16 nDefTab ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->GetEditDoc().SetDefTab( nDefTab ); + if ( pImpEditEngine->IsFormatted() ) + { + pImpEditEngine->FormatFullDoc(); + pImpEditEngine->UpdateViews( (EditView*) 0 ); + } +} + +sal_uInt16 EditEngine::GetDefTab() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditDoc().GetDefTab(); +} + +void EditEngine::SetPaperSize( const Size& rNewSize ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + Size aOldSize( pImpEditEngine->GetPaperSize() ); + pImpEditEngine->SetValidPaperSize( rNewSize ); + Size aNewSize( pImpEditEngine->GetPaperSize() ); + + sal_Bool bAutoPageSize = pImpEditEngine->GetStatus().AutoPageSize(); + if ( bAutoPageSize || ( aNewSize.Width() != aOldSize.Width() ) ) + { + for ( sal_uInt16 nView = 0; nView < pImpEditEngine->aEditViews.Count(); nView++ ) + { + EditView* pView = pImpEditEngine->aEditViews[nView]; + DBG_CHKOBJ( pView, EditView, 0 ); + if ( bAutoPageSize ) + pView->pImpEditView->RecalcOutputArea(); + else if ( pView->pImpEditView->DoAutoSize() ) + { + pView->pImpEditView->ResetOutputArea( Rectangle( + pView->pImpEditView->GetOutputArea().TopLeft(), aNewSize ) ); + } + } + + if ( bAutoPageSize || pImpEditEngine->IsFormatted() ) + { + // Aendern der Breite hat bei AutoPageSize keine Wirkung, da durch + // Textbreite bestimmt. + // Optimierung erst nach Vobis-Auslieferung aktivieren... +// if ( !bAutoPageSize ) + pImpEditEngine->FormatFullDoc(); +// else +// { +// pImpEditEngine->FormatDoc(); // PageSize, falls Aenderung +// pImpEditEngine->CheckAutoPageSize(); // Falls nichts formatiert wurde +// } + + pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + + if ( pImpEditEngine->GetUpdateMode() && pImpEditEngine->GetActiveView() ) + pImpEditEngine->pActiveView->ShowCursor( sal_False, sal_False ); + } + } +} + +const Size& EditEngine::GetPaperSize() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetPaperSize(); +} + +void EditEngine::SetVertical( BOOL bVertical ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetVertical( bVertical ); +} + +BOOL EditEngine::IsVertical() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsVertical(); +} + +void EditEngine::SetFixedCellHeight( BOOL bUseFixedCellHeight ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); +} + +BOOL EditEngine::IsFixedCellHeight() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsFixedCellHeight(); +} + +void EditEngine::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetDefaultHorizontalTextDirection( eHTextDir ); +} + +EEHorizontalTextDirection EditEngine::GetDefaultHorizontalTextDirection() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetDefaultHorizontalTextDirection(); +} + +USHORT EditEngine::GetScriptType( const ESelection& rSelection ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); + return pImpEditEngine->GetScriptType( aSel ); +} + +LanguageType EditEngine::GetLanguage( USHORT nPara, USHORT nPos ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + DBG_ASSERT( pNode, "GetLanguage - nPara is invalid!" ); + return pNode ? pImpEditEngine->GetLanguage( EditPaM( pNode, nPos ) ) : LANGUAGE_DONTKNOW; +} + + +void EditEngine::TransliterateText( const ESelection& rSelection, sal_Int32 nTransliterationMode ) +{ + DBG_CHKTHIS( EditView, 0 ); + pImpEditEngine->TransliterateText( pImpEditEngine->CreateSel( rSelection ), nTransliterationMode ); +} + +void EditEngine::SetAsianCompressionMode( USHORT n ) +{ + DBG_CHKTHIS( EditView, 0 ); + pImpEditEngine->SetAsianCompressionMode( n ); +} + +USHORT EditEngine::GetAsianCompressionMode() const +{ + DBG_CHKTHIS( EditView, 0 ); + return pImpEditEngine->GetAsianCompressionMode(); +} + +void EditEngine::SetKernAsianPunctuation( BOOL b ) +{ + DBG_CHKTHIS( EditView, 0 ); + pImpEditEngine->SetKernAsianPunctuation( b ); +} + +BOOL EditEngine::IsKernAsianPunctuation() const +{ + DBG_CHKTHIS( EditView, 0 ); + return pImpEditEngine->IsKernAsianPunctuation(); +} + +void EditEngine::SetAddExtLeading( BOOL b ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetAddExtLeading( b ); +} + +BOOL EditEngine::IsAddExtLeading() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsAddExtLeading(); +} + +void EditEngine::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + SetPolygon( rPolyPolygon, 0L ); +} + +void EditEngine::SetPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon) +{ + DBG_CHKTHIS( EditEngine, 0 ); + sal_Bool bSimple(sal_False); + + if(pLinePolyPolygon && 1L == rPolyPolygon.count()) + { + if(rPolyPolygon.getB2DPolygon(0L).isClosed()) + { + // open polygon + bSimple = sal_True; + } + } + + TextRanger* pRanger = new TextRanger( rPolyPolygon, pLinePolyPolygon, 30, 2, 2, bSimple, sal_True ); + pImpEditEngine->SetTextRanger( pRanger ); + pImpEditEngine->SetPaperSize( pRanger->GetBoundRect().GetSize() ); +} + +void EditEngine::ClearPolygon() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetTextRanger( 0 ); +} + +const PolyPolygon* EditEngine::GetPolygon() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetTextRanger() ? + &pImpEditEngine->GetTextRanger()->GetPolyPolygon() : NULL; +} + +const Size& EditEngine::GetMinAutoPaperSize() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetMinAutoPaperSize(); +} + +void EditEngine::SetMinAutoPaperSize( const Size& rSz ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetMinAutoPaperSize( rSz ); +} + +const Size& EditEngine::GetMaxAutoPaperSize() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetMaxAutoPaperSize(); +} + +void EditEngine::SetMaxAutoPaperSize( const Size& rSz ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetMaxAutoPaperSize( rSz ); +} + +XubString EditEngine::GetText( LineEnd eEnd ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditDoc().GetText( eEnd ); +} + +XubString EditEngine::GetText( const ESelection& rESelection, const LineEnd eEnd ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); + return pImpEditEngine->GetSelected( aSel, eEnd ); +} + +sal_uInt32 EditEngine::GetTextLen() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditDoc().GetTextLen(); +} + +sal_uInt16 EditEngine::GetParagraphCount() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->aEditDoc.Count(); +} + +sal_uInt16 EditEngine::GetLineCount( sal_uInt16 nParagraph ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + return pImpEditEngine->GetLineCount( nParagraph ); +} + +sal_uInt16 EditEngine::GetLineLen( sal_uInt16 nParagraph, sal_uInt16 nLine ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + return pImpEditEngine->GetLineLen( nParagraph, nLine ); +} + +void EditEngine::GetLineBoundaries( /*out*/USHORT &rStart, /*out*/USHORT &rEnd, USHORT nParagraph, USHORT nLine ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + return pImpEditEngine->GetLineBoundaries( rStart, rEnd, nParagraph, nLine ); +} + +USHORT EditEngine::GetLineNumberAtIndex( USHORT nPara, USHORT nIndex ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + return pImpEditEngine->GetLineNumberAtIndex( nPara, nIndex ); +} + +sal_uInt32 EditEngine::GetLineHeight( sal_uInt16 nParagraph, sal_uInt16 nLine ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + // Falls jemand mit einer leeren Engine ein GetLineHeight() macht. + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + return pImpEditEngine->GetLineHeight( nParagraph, nLine ); +} + +sal_uInt16 EditEngine::GetFirstLineOffset( sal_uInt16 nParagraph ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph ); + return ( pPortion ? pPortion->GetFirstLineOffset() : 0 ); +} + +sal_uInt32 EditEngine::GetTextHeight( sal_uInt16 nParagraph ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + + sal_uInt32 nHeight = pImpEditEngine->GetParaHeight( nParagraph ); + return nHeight; +} + +XubString EditEngine::GetWord( sal_uInt16 nPara, sal_uInt16 nIndex ) +{ + ESelection aESel( nPara, nIndex, nPara, nIndex ); + EditSelection aSel( pImpEditEngine->CreateSel( aESel ) ); + aSel = pImpEditEngine->SelectWord( aSel ); + return pImpEditEngine->GetSelected( aSel ); +} + +ESelection EditEngine::GetWord( const ESelection& rSelection, USHORT nWordType ) const +{ + // ImpEditEngine-Iteration-Methods should be const! + EditEngine* pE = (EditEngine*)this; + + EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); + aSel = pE->pImpEditEngine->SelectWord( aSel, nWordType ); + return pE->pImpEditEngine->CreateESel( aSel ); +} + +ESelection EditEngine::WordLeft( const ESelection& rSelection, USHORT nWordType ) const +{ + // ImpEditEngine-Iteration-Methods should be const! + EditEngine* pE = (EditEngine*)this; + + EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); + aSel = pE->pImpEditEngine->WordLeft( aSel.Min(), nWordType ); + return pE->pImpEditEngine->CreateESel( aSel ); +} + +ESelection EditEngine::WordRight( const ESelection& rSelection, USHORT nWordType ) const +{ + // ImpEditEngine-Iteration-Methods should be const! + EditEngine* pE = (EditEngine*)this; + + EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); + aSel = pE->pImpEditEngine->WordRight( aSel.Max(), nWordType ); + return pE->pImpEditEngine->CreateESel( aSel ); +} + +ESelection EditEngine::CursorLeft( const ESelection& rSelection, USHORT nCharacterIteratorMode ) const +{ + // ImpEditEngine-Iteration-Methods should be const! + EditEngine* pE = (EditEngine*)this; + + EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); + aSel = pE->pImpEditEngine->CursorLeft( aSel.Min(), nCharacterIteratorMode ); + return pE->pImpEditEngine->CreateESel( aSel ); +} + +ESelection EditEngine::CursorRight( const ESelection& rSelection, USHORT nCharacterIteratorMode ) const +{ + // ImpEditEngine-Iteration-Methods should be const! + EditEngine* pE = (EditEngine*)this; + + EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); + aSel = pE->pImpEditEngine->CursorRight( aSel.Max(), nCharacterIteratorMode ); + return pE->pImpEditEngine->CreateESel( aSel ); +} + +sal_Bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_CHKOBJ( pEditView, EditView, 0 ); + DBG_ASSERT( pEditView, "Keine View - keine Kekse !" ); + + sal_Bool bDone = sal_True; + + sal_Bool bModified = sal_False; + sal_Bool bMoved = sal_False; + sal_Bool bAllowIdle = sal_True; + sal_Bool bReadOnly = pEditView->IsReadOnly(); + + USHORT nNewCursorFlags = 0; + BOOL bSetCursorFlags = TRUE; + + EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + DBG_ASSERT( !aCurSel.IsInvalid(), "Blinde Selection in EditEngine::PostKeyEvent" ); + + String aAutoText( pImpEditEngine->GetAutoCompleteText() ); + if ( pImpEditEngine->GetAutoCompleteText().Len() ) + pImpEditEngine->SetAutoCompleteText( String(), sal_True ); + + sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); + KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); + if ( eFunc != KEYFUNC_DONTKNOW ) + { + switch ( eFunc ) + { + case KEYFUNC_UNDO: + { + if ( !bReadOnly ) + pEditView->Undo(); + return sal_True; + } + // break; + case KEYFUNC_REDO: + { + if ( !bReadOnly ) + pEditView->Redo(); + return sal_True; + } + // break; + + default: // wird dann evtl. unten bearbeitet. + eFunc = KEYFUNC_DONTKNOW; + } + } + + pImpEditEngine->EnterBlockNotifications(); + + if ( GetNotifyHdl().IsSet() ) + { + EENotify aNotify( EE_NOTIFY_INPUT_START ); + aNotify.pEditEngine = this; + pImpEditEngine->CallNotify( aNotify ); + } + + if ( eFunc == KEYFUNC_DONTKNOW ) + { + switch ( nCode ) + { + #if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1) + case KEY_F1: + { + if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() ) + { + USHORT nParas = GetParagraphCount(); + Point aPos; + Point aViewStart( pEditView->GetOutputArea().TopLeft() ); + long n20 = 40 * pImpEditEngine->nOnePixelInRef; + for ( USHORT n = 0; n < nParas; n++ ) + { + long nH = GetTextHeight( n ); + Point P1( aViewStart.X() + n20 + n20*(n%2), aViewStart.Y() + aPos.Y() ); + Point P2( P1 ); + P2.X() += n20; + P2.Y() += nH; + pEditView->GetWindow()->SetLineColor(); + pEditView->GetWindow()->SetFillColor( Color( (n%2) ? COL_YELLOW : COL_LIGHTGREEN ) ); + pEditView->GetWindow()->DrawRect( Rectangle( P1, P2 ) ); + aPos.Y() += nH; + } + } + bDone = FALSE; + } + break; + case KEY_F11: + { + if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() ) + { + bDebugPaint = !bDebugPaint; + ByteString aInfo( "DebugPaint: " ); + aInfo += bDebugPaint ? "On" : "Off"; + InfoBox( NULL, String( aInfo, RTL_TEXTENCODING_ASCII_US ) ).Execute(); + } + bDone = FALSE; + } + break; + case KEY_F12: + { + if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() ) + { + EditDbg::ShowEditEngineData( this ); + #ifdef EDIT_PRINTER_LOG + SvFileStream aLog( "d:\\editprn.log", STREAM_WRITE ); + aLog.Seek( STREAM_SEEK_TO_END ); + aLog << '' << endl << "Debug: "; + aLog << GetText( "\n\r" ).GetStr(); + aLog << endl << endl; + aLog << "Ref-Device: " << String( (sal_uInt32)GetRefDevice() ).GetStr() << " Type=" << String( (sal_uInt16)GetRefDevice()->GetOutDevType() ).GetStr() << ", MapX=" << String( GetRefDevice()->GetMapMode().GetScaleX().GetNumerator() ).GetStr() << "/" << String( GetRefDevice()->GetMapMode().GetScaleX().GetDenominator() ).GetStr() <<endl; + aLog << "Paper-Width: " << String( GetPaperSize().Width() ).GetStr() << ",\tCalculated: " << String( CalcTextWidth() ).GetStr() << endl; + aLog << "Paper-Height: " << String( GetPaperSize().Height() ).GetStr() << ",\tCalculated: " << String( GetTextHeight() ).GetStr() << endl; + aLog << endl; + #endif + } + bDone = FALSE; + } + break; + #endif + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + case KEY_HOME: + case KEY_END: + case KEY_PAGEUP: + case KEY_PAGEDOWN: + case com::sun::star::awt::Key::MOVE_WORD_FORWARD: + case com::sun::star::awt::Key::SELECT_WORD_FORWARD: + case com::sun::star::awt::Key::MOVE_WORD_BACKWARD: + case com::sun::star::awt::Key::SELECT_WORD_BACKWARD: + case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE: + case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE: + case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE: + case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE: + case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: + case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH: + case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: + case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH: + case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: + case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT: + case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: + case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT: + { + if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) + { + if ( pImpEditEngine->DoVisualCursorTraveling( aCurSel.Max().GetNode() ) && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) ) + bSetCursorFlags = FALSE; // Will be manipulated within visual cursor move + + aCurSel = pImpEditEngine->MoveCursor( rKeyEvent, pEditView ); + + if ( aCurSel.HasRange() ) { + Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(pEditView->GetWindow()->GetPrimarySelection()); + pEditView->pImpEditView->CutCopy( aSelection, FALSE ); + } + + bMoved = sal_True; + if ( nCode == KEY_HOME ) + nNewCursorFlags |= GETCRSR_STARTOFLINE; + else if ( nCode == KEY_END ) + nNewCursorFlags |= GETCRSR_ENDOFLINE; + + } +#if OSL_DEBUG_LEVEL > 1 + GetLanguage( pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex() ); +#endif + } + break; + case KEY_BACKSPACE: + case KEY_DELETE: + case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: + case com::sun::star::awt::Key::DELETE_WORD_FORWARD: + case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH: + case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH: + { + if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod2() ) + { + // check if we are behind a bullet and using the backspace key + ContentNode *pNode = aCurSel.Min().GetNode(); + const SvxNumberFormat *pFmt = pImpEditEngine->GetNumberFormat( pNode ); + if (pFmt && nCode == KEY_BACKSPACE && + !aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0) + { + // if the bullet is still visible just do not paint it from + // now on and that will be all. Otherwise continue as usual. + // ... + + USHORT nPara = pImpEditEngine->GetEditDoc().GetPos( pNode ); + SfxBoolItem aBulletState( (const SfxBoolItem&) pImpEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) ); + bool bBulletIsVisible = aBulletState.GetValue() ? true : false; + + // just toggling EE_PARA_BULLETSTATE should be fine for both cases... + aBulletState.SetValue( !bBulletIsVisible ); + SfxItemSet aSet( pImpEditEngine->GetParaAttribs( nPara ) ); + aSet.Put( aBulletState ); + pImpEditEngine->SetParaAttribs( nPara, aSet ); + + // have this and the following paragraphs formatted and repainted. + // (not painting a numbering in the list may cause the following + // numberings to have different numbers than before and thus the + // length may have changed as well ) + pImpEditEngine->FormatAndUpdate( pImpEditEngine->GetActiveView() ); + + if (bBulletIsVisible) // bullet just turned invisible... + break; + } + + BYTE nDel = 0, nMode = 0; + switch( nCode ) + { + case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: + nMode = DELMODE_RESTOFWORD; + nDel = DEL_LEFT; + break; + case com::sun::star::awt::Key::DELETE_WORD_FORWARD: + nMode = DELMODE_RESTOFWORD; + nDel = DEL_RIGHT; + break; + case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH: + nMode = DELMODE_RESTOFCONTENT; + nDel = DEL_LEFT; + break; + case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH: + nMode = DELMODE_RESTOFCONTENT; + nDel = DEL_RIGHT; + break; + default: + nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT; + nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE; + if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() ) + nMode = DELMODE_RESTOFCONTENT; + break; + } + + pEditView->pImpEditView->DrawSelection(); + pImpEditEngine->UndoActionStart( EDITUNDO_DELETE ); + aCurSel = pImpEditEngine->DeleteLeftOrRight( aCurSel, nDel, nMode ); + pImpEditEngine->UndoActionEnd( EDITUNDO_DELETE ); + bModified = sal_True; + bAllowIdle = sal_False; + } + } + break; + case KEY_TAB: + { + if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) + { + sal_Bool bShift = rKeyEvent.GetKeyCode().IsShift(); + if ( pImpEditEngine->GetStatus().DoTabIndenting() && + ( aCurSel.Min().GetNode() != aCurSel.Max().GetNode() ) ) + { + pImpEditEngine->IndentBlock( pEditView, !bShift ); + } + else if ( !bShift ) + { + sal_Bool bSel = pEditView->HasSelection(); + if ( bSel ) + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) + aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() ); + aCurSel = pImpEditEngine->InsertTab( aCurSel ); + if ( bSel ) + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + bModified = sal_True; + } + } + else + bDone = sal_False; + } + break; + case KEY_RETURN: + { + if ( !bReadOnly ) + { + pEditView->pImpEditView->DrawSelection(); + if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) + { + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + if ( rKeyEvent.GetKeyCode().IsShift() ) + { + aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() ); + aCurSel = pImpEditEngine->InsertLineBreak( aCurSel ); + } + else + { + if ( !aAutoText.Len() ) + { + if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) + aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() ); + aCurSel = pImpEditEngine->InsertParaBreak( aCurSel ); + } + else + { + DBG_ASSERT( !aCurSel.HasRange(), "Selektion bei Complete?!" ); + EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); + aCurSel = pImpEditEngine->InsertText( + EditSelection( aStart, aCurSel.Max() ), aAutoText ); + pImpEditEngine->SetAutoCompleteText( String(), sal_True ); + } + } + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + bModified = sal_True; + } + } + } + break; + case KEY_INSERT: + { + if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) + pEditView->SetInsertMode( !pEditView->IsInsertMode() ); + } + break; + default: + { + #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) + if ( ( nCode == KEY_W ) && rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() ) + { + SfxItemSet aAttribs = pEditView->GetAttribs(); + const SvxFrameDirectionItem& rCurrentWritingMode = (const SvxFrameDirectionItem&)aAttribs.Get( EE_PARA_WRITINGDIR ); + SvxFrameDirectionItem aNewItem( FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR ); + if ( rCurrentWritingMode.GetValue() != FRMDIR_HORI_RIGHT_TOP ) + aNewItem.SetValue( FRMDIR_HORI_RIGHT_TOP ); + aAttribs.Put( aNewItem ); + pEditView->SetAttribs( aAttribs ); + } + #endif + if ( !bReadOnly && IsSimpleCharInput( rKeyEvent ) ) + { + xub_Unicode nCharCode = rKeyEvent.GetCharCode(); + pEditView->pImpEditView->DrawSelection(); + // Autokorrektur ? + if ( ( pImpEditEngine->GetStatus().DoAutoCorrect() ) && + ( ( nCharCode == ' ' ) || ( nCharCode == '*' ) || + ( nCharCode == '\"' ) || ( nCharCode == '\'' ) || + ( nCharCode == '_' ) )) + { + aCurSel = pImpEditEngine->AutoCorrect( aCurSel, nCharCode, !pEditView->IsInsertMode() ); + } + else + { + aCurSel = pImpEditEngine->InsertText( (const EditSelection&)aCurSel, nCharCode, !pEditView->IsInsertMode(), sal_True ); + } + // AutoComplete ??? + if ( pImpEditEngine->GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) ) + { + // Aber nur wenn Wort-Ende... + sal_uInt16 nIndex = aCurSel.Max().GetIndex(); + if ( ( nIndex >= aCurSel.Max().GetNode()->Len() ) || + ( pImpEditEngine->aWordDelimiters.Search( aCurSel.Max().GetNode()->GetChar( nIndex ) ) != STRING_NOTFOUND ) ) + { + EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); + String aWord = pImpEditEngine->GetSelected( EditSelection( aStart, aCurSel.Max() ) ); + if ( aWord.Len() >= 3 ) + { + String aComplete; + + LanguageType eLang = pImpEditEngine->GetLanguage( EditPaM( aStart.GetNode(), aStart.GetIndex()+1)); + lang::Locale aLocale( MsLangId::convertLanguageToLocale( eLang)); + + if (!pImpEditEngine->xLocaleDataWrapper.isInitialized()) + pImpEditEngine->xLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getServiceFactory(), aLocale, eLang); + else + pImpEditEngine->xLocaleDataWrapper.changeLocale( aLocale, eLang); + + if (!pImpEditEngine->xTransliterationWrapper.isInitialized()) + pImpEditEngine->xTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getServiceFactory(), eLang, i18n::TransliterationModules_IGNORE_CASE); + else + pImpEditEngine->xTransliterationWrapper.changeLocale( eLang); + + const ::utl::TransliterationWrapper* pTransliteration = pImpEditEngine->xTransliterationWrapper.get(); + Sequence< i18n::CalendarItem > xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarDays(); + sal_Int32 nCount = xItem.getLength(); + const i18n::CalendarItem* pArr = xItem.getArray(); + for( sal_Int32 n = 0; n <= nCount; ++n ) + { + const ::rtl::OUString& rDay = pArr[n].FullName; + if( pTransliteration->isMatch( aWord, rDay) ) + { + aComplete = rDay; + break; + } + } + + if ( !aComplete.Len() ) + { + xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarMonths(); + sal_Int32 nMonthCount = xItem.getLength(); + const i18n::CalendarItem* pMonthArr = xItem.getArray(); + for( sal_Int32 n = 0; n <= nMonthCount; ++n ) + { + const ::rtl::OUString& rMon = pMonthArr[n].FullName; + if( pTransliteration->isMatch( aWord, rMon) ) + { + aComplete = rMon; + break; + } + } + } + + if( aComplete.Len() && ( ( aWord.Len() + 1 ) < aComplete.Len() ) ) + { + pImpEditEngine->SetAutoCompleteText( aComplete, sal_False ); + Point aPos = pImpEditEngine->PaMtoEditCursor( aCurSel.Max() ).TopLeft(); + aPos = pEditView->pImpEditView->GetWindowPos( aPos ); + aPos = pEditView->pImpEditView->GetWindow()->LogicToPixel( aPos ); + aPos = pEditView->GetWindow()->OutputToScreenPixel( aPos ); + aPos.Y() -= 3; + Help::ShowQuickHelp( pEditView->GetWindow(), Rectangle( aPos, Size( 1, 1 ) ), aComplete, QUICKHELP_BOTTOM|QUICKHELP_LEFT ); + } + } + } + } + bModified = sal_True; + } + else + bDone = sal_False; + } + } + } + + pEditView->pImpEditView->SetEditSelection( aCurSel ); + pImpEditEngine->UpdateSelections(); + + if ( ( !IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) || + ( IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) )) + { + pEditView->pImpEditView->nTravelXPos = TRAVEL_X_DONTKNOW; + } + + if ( /* ( nCode != KEY_HOME ) && ( nCode != KEY_END ) && */ + ( !IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) || + ( IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )) + { + pEditView->pImpEditView->SetCursorBidiLevel( 0xFFFF ); + } + + if ( bSetCursorFlags ) + pEditView->pImpEditView->nExtraCursorFlags = nNewCursorFlags; + + if ( bModified ) + { + DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" ); + // Idle-Formatter nur, wenn AnyInput. + if ( bAllowIdle && pImpEditEngine->GetStatus().UseIdleFormatter() + && Application::AnyInput( INPUT_KEYBOARD) ) + pImpEditEngine->IdleFormatAndUpdate( pEditView ); + else + pImpEditEngine->FormatAndUpdate( pEditView ); + } + else if ( bMoved ) + { + sal_Bool bGotoCursor = pEditView->pImpEditView->DoAutoScroll(); + pEditView->pImpEditView->ShowCursor( bGotoCursor, sal_True ); + pImpEditEngine->CallStatusHdl(); + } + + if ( GetNotifyHdl().IsSet() ) + { + EENotify aNotify( EE_NOTIFY_INPUT_END ); + aNotify.pEditEngine = this; + pImpEditEngine->CallNotify( aNotify ); + } + + pImpEditEngine->LeaveBlockNotifications(); + + return bDone; +} + +sal_uInt32 EditEngine::GetTextHeight() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + + sal_uInt32 nHeight = !IsVertical() ? pImpEditEngine->GetTextHeight() : pImpEditEngine->CalcTextWidth( TRUE ); + return nHeight; +} + +sal_uInt32 EditEngine::CalcTextWidth() +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + + sal_uInt32 nWidth = !IsVertical() ? pImpEditEngine->CalcTextWidth( TRUE ) : pImpEditEngine->GetTextHeight(); + return nWidth; +} + +void EditEngine::SetUpdateMode( sal_Bool bUpdate ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetUpdateMode( bUpdate ); + if ( pImpEditEngine->pActiveView ) + pImpEditEngine->pActiveView->ShowCursor( sal_False, sal_False ); +} + +sal_Bool EditEngine::GetUpdateMode() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetUpdateMode(); +} + +void EditEngine::Clear() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->Clear(); +} + +void EditEngine::SetText( const XubString& rText ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetText( rText ); + if ( rText.Len() ) + pImpEditEngine->FormatAndUpdate(); +} + +ULONG EditEngine::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs /* = NULL */ ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + sal_Bool bUndoEnabled = pImpEditEngine->IsUndoEnabled(); + pImpEditEngine->EnableUndo( sal_False ); + pImpEditEngine->SetText( XubString() ); + EditPaM aPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); + pImpEditEngine->Read( rInput, rBaseURL, eFormat, EditSelection( aPaM, aPaM ), pHTTPHeaderAttrs ); + pImpEditEngine->EnableUndo( bUndoEnabled ); + return rInput.GetError(); +} + +ULONG EditEngine::Write( SvStream& rOutput, EETextFormat eFormat ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditPaM aStartPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); + EditPaM aEndPaM( pImpEditEngine->GetEditDoc().GetEndPaM() ); + pImpEditEngine->Write( rOutput, eFormat, EditSelection( aStartPaM, aEndPaM ) ); + return rOutput.GetError(); +} + +EditTextObject* EditEngine::CreateTextObject() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->CreateTextObject(); +} + +EditTextObject* EditEngine::CreateTextObject( const ESelection& rESelection ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); + return pImpEditEngine->CreateTextObject( aSel ); +} + +void EditEngine::SetText( const EditTextObject& rTextObject ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->EnterBlockNotifications(); + pImpEditEngine->SetText( rTextObject ); + pImpEditEngine->FormatAndUpdate(); + pImpEditEngine->LeaveBlockNotifications(); +} + +void EditEngine::ShowParagraph( sal_uInt16 nParagraph, sal_Bool bShow ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->ShowParagraph( nParagraph, bShow ); +} + +sal_Bool EditEngine::IsParagraphVisible( sal_uInt16 nParagraph ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsParagraphVisible( nParagraph ); +} + +void EditEngine::SetNotifyHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetNotifyHdl( rLink ); +} + +Link EditEngine::GetNotifyHdl() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetNotifyHdl(); +} + +void EditEngine::SetStatusEventHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetStatusEventHdl( rLink ); +} + +Link EditEngine::GetStatusEventHdl() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetStatusEventHdl(); +} + +void EditEngine::SetImportHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->aImportHdl = rLink; +} + +Link EditEngine::GetImportHdl() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->aImportHdl; +} + +void EditEngine::SetBeginMovingParagraphsHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->aBeginMovingParagraphsHdl = rLink; +} + +void EditEngine::SetEndMovingParagraphsHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->aEndMovingParagraphsHdl = rLink; +} + +void EditEngine::SetBeginPasteOrDropHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + pImpEditEngine->aBeginPasteOrDropHdl = rLink; +} + +void EditEngine::SetEndPasteOrDropHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->aEndPasteOrDropHdl = rLink; +} + +EditTextObject* EditEngine::CreateTextObject( sal_uInt16 nPara, sal_uInt16 nParas ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( nPara < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Startpara out of Range" ); + DBG_ASSERT( nPara+nParas-1 < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Endpara out of Range" ); + + ContentNode* pStartNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + ContentNode* pEndNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara+nParas-1 ); + DBG_ASSERT( pStartNode, "Start-Absatz existiert nicht: CreateTextObject" ); + DBG_ASSERT( pEndNode, "End-Absatz existiert nicht: CreateTextObject" ); + + if ( pStartNode && pEndNode ) + { + EditSelection aTmpSel; + aTmpSel.Min() = EditPaM( pStartNode, 0 ); + aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() ); + return pImpEditEngine->CreateTextObject( aTmpSel ); + } + return 0; +} + +void EditEngine::RemoveParagraph( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( pImpEditEngine->GetEditDoc().Count() > 1, "Der erste Absatz darf nicht geloescht werden!" ); + if( pImpEditEngine->GetEditDoc().Count() <= 1 ) + return; + + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara ); + DBG_ASSERT( pPortion && pNode, "Absatz nicht gefunden: RemoveParagraph" ); + if ( pNode && pPortion ) + { + // Keine Undokappselung noetig. + pImpEditEngine->ImpRemoveParagraph( nPara ); + pImpEditEngine->InvalidateFromParagraph( nPara ); + pImpEditEngine->UpdateSelections(); + pImpEditEngine->FormatAndUpdate(); + } +} + +sal_uInt16 EditEngine::GetTextLen( sal_uInt16 nPara ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + DBG_ASSERT( pNode, "Absatz nicht gefunden: GetTextLen" ); + if ( pNode ) + return pNode->Len(); + return 0; +} + +XubString EditEngine::GetText( sal_uInt16 nPara ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + XubString aStr; + if ( nPara < pImpEditEngine->GetEditDoc().Count() ) + aStr = pImpEditEngine->GetEditDoc().GetParaAsString( nPara ); + return aStr; +} + +void EditEngine::SetModifyHdl( const Link& rLink ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetModifyHdl( rLink ); +} + +Link EditEngine::GetModifyHdl() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetModifyHdl(); +} + + +void EditEngine::ClearModifyFlag() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetModifyFlag( sal_False ); +} + +void EditEngine::SetModified() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetModifyFlag( sal_True ); +} + +sal_Bool EditEngine::IsModified() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsModified(); +} + +sal_Bool EditEngine::IsInSelectionMode() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return ( pImpEditEngine->IsInSelectionMode() || + pImpEditEngine->GetSelEngine().IsInSelection() ); +} + +void EditEngine::StopSelectionMode() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->StopSelectionMode(); +} + +void EditEngine::InsertParagraph( sal_uInt16 nPara, const EditTextObject& rTxtObj ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( nPara > GetParagraphCount() ) + { + DBG_ASSERTWARNING( nPara == USHRT_MAX, "AbsatzNr zu Gro???, aber nicht LIST_APPEND! " ); + nPara = GetParagraphCount(); + } + + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + + // Keine Undoklammerung noetig. + EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + // Bei einem InsertParagraph von aussen sollen keine Harten + // Attribute uebernommen werden ! + pImpEditEngine->RemoveCharAttribs( nPara ); + pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) ); + + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + + pImpEditEngine->FormatAndUpdate(); +} + +void EditEngine::InsertParagraph( sal_uInt16 nPara, const XubString& rTxt ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( nPara > GetParagraphCount() ) + { + DBG_ASSERTWARNING( nPara == USHRT_MAX, "AbsatzNr zu Gro???, aber nicht LIST_APPEND! " ); + nPara = GetParagraphCount(); + } + + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + // Bei einem InsertParagraph von aussen sollen keine Harten + // Attribute uebernommen werden ! + pImpEditEngine->RemoveCharAttribs( nPara ); + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + pImpEditEngine->ImpInsertText( EditSelection( aPaM, aPaM ), rTxt ); + pImpEditEngine->FormatAndUpdate(); +} + +void EditEngine::SetText( sal_uInt16 nPara, const EditTextObject& rTxtObj ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection* pSel = pImpEditEngine->SelectParagraph( nPara ); + if ( pSel ) + { + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + pImpEditEngine->InsertText( rTxtObj, *pSel ); + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + pImpEditEngine->FormatAndUpdate(); + delete pSel; + } +} + +void EditEngine::SetText( sal_uInt16 nPara, const XubString& rTxt ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection* pSel = pImpEditEngine->SelectParagraph( nPara ); + if ( pSel ) + { + pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + pImpEditEngine->ImpInsertText( *pSel, rTxt ); + pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT ); + pImpEditEngine->FormatAndUpdate(); + delete pSel; + } +} + +void EditEngine::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + // Keine Undoklammerung noetig. + pImpEditEngine->SetParaAttribs( nPara, rSet ); + pImpEditEngine->FormatAndUpdate(); +} + +const SfxItemSet& EditEngine::GetParaAttribs( sal_uInt16 nPara ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetParaAttribs( nPara ); +} + +sal_Bool EditEngine::HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->HasParaAttrib( nPara, nWhich ); +} + +const SfxPoolItem& EditEngine::GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetParaAttrib( nPara, nWhich ); +} + +void EditEngine::GetCharAttribs( sal_uInt16 nPara, EECharAttribArray& rLst ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->GetCharAttribs( nPara, rLst ); +} + +SfxItemSet EditEngine::GetAttribs( const ESelection& rSel, BOOL bOnlyHardAttrib ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + return pImpEditEngine->GetAttribs( aSel, bOnlyHardAttrib ); +} + +SfxItemSet EditEngine::GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetAttribs( nPara, nStart, nEnd, nFlags ); +} + +void EditEngine::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + pImpEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); + EditSelection aSel( pImpEditEngine->ConvertSelection( rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos ) ); + pImpEditEngine->RemoveCharAttribs( aSel, bRemoveParaAttribs, nWhich ); + pImpEditEngine->UndoActionEnd( EDITUNDO_RESETATTRIBS ); + pImpEditEngine->FormatAndUpdate(); +} + +// MT: Can be removed after 6.x? +Font EditEngine::GetStandardFont( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return GetStandardSvxFont( nPara ); +} + +SvxFont EditEngine::GetStandardSvxFont( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + return pNode->GetCharAttribs().GetDefFont(); +} + +void EditEngine::StripPortions() +{ + DBG_CHKTHIS( EditEngine, 0 ); + VirtualDevice aTmpDev; + Rectangle aBigRec( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) ); + if ( IsVertical() ) + { + aBigRec.Right() = 0; + aBigRec.Left() = -0x7FFFFFFF; + } + pImpEditEngine->Paint( &aTmpDev, aBigRec, Point(), sal_True ); +} + +void EditEngine::GetPortions( sal_uInt16 nPara, SvUShorts& rList ) +{ + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatFullDoc(); + + ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara ); + if ( pParaPortion ) + { + sal_uInt16 nEnd = 0; + sal_uInt16 nTextPortions = pParaPortion->GetTextPortions().Count(); + for ( sal_uInt16 n = 0; n < nTextPortions; n++ ) + { + nEnd = nEnd + pParaPortion->GetTextPortions()[n]->GetLen(); + rList.Insert( nEnd, rList.Count() ); + } + } +} + +void EditEngine::SetFlatMode( sal_Bool bFlat) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetFlatMode( bFlat ); +} + +sal_Bool EditEngine::IsFlatMode() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return !( pImpEditEngine->aStatus.UseCharAttribs() ); +} + +void EditEngine::SetControlWord( sal_uInt32 nWord ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( nWord != pImpEditEngine->aStatus.GetControlWord() ) + { + sal_uInt32 nPrev = pImpEditEngine->aStatus.GetControlWord(); + pImpEditEngine->aStatus.GetControlWord() = nWord; + + sal_uInt32 nChanges = nPrev ^ nWord; + if ( pImpEditEngine->IsFormatted() ) + { + // ggf. neu formatieren: + if ( ( nChanges & EE_CNTRL_USECHARATTRIBS ) || + ( nChanges & EE_CNTRL_USEPARAATTRIBS ) || + ( nChanges & EE_CNTRL_ONECHARPERLINE ) || + ( nChanges & EE_CNTRL_STRETCHING ) || + ( nChanges & EE_CNTRL_OUTLINER ) || + ( nChanges & EE_CNTRL_NOCOLORS ) || + ( nChanges & EE_CNTRL_OUTLINER2 ) ) + { + if ( ( nChanges & EE_CNTRL_USECHARATTRIBS ) || + ( nChanges & EE_CNTRL_USEPARAATTRIBS ) ) + { + sal_Bool bUseCharAttribs = ( nWord & EE_CNTRL_USECHARATTRIBS ) ? sal_True : sal_False; + pImpEditEngine->GetEditDoc().CreateDefFont( bUseCharAttribs ); + } + + pImpEditEngine->FormatFullDoc(); + pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + } + } + + sal_Bool bSpellingChanged = nChanges & EE_CNTRL_ONLINESPELLING ? sal_True : sal_False; + + if ( bSpellingChanged ) + { + pImpEditEngine->StopOnlineSpellTimer(); + if ( bSpellingChanged && ( nWord & EE_CNTRL_ONLINESPELLING ) ) + { + // WrongListen anlegen, Timer starten... + sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count(); + for ( sal_uInt16 n = 0; n < nNodes; n++ ) + { + ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + pNode->CreateWrongList(); + } + pImpEditEngine->StartOnlineSpellTimer(); + } + else + { + long nY = 0; + sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count(); + for ( sal_uInt16 n = 0; n < nNodes; n++ ) + { + ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + ParaPortion* pPortion = pImpEditEngine->GetParaPortions().GetObject( n ); + sal_Bool bWrongs = ( bSpellingChanged || ( nWord & EE_CNTRL_ONLINESPELLING ) ) ? pNode->GetWrongList()->HasWrongs() : sal_False; + if ( bSpellingChanged ) // Also aus + pNode->DestroyWrongList(); // => vorm Paint weghaun. + if ( bWrongs ) + { + pImpEditEngine->aInvalidRec.Left() = 0; + pImpEditEngine->aInvalidRec.Right() = pImpEditEngine->GetPaperSize().Width(); + pImpEditEngine->aInvalidRec.Top() = nY+1; + pImpEditEngine->aInvalidRec.Bottom() = nY+pPortion->GetHeight()-1; + pImpEditEngine->UpdateViews( pImpEditEngine->pActiveView ); + } + nY += pPortion->GetHeight(); + } + } + } + } +} + +sal_uInt32 EditEngine::GetControlWord() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->aStatus.GetControlWord(); +} + +long EditEngine::GetFirstLineStartX( sal_uInt16 nParagraph ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + long nX = 0; + ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph ); + if ( pPPortion ) + { + DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!" ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + EditLine* pFirstLine = pPPortion->GetLines()[0]; + nX = pFirstLine->GetStartPosX(); + } + return nX; +} + +Point EditEngine::GetDocPos( const Point& rPaperPos ) const +{ + Point aDocPos( rPaperPos ); + if ( IsVertical() ) + { + aDocPos.X() = rPaperPos.Y(); + aDocPos.Y() = GetPaperSize().Width() - rPaperPos.X(); + } + return aDocPos; +} + +Point EditEngine::GetDocPosTopLeft( sal_uInt16 nParagraph ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph ); + DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetWindowPosTopLeft" ); + Point aPoint; + if ( pPPortion ) + { + // Falls jemand mit einer leeren Engine ein GetLineHeight() macht. + DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!" ); + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatAndUpdate(); + if ( pPPortion->GetLines().Count() ) + { + // So richtiger, falls grosses Bullet. + EditLine* pFirstLine = pPPortion->GetLines()[0]; + aPoint.X() = pFirstLine->GetStartPosX(); + } + else + { + const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() ); +// TL_NF_LR aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTxtLeft() + rLRItem.GetTxtFirstLineOfst()) ); + sal_Int32 nSpaceBefore = 0; + pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore ); + short nX = (short)(rLRItem.GetTxtLeft() + + rLRItem.GetTxtFirstLineOfst() + + nSpaceBefore); + aPoint.X() = pImpEditEngine->GetXValue( nX + ); + } + aPoint.Y() = pImpEditEngine->GetParaPortions().GetYOffset( pPPortion ); + } + return aPoint; +} + +const SvxNumberFormat* EditEngine::GetNumberFormat( USHORT nPara ) const +{ + // derived objects may overload this function to give access to + // bullet information (see Outliner) + (void) nPara; + return 0; +} + +BOOL EditEngine::IsRightToLeft( USHORT nPara ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->IsRightToLeft( nPara ); +} + +sal_Bool EditEngine::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + + sal_Bool bTextPos = sal_False; + // #90780# take unrotated positions for calculation here + Point aDocPos = GetDocPos( rPaperPos ); + + if ( ( aDocPos.Y() > 0 ) && ( aDocPos.Y() < (long)pImpEditEngine->GetTextHeight() ) ) + { + EditPaM aPaM = pImpEditEngine->GetPaM( aDocPos, sal_False ); + if ( aPaM.GetNode() ) + { + ParaPortion* pParaPortion = pImpEditEngine->FindParaPortion( aPaM.GetNode() ); + DBG_ASSERT( pParaPortion, "ParaPortion?" ); + + sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex() ); + EditLine* pLine = pParaPortion->GetLines().GetObject( nLine ); + Range aLineXPosStartEnd = pImpEditEngine->GetLineXPosStartEnd( pParaPortion, pLine ); + if ( ( aDocPos.X() >= aLineXPosStartEnd.Min() - nBorder ) && + ( aDocPos.X() <= aLineXPosStartEnd.Max() + nBorder ) ) + { + bTextPos = sal_True; + } + } + } + return bTextPos; +} + +void EditEngine::SetEditTextObjectPool( SfxItemPool* pPool ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetEditTextObjectPool( pPool ); +} + +SfxItemPool* EditEngine::GetEditTextObjectPool() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetEditTextObjectPool(); +} + +void EditEngine::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + + pImpEditEngine->SetAttribs( aSel, rSet ); +} + +void EditEngine::QuickMarkInvalid( const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( rSel.nStartPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: Start out of Range!" ); + DBG_ASSERT( rSel.nEndPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: End out of Range!" ); + for ( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ ) + { + ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara ); + if ( pPortion ) + pPortion->MarkSelectionInvalid( 0, pPortion->GetNode()->Len() ); + } +} + +void EditEngine::QuickInsertText( const XubString& rText, const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + + pImpEditEngine->ImpInsertText( aSel, rText ); +} + +void EditEngine::QuickDelete( const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + + pImpEditEngine->ImpDeleteSelection( aSel ); +} + +void EditEngine::QuickMarkToBeRepainted( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara ); + if ( pPortion ) + pPortion->SetMustRepaint( sal_True ); +} + +void EditEngine::QuickInsertLineBreak( const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + + pImpEditEngine->InsertLineBreak( aSel ); +} + +void EditEngine::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + EditSelection aSel( pImpEditEngine-> + ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); + + pImpEditEngine->ImpInsertFeature( aSel, rFld ); +} + +void EditEngine::QuickFormatDoc( sal_Bool bFull ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( bFull ) + pImpEditEngine->FormatFullDoc(); + else + pImpEditEngine->FormatDoc(); + + // #111072# Don't pass active view, maybe selection is not updated yet... + pImpEditEngine->UpdateViews( NULL ); +} + +void EditEngine::QuickRemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->RemoveCharAttribs( nPara, nWhich ); +} + +void EditEngine::SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetStyleSheet( nPara, pStyle ); +} + +SfxStyleSheet* EditEngine::GetStyleSheet( sal_uInt16 nPara ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetStyleSheet( nPara ); +} + +void EditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetStyleSheetPool( pSPool ); +} + +SfxStyleSheetPool* EditEngine::GetStyleSheetPool() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetStyleSheetPool(); +} + +void EditEngine::SetWordDelimiters( const XubString& rDelimiters ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->aWordDelimiters = rDelimiters; + if ( pImpEditEngine->aWordDelimiters.Search( CH_FEATURE ) == STRING_NOTFOUND ) + pImpEditEngine->aWordDelimiters.Insert( CH_FEATURE ); +} + +XubString EditEngine::GetWordDelimiters() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->aWordDelimiters; +} + +void EditEngine::SetGroupChars( const XubString& rChars ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + DBG_ASSERT( ( rChars.Len() % 2 ) == 0, "SetGroupChars: Ungerade Anzahl!" ); + pImpEditEngine->aGroupChars = rChars; +} + +XubString EditEngine::GetGroupChars() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->aGroupChars; +} + +void EditEngine::EnablePasteSpecial( sal_Bool bEnable ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( bEnable ) + pImpEditEngine->GetStatus().TurnOnFlags( EE_CNTRL_PASTESPECIAL ); + else + pImpEditEngine->GetStatus().TurnOffFlags( EE_CNTRL_PASTESPECIAL ); +} + +sal_Bool EditEngine::IsPasteSpecialEnabled() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetStatus().AllowPasteSpecial(); +} + +void EditEngine::EnableIdleFormatter( sal_Bool bEnable ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( bEnable ) + pImpEditEngine->GetStatus().TurnOnFlags( EE_CNTRL_DOIDLEFORMAT ); + else + pImpEditEngine->GetStatus().TurnOffFlags( EE_CNTRL_DOIDLEFORMAT); +} + +sal_Bool EditEngine::IsIdleFormatterEnabled() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetStatus().UseIdleFormatter(); +} + +void EditEngine::EraseVirtualDevice() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->EraseVirtualDevice(); +} + +void EditEngine::SetSpeller( Reference< XSpellChecker1 > &xSpeller ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetSpeller( xSpeller ); +} +Reference< XSpellChecker1 > EditEngine::GetSpeller() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetSpeller(); +} +Reference< XHyphenator > EditEngine::GetHyphenator() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetHyphenator(); +} + +void EditEngine::SetHyphenator( Reference< XHyphenator > & xHyph ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetHyphenator( xHyph ); +} + +void EditEngine::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetForbiddenCharsTable( xForbiddenChars ); +} + +vos::ORef<SvxForbiddenCharactersTable> EditEngine::GetForbiddenCharsTable() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetForbiddenCharsTable( FALSE ); +} + + +void EditEngine::SetDefaultLanguage( LanguageType eLang ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetDefaultLanguage( eLang ); +} + +LanguageType EditEngine::GetDefaultLanguage() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetDefaultLanguage(); +} + +sal_Bool __EXPORT EditEngine::SpellNextDocument() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return sal_False; +} + +EESpellState EditEngine::HasSpellErrors() +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( !pImpEditEngine->GetSpeller().is() ) + return EE_SPELL_NOSPELLER; + + return pImpEditEngine->HasSpellErrors(); +} +/*-- 13.10.2003 16:56:23--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void EditEngine::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->StartSpelling(rEditView, bMultipleDoc); +} +/*-- 13.10.2003 16:56:23--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void EditEngine::EndSpelling() +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->EndSpelling(); +} + +/*-- 13.10.2003 16:43:27--------------------------------------------------- + + -----------------------------------------------------------------------*/ +bool EditEngine::SpellSentence(EditView& rView, ::svx::SpellPortions& rToFill, bool bIsGrammarChecking ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->SpellSentence( rView, rToFill, bIsGrammarChecking ); +} +/*-- 08.09.2008 11:38:32--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void EditEngine::PutSpellingToSentenceStart( EditView& rEditView ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->PutSpellingToSentenceStart( rEditView ); +} +/*-- 13.10.2003 16:43:27--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void EditEngine::ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool bIsGrammarChecking ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bIsGrammarChecking ); +} + +sal_Bool EditEngine::HasConvertibleTextPortion( LanguageType nLang ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->HasConvertibleTextPortion( nLang ); +} + +sal_Bool __EXPORT EditEngine::ConvertNextDocument() +{ + DBG_CHKTHIS( EditEngine, 0 ); + return sal_False; +} + +sal_Bool EditEngine::HasText( const SvxSearchItem& rSearchItem ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->HasText( rSearchItem ); +} + +void EditEngine::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetCharStretching( nX, nY ); +} + +void EditEngine::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->GetCharStretching( rX, rY ); +} + +void EditEngine::DoStretchChars( sal_uInt16 nX, sal_uInt16 nY ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->DoStretchChars( nX, nY ); +} + +void EditEngine::SetBigTextObjectStart( sal_uInt16 nStartAtPortionCount ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + pImpEditEngine->SetBigTextObjectStart( nStartAtPortionCount ); +} + +sal_uInt16 EditEngine::GetBigTextObjectStart() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->GetBigTextObjectStart(); +} + +sal_Bool EditEngine::ShouldCreateBigTextObject() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + sal_uInt16 nTextPortions = 0; + sal_uInt16 nParas = pImpEditEngine->GetEditDoc().Count(); + for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ ) + { + ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara]; + nTextPortions = nTextPortions + pParaPortion->GetTextPortions().Count(); + } + return ( nTextPortions >= pImpEditEngine->GetBigTextObjectStart() ) ? sal_True : sal_False; +} + +USHORT EditEngine::GetFieldCount( USHORT nPara ) const +{ + USHORT nFields = 0; + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + if ( pNode ) + { + const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); + for ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ ) + { + EditCharAttrib* pAttr = rAttrs[nAttr]; + if ( pAttr->Which() == EE_FEATURE_FIELD ) + nFields++; + } + } + + return nFields; +} + +EFieldInfo EditEngine::GetFieldInfo( USHORT nPara, USHORT nField ) const +{ + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara ); + if ( pNode ) + { + USHORT nCurrentField = 0; + const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); + for ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ ) + { + EditCharAttrib* pAttr = rAttrs[nAttr]; + if ( pAttr->Which() == EE_FEATURE_FIELD ) + { + if ( nCurrentField == nField ) + { + EFieldInfo aInfo( *(const SvxFieldItem*)pAttr->GetItem(), nPara, pAttr->GetStart() ); + aInfo.aCurrentText = ((EditCharAttribField*)pAttr)->GetFieldValue(); + return aInfo; + } + + nCurrentField++; + } + } + } + return EFieldInfo(); +} + + +sal_Bool EditEngine::UpdateFields() +{ + DBG_CHKTHIS( EditEngine, 0 ); + sal_Bool bChanges = pImpEditEngine->UpdateFields(); + if ( bChanges ) + pImpEditEngine->FormatAndUpdate(); + return bChanges; +} + +void EditEngine::RemoveFields( sal_Bool bKeepFieldText, TypeId aType ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( bKeepFieldText ) + pImpEditEngine->UpdateFields(); + + sal_uInt16 nParas = pImpEditEngine->GetEditDoc().Count(); + for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ ) + { + ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); + for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; ) + { + const EditCharAttrib* pAttr = rAttrs[--nAttr]; + if ( pAttr->Which() == EE_FEATURE_FIELD ) + { + const SvxFieldData* pFldData = ((const SvxFieldItem*)pAttr->GetItem())->GetField(); + if ( pFldData && ( !aType || ( pFldData->IsA( aType ) ) ) ) + { + DBG_ASSERT( pAttr->GetItem()->ISA( SvxFieldItem ), "Kein FeldItem..." ); + EditSelection aSel( EditPaM( pNode, pAttr->GetStart() ), EditPaM( pNode, pAttr->GetEnd() ) ); + String aFieldText = ((EditCharAttribField*)pAttr)->GetFieldValue(); + pImpEditEngine->ImpInsertText( aSel, aFieldText ); + } + } + } + } +} + +sal_Bool EditEngine::HasOnlineSpellErrors() const +{ + DBG_CHKTHIS( EditEngine, 0 ); + sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count(); + for ( sal_uInt16 n = 0; n < nNodes; n++ ) + { + ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + if ( pNode->GetWrongList() && pNode->GetWrongList()->Count() ) + return sal_True; + } + return sal_False; +} + +void EditEngine::CompleteOnlineSpelling() +{ + DBG_CHKTHIS( EditEngine, 0 ); + if ( pImpEditEngine->GetStatus().DoOnlineSpelling() ) + { + if( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatAndUpdate(); + + pImpEditEngine->StopOnlineSpellTimer(); + pImpEditEngine->DoOnlineSpelling( 0, sal_True, sal_False ); + } +} + +USHORT EditEngine::FindParagraph( long nDocPosY ) +{ + return pImpEditEngine->GetParaPortions().FindParagraph( nDocPosY ); +} + +EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const +{ + EPosition aPos; + // From the point of the API, this is const.... + EditPaM aPaM = ((EditEngine*)this)->pImpEditEngine->GetPaM( rDocPos, FALSE ); + if ( aPaM.GetNode() ) + { + aPos.nPara = pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() ); + aPos.nIndex = aPaM.GetIndex(); + } + return aPos; +} + +Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const +{ + Rectangle aBounds; + ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( rPos.nPara ); + + // #109151# Check against index, not paragraph + if ( pNode && ( rPos.nIndex < pNode->Len() ) ) + { + aBounds = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex ), GETCRSR_TXTONLY ); + Rectangle aR2 = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex+1 ), GETCRSR_TXTONLY|GETCRSR_ENDOFLINE ); + if ( aR2.Right() > aBounds.Right() ) + aBounds.Right() = aR2.Right(); + } + return aBounds; +} + +ParagraphInfos EditEngine::GetParagraphInfos( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + // Funktioniert nur, wenn nicht bereits in der Formatierung... + if ( !pImpEditEngine->IsFormatted() ) + pImpEditEngine->FormatDoc(); + + ParagraphInfos aInfos; + aInfos.bValid = pImpEditEngine->IsFormatted(); + if ( pImpEditEngine->IsFormatted() ) + { + ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara]; + EditLine* pLine = (pParaPortion && pParaPortion->GetLines().Count()) ? + pParaPortion->GetLines().GetObject( 0 ) : NULL; + DBG_ASSERT( pParaPortion && pLine, "GetParagraphInfos - Paragraph out of range" ); + if ( pParaPortion && pLine ) + { + aInfos.nParaHeight = (USHORT)pParaPortion->GetHeight(); + aInfos.nLines = pParaPortion->GetLines().Count(); + aInfos.nFirstLineStartX = pLine->GetStartPosX(); + aInfos.nFirstLineOffset = pParaPortion->GetFirstLineOffset(); + aInfos.nFirstLineHeight = pLine->GetHeight(); + aInfos.nFirstLineTextHeight = pLine->GetTxtHeight(); + aInfos.nFirstLineMaxAscent = pLine->GetMaxAscent(); + } + } + return aInfos; +} + +::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > + EditEngine::CreateTransferable( const ESelection& rSelection ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); + return pImpEditEngine->CreateTransferable( aSel ); +} + +// ===================================================================== +// ====================== Virtuelle Methoden ======================= +// ===================================================================== +void __EXPORT EditEngine::DrawingText( const Point&, const XubString&, USHORT, USHORT, + const sal_Int32*, const SvxFont&, sal_uInt16, sal_uInt16, BYTE, + const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool, bool, + const ::com::sun::star::lang::Locale*, const Color&, const Color&) + +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +void __EXPORT EditEngine::PaintingFirstLine( sal_uInt16, const Point&, long, const Point&, short, OutputDevice* ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +void __EXPORT EditEngine::ParagraphInserted( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( GetNotifyHdl().IsSet() ) + { + EENotify aNotify( EE_NOTIFY_PARAGRAPHINSERTED ); + aNotify.pEditEngine = this; + aNotify.nParagraph = nPara; + pImpEditEngine->CallNotify( aNotify ); + } +} + +void __EXPORT EditEngine::ParagraphDeleted( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( GetNotifyHdl().IsSet() ) + { + EENotify aNotify( EE_NOTIFY_PARAGRAPHREMOVED ); + aNotify.pEditEngine = this; + aNotify.nParagraph = nPara; + pImpEditEngine->CallNotify( aNotify ); + } +} +void EditEngine::ParagraphConnected( USHORT /*nLeftParagraph*/, USHORT /*nRightParagraph*/ ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +sal_Bool __EXPORT EditEngine::FormattingParagraph( sal_uInt16 ) +{ + // return sal_True, wenn die Attribute geaendert wurden... + DBG_CHKTHIS( EditEngine, 0 ); + return sal_False; +} + +void __EXPORT EditEngine::ParaAttribsChanged( sal_uInt16 /* nParagraph */ ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +void __EXPORT EditEngine::StyleSheetChanged( SfxStyleSheet* /* pStyle */ ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +void __EXPORT EditEngine::ParagraphHeightChanged( sal_uInt16 nPara ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + + if ( GetNotifyHdl().IsSet() ) + { + EENotify aNotify( EE_NOTIFY_TEXTHEIGHTCHANGED ); + aNotify.pEditEngine = this; + aNotify.nParagraph = nPara; + pImpEditEngine->CallNotify( aNotify ); + } +} + +XubString __EXPORT EditEngine::GetUndoComment( sal_uInt16 nId ) const +{ + DBG_CHKTHIS( EditEngine, 0 ); + XubString aComment; + switch ( nId ) + { + case EDITUNDO_REMOVECHARS: + case EDITUNDO_CONNECTPARAS: + case EDITUNDO_REMOVEFEATURE: + case EDITUNDO_DELCONTENT: + case EDITUNDO_DELETE: + case EDITUNDO_CUT: + aComment = XubString( EditResId( RID_EDITUNDO_DEL ) ); + break; + case EDITUNDO_MOVEPARAGRAPHS: + case EDITUNDO_MOVEPARAS: + case EDITUNDO_DRAGANDDROP: + aComment = XubString( EditResId( RID_EDITUNDO_MOVE ) ); + break; + case EDITUNDO_INSERTFEATURE: + case EDITUNDO_SPLITPARA: + case EDITUNDO_INSERTCHARS: + case EDITUNDO_PASTE: + case EDITUNDO_INSERT: + case EDITUNDO_READ: + aComment = XubString( EditResId( RID_EDITUNDO_INSERT ) ); + break; + case EDITUNDO_SRCHANDREPL: + case EDITUNDO_REPLACEALL: + aComment = XubString( EditResId( RID_EDITUNDO_REPLACE ) ); + break; + case EDITUNDO_ATTRIBS: + case EDITUNDO_PARAATTRIBS: + case EDITUNDO_STRETCH: + aComment = XubString( EditResId( RID_EDITUNDO_SETATTRIBS ) ); + break; + case EDITUNDO_RESETATTRIBS: + aComment = XubString( EditResId( RID_EDITUNDO_RESETATTRIBS ) ); + break; + case EDITUNDO_STYLESHEET: + aComment = XubString( EditResId( RID_EDITUNDO_SETSTYLE ) ); + break; + case EDITUNDO_TRANSLITERATE: + aComment = XubString( EditResId( RID_EDITUNDO_TRANSLITERATE ) ); + break; + case EDITUNDO_INDENTBLOCK: + case EDITUNDO_UNINDENTBLOCK: + aComment = XubString( EditResId( RID_EDITUNDO_INDENT ) ); + break; + } + return aComment; +} + +Rectangle EditEngine::GetBulletArea( sal_uInt16 ) +{ + return Rectangle( Point(), Point() ); +} + +XubString __EXPORT EditEngine::CalcFieldValue( const SvxFieldItem&, sal_uInt16, sal_uInt16, Color*&, Color*& ) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return ' '; +} + +void __EXPORT EditEngine::FieldClicked( const SvxFieldItem&, sal_uInt16, sal_uInt16 ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +void __EXPORT EditEngine::FieldSelected( const SvxFieldItem&, sal_uInt16, sal_uInt16 ) +{ + DBG_CHKTHIS( EditEngine, 0 ); +} + +// ===================================================================== +// ====================== Statische Methoden ======================= +// ===================================================================== +SfxItemPool* EditEngine::CreatePool( sal_Bool bPersistentRefCounts ) +{ + SfxItemPool* pPool = new EditEngineItemPool( bPersistentRefCounts ); + return pPool; +} + +SfxItemPool& EditEngine::GetGlobalItemPool() +{ + if ( !pGlobalPool ) + pGlobalPool = CreatePool(); + return *pGlobalPool; +} + +sal_uInt32 EditEngine::RegisterClipboardFormatName() +{ + static sal_uInt32 nFormat = 0; + if ( !nFormat ) + nFormat = SotExchange::RegisterFormatName( String( RTL_CONSTASCII_USTRINGPARAM( "EditEngineFormat" ) ) ); + return nFormat; +} + +sal_uInt16 EditEngine::GetAvailableSearchOptions() +{ + return SEARCH_OPTIONS_SEARCH | SEARCH_OPTIONS_REPLACE | + SEARCH_OPTIONS_REPLACE_ALL | SEARCH_OPTIONS_WHOLE_WORDS | + SEARCH_OPTIONS_BACKWARDS | SEARCH_OPTIONS_REG_EXP | + SEARCH_OPTIONS_EXACT | SEARCH_OPTIONS_SELECTION; +} + +void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const Font& rFont ) +{ + SvxFont aSvxFont( rFont ); + SetFontInfoInItemSet( rSet, aSvxFont ); + +} + +void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const SvxFont& rFont ) +{ + rSet.Put( SvxLanguageItem( rFont.GetLanguage(), EE_CHAR_LANGUAGE ) ); + rSet.Put( SvxFontItem( rFont.GetFamily(), rFont.GetName(), XubString(), rFont.GetPitch(), rFont.GetCharSet(), EE_CHAR_FONTINFO ) ); + rSet.Put( SvxFontHeightItem( rFont.GetSize().Height(), 100, EE_CHAR_FONTHEIGHT ) ); + rSet.Put( SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ) ); + rSet.Put( SvxShadowedItem( rFont.IsShadow(), EE_CHAR_SHADOW ) ); + rSet.Put( SvxEscapementItem( rFont.GetEscapement(), rFont.GetPropr(), EE_CHAR_ESCAPEMENT ) ); + rSet.Put( SvxWeightItem( rFont.GetWeight(), EE_CHAR_WEIGHT ) ); + rSet.Put( SvxColorItem( rFont.GetColor(), EE_CHAR_COLOR ) ); + rSet.Put( SvxUnderlineItem( rFont.GetUnderline(), EE_CHAR_UNDERLINE ) ); + rSet.Put( SvxOverlineItem( rFont.GetOverline(), EE_CHAR_OVERLINE ) ); + rSet.Put( SvxCrossedOutItem( rFont.GetStrikeout(), EE_CHAR_STRIKEOUT ) ); + rSet.Put( SvxPostureItem( rFont.GetItalic(), EE_CHAR_ITALIC ) ); + rSet.Put( SvxContourItem( rFont.IsOutline(), EE_CHAR_OUTLINE ) ); + rSet.Put( SvxAutoKernItem( rFont.IsKerning(), EE_CHAR_PAIRKERNING ) ); + rSet.Put( SvxKerningItem( rFont.GetFixKerning(), EE_CHAR_KERNING ) ); + rSet.Put( SvxWordLineModeItem( rFont.IsWordLineMode(), EE_CHAR_WLM ) ); + rSet.Put( SvxEmphasisMarkItem( rFont.GetEmphasisMark(), EE_CHAR_EMPHASISMARK ) ); + rSet.Put( SvxCharReliefItem( rFont.GetRelief(), EE_CHAR_RELIEF ) ); +} + +Font EditEngine::CreateFontFromItemSet( const SfxItemSet& rItemSet, USHORT nScriptType ) +{ + SvxFont aFont; + CreateFont( aFont, rItemSet, true, nScriptType ); + return aFont; +} + +// Maybe we can remove the next two methods, check after 6.x +Font EditEngine::CreateFontFromItemSet( const SfxItemSet& rItemSet ) +{ + return CreateSvxFontFromItemSet( rItemSet ); +} + +SvxFont EditEngine::CreateSvxFontFromItemSet( const SfxItemSet& rItemSet ) +{ + SvxFont aFont; + CreateFont( aFont, rItemSet ); + return aFont; +} + +sal_Bool EditEngine::DoesKeyMoveCursor( const KeyEvent& rKeyEvent ) +{ + sal_Bool bDoesMove = sal_False; + + switch ( rKeyEvent.GetKeyCode().GetCode() ) + { + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + case KEY_HOME: + case KEY_END: + case KEY_PAGEUP: + case KEY_PAGEDOWN: + { + if ( !rKeyEvent.GetKeyCode().IsMod2() ) + bDoesMove = sal_True; + } + break; + } + return bDoesMove; +} + +sal_Bool EditEngine::DoesKeyChangeText( const KeyEvent& rKeyEvent ) +{ + sal_Bool bDoesChange = sal_False; + + KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); + if ( eFunc != KEYFUNC_DONTKNOW ) + { + switch ( eFunc ) + { + case KEYFUNC_UNDO: + case KEYFUNC_REDO: + case KEYFUNC_CUT: + case KEYFUNC_PASTE: bDoesChange = sal_True; + break; + default: // wird dann evtl. unten bearbeitet. + eFunc = KEYFUNC_DONTKNOW; + } + } + if ( eFunc == KEYFUNC_DONTKNOW ) + { + switch ( rKeyEvent.GetKeyCode().GetCode() ) + { + case KEY_DELETE: + case KEY_BACKSPACE: bDoesChange = sal_True; + break; + case KEY_RETURN: + case KEY_TAB: + { + if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) + bDoesChange = sal_True; + } + break; + default: + { + bDoesChange = IsSimpleCharInput( rKeyEvent ); + } + } + } + return bDoesChange; +} + +sal_Bool EditEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent ) +{ + if( EditEngine::IsPrintable( rKeyEvent.GetCharCode() ) && + ( KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) ) && + ( KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) ) ) + { + return sal_True; + } + return sal_False; +} + +// Mal in den Outliner schieben... +void EditEngine::ImportBulletItem( SvxNumBulletItem& /*rNumBullet*/, sal_uInt16 /*nLevel*/, + const SvxBulletItem* /*pOldBullet*/, const SvxLRSpaceItem* /*pOldLRSpace*/ ) +{ +/* TL_NFLR + if ( pOldBullet || pOldLRSpace ) + { + // Numberformat dynamisch, weil Zuweisungsoperator nicht implementiert. + + // Altes NumBulletItem nur uebernehmen, wenn kein altes BulletItem + const SvxNumberFormat* pFmt = ( !pOldBullet && ( rNumBullet.GetNumRule()->GetLevelCount() > nLevel ) ) ? + rNumBullet.GetNumRule()->Get( nLevel ) : NULL; + SvxNumberFormat* pNumberFormat = pFmt + ? new SvxNumberFormat( *pFmt ) + : new SvxNumberFormat( SVX_NUM_NUMBER_NONE ); + if ( pOldBullet ) + { + // Style + SvxExtNumType eNumType; + switch( pOldBullet->GetStyle() ) + { + case BS_BMP: eNumType = SVX_NUM_BITMAP; break; + case BS_BULLET: eNumType = SVX_NUM_CHAR_SPECIAL; break; + case BS_ROMAN_BIG: eNumType = SVX_NUM_ROMAN_UPPER; break; + case BS_ROMAN_SMALL: eNumType = SVX_NUM_ROMAN_LOWER; break; + case BS_ABC_BIG: eNumType = SVX_NUM_CHARS_UPPER_LETTER; break; + case BS_ABC_SMALL: eNumType = SVX_NUM_CHARS_LOWER_LETTER; break; + case BS_123: eNumType = SVX_NUM_ARABIC; break; + default: eNumType = SVX_NUM_NUMBER_NONE; break; + } + pNumberFormat->SetNumberingType( + sal::static_int_cast< sal_Int16 >( eNumType ) ); + + // Justification + SvxAdjust eAdjust; + switch( pOldBullet->GetJustification() & (BJ_HRIGHT|BJ_HCENTER|BJ_HLEFT) ) + { + case BJ_HRIGHT: eAdjust = SVX_ADJUST_RIGHT; break; + case BJ_HCENTER: eAdjust = SVX_ADJUST_CENTER; break; + default: eAdjust = SVX_ADJUST_LEFT; break; + } + pNumberFormat->SetNumAdjust(eAdjust); + + // Prefix/Suffix + pNumberFormat->SetPrefix( pOldBullet->GetPrevText() ); + pNumberFormat->SetSuffix( pOldBullet->GetFollowText() ); + + //Font + if ( eNumType != SVX_NUM_BITMAP ) + { + Font aTmpFont = pOldBullet->GetFont(); + pNumberFormat->SetBulletFont( &aTmpFont ); + } + + // Color + pNumberFormat->SetBulletColor( pOldBullet->GetFont().GetColor() ); + + // Start + pNumberFormat->SetStart( pOldBullet->GetStart() ); + + // Scale + pNumberFormat->SetBulletRelSize( pOldBullet->GetScale() ); + + // Bullet/Bitmap + if( eNumType == SVX_NUM_CHAR_SPECIAL ) + { + pNumberFormat->SetBulletChar( pOldBullet->GetSymbol() ); + } + else if( eNumType == SVX_NUM_BITMAP ) + { + SvxBrushItem aBItem( Graphic( pOldBullet->GetBitmap() ), GPOS_NONE, SID_ATTR_BRUSH ); + pNumberFormat->SetGraphicBrush( &aBItem ); + } + } + + // Einzug und Erstzeileneinzug +//TL_NFLR if ( pOldLRSpace ) +//TL_NFLR { +//TL_NFLR short nLSpace = (short)pOldLRSpace->GetTxtLeft(); +//TL_NFLR pNumberFormat->SetLSpace( nLSpace ); +//TL_NFLR pNumberFormat->SetAbsLSpace( nLSpace ); +//TL_NFLR pNumberFormat->SetFirstLineOffset( pOldLRSpace->GetTxtFirstLineOfst() ); +//TL_NFLR } + + rNumBullet.GetNumRule()->SetLevel( nLevel, *pNumberFormat ); + delete pNumberFormat; + } +*/ +} + +BOOL EditEngine::HasValidData( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& rTransferable ) +{ + BOOL bValidData = FALSE; + + if ( rTransferable.is() ) + { + // Every application that copies rtf or any other text format also copies plain text into the clipboard.... + datatransfer::DataFlavor aFlavor; + SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); + bValidData = rTransferable->isDataFlavorSupported( aFlavor ); + } + + return bValidData; +} + +/** sets a link that is called at the beginning of a drag operation at an edit view */ +void EditEngine::SetBeginDropHdl( const Link& rLink ) +{ + pImpEditEngine->SetBeginDropHdl( rLink ); +} + +Link EditEngine::GetBeginDropHdl() const +{ + return pImpEditEngine->GetBeginDropHdl(); +} + +/** sets a link that is called at the end of a drag operation at an edit view */ +void EditEngine::SetEndDropHdl( const Link& rLink ) +{ + pImpEditEngine->SetEndDropHdl( rLink ); +} + +Link EditEngine::GetEndDropHdl() const +{ + return pImpEditEngine->GetEndDropHdl(); +} + +void EditEngine::SetFirstWordCapitalization( BOOL bCapitalize ) +{ + pImpEditEngine->SetFirstWordCapitalization( bCapitalize ); +} + +BOOL EditEngine::IsFirstWordCapitalization() const +{ + return pImpEditEngine->IsFirstWordCapitalization(); +} + + +// --------------------------------------------------- + + +EFieldInfo::EFieldInfo() +{ + pFieldItem = NULL; +} + + +EFieldInfo::EFieldInfo( const SvxFieldItem& rFieldItem, USHORT nPara, USHORT nPos ) : aPosition( nPara, nPos ) +{ + pFieldItem = new SvxFieldItem( rFieldItem ); +} + +EFieldInfo::~EFieldInfo() +{ + delete pFieldItem; +} + +EFieldInfo::EFieldInfo( const EFieldInfo& rFldInfo ) +{ + *this = rFldInfo; +} + +EFieldInfo& EFieldInfo::operator= ( const EFieldInfo& rFldInfo ) +{ + if( this == &rFldInfo ) + return *this; + + pFieldItem = rFldInfo.pFieldItem ? new SvxFieldItem( *rFldInfo.pFieldItem ) : 0; + aCurrentText = rFldInfo.aCurrentText; + aPosition = rFldInfo.aPosition; + + return *this; +} diff --git a/editeng/source/editeng/editeng.src b/editeng/source/editeng/editeng.src new file mode 100644 index 0000000000..1204ba1661 --- /dev/null +++ b/editeng/source/editeng/editeng.src @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editeng.src,v $ + * $Revision: 1.47 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <editeng.hrc> +#include <helpid.hrc> + +String RID_EDITUNDO_DEL +{ + Text [ en-US ] = "Delete" ; +}; + +String RID_EDITUNDO_MOVE +{ + Text [ en-US ] = "Move" ; +}; + +String RID_EDITUNDO_INSERT +{ + Text [ en-US ] = "Insert" ; +}; + +String RID_EDITUNDO_REPLACE +{ + Text [ en-US ] = "Replace" ; +}; + +String RID_EDITUNDO_SETATTRIBS +{ + Text [ en-US ] = "Apply attributes" ; +}; + +String RID_EDITUNDO_RESETATTRIBS +{ + Text [ en-US ] = "Reset attributes" ; +}; + +String RID_EDITUNDO_INDENT +{ + Text [ en-US ] = "Indent" ; +}; + +String RID_EDITUNDO_SETSTYLE +{ + Text [ en-US ] = "Apply Styles" ; +}; + +String RID_EDITUNDO_TRANSLITERATE +{ + Text [ en-US ] = "Case/Characters"; +}; + + +Menu RID_MENU_SPELL +{ + ItemList = + { + MenuItem + { + Identifier = MN_SPELLING ; + HelpId = HID_EDITENG_SPELLER_START; + Text [ en-US ] = "~Spellcheck..." ; + }; + MenuItem + { + Identifier = MN_INSERT ; + HelpId = HID_EDITENG_SPELLER_ADDWORD; + SubMenu = Menu + { + }; + Text [ en-US ] = "~Add" ; + }; + MenuItem + { + Identifier = MN_IGNORE ; + HelpId = HID_EDITENG_SPELLER_IGNORE; + Text [ en-US ] = "Ignore All" ; + }; + MenuItem + { + Identifier = MN_AUTOCORR ; + HelpId = HID_EDITENG_SPELLER_AUTOCORRECT; + SubMenu = Menu + { + }; + Text [ en-US ] = "AutoCorrect" ; + }; + }; +}; + + +String RID_STR_WORD +{ + Text [ en-US ] = "Word is %x"; +}; + +String RID_STR_PARAGRAPH +{ + Text [ en-US ] = "Paragraph is %x"; +}; + diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx new file mode 100644 index 0000000000..c224410ca0 --- /dev/null +++ b/editeng/source/editeng/editobj.cxx @@ -0,0 +1,1728 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: editobj.cxx,v $ + * $Revision: 1.30 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <vcl/wrkwin.hxx> +#include <vcl/dialog.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#define ENABLE_STRING_STREAM_OPERATORS +#include <tools/stream.hxx> + +#include <editobj2.hxx> +#include <editeng/editdata.hxx> +#include <editattr.hxx> +#include <editeng/editeng.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/cscoitem.hxx> +#include <editeng/flditem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/bulitem.hxx> +#include <editeng/numitem.hxx> +#include <editeng/brshitem.hxx> +#include <vcl/graph.hxx> +#include <svl/intitem.hxx> +#include <unotools/fontcvt.hxx> +#include <tools/tenccvt.hxx> + +DBG_NAME( EE_EditTextObject ) +DBG_NAME( XEditAttribute ) + +//-------------------------------------------------------------- + +BOOL lcl_CreateBulletItem( const SvxNumBulletItem& rNumBullet, USHORT nLevel, SvxBulletItem& rBullet ) +{ + const SvxNumberFormat* pFmt = rNumBullet.GetNumRule()->Get( nLevel ); + if ( pFmt ) + { + rBullet.SetWidth( (-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance() ); + rBullet.SetSymbol( pFmt->GetBulletChar() ); + rBullet.SetPrevText( pFmt->GetPrefix() ); + rBullet.SetFollowText( pFmt->GetSuffix() ); + rBullet.SetStart( pFmt->GetStart() ); + rBullet.SetScale( pFmt->GetBulletRelSize() ); + + Font aBulletFont( rBullet.GetFont() ); + if ( pFmt->GetBulletFont() ) + aBulletFont = *pFmt->GetBulletFont(); + aBulletFont.SetColor( pFmt->GetBulletColor() ); + rBullet.SetFont( aBulletFont ); + + if ( pFmt->GetBrush() && pFmt->GetBrush()->GetGraphic() ) + { + Bitmap aBmp( pFmt->GetBrush()->GetGraphic()->GetBitmap() ); + aBmp.SetPrefSize( pFmt->GetGraphicSize() ); + aBmp.SetPrefMapMode( MAP_100TH_MM ); + rBullet.SetBitmap( aBmp ); + } + + switch ( pFmt->GetNumberingType() ) + { + case SVX_NUM_CHARS_UPPER_LETTER: + case SVX_NUM_CHARS_UPPER_LETTER_N: + rBullet.SetStyle( BS_ABC_BIG ); + break; + case SVX_NUM_CHARS_LOWER_LETTER: + case SVX_NUM_CHARS_LOWER_LETTER_N: + rBullet.SetStyle( BS_ABC_SMALL ); + break; + case SVX_NUM_ROMAN_UPPER: + rBullet.SetStyle( BS_ROMAN_BIG ); + break; + case SVX_NUM_ROMAN_LOWER: + rBullet.SetStyle( BS_ROMAN_SMALL ); + break; + case SVX_NUM_ARABIC: + rBullet.SetStyle( BS_123 ); + break; + case SVX_NUM_NUMBER_NONE: + rBullet.SetStyle( BS_NONE ); + break; + case SVX_NUM_CHAR_SPECIAL: + rBullet.SetStyle( BS_BULLET ); + break; + case SVX_NUM_PAGEDESC: + DBG_ERROR( "Unknown: SVX_NUM_PAGEDESC" ); + rBullet.SetStyle( BS_BULLET ); + break; + case SVX_NUM_BITMAP: + rBullet.SetStyle( BS_BMP ); + break; + default: + DBG_ERROR( "Unknown NumType" ); + } + + switch ( pFmt->GetNumAdjust() ) + { + case SVX_ADJUST_LEFT: + rBullet.SetJustification( BJ_VCENTER|BJ_HLEFT ); + break; + case SVX_ADJUST_RIGHT: + rBullet.SetJustification( BJ_VCENTER|BJ_HRIGHT ); + break; + case SVX_ADJUST_CENTER: + rBullet.SetJustification( BJ_VCENTER|BJ_HCENTER ); + break; + default: + DBG_ERROR( "Unknown or invalid NumAdjust" ); + } + } + return pFmt ? TRUE : FALSE; +} + + +XEditAttribute* MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, USHORT nStart, USHORT nEnd ) +{ + // das neue Attribut im Pool anlegen + const SfxPoolItem& rNew = rPool.Put( rItem ); + + XEditAttribute* pNew = new XEditAttribute( rNew, nStart, nEnd ); + return pNew; +} + + +XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr ) +{ + DBG_CTOR( XEditAttribute, 0 ); + pItem = &rAttr; + nStart = 0; + nEnd = 0; +} + +XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, USHORT nS, USHORT nE ) +{ + DBG_CTOR( XEditAttribute, 0 ); + pItem = &rAttr; + nStart = nS; + nEnd = nE; +} + +XEditAttribute::~XEditAttribute() +{ + DBG_DTOR( XEditAttribute, 0 ); + pItem = 0; // Gehoert dem Pool. +} + +XEditAttribute* XEditAttributeList::FindAttrib( USHORT _nWhich, USHORT nChar ) const +{ + for ( USHORT n = Count(); n; ) + { + XEditAttribute* pAttr = GetObject( --n ); + if( ( pAttr->GetItem()->Which() == _nWhich ) && ( pAttr->GetStart() <= nChar ) && ( pAttr->GetEnd() > nChar ) ) + return pAttr; + } + return NULL; +} + +ContentInfo::ContentInfo( SfxItemPool& rPool ) : aParaAttribs( rPool, EE_PARA_START, EE_CHAR_END ) +{ + eFamily = SFX_STYLE_FAMILY_PARA; + pWrongs = NULL; +/* cl removed because not needed anymore since binfilter + pTempLoadStoreInfos = NULL; +*/ +} + +// Richtiger CopyCTOR unsinning, weil ich mit einem anderen Pool arbeiten muss! +ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ) + : aParaAttribs( rPoolToUse, EE_PARA_START, EE_CHAR_END ) +{ + pWrongs = NULL; +/* cl removed because not needed anymore since binfilter + pTempLoadStoreInfos = NULL; +*/ + if ( rCopyFrom.GetWrongList() ) + pWrongs = rCopyFrom.GetWrongList()->Clone(); + // So sollten die Items im richtigen Pool landen! + aParaAttribs.Set( rCopyFrom.GetParaAttribs() ); + aText = rCopyFrom.GetText(); + aStyle = rCopyFrom.GetStyle(); + eFamily = rCopyFrom.GetFamily(); + + // Attribute kopieren... + for ( USHORT n = 0; n < rCopyFrom.GetAttribs().Count(); n++ ) + { + XEditAttribute* pAttr = rCopyFrom.GetAttribs().GetObject( n ); + XEditAttribute* pMyAttr = MakeXEditAttribute( rPoolToUse, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() ); + aAttribs.Insert( pMyAttr, aAttribs.Count() ); + } + + // Wrongs + pWrongs = NULL; +#ifndef SVX_LIGHT + if ( rCopyFrom.GetWrongList() ) + pWrongs = rCopyFrom.GetWrongList()->Clone(); +#endif // !SVX_LIGHT +} + +ContentInfo::~ContentInfo() +{ + for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) + { + XEditAttribute* pAttr = aAttribs.GetObject(nAttr); + // Item aus Pool entfernen! + aParaAttribs.GetPool()->Remove( *pAttr->GetItem() ); + delete pAttr; + } + aAttribs.Remove( 0, aAttribs.Count() ); +#ifndef SVX_LIGHT + delete pWrongs; +#endif +} + +/* cl removed because not needed anymore since binfilter +void ContentInfo::CreateLoadStoreTempInfos() +{ + delete pTempLoadStoreInfos; + pTempLoadStoreInfos = new LoadStoreTempInfos; +} + +void ContentInfo::DestroyLoadStoreTempInfos() +{ + delete pTempLoadStoreInfos; + pTempLoadStoreInfos = NULL; +} +*/ + +// #i102062# +bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const +{ + if(GetWrongList() == rCompare.GetWrongList()) + return true; + + if(!GetWrongList() || !rCompare.GetWrongList()) + return false; + + return (*GetWrongList() == *rCompare.GetWrongList()); +} + +bool ContentInfo::operator==( const ContentInfo& rCompare ) const +{ + if( (aText == rCompare.aText) && + (aStyle == rCompare.aStyle ) && + (aAttribs.Count() == rCompare.aAttribs.Count() ) && + (eFamily == rCompare.eFamily ) && + (aParaAttribs == rCompare.aParaAttribs ) ) + { + const USHORT nCount = aAttribs.Count(); + if( nCount == rCompare.aAttribs.Count() ) + { + USHORT n; + for( n = 0; n < nCount; n++ ) + { + if( !(*aAttribs.GetObject(n) == *rCompare.aAttribs.GetObject(n)) ) + return false; + } + + return true; + } + } + + return false; +} + +EditTextObject::EditTextObject( USHORT n) +{ + DBG_CTOR( EE_EditTextObject, 0 ); + nWhich = n; +} + +EditTextObject::EditTextObject( const EditTextObject& r ) +{ + DBG_CTOR( EE_EditTextObject, 0 ); + nWhich = r.nWhich; +} + +__EXPORT EditTextObject::~EditTextObject() +{ + DBG_DTOR( EE_EditTextObject, 0 ); +} + +USHORT EditTextObject::GetParagraphCount() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +XubString EditTextObject::GetText( USHORT /* nParagraph */ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return XubString(); +} + +void EditTextObject::Insert( const EditTextObject& /* rObj */, USHORT /* nPara */) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +EditTextObject* EditTextObject::CreateTextObject( USHORT /*nPara*/, USHORT /*nParas*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +void EditTextObject::RemoveParagraph( USHORT /*nPara*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL EditTextObject::HasPortionInfo() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +void EditTextObject::ClearPortionInfo() +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL EditTextObject::HasOnlineSpellErrors() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +BOOL EditTextObject::HasCharAttribs( USHORT ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +void EditTextObject::GetCharAttribs( USHORT /*nPara*/, EECharAttribArray& /*rLst*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +void EditTextObject::MergeParaAttribs( const SfxItemSet& /*rAttribs*/, USHORT /*nStart*/, USHORT /*nEnd*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL EditTextObject::IsFieldObject() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +const SvxFieldItem* EditTextObject::GetField() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +BOOL EditTextObject::HasField( TypeId /*aType*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +SfxItemSet EditTextObject::GetParaAttribs( USHORT /*nPara*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return SfxItemSet( *(SfxItemPool*)NULL ); +} + +void EditTextObject::SetParaAttribs( USHORT /*nPara*/, const SfxItemSet& /*rAttribs*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL EditTextObject::RemoveCharAttribs( USHORT /*nWhich*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +BOOL EditTextObject::RemoveParaAttribs( USHORT /*nWhich*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +BOOL EditTextObject::HasStyleSheet( const XubString& /*rName*/, SfxStyleFamily /*eFamily*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +void EditTextObject::GetStyleSheet( USHORT /*nPara*/, XubString& /*rName*/, SfxStyleFamily& /*eFamily*/ ) const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +void EditTextObject::SetStyleSheet( USHORT /*nPara*/, const XubString& /*rName*/, const SfxStyleFamily& /*eFamily*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL __EXPORT EditTextObject::ChangeStyleSheets( const XubString&, SfxStyleFamily, + const XubString&, SfxStyleFamily ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +void __EXPORT EditTextObject::ChangeStyleSheetName( SfxStyleFamily /*eFamily*/, + const XubString& /*rOldName*/, const XubString& /*rNewName*/ ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +USHORT EditTextObject::GetUserType() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +void EditTextObject::SetUserType( USHORT ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +ULONG EditTextObject::GetObjectSettings() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +void EditTextObject::SetObjectSettings( ULONG ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); +} + +BOOL EditTextObject::IsVertical() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return FALSE; +} + +void EditTextObject::SetVertical( BOOL bVertical ) +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + ((BinTextObject*)this)->SetVertical( bVertical ); +} + +USHORT EditTextObject::GetScriptType() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return ((const BinTextObject*)this)->GetScriptType(); +} + + +BOOL EditTextObject::Store( SvStream& rOStream ) const +{ + if ( rOStream.GetError() ) + return FALSE; + + // Vorspann: + sal_Size nStartPos = rOStream.Tell(); + + rOStream << (USHORT)Which(); + + sal_uInt32 nStructSz = 0; + rOStream << nStructSz; + + // Eigene Daten: + StoreData( rOStream ); + + // Nachspann: + sal_Size nEndPos = rOStream.Tell(); + nStructSz = nEndPos - nStartPos - sizeof( nWhich ) - sizeof( nStructSz ); + rOStream.Seek( nStartPos + sizeof( nWhich ) ); + rOStream << nStructSz; + rOStream.Seek( nEndPos ); + + return rOStream.GetError() ? FALSE : TRUE; +} + +EditTextObject* EditTextObject::Create( SvStream& rIStream, SfxItemPool* pGlobalTextObjectPool ) +{ + ULONG nStartPos = rIStream.Tell(); + + // Ertmal sehen, was fuer ein Object... + USHORT nWhich; + rIStream >> nWhich; + + sal_uInt32 nStructSz; + rIStream >> nStructSz; + + DBG_ASSERT( ( nWhich == 0x22 /*EE_FORMAT_BIN300*/ ) || ( nWhich == EE_FORMAT_BIN ), "CreateTextObject: Unbekanntes Objekt!" ); + + if ( rIStream.GetError() ) + return NULL; + + EditTextObject* pTxtObj = NULL; + switch ( nWhich ) + { + case 0x22 /*BIN300*/: pTxtObj = new BinTextObject( 0 ); + ((BinTextObject*)pTxtObj)->CreateData300( rIStream ); + break; + case EE_FORMAT_BIN: pTxtObj = new BinTextObject( pGlobalTextObjectPool ); + pTxtObj->CreateData( rIStream ); + break; + default: + { + // Wenn ich das Format nicht kenne, ueberlese ich den Inhalt: + rIStream.SetError( EE_READWRITE_WRONGFORMAT ); + } + } + + // Sicherstellen, dass der Stream an der richtigen Stelle hinterlassen wird. + sal_Size nFullSz = sizeof( nWhich ) + sizeof( nStructSz ) + nStructSz; + rIStream.Seek( nStartPos + nFullSz ); + return pTxtObj; +} + +void EditTextObject::Skip( SvStream& rIStream ) +{ + sal_Size nStartPos = rIStream.Tell(); + + USHORT _nWhich; + rIStream >> _nWhich; + + sal_uInt32 nStructSz; + rIStream >> nStructSz; + + sal_Size nFullSz = sizeof( _nWhich ) + sizeof( nStructSz ) + nStructSz; + rIStream.Seek( nStartPos + nFullSz ); +} + +void __EXPORT EditTextObject::StoreData( SvStream& ) const +{ + DBG_ERROR( "StoreData: Basisklasse!" ); +} + +void __EXPORT EditTextObject::CreateData( SvStream& ) +{ + DBG_ERROR( "CreateData: Basisklasse!" ); +} + +USHORT EditTextObject::GetVersion() const +{ + DBG_ERROR( "V-Methode direkt vom EditTextObject!" ); + return 0; +} + +bool EditTextObject::operator==( const EditTextObject& rCompare ) const +{ + return static_cast< const BinTextObject* >( this )->operator==( static_cast< const BinTextObject& >( rCompare ) ); +} + +// #i102062# +bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const +{ + return static_cast< const BinTextObject* >(this)->isWrongListEqual(static_cast< const BinTextObject& >(rCompare)); +} + +// from SfxItemPoolUser +void BinTextObject::ObjectInDestruction(const SfxItemPool& rSfxItemPool) +{ + if(!bOwnerOfPool && pPool && pPool == &rSfxItemPool) + { + // The pool we are based on gets destructed; get owner of pool by creating own one. + // No need to call RemoveSfxItemPoolUser(), this is done from the pool's destructor + // Base new pool on EditEnginePool; it would also be possible to clone the used + // pool if needed, but only text attributes should be used. + SfxItemPool* pNewPool = EditEngine::CreatePool(); + + if(pPool) + { + pNewPool->SetDefaultMetric(pPool->GetMetric(DEF_METRIC)); + } + + for(sal_uInt16 n(0); n < aContents.Count(); n++) + { + // clone ContentInfos for new pool + ContentInfo* pOrg = aContents.GetObject(n); + DBG_ASSERT(pOrg, "NULL-Pointer in ContentList!"); + + ContentInfo* pNew = new ContentInfo(*pOrg, *pNewPool); + aContents.Replace(pNew, n); + delete pOrg; + } + + // set local variables + pPool = pNewPool; + bOwnerOfPool = TRUE; + } +} + +EditEngineItemPool* getEditEngineItemPool(SfxItemPool* pPool) +{ + EditEngineItemPool* pRetval = dynamic_cast< EditEngineItemPool* >(pPool); + + while(!pRetval && pPool && pPool->GetSecondaryPool()) + { + pPool = pPool->GetSecondaryPool(); + + if(pPool) + { + pRetval = dynamic_cast< EditEngineItemPool* >(pPool); + } + } + + return pRetval; +} + +BinTextObject::BinTextObject( SfxItemPool* pP ) : + EditTextObject( EE_FORMAT_BIN ), + SfxItemPoolUser() +{ + nVersion = 0; + nMetric = 0xFFFF; + nUserType = 0; + nObjSettings = 0; + pPortionInfo = 0; + + // #i101239# ensure target is a EditEngineItemPool, else + // fallback to pool ownership. This is needed to ensure that at + // pool destruction time of an alien pool, the pool is still alive. + // When registering would happen at an alien pool which just uses an + // EditEngineItemPool as some sub-pool, that pool could already + // be decoupled and deleted whcih would lead to crashes. + pPool = getEditEngineItemPool(pP); + + if ( pPool ) + { + bOwnerOfPool = FALSE; + } + else + { + pPool = EditEngine::CreatePool(); + bOwnerOfPool = TRUE; + } + + if(!bOwnerOfPool && pPool) + { + // it is sure now that the pool is an EditEngineItemPool + pPool->AddSfxItemPoolUser(*this); + } + + bVertical = FALSE; + bStoreUnicodeStrings = FALSE; + nScriptType = 0; +} + +BinTextObject::BinTextObject( const BinTextObject& r ) : + EditTextObject( r ), + SfxItemPoolUser() +{ + nVersion = r.nVersion; + nMetric = r.nMetric; + nUserType = r.nUserType; + nObjSettings = r.nObjSettings; + bVertical = r.bVertical; + nScriptType = r.nScriptType; + pPortionInfo = NULL; // PortionInfo nicht kopieren + bStoreUnicodeStrings = FALSE; + + if ( !r.bOwnerOfPool ) + { + // reuse alien pool; this must be a EditEngineItemPool + // since there is no other way to construct a BinTextObject + // than it's regular constructor where that is ensured + pPool = r.pPool; + bOwnerOfPool = FALSE; + } + else + { + pPool = EditEngine::CreatePool(); + bOwnerOfPool = TRUE; + + } + + if(!bOwnerOfPool && pPool) + { + // it is sure now that the pool is an EditEngineItemPool + pPool->AddSfxItemPoolUser(*this); + } + + if ( bOwnerOfPool && pPool && r.pPool ) + pPool->SetDefaultMetric( r.pPool->GetMetric( DEF_METRIC ) ); + + for ( USHORT n = 0; n < r.aContents.Count(); n++ ) + { + ContentInfo* pOrg = r.aContents.GetObject( n ); + DBG_ASSERT( pOrg, "NULL-Pointer in ContentList!" ); + ContentInfo* pNew = new ContentInfo( *pOrg, *pPool ); + aContents.Insert( pNew, aContents.Count() ); + } +} + +__EXPORT BinTextObject::~BinTextObject() +{ + if(!bOwnerOfPool && pPool) + { + pPool->RemoveSfxItemPoolUser(*this); + } + + ClearPortionInfo(); + DeleteContents(); + if ( bOwnerOfPool ) + { + // Nicht mehr, wegen 1xDefItems. + // siehe auch ~EditDoc(). +// pPool->ReleaseDefaults( TRUE /* bDelete */ ); + SfxItemPool::Free(pPool); + } +} + +USHORT BinTextObject::GetUserType() const +{ + return nUserType; +} + +void BinTextObject::SetUserType( USHORT n ) +{ + nUserType = n; +} + +ULONG BinTextObject::GetObjectSettings() const +{ + return nObjSettings; +} + +void BinTextObject::SetObjectSettings( ULONG n ) +{ + nObjSettings = n; +} + +BOOL BinTextObject::IsVertical() const +{ + return bVertical; +} + +void BinTextObject::SetVertical( BOOL b ) +{ + if ( b != bVertical ) + { + bVertical = b; + ClearPortionInfo(); + } +} + +USHORT BinTextObject::GetScriptType() const +{ + return nScriptType; +} + +void BinTextObject::SetScriptType( USHORT nType ) +{ + nScriptType = nType; +} + + +void BinTextObject::DeleteContents() +{ + for ( USHORT n = 0; n < aContents.Count(); n++ ) + { + ContentInfo* p = aContents.GetObject( n ); + DBG_ASSERT( p, "NULL-Pointer in ContentList!" ); + delete p; + } + aContents.Remove( 0, aContents.Count() ); +} + +EditTextObject* __EXPORT BinTextObject::Clone() const +{ + return new BinTextObject( *this ); +} + +XEditAttribute* BinTextObject::CreateAttrib( const SfxPoolItem& rItem, USHORT nStart, USHORT nEnd ) +{ + return MakeXEditAttribute( *pPool, rItem, nStart, nEnd ); +} + +void BinTextObject::DestroyAttrib( XEditAttribute* pAttr ) +{ + pPool->Remove( *pAttr->GetItem() ); + delete pAttr; +} + +ContentInfo* BinTextObject::CreateAndInsertContent() +{ + ContentInfo* pC = new ContentInfo( *pPool ); + aContents.Insert( pC, aContents.Count() ); + return pC; +} + +USHORT BinTextObject::GetParagraphCount() const +{ + return aContents.Count(); +} + +XubString BinTextObject::GetText( USHORT nPara ) const +{ + DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" ); + if ( nPara < aContents.Count() ) + { + ContentInfo* pC = aContents[ nPara ]; + return pC->GetText(); + } + return XubString(); +} + +void BinTextObject::Insert( const EditTextObject& rObj, USHORT nDestPara ) +{ + DBG_ASSERT( rObj.Which() == EE_FORMAT_BIN, "UTO: Unbekanntes Textobjekt" ); + + const BinTextObject& rBinObj = (const BinTextObject&)rObj; + + if ( nDestPara > aContents.Count() ) + nDestPara = aContents.Count(); + + const USHORT nParas = rBinObj.GetContents().Count(); + for ( USHORT nP = 0; nP < nParas; nP++ ) + { + ContentInfo* pC = rBinObj.GetContents()[ nP ]; + ContentInfo* pNew = new ContentInfo( *pC, *GetPool() ); + aContents.Insert( pNew, nDestPara+nP ); + } + ClearPortionInfo(); +} + +EditTextObject* BinTextObject::CreateTextObject( USHORT nPara, USHORT nParas ) const +{ + if ( ( nPara >= aContents.Count() ) || !nParas ) + return NULL; + + // Pool nur teilen, wenn von aussen eingestellter Pool. + BinTextObject* pObj = new BinTextObject( bOwnerOfPool ? 0 : pPool ); + if ( bOwnerOfPool && pPool ) + pObj->GetPool()->SetDefaultMetric( pPool->GetMetric( DEF_METRIC ) ); + + // If complete text is only one ScriptType, this is valid. + // If text contains different ScriptTypes, this shouldn't be a problem... + pObj->nScriptType = nScriptType; + + const USHORT nEndPara = nPara+nParas-1; + for ( USHORT nP = nPara; nP <= nEndPara; nP++ ) + { + ContentInfo* pC = aContents[ nP ]; + ContentInfo* pNew = new ContentInfo( *pC, *pObj->GetPool() ); + pObj->GetContents().Insert( pNew, pObj->GetContents().Count() ); + } + return pObj; +} + +void BinTextObject::RemoveParagraph( USHORT nPara ) +{ + DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" ); + if ( nPara < aContents.Count() ) + { + ContentInfo* pC = aContents[ nPara ]; + aContents.Remove( nPara ); + delete pC; + ClearPortionInfo(); + } +} + +BOOL BinTextObject::HasPortionInfo() const +{ + return pPortionInfo ? TRUE : FALSE; +} + +void BinTextObject::ClearPortionInfo() +{ + if ( pPortionInfo ) + { + for ( USHORT n = pPortionInfo->Count(); n; ) + delete pPortionInfo->GetObject( --n ); + delete pPortionInfo; + pPortionInfo = NULL; + } +} + +BOOL BinTextObject::HasOnlineSpellErrors() const +{ +#ifndef SVX_LIGHT + for ( USHORT n = 0; n < aContents.Count(); n++ ) + { + ContentInfo* p = aContents.GetObject( n ); + if ( p->GetWrongList() && p->GetWrongList()->Count() ) + return TRUE; + } +#endif // !SVX_LIGHT + return FALSE; + +} + +BOOL BinTextObject::HasCharAttribs( USHORT _nWhich ) const +{ + for ( USHORT nPara = GetContents().Count(); nPara; ) + { + ContentInfo* pC = GetContents().GetObject( --nPara ); + + USHORT nAttribs = pC->GetAttribs().Count(); + if ( nAttribs && !_nWhich ) + return TRUE; + + for ( USHORT nAttr = nAttribs; nAttr; ) + { + XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr ); + if ( pX->GetItem()->Which() == _nWhich ) + return TRUE; + } + } + return FALSE; +} + +void BinTextObject::GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const +{ + rLst.Remove( 0, rLst.Count() ); + ContentInfo* pC = GetContents().GetObject( nPara ); + if ( pC ) + { + for ( USHORT nAttr = 0; nAttr < pC->GetAttribs().Count(); nAttr++ ) + { + XEditAttribute* pAttr = pC->GetAttribs().GetObject( nAttr ); + EECharAttrib aEEAttr; + aEEAttr.pAttr = pAttr->GetItem(); + aEEAttr.nPara = nPara; + aEEAttr.nStart = pAttr->GetStart(); + aEEAttr.nEnd = pAttr->GetEnd(); + rLst.Insert( aEEAttr, rLst.Count() ); + } + } +} + +void BinTextObject::MergeParaAttribs( const SfxItemSet& rAttribs, USHORT nStart, USHORT nEnd ) +{ + BOOL bChanged = FALSE; + + for ( USHORT nPara = GetContents().Count(); nPara; ) + { + ContentInfo* pC = GetContents().GetObject( --nPara ); + + for ( USHORT nW = nStart; nW <= nEnd; nW++ ) + { + if ( ( pC->GetParaAttribs().GetItemState( nW, FALSE ) != SFX_ITEM_ON ) + && ( rAttribs.GetItemState( nW, FALSE ) == SFX_ITEM_ON ) ) + { + pC->GetParaAttribs().Put( rAttribs.Get( nW ) ); + bChanged = TRUE; + } + } + } + + if ( bChanged ) + ClearPortionInfo(); +} + +BOOL BinTextObject::IsFieldObject() const +{ + return BinTextObject::GetField() ? TRUE : FALSE; +} + +const SvxFieldItem* BinTextObject::GetField() const +{ + if ( GetContents().Count() == 1 ) + { + ContentInfo* pC = GetContents()[0]; + if ( pC->GetText().Len() == 1 ) + { + USHORT nAttribs = pC->GetAttribs().Count(); + for ( USHORT nAttr = nAttribs; nAttr; ) + { + XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr ); + if ( pX->GetItem()->Which() == EE_FEATURE_FIELD ) + return (const SvxFieldItem*)pX->GetItem(); + } + } + } + return 0; +} + +BOOL BinTextObject::HasField( TypeId aType ) const +{ + USHORT nParagraphs = GetContents().Count(); + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = GetContents().GetObject( nPara ); + USHORT nAttrs = pC->GetAttribs().Count(); + for ( USHORT nAttr = 0; nAttr < nAttrs; nAttr++ ) + { + XEditAttribute* pAttr = pC->GetAttribs()[nAttr]; + if ( pAttr->GetItem()->Which() == EE_FEATURE_FIELD ) + { + if ( !aType ) + return TRUE; + + const SvxFieldData* pFldData = ((const SvxFieldItem*)pAttr->GetItem())->GetField(); + if ( pFldData && pFldData->IsA( aType ) ) + return TRUE; + } + } + } + return FALSE; +} + +SfxItemSet BinTextObject::GetParaAttribs( USHORT nPara ) const +{ + ContentInfo* pC = GetContents().GetObject( nPara ); + return pC->GetParaAttribs(); +} + +void BinTextObject::SetParaAttribs( USHORT nPara, const SfxItemSet& rAttribs ) +{ + ContentInfo* pC = GetContents().GetObject( nPara ); + pC->GetParaAttribs().Set( rAttribs ); + ClearPortionInfo(); +} + +BOOL BinTextObject::RemoveCharAttribs( USHORT _nWhich ) +{ + BOOL bChanged = FALSE; + + for ( USHORT nPara = GetContents().Count(); nPara; ) + { + ContentInfo* pC = GetContents().GetObject( --nPara ); + + for ( USHORT nAttr = pC->GetAttribs().Count(); nAttr; ) + { + XEditAttribute* pAttr = pC->GetAttribs().GetObject( --nAttr ); + if ( !_nWhich || ( pAttr->GetItem()->Which() == _nWhich ) ) + { + pC->GetAttribs().Remove( nAttr ); + DestroyAttrib( pAttr ); + bChanged = TRUE; + } + } + } + + if ( bChanged ) + ClearPortionInfo(); + + return bChanged; +} + +BOOL BinTextObject::RemoveParaAttribs( USHORT _nWhich ) +{ + BOOL bChanged = FALSE; + + for ( USHORT nPara = GetContents().Count(); nPara; ) + { + ContentInfo* pC = GetContents().GetObject( --nPara ); + + if ( !_nWhich ) + { + if( pC->GetParaAttribs().Count() ) + bChanged = TRUE; + pC->GetParaAttribs().ClearItem(); + } + else + { + if ( pC->GetParaAttribs().GetItemState( _nWhich ) == SFX_ITEM_ON ) + { + pC->GetParaAttribs().ClearItem( _nWhich ); + bChanged = TRUE; + } + } + } + + if ( bChanged ) + ClearPortionInfo(); + + return bChanged; +} + +BOOL BinTextObject::HasStyleSheet( const XubString& rName, SfxStyleFamily eFamily ) const +{ + USHORT nParagraphs = GetContents().Count(); + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = GetContents().GetObject( nPara ); + if ( ( pC->GetFamily() == eFamily ) && ( pC->GetStyle() == rName ) ) + return TRUE; + } + return FALSE; +} + +void BinTextObject::GetStyleSheet( USHORT nPara, XubString& rName, SfxStyleFamily& rFamily ) const +{ + if ( nPara < aContents.Count() ) + { + ContentInfo* pC = aContents[ nPara ]; + rName = pC->GetStyle(); + rFamily = pC->GetFamily(); + } +} + +void BinTextObject::SetStyleSheet( USHORT nPara, const XubString& rName, const SfxStyleFamily& rFamily ) +{ + if ( nPara < aContents.Count() ) + { + ContentInfo* pC = aContents[ nPara ]; + pC->GetStyle() = rName; + pC->GetFamily() = rFamily; + } +} + +BOOL BinTextObject::ImpChangeStyleSheets( + const XubString& rOldName, SfxStyleFamily eOldFamily, + const XubString& rNewName, SfxStyleFamily eNewFamily ) +{ + const USHORT nParagraphs = GetContents().Count(); + BOOL bChanges = FALSE; + + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = GetContents().GetObject( nPara ); + if ( pC->GetFamily() == eOldFamily ) + { + if ( pC->GetStyle() == rOldName ) + { + pC->GetStyle() = rNewName; + pC->GetFamily() = eNewFamily; + bChanges = TRUE; + } + } + } + return bChanges; +} + +BOOL __EXPORT BinTextObject::ChangeStyleSheets( + const XubString& rOldName, SfxStyleFamily eOldFamily, + const XubString& rNewName, SfxStyleFamily eNewFamily ) +{ + BOOL bChanges = ImpChangeStyleSheets( rOldName, eOldFamily, rNewName, eNewFamily ); + if ( bChanges ) + ClearPortionInfo(); + + return bChanges; +} + +void __EXPORT BinTextObject::ChangeStyleSheetName( SfxStyleFamily eFamily, + const XubString& rOldName, const XubString& rNewName ) +{ + ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily ); +} + +void __EXPORT BinTextObject::StoreData( SvStream& rOStream ) const +{ + USHORT nVer = 602; + rOStream << nVer; + + rOStream << bOwnerOfPool; + + // Erst den Pool speichern, spaeter nur noch Surregate + if ( bOwnerOfPool ) + { + GetPool()->SetFileFormatVersion( SOFFICE_FILEFORMAT_50 ); + GetPool()->Store( rOStream ); + } + + // Aktuelle Zeichensatz speichern... + // #90477# GetSOStoreTextEncoding: Bug in 5.2, when default char set is multi byte text encoding + rtl_TextEncoding eEncoding = GetSOStoreTextEncoding( gsl_getSystemTextEncoding(), (USHORT) rOStream.GetVersion() ); + rOStream << (USHORT) eEncoding; + + // Die Anzahl der Absaetze... + USHORT nParagraphs = GetContents().Count(); + rOStream << nParagraphs; + + char cFeatureConverted = ByteString( CH_FEATURE, eEncoding ).GetChar(0); + + // Die einzelnen Absaetze... + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = GetContents().GetObject( nPara ); + + // Text... + ByteString aText( pC->GetText(), eEncoding ); + + // Symbols? + BOOL bSymbolPara = FALSE; + if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON ) + { + const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO ); + if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) + { + aText = ByteString( pC->GetText(), RTL_TEXTENCODING_SYMBOL ); + bSymbolPara = TRUE; + } + } + for ( USHORT nA = 0; nA < pC->GetAttribs().Count(); nA++ ) + { + XEditAttribute* pAttr = pC->GetAttribs().GetObject( nA ); + + if ( pAttr->GetItem()->Which() == EE_CHAR_FONTINFO ) + { + const SvxFontItem& rFontItem = (const SvxFontItem&)*pAttr->GetItem(); + if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) ) + || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) ) + { + // Not correctly converted + String aPart( pC->GetText(), pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() ); + ByteString aNew( aPart, rFontItem.GetCharSet() ); + aText.Erase( pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() ); + aText.Insert( aNew, pAttr->GetStart() ); + } + + // #88414# Convert StarSymbol back to StarBats + FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS ); + if ( hConv ) + { + // Don't create a new Attrib with StarBats font, MBR changed the + // SvxFontItem::Store() to store StarBats instead of StarSymbol! + for ( USHORT nChar = pAttr->GetStart(); nChar < pAttr->GetEnd(); nChar++ ) + { + sal_Unicode cOld = pC->GetText().GetChar( nChar ); + char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL ); + if ( cConv ) + aText.SetChar( nChar, cConv ); + } + + DestroyFontToSubsFontConverter( hConv ); + } + } + } + + // #88414# Convert StarSymbol back to StarBats + // StarSymbol as paragraph attribute or in StyleSheet? + + FontToSubsFontConverter hConv = NULL; + if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON ) + { + hConv = CreateFontToSubsFontConverter( ((const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO )).GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS ); + } +/* cl removed because not needed anymore since binfilter + + else if ( pC->GetStyle().Len() && pC->GetLoadStoreTempInfos() ) + { + hConv = pC->GetLoadStoreTempInfos()->hOldSymbolConv_Store; + } +*/ + if ( hConv ) + { + for ( USHORT nChar = 0; nChar < pC->GetText().Len(); nChar++ ) + { + if ( !pC->GetAttribs().FindAttrib( EE_CHAR_FONTINFO, nChar ) ) + { + sal_Unicode cOld = pC->GetText().GetChar( nChar ); + char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL ); + if ( cConv ) + aText.SetChar( nChar, cConv ); + } + } + + DestroyFontToSubsFontConverter( hConv ); + + } + + + // Convert CH_FEATURE to CH_FEATURE_OLD + aText.SearchAndReplaceAll( cFeatureConverted, CH_FEATURE_OLD ); + rOStream.WriteByteString( aText ); + + // StyleName und Family... + rOStream.WriteByteString( ByteString( pC->GetStyle(), eEncoding ) ); + rOStream << (USHORT)pC->GetFamily(); + + // Absatzattribute... + pC->GetParaAttribs().Store( rOStream ); + + // Die Anzahl der Attribute... + USHORT nAttribs = pC->GetAttribs().Count(); + rOStream << nAttribs; + + // Und die einzelnen Attribute + // Items als Surregate => immer 8 Byte pro Attrib + // Which = 2; Surregat = 2; Start = 2; End = 2; + for ( USHORT nAttr = 0; nAttr < nAttribs; nAttr++ ) + { + XEditAttribute* pX = pC->GetAttribs().GetObject( nAttr ); + + rOStream << pX->GetItem()->Which(); + GetPool()->StoreSurrogate( rOStream, pX->GetItem() ); + rOStream << pX->GetStart(); + rOStream << pX->GetEnd(); + } + } + + // Ab 400: + rOStream << nMetric; + + // Ab 600 + rOStream << nUserType; + rOStream << nObjSettings; + + // Ab 601 + rOStream << bVertical; + + // Ab 602 + rOStream << nScriptType; + + rOStream << bStoreUnicodeStrings; + if ( bStoreUnicodeStrings ) + { + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = GetContents().GetObject( nPara ); + USHORT nL = pC->GetText().Len(); + rOStream << nL; + rOStream.Write( pC->GetText().GetBuffer(), nL*sizeof(sal_Unicode) ); + + // #91575# StyleSheetName must be Unicode too! + // Copy/Paste from EA3 to BETA or from BETA to EA3 not possible, not needed... + // If needed, change nL back to ULONG and increase version... + nL = pC->GetStyle().Len(); + rOStream << nL; + rOStream.Write( pC->GetStyle().GetBuffer(), nL*sizeof(sal_Unicode) ); + } + } +} + +void __EXPORT BinTextObject::CreateData( SvStream& rIStream ) +{ + rIStream >> nVersion; + + // Das Textobject wurde erstmal mit der aktuellen Einstellung + // von pTextObjectPool erzeugt. + BOOL bOwnerOfCurrent = bOwnerOfPool; + rIStream >> bOwnerOfPool; + + if ( bOwnerOfCurrent && !bOwnerOfPool ) + { + // Es wurde ein globaler Pool verwendet, mir jetzt nicht uebergeben, + // aber ich brauche ihn! + DBG_ERROR( "Man gebe mir den globalen TextObjectPool!" ); + return; + } + else if ( !bOwnerOfCurrent && bOwnerOfPool ) + { + // Es soll ein globaler Pool verwendet werden, aber dieses + // Textobject hat einen eigenen. + pPool = EditEngine::CreatePool(); + } + + if ( bOwnerOfPool ) + GetPool()->Load( rIStream ); + + // CharSet, in dem gespeichert wurde: + USHORT nCharSet; + rIStream >> nCharSet; + + rtl_TextEncoding eSrcEncoding = GetSOLoadTextEncoding( (rtl_TextEncoding)nCharSet, (USHORT)rIStream.GetVersion() ); + + // Die Anzahl der Absaetze... + USHORT nParagraphs; + rIStream >> nParagraphs; + + // Die einzelnen Absaetze... + for ( ULONG nPara = 0; nPara < nParagraphs; nPara++ ) + { + ContentInfo* pC = CreateAndInsertContent(); + + // Der Text... + ByteString aByteString; + rIStream.ReadByteString( aByteString ); + pC->GetText() = String( aByteString, eSrcEncoding ); + + // StyleName und Family... + rIStream.ReadByteString( pC->GetStyle(), eSrcEncoding ); + USHORT nStyleFamily; + rIStream >> nStyleFamily; + pC->GetFamily() = (SfxStyleFamily)nStyleFamily; + + // Absatzattribute... + pC->GetParaAttribs().Load( rIStream ); + + // Die Anzahl der Attribute... + USHORT nAttribs; + rIStream >> nAttribs; + + // Und die einzelnen Attribute + // Items als Surregate => immer 8 Byte pro Attrib + // Which = 2; Surregat = 2; Start = 2; End = 2; + USHORT nAttr; + |