1#include "gtktexthistoryprivate.h"
2
3#if 0
4# define DEBUG_COMMANDS
5#endif
6
7typedef struct
8{
9 GtkTextHistory *history;
10 GString *buf;
11 struct {
12 int insert;
13 int bound;
14 } selection;
15 guint can_redo : 1;
16 guint can_undo : 1;
17 guint is_modified : 1;
18} Text;
19
20enum {
21 IGNORE = 0,
22 SET = 1,
23 UNSET = 2,
24};
25
26enum {
27 IGNORE_SELECT = 0,
28 DO_SELECT = 1,
29};
30
31enum {
32 INSERT = 1,
33 INSERT_SEQ,
34 BACKSPACE,
35 DELETE_KEY,
36 UNDO,
37 REDO,
38 BEGIN_IRREVERSIBLE,
39 END_IRREVERSIBLE,
40 BEGIN_USER,
41 END_USER,
42 MODIFIED,
43 UNMODIFIED,
44 SELECT,
45 CHECK_SELECT,
46 SET_MAX_UNDO,
47};
48
49typedef struct
50{
51 int kind;
52 int location;
53 int end_location;
54 const char *text;
55 const char *expected;
56 int can_undo;
57 int can_redo;
58 int is_modified;
59 int select;
60} Command;
61
62static void
63do_change_state (gpointer funcs_data,
64 gboolean is_modified,
65 gboolean can_undo,
66 gboolean can_redo)
67{
68 Text *text = funcs_data;
69
70 text->is_modified = is_modified;
71 text->can_undo = can_undo;
72 text->can_redo = can_redo;
73}
74
75static void
76do_insert (gpointer funcs_data,
77 guint begin,
78 guint end,
79 const char *text,
80 guint len)
81{
82 Text *t = funcs_data;
83
84#ifdef DEBUG_COMMANDS
85 g_printerr ("Insert Into '%s' (begin=%u end=%u text=%s)\n",
86 t->buf->str, begin, end, text);
87#endif
88
89 g_string_insert_len (string: t->buf, pos: begin, val: text, len);
90}
91
92static void
93do_delete (gpointer funcs_data,
94 guint begin,
95 guint end,
96 const char *expected_text,
97 guint len)
98{
99 Text *t = funcs_data;
100
101#ifdef DEBUG_COMMANDS
102 g_printerr ("Delete(begin=%u end=%u expected_text=%s)\n", begin, end, expected_text);
103#endif
104
105 if (end < begin)
106 {
107 guint tmp = end;
108 end = begin;
109 begin = tmp;
110 }
111
112 g_assert_cmpint (memcmp (t->buf->str + begin, expected_text, len), ==, 0);
113
114 if (end >= t->buf->len)
115 {
116 t->buf->len = begin;
117 t->buf->str[begin] = 0;
118 return;
119 }
120
121 memmove (dest: t->buf->str + begin,
122 src: t->buf->str + end,
123 n: t->buf->len - end);
124 g_string_truncate (string: t->buf, len: t->buf->len - (end - begin));
125}
126
127static void
128do_select (gpointer funcs_data,
129 int selection_insert,
130 int selection_bound)
131{
132 Text *text = funcs_data;
133
134 text->selection.insert = selection_insert;
135 text->selection.bound = selection_bound;
136}
137
138static GtkTextHistoryFuncs funcs = {
139 do_change_state,
140 do_insert,
141 do_delete,
142 do_select,
143};
144
145static Text *
146text_new (void)
147{
148 Text *text = g_slice_new0 (Text);
149
150 text->history = gtk_text_history_new (funcs: &funcs, funcs_data: text);
151 text->buf = g_string_new (NULL);
152 text->selection.insert = -1;
153 text->selection.bound = -1;
154
155 return text;
156}
157
158static void
159text_free (Text *text)
160{
161 g_object_unref (object: text->history);
162 g_string_free (string: text->buf, TRUE);
163 g_slice_free (Text, text);
164}
165
166static void
167command_insert (const Command *cmd,
168 Text *text)
169{
170 do_insert (funcs_data: text,
171 begin: cmd->location,
172 end: cmd->location + g_utf8_strlen (p: cmd->text, max: -1),
173 text: cmd->text,
174 len: strlen (s: cmd->text));
175 gtk_text_history_text_inserted (self: text->history, position: cmd->location, text: cmd->text, len: -1);
176}
177
178static void
179command_delete_key (const Command *cmd,
180 Text *text)
181{
182 do_delete (funcs_data: text,
183 begin: cmd->location,
184 end: cmd->end_location,
185 expected_text: cmd->text,
186 len: strlen (s: cmd->text));
187 gtk_text_history_text_deleted (self: text->history,
188 begin: cmd->location,
189 end: cmd->end_location,
190 text: cmd->text,
191 ABS (cmd->end_location - cmd->location));
192}
193
194static void
195command_undo (const Command *cmd,
196 Text *text)
197{
198 gtk_text_history_undo (self: text->history);
199}
200
201static void
202command_redo (const Command *cmd,
203 Text *text)
204{
205 gtk_text_history_redo (self: text->history);
206}
207
208static void
209set_selection (Text *text,
210 int begin,
211 int end)
212{
213 gtk_text_history_selection_changed (self: text->history, selection_insert: begin, selection_bound: end);
214}
215
216static void
217run_test (const Command *commands,
218 guint n_commands,
219 guint max_undo)
220{
221 Text *text = text_new ();
222
223 if (max_undo)
224 gtk_text_history_set_max_undo_levels (self: text->history, max_undo_levels: max_undo);
225
226 for (guint i = 0; i < n_commands; i++)
227 {
228 const Command *cmd = &commands[i];
229
230#ifdef DEBUG_COMMANDS
231 g_printerr ("%d: %d\n", i, cmd->kind);
232#endif
233
234 switch (cmd->kind)
235 {
236 case INSERT:
237 command_insert (cmd, text);
238 break;
239
240 case INSERT_SEQ:
241 for (guint j = 0; cmd->text[j]; j++)
242 {
243 const char seqtext[2] = { cmd->text[j], 0 };
244 Command seq = { INSERT, cmd->location + j, 1, seqtext, NULL };
245 command_insert (cmd: &seq, text);
246 }
247 break;
248
249 case DELETE_KEY:
250 if (cmd->select == DO_SELECT)
251 set_selection (text, begin: cmd->location, end: cmd->end_location);
252 else if (strlen (s: cmd->text) == 1)
253 set_selection (text, begin: cmd->location, end: -1);
254 command_delete_key (cmd, text);
255 break;
256
257 case BACKSPACE:
258 if (cmd->select == DO_SELECT)
259 set_selection (text, begin: cmd->location, end: cmd->end_location);
260 else if (strlen (s: cmd->text) == 1)
261 set_selection (text, begin: cmd->end_location, end: -1);
262 command_delete_key (cmd, text);
263 break;
264
265 case UNDO:
266 command_undo (cmd, text);
267 break;
268
269 case REDO:
270 command_redo (cmd, text);
271 break;
272
273 case BEGIN_USER:
274 gtk_text_history_begin_user_action (self: text->history);
275 break;
276
277 case END_USER:
278 gtk_text_history_end_user_action (self: text->history);
279 break;
280
281 case BEGIN_IRREVERSIBLE:
282 gtk_text_history_begin_irreversible_action (self: text->history);
283 break;
284
285 case END_IRREVERSIBLE:
286 gtk_text_history_end_irreversible_action (self: text->history);
287 break;
288
289 case MODIFIED:
290 gtk_text_history_modified_changed (self: text->history, TRUE);
291 break;
292
293 case UNMODIFIED:
294 gtk_text_history_modified_changed (self: text->history, FALSE);
295 break;
296
297 case SELECT:
298 gtk_text_history_selection_changed (self: text->history,
299 selection_insert: cmd->location,
300 selection_bound: cmd->end_location);
301 break;
302
303 case CHECK_SELECT:
304 g_assert_cmpint (text->selection.insert, ==, cmd->location);
305 g_assert_cmpint (text->selection.bound, ==, cmd->end_location);
306 break;
307
308 case SET_MAX_UNDO:
309 /* Not ideal use of location, but fine */
310 gtk_text_history_set_max_undo_levels (self: text->history, max_undo_levels: cmd->location);
311 break;
312
313 default:
314 break;
315 }
316
317 if (cmd->expected)
318 g_assert_cmpstr (text->buf->str, ==, cmd->expected);
319
320 if (cmd->can_redo == SET)
321 g_assert_cmpint (text->can_redo, ==, TRUE);
322 else if (cmd->can_redo == UNSET)
323 g_assert_cmpint (text->can_redo, ==, FALSE);
324
325 if (cmd->can_undo == SET)
326 g_assert_cmpint (text->can_undo, ==, TRUE);
327 else if (cmd->can_undo == UNSET)
328 g_assert_cmpint (text->can_undo, ==, FALSE);
329
330 if (cmd->is_modified == SET)
331 g_assert_cmpint (text->is_modified, ==, TRUE);
332 else if (cmd->is_modified == UNSET)
333 g_assert_cmpint (text->is_modified, ==, FALSE);
334 }
335
336 text_free (text);
337}
338
339static void
340test1 (void)
341{
342 static const Command commands[] = {
343 { INSERT, 0, -1, "test", "test", SET, UNSET },
344 { INSERT, 2, -1, "s", "tesst", SET, UNSET },
345 { INSERT, 3, -1, "ss", "tesssst", SET, UNSET },
346 { DELETE_KEY, 2, 5, "sss", "test", SET, UNSET },
347 { UNDO, -1, -1, NULL, "tesssst", SET, SET },
348 { REDO, -1, -1, NULL, "test", SET, UNSET },
349 { UNDO, -1, -1, NULL, "tesssst", SET, SET },
350 { DELETE_KEY, 0, 7, "tesssst", "", SET, UNSET },
351 { INSERT, 0, -1, "z", "z", SET, UNSET },
352 { UNDO, -1, -1, NULL, "", SET, SET },
353 { UNDO, -1, -1, NULL, "tesssst", SET, SET },
354 { UNDO, -1, -1, NULL, "test", SET, SET },
355 };
356
357 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
358}
359
360static void
361test2 (void)
362{
363 static const Command commands[] = {
364 { BEGIN_IRREVERSIBLE, -1, -1, NULL, "", UNSET, UNSET },
365 { INSERT, 0, -1, "this is a test", "this is a test", UNSET, UNSET },
366 { END_IRREVERSIBLE, -1, -1, NULL, "this is a test", UNSET, UNSET },
367 { UNDO, -1, -1, NULL, "this is a test", UNSET, UNSET },
368 { REDO, -1, -1, NULL, "this is a test", UNSET, UNSET },
369 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
370 { INSERT, 0, -1, "first", "firstthis is a test", UNSET, UNSET },
371 { INSERT, 5, -1, " ", "first this is a test", UNSET, UNSET },
372 { END_USER, -1, -1, NULL, "first this is a test", SET, UNSET },
373 { UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
374 { UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
375 { REDO, -1, -1, NULL, "first this is a test", SET, UNSET },
376 { UNDO, -1, -1, NULL, "this is a test", UNSET, SET },
377 };
378
379 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
380}
381
382static void
383test3 (void)
384{
385 static const Command commands[] = {
386 { INSERT_SEQ, 0, -1, "this is a test of insertions.", "this is a test of insertions.", SET, UNSET },
387 { UNDO, -1, -1, NULL, "this is a test of", SET, SET },
388 { UNDO, -1, -1, NULL, "this is a test", SET, SET },
389 { UNDO, -1, -1, NULL, "this is a", SET, SET },
390 { UNDO, -1, -1, NULL, "this is", SET, SET },
391 { UNDO, -1, -1, NULL, "this", SET, SET },
392 { UNDO, -1, -1, NULL, "", UNSET, SET },
393 { UNDO, -1, -1, NULL, "" , UNSET, SET },
394 { REDO, -1, -1, NULL, "this", SET, SET },
395 { REDO, -1, -1, NULL, "this is", SET, SET },
396 { REDO, -1, -1, NULL, "this is a", SET, SET },
397 { REDO, -1, -1, NULL, "this is a test", SET, SET },
398 { REDO, -1, -1, NULL, "this is a test of", SET, SET },
399 { REDO, -1, -1, NULL, "this is a test of insertions.", SET, UNSET },
400 };
401
402 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
403}
404
405static void
406test4 (void)
407{
408 static const Command commands[] = {
409 { INSERT, 0, -1, "initial text", "initial text", SET, UNSET },
410 /* Barrier */
411 { BEGIN_IRREVERSIBLE, -1, -1, NULL, NULL, UNSET, UNSET },
412 { END_IRREVERSIBLE, -1, -1, NULL, NULL, UNSET, UNSET },
413 { INSERT, 0, -1, "more text ", "more text initial text", SET, UNSET },
414 { UNDO, -1, -1, NULL, "initial text", UNSET, SET },
415 { UNDO, -1, -1, NULL, "initial text", UNSET, SET },
416 { REDO, -1, -1, NULL, "more text initial text", SET, UNSET },
417 /* Barrier */
418 { BEGIN_IRREVERSIBLE, UNSET, UNSET },
419 { END_IRREVERSIBLE, UNSET, UNSET },
420 { UNDO, -1, -1, NULL, "more text initial text", UNSET, UNSET },
421 };
422
423 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
424}
425
426static void
427test5 (void)
428{
429 static const Command commands[] = {
430 { INSERT, 0, -1, "initial text", "initial text", SET, UNSET },
431 { DELETE_KEY, 0, 12, "initial text", "", SET, UNSET },
432 /* Add empty nested user action (should get ignored) */
433 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
434 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
435 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET },
436 { END_USER, -1, -1, NULL, NULL, UNSET, UNSET },
437 { END_USER, -1, -1, NULL, NULL, UNSET, UNSET },
438 { END_USER, -1, -1, NULL, NULL, SET, UNSET },
439 { UNDO, -1, -1, NULL, "initial text" },
440 };
441
442 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
443}
444
445static void
446test6 (void)
447{
448 static const Command commands[] = {
449 { INSERT_SEQ, 0, -1, " \t\t this is some text", " \t\t this is some text", SET, UNSET },
450 { UNDO, -1, -1, NULL, " \t\t this is some", SET, SET },
451 { UNDO, -1, -1, NULL, " \t\t this is", SET, SET },
452 { UNDO, -1, -1, NULL, " \t\t this", SET, SET },
453 { UNDO, -1, -1, NULL, "", UNSET, SET },
454 { UNDO, -1, -1, NULL, "", UNSET, SET },
455 };
456
457 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
458}
459
460static void
461test7 (void)
462{
463 static const Command commands[] = {
464 { MODIFIED, -1, -1, NULL, NULL, UNSET, UNSET, SET },
465 { UNMODIFIED, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
466 { INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
467 { MODIFIED, -1, -1, NULL, NULL, SET, UNSET, SET },
468 { UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
469 { REDO, -1, -1, NULL, "foo bar", SET, UNSET, SET },
470 { UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
471 { REDO, -1, -1, NULL, "foo bar", SET, UNSET, SET },
472 };
473
474 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
475}
476
477static void
478test8 (void)
479{
480 static const Command commands[] = {
481 { INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
482 { MODIFIED, -1, -1, NULL, NULL, SET, UNSET, SET },
483 { INSERT, 0, -1, "f", "ffoo bar", SET, UNSET, SET },
484 { UNMODIFIED, -1, -1, NULL, NULL, SET, UNSET, UNSET },
485 { UNDO, -1, -1, NULL, "foo bar", SET, SET, SET },
486 { UNDO, -1, -1, NULL, "", UNSET, SET, SET },
487 { REDO, -1, -1, NULL, "foo bar", SET, SET, SET },
488 { REDO, -1, -1, NULL, "ffoo bar", SET, UNSET, UNSET },
489 };
490
491 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
492}
493
494static void
495test9 (void)
496{
497 static const Command commands[] = {
498 { INSERT, 0, -1, "foo bar", "foo bar", SET, UNSET, UNSET },
499 { DELETE_KEY, 0, 3, "foo", " bar", SET, UNSET, UNSET, DO_SELECT },
500 { DELETE_KEY, 0, 4, " bar", "", SET, UNSET, UNSET, DO_SELECT },
501 { UNDO, -1, -1, NULL, " bar", SET, SET, UNSET },
502 { CHECK_SELECT, 0, 4, NULL, " bar", SET, SET, UNSET },
503 { UNDO, -1, -1, NULL, "foo bar", SET, SET, UNSET },
504 { CHECK_SELECT, 0, 3, NULL, "foo bar", SET, SET, UNSET },
505 { BEGIN_IRREVERSIBLE, -1, -1, NULL, "foo bar", UNSET, UNSET, UNSET },
506 { END_IRREVERSIBLE, -1, -1, NULL, "foo bar", UNSET, UNSET, UNSET },
507 };
508
509 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
510}
511
512static void
513test10 (void)
514{
515 static const Command commands[] = {
516 { BEGIN_USER }, { INSERT, 0, -1, "t", "t", UNSET, UNSET, UNSET }, { END_USER },
517 { BEGIN_USER }, { INSERT, 1, -1, " ", "t ", UNSET, UNSET, UNSET }, { END_USER },
518 { BEGIN_USER }, { INSERT, 2, -1, "t", "t t", UNSET, UNSET, UNSET }, { END_USER },
519 { BEGIN_USER }, { INSERT, 3, -1, "h", "t th", UNSET, UNSET, UNSET }, { END_USER },
520 { BEGIN_USER }, { INSERT, 4, -1, "i", "t thi", UNSET, UNSET, UNSET }, { END_USER },
521 { BEGIN_USER }, { INSERT, 5, -1, "s", "t this", UNSET, UNSET, UNSET }, { END_USER },
522 };
523
524 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
525}
526
527static void
528test11 (void)
529{
530 /* Test backspace */
531 static const Command commands[] = {
532 { INSERT_SEQ, 0, -1, "insert some text", "insert some text", SET, UNSET, UNSET },
533 { BACKSPACE, 15, 16, "t", "insert some tex", SET, UNSET, UNSET },
534 { BACKSPACE, 14, 15, "x", "insert some te", SET, UNSET, UNSET },
535 { BACKSPACE, 13, 14, "e", "insert some t", SET, UNSET, UNSET },
536 { BACKSPACE, 12, 13, "t", "insert some ", SET, UNSET, UNSET },
537 { UNDO, -1, -1, NULL, "insert some text", SET, SET, UNSET },
538 };
539
540 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
541}
542
543static void
544test12 (void)
545{
546 static const Command commands[] = {
547 { INSERT_SEQ, 0, -1, "this is a test\nmore", "this is a test\nmore", SET, UNSET, UNSET },
548 { UNDO, -1, -1, NULL, "this is a test\n", SET, SET, UNSET },
549 { UNDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
550 { UNDO, -1, -1, NULL, "this is a", SET, SET, UNSET },
551 { UNDO, -1, -1, NULL, "this is", SET, SET, UNSET },
552 { UNDO, -1, -1, NULL, "this", SET, SET, UNSET },
553 { UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
554 };
555
556 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
557}
558
559static void
560test13 (void)
561{
562 static const Command commands[] = {
563 { INSERT_SEQ, 0, -1, "this is a test\nmore", "this is a test\nmore", SET, UNSET, UNSET },
564 { UNDO, -1, -1, NULL, "this is a test\n", SET, SET, UNSET },
565 { UNDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
566 { UNDO, -1, -1, NULL, "this is a", UNSET, SET, UNSET },
567 { UNDO, -1, -1, NULL, "this is a", UNSET, SET, UNSET },
568 { SET_MAX_UNDO, 2, -1, NULL, "this is a", UNSET, SET, UNSET },
569 { REDO, -1, -1, NULL, "this is a test", SET, SET, UNSET },
570 { REDO, -1, -1, NULL, "this is a test\n", SET, UNSET, UNSET },
571 { REDO, -1, -1, NULL, "this is a test\n", SET, UNSET, UNSET },
572 };
573
574 run_test (commands, G_N_ELEMENTS (commands), max_undo: 3);
575}
576
577static void
578test14 (void)
579{
580 char *fill = g_strnfill (length: 1024, fill_char: 'x');
581 char *fill_after = g_strnfill (length: 1025, fill_char: 'x');
582 char *fill_after_2 = g_strdup_printf (format: "%s word", fill_after);
583 const Command commands[] = {
584 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
585 { INSERT, 0, -1, fill, fill, UNSET, UNSET, UNSET },
586 { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
587 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
588 { INSERT, 0, -1, "x", fill_after, UNSET, UNSET, UNSET },
589 { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
590 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
591 { INSERT_SEQ, strlen(s: fill_after), -1, " word", fill_after_2, UNSET, UNSET, UNSET },
592 { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
593 { UNDO, -1, -1, NULL, fill_after, SET, SET, UNSET },
594 { UNDO, -1, -1, NULL, fill, SET, SET, UNSET },
595 { UNDO, -1, -1, NULL, "", UNSET, SET, UNSET },
596 };
597
598 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
599
600 g_free (mem: fill);
601 g_free (mem: fill_after);
602 g_free (mem: fill_after_2);
603}
604
605static void
606test_issue_4276 (void)
607{
608 const Command commands[] = {
609 { INSERT, 0, -1, "this is some text", "this is some text", SET, UNSET, UNSET },
610 { SELECT, 0, 17, NULL, "this is some text", SET, UNSET, UNSET },
611 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
612 { DELETE_KEY, 0, 17, "this is some text", "", UNSET, UNSET, UNSET },
613 { INSERT, 0, -1, "z", "z", UNSET, UNSET, UNSET },
614 { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
615 { INSERT, 1, -1, "zzz", "zzzz", SET, UNSET, UNSET },
616 { UNDO, -1, -1, NULL, "z", SET, SET, UNSET },
617 };
618
619 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
620}
621
622static void
623test_issue_4575 (void)
624{
625 const Command commands[] = {
626 { INSERT, 0, -1, "this is some text", "this is some text", SET, UNSET, UNSET },
627 { SELECT, 5, 8, NULL, NULL, SET, UNSET, UNSET },
628 { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
629 { DELETE_KEY, 5, 8, "is ", "this some text", UNSET, UNSET, UNSET, IGNORE_SELECT },
630 { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
631 { UNDO, -1, -1, NULL, "this is some text", SET, SET, UNSET },
632 { CHECK_SELECT, 5, 8, NULL, "this is some text", SET, SET, UNSET },
633 };
634
635 run_test (commands, G_N_ELEMENTS (commands), max_undo: 0);
636}
637
638int
639main (int argc,
640 char *argv[])
641{
642 (g_test_init) (argc: &argc, argv: &argv, NULL);
643
644 g_test_add_func (testpath: "/Gtk/TextHistory/test1", test_func: test1);
645 g_test_add_func (testpath: "/Gtk/TextHistory/test2", test_func: test2);
646 g_test_add_func (testpath: "/Gtk/TextHistory/test3", test_func: test3);
647 g_test_add_func (testpath: "/Gtk/TextHistory/test4", test_func: test4);
648 g_test_add_func (testpath: "/Gtk/TextHistory/test5", test_func: test5);
649 g_test_add_func (testpath: "/Gtk/TextHistory/test6", test_func: test6);
650 g_test_add_func (testpath: "/Gtk/TextHistory/test7", test_func: test7);
651 g_test_add_func (testpath: "/Gtk/TextHistory/test8", test_func: test8);
652 g_test_add_func (testpath: "/Gtk/TextHistory/test9", test_func: test9);
653 g_test_add_func (testpath: "/Gtk/TextHistory/test10", test_func: test10);
654 g_test_add_func (testpath: "/Gtk/TextHistory/test11", test_func: test11);
655 g_test_add_func (testpath: "/Gtk/TextHistory/test12", test_func: test12);
656 g_test_add_func (testpath: "/Gtk/TextHistory/test13", test_func: test13);
657 g_test_add_func (testpath: "/Gtk/TextHistory/test14", test_func: test14);
658 g_test_add_func (testpath: "/Gtk/TextHistory/issue_4276", test_func: test_issue_4276);
659 g_test_add_func (testpath: "/Gtk/TextHistory/issue_4575", test_func: test_issue_4575);
660
661 return g_test_run ();
662}
663

source code of gtk/testsuite/gtk/texthistory.c