1 /* ATK - The Accessibility Toolkit for GTK+
2 * Copyright 2001 Sun Microsystems Inc.
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.
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.
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.
21 #include "atkmarshal.h"
22 #include "atk-enum-types.h"
24 GPtrArray *extra_attributes = NULL;
29 TEXT_SELECTION_CHANGED,
33 static const gchar *bool[] = {"false",
35 static const gchar *style[] = {"normal",
38 static const gchar *variant[] = {"normal",
40 static const gchar *stretch[] = {"ultra_condensed",
49 static const gchar *justification[] = {"left",
54 static const gchar *direction[] = {"none",
57 static const gchar *wrap_mode[] = {"none",
60 static const gchar *underline[] = {"none",
65 static void atk_text_base_init (gpointer *g_class);
67 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
72 static GType type = 0;
76 static const GTypeInfo tinfo =
78 sizeof (AtkTextIface),
79 (GBaseInitFunc) atk_text_base_init,
80 (GBaseFinalizeFunc) NULL,
81 (GClassInitFunc) NULL /* atk_text_interface_init */ ,
82 (GClassFinalizeFunc) NULL,
86 type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
93 atk_text_base_init (gpointer *g_class)
95 static gboolean initialized = FALSE;
100 * Note that text_changed signal supports details "insert", "delete",
101 * possibly "replace".
104 atk_text_signals[TEXT_CHANGED] =
105 g_signal_new ("text_changed",
107 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
108 G_STRUCT_OFFSET (AtkTextIface, text_changed),
109 (GSignalAccumulator) NULL, NULL,
110 atk_marshal_VOID__INT_INT,
112 2, G_TYPE_INT, G_TYPE_INT);
114 atk_text_signals[CARET_MOVED] =
115 g_signal_new ("text_caret_moved",
118 G_STRUCT_OFFSET (AtkTextIface, caret_changed),
119 (GSignalAccumulator) NULL, NULL,
120 g_cclosure_marshal_VOID__INT,
123 atk_text_signals[TEXT_SELECTION_CHANGED] =
124 g_signal_new ("text_selection_changed",
127 G_STRUCT_OFFSET (AtkTextIface, text_selection_changed),
128 (GSignalAccumulator) NULL, NULL,
129 g_cclosure_marshal_VOID__VOID,
140 * @start_offset: start position
141 * @end_offset: end position
143 * Gets the specified text.
145 * Returns: the text from @start_offset up to, but not including @end_offset.
148 atk_text_get_text (AtkText *text,
154 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
156 iface = ATK_TEXT_GET_IFACE (text);
159 return (*(iface->get_text)) (text, start_offset, end_offset);
165 * atk_text_get_character_at_offset:
169 * Gets the specified text.
171 * Returns: the character at @offset.
174 atk_text_get_character_at_offset (AtkText *text,
179 g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
181 iface = ATK_TEXT_GET_IFACE (text);
183 if (iface->get_character_at_offset)
184 return (*(iface->get_character_at_offset)) (text, offset);
190 * atk_text_get_text_after_offset:
193 * @boundary_type: An #AtkTextBoundary
194 * @start_offset: the start offset of the returned string.
195 * @end_offset: the end offset of the returned string.
197 * Gets the specified text.
199 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character after the
200 * offset is returned.
202 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
203 * is from the word start after the offset to the next word start.
205 * The returned string will contain the word after the offset if the offset
206 * is inside a word or if the offset is not inside a word.
208 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
209 * is from the word end at or after the offset to the next work end.
211 * The returned string will contain the word after the offset if the offset
212 * is inside a word and will contain the word after the word after the offset
213 * if the offset is not inside a word.
215 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
216 * string is from the sentence start after the offset to the next sentence
219 * The returned string will contain the sentence after the offset if the offset
220 * is inside a sentence or if the offset is not inside a sentence.
222 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
223 * is from the sentence end at or after the offset to the next sentence end.
225 * The returned string will contain the sentence after the offset if the offset
226 * is inside a sentence and will contain the sentence after the sentence
227 * after the offset if the offset is not inside a sentence.
229 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
230 * string is from the line start after the offset to the next line start.
232 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
233 * is from the line end at or after the offset to the next line start.
235 * Returns: the text after @offset bounded by the specified @boundary_type.
238 atk_text_get_text_after_offset (AtkText *text,
240 AtkTextBoundary boundary_type,
245 gint local_start_offset, local_end_offset;
246 gint *real_start_offset, *real_end_offset;
248 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
251 real_start_offset = start_offset;
253 real_start_offset = &local_start_offset;
255 real_end_offset = end_offset;
257 real_end_offset = &local_end_offset;
259 iface = ATK_TEXT_GET_IFACE (text);
261 if (iface->get_text_after_offset)
262 return (*(iface->get_text_after_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
268 * atk_text_get_text_at_offset:
271 * @boundary_type: An #AtkTextBoundary
272 * @start_offset: the start offset of the returned string.
273 * @end_offset: the end offset of the returned string.
275 * Gets the specified text.
277 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character at the
278 * offset is returned.
280 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
281 * is from the word start at or before the offset to the word start after
284 * The returned string will contain the word at the offset if the offset
285 * is inside a word and will contain the word before the offset if the
286 * offset is not inside a word.
288 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
289 * is from the word end before the offset to the word end at or after the
292 * The returned string will contain the word at the offset if the offset
293 * is inside a word and will contain the word after to the offset if the
294 * offset is not inside a word.
296 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
297 * string is from the sentence start at or before the offset to the sentence
298 * start after the offset.
300 * The returned string will contain the sentence at the offset if the offset
301 * is inside a sentence and will contain the sentence before the offset
302 * if the offset is not inside a sentence.
304 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
305 * is from the sentence end before the offset to the sentence end at or
308 * The returned string will contain the sentence at the offset if the offset
309 * is inside a sentence and will contain the sentence after the offset
310 * if the offset is not inside a sentence.
312 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
313 * string is from the line start at or before the offset to the line
314 * start after the offset.
316 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
317 * is from the line end before the offset to the line end at or after
320 * Returns: the text at @offset bounded by the specified @boundary_type.
323 atk_text_get_text_at_offset (AtkText *text,
325 AtkTextBoundary boundary_type,
330 gint local_start_offset, local_end_offset;
331 gint *real_start_offset, *real_end_offset;
333 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
336 real_start_offset = start_offset;
338 real_start_offset = &local_start_offset;
340 real_end_offset = end_offset;
342 real_end_offset = &local_end_offset;
344 iface = ATK_TEXT_GET_IFACE (text);
346 if (iface->get_text_at_offset)
347 return (*(iface->get_text_at_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
353 * atk_text_get_text_before_offset:
356 * @boundary_type: An #AtkTextBoundary
357 * @start_offset: the start offset of the returned string.
358 * @end_offset: the end offset of the returned string.
360 * Gets the specified text.
362 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character before the
363 * offset is returned.
365 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
366 * is from the word start before the word start before the offset to
367 * the word start before the offset.
369 * The returned string will contain the word before the offset if the offset
370 * is inside a word and will contain the word before the word before the
371 * offset if the offset is not inside a word.
373 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
374 * is from the word end before the word end at or before the offset to the
375 * word end at or before the offset.
377 * The returned string will contain the word before the offset if the offset
378 * is inside a word or if the offset is not inside a word.
380 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
381 * string is from the sentence start before the sentence start before
382 * the offset to the sentence start before the offset.
384 * The returned string will contain the sentence before the offset if the
385 * offset is inside a sentence and will contain the sentence before the
386 * sentence before the offset if the offset is not inside a sentence.
388 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
389 * is from the sentence end before the sentence end at or before the offset to
390 * the sentence end at or before the offset.
392 * The returned string will contain the sentence before the offset if the
393 * offset is inside a sentence or if the offset is not inside a sentence.
395 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
396 * string is from the line start before the line start ar or before the offset
397 * to the line start ar or before the offset.
399 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
400 * is from the line end before the line end before the offset to the
401 * line end before the offset.
403 * Returns: the text before @offset bounded by the specified @boundary_type.
406 atk_text_get_text_before_offset (AtkText *text,
408 AtkTextBoundary boundary_type,
413 gint local_start_offset, local_end_offset;
414 gint *real_start_offset, *real_end_offset;
416 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
419 real_start_offset = start_offset;
421 real_start_offset = &local_start_offset;
423 real_end_offset = end_offset;
425 real_end_offset = &local_end_offset;
427 iface = ATK_TEXT_GET_IFACE (text);
429 if (iface->get_text_before_offset)
430 return (*(iface->get_text_before_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
436 * atk_text_get_caret_offset:
439 * Gets the offset position of the caret (cursor).
441 * Returns: the offset position of the caret (cursor).
444 atk_text_get_caret_offset (AtkText *text)
448 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
450 iface = ATK_TEXT_GET_IFACE (text);
452 if (iface->get_caret_offset)
453 return (*(iface->get_caret_offset)) (text);
459 * atk_text_get_character_extents:
462 * @x: x-position of character
463 * @y: y-position of character
464 * @width: width of character
465 * @height: height of character
466 * @coords: specify whether coordinates are relative to the screen or widget window
468 * Given an @offset, the @x, @y, @width, and @height values are filled
472 atk_text_get_character_extents (AtkText *text,
481 gint local_x, local_y, local_width, local_height;
482 gint *real_x, *real_y, *real_width, *real_height;
484 g_return_if_fail (ATK_IS_TEXT (text));
497 real_width = &local_width;
499 real_height = height;
501 real_height = &local_height;
503 iface = ATK_TEXT_GET_IFACE (text);
505 if (iface->get_character_extents)
506 (*(iface->get_character_extents)) (text, offset, real_x, real_y, real_width, real_height, coords);
517 *atk_text_get_run_attributes:
519 *@offset: the offset at which to get the attributes
520 *@start_offset: the address to put the start offset of the range
521 *@end_offset: the address to put the end offset of the range
523 *Creates an #AtkAttributeSet which consists of the attributes explicitly
524 *set at the position @offset in the text. @start_offset and @end_offset are
525 *set to the start and end of the range around @offset where the attributes are
526 *invariant. See the enum AtkTextAttribute for types of text attributes that
527 *can be returned. Note that other attributes may also be returned.
529 *Returns: an #AtkAttributeSet which contains the attributes explicitly set
530 *at @offset. This #AtkAttributeSet should be freed by a call to
531 *atk_attribute_set_free().
534 atk_text_get_run_attributes (AtkText *text,
540 gint local_start_offset, local_end_offset;
541 gint *real_start_offset, *real_end_offset;
543 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
546 real_start_offset = start_offset;
548 real_start_offset = &local_start_offset;
550 real_end_offset = end_offset;
552 real_end_offset = &local_end_offset;
554 iface = ATK_TEXT_GET_IFACE (text);
556 if (iface->get_run_attributes)
557 return (*(iface->get_run_attributes)) (text, offset, real_start_offset, real_end_offset);
563 *atk_text_get_default_attributes:
566 *Creates an #AtkAttributeSet which consists of the default values of
567 *attributes for the text. See the enum AtkTextAttribute for types of text
568 *attributes that can be returned. Note that other attributes may also be
571 *Returns: an #AtkAttributeSet which contains the default values of attributes.
572 *at @offset. This #AtkAttributeSet should be freed by a call to
573 *atk_attribute_set_free().
576 atk_text_get_default_attributes (AtkText *text)
580 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
582 iface = ATK_TEXT_GET_IFACE (text);
584 if (iface->get_default_attributes)
585 return (*(iface->get_default_attributes)) (text);
591 * atk_text_get_character_count:
594 * Gets the character count.
596 * Returns: the number of characters.
599 atk_text_get_character_count (AtkText *text)
603 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
605 iface = ATK_TEXT_GET_IFACE (text);
607 if (iface->get_character_count)
608 return (*(iface->get_character_count)) (text);
614 * atk_text_get_offset_at_point:
616 * @x: screen x-position of character
617 * @y: screen y-position of character
618 * @coords: specify whether coordinates are relative to the screen or
621 * Gets the offset of the character located at coordinates @x and @y. @x and @y
622 * are interpreted as being relative to the screen or this widget's window
623 * depending on @coords.
625 * Returns: the offset to the character which is located at
626 * the specified @x and @y coordinates.
629 atk_text_get_offset_at_point (AtkText *text,
636 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
638 iface = ATK_TEXT_GET_IFACE (text);
640 if (iface->get_offset_at_point)
641 return (*(iface->get_offset_at_point)) (text, x, y, coords);
647 * atk_text_get_n_selections:
650 * Gets the number of selected regions.
652 * Returns: The number of selected regions, or -1 if a failure
656 atk_text_get_n_selections (AtkText *text)
660 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
662 iface = ATK_TEXT_GET_IFACE (text);
664 if (iface->get_n_selections)
665 return (*(iface->get_n_selections)) (text);
671 * atk_text_get_selection:
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 * @start_offset: passes back the start position of the selected region
679 * @end_offset: passes back the end position of the selected region
681 * Gets the text from the specified selection.
683 * Returns: the selected text.
686 atk_text_get_selection (AtkText *text,
692 gint local_start_offset, local_end_offset;
693 gint *real_start_offset, *real_end_offset;
695 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
698 real_start_offset = start_offset;
700 real_start_offset = &local_start_offset;
702 real_end_offset = end_offset;
704 real_end_offset = &local_end_offset;
706 iface = ATK_TEXT_GET_IFACE (text);
708 if (iface->get_selection)
710 return (*(iface->get_selection)) (text, selection_num,
711 real_start_offset, real_end_offset);
718 * atk_text_add_selection:
720 * @start_offset: the start position of the selected region
721 * @end_offset: the end position of the selected region
723 * Adds a selection bounded by the specified offsets.
725 * Returns: %TRUE if success, %FALSE otherwise
728 atk_text_add_selection (AtkText *text,
734 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
736 iface = ATK_TEXT_GET_IFACE (text);
738 if (iface->add_selection)
739 return (*(iface->add_selection)) (text, start_offset, end_offset);
745 * atk_text_remove_selection:
747 * @selection_num: The selection number. The selected regions are
748 * assigned numbers that correspond to how far the region is from the
749 * start of the text. The selected region closest to the beginning
750 * of the text region is assigned the number 0, etc. Note that adding,
751 * moving or deleting a selected region can change the numbering.
753 * Removes the specified selection.
755 * Returns: %TRUE if success, %FALSE otherwise
758 atk_text_remove_selection (AtkText *text,
763 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
765 iface = ATK_TEXT_GET_IFACE (text);
767 if (iface->remove_selection)
768 return (*(iface->remove_selection)) (text, selection_num);
774 * atk_text_set_selection:
776 * @selection_num: The selection number. The selected regions are
777 * assigned numbers that correspond to how far the region is from the
778 * start of the text. The selected region closest to the beginning
779 * of the text region is assigned the number 0, etc. Note that adding,
780 * moving or deleting a selected region can change the numbering.
781 * @start_offset: the new start position of the selection
782 * @end_offset: the new end position of the selection
784 * Changes the start and end offset of the specified selection.
786 * Returns: %TRUE if success, %FALSE otherwise
789 atk_text_set_selection (AtkText *text,
796 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
798 iface = ATK_TEXT_GET_IFACE (text);
800 if (iface->set_selection)
802 return (*(iface->set_selection)) (text, selection_num,
803 start_offset, end_offset);
810 * atk_text_set_caret_offset:
814 * Sets the caret (cursor) position to the specified @offset.
816 * Returns: %TRUE if success, %FALSE otherwise.
819 atk_text_set_caret_offset (AtkText *text,
824 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
826 iface = ATK_TEXT_GET_IFACE (text);
828 if (iface->set_caret_offset)
830 return (*(iface->set_caret_offset)) (text, offset);
839 * atk_attribute_set_free:
840 * @attrib_set: The #AtkAttributeSet to free
842 * Frees the memory used by an #AtkAttributeSet, including all its
846 atk_attribute_set_free (AtkAttributeSet *attrib_set)
863 g_slist_free (attrib_set);
867 * atk_attribute_register:
868 * @name: a name string
870 * Associate @name with a new #AtkTextAttribute
872 * Returns: an #AtkTextAttribute associated with @name
875 atk_attribute_register (const gchar *name)
877 g_return_val_if_fail (name, ATK_TEXT_ATTR_INVALID);
879 if (!extra_attributes)
880 extra_attributes = g_ptr_array_new ();
882 g_ptr_array_add (extra_attributes, g_strdup (name));
883 return extra_attributes->len + ATK_TEXT_ATTR_LAST_DEFINED;
887 * atk_attribute_get_name:
888 * @attr: The #AtkTextAttribute whose name is required
890 * Gets the name corresponding to the #AtkTextAttribute
892 * Returns: a string containing the name; this string should not be freed
894 G_CONST_RETURN gchar*
895 atk_attribute_get_name (AtkTextAttribute attr)
897 GTypeClass *type_class;
901 type_class = g_type_class_ref (ATK_TYPE_TEXT_ATTRIBUTE);
902 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
904 value = g_enum_get_value (G_ENUM_CLASS (type_class), attr);
908 name = value->value_nick;
912 if (extra_attributes)
916 n -= ATK_TEXT_ATTR_LAST_DEFINED + 1;
918 if (n < extra_attributes->len)
920 name = g_ptr_array_index (extra_attributes, n);
923 g_type_class_unref (type_class);
928 * atk_attribute_for_name:
929 * @name: a string which is the (non-localized) name of an ATK text attribute.
931 * Get the #AtkTextAttribute type corresponding to a text attribute name.
933 * Returns: the #AtkTextAttribute enumerated type corresponding to the specified
935 * or #ATK_TEXT_ATTRIBUTE_INVALID if no matching text attribute is found.
938 atk_attribute_for_name (const gchar *name)
940 GTypeClass *type_class;
942 AtkTextAttribute type = ATK_TEXT_ATTR_INVALID;
944 g_return_val_if_fail (name, ATK_TEXT_ATTR_INVALID);
946 type_class = g_type_class_ref (ATK_TYPE_TEXT_ATTRIBUTE);
947 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_TEXT_ATTR_INVALID);
949 value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
959 if (extra_attributes)
961 for (i = 0; i < extra_attributes->len; i++)
963 gchar *extra_attribute = (gchar *)g_ptr_array_index (extra_attributes, i);
965 g_return_val_if_fail (extra_attribute, ATK_TEXT_ATTR_INVALID);
967 if (strcmp (name, extra_attribute) == 0)
969 type = i + 1 + ATK_TEXT_ATTR_LAST_DEFINED;
975 g_type_class_unref (type_class);
982 * atk_attribute_get_value:
983 * @attr: The #AtkTextAttribute for which a value is required
984 * @index: The index of the required value
986 * Gets the value for the index of the #AtkTextAttribute
988 * Returns: a string containing the value; this string should not be freed;
989 * NULL is returned if there are no values maintained for the attr value.
991 G_CONST_RETURN gchar*
992 atk_attribute_get_value (AtkTextAttribute attr,
997 case ATK_TEXT_ATTR_INVISIBLE:
998 case ATK_TEXT_ATTR_EDITABLE:
999 case ATK_TEXT_ATTR_BG_FULL_HEIGHT:
1000 case ATK_TEXT_ATTR_STRIKETHROUGH:
1001 case ATK_TEXT_ATTR_BG_STIPPLE:
1002 case ATK_TEXT_ATTR_FG_STIPPLE:
1003 g_assert (index >= 0 && index < 2);
1005 case ATK_TEXT_ATTR_UNDERLINE:
1006 g_assert (index >= 0 && index < 4);
1007 return underline[index];
1008 case ATK_TEXT_ATTR_WRAP_MODE:
1009 g_assert (index >= 0 && index < 3);
1010 return wrap_mode[index];
1011 case ATK_TEXT_ATTR_DIRECTION:
1012 g_assert (index >= 0 && index < 3);
1013 return direction[index];
1014 case ATK_TEXT_ATTR_JUSTIFICATION:
1015 g_assert (index >= 0 && index < 3);
1016 return justification[index];
1017 case ATK_TEXT_ATTR_STRETCH:
1018 g_assert (index >= 0 && index < 9);
1019 return stretch[index];
1020 case ATK_TEXT_ATTR_VARIANT:
1021 g_assert (index >= 0 && index < 2);
1022 return variant[index];
1023 case ATK_TEXT_ATTR_STYLE:
1024 g_assert (index >= 0 && index < 3);
1025 return style[index];