summaryrefslogtreecommitdiff
path: root/vcl/unx/gtk/a11y
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/gtk/a11y')
-rw-r--r--vcl/unx/gtk/a11y/TODO49
-rw-r--r--vcl/unx/gtk/a11y/atkaction.cxx278
-rw-r--r--vcl/unx/gtk/a11y/atkbridge.cxx78
-rw-r--r--vcl/unx/gtk/a11y/atkcomponent.cxx382
-rw-r--r--vcl/unx/gtk/a11y/atkeditabletext.cxx202
-rw-r--r--vcl/unx/gtk/a11y/atkfactory.cxx183
-rw-r--r--vcl/unx/gtk/a11y/atkfactory.hxx41
-rw-r--r--vcl/unx/gtk/a11y/atkhypertext.cxx291
-rw-r--r--vcl/unx/gtk/a11y/atkimage.cxx138
-rw-r--r--vcl/unx/gtk/a11y/atklistener.cxx537
-rw-r--r--vcl/unx/gtk/a11y/atklistener.hxx79
-rw-r--r--vcl/unx/gtk/a11y/atkregistry.cxx71
-rw-r--r--vcl/unx/gtk/a11y/atkregistry.hxx40
-rw-r--r--vcl/unx/gtk/a11y/atkselection.cxx195
-rw-r--r--vcl/unx/gtk/a11y/atktable.cxx721
-rw-r--r--vcl/unx/gtk/a11y/atktext.cxx876
-rw-r--r--vcl/unx/gtk/a11y/atktextattributes.cxx1456
-rw-r--r--vcl/unx/gtk/a11y/atktextattributes.hxx54
-rw-r--r--vcl/unx/gtk/a11y/atkutil.cxx802
-rw-r--r--vcl/unx/gtk/a11y/atkutil.hxx37
-rw-r--r--vcl/unx/gtk/a11y/atkvalue.cxx147
-rw-r--r--vcl/unx/gtk/a11y/atkwindow.cxx331
-rw-r--r--vcl/unx/gtk/a11y/atkwindow.hxx38
-rw-r--r--vcl/unx/gtk/a11y/atkwrapper.cxx953
-rw-r--r--vcl/unx/gtk/a11y/atkwrapper.hxx125
-rw-r--r--vcl/unx/gtk/a11y/makefile.mk93
26 files changed, 8197 insertions, 0 deletions
diff --git a/vcl/unx/gtk/a11y/TODO b/vcl/unx/gtk/a11y/TODO
new file mode 100644
index 000000000000..1048bd96ef75
--- /dev/null
+++ b/vcl/unx/gtk/a11y/TODO
@@ -0,0 +1,49 @@
+cws 'atkbridge'
+#Issue number: i#47890#
+Submitted by: mmeeks
+
+Hacked up prototype of atk bridge
+
+
+Serious problems
+ + Threading/locking:
+ + incoming CORBA calls & the GDK lock
+ + how are these being processed & on what thread ?
+ + are we holding the GDK_THREADS lock ?
+ + can we even do that ?
+ + is it really necessary to be thread safe ?
+ + how does this work in combination with the (unsafe) GAIL code ?
+ + what should incoming CORBA calls be doing ?
+ + esp. since we can't tell if they're coming from
+ in-proc or not either [ though this is unlikely ]
+
+
+Test:
+ + in-line text editing, does the TEXT_CHANGED signal get it right,
+ + why not copy/paste/delete etc. ?
+ + check vs. writer & other bits ...
+ + AtkSelection
+ + AtkHyper*
+
+* At-poke
+ + implement non-gui mode - for to-console event logging
+ + logging
+ + more detail from remaining events
+ + add a Tree navigation thing instead (?)
+ + poke a sub-child (?)
+ + embed a tree widget inside the tree view ?
+ + AtkHyperText testing (?)
+
+
+Known bugs:
+ + AtkText
+ + selection interface - multiple selections ?
+ + word boundary issues
+ + copy AccessibleTextImpl.java's getAfterIndex eg.
+ + the 'getFoo' methods need to use UNO_QUERY_THROW &
+ throw an exception to avoid null pointer dereferences.
+ + AtkAttributeSet (etc.)
+ + AtkEditableText
+ + finish/test AtkTable
+ + HyperLink 'link_activated', HyperText 'link_selected' (?)
+ + tooltips create new toplevels with broken roles.
diff --git a/vcl/unx/gtk/a11y/atkaction.cxx b/vcl/unx/gtk/a11y/atkaction.cxx
new file mode 100644
index 000000000000..4329dd345d14
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkaction.cxx
@@ -0,0 +1,278 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleAction.hpp>
+#include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
+
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+#include <rtl/strbuf.hxx>
+#include <algorithm>
+#include <map>
+
+#include <stdio.h>
+
+using namespace ::com::sun::star;
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( const rtl::OString& rString )
+{
+ static const int nMax = 10;
+ static rtl::OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = rString;
+ return aUgly[ nIdx ];
+}
+
+static accessibility::XAccessibleAction*
+ getAction( AtkAction *action ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( action );
+
+ if( pWrap )
+ {
+ if( !pWrap->mpAction && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleAction::static_type(NULL) );
+ pWrap->mpAction = reinterpret_cast< accessibility::XAccessibleAction * > (any.pReserved);
+ pWrap->mpAction->acquire();
+ }
+
+ return pWrap->mpAction;
+ }
+
+ return NULL;
+}
+
+extern "C" {
+
+static gboolean
+action_wrapper_do_action (AtkAction *action,
+ gint i)
+{
+ try {
+ accessibility::XAccessibleAction* pAction = getAction( action );
+ if( pAction )
+ return pAction->doAccessibleAction( i );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in doAccessibleAction()" );
+ }
+
+ return FALSE;
+}
+
+static gint
+action_wrapper_get_n_actions (AtkAction *action)
+{
+ try {
+ accessibility::XAccessibleAction* pAction = getAction( action );
+ if( pAction )
+ return pAction->getAccessibleActionCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleActionCount()" );
+ }
+
+ return 0;
+}
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_description (AtkAction *, gint)
+{
+ // GAIL implement this only for cells
+ g_warning( "Not implemented: get_description()" );
+ return "";
+}
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_localized_name (AtkAction *, gint)
+{
+ // GAIL doesn't implement this as well
+ g_warning( "Not implemented: get_localized_name()" );
+ return "";
+}
+
+#define ACTION_NAME_PAIR( OOoName, AtkName ) \
+ std::pair< const rtl::OUString, const gchar * > ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OOoName ) ), AtkName )
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_name (AtkAction *action,
+ gint i)
+{
+ static std::map< rtl::OUString, const gchar * > aNameMap;
+
+ if( aNameMap.empty() )
+ {
+ aNameMap.insert( ACTION_NAME_PAIR( "click", "click" ) );
+ aNameMap.insert( ACTION_NAME_PAIR( "select", "click" ) );
+ aNameMap.insert( ACTION_NAME_PAIR( "togglePopup", "push" ) );
+ }
+
+ try {
+ accessibility::XAccessibleAction* pAction = getAction( action );
+ if( pAction )
+ {
+ std::map< rtl::OUString, const gchar * >::iterator iter;
+
+ rtl::OUString aDesc( pAction->getAccessibleActionDescription( i ) );
+
+ iter = aNameMap.find( aDesc );
+ if( iter != aNameMap.end() )
+ return iter->second;
+
+ std::pair< const rtl::OUString, const gchar * > aNewVal( aDesc,
+ g_strdup( OUStringToConstGChar(aDesc) ) );
+
+ if( aNameMap.insert( aNewVal ).second )
+ return aNewVal.second;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleActionDescription()" );
+ }
+
+ return "";
+}
+
+/*
+* GNOME Expects a string in the format:
+*
+* <nmemonic>;<full-path>;<accelerator>
+*
+* The keybindings in <full-path> should be separated by ":"
+*/
+
+static inline void
+appendKeyStrokes(rtl::OStringBuffer& rBuffer, const uno::Sequence< awt::KeyStroke >& rKeyStrokes)
+{
+ for( sal_Int32 i = 0; i < rKeyStrokes.getLength(); i++ )
+ {
+ if( rKeyStrokes[i].Modifiers & awt::KeyModifier::SHIFT )
+ rBuffer.append("<Shift>");
+ if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD1 )
+ rBuffer.append("<Control>");
+ if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD2 )
+ rBuffer.append("<Alt>");
+
+ if( ( rKeyStrokes[i].KeyCode >= awt::Key::A ) && ( rKeyStrokes[i].KeyCode <= awt::Key::Z ) )
+ rBuffer.append( (sal_Char) ( 'a' + ( rKeyStrokes[i].KeyCode - awt::Key::A ) ) );
+ else
+ {
+ sal_Char c = '\0';
+
+ switch( rKeyStrokes[i].KeyCode )
+ {
+ case awt::Key::TAB: c = '\t'; break;
+ case awt::Key::SPACE: c = ' '; break;
+ case awt::Key::ADD: c = '+'; break;
+ case awt::Key::SUBTRACT: c = '-'; break;
+ case awt::Key::MULTIPLY: c = '*'; break;
+ case awt::Key::DIVIDE: c = '/'; break;
+ case awt::Key::POINT: c = '.'; break;
+ case awt::Key::COMMA: c = ','; break;
+ case awt::Key::LESS: c = '<'; break;
+ case awt::Key::GREATER: c = '>'; break;
+ case awt::Key::EQUAL: c = '='; break;
+ case 0:
+ break;
+ default:
+ g_warning( "Unmapped KeyCode: %d", rKeyStrokes[i].KeyCode );
+ break;
+ }
+
+ if( c != '\0' )
+ rBuffer.append( c );
+ }
+ }
+}
+
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_keybinding (AtkAction *action,
+ gint i)
+{
+ try {
+ accessibility::XAccessibleAction* pAction = getAction( action );
+ if( pAction )
+ {
+ uno::Reference< accessibility::XAccessibleKeyBinding > xBinding( pAction->getAccessibleActionKeyBinding( i ));
+
+ if( xBinding.is() )
+ {
+ rtl::OStringBuffer aRet;
+
+ sal_Int32 nmax = std::min( xBinding->getAccessibleKeyBindingCount(), (sal_Int32) 3 );
+ for( sal_Int32 n = 0; n < nmax; n++ )
+ {
+ appendKeyStrokes( aRet, xBinding->getAccessibleKeyBinding( n ) );
+
+ if( n < 2 )
+ aRet.append( (sal_Char) ';' );
+ }
+
+ // !! FIXME !! remember keystroke in wrapper object ?
+ return getAsConst( aRet.makeStringAndClear() );
+ }
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in get_keybinding()" );
+ }
+
+ return "";
+}
+
+static gboolean
+action_wrapper_set_description (AtkAction *, gint, const gchar *)
+{
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+actionIfaceInit (AtkActionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->do_action = action_wrapper_do_action;
+ iface->get_n_actions = action_wrapper_get_n_actions;
+ iface->get_description = action_wrapper_get_description;
+ iface->get_keybinding = action_wrapper_get_keybinding;
+ iface->get_name = action_wrapper_get_name;
+ iface->get_localized_name = action_wrapper_get_localized_name;
+ iface->set_description = action_wrapper_set_description;
+}
diff --git a/vcl/unx/gtk/a11y/atkbridge.cxx b/vcl/unx/gtk/a11y/atkbridge.cxx
new file mode 100644
index 000000000000..25add8e0dd18
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkbridge.cxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <plugins/gtk/atkbridge.hxx>
+#include <plugins/gtk/gtkframe.hxx>
+
+#include "atkfactory.hxx"
+#include "atkutil.hxx"
+#include "atkwindow.hxx"
+#include <stdio.h>
+
+bool InitAtkBridge(void)
+{
+ const char* pVersion = atk_get_toolkit_version();
+ if( ! pVersion )
+ return false;
+
+ unsigned int major, minor, micro;
+
+ /* check gail minimum version requirements */
+ if( sscanf( pVersion, "%u.%u.%u", &major, &minor, &micro) < 3 )
+ {
+ // g_warning( "unable to parse gail version number" );
+ return false;
+ }
+
+ if( ( (major << 16) | (minor << 8) | micro ) < ( (1 << 16) | 8 << 8 | 6 ) )
+ {
+ g_warning( "libgail >= 1.8.6 required for accessibility support" );
+ return false;
+ }
+
+ /* Initialize the AtkUtilityWrapper class */
+ g_type_class_unref( g_type_class_ref( OOO_TYPE_ATK_UTIL ) );
+
+ /* Initialize the GailWindow wrapper class */
+ g_type_class_unref( g_type_class_ref( OOO_TYPE_WINDOW_WRAPPER ) );
+
+ /* Register AtkObject wrapper factory */
+ AtkRegistry * registry = atk_get_default_registry();
+ if( registry )
+ atk_registry_set_factory_type( registry, OOO_TYPE_FIXED, OOO_TYPE_WRAPPER_FACTORY );
+
+ return true;
+}
+
+void DeInitAtkBridge()
+{
+ restore_gail_window_vtable();
+}
+
diff --git a/vcl/unx/gtk/a11y/atkcomponent.cxx b/vcl/unx/gtk/a11y/atkcomponent.cxx
new file mode 100644
index 000000000000..24cf335ebeb0
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkcomponent.cxx
@@ -0,0 +1,382 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+
+#ifdef ENABLE_TRACING
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+
+static accessibility::XAccessibleComponent*
+ getComponent( AtkComponent *pComponent ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pComponent );
+ if( pWrap )
+ {
+ if( !pWrap->mpComponent && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
+ pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
+ pWrap->mpComponent->acquire();
+ }
+
+ return pWrap->mpComponent;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static awt::Point
+translatePoint( accessibility::XAccessibleComponent *pComponent,
+ gint x, gint y, AtkCoordType t)
+{
+ awt::Point aOrigin( 0, 0 );
+ if( t == ATK_XY_SCREEN )
+ aOrigin = pComponent->getLocationOnScreen();
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "coordinates ( %u, %u ) translated to: ( %u, %u )\n",
+ x, y, x - aOrigin.X, y - aOrigin.Y);
+#endif
+
+ return awt::Point( x - aOrigin.X, y - aOrigin.Y );
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gboolean
+component_wrapper_grab_focus (AtkComponent *component)
+{
+ try
+ {
+ accessibility::XAccessibleComponent* pComponent = getComponent( component );
+ if( pComponent )
+ {
+ pComponent->grabFocus();
+ return TRUE;
+ }
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception in grabFocus()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_contains (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ try
+ {
+ accessibility::XAccessibleComponent* pComponent = getComponent( component );
+ if( pComponent )
+ return pComponent->containsPoint( translatePoint( pComponent, x, y, coord_type ) );
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception in containsPoint()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+component_wrapper_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ try
+ {
+ accessibility::XAccessibleComponent* pComponent = getComponent( component );
+
+ if( pComponent )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible;
+ xAccessible = pComponent->getAccessibleAtPoint(
+ translatePoint( pComponent, x, y, coord_type ) );
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "getAccessibleAtPoint( %u, %u ) returned %p\n",
+ x, y, xAccessible.get());
+
+ uno::Reference< accessibility::XAccessibleComponent > xComponent(
+ xAccessible->getAccessibleContext(), uno::UNO_QUERY );
+
+ if( xComponent.is() )
+ {
+ awt::Rectangle rect = xComponent->getBounds();
+ fprintf(stderr, "%p->getBounds() returned: ( %u, %u, %u, %u )\n",
+ xAccessible.get(), rect.X, rect.Y, rect.Width, rect.Height );
+ }
+#endif
+
+ return atk_object_wrapper_ref( xAccessible );
+ }
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception in getAccessibleAtPoint()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_position (AtkComponent *component,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type)
+{
+ try
+ {
+ accessibility::XAccessibleComponent* pComponent = getComponent( component );
+ if( pComponent )
+ {
+ awt::Point aPos;
+
+ if( coord_type == ATK_XY_SCREEN )
+ aPos = pComponent->getLocationOnScreen();
+ else
+ aPos = pComponent->getLocation();
+
+ *x = aPos.X;
+ *y = aPos.Y;
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "getLocation[OnScreen]() returned: ( %u, %u )\n", *x, *y );
+#endif
+ }
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception in getLocation[OnScreen]()" );
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_size (AtkComponent *component,
+ gint *width,
+ gint *height)
+{
+ try
+ {
+ accessibility::XAccessibleComponent* pComponent = getComponent( component );
+ if( pComponent )
+ {
+ awt::Size aSize = pComponent->getSize();
+ *width = aSize.Width;
+ *height = aSize.Height;
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "getSize() returned: ( %u, %u )\n", *width, *height );
+#endif
+ }
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception in getSize()" );
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ component_wrapper_get_position( component, x, y, coord_type );
+ component_wrapper_get_size( component, width, height );
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_extents (AtkComponent *, gint, gint, gint, gint, AtkCoordType)
+{
+ g_warning( "AtkComponent::set_extents unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_position (AtkComponent *, gint, gint, AtkCoordType)
+{
+ g_warning( "AtkComponent::set_position unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_size (AtkComponent *, gint, gint)
+{
+ g_warning( "AtkComponent::set_size unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static AtkLayer
+component_wrapper_get_layer (AtkComponent *component)
+{
+ AtkRole role = atk_object_get_role( ATK_OBJECT( component ) );
+ AtkLayer layer = ATK_LAYER_WIDGET;
+
+ switch (role)
+ {
+ case ATK_ROLE_POPUP_MENU:
+ case ATK_ROLE_MENU_ITEM:
+ case ATK_ROLE_CHECK_MENU_ITEM:
+ case ATK_ROLE_SEPARATOR:
+ case ATK_ROLE_LIST_ITEM:
+ layer = ATK_LAYER_POPUP;
+ break;
+ case ATK_ROLE_MENU:
+ {
+ AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
+ if( atk_object_get_role( parent ) != ATK_ROLE_MENU_BAR )
+ layer = ATK_LAYER_POPUP;
+ }
+ break;
+
+ case ATK_ROLE_LIST:
+ {
+ AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
+ if( atk_object_get_role( parent ) == ATK_ROLE_COMBO_BOX )
+ layer = ATK_LAYER_POPUP;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return layer;
+}
+
+/*****************************************************************************/
+
+static gint
+component_wrapper_get_mdi_zorder (AtkComponent *)
+{
+ // only needed for ATK_LAYER_MDI (not used) or ATK_LAYER_WINDOW (inherited from GAIL)
+ return G_MININT;
+}
+
+/*****************************************************************************/
+
+// This code is mostly stolen from libgail ..
+
+static guint
+component_wrapper_add_focus_handler (AtkComponent *component,
+ AtkFocusHandler handler)
+{
+ GSignalMatchType match_type;
+ gulong ret;
+ guint signal_id;
+
+ match_type = (GSignalMatchType) (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
+ signal_id = g_signal_lookup( "focus-event", ATK_TYPE_OBJECT );
+
+ ret = g_signal_handler_find( component, match_type, signal_id, 0, NULL,
+ (gpointer) &handler, NULL);
+ if (!ret)
+ {
+ return g_signal_connect_closure_by_id (component,
+ signal_id, 0,
+ g_cclosure_new (
+ G_CALLBACK (handler), NULL,
+ (GClosureNotify) NULL),
+ FALSE);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_remove_focus_handler (AtkComponent *component,
+ guint handler_id)
+{
+ g_signal_handler_disconnect (component, handler_id);
+}
+
+/*****************************************************************************/
+
+} // extern "C"
+
+void
+componentIfaceInit (AtkComponentIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->add_focus_handler = component_wrapper_add_focus_handler;
+ iface->contains = component_wrapper_contains;
+ iface->get_extents = component_wrapper_get_extents;
+ iface->get_layer = component_wrapper_get_layer;
+ iface->get_mdi_zorder = component_wrapper_get_mdi_zorder;
+ iface->get_position = component_wrapper_get_position;
+ iface->get_size = component_wrapper_get_size;
+ iface->grab_focus = component_wrapper_grab_focus;
+ iface->ref_accessible_at_point = component_wrapper_ref_accessible_at_point;
+ iface->remove_focus_handler = component_wrapper_remove_focus_handler;
+ iface->set_extents = component_wrapper_set_extents;
+ iface->set_position = component_wrapper_set_position;
+ iface->set_size = component_wrapper_set_size;
+}
diff --git a/vcl/unx/gtk/a11y/atkeditabletext.cxx b/vcl/unx/gtk/a11y/atkeditabletext.cxx
new file mode 100644
index 000000000000..c0399145b07c
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkeditabletext.cxx
@@ -0,0 +1,202 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+#include "atktextattributes.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+
+// #include <functional>
+// #include <hash_map>
+
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+static accessibility::XAccessibleEditableText*
+ getEditableText( AtkEditableText *pEditableText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pEditableText );
+ if( pWrap )
+ {
+ if( !pWrap->mpEditableText && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleEditableText::static_type(NULL) );
+ pWrap->mpEditableText = reinterpret_cast< accessibility::XAccessibleEditableText * > (any.pReserved);
+ pWrap->mpEditableText->acquire();
+ }
+
+ return pWrap->mpEditableText;
+ }
+
+ return NULL;
+}
+
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gboolean
+editable_text_wrapper_set_run_attributes( AtkEditableText *text,
+ AtkAttributeSet *attribute_set,
+ gint nStartOffset,
+ gint nEndOffset)
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList;
+
+ if( attribute_set_map_to_property_values( attribute_set, aAttributeList ) )
+ return pEditableText->setAttributes(nStartOffset, nEndOffset, aAttributeList);
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setAttributes()" );
+ }
+
+ return FALSE;
+}
+
+static void
+editable_text_wrapper_set_text_contents( AtkEditableText *text,
+ const gchar *string )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ {
+ rtl::OUString aString ( string, strlen(string), RTL_TEXTENCODING_UTF8 );
+ pEditableText->setText( aString );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setText()" );
+ }
+}
+
+static void
+editable_text_wrapper_insert_text( AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *pos )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ {
+ rtl::OUString aString ( string, length, RTL_TEXTENCODING_UTF8 );
+ if( pEditableText->insertText( aString, *pos ) )
+ *pos += length;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in insertText()" );
+ }
+}
+
+static void
+editable_text_wrapper_cut_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ pEditableText->cutText( start, end );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in cutText()" );
+ }
+}
+
+static void
+editable_text_wrapper_delete_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ pEditableText->deleteText( start, end );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in deleteText()" );
+ }
+}
+
+static void
+editable_text_wrapper_paste_text( AtkEditableText *text,
+ gint pos )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ pEditableText->pasteText( pos );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in pasteText()" );
+ }
+}
+
+static void
+editable_text_wrapper_copy_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ accessibility::XAccessibleEditableText* pEditableText = getEditableText( text );
+ if( pEditableText )
+ pEditableText->copyText( start, end );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in copyText()" );
+ }
+}
+
+} // extern "C"
+
+void
+editableTextIfaceInit (AtkEditableTextIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->set_text_contents = editable_text_wrapper_set_text_contents;
+ iface->insert_text = editable_text_wrapper_insert_text;
+ iface->copy_text = editable_text_wrapper_copy_text;
+ iface->cut_text = editable_text_wrapper_cut_text;
+ iface->delete_text = editable_text_wrapper_delete_text;
+ iface->paste_text = editable_text_wrapper_paste_text;
+ iface->set_run_attributes = editable_text_wrapper_set_run_attributes;
+}
diff --git a/vcl/unx/gtk/a11y/atkfactory.cxx b/vcl/unx/gtk/a11y/atkfactory.cxx
new file mode 100644
index 000000000000..d2574f616539
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkfactory.cxx
@@ -0,0 +1,183 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <plugins/gtk/gtkframe.hxx>
+#include <vcl/window.hxx>
+#include "atkwrapper.hxx"
+#include "atkfactory.hxx"
+#include "atkregistry.hxx"
+
+using namespace ::com::sun::star;
+
+extern "C" {
+
+/*
+ * Instances of this dummy object class are returned whenever we have to
+ * create an AtkObject, but can't touch the OOo object anymore since it
+ * is already disposed.
+ */
+
+static AtkStateSet *
+noop_wrapper_ref_state_set( AtkObject * )
+{
+ AtkStateSet *state_set = atk_state_set_new();
+ atk_state_set_add_state( state_set, ATK_STATE_DEFUNCT );
+ return state_set;
+}
+
+static void
+atk_noop_object_wrapper_class_init(AtkNoOpObjectClass *klass)
+{
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
+ atk_class->ref_state_set = noop_wrapper_ref_state_set;
+}
+
+static GType
+atk_noop_object_wrapper_get_type(void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo typeInfo =
+ {
+ sizeof (AtkNoOpObjectClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) atk_noop_object_wrapper_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (AtkObjectWrapper),
+ 0,
+ (GInstanceInitFunc) NULL,
+ NULL
+ } ;
+
+ type = g_type_register_static (ATK_TYPE_OBJECT, "OOoAtkNoOpObj", &typeInfo, (GTypeFlags)0) ;
+ }
+ return type;
+}
+
+AtkObject*
+atk_noop_object_wrapper_new()
+{
+ AtkObject *accessible;
+
+ accessible = (AtkObject *) g_object_new (atk_noop_object_wrapper_get_type(), NULL);
+ g_return_val_if_fail (accessible != NULL, NULL);
+
+ accessible->role = ATK_ROLE_INVALID;
+ accessible->layer = ATK_LAYER_INVALID;
+
+ return accessible;
+}
+
+/*
+ * The wrapper factory
+ */
+
+static GType
+wrapper_factory_get_accessible_type(void)
+{
+ return atk_object_wrapper_get_type();
+}
+
+static AtkObject*
+wrapper_factory_create_accessible( GObject *obj )
+{
+ GtkWidget* parent_widget = gtk_widget_get_parent( GTK_WIDGET( obj ) );
+
+ // gail_container_real_remove_gtk tries to re-instanciate an accessible
+ // for a widget that is about to vanish ..
+ if( ! parent_widget )
+ return atk_noop_object_wrapper_new();
+
+ GtkSalFrame* pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( parent_widget ) );
+ g_return_val_if_fail( pFrame != NULL, NULL );
+
+ Window* pFrameWindow = pFrame->GetWindow();
+ if( pFrameWindow )
+ {
+ Window* pWindow = pFrameWindow;
+
+ // skip accessible objects already exposed by the frame objects
+ if( WINDOW_BORDERWINDOW == pWindow->GetType() )
+ pWindow = pFrameWindow->GetAccessibleChildWindow(0);
+
+ if( pWindow )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible = pWindow->GetAccessible(true);
+ if( xAccessible.is() )
+ {
+ AtkObject *accessible = ooo_wrapper_registry_get( xAccessible );
+
+ if( accessible )
+ g_object_ref( G_OBJECT(accessible) );
+ else
+ accessible = atk_object_wrapper_new( xAccessible, gtk_widget_get_accessible(parent_widget) );
+
+ return accessible;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void
+wrapper_factory_class_init( AtkObjectFactoryClass *klass )
+{
+ klass->create_accessible = wrapper_factory_create_accessible;
+ klass->get_accessible_type = wrapper_factory_get_accessible_type;
+}
+
+GType
+wrapper_factory_get_type (void)
+{
+ static GType t = 0;
+
+ if (!t) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtkObjectFactoryClass),
+ NULL, NULL, (GClassInitFunc) wrapper_factory_class_init,
+ NULL, NULL, sizeof (AtkObjectFactory), 0, NULL, NULL
+ };
+
+ t = g_type_register_static (
+ ATK_TYPE_OBJECT_FACTORY, "OOoAtkObjectWrapperFactory",
+ &tinfo, (GTypeFlags) 0);
+ }
+
+ return t;
+}
+
+} // extern C
+
diff --git a/vcl/unx/gtk/a11y/atkfactory.hxx b/vcl/unx/gtk/a11y/atkfactory.hxx
new file mode 100644
index 000000000000..82be08cfad1b
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkfactory.hxx
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_FACTORY_HXX__
+#define __ATK_FACTORY_HXX__
+
+#include <atk/atk.h>
+
+#define OOO_TYPE_WRAPPER_FACTORY wrapper_factory_get_type()
+
+extern "C" {
+
+GType wrapper_factory_get_type (void);
+
+} // extern "C"
+
+#endif
diff --git a/vcl/unx/gtk/a11y/atkhypertext.cxx b/vcl/unx/gtk/a11y/atkhypertext.cxx
new file mode 100644
index 000000000000..90d735890655
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkhypertext.cxx
@@ -0,0 +1,291 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+
+#include <stdio.h>
+
+using namespace ::com::sun::star;
+
+
+// ---------------------- AtkHyperlink ----------------------
+
+typedef struct {
+ AtkHyperlink atk_hyper_link;
+
+ uno::Reference< accessibility::XAccessibleHyperlink > xLink;
+} HyperLink;
+
+static uno::Reference< accessibility::XAccessibleHyperlink >
+ getHyperlink( AtkHyperlink *pHyperlink )
+{
+ HyperLink *pLink = (HyperLink *) pHyperlink;
+ return pLink->xLink;
+}
+
+static GObjectClass *hyper_parent_class = NULL;
+
+extern "C" {
+
+static void
+hyper_link_finalize (GObject *obj)
+{
+ HyperLink *hl = (HyperLink *) obj;
+ hl->xLink.clear();
+ hyper_parent_class->finalize (obj);
+}
+
+static gchar *
+hyper_link_get_uri( AtkHyperlink *pLink,
+ gint i )
+{
+ try {
+ uno::Any aAny = getHyperlink( pLink )->getAccessibleActionObject( i );
+ rtl::OUString aUri = aAny.get< rtl::OUString > ();
+ return OUStringToGChar(aUri);
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in hyper_link_get_uri" );
+ }
+ return NULL;
+}
+
+static AtkObject *
+hyper_link_get_object( AtkHyperlink *pLink,
+ gint i)
+{
+ try {
+ uno::Any aAny = getHyperlink( pLink )->getAccessibleActionObject( i );
+ uno::Reference< accessibility::XAccessible > xObj( aAny, uno::UNO_QUERY_THROW );
+ return atk_object_wrapper_ref( xObj );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in hyper_link_get_object" );
+ }
+ return NULL;
+}
+static gint
+hyper_link_get_end_index( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getEndIndex();
+ }
+ catch(const uno::Exception& e) {
+ }
+ return -1;
+}
+static gint
+hyper_link_get_start_index( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getStartIndex();
+ }
+ catch(const uno::Exception& e) {
+ }
+ return -1;
+}
+static gboolean
+hyper_link_is_valid( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->isValid();
+ }
+ catch(const uno::Exception& e) {
+ }
+ return FALSE;
+}
+static gint
+hyper_link_get_n_anchors( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getAccessibleActionCount();
+ }
+ catch(const uno::Exception& e) {
+ }
+ return 0;
+}
+
+static guint
+hyper_link_link_state( AtkHyperlink * )
+{
+ g_warning( "FIXME: hyper_link_link_state unimplemented" );
+ return 0;
+}
+static gboolean
+hyper_link_is_selected_link( AtkHyperlink * )
+{
+ g_warning( "FIXME: hyper_link_is_selected_link unimplemented" );
+ return FALSE;
+}
+
+static void
+hyper_link_class_init (AtkHyperlinkClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = hyper_link_finalize;
+
+ hyper_parent_class = (GObjectClass *)g_type_class_peek_parent (klass);
+
+ klass->get_uri = hyper_link_get_uri;
+ klass->get_object = hyper_link_get_object;
+ klass->get_end_index = hyper_link_get_end_index;
+ klass->get_start_index = hyper_link_get_start_index;
+ klass->is_valid = hyper_link_is_valid;
+ klass->get_n_anchors = hyper_link_get_n_anchors;
+ klass->link_state = hyper_link_link_state;
+ klass->is_selected_link = hyper_link_is_selected_link;
+}
+
+static GType
+hyper_link_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo = {
+ sizeof (AtkHyperlinkClass),
+ NULL, /* base init */
+ NULL, /* base finalize */
+ (GClassInitFunc) hyper_link_class_init,
+ NULL, /* class finalize */
+ NULL, /* class data */
+ sizeof (HyperLink), /* instance size */
+ 0, /* nb preallocs */
+ NULL, /* instance init */
+ NULL /* value table */
+ };
+
+ static const GInterfaceInfo atk_action_info = {
+ (GInterfaceInitFunc) actionIfaceInit,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static (ATK_TYPE_HYPERLINK,
+ "OOoAtkObjHyperLink", &tinfo,
+ (GTypeFlags)0);
+ g_type_add_interface_static (type, ATK_TYPE_ACTION,
+ &atk_action_info);
+ }
+
+ return type;
+}
+
+// ---------------------- AtkHyperText ----------------------
+
+static accessibility::XAccessibleHypertext*
+ getHypertext( AtkHypertext *pHypertext ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pHypertext );
+ if( pWrap )
+ {
+ if( !pWrap->mpHypertext && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleHypertext::static_type(NULL) );
+ pWrap->mpHypertext = reinterpret_cast< accessibility::XAccessibleHypertext * > (any.pReserved);
+ pWrap->mpHypertext->acquire();
+ }
+
+ return pWrap->mpHypertext;
+ }
+
+ return NULL;
+}
+
+
+static AtkHyperlink *
+hypertext_get_link( AtkHypertext *hypertext,
+ gint link_index)
+{
+ try {
+ accessibility::XAccessibleHypertext* pHypertext = getHypertext( hypertext );
+ if( pHypertext )
+ {
+ HyperLink *pLink = (HyperLink *)g_object_new( hyper_link_get_type(), NULL );
+ pLink->xLink = pHypertext->getHyperLink( link_index );
+ if( !pLink->xLink.is() ) {
+ g_object_unref( G_OBJECT( pLink ) );
+ pLink = NULL;
+ }
+ return ATK_HYPERLINK( pLink );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getHyperLink()" );
+ }
+
+ return NULL;
+}
+
+static gint
+hypertext_get_n_links( AtkHypertext *hypertext )
+{
+ try {
+ accessibility::XAccessibleHypertext* pHypertext = getHypertext( hypertext );
+ if( pHypertext )
+ return pHypertext->getHyperLinkCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getHyperLinkCount()" );
+ }
+
+ return 0;
+}
+
+static gint
+hypertext_get_link_index( AtkHypertext *hypertext,
+ gint index)
+{
+ try {
+ accessibility::XAccessibleHypertext* pHypertext = getHypertext( hypertext );
+ if( pHypertext )
+ return pHypertext->getHyperLinkIndex( index );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getHyperLinkIndex()" );
+ }
+
+ return 0;
+}
+
+} // extern "C"
+
+void
+hypertextIfaceInit (AtkHypertextIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_link = hypertext_get_link;
+ iface->get_n_links = hypertext_get_n_links;
+ iface->get_link_index = hypertext_get_link_index;
+}
diff --git a/vcl/unx/gtk/a11y/atkimage.cxx b/vcl/unx/gtk/a11y/atkimage.cxx
new file mode 100644
index 000000000000..b48c59555a29
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkimage.cxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+
+#include <stdio.h>
+
+using namespace ::com::sun::star;
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( rtl::OUString rString )
+{
+ static const int nMax = 10;
+ static rtl::OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
+ return aUgly[ nIdx ];
+}
+
+static accessibility::XAccessibleImage*
+ getImage( AtkImage *pImage ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pImage );
+ if( pWrap )
+ {
+ if( !pWrap->mpImage && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleImage::static_type(NULL) );
+ pWrap->mpImage = reinterpret_cast< accessibility::XAccessibleImage * > (any.pReserved);
+ pWrap->mpImage->acquire();
+ }
+
+ return pWrap->mpImage;
+ }
+
+ return NULL;
+}
+
+extern "C" {
+
+static G_CONST_RETURN gchar *
+image_get_image_description( AtkImage *image )
+{
+ try {
+ accessibility::XAccessibleImage* pImage = getImage( image );
+ if( pImage )
+ return getAsConst( pImage->getAccessibleImageDescription() );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleImageDescription()" );
+ }
+
+ return NULL;
+}
+
+static void
+image_get_image_position( AtkImage *image,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type )
+{
+ *x = *y = 0;
+ if( ATK_IS_COMPONENT( image ) )
+ atk_component_get_position( ATK_COMPONENT( image ), x, y, coord_type );
+ else
+ g_warning( "FIXME: no image position information" );
+}
+
+static void
+image_get_image_size( AtkImage *image,
+ gint *width,
+ gint *height )
+{
+ *width = 0;
+ *height = 0;
+ try {
+ accessibility::XAccessibleImage* pImage = getImage( image );
+ if( pImage )
+ {
+ *width = pImage->getAccessibleImageWidth();
+ *height = pImage->getAccessibleImageHeight();
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleImageHeight() or Width" );
+ }
+}
+
+static gboolean
+image_set_image_description( AtkImage *, const gchar * )
+{
+ g_warning ("FIXME: no set image description");
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+imageIfaceInit (AtkImageIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->set_image_description = image_set_image_description;
+ iface->get_image_description = image_get_image_description;
+ iface->get_image_position = image_get_image_position;
+ iface->get_image_size = image_get_image_size;
+}
diff --git a/vcl/unx/gtk/a11y/atklistener.cxx b/vcl/unx/gtk/a11y/atklistener.cxx
new file mode 100644
index 000000000000..e02478ac8ad8
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atklistener.cxx
@@ -0,0 +1,537 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <com/sun/star/accessibility/TextSegment.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include "atklistener.hxx"
+#include "atkwrapper.hxx"
+
+#include <rtl/ref.hxx>
+#include <stdio.h>
+
+using namespace com::sun::star;
+
+
+#define CSTRING_FROM_ANY(i) rtl::OUStringToOString( i.get< rtl::OUString >(), RTL_TEXTENCODING_UTF8 ).getStr()
+
+AtkListener::AtkListener( AtkObjectWrapper* pWrapper ) : mpWrapper( pWrapper )
+{
+ if( mpWrapper )
+ {
+ g_object_ref( mpWrapper );
+ updateChildList( mpWrapper->mpContext );
+ }
+}
+
+AtkListener::~AtkListener()
+{
+ if( mpWrapper )
+ g_object_unref( mpWrapper );
+}
+
+/*****************************************************************************/
+
+AtkStateType mapState( const uno::Any &rAny )
+{
+ sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
+ rAny >>= nState;
+ return mapAtkState( nState );
+}
+
+/*****************************************************************************/
+
+// XEventListener implementation
+void AtkListener::disposing( const lang::EventObject& ) throw (uno::RuntimeException)
+{
+ if( mpWrapper )
+ {
+ AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
+
+ // Release all interface references to avoid shutdown problems with
+ // global mutex
+ atk_object_wrapper_dispose( mpWrapper );
+
+ // This is an equivalent to a state change to DEFUNC(T).
+ atk_object_notify_state_change( atk_obj, ATK_STATE_DEFUNCT, TRUE );
+
+ if( atk_get_focus_object() == atk_obj )
+ atk_focus_tracker_notify( NULL );
+
+ // Release the wrapper object so that it can vanish ..
+ g_object_unref( mpWrapper );
+ mpWrapper = NULL;
+ }
+}
+
+/*****************************************************************************/
+
+static AtkObject *getObjFromAny( const uno::Any &rAny )
+{
+ uno::Reference< accessibility::XAccessible > xAccessible;
+ rAny >>= xAccessible;
+ return xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : NULL;
+}
+
+/*****************************************************************************/
+
+// Updates the child list held to provide the old IndexInParent on children_changed::remove
+void AtkListener::updateChildList(accessibility::XAccessibleContext* pContext)
+{
+ m_aChildList.clear();
+
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet = pContext->getAccessibleStateSet();
+ if( xStateSet.is()
+ && !xStateSet->contains(accessibility::AccessibleStateType::DEFUNC)
+ && !xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS) )
+ {
+ sal_Int32 nChildren = pContext->getAccessibleChildCount();
+ m_aChildList.resize(nChildren);
+ for(sal_Int32 n = 0; n < nChildren; n++)
+ {
+ m_aChildList[n] = pContext->getAccessibleChild(n);
+ OSL_ASSERT(m_aChildList[n].is());
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleChildAdded(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent,
+ const uno::Reference< accessibility::XAccessible>& rxAccessible)
+{
+ AtkObject * pChild = atk_object_wrapper_ref( rxAccessible );
+
+ if( pChild )
+ {
+ updateChildList(rxParent.get());
+
+ atk_object_wrapper_add_child( mpWrapper, pChild,
+ atk_object_get_index_in_parent( pChild ));
+
+ g_object_unref( pChild );
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleChildRemoved(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent,
+ const uno::Reference< accessibility::XAccessible>& rxChild)
+{
+ sal_Int32 nIndex = -1;
+
+ // Locate the child in the children list
+ size_t n, nmax = m_aChildList.size();
+ for( n = 0; n < nmax; ++n )
+ {
+ if( rxChild == m_aChildList[n] )
+ {
+ nIndex = n;
+ break;
+ }
+ }
+
+ // FIXME: two problems here:
+ // a) we get child-removed events for objects that are no real childs
+ // in the accessibility hierarchy or have been removed before due to
+ // some child removing batch.
+ // b) spi_atk_bridge_signal_listener ignores the given parameters
+ // for children_changed events and always asks the parent for the
+ // 0. child, which breaks somehow on vanishing list boxes.
+ // Ignoring "remove" events for objects not in the m_aChildList
+ // for now.
+ if( nIndex >= 0 )
+ {
+ updateChildList(rxParent.get());
+
+ AtkObject * pChild = atk_object_wrapper_ref( rxChild, false );
+ if( pChild )
+ {
+ atk_object_wrapper_remove_child( mpWrapper, pChild, nIndex );
+ g_object_unref( pChild );
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleInvalidateChildren(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent)
+{
+ // Send notifications for all previous children
+ size_t n = m_aChildList.size();
+ while( n-- > 0 )
+ {
+ if( m_aChildList[n].is() )
+ {
+ AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n], false );
+ if( pChild )
+ {
+ atk_object_wrapper_remove_child( mpWrapper, pChild, n );
+ g_object_unref( pChild );
+ }
+ }
+ }
+
+ updateChildList(rxParent.get());
+
+ // Send notifications for all new children
+ size_t nmax = m_aChildList.size();
+ for( n = 0; n < nmax; ++n )
+ {
+ if( m_aChildList[n].is() )
+ {
+ AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n] );
+
+ if( pChild )
+ {
+ atk_object_wrapper_add_child( mpWrapper, pChild, n );
+ g_object_unref( pChild );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static uno::Reference< accessibility::XAccessibleContext >
+getAccessibleContextFromSource( const uno::Reference< uno::XInterface >& rxSource )
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext(rxSource, uno::UNO_QUERY);
+ if( ! xContext.is() )
+ {
+ g_warning( "ERROR: Event source does not implement XAccessibleContext" );
+
+ // Second try - query for XAccessible, which should give us access to
+ // XAccessibleContext.
+ uno::Reference< accessibility::XAccessible > xAccessible(rxSource, uno::UNO_QUERY);
+ if( xAccessible.is() )
+ xContext = xAccessible->getAccessibleContext();
+ }
+
+ return xContext;
+}
+
+/*****************************************************************************/
+
+// XAccessibleEventListener
+void AtkListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent ) throw( uno::RuntimeException )
+{
+ if( !mpWrapper )
+ return;
+
+ AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
+
+ switch( aEvent.EventId )
+ {
+ // AtkObject signals:
+ // Hierarchy signals
+ case accessibility::AccessibleEventId::CHILD:
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParent;
+ uno::Reference< accessibility::XAccessible > xChild;
+
+ xParent = getAccessibleContextFromSource(aEvent.Source);
+ g_return_if_fail( xParent.is() );
+
+ if( aEvent.OldValue >>= xChild )
+ handleChildRemoved(xParent, xChild);
+
+ if( aEvent.NewValue >>= xChild )
+ handleChildAdded(xParent, xChild);
+ }
+ break;
+
+ case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParent;
+
+ xParent = getAccessibleContextFromSource(aEvent.Source);
+ g_return_if_fail( xParent.is() );
+
+ handleInvalidateChildren(xParent);
+ }
+ break;
+
+ case accessibility::AccessibleEventId::NAME_CHANGED:
+ {
+ rtl::OUString aName;
+ if( aEvent.NewValue >>= aName )
+ {
+ atk_object_set_name(atk_obj,
+ rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+ break;
+
+ case accessibility::AccessibleEventId::DESCRIPTION_CHANGED:
+ {
+ rtl::OUString aDescription;
+ if( aEvent.NewValue >>= aDescription )
+ {
+ atk_object_set_description(atk_obj,
+ rtl::OUStringToOString(aDescription, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+ break;
+
+ case accessibility::AccessibleEventId::STATE_CHANGED:
+ {
+ AtkStateType eOldState = mapState( aEvent.OldValue );
+ AtkStateType eNewState = mapState( aEvent.NewValue );
+
+ gboolean bState = eNewState != ATK_STATE_INVALID;
+ AtkStateType eRealState = bState ? eNewState : eOldState;
+
+ atk_object_notify_state_change( atk_obj, eRealState, bState );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::BOUNDRECT_CHANGED:
+
+#ifdef HAS_ATKRECTANGLE
+ if( ATK_IS_COMPONENT( atk_obj ) )
+ {
+ AtkRectangle rect;
+
+ atk_component_get_extents( ATK_COMPONENT( atk_obj ),
+ &rect.x,
+ &rect.y,
+ &rect.width,
+ &rect.height,
+ ATK_XY_SCREEN );
+
+ g_signal_emit_by_name( atk_obj, "bounds_changed", &rect );
+ }
+ else
+ g_warning( "bounds_changed event for object not implementing AtkComponent\n");
+#endif
+
+ break;
+
+ case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED:
+ g_signal_emit_by_name( atk_obj, "visible-data-changed" );
+ break;
+
+ case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ g_signal_emit_by_name( atk_obj, "active-descendant-changed", pChild );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+
+ // --> OD 2009-05-26 #i92103#
+ case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ AtkStateType eExpandedState = ATK_STATE_EXPANDED;
+ atk_object_notify_state_change( pChild, eExpandedState, true );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+
+ case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ AtkStateType eExpandedState = ATK_STATE_EXPANDED;
+ atk_object_notify_state_change( pChild, eExpandedState, false );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+ // <--
+
+ // AtkAction signals ...
+ case accessibility::AccessibleEventId::ACTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-actions");
+ break;
+
+ // AtkText
+ case accessibility::AccessibleEventId::CARET_CHANGED:
+ {
+ sal_Int32 nPos=0;
+ aEvent.NewValue >>= nPos;
+ g_signal_emit_by_name( atk_obj, "text_caret_moved", nPos );
+ break;
+ }
+ case accessibility::AccessibleEventId::TEXT_CHANGED:
+ {
+ // TESTME: and remove this comment:
+ // cf. comphelper/source/misc/accessibletexthelper.cxx (implInitTextChangedEvent)
+ accessibility::TextSegment aDeletedText;
+ accessibility::TextSegment aInsertedText;
+
+ // TODO: when GNOME starts to send "update" kind of events, change
+ // we need to re-think this implementation as well
+ if( aEvent.OldValue >>= aDeletedText )
+ {
+ /* Remember the text segment here to be able to return removed text in get_text().
+ * This is clearly a hack to be used until appropriate API exists in atk to pass
+ * the string value directly or we find a compelling reason to start caching the
+ * UTF-8 converted strings in the atk wrapper object.
+ */
+
+ g_object_set_data( G_OBJECT(atk_obj), "ooo::text_changed::delete", &aDeletedText);
+
+ g_signal_emit_by_name( atk_obj, "text_changed::delete",
+ (gint) aDeletedText.SegmentStart,
+ (gint)( aDeletedText.SegmentEnd - aDeletedText.SegmentStart ) );
+
+ g_object_steal_data( G_OBJECT(atk_obj), "ooo::text_changed::delete" );
+ }
+
+ if( aEvent.NewValue >>= aInsertedText )
+ g_signal_emit_by_name( atk_obj, "text_changed::insert",
+ (gint) aInsertedText.SegmentStart,
+ (gint)( aInsertedText.SegmentEnd - aInsertedText.SegmentStart ) );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED:
+ {
+ g_signal_emit_by_name( atk_obj, "text-selection-changed" );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED:
+ g_signal_emit_by_name( atk_obj, "text-attributes-changed" );
+ break;
+
+ // AtkValue
+ case accessibility::AccessibleEventId::VALUE_CHANGED:
+ g_object_notify( G_OBJECT( atk_obj ), "accessible-value" );
+ break;
+
+ case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED:
+ // FIXME: ask Bill how Atk copes with this little lot ...
+ break;
+
+ // AtkTable
+ case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED:
+ {
+ accessibility::AccessibleTableModelChange aChange;
+ aEvent.NewValue >>= aChange;
+
+ sal_Int32 nRowsChanged = aChange.LastRow - aChange.FirstRow + 1;
+ sal_Int32 nColumnsChanged = aChange.LastColumn - aChange.FirstColumn + 1;
+
+ static const struct {
+ const char *row;
+ const char *col;
+ } aSignalNames[] =
+ {
+ { NULL, NULL }, // dummy
+ { "row_inserted", "column_inserted" }, // INSERT = 1
+ { "row_deleted", "column_deleted" } // DELETE = 2
+ };
+ switch( aChange.Type )
+ {
+ case accessibility::AccessibleTableModelChangeType::INSERT:
+ case accessibility::AccessibleTableModelChangeType::DELETE:
+ if( nRowsChanged > 0 )
+ g_signal_emit_by_name( G_OBJECT( atk_obj ),
+ aSignalNames[aChange.Type].row,
+ aChange.FirstRow, nRowsChanged );
+ if( nColumnsChanged > 0 )
+ g_signal_emit_by_name( G_OBJECT( atk_obj ),
+ aSignalNames[aChange.Type].col,
+ aChange.FirstColumn, nColumnsChanged );
+ break;
+
+ case accessibility::AccessibleTableModelChangeType::UPDATE:
+ // This is not really a model change, is it ?
+ break;
+ default:
+ g_warning( "TESTME: unusual table model change %d\n", aChange.Type );
+ break;
+ }
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "model-changed" );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-column-header");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-caption");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-column-description");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-description");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-header");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-summary");
+ break;
+
+ case accessibility::AccessibleEventId::SELECTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "selection_changed");
+ break;
+
+ case accessibility::AccessibleEventId::HYPERTEXT_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-hypertext-offset");
+ break;
+
+ default:
+ g_warning( "Unknown event notification %d", aEvent.EventId );
+ break;
+ }
+}
diff --git a/vcl/unx/gtk/a11y/atklistener.hxx b/vcl/unx/gtk/a11y/atklistener.hxx
new file mode 100644
index 000000000000..d2889caa3e24
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atklistener.hxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 _ATK_LISTENER_HXX_
+#define _ATK_LISTENER_HXX_
+
+#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+#include <vector>
+
+#include "atkwrapper.hxx"
+
+typedef std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > > AccessibleVector;
+
+class AtkListener : public ::cppu::WeakImplHelper1< ::com::sun::star::accessibility::XAccessibleEventListener >
+{
+public:
+ AtkListener(AtkObjectWrapper * pWrapper);
+
+ // XEventListener
+ virtual void disposing( const ::com::sun::star::lang::EventObject& Source )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleEventListener
+ virtual void notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent )
+ throw( ::com::sun::star::uno::RuntimeException );
+
+ AtkObjectWrapper *mpWrapper;
+ AccessibleVector m_aChildList;
+
+private:
+
+ virtual ~AtkListener();
+
+ // Updates the child list held to provide the old IndexInParent on children_changed::remove
+ void updateChildList(::com::sun::star::accessibility::XAccessibleContext* pContext);
+
+ // Process CHILD_EVENT notifications with a new child added
+ void handleChildAdded(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& rxParent,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible>& rxChild);
+
+ // Process CHILD_EVENT notifications with a child removed
+ void handleChildRemoved(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& rxParent,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible>& rxChild);
+
+ // Process INVALIDATE_ALL_CHILDREN notification
+ void handleInvalidateChildren(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& rxParent);
+};
+
+#endif /* _ATK_LISTENER_HXX_ */
+
diff --git a/vcl/unx/gtk/a11y/atkregistry.cxx b/vcl/unx/gtk/a11y/atkregistry.cxx
new file mode 100644
index 000000000000..81ec22dc4ce1
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkregistry.cxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 "atkregistry.hxx"
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+static GHashTable *uno_to_gobject = NULL;
+
+/*****************************************************************************/
+
+AtkObject *
+ooo_wrapper_registry_get(const Reference< XAccessible >& rxAccessible)
+{
+ if( uno_to_gobject )
+ {
+ gpointer cached =
+ g_hash_table_lookup(uno_to_gobject, (gpointer) rxAccessible.get());
+
+ if( cached )
+ return ATK_OBJECT( cached );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+void
+ooo_wrapper_registry_add(const Reference< XAccessible >& rxAccessible, AtkObject *obj)
+{
+ if( !uno_to_gobject )
+ uno_to_gobject = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert( uno_to_gobject, (gpointer) rxAccessible.get(), obj );
+}
+
+/*****************************************************************************/
+
+void
+ooo_wrapper_registry_remove(XAccessible *pAccessible)
+{
+ if( uno_to_gobject )
+ g_hash_table_remove( uno_to_gobject, (gpointer) pAccessible );
+}
+
diff --git a/vcl/unx/gtk/a11y/atkregistry.hxx b/vcl/unx/gtk/a11y/atkregistry.hxx
new file mode 100644
index 000000000000..f4de3b2e4c1e
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkregistry.hxx
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_REGISTRY_HXX__
+#define __ATK_REGISTRY_HXX__
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <atk/atk.h>
+
+AtkObject * ooo_wrapper_registry_get(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible);
+
+void ooo_wrapper_registry_add(const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible, AtkObject *obj);
+
+void ooo_wrapper_registry_remove(::com::sun::star::accessibility::XAccessible *pAccessible);
+
+#endif // __ATK_REGISTRY_HXX_
diff --git a/vcl/unx/gtk/a11y/atkselection.cxx b/vcl/unx/gtk/a11y/atkselection.cxx
new file mode 100644
index 000000000000..172faac4c704
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkselection.cxx
@@ -0,0 +1,195 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+#include <stdio.h>
+
+using namespace ::com::sun::star;
+
+static accessibility::XAccessibleSelection*
+ getSelection( AtkSelection *pSelection ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pSelection );
+ if( pWrap )
+ {
+ if( !pWrap->mpSelection && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleSelection::static_type(NULL) );
+ pWrap->mpSelection = reinterpret_cast< accessibility::XAccessibleSelection * > (any.pReserved);
+ pWrap->mpSelection->acquire();
+ }
+
+ return pWrap->mpSelection;
+ }
+
+ return NULL;
+}
+
+extern "C" {
+
+static gboolean
+selection_add_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ {
+ pSelection->selectAccessibleChild( i );
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in selectAccessibleChild()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_clear_selection( AtkSelection *selection )
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ {
+ pSelection->clearAccessibleSelection();
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in selectAccessibleChild()" );
+ }
+
+ return FALSE;
+}
+
+static AtkObject*
+selection_ref_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ return atk_object_wrapper_ref( pSelection->getSelectedAccessibleChild( i ) );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleChild()" );
+ }
+
+ return NULL;
+}
+
+static gint
+selection_get_selection_count( AtkSelection *selection)
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ return pSelection->getSelectedAccessibleChildCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return -1;
+}
+
+static gboolean
+selection_is_child_selected( AtkSelection *selection,
+ gint i)
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ return pSelection->isAccessibleChildSelected( i );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_remove_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ {
+ pSelection->deselectAccessibleChild( i );
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_select_all_selection( AtkSelection *selection)
+{
+ try {
+ accessibility::XAccessibleSelection* pSelection = getSelection( selection );
+ if( pSelection )
+ {
+ pSelection->selectAllAccessibleChildren();
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+selectionIfaceInit( AtkSelectionIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->add_selection = selection_add_selection;
+ iface->clear_selection = selection_clear_selection;
+ iface->ref_selection = selection_ref_selection;
+ iface->get_selection_count = selection_get_selection_count;
+ iface->is_child_selected = selection_is_child_selected;
+ iface->remove_selection = selection_remove_selection;
+ iface->select_all_selection = selection_select_all_selection;
+}
diff --git a/vcl/unx/gtk/a11y/atktable.cxx b/vcl/unx/gtk/a11y/atktable.cxx
new file mode 100644
index 000000000000..78571ff11c34
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atktable.cxx
@@ -0,0 +1,721 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+
+#ifdef ENABLE_TRACING
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+
+static inline AtkObject *
+atk_object_wrapper_conditional_ref( const uno::Reference< accessibility::XAccessible >& rxAccessible )
+{
+#ifdef ENABLE_TRACING
+ fprintf( stderr, ": %p\n", rxAccessible.get() );
+#endif
+
+ if( rxAccessible.is() )
+ return atk_object_wrapper_ref( rxAccessible );
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( rtl::OUString rString )
+{
+ static const int nMax = 10;
+ static rtl::OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
+ return aUgly[ nIdx ];
+}
+
+/*****************************************************************************/
+
+static accessibility::XAccessibleTable*
+ getTable( AtkTable *pTable ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pTable );
+ if( pWrap )
+ {
+ if( !pWrap->mpTable && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleTable::static_type(NULL) );
+ pWrap->mpTable = reinterpret_cast< accessibility::XAccessibleTable * > (any.pReserved);
+ pWrap->mpTable->acquire();
+ }
+
+ return pWrap->mpTable;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static AtkObject*
+table_wrapper_ref_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleCellAt( %u, %u ) returns", row, column );
+
+ if( column >= 255 )
+ fprintf(stderr, "getAccessibleCellAt( %u, %u ) returns", row, column );
+
+#endif
+
+ if( pTable )
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleCellAt( row, column ) );
+ }
+
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleCellAt()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_index_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleIndex( %u, %u ) returns %u\n",
+ row, column, pTable->getAccessibleIndex( row, column ) );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleIndex( row, column );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleIndex()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_column_at_index (AtkTable *table,
+ gint nIndex)
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleColumn( %u ) returns %u\n",
+ nIndex, pTable->getAccessibleColumn( nIndex ) );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleColumn( nIndex );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleColumn()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_row_at_index( AtkTable *table,
+ gint nIndex )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleRow( %u ) returns %u\n",
+ nIndex, pTable->getAccessibleRow( nIndex ) );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleRow( nIndex );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleRow()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_n_columns( AtkTable *table )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "XAccessibleTable::getAccessibleColumnCount returns %u\n",
+ pTable->getAccessibleColumnCount() );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleColumnCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleColumnCount()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_n_rows( AtkTable *table )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleRowCount() returns %u\n",
+ pTable->getAccessibleRowCount() );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleRowCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleRowCount()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_column_extent_at( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleColumnExtentAt( %u, %u ) returns %u\n",
+ row, column, pTable->getAccessibleColumnExtentAt( row, column ) );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleColumnExtentAt( row, column );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleColumnExtentAt()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_row_extent_at( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleRowExtentAt( %u, %u ) returns %u\n",
+ row, column, pTable->getAccessibleRowExtentAt( row, column ) );
+#endif
+
+ if( pTable )
+ return pTable->getAccessibleRowExtentAt( row, column );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleRowExtentAt()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_caption( AtkTable *table )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleCaption() returns" );
+#endif
+
+ if( pTable )
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleCaption() );
+ }
+
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleCaption()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+table_wrapper_get_row_description( AtkTable *table,
+ gint row )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleRowDescription( %u ) returns %s\n",
+ row, getAsConst( pTable->getAccessibleRowDescription( row ) ) );
+#endif
+
+ if( pTable )
+ return getAsConst( pTable->getAccessibleRowDescription( row ) );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleRowDescription()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+table_wrapper_get_column_description( AtkTable *table,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleColumnDescription( %u ) returns %s\n",
+ column, getAsConst( pTable->getAccessibleColumnDescription( column ) ) );
+#endif
+
+ if( pTable )
+ return getAsConst( pTable->getAccessibleColumnDescription( column ) );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleColumnDescription()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_row_header( AtkTable *table,
+ gint row )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+ if( pTable )
+ {
+ uno::Reference< accessibility::XAccessibleTable > xRowHeaders( pTable->getAccessibleRowHeaders() );
+
+#ifdef ENABLE_TRACING
+ if( xRowHeaders.is() )
+ fprintf(stderr, "getAccessibleRowHeader( %u )->getAccessibleCellAt( 0, %u ) returns",
+ row, row );
+ else
+ fprintf(stderr, "getAccessibleRowHeader( %u ) returns %p\n", row, xRowHeaders.get() );
+#endif
+
+ if( xRowHeaders.is() )
+ return atk_object_wrapper_conditional_ref( xRowHeaders->getAccessibleCellAt( row, 0 ) );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleRowHeaders()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_column_header( AtkTable *table,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+ if( pTable )
+ {
+ uno::Reference< accessibility::XAccessibleTable > xColumnHeaders( pTable->getAccessibleColumnHeaders() );
+
+#ifdef ENABLE_TRACING
+ if( xColumnHeaders.is() )
+ fprintf(stderr, "getAccessibleColumnHeader( %u )->getAccessibleCellAt( 0, %u ) returns",
+ column, column );
+ else
+ fprintf(stderr, "getAccessibleColumnHeader( %u ) returns %p\n", column, xColumnHeaders.get() );
+#endif
+
+ if( xColumnHeaders.is() )
+ return atk_object_wrapper_conditional_ref( xColumnHeaders->getAccessibleCellAt( 0, column ) );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleColumnHeaders()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_summary( AtkTable *table )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getAccessibleSummary() returns" );
+#endif
+
+ if( pTable )
+ {
+ // FIXME: Summary ??
+// AtkObject* summary;
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleSummary() );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleSummary()" );
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static gint
+convertToGIntArray( const uno::Sequence< ::sal_Int32 >& aSequence, gint **pSelected )
+{
+ if( aSequence.getLength() )
+ {
+ *pSelected = g_new( gint, aSequence.getLength() );
+
+ for( sal_Int32 i = 0; i < aSequence.getLength(); i++ )
+ (*pSelected) [i] = aSequence[i];
+ }
+
+ return aSequence.getLength();
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_selected_columns( AtkTable *table,
+ gint **pSelected )
+{
+ *pSelected = NULL;
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getSelectedAccessibleColumns() \n" );
+#endif
+
+ if( pTable )
+ return convertToGIntArray( pTable->getSelectedAccessibleColumns(), pSelected );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleColumns()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_selected_rows( AtkTable *table,
+ gint **pSelected )
+{
+ *pSelected = NULL;
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "getSelectedAccessibleRows() \n" );
+#endif
+
+ if( pTable )
+ return convertToGIntArray( pTable->getSelectedAccessibleRows(), pSelected );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectedAccessibleRows()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_column_selected( AtkTable *table,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "isAccessibleColumnSelected( %u ) returns %s\n",
+ column, pTable->isAccessibleColumnSelected( column ) ? "true" : "false" );
+#endif
+
+ if( pTable )
+ return pTable->isAccessibleColumnSelected( column );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in isAccessibleColumnSelected()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_row_selected( AtkTable *table,
+ gint row )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "isAccessibleRowSelected( %u ) returns %s\n",
+ row, pTable->isAccessibleRowSelected( row ) ? "true" : "false" );
+#endif
+
+ if( pTable )
+ return pTable->isAccessibleRowSelected( row );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in isAccessibleRowSelected()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_selected( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ accessibility::XAccessibleTable* pTable = getTable( table );
+
+#ifdef ENABLE_TRACING
+ if( pTable )
+ fprintf(stderr, "isAccessibleSelected( %u, %u ) returns %s\n",
+ row, column, pTable->isAccessibleSelected( row , column ) ? "true" : "false" );
+#endif
+
+ if( pTable )
+ return pTable->isAccessibleSelected( row, column );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in isAccessibleSelected()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_add_row_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for add_row_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_remove_row_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for remove_row_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_add_column_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for add_column_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_remove_column_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for remove_column_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_caption( AtkTable *, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_column_description( AtkTable *, gint, const gchar * )
+{ // meaningless helper
+}
+
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_column_header( AtkTable *, gint, AtkObject * )
+{ // meaningless helper
+}
+
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_row_description( AtkTable *, gint, const gchar * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_row_header( AtkTable *, gint, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_summary( AtkTable *, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+} // extern "C"
+
+void
+tableIfaceInit (AtkTableIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->ref_at = table_wrapper_ref_at;
+ iface->get_n_rows = table_wrapper_get_n_rows;
+ iface->get_n_columns = table_wrapper_get_n_columns;
+ iface->get_index_at = table_wrapper_get_index_at;
+ iface->get_column_at_index = table_wrapper_get_column_at_index;
+ iface->get_row_at_index = table_wrapper_get_row_at_index;
+ iface->is_row_selected = table_wrapper_is_row_selected;
+ iface->is_selected = table_wrapper_is_selected;
+ iface->get_selected_rows = table_wrapper_get_selected_rows;
+ iface->add_row_selection = table_wrapper_add_row_selection;
+ iface->remove_row_selection = table_wrapper_remove_row_selection;
+ iface->add_column_selection = table_wrapper_add_column_selection;
+ iface->remove_column_selection = table_wrapper_remove_column_selection;
+ iface->get_selected_columns = table_wrapper_get_selected_columns;
+ iface->is_column_selected = table_wrapper_is_column_selected;
+ iface->get_column_extent_at = table_wrapper_get_column_extent_at;
+ iface->get_row_extent_at = table_wrapper_get_row_extent_at;
+ iface->get_row_header = table_wrapper_get_row_header;
+ iface->set_row_header = table_wrapper_set_row_header;
+ iface->get_column_header = table_wrapper_get_column_header;
+ iface->set_column_header = table_wrapper_set_column_header;
+ iface->get_caption = table_wrapper_get_caption;
+ iface->set_caption = table_wrapper_set_caption;
+ iface->get_summary = table_wrapper_get_summary;
+ iface->set_summary = table_wrapper_set_summary;
+ iface->get_row_description = table_wrapper_get_row_description;
+ iface->set_row_description = table_wrapper_set_row_description;
+ iface->get_column_description = table_wrapper_get_column_description;
+ iface->set_column_description = table_wrapper_set_column_description;
+}
diff --git a/vcl/unx/gtk/a11y/atktext.cxx b/vcl/unx/gtk/a11y/atktext.cxx
new file mode 100644
index 000000000000..e6d3276891de
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atktext.cxx
@@ -0,0 +1,876 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+#include "atktextattributes.hxx"
+#include <algorithm>
+
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/text/TextMarkupType.hpp>
+
+// #define ENABLE_TRACING
+
+#ifdef ENABLE_TRACING
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+
+static sal_Int16
+text_type_from_boundary(AtkTextBoundary boundary_type)
+{
+ switch(boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ return accessibility::AccessibleTextType::CHARACTER;
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ return accessibility::AccessibleTextType::WORD;
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ return accessibility::AccessibleTextType::SENTENCE;
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ return accessibility::AccessibleTextType::LINE;
+ default:
+ return -1;
+ }
+}
+
+/*****************************************************************************/
+
+static gchar *
+adjust_boundaries( accessibility::XAccessibleText* pText,
+ accessibility::TextSegment& rTextSegment,
+ AtkTextBoundary boundary_type,
+ gint * start_offset, gint * end_offset )
+{
+ accessibility::TextSegment aTextSegment;
+ rtl::OUString aString;
+ gint start = 0, end = 0;
+
+ if( rTextSegment.SegmentText.getLength() > 0 )
+ {
+ switch(boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ start = rTextSegment.SegmentStart;
+ end = rTextSegment.SegmentEnd;
+ aString = rTextSegment.SegmentText;
+ break;
+
+ // the OOo break iterator behaves as SENTENCE_START
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ start = rTextSegment.SegmentStart;
+ end = rTextSegment.SegmentEnd;
+
+ if( start > 0 )
+ --start;
+ if( end > 0 && end < pText->getCharacterCount() - 1 )
+ --end;
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ start = rTextSegment.SegmentStart;
+
+ // Determine the start index of the next segment
+ aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
+ text_type_from_boundary(boundary_type));
+ if( aTextSegment.SegmentText.getLength() > 0 )
+ end = aTextSegment.SegmentStart;
+ else
+ end = pText->getCharacterCount();
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ end = rTextSegment.SegmentEnd;
+
+ // Determine the end index of the previous segment
+ aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
+ text_type_from_boundary(boundary_type));
+ if( aTextSegment.SegmentText.getLength() > 0 )
+ start = aTextSegment.SegmentEnd;
+ else
+ start = 0;
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+
+ *start_offset = start;
+ *end_offset = end;
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "adjust_boundaries( %d, %d, %d ) returns %d, %d\n",
+ rTextSegment.SegmentStart, rTextSegment.SegmentEnd, boundary_type,
+ start, end);
+#endif
+
+ return OUStringToGChar(aString);
+}
+
+/*****************************************************************************/
+
+static accessibility::XAccessibleText*
+ getText( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpText && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleText::static_type(NULL) );
+ pWrap->mpText = reinterpret_cast< accessibility::XAccessibleText * > (any.pReserved);
+ pWrap->mpText->acquire();
+ }
+
+ return pWrap->mpText;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static accessibility::XAccessibleTextMarkup*
+ getTextMarkup( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpTextMarkup && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleTextMarkup::static_type(NULL) );
+ /* Since this not a dedicated interface in Atk and thus has not
+ * been queried during wrapper initialization, we need to check
+ * the return value here.
+ */
+ if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
+ {
+ pWrap->mpTextMarkup = reinterpret_cast< accessibility::XAccessibleTextMarkup * > (any.pReserved);
+ if( pWrap->mpTextMarkup )
+ pWrap->mpTextMarkup->acquire();
+ }
+ }
+
+ return pWrap->mpTextMarkup;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static accessibility::XAccessibleTextAttributes*
+ getTextAttributes( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpTextAttributes && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleTextAttributes::static_type(NULL) );
+ /* Since this not a dedicated interface in Atk and thus has not
+ * been queried during wrapper initialization, we need to check
+ * the return value here.
+ */
+ if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
+ {
+ pWrap->mpTextAttributes = reinterpret_cast< accessibility::XAccessibleTextAttributes * > (any.pReserved);
+ pWrap->mpTextAttributes->acquire();
+ }
+ }
+
+ return pWrap->mpTextAttributes;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static accessibility::XAccessibleMultiLineText*
+ getMultiLineText( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpMultiLineText && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleMultiLineText::static_type(NULL) );
+ /* Since this not a dedicated interface in Atk and thus has not
+ * been queried during wrapper initialization, we need to check
+ * the return value here.
+ */
+ if( typelib_TypeClass_INTERFACE == any.pType->eTypeClass )
+ {
+ pWrap->mpMultiLineText = reinterpret_cast< accessibility::XAccessibleMultiLineText * > (any.pReserved);
+ pWrap->mpMultiLineText->acquire();
+ }
+ }
+
+ return pWrap->mpMultiLineText;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gchar *
+text_wrapper_get_text (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ gchar * ret = NULL;
+
+ g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), NULL );
+
+ /* at-spi expects the delete event to be send before the deletion happened
+ * so we save the deleted string object in the UNO event notification and
+ * fool libatk-bridge.so here ..
+ */
+ void * pData = g_object_get_data( G_OBJECT(text), "ooo::text_changed::delete" );
+ if( pData != NULL )
+ {
+ accessibility::TextSegment * pTextSegment =
+ reinterpret_cast <accessibility::TextSegment *> (pData);
+
+ if( pTextSegment->SegmentStart == start_offset &&
+ pTextSegment->SegmentEnd == end_offset )
+ {
+ rtl::OString aUtf8 = rtl::OUStringToOString( pTextSegment->SegmentText, RTL_TEXTENCODING_UTF8 );
+ return g_strdup( aUtf8.getStr() );
+ }
+ }
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ rtl::OUString aText;
+ sal_Int32 n = pText->getCharacterCount();
+
+ if( -1 == end_offset )
+ aText = pText->getText();
+ else if( start_offset < n )
+ aText = pText->getTextRange(start_offset, end_offset);
+
+ ret = g_strdup( rtl::OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getText()" );
+ }
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "text_wrapper_get_text( %d,%d ) returns %s\n", start_offset, end_offset, ret ? ret : "null" );
+#endif
+ return ret;
+}
+
+static gchar *
+text_wrapper_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in get_text_after_offset()" );
+ }
+
+ return NULL;
+}
+
+static gchar *
+text_wrapper_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ /* If the user presses the 'End' key, the caret will be placed behind the last character,
+ * which is the same index as the first character of the next line. In atk the magic offset
+ * '-2' is used to cover this special case.
+ */
+ if (
+ -2 == offset &&
+ (ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
+ ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
+ )
+ {
+ accessibility::XAccessibleMultiLineText* pMultiLineText = getMultiLineText( text );
+ if( pMultiLineText )
+ {
+ accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret();
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+
+ accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in get_text_at_offset()" );
+ }
+
+ return NULL;
+}
+
+static gunichar
+text_wrapper_get_character_at_offset (AtkText *text,
+ gint offset)
+{
+ gint start, end;
+ gunichar uc = 0;
+
+ gchar * char_as_string =
+ text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
+ &start, &end);
+ if( char_as_string )
+ {
+ uc = g_utf8_get_char( char_as_string );
+ g_free( char_as_string );
+ }
+
+ return uc;
+}
+
+static gchar *
+text_wrapper_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in text_before_offset()" );
+ }
+
+ return NULL;
+}
+
+static gint
+text_wrapper_get_caret_offset (AtkText *text)
+{
+ gint offset = -1;
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ offset = pText->getCaretPosition();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCaretPosition()" );
+ }
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "get_caret_offset(%p) returns %d\n", text, offset);
+#endif
+
+ return offset;
+}
+
+static gboolean
+text_wrapper_set_caret_offset (AtkText *text,
+ gint offset)
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ return pText->setCaretPosition( offset );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setCaretPosition()" );
+ }
+
+ return FALSE;
+}
+
+// --> OD 2010-03-04 #i92232#
+AtkAttributeSet*
+handle_text_markup_as_run_attribute( accessibility::XAccessibleTextMarkup* pTextMarkup,
+ const gint nTextMarkupType,
+ const gint offset,
+ AtkAttributeSet* pSet,
+ gint *start_offset,
+ gint *end_offset )
+{
+ const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
+ if ( nTextMarkupCount > 0 )
+ {
+ for ( gint nTextMarkupIndex = 0;
+ nTextMarkupIndex < nTextMarkupCount;
+ ++nTextMarkupIndex )
+ {
+ accessibility::TextSegment aTextSegment =
+ pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
+ const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
+ const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
+ if ( nStartOffsetTextMarkup <= offset )
+ {
+ if ( offset < nEndOffsetTextMarkup )
+ {
+ // text markup at <offset>
+ *start_offset = ::std::max( *start_offset,
+ nStartOffsetTextMarkup );
+ *end_offset = ::std::min( *end_offset,
+ nEndOffsetTextMarkup );
+ switch ( nTextMarkupType )
+ {
+ case com::sun::star::text::TextMarkupType::SPELLCHECK:
+ {
+ pSet = attribute_set_prepend_misspelled( pSet );
+ }
+ break;
+ case com::sun::star::text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ {
+ pSet = attribute_set_prepend_tracked_change_insertion( pSet );
+ }
+ break;
+ case com::sun::star::text::TextMarkupType::TRACK_CHANGE_DELETION:
+ {
+ pSet = attribute_set_prepend_tracked_change_deletion( pSet );
+ }
+ break;
+ case com::sun::star::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
+ }
+ break;
+ default:
+ {
+ OSL_ASSERT( false );
+ }
+ }
+ break; // no further iteration needed.
+ }
+ else
+ {
+ *start_offset = ::std::max( *start_offset,
+ nEndOffsetTextMarkup );
+ // continue iteration.
+ }
+ }
+ else
+ {
+ *end_offset = ::std::min( *end_offset,
+ nStartOffsetTextMarkup );
+ break; // no further iteration.
+ }
+ } // eof iteration over text markups
+ }
+
+ return pSet;
+}
+// <--
+
+static AtkAttributeSet *
+text_wrapper_get_run_attributes( AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ AtkAttributeSet *pSet = NULL;
+
+ try {
+ bool bOffsetsAreValid = false;
+
+ accessibility::XAccessibleText* pText = getText( text );
+ accessibility::XAccessibleTextAttributes* pTextAttributes = getTextAttributes( text );
+ if( pText && pTextAttributes )
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList =
+ pTextAttributes->getRunAttributes( offset, uno::Sequence< rtl::OUString > () );
+
+ pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
+ // --> OD 2009-06-22 #i100938#
+ // - always provide start_offset and end_offset
+// if( pSet )
+ // <--
+ {
+ accessibility::TextSegment aTextSegment =
+ pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+
+ *start_offset = aTextSegment.SegmentStart;
+ // --> OD 2009-06-22 #i100938#
+ // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
+// *end_offset = aTextSegment.SegmentEnd + 1; // FIXME: TESTME
+ *end_offset = aTextSegment.SegmentEnd;
+ // <--
+ bOffsetsAreValid = true;
+ }
+ }
+
+ // Special handling for misspelled text
+ // --> OD 2010-03-01 #i92232#
+ // - add special handling for tracked changes and refactor the
+ // corresponding code for handling misspelled text.
+ accessibility::XAccessibleTextMarkup* pTextMarkup = getTextMarkup( text );
+ if( pTextMarkup )
+ {
+ // Get attribute run here if it hasn't been done before
+ if( !bOffsetsAreValid )
+ {
+ accessibility::TextSegment aAttributeTextSegment =
+ pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+ *start_offset = aAttributeTextSegment.SegmentStart;
+ *end_offset = aAttributeTextSegment.SegmentEnd;
+ }
+ // handle misspelled text
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ com::sun::star::text::TextMarkupType::SPELLCHECK,
+ offset, pSet, start_offset, end_offset );
+ // handle tracked changes
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ com::sun::star::text::TextMarkupType::TRACK_CHANGE_INSERTION,
+ offset, pSet, start_offset, end_offset );
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ com::sun::star::text::TextMarkupType::TRACK_CHANGE_DELETION,
+ offset, pSet, start_offset, end_offset );
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ com::sun::star::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
+ offset, pSet, start_offset, end_offset );
+ }
+ // <--
+ }
+ catch(const uno::Exception& e){
+
+ g_warning( "Exception in get_run_attributes()" );
+
+ if( pSet )
+ {
+ atk_attribute_set_free( pSet );
+ pSet = NULL;
+ }
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static AtkAttributeSet *
+text_wrapper_get_default_attributes( AtkText *text )
+{
+ AtkAttributeSet *pSet = NULL;
+
+ try {
+ accessibility::XAccessibleTextAttributes* pTextAttributes = getTextAttributes( text );
+ if( pTextAttributes )
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList =
+ pTextAttributes->getDefaultAttributes( uno::Sequence< rtl::OUString > () );
+
+ pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
+ }
+ }
+ catch(const uno::Exception& e) {
+
+ g_warning( "Exception in get_default_attributes()" );
+
+ if( pSet )
+ {
+ atk_attribute_set_free( pSet );
+ pSet = NULL;
+ }
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static void
+text_wrapper_get_character_extents( AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords )
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ *x = *y = *width = *height = 0;
+ awt::Rectangle aRect = pText->getCharacterBounds( offset );
+
+ gint origin_x = 0;
+ gint origin_y = 0;
+
+ if( coords == ATK_XY_SCREEN )
+ {
+ g_return_if_fail( ATK_IS_COMPONENT( text ) );
+ atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
+ }
+
+ *x = aRect.X + origin_x;
+ *y = aRect.Y + origin_y;
+ *width = aRect.Width;
+ *height = aRect.Height;
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "get_character_extents(%d, %d) returns: %d,%d,%d,%d ",
+ offset, coords, *x, *y, *width, *height);
+#endif
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCharacterBounds" );
+ }
+}
+
+static gint
+text_wrapper_get_character_count (AtkText *text)
+{
+ gint rv = 0;
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ rv = pText->getCharacterCount();
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCharacterCount" );
+ }
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "get_character_count(%p) returns: %d\n", text, rv);
+#endif
+
+ return rv;
+}
+
+static gint
+text_wrapper_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords)
+{
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ gint origin_x = 0;
+ gint origin_y = 0;
+
+ if( coords == ATK_XY_SCREEN )
+ {
+ g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
+ atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
+ }
+
+ return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getIndexAtPoint" );
+ }
+
+ return -1;
+}
+
+// FIXME: the whole series of selections API is problematic ...
+
+static gint
+text_wrapper_get_n_selections (AtkText *text)
+{
+ gint rv = 0;
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
+ }
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "get_n_selections(%p) returns %d\n", text, rv);
+#endif
+
+ return rv;
+}
+
+static gchar *
+text_wrapper_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_offset,
+ gint *end_offset)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ {
+ *start_offset = pText->getSelectionStart();
+ *end_offset = pText->getSelectionEnd();
+
+ return OUStringToGChar( pText->getSelectedText() );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
+ }
+
+ return NULL;
+}
+
+static gboolean
+text_wrapper_add_selection (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ // FIXME: can we try to be more compatible by expanding an
+ // existing adjacent selection ?
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ return pText->setSelection( start_offset, end_offset ); // ?
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+text_wrapper_remove_selection (AtkText *text,
+ gint selection_num)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ return pText->setSelection( 0, 0 ); // ?
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+text_wrapper_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ accessibility::XAccessibleText* pText = getText( text );
+ if( pText )
+ return pText->setSelection( start_offset, end_offset );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+textIfaceInit (AtkTextIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_text = text_wrapper_get_text;
+ iface->get_character_at_offset = text_wrapper_get_character_at_offset;
+ iface->get_text_before_offset = text_wrapper_get_text_before_offset;
+ iface->get_text_at_offset = text_wrapper_get_text_at_offset;
+ iface->get_text_after_offset = text_wrapper_get_text_after_offset;
+ iface->get_caret_offset = text_wrapper_get_caret_offset;
+ iface->set_caret_offset = text_wrapper_set_caret_offset;
+ iface->get_character_count = text_wrapper_get_character_count;
+ iface->get_n_selections = text_wrapper_get_n_selections;
+ iface->get_selection = text_wrapper_get_selection;
+ iface->add_selection = text_wrapper_add_selection;
+ iface->remove_selection = text_wrapper_remove_selection;
+ iface->set_selection = text_wrapper_set_selection;
+ iface->get_run_attributes = text_wrapper_get_run_attributes;
+ iface->get_default_attributes = text_wrapper_get_default_attributes;
+ iface->get_character_extents = text_wrapper_get_character_extents;
+ iface->get_offset_at_point = text_wrapper_get_offset_at_point;
+}
diff --git a/vcl/unx/gtk/a11y/atktextattributes.cxx b/vcl/unx/gtk/a11y/atktextattributes.cxx
new file mode 100644
index 000000000000..04498810597f
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atktextattributes.cxx
@@ -0,0 +1,1456 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atktextattributes.hxx"
+
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+
+#include <com/sun/star/style/CaseMap.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/style/TabAlign.hpp>
+#include <com/sun/star/style/TabStop.hpp>
+
+#include <com/sun/star/text/WritingMode2.hpp>
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
+typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
+
+#define STRNCMP_PARAM( s ) s,sizeof( s )-1
+
+
+/*****************************************************************************/
+
+static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
+// --> OD 2010-03-01 #i92232#
+static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
+// <--
+// --> OD 2010-03-05 #i92233#
+static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
+// <--
+
+/*****************************************************************************/
+
+/**
+ * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
+ * and re-arrange the enum values accordingly.
+ */
+
+enum ExportedAttribute
+{
+ TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
+ TEXT_ATTRIBUTE_CASEMAP,
+ TEXT_ATTRIBUTE_FOREGROUND_COLOR,
+ TEXT_ATTRIBUTE_CONTOURED,
+ TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
+ TEXT_ATTRIBUTE_BLINKING,
+ TEXT_ATTRIBUTE_FONT_NAME,
+ TEXT_ATTRIBUTE_HEIGHT,
+ TEXT_ATTRIBUTE_HIDDEN,
+ TEXT_ATTRIBUTE_KERNING,
+ TEXT_ATTRIBUTE_LOCALE,
+ TEXT_ATTRIBUTE_POSTURE,
+ TEXT_ATTRIBUTE_RELIEF,
+ TEXT_ATTRIBUTE_ROTATION,
+ TEXT_ATTRIBUTE_SCALE,
+ TEXT_ATTRIBUTE_SHADOWED,
+ TEXT_ATTRIBUTE_STRIKETHROUGH,
+ TEXT_ATTRIBUTE_UNDERLINE,
+ TEXT_ATTRIBUTE_WEIGHT,
+ // --> OD 2010-03-05 #i92233#
+ TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
+ // <--
+ TEXT_ATTRIBUTE_JUSTIFICATION,
+ TEXT_ATTRIBUTE_BOTTOM_MARGIN,
+ TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
+ TEXT_ATTRIBUTE_LEFT_MARGIN,
+ TEXT_ATTRIBUTE_LINE_SPACING,
+ TEXT_ATTRIBUTE_RIGHT_MARGIN,
+ TEXT_ATTRIBUTE_STYLE_NAME,
+ TEXT_ATTRIBUTE_TAB_STOPS,
+ TEXT_ATTRIBUTE_TOP_MARGIN,
+ TEXT_ATTRIBUTE_WRITING_MODE,
+ TEXT_ATTRIBUTE_LAST
+};
+
+static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
+{
+ "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
+ "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
+ "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
+ "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
+ "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
+ "CharFlash", // TEXT_ATTRIBUTE_BLINKING
+ "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
+ "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
+ "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
+ "CharKerning", // TEXT_ATTRIBUTE_KERNING
+ "CharLocale", // TEXT_ATTRIBUTE_LOCALE
+ "CharPosture", // TEXT_ATTRIBUTE_POSTURE
+ "CharRelief", // TEXT_ATTRIBUTE_RELIEF
+ "CharRotation", // TEXT_ATTRIBUTE_ROTATION
+ "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
+ "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
+ "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
+ "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
+ "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
+ // --> OD 2010-03-05 #i92233#
+ "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
+ // <--
+ "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
+ "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
+ "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
+ "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
+ "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
+ "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
+ "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
+ "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
+ "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
+ "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
+};
+
+
+/*****************************************************************************/
+
+static gchar*
+get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nIndex, AtkTextAttrFunc func )
+{
+ if( nIndex != -1 )
+ return func(rAttributeList[nIndex].Value);
+
+ return NULL;
+}
+
+#define get_bool_value( list, index ) get_value( list, index, Bool2String )
+#define get_short_value( list, index ) get_value( list, index, Short2String )
+//#define get_long_value( list, index ) get_value( list, index, Long2String ) pb: not used (warning on linux)
+#define get_height_value( list, index ) get_value( list, index, Float2String )
+#define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
+#define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
+#define get_scale_width( list, index ) get_value( list, index, Scale2String )
+#define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
+#define get_string_value( list, index ) get_value( list, index, GetString )
+#define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
+#define get_underline_value( list, index ) get_value( list, index, Underline2String )
+#define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
+#define get_weight_value( list, index ) get_value( list, index, Weight2String )
+#define get_language_string( list, index ) get_value( list, index, Locale2String )
+
+/*
+static gchar*
+dump_value( const uno::Sequence< beans::PropertyValue >& rAttributeList, sal_Int32 nIndex )
+{
+ if( nIndex != -1 )
+ {
+ rtl::OString aName = rtl::OUStringToOString(rAttributeList[nIndex].Name, RTL_TEXTENCODING_UTF8);
+
+ if( rAttributeList[nIndex].Value.has<sal_Int16> () )
+ OSL_TRACE( "%s = %d (short value)", aName.getStr(),
+ rAttributeList[nIndex].Value.get<sal_Int16> () );
+
+ else if( rAttributeList[nIndex].Value.has<sal_Int8> () )
+ OSL_TRACE( "%s = %d (byte value)", aName.getStr(),
+ rAttributeList[nIndex].Value.get<sal_Int8> () );
+
+ else if( rAttributeList[nIndex].Value.has<sal_Bool> () )
+ OSL_TRACE( "%s = %s (bool value)", aName.getStr(),
+ rAttributeList[nIndex].Value.get<sal_Bool> () ? "true" : "false" );
+
+ else if( rAttributeList[nIndex].Value.has<rtl::OUString> () )
+ OSL_TRACE( "%s = %s", aName.getStr(),
+ rtl::OUStringToOString(rAttributeList[nIndex].Value.get<rtl::OUString> (),
+ RTL_TEXTENCODING_UTF8).getStr() );
+ }
+
+ return NULL;
+}
+*/
+
+static inline
+double toPoint(sal_Int16 n)
+{
+ // 100th mm -> pt
+ return (double) (n * 72) / 2540;
+}
+
+
+/*****************************************************************************/
+
+/*
+static gchar*
+NullString(const uno::Any&)
+{
+ return NULL;
+}
+*/
+
+static bool
+InvalidValue( uno::Any&, const gchar * )
+{
+ return false;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Float2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%g", rAny.get<float>() );
+}
+
+static bool
+String2Float( uno::Any& rAny, const gchar * value )
+{
+ float fval;
+
+ if( 1 != sscanf( value, "%g", &fval ) )
+ return false;
+
+ rAny = uno::makeAny( fval );
+ return true;
+}
+
+/*****************************************************************************/
+
+/*
+static gchar*
+Short2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%d", rAny.get<sal_Int16>() );
+}
+
+static bool
+String2Short( uno::Any& rAny, const gchar * value )
+{
+ sal_Int32 lval;
+
+ if( 1 != sscanf( value, "%d", &lval ) )
+ return false;
+
+ rAny = uno::makeAny( (sal_Int16) lval );
+ return true;
+}
+*/
+
+/*****************************************************************************/
+/* pb: not used (warning on linux)
+static gchar*
+Long2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%ld", rAny.get<sal_Int32>() );
+}
+
+static bool
+String2Long( uno::Any& rAny, const gchar * value )
+{
+ sal_Int32 lval;
+
+ if( 1 != sscanf( value, "%ld", &lval ) )
+ return false;
+
+ rAny = uno::makeAny( lval );
+ return true;
+}
+*/
+/*****************************************************************************/
+
+static accessibility::XAccessibleComponent*
+ getComponent( AtkText *pText ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpComponent && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
+ pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
+ pWrap->mpComponent->acquire();
+ }
+
+ return pWrap->mpComponent;
+ }
+
+ return NULL;
+}
+
+static gchar*
+get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ const sal_Int32 * pIndexArray,
+ ExportedAttribute attr,
+ AtkText * text)
+{
+ sal_Int32 nColor = -1; // AUTOMATIC
+ sal_Int32 nIndex = pIndexArray[attr];
+
+ if( nIndex != -1 )
+ nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
+
+ /*
+ * Check for color value for 100% alpha white, which means
+ * "automatic". Grab the RGB value from XAccessibleComponent
+ * in this case.
+ */
+
+ if( (nColor == -1) && text )
+ {
+ try
+ {
+ accessibility::XAccessibleComponent *pComponent = getComponent( text );
+ if( pComponent )
+ {
+ switch( attr )
+ {
+ case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
+ nColor = pComponent->getBackground();
+ break;
+ case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
+ nColor = pComponent->getForeground();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in get[Fore|Back]groundColor()" );
+ }
+ }
+
+ if( nColor != -1 )
+ {
+ sal_uInt8 blue = nColor & 0xFF;
+ sal_uInt8 green = (nColor >> 8) & 0xFF;
+ sal_uInt8 red = (nColor >> 16) & 0xFF;
+
+ return g_strdup_printf( "%u,%u,%u", red, green, blue );
+ }
+
+ return NULL;
+}
+
+static bool
+String2Color( uno::Any& rAny, const gchar * value )
+{
+ int red, green, blue;
+
+ if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
+ return false;
+
+ sal_Int32 nColor = (sal_Int32) blue | ( (sal_Int32) green << 8 ) | ( ( sal_Int32 ) red << 16 );
+ rAny = uno::makeAny( nColor );
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+FontSlant2Style(const uno::Any& rAny)
+{
+ const gchar * value = NULL;
+
+ switch( rAny.get<awt::FontSlant>() )
+ {
+ case awt::FontSlant_NONE:
+ value = "normal";
+ break;
+
+ case awt::FontSlant_OBLIQUE:
+ value = "oblique";
+ break;
+
+ case awt::FontSlant_ITALIC:
+ value = "italic";
+ break;
+
+ case awt::FontSlant_REVERSE_OBLIQUE:
+ value = "reverse oblique";
+ break;
+
+ case awt::FontSlant_REVERSE_ITALIC:
+ value = "reverse italic";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return NULL;
+}
+
+static bool
+Style2FontSlant( uno::Any& rAny, const gchar * value )
+{
+ awt::FontSlant aFontSlant;
+
+ if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
+ aFontSlant = awt::FontSlant_NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) )
+ aFontSlant = awt::FontSlant_OBLIQUE;
+ else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) )
+ aFontSlant = awt::FontSlant_ITALIC;
+ else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) )
+ aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
+ else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) )
+ aFontSlant = awt::FontSlant_REVERSE_ITALIC;
+ else
+ return false;
+
+ rAny = uno::makeAny( aFontSlant );
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Weight2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%g", rAny.get<float>() * 4 );
+}
+
+static bool
+String2Weight( uno::Any& rAny, const gchar * value )
+{
+ float weight;
+
+ if( 1 != sscanf( value, "%g", &weight ) )
+ return false;
+
+ rAny = uno::makeAny( weight / 4 );
+ return true;
+}
+
+
+/*****************************************************************************/
+
+static gchar*
+Adjust2Justification(const uno::Any& rAny)
+{
+ const gchar * value = NULL;
+
+ switch( rAny.get<short>() )
+ {
+ case style::ParagraphAdjust_LEFT:
+ value = "left";
+ break;
+
+ case style::ParagraphAdjust_RIGHT:
+ value = "right";
+ break;
+
+ case style::ParagraphAdjust_BLOCK:
+ case style::ParagraphAdjust_STRETCH:
+ value = "fill";
+ break;
+
+ case style::ParagraphAdjust_CENTER:
+ value = "center";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return NULL;
+}
+
+static bool
+Justification2Adjust( uno::Any& rAny, const gchar * value )
+{
+ short nParagraphAdjust;
+
+ if( strncmp( value, STRNCMP_PARAM( "left" ) ) )
+ nParagraphAdjust = style::ParagraphAdjust_LEFT;
+ else if( strncmp( value, STRNCMP_PARAM( "right" ) ) )
+ nParagraphAdjust = style::ParagraphAdjust_RIGHT;
+ else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) )
+ nParagraphAdjust = style::ParagraphAdjust_BLOCK;
+ else if( strncmp( value, STRNCMP_PARAM( "center" ) ) )
+ nParagraphAdjust = style::ParagraphAdjust_CENTER;
+ else
+ return false;
+
+ rAny = uno::makeAny( nParagraphAdjust );
+ return true;
+}
+
+/*****************************************************************************/
+
+const gchar * font_strikethrough[] = {
+ "none", // FontStrikeout::NONE
+ "single", // FontStrikeout::SINGLE
+ "double", // FontStrikeout::DOUBLE
+ NULL, // FontStrikeout::DONTKNOW
+ "bold", // FontStrikeout::BOLD
+ "with /", // FontStrikeout::SLASH
+ "with X" // FontStrikeout::X
+};
+
+const sal_Int16 n_strikeout_constants = sizeof(font_strikethrough) / sizeof(gchar*);
+
+static gchar*
+Strikeout2String(const uno::Any& rAny)
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( n >= 0 && n < n_strikeout_constants )
+ return g_strdup( font_strikethrough[n] );
+
+ return NULL;
+}
+
+static bool
+String2Strikeout( uno::Any& rAny, const gchar * value )
+{
+ for( sal_Int16 n=0; n < n_strikeout_constants; ++n )
+ {
+ if( ( NULL != font_strikethrough[n] ) &&
+ 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
+ {
+ rAny = uno::makeAny( n );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Underline2String(const uno::Any& rAny)
+{
+ const gchar * value = NULL;
+
+ switch( rAny.get<sal_Int16>() )
+ {
+ case awt::FontUnderline::NONE:
+ value = "none";
+ break;
+
+ case awt::FontUnderline::SINGLE:
+ value = "single";
+ break;
+
+ case awt::FontUnderline::DOUBLE:
+ value = "double";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return NULL;
+}
+
+static bool
+String2Underline( uno::Any& rAny, const gchar * value )
+{
+ short nUnderline;
+
+ if( strncmp( value, STRNCMP_PARAM( "none" ) ) )
+ nUnderline = awt::FontUnderline::NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "single" ) ) )
+ nUnderline = awt::FontUnderline::SINGLE;
+ else if( strncmp( value, STRNCMP_PARAM( "double" ) ) )
+ nUnderline = awt::FontUnderline::DOUBLE;
+ else
+ return false;
+
+ rAny = uno::makeAny( nUnderline );
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+GetString(const uno::Any& rAny)
+{
+ rtl::OString aFontName = rtl::OUStringToOString( rAny.get< rtl::OUString > (), RTL_TEXTENCODING_UTF8 );
+
+ if( aFontName.getLength() )
+ return g_strdup( aFontName.getStr() );
+
+ return NULL;
+}
+
+static bool
+SetString( uno::Any& rAny, const gchar * value )
+{
+ rtl::OString aFontName( value );
+
+ if( aFontName.getLength() )
+ {
+ rAny = uno::makeAny( rtl::OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ) );
+ return true;
+ }
+
+ return false;
+}
+
+/*****************************************************************************/
+
+// @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
+
+// CMM = 100th of mm
+static gchar*
+CMM2UnitString(const uno::Any& rAny)
+{
+ double fValue = rAny.get<sal_Int32>();
+ fValue = fValue * 0.01;
+
+ return g_strdup_printf( "%gmm", fValue );
+}
+
+static bool
+UnitString2CMM( uno::Any& rAny, const gchar * value )
+{
+ float fValue = 0.0; // pb: dont use double here because of warning on linux
+
+ if( 1 != sscanf( value, "%gmm", &fValue ) )
+ return false;
+
+ fValue = fValue * 100;
+
+ rAny = uno::makeAny( (sal_Int32) fValue);
+ return true;
+}
+
+/*****************************************************************************/
+
+static const gchar * bool_values[] = { "true", "false" };
+
+static gchar *
+Bool2String( const uno::Any& rAny )
+{
+ int n = 1;
+
+ if( rAny.get<sal_Bool>() )
+ n = 0;
+
+ return g_strdup( bool_values[n] );
+}
+
+static bool
+String2Bool( uno::Any& rAny, const gchar * value )
+{
+ sal_Bool bValue;
+
+ if( strncmp( value, STRNCMP_PARAM( "true" ) ) )
+ bValue = sal_True;
+ else if( strncmp( value, STRNCMP_PARAM( "false" ) ) )
+ bValue = sal_False;
+ else
+ return false;
+
+ rAny = uno::makeAny(bValue);
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Scale2String( const uno::Any& rAny )
+{
+ return g_strdup_printf( "%g", (double) (rAny.get< sal_Int16 > ()) / 100 );
+}
+
+static bool
+String2Scale( uno::Any& rAny, const gchar * value )
+{
+ double dval;
+
+ if( 1 != sscanf( value, "%lg", &dval ) )
+ return false;
+
+ rAny = uno::makeAny((sal_Int16) (dval * 100));
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar *
+CaseMap2String( const uno::Any& rAny )
+{
+ const gchar * value = NULL;
+
+ switch( rAny.get<short>() )
+ {
+ case style::CaseMap::SMALLCAPS:
+ value = "small_caps";
+ break;
+
+ default:
+ value = "normal";
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return NULL;
+}
+
+static bool
+String2CaseMap( uno::Any& rAny, const gchar * value )
+{
+ short nCaseMap;
+
+ if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
+ nCaseMap = style::CaseMap::NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) )
+ nCaseMap = style::CaseMap::SMALLCAPS;
+ else
+ return false;
+
+ rAny = uno::makeAny( nCaseMap );
+ return true;
+}
+
+/*****************************************************************************/
+
+const gchar * font_stretch[] = {
+ "ultra_condensed",
+ "extra_condensed",
+ "condensed",
+ "semi_condensed",
+ "normal",
+ "semi_expanded",
+ "expanded",
+ "extra_expanded",
+ "ultra_expanded"
+};
+
+static gchar*
+Kerning2Stretch(const uno::Any& rAny)
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+ int i = 4;
+
+ // No good idea for a mapping - just return the basic info
+ if( n < 0 )
+ i=2;
+ else if( n > 0 )
+ i=6;
+
+ return g_strdup(font_stretch[i]);
+}
+
+/*****************************************************************************/
+
+static gchar*
+Locale2String(const uno::Any& rAny)
+{
+ lang::Locale aLocale = rAny.get<lang::Locale> ();
+ return g_strdup_printf( "%s-%s",
+ rtl::OUStringToOString( aLocale.Language, RTL_TEXTENCODING_ASCII_US).getStr(),
+ rtl::OUStringToOString( aLocale.Country, RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
+}
+
+static bool
+String2Locale( uno::Any& rAny, const gchar * value )
+{
+ bool ret = false;
+
+ gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
+ if( str_array[0] != NULL )
+ {
+ ret = true;
+
+ lang::Locale aLocale;
+
+ aLocale.Language = rtl::OUString::createFromAscii(str_array[0]);
+ if( str_array[1] != NULL )
+ {
+ gchar * country = g_ascii_strup(str_array[1], -1);
+ aLocale.Country = rtl::OUString::createFromAscii(country);
+ g_free(country);
+ }
+
+ rAny = uno::makeAny(aLocale);
+ }
+
+ g_strfreev(str_array);
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
+static const gchar * relief[] = { "none", "emboss", "engrave" };
+static const gchar * outline = "outline";
+
+static gchar *
+get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
+{
+ if( nContourIndex != -1 )
+ {
+ if( rAttributeList[nContourIndex].Value.get<sal_Bool>() )
+ return g_strdup(outline);
+ }
+
+ if( nReliefIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
+ if( n < 3)
+ return g_strdup(relief[n]);
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
+
+
+enum
+{
+ DECORATION_NONE = 0,
+ DECORATION_BLINK,
+ DECORATION_UNDERLINE,
+ DECORATION_LINE_THROUGH
+};
+
+
+static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
+
+static gchar *
+get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
+ sal_Int16 nStrikeoutIndex)
+{
+ gchar * value_list[4] = { NULL, NULL, NULL, NULL };
+ gint count = 0;
+
+ // no property value found
+ if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
+ return NULL;
+
+ if( nBlinkIndex != -1 )
+ {
+ if( rAttributeList[nBlinkIndex].Value.get<sal_Bool>() )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
+ }
+ if( nUnderlineIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
+ if( n != awt::FontUnderline::NONE )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
+ }
+ if( nStrikeoutIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
+ if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
+ }
+
+ if( count == 0 )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
+
+ return g_strjoinv(" ", value_list);
+}
+
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
+
+static const gchar * shadow_values[] = { "none", "black" };
+
+static gchar *
+Bool2Shadow( const uno::Any& rAny )
+{
+ int n = 0;
+
+ if( rAny.get<sal_Bool>() )
+ n = 1;
+
+ return g_strdup( shadow_values[n] );
+}
+
+/*****************************************************************************/
+
+static gchar *
+Short2Degree( const uno::Any& rAny )
+{
+ float f = rAny.get<sal_Int16>() / 10;
+ return g_strdup_printf( "%g", f );
+}
+
+/*****************************************************************************/
+
+const gchar * directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
+
+static gchar *
+WritingMode2Direction( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( 0 <= n && n <= text::WritingMode2::PAGE )
+ return g_strdup(directions[n]);
+
+ return NULL;
+}
+
+// @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
+
+const gchar * writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
+static gchar *
+WritingMode2String( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( 0 <= n && n <= text::WritingMode2::PAGE )
+ return g_strdup(writing_modes[n]);
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+const char * baseline_values[] = { "baseline", "sub", "super" };
+
+// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
+static gchar *
+Escapement2VerticalAlign( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+ gchar * ret = NULL;
+
+ // Values are in %, 101% means "automatic"
+ if( n == 0 )
+ ret = g_strdup(baseline_values[0]);
+ else if( n == 101 )
+ ret = g_strdup(baseline_values[2]);
+ else if( n == -101 )
+ ret = g_strdup(baseline_values[1]);
+ else
+ ret = g_strdup_printf( "%d%%", n );
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
+static gchar *
+LineSpacing2LineHeight( const uno::Any& rAny )
+{
+ style::LineSpacing ls;
+ gchar * ret = NULL;
+
+ if( rAny >>= ls )
+ {
+ if( ls.Mode == style::LineSpacingMode::PROP )
+ ret = g_strdup_printf( "%d%%", ls.Height );
+ else if( ls.Mode == style::LineSpacingMode::FIX )
+ ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
+static gchar *
+TabStopList2String( const uno::Any& rAny, bool default_tabs )
+{
+ uno::Sequence< style::TabStop > theTabStops;
+ gchar * ret = NULL;
+
+ if( rAny >>= theTabStops)
+ {
+ sal_Int32 indexOfTab = 0;
+ sal_Int32 numberOfTabs = theTabStops.getLength();
+ sal_Unicode lastFillChar = (sal_Unicode) ' ';
+
+ for( ; indexOfTab < numberOfTabs; ++indexOfTab )
+ {
+ bool is_default_tab = (style::TabAlign_DEFAULT == theTabStops[indexOfTab].Alignment);
+
+ if( is_default_tab != default_tabs )
+ continue;
+
+ double fValue = theTabStops[indexOfTab].Position;
+ fValue = fValue * 0.01;
+
+ const gchar * tab_align = "";
+ switch( theTabStops[indexOfTab].Alignment )
+ {
+ case style::TabAlign_LEFT :
+ tab_align = "left ";
+ break;
+ case style::TabAlign_CENTER :
+ tab_align = "center ";
+ break;
+ case style::TabAlign_RIGHT :
+ tab_align = "right ";
+ break;
+ case style::TabAlign_DECIMAL :
+ tab_align = "decimal ";
+ break;
+ default:
+ break;
+ }
+
+ const gchar * lead_char = "";
+
+ if( theTabStops[indexOfTab].FillChar != lastFillChar )
+ {
+ lastFillChar = theTabStops[indexOfTab].FillChar;
+ switch (lastFillChar)
+ {
+ case (sal_Unicode) ' ':
+ lead_char = "blank ";
+ break;
+
+ case (sal_Unicode) '.':
+ lead_char = "dotted ";
+ break;
+
+ case (sal_Unicode) '-':
+ lead_char = "dashed ";
+ break;
+
+ case (sal_Unicode) '_':
+ lead_char = "lined ";
+ break;
+
+ default:
+ lead_char = "custom ";
+ break;
+ }
+ }
+
+ gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
+
+ if( ret )
+ {
+ gchar * old_tab_str = ret;
+ ret = g_strconcat(old_tab_str, " ", tab_str, NULL /* terminated */);
+ g_free( old_tab_str );
+ }
+ else
+ ret = tab_str;
+ }
+ }
+
+ return ret;
+}
+
+static gchar *
+TabStops2String( const uno::Any& rAny )
+{
+ return TabStopList2String(rAny, false);
+}
+
+static gchar *
+DefaultTabStops2String( const uno::Any& rAny )
+{
+ return TabStopList2String(rAny, true);
+}
+
+/*****************************************************************************/
+
+extern "C" int
+attr_compare(const void *p1,const void *p2)
+{
+ const rtl_uString * pustr = (const rtl_uString *) p1;
+ const char * pc = *((const char **) p2);
+
+ return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
+}
+
+static void
+find_exported_attributes( sal_Int32 *pArray,
+ const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList )
+{
+ for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
+ {
+ const char ** pAttr = (const char **) bsearch(rAttributeList[i].Name.pData,
+ ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
+ attr_compare);
+
+ if( pAttr )
+ {
+ sal_Int32 nIndex = pAttr - ExportedTextAttributes;
+ pArray[nIndex] = i;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static AtkAttributeSet*
+attribute_set_prepend( AtkAttributeSet* attribute_set,
+ AtkTextAttribute attribute,
+ gchar * value )
+{
+ if( value )
+ {
+ AtkAttribute *at = (AtkAttribute *) g_malloc( sizeof (AtkAttribute) );
+ at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
+ at->value = value;
+
+ return g_slist_prepend(attribute_set, at);
+ }
+
+ return attribute_set;
+}
+
+/*****************************************************************************/
+
+AtkAttributeSet*
+attribute_set_new_from_property_values(
+ const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ bool run_attributes_only,
+ AtkText *text)
+{
+ AtkAttributeSet* attribute_set = NULL;
+
+ sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
+
+ // Initialize index array with -1
+ for( sal_Int32 attr = 0; attr < TEXT_ATTRIBUTE_LAST; ++attr )
+ aIndexList[attr] = -1;
+
+ find_exported_attributes(aIndexList, rAttributeList);
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
+ get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? NULL : text ) );
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
+ get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? NULL : text) );
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
+ get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
+ get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
+ get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
+ get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
+ get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
+ get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
+ get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
+ get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
+ get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
+ get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
+ atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
+ get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
+ atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
+ get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
+ aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
+ atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
+ atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
+ atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
+ atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
+
+ if( run_attributes_only )
+ return attribute_set;
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
+ get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
+ atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
+ get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
+ atk_text_attribute_line_height = atk_text_attribute_register("line-height");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
+ atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
+ atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
+
+ // --> OD 2010-03-05 #i92233#
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
+ atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
+
+ attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
+ // <--
+
+ return attribute_set;
+}
+
+
+AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
+{
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
+ atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
+
+ attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
+ g_strdup_printf( "misspelled" ) );
+
+ return attribute_set;
+}
+
+// --> OD 2010-03-01 #i92232#
+AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "insertion" ) );
+
+ return attribute_set;
+}
+
+AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "deletion" ) );
+
+ return attribute_set;
+}
+
+AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "attribute-change" ) );
+
+ return attribute_set;
+}
+// <--
+
+/*****************************************************************************/
+
+struct AtkTextAttrMapping
+{
+ const char * name;
+ TextPropertyValueFunc toPropertyValue;
+};
+
+const AtkTextAttrMapping g_TextAttrMap[] =
+{
+ { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
+ { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
+ { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
+ { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
+ { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
+ { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
+ { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
+ { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
+ { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
+ { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
+ { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
+ { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
+ { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
+ { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
+ { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
+ { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
+ { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
+ { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
+ { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
+ { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
+ { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
+ { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
+ { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
+ { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
+};
+
+static const sal_Int32 g_TextAttrMapSize = sizeof( g_TextAttrMap ) / sizeof( AtkTextAttrMapping );
+
+/*****************************************************************************/
+
+bool
+attribute_set_map_to_property_values(
+ AtkAttributeSet* attribute_set,
+ uno::Sequence< beans::PropertyValue >& rValueList )
+{
+ // Ensure enough space ..
+ uno::Sequence< beans::PropertyValue > aAttributeList (g_TextAttrMapSize);
+
+ sal_Int32 nIndex = 0;
+ for( GSList * item = attribute_set; item != NULL; item = g_slist_next( item ) )
+ {
+ AtkAttribute* attribute = (AtkAttribute *) item;
+
+ AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
+ if( text_attr < g_TextAttrMapSize )
+ {
+ if( g_TextAttrMap[text_attr].name[0] != '\0' )
+ {
+ if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
+ return false;
+
+ aAttributeList[nIndex].Name = rtl::OUString::createFromAscii( g_TextAttrMap[text_attr].name );
+ aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
+ ++nIndex;
+ }
+ }
+ else
+ {
+ // Unsupported text attribute
+ return false;
+ }
+ }
+
+ aAttributeList.realloc( nIndex );
+ rValueList = aAttributeList;
+ return true;
+}
+
diff --git a/vcl/unx/gtk/a11y/atktextattributes.hxx b/vcl/unx/gtk/a11y/atktextattributes.hxx
new file mode 100644
index 000000000000..9c7628bf927e
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atktextattributes.hxx
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_ATKTEXTATTRIBUTES_HXX__
+#define __ATK_ATKTEXTATTRIBUTES_HXX__
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <atk/atk.h>
+
+AtkAttributeSet*
+attribute_set_new_from_property_values(
+ const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList,
+ bool run_attributes_only,
+ AtkText *text);
+
+bool
+attribute_set_map_to_property_values(
+ AtkAttributeSet* attribute_set,
+ com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rValueList );
+
+AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set );
+// --> OD 2010-03-01 #i92232#
+AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set );
+AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set );
+AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set );
+// <--
+
+#endif
diff --git a/vcl/unx/gtk/a11y/atkutil.cxx b/vcl/unx/gtk/a11y/atkutil.cxx
new file mode 100644
index 000000000000..13492f3d4a5c
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkutil.cxx
@@ -0,0 +1,802 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+// --> OD 2009-04-14 #i93269#
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+// <--
+#include <cppuhelper/implbase1.hxx>
+#include <vos/mutex.hxx>
+#include <rtl/ref.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/toolbox.hxx>
+
+#include "atkwrapper.hxx"
+#include "atkutil.hxx"
+
+#include <gtk/gtk.h>
+
+#include <set>
+
+// #define ENABLE_TRACING
+
+#ifdef ENABLE_TRACING
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+
+static uno::WeakReference< accessibility::XAccessible > xNextFocusObject;
+static guint focus_notify_handler = 0;
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gint
+atk_wrapper_focus_idle_handler (gpointer data)
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ focus_notify_handler = 0;
+
+ uno::Reference< accessibility::XAccessible > xAccessible = xNextFocusObject;
+ if( xAccessible.get() == reinterpret_cast < accessibility::XAccessible * > (data) )
+ {
+ // Gail does not notify focus changes to NULL, so do we ..
+ if( xAccessible.is() )
+ {
+ AtkObject *atk_obj = atk_object_wrapper_ref( xAccessible );
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "notifying focus event for %p\n", atk_obj);
+#endif
+ atk_focus_tracker_notify(atk_obj);
+ // --> OD 2009-04-14 #i93269#
+ // emit text_caret_moved event for <XAccessibleText> object,
+ // if cursor is inside the <XAccessibleText> object.
+ // also emit state-changed:focused event under the same condition.
+ {
+ AtkObjectWrapper* wrapper_obj = ATK_OBJECT_WRAPPER (atk_obj);
+ if( !wrapper_obj->mpText && wrapper_obj->mpContext )
+ {
+ uno::Any any = wrapper_obj->mpContext->queryInterface( accessibility::XAccessibleText::static_type(NULL) );
+ if ( typelib_TypeClass_INTERFACE == any.pType->eTypeClass &&
+ any.pReserved != 0 )
+ {
+ wrapper_obj->mpText = reinterpret_cast< accessibility::XAccessibleText * > (any.pReserved);
+ if ( wrapper_obj->mpText != 0 )
+ {
+ wrapper_obj->mpText->acquire();
+ gint caretPos = wrapper_obj->mpText->getCaretPosition();
+
+ if ( caretPos != -1 )
+ {
+ atk_object_notify_state_change( atk_obj, ATK_STATE_FOCUSED, TRUE );
+ g_signal_emit_by_name( atk_obj, "text_caret_moved", caretPos );
+ }
+ }
+ }
+ }
+ }
+ // <--
+ g_object_unref(atk_obj);
+ }
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+/*****************************************************************************/
+
+static void
+atk_wrapper_focus_tracker_notify_when_idle( const uno::Reference< accessibility::XAccessible > &xAccessible )
+{
+ if( focus_notify_handler )
+ g_source_remove(focus_notify_handler);
+
+ xNextFocusObject = xAccessible;
+
+ focus_notify_handler = g_idle_add (atk_wrapper_focus_idle_handler, xAccessible.get());
+}
+
+/*****************************************************************************/
+
+class DocumentFocusListener :
+ public ::cppu::WeakImplHelper1< accessibility::XAccessibleEventListener >
+{
+
+ std::set< uno::Reference< uno::XInterface > > m_aRefList;
+
+public:
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ static uno::Reference< accessibility::XAccessible > getAccessible(const lang::EventObject& aEvent )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
+
+ // XEventListener
+ virtual void disposing( const lang::EventObject& Source ) throw (uno::RuntimeException);
+
+ // XAccessibleEventListener
+ virtual void notifyEvent( const accessibility::AccessibleEventObject& aEvent ) throw( uno::RuntimeException );
+};
+
+/*****************************************************************************/
+
+void DocumentFocusListener::disposing( const lang::EventObject& aEvent )
+ throw (uno::RuntimeException)
+{
+// fprintf(stderr, "In DocumentFocusListener::disposing (%p)\n", this);
+// fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
+
+ // Unref the object here, but do not remove as listener since the object
+ // might no longer be in a state that safely allows this.
+ if( aEvent.Source.is() )
+ m_aRefList.erase(aEvent.Source);
+
+// fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
+
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
+ throw( uno::RuntimeException )
+{
+ switch( aEvent.EventId )
+ {
+ case accessibility::AccessibleEventId::STATE_CHANGED:
+ try
+ {
+ sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
+ aEvent.NewValue >>= nState;
+
+ if( accessibility::AccessibleStateType::FOCUSED == nState )
+ atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) );
+ }
+ catch(const lang::IndexOutOfBoundsException &e)
+ {
+ g_warning("Focused object has invalid index in parent");
+ }
+ break;
+
+ case accessibility::AccessibleEventId::CHILD:
+ {
+ uno::Reference< accessibility::XAccessible > xChild;
+ if( (aEvent.OldValue >>= xChild) && xChild.is() )
+ detachRecursive(xChild);
+
+ if( (aEvent.NewValue >>= xChild) && xChild.is() )
+ attachRecursive(xChild);
+ }
+ break;
+
+ case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+/* {
+ uno::Reference< accessibility::XAccessible > xAccessible( getAccessible(aEvent) );
+ detachRecursive(xAccessible);
+ attachRecursive(xAccessible);
+ }
+*/
+ g_warning( "Invalidate all children called\n" );
+ break;
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************/
+
+uno::Reference< accessibility::XAccessible > DocumentFocusListener::getAccessible(const lang::EventObject& aEvent )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessible > xAccessible(aEvent.Source, uno::UNO_QUERY);
+
+ if( xAccessible.is() )
+ return xAccessible;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext(aEvent.Source, uno::UNO_QUERY);
+
+ if( xContext.is() )
+ {
+ uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ {
+ return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() );
+ }
+ }
+ }
+
+ return uno::Reference< accessibility::XAccessible >();
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( xContext.is() )
+ attachRecursive(xAccessible, xContext);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( xStateSet.is() )
+ attachRecursive(xAccessible, xContext, xStateSet);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED ) )
+ atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
+
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
+ uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
+
+ // If not already done, add the broadcaster to the list and attach as listener.
+ if( xBroadcaster.is() && m_aRefList.insert(xBroadcaster).second )
+ {
+ xBroadcaster->addEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
+
+ if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
+ {
+ sal_Int32 n, nmax = xContext->getAccessibleChildCount();
+ for( n = 0; n < nmax; n++ )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
+
+ if( xChild.is() )
+ attachRecursive(xChild);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( xContext.is() )
+ detachRecursive(xAccessible, xContext);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( xStateSet.is() )
+ detachRecursive(xAccessible, xContext, xStateSet);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessible >&,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
+ uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
+
+ if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) )
+ {
+ xBroadcaster->removeEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
+
+ if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
+ {
+ sal_Int32 n, nmax = xContext->getAccessibleChildCount();
+ for( n = 0; n < nmax; n++ )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
+
+ if( xChild.is() )
+ detachRecursive(xChild);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/*
+ * page tabs in gtk are widgets, so we need to simulate focus events for those
+ */
+
+static void handle_tabpage_activated(Window *pWindow)
+{
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pWindow->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleSelection > xSelection(
+ xAccessible->getAccessibleContext(), uno::UNO_QUERY);
+
+ if( xSelection.is() )
+ atk_wrapper_focus_tracker_notify_when_idle( xSelection->getSelectedAccessibleChild(0) );
+}
+
+/*****************************************************************************/
+
+/*
+ * toolbar items in gtk are widgets, so we need to simulate focus events for those
+ */
+
+static void notify_toolbox_item_focus(ToolBox *pToolBox)
+{
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pToolBox->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( ! xContext.is() )
+ return;
+
+ sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
+ if( nPos != TOOLBOX_ITEM_NOTFOUND )
+ atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
+}
+
+static void handle_toolbox_highlight(Window *pWindow)
+{
+ ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
+
+ // Make sure either the toolbox or its parent toolbox has the focus
+ if ( ! pToolBox->HasFocus() )
+ {
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
+ if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
+ return;
+ }
+
+ notify_toolbox_item_focus(pToolBox);
+}
+
+static void handle_toolbox_highlightoff(Window *pWindow)
+{
+ ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
+
+ // Notify when leaving sub toolboxes
+ if( pToolBoxParent && pToolBoxParent->HasFocus() )
+ notify_toolbox_item_focus( pToolBoxParent );
+}
+
+/*****************************************************************************/
+
+static void create_wrapper_for_child(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ sal_Int32 index)
+{
+ if( xContext.is() )
+ {
+ uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(index));
+ if( xChild.is() )
+ {
+ // create the wrapper object - it will survive the unref unless it is a transient object
+ g_object_unref( atk_object_wrapper_ref( xChild ) );
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static void handle_toolbox_buttonchange(VclWindowEvent const *pEvent)
+{
+ Window* pWindow = pEvent->GetWindow();
+ sal_Int32 index = (sal_Int32)(sal_IntPtr) pEvent->GetData();
+
+ if( pWindow && pWindow->IsReallyVisible() )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
+ if( xAccessible.is() )
+ {
+ create_wrapper_for_child(xAccessible->getAccessibleContext(), index);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/* currently not needed anymore...
+static void create_wrapper_for_children(Window *pWindow)
+{
+ if( pWindow && pWindow->IsReallyVisible() )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
+ if( xAccessible.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xContext(xAccessible->getAccessibleContext());
+ if( xContext.is() )
+ {
+ sal_Int32 nChildren = xContext->getAccessibleChildCount();
+ for( sal_Int32 i = 0; i < nChildren; ++i )
+ create_wrapper_for_child(xContext, i);
+ }
+ }
+ }
+}
+*/
+
+/*****************************************************************************/
+
+static std::set< Window * > g_aWindowList;
+
+static void handle_get_focus(::VclWindowEvent const * pEvent)
+{
+ static rtl::Reference< DocumentFocusListener > aDocumentFocusListener =
+ new DocumentFocusListener();
+
+ Window *pWindow = pEvent->GetWindow();
+
+ // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED
+ if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW )
+ return;
+
+ // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
+ if( pWindow->GetType() == WINDOW_TOOLBOX )
+ return;
+
+ if( pWindow->GetType() == WINDOW_TABCONTROL )
+ {
+ handle_tabpage_activated( pWindow );
+ return;
+ }
+
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pWindow->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( ! xContext.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( ! xStateSet.is() )
+ return;
+
+/* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
+ * need to add listeners to the children instead of re-using the tabpage stuff
+ */
+ if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED) &&
+ ( pWindow->GetType() != WINDOW_TREELISTBOX ) )
+ {
+ atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
+ }
+ else
+ {
+ if( g_aWindowList.find(pWindow) == g_aWindowList.end() )
+ {
+ g_aWindowList.insert(pWindow);
+ try
+ {
+ aDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet);
+ }
+ catch( const uno::Exception &e )
+ {
+ g_warning( "Exception caught processing focus events" );
+ }
+ }
+#ifdef ENABLE_TRACING
+ else
+ fprintf(stderr, "Window %p already in the list\n", pWindow );
+#endif
+ }
+}
+
+/*****************************************************************************/
+
+static void handle_menu_highlighted(::VclMenuEvent const * pEvent)
+{
+ try
+ {
+ Menu* pMenu = pEvent->GetMenu();
+ USHORT nPos = pEvent->GetItemPos();
+
+ if( pMenu && nPos != 0xFFFF)
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible ( pMenu->GetAccessible() );
+
+ if( xAccessible.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xContext ( xAccessible->getAccessibleContext() );
+
+ if( xContext.is() )
+ atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
+ }
+ }
+ }
+ catch( const uno::Exception& e )
+ {
+ g_warning( "Exception caught processing menu highlight events" );
+ }
+}
+
+/*****************************************************************************/
+
+long WindowEventHandler(void *, ::VclSimpleEvent const * pEvent)
+{
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_SHOW:
+// fprintf(stderr, "got VCLEVENT_WINDOW_SHOW for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_HIDE:
+// fprintf(stderr, "got VCLEVENT_WINDOW_HIDE for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_CLOSE:
+// fprintf(stderr, "got VCLEVENT_WINDOW_CLOSE for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_GETFOCUS:
+ handle_get_focus(static_cast< ::VclWindowEvent const * >(pEvent));
+ break;
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+// fprintf(stderr, "got VCLEVENT_WINDOW_LOSEFOCUS for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_MINIMIZE:
+// fprintf(stderr, "got VCLEVENT_WINDOW_MINIMIZE for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_NORMALIZE:
+// fprintf(stderr, "got VCLEVENT_WINDOW_NORMALIZE for %p\n",
+// static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+ case VCLEVENT_WINDOW_KEYINPUT:
+ case VCLEVENT_WINDOW_KEYUP:
+ case VCLEVENT_WINDOW_COMMAND:
+ case VCLEVENT_WINDOW_MOUSEMOVE:
+ break;
+ /*
+ fprintf(stderr, "got VCLEVENT_WINDOW_COMMAND (%d) for %p\n",
+ static_cast< ::CommandEvent const * > (
+ static_cast< ::VclWindowEvent const * >(pEvent)->GetData())->GetCommand(),
+ static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ */
+ case VCLEVENT_MENU_HIGHLIGHT:
+ if (const VclMenuEvent* pMenuEvent = dynamic_cast<const VclMenuEvent*>(pEvent))
+ {
+ handle_menu_highlighted(pMenuEvent);
+ }
+ else if (const VclAccessibleEvent* pAccEvent = dynamic_cast<const VclAccessibleEvent*>(pEvent))
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible = pAccEvent->GetAccessible();
+ if (xAccessible.is())
+ atk_wrapper_focus_tracker_notify_when_idle(xAccessible);
+ }
+ break;
+
+ case VCLEVENT_TOOLBOX_HIGHLIGHT:
+ handle_toolbox_highlight(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+
+ case VCLEVENT_TOOLBOX_BUTTONSTATECHANGED:
+ handle_toolbox_buttonchange(static_cast< ::VclWindowEvent const * >(pEvent));
+ break;
+
+ case VCLEVENT_OBJECT_DYING:
+ g_aWindowList.erase( static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow() );
+ // fallthrough intentional !
+ case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
+ handle_toolbox_highlightoff(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+
+ case VCLEVENT_TABPAGE_ACTIVATE:
+ handle_tabpage_activated(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+
+ case VCLEVENT_COMBOBOX_SETTEXT:
+ // MT 2010/02: This looks quite strange to me. Stumbled over this when fixing #i104290#.
+ // This kicked in when leaving the combobox in the toolbar, after that the events worked.
+ // I guess this was a try to work around missing combobox events, which didn't do the full job, and shouldn't be necessary anymore.
+ // Fix for #i104290# was done in toolkit/source/awt/vclxaccessiblecomponent, FOCUSED state for compound controls in general.
+ // create_wrapper_for_children(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+
+ default:
+// OSL_TRACE("got event %d \n", pEvent->GetId());
+ break;
+ }
+ return 0;
+}
+
+static Link g_aEventListenerLink( NULL, (PSTUB) WindowEventHandler );
+
+/*****************************************************************************/
+
+extern "C" {
+
+static G_CONST_RETURN gchar *
+ooo_atk_util_get_toolkit_name (void)
+{
+ return "VCL";
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+ooo_atk_util_get_toolkit_version (void)
+{
+ /*
+ * Version is passed in as a -D flag when this file is
+ * compiled.
+ */
+
+ return VERSION;
+}
+
+/*****************************************************************************/
+
+/*
+ * GObject inheritance
+ */
+
+static void
+ooo_atk_util_class_init (AtkUtilClass *)
+{
+ AtkUtilClass *atk_class;
+ gpointer data;
+
+ data = g_type_class_peek (ATK_TYPE_UTIL);
+ atk_class = ATK_UTIL_CLASS (data);
+
+ atk_class->get_toolkit_name = ooo_atk_util_get_toolkit_name;
+ atk_class->get_toolkit_version = ooo_atk_util_get_toolkit_version;
+
+ Application::AddEventListener( g_aEventListenerLink );
+}
+
+} // extern "C"
+
+/*****************************************************************************/
+
+GType
+ooo_atk_util_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ GType parent_type = g_type_from_name( "GailUtil" );
+
+ if( ! parent_type )
+ {
+ g_warning( "Unknown type: GailUtil" );
+ parent_type = ATK_TYPE_UTIL;
+ }
+
+ GTypeQuery type_query;
+ g_type_query( parent_type, &type_query );
+
+ static const GTypeInfo typeInfo =
+ {
+ type_query.class_size,
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ooo_atk_util_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ type_query.instance_size,
+ 0,
+ (GInstanceInitFunc) NULL,
+ NULL
+ } ;
+
+ type = g_type_register_static (parent_type, "OOoUtil", &typeInfo, (GTypeFlags)0) ;
+ }
+
+ return type;
+}
+
+
diff --git a/vcl/unx/gtk/a11y/atkutil.hxx b/vcl/unx/gtk/a11y/atkutil.hxx
new file mode 100644
index 000000000000..8c8ddf59c65f
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkutil.hxx
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_UTIL_HXX__
+#define __ATK_UTIL_HXX__
+
+#include <atk/atk.h>
+
+#define OOO_TYPE_ATK_UTIL ooo_atk_util_get_type()
+
+GType ooo_atk_util_get_type (void);
+
+#endif
diff --git a/vcl/unx/gtk/a11y/atkvalue.cxx b/vcl/unx/gtk/a11y/atkvalue.cxx
new file mode 100644
index 000000000000..9b8e9743eb18
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkvalue.cxx
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+static accessibility::XAccessibleValue*
+ getValue( AtkValue *pValue ) throw (uno::RuntimeException)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pValue );
+ if( pWrap )
+ {
+ if( !pWrap->mpValue && pWrap->mpContext )
+ {
+ uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleValue::static_type(NULL) );
+ pWrap->mpValue = reinterpret_cast< accessibility::XAccessibleValue * > (any.pReserved);
+ pWrap->mpValue->acquire();
+ }
+
+ return pWrap->mpValue;
+ }
+
+ return NULL;
+}
+
+static void anyToGValue( uno::Any aAny, GValue *pValue )
+{
+ // FIXME: expand to lots of types etc.
+ double aDouble=0;
+ aAny >>= aDouble;
+
+ memset( pValue, 0, sizeof( GValue ) );
+ g_value_init( pValue, G_TYPE_DOUBLE );
+ g_value_set_double( pValue, aDouble );
+}
+
+extern "C" {
+
+static void
+value_wrapper_get_current_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ accessibility::XAccessibleValue* pValue = getValue( value );
+ if( pValue )
+ anyToGValue( pValue->getCurrentValue(), gval );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static void
+value_wrapper_get_maximum_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ accessibility::XAccessibleValue* pValue = getValue( value );
+ if( pValue )
+ anyToGValue( pValue->getMaximumValue(), gval );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static void
+value_wrapper_get_minimum_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ accessibility::XAccessibleValue* pValue = getValue( value );
+ if( pValue )
+ anyToGValue( pValue->getMinimumValue(), gval );
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static gboolean
+value_wrapper_set_current_value( AtkValue *value,
+ const GValue *gval )
+{
+ try {
+ accessibility::XAccessibleValue* pValue = getValue( value );
+ if( pValue )
+ {
+ // FIXME - this needs expanding
+ double aDouble = g_value_get_double( gval );
+ uno::Any aAny;
+ aAny <<= aDouble;
+ return pValue->setCurrentValue( aAny );
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+valueIfaceInit (AtkValueIface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_current_value = value_wrapper_get_current_value;
+ iface->get_maximum_value = value_wrapper_get_maximum_value;
+ iface->get_minimum_value = value_wrapper_get_minimum_value;
+ iface->set_current_value = value_wrapper_set_current_value;
+}
diff --git a/vcl/unx/gtk/a11y/atkwindow.cxx b/vcl/unx/gtk/a11y/atkwindow.cxx
new file mode 100644
index 000000000000..5448235998e8
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkwindow.cxx
@@ -0,0 +1,331 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <plugins/gtk/gtkframe.hxx>
+#include <vcl/window.hxx>
+#include "vcl/popupmenuwindow.hxx"
+
+#include "atkwindow.hxx"
+#include "atkwrapper.hxx"
+#include "atkregistry.hxx"
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+extern "C" {
+
+static void (* window_real_initialize) (AtkObject *obj, gpointer data) = NULL;
+static void (* window_real_finalize) (GObject *obj) = NULL;
+
+static void
+init_from_window( AtkObject *accessible, Window *pWindow )
+{
+ static AtkRole aDefaultRole = ATK_ROLE_INVALID;
+
+ // Special role for sub-menu and combo-box popups that are exposed directly
+ // by their parents already.
+ if( aDefaultRole == ATK_ROLE_INVALID )
+ aDefaultRole = atk_role_register( "redundant object" );
+
+ AtkRole role = aDefaultRole;
+
+ // Determine the appropriate role for the GtkWindow
+ switch( pWindow->GetAccessibleRole() )
+ {
+ case AccessibleRole::ALERT:
+ role = ATK_ROLE_ALERT;
+ break;
+
+ case AccessibleRole::DIALOG:
+ role = ATK_ROLE_DIALOG;
+ break;
+
+ case AccessibleRole::FRAME:
+ role = ATK_ROLE_FRAME;
+ break;
+
+ /* Ignore window objects for sub-menus, combo- and list boxes,
+ * which are exposed as children of their parents.
+ */
+ case AccessibleRole::WINDOW:
+ {
+ USHORT type = WINDOW_WINDOW;
+ bool parentIsMenuFloatingWindow = false;
+
+ Window *pParent = pWindow->GetParent();
+ if( pParent ) {
+ type = pParent->GetType();
+ parentIsMenuFloatingWindow = ( TRUE == pParent->IsMenuFloatingWindow() );
+ }
+
+ if( (WINDOW_LISTBOX != type) && (WINDOW_COMBOBOX != type) &&
+ (WINDOW_MENUBARWINDOW != type) && ! parentIsMenuFloatingWindow )
+ {
+ role = ATK_ROLE_WINDOW;
+ }
+ }
+ break;
+
+ default:
+ {
+ Window *pChild = pWindow->GetChild( 0 );
+ if( pChild )
+ {
+ if( WINDOW_HELPTEXTWINDOW == pChild->GetType() )
+ {
+ role = ATK_ROLE_TOOL_TIP;
+ pChild->SetAccessibleRole( AccessibleRole::LABEL );
+ accessible->name = g_strdup( rtl::OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ else if ( pWindow->GetType() == WINDOW_BORDERWINDOW && pChild->GetType() == WINDOW_FLOATINGWINDOW )
+ {
+ PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
+ if (p && p->IsPopupMenu() && p->GetMenuStackLevel() == 0)
+ {
+ // This is a top-level menu popup. Register it.
+ role = ATK_ROLE_POPUP_MENU;
+ pChild->SetAccessibleRole( AccessibleRole::POPUP_MENU );
+ accessible->name = g_strdup( rtl::OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ accessible->role = role;
+}
+
+/*****************************************************************************/
+
+static gint
+ooo_window_wrapper_clear_focus(gpointer)
+{
+ atk_focus_tracker_notify( NULL );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
+{
+ g_idle_add( ooo_window_wrapper_clear_focus, NULL );
+ return FALSE;
+}
+
+static gboolean ooo_tooltip_map( GtkWidget* pToolTip, gpointer )
+{
+ AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
+ if( pAccessible )
+ atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, TRUE );
+ return FALSE;
+}
+
+static gboolean ooo_tooltip_unmap( GtkWidget* pToolTip, gpointer )
+{
+ AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
+ if( pAccessible )
+ atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, FALSE );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static bool
+isChildPopupMenu(Window* pWindow)
+{
+ Window* pChild = pWindow->GetAccessibleChildWindow(0);
+ if (!pChild)
+ return false;
+
+ if (WINDOW_FLOATINGWINDOW != pChild->GetType())
+ return false;
+
+ PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
+ if (!p)
+ return false;
+
+ return p->IsPopupMenu();
+}
+
+static void
+ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
+{
+ window_real_initialize(obj, data);
+
+ GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
+ if( pFrame )
+ {
+ Window *pWindow = pFrame->GetWindow();
+ if( pWindow )
+ {
+ init_from_window( obj, pWindow );
+
+ Reference< XAccessible > xAccessible( pWindow->GetAccessible(true) );
+
+ /* We need the wrapper object for the top-level XAccessible to be
+ * in the wrapper registry when atk traverses the hierachy up on
+ * focus events
+ */
+ if( WINDOW_BORDERWINDOW == pWindow->GetType() )
+ {
+ if ( isChildPopupMenu(pWindow) )
+ {
+ AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
+ ooo_wrapper_registry_add( xAccessible, child );
+ }
+ else
+ {
+ ooo_wrapper_registry_add( xAccessible, obj );
+ g_object_set_data( G_OBJECT(obj), "ooo:atk-wrapper-key", xAccessible.get() );
+ }
+ }
+ else
+ {
+ AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
+ child->role = ATK_ROLE_FILLER;
+ if( (ATK_ROLE_DIALOG == obj->role) || (ATK_ROLE_ALERT == obj->role) )
+ child->role = ATK_ROLE_OPTION_PANE;
+ ooo_wrapper_registry_add( xAccessible, child );
+ }
+ }
+ }
+
+ g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
+ G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
+ NULL);
+
+ if( obj->role == ATK_ROLE_TOOL_TIP )
+ {
+ g_signal_connect_after( GTK_WIDGET( data ), "map-event",
+ G_CALLBACK (ooo_tooltip_map),
+ NULL);
+ g_signal_connect_after( GTK_WIDGET( data ), "unmap-event",
+ G_CALLBACK (ooo_tooltip_unmap),
+ NULL);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+ooo_window_wrapper_real_finalize (GObject *obj)
+{
+ ooo_wrapper_registry_remove( (XAccessible *) g_object_get_data( obj, "ooo:atk-wrapper-key" ));
+ window_real_finalize( obj );
+}
+
+/*****************************************************************************/
+
+static void
+ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
+{
+ AtkObjectClass *atk_class;
+ GObjectClass *gobject_class;
+ gpointer data;
+
+ /*
+ * Patch the gobject vtable of GailWindow to refer to our instance of
+ * "initialize".
+ */
+
+ data = g_type_class_peek_parent( klass );
+ atk_class = ATK_OBJECT_CLASS (data);
+
+ window_real_initialize = atk_class->initialize;
+ atk_class->initialize = ooo_window_wrapper_real_initialize;
+
+ gobject_class = G_OBJECT_CLASS (data);
+
+ window_real_finalize = gobject_class->finalize;
+ gobject_class->finalize = ooo_window_wrapper_real_finalize;
+}
+
+} // extern "C"
+
+/*****************************************************************************/
+
+GType
+ooo_window_wrapper_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ GType parent_type = g_type_from_name( "GailWindow" );
+
+ if( ! parent_type )
+ {
+ g_warning( "Unknown type: GailWindow" );
+ parent_type = ATK_TYPE_OBJECT;
+ }
+
+ GTypeQuery type_query;
+ g_type_query( parent_type, &type_query );
+
+ static const GTypeInfo typeInfo =
+ {
+ type_query.class_size,
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ooo_window_wrapper_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ type_query.instance_size,
+ 0,
+ (GInstanceInitFunc) NULL,
+ NULL
+ } ;
+
+ type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, (GTypeFlags)0) ;
+ }
+
+ return type;
+}
+
+void restore_gail_window_vtable (void)
+{
+ AtkObjectClass *atk_class;
+ gpointer data;
+
+ GType type = g_type_from_name( "GailWindow" );
+
+ if( type == G_TYPE_INVALID )
+ return;
+
+ data = g_type_class_peek( type );
+ atk_class = ATK_OBJECT_CLASS (data);
+
+ atk_class->initialize = window_real_initialize;
+}
+
diff --git a/vcl/unx/gtk/a11y/atkwindow.hxx b/vcl/unx/gtk/a11y/atkwindow.hxx
new file mode 100644
index 000000000000..6a9862256999
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkwindow.hxx
@@ -0,0 +1,38 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_WINDOW_HXX__
+#define __ATK_WINDOW_HXX__
+
+#include <atk/atk.h>
+
+#define OOO_TYPE_WINDOW_WRAPPER ooo_window_wrapper_get_type()
+
+GType ooo_window_wrapper_get_type (void);
+void restore_gail_window_vtable (void);
+
+#endif
diff --git a/vcl/unx/gtk/a11y/atkwrapper.cxx b/vcl/unx/gtk/a11y/atkwrapper.cxx
new file mode 100644
index 000000000000..10f75309708d
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkwrapper.cxx
@@ -0,0 +1,953 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_vcl.hxx"
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleRelation.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+#include <com/sun/star/accessibility/XAccessibleAction.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/awt/XExtendedToolkit.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XTopWindowListener.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/beans/Property.hpp>
+
+#include <rtl/ref.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include "atkwrapper.hxx"
+#include "atkregistry.hxx"
+#include "atklistener.hxx"
+
+#ifdef ENABLE_TRACING
+#include <stdio.h>
+#endif
+
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+static GObjectClass *parent_class = NULL;
+
+static AtkRelationType mapRelationType( sal_Int16 nRelation )
+{
+ AtkRelationType type = ATK_RELATION_NULL;
+
+ switch( nRelation )
+ {
+ case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
+ type = ATK_RELATION_FLOWS_FROM;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
+ type = ATK_RELATION_FLOWS_TO;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTROLLED_BY:
+ type = ATK_RELATION_CONTROLLED_BY;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTROLLER_FOR:
+ type = ATK_RELATION_CONTROLLER_FOR;
+ break;
+
+ case accessibility::AccessibleRelationType::LABEL_FOR:
+ type = ATK_RELATION_LABEL_FOR;
+ break;
+
+ case accessibility::AccessibleRelationType::LABELED_BY:
+ type = ATK_RELATION_LABELLED_BY;
+ break;
+
+ case accessibility::AccessibleRelationType::MEMBER_OF:
+ type = ATK_RELATION_MEMBER_OF;
+ break;
+
+ case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
+ type = ATK_RELATION_SUBWINDOW_OF;
+ break;
+
+ case accessibility::AccessibleRelationType::NODE_CHILD_OF:
+ type = ATK_RELATION_NODE_CHILD_OF;
+ break;
+
+ default:
+ break;
+ }
+#if 0
+ ATK_RELATION_NODE_CHILD_OF,
+ ATK_RELATION_EMBEDS,
+ ATK_RELATION_EMBEDDED_BY,
+ ATK_RELATION_POPUP_FOR,
+#endif
+ return type;
+}
+
+
+AtkStateType mapAtkState( sal_Int16 nState )
+{
+ AtkStateType type = ATK_STATE_INVALID;
+
+ // A perfect / complete mapping ...
+ switch( nState )
+ {
+#define MAP_DIRECT( a ) \
+ case accessibility::AccessibleStateType::a: \
+ type = ATK_STATE_##a; break
+
+ MAP_DIRECT( INVALID );
+ MAP_DIRECT( ACTIVE );
+ MAP_DIRECT( ARMED );
+ MAP_DIRECT( BUSY );
+ MAP_DIRECT( CHECKED );
+ MAP_DIRECT( EDITABLE );
+ MAP_DIRECT( ENABLED );
+ MAP_DIRECT( EXPANDABLE );
+ MAP_DIRECT( EXPANDED );
+ MAP_DIRECT( FOCUSABLE );
+ MAP_DIRECT( FOCUSED );
+ MAP_DIRECT( HORIZONTAL );
+ MAP_DIRECT( ICONIFIED );
+ MAP_DIRECT( INDETERMINATE );
+ MAP_DIRECT( MANAGES_DESCENDANTS );
+ MAP_DIRECT( MODAL );
+ MAP_DIRECT( MULTI_LINE );
+ MAP_DIRECT( OPAQUE );
+ MAP_DIRECT( PRESSED );
+ MAP_DIRECT( RESIZABLE );
+ MAP_DIRECT( SELECTABLE );
+ MAP_DIRECT( SELECTED );
+ MAP_DIRECT( SENSITIVE );
+ MAP_DIRECT( SHOWING );
+ MAP_DIRECT( SINGLE_LINE );
+ MAP_DIRECT( STALE );
+ MAP_DIRECT( TRANSIENT );
+ MAP_DIRECT( VERTICAL );
+ MAP_DIRECT( VISIBLE );
+ // a spelling error ...
+ case accessibility::AccessibleStateType::DEFUNC:
+ type = ATK_STATE_DEFUNCT; break;
+ case accessibility::AccessibleStateType::MULTI_SELECTABLE:
+ type = ATK_STATE_MULTISELECTABLE; break;
+ default:
+ break;
+ }
+
+ return type;
+}
+
+static inline AtkRole registerRole( const gchar * name )
+{
+ AtkRole ret = atk_role_for_name( name );
+ if( ATK_ROLE_INVALID == ret )
+ ret = atk_role_register( name );
+
+ return ret;
+}
+
+static AtkRole mapToAtkRole( sal_Int16 nRole )
+{
+ AtkRole role = ATK_ROLE_UNKNOWN;
+
+ static AtkRole roleMap[] = {
+ ATK_ROLE_UNKNOWN,
+ ATK_ROLE_ALERT,
+ ATK_ROLE_COLUMN_HEADER,
+ ATK_ROLE_CANVAS,
+ ATK_ROLE_CHECK_BOX,
+ ATK_ROLE_CHECK_MENU_ITEM,
+ ATK_ROLE_COLOR_CHOOSER,
+ ATK_ROLE_COMBO_BOX,
+ ATK_ROLE_DATE_EDITOR,
+ ATK_ROLE_DESKTOP_ICON,
+ ATK_ROLE_DESKTOP_FRAME, // ? pane
+ ATK_ROLE_DIRECTORY_PANE,
+ ATK_ROLE_DIALOG,
+ ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
+ ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
+ ATK_ROLE_UNKNOWN, // END_NOTE - registered below
+ ATK_ROLE_FILE_CHOOSER,
+ ATK_ROLE_FILLER,
+ ATK_ROLE_FONT_CHOOSER,
+ ATK_ROLE_FOOTER,
+ ATK_ROLE_TEXT, // FOOTNOTE - registered below
+ ATK_ROLE_FRAME,
+ ATK_ROLE_GLASS_PANE,
+ ATK_ROLE_IMAGE, // GRAPHIC
+ ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
+ ATK_ROLE_HEADER,
+ ATK_ROLE_PARAGRAPH, // HEADING - registered below
+ ATK_ROLE_TEXT, // HYPER_LINK - registered below
+ ATK_ROLE_ICON,
+ ATK_ROLE_INTERNAL_FRAME,
+ ATK_ROLE_LABEL,
+ ATK_ROLE_LAYERED_PANE,
+ ATK_ROLE_LIST,
+ ATK_ROLE_LIST_ITEM,
+ ATK_ROLE_MENU,
+ ATK_ROLE_MENU_BAR,
+ ATK_ROLE_MENU_ITEM,
+ ATK_ROLE_OPTION_PANE,
+ ATK_ROLE_PAGE_TAB,
+ ATK_ROLE_PAGE_TAB_LIST,
+ ATK_ROLE_PANEL,
+ ATK_ROLE_PARAGRAPH,
+ ATK_ROLE_PASSWORD_TEXT,
+ ATK_ROLE_POPUP_MENU,
+ ATK_ROLE_PUSH_BUTTON,
+ ATK_ROLE_PROGRESS_BAR,
+ ATK_ROLE_RADIO_BUTTON,
+ ATK_ROLE_RADIO_MENU_ITEM,
+ ATK_ROLE_ROW_HEADER,
+ ATK_ROLE_ROOT_PANE,
+ ATK_ROLE_SCROLL_BAR,
+ ATK_ROLE_SCROLL_PANE,
+ ATK_ROLE_UNKNOWN, // SHAPE - registered below
+ ATK_ROLE_SEPARATOR,
+ ATK_ROLE_SLIDER,
+ ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
+ ATK_ROLE_SPLIT_PANE,
+ ATK_ROLE_STATUSBAR,
+ ATK_ROLE_TABLE,
+ ATK_ROLE_TABLE_CELL,
+ ATK_ROLE_TEXT,
+ ATK_ROLE_INTERNAL_FRAME, // TEXT_FRAME - registered below
+ ATK_ROLE_TOGGLE_BUTTON,
+ ATK_ROLE_TOOL_BAR,
+ ATK_ROLE_TOOL_TIP,
+ ATK_ROLE_TREE,
+ ATK_ROLE_VIEWPORT,
+ ATK_ROLE_WINDOW,
+ ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
+ ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
+ ATK_ROLE_UNKNOWN, // CAPTION - registered below
+ ATK_ROLE_UNKNOWN, // CHART - registered below
+ ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
+ ATK_ROLE_UNKNOWN, // FORM - registered below
+ ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
+ ATK_ROLE_UNKNOWN, // NOTE - registered below
+ ATK_ROLE_UNKNOWN, // PAGE - registered below
+ ATK_ROLE_RULER,
+ ATK_ROLE_UNKNOWN, // SECTION - registered below
+ ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
+ ATK_ROLE_TREE_TABLE,
+ ATK_ROLE_SCROLL_PANE, // COMMENT - mapped to atk_role_scroll_pane
+ ATK_ROLE_UNKNOWN // COMMENT_END - mapped to atk_role_unknown
+ };
+
+ static bool initialized = false;
+
+ if( ! initialized )
+ {
+ // re-use strings from ATK library
+ roleMap[accessibility::AccessibleRole::EDIT_BAR] = registerRole("edit bar");
+ roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = registerRole("embedded component");
+ roleMap[accessibility::AccessibleRole::CHART] = registerRole("chart");
+ roleMap[accessibility::AccessibleRole::CAPTION] = registerRole("caption");
+ roleMap[accessibility::AccessibleRole::DOCUMENT] = registerRole("document frame");
+ roleMap[accessibility::AccessibleRole::HEADING] = registerRole("heading");
+ roleMap[accessibility::AccessibleRole::PAGE] = registerRole("page");
+ roleMap[accessibility::AccessibleRole::SECTION] = registerRole("section");
+ roleMap[accessibility::AccessibleRole::FORM] = registerRole("form");
+
+ // these don't exist in ATK yet
+ roleMap[accessibility::AccessibleRole::END_NOTE] = registerRole("end note");
+ roleMap[accessibility::AccessibleRole::FOOTNOTE] = registerRole("foot note");
+ roleMap[accessibility::AccessibleRole::GROUP_BOX] = registerRole("group box");
+ roleMap[accessibility::AccessibleRole::HYPER_LINK] = registerRole("hyper link");
+ roleMap[accessibility::AccessibleRole::SHAPE] = registerRole("shape");
+ roleMap[accessibility::AccessibleRole::TEXT_FRAME] = registerRole("text frame");
+ roleMap[accessibility::AccessibleRole::IMAGE_MAP] = registerRole("image map");
+ roleMap[accessibility::AccessibleRole::NOTE] = registerRole("note");
+ roleMap[accessibility::AccessibleRole::TREE_ITEM] = registerRole("tree item");
+
+ initialized = true;
+ }
+
+ static const sal_Int32 nMapSize = sizeof(roleMap)/sizeof(sal_Int16);
+ if( 0 <= nRole && nMapSize > nRole )
+ role = roleMap[nRole];
+
+ return role;
+}
+
+
+/*****************************************************************************/
+
+extern "C" {
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar*
+wrapper_get_name( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ if( obj->mpContext )
+ {
+ try {
+ rtl::OString aName =
+ rtl::OUStringToOString(
+ obj->mpContext->getAccessibleName(),
+ RTL_TEXTENCODING_UTF8);
+
+ int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
+ if( nCmp != 0 )
+ {
+ if( atk_obj->name )
+ g_free(atk_obj->name);
+ atk_obj->name = g_strdup(aName.getStr());
+ }
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleName()" );
+ }
+ }
+
+ return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar*
+wrapper_get_description( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ if( obj->mpContext )
+ {
+ try {
+ rtl::OString aDescription =
+ rtl::OUStringToOString(
+ obj->mpContext->getAccessibleDescription(),
+ RTL_TEXTENCODING_UTF8);
+
+ g_free(atk_obj->description);
+ atk_obj->description = g_strdup(aDescription.getStr());
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleDescription()" );
+ }
+ }
+
+ return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
+
+}
+
+/*****************************************************************************/
+
+static gint
+wrapper_get_n_children( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ gint n = 0;
+
+ if( obj->mpContext )
+ {
+ try {
+ n = obj->mpContext->getAccessibleChildCount();
+ }
+ catch(const uno::Exception& e) {
+ OSL_ENSURE(0, "Exception in getAccessibleChildCount()" );
+ }
+ }
+
+ return n;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+wrapper_ref_child( AtkObject *atk_obj,
+ gint i )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ AtkObject* child = NULL;
+
+ // see comments above atk_object_wrapper_remove_child
+ if( -1 < i && obj->index_of_child_about_to_be_removed == i )
+ {
+ g_object_ref( obj->child_about_to_be_removed );
+ return obj->child_about_to_be_removed;
+ }
+
+ if( obj->mpContext )
+ {
+ try {
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ obj->mpContext->getAccessibleChild( i );
+
+ child = atk_object_wrapper_ref( xAccessible );
+ }
+ catch(const uno::Exception& e) {
+ OSL_ENSURE(0, "Exception in getAccessibleChild");
+ }
+ }
+
+ return child;
+}
+
+/*****************************************************************************/
+
+static gint
+wrapper_get_index_in_parent( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ gint i = -1;
+
+ if( obj->mpContext )
+ {
+ try {
+ i = obj->mpContext->getAccessibleIndexInParent();
+
+#ifdef ENABLE_TRACING
+ fprintf(stderr, "%p->getAccessibleIndexInParent() returned: %u\n",
+ obj->mpAccessible, i);
+#endif
+ }
+ catch(const uno::Exception& e) {
+ g_warning( "Exception in getAccessibleIndexInParent()" );
+ }
+ }
+ return i;
+}
+
+/*****************************************************************************/
+
+static AtkRelationSet *
+wrapper_ref_relation_set( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ AtkRelationSet *pSet = atk_relation_set_new();
+
+ if( obj->mpContext )
+ {
+ try {
+ uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
+ obj->mpContext->getAccessibleRelationSet()
+ );
+
+ sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
+ for( sal_Int32 n = 0; n < nRelations; n++ )
+ {
+ accessibility::AccessibleRelation aRelation = xRelationSet->getRelation( n );
+ sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
+ AtkObject **pTargets = (AtkObject **) alloca( nTargetCount * sizeof(AtkObject *) );
+
+ for( sal_uInt32 i = 0; i < nTargetCount; i++ )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible(
+ aRelation.TargetSet[i], uno::UNO_QUERY );
+ pTargets[i] = atk_object_wrapper_ref( xAccessible );
+ }
+
+ AtkRelation *pRel =
+ atk_relation_new(
+ pTargets, nTargetCount,
+ mapRelationType( aRelation.RelationType )
+ );
+ atk_relation_set_add( pSet, pRel );
+ g_object_unref( G_OBJECT( pRel ) );
+ }
+ }
+ catch(const uno::Exception &e) {
+ g_object_unref( G_OBJECT( pSet ) );
+ pSet = NULL;
+ }
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+#if 0
+struct {
+ sal_Int16 value;
+ const sal_Char* name;
+} aStateTypeTable[] = {
+ { accessibility::AccessibleStateType::INVALID, "INVALID" },
+ { accessibility::AccessibleStateType::ACTIVE, "ACTIVE" },
+ { accessibility::AccessibleStateType::ARMED, "ARMED" },
+ { accessibility::AccessibleStateType::BUSY, "BUSY" },
+ { accessibility::AccessibleStateType::CHECKED, "CHECKED" },
+ { accessibility::AccessibleStateType::DEFUNC, "DEFUNC" },
+ { accessibility::AccessibleStateType::EDITABLE, "EDITABLE" },
+ { accessibility::AccessibleStateType::ENABLED, "ENABLED" },
+ { accessibility::AccessibleStateType::EXPANDABLE, "EXPANDABLE" },
+ { accessibility::AccessibleStateType::EXPANDED, "EXPANDED" },
+ { accessibility::AccessibleStateType::FOCUSABLE, "FOCUSABLE" },
+ { accessibility::AccessibleStateType::FOCUSED, "FOCUSED" },
+ { accessibility::AccessibleStateType::HORIZONTAL, "HORIZONTAL" },
+ { accessibility::AccessibleStateType::ICONIFIED, "ICONIFIED" },
+ { accessibility::AccessibleStateType::INDETERMINATE, "INDETERMINATE" },
+ { accessibility::AccessibleStateType::MANAGES_DESCENDANTS, "MANAGES_DESCENDANTS" },
+ { accessibility::AccessibleStateType::MODAL, "MODAL" },
+ { accessibility::AccessibleStateType::MULTI_LINE, "MULTI_LINE" },
+ { accessibility::AccessibleStateType::MULTI_SELECTABLE, "MULTI_SELECTABLE" },
+ { accessibility::AccessibleStateType::OPAQUE, "OPAQUE" },
+ { accessibility::AccessibleStateType::PRESSED, "PRESSED" },
+ { accessibility::AccessibleStateType::RESIZABLE, "RESIZABLE" },
+ { accessibility::AccessibleStateType::SELECTABLE, "SELECTABLE" },
+ { accessibility::AccessibleStateType::SELECTED, "SELECTED" },
+ { accessibility::AccessibleStateType::SENSITIVE, "SENSITIVE" },
+ { accessibility::AccessibleStateType::SHOWING, "SHOWING" },
+ { accessibility::AccessibleStateType::SINGLE_LINE, "SINGLE_LINE" },
+ { accessibility::AccessibleStateType::STALE, "STALE" },
+ { accessibility::AccessibleStateType::TRANSIENT, "TRANSIENT" },
+ { accessibility::AccessibleStateType::VERTICAL, "VERTICAL" },
+ { accessibility::AccessibleStateType::VISIBLE, "VISIBLE" }
+};
+
+static void printStates(const uno::Sequence<sal_Int16>& rStates)
+{
+ sal_Int32 n = rStates.getLength();
+ size_t nTypes = sizeof(aStateTypeTable)/sizeof(aStateTypeTable[0]);
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < nTypes; ++j)
+ {
+ if (aStateTypeTable[j].value == rStates[i])
+ printf("%s ", aStateTypeTable[j].name);
+ }
+ }
+ printf("\n");
+}
+#endif
+
+static AtkStateSet *
+wrapper_ref_state_set( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ AtkStateSet *pSet = atk_state_set_new();
+
+ if( obj->mpContext )
+ {
+ try {
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
+ obj->mpContext->getAccessibleStateSet());
+
+ if( xStateSet.is() )
+ {
+ uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
+
+ for( sal_Int32 n = 0; n < aStates.getLength(); n++ )
+ atk_state_set_add_state( pSet, mapAtkState( aStates[n] ) );
+
+ // We need to emulate FOCUS state for menus, menu-items etc.
+ if( atk_obj == atk_get_focus_object() )
+ atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
+/* FIXME - should we do this ?
+ else
+ atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
+*/
+ }
+ }
+
+ catch(const uno::Exception &e) {
+ g_warning( "Exception in wrapper_ref_state_set" );
+ atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
+ }
+ }
+ else
+ atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+
+static void
+atk_object_wrapper_finalize (GObject *obj)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
+
+ if( pWrap->mpAccessible )
+ {
+ ooo_wrapper_registry_remove( pWrap->mpAccessible );
+ pWrap->mpAccessible->release();
+ pWrap->mpAccessible = NULL;
+ }
+
+ atk_object_wrapper_dispose( pWrap );
+
+ parent_class->finalize( obj );
+}
+
+static void
+atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
+
+ parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
+
+ // GObject methods
+ gobject_class->finalize = atk_object_wrapper_finalize;
+
+ // AtkObject methods
+ atk_class->get_name = wrapper_get_name;
+ atk_class->get_description = wrapper_get_description;
+ atk_class->get_n_children = wrapper_get_n_children;
+ atk_class->ref_child = wrapper_ref_child;
+ atk_class->get_index_in_parent = wrapper_get_index_in_parent;
+ atk_class->ref_relation_set = wrapper_ref_relation_set;
+ atk_class->ref_state_set = wrapper_ref_state_set;
+}
+
+static void
+atk_object_wrapper_init (AtkObjectWrapper *wrapper,
+ AtkObjectWrapperClass)
+{
+ wrapper->mpAction = NULL;
+ wrapper->mpComponent = NULL;
+ wrapper->mpEditableText = NULL;
+ wrapper->mpHypertext = NULL;
+ wrapper->mpImage = NULL;
+ wrapper->mpSelection = NULL;
+ wrapper->mpTable = NULL;
+ wrapper->mpText = NULL;
+ wrapper->mpValue = NULL;
+}
+
+} // extern "C"
+
+GType
+atk_object_wrapper_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo typeInfo =
+ {
+ sizeof (AtkObjectWrapperClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) atk_object_wrapper_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (AtkObjectWrapper),
+ 0,
+ (GInstanceInitFunc) atk_object_wrapper_init,
+ NULL
+ } ;
+ type = g_type_register_static (ATK_TYPE_OBJECT,
+ "OOoAtkObj",
+ &typeInfo, (GTypeFlags)0) ;
+ }
+ return type;
+}
+
+static bool
+isOfType( uno::XInterface *pInterface, const uno::Type & rType )
+{
+ g_return_val_if_fail( pInterface != NULL, false );
+
+ bool bIs = false;
+ try {
+ uno::Any aRet = pInterface->queryInterface( rType );
+
+ bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
+ ( aRet.pReserved != NULL ) );
+ } catch( const uno::Exception &e) { }
+
+ return bIs;
+}
+
+extern "C" {
+typedef GType (* GetGIfaceType ) (void);
+}
+const struct {
+ const char *name;
+ GInterfaceInitFunc aInit;
+ GetGIfaceType aGetGIfaceType;
+ const uno::Type & (*aGetUnoType) (void *);
+} aTypeTable[] = {
+// re-location heaven:
+ {
+ "Comp", (GInterfaceInitFunc) componentIfaceInit,
+ atk_component_get_type,
+ accessibility::XAccessibleComponent::static_type
+ },
+ {
+ "Act", (GInterfaceInitFunc) actionIfaceInit,
+ atk_action_get_type,
+ accessibility::XAccessibleAction::static_type
+ },
+ {
+ "Txt", (GInterfaceInitFunc) textIfaceInit,
+ atk_text_get_type,
+ accessibility::XAccessibleText::static_type
+ },
+ {
+ "Val", (GInterfaceInitFunc) valueIfaceInit,
+ atk_value_get_type,
+ accessibility::XAccessibleValue::static_type
+ },
+ {
+ "Tab", (GInterfaceInitFunc) tableIfaceInit,
+ atk_table_get_type,
+ accessibility::XAccessibleTable::static_type
+ },
+ {
+ "Edt", (GInterfaceInitFunc) editableTextIfaceInit,
+ atk_editable_text_get_type,
+ accessibility::XAccessibleEditableText::static_type
+ },
+ {
+ "Img", (GInterfaceInitFunc) imageIfaceInit,
+ atk_image_get_type,
+ accessibility::XAccessibleImage::static_type
+ },
+ {
+ "Hyp", (GInterfaceInitFunc) hypertextIfaceInit,
+ atk_hypertext_get_type,
+ accessibility::XAccessibleHypertext::static_type
+ },
+ {
+ "Sel", (GInterfaceInitFunc) selectionIfaceInit,
+ atk_selection_get_type,
+ accessibility::XAccessibleSelection::static_type
+ }
+ // AtkDocument is a nastily broken interface (so far)
+ // we could impl. get_document_type perhaps though.
+};
+
+const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
+
+static GType
+ensureTypeFor( uno::XInterface *pAccessible )
+{
+ int i;
+ int bTypes[ aTypeTableSize ] = { 0, };
+ rtl::OString aTypeName( "OOoAtkObj" );
+
+ for( i = 0; i < aTypeTableSize; i++ )
+ {
+ if( isOfType( pAccessible, aTypeTable[i].aGetUnoType(0) ) )
+ {
+ aTypeName += aTypeTable[i].name;
+ bTypes[i] = TRUE;
+ }
+// g_message( "Accessible %p has type '%s' (%d)",
+// pAccessible, aTypeTable[i].name, bTypes[i] );
+ }
+
+ GType nType = g_type_from_name( aTypeName );
+ if( nType == G_TYPE_INVALID )
+ {
+ GTypeInfo aTypeInfo = {
+ sizeof( AtkObjectWrapperClass ),
+ NULL, NULL, NULL, NULL, NULL,
+ sizeof( AtkObjectWrapper ),
+ 0, NULL, NULL
+ } ;
+ nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
+ aTypeName, &aTypeInfo, (GTypeFlags)0 ) ;
+
+ for( int j = 0; j < aTypeTableSize; j++ )
+ if( bTypes[j] )
+ {
+ GInterfaceInfo aIfaceInfo = { NULL, NULL, NULL };
+ aIfaceInfo.interface_init = aTypeTable[j].aInit;
+ g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
+ &aIfaceInfo);
+ }
+ }
+ return nType;
+}
+
+AtkObject *
+atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
+{
+ g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
+
+ AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
+ if( obj )
+ {
+ g_object_ref( obj );
+ return obj;
+ }
+
+ if( create )
+ return atk_object_wrapper_new( rxAccessible );
+
+ return NULL;
+}
+
+
+AtkObject *
+atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
+ AtkObject* parent )
+{
+ g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
+
+ AtkObjectWrapper *pWrap = NULL;
+
+ try {
+ uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
+
+ g_return_val_if_fail( xContext.get() != NULL, NULL );
+
+ GType nType = ensureTypeFor( xContext.get() );
+ gpointer obj = g_object_new( nType, NULL);
+
+ pWrap = ATK_OBJECT_WRAPPER( obj );
+ pWrap->mpAccessible = rxAccessible.get();
+ rxAccessible->acquire();
+
+ pWrap->index_of_child_about_to_be_removed = -1;
+ pWrap->child_about_to_be_removed = NULL;
+
+ xContext->acquire();
+ pWrap->mpContext = xContext.get();
+
+ AtkObject* atk_obj = ATK_OBJECT(pWrap);
+ atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
+ atk_obj->accessible_parent = parent;
+
+ ooo_wrapper_registry_add( rxAccessible, atk_obj );
+
+ if( parent )
+ g_object_ref( atk_obj->accessible_parent );
+ else
+ {
+ /* gail_focus_tracker remembers the focused object at the first
+ * parent in the hierachy that is a Gtk+ widget, but at the time the
+ * event gets processed (at idle), it may be too late to create the
+ * hierachy, so doing it now ..
+ */
+ uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
+
+ /* The top-level objects should never be of this class */
+ OSL_ASSERT( xParent.is() );
+
+ if( xParent.is() )
+ atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
+ }
+
+ // Attach a listener to the UNO object if it's not TRANSIENT
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
+ if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
+ {
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
+ if( xBroadcaster.is() )
+ xBroadcaster->addEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) );
+ else
+ OSL_ASSERT( false );
+ }
+
+ return ATK_OBJECT( pWrap );
+ }
+ catch (const uno::Exception &e)
+ {
+ if( pWrap )
+ g_object_unref( pWrap );
+
+ return NULL;
+ }
+}
+
+
+/*****************************************************************************/
+
+void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
+{
+ AtkObject *atk_obj = ATK_OBJECT( wrapper );
+
+ atk_object_set_parent( child, atk_obj );
+ g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, NULL );
+}
+
+/*****************************************************************************/
+
+void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
+{
+ /*
+ * the atk-bridge GTK+ module get's back to the event source to ref the child just
+ * vanishing, so we keep this reference because the semantic on OOo side is different.
+ */
+ wrapper->child_about_to_be_removed = child;
+ wrapper->index_of_child_about_to_be_removed = index;
+
+ g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, NULL );
+
+ wrapper->index_of_child_about_to_be_removed = -1;
+ wrapper->child_about_to_be_removed = NULL;
+}
+
+/*****************************************************************************/
+
+#define RELEASE(i) if( i ) { i->release(); i = NULL; }
+
+void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
+{
+ RELEASE( wrapper->mpContext )
+ RELEASE( wrapper->mpAction )
+ RELEASE( wrapper->mpComponent )
+ RELEASE( wrapper->mpEditableText )
+ RELEASE( wrapper->mpHypertext )
+ RELEASE( wrapper->mpImage )
+ RELEASE( wrapper->mpSelection )
+ RELEASE( wrapper->mpMultiLineText )
+ RELEASE( wrapper->mpTable )
+ RELEASE( wrapper->mpText )
+ RELEASE( wrapper->mpTextMarkup )
+ RELEASE( wrapper->mpTextAttributes )
+ RELEASE( wrapper->mpValue )
+}
diff --git a/vcl/unx/gtk/a11y/atkwrapper.hxx b/vcl/unx/gtk/a11y/atkwrapper.hxx
new file mode 100644
index 000000000000..4252c0404833
--- /dev/null
+++ b/vcl/unx/gtk/a11y/atkwrapper.hxx
@@ -0,0 +1,125 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 __ATK_WRAPPER_HXX__
+#define __ATK_WRAPPER_HXX__
+
+#include <atk/atk.h>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+extern "C" {
+
+typedef struct _AtkObjectWrapper AtkObjectWrapper;
+typedef struct _AtkObjectWrapperClass AtkObjectWrapperClass;
+
+namespace com { namespace sun { namespace star { namespace accessibility {
+ class XAccessibleAction;
+ class XAccessibleComponent;
+ class XAccessibleEditableText;
+ class XAccessibleHypertext;
+ class XAccessibleImage;
+ class XAccessibleMultiLineText;
+ class XAccessibleSelection;
+ class XAccessibleTable;
+ class XAccessibleText;
+ class XAccessibleTextMarkup;
+ class XAccessibleTextAttributes;
+ class XAccessibleValue;
+} } } }
+
+
+struct _AtkObjectWrapper
+{
+ AtkObject aParent;
+
+ ::com::sun::star::accessibility::XAccessible *mpAccessible;
+ ::com::sun::star::accessibility::XAccessibleContext *mpContext;
+ ::com::sun::star::accessibility::XAccessibleAction *mpAction;
+ ::com::sun::star::accessibility::XAccessibleComponent *mpComponent;
+ ::com::sun::star::accessibility::XAccessibleEditableText *mpEditableText;
+ ::com::sun::star::accessibility::XAccessibleHypertext *mpHypertext;
+ ::com::sun::star::accessibility::XAccessibleImage *mpImage;
+ ::com::sun::star::accessibility::XAccessibleMultiLineText *mpMultiLineText;
+ ::com::sun::star::accessibility::XAccessibleSelection *mpSelection;
+ ::com::sun::star::accessibility::XAccessibleTable *mpTable;
+ ::com::sun::star::accessibility::XAccessibleText *mpText;
+ ::com::sun::star::accessibility::XAccessibleTextMarkup *mpTextMarkup;
+ ::com::sun::star::accessibility::XAccessibleTextAttributes *mpTextAttributes;
+ ::com::sun::star::accessibility::XAccessibleValue *mpValue;
+
+ AtkObject *child_about_to_be_removed;
+ gint index_of_child_about_to_be_removed;
+// ::rtl::OString * m_pKeyBindings
+};
+
+struct _AtkObjectWrapperClass
+{
+ AtkObjectClass aParentClass;
+};
+
+GType atk_object_wrapper_get_type (void) G_GNUC_CONST;
+AtkObject * atk_object_wrapper_ref(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
+ bool create = true );
+
+AtkObject * atk_object_wrapper_new(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
+ AtkObject* parent = NULL );
+
+void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index);
+void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index);
+
+void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper);
+
+AtkStateType mapAtkState( sal_Int16 nState );
+
+void actionIfaceInit(AtkActionIface *iface);
+void componentIfaceInit(AtkComponentIface *iface);
+void editableTextIfaceInit(AtkEditableTextIface *iface);
+void hypertextIfaceInit(AtkHypertextIface *iface);
+void imageIfaceInit(AtkImageIface *iface);
+void selectionIfaceInit(AtkSelectionIface *iface);
+void tableIfaceInit(AtkTableIface *iface);
+void textIfaceInit(AtkTextIface *iface);
+void valueIfaceInit(AtkValueIface *iface);
+
+} // extern "C"
+
+#define ATK_TYPE_OBJECT_WRAPPER atk_object_wrapper_get_type()
+#define ATK_OBJECT_WRAPPER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_OBJECT_WRAPPER, AtkObjectWrapper))
+
+static inline gchar *
+OUStringToGChar(const rtl::OUString& rString )
+{
+ rtl::OString aUtf8 = rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
+ return g_strdup( aUtf8 );
+}
+
+#define OUStringToConstGChar( string ) rtl::OUStringToOString( string, RTL_TEXTENCODING_UTF8 ).getStr()
+
+#endif /* __ATK_WRAPPER_HXX__ */
diff --git a/vcl/unx/gtk/a11y/makefile.mk b/vcl/unx/gtk/a11y/makefile.mk
new file mode 100644
index 000000000000..14d3014ddf11
--- /dev/null
+++ b/vcl/unx/gtk/a11y/makefile.mk
@@ -0,0 +1,93 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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=vcl
+TARGET=gtka11y
+ENABLE_EXCEPTIONS=TRUE
+
+# workaround for makedepend hang
+MKDEPENDSOLVER=
+NO_DEFAULT_STL=YES
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUIBASE)"!="unx"
+
+dummy:
+ @echo "Nothing to build for GUIBASE $(GUIBASE)"
+
+.ELSE # "$(GUIBASE)"!="unx"
+
+.IF "$(ENABLE_GTK)" != ""
+
+PKGCONFIG_MODULES=gtk+-2.0
+.INCLUDE : pkg_config.mk
+
+CFLAGS+=-DVERSION=$(EMQ)"$(UPD)$(LAST_MINOR)$(EMQ)"
+
+ATKVERSION:=$(shell @$(PKG_CONFIG) --modversion atk | $(AWK) -v num=true -f $(SOLARENV)$/bin$/getcompver.awk)
+
+.IF "$(ATKVERSION)" >= "000100070000"
+CFLAGS+=-DHAS_ATKRECTANGLE
+.ENDIF
+
+SLOFILES=\
+ $(SLO)$/atkaction.obj \
+ $(SLO)$/atkbridge.obj \
+ $(SLO)$/atkcomponent.obj \
+ $(SLO)$/atkeditabletext.obj \
+ $(SLO)$/atkfactory.obj \
+ $(SLO)$/atkhypertext.obj \
+ $(SLO)$/atkimage.obj \
+ $(SLO)$/atklistener.obj \
+ $(SLO)$/atkregistry.obj \
+ $(SLO)$/atkselection.obj \
+ $(SLO)$/atktable.obj \
+ $(SLO)$/atktext.obj \
+ $(SLO)$/atktextattributes.obj \
+ $(SLO)$/atkutil.obj \
+ $(SLO)$/atkvalue.obj \
+ $(SLO)$/atkwindow.obj \
+ $(SLO)$/atkwrapper.obj
+
+.ELSE # "$(ENABLE_GTK)" != ""
+
+dummy:
+ @echo GTK disabled - nothing to build
+.ENDIF
+.ENDIF # "$(GUIBASE)"!="unx"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+