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