87800605982648566f48de91b5f3064b65ffc955
[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
22 enum {
23   TEXT_CHANGED,
24   CARET_MOVED,
25   LAST_SIGNAL
26 };
27
28 struct _AtkTextIfaceClass
29 {
30   GObjectClass parent;
31 };
32
33 typedef struct _AtkTextIfaceClass AtkTextIfaceClass;
34
35 static void atk_text_base_init (gpointer *g_class);
36
37 static guint atk_text_signals[LAST_SIGNAL] = { 0 };
38
39 GType
40 atk_text_get_type ()
41 {
42   static GType type = 0;
43
44   if (!type) 
45     {
46       static const GTypeInfo tinfo =
47       {
48         sizeof (AtkTextIface),
49         (GBaseInitFunc) atk_text_base_init,
50         (GBaseFinalizeFunc) NULL,
51         (GClassInitFunc) NULL /* atk_text_interface_init */ ,
52         (GClassFinalizeFunc) NULL,
53
54       };
55
56       type = g_type_register_static (G_TYPE_INTERFACE, "AtkText", &tinfo, 0);
57     }
58
59   return type;
60 }
61
62 static void
63 atk_text_base_init (gpointer *g_class)
64 {
65   static gboolean initialized = FALSE;
66
67   if (! initialized)
68     {
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_newc ("text_changed",
77                      ATK_TYPE_TEXT,
78                      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
79                      G_STRUCT_OFFSET (AtkTextIface, text_changed), 
80                      NULL, NULL,
81                      g_cclosure_marshal_VOID__VOID,
82                      G_TYPE_NONE,
83                      0, G_TYPE_NONE);
84
85     atk_text_signals[CARET_MOVED] =
86       g_signal_newc ("text_caret_moved",
87                      ATK_TYPE_TEXT,
88                      G_SIGNAL_RUN_LAST,
89                      G_STRUCT_OFFSET (AtkTextIface, caret_changed),
90                      NULL, NULL,
91                      g_cclosure_marshal_VOID__INT,
92                      G_TYPE_NONE,
93                      1, G_TYPE_INT);
94   }
95 }
96
97 /**
98  *atk_text_get_text:
99  *@text: an #AtkText
100  *@start_offset: start position
101  *@end_offset: end position
102  *
103  *Returns the text between @start_offset and @end_offset.
104  **/
105 gchar*
106 atk_text_get_text (AtkText      *text,
107                    gint         start_offset,
108                    gint         end_offset)
109 {
110   AtkTextIface *iface;
111
112   g_return_val_if_fail (text != NULL, NULL);
113   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
114
115   iface = ATK_TEXT_GET_IFACE (text);
116
117   if (iface->get_text)
118     return (*(iface->get_text)) (text, start_offset, end_offset);
119   else
120     return NULL;
121 }
122
123 /**
124  *atk_text_get_character_at_offset
125  *@text: an #AtkText
126  *@offset: position
127  *
128  *Returns the character at @offset.
129  **/
130 gunichar
131 atk_text_get_character_at_offset (AtkText      *text,
132                                   gint         offset)
133 {
134   AtkTextIface *iface;
135
136   g_return_val_if_fail (text != NULL, (gunichar) 0);
137   g_return_val_if_fail (ATK_IS_TEXT (text), (gunichar) 0);
138
139   iface = ATK_TEXT_GET_IFACE (text);
140
141   if (iface->get_character_at_offset)
142     return (*(iface->get_character_at_offset)) (text, offset);
143   else
144     return (gunichar) 0;
145 }
146
147 /**
148  *atk_text_get_text_after_offset
149  *@text: an #AtkText
150  *@offset: position
151  *@boundary_type: An #AtkTextBoundary
152  *
153  *Returns the text after @offset up to the specified @boundary_type.
154  **/
155 gchar*
156 atk_text_get_text_after_offset (AtkText          *text,
157                                 gint             offset,
158                                 AtkTextBoundary  boundary_type)
159 {
160   AtkTextIface *iface;
161
162   g_return_val_if_fail (text != NULL, NULL);
163   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
164
165   iface = ATK_TEXT_GET_IFACE (text);
166
167   if (iface->get_text_after_offset)
168     return (*(iface->get_text_after_offset)) (text, offset, boundary_type);
169   else
170     return NULL;
171 }
172
173 /**
174  *atk_text_get_text_at_offset
175  *@text: an #AtkText
176  *@offset: position
177  *@boundary_type: An #AtkTextBoundary
178  *
179  *Returns the text at @offset up to the specified @boundary_type.
180  **/
181 gchar*
182 atk_text_get_text_at_offset (AtkText          *text,
183                              gint             offset,
184                              AtkTextBoundary  boundary_type)
185 {
186   AtkTextIface *iface;
187
188   g_return_val_if_fail (text != NULL, NULL);
189   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
190
191   iface = ATK_TEXT_GET_IFACE (text);
192
193   if (iface->get_text_at_offset)
194     return (*(iface->get_text_at_offset)) (text, offset, boundary_type);
195   else
196     return NULL;
197 }
198
199 /**
200  *atk_text_get_text_before_offset
201  *@text: an #AtkText
202  *@offset: position
203  *@boundary_type: An #AtkTextBoundary
204  *
205  *Returns the text before @offset up to the specified @boundary_type.
206  **/
207 gchar*
208 atk_text_get_text_before_offset (AtkText          *text,
209                                  gint             offset,
210                                  AtkTextBoundary  boundary_type)
211 {
212   AtkTextIface *iface;
213
214   g_return_val_if_fail (text != NULL, NULL);
215   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
216
217   iface = ATK_TEXT_GET_IFACE (text);
218
219   if (iface->get_text_before_offset)
220     return (*(iface->get_text_before_offset)) (text, offset, boundary_type);
221   else
222     return NULL;
223 }
224
225 /**
226  *atk_text_get_caret_offset
227  *@text: an #AtkText
228  *
229  *Returns the position of the caret (cursor).
230  **/
231 gint
232 atk_text_get_caret_offset (AtkText *text)
233 {
234   AtkTextIface *iface;
235
236   g_return_val_if_fail (text != NULL, -1);
237   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
238
239   iface = ATK_TEXT_GET_IFACE (text);
240
241   if (iface->get_caret_offset)
242     return (*(iface->get_caret_offset)) (text);
243   else
244     return -1;
245 }
246
247 /**
248  *atk_text_get_row_col_at_offset
249  *@text: an #AtkText
250  *@offset: position
251  *@row: row number
252  *@col: column number
253  *
254  *Given an @offset, the @row and @col arguments are filled appropriately.
255  **/
256 void
257 atk_text_get_row_col_at_offset (AtkText *text,
258                                 gint offset,
259                                 gint *row,
260                                 gint *col)
261 {
262   AtkTextIface *iface;
263
264   g_return_if_fail (text != NULL);
265   g_return_if_fail (ATK_IS_TEXT (text));
266
267   iface = ATK_TEXT_GET_IFACE (text);
268
269   if (iface->get_row_col_at_offset)
270     (*(iface->get_row_col_at_offset)) (text, offset, row, col);
271   else
272     {
273       *row = 0;
274       *col = 0;
275     }
276 }
277
278 /**
279  *atk_text_get_range_attributes
280  *@text: an #AtkText
281  *@start_offset: start position
282  *@end_offset: end position
283  *
284  *Returns a #PangoAttrList with the text attributes between the
285  *@start_offset and the @end_offset.
286  **/
287 PangoAttrList*
288 atk_text_get_range_attributes (AtkText *text,
289                                gint start_offset,
290                                gint end_offset)
291 {
292   AtkTextIface *iface;
293
294   g_return_val_if_fail (text != NULL, NULL);
295   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
296
297   iface = ATK_TEXT_GET_IFACE (text);
298
299   if (iface->get_range_attributes)
300     return (*(iface->get_range_attributes)) (text, start_offset, end_offset);
301   else
302     return NULL;
303 }
304
305 /**
306  *atk_text_get_character_extents
307  *@text: an #AtkText
308  *@offset: position
309  *@x: x-position of character
310  *@y: y-position of character
311  *@length: length of character
312  *@width: width of character
313  *
314  *Given an @offset, the @x, @y, @length, and @width values are filled
315  *appropriately.
316  **/
317 void
318 atk_text_get_character_extents (AtkText *text,
319                                 gint offset,
320                                 gint *x,
321                                 gint *y,
322                                 gint *length,
323                                 gint *width)
324 {
325   AtkTextIface *iface;
326
327   g_return_if_fail (text != NULL);
328   g_return_if_fail (ATK_IS_TEXT (text));
329
330   iface = ATK_TEXT_GET_IFACE (text);
331
332   if (iface->get_character_extents)
333     (*(iface->get_character_extents)) (text, offset, x, y, length, width);
334   else
335     {
336       *x = 0;
337       *x = 0;
338       *length = 0;
339       *width = 0;
340     }
341 }
342
343 /**
344  *atk_text_get_character_count
345  *@text: an #AtkText
346  *
347  *Returns the number of characters.
348  **/
349 gint
350 atk_text_get_character_count (AtkText *text)
351 {
352   AtkTextIface *iface;
353
354   g_return_val_if_fail (text != NULL, -1);
355   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
356
357   iface = ATK_TEXT_GET_IFACE (text);
358
359   if (iface->get_character_count)
360     return (*(iface->get_character_count)) (text);
361   else
362     return -1;
363 }
364
365 /**
366  *atk_text_get_offset_at_point
367  *@text: an #AtkText
368  *@x: x-position of character
369  *@y: y-position of character
370  *
371  *Returns the offset to the character which is located at
372  *the specified @x and @y coordinates.
373  **/
374 gint
375 atk_text_get_offset_at_point (AtkText *text,
376                               gint x,
377                               gint y)
378 {
379   AtkTextIface *iface;
380
381   g_return_val_if_fail (text != NULL, -1);
382   g_return_val_if_fail (ATK_IS_TEXT (text), -1);
383
384   iface = ATK_TEXT_GET_IFACE (text);
385
386   if (iface->get_offset_at_point)
387     return (*(iface->get_offset_at_point)) (text, x, y);
388   else
389     return -1;
390 }
391
392 /**
393  *atk_text_get_selected_text
394  *@text: an #AtkText
395  *
396  *Returns the selected text.
397  **/
398 gchar*
399 atk_text_get_selected_text (AtkText *text)
400 {
401   AtkTextIface *iface;
402
403   g_return_val_if_fail (text != NULL, NULL);
404   g_return_val_if_fail (ATK_IS_TEXT (text), NULL);
405
406   iface = ATK_TEXT_GET_IFACE (text);
407
408   if (iface->get_selected_text)
409     return (*(iface->get_selected_text)) (text);
410   else
411     return NULL;
412 }
413
414 /**
415  *atk_text_get_selection_bounds
416  *@text: an #AtkText
417  *@start_offset: start position
418  *@end_offset: end position
419  *
420  *@start_offset and @end_offset are filled with the
421  *current selection bounds.
422  **/
423 void
424 atk_text_get_selection_bounds (AtkText *text,
425                                gint    *start_offset,
426                                gint    *end_offset)
427 {
428   AtkTextIface *iface;
429
430   g_return_if_fail (text != NULL);
431   g_return_if_fail (ATK_IS_TEXT (text));
432
433   iface = ATK_TEXT_GET_IFACE (text);
434
435   if (iface->get_selection_bounds)
436     (*(iface->get_selection_bounds)) (text, start_offset, end_offset);
437   else
438   {
439     *start_offset = 0;
440     *end_offset = 0;
441   }
442 }
443
444 /**
445  *atk_text_set_selection_bounds
446  *@text: an #AtkText
447  *@start_offset: start position
448  *@end_offset: end position
449  *
450  *The selection bounds are set to the specified @start_offset
451  *and @end_offset values.
452  *Returns TRUE if success, FALSE otherwise.
453  **/
454 gboolean
455 atk_text_set_selection_bounds (AtkText *text,
456                                gint    start_offset,
457                                gint    end_offset)
458 {
459   AtkTextIface *iface;
460
461   g_return_val_if_fail (text != NULL, FALSE);
462   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
463
464   iface = ATK_TEXT_GET_IFACE (text);
465
466   if (iface->set_selection_bounds)
467     {
468       return (*(iface->set_selection_bounds)) (text, start_offset, end_offset);
469     }
470   else
471     {
472       return FALSE;
473     }
474 }
475
476 /**
477  *atk_text_set_caret_offset
478  *@text: an #AtkText
479  *@offset: position
480  *
481  *Sets the caret (cursor) position to the specified @offset.
482  *Returns TRUE if success, FALSE otherwise.
483  **/
484 gboolean
485 atk_text_set_caret_offset (AtkText *text,
486                            gint    offset)
487 {
488   AtkTextIface *iface;
489
490   g_return_val_if_fail (text != NULL, FALSE);
491   g_return_val_if_fail (ATK_IS_TEXT (text), FALSE);
492
493   iface = ATK_TEXT_GET_IFACE (text);
494
495   if (iface->set_caret_offset)
496     {
497       return (*(iface->set_caret_offset)) (text, offset);
498     }
499   else
500     {
501       return FALSE;
502     }
503 }