ea954ab43fd55023352fdba112ec89a3d5a3abb6
[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 #include "atkmarshal.h"
22
23 enum {
24   TEXT_CHANGED,
25   CARET_MOVED,
26   LAST_SIGNAL
27 };
28
29 static const gchar * text_attr_name[] = {
30   "left_margin",
31   "right_margin",
32   "indent",
33   "invisible",
34   "editable",
35   "pixels_above_lines",
36   "pixels_below_lines",
37   "pixels_inside_wrap",
38   "bg_full_height",
39   "rise",
40   "underline",
41   "strikethrough",
42   "size",
43   "scale",
44   "weight",
45   "language",
46   "family_name",
47   "bg_color",
48   "fg_color",
49   "bg_stipple",
50   "fg_stipple",
51   "wrap_mode",
52   "direction",
53   "justification",
54   "stretch",
55   "variant",
56   "slant_style",
57 };
58
59 static const gchar *bool[] = {"false",
60                               "true"};
61 static const gchar *style[] = {"normal",
62                                "oblique",
63                                "italic"};
64 static const gchar *variant[] = {"normal",
65                                  "small_caps"};
66 static const gchar *stretch[] = {"ultra_condensed",
67                                  "extra_condensed",
68                                  "condensed",
69                                  "semi_condensed",
70                                  "normal",
71                                  "semi_expanded",
72                                  "expanded",
73                                  "extra_expanded",
74                                  "ultra_expanded"};
75 static const gchar *justification[] = {"left",
76                                        "right",
77                                        "center",
78
79                                        "fill"};
80 static const gchar *direction[] = {"none",
81                                    "ltr",
82                                    "rtl"};
83 static const gchar *wrap_mode[] = {"none",
84                                    "char",
85                                    "word"};
86 static const gchar *underline[] = {"none",
87                                    "single",
88                                    "double",
89                                    "low"};
90
91 struct _AtkTextIfaceClass
92 {
93   GObjectClass parent;
94 };
95
96 typedef struct _AtkTextIfaceClass AtkTextIfaceClass;
97
98 static void atk_text_base_init (gpointer *g_class);
99
100 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
101
102 GType
103 atk_text_get_type ()
104 {
105   static GType type = 0;
106
107   if (!type) 
108     {
109       static const GTypeInfo tinfo =
110       {
111         sizeof (AtkTextIface),
112         (GBaseInitFunc) atk_text_base_init,
113         (GBaseFinalizeFunc) NULL,
114         (GClassInitFunc) NULL /* atk_text_interface_init */ ,
115         (GClassFinalizeFunc) NULL,
116
117       };
118
119       type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
120     }
121
122   return type;
123 }
124
125 static void
126 atk_text_base_init (gpointer *g_class)
127 {
128   static gboolean initialized = FALSE;
129   
130   if (! initialized)
131     {
132       /* 
133        * Note that text_changed signal supports details "insert", "delete", 
134        * possibly "replace". 
135        */
136       
137       atk_text_signals[TEXT_CHANGED] =
138         g_signal_new ("text_changed",
139                       ATK_TYPE_TEXT,
140                       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
141                       G_STRUCT_OFFSET (AtkTextIface, text_changed), 
142                       (GSignalAccumulator) NULL, NULL,
143                       atk_marshal_VOID__INT_INT,
144                       G_TYPE_NONE,
145                       2, G_TYPE_INT, G_TYPE_INT);
146       
147       atk_text_signals[CARET_MOVED] =
148         g_signal_new ("text_caret_moved",
149                       ATK_TYPE_TEXT,
150                       G_SIGNAL_RUN_LAST,
151                       G_STRUCT_OFFSET (AtkTextIface, caret_changed),
152                       (GSignalAccumulator) NULL, NULL,
153                       g_cclosure_marshal_VOID__INT,
154                       G_TYPE_NONE,
155                       1, G_TYPE_INT);
156       
157       initialized = TRUE;
158     }
159 }
160
161 /**
162  * atk_text_get_text:
163  * @text: an #AtkText
164  * @start_offset: start position
165  * @end_offset: end position
166  *
167  * Gets the specified text.
168  *
169  * Returns: the text from @start_offset up to, but not including @end_offset.
170  **/
171 gchar*
172 atk_text_get_text (AtkText      *text,
173                    gint         start_offset,
174                    gint         end_offset)
175 {
176   AtkTextIface *iface;
177   
178   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
179
180   iface = ATK_TEXT_GET_IFACE (text);
181
182   if (iface->get_text)
183     return (*(iface->get_text)) (text, start_offset, end_offset);
184   else
185     return NULL;
186 }
187
188 /**
189  * atk_text_get_character_at_offset:
190  * @text: an #AtkText
191  * @offset: position
192  *
193  * Gets the specified text.
194  *
195  * Returns: the character at @offset.
196  **/
197 gunichar
198 atk_text_get_character_at_offset (AtkText      *text,
199                                   gint         offset)
200 {
201   AtkTextIface *iface;
202
203   g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
204
205   iface = ATK_TEXT_GET_IFACE (text);
206
207   if (iface->get_character_at_offset)
208     return (*(iface->get_character_at_offset)) (text, offset);
209   else
210     return (gunichar) 0;
211 }
212
213 /**
214  * atk_text_get_text_after_offset:
215  * @text: an #AtkText
216  * @offset: position
217  * @boundary_type: An #AtkTextBoundary
218  * @start_offset: the start offset of the returned string.
219  * @end_offset: the end offset of the returned string.
220  *
221  * Gets the specified text.
222  *
223  * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character after the 
224  * offset is returned.
225  *
226  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
227  * is from the word start after the offset to the next word start.
228  *
229  * The returned string will contain the word after the offset if the offset 
230  * is inside a word or if the offset is not inside a word.
231  *
232  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
233  * is from the word end at or after the offset to the next work end.
234  *
235  * The returned string will contain the word after the offset if the offset
236  * is inside a word and will contain the word after the word after the offset
237  * if the offset is not inside a word.
238  *
239  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
240  * string is from the sentence start after the offset to the next sentence
241  * start.
242  *
243  * The returned string will contain the sentence after the offset if the offset
244  * is inside a sentence or if the offset is not inside a sentence.
245  *
246  * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
247  * is from the sentence end at or after the offset to the next sentence end.
248  *
249  * The returned string will contain the sentence after the offset if the offset
250  * is inside a sentence and will contain the sentence after the sentence
251  * after the offset if the offset is not inside a sentence.
252  *
253  * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
254  * string is from the line start after the offset to the next line start.
255  *
256  * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
257  * is from the line end at or after the offset to the next line start.
258  *
259  * Returns: the text after @offset bounded by the specified @boundary_type.
260  **/
261 gchar*
262 atk_text_get_text_after_offset (AtkText          *text,
263                                 gint             offset,
264                                 AtkTextBoundary  boundary_type,
265                                 gint             *start_offset,
266                                 gint             *end_offset)
267 {
268   AtkTextIface *iface;
269   gint local_start_offset, local_end_offset;
270   gint *real_start_offset, *real_end_offset;
271
272   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
273
274   if (start_offset)
275     real_start_offset = start_offset;
276   else
277     real_start_offset = &local_start_offset;
278   if (end_offset)
279     real_end_offset = end_offset;
280   else
281     real_end_offset = &local_end_offset;
282
283   iface = ATK_TEXT_GET_IFACE (text);
284
285   if (iface->get_text_after_offset)
286     return (*(iface->get_text_after_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
287   else
288     return NULL;
289 }
290
291 /**
292  * atk_text_get_text_at_offset:
293  * @text: an #AtkText
294  * @offset: position
295  * @boundary_type: An #AtkTextBoundary
296  * @start_offset: the start offset of the returned string.
297  * @end_offset: the end offset of the returned string.
298  *
299  * Gets the specified text.
300  *
301  * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character at the
302  * offset is returned.
303  *
304  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
305  * is from the word start at or before the offset to the word start after 
306  * the offset.
307  *
308  * The returned string will contain the word at the offset if the offset
309  * is inside a word and will contain the word before the offset if the 
310  * offset is not inside a word.
311  *
312  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
313  * is from the word end before the offset to the word end at or after the
314  * offset.
315  *
316  * The returned string will contain the word at the offset if the offset
317  * is inside a word and will contain the word after to the offset if the 
318  * offset is not inside a word.
319  *
320  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
321  * string is from the sentence start at or before the offset to the sentence
322  * start after the offset.
323  *
324  * The returned string will contain the sentence at the offset if the offset
325  * is inside a sentence and will contain the sentence before the offset 
326  * if the offset is not inside a sentence.
327  *
328  * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
329  * is from the sentence end before the offset to the sentence end at or
330  * after the offset.
331  *
332  * The returned string will contain the sentence at the offset if the offset
333  * is inside a sentence and will contain the sentence after the offset 
334  * if the offset is not inside a sentence.
335  *
336  * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
337  * string is from the line start at or before the offset to the line
338  * start after the offset.
339  *
340  * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
341  * is from the line end before the offset to the line end at or after
342  * the offset.
343  *
344  * Returns: the text at @offset bounded by the specified @boundary_type.
345  **/
346 gchar*
347 atk_text_get_text_at_offset (AtkText          *text,
348                              gint             offset,
349                              AtkTextBoundary  boundary_type,
350                              gint             *start_offset,
351                              gint             *end_offset)
352 {
353   AtkTextIface *iface;
354   gint local_start_offset, local_end_offset;
355   gint *real_start_offset, *real_end_offset;
356
357   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
358
359   if (start_offset)
360     real_start_offset = start_offset;
361   else
362     real_start_offset = &local_start_offset;
363   if (end_offset)
364     real_end_offset = end_offset;
365   else
366     real_end_offset = &local_end_offset;
367
368   iface = ATK_TEXT_GET_IFACE (text);
369
370   if (iface->get_text_at_offset)
371     return (*(iface->get_text_at_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
372   else
373     return NULL;
374 }
375
376 /**
377  * atk_text_get_text_before_offset:
378  * @text: an #AtkText
379  * @offset: position
380  * @boundary_type: An #AtkTextBoundary
381  * @start_offset: the start offset of the returned string.
382  * @end_offset: the end offset of the returned string.
383  *
384  * Gets the specified text.
385  *
386  * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character before the
387  * offset is returned.
388  *
389  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
390  * is from the word start before the word start before the offset to 
391  * the word start before the offset.
392  *
393  * The returned string will contain the word before the offset if the offset
394  * is inside a word and will contain the word before the word before the 
395  * offset if the offset is not inside a word.
396  *
397  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
398  * is from the word end before the word end at or before the offset to the 
399  * word end at or before the offset.
400  *
401  * The returned string will contain the word before the offset if the offset
402  * is inside a word or if the offset is not inside a word.
403  *
404  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
405  * string is from the sentence start before the sentence start before 
406  * the offset to the sentence start before the offset.
407  *
408  * The returned string will contain the sentence before the offset if the 
409  * offset is inside a sentence and will contain the sentence before the 
410  * sentence before the offset if the offset is not inside a sentence.
411  *
412  * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
413  * is from the sentence end before the sentence end at or before the offset to 
414  * the sentence end at or before the offset.
415  *
416  * The returned string will contain the sentence before the offset if the 
417  * offset is inside a sentence or if the offset is not inside a sentence.
418  *
419  * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
420  * string is from the line start before the line start ar or before the offset 
421  * to the line start ar or before the offset.
422  *
423  * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
424  * is from the line end before the line end before the offset to the 
425  * line end before the offset.
426  *
427  * Returns: the text before @offset bounded by the specified @boundary_type.
428  **/
429 gchar*
430 atk_text_get_text_before_offset (AtkText          *text,
431                                  gint             offset,
432                                  AtkTextBoundary  boundary_type,
433                                  gint             *start_offset,
434                                  gint             *end_offset)
435 {
436   AtkTextIface *iface;
437   gint local_start_offset, local_end_offset;
438   gint *real_start_offset, *real_end_offset;
439
440   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
441
442   if (start_offset)
443     real_start_offset = start_offset;
444   else
445     real_start_offset = &local_start_offset;
446   if (end_offset)
447     real_end_offset = end_offset;
448   else
449     real_end_offset = &local_end_offset;
450
451   iface = ATK_TEXT_GET_IFACE (text);
452
453   if (iface->get_text_before_offset)
454     return (*(iface->get_text_before_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
455   else
456     return NULL;
457 }
458
459 /**
460  * atk_text_get_caret_offset:
461  * @text: an #AtkText
462  *
463  * Gets the offset position of the caret (cursor).
464  *
465  * Returns: the offset position of the caret (cursor).
466  **/
467 gint
468 atk_text_get_caret_offset (AtkText *text)
469 {
470   AtkTextIface *iface;
471
472   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
473
474   iface = ATK_TEXT_GET_IFACE (text);
475
476   if (iface->get_caret_offset)
477     return (*(iface->get_caret_offset)) (text);
478   else
479     return -1;
480 }
481
482 /**
483  * atk_text_get_character_extents:
484  * @text: an #AtkText
485  * @offset: position
486  * @x: x-position of character
487  * @y: y-position of character
488  * @width: width of character
489  * @height: height of character
490  * @coords: specify whether coordinates are relative to the screen or widget window 
491  *
492  * Given an @offset, the @x, @y, @width, and @height values are filled
493  * appropriately. 
494  **/
495 void
496 atk_text_get_character_extents (AtkText *text,
497                                 gint offset,
498                                 gint *x,
499                                 gint *y,
500                                 gint *width,
501                                 gint *height,
502                                 AtkCoordType coords)
503 {
504   AtkTextIface *iface;
505   gint local_x, local_y, local_width, local_height;
506   gint *real_x, *real_y, *real_width, *real_height;
507
508   g_return_if_fail (ATK_IS_TEXT (text));
509
510   if (x)
511     real_x = x;
512   else
513     real_x = &local_x;
514   if (y)
515     real_y = y;
516   else
517     real_y = &local_y;
518   if (width)
519     real_width = width;
520   else
521     real_width = &local_width;
522   if (height)
523     real_height = height;
524   else
525     real_height = &local_height;
526
527   iface = ATK_TEXT_GET_IFACE (text);
528
529   if (iface->get_character_extents)
530     (*(iface->get_character_extents)) (text, offset, real_x, real_y, real_width, real_height, coords);
531   else
532     {
533       *real_x = 0;
534       *real_y = 0;
535       *real_width = 0;
536       *real_height = 0;
537     }
538 }
539
540 /**
541  *atk_text_get_run_attributes:
542  *@text: an #AtkText
543  *@offset: the offset at which to get the attributes
544  *@start_offset: the address to put the start offset of the range
545  *@end_offset: the address to put the end offset of the range
546  *
547  *Creates an #AtkAttributeSet which consists of the attributes explicitly
548  *set at the position @offset in the text. @start_offset and @end_offset are
549  *set to the start and end of the range around @offset where the attributes are
550  *invariant. See the enum AtkTextAttribute for types of text attributes that 
551  *can be returned. Note that other attributes may also be returned.
552  *
553  *Returns: an #AtkAttributeSet which contains the attributes explicitly set
554  *at @offset. This #AtkAttributeSet should be freed by a call to
555  *atk_attribute_set_free().
556  **/
557 AtkAttributeSet* 
558 atk_text_get_run_attributes (AtkText          *text,
559                              gint             offset,
560                              gint             *start_offset,
561                              gint             *end_offset)
562 {
563   AtkTextIface *iface;
564   gint local_start_offset, local_end_offset;
565   gint *real_start_offset, *real_end_offset;
566
567   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
568
569   if (start_offset)
570     real_start_offset = start_offset;
571   else
572     real_start_offset = &local_start_offset;
573   if (end_offset)
574     real_end_offset = end_offset;
575   else
576     real_end_offset = &local_end_offset;
577
578   iface = ATK_TEXT_GET_IFACE (text);
579
580   if (iface->get_run_attributes)
581     return (*(iface->get_run_attributes)) (text, offset, real_start_offset, real_end_offset);
582   else
583     return NULL;
584 }
585
586 /**
587  *atk_text_get_default_attributes:
588  *@text: an #AtkText
589  *
590  *Creates an #AtkAttributeSet which consists of the default values of
591  *attributes for the text. See the enum AtkTextAttribute for types of text 
592  *attributes that can be returned. Note that other attributes may also be 
593  *returned.
594  *
595  *Returns: an #AtkAttributeSet which contains the default values of attributes.
596  *at @offset. This #AtkAttributeSet should be freed by a call to
597  *atk_attribute_set_free().
598  */
599 AtkAttributeSet* 
600 atk_text_get_default_attributes (AtkText          *text)
601 {
602   AtkTextIface *iface;
603
604   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
605
606   iface = ATK_TEXT_GET_IFACE (text);
607
608   if (iface->get_default_attributes)
609     return (*(iface->get_default_attributes)) (text);
610   else
611     return NULL;
612 }
613
614 /**
615  * atk_text_get_character_count:
616  * @text: an #AtkText
617  *
618  * Gets the character count.
619  *
620  * Returns: the number of characters.
621  **/
622 gint
623 atk_text_get_character_count (AtkText *text)
624 {
625   AtkTextIface *iface;
626
627   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
628
629   iface = ATK_TEXT_GET_IFACE (text);
630
631   if (iface->get_character_count)
632     return (*(iface->get_character_count)) (text);
633   else
634     return -1;
635 }
636
637 /**
638  * atk_text_get_offset_at_point:
639  * @text: an #AtkText
640  * @x: screen x-position of character
641  * @y: screen y-position of character
642  * @coords: specify whether coordinates are relative to the screen or
643  * widget window 
644  *
645  * Gets the offset of the character located at coordinates @x and @y. @x and @y
646  * are interpreted as being relative to the screen or this widget's window
647  * depending on @coords.
648  *
649  * Returns: the offset to the character which is located at
650  * the specified @x and @y coordinates.
651  **/
652 gint
653 atk_text_get_offset_at_point (AtkText *text,
654                               gint x,
655                               gint y,
656                               AtkCoordType coords)
657 {
658   AtkTextIface *iface;
659
660   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
661
662   iface = ATK_TEXT_GET_IFACE (text);
663
664   if (iface->get_offset_at_point)
665     return (*(iface->get_offset_at_point)) (text, x, y, coords);
666   else
667     return -1;
668 }
669
670 /**
671  * atk_text_get_n_selections:
672  * @text: an #AtkText
673  *
674  * Gets the number of selected regions.
675  *
676  * Returns: The number of selected regions, or -1 if a failure
677  *   occurred.
678  **/
679 gint
680 atk_text_get_n_selections (AtkText *text)
681 {
682   AtkTextIface *iface;
683
684   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
685
686   iface = ATK_TEXT_GET_IFACE (text);
687
688   if (iface->get_n_selections)
689     return (*(iface->get_n_selections)) (text);
690   else
691     return -1;
692 }
693
694 /**
695  * atk_text_get_selection:
696  * @text: an #AtkText
697  * @selection_num: The selection number.  The selected regions are
698  * assigned numbers that correspond to how far the region is from the
699  * start of the text.  The selected region closest to the beginning
700  * of the text region is assigned the number 0, etc.  Note that adding,
701  * moving or deleting a selected region can change the numbering.
702  * @start_offset: passes back the start position of the selected region
703  * @end_offset: passes back the end position of the selected region
704  *
705  * Gets the text from the specified selection.
706  *
707  * Returns: the selected text.
708  **/
709 gchar*
710 atk_text_get_selection (AtkText *text, 
711                         gint    selection_num,
712                         gint    *start_offset,
713                         gint    *end_offset)
714 {
715   AtkTextIface *iface;
716   gint local_start_offset, local_end_offset;
717   gint *real_start_offset, *real_end_offset;
718
719   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
720
721   if (start_offset)
722     real_start_offset = start_offset;
723   else
724     real_start_offset = &local_start_offset;
725   if (end_offset)
726     real_end_offset = end_offset;
727   else
728     real_start_offset = &local_end_offset;
729
730   iface = ATK_TEXT_GET_IFACE (text);
731
732   if (iface->get_selection)
733   {
734     return (*(iface->get_selection)) (text, selection_num,
735        real_start_offset, real_end_offset);
736   }
737   else
738     return NULL;
739 }
740
741 /**
742  * atk_text_add_selection:
743  * @text: an #AtkText
744  * @start_offset: the start position of the selected region
745  * @end_offset: the end position of the selected region
746  *
747  * Adds a selection bounded by the specified offsets.
748  *
749  * Returns: %TRUE if success, %FALSE otherwise
750  **/
751 gboolean
752 atk_text_add_selection (AtkText *text, 
753                         gint    start_offset,
754                         gint    end_offset)
755 {
756   AtkTextIface *iface;
757
758   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
759
760   iface = ATK_TEXT_GET_IFACE (text);
761
762   if (iface->add_selection)
763     return (*(iface->add_selection)) (text, start_offset, end_offset);
764   else
765     return FALSE;
766 }
767
768 /**
769  * atk_text_remove_selection:
770  * @text: an #AtkText
771  * @selection_num: The selection number.  The selected regions are
772  * assigned numbers that correspond to how far the region is from the
773  * start of the text.  The selected region closest to the beginning
774  * of the text region is assigned the number 0, etc.  Note that adding,
775  * moving or deleting a selected region can change the numbering.
776  *
777  * Removes the specified selection.
778  *
779  * Returns: %TRUE if success, %FALSE otherwise
780  **/
781 gboolean
782 atk_text_remove_selection (AtkText *text, 
783                            gint    selection_num)
784 {
785   AtkTextIface *iface;
786
787   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
788
789   iface = ATK_TEXT_GET_IFACE (text);
790
791   if (iface->remove_selection)
792     return (*(iface->remove_selection)) (text, selection_num);
793   else
794     return FALSE;
795 }
796
797 /**
798  * atk_text_set_selection:
799  * @text: an #AtkText
800  * @selection_num: The selection number.  The selected regions are
801  * assigned numbers that correspond to how far the region is from the
802  * start of the text.  The selected region closest to the beginning
803  * of the text region is assigned the number 0, etc.  Note that adding,
804  * moving or deleting a selected region can change the numbering.
805  * @start_offset: the new start position of the selection
806  * @end_offset: the new end position of the selection
807  *
808  * Changes the start and end offset of the specified selection.
809  *
810  * Returns: %TRUE if success, %FALSE otherwise
811  **/
812 gboolean
813 atk_text_set_selection (AtkText *text, 
814                         gint    selection_num,
815                         gint    start_offset, 
816                         gint    end_offset)
817 {
818   AtkTextIface *iface;
819
820   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
821
822   iface = ATK_TEXT_GET_IFACE (text);
823
824   if (iface->set_selection)
825   {
826     return (*(iface->set_selection)) (text, selection_num,
827        start_offset, end_offset);
828   }
829   else
830     return FALSE;
831 }
832
833 /**
834  * atk_text_set_caret_offset:
835  * @text: an #AtkText
836  * @offset: position
837  *
838  * Sets the caret (cursor) position to the specified @offset.
839  *
840  * Returns: %TRUE if success, %FALSE otherwise.
841  **/
842 gboolean
843 atk_text_set_caret_offset (AtkText *text,
844                            gint    offset)
845 {
846   AtkTextIface *iface;
847
848   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
849
850   iface = ATK_TEXT_GET_IFACE (text);
851
852   if (iface->set_caret_offset)
853     {
854       return (*(iface->set_caret_offset)) (text, offset);
855     }
856   else
857     {
858       return FALSE;
859     }
860 }
861
862 /**
863  * atk_attribute_set_free:
864  * @attrib_set: The #AtkAttributeSet to free
865  *
866  * Frees the memory used by an #AtkAttributeSet, including all its
867  * #AtkAttributes.
868  **/
869 void
870 atk_attribute_set_free(AtkAttributeSet *attrib_set)
871 {
872   GSList *temp;
873
874   temp = attrib_set;
875
876   while (temp != NULL)
877     {
878       AtkAttribute *att;
879
880       att = temp->data;
881
882       g_free (att->name);
883       g_free (att->value);
884       g_free (att);
885       temp = temp->next;
886     }
887   g_slist_free (attrib_set);
888 }
889
890 /**
891  * atk_attribute_get_name:
892  * @attr: The #AtkTextAttribute whose name is required
893  *
894  * Gets the name corresponding to the #AtkTextAttribute
895  *
896  * Returns: a string containing the name; this string should not be freed
897  **/
898 G_CONST_RETURN gchar*
899 atk_attribute_get_name (AtkTextAttribute attr)
900 {
901   g_assert (attr >= 0 && attr <= ATK_TEXT_ATTR_STYLE);
902   return text_attr_name[attr];
903 }
904
905 /**
906  * atk_attribute_get_value:
907  * @attr: The #AtkTextAttribute for which a value is required
908  * @index: The index of the required value
909  *
910  * Gets the value for the index of the #AtkTextAttribute
911  *
912  * Returns: a string containing the value; this string should not be freed;
913  * NULL is returned if there are no values maintained for the attr value. 
914  **/
915 G_CONST_RETURN gchar*
916 atk_attribute_get_value (AtkTextAttribute attr,
917                          gint             index)
918 {
919   switch (attr)
920     {
921     case ATK_TEXT_ATTR_INVISIBLE:
922     case ATK_TEXT_ATTR_EDITABLE:
923     case ATK_TEXT_ATTR_BG_FULL_HEIGHT:
924     case ATK_TEXT_ATTR_STRIKETHROUGH:
925     case ATK_TEXT_ATTR_BG_STIPPLE:
926     case ATK_TEXT_ATTR_FG_STIPPLE:
927       g_assert (index >= 0 && index < 2);
928       return bool[index];
929     case ATK_TEXT_ATTR_UNDERLINE:
930       g_assert (index >= 0 && index < 4);
931       return underline[index];
932     case ATK_TEXT_ATTR_WRAP_MODE:
933       g_assert (index >= 0 && index < 3);
934       return wrap_mode[index];
935     case ATK_TEXT_ATTR_DIRECTION:
936       g_assert (index >= 0 && index < 3);
937       return direction[index];
938     case ATK_TEXT_ATTR_JUSTIFICATION:
939       g_assert (index >= 0 && index < 3);
940       return justification[index];
941     case ATK_TEXT_ATTR_STRETCH:
942       g_assert (index >= 0 && index < 9);
943       return stretch[index];
944     case ATK_TEXT_ATTR_VARIANT:
945       g_assert (index >= 0 && index < 2);
946       return variant[index];
947     case ATK_TEXT_ATTR_STYLE:
948       g_assert (index >= 0 && index < 3);
949       return style[index];
950     default:
951       return NULL;
952    }
953 }