evolution-3.6.4/libgnomecanvas/gailcanvastext.c

No issues found

  1 /* GAIL - The GNOME Accessibility Implementation Library
  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 Lesser 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  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser 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 #ifdef HAVE_CONFIG_H
 21 #include <config.h>
 22 #endif
 23 
 24 #include <gtk/gtk.h>
 25 #include <libgnomecanvas/libgnomecanvas.h>
 26 #include "gailcanvasitem.h"
 27 #include "gailcanvastext.h"
 28 #include <libgail-util/gail-util.h>
 29 
 30 struct _GailCanvasText
 31 {
 32   GailCanvasItem parent;
 33   GailTextUtil *textutil;
 34 };
 35 
 36 static void           gail_canvas_text_text_interface_init (AtkTextIface        *iface);
 37 static gchar *         gail_canvas_text_get_text            (AtkText             *text,
 38                                                             gint                start_offset,
 39                                                             gint                end_offset);
 40 static gchar *         gail_canvas_text_get_text_after_offset
 41                                                            (AtkText             *text,
 42                                                             gint                offset,
 43                                                             AtkTextBoundary     boundary_type,
 44                                                             gint                *start_offset,
 45                                                             gint                *end_offset);
 46 static gchar *         gail_canvas_text_get_text_at_offset  (AtkText             *text,
 47                                                             gint                offset,
 48                                                             AtkTextBoundary     boundary_type,
 49                                                             gint                *start_offset,
 50                                                             gint                *end_offset);
 51 static gchar *         gail_canvas_text_get_text_before_offset
 52                                                            (AtkText             *text,
 53                                                             gint                offset,
 54                                                             AtkTextBoundary     boundary_type,
 55                                                             gint                *start_offset,
 56                                                             gint                *end_offset);
 57 static gunichar       gail_canvas_text_get_character_at_offset
 58                                                             (AtkText            *text,
 59                                                              gint               offset);
 60 static gint           gail_canvas_text_get_character_count  (AtkText            *text);
 61 static gint           gail_canvas_text_get_caret_offset     (AtkText            *text);
 62 static gboolean       gail_canvas_text_set_caret_offset     (AtkText            *text,
 63                                                              gint               offset);
 64 static gint           gail_canvas_text_get_offset_at_point  (AtkText            *text,
 65                                                              gint               x,
 66                                                              gint               y,
 67                                                              AtkCoordType       coords);
 68 static void           gail_canvas_text_get_character_extents (AtkText           *text,
 69                                                               gint              offset,
 70                                                               gint              *x,
 71                                                               gint              *y,
 72                                                               gint              *width,
 73                                                               gint              *height,
 74                                                               AtkCoordType      coords);
 75 static AtkAttributeSet *
 76                       gail_canvas_text_get_run_attributes    (AtkText           *text,
 77                                                               gint              offset,
 78                                                               gint              *start_offset,
 79                                                               gint              *end_offset);
 80 static AtkAttributeSet *
 81                       gail_canvas_text_get_default_attributes (AtkText          *text);
 82 static gint           gail_canvas_text_get_n_selections      (AtkText           *text);
 83 static gchar *         gail_canvas_text_get_selection         (AtkText           *text,
 84                                                               gint              selection_num,
 85                                                               gint              *start_pos,
 86                                                               gint              *end_pos);
 87 static gboolean       gail_canvas_text_add_selection         (AtkText           *text,
 88                                                               gint              start_pos,
 89                                                               gint              end_pos);
 90 static gboolean       gail_canvas_text_remove_selection      (AtkText           *text,
 91                                                               gint              selection_num);
 92 static gboolean       gail_canvas_text_set_selection         (AtkText           *text,
 93                                                               gint              selection_num,
 94                                                               gint              start_pos,
 95                                                               gint              end_pos);
 96 static gchar *         get_text_near_offset                   (AtkText           *text,
 97                                                               GailOffsetType    function,
 98                                                               AtkTextBoundary   boundary_type,
 99                                                               gint              offset,
100                                                               gint              *start_offset,
101                                                               gint              *end_offset);
102 
103 G_DEFINE_TYPE_WITH_CODE (GailCanvasText,
104 			gail_canvas_text,
105 			GAIL_TYPE_CANVAS_ITEM,
106 			G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT,
107 					       gail_canvas_text_text_interface_init);)
108 
109 static void
110 gail_canvas_text_init (GailCanvasText *foo)
111 {
112   ;
113 }
114 
115 AtkObject *
116 gail_canvas_text_new (GObject *obj)
117 {
118   gpointer object;
119   AtkObject *atk_object;
120   GailCanvasText *gail_text;
121 
122   g_return_val_if_fail (GNOME_IS_CANVAS_ITEM (obj), NULL);
123   object = g_object_new (GAIL_TYPE_CANVAS_TEXT, NULL);
124   atk_object = ATK_OBJECT (object);
125   gail_text = GAIL_CANVAS_TEXT (object);
126 
127   atk_object_initialize (atk_object, obj);
128   gail_text->textutil = gail_text_util_new ();
129 
130   if (GNOME_IS_CANVAS_TEXT (obj))
131     {
132       gail_text_util_text_setup (gail_text->textutil,
133 				   GNOME_CANVAS_TEXT (obj)->text);
134     }
135 
136   atk_object->role =  ATK_ROLE_TEXT;
137   return atk_object;
138 }
139 
140 static void
141 gail_canvas_text_class_init (GailCanvasTextClass *klass)
142 {
143 }
144 
145 static void
146 gail_canvas_text_text_interface_init (AtkTextIface *iface)
147 {
148   g_return_if_fail (iface != NULL);
149 
150   iface->get_text = gail_canvas_text_get_text;
151   iface->get_text_after_offset = gail_canvas_text_get_text_after_offset;
152   iface->get_text_at_offset = gail_canvas_text_get_text_at_offset;
153   iface->get_text_before_offset = gail_canvas_text_get_text_before_offset;
154   iface->get_character_at_offset = gail_canvas_text_get_character_at_offset;
155   iface->get_character_count = gail_canvas_text_get_character_count;
156   iface->get_caret_offset = gail_canvas_text_get_caret_offset;
157   iface->set_caret_offset = gail_canvas_text_set_caret_offset;
158   iface->get_offset_at_point = gail_canvas_text_get_offset_at_point;
159   iface->get_character_extents = gail_canvas_text_get_character_extents;
160   iface->get_n_selections = gail_canvas_text_get_n_selections;
161   iface->get_selection = gail_canvas_text_get_selection;
162   iface->add_selection = gail_canvas_text_add_selection;
163   iface->remove_selection = gail_canvas_text_remove_selection;
164   iface->set_selection = gail_canvas_text_set_selection;
165   iface->get_run_attributes = gail_canvas_text_get_run_attributes;
166   iface->get_default_attributes = gail_canvas_text_get_default_attributes;
167 }
168 
169 static gchar *
170 gail_canvas_text_get_text (AtkText *text,
171                            gint start_offset,
172                            gint end_offset)
173 {
174   GailCanvasText *gail_text;
175   GtkTextBuffer *buffer;
176   GtkTextIter start, end;
177 
178   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), NULL);
179   gail_text = GAIL_CANVAS_TEXT (text);
180   g_return_val_if_fail (gail_text->textutil, NULL);
181 
182   buffer = gail_text->textutil->buffer;
183   gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
184   gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
185 
186   return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
187 }
188 
189 static gchar *
190 gail_canvas_text_get_text_after_offset (AtkText *text,
191                                         gint offset,
192                                         AtkTextBoundary boundary_type,
193                                         gint *start_offset,
194                                         gint *end_offset)
195 {
196   return get_text_near_offset (text, GAIL_AFTER_OFFSET,
197 			       boundary_type, offset,
198 			       start_offset, end_offset);
199 }
200 
201 static gchar *
202 gail_canvas_text_get_text_at_offset (AtkText *text,
203                                      gint offset,
204                                      AtkTextBoundary boundary_type,
205                                      gint *start_offset,
206                                      gint *end_offset)
207 {
208   return get_text_near_offset (text, GAIL_AT_OFFSET,
209 			       boundary_type, offset,
210 			       start_offset, end_offset);
211 }
212 
213 static gchar *
214 gail_canvas_text_get_text_before_offset (AtkText *text,
215                                          gint offset,
216                                          AtkTextBoundary boundary_type,
217                                          gint *start_offset,
218                                          gint *end_offset)
219 {
220   return get_text_near_offset (text, GAIL_BEFORE_OFFSET,
221 			       boundary_type, offset,
222 			       start_offset, end_offset);
223 }
224 
225 static gunichar
226 gail_canvas_text_get_character_at_offset (AtkText *text,
227                                           gint offset)
228 {
229   GailCanvasText *gail_item;
230   GtkTextIter start, end;
231   GtkTextBuffer *buffer;
232   gchar *string;
233   gchar *index;
234   gunichar unichar;
235 
236   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), '\0');
237   gail_item = GAIL_CANVAS_TEXT (text);
238   buffer = gail_item->textutil->buffer;
239   if (offset >= gtk_text_buffer_get_char_count (buffer))
240     return '\0';
241 
242   gtk_text_buffer_get_start_iter (buffer, &start);
243   gtk_text_buffer_get_end_iter (buffer, &end);
244   string = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
245   index = g_utf8_offset_to_pointer (string, offset);
246 
247   unichar = g_utf8_get_char (index);
248   g_free (string);
249   return unichar;
250 }
251 
252 static gint
253 gail_canvas_text_get_character_count (AtkText *text)
254 {
255   GtkTextBuffer *buffer;
256   GailCanvasText *gail_text;
257 
258   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), 0);
259   gail_text = GAIL_CANVAS_TEXT (text);
260   g_return_val_if_fail (gail_text->textutil, 0);
261   buffer = gail_text->textutil->buffer;
262   return gtk_text_buffer_get_char_count (buffer);
263 }
264 
265 static gint
266 gail_canvas_text_get_caret_offset (AtkText *text)
267 {
268   GailCanvasText *gail_text;
269   GtkTextBuffer *buffer;
270   GtkTextMark *cursor_mark;
271   GtkTextIter cursor_itr;
272 
273   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), 0);
274   gail_text = GAIL_CANVAS_TEXT (text);
275   g_return_val_if_fail (gail_text->textutil, 0);
276   buffer = gail_text->textutil->buffer;
277   cursor_mark = gtk_text_buffer_get_insert (buffer);
278   gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
279   return gtk_text_iter_get_offset (&cursor_itr);
280 }
281 
282 static gboolean
283 gail_canvas_text_set_caret_offset (AtkText *text,
284                                    gint offset)
285 {
286   GailCanvasText *gail_text;
287   GtkTextBuffer *buffer;
288   GtkTextIter pos_itr;
289 
290   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), FALSE);
291   gail_text = GAIL_CANVAS_TEXT (text);
292   g_return_val_if_fail (gail_text->textutil, FALSE);
293   buffer = gail_text->textutil->buffer;
294   gtk_text_buffer_get_iter_at_offset (buffer,  &pos_itr, offset);
295   gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
296   return TRUE;
297 }
298 
299 static gint
300 gail_canvas_text_get_offset_at_point (AtkText *text,
301                                       gint x,
302                                       gint y,
303                                       AtkCoordType coords)
304 {
305   return -1;
306 }
307 
308 static void
309 gail_canvas_text_get_character_extents (AtkText *text,
310                                         gint offset,
311                                         gint *x,
312                                         gint *y,
313                                         gint *width,
314                                         gint *height,
315                                         AtkCoordType coords)
316 {
317   return;
318 }
319 
320 static AtkAttributeSet *
321 gail_canvas_text_get_run_attributes (AtkText *text,
322                                      gint offset,
323                                      gint *start_offset,
324                                      gint *end_offset)
325 {
326   GailCanvasText *gail_text;
327 
328   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), NULL);
329   gail_text = GAIL_CANVAS_TEXT (text);
330   g_return_val_if_fail (gail_text->textutil, NULL);
331 
332   return gail_misc_buffer_get_run_attributes (gail_text->textutil->buffer,
333 					      offset, start_offset, end_offset);
334 }
335 
336 static AtkAttributeSet *
337 gail_canvas_text_get_default_attributes (AtkText *text)
338 {
339   return NULL;
340 }
341 
342 static gint
343 gail_canvas_text_get_n_selections (AtkText *text)
344 {
345   GailCanvasText *gail_text;
346   GtkTextBuffer *buffer;
347   GtkTextIter start, end;
348   gint select_start, select_end;
349 
350   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), -1);
351   gail_text = GAIL_CANVAS_TEXT (text);
352   g_return_val_if_fail (gail_text->textutil, -1);
353   buffer = gail_text->textutil->buffer;
354 
355   gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
356   select_start = gtk_text_iter_get_offset (&start);
357   select_end = gtk_text_iter_get_offset (&end);
358 
359   if (select_start != select_end)
360      return 1;
361   else
362      return 0;
363 }
364 
365 static gchar *
366 gail_canvas_text_get_selection (AtkText *text,
367                                 gint selection_num,
368                                 gint *start_pos,
369                                 gint *end_pos)
370 {
371   GailCanvasText *gail_text;
372   GtkTextBuffer *buffer;
373   GtkTextIter start, end;
374 
375  /* Only let the user get the selection if one is set, and if the
376   * selection_num is 0.
377   */
378   if (selection_num != 0)
379      return NULL;
380 
381   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), NULL);
382   gail_text = GAIL_CANVAS_TEXT (text);
383   g_return_val_if_fail (gail_text->textutil, NULL);
384   buffer = gail_text->textutil->buffer;
385 
386   gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
387   *start_pos = gtk_text_iter_get_offset (&start);
388   *end_pos = gtk_text_iter_get_offset (&end);
389 
390   if (*start_pos != *end_pos)
391     return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
392   else
393     return NULL;
394 }
395 
396 static gboolean
397 gail_canvas_text_add_selection (AtkText *text,
398                                 gint start_pos,
399                                 gint end_pos)
400 {
401   GailCanvasText *gail_text;
402   GtkTextBuffer *buffer;
403   GtkTextIter pos_itr;
404   GtkTextIter start, end;
405   gint select_start, select_end;
406 
407   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), FALSE);
408   gail_text = GAIL_CANVAS_TEXT (text);
409   g_return_val_if_fail (gail_text->textutil, FALSE);
410   buffer = gail_text->textutil->buffer;
411 
412   gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
413   select_start = gtk_text_iter_get_offset (&start);
414   select_end = gtk_text_iter_get_offset (&end);
415 
416  /* If there is already a selection, then don't allow another to be added,
417   * since GtkTextView only supports one selected region.
418   */
419   if (select_start == select_end)
420     {
421       gtk_text_buffer_get_iter_at_offset (buffer,  &pos_itr, start_pos);
422       gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
423       gtk_text_buffer_get_iter_at_offset (buffer,  &pos_itr, end_pos);
424       gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
425       return TRUE;
426     }
427   else
428     return FALSE;
429 }
430 
431 static gboolean
432 gail_canvas_text_remove_selection (AtkText *text,
433                                  gint selection_num)
434 {
435   GailCanvasText *gail_text;
436   GtkTextBuffer *buffer;
437   GtkTextMark *cursor_mark;
438   GtkTextIter cursor_itr;
439   GtkTextIter start, end;
440   gint select_start, select_end;
441 
442   if (selection_num != 0)
443      return FALSE;
444 
445   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), FALSE);
446   gail_text = GAIL_CANVAS_TEXT (text);
447   g_return_val_if_fail (gail_text->textutil, FALSE);
448   buffer = gail_text->textutil->buffer;
449 
450   gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
451   select_start = gtk_text_iter_get_offset (&start);
452   select_end = gtk_text_iter_get_offset (&end);
453 
454   if (select_start != select_end)
455     {
456      /* Setting the start & end of the selected region to the caret position
457       * turns off the selection.
458       */
459       cursor_mark = gtk_text_buffer_get_insert (buffer);
460       gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
461       gtk_text_buffer_move_mark_by_name (buffer, "insert", &cursor_itr);
462       gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &cursor_itr);
463       return TRUE;
464     }
465   else
466     return FALSE;
467 }
468 
469 static gboolean
470 gail_canvas_text_set_selection (AtkText *text,
471                               gint selection_num,
472                               gint start_pos,
473                               gint end_pos)
474 {
475   GailCanvasText *gail_text;
476   GtkTextBuffer *buffer;
477   GtkTextIter pos_itr;
478   GtkTextIter start, end;
479   gint select_start, select_end;
480 
481  /* Only let the user move the selection if one is set, and if the
482   * selection_num is 0
483   */
484   if (selection_num != 0)
485      return FALSE;
486 
487   g_return_val_if_fail (GAIL_IS_CANVAS_TEXT (text), FALSE);
488   gail_text = GAIL_CANVAS_TEXT (text);
489   g_return_val_if_fail (gail_text->textutil, FALSE);
490   buffer = gail_text->textutil->buffer;
491 
492   gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
493   select_start = gtk_text_iter_get_offset (&start);
494   select_end = gtk_text_iter_get_offset (&end);
495 
496   if (select_start != select_end)
497     {
498       gtk_text_buffer_get_iter_at_offset (buffer,  &pos_itr, start_pos);
499       gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
500       gtk_text_buffer_get_iter_at_offset (buffer,  &pos_itr, end_pos);
501       gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
502       return TRUE;
503     }
504   else
505     return FALSE;
506 }
507 
508 static gchar *
509 get_text_near_offset (AtkText *text,
510                       GailOffsetType function,
511                       AtkTextBoundary boundary_type,
512                       gint offset,
513                       gint *start_offset,
514                       gint *end_offset)
515 {
516   return gail_text_util_get_text (GAIL_CANVAS_TEXT (text)->textutil, NULL,
517 				  function, boundary_type, offset,
518 				  start_offset, end_offset);
519 }