gtk/tests/a11y/text.c
Benjamin Otte 87c33fa21a tests: Update text test for textview
1) Allow inserting text to move the cursor to after the inserted text
2) Implement selecting text for GtkTextView. Also assert if it's an
   unsupported widget type.
3) Select an inside part of the widget, not the end.
2011-07-06 16:50:09 +02:00

754 lines
24 KiB
C

/*
* Copyright (C) 2011 Red Hat Inc.
*
* Author:
* Matthias Clasen <mclasen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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 <gtk/gtk.h>
#include <string.h>
static void
set_text (GtkWidget *widget,
const gchar *text)
{
if (GTK_IS_LABEL (widget))
gtk_label_set_text (GTK_LABEL (widget), text);
else if (GTK_IS_ENTRY (widget))
gtk_entry_set_text (GTK_ENTRY (widget), text);
else if (GTK_IS_TEXT_VIEW (widget))
gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget)), text, -1);
else
g_assert_not_reached ();
}
static void
test_basic (GtkWidget *widget)
{
AtkText *atk_text;
const gchar *text = "Text goes here";
gchar *ret;
gint count;
gunichar c;
atk_text = ATK_TEXT (gtk_widget_get_accessible (widget));
set_text (widget, text);
ret = atk_text_get_text (atk_text, 5, 9);
g_assert_cmpstr (ret, ==, "goes");
g_free (ret);
ret = atk_text_get_text (atk_text, 0, 14);
g_assert_cmpstr (ret, ==, text);
g_free (ret);
ret = atk_text_get_text (atk_text, 0, -1);
g_assert_cmpstr (ret, ==, text);
g_free (ret);
count = atk_text_get_character_count (atk_text);
g_assert_cmpint (count, ==, g_utf8_strlen (text, -1));
c = atk_text_get_character_at_offset (atk_text, 0);
g_assert_cmpint (c, ==, 'T');
c = atk_text_get_character_at_offset (atk_text, 13);
g_assert_cmpint (c, ==, 'e');
}
typedef struct {
gint count;
gint position;
gint length;
} SignalData;
static void
text_deleted (AtkText *atk_text, gint position, gint length, SignalData *data)
{
data->count++;
data->position = position;
data->length = length;
}
static void
text_inserted (AtkText *atk_text, gint position, gint length, SignalData *data)
{
data->count++;
data->position = position;
data->length = length;
}
static void
test_text_changed (GtkWidget *widget)
{
AtkText *atk_text;
const gchar *text = "Text goes here";
const gchar *text2 = "Text again";
SignalData delete_data;
SignalData insert_data;
atk_text = ATK_TEXT (gtk_widget_get_accessible (widget));
delete_data.count = 0;
insert_data.count = 0;
g_signal_connect (atk_text, "text_changed::delete",
G_CALLBACK (text_deleted), &delete_data);
g_signal_connect (atk_text, "text_changed::insert",
G_CALLBACK (text_inserted), &insert_data);
set_text (widget, text);
g_assert_cmpint (delete_data.count, ==, 0);
g_assert_cmpint (insert_data.count, ==, 1);
g_assert_cmpint (insert_data.position, ==, 0);
g_assert_cmpint (insert_data.length, ==, g_utf8_strlen (text, -1));
set_text (widget, text2);
g_assert_cmpint (delete_data.count, ==, 1);
g_assert_cmpint (delete_data.position, ==, 0);
g_assert_cmpint (delete_data.length, ==, g_utf8_strlen (text, -1));
g_assert_cmpint (insert_data.count, ==, 2);
g_assert_cmpint (insert_data.position, ==, 0);
g_assert_cmpint (insert_data.length, ==, g_utf8_strlen (text2, -1));
set_text (widget, "");
g_assert_cmpint (delete_data.count, ==, 2);
g_assert_cmpint (delete_data.position, ==, 0);
g_assert_cmpint (delete_data.length, ==, g_utf8_strlen (text2, -1));
g_assert_cmpint (insert_data.count, ==, 2);
g_signal_handlers_disconnect_by_func (atk_text, G_CALLBACK (text_deleted), &delete_data);
g_signal_handlers_disconnect_by_func (atk_text, G_CALLBACK (text_inserted), &insert_data);
}
typedef struct {
gint gravity;
gint offset;
AtkTextBoundary boundary;
gint start;
gint end;
const gchar *word;
} Word;
#ifdef DUMP_RESULTS
static const gchar *
boundary (AtkTextBoundary b)
{
switch (b)
{
case ATK_TEXT_BOUNDARY_CHAR: return "ATK_TEXT_BOUNDARY_CHAR, ";
case ATK_TEXT_BOUNDARY_WORD_START: return "ATK_TEXT_BOUNDARY_WORD_START, ";
case ATK_TEXT_BOUNDARY_WORD_END: return "ATK_TEXT_BOUNDARY_WORD_END, ";
case ATK_TEXT_BOUNDARY_SENTENCE_START: return "ATK_TEXT_BOUNDARY_SENTENCE_START,";
case ATK_TEXT_BOUNDARY_SENTENCE_END: return "ATK_TEXT_BOUNDARY_SENTENCE_END, ";
case ATK_TEXT_BOUNDARY_LINE_START: return "ATK_TEXT_BOUNDARY_LINE_START, ";
case ATK_TEXT_BOUNDARY_LINE_END: return "ATK_TEXT_BOUNDARY_LINE_END, ";
default: g_assert_not_reached ();
}
}
static const gchar *
gravity (gint g)
{
if (g < 0) return "before";
else if (g > 0) return "after";
else return "around";
}
const gchar *
char_rep (gunichar c)
{
static gchar out[6];
switch (c)
{
case '\n': return "\\n";
case 196: return "?";
case 214: return "?";
case 220: return "?";
default:
memset (out, 0, 6);
g_unichar_to_utf8 (c, out);
return out;
}
}
gchar *
escape (const gchar *p)
{
GString *s;
s = g_string_new ("");
while (*p)
{
if (*p == '\n')
g_string_append (s, "\\n");
else
g_string_append_c (s, *p);
p++;
}
return g_string_free (s, FALSE);
}
#endif
#ifdef SHOW_TEXT_ATTRIBUTES
static void
show_text_attributes (PangoLayout *l)
{
const PangoLogAttr *attr;
gint n_attrs;
const gchar *s;
gchar e;
const gchar *p;
gint i;
const gchar *text;
GSList *lines, *li;
glong so, eo;
printf ("\n");
text = pango_layout_get_text (l);
attr = pango_layout_get_log_attrs_readonly (l, &n_attrs);
p = text;
while (*p)
{
s = char_rep (g_utf8_get_char (p));
printf (" %s", s);
p = g_utf8_next_char (p);
}
printf ("\n");
p = text;
i = 0;
do
{
if (*p)
s = char_rep (g_utf8_get_char (p));
else
s = "";
if (attr[i].is_word_start && attr[i].is_word_end)
e = '|';
else if (attr[i].is_word_start)
e = '<';
else if (attr[i].is_word_end)
e = '>';
else
e = ' ';
printf ("%c%*s", e, strlen (s), "");
if (*p)
p = g_utf8_next_char (p);
i++;
}
while (*p || i < n_attrs);
printf ("\n");
p = text;
i = 0;
do
{
if (*p)
s = char_rep (g_utf8_get_char (p));
else
s = "";
if (attr[i].is_sentence_start && attr[i].is_sentence_end)
e = '|';
else if (attr[i].is_sentence_start)
e = '<';
else if (attr[i].is_sentence_end)
e = '>';
else
e = ' ';
printf ("%c%*s", e, strlen (s), "");
if (*p)
p = g_utf8_next_char (p);
i++;
}
while (*p || i < n_attrs);
printf ("\n");
lines = pango_layout_get_lines_readonly (l);
p = text;
i = 0;
do
{
gboolean start, end;
if (*p)
s = char_rep (g_utf8_get_char (p));
else
s = "";
start = end = FALSE;
for (li = lines; li; li = li->next)
{
PangoLayoutLine *line = li->data;
so = g_utf8_pointer_to_offset (text, text + line->start_index);
eo = g_utf8_pointer_to_offset (text, text + line->start_index + line->length);
if (so == i)
start = TRUE;
if (eo == i)
end = TRUE;
}
if (start && end)
e = '|';
else if (start)
e = '<';
else if (end)
e = '>';
else
e = ' ';
printf ("%c%*s", e, strlen (s), "");
if (*p)
p = g_utf8_next_char (p);
i++;
}
while (*p || i < n_attrs);
printf ("\n");
}
#endif
static void
test_words (GtkWidget *widget)
{
AtkText *atk_text;
const gchar *text = "abc! def\nghi jkl\nmno";
Word expected[] = {
{ -1, 0, ATK_TEXT_BOUNDARY_CHAR, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_CHAR, 0, 1, "a" },
{ -1, 2, ATK_TEXT_BOUNDARY_CHAR, 1, 2, "b" },
{ -1, 3, ATK_TEXT_BOUNDARY_CHAR, 2, 3, "c" },
{ -1, 4, ATK_TEXT_BOUNDARY_CHAR, 3, 4, "!" },
{ -1, 5, ATK_TEXT_BOUNDARY_CHAR, 4, 5, " " },
{ -1, 6, ATK_TEXT_BOUNDARY_CHAR, 5, 6, "d" },
{ -1, 7, ATK_TEXT_BOUNDARY_CHAR, 6, 7, "e" },
{ -1, 8, ATK_TEXT_BOUNDARY_CHAR, 7, 8, "f" },
{ -1, 9, ATK_TEXT_BOUNDARY_CHAR, 8, 9, "\n" },
{ -1, 10, ATK_TEXT_BOUNDARY_CHAR, 9, 10, "g" },
{ -1, 11, ATK_TEXT_BOUNDARY_CHAR, 10, 11, "h" },
{ -1, 12, ATK_TEXT_BOUNDARY_CHAR, 11, 12, "i" },
{ -1, 13, ATK_TEXT_BOUNDARY_CHAR, 12, 13, " " },
{ -1, 14, ATK_TEXT_BOUNDARY_CHAR, 13, 14, "j" },
{ -1, 15, ATK_TEXT_BOUNDARY_CHAR, 14, 15, "k" },
{ -1, 16, ATK_TEXT_BOUNDARY_CHAR, 15, 16, "l" },
{ -1, 17, ATK_TEXT_BOUNDARY_CHAR, 16, 17, "\n" },
{ -1, 18, ATK_TEXT_BOUNDARY_CHAR, 17, 18, "m" },
{ -1, 19, ATK_TEXT_BOUNDARY_CHAR, 18, 19, "n" },
{ -1, 20, ATK_TEXT_BOUNDARY_CHAR, 19, 20, "o" },
{ -1, 0, ATK_TEXT_BOUNDARY_WORD_START, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_WORD_START, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_WORD_START, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_WORD_START, 0, 0, "" },
{ -1, 4, ATK_TEXT_BOUNDARY_WORD_START, 0, 0, "" },
{ -1, 5, ATK_TEXT_BOUNDARY_WORD_START, 0, 5, "abc! " },
{ -1, 6, ATK_TEXT_BOUNDARY_WORD_START, 0, 5, "abc! " },
{ -1, 7, ATK_TEXT_BOUNDARY_WORD_START, 0, 5, "abc! " },
{ -1, 8, ATK_TEXT_BOUNDARY_WORD_START, 0, 5, "abc! " },
{ -1, 9, ATK_TEXT_BOUNDARY_WORD_START, 5, 9, "def\n" },
{ -1, 10, ATK_TEXT_BOUNDARY_WORD_START, 5, 9, "def\n" },
{ -1, 11, ATK_TEXT_BOUNDARY_WORD_START, 5, 9, "def\n" },
{ -1, 12, ATK_TEXT_BOUNDARY_WORD_START, 5, 9, "def\n" },
{ -1, 13, ATK_TEXT_BOUNDARY_WORD_START, 9, 13, "ghi " },
{ -1, 14, ATK_TEXT_BOUNDARY_WORD_START, 9, 13, "ghi " },
{ -1, 15, ATK_TEXT_BOUNDARY_WORD_START, 9, 13, "ghi " },
{ -1, 16, ATK_TEXT_BOUNDARY_WORD_START, 9, 13, "ghi " },
{ -1, 17, ATK_TEXT_BOUNDARY_WORD_START, 13, 17, "jkl\n" },
{ -1, 18, ATK_TEXT_BOUNDARY_WORD_START, 13, 17, "jkl\n" },
{ -1, 19, ATK_TEXT_BOUNDARY_WORD_START, 13, 17, "jkl\n" },
{ -1, 20, ATK_TEXT_BOUNDARY_WORD_START, 13, 17, "jkl\n" },
{ -1, 0, ATK_TEXT_BOUNDARY_WORD_END, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_WORD_END, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_WORD_END, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_WORD_END, 0, 3, "abc" },
{ -1, 4, ATK_TEXT_BOUNDARY_WORD_END, 0, 3, "abc" },
{ -1, 5, ATK_TEXT_BOUNDARY_WORD_END, 0, 3, "abc" },
{ -1, 6, ATK_TEXT_BOUNDARY_WORD_END, 0, 3, "abc" },
{ -1, 7, ATK_TEXT_BOUNDARY_WORD_END, 0, 3, "abc" },
{ -1, 8, ATK_TEXT_BOUNDARY_WORD_END, 3, 8, "! def" },
{ -1, 9, ATK_TEXT_BOUNDARY_WORD_END, 3, 8, "! def" },
{ -1, 10, ATK_TEXT_BOUNDARY_WORD_END, 3, 8, "! def" },
{ -1, 11, ATK_TEXT_BOUNDARY_WORD_END, 3, 8, "! def" },
{ -1, 12, ATK_TEXT_BOUNDARY_WORD_END, 8, 12, "\nghi" },
{ -1, 13, ATK_TEXT_BOUNDARY_WORD_END, 8, 12, "\nghi" },
{ -1, 14, ATK_TEXT_BOUNDARY_WORD_END, 8, 12, "\nghi" },
{ -1, 15, ATK_TEXT_BOUNDARY_WORD_END, 8, 12, "\nghi" },
{ -1, 16, ATK_TEXT_BOUNDARY_WORD_END, 12, 16, " jkl" },
{ -1, 17, ATK_TEXT_BOUNDARY_WORD_END, 12, 16, " jkl" },
{ -1, 18, ATK_TEXT_BOUNDARY_WORD_END, 12, 16, " jkl" },
{ -1, 19, ATK_TEXT_BOUNDARY_WORD_END, 12, 16, " jkl" },
{ -1, 20, ATK_TEXT_BOUNDARY_WORD_END, 16, 20, "\nmno" },
{ -1, 0, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 0, "" },
{ -1, 4, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 0, "" },
{ -1, 5, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 5, "abc! " },
{ -1, 6, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 5, "abc! " },
{ -1, 7, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 5, "abc! " },
{ -1, 8, ATK_TEXT_BOUNDARY_SENTENCE_START, 0, 5, "abc! " },
{ -1, 9, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 10, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 11, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 12, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 13, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 14, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 15, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 16, ATK_TEXT_BOUNDARY_SENTENCE_START, 5, 9, "def\n" },
{ -1, 17, ATK_TEXT_BOUNDARY_SENTENCE_START, 9, 17, "ghi jkl\n" },
{ -1, 18, ATK_TEXT_BOUNDARY_SENTENCE_START, 9, 17, "ghi jkl\n" },
{ -1, 19, ATK_TEXT_BOUNDARY_SENTENCE_START, 9, 17, "ghi jkl\n" },
{ -1, 20, ATK_TEXT_BOUNDARY_SENTENCE_START, 9, 17, "ghi jkl\n" },
{ -1, 0, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 0, "" },
{ -1, 4, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 4, "abc!" },
{ -1, 5, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 4, "abc!" },
{ -1, 6, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 4, "abc!" },
{ -1, 7, ATK_TEXT_BOUNDARY_SENTENCE_END, 0, 4, "abc!" },
{ -1, 8, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 9, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 10, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 11, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 12, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 13, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 14, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 15, ATK_TEXT_BOUNDARY_SENTENCE_END, 4, 8, " def" },
{ -1, 16, ATK_TEXT_BOUNDARY_SENTENCE_END, 8, 16, "\nghi jkl" },
{ -1, 17, ATK_TEXT_BOUNDARY_SENTENCE_END, 8, 16, "\nghi jkl" },
{ -1, 18, ATK_TEXT_BOUNDARY_SENTENCE_END, 8, 16, "\nghi jkl" },
{ -1, 19, ATK_TEXT_BOUNDARY_SENTENCE_END, 8, 16, "\nghi jkl" },
{ -1, 20, ATK_TEXT_BOUNDARY_SENTENCE_END, 16, 20, "\nmno" },
{ -1, 0, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 4, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 5, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 6, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 7, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 8, ATK_TEXT_BOUNDARY_LINE_START, 0, 0, "" },
{ -1, 9, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 10, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 11, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 12, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 13, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 14, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 15, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 16, ATK_TEXT_BOUNDARY_LINE_START, 0, 9, "abc! def\n" },
{ -1, 17, ATK_TEXT_BOUNDARY_LINE_START, 9, 17, "ghi jkl\n" },
{ -1, 18, ATK_TEXT_BOUNDARY_LINE_START, 9, 17, "ghi jkl\n" },
{ -1, 19, ATK_TEXT_BOUNDARY_LINE_START, 9, 17, "ghi jkl\n" },
{ -1, 20, ATK_TEXT_BOUNDARY_LINE_START, 9, 17, "ghi jkl\n" },
{ -1, 0, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 1, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 2, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 3, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 4, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 5, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 6, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 7, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 8, ATK_TEXT_BOUNDARY_LINE_END, 0, 0, "" },
{ -1, 9, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 10, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 11, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 12, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 13, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 14, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 15, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 16, ATK_TEXT_BOUNDARY_LINE_END, 0, 8, "abc! def" },
{ -1, 17, ATK_TEXT_BOUNDARY_LINE_END, 8, 16, "\nghi jkl" },
{ -1, 18, ATK_TEXT_BOUNDARY_LINE_END, 8, 16, "\nghi jkl" },
{ -1, 19, ATK_TEXT_BOUNDARY_LINE_END, 8, 16, "\nghi jkl" },
{ -1, 20, ATK_TEXT_BOUNDARY_LINE_END, 8, 16, "\nghi jkl" },
{ 0, -1, }
};
gint start, end;
gchar *word;
gint i;
atk_text = ATK_TEXT (gtk_widget_get_accessible (widget));
set_text (widget, text);
#ifdef SHOW_TEXT_ATTRIBUTES
if (GTK_IS_LABEL (widget))
show_text_attributes (gtk_label_get_layout (GTK_LABEL (widget)));
else if (GTK_IS_ENTRY (widget))
show_text_attributes (gtk_entry_get_layout (GTK_ENTRY (widget)));
#endif
#if DUMP_RESULTS
for (i = -1; i < 2; i++)
{
gint j, k;
for (j = ATK_TEXT_BOUNDARY_CHAR; j <= ATK_TEXT_BOUNDARY_LINE_END; j++)
for (k = 0; k <= strlen (text); k++)
{
switch (i)
{
case -1:
word = atk_text_get_text_before_offset (atk_text, k, j, &start, &end);
break;
case 0:
word = atk_text_get_text_at_offset (atk_text, k, j, &start, &end);
break;
case 1:
word = atk_text_get_text_after_offset (atk_text, k, j, &start, &end);
break;
default:
g_assert_not_reached ();
break;
}
printf (" { %2d, %2d, %s %2d, %2d, \"%s\" },\n", i, k, boundary(j), start, end, escape (word));
g_free (word);
}
}
#endif
for (i = 0; expected[i].offset != -1; i++)
{
if (GTK_IS_ENTRY (widget))
{
/* GtkEntry sets single-paragraph mode on its pango layout */
if (expected[i].boundary == ATK_TEXT_BOUNDARY_LINE_START ||
expected[i].boundary == ATK_TEXT_BOUNDARY_LINE_END)
continue;
}
switch (expected[i].gravity)
{
case -1:
word = atk_text_get_text_before_offset (atk_text,
expected[i].offset,
expected[i].boundary,
&start, &end);
break;
case 0:
word = atk_text_get_text_at_offset (atk_text,
expected[i].offset,
expected[i].boundary,
&start, &end);
break;
case 1:
word = atk_text_get_text_after_offset (atk_text,
expected[i].offset,
expected[i].boundary,
&start, &end);
break;
default:
g_assert_not_reached ();
break;
}
g_assert_cmpstr (word, ==, expected[i].word);
g_assert_cmpint (start, ==, expected[i].start);
g_assert_cmpint (end, ==, expected[i].end);
g_free (word);
}
}
static void
select_region (GtkWidget *widget,
gint start,
gint end)
{
if (GTK_IS_EDITABLE (widget))
gtk_editable_select_region (GTK_EDITABLE (widget), start, end);
else if (GTK_IS_LABEL (widget))
gtk_label_select_region (GTK_LABEL (widget), start, end);
else if (GTK_IS_TEXT_VIEW (widget))
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
GtkTextIter start_iter, end_iter;
gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, end);
gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, start);
gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
}
else
g_assert_not_reached ();
}
typedef struct {
gint count;
gint position;
gint bound;
} SelectionData;
static void
caret_moved_cb (AtkText *text, gint position, SelectionData *data)
{
data->count++;
data->position = position;
}
static void
selection_changed_cb (AtkText *text, SelectionData *data)
{
data->count++;
atk_text_get_selection (text, 0, &data->bound, &data->position);
}
static void
test_selection (GtkWidget *widget)
{
AtkText *atk_text;
const gchar *text = "Bla bla bla";
gint n;
gchar *ret;
gint start, end;
SelectionData data1;
SelectionData data2;
if (GTK_IS_LABEL (widget))
gtk_label_set_selectable (GTK_LABEL (widget), TRUE);
atk_text = ATK_TEXT (gtk_widget_get_accessible (widget));
data1.count = 0;
data2.count = 0;
g_signal_connect (atk_text, "text_caret_moved",
G_CALLBACK (caret_moved_cb), &data1);
g_signal_connect (atk_text, "text_selection_changed",
G_CALLBACK (selection_changed_cb), &data2);
set_text (widget, text);
n = atk_text_get_n_selections (atk_text);
g_assert_cmpint (n, ==, 0);
if (data1.count == 1)
/* insertion before cursor */
g_assert_cmpint (data1.position, ==, 11);
else
/* insertion after cursor */
g_assert_cmpint (data1.count, ==, 0);
g_assert_cmpint (data2.count, ==, 0);
select_region (widget, 4, 7);
g_assert_cmpint (data1.count, >=, 1);
g_assert_cmpint (data1.position, ==, 7);
g_assert_cmpint (data2.count, >=, 1);
g_assert_cmpint (data2.bound, ==, 4);
g_assert_cmpint (data2.position, ==, 7);
n = atk_text_get_n_selections (atk_text);
g_assert_cmpint (n, ==, 1);
ret = atk_text_get_selection (atk_text, 0, &start, &end);
g_assert_cmpstr (ret, ==, "bla");
g_assert_cmpint (start, ==, 4);
g_assert_cmpint (end, ==, 7);
g_free (ret);
atk_text_remove_selection (atk_text, 0);
n = atk_text_get_n_selections (atk_text);
g_assert_cmpint (n, ==, 0);
g_assert_cmpint (data1.count, >=, 1);
g_assert_cmpint (data2.count, >=, 2);
g_assert_cmpint (data2.position, ==, 7);
g_assert_cmpint (data2.bound, ==, 7);
}
static void
setup_test (GtkWidget *widget)
{
set_text (widget, "");
}
static void
add_text_test (const gchar *prefix,
GTestFixtureFunc test_func,
GtkWidget *widget)
{
gchar *path;
path = g_strdup_printf ("%s/%s", prefix, G_OBJECT_TYPE_NAME (widget));
g_test_add_vtable (path,
0,
g_object_ref (widget),
(GTestFixtureFunc) setup_test,
(GTestFixtureFunc) test_func,
(GTestFixtureFunc) g_object_unref);
g_free (path);
}
static void
add_text_tests (GtkWidget *widget)
{
g_object_ref_sink (widget);
add_text_test ("/text/basic", (GTestFixtureFunc) test_basic, widget);
add_text_test ("/text/words", (GTestFixtureFunc) test_words, widget);
add_text_test ("/text/changed", (GTestFixtureFunc) test_text_changed, widget);
add_text_test ("/text/selection", (GTestFixtureFunc) test_selection, widget);
g_object_unref (widget);
}
static void
test_bold_label (void)
{
GtkWidget *label;
AtkObject *atk_obj;
gchar *text;
g_test_bug ("126797");
label = gtk_label_new ("<b>Bold?</b>");
g_object_ref_sink (label);
atk_obj = gtk_widget_get_accessible (label);
text = atk_text_get_text (ATK_TEXT (atk_obj), 0, -1);
g_assert_cmpstr (text, ==, "<b>Bold?</b>");
g_free (text);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
text = atk_text_get_text (ATK_TEXT (atk_obj), 0, -1);
g_assert_cmpstr (text, ==, "Bold?");
g_free (text);
g_object_unref (label);
}
int
main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/text/bold/GtkLabel", test_bold_label);
add_text_tests (gtk_label_new (""));
add_text_tests (gtk_entry_new ());
add_text_tests (gtk_text_view_new ());
return g_test_run ();
}