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"
26 GPtrArray *extra_attributes = NULL;
31 TEXT_SELECTION_CHANGED,
35 static const gchar *bool[] = {"false",
37 static const gchar *style[] = {"normal",
40 static const gchar *variant[] = {"normal",
42 static const gchar *stretch[] = {"ultra_condensed",
51 static const gchar *justification[] = {"left",
55 static const gchar *direction[] = {"none",
58 static const gchar *wrap_mode[] = {"none",
61 static const gchar *underline[] = {"none",
66 static void atk_text_base_init (gpointer *g_class);
68 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
73 static GType type = 0;
77 static const GTypeInfo tinfo =
79 sizeof (AtkTextIface),
80 (GBaseInitFunc) atk_text_base_init,
81 (GBaseFinalizeFunc) NULL,
82 (GClassInitFunc) NULL /* atk_text_interface_init */ ,
83 (GClassFinalizeFunc) NULL,
87 type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
94 atk_text_base_init (gpointer *g_class)
96 static gboolean initialized = FALSE;
101 * Note that text_changed signal supports details "insert", "delete",
102 * possibly "replace".
105 atk_text_signals[TEXT_CHANGED] =
106 g_signal_new ("text_changed",
108 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
109 G_STRUCT_OFFSET (AtkTextIface, text_changed),
110 (GSignalAccumulator) NULL, NULL,
111 atk_marshal_VOID__INT_INT,
113 2, G_TYPE_INT, G_TYPE_INT);
115 atk_text_signals[TEXT_CARET_MOVED] =
116 g_signal_new ("text_caret_moved",
119 G_STRUCT_OFFSET (AtkTextIface, text_caret_moved),
120 (GSignalAccumulator) NULL, NULL,
121 g_cclosure_marshal_VOID__INT,
124 atk_text_signals[TEXT_SELECTION_CHANGED] =
125 g_signal_new ("text_selection_changed",
128 G_STRUCT_OFFSET (AtkTextIface, text_selection_changed),
129 (GSignalAccumulator) NULL, NULL,
130 g_cclosure_marshal_VOID__VOID,
141 * @start_offset: start position
142 * @end_offset: end position
144 * Gets the specified text.
146 * Returns: the text from @start_offset up to, but not including @end_offset.
149 atk_text_get_text (AtkText *text,
155 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
157 iface = ATK_TEXT_GET_IFACE (text);
159 if (start_offset < 0 || end_offset < -1)
163 return (*(iface->get_text)) (text, start_offset, end_offset);
169 * atk_text_get_character_at_offset:
173 * Gets the specified text.
175 * Returns: the character at @offset.
178 atk_text_get_character_at_offset (AtkText *text,
183 g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
188 iface = ATK_TEXT_GET_IFACE (text);
190 if (iface->get_character_at_offset)
191 return (*(iface->get_character_at_offset)) (text, offset);
197 * atk_text_get_text_after_offset:
200 * @boundary_type: An #AtkTextBoundary
201 * @start_offset: the start offset of the returned string.
202 * @end_offset: the end offset of the returned string.
204 * Gets the specified text.
206 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character after the
207 * offset is returned.
209 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
210 * is from the word start after the offset to the next word start.
212 * The returned string will contain the word after the offset if the offset
213 * is inside a word or if the offset is not inside a word.
215 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
216 * is from the word end at or after the offset to the next work end.
218 * The returned string will contain the word after the offset if the offset
219 * is inside a word and will contain the word after the word after the offset
220 * if the offset is not inside a word.
222 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
223 * string is from the sentence start after the offset to the next sentence
226 * The returned string will contain the sentence after the offset if the offset
227 * is inside a sentence or if the offset is not inside a sentence.
229 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
230 * is from the sentence end at or after the offset to the next sentence end.
232 * The returned string will contain the sentence after the offset if the offset
233 * is inside a sentence and will contain the sentence after the sentence
234 * after the offset if the offset is not inside a sentence.
236 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
237 * string is from the line start after the offset to the next line start.
239 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
240 * is from the line end at or after the offset to the next line start.
242 * Returns: the text after @offset bounded by the specified @boundary_type.
245 atk_text_get_text_after_offset (AtkText *text,
247 AtkTextBoundary boundary_type,
252 gint local_start_offset, local_end_offset;
253 gint *real_start_offset, *real_end_offset;
255 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
258 real_start_offset = start_offset;
260 real_start_offset = &local_start_offset;
262 real_end_offset = end_offset;
264 real_end_offset = &local_end_offset;
269 iface = ATK_TEXT_GET_IFACE (text);
271 if (iface->get_text_after_offset)
272 return (*(iface->get_text_after_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
278 * atk_text_get_text_at_offset:
281 * @boundary_type: An #AtkTextBoundary
282 * @start_offset: the start offset of the returned string.
283 * @end_offset: the end offset of the returned string.
285 * Gets the specified text.
287 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character at the
288 * offset is returned.
290 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
291 * is from the word start at or before the offset to the word start after
294 * The returned string will contain the word at the offset if the offset
295 * is inside a word and will contain the word before the offset if the
296 * offset is not inside a word.
298 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
299 * is from the word end before the offset to the word end at or after the
302 * The returned string will contain the word at the offset if the offset
303 * is inside a word and will contain the word after to the offset if the
304 * offset is not inside a word.
306 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
307 * string is from the sentence start at or before the offset to the sentence
308 * start after the offset.
310 * The returned string will contain the sentence at the offset if the offset
311 * is inside a sentence and will contain the sentence before the offset
312 * if the offset is not inside a sentence.
314 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
315 * is from the sentence end before the offset to the sentence end at or
318 * The returned string will contain the sentence at the offset if the offset
319 * is inside a sentence and will contain the sentence after the offset
320 * if the offset is not inside a sentence.
322 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
323 * string is from the line start at or before the offset to the line
324 * start after the offset.
326 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
327 * is from the line end before the offset to the line end at or after
330 * Returns: the text at @offset bounded by the specified @boundary_type.
333 atk_text_get_text_at_offset (AtkText *text,
335 AtkTextBoundary boundary_type,
340 gint local_start_offset, local_end_offset;
341 gint *real_start_offset, *real_end_offset;
343 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
346 real_start_offset = start_offset;
348 real_start_offset = &local_start_offset;
350 real_end_offset = end_offset;
352 real_end_offset = &local_end_offset;
357 iface = ATK_TEXT_GET_IFACE (text);
359 if (iface->get_text_at_offset)
360 return (*(iface->get_text_at_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
366 * atk_text_get_text_before_offset:
369 * @boundary_type: An #AtkTextBoundary
370 * @start_offset: the start offset of the returned string.
371 * @end_offset: the end offset of the returned string.
373 * Gets the specified text.
375 * If the boundary_type if ATK_TEXT_BOUNDARY_CHAR the character before the
376 * offset is returned.
378 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START the returned string
379 * is from the word start before the word start before the offset to
380 * the word start before the offset.
382 * The returned string will contain the word before the offset if the offset
383 * is inside a word and will contain the word before the word before the
384 * offset if the offset is not inside a word.
386 * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_END the returned string
387 * is from the word end before the word end at or before the offset to the
388 * word end at or before the offset.
390 * The returned string will contain the word before the offset if the offset
391 * is inside a word or if the offset is not inside a word.
393 * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the returned
394 * string is from the sentence start before the sentence start before
395 * the offset to the sentence start before the offset.
397 * The returned string will contain the sentence before the offset if the
398 * offset is inside a sentence and will contain the sentence before the
399 * sentence before the offset if the offset is not inside a sentence.
401 * If the boundary_type is ATK_TEXT_BOUNDARY_SENTENCE_END the returned string
402 * is from the sentence end before the sentence end at or before the offset to
403 * the sentence end at or before the offset.
405 * The returned string will contain the sentence before the offset if the
406 * offset is inside a sentence or if the offset is not inside a sentence.
408 * If the boundary type is ATK_TEXT_BOUNDARY_LINE_START the returned
409 * string is from the line start before the line start ar or before the offset
410 * to the line start ar or before the offset.
412 * If the boundary_type is ATK_TEXT_BOUNDARY_LINE_END the returned string
413 * is from the line end before the line end before the offset to the
414 * line end before the offset.
416 * Returns: the text before @offset bounded by the specified @boundary_type.
419 atk_text_get_text_before_offset (AtkText *text,
421 AtkTextBoundary boundary_type,
426 gint local_start_offset, local_end_offset;
427 gint *real_start_offset, *real_end_offset;
429 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
432 real_start_offset = start_offset;
434 real_start_offset = &local_start_offset;
436 real_end_offset = end_offset;
438 real_end_offset = &local_end_offset;
443 iface = ATK_TEXT_GET_IFACE (text);
445 if (iface->get_text_before_offset)
446 return (*(iface->get_text_before_offset)) (text, offset, boundary_type, real_start_offset, real_end_offset);
452 * atk_text_get_caret_offset:
455 * Gets the offset position of the caret (cursor).
457 * Returns: the offset position of the caret (cursor).
460 atk_text_get_caret_offset (AtkText *text)
464 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
466 iface = ATK_TEXT_GET_IFACE (text);
468 if (iface->get_caret_offset)
469 return (*(iface->get_caret_offset)) (text);
475 * atk_text_get_character_extents:
478 * @x: x-position of character
479 * @y: y-position of character
480 * @width: width of character
481 * @height: height of character
482 * @coords: specify whether coordinates are relative to the screen or widget window
484 * Given an @offset, the @x, @y, @width, and @height values are filled
488 atk_text_get_character_extents (AtkText *text,
497 gint local_x, local_y, local_width, local_height;
498 gint *real_x, *real_y, *real_width, *real_height;
500 g_return_if_fail (ATK_IS_TEXT (text));
513 real_width = &local_width;
515 real_height = height;
517 real_height = &local_height;
527 iface = ATK_TEXT_GET_IFACE (text);
529 if (iface->get_character_extents)
530 (*(iface->get_character_extents)) (text, offset, real_x, real_y, real_width, real_height, coords);
534 *atk_text_get_run_attributes:
536 *@offset: the offset at which to get the attributes
537 *@start_offset: the address to put the start offset of the range
538 *@end_offset: the address to put the end offset of the range
540 *Creates an #AtkAttributeSet which consists of the attributes explicitly
541 *set at the position @offset in the text. @start_offset and @end_offset are
542 *set to the start and end of the range around @offset where the attributes are
543 *invariant. See the enum AtkTextAttribute for types of text attributes that
544 *can be returned. Note that other attributes may also be returned.
546 *Returns: an #AtkAttributeSet which contains the attributes explicitly set
547 *at @offset. This #AtkAttributeSet should be freed by a call to
548 *atk_attribute_set_free().
551 atk_text_get_run_attributes (AtkText *text,
557 gint local_start_offset, local_end_offset;
558 gint *real_start_offset, *real_end_offset;
560 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
563 real_start_offset = start_offset;
565 real_start_offset = &local_start_offset;
567 real_end_offset = end_offset;
569 real_end_offset = &local_end_offset;
574 iface = ATK_TEXT_GET_IFACE (text);
576 if (iface->get_run_attributes)
577 return (*(iface->get_run_attributes)) (text, offset, real_start_offset, real_end_offset);
583 *atk_text_get_default_attributes:
586 *Creates an #AtkAttributeSet which consists of the default values of
587 *attributes for the text. See the enum AtkTextAttribute for types of text
588 *attributes that can be returned. Note that other attributes may also be
591 *Returns: an #AtkAttributeSet which contains the default values of attributes.
592 *at @offset. This #AtkAttributeSet should be freed by a call to
593 *atk_attribute_set_free().
596 atk_text_get_default_attributes (AtkText *text)
600 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
602 iface = ATK_TEXT_GET_IFACE (text);
604 if (iface->get_default_attributes)
605 return (*(iface->get_default_attributes)) (text);
611 * atk_text_get_character_count:
614 * Gets the character count.
616 * Returns: the number of characters.
619 atk_text_get_character_count (AtkText *text)
623 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
625 iface = ATK_TEXT_GET_IFACE (text);
627 if (iface->get_character_count)
628 return (*(iface->get_character_count)) (text);
634 * atk_text_get_offset_at_point:
636 * @x: screen x-position of character
637 * @y: screen y-position of character
638 * @coords: specify whether coordinates are relative to the screen or
641 * Gets the offset of the character located at coordinates @x and @y. @x and @y
642 * are interpreted as being relative to the screen or this widget's window
643 * depending on @coords.
645 * Returns: the offset to the character which is located at
646 * the specified @x and @y coordinates.
649 atk_text_get_offset_at_point (AtkText *text,
656 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
658 iface = ATK_TEXT_GET_IFACE (text);
660 if (iface->get_offset_at_point)
661 return (*(iface->get_offset_at_point)) (text, x, y, coords);
667 * atk_text_get_n_selections:
670 * Gets the number of selected regions.
672 * Returns: The number of selected regions, or -1 if a failure
676 atk_text_get_n_selections (AtkText *text)
680 g_return_val_if_fail (ATK_IS_TEXT (text), -1);
682 iface = ATK_TEXT_GET_IFACE (text);
684 if (iface->get_n_selections)
685 return (*(iface->get_n_selections)) (text);
691 * atk_text_get_selection:
693 * @selection_num: The selection number. The selected regions are
694 * assigned numbers that correspond to how far the region is from the
695 * start of the text. The selected region closest to the beginning
696 * of the text region is assigned the number 0, etc. Note that adding,
697 * moving or deleting a selected region can change the numbering.
698 * @start_offset: passes back the start position of the selected region
699 * @end_offset: passes back the end position of the selected region
701 * Gets the text from the specified selection.
703 * Returns: the selected text.
706 atk_text_get_selection (AtkText *text,
712 gint local_start_offset, local_end_offset;
713 gint *real_start_offset, *real_end_offset;
715 g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
718 real_start_offset = start_offset;
720 real_start_offset = &local_start_offset;
722 real_end_offset = end_offset;
724 real_end_offset = &local_end_offset;
726 iface = ATK_TEXT_GET_IFACE (text);
728 if (iface->get_selection)
730 return (*(iface->get_selection)) (text, selection_num,
731 real_start_offset, real_end_offset);
738 * atk_text_add_selection:
740 * @start_offset: the start position of the selected region
741 * @end_offset: the end position of the selected region
743 * Adds a selection bounded by the specified offsets.
745 * Returns: %TRUE if success, %FALSE otherwise
748 atk_text_add_selection (AtkText *text,
754 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
756 iface = ATK_TEXT_GET_IFACE (text);
758 if (iface->add_selection)
759 return (*(iface->add_selection)) (text, start_offset, end_offset);
765 * atk_text_remove_selection:
767 * @selection_num: The selection number. The selected regions are
768 * assigned numbers that correspond to how far the region is from the
769 * start of the text. The selected region closest to the beginning
770 * of the text region is assigned the number 0, etc. Note that adding,
771 * moving or deleting a selected region can change the numbering.
773 * Removes the specified selection.
775 * Returns: %TRUE if success, %FALSE otherwise
778 atk_text_remove_selection (AtkText *text,
783 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
785 iface = ATK_TEXT_GET_IFACE (text);
787 if (iface->remove_selection)
788 return (*(iface->remove_selection)) (text, selection_num);
794 * atk_text_set_selection:
796 * @selection_num: The selection number. The selected regions are
797 * assigned numbers that correspond to how far the region is from the
798 * start of the text. The selected region closest to the beginning
799 * of the text region is assigned the number 0, etc. Note that adding,
800 * moving or deleting a selected region can change the numbering.
801 * @start_offset: the new start position of the selection
802 * @end_offset: the new end position of the selection
804 * Changes the start and end offset of the specified selection.
806 * Returns: %TRUE if success, %FALSE otherwise
809 atk_text_set_selection (AtkText *text,
816 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
818 iface = ATK_TEXT_GET_IFACE (text);
820 if (iface->set_selection)
822 return (*(iface->set_selection)) (text, selection_num,
823 start_offset, end_offset);
830 * atk_text_set_caret_offset:
834 * Sets the caret (cursor) position to the specified @offset.
836 * Returns: %TRUE if success, %FALSE otherwise.
839 atk_text_set_caret_offset (AtkText *text,
844 g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
846 iface = ATK_TEXT_GET_IFACE (text);
848 if (iface->set_caret_offset)
850 return (*(iface->set_caret_offset)) (text, offset);
859 * atk_attribute_set_free:
860 * @attrib_set: The #AtkAttributeSet to free
862 * Frees the memory used by an #AtkAttributeSet, including all its
866 atk_attribute_set_free (AtkAttributeSet *attrib_set)
883 g_slist_free (attrib_set);
887 * atk_text_attribute_register:
888 * @name: a name string
890 * Associate @name with a new #AtkTextAttribute
892 * Returns: an #AtkTextAttribute associated with @name
895 atk_text_attribute_register (const gchar *name)
897 g_return_val_if_fail (name, ATK_TEXT_ATTR_INVALID);
899 if (!extra_attributes)
900 extra_attributes = g_ptr_array_new ();
902 g_ptr_array_add (extra_attributes, g_strdup (name));
903 return extra_attributes->len + ATK_TEXT_ATTR_LAST_DEFINED;
907 * atk_text_attribute_get_name:
908 * @attr: The #AtkTextAttribute whose name is required
910 * Gets the name corresponding to the #AtkTextAttribute
912 * Returns: a string containing the name; this string should not be freed
914 G_CONST_RETURN gchar*
915 atk_text_attribute_get_name (AtkTextAttribute attr)
917 GTypeClass *type_class;
921 type_class = g_type_class_ref (ATK_TYPE_TEXT_ATTRIBUTE);
922 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
924 value = g_enum_get_value (G_ENUM_CLASS (type_class), attr);
928 name = value->value_nick;
932 if (extra_attributes)
936 n -= ATK_TEXT_ATTR_LAST_DEFINED + 1;
938 if (n < extra_attributes->len)
940 name = g_ptr_array_index (extra_attributes, n);
943 g_type_class_unref (type_class);
948 * atk_text_attribute_for_name:
949 * @name: a string which is the (non-localized) name of an ATK text attribute.
951 * Get the #AtkTextAttribute type corresponding to a text attribute name.
953 * Returns: the #AtkTextAttribute enumerated type corresponding to the specified
955 * or #ATK_TEXT_ATTRIBUTE_INVALID if no matching text attribute is found.
958 atk_text_attribute_for_name (const gchar *name)
960 GTypeClass *type_class;
962 AtkTextAttribute type = ATK_TEXT_ATTR_INVALID;
964 g_return_val_if_fail (name, ATK_TEXT_ATTR_INVALID);
966 type_class = g_type_class_ref (ATK_TYPE_TEXT_ATTRIBUTE);
967 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_TEXT_ATTR_INVALID);
969 value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
979 if (extra_attributes)
981 for (i = 0; i < extra_attributes->len; i++)
983 gchar *extra_attribute = (gchar *)g_ptr_array_index (extra_attributes, i);
985 g_return_val_if_fail (extra_attribute, ATK_TEXT_ATTR_INVALID);
987 if (strcmp (name, extra_attribute) == 0)
989 type = i + 1 + ATK_TEXT_ATTR_LAST_DEFINED;
995 g_type_class_unref (type_class);
1002 * atk_text_attribute_get_value:
1003 * @attr: The #AtkTextAttribute for which a value is required
1004 * @index: The index of the required value
1006 * Gets the value for the index of the #AtkTextAttribute
1008 * Returns: a string containing the value; this string should not be freed;
1009 * NULL is returned if there are no values maintained for the attr value.
1011 G_CONST_RETURN gchar*
1012 atk_text_attribute_get_value (AtkTextAttribute attr,
1017 case ATK_TEXT_ATTR_INVISIBLE:
1018 case ATK_TEXT_ATTR_EDITABLE:
1019 case ATK_TEXT_ATTR_BG_FULL_HEIGHT:
1020 case ATK_TEXT_ATTR_STRIKETHROUGH:
1021 case ATK_TEXT_ATTR_BG_STIPPLE:
1022 case ATK_TEXT_ATTR_FG_STIPPLE:
1023 g_assert (index >= 0 && index < 2);
1025 case ATK_TEXT_ATTR_UNDERLINE:
1026 g_assert (index >= 0 && index < 4);
1027 return underline[index];
1028 case ATK_TEXT_ATTR_WRAP_MODE:
1029 g_assert (index >= 0 && index < 3);
1030 return wrap_mode[index];
1031 case ATK_TEXT_ATTR_DIRECTION:
1032 g_assert (index >= 0 && index < 3);
1033 return direction[index];
1034 case ATK_TEXT_ATTR_JUSTIFICATION:
1035 g_assert (index >= 0 && index < 3);
1036 return justification[index];
1037 case ATK_TEXT_ATTR_STRETCH:
1038 g_assert (index >= 0 && index < 9);
1039 return stretch[index];
1040 case ATK_TEXT_ATTR_VARIANT:
1041 g_assert (index >= 0 && index < 2);
1042 return variant[index];
1043 case ATK_TEXT_ATTR_STYLE:
1044 g_assert (index >= 0 && index < 3);
1045 return style[index];