Swapped order of width and height arguments to
[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 struct _AtkTextIfaceClass
30 {
31   GObjectClass parent;
32 };
33
34 typedef struct _AtkTextIfaceClass AtkTextIfaceClass;
35
36 static void atk_text_base_init (gpointer *g_class);
37
38 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
39
40 GType
41 atk_text_get_type ()
42 {
43   static GType type = 0;
44
45   if (!type) 
46     {
47       static const GTypeInfo tinfo =
48       {
49         sizeof (AtkTextIface),
50         (GBaseInitFunc) atk_text_base_init,
51         (GBaseFinalizeFunc) NULL,
52         (GClassInitFunc) NULL /* atk_text_interface_init */ ,
53         (GClassFinalizeFunc) NULL,
54
55       };
56
57       type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
58     }
59
60   return type;
61 }
62
63 static void
64 atk_text_base_init (gpointer *g_class)
65 {
66   static gboolean initialized = FALSE;
67   
68   if (! initialized)
69     {
70       /* 
71        * Note that text_changed signal supports details "insert", "delete", 
72        * possibly "replace". 
73        */
74       
75       atk_text_signals[TEXT_CHANGED] =
76         g_signal_new ("text_changed",
77                       ATK_TYPE_TEXT,
78                       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
79                       G_STRUCT_OFFSET (AtkTextIface, text_changed), 
80                       (GSignalAccumulator) NULL, NULL,
81                       atk_marshal_VOID__INT_INT,
82                       G_TYPE_NONE,
83                       2, G_TYPE_INT, G_TYPE_INT);
84       
85       atk_text_signals[CARET_MOVED] =
86         g_signal_new ("text_caret_moved",
87                       ATK_TYPE_TEXT,
88                       G_SIGNAL_RUN_LAST,
89                       G_STRUCT_OFFSET (AtkTextIface, caret_changed),
90                       (GSignalAccumulator) NULL, NULL,
91                       g_cclosure_marshal_VOID__INT,
92                       G_TYPE_NONE,
93                       1, G_TYPE_INT);
94       
95       initialized = TRUE;
96     }
97 }
98
99 /**
100  * atk_text_get_text:
101  * @text: an #AtkText
102  * @start_offset: start position
103  * @end_offset: end position
104  *
105  * Gets the specified text.
106  *
107  * Returns: the text from @start_offset up to, but not including @end_offset.
108  **/
109 gchar*
110 atk_text_get_text (AtkText      *text,
111                    gint         start_offset,
112                    gint         end_offset)
113 {
114   AtkTextIface *iface;
115
116   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
117
118   iface = ATK_TEXT_GET_IFACE (text);
119
120   if (iface->get_text)
121     return (*(iface->get_text)) (text, start_offset, end_offset);
122   else
123     return NULL;
124 }
125
126 /**
127  * atk_text_get_character_at_offset:
128  * @text: an #AtkText
129  * @offset: position
130  *
131  * Gets the specified text.
132  *
133  * Returns: the character at @offset.
134  **/
135 gunichar
136 atk_text_get_character_at_offset (AtkText      *text,
137                                   gint         offset)
138 {
139   AtkTextIface *iface;
140
141   g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
142
143   iface = ATK_TEXT_GET_IFACE (text);
144
145   if (iface->get_character_at_offset)
146     return (*(iface->get_character_at_offset)) (text, offset);
147   else
148     return (gunichar) 0;
149 }
150
151 /**
152  * atk_text_get_text_after_offset:
153  * @text: an #AtkText
154  * @offset: position
155  * @boundary_type: An #AtkTextBoundary
156  * @startOffset: the start offset of the returned string.
157  * @endOffset: the end offset of the returned string.
158  *
159  * Gets the specified text.
160  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
161  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
162  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
163  * will be the offset and will continue to the start of the next sentence. 
164  * The first word may not be a complete word. Similarly for 
165  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
166  * ATK_TEXT_BOUNDARY_LINE_END
167  *
168  * Returns: the text after @offset up to the specified @boundary_type.
169  **/
170 gchar*
171 atk_text_get_text_after_offset (AtkText          *text,
172                                 gint             offset,
173                                 AtkTextBoundary  boundary_type,
174                                 gint             *startOffset,
175                                 gint             *endOffset)
176 {
177   AtkTextIface *iface;
178
179   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
180
181   iface = ATK_TEXT_GET_IFACE (text);
182
183   if (iface->get_text_after_offset)
184     return (*(iface->get_text_after_offset)) (text, offset, boundary_type, startOffset, endOffset);
185   else
186     return NULL;
187 }
188
189 /**
190  * atk_text_get_text_at_offset:
191  * @text: an #AtkText
192  * @offset: position
193  * @boundary_type: An #AtkTextBoundary
194  * @startOffset: the start offset of the returned string.
195  * @endOffset: the end offset of the returned string.
196  *
197  * Gets the specified text.
198  * If the boundary_type is ATK_TEXT_BOUNDARY_WORD_START or 
199  * ATK_TEXT_BOUNDARY_WORD_END a complete word is returned; 
200  * if the boundary type is  ATK_TEXT_BOUNDARY_SENTENCE_START or 
201  * ATK_TEXT_BOUNDARY_SENTENCE_END a complete sentence
202  * is returned; if the boundary type is ATK_TEXT_BOUNDARY_LINE_START or
203  * ATK_TEXT_BOUNDARY_LINE_END a complete line is returned.
204  *
205  * Returns: the text at @offset up to the specified @boundary_type.
206  **/
207 gchar*
208 atk_text_get_text_at_offset (AtkText          *text,
209                              gint             offset,
210                              AtkTextBoundary  boundary_type,
211                              gint             *startOffset,
212                              gint             *endOffset)
213 {
214   AtkTextIface *iface;
215
216   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
217
218   iface = ATK_TEXT_GET_IFACE (text);
219
220   if (iface->get_text_at_offset)
221     return (*(iface->get_text_at_offset)) (text, offset, boundary_type, startOffset, endOffset);
222   else
223     return NULL;
224 }
225
226 /**
227  * atk_text_get_text_before_offset:
228  * @text: an #AtkText
229  * @offset: position
230  * @boundary_type: An #AtkTextBoundary
231  * @startOffset: the start offset of the returned string.
232  * @endOffset: the end offset of the returned string.
233  *
234  * Gets the specified text.
235  * If the boundary type is ATK_TEXT_BOUNDARY_WORD_START or
236  * ATK_TEXT_BOUNDARY_WORD_END part of a word may be returned.
237  * If the boundary type is ATK_TEXT_BOUNDARY_SENTENCE_START the start point 
238  * will be at the start of the sentence, and will continue to the offset. 
239  * The last word may not be a complete word. Similarly for 
240  * ATK_TEXT_BOUNDARY_SENTENCE_END, ATK_TEXT_BOUNDARY_LINE_START and
241  * ATK_TEXT_BOUNDARY_LINE_END
242  *
243  * Returns: the text before @offset starting from the specified @boundary_type.
244  **/
245 gchar*
246 atk_text_get_text_before_offset (AtkText          *text,
247                                  gint             offset,
248                                  AtkTextBoundary  boundary_type,
249                                  gint             *startOffset,
250                                  gint             *endOffset)
251 {
252   AtkTextIface *iface;
253
254   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
255
256   iface = ATK_TEXT_GET_IFACE (text);
257
258   if (iface->get_text_before_offset)
259     return (*(iface->get_text_before_offset)) (text, offset, boundary_type, startOffset, endOffset);
260   else
261     return NULL;
262 }
263
264 /**
265  * atk_text_get_caret_offset:
266  * @text: an #AtkText
267  *
268  * Gets the offset position of the caret (cursor).
269  *
270  * Returns: the offset position of the caret (cursor).
271  **/
272 gint
273 atk_text_get_caret_offset (AtkText *text)
274 {
275   AtkTextIface *iface;
276
277   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
278
279   iface = ATK_TEXT_GET_IFACE (text);
280
281   if (iface->get_caret_offset)
282     return (*(iface->get_caret_offset)) (text);
283   else
284     return -1;
285 }
286
287 /**
288  * atk_text_get_character_extents:
289  * @text: an #AtkText
290  * @offset: position
291  * @x: x-position of character
292  * @y: y-position of character
293  * @width: width of character
294  * @height: height of character
295  * @coords: specify whether coordinates are relative to the screen or widget window 
296  *
297  * Given an @offset, the @x, @y, @width, and @height values are filled
298  * appropriately. 
299  **/
300 void
301 atk_text_get_character_extents (AtkText *text,
302                                 gint offset,
303                                 gint *x,
304                                 gint *y,
305                                 gint *width,
306                                 gint *height,
307                                 AtkCoordType coords)
308 {
309   AtkTextIface *iface;
310
311   g_return_if_fail (ATK_IS_TEXT (text));
312
313   iface = ATK_TEXT_GET_IFACE (text);
314
315   if (iface->get_character_extents)
316     (*(iface->get_character_extents)) (text, offset, x, y, width, height, coords);
317   else
318     {
319       *x = 0;
320       *x = 0;
321       *width = 0;
322       *height = 0;
323     }
324 }
325
326 /**
327  *atk_text_ref_run_attributes:
328  *@text: an #AtkText
329  *@offset: the offset at which to get the attributes
330  *@start_offset: the address to put the start offset of the range
331  *@end_offset: the address to put the end offset of the range
332  *
333  *Creates an #AtkAttributeSet which consists of the attributes explicitly
334  *set at the position @offset in the text. @start_offset and @end_offset are
335  *set to the start and end of the range around @offset where the attributes are
336  *invariant. See the ATK_ATTRIBUTE macros, such as #ATK_ATTRIBUTE_LEFT_MARGIN
337  *for types of text attributes that can be returned. Note that other 
338  *attributes that do not have corresponding macros may also be returned.
339  *
340  *Returns: an #AtkAttributeSet which contains the attributes explicitly set
341  *at @offset
342  **/
343 AtkAttributeSet* atk_text_ref_run_attributes              (AtkText          *text,
344                                                            gint             offset,
345                                                            gint             *start_offset,
346                                                            gint             *end_offset)
347 {
348   AtkTextIface *iface;
349
350   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
351
352   iface = ATK_TEXT_GET_IFACE (text);
353
354   if (iface->ref_run_attributes)
355     return (*(iface->ref_run_attributes)) (text, offset, start_offset, end_offset);
356   else
357     return NULL;
358 }
359
360 /**
361  * atk_text_get_character_count:
362  * @text: an #AtkText
363  *
364  * Gets the character count.
365  *
366  * Returns: the number of characters.
367  **/
368 gint
369 atk_text_get_character_count (AtkText *text)
370 {
371   AtkTextIface *iface;
372
373   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
374
375   iface = ATK_TEXT_GET_IFACE (text);
376
377   if (iface->get_character_count)
378     return (*(iface->get_character_count)) (text);
379   else
380     return -1;
381 }
382
383 /**
384  * atk_text_get_offset_at_point:
385  * @text: an #AtkText
386  * @x: screen x-position of character
387  * @y: screen y-position of character
388  * @coords: specify whether coordinates are relative to the screen or
389  * widget window 
390  *
391  * Gets the offset of the character located at coordinates @x and @y. @x and @y
392  * are interpreted as being relative to the screen or this widget's window
393  * depending on @coords.
394  *
395  * Returns: the offset to the character which is located at
396  * the specified @x and @y coordinates.
397  **/
398 gint
399 atk_text_get_offset_at_point (AtkText *text,
400                               gint x,
401                               gint y,
402                               AtkCoordType coords)
403 {
404   AtkTextIface *iface;
405
406   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
407
408   iface = ATK_TEXT_GET_IFACE (text);
409
410   if (iface->get_offset_at_point)
411     return (*(iface->get_offset_at_point)) (text, x, y, coords);
412   else
413     return -1;
414 }
415
416 /**
417  * atk_text_get_n_selections:
418  * @text: an #AtkText
419  *
420  * Gets the number of selected regions.
421  *
422  * Returns: The number of selected regions, or -1 if a failure
423  *   occurred.
424  **/
425 gint
426 atk_text_get_n_selections (AtkText *text)
427 {
428   AtkTextIface *iface;
429
430   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
431
432   iface = ATK_TEXT_GET_IFACE (text);
433
434   if (iface->get_n_selections)
435     return (*(iface->get_n_selections)) (text);
436   else
437     return -1;
438 }
439
440 /**
441  * atk_text_get_selection:
442  * @text: an #AtkText
443  * @selection_num: The selection number.  The selected regions are
444  * assigned numbers that correspond to how far the region is from the
445  * start of the text.  The selected region closest to the beginning
446  * of the text region is assigned the number 0, etc.  Note that adding,
447  * moving or deleting a selected region can change the numbering.
448  * @start_offset: passes back the start position of the selected region
449  * @end_offset: passes back the end position of the selected region
450  *
451  * Gets the text from the specified selection.
452  *
453  * Returns: the selected text.
454  **/
455 gchar*
456 atk_text_get_selection (AtkText *text, gint selection_num,
457    gint *start_offset, gint *end_offset)
458 {
459   AtkTextIface *iface;
460
461   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
462
463   iface = ATK_TEXT_GET_IFACE (text);
464
465   if (iface->get_selection)
466   {
467     return (*(iface->get_selection)) (text, selection_num,
468        start_offset, end_offset);
469   }
470   else
471     return NULL;
472 }
473
474 /**
475  * atk_text_add_selection:
476  * @text: an #AtkText
477  * @start_offset: the start position of the selected region
478  * @end_offset: the end position of the selected region
479  *
480  * Adds a selection bounded by the specified offsets.
481  *
482  * Returns: %TRUE if success, %FALSE otherwise
483  **/
484 gboolean
485 atk_text_add_selection (AtkText *text, gint start_offset,
486    gint end_offset)
487 {
488   AtkTextIface *iface;
489
490   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
491
492   iface = ATK_TEXT_GET_IFACE (text);
493
494   if (iface->add_selection)
495     return (*(iface->add_selection)) (text, start_offset, end_offset);
496   else
497     return FALSE;
498 }
499
500 /**
501  * atk_text_remove_selection:
502  * @text: an #AtkText
503  * @selection_num: The selection number.  The selected regions are
504  * assigned numbers that correspond to how far the region is from the
505  * start of the text.  The selected region closest to the beginning
506  * of the text region is assigned the number 0, etc.  Note that adding,
507  * moving or deleting a selected region can change the numbering.
508  *
509  * Removes the specified selection.
510  *
511  * Returns: %TRUE if success, %FALSE otherwise
512  **/
513 gboolean
514 atk_text_remove_selection (AtkText *text, gint selection_num)
515 {
516   AtkTextIface *iface;
517
518   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
519
520   iface = ATK_TEXT_GET_IFACE (text);
521
522   if (iface->remove_selection)
523     return (*(iface->remove_selection)) (text, selection_num);
524   else
525     return FALSE;
526 }
527
528 /**
529  * atk_text_set_selection:
530  * @text: an #AtkText
531  * @selection_num: The selection number.  The selected regions are
532  * assigned numbers that correspond to how far the region is from the
533  * start of the text.  The selected region closest to the beginning
534  * of the text region is assigned the number 0, etc.  Note that adding,
535  * moving or deleting a selected region can change the numbering.
536  * @start_offset: the new start position of the selection
537  * @end_offset: the new end position of the selection
538  *
539  * Changes the start and end offset of the specified selection.
540  *
541  * Returns: %TRUE if success, %FALSE otherwise
542  **/
543 gboolean
544 atk_text_set_selection (AtkText *text, gint selection_num,
545    gint start_offset, gint end_offset)
546 {
547   AtkTextIface *iface;
548
549   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
550
551   iface = ATK_TEXT_GET_IFACE (text);
552
553   if (iface->set_selection)
554   {
555     return (*(iface->set_selection)) (text, selection_num,
556        start_offset, end_offset);
557   }
558   else
559     return FALSE;
560 }
561
562 /**
563  * atk_text_set_caret_offset:
564  * @text: an #AtkText
565  * @offset: position
566  *
567  * Sets the caret (cursor) position to the specified @offset.
568  *
569  * Returns: %TRUE if success, %FALSE otherwise.
570  **/
571 gboolean
572 atk_text_set_caret_offset (AtkText *text,
573                            gint    offset)
574 {
575   AtkTextIface *iface;
576
577   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
578
579   iface = ATK_TEXT_GET_IFACE (text);
580
581   if (iface->set_caret_offset)
582     {
583       return (*(iface->set_caret_offset)) (text, offset);
584     }
585   else
586     {
587       return FALSE;
588     }
589 }
590
591 /**
592  * atk_attribute_set_free:
593  * @attrib_set: The #AtkAttributeSet to free
594  *
595  * Frees the memory used by an #AtkAttributeSet, including all its
596  * #AtkAttributes.
597  **/
598 void
599 atk_attribute_set_free(AtkAttributeSet *attrib_set)
600 {
601   gint index;
602
603   if (attrib_set == NULL)
604     return;
605
606   for (index = 0; index < g_slist_length(attrib_set); index++)
607   {
608     g_free(((AtkAttribute*) (g_slist_nth(attrib_set,index)->data))->name);
609     g_free(((AtkAttribute*) (g_slist_nth(attrib_set,index)->data))->value);
610   }
611   g_slist_free(attrib_set);
612 }