summaryrefslogtreecommitdiff
path: root/clutter/clutter/cally/cally-text.c
diff options
context:
space:
mode:
Diffstat (limited to 'clutter/clutter/cally/cally-text.c')
-rw-r--r--clutter/clutter/cally/cally-text.c2328
1 files changed, 0 insertions, 2328 deletions
diff --git a/clutter/clutter/cally/cally-text.c b/clutter/clutter/cally/cally-text.c
deleted file mode 100644
index fe4abb710..000000000
--- a/clutter/clutter/cally/cally-text.c
+++ /dev/null
@@ -1,2328 +0,0 @@
-/* CALLY - The Clutter Accessibility Implementation Library
- *
- * Copyright (C) 2009 Igalia, S.L.
- *
- * Author: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
- *
- * Some parts are based on GailLabel, GailEntry, GailTextView from GAIL
- * GAIL - The GNOME Accessibility Implementation Library
- * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
- *
- * Implementation of atk_text_get_text_[before/at/after]_offset
- * copied from gtkpango.c, part of GTK+ project
- * Copyright (c) 2010 Red Hat, 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.
- */
-
-/**
- * SECTION:cally-text
- * @short_description: Implementation of the ATK interfaces for a #ClutterText
- * @see_also: #ClutterText
- *
- * #CallyText implements the required ATK interfaces of
- * #ClutterText, #AtkText and #AtkEditableText
- *
- *
- */
-
-#include "clutter-build-config.h"
-
-#include "cally-text.h"
-#include "cally-actor-private.h"
-
-#include "clutter-color.h"
-#include "clutter-main.h"
-#include "clutter-text.h"
-
-static void cally_text_finalize (GObject *obj);
-
-/* AtkObject */
-static void cally_text_real_initialize (AtkObject *obj,
- gpointer data);
-static AtkStateSet* cally_text_ref_state_set (AtkObject *obj);
-
-/* atkaction */
-
-static void _cally_text_activate_action (CallyActor *cally_actor);
-static void _check_activate_action (CallyText *cally_text,
- ClutterText *clutter_text);
-
-/* AtkText */
-static void cally_text_text_interface_init (AtkTextIface *iface);
-static gchar* cally_text_get_text (AtkText *text,
- gint start_offset,
- gint end_offset);
-static gunichar cally_text_get_character_at_offset (AtkText *text,
- gint offset);
-static gchar* cally_text_get_text_before_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gchar* cally_text_get_text_at_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gchar* cally_text_get_text_after_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gint cally_text_get_caret_offset (AtkText *text);
-static gboolean cally_text_set_caret_offset (AtkText *text,
- gint offset);
-static gint cally_text_get_character_count (AtkText *text);
-static gint cally_text_get_n_selections (AtkText *text);
-static gchar* cally_text_get_selection (AtkText *text,
- gint selection_num,
- gint *start_offset,
- gint *end_offset);
-static gboolean cally_text_add_selection (AtkText *text,
- gint start_offset,
- gint end_offset);
-static gboolean cally_text_remove_selection (AtkText *text,
- gint selection_num);
-static gboolean cally_text_set_selection (AtkText *text,
- gint selection_num,
- gint start_offset,
- gint end_offset);
-static AtkAttributeSet* cally_text_get_run_attributes (AtkText *text,
- gint offset,
- gint *start_offset,
- gint *end_offset);
-static AtkAttributeSet* cally_text_get_default_attributes (AtkText *text);
-static void cally_text_get_character_extents (AtkText *text,
- gint offset,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- AtkCoordType coords);
-static gint cally_text_get_offset_at_point (AtkText *text,
- gint x,
- gint y,
- AtkCoordType coords);
-
-static void _cally_text_get_selection_bounds (ClutterText *clutter_text,
- gint *start_offset,
- gint *end_offset);
-static void _cally_text_insert_text_cb (ClutterText *clutter_text,
- gchar *new_text,
- gint new_text_length,
- gint *position,
- gpointer data);
-static void _cally_text_delete_text_cb (ClutterText *clutter_text,
- gint start_pos,
- gint end_pos,
- gpointer data);
-static gboolean _idle_notify_insert (gpointer data);
-static void _notify_insert (CallyText *cally_text);
-static void _notify_delete (CallyText *cally_text);
-
-/* AtkEditableText */
-static void cally_text_editable_text_interface_init (AtkEditableTextIface *iface);
-static void cally_text_set_text_contents (AtkEditableText *text,
- const gchar *string);
-static void cally_text_insert_text (AtkEditableText *text,
- const gchar *string,
- gint length,
- gint *position);
-static void cally_text_delete_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos);
-
-/* CallyActor */
-static void cally_text_notify_clutter (GObject *obj,
- GParamSpec *pspec);
-
-static gboolean _check_for_selection_change (CallyText *cally_text,
- ClutterText *clutter_text);
-
-/* Misc functions */
-static AtkAttributeSet* _cally_misc_add_attribute (AtkAttributeSet *attrib_set,
- AtkTextAttribute attr,
- gchar *value);
-
-static AtkAttributeSet* _cally_misc_layout_get_run_attributes (AtkAttributeSet *attrib_set,
- ClutterText *clutter_text,
- gint offset,
- gint *start_offset,
- gint *end_offset);
-
-static AtkAttributeSet* _cally_misc_layout_get_default_attributes (AtkAttributeSet *attrib_set,
- ClutterText *text);
-
-static int _cally_misc_get_index_at_point (ClutterText *clutter_text,
- gint x,
- gint y,
- AtkCoordType coords);
-
-struct _CallyTextPrivate
-{
- /* Cached ClutterText values*/
- gint cursor_position;
- gint selection_bound;
-
- /* text_changed::insert stuff */
- const gchar *signal_name_insert;
- gint position_insert;
- gint length_insert;
- guint insert_idle_handler;
-
- /* text_changed::delete stuff */
- const gchar *signal_name_delete;
- gint position_delete;
- gint length_delete;
-
- /* action */
- guint activate_action_id;
-};
-
-G_DEFINE_TYPE_WITH_CODE (CallyText,
- cally_text,
- CALLY_TYPE_ACTOR,
- G_ADD_PRIVATE (CallyText)
- G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT,
- cally_text_text_interface_init)
- G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT,
- cally_text_editable_text_interface_init));
-
-static void
-cally_text_class_init (CallyTextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
- CallyActorClass *cally_class = CALLY_ACTOR_CLASS (klass);
-
- gobject_class->finalize = cally_text_finalize;
-
- class->initialize = cally_text_real_initialize;
- class->ref_state_set = cally_text_ref_state_set;
-
- cally_class->notify_clutter = cally_text_notify_clutter;
-}
-
-static void
-cally_text_init (CallyText *cally_text)
-{
- CallyTextPrivate *priv = cally_text_get_instance_private (cally_text);
-
- cally_text->priv = priv;
-
- priv->cursor_position = 0;
- priv->selection_bound = 0;
-
- priv->signal_name_insert = NULL;
- priv->position_insert = -1;
- priv->length_insert = -1;
- priv->insert_idle_handler = 0;
-
- priv->signal_name_delete = NULL;
- priv->position_delete = -1;
- priv->length_delete = -1;
-
- priv->activate_action_id = 0;
-}
-
-static void
-cally_text_finalize (GObject *obj)
-{
- CallyText *cally_text = CALLY_TEXT (obj);
-
-/* g_object_unref (cally_text->priv->textutil); */
-/* cally_text->priv->textutil = NULL; */
-
- g_clear_handle_id (&cally_text->priv->insert_idle_handler, g_source_remove);
-
- G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj);
-}
-
-/**
- * cally_text_new:
- * @actor: a #ClutterActor
- *
- * Creates a new #CallyText for the given @actor. @actor must be a
- * #ClutterText.
- *
- * Return value: the newly created #AtkObject
- *
- * Since: 1.4
- */
-AtkObject*
-cally_text_new (ClutterActor *actor)
-{
- GObject *object = NULL;
- AtkObject *accessible = NULL;
-
- g_return_val_if_fail (CLUTTER_IS_TEXT (actor), NULL);
-
- object = g_object_new (CALLY_TYPE_TEXT, NULL);
-
- accessible = ATK_OBJECT (object);
- atk_object_initialize (accessible, actor);
-
- return accessible;
-}
-
-/* atkobject.h */
-
-static void
-cally_text_real_initialize(AtkObject *obj,
- gpointer data)
-{
- ClutterText *clutter_text = NULL;
- CallyText *cally_text = NULL;
-
- ATK_OBJECT_CLASS (cally_text_parent_class)->initialize (obj, data);
-
- g_return_if_fail (CLUTTER_TEXT (data));
-
- cally_text = CALLY_TEXT (obj);
- clutter_text = CLUTTER_TEXT (data);
-
- cally_text->priv->cursor_position = clutter_text_get_cursor_position (clutter_text);
- cally_text->priv->selection_bound = clutter_text_get_selection_bound (clutter_text);
-
- g_signal_connect (clutter_text, "insert-text",
- G_CALLBACK (_cally_text_insert_text_cb),
- cally_text);
- g_signal_connect (clutter_text, "delete-text",
- G_CALLBACK (_cally_text_delete_text_cb),
- cally_text);
-
- _check_activate_action (cally_text, clutter_text);
-
- if (clutter_text_get_password_char (clutter_text) != 0)
- atk_object_set_role (obj, ATK_ROLE_PASSWORD_TEXT);
- else
- atk_object_set_role (obj, ATK_ROLE_TEXT);
-}
-
-static AtkStateSet*
-cally_text_ref_state_set (AtkObject *obj)
-{
- AtkStateSet *result = NULL;
- ClutterActor *actor = NULL;
-
- result = ATK_OBJECT_CLASS (cally_text_parent_class)->ref_state_set (obj);
-
- actor = CALLY_GET_CLUTTER_ACTOR (obj);
-
- if (actor == NULL)
- return result;
-
- if (clutter_text_get_editable (CLUTTER_TEXT (actor)))
- atk_state_set_add_state (result, ATK_STATE_EDITABLE);
-
- if (clutter_text_get_selectable (CLUTTER_TEXT (actor)))
- atk_state_set_add_state (result, ATK_STATE_SELECTABLE_TEXT);
-
- return result;
-}
-
-/***** pango stuff ****
- *
- * FIXME: all this pango related code used to implement
- * atk_text_get_text_[before/at/after]_offset was copied from GTK, and
- * should be on a common library (like pango itself).
- *
- *********************/
-
-/*
- * _gtk_pango_move_chars:
- * @layout: a #PangoLayout
- * @offset: a character offset in @layout
- * @count: the number of characters to move from @offset
- *
- * Returns the position that is @count characters from the
- * given @offset. @count may be positive or negative.
- *
- * For the purpose of this function, characters are defined
- * by what Pango considers cursor positions.
- *
- * Returns: the new position
- */
-static gint
-_gtk_pango_move_chars (PangoLayout *layout,
- gint offset,
- gint count)
-{
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- while (count > 0 && offset < n_attrs - 1)
- {
- do
- offset++;
- while (offset < n_attrs - 1 && !attrs[offset].is_cursor_position);
-
- count--;
- }
- while (count < 0 && offset > 0)
- {
- do
- offset--;
- while (offset > 0 && !attrs[offset].is_cursor_position);
-
- count++;
- }
-
- return offset;
-}
-
-/*
- * _gtk_pango_move_words:
- * @layout: a #PangoLayout
- * @offset: a character offset in @layout
- * @count: the number of words to move from @offset
- *
- * Returns the position that is @count words from the
- * given @offset. @count may be positive or negative.
- *
- * If @count is positive, the returned position will
- * be a word end, otherwise it will be a word start.
- * See the Pango documentation for details on how
- * word starts and ends are defined.
- *
- * Returns: the new position
- */
-static gint
-_gtk_pango_move_words (PangoLayout *layout,
- gint offset,
- gint count)
-{
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- while (count > 0 && offset < n_attrs - 1)
- {
- do
- offset++;
- while (offset < n_attrs - 1 && !attrs[offset].is_word_end);
-
- count--;
- }
- while (count < 0 && offset > 0)
- {
- do
- offset--;
- while (offset > 0 && !attrs[offset].is_word_start);
-
- count++;
- }
-
- return offset;
-}
-
-/*
- * _gtk_pango_move_sentences:
- * @layout: a #PangoLayout
- * @offset: a character offset in @layout
- * @count: the number of sentences to move from @offset
- *
- * Returns the position that is @count sentences from the
- * given @offset. @count may be positive or negative.
- *
- * If @count is positive, the returned position will
- * be a sentence end, otherwise it will be a sentence start.
- * See the Pango documentation for details on how
- * sentence starts and ends are defined.
- *
- * Returns: the new position
- */
-static gint
-_gtk_pango_move_sentences (PangoLayout *layout,
- gint offset,
- gint count)
-{
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- while (count > 0 && offset < n_attrs - 1)
- {
- do
- offset++;
- while (offset < n_attrs - 1 && !attrs[offset].is_sentence_end);
-
- count--;
- }
- while (count < 0 && offset > 0)
- {
- do
- offset--;
- while (offset > 0 && !attrs[offset].is_sentence_start);
-
- count++;
- }
-
- return offset;
-}
-
-/*
- * _gtk_pango_is_inside_word:
- * @layout: a #PangoLayout
- * @offset: a character offset in @layout
- *
- * Returns whether the given position is inside
- * a word.
- *
- * Returns: %TRUE if @offset is inside a word
- */
-static gboolean
-_gtk_pango_is_inside_word (PangoLayout *layout,
- gint offset)
-{
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- while (offset >= 0 &&
- !(attrs[offset].is_word_start || attrs[offset].is_word_end))
- offset--;
-
- if (offset >= 0)
- return attrs[offset].is_word_start;
-
- return FALSE;
-}
-
-/*
- * _gtk_pango_is_inside_sentence:
- * @layout: a #PangoLayout
- * @offset: a character offset in @layout
- *
- * Returns whether the given position is inside
- * a sentence.
- *
- * Returns: %TRUE if @offset is inside a sentence
- */
-static gboolean
-_gtk_pango_is_inside_sentence (PangoLayout *layout,
- gint offset)
-{
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- while (offset >= 0 &&
- !(attrs[offset].is_sentence_start || attrs[offset].is_sentence_end))
- offset--;
-
- if (offset >= 0)
- return attrs[offset].is_sentence_start;
-
- return FALSE;
-}
-
-static void
-pango_layout_get_line_before (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- PangoLayoutIter *iter;
- PangoLayoutLine *line, *prev_line = NULL, *prev_prev_line = NULL;
- gint index, start_index, end_index;
- const gchar *text;
- gboolean found = FALSE;
-
- text = pango_layout_get_text (layout);
- index = g_utf8_offset_to_pointer (text, offset) - text;
- iter = pango_layout_get_iter (layout);
- do
- {
- line = pango_layout_iter_get_line (iter);
- start_index = line->start_index;
- end_index = start_index + line->length;
-
- if (index >= start_index && index <= end_index)
- {
- /* Found line for offset */
- if (prev_line)
- {
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_LINE_START:
- end_index = start_index;
- start_index = prev_line->start_index;
- break;
- case ATK_TEXT_BOUNDARY_LINE_END:
- if (prev_prev_line)
- start_index = prev_prev_line->start_index + prev_prev_line->length;
- else
- start_index = 0;
- end_index = prev_line->start_index + prev_line->length;
- break;
- default:
- g_assert_not_reached();
- }
- }
- else
- start_index = end_index = 0;
-
- found = TRUE;
- break;
- }
-
- prev_prev_line = prev_line;
- prev_line = line;
- }
- while (pango_layout_iter_next_line (iter));
-
- if (!found)
- {
- start_index = prev_line->start_index + prev_line->length;
- end_index = start_index;
- }
- pango_layout_iter_free (iter);
-
- *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
- *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
-}
-
-static void
-pango_layout_get_line_at (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- PangoLayoutIter *iter;
- PangoLayoutLine *line, *prev_line = NULL;
- gint index, start_index, end_index;
- const gchar *text;
- gboolean found = FALSE;
-
- text = pango_layout_get_text (layout);
- index = g_utf8_offset_to_pointer (text, offset) - text;
- iter = pango_layout_get_iter (layout);
- do
- {
- line = pango_layout_iter_get_line (iter);
- start_index = line->start_index;
- end_index = start_index + line->length;
-
- if (index >= start_index && index <= end_index)
- {
- /* Found line for offset */
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_LINE_START:
- if (pango_layout_iter_next_line (iter))
- end_index = pango_layout_iter_get_line (iter)->start_index;
- break;
- case ATK_TEXT_BOUNDARY_LINE_END:
- if (prev_line)
- start_index = prev_line->start_index + prev_line->length;
- break;
- default:
- g_assert_not_reached();
- }
-
- found = TRUE;
- break;
- }
-
- prev_line = line;
- }
- while (pango_layout_iter_next_line (iter));
-
- if (!found)
- {
- start_index = prev_line->start_index + prev_line->length;
- end_index = start_index;
- }
- pango_layout_iter_free (iter);
-
- *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
- *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
-}
-
-static void
-pango_layout_get_line_after (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- PangoLayoutIter *iter;
- PangoLayoutLine *line, *prev_line = NULL;
- gint index, start_index, end_index;
- const gchar *text;
- gboolean found = FALSE;
-
- text = pango_layout_get_text (layout);
- index = g_utf8_offset_to_pointer (text, offset) - text;
- iter = pango_layout_get_iter (layout);
- do
- {
- line = pango_layout_iter_get_line (iter);
- start_index = line->start_index;
- end_index = start_index + line->length;
-
- if (index >= start_index && index <= end_index)
- {
- /* Found line for offset */
- if (pango_layout_iter_next_line (iter))
- {
- line = pango_layout_iter_get_line (iter);
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_LINE_START:
- start_index = line->start_index;
- if (pango_layout_iter_next_line (iter))
- end_index = pango_layout_iter_get_line (iter)->start_index;
- else
- end_index = start_index + line->length;
- break;
- case ATK_TEXT_BOUNDARY_LINE_END:
- start_index = end_index;
- end_index = line->start_index + line->length;
- break;
- default:
- g_assert_not_reached();
- }
- }
- else
- start_index = end_index;
-
- found = TRUE;
- break;
- }
-
- prev_line = line;
- }
- while (pango_layout_iter_next_line (iter));
-
- if (!found)
- {
- start_index = prev_line->start_index + prev_line->length;
- end_index = start_index;
- }
- pango_layout_iter_free (iter);
-
- *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
- *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
-}
-
-/*
- * _gtk_pango_get_text_at:
- * @layout: a #PangoLayout
- * @boundary_type: a #AtkTextBoundary
- * @offset: a character offset in @layout
- * @start_offset: return location for the start of the returned text
- * @end_offset: return location for the end of the return text
- *
- * Gets a slice of the text from @layout at @offset.
- *
- * The @boundary_type determines the size of the returned slice of
- * text. For the exact semantics of this function, see
- * atk_text_get_text_after_offset().
- *
- * Returns: a newly allocated string containing a slice of text
- * from layout. Free with g_free().
- */
-static gchar *
-_gtk_pango_get_text_at (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- const gchar *text;
- gint start, end;
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- text = pango_layout_get_text (layout);
-
- if (text[0] == 0)
- {
- *start_offset = 0;
- *end_offset = 0;
- return g_strdup ("");
- }
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- start = offset;
- end = start;
-
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_CHAR:
- end = _gtk_pango_move_chars (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_START:
- if (!attrs[start].is_word_start)
- start = _gtk_pango_move_words (layout, start, -1);
- if (_gtk_pango_is_inside_word (layout, end))
- end = _gtk_pango_move_words (layout, end, 1);
- while (!attrs[end].is_word_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_END:
- if (_gtk_pango_is_inside_word (layout, start) &&
- !attrs[start].is_word_start)
- start = _gtk_pango_move_words (layout, start, -1);
- while (!attrs[start].is_word_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- end = _gtk_pango_move_words (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- if (!attrs[start].is_sentence_start)
- start = _gtk_pango_move_sentences (layout, start, -1);
- if (_gtk_pango_is_inside_sentence (layout, end))
- end = _gtk_pango_move_sentences (layout, end, 1);
- while (!attrs[end].is_sentence_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_END:
- if (_gtk_pango_is_inside_sentence (layout, start) &&
- !attrs[start].is_sentence_start)
- start = _gtk_pango_move_sentences (layout, start, -1);
- while (!attrs[start].is_sentence_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- end = _gtk_pango_move_sentences (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_LINE_START:
- case ATK_TEXT_BOUNDARY_LINE_END:
- pango_layout_get_line_at (layout, boundary_type, offset, &start, &end);
- break;
- }
-
- *start_offset = start;
- *end_offset = end;
-
- g_assert (start <= end);
-
- return g_utf8_substring (text, start, end);
-}
-
-/*
- * _gtk_pango_get_text_before:
- * @layout: a #PangoLayout
- * @boundary_type: a #AtkTextBoundary
- * @offset: a character offset in @layout
- * @start_offset: return location for the start of the returned text
- * @end_offset: return location for the end of the return text
- *
- * Gets a slice of the text from @layout before @offset.
- *
- * The @boundary_type determines the size of the returned slice of
- * text. For the exact semantics of this function, see
- * atk_text_get_text_before_offset().
- *
- * Returns: a newly allocated string containing a slice of text
- * from layout. Free with g_free().
- */
-static gchar *
-_gtk_pango_get_text_before (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- const gchar *text;
- gint start, end;
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- text = pango_layout_get_text (layout);
-
- if (text[0] == 0)
- {
- *start_offset = 0;
- *end_offset = 0;
- return g_strdup ("");
- }
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- start = offset;
- end = start;
-
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_CHAR:
- start = _gtk_pango_move_chars (layout, start, -1);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_START:
- if (!attrs[start].is_word_start)
- start = _gtk_pango_move_words (layout, start, -1);
- end = start;
- start = _gtk_pango_move_words (layout, start, -1);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_END:
- if (_gtk_pango_is_inside_word (layout, start) &&
- !attrs[start].is_word_start)
- start = _gtk_pango_move_words (layout, start, -1);
- while (!attrs[start].is_word_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- end = start;
- start = _gtk_pango_move_words (layout, start, -1);
- while (!attrs[start].is_word_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- if (!attrs[start].is_sentence_start)
- start = _gtk_pango_move_sentences (layout, start, -1);
- end = start;
- start = _gtk_pango_move_sentences (layout, start, -1);
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_END:
- if (_gtk_pango_is_inside_sentence (layout, start) &&
- !attrs[start].is_sentence_start)
- start = _gtk_pango_move_sentences (layout, start, -1);
- while (!attrs[start].is_sentence_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- end = start;
- start = _gtk_pango_move_sentences (layout, start, -1);
- while (!attrs[start].is_sentence_end && start > 0)
- start = _gtk_pango_move_chars (layout, start, -1);
- break;
-
- case ATK_TEXT_BOUNDARY_LINE_START:
- case ATK_TEXT_BOUNDARY_LINE_END:
- pango_layout_get_line_before (layout, boundary_type, offset, &start, &end);
- break;
- }
-
- *start_offset = start;
- *end_offset = end;
-
- g_assert (start <= end);
-
- return g_utf8_substring (text, start, end);
-}
-
-/*
- * _gtk_pango_get_text_after:
- * @layout: a #PangoLayout
- * @boundary_type: a #AtkTextBoundary
- * @offset: a character offset in @layout
- * @start_offset: return location for the start of the returned text
- * @end_offset: return location for the end of the return text
- *
- * Gets a slice of the text from @layout after @offset.
- *
- * The @boundary_type determines the size of the returned slice of
- * text. For the exact semantics of this function, see
- * atk_text_get_text_after_offset().
- *
- * Returns: a newly allocated string containing a slice of text
- * from layout. Free with g_free().
- */
-static gchar *
-_gtk_pango_get_text_after (PangoLayout *layout,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- const gchar *text;
- gint start, end;
- const PangoLogAttr *attrs;
- gint n_attrs;
-
- text = pango_layout_get_text (layout);
-
- if (text[0] == 0)
- {
- *start_offset = 0;
- *end_offset = 0;
- return g_strdup ("");
- }
-
- attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-
- start = offset;
- end = start;
-
- switch (boundary_type)
- {
- case ATK_TEXT_BOUNDARY_CHAR:
- start = _gtk_pango_move_chars (layout, start, 1);
- end = start;
- end = _gtk_pango_move_chars (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_START:
- if (_gtk_pango_is_inside_word (layout, end))
- end = _gtk_pango_move_words (layout, end, 1);
- while (!attrs[end].is_word_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- start = end;
- if (end < n_attrs - 1)
- {
- end = _gtk_pango_move_words (layout, end, 1);
- while (!attrs[end].is_word_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- }
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_END:
- end = _gtk_pango_move_words (layout, end, 1);
- start = end;
- if (end < n_attrs - 1)
- end = _gtk_pango_move_words (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- if (_gtk_pango_is_inside_sentence (layout, end))
- end = _gtk_pango_move_sentences (layout, end, 1);
- while (!attrs[end].is_sentence_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- start = end;
- if (end < n_attrs - 1)
- {
- end = _gtk_pango_move_sentences (layout, end, 1);
- while (!attrs[end].is_sentence_start && end < n_attrs - 1)
- end = _gtk_pango_move_chars (layout, end, 1);
- }
- break;
-
- case ATK_TEXT_BOUNDARY_SENTENCE_END:
- end = _gtk_pango_move_sentences (layout, end, 1);
- start = end;
- if (end < n_attrs - 1)
- end = _gtk_pango_move_sentences (layout, end, 1);
- break;
-
- case ATK_TEXT_BOUNDARY_LINE_START:
- case ATK_TEXT_BOUNDARY_LINE_END:
- pango_layout_get_line_after (layout, boundary_type, offset, &start, &end);
- break;
- }
-
- *start_offset = start;
- *end_offset = end;
-
- g_assert (start <= end);
-
- return g_utf8_substring (text, start, end);
-}
-
-/***** atktext.h ******/
-
-static void
-cally_text_text_interface_init (AtkTextIface *iface)
-{
- g_return_if_fail (iface != NULL);
-
- iface->get_text = cally_text_get_text;
- iface->get_character_at_offset = cally_text_get_character_at_offset;
- iface->get_text_before_offset = cally_text_get_text_before_offset;
- iface->get_text_at_offset = cally_text_get_text_at_offset;
- iface->get_text_after_offset = cally_text_get_text_after_offset;
- iface->get_character_count = cally_text_get_character_count;
- iface->get_caret_offset = cally_text_get_caret_offset;
- iface->set_caret_offset = cally_text_set_caret_offset;
- iface->get_n_selections = cally_text_get_n_selections;
- iface->get_selection = cally_text_get_selection;
- iface->add_selection = cally_text_add_selection;
- iface->remove_selection = cally_text_remove_selection;
- iface->set_selection = cally_text_set_selection;
- iface->get_run_attributes = cally_text_get_run_attributes;
- iface->get_default_attributes = cally_text_get_default_attributes;
- iface->get_character_extents = cally_text_get_character_extents;
- iface->get_offset_at_point = cally_text_get_offset_at_point;
-
-}
-
-static gchar*
-cally_text_get_text (AtkText *text,
- gint start_offset,
- gint end_offset)
-{
- ClutterActor *actor = NULL;
- PangoLayout *layout = NULL;
- const gchar *string = NULL;
- gint character_count = 0;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* Object is defunct */
- return NULL;
-
- /* we use the pango layout instead of clutter_text_get_chars because
- it take into account password-char */
-
- layout = clutter_text_get_layout (CLUTTER_TEXT (actor));
- string = pango_layout_get_text (layout);
- character_count = pango_layout_get_character_count (layout);
-
- if (end_offset == -1 || end_offset > character_count)
- end_offset = character_count;
-
- if (string[0] == 0)
- return g_strdup("");
- else
- return g_utf8_substring (string, start_offset, end_offset);
-}
-
-static gunichar
-cally_text_get_character_at_offset (AtkText *text,
- gint offset)
-{
- ClutterActor *actor = NULL;
- const gchar *string = NULL;
- gchar *index = NULL;
- gunichar unichar;
- PangoLayout *layout = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return '\0';
-
- /* we use the pango layout instead of clutter_text_get_chars because
- it take into account password-char */
-
- layout = clutter_text_get_layout (CLUTTER_TEXT (actor));
- string = pango_layout_get_text (layout);
-
- if (offset >= g_utf8_strlen (string, -1))
- {
- unichar = '\0';
- }
- else
- {
- index = g_utf8_offset_to_pointer (string, offset);
-
- unichar = g_utf8_get_char (index);
- }
-
- return unichar;
-}
-
-static gchar*
-cally_text_get_text_before_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- return _gtk_pango_get_text_before (clutter_text_get_layout (CLUTTER_TEXT (actor)),
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gchar*
-cally_text_get_text_at_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- return _gtk_pango_get_text_at (clutter_text_get_layout (CLUTTER_TEXT (actor)),
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gchar*
-cally_text_get_text_after_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- return _gtk_pango_get_text_after (clutter_text_get_layout (CLUTTER_TEXT (actor)),
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gint
-cally_text_get_caret_offset (AtkText *text)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return -1;
-
- return clutter_text_get_cursor_position (CLUTTER_TEXT (actor));
-}
-
-static gboolean
-cally_text_set_caret_offset (AtkText *text,
- gint offset)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return FALSE;
-
- clutter_text_set_cursor_position (CLUTTER_TEXT (actor), offset);
-
- /* like in gailentry, we suppose that this always works, as clutter text
- doesn't return anything */
- return TRUE;
-}
-
-static gint
-cally_text_get_character_count (AtkText *text)
-{
- ClutterActor *actor = NULL;
- ClutterText *clutter_text = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return 0;
-
- clutter_text = CLUTTER_TEXT (actor);
- return g_utf8_strlen (clutter_text_get_text (clutter_text), -1);
-}
-
-static gint
-cally_text_get_n_selections (AtkText *text)
-{
- ClutterActor *actor = NULL;
- gint selection_bound = -1;
- gint cursor_position = -1;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return 0;
-
- if (!clutter_text_get_selectable (CLUTTER_TEXT (actor)))
- return 0;
-
- selection_bound = clutter_text_get_selection_bound (CLUTTER_TEXT (actor));
- cursor_position = clutter_text_get_cursor_position (CLUTTER_TEXT (actor));
-
- if (selection_bound == cursor_position)
- return 0;
- else
- return 1;
-}
-
-static gchar*
-cally_text_get_selection (AtkText *text,
- gint selection_num,
- gint *start_offset,
- gint *end_offset)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- /* As in gailentry, only let the user get the selection if one is set, and if
- * the selection_num is 0.
- */
- if (selection_num != 0)
- return NULL;
-
- _cally_text_get_selection_bounds (CLUTTER_TEXT (actor), start_offset, end_offset);
-
- if (*start_offset != *end_offset)
- return clutter_text_get_selection (CLUTTER_TEXT (actor));
- else
- return NULL;
-}
-
-/* ClutterText only allows one selection. So this method will set the selection
- if no selection exists, but as in gailentry, it will not change the current
- selection */
-static gboolean
-cally_text_add_selection (AtkText *text,
- gint start_offset,
- gint end_offset)
-{
- ClutterActor *actor;
- gint select_start, select_end;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return FALSE;
-
- _cally_text_get_selection_bounds (CLUTTER_TEXT (actor),
- &select_start, &select_end);
-
- /* Like in gailentry, if there is already a selection, then don't allow another
- * to be added, since ClutterText only supports one selected region.
- */
- if (select_start == select_end)
- {
- clutter_text_set_selection (CLUTTER_TEXT (actor),
- start_offset, end_offset);
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-static gboolean
-cally_text_remove_selection (AtkText *text,
- gint selection_num)
-{
- ClutterActor *actor = NULL;
- gint caret_pos = -1;
- gint select_start = -1;
- gint select_end = -1;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return FALSE;
-
- /* only one selection is allowed */
- if (selection_num != 0)
- return FALSE;
-
- _cally_text_get_selection_bounds (CLUTTER_TEXT (actor),
- &select_start, &select_end);
-
- if (select_start != select_end)
- {
- /* Setting the start & end of the selected region to the caret position
- * turns off the selection.
- */
- caret_pos = clutter_text_get_cursor_position (CLUTTER_TEXT (actor));
- clutter_text_set_selection (CLUTTER_TEXT (actor),
- caret_pos, caret_pos);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-static gboolean
-cally_text_set_selection (AtkText *text,
- gint selection_num,
- gint start_offset,
- gint end_offset)
-{
- ClutterActor *actor = NULL;
- gint select_start = -1;
- gint select_end = -1;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return FALSE;
-
- /* Like in gailentry, only let the user move the selection if one is set,
- * and if the selection_num is 0
- */
- if (selection_num != 0)
- return FALSE;
-
- _cally_text_get_selection_bounds (CLUTTER_TEXT (actor),
- &select_start, &select_end);
-
- if (select_start != select_end)
- {
- clutter_text_set_selection (CLUTTER_TEXT (actor),
- start_offset, end_offset);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-static AtkAttributeSet*
-cally_text_get_run_attributes (AtkText *text,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- ClutterActor *actor = NULL;
- ClutterText *clutter_text = NULL;
- AtkAttributeSet *at_set = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- /* Clutter don't have any reference to the direction*/
-
- clutter_text = CLUTTER_TEXT (actor);
-
- at_set = _cally_misc_layout_get_run_attributes (at_set,
- clutter_text,
- offset,
- start_offset,
- end_offset);
-
- return at_set;
-}
-
-static AtkAttributeSet*
-cally_text_get_default_attributes (AtkText *text)
-{
- ClutterActor *actor = NULL;
- ClutterText *clutter_text = NULL;
- AtkAttributeSet *at_set = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return NULL;
-
- clutter_text = CLUTTER_TEXT (actor);
-
- at_set = _cally_misc_layout_get_default_attributes (at_set, clutter_text);
-
- return at_set;
-}
-
-static void cally_text_get_character_extents (AtkText *text,
- gint offset,
- gint *xp,
- gint *yp,
- gint *widthp,
- gint *heightp,
- AtkCoordType coords)
-{
- ClutterActor *actor = NULL;
- ClutterText *clutter_text = NULL;
- gint x = 0, y = 0, width = 0, height = 0;
- gint index, x_window, y_window, x_toplevel, y_toplevel;
- gint x_layout, y_layout;
- PangoLayout *layout;
- PangoRectangle extents;
- const gchar *text_value;
- graphene_point3d_t verts[4];
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- goto done;
-
- clutter_text = CLUTTER_TEXT (actor);
-
- text_value = clutter_text_get_text (clutter_text);
- index = g_utf8_offset_to_pointer (text_value, offset) - text_value;
-
- layout = clutter_text_get_layout (clutter_text);
- pango_layout_index_to_pos (layout, index, &extents);
-
- /* handle RTL text layout */
- if (extents.width < 0)
- {
- extents.x += extents.width;
- extents.width = -extents.width;
- }
-
- clutter_actor_get_abs_allocation_vertices (actor, verts);
- x_window = verts[0].x;
- y_window = verts[0].y;
-
- clutter_text_get_layout_offsets (clutter_text, &x_layout, &y_layout);
-
- x = (extents.x / PANGO_SCALE) + x_layout + x_window;
- y = (extents.y / PANGO_SCALE) + y_layout + y_window;
- width = extents.width / PANGO_SCALE;
- height = extents.height / PANGO_SCALE;
-
- if (coords == ATK_XY_SCREEN)
- {
- _cally_actor_get_top_level_origin (actor, &x_toplevel, &y_toplevel);
- x += x_toplevel;
- y += y_toplevel;
- }
-
-done:
- if (widthp)
- *widthp = width;
-
- if (heightp)
- *heightp = height;
-
- if (xp)
- *xp = x;
-
- if (yp)
- *yp = y;
-}
-
-static gint
-cally_text_get_offset_at_point (AtkText *text,
- gint x,
- gint y,
- AtkCoordType coords)
-{
- ClutterActor *actor = NULL;
- ClutterText *clutter_text = NULL;
- const gchar *text_value;
- gint index;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL) /* State is defunct */
- return -1;
-
- clutter_text = CLUTTER_TEXT (actor);
-
- index = _cally_misc_get_index_at_point (clutter_text, x, y, coords);
- text_value = clutter_text_get_text (clutter_text);
- if (index == -1)
- return g_utf8_strlen (text_value, -1);
- else
- return g_utf8_pointer_to_offset (text_value, text_value + index);
-}
-
-
-/******** Auxiliary private methods ******/
-
-/* ClutterText only maintains the current cursor position and a extra selection
- bound, but this could be before or after the cursor. This method returns
- the start and end positions in a proper order (so start<=end). This is
- similar to the function gtk_editable_get_selection_bounds */
-static void
-_cally_text_get_selection_bounds (ClutterText *clutter_text,
- gint *start_offset,
- gint *end_offset)
-{
- gint pos = -1;
- gint selection_bound = -1;
-
- pos = clutter_text_get_cursor_position (clutter_text);
- selection_bound = clutter_text_get_selection_bound (clutter_text);
-
- if (pos < selection_bound)
- {
- *start_offset = pos;
- *end_offset = selection_bound;
- }
- else
- {
- *start_offset = selection_bound;
- *end_offset = pos;
- }
-}
-
-static void
-_cally_text_delete_text_cb (ClutterText *clutter_text,
- gint start_pos,
- gint end_pos,
- gpointer data)
-{
- CallyText *cally_text = NULL;
-
- g_return_if_fail (CALLY_IS_TEXT (data));
-
- /* Ignore zero length deletions */
- if (end_pos - start_pos == 0)
- return;
-
- cally_text = CALLY_TEXT (data);
-
- if (!cally_text->priv->signal_name_delete)
- {
- cally_text->priv->signal_name_delete = "text_changed::delete";
- cally_text->priv->position_delete = start_pos;
- cally_text->priv->length_delete = end_pos - start_pos;
- }
-
- _notify_delete (cally_text);
-}
-
-static void
-_cally_text_insert_text_cb (ClutterText *clutter_text,
- gchar *new_text,
- gint new_text_length,
- gint *position,
- gpointer data)
-{
- CallyText *cally_text = NULL;
-
- g_return_if_fail (CALLY_IS_TEXT (data));
-
- cally_text = CALLY_TEXT (data);
-
- if (!cally_text->priv->signal_name_insert)
- {
- cally_text->priv->signal_name_insert = "text_changed::insert";
- cally_text->priv->position_insert = *position;
- cally_text->priv->length_insert = g_utf8_strlen (new_text, new_text_length);
- }
-
- /*
- * The signal will be emitted when the cursor position is updated,
- * or in an idle handler if it not updated.
- */
- if (cally_text->priv->insert_idle_handler == 0)
- cally_text->priv->insert_idle_handler = clutter_threads_add_idle (_idle_notify_insert,
- cally_text);
-}
-
-/***** atkeditabletext.h ******/
-
-static void
-cally_text_editable_text_interface_init (AtkEditableTextIface *iface)
-{
- g_return_if_fail (iface != NULL);
-
- iface->set_text_contents = cally_text_set_text_contents;
- iface->insert_text = cally_text_insert_text;
- iface->delete_text = cally_text_delete_text;
-
- iface->set_run_attributes = NULL;
- iface->copy_text = NULL;
- iface->cut_text = NULL;
- iface->paste_text = NULL;
-}
-
-static void
-cally_text_set_text_contents (AtkEditableText *text,
- const gchar *string)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL)
- return;
-
- if (!clutter_text_get_editable (CLUTTER_TEXT (actor)))
- return;
-
- clutter_text_set_text (CLUTTER_TEXT (actor),
- string);
-}
-
-
-static void
-cally_text_insert_text (AtkEditableText *text,
- const gchar *string,
- gint length,
- gint *position)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL)
- return;
-
- if (!clutter_text_get_editable (CLUTTER_TEXT (actor)))
- return;
-
- if (length < 0)
- length = g_utf8_strlen (string, -1);
-
- clutter_text_insert_text (CLUTTER_TEXT (actor),
- string, *position);
-
- /* we suppose that the text insertion will be successful,
- clutter-text doesn't warn about it. A option would be search for
- the text, but it seems not really required */
- *position += length;
-}
-
-static void cally_text_delete_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (text);
- if (actor == NULL)
- return;
-
- if (!clutter_text_get_editable (CLUTTER_TEXT (actor)))
- return;
-
- clutter_text_delete_text (CLUTTER_TEXT (actor),
- start_pos, end_pos);
-}
-
-/* CallyActor */
-static void
-cally_text_notify_clutter (GObject *obj,
- GParamSpec *pspec)
-{
- ClutterText *clutter_text = NULL;
- CallyText *cally_text = NULL;
- AtkObject *atk_obj = NULL;
-
- clutter_text = CLUTTER_TEXT (obj);
- atk_obj = clutter_actor_get_accessible (CLUTTER_ACTOR (obj));
- cally_text = CALLY_TEXT (atk_obj);
-
- if (g_strcmp0 (pspec->name, "position") == 0)
- {
- /* the selection can change also for the cursor position */
- if (_check_for_selection_change (cally_text, clutter_text))
- g_signal_emit_by_name (atk_obj, "text_selection_changed");
-
- g_signal_emit_by_name (atk_obj, "text_caret_moved",
- clutter_text_get_cursor_position (clutter_text));
- }
- else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
- {
- if (_check_for_selection_change (cally_text, clutter_text))
- g_signal_emit_by_name (atk_obj, "text_selection_changed");
- }
- else if (g_strcmp0 (pspec->name, "editable") == 0)
- {
- atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE,
- clutter_text_get_editable (clutter_text));
- }
- else if (g_strcmp0 (pspec->name, "activatable") == 0)
- {
- _check_activate_action (cally_text, clutter_text);
- }
- else if (g_strcmp0 (pspec->name, "password-char") == 0)
- {
- if (clutter_text_get_password_char (clutter_text) != 0)
- atk_object_set_role (atk_obj, ATK_ROLE_PASSWORD_TEXT);
- else
- atk_object_set_role (atk_obj, ATK_ROLE_TEXT);
- }
- else
- {
- CALLY_ACTOR_CLASS (cally_text_parent_class)->notify_clutter (obj, pspec);
- }
-}
-
-static gboolean
-_check_for_selection_change (CallyText *cally_text,
- ClutterText *clutter_text)
-{
- gboolean ret_val = FALSE;
- gint clutter_pos = -1;
- gint clutter_bound = -1;
-
- clutter_pos = clutter_text_get_cursor_position (clutter_text);
- clutter_bound = clutter_text_get_selection_bound (clutter_text);
-
- if (clutter_pos != clutter_bound)
- {
- if (clutter_pos != cally_text->priv->cursor_position ||
- clutter_bound != cally_text->priv->selection_bound)
- /*
- * This check is here as this function can be called for
- * notification of selection_bound and current_pos. The
- * values of current_pos and selection_bound may be the same
- * for both notifications and we only want to generate one
- * text_selection_changed signal.
- */
- ret_val = TRUE;
- }
- else
- {
- /* We had a selection */
- ret_val = (cally_text->priv->cursor_position != cally_text->priv->selection_bound);
- }
-
- cally_text->priv->cursor_position = clutter_pos;
- cally_text->priv->selection_bound = clutter_bound;
-
- return ret_val;
-}
-
-static gboolean
-_idle_notify_insert (gpointer data)
-{
- CallyText *cally_text = NULL;
-
- cally_text = CALLY_TEXT (data);
- cally_text->priv->insert_idle_handler = 0;
-
- _notify_insert (cally_text);
-
- return FALSE;
-}
-
-static void
-_notify_insert (CallyText *cally_text)
-{
- if (cally_text->priv->signal_name_insert)
- {
- g_signal_emit_by_name (cally_text,
- cally_text->priv->signal_name_insert,
- cally_text->priv->position_insert,
- cally_text->priv->length_insert);
- cally_text->priv->signal_name_insert = NULL;
- }
-}
-
-static void
-_notify_delete (CallyText *cally_text)
-{
- if (cally_text->priv->signal_name_delete)
- {
- g_signal_emit_by_name (cally_text,
- cally_text->priv->signal_name_delete,
- cally_text->priv->position_delete,
- cally_text->priv->length_delete);
- cally_text->priv->signal_name_delete = NULL;
- }
-}
-/* atkaction */
-
-static void
-_cally_text_activate_action (CallyActor *cally_actor)
-{
- ClutterActor *actor = NULL;
-
- actor = CALLY_GET_CLUTTER_ACTOR (cally_actor);
-
- clutter_text_activate (CLUTTER_TEXT (actor));
-}
-
-static void
-_check_activate_action (CallyText *cally_text,
- ClutterText *clutter_text)
-{
-
- if (clutter_text_get_activatable (clutter_text))
- {
- if (cally_text->priv->activate_action_id != 0)
- return;
-
- cally_text->priv->activate_action_id = cally_actor_add_action (CALLY_ACTOR (cally_text),
- "activate", NULL, NULL,
- _cally_text_activate_action);
- }
- else
- {
- if (cally_text->priv->activate_action_id == 0)
- return;
-
- if (cally_actor_remove_action (CALLY_ACTOR (cally_text),
- cally_text->priv->activate_action_id))
- {
- cally_text->priv->activate_action_id = 0;
- }
- }
-}
-
-/* GailTextUtil/GailMisc reimplementation methods */
-
-/**
- * _cally_misc_add_attribute:
- *
- * Reimplementation of gail_misc_layout_get_run_attributes (check this
- * function for more documentation).
- *
- * Returns: A pointer to the new #AtkAttributeSet.
- **/
-static AtkAttributeSet*
-_cally_misc_add_attribute (AtkAttributeSet *attrib_set,
- AtkTextAttribute attr,
- gchar *value)
-{
- AtkAttributeSet *return_set;
- AtkAttribute *at = g_malloc (sizeof (AtkAttribute));
- at->name = g_strdup (atk_text_attribute_get_name (attr));
- at->value = value;
- return_set = g_slist_prepend(attrib_set, at);
- return return_set;
-}
-
-
-static gint
-_cally_atk_attribute_lookup_func (gconstpointer data,
- gconstpointer user_data)
-{
- AtkTextAttribute attr = (AtkTextAttribute) GPOINTER_TO_INT (user_data);
- AtkAttribute *at = (AtkAttribute *) data;
- if (!g_strcmp0 (at->name, atk_text_attribute_get_name (attr)))
- return 0;
- return -1;
-}
-
-static gboolean
-_cally_misc_find_atk_attribute (AtkAttributeSet *attrib_set,
- AtkTextAttribute attr)
-{
- GSList* result = g_slist_find_custom ((GSList*) attrib_set,
- (gconstpointer) attr,
- _cally_atk_attribute_lookup_func);
- return (result != NULL);
-}
-
-/**
- * _cally_misc_layout_atk_attributes_from_pango:
- *
- * Store the pango attributes as their ATK equivalent in an existing
- * #AtkAttributeSet.
- *
- * Returns: A pointer to the updated #AtkAttributeSet.
- **/
-static AtkAttributeSet*
-_cally_misc_layout_atk_attributes_from_pango (AtkAttributeSet *attrib_set,
- PangoAttrIterator *iter)
-{
- PangoAttrString *pango_string;
- PangoAttrInt *pango_int;
- PangoAttrColor *pango_color;
- PangoAttrLanguage *pango_lang;
- PangoAttrFloat *pango_float;
- gchar *value = NULL;
-
- if ((pango_string = (PangoAttrString*) pango_attr_iterator_get (iter,
- PANGO_ATTR_FAMILY)) != NULL)
- {
- value = g_strdup_printf("%s", pango_string->value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_FAMILY_NAME,
- value);
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_STYLE)) != NULL)
- {
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_STYLE,
- g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, pango_int->value)));
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_WEIGHT)) != NULL)
- {
- value = g_strdup_printf("%i", pango_int->value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_WEIGHT,
- value);
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_VARIANT)) != NULL)
- {
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_VARIANT,
- g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, pango_int->value)));
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_STRETCH)) != NULL)
- {
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_STRETCH,
- g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, pango_int->value)));
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_SIZE)) != NULL)
- {
- value = g_strdup_printf("%i", pango_int->value / PANGO_SCALE);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_SIZE,
- value);
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_UNDERLINE)) != NULL)
- {
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_UNDERLINE,
- g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE, pango_int->value)));
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_STRIKETHROUGH)) != NULL)
- {
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_STRIKETHROUGH,
- g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH, pango_int->value)));
- }
- if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter,
- PANGO_ATTR_RISE)) != NULL)
- {
- value = g_strdup_printf("%i", pango_int->value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_RISE,
- value);
- }
- if ((pango_lang = (PangoAttrLanguage*) pango_attr_iterator_get (iter,
- PANGO_ATTR_LANGUAGE)) != NULL)
- {
- value = g_strdup( pango_language_to_string( pango_lang->value));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_LANGUAGE,
- value);
- }
- if ((pango_float = (PangoAttrFloat*) pango_attr_iterator_get (iter,
- PANGO_ATTR_SCALE)) != NULL)
- {
- value = g_strdup_printf("%g", pango_float->value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_SCALE,
- value);
- }
- if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter,
- PANGO_ATTR_FOREGROUND)) != NULL)
- {
- value = g_strdup_printf ("%u,%u,%u",
- pango_color->color.red,
- pango_color->color.green,
- pango_color->color.blue);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_FG_COLOR,
- value);
- }
- if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter,
- PANGO_ATTR_BACKGROUND)) != NULL)
- {
- value = g_strdup_printf ("%u,%u,%u",
- pango_color->color.red,
- pango_color->color.green,
- pango_color->color.blue);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_BG_COLOR,
- value);
- }
-
- return attrib_set;
-}
-
-static AtkAttributeSet*
-_cally_misc_add_actor_color_to_attribute_set (AtkAttributeSet *attrib_set,
- ClutterText *clutter_text)
-{
- ClutterColor color;
- gchar *value;
-
- clutter_text_get_color (clutter_text, &color);
- value = g_strdup_printf ("%u,%u,%u",
- (guint) (color.red * 65535 / 255),
- (guint) (color.green * 65535 / 255),
- (guint) (color.blue * 65535 / 255));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_FG_COLOR,
- value);
- return attrib_set;
-}
-
-
-/**
- * _cally_misc_layout_get_run_attributes:
- *
- * Reimplementation of gail_misc_layout_get_run_attributes (check this
- * function for more documentation).
- *
- * Returns: A pointer to the #AtkAttributeSet.
- **/
-static AtkAttributeSet*
-_cally_misc_layout_get_run_attributes (AtkAttributeSet *attrib_set,
- ClutterText *clutter_text,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- PangoAttrIterator *iter;
- PangoAttrList *attr;
- gint index, start_index, end_index;
- gboolean is_next = TRUE;
- glong len;
- PangoLayout *layout = clutter_text_get_layout (clutter_text);
- gchar *text = (gchar*) clutter_text_get_text (clutter_text);
-
- len = g_utf8_strlen (text, -1);
- /* Grab the attributes of the PangoLayout, if any */
- if ((attr = pango_layout_get_attributes (layout)) == NULL)
- {
- *start_offset = 0;
- *end_offset = len;
- _cally_misc_add_actor_color_to_attribute_set (attrib_set, clutter_text);
- }
- else
- {
- iter = pango_attr_list_get_iterator (attr);
- /* Get invariant range offsets */
- /* If offset out of range, set offset in range */
- if (offset > len)
- offset = len;
- else if (offset < 0)
- offset = 0;
-
- index = g_utf8_offset_to_pointer (text, offset) - text;
- pango_attr_iterator_range (iter, &start_index, &end_index);
- while (is_next)
- {
- if (index >= start_index && index < end_index)
- {
- *start_offset = g_utf8_pointer_to_offset (text,
- text + start_index);
- if (end_index == G_MAXINT)
- /* Last iterator */
- end_index = len;
-
- *end_offset = g_utf8_pointer_to_offset (text,
- text + end_index);
- break;
- }
- is_next = pango_attr_iterator_next (iter);
- pango_attr_iterator_range (iter, &start_index, &end_index);
- }
-
- /* Get attributes */
- attrib_set = _cally_misc_layout_atk_attributes_from_pango (attrib_set, iter);
- pango_attr_iterator_destroy (iter);
- }
-
- if (!_cally_misc_find_atk_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR))
- attrib_set = _cally_misc_add_actor_color_to_attribute_set (attrib_set, clutter_text);
-
- return attrib_set;
-}
-
-
-/**
- * _cally_misc_layout_get_default_attributes:
- *
- * Reimplementation of gail_misc_layout_get_default_attributes (check this
- * function for more documentation).
- *
- * Returns: A pointer to the #AtkAttributeSet.
- **/
-static AtkAttributeSet*
-_cally_misc_layout_get_default_attributes (AtkAttributeSet *attrib_set,
- ClutterText *clutter_text)
-{
- PangoLayout *layout;
- PangoContext *context;
- PangoLanguage* language;
- PangoFontDescription* font;
- PangoWrapMode mode;
- gchar *value = NULL;
- gint int_value;
- ClutterTextDirection text_direction;
- PangoAttrIterator *iter;
- PangoAttrList *attr;
-
- text_direction = clutter_actor_get_text_direction (CLUTTER_ACTOR (clutter_text));
- switch (text_direction)
- {
- case CLUTTER_TEXT_DIRECTION_DEFAULT:
- value = g_strdup ("none");
- break;
-
- case CLUTTER_TEXT_DIRECTION_LTR:
- value = g_strdup ("ltr");
- break;
-
- case CLUTTER_TEXT_DIRECTION_RTL:
- value = g_strdup ("rtl");
- break;
-
- default:
- value = g_strdup ("none");
- break;
- }
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_DIRECTION,
- value);
-
- layout = clutter_text_get_layout (clutter_text);
- context = pango_layout_get_context (layout);
- if (context)
- {
- if ((language = pango_context_get_language (context)))
- {
- value = g_strdup (pango_language_to_string (language));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_LANGUAGE, value);
- }
-
- if ((font = pango_context_get_font_description (context)))
- {
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE,
- pango_font_description_get_style (font)));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_STYLE,
- value);
-
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT,
- pango_font_description_get_variant (font)));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_VARIANT, value);
-
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH,
- pango_font_description_get_stretch (font)));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_STRETCH, value);
-
- value = g_strdup (pango_font_description_get_family (font));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_FAMILY_NAME, value);
- value = g_strdup_printf ("%d", pango_font_description_get_weight (font));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_WEIGHT, value);
-
- value = g_strdup_printf ("%i", pango_font_description_get_size (font) / PANGO_SCALE);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_SIZE, value);
-
- }
-
- }
-
- if (pango_layout_get_justify (layout))
- int_value = 3;
- else
- {
- PangoAlignment align;
-
- align = pango_layout_get_alignment (layout);
- if (align == PANGO_ALIGN_LEFT)
- int_value = 0;
- else if (align == PANGO_ALIGN_CENTER)
- int_value = 2;
- else /* if (align == PANGO_ALIGN_RIGHT) */
- int_value = 1;
- }
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION,
- int_value));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_JUSTIFICATION,
- value);
-
- mode = pango_layout_get_wrap (layout);
- if (mode == PANGO_WRAP_WORD)
- int_value = 2;
- else /* if (mode == PANGO_WRAP_CHAR) */
- int_value = 1;
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_WRAP_MODE,
- int_value));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_WRAP_MODE, value);
-
- if ((attr = clutter_text_get_attributes (clutter_text)))
- {
- iter = pango_attr_list_get_iterator (attr);
- /* Get attributes */
- attrib_set = _cally_misc_layout_atk_attributes_from_pango (attrib_set, iter);
- pango_attr_iterator_destroy (iter);
- }
-
-
- if (!_cally_misc_find_atk_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR))
- attrib_set = _cally_misc_add_actor_color_to_attribute_set (attrib_set,
- clutter_text);
-
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_FG_STIPPLE, 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_FG_STIPPLE,
- value);
-
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_BG_STIPPLE, 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_BG_STIPPLE,
- value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_BG_FULL_HEIGHT,
- g_strdup_printf ("%i", 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP,
- g_strdup_printf ("%i", 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
- g_strdup_printf ("%i", 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
- g_strdup_printf ("%i", 0));
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE,
- clutter_text_get_editable (clutter_text)));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_EDITABLE,
- value);
-
- value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_INVISIBLE,
- !clutter_actor_is_visible (CLUTTER_ACTOR (clutter_text))));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_INVISIBLE, value);
-
- value = g_strdup_printf ("%i", pango_layout_get_indent (layout));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_INDENT, value);
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_RIGHT_MARGIN,
- g_strdup_printf ("%i", 0));
- attrib_set = _cally_misc_add_attribute (attrib_set,
- ATK_TEXT_ATTR_LEFT_MARGIN,
- g_strdup_printf ("%i", 0));
-
- return attrib_set;
-}
-
-static int
-_cally_misc_get_index_at_point (ClutterText *clutter_text,
- gint x,
- gint y,
- AtkCoordType coords)
-{
- gint index, x_window, y_window, x_toplevel, y_toplevel;
- gint x_temp, y_temp;
- gboolean ret;
- graphene_point3d_t verts[4];
- PangoLayout *layout;
- gint x_layout, y_layout;
-
- clutter_text_get_layout_offsets (clutter_text, &x_layout, &y_layout);
-
- clutter_actor_get_abs_allocation_vertices (CLUTTER_ACTOR (clutter_text), verts);
- x_window = verts[0].x;
- y_window = verts[0].y;
-
- x_temp = x - x_layout - x_window;
- y_temp = y - y_layout - y_window;
-
- if (coords == ATK_XY_SCREEN)
- {
- _cally_actor_get_top_level_origin (CLUTTER_ACTOR (clutter_text), &x_toplevel,
- &y_toplevel);
- x_temp -= x_toplevel;
- y_temp -= y_toplevel;
- }
-
- layout = clutter_text_get_layout (clutter_text);
- 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;
- }
- return index;
-}