Updated atktext.c so that the initialized flag is set up properly when
[platform/upstream/atk.git] / atk / atktext.c
1 /* ATK - The Accessibility Toolkit for GTK+
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 "atktext.h"
21
22 enum {
23   TEXT_CHANGED,
24   CARET_MOVED,
25   LAST_SIGNAL
26 };
27
28 struct _AtkTextIfaceClass
29 {
30   GObjectClass parent;
31 };
32
33 typedef struct _AtkTextIfaceClass AtkTextIfaceClass;
34
35 static void atk_text_base_init (gpointer *g_class);
36
37 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
38
39 GType
40 atk_text_get_type ()
41 {
42   static GType type = 0;
43
44   if (!type) 
45     {
46       static const GTypeInfo tinfo =
47       {
48         sizeof (AtkTextIface),
49         (GBaseInitFunc) atk_text_base_init,
50         (GBaseFinalizeFunc) NULL,
51         (GClassInitFunc) NULL /* atk_text_interface_init */ ,
52         (GClassFinalizeFunc) NULL,
53
54       };
55
56       type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
57     }
58
59   return type;
60 }
61
62 static void
63 atk_text_base_init (gpointer *g_class)
64 {
65   static gboolean initialized = FALSE;
66
67   if (! initialized)
68     {
69 /*
70     ATK_TEXT_GET_IFACE(g_class)->text_changed = 0;
71     ATK_TEXT_GET_IFACE(g_class)->caret_changed = 0;
72 */
73
74   /* 
75    * Note that text_changed signal supports details "insert", "delete", 
76    * possibly "replace". 
77    */
78
79     atk_text_signals[TEXT_CHANGED] =
80       g_signal_newc ("text_changed",
81                      ATK_TYPE_TEXT,
82                      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
83                      G_STRUCT_OFFSET (AtkTextIface, text_changed), 
84                      (GSignalAccumulator) NULL, NULL,
85                      g_cclosure_marshal_VOID__VOID,
86                      G_TYPE_NONE,
87                      0, G_TYPE_NONE);
88
89     atk_text_signals[CARET_MOVED] =
90       g_signal_newc ("text_caret_moved",
91                      ATK_TYPE_TEXT,
92                      G_SIGNAL_RUN_LAST,
93                      G_STRUCT_OFFSET (AtkTextIface, caret_changed),
94                      (GSignalAccumulator) NULL, NULL,
95                      g_cclosure_marshal_VOID__INT,
96                      G_TYPE_NONE,
97                      1, G_TYPE_INT);
98
99   initialized = TRUE;
100   }
101 }
102
103 /**
104  * atk_text_get_text:
105  * @text: an #AtkText
106  * @start_offset: start position
107  * @end_offset: end position
108  *
109  * Returns: the text from @start_offset up to, but not including @end_offset.
110  **/
111 gchar*
112 atk_text_get_text (AtkText      *text,
113                    gint         start_offset,
114                    gint         end_offset)
115 {
116   AtkTextIface *iface;
117
118   g_return_val_if_fail (text != NULL, NULL);
119   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
120
121   iface = ATK_TEXT_GET_IFACE (text);
122
123   if (iface->get_text)
124     return (*(iface->get_text)) (text, start_offset, end_offset);
125   else
126     return NULL;
127 }
128
129 /**
130  * atk_text_get_character_at_offset
131  * @text: an #AtkText
132  * @offset: position
133  *
134  * Returns: the character at @offset.
135  **/
136 gunichar
137 atk_text_get_character_at_offset (AtkText      *text,
138                                   gint         offset)
139 {
140   AtkTextIface *iface;
141
142   g_return_val_if_fail (text != NULL, (gunichar) 0);
143   g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
144
145   iface = ATK_TEXT_GET_IFACE (text);
146
147   if (iface->get_character_at_offset)
148     return (*(iface->get_character_at_offset)) (text, offset);
149   else
150     return (gunichar) 0;
151 }
152
153 /**
154  * atk_text_get_text_after_offset
155  * @text: an #AtkText
156  * @offset: position
157  * @boundary_type: An #AtkTextBoundary
158  *
159  * Returns: the text after @offset up to the specified @boundary_type.
160  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
161  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
162  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
163  * will be the offset and will continue to the start of the next sentence. 
164  * The first word may not be a complete word. Similarly for 
165  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
166  * ATK_TEXT_BOUNDARY_LINE_END
167  **/
168 gchar*
169 atk_text_get_text_after_offset (AtkText          *text,
170                                 gint             offset,
171                                 AtkTextBoundary  boundary_type)
172 {
173   AtkTextIface *iface;
174
175   g_return_val_if_fail (text != NULL, NULL);
176   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
177
178   iface = ATK_TEXT_GET_IFACE (text);
179
180   if (iface->get_text_after_offset)
181     return (*(iface->get_text_after_offset)) (text, offset, boundary_type);
182   else
183     return NULL;
184 }
185
186 /**
187  * atk_text_get_text_at_offset
188  * @text: an #AtkText
189  * @offset: position
190  * @boundary_type: An #AtkTextBoundary
191  *
192  * Returns: the text at @offset up to the specified @boundary_type.
193  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START or 
194  * ATK_TEXT_BOUNDARY_WORD_END a complete word is returned; 
195  * if the boundary type is  ATK_TEXT_BOUNDARY_SENTENCE_START or 
196  * ATK_TEXT_BOUNDARY_SENTENCE_END a complete sentence
197  * is returned; if the boundary type is ATK_TEXT_BOUNDARY_LINE_START or
198  * ATK_TEXT_BOUNDARY_LINE_END a complete line is returned.
199  **/
200 gchar*
201 atk_text_get_text_at_offset (AtkText          *text,
202                              gint             offset,
203                              AtkTextBoundary  boundary_type)
204 {
205   AtkTextIface *iface;
206
207   g_return_val_if_fail (text != NULL, NULL);
208   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
209
210   iface = ATK_TEXT_GET_IFACE (text);
211
212   if (iface->get_text_at_offset)
213     return (*(iface->get_text_at_offset)) (text, offset, boundary_type);
214   else
215     return NULL;
216 }
217
218 /**
219  * atk_text_get_text_before_offset
220  * @text: an #AtkText
221  * @offset: position
222  * @boundary_type: An #AtkTextBoundary
223  *
224  * Returns: the text before @offset starting from the specified @boundary_type.
225  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
226  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
227  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
228  * will be at the start of the sentence, and will continue to the offset. 
229  * The last word may not be a complete word. Similarly for 
230  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
231  * ATK_TEXT_BOUNDARY_LINE_END
232  **/
233 gchar*
234 atk_text_get_text_before_offset (AtkText          *text,
235                                  gint             offset,
236                                  AtkTextBoundary  boundary_type)
237 {
238   AtkTextIface *iface;
239
240   g_return_val_if_fail (text != NULL, NULL);
241   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
242
243   iface = ATK_TEXT_GET_IFACE (text);
244
245   if (iface->get_text_before_offset)
246     return (*(iface->get_text_before_offset)) (text, offset, boundary_type);
247   else
248     return NULL;
249 }
250
251 /**
252  * atk_text_get_caret_offset
253  * @text: an #AtkText
254  *
255  * Returns: the position of the caret (cursor).
256  **/
257 gint
258 atk_text_get_caret_offset (AtkText *text)
259 {
260   AtkTextIface *iface;
261
262   g_return_val_if_fail (text != NULL, -1);
263   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
264
265   iface = ATK_TEXT_GET_IFACE (text);
266
267   if (iface->get_caret_offset)
268     return (*(iface->get_caret_offset)) (text);
269   else
270     return -1;
271 }
272
273 /**
274  * atk_text_get_row_col_at_offset
275  * @text: an #AtkText
276  * @offset: position
277  * @row: row number
278  * @col: column number
279  *
280  * Given an @offset, the @row and @col arguments are filled appropriately.
281  **/
282 void
283 atk_text_get_row_col_at_offset (AtkText *text,
284                                 gint offset,
285                                 gint *row,
286                                 gint *col)
287 {
288   AtkTextIface *iface;
289
290   g_return_if_fail (text != NULL);
291   g_return_if_fail (ATK_IS_TEXT (text));
292
293   iface = ATK_TEXT_GET_IFACE (text);
294
295   if (iface->get_row_col_at_offset)
296     (*(iface->get_row_col_at_offset)) (text, offset, row, col);
297   else
298     {
299       *row = 0;
300       *col = 0;
301     }
302 }
303
304 /**
305  * atk_text_get_range_attributes
306  * @text: an #AtkText
307  * @start_offset: start position
308  * @end_offset: end position
309  *
310  * Returns a #PangoAttrList with the text attributes between the
311  * @start_offset and the @end_offset.
312  **/
313 PangoAttrList*
314 atk_text_get_range_attributes (AtkText *text,
315                                gint start_offset,
316                                gint end_offset)
317 {
318   AtkTextIface *iface;
319
320   g_return_val_if_fail (text != NULL, NULL);
321   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
322
323   iface = ATK_TEXT_GET_IFACE (text);
324
325   if (iface->get_range_attributes)
326     return (*(iface->get_range_attributes)) (text, start_offset, end_offset);
327   else
328     return NULL;
329 }
330
331 /**
332  * atk_text_get_character_extents
333  * @text: an #AtkText
334  * @offset: position
335  * @x: x-position of character
336  * @y: y-position of character
337  * @length: length of character
338  * @width: width of character
339  *
340  * Given an @offset, the @x, @y, @length, and @width values are filled
341  * appropriately.
342  **/
343 void
344 atk_text_get_character_extents (AtkText *text,
345                                 gint offset,
346                                 gint *x,
347                                 gint *y,
348                                 gint *length,
349                                 gint *width)
350 {
351   AtkTextIface *iface;
352
353   g_return_if_fail (text != NULL);
354   g_return_if_fail (ATK_IS_TEXT (text));
355
356   iface = ATK_TEXT_GET_IFACE (text);
357
358   if (iface->get_character_extents)
359     (*(iface->get_character_extents)) (text, offset, x, y, length, width);
360   else
361     {
362       *x = 0;
363       *x = 0;
364       *length = 0;
365       *width = 0;
366     }
367 }
368
369 /**
370  * atk_text_get_character_count
371  * @text: an #AtkText
372  *
373  * Returns: the number of characters.
374  **/
375 gint
376 atk_text_get_character_count (AtkText *text)
377 {
378   AtkTextIface *iface;
379
380   g_return_val_if_fail (text != NULL, -1);
381   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
382
383   iface = ATK_TEXT_GET_IFACE (text);
384
385   if (iface->get_character_count)
386     return (*(iface->get_character_count)) (text);
387   else
388     return -1;
389 }
390
391 /**
392  * atk_text_get_offset_at_point
393  * @text: an #AtkText
394  * @x: x-position of character
395  * @y: y-position of character
396  *
397  * Returns: the offset to the character which is located at
398  * the specified @x and @y coordinates.
399  **/
400 gint
401 atk_text_get_offset_at_point (AtkText *text,
402                               gint x,
403                               gint y)
404 {
405   AtkTextIface *iface;
406
407   g_return_val_if_fail (text != NULL, -1);
408   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
409
410   iface = ATK_TEXT_GET_IFACE (text);
411
412   if (iface->get_offset_at_point)
413     return (*(iface->get_offset_at_point)) (text, x, y);
414   else
415     return -1;
416 }
417
418 /**
419  * atk_text_get_selected_text
420  * @text: an #AtkText
421  *
422  * Returns: the selected text.
423  **/
424 gchar*
425 atk_text_get_selected_text (AtkText *text)
426 {
427   AtkTextIface *iface;
428
429   g_return_val_if_fail (text != NULL, NULL);
430   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
431
432   iface = ATK_TEXT_GET_IFACE (text);
433
434   if (iface->get_selected_text)
435     return (*(iface->get_selected_text)) (text);
436   else
437     return NULL;
438 }
439
440 /**
441  * atk_text_get_selection_bounds
442  * @text: an #AtkText
443  * @start_offset: start position
444  * @end_offset: end position
445  *
446  * @start_offset and @end_offset are filled with the
447  * current selection bounds.
448  **/
449 void
450 atk_text_get_selection_bounds (AtkText *text,
451                                gint    *start_offset,
452                                gint    *end_offset)
453 {
454   AtkTextIface *iface;
455
456   g_return_if_fail (text != NULL);
457   g_return_if_fail (ATK_IS_TEXT (text));
458
459   iface = ATK_TEXT_GET_IFACE (text);
460
461   if (iface->get_selection_bounds)
462     (*(iface->get_selection_bounds)) (text, start_offset, end_offset);
463   else
464   {
465     *start_offset = 0;
466     *end_offset = 0;
467   }
468 }
469
470 /**
471  * atk_text_set_selection_bounds
472  * @text: an #AtkText
473  * @start_offset: start position
474  * @end_offset: end position
475  *
476  * The selection bounds are set to the specified @start_offset
477  * and @end_offset values.
478  * 
479  * Returns: %TRUE if success, %FALSE otherwise.
480  **/
481 gboolean
482 atk_text_set_selection_bounds (AtkText *text,
483                                gint    start_offset,
484                                gint    end_offset)
485 {
486   AtkTextIface *iface;
487
488   g_return_val_if_fail (text != NULL, FALSE);
489   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
490
491   iface = ATK_TEXT_GET_IFACE (text);
492
493   if (iface->set_selection_bounds)
494     {
495       return (*(iface->set_selection_bounds)) (text, start_offset, end_offset);
496     }
497   else
498     {
499       return FALSE;
500     }
501 }
502
503 /**
504  * atk_text_set_caret_offset
505  * @text: an #AtkText
506  * @offset: position
507  *
508  * Sets the caret (cursor) position to the specified @offset.
509  *
510  * Returns: %TRUE if success, %FALSE otherwise.
511  **/
512 gboolean
513 atk_text_set_caret_offset (AtkText *text,
514                            gint    offset)
515 {
516   AtkTextIface *iface;
517
518   g_return_val_if_fail (text != NULL, FALSE);
519   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
520
521   iface = ATK_TEXT_GET_IFACE (text);
522
523   if (iface->set_caret_offset)
524     {
525       return (*(iface->set_caret_offset)) (text, offset);
526     }
527   else
528     {
529       return FALSE;
530     }
531 }