gtk2/gtk/a11y/gtktextcellaccessible.c
Benjamin Otte 08d86fabc4 a11y: Implement ref_state_set using the new APIs
Various tiny semantic changes in here.

The big fix is that we consider every cell as visible and as showing if
the treeview is mapped.
This was also fixed in the tree dump test.
2011-11-24 18:29:45 +01:00

817 lines
27 KiB
C

/* GAIL - The GNOME Accessibility Enabling Library
* Copyright 2001 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "../gtkpango.h"
#include "gtktextcellaccessible.h"
#include "gtkcontainercellaccessible.h"
#include "gtkcellaccessibleparent.h"
static const gchar* gtk_text_cell_accessible_get_name (AtkObject *atk_obj);
/* atktext.h */
static gchar* gtk_text_cell_accessible_get_text (AtkText *text,
gint start_pos,
gint end_pos);
static gunichar gtk_text_cell_accessible_get_character_at_offset (AtkText *text,
gint offset);
static gchar* gtk_text_cell_accessible_get_text_before_offset (AtkText *text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset);
static gchar* gtk_text_cell_accessible_get_text_at_offset (AtkText *text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset);
static gchar* gtk_text_cell_accessible_get_text_after_offset (AtkText *text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset);
static gint gtk_text_cell_accessible_get_character_count (AtkText *text);
static gint gtk_text_cell_accessible_get_caret_offset (AtkText *text);
static gboolean gtk_text_cell_accessible_set_caret_offset (AtkText *text,
gint offset);
static void gtk_text_cell_accessible_get_character_extents (AtkText *text,
gint offset,
gint *x,
gint *y,
gint *width,
gint *height,
AtkCoordType coords);
static gint gtk_text_cell_accessible_get_offset_at_point (AtkText *text,
gint x,
gint y,
AtkCoordType coords);
static AtkAttributeSet* gtk_text_cell_accessible_get_run_attributes
(AtkText *text,
gint offset,
gint *start_offset,
gint *end_offset);
static AtkAttributeSet* gtk_text_cell_accessible_get_default_attributes
(AtkText *text);
static GtkWidget* get_widget (GtkTextCellAccessible *cell);
static PangoLayout* create_pango_layout (GtkTextCellAccessible *cell);
static void add_attr (PangoAttrList *attr_list,
PangoAttribute *attr);
/* Misc */
static gboolean gtk_text_cell_accessible_update_cache (GtkRendererCellAccessible *cell,
gboolean emit_change_signal);
static gchar *property_list[] = {
/* Set font_desc first since it resets other values if it is NULL */
"font-desc",
"attributes",
"background-gdk",
"editable",
"family",
"foreground-gdk",
"rise",
"scale",
"size",
"size-points",
"stretch",
"strikethrough",
"style",
"text",
"underline",
"variant",
"weight",
/* Also need the sets */
"background-set",
"editable-set",
"family-set",
"foreground-set",
"rise-set",
"scale-set",
"size-set",
"stretch-set",
"strikethrough-set",
"style-set",
"underline-set",
"variant-set",
"weight-set",
NULL
};
static void atk_text_interface_init (AtkTextIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkTextCellAccessible, _gtk_text_cell_accessible, GTK_TYPE_RENDERER_CELL_ACCESSIBLE,
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
static AtkStateSet *
gtk_text_cell_accessible_ref_state_set (AtkObject *accessible)
{
AtkStateSet *state_set;
state_set = ATK_OBJECT_CLASS (_gtk_text_cell_accessible_parent_class)->ref_state_set (accessible);
atk_state_set_add_state (state_set, ATK_STATE_SINGLE_LINE);
return state_set;
}
static void
gtk_text_cell_accessible_finalize (GObject *object)
{
GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (object);
g_free (text_cell->cell_text);
G_OBJECT_CLASS (_gtk_text_cell_accessible_parent_class)->finalize (object);
}
static const gchar *
gtk_text_cell_accessible_get_name (AtkObject *atk_obj)
{
GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (atk_obj);
if (atk_obj->name)
return atk_obj->name;
return text_cell->cell_text;
}
static gboolean
gtk_text_cell_accessible_update_cache (GtkRendererCellAccessible *cell,
gboolean emit_change_signal)
{
GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (cell);
AtkObject *obj = ATK_OBJECT (cell);
gboolean rv = FALSE;
gint temp_length;
gchar *text;
g_object_get (G_OBJECT (cell->renderer), "text", &text, NULL);
if (text_cell->cell_text)
{
if (text == NULL || g_strcmp0 (text_cell->cell_text, text) != 0)
{
g_free (text_cell->cell_text);
temp_length = text_cell->cell_length;
text_cell->cell_text = NULL;
text_cell->cell_length = 0;
if (emit_change_signal)
{
g_signal_emit_by_name (cell, "text-changed::delete", 0, temp_length);
if (obj->name == NULL)
g_object_notify (G_OBJECT (obj), "accessible-name");
}
if (text)
rv = TRUE;
}
}
else
rv = TRUE;
if (rv)
{
if (text == NULL)
{
text_cell->cell_text = g_strdup ("");
text_cell->cell_length = 0;
}
else
{
text_cell->cell_text = g_strdup (text);
text_cell->cell_length = g_utf8_strlen (text, -1);
}
}
g_free (text);
if (rv)
{
if (emit_change_signal)
{
g_signal_emit_by_name (cell, "text-changed::insert",
0, text_cell->cell_length);
if (obj->name == NULL)
g_object_notify (G_OBJECT (obj), "accessible-name");
}
}
return rv;
}
static void
_gtk_text_cell_accessible_class_init (GtkTextCellAccessibleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
GtkRendererCellAccessibleClass *renderer_cell_class = GTK_RENDERER_CELL_ACCESSIBLE_CLASS (klass);
renderer_cell_class->update_cache = gtk_text_cell_accessible_update_cache;
renderer_cell_class->property_list = property_list;
atk_object_class->get_name = gtk_text_cell_accessible_get_name;
atk_object_class->ref_state_set = gtk_text_cell_accessible_ref_state_set;
gobject_class->finalize = gtk_text_cell_accessible_finalize;
}
static void
_gtk_text_cell_accessible_init (GtkTextCellAccessible *text_cell)
{
text_cell->cell_text = NULL;
text_cell->caret_pos = 0;
text_cell->cell_length = 0;
}
AtkObject *
_gtk_text_cell_accessible_new (void)
{
GObject *object;
AtkObject *atk_object;
GtkRendererCellAccessible *cell;
object = g_object_new (GTK_TYPE_TEXT_CELL_ACCESSIBLE, NULL);
g_return_val_if_fail (object != NULL, NULL);
atk_object = ATK_OBJECT (object);
atk_object->role = ATK_ROLE_TABLE_CELL;
cell = GTK_RENDERER_CELL_ACCESSIBLE(object);
cell->renderer = gtk_cell_renderer_text_new ();
g_object_ref_sink (cell->renderer);
return atk_object;
}
static gchar *
gtk_text_cell_accessible_get_text (AtkText *atk_text,
gint start_pos,
gint end_pos)
{
gchar *text;
text = GTK_TEXT_CELL_ACCESSIBLE (atk_text)->cell_text;
if (text)
return g_utf8_substring (text, start_pos, end_pos > -1 ? end_pos : g_utf8_strlen (text, -1));
else
return g_strdup ("");
}
static gchar *
gtk_text_cell_accessible_get_text_before_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
PangoLayout *layout;
gchar *text;
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
text = _gtk_pango_get_text_before (layout, boundary_type, offset, start_offset, end_offset);
g_object_unref (layout);
return text;
}
static gchar *
gtk_text_cell_accessible_get_text_at_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
PangoLayout *layout;
gchar *text;
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
text = _gtk_pango_get_text_at (layout, boundary_type, offset, start_offset, end_offset);
g_object_unref (layout);
return text;
}
static gchar *
gtk_text_cell_accessible_get_text_after_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
PangoLayout *layout;
gchar *text;
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
text = _gtk_pango_get_text_after (layout, boundary_type, offset, start_offset, end_offset);
g_object_unref (layout);
return text;
}
static gint
gtk_text_cell_accessible_get_character_count (AtkText *text)
{
if (GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text != NULL)
return GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length;
else
return 0;
}
static gint
gtk_text_cell_accessible_get_caret_offset (AtkText *text)
{
return GTK_TEXT_CELL_ACCESSIBLE (text)->caret_pos;
}
static gboolean
gtk_text_cell_accessible_set_caret_offset (AtkText *text,
gint offset)
{
GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (text);
if (text_cell->cell_text == NULL)
return FALSE;
else
{
/* Only set the caret within the bounds and if it is to a new position. */
if (offset >= 0 &&
offset <= text_cell->cell_length &&
offset != text_cell->caret_pos)
{
text_cell->caret_pos = offset;
/* emit the signal */
g_signal_emit_by_name (text, "text-caret-moved", offset);
return TRUE;
}
else
return FALSE;
}
}
static AtkAttributeSet *
gtk_text_cell_accessible_get_run_attributes (AtkText *text,
gint offset,
gint *start_offset,
gint *end_offset)
{
AtkAttributeSet *attrib_set = NULL;
PangoLayout *layout;
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
attrib_set = _gtk_pango_get_run_attributes (NULL, layout, offset, start_offset, end_offset);
g_object_unref (G_OBJECT (layout));
return attrib_set;
}
static AtkAttributeSet *
add_attribute (AtkAttributeSet *attributes,
AtkTextAttribute attr,
const gchar *value)
{
AtkAttribute *at;
at = g_new (AtkAttribute, 1);
at->name = g_strdup (atk_text_attribute_get_name (attr));
at->value = g_strdup (value);
return g_slist_prepend (attributes, at);
}
static AtkAttributeSet *
gtk_text_cell_accessible_get_default_attributes (AtkText *text)
{
AtkAttributeSet *attrib_set = NULL;
PangoLayout *layout;
GtkWidget *widget;
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
widget = get_widget (GTK_TEXT_CELL_ACCESSIBLE (text));
attrib_set = add_attribute (attrib_set, ATK_TEXT_ATTR_DIRECTION,
atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
gtk_widget_get_direction (widget)));
attrib_set = _gtk_pango_get_default_attributes (NULL, layout);
attrib_set = _gtk_style_context_get_attributes (attrib_set,
gtk_widget_get_style_context (widget),
gtk_widget_get_state_flags (widget));
g_object_unref (G_OBJECT (layout));
return attrib_set;
}
GtkWidget *
get_widget (GtkTextCellAccessible *text)
{
AtkObject *parent;
parent = atk_object_get_parent (ATK_OBJECT (text));
if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
parent = atk_object_get_parent (parent);
return gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
}
/* This function is used by gtk_text_cell_accessible_get_offset_at_point()
* and gtk_text_cell_accessible_get_character_extents(). There is no
* cached PangoLayout so we must create a temporary one using this function.
*/
static PangoLayout *
create_pango_layout (GtkTextCellAccessible *text)
{
GdkRGBA *foreground_rgba;
PangoAttrList *attr_list, *attributes;
PangoLayout *layout;
PangoUnderline uline, underline;
PangoFontMask mask;
PangoFontDescription *font_desc;
gboolean foreground_set, strikethrough_set, strikethrough;
gboolean scale_set, underline_set, rise_set;
gchar *renderer_text;
gdouble scale;
gint rise;
GtkRendererCellAccessible *gail_renderer;
GtkCellRendererText *gtk_renderer;
gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
g_object_get (gtk_renderer,
"text", &renderer_text,
"attributes", &attributes,
"foreground-set", &foreground_set,
"foreground-rgba", &foreground_rgba,
"strikethrough-set", &strikethrough_set,
"strikethrough", &strikethrough,
"font-desc", &font_desc,
"scale-set", &scale_set,
"scale", &scale,
"underline-set", &underline_set,
"underline", &underline,
"rise-set", &rise_set,
"rise", &rise,
NULL);
layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text);
if (attributes)
attr_list = pango_attr_list_copy (attributes);
else
attr_list = pango_attr_list_new ();
if (foreground_set)
{
add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535,
foreground_rgba->green * 65535,
foreground_rgba->blue * 65535));
}
if (strikethrough_set)
add_attr (attr_list,
pango_attr_strikethrough_new (strikethrough));
mask = pango_font_description_get_set_fields (font_desc);
if (mask & PANGO_FONT_MASK_FAMILY)
add_attr (attr_list,
pango_attr_family_new (pango_font_description_get_family (font_desc)));
if (mask & PANGO_FONT_MASK_STYLE)
add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc)));
if (mask & PANGO_FONT_MASK_VARIANT)
add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc)));
if (mask & PANGO_FONT_MASK_WEIGHT)
add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc)));
if (mask & PANGO_FONT_MASK_STRETCH)
add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc)));
if (mask & PANGO_FONT_MASK_SIZE)
add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc)));
if (scale_set && scale != 1.0)
add_attr (attr_list, pango_attr_scale_new (scale));
if (underline_set)
uline = underline;
else
uline = PANGO_UNDERLINE_NONE;
if (uline != PANGO_UNDERLINE_NONE)
add_attr (attr_list,
pango_attr_underline_new (underline));
if (rise_set)
add_attr (attr_list, pango_attr_rise_new (rise));
pango_layout_set_attributes (layout, attr_list);
pango_layout_set_width (layout, -1);
pango_attr_list_unref (attr_list);
pango_font_description_free (font_desc);
pango_attr_list_unref (attributes);
g_free (renderer_text);
gdk_rgba_free (foreground_rgba);
return layout;
}
static void
add_attr (PangoAttrList *attr_list,
PangoAttribute *attr)
{
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_insert (attr_list, attr);
}
static void
get_origins (GtkWidget *widget,
gint *x_window,
gint *y_window,
gint *x_toplevel,
gint *y_toplevel)
{
GdkWindow *window;
if (GTK_IS_TREE_VIEW (widget))
window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget));
else
window = gtk_widget_get_window (widget);
gdk_window_get_origin (window, x_window, y_window);
window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
gdk_window_get_origin (window, x_toplevel, y_toplevel);
}
static void
gtk_text_cell_accessible_get_character_extents (AtkText *text,
gint offset,
gint *x,
gint *y,
gint *width,
gint *height,
AtkCoordType coords)
{
GtkRendererCellAccessible *gail_renderer;
GtkRequisition min_size;
GtkCellRendererText *gtk_renderer;
GdkRectangle rendered_rect;
GtkWidget *widget;
AtkObject *parent;
PangoRectangle char_rect;
PangoLayout *layout;
gchar *renderer_text;
gfloat xalign, yalign;
gint x_offset, y_offset, index;
gint xpad, ypad;
gint x_window, y_window, x_toplevel, y_toplevel;
if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
{
*x = *y = *height = *width = 0;
return;
}
if (offset < 0 || offset >= GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length)
{
*x = *y = *height = *width = 0;
return;
}
gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
g_object_get (gtk_renderer, "text", &renderer_text, NULL);
if (text == NULL)
{
g_free (renderer_text);
return;
}
parent = atk_object_get_parent (ATK_OBJECT (text));
if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
parent = atk_object_get_parent (parent);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
g_return_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent));
_gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent),
GTK_CELL_ACCESSIBLE (text),
&rendered_rect);
gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
widget,
&min_size, NULL);
gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
xalign = 1.0 - xalign;
x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
index = g_utf8_offset_to_pointer (renderer_text, offset) - renderer_text;
pango_layout_index_to_pos (layout, index, &char_rect);
gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
*x = (char_rect.x / PANGO_SCALE) + x_offset + rendered_rect.x + xpad + x_window;
*y = (char_rect.y / PANGO_SCALE) + y_offset + rendered_rect.y + ypad + y_window;
*height = char_rect.height / PANGO_SCALE;
*width = char_rect.width / PANGO_SCALE;
if (coords == ATK_XY_WINDOW)
{
*x -= x_toplevel;
*y -= y_toplevel;
}
else if (coords != ATK_XY_SCREEN)
{
*x = 0;
*y = 0;
*height = 0;
*width = 0;
}
g_free (renderer_text);
g_object_unref (layout);
}
static gint
gtk_text_cell_accessible_get_offset_at_point (AtkText *text,
gint x,
gint y,
AtkCoordType coords)
{
AtkObject *parent;
GtkRendererCellAccessible *gail_renderer;
GtkCellRendererText *gtk_renderer;
GtkRequisition min_size;
GtkWidget *widget;
GdkRectangle rendered_rect;
PangoLayout *layout;
gchar *renderer_text;
gfloat xalign, yalign;
gint x_offset, y_offset, index;
gint xpad, ypad;
gint x_window, y_window, x_toplevel, y_toplevel;
gint x_temp, y_temp;
gboolean ret;
if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
return -1;
gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
parent = atk_object_get_parent (ATK_OBJECT (text));
g_object_get (gtk_renderer, "text", &renderer_text, NULL);
if (text == NULL)
{
g_free (renderer_text);
return -1;
}
if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
parent = atk_object_get_parent (parent);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), -1);
_gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent),
GTK_CELL_ACCESSIBLE (text),
&rendered_rect);
gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
widget,
&min_size, NULL);
gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
xalign = 1.0 - xalign;
x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
x_temp = x - (x_offset + rendered_rect.x + xpad) - x_window;
y_temp = y - (y_offset + rendered_rect.y + ypad) - y_window;
if (coords == ATK_XY_WINDOW)
{
x_temp += x_toplevel;
y_temp += y_toplevel;
}
else if (coords != ATK_XY_SCREEN)
index = -1;
ret = pango_layout_xy_to_index (layout,
x_temp * PANGO_SCALE,
y_temp * PANGO_SCALE,
&index, NULL);
if (!ret)
{
if (x_temp < 0 || y_temp < 0)
index = 0;
else
index = -1;
}
g_object_unref (layout);
if (index == -1)
{
if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
{
glong length;
length = g_utf8_strlen (renderer_text, -1);
g_free (renderer_text);
return length;
}
g_free (renderer_text);
return index;
}
else
{
glong offset;
offset = g_utf8_pointer_to_offset (renderer_text,
renderer_text + index);
g_free (renderer_text);
return offset;
}
}
static gunichar
gtk_text_cell_accessible_get_character_at_offset (AtkText *text,
gint offset)
{
gchar *index;
gchar *string;
string = GTK_TEXT_CELL_ACCESSIBLE(text)->cell_text;
if (!string)
return '\0';
if (offset >= g_utf8_strlen (string, -1))
return '\0';
index = g_utf8_offset_to_pointer (string, offset);
return g_utf8_get_char (index);
}
static void
atk_text_interface_init (AtkTextIface *iface)
{
iface->get_text = gtk_text_cell_accessible_get_text;
iface->get_character_at_offset = gtk_text_cell_accessible_get_character_at_offset;
iface->get_text_before_offset = gtk_text_cell_accessible_get_text_before_offset;
iface->get_text_at_offset = gtk_text_cell_accessible_get_text_at_offset;
iface->get_text_after_offset = gtk_text_cell_accessible_get_text_after_offset;
iface->get_character_count = gtk_text_cell_accessible_get_character_count;
iface->get_caret_offset = gtk_text_cell_accessible_get_caret_offset;
iface->set_caret_offset = gtk_text_cell_accessible_set_caret_offset;
iface->get_run_attributes = gtk_text_cell_accessible_get_run_attributes;
iface->get_default_attributes = gtk_text_cell_accessible_get_default_attributes;
iface->get_character_extents = gtk_text_cell_accessible_get_character_extents;
iface->get_offset_at_point = gtk_text_cell_accessible_get_offset_at_point;
}