Added byline
[anjuta.git] / plugins / sourceview / sourceview.c
blob8323084754a336692709919667eb8b2849a8c9a6
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /****************************************************************************
3 * sourceview.c
5 * Do Dez 29 00:50:15 2005
6 * Copyright 2005 Johannes Schmid
7 * jhs@gnome.org
8 ****************************************************************************/
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <libanjuta/anjuta-debug.h>
27 #include <libanjuta/anjuta-preferences.h>
28 #include <libanjuta/anjuta-encodings.h>
29 #include <libanjuta/anjuta-shell.h>
30 #include <libanjuta/anjuta-language-provider.h>
31 #include <libanjuta/interfaces/ianjuta-file.h>
32 #include <libanjuta/interfaces/ianjuta-file-savable.h>
33 #include <libanjuta/interfaces/ianjuta-markable.h>
34 #include <libanjuta/interfaces/ianjuta-indicable.h>
35 #include <libanjuta/interfaces/ianjuta-print.h>
36 #include <libanjuta/interfaces/ianjuta-document.h>
37 #include <libanjuta/interfaces/ianjuta-document-manager.h>
38 #include <libanjuta/interfaces/ianjuta-editor.h>
39 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
40 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
41 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
42 #include <libanjuta/interfaces/ianjuta-editor-convert.h>
43 #include <libanjuta/interfaces/ianjuta-editor-language.h>
44 #include <libanjuta/interfaces/ianjuta-editor-search.h>
45 #include <libanjuta/interfaces/ianjuta-editor-hover.h>
46 #include <libanjuta/interfaces/ianjuta-editor-glade-signal.h>
47 #include <libanjuta/interfaces/ianjuta-language-provider.h>
48 #include <libanjuta/interfaces/ianjuta-provider.h>
49 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
51 #include <gtksourceview/gtksource.h>
53 #include "config.h"
54 #include "anjuta-view.h"
56 #include "sourceview.h"
57 #include "sourceview-io.h"
58 #include "sourceview-private.h"
59 #include "sourceview-prefs.h"
60 #include "sourceview-print.h"
61 #include "sourceview-cell.h"
62 #include "sourceview-provider.h"
63 #include "plugin.h"
65 #define FORWARD 0
66 #define BACKWARD 1
68 #define MONITOR_KEY "sourceview.enable.vfs"
70 #define LOCATION_TO_LINE(o) ((o) - 1)
71 #define LINE_TO_LOCATION(o) ((o) + 1)
73 #define MARK_NAME "anjuta-mark-"
74 #define CREATE_MARK_NAME(o) (g_strdup_printf (MARK_NAME "%d", (o)))
76 static void sourceview_class_init(SourceviewClass *klass);
77 static void sourceview_instance_init(Sourceview *sv);
78 static void sourceview_dispose(GObject *object);
80 static GObjectClass *parent_class = NULL;
82 enum
84 PROP_O,
85 PROP_PLUGIN,
86 PROP_LAST
88 static GParamSpec* properties[PROP_LAST];
91 static gboolean on_sourceview_hover_over (GtkWidget *widget, gint x, gint y,
92 gboolean keyboard_tip, GtkTooltip *tooltip,
93 gpointer data);
95 /* Utils */
96 /* Sync with IANJUTA_MARKABLE_MARKER */
98 #define MARKER_PIXMAP_LINEMARKER "anjuta-linemark-16.png"
99 #define MARKER_PIXMAP_PROGRAM_COUNTER "anjuta-pcmark-16.png"
100 #define MARKER_PIXMAP_MESSAGE "anjuta-message-16.png"
101 #define MARKER_PIXMAP_BREAKPOINT_DISABLED "anjuta-breakpoint-disabled-16.png"
102 #define MARKER_PIXMAP_BREAKPOINT_ENABLED "anjuta-breakpoint-enabled-16.png"
103 #define MARKER_PIXMAP_BOOKMARK "anjuta-bookmark-16.png"
105 #define MARKER_TOOLTIP_DATA "__tooltip"
107 /* Keep in sync with IAnjutaMarkableMarker */
109 static const gchar* marker_types [] =
111 "sv-linemarker",
112 "sv-bookmark",
113 "sv-message",
114 "sv-breakpoint-enabled",
115 "sv-breakpoint-disabled",
116 "sv-program-counter",
117 NULL
120 typedef struct
122 gint handle;
123 gint line;
124 const gchar* category;
125 gchar* tooltip;
126 } MarkerReload;
128 static MarkerReload*
129 marker_reload_new (void)
131 return g_slice_new0 (MarkerReload);
134 static void
135 marker_reload_free (MarkerReload* mark)
137 g_free (mark->tooltip);
138 g_slice_free (MarkerReload, mark);
141 /* HIGHLIGHTED TAGS */
143 #define IMPORTANT_INDIC "important_indic"
144 #define WARNING_INDIC "warning_indic"
145 #define CRITICAL_INDIC "critical_indic"
147 static GtkWidget *
148 anjuta_message_area_new (const gchar *text,
149 GtkMessageType type)
151 GtkInfoBar *message_area;
152 GtkWidget *content_area;
153 GtkWidget *message_label = gtk_label_new ("");
155 gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE);
156 gtk_label_set_line_wrap_mode (GTK_LABEL (message_label), PANGO_WRAP_WORD);
158 message_area = GTK_INFO_BAR (gtk_info_bar_new ());
159 gtk_info_bar_set_message_type (message_area, type);
160 content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (message_area));
161 gtk_widget_show (message_label);
162 gtk_container_add (GTK_CONTAINER (content_area), message_label);
164 gchar *markup = g_strdup_printf ("<b>%s</b>", text);
165 gtk_label_set_markup (GTK_LABEL (message_label), markup);
166 g_free (markup);
168 return GTK_WIDGET (message_area);
171 static gchar*
172 on_marker_tooltip (GtkSourceMarkAttributes* cat, GtkSourceMark* mark, gpointer data)
174 //Sourceview* sv = ANJUTA_SOURCEVIEW (data);
175 gchar* tooltip;
176 tooltip = g_object_get_data (G_OBJECT (mark), MARKER_TOOLTIP_DATA);
177 if (tooltip)
178 return g_strdup (tooltip);
179 else
180 return NULL;
183 static void
184 sourceview_create_marker_category (Sourceview* sv, const gchar* marker_pixbuf,
185 IAnjutaMarkableMarker marker_type)
187 GdkPixbuf * pixbuf;
188 GtkSourceView* view = GTK_SOURCE_VIEW(sv->priv->view);
189 if ((pixbuf = gdk_pixbuf_new_from_file (marker_pixbuf, NULL)))
191 GtkSourceMarkAttributes* cat = gtk_source_mark_attributes_new ();
192 gtk_source_mark_attributes_set_pixbuf (cat, pixbuf);
193 g_signal_connect (cat, "query-tooltip-text", G_CALLBACK (on_marker_tooltip), sv);
194 gtk_source_view_set_mark_attributes (view, marker_types [marker_type], cat, marker_type);
195 g_object_unref (pixbuf);
199 /* Create pixmaps for the markers */
200 static void sourceview_create_markers(Sourceview* sv)
202 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BOOKMARK,
203 IANJUTA_MARKABLE_BOOKMARK);
204 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BREAKPOINT_DISABLED,
205 IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
206 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BREAKPOINT_ENABLED,
207 IANJUTA_MARKABLE_BREAKPOINT_ENABLED);
208 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_PROGRAM_COUNTER,
209 IANJUTA_MARKABLE_PROGRAM_COUNTER);
210 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_LINEMARKER,
211 IANJUTA_MARKABLE_LINEMARKER);
212 sourceview_create_marker_category (sv, PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_MESSAGE,
213 IANJUTA_MARKABLE_MESSAGE);
216 #define PREF_COLOR_ERROR "color-error"
217 #define PREF_COLOR_WARNING "color-warning"
218 #define PREF_COLOR_IMPORTANT "color-important"
221 /* Create tags for highlighting */
222 static void sourceview_create_highlight_indic(Sourceview* sv)
224 char* error_color =
225 g_settings_get_string (sv->priv->msgman_settings,
226 PREF_COLOR_ERROR);
227 char* warning_color =
228 g_settings_get_string (sv->priv->msgman_settings,
229 PREF_COLOR_WARNING);
230 char* important_color =
231 g_settings_get_string (sv->priv->msgman_settings,
232 PREF_COLOR_IMPORTANT);
233 sv->priv->important_indic =
234 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
235 IMPORTANT_INDIC,
236 "background", important_color, NULL);
237 sv->priv->warning_indic =
238 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
239 WARNING_INDIC,
240 "foreground", warning_color,
241 "underline", PANGO_UNDERLINE_SINGLE,
242 NULL);
243 sv->priv->critical_indic =
244 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
245 CRITICAL_INDIC,
246 "foreground", error_color, "underline",
247 PANGO_UNDERLINE_ERROR, NULL);
248 g_free (error_color);
249 g_free (warning_color);
250 g_free (important_color);
253 static void
254 goto_line (Sourceview* sv, gint line)
256 GtkTextIter iter;
257 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
259 gtk_text_buffer_get_iter_at_line (buffer,
260 &iter,
261 line);
262 gtk_text_buffer_select_range (buffer, &iter, &iter);
265 static void
266 on_destroy_message_area (Sourceview* sv, GObject *finalized_object)
268 if ((void*)finalized_object == (void*)sv->priv->message_area)
269 sv->priv->message_area = NULL;
271 g_signal_emit_by_name (G_OBJECT (sv), "update-save-ui");
274 static void
275 message_area_destroy (GtkWidget* message_area)
277 #if GTK_CHECK_VERSION(3, 9, 0)
278 GtkWidget* revealer;
280 revealer = gtk_widget_get_parent (message_area);
281 g_signal_connect (revealer, "notify::child-revealed",
282 G_CALLBACK(gtk_widget_destroy), NULL);
283 gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE);
284 #else
285 gtk_widget_destroy (message_area);
286 #endif
289 static void
290 sourceview_set_message_area (Sourceview* sv, GtkWidget *message_area)
292 if (sv->priv->message_area != NULL)
293 message_area_destroy (sv->priv->message_area);
295 sv->priv->message_area = message_area;
297 if (sv->priv->message_area == NULL)
298 return;
300 gtk_widget_show (message_area);
302 #if GTK_CHECK_VERSION(3, 9, 0)
303 GtkWidget *revealer;
305 revealer = gtk_revealer_new ();
306 gtk_widget_show (revealer);
307 gtk_container_add (GTK_CONTAINER (revealer), message_area);
308 gtk_box_pack_start (GTK_BOX (sv), revealer, FALSE, FALSE, 0);
310 gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
311 #else
312 gtk_box_pack_start (GTK_BOX (sv), message_area, FALSE, FALSE, 0);
313 #endif
315 g_object_weak_ref (G_OBJECT (message_area),
316 (GWeakNotify)on_destroy_message_area, sv);
318 g_signal_emit_by_name (G_OBJECT (sv), "update-save-ui");
321 /* Callbacks */
322 static void
323 on_assist_tip_destroyed (Sourceview* sv, gpointer where_object_was)
325 sv->priv->assist_tip = NULL;
328 static void
329 on_insert_text (GtkTextBuffer *buffer,
330 GtkTextIter *location,
331 gchar *text,
332 gint len,
333 Sourceview *sv)
335 int i = 0, lines = 0;
336 gchar* signal_text;
337 SourceviewCell *cell = sourceview_cell_new (location, GTK_TEXT_VIEW (sv->priv->view));
338 IAnjutaIterable *iter = ianjuta_iterable_clone (IANJUTA_ITERABLE (cell), NULL);
339 GtkTextMark *mark = gtk_text_buffer_create_mark (buffer, NULL, location, TRUE);
340 g_object_unref (cell);
342 ianjuta_iterable_set_position (iter,
343 ianjuta_iterable_get_position (iter, NULL) - len,
344 NULL);
346 /* Update the status bar */
347 g_signal_emit_by_name (G_OBJECT (sv), "update-ui");
349 if (len <= 1 && strlen (text) <= 1)
351 /* Send the "char-added" signal and revalidate the iterator */
352 g_signal_emit_by_name (G_OBJECT (sv), "char-added", iter, text[0]);
353 gtk_text_buffer_get_iter_at_mark (buffer, location, mark);
356 for (i = 0; i < len; i ++)
357 if (text[i] == '\n')
358 lines ++;
360 /* text might not be NULL-terminated, so make sure to fix that. */
361 signal_text = g_strndup (text, len);
362 /* Send the "changed" signal and revalidate the iterator */
363 g_signal_emit_by_name (G_OBJECT (sv), "changed", iter, TRUE, len, lines, signal_text);
364 g_free (signal_text);
366 gtk_text_buffer_get_iter_at_mark (buffer, location, mark);
369 static void
370 on_delete_range (GtkTextBuffer *buffer,
371 GtkTextIter *start_iter,
372 GtkTextIter *end_iter,
373 gpointer user_data)
375 Sourceview *sv = NULL;
377 /* Assertions */
378 g_return_if_fail (ANJUTA_IS_SOURCEVIEW (user_data));
379 sv = ANJUTA_SOURCEVIEW (user_data);
381 sv->priv->deleted_text = gtk_text_buffer_get_text (buffer, start_iter, end_iter, TRUE);
385 static void
386 on_delete_range_after (GtkTextBuffer *buffer,
387 GtkTextIter *start_iter,
388 GtkTextIter *end_iter,
389 gpointer user_data)
391 Sourceview *sv = NULL;
392 GtkTextMark *start_mark = NULL, *end_mark = NULL;
393 SourceviewCell *cell = NULL;
394 IAnjutaIterable *position = NULL;
395 gint length = 0, i = 0, lines = 0;
397 /* Assertions */
398 g_return_if_fail (ANJUTA_IS_SOURCEVIEW (user_data));
399 sv = ANJUTA_SOURCEVIEW (user_data);
401 /* Get the start iterator of the changed text */
402 cell = sourceview_cell_new (start_iter, GTK_TEXT_VIEW (sv->priv->view));
403 position = IANJUTA_ITERABLE (cell);
405 /* We save the text before the default handler */
406 length = g_utf8_strlen (sv->priv->deleted_text, -1);
407 for (i = 0; i < length; i ++)
408 if (sv->priv->deleted_text[i] == '\n')
409 lines ++;
411 /* Save the iterators */
412 start_mark = gtk_text_buffer_create_mark (buffer, NULL, start_iter, TRUE);
413 end_mark = gtk_text_buffer_create_mark (buffer, NULL, end_iter, TRUE);
415 g_signal_emit_by_name (G_OBJECT (sv), "changed",
416 position, FALSE, length, lines, sv->priv->deleted_text);
418 /* Revalidate the iterators */
419 gtk_text_buffer_get_iter_at_mark (buffer, start_iter, start_mark);
420 gtk_text_buffer_get_iter_at_mark (buffer, end_iter, end_mark);
422 /* Delete the saved text */
423 g_free (sv->priv->deleted_text);
424 sv->priv->deleted_text = NULL;
428 static void
429 on_cursor_position_changed (GObject *buffer_obj,
430 GParamSpec *param_spec,
431 gpointer user_data)
434 /* Assertions */
435 g_return_if_fail (ANJUTA_IS_SOURCEVIEW (user_data));
437 g_signal_emit_by_name (G_OBJECT (user_data), "cursor-moved");
441 /* Called whenever the document is changed */
442 static void on_document_modified_changed(GtkTextBuffer* buffer, Sourceview* sv)
444 /* Emit IAnjutaFileSavable signals */
445 g_signal_emit_by_name(G_OBJECT(sv), "update-save-ui",
446 !gtk_text_buffer_get_modified(buffer));
449 /* Update document status */
450 static void on_overwrite_toggled (GtkTextView* view,
451 Sourceview* sv)
453 g_signal_emit_by_name(G_OBJECT(sv), "update_ui");
457 static void on_mark_set (GtkTextBuffer *buffer,
458 GtkTextIter* location,
459 GtkTextMark* mark,
460 Sourceview* sv)
462 /* Emit IAnjutaEditor signal */
463 if (mark == gtk_text_buffer_get_insert (buffer))
464 g_signal_emit_by_name(G_OBJECT(sv), "update_ui");
467 static void on_backspace (GtkTextView* view,
468 Sourceview* sv)
470 g_signal_emit_by_name(G_OBJECT(sv), "backspace");
471 g_signal_emit_by_name(G_OBJECT(sv), "update_ui");
474 static void
475 on_line_mark_activated(GtkTextView* view,
476 GtkTextIter *iter,
477 GdkEventButton *event,
478 Sourceview* sv)
480 /* proceed only if its a double click with left button*/
481 if( (event->button != 1) || (GDK_2BUTTON_PRESS != event->type) ) {
482 return;
485 /* line number starts with 0, so add 1 */
486 gint line_number = LINE_TO_LOCATION(gtk_text_iter_get_line(iter));
488 if (!IANJUTA_IS_EDITOR(sv))
490 return;
492 g_signal_emit_by_name(G_OBJECT(sv), "line-marks-gutter-clicked", line_number);
496 /* Open / Save stuff */
498 static void
499 sourceview_reload_save_markers (Sourceview* sv)
501 GSList* marks;
502 GtkTextIter begin;
503 GtkTextIter end;
504 GtkTextIter* iter;
505 GtkSourceMark* source_mark;
507 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document), &begin, 0);
508 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document), &end, -1);
510 if (!gtk_source_buffer_forward_iter_to_source_mark (GTK_SOURCE_BUFFER (sv->priv->document),
511 &begin, NULL))
512 return;
514 iter = gtk_text_iter_copy (&begin);
515 marks = gtk_source_buffer_get_source_marks_at_iter (GTK_SOURCE_BUFFER (sv->priv->document),
516 iter, NULL);
517 source_mark = marks->data;
518 g_slist_free (marks);
522 MarkerReload* reload = marker_reload_new ();
524 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (sv->priv->document),
525 iter, GTK_TEXT_MARK (source_mark));
526 reload->line = gtk_text_iter_get_line (iter);
527 reload->category = gtk_source_mark_get_category (source_mark);
529 sscanf (gtk_text_mark_get_name (GTK_TEXT_MARK (source_mark)),
530 MARK_NAME "%d", &reload->handle);
531 reload->tooltip = g_strdup (g_object_get_data (G_OBJECT (source_mark),
532 MARKER_TOOLTIP_DATA));
534 sv->priv->reload_marks = g_slist_append (sv->priv->reload_marks, reload);
536 while ((source_mark = gtk_source_mark_next (source_mark, NULL)));
538 gtk_source_buffer_remove_source_marks (GTK_SOURCE_BUFFER (sv->priv->document), &begin, &end, NULL);
539 gtk_text_iter_free (iter);
542 static void
543 sourceview_add_mark (Sourceview* sv, gint handle, gint line,
544 const gchar* category, const gchar* tooltip)
546 GtkTextIter iter;
547 gchar* name;
548 GtkSourceMark* source_mark;
550 gtk_text_buffer_get_iter_at_line(GTK_TEXT_BUFFER(sv->priv->document),
551 &iter, line);
553 name = CREATE_MARK_NAME (handle);
554 source_mark = gtk_source_buffer_create_source_mark(GTK_SOURCE_BUFFER(sv->priv->document),
555 name, category, &iter);
557 g_object_set_data_full (G_OBJECT (source_mark), MARKER_TOOLTIP_DATA,
558 g_strdup (tooltip), (GDestroyNotify)g_free);
559 g_free (name);
562 static void
563 sourceview_reload_restore_markers (Sourceview* sv)
565 GSList* cur_mark;
566 for (cur_mark = sv->priv->reload_marks; cur_mark != NULL;
567 cur_mark = g_slist_next (cur_mark))
569 MarkerReload* mark = cur_mark->data;
571 sourceview_add_mark (sv, mark->handle, mark->line, mark->category,
572 mark->tooltip);
574 g_slist_free_full (sv->priv->reload_marks, (GDestroyNotify)marker_reload_free);
575 sv->priv->reload_marks = NULL;
578 /* Callback for dialog below */
579 static void
580 on_reload_dialog_response (GtkWidget *message_area, gint res, Sourceview *sv)
582 if (res == GTK_RESPONSE_YES)
584 GFile* file = sourceview_io_get_file (sv->priv->io);
586 ianjuta_file_open(IANJUTA_FILE(sv),
587 file, NULL);
588 g_object_unref (file);
591 else
593 /* Set dirty */
594 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document), TRUE);
596 message_area_destroy (message_area);
599 static void
600 on_close_dialog_response (GtkWidget *message_area, gint res, Sourceview *sv)
602 if (res == GTK_RESPONSE_YES)
604 IAnjutaDocumentManager *docman;
606 docman = anjuta_shell_get_interface (sv->priv->plugin->shell, IAnjutaDocumentManager, NULL);
607 if (docman == NULL) return;
609 ianjuta_document_manager_remove_document (docman, IANJUTA_DOCUMENT (sv), FALSE, NULL);
611 else
613 /* Set dirty */
614 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document), TRUE);
616 message_area_destroy (message_area);
619 static gboolean
620 on_file_changed (SourceviewIO* sio, Sourceview* sv)
622 GtkWidget *message_area;
623 gchar *buff;
625 const gchar* filename = sourceview_io_get_filename (sio);
627 buff =
628 g_strdup_printf (_
629 ("The file \"%s\" on the disk is more recent than "
630 "the current buffer.\nDo you want to reload it?"),
631 filename);
633 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
634 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
635 GTK_STOCK_REFRESH,
636 GTK_RESPONSE_YES);
637 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
638 GTK_STOCK_CANCEL,
639 GTK_RESPONSE_NO);
640 g_free (buff);
642 g_signal_connect (G_OBJECT(message_area), "response",
643 G_CALLBACK (on_reload_dialog_response),
644 sv);
646 sourceview_set_message_area (sv, message_area);
648 return FALSE;
651 static gboolean
652 on_file_deleted (SourceviewIO* sio, Sourceview* sv)
654 GtkWidget *message_area;
655 gchar *buff;
657 const gchar* filename = sourceview_io_get_filename (sio);
659 buff =
660 g_strdup_printf (_
661 ("The file \"%s\" has been deleted on the disk.\n"
662 "Do you want to close it?"),
663 filename);
665 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
666 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
667 GTK_STOCK_DELETE,
668 GTK_RESPONSE_YES);
669 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
670 GTK_STOCK_CANCEL,
671 GTK_RESPONSE_NO);
672 g_free (buff);
674 g_signal_connect (G_OBJECT(message_area), "response",
675 G_CALLBACK (on_close_dialog_response),
676 sv);
678 sourceview_set_message_area (sv, message_area);
680 return FALSE;
683 static void
684 on_open_failed (SourceviewIO* io, GError* err, Sourceview* sv)
686 AnjutaShell* shell = ANJUTA_PLUGIN (sv->priv->plugin)->shell;
687 IAnjutaDocumentManager *docman =
688 anjuta_shell_get_interface (shell, IAnjutaDocumentManager, NULL);
689 g_return_if_fail (docman != NULL);
690 GList* documents = ianjuta_document_manager_get_doc_widgets (docman, NULL);
691 GtkWidget* message_area;
693 /* Could not open <filename>: <error message> */
694 gchar* message = g_strdup_printf (_("Could not open %s: %s"),
695 sourceview_io_get_filename (sv->priv->io),
696 err->message);
698 if (g_list_find (documents, sv))
700 message_area = anjuta_message_area_new (message, GTK_MESSAGE_WARNING);
701 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
702 GTK_STOCK_OK,
703 GTK_RESPONSE_OK);
704 g_signal_connect (message_area, "response", G_CALLBACK(message_area_destroy), NULL);
706 sourceview_set_message_area (sv, message_area);
708 else
710 GtkWidget* dialog = gtk_message_dialog_new (NULL, 0,
711 GTK_MESSAGE_ERROR,
712 GTK_BUTTONS_OK,
713 "%s", message);
714 g_signal_connect (dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
715 gtk_dialog_run (GTK_DIALOG (dialog));
717 g_free (message);
718 sv->priv->loading = FALSE;
719 gtk_text_view_set_editable (GTK_TEXT_VIEW (sv->priv->view), TRUE);
722 static void
723 on_read_only_dialog_response (GtkWidget *message_area, gint res, Sourceview *sv)
725 if (res == GTK_RESPONSE_YES)
727 gtk_text_view_set_editable (GTK_TEXT_VIEW (sv->priv->view),
728 TRUE);
729 sv->priv->read_only = FALSE;
731 message_area_destroy (message_area);
734 /* Called when document is loaded completly */
735 static void
736 on_open_finish(SourceviewIO* io, Sourceview* sv)
738 const gchar *lang;
740 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document), FALSE);
742 if (sourceview_io_get_read_only (io))
744 const gchar* filename = sourceview_io_get_filename (io);
745 gchar* buff = g_strdup_printf (_("The file \"%s\" is read-only! Edit anyway?"),
746 filename);
747 GtkWidget* message_area;
749 message_area = anjuta_message_area_new (buff, GTK_MESSAGE_WARNING);
750 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
751 GTK_STOCK_YES,
752 GTK_RESPONSE_YES);
753 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
754 GTK_STOCK_NO,
755 GTK_RESPONSE_NO);
756 g_free (buff);
758 g_signal_connect (G_OBJECT(message_area), "response",
759 G_CALLBACK (on_read_only_dialog_response),
760 sv);
762 sv->priv->read_only = TRUE;
764 sourceview_set_message_area (sv, message_area);
766 else
767 gtk_text_view_set_editable (GTK_TEXT_VIEW (sv->priv->view), TRUE);
769 g_signal_emit_by_name(G_OBJECT(sv), "update-save-ui");
771 sourceview_reload_restore_markers (sv);
773 if (sv->priv->goto_line > 0)
775 goto_line (sv, sv->priv->goto_line);
776 sv->priv->goto_line = -1;
778 else
779 goto_line (sv, 0);
780 anjuta_view_scroll_to_cursor(sv->priv->view);
781 sv->priv->loading = FALSE;
783 /* Autodetect language */
784 ianjuta_editor_language_set_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL, NULL);
786 lang = ianjuta_editor_language_get_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL);
787 g_signal_emit_by_name (sv, "language-changed", lang);
789 g_signal_emit_by_name (sv, "opened");
792 static void on_save_failed (SourceviewIO* sio, GError* err, Sourceview* sv)
794 AnjutaShell* shell = ANJUTA_PLUGIN (sv->priv->plugin)->shell;
795 IAnjutaDocumentManager *docman =
796 anjuta_shell_get_interface (shell, IAnjutaDocumentManager, NULL);
797 g_return_if_fail (docman != NULL);
798 GList* documents = ianjuta_document_manager_get_doc_widgets (docman, NULL);
799 GtkWidget* message_area;
801 g_signal_emit_by_name(G_OBJECT(sv), "saved", NULL);
803 /* Could not open <filename>: <error message> */
804 gchar* message = g_strdup_printf (_("Could not save %s: %s"),
805 sourceview_io_get_filename (sv->priv->io),
806 err->message);
808 if (g_list_find (documents, sv))
810 message_area = anjuta_message_area_new (message, GTK_MESSAGE_ERROR);
811 gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
812 GTK_STOCK_OK,
813 GTK_RESPONSE_OK);
814 g_signal_connect (message_area, "response", G_CALLBACK(message_area_destroy), NULL);
816 sourceview_set_message_area (sv, message_area);
818 else
820 GtkWidget* dialog = gtk_message_dialog_new (NULL, 0,
821 GTK_MESSAGE_ERROR,
822 GTK_BUTTONS_OK,
823 "%s", message);
824 g_signal_connect (dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
825 gtk_dialog_run (GTK_DIALOG (dialog));
827 g_free (message);
830 /* Called when document is saved completly */
831 static void on_save_finish(SourceviewIO* sio, Sourceview* sv)
833 const gchar* lang;
834 GFile* file = sourceview_io_get_file(sio);
835 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document), FALSE);
836 sv->priv->read_only = FALSE;
837 g_signal_emit_by_name(G_OBJECT(sv), "saved", file);
838 g_signal_emit_by_name(G_OBJECT(sv), "update-save-ui");
839 g_object_unref (file);
840 /* Autodetect language */
841 ianjuta_editor_language_set_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL, NULL);
842 lang = ianjuta_editor_language_get_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL);
843 g_signal_emit_by_name (sv, "language-changed", lang);
846 static void
847 sourceview_adjustment_changed(GtkAdjustment* ad, Sourceview* sv)
849 /* Hide assistance windows when scrolling vertically */
850 if (sv->priv->assist_tip)
851 gtk_widget_destroy (GTK_WIDGET (sv->priv->assist_tip));
854 static void
855 sourceview_set_property (GObject* object, guint property_id,
856 const GValue* value, GParamSpec* pspec)
858 Sourceview* sv = ANJUTA_SOURCEVIEW(object);
860 switch (property_id)
862 case PROP_PLUGIN:
863 sv->priv->plugin = g_value_get_object (value);
864 break;
866 default:
867 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
871 static void
872 sourceview_constructed (GObject* object)
874 Sourceview* sv = ANJUTA_SOURCEVIEW(object);
876 GtkAdjustment* v_adj;
878 DEBUG_PRINT("%s", "============ Creating new editor =============");
880 sv->priv->io = sourceview_io_new (sv);
881 g_signal_connect_object (sv->priv->io, "changed", G_CALLBACK (on_file_changed),
882 sv, 0);
883 g_signal_connect_object (sv->priv->io, "deleted", G_CALLBACK (on_file_deleted),
884 sv, 0);
885 g_signal_connect_object (sv->priv->io, "open-finished", G_CALLBACK (on_open_finish),
886 sv, 0);
887 g_signal_connect_object (sv->priv->io, "open-failed", G_CALLBACK (on_open_failed),
888 sv, 0);
889 g_signal_connect_object (sv->priv->io, "save-finished", G_CALLBACK (on_save_finish),
890 sv, 0);
891 g_signal_connect_object (sv->priv->io, "save-failed", G_CALLBACK (on_save_failed),
892 sv, 0);
894 /* Create buffer */
895 sv->priv->document = gtk_source_buffer_new(NULL);
897 g_signal_connect_after(G_OBJECT(sv->priv->document), "modified-changed",
898 G_CALLBACK(on_document_modified_changed), sv);
899 g_signal_connect_after(G_OBJECT(sv->priv->document), "mark-set",
900 G_CALLBACK(on_mark_set),sv);
901 g_signal_connect_after (G_OBJECT(sv->priv->document), "insert-text",
902 G_CALLBACK(on_insert_text), sv);
903 g_signal_connect (G_OBJECT(sv->priv->document), "delete-range",
904 G_CALLBACK(on_delete_range), sv);
905 g_signal_connect_after (G_OBJECT(sv->priv->document), "delete-range",
906 G_CALLBACK(on_delete_range_after), sv);
908 g_signal_connect (G_OBJECT (sv->priv->document), "notify::cursor-position",
909 G_CALLBACK (on_cursor_position_changed), sv);
911 /* Create View instance */
912 sv->priv->view = ANJUTA_VIEW(anjuta_view_new(sv));
913 /* The view doesn't take a reference on the buffer, we have to unref it */
914 g_object_unref (sv->priv->document);
916 g_signal_connect_after (G_OBJECT(sv->priv->view), "toggle-overwrite",
917 G_CALLBACK(on_overwrite_toggled), sv);
918 g_signal_connect (G_OBJECT(sv->priv->view), "query-tooltip",
919 G_CALLBACK (on_sourceview_hover_over), sv);
920 g_signal_connect_after(G_OBJECT(sv->priv->view), "backspace",
921 G_CALLBACK(on_backspace),sv);
923 g_object_set (G_OBJECT (sv->priv->view), "has-tooltip", TRUE, NULL);
925 /* Apply Preferences */
926 sourceview_prefs_init(sv);
928 /* Create Markers */
929 sourceview_create_markers(sv);
931 /* Create Higlight Tag */
932 sourceview_create_highlight_indic(sv);
934 /* Add View */
935 sv->priv->window = gtk_scrolled_window_new (NULL, NULL);
936 gtk_box_pack_end (GTK_BOX (sv), sv->priv->window, TRUE, TRUE, 0);
938 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sv->priv->window),
939 GTK_POLICY_AUTOMATIC,
940 GTK_POLICY_AUTOMATIC);
941 gtk_container_add(GTK_CONTAINER(sv->priv->window), GTK_WIDGET(sv->priv->view));
942 gtk_widget_show_all(GTK_WIDGET(sv));
943 v_adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sv->priv->window));
944 g_signal_connect (v_adj, "value-changed", G_CALLBACK (sourceview_adjustment_changed), sv);
946 g_signal_connect_after(G_OBJECT(sv->priv->view), "line-mark-activated",
947 G_CALLBACK(on_line_mark_activated), sv);
950 static void
951 sourceview_instance_init(Sourceview* sv)
954 sv->priv = G_TYPE_INSTANCE_GET_PRIVATE (sv,
955 ANJUTA_TYPE_SOURCEVIEW,
956 SourceviewPrivate);
958 /* set properties */
959 g_object_set (G_OBJECT (sv), "orientation", GTK_ORIENTATION_VERTICAL,
960 NULL);
963 static void
964 sourceview_class_init(SourceviewClass *klass)
966 GObjectClass *object_class = G_OBJECT_CLASS(klass);
968 parent_class = g_type_class_peek_parent(klass);
970 object_class->constructed = sourceview_constructed;
971 object_class->set_property = sourceview_set_property;
972 object_class->dispose = sourceview_dispose;
974 g_type_class_add_private (klass, sizeof (SourceviewPrivate));
976 properties[PROP_PLUGIN] =
977 g_param_spec_object ("plugin", "Plugin", "Plugin",
978 ANJUTA_TYPE_PLUGIN_SOURCEVIEW,
979 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
980 g_object_class_install_properties (object_class, PROP_LAST, properties);
983 static void
984 sourceview_dispose(GObject *object)
986 Sourceview *cobj = ANJUTA_SOURCEVIEW(object);
988 if (cobj->priv->reload_marks)
990 g_slist_free_full (cobj->priv->reload_marks, (GDestroyNotify)marker_reload_free);
991 g_slist_free (cobj->priv->reload_marks);
993 if (cobj->priv->assist_tip)
995 gtk_widget_destroy(GTK_WIDGET(cobj->priv->assist_tip));
996 cobj->priv->assist_tip = NULL;
999 g_clear_object (&cobj->priv->io);
1000 g_clear_object (&cobj->priv->tooltip_cell);
1002 sourceview_prefs_destroy(cobj);
1004 G_OBJECT_CLASS (parent_class)->dispose (object);
1007 /* Create a new sourceview instance. If uri is valid,
1008 the file will be loaded in the buffer */
1010 Sourceview *
1011 sourceview_new(GFile* file, const gchar* filename, AnjutaPlugin* plugin)
1013 Sourceview *sv = ANJUTA_SOURCEVIEW(g_object_new(ANJUTA_TYPE_SOURCEVIEW,
1014 "plugin", plugin, NULL));
1016 if (file != NULL)
1018 ianjuta_file_open(IANJUTA_FILE(sv), file, NULL);
1020 else if (filename != NULL && strlen(filename) > 0)
1021 sourceview_io_set_filename (sv->priv->io, filename);
1023 g_signal_emit_by_name (G_OBJECT(sv), "update-ui");
1025 return sv;
1028 /* IAnjutaFile interface */
1030 /* Open uri in Editor */
1031 static void
1032 ifile_open (IAnjutaFile* ifile, GFile* file, GError** e)
1034 Sourceview* sv = ANJUTA_SOURCEVIEW(ifile);
1036 GFile *previous_file;
1038 previous_file = sourceview_io_get_file (sv->priv->io);
1039 if (previous_file && g_file_equal (file, previous_file))
1041 /* This is a reload so save marks and position */
1042 sv->priv->goto_line =
1043 LOCATION_TO_LINE(ianjuta_editor_get_lineno (IANJUTA_EDITOR(sv), NULL));
1044 sourceview_reload_save_markers (sv);
1047 gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (sv->priv->document));
1048 gtk_text_buffer_set_text (GTK_TEXT_BUFFER(sv->priv->document),
1051 gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (sv->priv->document));
1053 gtk_text_view_set_editable (GTK_TEXT_VIEW (sv->priv->view),
1054 FALSE);
1055 sv->priv->loading = TRUE;
1056 sourceview_io_open (sv->priv->io, file);
1059 /* Return the currently loaded uri */
1061 static GFile*
1062 ifile_get_file (IAnjutaFile* ifile, GError** e)
1064 Sourceview* sv = ANJUTA_SOURCEVIEW(ifile);
1065 return sourceview_io_get_file (sv->priv->io);
1068 /* IAnjutaFileSavable interface */
1070 /* Save file */
1071 static void
1072 ifile_savable_save (IAnjutaFileSavable* file, GError** e)
1074 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
1076 sourceview_io_save (sv->priv->io);
1079 /* Save file as */
1080 static void
1081 ifile_savable_save_as (IAnjutaFileSavable* ifile, GFile* file, GError** e)
1083 Sourceview* sv = ANJUTA_SOURCEVIEW(ifile);
1085 sourceview_io_save_as (sv->priv->io, file);
1088 static void
1089 ifile_savable_set_dirty (IAnjutaFileSavable* file, gboolean dirty, GError** e)
1091 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
1092 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document),
1093 dirty);
1096 static gboolean
1097 ifile_savable_is_dirty (IAnjutaFileSavable* file, GError** e)
1099 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
1100 return gtk_text_buffer_get_modified(GTK_TEXT_BUFFER(sv->priv->document));
1103 static gboolean
1104 ifile_savable_is_read_only (IAnjutaFileSavable* file, GError** e)
1106 Sourceview* sv = ANJUTA_SOURCEVIEW (file);
1107 return sv->priv->read_only;
1110 static gboolean
1111 ifile_savable_is_conflict (IAnjutaFileSavable* file, GError** e)
1113 Sourceview* sv = ANJUTA_SOURCEVIEW (file);
1114 return sv->priv->message_area != NULL;
1117 static void
1118 isavable_iface_init (IAnjutaFileSavableIface *iface)
1120 iface->save = ifile_savable_save;
1121 iface->save_as = ifile_savable_save_as;
1122 iface->set_dirty = ifile_savable_set_dirty;
1123 iface->is_dirty = ifile_savable_is_dirty;
1124 iface->is_read_only = ifile_savable_is_read_only;
1125 iface->is_conflict = ifile_savable_is_conflict;
1128 static void
1129 ifile_iface_init (IAnjutaFileIface *iface)
1131 iface->open = ifile_open;
1132 iface->get_file = ifile_get_file;
1135 /* IAnjutaEditor interface */
1137 static gint
1138 ieditor_get_tab_size (IAnjutaEditor *editor, GError **e)
1140 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1141 return gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (sv->priv->view));
1144 static void
1145 ieditor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
1147 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1148 gtk_source_view_set_tab_width(GTK_SOURCE_VIEW(sv->priv->view), tabsize);
1151 static gboolean
1152 ieditor_get_use_spaces (IAnjutaEditor *editor, GError **e)
1154 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1155 return gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW(sv->priv->view));
1158 static void
1159 ieditor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
1161 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1162 gtk_source_view_set_insert_spaces_instead_of_tabs(GTK_SOURCE_VIEW(sv->priv->view),
1163 use_spaces);
1166 static void
1167 ieditor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
1169 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1170 gtk_source_view_set_auto_indent(GTK_SOURCE_VIEW(sv->priv->view),
1171 auto_indent);
1174 static gint
1175 ieditor_get_indent_size (IAnjutaEditor *editor, GError **e)
1177 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1178 return gtk_source_view_get_indent_width (GTK_SOURCE_VIEW (sv->priv->view));
1181 static void
1182 ieditor_set_indent_size (IAnjutaEditor *editor, gint indentsize, GError **e)
1184 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1185 gtk_source_view_set_indent_width (GTK_SOURCE_VIEW (sv->priv->view), indentsize);
1188 /* Scroll to line */
1189 static void ieditor_goto_line(IAnjutaEditor *editor, gint line, GError **e)
1191 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1193 if (!sv->priv->loading)
1195 goto_line(sv, LOCATION_TO_LINE (line));
1196 anjuta_view_scroll_to_cursor(sv->priv->view);
1197 gtk_widget_grab_focus (GTK_WIDGET (sv->priv->view));
1199 else
1200 sv->priv->goto_line = LOCATION_TO_LINE (line);
1203 /* Scroll to position */
1204 static void ieditor_goto_position(IAnjutaEditor *editor, IAnjutaIterable* icell,
1205 GError **e)
1207 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
1208 GtkTextIter iter;
1209 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1210 sourceview_cell_get_iter (cell, &iter);
1211 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), &iter);
1212 gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (sv->priv->view),
1213 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (sv->priv->document)));
1216 /* Return a newly allocated pointer containing the whole text */
1217 static gchar* ieditor_get_text (IAnjutaEditor* editor,
1218 IAnjutaIterable* start,
1219 IAnjutaIterable* end, GError **e)
1221 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1223 GtkTextIter start_iter;
1224 GtkTextIter end_iter;
1225 sourceview_cell_get_iter (SOURCEVIEW_CELL(start), &start_iter);
1226 sourceview_cell_get_iter (SOURCEVIEW_CELL(end), &end_iter);
1228 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
1229 &start_iter, &end_iter, TRUE);
1232 static gchar*
1233 ieditor_get_text_all (IAnjutaEditor* edit, GError **e)
1235 GtkTextIter start_iter;
1236 GtkTextIter end_iter;
1237 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1238 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1240 gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, 0);
1241 gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, -1);
1243 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
1244 &start_iter, &end_iter, TRUE);
1247 /* Get cursor position */
1248 static IAnjutaIterable*
1249 ieditor_get_position (IAnjutaEditor* editor, GError **e)
1251 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1252 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1253 GtkTextIter iter;
1254 SourceviewCell* cell;
1256 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
1257 gtk_text_buffer_get_insert(buffer));
1259 cell = sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view));
1261 return IANJUTA_ITERABLE (cell);
1264 static gint
1265 ieditor_get_offset (IAnjutaEditor* editor, GError **e)
1267 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1268 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1269 GtkTextIter iter;
1271 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
1272 gtk_text_buffer_get_insert(buffer));
1274 return gtk_text_iter_get_offset (&iter);
1277 /* Return line of cursor */
1278 static gint ieditor_get_lineno(IAnjutaEditor *editor, GError **e)
1280 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1281 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1282 GtkTextIter iter;
1284 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
1285 gtk_text_buffer_get_insert(buffer));
1286 return gtk_text_iter_get_line(&iter) + 1;
1289 /* Return the length of the text in the buffer */
1290 static gint ieditor_get_length(IAnjutaEditor *editor, GError **e)
1292 /* We do not use gtk_text_buffer_get_char_count here because
1293 we need a size in bytes not in characters */
1295 GtkTextIter start_iter;
1296 GtkTextIter end_iter;
1297 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1298 gchar* text;
1299 gint length;
1301 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(sv->priv->document),
1302 &start_iter);
1303 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(sv->priv->document),
1304 &end_iter);
1305 text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
1306 &start_iter, &end_iter, TRUE);
1307 length = strlen(text);
1308 g_free(text);
1310 return length;
1313 /* Return word on cursor position */
1314 static gchar* ieditor_get_current_word(IAnjutaEditor *editor, GError **e)
1316 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1317 GtkTextIter start;
1318 GtkTextIter end;
1320 anjuta_view_get_current_word (sv->priv->view,
1321 &start, &end);
1323 return gtk_text_buffer_get_text (gtk_text_iter_get_buffer (&start),
1324 &start, &end, FALSE);
1327 /* Insert text at position */
1328 static void ieditor_insert(IAnjutaEditor *editor, IAnjutaIterable* icell,
1329 const gchar* text, gint length, GError **e)
1331 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
1332 GtkTextIter iter;
1333 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1334 sourceview_cell_get_iter (cell, &iter);
1336 /* Avoid processing text that is inserted programatically */
1337 g_signal_handlers_block_by_func (sv->priv->document,
1338 on_insert_text,
1339 sv);
1341 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
1342 &iter, text, length);
1343 g_signal_handlers_unblock_by_func (sv->priv->document,
1344 on_insert_text,
1345 sv);
1348 /* Append text to buffer */
1349 static void ieditor_append(IAnjutaEditor *editor, const gchar* text,
1350 gint length, GError **e)
1352 GtkTextIter iter;
1353 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1355 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(sv->priv->document),
1356 &iter);
1358 /* Avoid processing text that is inserted programatically */
1359 g_signal_handlers_block_by_func (sv->priv->document,
1360 on_insert_text,
1361 sv);
1362 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
1363 &iter, text, length);
1364 g_signal_handlers_unblock_by_func (sv->priv->document,
1365 on_insert_text,
1366 sv);
1369 static void ieditor_erase(IAnjutaEditor* editor, IAnjutaIterable* istart_cell,
1370 IAnjutaIterable* iend_cell, GError **e)
1372 SourceviewCell* start_cell = SOURCEVIEW_CELL (istart_cell);
1373 GtkTextIter start;
1374 GtkTextIter end;
1375 SourceviewCell* end_cell = SOURCEVIEW_CELL (iend_cell);
1376 sourceview_cell_get_iter (end_cell, &end);
1377 sourceview_cell_get_iter (start_cell, &start);
1379 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1380 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1382 gtk_text_buffer_delete (buffer, &start, &end);
1385 static void ieditor_erase_all(IAnjutaEditor *editor, GError **e)
1387 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1388 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(sv->priv->document), "", 0);
1391 /* Return column of cursor */
1392 static gint ieditor_get_column(IAnjutaEditor *editor, GError **e)
1394 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1395 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1396 GtkTextIter iter;
1397 GtkTextIter end_iter;
1398 guint column;
1399 guint end_column;
1400 guint tab_size;
1402 gtk_text_buffer_get_iter_at_mark(buffer, &end_iter,
1403 gtk_text_buffer_get_insert(buffer));
1404 gtk_text_buffer_get_iter_at_line(buffer, &iter,
1405 gtk_text_iter_get_line(&end_iter));
1407 column = 0;
1408 end_column = gtk_text_iter_get_line_offset(&end_iter);
1410 tab_size = ieditor_get_tab_size(editor, e);
1412 for ( ;
1413 gtk_text_iter_get_line_offset(&iter) != end_column;
1414 gtk_text_iter_forward_char(&iter), column++)
1416 /* Tab is U+0009 */
1417 if (gtk_text_iter_get_char(&iter) == 9)
1419 column += tab_size - (column % tab_size) - 1;
1423 return column;
1426 /* Return TRUE if editor is in overwrite mode */
1427 static gboolean ieditor_get_overwrite(IAnjutaEditor *editor, GError **e)
1429 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1430 return gtk_text_view_get_overwrite(GTK_TEXT_VIEW(sv->priv->view));
1434 /* Set the editor popup menu */
1435 static void ieditor_set_popup_menu(IAnjutaEditor *editor,
1436 GtkWidget* menu, GError **e)
1438 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1439 g_object_set(G_OBJECT(sv->priv->view), "popup", menu, NULL);
1442 /* Convert from position to line */
1443 static gint ieditor_get_line_from_position(IAnjutaEditor *editor,
1444 IAnjutaIterable* icell, GError **e)
1446 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
1447 GtkTextIter iter;
1448 sourceview_cell_get_iter (cell, &iter);
1449 return LINE_TO_LOCATION (gtk_text_iter_get_line(&iter));
1452 static IAnjutaIterable* ieditor_get_line_begin_position(IAnjutaEditor *editor,
1453 gint line, GError **e)
1455 GtkTextIter iter;
1456 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1458 gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER(sv->priv->document),
1459 &iter, LOCATION_TO_LINE (line), 0);
1460 return IANJUTA_ITERABLE (sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view)));
1463 static IAnjutaIterable* ieditor_get_line_end_position(IAnjutaEditor *editor,
1464 gint line, GError **e)
1466 GtkTextIter iter;
1467 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1469 gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER(sv->priv->document),
1470 &iter, LOCATION_TO_LINE (line), 0);
1471 /* If iter is not at line end, move it */
1472 if (!gtk_text_iter_ends_line(&iter))
1473 gtk_text_iter_forward_to_line_end (&iter);
1474 return IANJUTA_ITERABLE (sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view)));
1477 static IAnjutaIterable*
1478 ieditor_get_position_from_offset(IAnjutaEditor* edit, gint position, GError** e)
1480 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1481 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1482 GtkTextIter iter;
1483 SourceviewCell* cell;
1485 gtk_text_buffer_get_iter_at_offset(buffer, &iter, position);
1486 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1488 return IANJUTA_ITERABLE(cell);
1491 static IAnjutaIterable*
1492 ieditor_get_start_position (IAnjutaEditor* edit, GError** e)
1494 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1495 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1496 GtkTextIter iter;
1497 SourceviewCell* cell;
1499 gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
1500 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1502 return IANJUTA_ITERABLE(cell);
1505 static IAnjutaIterable*
1506 ieditor_get_end_position (IAnjutaEditor* edit, GError** e)
1508 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1509 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1510 GtkTextIter iter;
1511 SourceviewCell* cell;
1513 gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1);
1514 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1516 return IANJUTA_ITERABLE(cell);
1519 static void
1520 ieditor_goto_start (IAnjutaEditor* edit, GError** e)
1522 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1523 GtkTextIter iter;
1524 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document),
1525 &iter, 0);
1526 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), &iter);
1527 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
1528 &iter, 0, FALSE, 0, 0);
1531 static void
1532 ieditor_goto_end (IAnjutaEditor* edit, GError** e)
1534 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1535 GtkTextIter iter;
1536 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document),
1537 &iter, -1);
1538 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), &iter);
1539 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
1540 &iter, 0, FALSE, 0, 0);
1543 static void
1544 ieditor_iface_init (IAnjutaEditorIface *iface)
1546 iface->get_tabsize = ieditor_get_tab_size;
1547 iface->set_tabsize = ieditor_set_tab_size;
1548 iface->get_use_spaces = ieditor_get_use_spaces;
1549 iface->set_use_spaces = ieditor_set_use_spaces;
1550 iface->set_auto_indent = ieditor_set_auto_indent;
1551 iface->get_indentsize = ieditor_get_indent_size;
1552 iface->set_indentsize = ieditor_set_indent_size;
1553 iface->goto_line = ieditor_goto_line;
1554 iface->goto_position = ieditor_goto_position;
1555 iface->get_text = ieditor_get_text;
1556 iface->get_text_all = ieditor_get_text_all;
1557 iface->get_position = ieditor_get_position;
1558 iface->get_offset = ieditor_get_offset;
1559 iface->get_lineno = ieditor_get_lineno;
1560 iface->get_length = ieditor_get_length;
1561 iface->get_current_word = ieditor_get_current_word;
1562 iface->insert = ieditor_insert;
1563 iface->append = ieditor_append;
1564 iface->erase = ieditor_erase;
1565 iface->erase_all = ieditor_erase_all;
1566 iface->get_column = ieditor_get_column;
1567 iface->get_overwrite = ieditor_get_overwrite;
1568 iface->set_popup_menu = ieditor_set_popup_menu;
1569 iface->get_line_from_position = ieditor_get_line_from_position;
1570 iface->get_line_begin_position = ieditor_get_line_begin_position;
1571 iface->get_line_end_position = ieditor_get_line_end_position;
1572 iface->goto_start = ieditor_goto_start;
1573 iface->goto_end = ieditor_goto_end;
1574 iface->get_position_from_offset = ieditor_get_position_from_offset;
1575 iface->get_start_position = ieditor_get_start_position;
1576 iface->get_end_position = ieditor_get_end_position;
1579 /* Return true if editor can redo */
1580 static gboolean idocument_can_redo(IAnjutaDocument *editor, GError **e)
1582 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1583 return gtk_source_buffer_can_redo(GTK_SOURCE_BUFFER(sv->priv->document));
1586 /* Return true if editor can undo */
1587 static gboolean idocument_can_undo(IAnjutaDocument *editor, GError **e)
1589 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1590 return gtk_source_buffer_can_undo(GTK_SOURCE_BUFFER(sv->priv->document));
1593 /* Return true if editor can undo */
1594 static void idocument_begin_undo_action (IAnjutaDocument *editor, GError **e)
1596 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1597 gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER(sv->priv->document));
1600 /* Return true if editor can undo */
1601 static void idocument_end_undo_action (IAnjutaDocument *editor, GError **e)
1603 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1604 gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER(sv->priv->document));
1607 static void
1608 update_symbols(IAnjutaDocument* edit)
1610 g_signal_emit_by_name (G_OBJECT (IANJUTA_EDITOR(edit)), "code-changed", NULL, NULL);
1613 static void
1614 idocument_undo(IAnjutaDocument* edit, GError** ee)
1616 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1618 if (idocument_can_undo(edit, NULL))
1620 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1621 gtk_source_buffer_undo(GTK_SOURCE_BUFFER(sv->priv->document));
1622 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1625 anjuta_view_scroll_to_cursor(sv->priv->view);
1626 g_signal_emit_by_name(G_OBJECT(sv), "update_ui", sv);
1627 update_symbols(edit);
1630 static void
1631 idocument_redo(IAnjutaDocument* edit, GError** ee)
1633 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1634 if (idocument_can_redo(edit, NULL))
1635 gtk_source_buffer_redo(GTK_SOURCE_BUFFER(sv->priv->document));
1636 anjuta_view_scroll_to_cursor(sv->priv->view);
1637 g_signal_emit_by_name(G_OBJECT(sv), "update_ui", sv);
1638 update_symbols(edit);
1641 /* Grab focus */
1642 static void idocument_grab_focus (IAnjutaDocument *editor, GError **e)
1644 gtk_widget_grab_focus (GTK_WIDGET (ANJUTA_SOURCEVIEW (editor)->priv->view));
1647 /* Return the opened filename */
1648 static const gchar* idocument_get_filename(IAnjutaDocument *editor, GError **e)
1650 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1651 return sourceview_io_get_filename (sv->priv->io);
1654 static void
1655 idocument_cut(IAnjutaDocument* edit, GError** ee)
1657 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1659 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1660 anjuta_view_cut_clipboard(sv->priv->view);
1661 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1662 update_symbols(edit);
1665 static void
1666 idocument_copy(IAnjutaDocument* edit, GError** ee)
1668 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1669 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1670 anjuta_view_copy_clipboard(sv->priv->view);
1671 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1674 static void
1675 idocument_paste(IAnjutaDocument* edit, GError** ee)
1677 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1678 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1679 anjuta_view_paste_clipboard(sv->priv->view);
1680 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1681 update_symbols(edit);
1684 static void
1685 idocument_clear(IAnjutaDocument* edit, GError** ee)
1687 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1688 if (gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(sv->priv->document)))
1689 anjuta_view_delete_selection(sv->priv->view);
1690 else
1692 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1693 GtkTextIter cursor;
1694 gtk_text_buffer_get_iter_at_mark(buffer, &cursor, gtk_text_buffer_get_insert(buffer));
1696 /* Fix #388731 */
1697 gtk_text_iter_forward_char(&cursor);
1698 gtk_text_buffer_backspace(buffer, &cursor, TRUE, TRUE);
1702 static void
1703 idocument_iface_init (IAnjutaDocumentIface *iface)
1705 iface->grab_focus = idocument_grab_focus;
1706 iface->get_filename = idocument_get_filename;
1707 iface->can_undo = idocument_can_undo;
1708 iface->can_redo = idocument_can_redo;
1709 iface->begin_undo_action = idocument_begin_undo_action;
1710 iface->end_undo_action = idocument_end_undo_action;
1711 iface->undo = idocument_undo;
1712 iface->redo = idocument_redo;
1713 iface->cut = idocument_cut;
1714 iface->copy = idocument_copy;
1715 iface->paste = idocument_paste;
1716 iface->clear = idocument_clear;
1719 static void
1720 set_select(Sourceview* sv, GtkTextIter* start_iter, GtkTextIter* end_iter, gboolean scroll)
1722 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1723 gtk_text_buffer_select_range (buffer, start_iter, end_iter);
1725 if (scroll)
1726 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (sv->priv->view),
1727 gtk_text_buffer_get_insert (buffer),
1728 0.25,
1729 FALSE,
1730 0.0,
1731 0.0);
1734 /* IAnjutaEditorSelection */
1736 /* Find the previous open brace that begins the current indentation level. */
1737 static gboolean find_open_bracket(GtkTextIter *iter)
1739 int level = 1;
1741 while (gtk_text_iter_backward_char (iter))
1743 switch (gtk_text_iter_get_char (iter))
1745 case '{':
1746 if (!--level)
1747 return TRUE;
1748 break;
1749 case '}':
1750 ++level;
1751 break;
1755 return FALSE;
1758 /* Find the following close brace that ends the current indentation level. */
1759 static gboolean find_close_bracket(GtkTextIter *iter)
1761 int level = 1;
1763 while (gtk_text_iter_forward_char (iter))
1765 switch (gtk_text_iter_get_char (iter))
1767 case '{':
1768 ++level;
1769 break;
1770 case '}':
1771 if (!--level)
1772 return TRUE;
1773 break;
1777 return FALSE;
1780 static void
1781 iselect_block(IAnjutaEditorSelection* edit, GError** e)
1783 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1784 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1786 GtkTextIter iter;
1787 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
1788 gtk_text_buffer_get_insert(buffer));
1789 if (find_open_bracket (&iter))
1791 GtkTextIter end_iter;
1792 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER(sv->priv->document),
1793 &iter);
1794 end_iter = iter;
1795 if (find_close_bracket (&end_iter))
1797 gtk_text_iter_forward_char (&end_iter); /* move past brace */
1798 set_select (sv, &iter, &end_iter, TRUE);
1803 static void
1804 iselect_set (IAnjutaEditorSelection* edit,
1805 IAnjutaIterable* istart,
1806 IAnjutaIterable* iend,
1807 gboolean scroll,
1808 GError** e)
1810 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1811 GtkTextIter start, end;
1812 sourceview_cell_get_iter (SOURCEVIEW_CELL (istart), &start);
1813 sourceview_cell_get_iter (SOURCEVIEW_CELL (iend), &end);
1814 set_select(sv,
1815 &start,
1816 &end,
1817 scroll);
1821 static void
1822 iselect_all(IAnjutaEditorSelection* edit, GError** e)
1824 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1825 anjuta_view_select_all(sv->priv->view);
1828 static gboolean
1829 iselect_has_selection (IAnjutaEditorSelection *editor, GError **e)
1831 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1833 return gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(sv->priv->document));
1836 /* Return a newly allocated pointer containing selected text or
1837 NULL if no text is selected */
1838 static gchar* iselect_get(IAnjutaEditorSelection* editor, GError **e)
1840 GtkTextIter start_iter;
1841 GtkTextIter end_iter;
1842 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1844 if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(sv->priv->document),
1845 &start_iter, &end_iter))
1847 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
1848 &start_iter, &end_iter, TRUE);
1850 else
1851 return NULL;
1855 static IAnjutaIterable*
1856 iselect_get_start (IAnjutaEditorSelection *edit, GError **e)
1858 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1859 GtkTextIter start;
1860 if (gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (sv->priv->document),
1861 &start, NULL))
1863 return IANJUTA_ITERABLE (sourceview_cell_new (&start, GTK_TEXT_VIEW (sv->priv->view)));
1865 return NULL;
1868 static IAnjutaIterable*
1869 iselect_get_end (IAnjutaEditorSelection *edit, GError **e)
1871 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1872 GtkTextIter end;
1873 if (gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (sv->priv->document),
1874 NULL, &end))
1876 return IANJUTA_ITERABLE (sourceview_cell_new (&end, GTK_TEXT_VIEW (sv->priv->view)));
1878 return NULL;
1882 static void iselect_function(IAnjutaEditorSelection *editor, GError **e)
1884 // TODO
1887 /* If text is selected, replace with given text */
1888 static void iselect_replace(IAnjutaEditorSelection* editor,
1889 const gchar* text, gint length, GError **e)
1891 GtkTextIter start_iter;
1892 GtkTextIter end_iter;
1893 GtkTextIter iter;
1894 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1895 gint position;
1897 if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(sv->priv->document),
1898 &start_iter, &end_iter))
1900 position = gtk_text_iter_get_offset(&start_iter);
1901 gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(sv->priv->document),
1902 FALSE, TRUE);
1903 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(sv->priv->document),
1904 &iter, position);
1905 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
1906 &iter, text, length);
1910 static void
1911 iselect_iface_init(IAnjutaEditorSelectionIface *iface)
1913 iface->set = iselect_set;
1914 iface->has_selection = iselect_has_selection;
1915 iface->get_start = iselect_get_start;
1916 iface->get_end = iselect_get_end;
1917 iface->select_block = iselect_block;
1918 iface->select_function = iselect_function;
1919 iface->select_all = iselect_all;
1920 iface->select_block = iselect_block;
1921 iface->get = iselect_get;
1922 iface->replace = iselect_replace;
1925 /* IAnjutaEditorConvert Interface */
1927 static void
1928 iconvert_to_upper(IAnjutaEditorConvert* edit, IAnjutaIterable *start_position,
1929 IAnjutaIterable *end_position, GError** e)
1931 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1932 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1933 GtkTextIter start, end;
1934 sourceview_cell_get_iter (SOURCEVIEW_CELL (end_position), &end);
1935 sourceview_cell_get_iter (SOURCEVIEW_CELL (start_position), &start);
1937 gchar* text_buffer = gtk_text_buffer_get_text (buffer,
1938 &start, &end, TRUE);
1939 gtk_text_buffer_begin_user_action (buffer);
1940 gtk_text_buffer_delete (buffer, &start, &end);
1941 gtk_text_buffer_insert (buffer, &start, g_utf8_strup (text_buffer, -1), -1);
1942 gtk_text_buffer_end_user_action (buffer);
1943 g_free (text_buffer);
1946 static void
1947 iconvert_to_lower(IAnjutaEditorConvert* edit, IAnjutaIterable *start_position,
1948 IAnjutaIterable *end_position, GError** e)
1950 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1951 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1952 GtkTextIter start, end;
1953 sourceview_cell_get_iter (SOURCEVIEW_CELL (end_position), &end);
1954 sourceview_cell_get_iter (SOURCEVIEW_CELL (start_position), &start);
1956 gchar* text_buffer = gtk_text_buffer_get_text (buffer,
1957 &start, &end, TRUE);
1958 gtk_text_buffer_begin_user_action (buffer);
1959 gtk_text_buffer_delete (buffer, &start, &end);
1960 gtk_text_buffer_insert (buffer, &start, g_utf8_strdown (text_buffer, -1), -1);
1961 gtk_text_buffer_end_user_action (buffer);
1962 g_free (text_buffer);
1966 static void
1967 iconvert_iface_init(IAnjutaEditorConvertIface* iface)
1969 iface->to_upper = iconvert_to_upper;
1970 iface->to_lower = iconvert_to_lower;
1973 static gint
1974 imark_mark(IAnjutaMarkable* mark, gint location, IAnjutaMarkableMarker marker,
1975 const gchar* tooltip, GError **e)
1977 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
1979 if (location <= 0)
1981 g_set_error (e, IANJUTA_MARKABLE_ERROR, IANJUTA_MARKABLE_INVALID_LOCATION,
1982 "Invalid marker location: %d!", location);
1983 return -1;
1986 static gint marker_count = 0;
1988 marker_count++;
1990 if (sv->priv->loading)
1992 MarkerReload* mark = marker_reload_new ();
1994 mark->handle = marker_count;
1995 mark->line = LOCATION_TO_LINE(location);
1996 mark->category = marker_types[marker];
1997 mark->tooltip = g_strdup (tooltip);
1999 sv->priv->reload_marks = g_slist_prepend (sv->priv->reload_marks, mark);
2001 else
2002 sourceview_add_mark (sv, marker_count, LOCATION_TO_LINE(location), marker_types[marker],
2003 tooltip);
2005 return marker_count;
2008 static void
2009 imark_unmark(IAnjutaMarkable* mark, gint location, IAnjutaMarkableMarker marker,
2010 GError **e)
2012 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
2013 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
2014 GtkTextIter begin;
2015 GtkTextIter end;
2017 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &begin, LOCATION_TO_LINE (location));
2018 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &end, LOCATION_TO_LINE (location));
2020 gtk_source_buffer_remove_source_marks (buffer, &begin, &end, marker_types[marker]);
2024 static gboolean
2025 imark_is_marker_set(IAnjutaMarkable* mark, gint location,
2026 IAnjutaMarkableMarker marker, GError **e)
2028 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
2029 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
2030 GSList* markers;
2031 gboolean retval;
2033 markers = gtk_source_buffer_get_source_marks_at_line (buffer,
2034 LOCATION_TO_LINE (location),
2035 marker_types[marker]);
2037 retval = (markers != NULL);
2039 g_slist_free (markers);
2040 return retval;
2043 static gint
2044 imark_location_from_handle(IAnjutaMarkable* imark, gint handle, GError **e)
2046 Sourceview* sv = ANJUTA_SOURCEVIEW(imark);
2047 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
2048 GtkTextMark* mark;
2049 GtkTextIter iter;
2050 gint location;
2051 gchar* name = CREATE_MARK_NAME (handle);
2053 mark = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (buffer), name);
2054 if (mark)
2056 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, mark);
2057 location = LINE_TO_LOCATION (gtk_text_iter_get_line (&iter));
2059 else
2060 location = -1;
2062 g_free (name);
2064 return location;
2067 static void
2068 imark_delete_all_markers(IAnjutaMarkable* imark, IAnjutaMarkableMarker marker,
2069 GError **e)
2071 Sourceview* sv = ANJUTA_SOURCEVIEW(imark);
2072 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
2073 GtkTextIter begin;
2074 GtkTextIter end;
2076 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &begin, 0);
2077 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &end, -1);
2079 gtk_source_buffer_remove_source_marks (buffer, &begin, &end, marker_types[marker]);
2082 static void
2083 imark_iface_init(IAnjutaMarkableIface* iface)
2085 iface->mark = imark_mark;
2086 iface->unmark = imark_unmark;
2087 iface->location_from_handle = imark_location_from_handle;
2088 iface->is_marker_set = imark_is_marker_set;
2089 iface->delete_all_markers = imark_delete_all_markers;
2092 /* IanjutaIndic Interface */
2095 static void
2096 iindic_clear (IAnjutaIndicable *indic, GError **e)
2098 Sourceview* sv = ANJUTA_SOURCEVIEW(indic);
2099 GtkTextIter start, end;
2101 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(sv->priv->document),
2102 &start, 0);
2103 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(sv->priv->document),
2104 &end, -1);
2105 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
2106 IMPORTANT_INDIC,
2107 &start, &end);
2108 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
2109 WARNING_INDIC,
2110 &start, &end);
2111 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
2112 CRITICAL_INDIC,
2113 &start, &end);
2116 static void
2117 iindic_set (IAnjutaIndicable *indic, IAnjutaIterable* ibegin, IAnjutaIterable *iend,
2118 IAnjutaIndicableIndicator indicator, GError **e)
2120 GtkTextTag *tag = NULL;
2121 Sourceview* sv = ANJUTA_SOURCEVIEW(indic);
2122 GtkTextIter start, end;
2124 switch (indicator)
2126 case IANJUTA_INDICABLE_IMPORTANT :
2127 tag = sv->priv->important_indic;
2128 break;
2129 case IANJUTA_INDICABLE_WARNING :
2130 tag = sv->priv->warning_indic;
2131 break;
2132 case IANJUTA_INDICABLE_CRITICAL :
2133 tag = sv->priv->critical_indic;
2134 break;
2135 default:
2136 return;
2138 sourceview_cell_get_iter (SOURCEVIEW_CELL (ibegin), &start);
2139 sourceview_cell_get_iter (SOURCEVIEW_CELL (iend), &end);
2140 gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER(sv->priv->document), tag,
2141 &start,
2142 &end);
2145 static void
2146 iindic_iface_init(IAnjutaIndicableIface* iface)
2148 iface->clear = iindic_clear;
2149 iface->set = iindic_set;
2152 static void
2153 iprint_print(IAnjutaPrint* print, GError** e)
2155 Sourceview* sv = ANJUTA_SOURCEVIEW(print);
2156 sourceview_print(sv);
2159 static void
2160 iprint_print_preview(IAnjutaPrint* print, GError** e)
2162 Sourceview* sv = ANJUTA_SOURCEVIEW(print);
2163 sourceview_print_preview(sv);
2166 static void
2167 iprint_iface_init(IAnjutaPrintIface* iface)
2169 iface->print = iprint_print;
2170 iface->print_preview = iprint_print_preview;
2174 static const GList*
2175 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
2176 GError **err)
2178 /* Cache the list */
2179 static GList* languages = NULL;
2180 if (!languages)
2182 const gchar* const * langs = gtk_source_language_manager_get_language_ids (gtk_source_language_manager_get_default());
2183 if (langs)
2185 const gchar* const * lang;
2187 for (lang = langs; *lang != NULL; lang++)
2189 languages = g_list_append (languages, (gpointer)*lang);
2193 return languages;
2196 static const gchar*
2197 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
2198 const gchar *language, GError **err)
2200 return language;
2203 static const gchar*
2204 autodetect_language (Sourceview* sv)
2206 gchar* io_mime_type = sourceview_io_get_mime_type (sv->priv->io);
2207 const gchar* filename = sourceview_io_get_filename (sv->priv->io);
2208 GtkSourceLanguage *language;
2209 const gchar* detected_language = NULL;
2211 language = gtk_source_language_manager_guess_language (gtk_source_language_manager_get_default (), filename, io_mime_type);
2212 if (!language)
2214 goto out;
2217 detected_language = gtk_source_language_get_id (language);
2219 g_signal_emit_by_name (sv, "language-changed", detected_language);
2220 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (sv->priv->document), language);
2222 out:
2223 if (io_mime_type)
2224 g_free (io_mime_type);
2226 return detected_language;
2229 static void
2230 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
2231 const gchar *language, GError **err)
2233 Sourceview* sv = ANJUTA_SOURCEVIEW (ilanguage);
2234 gboolean found = FALSE;
2235 const GList* languages = ilanguage_get_supported_languages(ilanguage, err);
2236 const GList* cur_lang;
2237 for (cur_lang = languages; cur_lang != NULL && language != NULL; cur_lang = g_list_next (cur_lang))
2239 GtkSourceLanguage* source_language =
2240 gtk_source_language_manager_get_language (gtk_source_language_manager_get_default(),
2241 cur_lang->data);
2242 const gchar* id = gtk_source_language_get_id (source_language);
2244 if (g_str_equal (language, id))
2246 g_signal_emit_by_name (G_OBJECT(sv), "language-changed",
2247 id);
2248 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (sv->priv->document),
2249 source_language);
2250 found = TRUE;
2251 break;
2254 if (!found)
2256 autodetect_language (sv);
2260 static const gchar*
2261 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
2263 Sourceview* sv = ANJUTA_SOURCEVIEW(ilanguage);
2264 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
2265 GtkSourceLanguage* lang = gtk_source_buffer_get_language(buffer);
2266 if (lang)
2268 return gtk_source_language_get_id(lang);
2270 else
2272 const gchar* language = autodetect_language (sv);
2273 return language;
2277 static void
2278 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
2280 iface->get_supported_languages = ilanguage_get_supported_languages;
2281 iface->get_language_name = ilanguage_get_language_name;
2282 iface->get_language = ilanguage_get_language;
2283 iface->set_language = ilanguage_set_language;
2286 static void
2287 itips_show (IAnjutaEditorTip *iassist, GList* tips, IAnjutaIterable* ipos,
2288 GError **err)
2290 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2291 SourceviewCell* cell = SOURCEVIEW_CELL (ipos);
2292 GtkTextIter iter;
2293 sourceview_cell_get_iter(cell, &iter);
2295 g_return_if_fail (tips != NULL);
2297 if (!sv->priv->assist_tip)
2299 sv->priv->assist_tip =
2300 ASSIST_TIP (assist_tip_new (GTK_TEXT_VIEW (sv->priv->view), tips));
2302 g_object_weak_ref (G_OBJECT(sv->priv->assist_tip),
2303 (GWeakNotify) on_assist_tip_destroyed,
2304 sv);
2305 assist_tip_move (sv->priv->assist_tip, GTK_TEXT_VIEW (sv->priv->view), &iter);
2306 gtk_widget_show (GTK_WIDGET (sv->priv->assist_tip));
2308 else
2310 assist_tip_set_tips (sv->priv->assist_tip, tips);
2311 assist_tip_move (sv->priv->assist_tip, GTK_TEXT_VIEW (sv->priv->view), &iter);
2315 static void
2316 itips_cancel (IAnjutaEditorTip* iassist, GError** err)
2318 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2319 if (sv->priv->assist_tip)
2320 gtk_widget_destroy (GTK_WIDGET (sv->priv->assist_tip));
2323 static gboolean
2324 itips_visible (IAnjutaEditorTip* iassist, GError** err)
2326 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2327 return (sv->priv->assist_tip != NULL);
2330 static void
2331 itip_iface_init(IAnjutaEditorTipIface* iface)
2333 iface->show = itips_show;
2334 iface->cancel = itips_cancel;
2335 iface->visible = itips_visible;
2338 static void
2339 iassist_add(IAnjutaEditorAssist* iassist,
2340 IAnjutaProvider* provider,
2341 GError** e)
2343 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2344 GtkSourceCompletion* completion = gtk_source_view_get_completion(GTK_SOURCE_VIEW(sv->priv->view));
2345 gtk_source_completion_add_provider(completion,
2346 GTK_SOURCE_COMPLETION_PROVIDER(sourceview_provider_new(sv, provider)),
2347 NULL);
2348 DEBUG_PRINT("Adding provider: %s", ianjuta_provider_get_name(provider, NULL));
2351 static void
2352 iassist_remove(IAnjutaEditorAssist* iassist,
2353 IAnjutaProvider* provider,
2354 GError** e)
2356 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2357 GtkSourceCompletion* completion = gtk_source_view_get_completion(GTK_SOURCE_VIEW(sv->priv->view));
2358 GList* node;
2359 for (node = gtk_source_completion_get_providers(completion); node != NULL; node = g_list_next(node))
2361 SourceviewProvider* prov;
2362 if (!SOURCEVIEW_IS_PROVIDER(node->data))
2363 continue;
2364 prov = SOURCEVIEW_PROVIDER(node->data);
2365 if (prov->iprov == provider)
2367 DEBUG_PRINT("Removing provider: %s", ianjuta_provider_get_name(provider, NULL));
2368 gtk_source_completion_remove_provider(completion,
2369 GTK_SOURCE_COMPLETION_PROVIDER(prov),
2370 NULL);
2375 static void
2376 iassist_invoke(IAnjutaEditorAssist* iassist,
2377 IAnjutaProvider* provider,
2378 GError** e)
2380 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2381 GtkSourceCompletion* completion = gtk_source_view_get_completion(GTK_SOURCE_VIEW(sv->priv->view));
2382 GList* node;
2383 SourceviewProvider* prov = NULL;
2384 GList* providers = NULL;
2385 GtkTextIter iter;
2386 GtkSourceCompletionContext* context;
2388 for (node = gtk_source_completion_get_providers(completion); node != NULL; node = g_list_next(node))
2390 if (provider == NULL)
2392 providers = g_list_append (providers, node->data);
2393 continue;
2395 if (!SOURCEVIEW_IS_PROVIDER (node->data))
2396 break;
2397 prov = SOURCEVIEW_PROVIDER(node->data);
2398 if (prov->iprov == provider)
2400 providers = g_list_append (providers, prov);
2404 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (sv->priv->document),
2405 &iter,
2406 gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(sv->priv->document)));
2407 context =
2408 gtk_source_completion_create_context(completion, &iter);
2410 gtk_source_completion_show(completion, providers, context);
2411 g_list_free(providers);
2414 static void
2415 iassist_proposals(IAnjutaEditorAssist* iassist,
2416 IAnjutaProvider* provider,
2417 GList* proposals,
2418 const gchar* pre_word,
2419 gboolean finished,
2420 GError** e)
2422 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2423 GtkSourceCompletion* completion = gtk_source_view_get_completion(GTK_SOURCE_VIEW(sv->priv->view));
2424 GList* node;
2425 for (node = gtk_source_completion_get_providers(completion); node != NULL; node = g_list_next(node))
2427 SourceviewProvider* prov;
2428 if (!SOURCEVIEW_IS_PROVIDER (node->data))
2429 continue;
2431 prov = SOURCEVIEW_PROVIDER(node->data);
2432 if (prov->iprov == provider)
2434 g_return_if_fail (!prov->cancelled);
2436 GList* prop;
2437 GList* items = NULL;
2438 for (prop = proposals; prop != NULL; prop = g_list_next(prop))
2440 IAnjutaEditorAssistProposal* proposal = prop->data;
2441 GtkSourceCompletionItem* item;
2442 if (proposal->markup)
2444 item = gtk_source_completion_item_new_with_markup(proposal->markup,
2445 proposal->text,
2446 proposal->icon,
2447 proposal->info);
2449 else
2451 item = gtk_source_completion_item_new(proposal->label,
2452 proposal->text,
2453 proposal->icon,
2454 proposal->info);
2456 items = g_list_append (items, item);
2457 g_object_set_data (G_OBJECT(item), "__data", proposal->data);
2459 gtk_source_completion_context_add_proposals (prov->context, GTK_SOURCE_COMPLETION_PROVIDER(prov),
2460 items, finished);
2461 g_list_free_full (items, g_object_unref);
2462 break;
2467 static void iassist_iface_init(IAnjutaEditorAssistIface* iface)
2469 iface->add = iassist_add;
2470 iface->remove = iassist_remove;
2471 iface->invoke = iassist_invoke;
2472 iface->proposals = iassist_proposals;
2476 static gboolean
2477 isearch_forward (IAnjutaEditorSearch* isearch,
2478 const gchar* search,
2479 gboolean case_sensitive,
2480 IAnjutaEditorCell* istart,
2481 IAnjutaEditorCell* iend,
2482 IAnjutaEditorCell** iresult_start,
2483 IAnjutaEditorCell** iresult_end,
2484 GError** e)
2486 Sourceview* sv = ANJUTA_SOURCEVIEW (isearch);
2488 SourceviewCell* start = SOURCEVIEW_CELL (istart);
2489 SourceviewCell* end = SOURCEVIEW_CELL (iend);
2491 GtkTextIter start_iter;
2492 GtkTextIter end_iter;
2494 GtkTextIter result_start, result_end;
2496 GtkTextSearchFlags flags = 0;
2498 sourceview_cell_get_iter (start, &start_iter);
2499 sourceview_cell_get_iter (end, &end_iter);
2502 if (!case_sensitive)
2504 flags = GTK_TEXT_SEARCH_CASE_INSENSITIVE;
2507 gboolean result =
2508 gtk_text_iter_forward_search (&start_iter, search, flags, &result_start, &result_end,
2509 &end_iter);
2511 if (result)
2513 if (iresult_start)
2515 *iresult_start = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_start,
2516 GTK_TEXT_VIEW (sv->priv->view)));
2518 if (iresult_end)
2520 *iresult_end = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_end,
2521 GTK_TEXT_VIEW (sv->priv->view)));
2525 return result;
2528 static gboolean
2529 isearch_backward (IAnjutaEditorSearch* isearch,
2530 const gchar* search,
2531 gboolean case_sensitive,
2532 IAnjutaEditorCell* istart,
2533 IAnjutaEditorCell* iend,
2534 IAnjutaEditorCell** iresult_start,
2535 IAnjutaEditorCell** iresult_end,
2536 GError** e)
2538 Sourceview* sv = ANJUTA_SOURCEVIEW (isearch);
2540 SourceviewCell* start = SOURCEVIEW_CELL (istart);
2541 SourceviewCell* end = SOURCEVIEW_CELL (iend);
2543 GtkTextIter start_iter;
2544 GtkTextIter end_iter;
2545 GtkTextIter result_start, result_end;
2547 GtkTextSearchFlags flags = 0;
2549 sourceview_cell_get_iter (start, &start_iter);
2550 sourceview_cell_get_iter (end, &end_iter);
2553 if (!case_sensitive)
2555 flags = GTK_TEXT_SEARCH_CASE_INSENSITIVE;
2558 gboolean result =
2559 gtk_text_iter_backward_search (&start_iter, search, flags, &result_start, &result_end,
2560 &end_iter);
2562 if (result)
2564 if (iresult_start)
2566 *iresult_start = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_start,
2567 GTK_TEXT_VIEW (sv->priv->view)));
2569 if (iresult_end)
2571 *iresult_end = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_end,
2572 GTK_TEXT_VIEW (sv->priv->view)));
2576 return result;
2579 static void
2580 isearch_iface_init(IAnjutaEditorSearchIface* iface)
2582 iface->forward = isearch_forward;
2583 iface->backward = isearch_backward;
2586 /* IAnjutaHover */
2587 static void on_sourceview_hover_destroy (gpointer data, GObject* where_the_data_was);
2588 static void
2589 on_sourceview_hover_leave(gpointer data, GObject* where_the_data_was)
2591 Sourceview* sv = ANJUTA_SOURCEVIEW (data);
2593 if (sv->priv->tooltip_cell)
2595 g_signal_emit_by_name (G_OBJECT (sv), "hover-leave", sv->priv->tooltip_cell);
2596 g_object_unref (sv->priv->tooltip_cell);
2597 sv->priv->tooltip_cell = NULL;
2599 g_object_weak_unref (G_OBJECT(sv), on_sourceview_hover_destroy, where_the_data_was);
2602 static void
2603 on_sourceview_hover_destroy (gpointer data, GObject* where_the_data_was)
2605 g_object_weak_unref (G_OBJECT(data), on_sourceview_hover_leave, where_the_data_was);
2609 static gboolean
2610 on_sourceview_hover_over (GtkWidget *widget, gint x, gint y,
2611 gboolean keyboard_tip, GtkTooltip *tooltip,
2612 gpointer data)
2614 Sourceview* sv = ANJUTA_SOURCEVIEW (data);
2615 SourceviewCell* cell;
2616 GtkTextIter iter;
2617 GtkTextView *text_view = GTK_TEXT_VIEW (widget);
2618 gint bx, by;
2620 gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_WIDGET,
2621 x, y, &bx, &by);
2622 gtk_text_view_get_iter_at_location (text_view, &iter, bx, by);
2624 cell = sourceview_cell_new (&iter, text_view);
2626 /* This should call ianjuta_hover_display() */
2627 g_signal_emit_by_name (G_OBJECT (sv), "hover-over", cell);
2629 if (sv->priv->tooltip)
2631 gtk_tooltip_set_text (tooltip, sv->priv->tooltip);
2632 g_object_weak_ref (G_OBJECT (tooltip), on_sourceview_hover_leave, sv);
2633 g_object_weak_ref (G_OBJECT (sv), on_sourceview_hover_destroy, tooltip);
2634 g_free (sv->priv->tooltip);
2635 sv->priv->tooltip = NULL;
2636 sv->priv->tooltip_cell = cell;
2637 return TRUE;
2640 return FALSE;
2643 static void
2644 ihover_display (IAnjutaEditorHover *ihover,
2645 IAnjutaIterable* position,
2646 const gchar* info,
2647 GError **e)
2649 Sourceview* sv = ANJUTA_SOURCEVIEW (ihover);
2650 g_assert (sv->priv->tooltip == NULL);
2651 sv->priv->tooltip = g_strdup (info);
2654 static void
2655 ihover_iface_init(IAnjutaEditorHoverIface* iface)
2657 iface->display = ihover_display;
2660 static void
2661 iglade_iface_init(IAnjutaEditorGladeSignalIface* iface)
2663 /* only signals */
2666 ANJUTA_TYPE_BEGIN(Sourceview, sourceview, GTK_TYPE_BOX);
2667 ANJUTA_TYPE_ADD_INTERFACE(idocument, IANJUTA_TYPE_DOCUMENT);
2668 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
2669 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
2670 ANJUTA_TYPE_ADD_INTERFACE(ieditor, IANJUTA_TYPE_EDITOR);
2671 ANJUTA_TYPE_ADD_INTERFACE(imark, IANJUTA_TYPE_MARKABLE);
2672 ANJUTA_TYPE_ADD_INTERFACE(iindic, IANJUTA_TYPE_INDICABLE);
2673 ANJUTA_TYPE_ADD_INTERFACE(iselect, IANJUTA_TYPE_EDITOR_SELECTION);
2674 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
2675 ANJUTA_TYPE_ADD_INTERFACE(itip, IANJUTA_TYPE_EDITOR_TIP);
2676 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
2677 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
2678 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
2679 ANJUTA_TYPE_ADD_INTERFACE(isearch, IANJUTA_TYPE_EDITOR_SEARCH);
2680 ANJUTA_TYPE_ADD_INTERFACE(ihover, IANJUTA_TYPE_EDITOR_HOVER);
2681 ANJUTA_TYPE_ADD_INTERFACE(iglade, IANJUTA_TYPE_EDITOR_GLADE_SIGNAL);
2682 ANJUTA_TYPE_END;