Correct order of attribute names in text_attr_name array.
[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  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
223  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
224  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
225  * will be the offset and will continue to the start of the next sentence. 
226  * The first word may not be a complete word. Similarly for 
227  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
228  * ATK_TEXT_BOUNDARY_LINE_END
229  *
230  * Returns: the text after @offset up to the specified @boundary_type.
231  **/
232 gchar*
233 atk_text_get_text_after_offset (AtkText          *text,
234                                 gint             offset,
235                                 AtkTextBoundary  boundary_type,
236                                 gint             *start_offset,
237                                 gint             *end_offset)
238 {
239   AtkTextIface *iface;
240   gint local_start_offset, local_end_offset;
241   gint *real_start_offset, *real_end_offset;
242
243   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
244
245   if (start_offset)
246     real_start_offset = start_offset;
247   else
248     real_start_offset = &local_start_offset;
249   if (end_offset)
250     real_end_offset = end_offset;
251   else
252     real_end_offset = &local_end_offset;
253
254   iface = ATK_TEXT_GET_IFACE (text);
255
256   if (iface->get_text_after_offset)
257     return (*(iface->get_text_after_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
258   else
259     return NULL;
260 }
261
262 /**
263  * atk_text_get_text_at_offset:
264  * @text: an #AtkText
265  * @offset: position
266  * @boundary_type: An #AtkTextBoundary
267  * @start_offset: the start offset of the returned string.
268  * @end_offset: the end offset of the returned string.
269  *
270  * Gets the specified text.
271  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START or 
272  * ATK_TEXT_BOUNDARY_WORD_END a complete word is returned; 
273  * if the boundary type is  ATK_TEXT_BOUNDARY_SENTENCE_START or 
274  * ATK_TEXT_BOUNDARY_SENTENCE_END a complete sentence
275  * is returned; if the boundary type is ATK_TEXT_BOUNDARY_LINE_START or
276  * ATK_TEXT_BOUNDARY_LINE_END a complete line is returned.
277  *
278  * Returns: the text at @offset up to the specified @boundary_type.
279  **/
280 gchar*
281 atk_text_get_text_at_offset (AtkText          *text,
282                              gint             offset,
283                              AtkTextBoundary  boundary_type,
284                              gint             *start_offset,
285                              gint             *end_offset)
286 {
287   AtkTextIface *iface;
288   gint local_start_offset, local_end_offset;
289   gint *real_start_offset, *real_end_offset;
290
291   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
292
293   if (start_offset)
294     real_start_offset = start_offset;
295   else
296     real_start_offset = &local_start_offset;
297   if (end_offset)
298     real_end_offset = end_offset;
299   else
300     real_end_offset = &local_end_offset;
301
302   iface = ATK_TEXT_GET_IFACE (text);
303
304   if (iface->get_text_at_offset)
305     return (*(iface->get_text_at_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
306   else
307     return NULL;
308 }
309
310 /**
311  * atk_text_get_text_before_offset:
312  * @text: an #AtkText
313  * @offset: position
314  * @boundary_type: An #AtkTextBoundary
315  * @start_offset: the start offset of the returned string.
316  * @end_offset: the end offset of the returned string.
317  *
318  * Gets the specified text.
319  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
320  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
321  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
322  * will be at the start of the sentence, and will continue to the offset. 
323  * The last word may not be a complete word. Similarly for 
324  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
325  * ATK_TEXT_BOUNDARY_LINE_END
326  *
327  * Returns: the text before @offset starting from the specified @boundary_type.
328  **/
329 gchar*
330 atk_text_get_text_before_offset (AtkText          *text,
331                                  gint             offset,
332                                  AtkTextBoundary  boundary_type,
333                                  gint             *start_offset,
334                                  gint             *end_offset)
335 {
336   AtkTextIface *iface;
337   gint local_start_offset, local_end_offset;
338   gint *real_start_offset, *real_end_offset;
339
340   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
341
342   if (start_offset)
343     real_start_offset = start_offset;
344   else
345     real_start_offset = &local_start_offset;
346   if (end_offset)
347     real_end_offset = end_offset;
348   else
349     real_end_offset = &local_end_offset;
350
351   iface = ATK_TEXT_GET_IFACE (text);
352
353   if (iface->get_text_before_offset)
354     return (*(iface->get_text_before_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
355   else
356     return NULL;
357 }
358
359 /**
360  * atk_text_get_caret_offset:
361  * @text: an #AtkText
362  *
363  * Gets the offset position of the caret (cursor).
364  *
365  * Returns: the offset position of the caret (cursor).
366  **/
367 gint
368 atk_text_get_caret_offset (AtkText *text)
369 {
370   AtkTextIface *iface;
371
372   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
373
374   iface = ATK_TEXT_GET_IFACE (text);
375
376   if (iface->get_caret_offset)
377     return (*(iface->get_caret_offset)) (text);
378   else
379     return -1;
380 }
381
382 /**
383  * atk_text_get_character_extents:
384  * @text: an #AtkText
385  * @offset: position
386  * @x: x-position of character
387  * @y: y-position of character
388  * @width: width of character
389  * @height: height of character
390  * @coords: specify whether coordinates are relative to the screen or widget window 
391  *
392  * Given an @offset, the @x, @y, @width, and @height values are filled
393  * appropriately. 
394  **/
395 void
396 atk_text_get_character_extents (AtkText *text,
397                                 gint offset,
398                                 gint *x,
399                                 gint *y,
400                                 gint *width,
401                                 gint *height,
402                                 AtkCoordType coords)
403 {
404   AtkTextIface *iface;
405   gint local_x, local_y, local_width, local_height;
406   gint *real_x, *real_y, *real_width, *real_height;
407
408   g_return_if_fail (ATK_IS_TEXT (text));
409
410   if (x)
411     real_x = x;
412   else
413     real_x = &local_x;
414   if (y)
415     real_y = y;
416   else
417     real_y = &local_y;
418   if (width)
419     real_width = width;
420   else
421     real_width = &local_width;
422   if (height)
423     real_height = height;
424   else
425     real_height = &local_height;
426
427   iface = ATK_TEXT_GET_IFACE (text);
428
429   if (iface->get_character_extents)
430     (*(iface->get_character_extents)) (text, offset, real_x, real_y, real_width, real_height, coords);
431   else
432     {
433       *real_x = 0;
434       *real_y = 0;
435       *real_width = 0;
436       *real_height = 0;
437     }
438 }
439
440 /**
441  *atk_text_get_run_attributes:
442  *@text: an #AtkText
443  *@offset: the offset at which to get the attributes
444  *@start_offset: the address to put the start offset of the range
445  *@end_offset: the address to put the end offset of the range
446  *
447  *Creates an #AtkAttributeSet which consists of the attributes explicitly
448  *set at the position @offset in the text. @start_offset and @end_offset are
449  *set to the start and end of the range around @offset where the attributes are
450  *invariant. See the ATK_ATTRIBUTE macros, such as #ATK_ATTRIBUTE_LEFT_MARGIN
451  *for types of text attributes that can be returned. Note that other 
452  *attributes that do not have corresponding macros may also be returned.
453  *
454  *Returns: an #AtkAttributeSet which contains the attributes explicitly set
455  *at @offset. This #AtkAttributeSet should be freed by a call to
456  *atk_attribute_set_free().
457  **/
458 AtkAttributeSet* 
459 atk_text_get_run_attributes (AtkText          *text,
460                              gint             offset,
461                              gint             *start_offset,
462                              gint             *end_offset)
463 {
464   AtkTextIface *iface;
465   gint local_start_offset, local_end_offset;
466   gint *real_start_offset, *real_end_offset;
467
468   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
469
470   if (start_offset)
471     real_start_offset = start_offset;
472   else
473     real_start_offset = &local_start_offset;
474   if (end_offset)
475     real_end_offset = end_offset;
476   else
477     real_end_offset = &local_end_offset;
478
479   iface = ATK_TEXT_GET_IFACE (text);
480
481   if (iface->get_run_attributes)
482     return (*(iface->get_run_attributes)) (text, offset, real_start_offset, real_end_offset);
483   else
484     return NULL;
485 }
486
487 /**
488  *atk_text_get_default_attributes:
489  *@text: an #AtkText
490  *
491  *Creates an #AtkAttributeSet which consists of the default values of
492  *attributes for the text. See the ATK_ATTRIBUTE macros, such as 
493  *#ATK_ATTRIBUTE_LEFT_MARGIN for types of text attributes that can be 
494  *returned. Note that other attributes that do not have corresponding macros 
495  *may also be returned.
496  *
497  *Returns: an #AtkAttributeSet which contains the default values of attributes.
498  *at @offset. This #AtkAttributeSet should be freed by a call to
499  *atk_attribute_set_free().
500  */
501 AtkAttributeSet* 
502 atk_text_get_default_attributes (AtkText          *text)
503 {
504   AtkTextIface *iface;
505
506   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
507
508   iface = ATK_TEXT_GET_IFACE (text);
509
510   if (iface->get_default_attributes)
511     return (*(iface->get_default_attributes)) (text);
512   else
513     return NULL;
514 }
515
516 /**
517  * atk_text_get_character_count:
518  * @text: an #AtkText
519  *
520  * Gets the character count.
521  *
522  * Returns: the number of characters.
523  **/
524 gint
525 atk_text_get_character_count (AtkText *text)
526 {
527   AtkTextIface *iface;
528
529   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
530
531   iface = ATK_TEXT_GET_IFACE (text);
532
533   if (iface->get_character_count)
534     return (*(iface->get_character_count)) (text);
535   else
536     return -1;
537 }
538
539 /**
540  * atk_text_get_offset_at_point:
541  * @text: an #AtkText
542  * @x: screen x-position of character
543  * @y: screen y-position of character
544  * @coords: specify whether coordinates are relative to the screen or
545  * widget window 
546  *
547  * Gets the offset of the character located at coordinates @x and @y. @x and @y
548  * are interpreted as being relative to the screen or this widget's window
549  * depending on @coords.
550  *
551  * Returns: the offset to the character which is located at
552  * the specified @x and @y coordinates.
553  **/
554 gint
555 atk_text_get_offset_at_point (AtkText *text,
556                               gint x,
557                               gint y,
558                               AtkCoordType coords)
559 {
560   AtkTextIface *iface;
561
562   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
563
564   iface = ATK_TEXT_GET_IFACE (text);
565
566   if (iface->get_offset_at_point)
567     return (*(iface->get_offset_at_point)) (text, x, y, coords);
568   else
569     return -1;
570 }
571
572 /**
573  * atk_text_get_n_selections:
574  * @text: an #AtkText
575  *
576  * Gets the number of selected regions.
577  *
578  * Returns: The number of selected regions, or -1 if a failure
579  *   occurred.
580  **/
581 gint
582 atk_text_get_n_selections (AtkText *text)
583 {
584   AtkTextIface *iface;
585
586   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
587
588   iface = ATK_TEXT_GET_IFACE (text);
589
590   if (iface->get_n_selections)
591     return (*(iface->get_n_selections)) (text);
592   else
593     return -1;
594 }
595
596 /**
597  * atk_text_get_selection:
598  * @text: an #AtkText
599  * @selection_num: The selection number.  The selected regions are
600  * assigned numbers that correspond to how far the region is from the
601  * start of the text.  The selected region closest to the beginning
602  * of the text region is assigned the number 0, etc.  Note that adding,
603  * moving or deleting a selected region can change the numbering.
604  * @start_offset: passes back the start position of the selected region
605  * @end_offset: passes back the end position of the selected region
606  *
607  * Gets the text from the specified selection.
608  *
609  * Returns: the selected text.
610  **/
611 gchar*
612 atk_text_get_selection (AtkText *text, 
613                         gint    selection_num,
614                         gint    *start_offset,
615                         gint    *end_offset)
616 {
617   AtkTextIface *iface;
618   gint local_start_offset, local_end_offset;
619   gint *real_start_offset, *real_end_offset;
620
621   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
622
623   if (start_offset)
624     real_start_offset = start_offset;
625   else
626     real_start_offset = &local_start_offset;
627   if (end_offset)
628     real_end_offset = end_offset;
629   else
630     real_start_offset = &local_end_offset;
631
632   iface = ATK_TEXT_GET_IFACE (text);
633
634   if (iface->get_selection)
635   {
636     return (*(iface->get_selection)) (text, selection_num,
637        real_start_offset, real_end_offset);
638   }
639   else
640     return NULL;
641 }
642
643 /**
644  * atk_text_add_selection:
645  * @text: an #AtkText
646  * @start_offset: the start position of the selected region
647  * @end_offset: the end position of the selected region
648  *
649  * Adds a selection bounded by the specified offsets.
650  *
651  * Returns: %TRUE if success, %FALSE otherwise
652  **/
653 gboolean
654 atk_text_add_selection (AtkText *text, 
655                         gint    start_offset,
656                         gint    end_offset)
657 {
658   AtkTextIface *iface;
659
660   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
661
662   iface = ATK_TEXT_GET_IFACE (text);
663
664   if (iface->add_selection)
665     return (*(iface->add_selection)) (text, start_offset, end_offset);
666   else
667     return FALSE;
668 }
669
670 /**
671  * atk_text_remove_selection:
672  * @text: an #AtkText
673  * @selection_num: The selection number.  The selected regions are
674  * assigned numbers that correspond to how far the region is from the
675  * start of the text.  The selected region closest to the beginning
676  * of the text region is assigned the number 0, etc.  Note that adding,
677  * moving or deleting a selected region can change the numbering.
678  *
679  * Removes the specified selection.
680  *
681  * Returns: %TRUE if success, %FALSE otherwise
682  **/
683 gboolean
684 atk_text_remove_selection (AtkText *text, 
685                            gint    selection_num)
686 {
687   AtkTextIface *iface;
688
689   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
690
691   iface = ATK_TEXT_GET_IFACE (text);
692
693   if (iface->remove_selection)
694     return (*(iface->remove_selection)) (text, selection_num);
695   else
696     return FALSE;
697 }
698
699 /**
700  * atk_text_set_selection:
701  * @text: an #AtkText
702  * @selection_num: The selection number.  The selected regions are
703  * assigned numbers that correspond to how far the region is from the
704  * start of the text.  The selected region closest to the beginning
705  * of the text region is assigned the number 0, etc.  Note that adding,
706  * moving or deleting a selected region can change the numbering.
707  * @start_offset: the new start position of the selection
708  * @end_offset: the new end position of the selection
709  *
710  * Changes the start and end offset of the specified selection.
711  *
712  * Returns: %TRUE if success, %FALSE otherwise
713  **/
714 gboolean
715 atk_text_set_selection (AtkText *text, 
716                         gint    selection_num,
717                         gint    start_offset, 
718                         gint    end_offset)
719 {
720   AtkTextIface *iface;
721
722   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
723
724   iface = ATK_TEXT_GET_IFACE (text);
725
726   if (iface->set_selection)
727   {
728     return (*(iface->set_selection)) (text, selection_num,
729        start_offset, end_offset);
730   }
731   else
732     return FALSE;
733 }
734
735 /**
736  * atk_text_set_caret_offset:
737  * @text: an #AtkText
738  * @offset: position
739  *
740  * Sets the caret (cursor) position to the specified @offset.
741  *
742  * Returns: %TRUE if success, %FALSE otherwise.
743  **/
744 gboolean
745 atk_text_set_caret_offset (AtkText *text,
746                            gint    offset)
747 {
748   AtkTextIface *iface;
749
750   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
751
752   iface = ATK_TEXT_GET_IFACE (text);
753
754   if (iface->set_caret_offset)
755     {
756       return (*(iface->set_caret_offset)) (text, offset);
757     }
758   else
759     {
760       return FALSE;
761     }
762 }
763
764 /**
765  * atk_attribute_set_free:
766  * @attrib_set: The #AtkAttributeSet to free
767  *
768  * Frees the memory used by an #AtkAttributeSet, including all its
769  * #AtkAttributes.
770  **/
771 void
772 atk_attribute_set_free(AtkAttributeSet *attrib_set)
773 {
774   GSList *temp;
775
776   temp = attrib_set;
777
778   while (temp != NULL)
779     {
780       AtkAttribute *att;
781
782       att = temp->data;
783
784       g_free (att->name);
785       g_free (att->value);
786       g_free (att);
787       temp = temp->next;
788     }
789   g_slist_free (attrib_set);
790 }
791
792 /**
793  * atk_attribute_get_name:
794  * @attr: The #AtkTextAttribute whose name is required
795  *
796  * Returns the name corresponding to the attr value.
797  **/
798 G_CONST_RETURN gchar*
799 atk_attribute_get_name (AtkTextAttribute attr)
800 {
801   g_assert (attr >= 0 && attr <= ATK_TEXT_ATTR_STYLE);
802   return text_attr_name[attr];
803 }
804
805 /**
806  * atk_attribute_get_value:
807  * @attr: The #AtkTextAttribute for which a value is required
808  * @index: The index of the required value
809  *
810  * Returns the value corresponding to the attr value and index.
811  * NULL is returned if there are no values maintained for the attr value. 
812  **/
813 G_CONST_RETURN gchar*
814 atk_attribute_get_value (AtkTextAttribute attr,
815                          gint             index)
816 {
817   switch (attr)
818     {
819     case ATK_TEXT_ATTR_INVISIBLE:
820     case ATK_TEXT_ATTR_EDITABLE:
821     case ATK_TEXT_ATTR_BG_FULL_HEIGHT:
822     case ATK_TEXT_ATTR_STRIKETHROUGH:
823     case ATK_TEXT_ATTR_BG_STIPPLE:
824     case ATK_TEXT_ATTR_FG_STIPPLE:
825       g_assert (index >= 0 && index < 2);
826       return bool[index];
827     case ATK_TEXT_ATTR_UNDERLINE:
828       g_assert (index >= 0 && index < 4);
829       return underline[index];
830     case ATK_TEXT_ATTR_WRAP_MODE:
831       g_assert (index >= 0 && index < 3);
832       return wrap_mode[index];
833     case ATK_TEXT_ATTR_DIRECTION:
834       g_assert (index >= 0 && index < 3);
835       return direction[index];
836     case ATK_TEXT_ATTR_JUSTIFICATION:
837       g_assert (index >= 0 && index < 3);
838       return justification[index];
839     case ATK_TEXT_ATTR_STRETCH:
840       g_assert (index >= 0 && index < 9);
841       return stretch[index];
842     case ATK_TEXT_ATTR_VARIANT:
843       g_assert (index >= 0 && index < 2);
844       return variant[index];
845     case ATK_TEXT_ATTR_STYLE:
846       g_assert (index >= 0 && index < 3);
847       return style[index];
848     default:
849       return NULL;
850    }
851 }