Provide implementation of getAttributes
[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 Sun Microsystems Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /* text.c : implements the Text interface */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <atk/atktext.h>
29 #include <libspi/text.h>
30
31 /* Our parent Gtk object type */
32 #define PARENT_TYPE SPI_TYPE_BASE
33
34 static AtkText *
35 get_text_from_servant (PortableServer_Servant servant)
36 {
37   SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
38
39   g_return_val_if_fail (object, NULL);
40   g_return_val_if_fail (ATK_IS_OBJECT(object->gobj), NULL);
41   return ATK_TEXT (object->gobj);
42 }
43
44 static CORBA_string
45 impl_getText (PortableServer_Servant servant,
46               const CORBA_long       startOffset,
47               const CORBA_long       endOffset,
48               CORBA_Environment     *ev)
49 {
50   gchar *txt;
51   CORBA_string rv;
52   AtkText *text = get_text_from_servant (servant);
53
54   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
55   
56   txt = atk_text_get_text (text, (gint) startOffset, (gint) endOffset);
57   if (txt)
58     {
59       rv = CORBA_string_dup (txt);
60       g_free (txt);
61     }
62   else
63     rv = CORBA_string_dup ("");
64
65   return rv;
66 }
67
68
69 CORBA_string
70 impl_getTextAfterOffset (PortableServer_Servant servant,
71                          const CORBA_long offset,
72                          const
73                          Accessibility_TEXT_BOUNDARY_TYPE
74                          type, CORBA_long * startOffset,
75                          CORBA_long * endOffset,
76                          CORBA_Environment *ev)
77 {
78   gchar *txt;
79   CORBA_char *rv;
80   gint intStartOffset, intEndOffset;
81   AtkText *text = get_text_from_servant (servant);
82
83   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
84
85   txt = atk_text_get_text_after_offset (text,
86                                         (gint) offset, (AtkTextBoundary) type,
87                                         &intStartOffset, &intEndOffset);
88   *startOffset = (CORBA_long) intStartOffset;
89   *endOffset = (CORBA_long) intEndOffset;
90
91   if (txt)
92     {
93       rv = CORBA_string_dup (txt);
94       g_free (txt);
95     }
96   else
97     rv = CORBA_string_dup ("");
98
99   return rv;
100 }
101
102
103 static CORBA_string
104 impl_getTextAtOffset (PortableServer_Servant servant,
105                       const CORBA_long offset,
106                       const Accessibility_TEXT_BOUNDARY_TYPE type,
107                       CORBA_long * startOffset,
108                       CORBA_long * endOffset,
109                       CORBA_Environment *ev)
110 {
111   CORBA_char *txt;
112   CORBA_char *rv;
113   gint intStartOffset, intEndOffset;
114   AtkText *text = get_text_from_servant (servant);
115
116   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
117
118   txt = (CORBA_char *) atk_text_get_text_at_offset (
119           text,
120           (gint) offset, (AtkTextBoundary) type,
121           &intStartOffset, &intEndOffset);
122
123   *startOffset = (CORBA_long) intStartOffset;
124   *endOffset = (CORBA_long) intEndOffset;
125
126   if (txt)
127     {
128       rv = CORBA_string_dup (txt);
129       g_free (txt);
130     }
131   else
132     rv = CORBA_string_dup ("");
133
134   return rv;
135 }
136
137
138 static CORBA_unsigned_long
139 impl_getCharacterAtOffset (PortableServer_Servant servant,
140                            const CORBA_long offset,
141                            CORBA_Environment *ev)
142 {
143   AtkText *text = get_text_from_servant (servant);
144
145   g_return_val_if_fail (text != NULL, 0);
146
147   return (CORBA_unsigned_long)
148     atk_text_get_character_at_offset (text, (gint) 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                                          (gint) offset, (AtkTextBoundary) type,
170                                          &intStartOffset, &intEndOffset);
171
172   *startOffset = (CORBA_long) intStartOffset;
173   *endOffset = (CORBA_long) 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 (CORBA_long) 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 = (CORBA_long) intstart_offset;
246   *endOffset = (CORBA_long) 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
263   g_return_if_fail (text != NULL);
264
265   /* FIXME: Casting a CORBA_long to a gint * is inherantly risky */
266   atk_text_get_character_extents (
267           text, (gint) offset,
268           (gint *) x, (gint *) y, (gint *) width, (gint *) height,
269           (AtkCoordType) coordType);
270 }
271
272
273 static CORBA_long
274 impl__get_characterCount (PortableServer_Servant servant,
275                           CORBA_Environment    *ev)
276 {
277   CORBA_long retval;
278   AtkText *text = get_text_from_servant (servant);
279
280   g_return_val_if_fail (text != NULL, 0);
281
282   retval = (CORBA_long) atk_text_get_character_count (text);
283
284   return retval;
285 }
286
287
288 static CORBA_long
289 impl_getOffsetAtPoint (PortableServer_Servant servant,
290                        const CORBA_long x, const CORBA_long y,
291                        const CORBA_short coordType,
292                        CORBA_Environment *ev)
293 {
294   AtkText *text = get_text_from_servant (servant);
295
296   g_return_val_if_fail (text != NULL, -1);
297
298   return (CORBA_long)
299     atk_text_get_offset_at_point (text,
300                                   (gint) x, (gint) 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 (CORBA_long) 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
325   g_return_if_fail (text != NULL);
326
327   atk_text_get_selection (text, (gint) selectionNum,
328                           (gint *) startOffset, (gint *) endOffset);
329 }
330
331
332 static CORBA_boolean
333 impl_addSelection (PortableServer_Servant servant,
334                    const CORBA_long startOffset,
335                    const CORBA_long endOffset,
336                    CORBA_Environment *ev)
337 {
338   AtkText *text = get_text_from_servant (servant);
339
340   g_return_val_if_fail (text != NULL, FALSE);
341
342   return (CORBA_boolean)
343     atk_text_add_selection (text,
344                             (gint) startOffset, (gint) endOffset);
345 }
346
347
348 static CORBA_boolean
349 impl_removeSelection (PortableServer_Servant servant,
350                       const CORBA_long selectionNum,
351                       CORBA_Environment *ev)
352 {
353   AtkText *text = get_text_from_servant (servant);
354
355   g_return_val_if_fail (text != NULL, FALSE);
356
357   return (CORBA_boolean)
358     atk_text_remove_selection (text, (gint) selectionNum);
359 }
360
361
362 static CORBA_boolean
363 impl_setSelection (PortableServer_Servant servant,
364                    const CORBA_long selectionNum,
365                    const CORBA_long startOffset,
366                    const CORBA_long endOffset,
367                    CORBA_Environment *ev)
368 {
369   AtkText *text = get_text_from_servant (servant);
370
371   g_return_val_if_fail (text != NULL, FALSE);
372
373   return (CORBA_boolean)
374     atk_text_set_selection (text,
375                             (gint) selectionNum, (gint) startOffset, (gint) endOffset);
376 }
377
378
379 static CORBA_boolean
380 impl_setCaretOffset (PortableServer_Servant servant,
381                      const CORBA_long value,
382                      CORBA_Environment *ev)
383 {
384   AtkText *text = get_text_from_servant (servant);
385
386   g_return_val_if_fail (text != NULL, FALSE);
387
388   return (CORBA_boolean)
389     atk_text_set_caret_offset (text, (gint) value);
390 }
391
392
393 static void 
394 impl_getRowColAtOffset (PortableServer_Servant servant,
395                         const CORBA_long offset, CORBA_long * row,
396                         CORBA_long * column, CORBA_Environment *ev)
397 {
398   AtkText *text = get_text_from_servant (servant);
399
400   g_return_if_fail (text != NULL);
401
402   g_print ("getRowColAtOffset not yet implemented\n");
403 }
404
405 static void
406 spi_text_class_init (SpiTextClass *klass)
407 {
408   POA_Accessibility_Text__epv *epv = &klass->epv;
409
410   /* Initialize epv table */
411
412   epv->getText = impl_getText;
413   epv->getTextAfterOffset = impl_getTextAfterOffset;
414   epv->getCharacterAtOffset = impl_getCharacterAtOffset;
415   epv->getTextAtOffset = impl_getTextAtOffset;
416   epv->getTextBeforeOffset = impl_getTextBeforeOffset;
417   epv->_get_caretOffset = impl__get_caretOffset;
418   epv->getAttributes = impl_getAttributes;
419   epv->getCharacterExtents = impl_getCharacterExtents;
420   epv->_get_characterCount = impl__get_characterCount;
421   epv->getOffsetAtPoint = impl_getOffsetAtPoint;
422   epv->getNSelections = impl_getNSelections;
423   epv->getSelection = impl_getSelection;
424   epv->addSelection = impl_addSelection;
425   epv->removeSelection = impl_removeSelection;
426   epv->setSelection = impl_setSelection;
427   epv->setCaretOffset = impl_setCaretOffset;
428 }
429
430 static void
431 spi_text_init (SpiText *text)
432 {
433 }
434
435 BONOBO_TYPE_FUNC_FULL (SpiText,
436                        Accessibility_Text,
437                        PARENT_TYPE,
438                        spi_text);
439
440 void
441 spi_text_construct (SpiText *text, AtkObject *obj)
442 {
443   spi_base_construct (SPI_BASE (text), G_OBJECT(obj));
444 }
445
446
447 SpiText *
448 spi_text_interface_new (AtkObject *obj)
449 {
450   SpiText *retval;
451
452   g_return_val_if_fail (ATK_IS_TEXT (obj), NULL);
453
454   retval = g_object_new (SPI_TEXT_TYPE, NULL);
455
456   spi_text_construct (retval, obj);
457
458   return retval;
459 }