]> Pileus Git - ~andy/gtk/blob - gtk/tests/entry.c
Merge branch 'bgo593793-filechooser-recent-folders-master'
[~andy/gtk] / gtk / tests / entry.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gtk/gtk.h>
21
22 static gint serial = 0;
23
24 typedef struct {
25   gint serial;
26   gint count;
27   gint start;
28   gint end;
29   gchar *text;
30   gchar *new_text;
31   gint position;
32   gint length;
33 } EntryData;
34
35 static void
36 notify (GtkEditable *editable, GParamSpec *pspec, EntryData *data)
37 {
38   data->serial = serial++;
39   data->count++;
40   data->text = gtk_editable_get_chars (editable, 0, -1);
41   gtk_editable_get_selection_bounds (editable, &data->start, &data->end);
42
43 #if 0
44   g_print ("notify::%s\n", pspec->name);
45   g_print ("\ttext: %s\n", data->text);
46   g_print ("\tstart: %d\n", data->start);
47   g_print ("\tend: %d\n", data->end);
48 #endif
49 }
50
51 static void
52 insert_text (GtkEditable *editable,
53              const gchar *new_text,
54              gint         new_text_length,
55              gint        *position,
56              EntryData   *data)
57 {
58   data->serial = serial++;
59   data->count++;
60   data->text = gtk_editable_get_chars (editable, 0, -1);
61   gtk_editable_get_selection_bounds (editable, &data->start, &data->end);
62   data->new_text = g_strdup (new_text);
63   data->position = *position;
64   data->length = new_text_length;
65
66 #if 0
67   g_print ("insert-text \"%s\", %d\n", new_text, *position);
68   g_print ("\ttext: %s\n", data->text);
69   g_print ("\tstart: %d\n", data->start);
70   g_print ("\tend: %d\n", data->end);
71 #endif
72 }
73
74 static void
75 delete_text (GtkEditable *editable,
76              gint         start_pos,
77              gint         end_pos,
78              EntryData   *data)
79 {
80   data->serial = serial++;
81   data->count++;
82   data->text = gtk_editable_get_chars (editable, 0, -1);
83   gtk_editable_get_selection_bounds (editable, &data->start, &data->end);
84   data->position = start_pos;
85   data->length = end_pos - start_pos;
86
87 #if 0
88   g_print ("delete-text %d %d\n", start_pos, end_pos);
89   g_print ("\ttext: %s\n", data->text);
90   g_print ("\tstart: %d\n", data->start);
91   g_print ("\tend: %d\n", data->end);
92 #endif
93 }
94
95 static void
96 changed (GtkEditable *editable,
97          EntryData   *data)
98 {
99   data->serial = serial++;
100   data->count++;
101   data->text = gtk_editable_get_chars (editable, 0, -1);
102   gtk_editable_get_selection_bounds (editable, &data->start, &data->end);
103
104 #if 0
105   g_print ("changed\n");
106   g_print ("\ttext: %s\n", data->text);
107   g_print ("\tstart: %d\n", data->start);
108   g_print ("\tend: %d\n", data->end);
109 #endif
110 }
111
112 static void
113 test_insert (void)
114 {
115   GtkWidget *entry;
116   gint pos;
117   EntryData data1;
118   EntryData data2;
119   EntryData data3;
120   EntryData data4;
121   EntryData data5;
122   EntryData data6;
123
124   entry = gtk_entry_new ();
125   g_object_ref_sink (entry);
126
127   gtk_entry_set_text (GTK_ENTRY (entry), "bar");
128   gtk_editable_set_position (GTK_EDITABLE (entry), -1);
129   pos = gtk_editable_get_position (GTK_EDITABLE (entry));
130   g_assert_cmpint (pos, ==, 3);
131
132   data1.count = 0;
133   data2.count = 0;
134   data3.count = 0;
135   data4.count = 0;
136   data5.count = 0;
137   data6.count = 0;
138   g_signal_connect (entry, "notify::cursor-position",
139                     G_CALLBACK (notify), &data1);
140   g_signal_connect (entry, "notify::selection-bound",
141                     G_CALLBACK (notify), &data2);
142   g_signal_connect (entry, "notify::text",
143                     G_CALLBACK (notify), &data3);
144   g_signal_connect (entry, "insert-text",
145                     G_CALLBACK (insert_text), &data4);
146   g_signal_connect (entry, "delete-text",
147                     G_CALLBACK (delete_text), &data5);
148   g_signal_connect (entry, "changed",
149                     G_CALLBACK (changed), &data6);
150
151   pos = 0;
152   gtk_editable_insert_text (GTK_EDITABLE (entry), "foo", -1, &pos);
153   g_assert_cmpint (pos, ==, 3);
154
155   pos = gtk_editable_get_position (GTK_EDITABLE (entry));
156   g_assert_cmpint (pos, ==, 6);
157
158   /* Check that notification for ::text, ::cursor-position and
159    * ::selection-bound happens in a consistent state after the
160    * change.
161    */
162   g_assert_cmpint (data1.count, ==, 1);
163   g_assert_cmpint (data1.start, ==, 6);
164   g_assert_cmpint (data1.end, ==, 6);
165   g_assert_cmpstr (data1.text, ==, "foobar");
166   g_free (data1.text);
167
168   g_assert_cmpint (data2.count, ==, 1);
169   g_assert_cmpint (data2.start, ==, 6);
170   g_assert_cmpint (data2.end, ==, 6);
171   g_assert_cmpstr (data2.text, ==, "foobar");
172   g_free (data2.text);
173
174   g_assert_cmpint (data3.count, ==, 1);
175   g_assert_cmpint (data3.start, ==, 6);
176   g_assert_cmpint (data3.end, ==, 6);
177   g_assert_cmpstr (data3.text, ==, "foobar");
178   g_free (data3.text);
179
180   /* Check that ::insert-text sees the state _before_ the insertion */
181   g_assert_cmpint (data4.count, ==, 1);
182   g_assert_cmpint (data4.start, ==, 3);
183   g_assert_cmpint (data4.end, ==, 3);
184   g_assert_cmpstr (data4.text, ==, "bar");
185   g_assert_cmpint (data4.position, ==, 0);
186   g_assert_cmpint (data4.length, ==, 3);
187   g_assert_cmpstr (data4.new_text, ==, "foo");
188   g_free (data4.text);
189   g_free (data4.new_text);
190
191   /* no deletion here */
192   g_assert_cmpint (data5.count, ==, 0);
193
194   /* Check that ::changed sees the post-change state */
195   g_assert_cmpint (data6.count, ==, 1);
196   g_assert_cmpint (data6.start, ==, 6);
197   g_assert_cmpint (data6.end, ==, 6);
198   g_assert_cmpstr (data6.text, ==, "foobar");
199   g_free (data6.text);
200
201   /* Now check ordering: ::insert-text comes before ::notify */
202   g_assert_cmpint (data4.serial, <, data1.serial);
203   g_assert_cmpint (data4.serial, <, data2.serial);
204   g_assert_cmpint (data4.serial, <, data3.serial);
205
206   /* ... and ::changed comes after ::notify */
207   g_assert_cmpint (data6.serial, >, data1.serial);
208   g_assert_cmpint (data6.serial, >, data2.serial);
209   g_assert_cmpint (data6.serial, >, data3.serial);
210
211   g_object_unref (entry);
212 }
213
214 static void
215 test_delete (void)
216 {
217   GtkWidget *entry;
218   gint pos;
219   EntryData data1;
220   EntryData data2;
221   EntryData data3;
222   EntryData data4;
223   EntryData data5;
224   EntryData data6;
225
226   entry = gtk_entry_new ();
227   g_object_ref_sink (entry);
228
229   gtk_entry_set_text (GTK_ENTRY (entry), "foobar");
230   gtk_editable_set_position (GTK_EDITABLE (entry), -1);
231   pos = gtk_editable_get_position (GTK_EDITABLE (entry));
232   g_assert_cmpint (pos, ==, 6);
233
234   data1.count = 0;
235   data2.count = 0;
236   data3.count = 0;
237   data4.count = 0;
238   data5.count = 0;
239   data6.count = 0;
240   g_signal_connect (entry, "notify::cursor-position",
241                     G_CALLBACK (notify), &data1);
242   g_signal_connect (entry, "notify::selection-bound",
243                     G_CALLBACK (notify), &data2);
244   g_signal_connect (entry, "notify::text",
245                     G_CALLBACK (notify), &data3);
246   g_signal_connect (entry, "insert-text",
247                     G_CALLBACK (insert_text), &data4);
248   g_signal_connect (entry, "delete-text",
249                     G_CALLBACK (delete_text), &data5);
250   g_signal_connect (entry, "changed",
251                     G_CALLBACK (changed), &data6);
252
253   gtk_editable_delete_text (GTK_EDITABLE (entry), 0, 3);
254
255   pos = gtk_editable_get_position (GTK_EDITABLE (entry));
256   g_assert_cmpint (pos, ==, 3);
257
258   /* Check that notification for ::text, ::cursor-position and
259    * ::selection-bound happens in a consistent state after the
260    * change.
261    */
262   g_assert_cmpint (data1.count, ==, 1);
263   g_assert_cmpint (data1.start, ==, 3);
264   g_assert_cmpint (data1.end, ==, 3);
265   g_assert_cmpstr (data1.text, ==, "bar");
266   g_free (data1.text);
267
268   g_assert_cmpint (data2.count, ==, 1);
269   g_assert_cmpint (data2.start, ==, 3);
270   g_assert_cmpint (data2.end, ==, 3);
271   g_assert_cmpstr (data2.text, ==, "bar");
272   g_free (data2.text);
273
274   g_assert_cmpint (data3.count, ==, 1);
275   g_assert_cmpint (data3.start, ==, 3);
276   g_assert_cmpint (data3.end, ==, 3);
277   g_assert_cmpstr (data3.text, ==, "bar");
278   g_free (data3.text);
279
280   /* no insertion here */
281   g_assert_cmpint (data4.count, ==, 0);
282
283   /* Check that ::delete-text sees the state _before_ the insertion */
284   g_assert_cmpint (data5.count, ==, 1);
285   g_assert_cmpint (data5.start, ==, 6);
286   g_assert_cmpint (data5.end, ==, 6);
287   g_assert_cmpstr (data5.text, ==, "foobar");
288   g_assert_cmpint (data5.position, ==, 0);
289   g_assert_cmpint (data5.length, ==, 3);
290   g_free (data5.text);
291
292   /* Check that ::changed sees the post-change state */
293   g_assert_cmpint (data6.count, ==, 1);
294   g_assert_cmpint (data6.start, ==, 3);
295   g_assert_cmpint (data6.end, ==, 3);
296   g_assert_cmpstr (data6.text, ==, "bar");
297   g_free (data6.text);
298
299   /* Now check ordering: ::delete-text comes before ::notify */
300   g_assert_cmpint (data5.serial, <, data1.serial);
301   g_assert_cmpint (data5.serial, <, data2.serial);
302   g_assert_cmpint (data5.serial, <, data3.serial);
303
304   /* ... and ::changed comes after ::notify */
305   g_assert_cmpint (data6.serial, >, data1.serial);
306   g_assert_cmpint (data6.serial, >, data2.serial);
307   g_assert_cmpint (data6.serial, >, data3.serial);
308   g_object_unref (entry);
309 }
310
311 int
312 main (int   argc,
313       char *argv[])
314 {
315   gtk_test_init (&argc, &argv);
316
317   g_test_add_func ("/entry/delete", test_delete);
318   g_test_add_func ("/entry/insert", test_insert);
319
320   return g_test_run();
321 }