mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
a11y: implementation for atk_text_get_text_[before/at/after]_offset
Copy and paste of the implementation done at Gtk+ based on pango. This should be moved to a common library, like the old GailTextUtil. Ideally on pango itself. https://bugzilla.gnome.org/show_bug.cgi?id=677221
This commit is contained in:
parent
a571c2933b
commit
dd7c1ed64a
@ -8,6 +8,10 @@
|
||||
* 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
|
||||
@ -368,6 +372,706 @@ cally_text_ref_state_set (AtkObject *obj)
|
||||
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 ******/
|
||||
|
||||
@ -449,28 +1153,14 @@ cally_text_get_text_before_offset (AtkText *text,
|
||||
gint *end_offset)
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
#if 0
|
||||
ClutterText *clutter_text = NULL;
|
||||
CallyText *cally_text = NULL;
|
||||
#endif
|
||||
|
||||
actor = CALLY_GET_CLUTTER_ACTOR (text);
|
||||
if (actor == NULL) /* State is defunct */
|
||||
return NULL;
|
||||
|
||||
#if 0
|
||||
clutter_text = CLUTTER_TEXT (actor);
|
||||
cally_text = CALLY_TEXT (text);
|
||||
|
||||
return gail_text_util_get_text (cally_text->priv->textutil,
|
||||
clutter_text_get_layout (clutter_text),
|
||||
GAIL_BEFORE_OFFSET,
|
||||
boundary_type,
|
||||
offset,
|
||||
return _gtk_pango_get_text_before (clutter_text_get_layout (CLUTTER_TEXT (actor)),
|
||||
boundary_type, offset,
|
||||
start_offset, end_offset);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
@ -481,28 +1171,14 @@ cally_text_get_text_at_offset (AtkText *text,
|
||||
gint *end_offset)
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
#if 0
|
||||
ClutterText *clutter_text = NULL;
|
||||
CallyText *cally_text = NULL;
|
||||
#endif
|
||||
|
||||
actor = CALLY_GET_CLUTTER_ACTOR (text);
|
||||
if (actor == NULL) /* State is defunct */
|
||||
return NULL;
|
||||
|
||||
#if 0
|
||||
clutter_text = CLUTTER_TEXT (actor);
|
||||
cally_text = CALLY_TEXT (text);
|
||||
|
||||
return gail_text_util_get_text (cally_text->priv->textutil,
|
||||
clutter_text_get_layout (clutter_text),
|
||||
GAIL_AT_OFFSET,
|
||||
boundary_type,
|
||||
offset,
|
||||
return _gtk_pango_get_text_at (clutter_text_get_layout (CLUTTER_TEXT (actor)),
|
||||
boundary_type, offset,
|
||||
start_offset, end_offset);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
@ -513,28 +1189,14 @@ cally_text_get_text_after_offset (AtkText *text,
|
||||
gint *end_offset)
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
#if 0
|
||||
ClutterText *clutter_text = NULL;
|
||||
CallyText *cally_text = NULL;
|
||||
#endif
|
||||
|
||||
actor = CALLY_GET_CLUTTER_ACTOR (text);
|
||||
if (actor == NULL) /* State is defunct */
|
||||
return NULL;
|
||||
|
||||
#if 0
|
||||
clutter_text = CLUTTER_TEXT (actor);
|
||||
cally_text = CALLY_TEXT (text);
|
||||
|
||||
return gail_text_util_get_text (cally_text->priv->textutil,
|
||||
clutter_text_get_layout (clutter_text),
|
||||
GAIL_AFTER_OFFSET,
|
||||
boundary_type,
|
||||
offset,
|
||||
return _gtk_pango_get_text_after (clutter_text_get_layout (CLUTTER_TEXT (actor)),
|
||||
boundary_type, offset,
|
||||
start_offset, end_offset);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gint
|
||||
|
Loading…
Reference in New Issue
Block a user