Fix for 95827, adds API for registering "AccessibleDeviceListeners"
[platform/core/uifw/at-spi2-atk.git] / libspi / text.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /* text.c : implements the Text interface */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <atk/atktext.h>
30 #include <libspi/text.h>
31
32 /* Our parent Gtk object type */
33 #define PARENT_TYPE SPI_TYPE_BASE
34
35 static AtkText *
36 get_text_from_servant (PortableServer_Servant servant)
37 {
38   SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
39
40   g_return_val_if_fail (object, NULL);
41   g_return_val_if_fail (ATK_IS_OBJECT(object->gobj), NULL);
42   return ATK_TEXT (object->gobj);
43 }
44
45 static CORBA_string
46 impl_getText (PortableServer_Servant servant,
47               const CORBA_long       startOffset,
48               const CORBA_long       endOffset,
49               CORBA_Environment     *ev)
50 {
51   gchar *txt;
52   CORBA_string rv;
53   AtkText *text = get_text_from_servant (servant);
54
55   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
56   
57   txt = atk_text_get_text (text, startOffset, endOffset);
58   if (txt)
59     {
60       rv = CORBA_string_dup (txt);
61       g_free (txt);
62     }
63   else
64     rv = CORBA_string_dup ("");
65
66   return rv;
67 }
68
69
70 CORBA_string
71 impl_getTextAfterOffset (PortableServer_Servant servant,
72                          const CORBA_long offset,
73                          const
74                          Accessibility_TEXT_BOUNDARY_TYPE
75                          type, CORBA_long * startOffset,
76                          CORBA_long * endOffset,
77                          CORBA_Environment *ev)
78 {
79   gchar *txt;
80   CORBA_char *rv;
81   gint intStartOffset, intEndOffset;
82   AtkText *text = get_text_from_servant (servant);
83
84   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
85
86   txt = atk_text_get_text_after_offset (text,
87                                         offset, (AtkTextBoundary) type,
88                                         &intStartOffset, &intEndOffset);
89   *startOffset = intStartOffset;
90   *endOffset = intEndOffset;
91
92   if (txt)
93     {
94       rv = CORBA_string_dup (txt);
95       g_free (txt);
96     }
97   else
98     rv = CORBA_string_dup ("");
99
100   return rv;
101 }
102
103
104 static CORBA_string
105 impl_getTextAtOffset (PortableServer_Servant servant,
106                       const CORBA_long offset,
107                       const Accessibility_TEXT_BOUNDARY_TYPE type,
108                       CORBA_long * startOffset,
109                       CORBA_long * endOffset,
110                       CORBA_Environment *ev)
111 {
112   gchar *txt;
113   CORBA_char *rv;
114   gint intStartOffset, intEndOffset;
115   AtkText *text = get_text_from_servant (servant);
116
117   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
118
119   txt = atk_text_get_text_at_offset (
120           text,
121           offset, (AtkTextBoundary) type,
122           &intStartOffset, &intEndOffset);
123
124   *startOffset = intStartOffset;
125   *endOffset = intEndOffset;
126
127   if (txt)
128     {
129       rv = CORBA_string_dup (txt);
130       g_free (txt);
131     }
132   else
133     rv = CORBA_string_dup ("");
134
135   return rv;
136 }
137
138
139 static CORBA_unsigned_long
140 impl_getCharacterAtOffset (PortableServer_Servant servant,
141                            const CORBA_long offset,
142                            CORBA_Environment *ev)
143 {
144   AtkText *text = get_text_from_servant (servant);
145
146   g_return_val_if_fail (text != NULL, 0);
147
148   return atk_text_get_character_at_offset (text, offset);
149 }
150
151
152 static CORBA_string
153 impl_getTextBeforeOffset (PortableServer_Servant servant,
154                           const CORBA_long offset,
155                           const
156                           Accessibility_TEXT_BOUNDARY_TYPE
157                           type, CORBA_long * startOffset,
158                           CORBA_long * endOffset,
159                           CORBA_Environment *ev)
160 {
161   gchar *txt;
162   CORBA_char *rv;
163   gint intStartOffset, intEndOffset;
164   AtkText *text = get_text_from_servant (servant);
165
166   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
167
168   txt = atk_text_get_text_before_offset (text,
169                                          offset, (AtkTextBoundary) type,
170                                          &intStartOffset, &intEndOffset);
171
172   *startOffset = intStartOffset;
173   *endOffset = intEndOffset;
174
175   if (txt)
176     {
177       rv = CORBA_string_dup (txt);
178       g_free (txt);
179     }
180   else
181     rv = CORBA_string_dup ("");
182
183   return rv;
184 }
185
186
187 static CORBA_long
188 impl__get_caretOffset (PortableServer_Servant servant,
189                      CORBA_Environment *ev)
190 {
191   AtkText *text = get_text_from_servant (servant);
192
193   g_return_val_if_fail (text != NULL, -1);
194
195   return atk_text_get_caret_offset (text);
196 }
197
198
199 static CORBA_char *
200 _string_from_attribute_set (AtkAttributeSet *set)
201 {
202   gchar *attributes, *tmp, *tmp2;
203   CORBA_char *rv;
204   GSList *cur_attr;
205   AtkAttribute *at;
206   
207   attributes = g_strdup ("");
208   cur_attr = (GSList *) set;
209   while (cur_attr)
210     {
211       at = (AtkAttribute *) cur_attr->data;
212       tmp = g_strdup_printf ("%s%s:%s%s",
213                              ((GSList *)(set) == cur_attr) ? "" : " ",
214                              at->name, at->value,
215                              (cur_attr->next) ? ";" : "");
216       tmp2 = g_strconcat (attributes, tmp, NULL);
217       g_free (tmp);
218       g_free (attributes);
219       attributes = tmp2;
220       cur_attr = cur_attr->next;
221     }
222   rv = CORBA_string_dup (attributes);
223   g_free (attributes);
224   return rv;
225 }
226
227
228
229 static CORBA_string
230 impl_getAttributes (PortableServer_Servant servant,
231                     const CORBA_long offset,
232                     CORBA_long * startOffset,
233                     CORBA_long * endOffset,
234                     CORBA_Environment *ev)
235 {
236   AtkAttributeSet *set;
237   gint intstart_offset, intend_offset;
238   CORBA_char *rv;
239   AtkText *text = get_text_from_servant (servant);
240
241   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
242
243   set = atk_text_get_run_attributes (text, offset,
244                                      &intstart_offset, &intend_offset);
245   *startOffset = intstart_offset;
246   *endOffset = intend_offset;
247   rv = _string_from_attribute_set (set);
248   atk_attribute_set_free (set);
249   return rv;  
250 }
251
252
253 static void 
254 impl_getCharacterExtents (PortableServer_Servant servant,
255                           const CORBA_long offset, CORBA_long * x,
256                           CORBA_long * y, CORBA_long * width,
257                           CORBA_long * height,
258                           const CORBA_short coordType,
259                           CORBA_Environment *ev)
260 {
261   AtkText *text = get_text_from_servant (servant);
262   gint ix, iy, iw, ih;
263
264   g_return_if_fail (text != NULL);
265
266   atk_text_get_character_extents (
267           text, offset,
268           &ix, &iy, &iw, &ih,
269           (AtkCoordType) coordType);
270   *x = ix;
271   *y = iy;
272   *width = iw;
273   *height = ih;
274 }
275
276
277 static CORBA_long
278 impl__get_characterCount (PortableServer_Servant servant,
279                           CORBA_Environment    *ev)
280 {
281   AtkText *text = get_text_from_servant (servant);
282
283   g_return_val_if_fail (text != NULL, 0);
284
285   return atk_text_get_character_count (text);
286 }
287
288
289 static CORBA_long
290 impl_getOffsetAtPoint (PortableServer_Servant servant,
291                        const CORBA_long x, const CORBA_long y,
292                        const CORBA_short coordType,
293                        CORBA_Environment *ev)
294 {
295   AtkText *text = get_text_from_servant (servant);
296
297   g_return_val_if_fail (text != NULL, -1);
298
299   return atk_text_get_offset_at_point (text,
300                                   x, y,
301                                   (AtkCoordType) coordType);
302 }
303
304
305 static CORBA_long
306 impl_getNSelections (PortableServer_Servant servant,
307                      CORBA_Environment *ev)
308 {
309   AtkText *text = get_text_from_servant (servant);
310
311   g_return_val_if_fail (text != NULL, 0);
312
313   return atk_text_get_n_selections (text);
314 }
315
316
317 static void 
318 impl_getSelection (PortableServer_Servant servant,
319                    const CORBA_long selectionNum,
320                    CORBA_long * startOffset, CORBA_long * endOffset,
321                    CORBA_Environment *ev)
322 {
323   AtkText *text = get_text_from_servant (servant);
324   gint intStartOffset, intEndOffset;
325   
326   g_return_if_fail (text != NULL);
327
328   /* atk_text_get_selection returns gchar* which we discard */
329   g_free (atk_text_get_selection (text, selectionNum,
330                                   &intStartOffset, &intEndOffset));
331   
332   *startOffset = intStartOffset;
333   *endOffset = intEndOffset;
334 }
335
336
337 static CORBA_boolean
338 impl_addSelection (PortableServer_Servant servant,
339                    const CORBA_long startOffset,
340                    const CORBA_long endOffset,
341                    CORBA_Environment *ev)
342 {
343   AtkText *text = get_text_from_servant (servant);
344
345   g_return_val_if_fail (text != NULL, FALSE);
346
347   return atk_text_add_selection (text,
348                             startOffset, endOffset);
349 }
350
351
352 static CORBA_boolean
353 impl_removeSelection (PortableServer_Servant servant,
354                       const CORBA_long selectionNum,
355                       CORBA_Environment *ev)
356 {
357   AtkText *text = get_text_from_servant (servant);
358
359   g_return_val_if_fail (text != NULL, FALSE);
360
361   return atk_text_remove_selection (text, selectionNum);
362 }
363
364
365 static CORBA_boolean
366 impl_setSelection (PortableServer_Servant servant,
367                    const CORBA_long selectionNum,
368                    const CORBA_long startOffset,
369                    const CORBA_long endOffset,
370                    CORBA_Environment *ev)
371 {
372   AtkText *text = get_text_from_servant (servant);
373
374   g_return_val_if_fail (text != NULL, FALSE);
375
376   return atk_text_set_selection (text,
377                             selectionNum, startOffset, endOffset);
378 }
379
380
381 static CORBA_boolean
382 impl_setCaretOffset (PortableServer_Servant servant,
383                      const CORBA_long value,
384                      CORBA_Environment *ev)
385 {
386   AtkText *text = get_text_from_servant (servant);
387
388   g_return_val_if_fail (text != NULL, FALSE);
389
390   return atk_text_set_caret_offset (text, value);
391 }
392
393 static void
394 spi_text_class_init (SpiTextClass *klass)
395 {
396   POA_Accessibility_Text__epv *epv = &klass->epv;
397
398   /* Initialize epv table */
399
400   epv->getText = impl_getText;
401   epv->getTextAfterOffset = impl_getTextAfterOffset;
402   epv->getCharacterAtOffset = impl_getCharacterAtOffset;
403   epv->getTextAtOffset = impl_getTextAtOffset;
404   epv->getTextBeforeOffset = impl_getTextBeforeOffset;
405   epv->_get_caretOffset = impl__get_caretOffset;
406   epv->getAttributes = impl_getAttributes;
407   epv->getCharacterExtents = impl_getCharacterExtents;
408   epv->_get_characterCount = impl__get_characterCount;
409   epv->getOffsetAtPoint = impl_getOffsetAtPoint;
410   epv->getNSelections = impl_getNSelections;
411   epv->getSelection = impl_getSelection;
412   epv->addSelection = impl_addSelection;
413   epv->removeSelection = impl_removeSelection;
414   epv->setSelection = impl_setSelection;
415   epv->setCaretOffset = impl_setCaretOffset;
416 }
417
418 static void
419 spi_text_init (SpiText *text)
420 {
421 }
422
423 BONOBO_TYPE_FUNC_FULL (SpiText,
424                        Accessibility_Text,
425                        PARENT_TYPE,
426                        spi_text);
427
428 void
429 spi_text_construct (SpiText *text, AtkObject *obj)
430 {
431   spi_base_construct (SPI_BASE (text), G_OBJECT(obj));
432 }
433
434
435 SpiText *
436 spi_text_interface_new (AtkObject *obj)
437 {
438   SpiText *retval;
439
440   g_return_val_if_fail (ATK_IS_TEXT (obj), NULL);
441
442   retval = g_object_new (SPI_TEXT_TYPE, NULL);
443
444   spi_text_construct (retval, obj);
445
446   return retval;
447 }