APIers, I have a program that automatically opens a new Writer document, listens for modification changes, makes/forces a modification, checks the current selection (since that's likely near where the change was made), and then closes. It's part of a much more complicated system in which the user makes the changes, but the same idea and sequence of events. One difference is that the complicated version is an extension in which this process works, while this example below is an application.
The problem is that OpenOffice, version 4.0.1, Windows 7, hangs when I try to query the end of the current selection. getStart() works fine. No exceptions are thrown. I don't see any related issues reported online, so I'm about to file a bug report, but I wonder if anyone can easily try out this C++ code, spot a problem, or say what could possibly be wrong. Thanks to any takers. Keith /****************************************************************************** Header ******************************************************************************/ // $Header$ /****************************************************************************** Include others ******************************************************************************/ //#include "sdkBeg.hpp" #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/container/XIndexAccess.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/frame/XController.hpp> #include <com/sun/star/frame/XDesktop.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/lang/EventObject.hpp> #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/lang/XMultiComponentFactory.hpp> #include <com/sun/star/text/XTextRange.hpp> #include <com/sun/star/text/XTextDocument.hpp> #include <com/sun/star/uno/RuntimeException.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/util/XModifiable.hpp> #include <com/sun/star/util/XModifyListener.hpp> #include <com/sun/star/view/XSelectionSupplier.hpp> #include <cppuhelper/bootstrap.hxx> #include <cppuhelper/implbase1.hxx> #include <sal/main.h> // Required for this to be a free-standing executable. //#include "sdkEnd.hpp" #include <iostream> /****************************************************************************** Using ******************************************************************************/ using namespace com::sun::star::beans; using namespace com::sun::star::container; using namespace com::sun::star::frame; using namespace com::sun::star::lang; using namespace com::sun::star::text; using namespace com::sun::star::uno; using namespace com::sun::star::util; using namespace com::sun::star::view; /****************************************************************************** ModifyBug ******************************************************************************/ class ModifyBug: public cppu::WeakImplHelper1<com::sun::star::util::XModifyListener> { protected: Reference<XComponent> xComponent; // needed for testing listener void testModification(Reference<XTextDocument> xTextDocument); virtual void SAL_CALL modified(const com::sun::star::lang::EventObject& event) throw (com::sun::star::uno::RuntimeException); virtual void SAL_CALL disposing(const com::sun::star::lang::EventObject& event) throw (com::sun::star::uno::RuntimeException); Reference<XComponentContext> newXComponentContext(); Reference<XInterface> newDesktop(Reference<XComponentContext> xComponentContext); Reference<XTextDocument> newXTextDocument(Reference<XInterface> desktop); public: ModifyBug() { } void run(); }; void SAL_CALL ModifyBug::disposing(const com::sun::star::lang::EventObject& event) throw (com::sun::star::uno::RuntimeException) { // TODO: remove listener } void SAL_CALL ModifyBug::modified(const com::sun::star::lang::EventObject& event) throw (com::sun::star::uno::RuntimeException) { Reference<XModel> xModel(this->xComponent, UNO_QUERY); Reference<XController> xController = xModel->getCurrentController(); Reference<XSelectionSupplier> xSelectionSupplier(xController, UNO_QUERY); Any anySelection = xSelectionSupplier->getSelection(); Reference<XIndexAccess> xIndexAccess; anySelection >>= xIndexAccess; sal_Int32 count = xIndexAccess->getCount(); for (int i = 0; i < count; i++) { Any anyIndex = xIndexAccess->getByIndex(i); Reference<XTextRange> xTextRange; anyIndex >>= xTextRange; xTextRange->getStart(); // This is fine try { xTextRange->getEnd(); // This is where it hangs! } catch (...) { std::cerr << "Caught!" << std::endl; // No exception is thrown } } } Reference<XComponentContext> ModifyBug::newXComponentContext() { Reference<XComponentContext> xComponentContext(cppu::bootstrap()); return xComponentContext; } Reference<XInterface> ModifyBug::newDesktop(Reference<XComponentContext> xComponentContext) { Reference<XMultiComponentFactory> xMultiComponentFactory(xComponentContext->getServiceManager(), UNO_QUERY); Reference<XInterface> desktop = xMultiComponentFactory->createInstanceWithContext( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")), xComponentContext); return desktop; } Reference<XTextDocument> ModifyBug::newXTextDocument(Reference<XInterface> desktop) { Reference<XComponentLoader> xComponentLoader(desktop, UNO_QUERY); Reference<XComponent> document = xComponentLoader->loadComponentFromURL( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/swriter")), rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, Sequence<PropertyValue>()); Reference<XTextDocument> xTextDocument(document, UNO_QUERY); return xTextDocument; } void ModifyBug::run() { try { Reference<XComponentContext> xComponentContext = newXComponentContext(); Reference<XInterface> desktop = newDesktop(xComponentContext); { Reference<XTextDocument> xTextDocument = newXTextDocument(desktop); Reference<XComponent> xComponent(xTextDocument, UNO_QUERY); this->xComponent = xComponent; // for testing Reference<XModifyBroadcaster> xModifyBroadcaster(xComponent, UNO_QUERY); xModifyBroadcaster->addModifyListener(this); Reference<XModifiable> xModifiable(xComponent, UNO_QUERY); xModifiable->setModified(sal_True); // Test it out xModifyBroadcaster->removeModifyListener(this); this->xComponent = Reference<XComponent>(); xTextDocument->dispose(); } Reference<XDesktop> xDesktop(desktop, UNO_QUERY); xDesktop->terminate(); } catch (...) { std::cerr << "Exception..." << std::endl; } } SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { ModifyBug modifyBug; modifyBug.run(); return 0; } /*****************************************************************************/