Updated HACKING, and fixed memory leak in libspi/text.c
[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, startOffset, 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                                         offset, (AtkTextBoundary) type,
87                                         &intStartOffset, &intEndOffset);
88   *startOffset = intStartOffset;
89   *endOffset = 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   gchar *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 = atk_text_get_text_at_offset (
119           text,
120           offset, (AtkTextBoundary) type,
121           &intStartOffset, &intEndOffset);
122
123   *startOffset = intStartOffset;
124   *endOffset = 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 atk_text_get_character_at_offset (text, offset);
148 }
149
150
151 static CORBA_string
152 impl_getTextBeforeOffset (PortableServer_Servant servant,
153                           const CORBA_long offset,
154                           const
155                           Accessibility_TEXT_BOUNDARY_TYPE
156                           type, CORBA_long * startOffset,
157                           CORBA_long * endOffset,
158                           CORBA_Environment *ev)
159 {
160   gchar *txt;
161   CORBA_char *rv;
162   gint intStartOffset, intEndOffset;
163   AtkText *text = get_text_from_servant (servant);
164
165   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
166
167   txt = atk_text_get_text_before_offset (text,
168                                          offset, (AtkTextBoundary) type,
169                                          &intStartOffset, &intEndOffset);
170
171   *startOffset = intStartOffset;
172   *endOffset = intEndOffset;
173
174   if (txt)
175     {
176       rv = CORBA_string_dup (txt);
177       g_free (txt);
178     }
179   else
180     rv = CORBA_string_dup ("");
181
182   return rv;
183 }
184
185
186 static CORBA_long
187 impl__get_caretOffset (PortableServer_Servant servant,
188                      CORBA_Environment *ev)
189 {
190   AtkText *text = get_text_from_servant (servant);
191
192   g_return_val_if_fail (text != NULL, -1);
193
194   return atk_text_get_caret_offset (text);
195 }
196
197
198 static CORBA_char *
199 _string_from_attribute_set (AtkAttributeSet *set)
200 {
201   gchar *attributes, *tmp, *tmp2;
202   CORBA_char *rv;
203   GSList *cur_attr;
204   AtkAttribute *at;
205   
206   attributes = g_strdup ("");
207   cur_attr = (GSList *) set;
208   while (cur_attr)
209     {
210       at = (AtkAttribute *) cur_attr->data;
211       tmp = g_strdup_printf ("%s%s:%s%s",
212                              ((GSList *)(set) == cur_attr) ? "" : " ",
213                              at->name, at->value,
214                              (cur_attr->next) ? ", " : "");
215       tmp2 = g_strconcat (attributes, tmp, NULL);
216       g_free (tmp);
217       g_free (attributes);
218       attributes = tmp2;
219       cur_attr = cur_attr->next;
220     }
221   rv = CORBA_string_dup (attributes);
222   g_free (attributes);
223   return rv;
224 }
225
226
227
228 static CORBA_string
229 impl_getAttributes (PortableServer_Servant servant,
230                     const CORBA_long offset,
231                     CORBA_long * startOffset,
232                     CORBA_long * endOffset,
233                     CORBA_Environment *ev)
234 {
235   AtkAttributeSet *set;
236   gint intstart_offset, intend_offset;
237   CORBA_char *rv;
238   AtkText *text = get_text_from_servant (servant);
239
240   g_return_val_if_fail (text != NULL, CORBA_string_dup (""));
241
242   set = atk_text_get_run_attributes (text, offset,
243                                      &intstart_offset, &intend_offset);
244   *startOffset = intstart_offset;
245   *endOffset = intend_offset;
246   rv = _string_from_attribute_set (set);
247   atk_attribute_set_free (set);
248   return rv;  
249 }
250
251
252 static void 
253 impl_getCharacterExtents (PortableServer_Servant servant,
254                           const CORBA_long offset, CORBA_long * x,
255                           CORBA_long * y, CORBA_long * width,
256                           CORBA_long * height,
257                           const CORBA_short coordType,
258                           CORBA_Environment *ev)
259 {
260   AtkText *text = get_text_from_servant (servant);
261   gint ix, iy, iw, ih;
262
263   g_return_if_fail (text != NULL);
264
265   atk_text_get_character_extents (
266           text, offset,
267           &ix, &iy, &iw, &ih,
268           (AtkCoordType) coordType);
269   *x = ix;
270   *y = iy;
271   *width = iw;
272   *height = ih;
273 }
274
275
276 static CORBA_long
277 impl__get_characterCount (PortableServer_Servant servant,
278                           CORBA_Environment    *ev)
279 {
280   AtkText *text = get_text_from_servant (servant);
281
282   g_return_val_if_fail (text != NULL, 0);
283
284   return atk_text_get_character_count (text);
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 atk_text_get_offset_at_point (text,
299                                   x, y,
300                                   (AtkCoordType) coordType);
301 }
302
303
304 static CORBA_long
305 impl_getNSelections (PortableServer_Servant servant,
306                      CORBA_Environment *ev)
307 {
308   AtkText *text = get_text_from_servant (servant);
309
310   g_return_val_if_fail (text != NULL, 0);
311
312   return atk_text_get_n_selections (text);
313 }
314
315
316 static void 
317 impl_getSelection (PortableServer_Servant servant,
318                    const CORBA_long selectionNum,
319                    CORBA_long * startOffset, CORBA_long * endOffset,
320                    CORBA_Environment *ev)
321 {
322   AtkText *text = get_text_from_servant (servant);
323   gint intStartOffset, intEndOffset;
324   
325   g_return_if_fail (text != NULL);
326
327   /* atk_text_get_selection returns gchar* which we discard */
328   g_free (atk_text_get_selection (text, selectionNum,
329                                   &intStartOffset, &intEndOffset));
330   
331   *startOffset = intStartOffset;
332   *endOffset = intEndOffset;
333 }
334
335
336 static CORBA_boolean
337 impl_addSelection (PortableServer_Servant servant,
338                    const CORBA_long startOffset,
339                    const CORBA_long endOffset,
340                    CORBA_Environment *ev)
341 {
342   AtkText *text = get_text_from_servant (servant);
343
344   g_return_val_if_fail (text != NULL, FALSE);
345
346   return atk_text_add_selection (text,
347                             startOffset, endOffset);
348 }
349
350
351 static CORBA_boolean
352 impl_removeSelection (PortableServer_Servant servant,
353                       const CORBA_long selectionNum,
354                       CORBA_Environment *ev)
355 {
356   AtkText *text = get_text_from_servant (servant);
357
358   g_return_val_if_fail (text != NULL, FALSE);
359
360   return atk_text_remove_selection (text, selectionNum);
361 }
362
363
364 static CORBA_boolean
365 impl_setSelection (PortableServer_Servant servant,
366                    const CORBA_long selectionNum,
367                    const CORBA_long startOffset,
368                    const CORBA_long endOffset,
369                    CORBA_Environment *ev)
370 {
371   AtkText *text = get_text_from_servant (servant);
372
373   g_return_val_if_fail (text != NULL, FALSE);
374
375   return atk_text_set_selection (text,
376                             selectionNum, startOffset, endOffset);
377 }
378
379
380 static CORBA_boolean
381 impl_setCaretOffset (PortableServer_Servant servant,
382                      const CORBA_long value,
383                      CORBA_Environment *ev)
384 {
385   AtkText *text = get_text_from_servant (servant);
386
387   g_return_val_if_fail (text != NULL, FALSE);
388
389   return atk_text_set_caret_offset (text, value);
390 }
391
392 static void
393 spi_text_class_init (SpiTextClass *klass)
394 {
395   POA_Accessibility_Text__epv *epv = &klass->epv;
396
397   /* Initialize epv table */
398
399   epv->getText = impl_getText;
400   epv->getTextAfterOffset = impl_getTextAfterOffset;
401   epv->getCharacterAtOffset = impl_getCharacterAtOffset;
402   epv->getTextAtOffset = impl_getTextAtOffset;
403   epv->getTextBeforeOffset = impl_getTextBeforeOffset;
404   epv->_get_caretOffset = impl__get_caretOffset;
405   epv->getAttributes = impl_getAttributes;
406   epv->getCharacterExtents = impl_getCharacterExtents;
407   epv->_get_characterCount = impl__get_characterCount;
408   epv->getOffsetAtPoint = impl_getOffsetAtPoint;
409   epv->getNSelections = impl_getNSelections;
410   epv->getSelection = impl_getSelection;
411   epv->addSelection = impl_addSelection;
412   epv->removeSelection = impl_removeSelection;
413   epv->setSelection = impl_setSelection;
414   epv->setCaretOffset = impl_setCaretOffset;
415 }
416
417 static void
418 spi_text_init (SpiText *text)
419 {
420 }
421
422 BONOBO_TYPE_FUNC_FULL (SpiText,
423                        Accessibility_Text,
424                        PARENT_TYPE,
425                        spi_text);
426
427 void
428 spi_text_construct (SpiText *text, AtkObject *obj)
429 {
430   spi_base_construct (SPI_BASE (text), G_OBJECT(obj));
431 }
432
433
434 SpiText *
435 spi_text_interface_new (AtkObject *obj)
436 {
437   SpiText *retval;
438
439   g_return_val_if_fail (ATK_IS_TEXT (obj), NULL);
440
441   retval = g_object_new (SPI_TEXT_TYPE, NULL);
442
443   spi_text_construct (retval, obj);
444
445   return retval;
446 }