forked from AuroraMiddleware/gtk
22b1abb36d
We don't need to apply these here, as it will clear the selection which is needed for the undo. Otherwise we won't be able to test that we end up at the right selection afterwards.
646 lines
19 KiB
C
646 lines
19 KiB
C
#include "gtktexthistoryprivate.h"
|
|
|
|
#if 0
|
|
# define DEBUG_COMMANDS
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
GtkTextHistory *history;
|
|
GString *buf;
|
|
struct {
|
|
int insert;
|
|
int bound;
|
|
} selection;
|
|
guint can_redo : 1;
|
|
guint can_undo : 1;
|
|
guint is_modified : 1;
|
|
} Text;
|
|
|
|
enum {
|
|
IGNORE = 0,
|
|
SET = 1,
|
|
UNSET = 2,
|
|
};
|
|
|
|
enum {
|
|
IGNORE_SELECT = 0,
|
|
DO_SELECT = 1,
|
|
};
|
|
|
|
enum {
|
|
INSERT = 1,
|
|
INSERT_SEQ,
|
|
BACKSPACE,
|
|
DELETE_KEY,
|
|
UNDO,
|
|
REDO,
|
|
BEGIN_IRREVERSIBLE,
|
|
END_IRREVERSIBLE,
|
|
BEGIN_USER,
|
|
END_USER,
|
|
MODIFIED,
|
|
UNMODIFIED,
|
|
SELECT,
|
|
CHECK_SELECT,
|
|
SET_MAX_UNDO,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
int kind;
|
|
int location;
|
|
int end_location;
|
|
const char *text;
|
|
const char *expected;
|
|
int can_undo;
|
|
int can_redo;
|
|
int is_modified;
|
|
int select;
|
|
} Command;
|
|
|
|
static void
|
|
do_change_state (gpointer funcs_data,
|
|
gboolean is_modified,
|
|
gboolean can_undo,
|
|
gboolean can_redo)
|
|
{
|
|
Text *text = funcs_data;
|
|
|
|
text->is_modified = is_modified;
|
|
text->can_undo = can_undo;
|
|
text->can_redo = can_redo;
|
|
}
|
|
|
|
static void
|
|
do_insert (gpointer funcs_data,
|
|
guint begin,
|
|
guint end,
|
|
const char *text,
|
|
guint len)
|
|
{
|
|
Text *t = funcs_data;
|
|
|
|
#ifdef DEBUG_COMMANDS
|
|
g_printerr ("Insert Into '%s' (begin=%u end=%u text=%s)\n",
|
|
t->buf->str, begin, end, text);
|
|
#endif
|
|
|
|
g_string_insert_len (t->buf, begin, text, len);
|
|
}
|
|
|
|
static void
|
|
do_delete (gpointer funcs_data,
|
|
guint begin,
|
|
guint end,
|
|
const char *expected_text,
|
|
guint len)
|
|
{
|
|
Text *t = funcs_data;
|
|
|
|
#ifdef DEBUG_COMMANDS
|
|
g_printerr ("Delete(begin=%u end=%u expected_text=%s)\n", begin, end, expected_text);
|
|
#endif
|
|
|
|
if (end < begin)
|
|
{
|
|
guint tmp = end;
|
|
end = begin;
|
|
begin = tmp;
|
|
}
|
|
|
|
g_assert_cmpint (memcmp (t->buf->str + begin, expected_text, len), ==, 0);
|
|
|
|
if (end >= t->buf->len)
|
|
{
|
|
t->buf->len = begin;
|
|
t->buf->str[begin] = 0;
|
|
return;
|
|
}
|
|
|
|
memmove (t->buf->str + begin,
|
|
t->buf->str + end,
|
|
t->buf->len - end);
|
|
g_string_truncate (t->buf, t->buf->len - (end - begin));
|
|
}
|
|
|
|
static void
|
|
do_select (gpointer funcs_data,
|
|
int selection_insert,
|
|
int selection_bound)
|
|
{
|
|
Text *text = funcs_data;
|
|
|
|
text->selection.insert = selection_insert;
|
|
text->selection.bound = selection_bound;
|
|
}
|
|
|
|
static GtkTextHistoryFuncs funcs = {
|
|
do_change_state,
|
|
do_insert,
|
|
do_delete,
|
|
do_select,
|
|
};
|
|
|
|
static Text *
|
|
text_new (void)
|
|
{
|
|
Text *text = g_slice_new0 (Text);
|
|
|
|
text->history = gtk_text_history_new (&funcs, text);
|
|
text->buf = g_string_new (NULL);
|
|
text->selection.insert = -1;
|
|
text->selection.bound = -1;
|
|
|
|
return text;
|
|
}
|
|
|
|
static void
|
|
text_free (Text *text)
|
|
{
|
|
g_object_unref (text->history);
|
|
g_string_free (text->buf, TRUE);
|
|
g_slice_free (Text, text);
|
|
}
|
|
|
|
static void
|
|
command_insert (const Command *cmd,
|
|
Text *text)
|
|
{
|
|
do_insert (text,
|
|
cmd->location,
|
|
cmd->location + g_utf8_strlen (cmd->text, -1),
|
|
cmd->text,
|
|
strlen (cmd->text));
|
|
gtk_text_history_text_inserted (text->history, cmd->location, cmd->text, -1);
|
|
}
|
|
|
|
static void
|
|
command_delete_key (const Command *cmd,
|
|
Text *text)
|
|
{
|
|
do_delete (text,
|
|
cmd->location,
|
|
cmd->end_location,
|
|
cmd->text,
|
|
strlen (cmd->text));
|
|
gtk_text_history_text_deleted (text->history,
|
|
cmd->location,
|
|
cmd->end_location,
|
|
cmd->text,
|
|
ABS (cmd->end_location - cmd->location));
|
|
}
|
|
|
|
static void
|
|
command_undo (const Command *cmd,
|
|
Text *text)
|
|
{
|
|
gtk_text_history_undo (text->history);
|
|
}
|
|
|
|
static void
|
|
command_redo (const Command *cmd,
|
|
Text *text)
|
|
{
|
|
gtk_text_history_redo (text->history);
|
|
}
|
|
|
|
static void
|
|
set_selection (Text *text,
|
|
int begin,
|
|
int end)
|
|
{
|
|
gtk_text_history_selection_changed (text->history, begin, end);
|
|
}
|
|
|
|
static void
|
|
run_test (const Command *commands,
|
|
guint n_commands,
|
|
guint max_undo)
|
|
{
|
|
Text *text = text_new ();
|
|
|
|
if (max_undo)
|
|
gtk_text_history_set_max_undo_levels (text->history, max_undo);
|
|
|
|
for (guint i = 0; i < n_commands; i++)
|
|
{
|
|
const Command *cmd = &commands[i];
|
|
|
|
#ifdef DEBUG_COMMANDS
|
|
g_printerr ("%d: %d\n", i, cmd->kind);
|
|
#endif
|
|
|
|
switch (cmd->kind)
|
|
{
|
|
case INSERT:
|
|
command_insert (cmd, text);
|
|
break;
|
|
|
|
case INSERT_SEQ:
|
|
for (guint j = 0; cmd->text[j]; j++)
|
|
{
|
|
const char seqtext[2] = { cmd->text[j], 0 };
|
|
Command seq = { INSERT, cmd->location + j, 1, seqtext, NULL };
|
|
command_insert (&seq, text);
|
|
}
|
|
break;
|
|
|
|
case DELETE_KEY:
|
|
if (cmd->select == DO_SELECT)
|
|
set_selection (text, cmd->location, cmd->end_location);
|
|
else if (strlen (cmd->text) == 1)
|
|
set_selection (text, cmd->location, -1);
|
|
command_delete_key (cmd, text);
|
|
break;
|
|
|
|
case BACKSPACE:
|
|
if (cmd->select == DO_SELECT)
|
|
set_selection (text, cmd->location, cmd->end_location);
|
|
else if (strlen (cmd->text) == 1)
|
|
set_selection (text, cmd->end_location, -1);
|
|
command_delete_key (cmd, text);
|
|
break;
|
|
|
|
case UNDO:
|
|
command_undo (cmd, text);
|
|
break;
|
|
|
|
case REDO:
|
|
command_redo (cmd, text);
|
|
break;
|
|
|
|
case BEGIN_USER:
|
|
gtk_text_history_begin_user_action (text->history);
|
|
break;
|
|
|
|
case END_USER:
|
|
gtk_text_history_end_user_action (text->history);
|
|
break;
|
|
|
|
case BEGIN_IRREVERSIBLE:
|
|
gtk_text_history_begin_irreversible_action (text->history);
|
|
break;
|
|
|
|
case END_IRREVERSIBLE:
|
|
gtk_text_history_end_irreversible_action (text->history);
|
|
break;
|
|
|
|
case MODIFIED:
|
|
gtk_text_history_modified_changed (text->history, TRUE);
|
|
break;
|
|
|
|
case UNMODIFIED:
|
|
gtk_text_history_modified_changed (text->history, FALSE);
|
|
break;
|
|
|
|
case SELECT:
|
|
gtk_text_history_selection_changed (text->history,
|
|
cmd->location,
|
|
cmd->end_location);
|
|
break;
|
|
|
|
case CHECK_SELECT:
|
|
g_assert_cmpint (text->selection.insert, ==, cmd->location);
|
|
g_assert_cmpint (text->selection.bound, ==, cmd->end_location);
|
|
break;
|
|
|
|
case SET_MAX_UNDO:
|
|
/* Not ideal use of location, but fine */
|
|
gtk_text_history_set_max_undo_levels (text->history, cmd->location);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (cmd->expected)
|
|
g_assert_cmpstr (text->buf->str, ==, cmd->expected);
|
|
|
|
if (cmd->can_redo == SET)
|
|
g_assert_cmpint (text->can_redo, ==, TRUE);
|
|
else if (cmd->can_redo == UNSET)
|
|
g_assert_cmpint (text->can_redo, ==, FALSE);
|
|
|
|
if (cmd->can_undo == SET)
|
|
g_assert_cmpint (text->can_undo, ==, TRUE);
|
|
else if (cmd->can_undo == UNSET)
|
|
g_assert_cmpint (text->can_undo, ==, FALSE);
|
|
|
|
if (cmd->is_modified == SET)
|
|
g_assert_cmpint (text->is_modified, ==, TRUE);
|
|
else if (cmd->is_modified == UNSET)
|
|
g_assert_cmpint (text->is_modified, ==, FALSE);
|
|
}
|
|
|
|
text_free (text);
|
|
}
|
|
|
|
static void
|
|
test1 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT, 0, -1, "test", "test", SET, UNSET },
|
|
{ INSERT, 2, -1, "s", "tesst", SET, UNSET },
|
|
{ INSERT, 3, -1, "ss", "tesssst", SET, UNSET },
|
|
{ DELETE_KEY, 2, 5, "sss", "test", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "tesssst", SET, SET },
|
|
{ REDO, -1, -1, NULL, "test", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "tesssst", SET, SET },
|
|
{ DELETE_KEY, 0, 7, "tesssst", "", SET, UNSET },
|
|
{ INSERT, 0, -1, "z", "z", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "tesssst", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "test", SET, SET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test2 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ BEGIN_IRREVERSIBLE, -1, -1, NULL, "", UNSET, UNSET },
|
|
{ INSERT, 0, -1, "this is a test", "this is a test", UNSET, UNSET },
|
|
{ END_IRREVERSIBLE, -1, -1, NULL, "this is a test", UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", UNSET, UNSET },
|
|
{ REDO, -1, -1, NULL, "this is a test", UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ INSERT, 0, -1, "first", "firstthis is a test", UNSET, UNSET },
|
|
{ INSERT, 5, -1, " ", "first this is a test", UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, "first this is a test", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
|
|
{ REDO, -1, -1, NULL, "first this is a test", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test3 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT_SEQ, 0, -1, "this is a test of insertions.", "this is a test of insertions.", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test of", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "this is a", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "this is", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "this", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "" , UNSET, SET },
|
|
{ REDO, -1, -1, NULL, "this", SET, SET },
|
|
{ REDO, -1, -1, NULL, "this is", SET, SET },
|
|
{ REDO, -1, -1, NULL, "this is a", SET, SET },
|
|
{ REDO, -1, -1, NULL, "this is a test", SET, SET },
|
|
{ REDO, -1, -1, NULL, "this is a test of", SET, SET },
|
|
{ REDO, -1, -1, NULL, "this is a test of insertions.", SET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test4 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT, 0, -1, "initial text", "initial text", SET, UNSET },
|
|
/* Barrier */
|
|
{ BEGIN_IRREVERSIBLE, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ END_IRREVERSIBLE, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ INSERT, 0, -1, "more text ", "more text initial text", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "initial text", UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "initial text", UNSET, SET },
|
|
{ REDO, -1, -1, NULL, "more text initial text", SET, UNSET },
|
|
/* Barrier */
|
|
{ BEGIN_IRREVERSIBLE, UNSET, UNSET },
|
|
{ END_IRREVERSIBLE, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "more text initial text", UNSET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test5 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT, 0, -1, "initial text", "initial text", SET, UNSET },
|
|
{ DELETE_KEY, 0, 12, "initial text", "", SET, UNSET },
|
|
/* Add empty nested user action (should get ignored) */
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "initial text" },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test6 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT_SEQ, 0, -1, " \t\t this is some text", " \t\t this is some text", SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, " \t\t this is some", SET, SET },
|
|
{ UNDO, -1, -1, NULL, " \t\t this is", SET, SET },
|
|
{ UNDO, -1, -1, NULL, " \t\t this", SET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test7 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ MODIFIED, -1, -1, NULL, NULL, UNSET, UNSET, SET },
|
|
{ UNMODIFIED, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
|
|
{ INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
|
|
{ MODIFIED, -1, -1, NULL, NULL, SET, UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
|
|
{ REDO, -1, -1, NULL, "foo bar", SET, UNSET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
|
|
{ REDO, -1, -1, NULL, "foo bar", SET, UNSET, SET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test8 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
|
|
{ MODIFIED, -1, -1, NULL, NULL, SET, UNSET, SET },
|
|
{ INSERT, 0, -1, "f", "ffoo bar", SET, UNSET, SET },
|
|
{ UNMODIFIED, -1, -1, NULL, NULL, SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "foo bar", SET, SET, SET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET, SET },
|
|
{ REDO, -1, -1, NULL, "foo bar", SET, SET, SET },
|
|
{ REDO, -1, -1, NULL, "ffoo bar", SET, UNSET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test9 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
|
|
{ DELETE_KEY, 0, 3, "foo", " bar", SET, UNSET, UNSET, DO_SELECT },
|
|
{ DELETE_KEY, 0, 4, " bar", "", SET, UNSET, UNSET, DO_SELECT },
|
|
{ UNDO, -1, -1, NULL, " bar", SET, SET, UNSET },
|
|
{ CHECK_SELECT, 0, 4, NULL, " bar", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "foo bar", SET, SET, UNSET },
|
|
{ CHECK_SELECT, 0, 3, NULL, "foo bar", SET, SET, UNSET },
|
|
{ BEGIN_IRREVERSIBLE, -1, -1, NULL, "foo bar", UNSET, UNSET, UNSET },
|
|
{ END_IRREVERSIBLE, -1, -1, NULL, "foo bar", UNSET, UNSET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test10 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ BEGIN_USER }, { INSERT, 0, -1, "t", "t", UNSET, UNSET, UNSET }, { END_USER },
|
|
{ BEGIN_USER }, { INSERT, 1, -1, " ", "t ", UNSET, UNSET, UNSET }, { END_USER },
|
|
{ BEGIN_USER }, { INSERT, 2, -1, "t", "t t", UNSET, UNSET, UNSET }, { END_USER },
|
|
{ BEGIN_USER }, { INSERT, 3, -1, "h", "t th", UNSET, UNSET, UNSET }, { END_USER },
|
|
{ BEGIN_USER }, { INSERT, 4, -1, "i", "t thi", UNSET, UNSET, UNSET }, { END_USER },
|
|
{ BEGIN_USER }, { INSERT, 5, -1, "s", "t this", UNSET, UNSET, UNSET }, { END_USER },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test11 (void)
|
|
{
|
|
/* Test backspace */
|
|
static const Command commands[] = {
|
|
{ INSERT_SEQ, 0, -1, "insert some text", "insert some text", SET, UNSET, UNSET },
|
|
{ BACKSPACE, 15, 16, "t", "insert some tex", SET, UNSET, UNSET },
|
|
{ BACKSPACE, 14, 15, "x", "insert some te", SET, UNSET, UNSET },
|
|
{ BACKSPACE, 13, 14, "e", "insert some t", SET, UNSET, UNSET },
|
|
{ BACKSPACE, 12, 13, "t", "insert some ", SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "insert some text", SET, SET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test12 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT_SEQ, 0, -1, "this is a test\nmore", "this is a test\nmore", SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test\n", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
static void
|
|
test13 (void)
|
|
{
|
|
static const Command commands[] = {
|
|
{ INSERT_SEQ, 0, -1, "this is a test\nmore", "this is a test\nmore", SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test\n", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a", UNSET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "this is a", UNSET, SET, UNSET },
|
|
{ SET_MAX_UNDO, 2, -1, NULL, "this is a", UNSET, SET, UNSET },
|
|
{ REDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
|
|
{ REDO, -1, -1, NULL, "this is a test\n", SET, UNSET, UNSET },
|
|
{ REDO, -1, -1, NULL, "this is a test\n", SET, UNSET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 3);
|
|
}
|
|
|
|
static void
|
|
test14 (void)
|
|
{
|
|
char *fill = g_strnfill (1024, 'x');
|
|
char *fill_after = g_strnfill (1025, 'x');
|
|
char *fill_after_2 = g_strdup_printf ("%s word", fill_after);
|
|
const Command commands[] = {
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
|
|
{ INSERT, 0, -1, fill, fill, UNSET, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
|
|
{ INSERT, 0, -1, "x", fill_after, UNSET, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
|
|
{ INSERT_SEQ, strlen(fill_after), -1, " word", fill_after_2, UNSET, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, fill_after, SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, fill, SET, SET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
|
|
g_free (fill);
|
|
g_free (fill_after);
|
|
g_free (fill_after_2);
|
|
}
|
|
|
|
static void
|
|
test_issue_4276 (void)
|
|
{
|
|
const Command commands[] = {
|
|
{ INSERT, 0, -1, "this is some text", "this is some text", SET, UNSET, UNSET },
|
|
{ SELECT, 0, 17, NULL, "this is some text", SET, UNSET, UNSET },
|
|
{ BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
|
|
{ DELETE_KEY, 0, 17, "this is some text", "", UNSET, UNSET, UNSET },
|
|
{ INSERT, 0, -1, "z", "z", UNSET, UNSET, UNSET },
|
|
{ END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
|
|
{ INSERT, 1, -1, "zzz", "zzzz", SET, UNSET, UNSET },
|
|
{ UNDO, -1, -1, NULL, "z", SET, SET, UNSET },
|
|
};
|
|
|
|
run_test (commands, G_N_ELEMENTS (commands), 0);
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char *argv[])
|
|
{
|
|
(g_test_init) (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/Gtk/TextHistory/test1", test1);
|
|
g_test_add_func ("/Gtk/TextHistory/test2", test2);
|
|
g_test_add_func ("/Gtk/TextHistory/test3", test3);
|
|
g_test_add_func ("/Gtk/TextHistory/test4", test4);
|
|
g_test_add_func ("/Gtk/TextHistory/test5", test5);
|
|
g_test_add_func ("/Gtk/TextHistory/test6", test6);
|
|
g_test_add_func ("/Gtk/TextHistory/test7", test7);
|
|
g_test_add_func ("/Gtk/TextHistory/test8", test8);
|
|
g_test_add_func ("/Gtk/TextHistory/test9", test9);
|
|
g_test_add_func ("/Gtk/TextHistory/test10", test10);
|
|
g_test_add_func ("/Gtk/TextHistory/test11", test11);
|
|
g_test_add_func ("/Gtk/TextHistory/test12", test12);
|
|
g_test_add_func ("/Gtk/TextHistory/test13", test13);
|
|
g_test_add_func ("/Gtk/TextHistory/test14", test14);
|
|
g_test_add_func ("/Gtk/TextHistory/issue_4276", test_issue_4276);
|
|
|
|
return g_test_run ();
|
|
}
|