2008-04-07 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / plugins / sourceview / sourceview.c
bloba35bda13346e38e0c183e3706102565644d394c5
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/interfaces/ianjuta-file.h>
29 #include <libanjuta/interfaces/ianjuta-file-savable.h>
30 #include <libanjuta/interfaces/ianjuta-markable.h>
31 #include <libanjuta/interfaces/ianjuta-indicable.h>
32 #include <libanjuta/interfaces/ianjuta-bookmark.h>
33 #include <libanjuta/interfaces/ianjuta-print.h>
34 #include <libanjuta/interfaces/ianjuta-language-support.h>
35 #include <libanjuta/interfaces/ianjuta-document.h>
36 #include <libanjuta/interfaces/ianjuta-editor.h>
37 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
38 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
39 #include <libanjuta/interfaces/ianjuta-editor-convert.h>
40 #include <libanjuta/interfaces/ianjuta-editor-language.h>
41 #include <libanjuta/interfaces/ianjuta-editor-search.h>
42 #include <libanjuta/interfaces/ianjuta-editor-hover.h>
44 #include <libgnomevfs/gnome-vfs-init.h>
45 #include <libgnomevfs/gnome-vfs-mime-utils.h>
46 #include <libgnomevfs/gnome-vfs-utils.h>
47 #include <libgnomevfs/gnome-vfs.h>
49 #include <gtksourceview/gtksourceview.h>
50 #include <gtksourceview/gtksourcelanguage.h>
51 #include <gtksourceview/gtksourcelanguagemanager.h>
52 #include <gtksourceview/gtksourcebuffer.h>
53 #include <gtksourceview/gtksourceiter.h>
55 #include "config.h"
56 #include "anjuta-encodings.h"
57 #include "anjuta-document.h"
58 #include "anjuta-view.h"
60 #include "sourceview.h"
61 #include "sourceview-private.h"
62 #include "sourceview-prefs.h"
63 #include "sourceview-print.h"
64 #include "sourceview-cell.h"
65 #include "plugin.h"
67 #define HAVE_TOOLTIP_API (GTK_MAJOR_VERSION > 2 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 12))
69 #define FORWARD 0
70 #define BACKWARD 1
72 #define MONITOR_KEY "sourceview.enable.vfs"
74 #define LOCATION_TO_LINE(o) ((o) - 1)
75 #define LINE_TO_LOCATION(o) ((o) + 1)
77 #define CREATE_MARK_NAME(o) (g_strdup_printf ("anjuta-mark-%d", (o)))
79 static void sourceview_class_init(SourceviewClass *klass);
80 static void sourceview_instance_init(Sourceview *sv);
81 static void sourceview_finalize(GObject *object);
82 static void sourceview_dispose(GObject *object);
84 static GObjectClass *parent_class = NULL;
86 #if HAVE_TOOLTIP_API
87 static gboolean on_sourceview_hover_over (GtkWidget *widget, gint x, gint y,
88 gboolean keyboard_tip, GtkTooltip *tooltip,
89 gpointer data);
90 #endif
91 static gboolean sourceview_add_monitor(Sourceview* sv);
93 /* Callbacks */
95 static void
96 on_assist_window_destroyed (AssistWindow* window, Sourceview* sv)
98 sv->priv->assist_win = NULL;
101 static void
102 on_assist_tip_destroyed (AssistTip* tip, Sourceview* sv)
104 sv->priv->assist_tip = NULL;
107 static void
108 on_assist_chosen(AssistWindow* assist_win, gint num, Sourceview* sv)
110 g_signal_emit_by_name(G_OBJECT(sv), "assist-chosen", num);
113 static void
114 on_assist_cancel(AssistWindow* assist_win, Sourceview* sv)
116 if (sv->priv->assist_win)
118 gtk_widget_destroy(GTK_WIDGET(sv->priv->assist_win));
122 static void on_insert_text (GtkTextBuffer* buffer,
123 GtkTextIter* location,
124 char* text,
125 gint len,
126 Sourceview* sv)
128 /* We only want ascii characters */
129 if (len > 1 || strlen(text) > 1)
130 return;
131 else
133 int offset = gtk_text_iter_get_offset (location);
134 SourceviewCell* cell = sourceview_cell_new (location,
135 GTK_TEXT_VIEW(sv->priv->view));
136 ianjuta_iterable_previous (IANJUTA_ITERABLE (cell), NULL);
137 g_signal_handlers_block_by_func (buffer, on_insert_text, sv);
138 g_signal_emit_by_name(G_OBJECT(sv), "char_added", cell, text[0]);
139 g_signal_handlers_unblock_by_func (buffer, on_insert_text, sv);
140 /* Reset iterator */
141 gtk_text_buffer_get_iter_at_offset (buffer, location,
142 offset);
146 /* Called whenever the document is changed */
147 static void on_document_modified_changed(AnjutaDocument* buffer, Sourceview* sv)
149 /* Emit IAnjutaFileSavable signals */
150 g_signal_emit_by_name(G_OBJECT(sv), "save_point",
151 !gtk_text_buffer_get_modified(GTK_TEXT_BUFFER(buffer)));
154 /* Called whenever the curser moves */
155 static void on_cursor_moved(AnjutaDocument *widget,
156 Sourceview* sv)
158 /* Emit IAnjutaEditor signals */
159 g_signal_emit_by_name(G_OBJECT(sv), "update_ui");
162 /* Callback for dialog below */
163 static void
164 on_reload_dialog_response (GtkWidget *dlg, gint res, Sourceview *sv)
166 if (res == GTK_RESPONSE_YES)
168 ianjuta_file_open(IANJUTA_FILE(sv),
169 anjuta_document_get_uri(sv->priv->document), NULL);
171 else
173 /* Set dirty */
174 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document), TRUE);
176 gtk_widget_destroy (dlg);
179 /* Update Monitor on load/save */
180 static void
181 sourceview_remove_monitor(Sourceview* sv)
183 gboolean monitor_enabled = anjuta_preferences_get_int (sv->priv->prefs, MONITOR_KEY);
185 if (monitor_enabled && sv->priv->monitor != NULL)
187 DEBUG_PRINT ("Monitor removed for %s", anjuta_document_get_uri(sv->priv->document));
188 gnome_vfs_monitor_cancel(sv->priv->monitor);
189 sv->priv->monitor = NULL;
193 static gboolean
194 on_sourceview_uri_changed_prompt (Sourceview* sv)
196 GtkWidget *dlg;
197 GtkWidget *parent;
198 gchar *buff;
200 buff =
201 g_strdup_printf (_
202 ("The file '%s' on the disk is more recent than\n"
203 "the current buffer.\nDo you want to reload it?"),
204 ianjuta_document_get_filename(IANJUTA_DOCUMENT(sv), NULL));
206 parent = gtk_widget_get_toplevel (GTK_WIDGET (sv));
208 dlg = gtk_message_dialog_new (GTK_WINDOW (parent),
209 GTK_DIALOG_DESTROY_WITH_PARENT,
210 GTK_MESSAGE_WARNING,
211 GTK_BUTTONS_NONE, buff);
212 gtk_dialog_add_button (GTK_DIALOG (dlg),
213 GTK_STOCK_NO,
214 GTK_RESPONSE_NO);
215 anjuta_util_dialog_add_button (GTK_DIALOG (dlg),
216 _("_Reload"),
217 GTK_STOCK_REFRESH,
218 GTK_RESPONSE_YES);
219 g_free (buff);
221 gtk_window_set_transient_for (GTK_WINDOW (dlg),
222 GTK_WINDOW (parent));
224 g_signal_connect (G_OBJECT(dlg), "response",
225 G_CALLBACK (on_reload_dialog_response),
226 sv);
227 gtk_widget_show (dlg);
229 g_signal_connect_swapped (G_OBJECT(dlg), "delete-event",
230 G_CALLBACK (gtk_widget_destroy),
231 dlg);
233 return FALSE;
236 static void
237 on_sourceview_uri_changed (GnomeVFSMonitorHandle *handle,
238 const gchar *monitor_uri,
239 const gchar *info_uri,
240 GnomeVFSMonitorEventType event_type,
241 gpointer user_data)
243 Sourceview *sv = ANJUTA_SOURCEVIEW (user_data);
245 if (!(event_type == GNOME_VFS_MONITOR_EVENT_CHANGED ||
246 event_type == GNOME_VFS_MONITOR_EVENT_CREATED))
247 return;
249 if (!anjuta_util_diff (anjuta_document_get_uri(sv->priv->document), sv->priv->last_saved_content))
251 return;
255 if (strcmp (monitor_uri, info_uri) != 0)
256 return;
258 on_sourceview_uri_changed_prompt(sv);
261 static gboolean
262 sourceview_add_monitor(Sourceview* sv)
264 gboolean monitor_enabled = anjuta_preferences_get_int (sv->priv->prefs, MONITOR_KEY);
266 if (monitor_enabled)
268 gchar* uri;
269 g_return_val_if_fail(sv->priv->monitor == NULL, FALSE);
270 DEBUG_PRINT ("Monitor added for %s", anjuta_document_get_uri(sv->priv->document));
271 uri = anjuta_document_get_uri(sv->priv->document);
272 gnome_vfs_monitor_add(&sv->priv->monitor, uri,
273 GNOME_VFS_MONITOR_FILE,
274 on_sourceview_uri_changed, sv);
275 g_free (uri);
277 return FALSE; /* for g_idle_add */
280 /* Called when document is loaded completly */
281 static void on_document_loaded(AnjutaDocument* doc, GError* err, Sourceview* sv)
283 const gchar *lang;
284 if (err)
286 anjuta_util_dialog_error(NULL,
287 "Could not open file: %s", err->message);
289 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(doc), FALSE);
290 g_signal_emit_by_name(G_OBJECT(sv), "save_point",
291 TRUE);
293 if (sv->priv->goto_line > 0)
295 anjuta_document_goto_line(doc, LOCATION_TO_LINE (sv->priv->goto_line));
296 sv->priv->goto_line = -1;
298 anjuta_view_scroll_to_cursor(sv->priv->view);
299 sv->priv->loading = FALSE;
301 sourceview_add_monitor(sv);
303 /* Autodetect language */
304 ianjuta_editor_language_set_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL, NULL);
306 lang = ianjuta_editor_language_get_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL);
307 g_signal_emit_by_name (sv, "language-changed", lang);
309 /* Get rid of reference from ifile_open */
310 g_object_unref(G_OBJECT(sv));
313 /* Show nice progress bar */
314 static void on_document_loading(AnjutaDocument *document,
315 GnomeVFSFileSize size,
316 GnomeVFSFileSize total_size,
317 Sourceview* sv)
319 AnjutaShell* shell;
320 AnjutaStatus* status;
322 g_object_get(G_OBJECT(sv->priv->plugin), "shell", &shell, NULL);
323 status = anjuta_shell_get_status(shell, NULL);
325 if (!sv->priv->loading)
327 gint procentage = 0;
328 if (size)
329 procentage = total_size/size;
330 anjuta_status_progress_add_ticks(status,procentage + 1);
331 sv->priv->loading = TRUE;
333 anjuta_status_progress_tick(status, NULL, _("Loading"));
336 /* Show nice progress bar */
337 static void on_document_saving(AnjutaDocument *document,
338 GnomeVFSFileSize size,
339 GnomeVFSFileSize total_size,
340 Sourceview* sv)
342 AnjutaShell* shell;
343 AnjutaStatus* status;
345 g_object_get(G_OBJECT(sv->priv->plugin), "shell", &shell, NULL);
346 status = anjuta_shell_get_status(shell, NULL);
348 if (!sv->priv->saving)
350 gint procentage = 0;
351 if (size)
352 procentage = total_size/size;
353 anjuta_status_progress_add_ticks(status,procentage + 1);
354 sv->priv->saving = TRUE;
356 anjuta_status_progress_tick(status, NULL, _("Saving..."));
359 static gboolean save_if_modified(AnjutaDocument* doc, GtkWindow* parent)
361 GtkWidget* dialog = gtk_message_dialog_new(parent,
362 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
363 _("The file %s was modified by another application. Save it anyway?"), anjuta_document_get_uri_for_display(doc));
364 int result = gtk_dialog_run(GTK_DIALOG(dialog));
365 gtk_widget_destroy(dialog);
366 switch (result)
368 case GTK_RESPONSE_YES:
370 return TRUE;
372 default:
373 return FALSE;
377 /* Need to avoid crash when unref is done before add_monitor */
378 static gboolean timeout_unref(Sourceview* sv)
380 g_object_unref(G_OBJECT(sv));
381 return FALSE;
384 /* Called when document is saved completly */
385 static void on_document_saved(AnjutaDocument* doc, GError* err, Sourceview* sv)
387 if (err)
389 switch(err->code)
391 case ANJUTA_DOCUMENT_ERROR_EXTERNALLY_MODIFIED:
393 if (save_if_modified(doc, GTK_WINDOW(sv->priv->plugin->shell)))
395 anjuta_document_save(doc, ANJUTA_DOCUMENT_SAVE_IGNORE_MTIME);
397 break;
399 default:
401 anjuta_util_dialog_error(NULL,
402 "Could not save file %s: %s",anjuta_document_get_uri_for_display(doc), err->message);
403 break;
407 else
409 const gchar* lang;
410 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(doc), FALSE);
411 g_signal_emit_by_name(G_OBJECT(sv), "save_point", TRUE);
412 /* Set up 2 sec timer */
413 if (sv->priv->monitor_delay > 0)
414 g_source_remove (sv->priv->monitor_delay);
415 sv->priv->monitor_delay = g_timeout_add (2000,
416 (GSourceFunc)sourceview_add_monitor, sv);
417 sv->priv->saving = FALSE;
418 /* Autodetect language */
419 ianjuta_editor_language_set_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL, NULL);
420 lang = ianjuta_editor_language_get_language(IANJUTA_EDITOR_LANGUAGE(sv), NULL);
421 g_signal_emit_by_name (sv, "language-changed", lang);
423 g_timeout_add(3000, (GSourceFunc)timeout_unref, sv);
426 static void
427 sourceview_adjustment_changed(GtkAdjustment* ad, Sourceview* sv)
429 /* Hide assistance windows when scrolling vertically */
431 if (sv->priv->assist_win)
432 gtk_widget_destroy (GTK_WIDGET (sv->priv->assist_win));
433 if (sv->priv->assist_tip)
434 gtk_widget_destroy (GTK_WIDGET (sv->priv->assist_tip));
437 static void
438 sourceview_instance_init(Sourceview* sv)
440 sv->priv = g_slice_new0 (SourceviewPrivate);
443 static void
444 sourceview_class_init(SourceviewClass *klass)
446 GObjectClass *object_class = G_OBJECT_CLASS(klass);
448 parent_class = g_type_class_peek_parent(klass);
449 object_class->dispose = sourceview_dispose;
450 object_class->finalize = sourceview_finalize;
452 /* Create signals here:
453 sourceview_signals[SIGNAL_TYPE_EXAMPLE] = g_signal_new(...)
457 static void
458 sourceview_dispose(GObject *object)
460 Sourceview *cobj = ANJUTA_SOURCEVIEW(object);
461 GSList* node;
462 if (cobj->priv->assist_win)
463 on_assist_cancel(cobj->priv->assist_win, cobj);
464 if (cobj->priv->assist_tip)
465 gtk_widget_destroy(GTK_WIDGET(cobj->priv->assist_tip));
467 for (node = cobj->priv->idle_sources; node != NULL; node = g_slist_next (node))
469 g_source_remove (GPOINTER_TO_UINT (node->data));
471 g_slist_free (cobj->priv->idle_sources);
473 G_OBJECT_CLASS (parent_class)->dispose (object);
476 static void
477 sourceview_finalize(GObject *object)
479 Sourceview *cobj;
480 cobj = ANJUTA_SOURCEVIEW(object);
482 sourceview_remove_monitor(cobj);
483 sourceview_prefs_destroy(cobj);
485 g_object_unref(cobj->priv->view);
487 g_slice_free(SourceviewPrivate, cobj->priv);
488 G_OBJECT_CLASS(parent_class)->finalize(object);
489 DEBUG_PRINT("=========== finalise =============");
492 /* Sync with IANJUTA_MARKABLE_MARKER */
494 #define MARKER_PIXMAP_LINEMARKER "anjuta-linemark-16.png"
495 #define MARKER_PIXMAP_PROGRAM_COUNTER "anjuta-pcmark-16.png"
496 #define MARKER_PIXMAP_BREAKPOINT_DISABLED "anjuta-breakpoint-disabled-16.png"
497 #define MARKER_PIXMAP_BREAKPOINT_ENABLED "anjuta-breakpoint-enabled-16.png"
498 #define MARKER_PIXMAP_BOOKMARK "anjuta-bookmark-16.png"
501 /* Keep in sync with IAnjutaMarkableMarker */
503 static const gchar* marker_types [] =
505 "sv-linemarker",
506 "sv-bookmark",
507 "sv-breakpoint-enabled",
508 "sv-breakpoint-disabled",
509 "sv-program-counter",
510 NULL
513 /* HIGHLIGHTED TAGS */
515 #define IMPORTANT_INDIC "important_indic"
516 #define WARNING_INDIC "warning_indic"
517 #define CRITICAL_INDIC "critical_indic"
519 /* Create pixmaps for the markers */
520 static void sourceview_create_markers(Sourceview* sv)
522 GdkPixbuf * pixbuf;
523 GtkSourceView* view = GTK_SOURCE_VIEW(sv->priv->view);
526 if ((pixbuf = gdk_pixbuf_new_from_file (PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BOOKMARK, NULL)))
528 gtk_source_view_set_mark_category_pixbuf (view,
529 marker_types[IANJUTA_MARKABLE_BOOKMARK], pixbuf);
530 gtk_source_view_set_mark_category_priority (view, marker_types [IANJUTA_MARKABLE_BOOKMARK],
531 IANJUTA_MARKABLE_BOOKMARK);
532 g_object_unref (pixbuf);
534 if ((pixbuf = gdk_pixbuf_new_from_file (PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BREAKPOINT_DISABLED, NULL)))
536 gtk_source_view_set_mark_category_pixbuf (view,
537 marker_types[IANJUTA_MARKABLE_BREAKPOINT_DISABLED], pixbuf);
538 gtk_source_view_set_mark_category_priority (view, marker_types [IANJUTA_MARKABLE_BREAKPOINT_DISABLED],
539 IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
541 g_object_unref (pixbuf);
543 if ((pixbuf = gdk_pixbuf_new_from_file (PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_BREAKPOINT_ENABLED, NULL)))
545 gtk_source_view_set_mark_category_pixbuf (view,
546 marker_types[IANJUTA_MARKABLE_BREAKPOINT_ENABLED], pixbuf);
547 gtk_source_view_set_mark_category_priority (view, marker_types [IANJUTA_MARKABLE_BREAKPOINT_ENABLED],
548 IANJUTA_MARKABLE_BREAKPOINT_ENABLED);
549 g_object_unref (pixbuf);
551 if ((pixbuf = gdk_pixbuf_new_from_file (PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_PROGRAM_COUNTER, NULL)))
553 gtk_source_view_set_mark_category_pixbuf (view,
554 marker_types[IANJUTA_MARKABLE_PROGRAM_COUNTER], pixbuf);
555 gtk_source_view_set_mark_category_priority (view, marker_types [IANJUTA_MARKABLE_PROGRAM_COUNTER],
556 IANJUTA_MARKABLE_PROGRAM_COUNTER);
557 g_object_unref (pixbuf);
559 if ((pixbuf = gdk_pixbuf_new_from_file (PACKAGE_PIXMAPS_DIR"/"MARKER_PIXMAP_LINEMARKER, NULL)))
561 gtk_source_view_set_mark_category_pixbuf (view,
562 marker_types[IANJUTA_MARKABLE_LINEMARKER], pixbuf);
563 gtk_source_view_set_mark_category_priority (view, marker_types [IANJUTA_MARKABLE_LINEMARKER],
564 IANJUTA_MARKABLE_LINEMARKER);
565 g_object_unref (pixbuf);
569 /* Create tags for highlighting */
570 static void sourceview_create_highligth_indic(Sourceview* sv)
572 sv->priv->important_indic =
573 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
574 IMPORTANT_INDIC,
575 "background", "#FFFF00", NULL);
576 sv->priv->warning_indic =
577 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
578 WARNING_INDIC,
579 "foreground", "#00FF00", NULL);
580 sv->priv->critical_indic =
581 gtk_text_buffer_create_tag (GTK_TEXT_BUFFER(sv->priv->document),
582 CRITICAL_INDIC,
583 "foreground", "#FF0000", "underline",
584 PANGO_UNDERLINE_ERROR, NULL);
588 /* Create a new sourceview instance. If uri is valid,
589 the file will be loaded in the buffer */
591 Sourceview *
592 sourceview_new(const gchar* uri, const gchar* filename, AnjutaPlugin* plugin)
594 AnjutaShell* shell;
595 GtkAdjustment* v_adj;
597 Sourceview *sv = ANJUTA_SOURCEVIEW(g_object_new(ANJUTA_TYPE_SOURCEVIEW, NULL));
599 /* Create buffer */
600 sv->priv->document = anjuta_document_new();
601 g_signal_connect_after(G_OBJECT(sv->priv->document), "modified-changed",
602 G_CALLBACK(on_document_modified_changed), sv);
603 g_signal_connect_after(G_OBJECT(sv->priv->document), "cursor-moved",
604 G_CALLBACK(on_cursor_moved),sv);
605 g_signal_connect_after(G_OBJECT(sv->priv->document), "loaded",
606 G_CALLBACK(on_document_loaded), sv);
607 g_signal_connect(G_OBJECT(sv->priv->document), "loading",
608 G_CALLBACK(on_document_loading), sv);
609 g_signal_connect_after(G_OBJECT(sv->priv->document), "saved",
610 G_CALLBACK(on_document_saved), sv);
611 g_signal_connect(G_OBJECT(sv->priv->document), "saving",
612 G_CALLBACK(on_document_saving), sv);
613 g_signal_connect_after (G_OBJECT(sv->priv->document), "insert-text",
614 G_CALLBACK(on_insert_text), sv);
616 /* Create View instance */
617 sv->priv->view = ANJUTA_VIEW(anjuta_view_new(sv));
618 #if HAVE_TOOLTIP_API
619 g_signal_connect (G_OBJECT(sv->priv->view), "query-tooltip",
620 G_CALLBACK (on_sourceview_hover_over), sv);
621 g_object_set (G_OBJECT (sv->priv->view), "has-tooltip", TRUE, NULL);
622 #endif
623 gtk_source_view_set_smart_home_end(GTK_SOURCE_VIEW(sv->priv->view), FALSE);
624 g_object_ref(sv->priv->view);
626 /* VFS monitor */
627 sv->priv->last_saved_content = NULL;
629 /* Apply Preferences */
630 g_object_get(G_OBJECT(plugin), "shell", &shell, NULL);
631 sv->priv->prefs = anjuta_shell_get_preferences(shell, NULL);
632 sourceview_prefs_init(sv);
633 sv->priv->plugin = plugin;
635 /* Create Markers */
636 sourceview_create_markers(sv);
638 /* Add View */
639 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sv),
640 GTK_POLICY_AUTOMATIC,
641 GTK_POLICY_AUTOMATIC);
642 gtk_container_add(GTK_CONTAINER(sv), GTK_WIDGET(sv->priv->view));
643 gtk_widget_show_all(GTK_WIDGET(sv));
644 v_adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sv));
645 g_signal_connect (v_adj, "value-changed", G_CALLBACK (sourceview_adjustment_changed), sv);
647 if (uri != NULL && strlen(uri) > 0)
649 ianjuta_file_open(IANJUTA_FILE(sv), uri, NULL);
651 else if (filename != NULL && strlen(filename) > 0)
652 sv->priv->filename = g_strdup(filename);
654 /* Create Higlight Tag */
655 sourceview_create_highligth_indic(sv);
657 DEBUG_PRINT("============ Creating new editor =============");
659 return sv;
662 /* IAnjutaFile interface */
664 /* Open uri in Editor */
665 static void
666 ifile_open (IAnjutaFile* file, const gchar *uri, GError** e)
668 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
669 sourceview_remove_monitor(sv);
670 /* Hold a reference here to avoid a destroyed editor */
671 g_object_ref(G_OBJECT(sv));
672 anjuta_document_load(sv->priv->document, uri, NULL,
673 -1, FALSE);
676 /* Return the currently loaded uri */
678 static gchar*
679 ifile_get_uri (IAnjutaFile* file, GError** e)
681 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
682 return anjuta_document_get_uri(sv->priv->document);
685 /* IAnjutaFileSavable interface */
687 /* Save file */
688 static void
689 ifile_savable_save (IAnjutaFileSavable* file, GError** e)
691 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
692 sourceview_remove_monitor(sv);
694 g_object_ref(G_OBJECT(sv));
695 anjuta_document_save(sv->priv->document, 0);
698 /* Save file as */
699 static void
700 ifile_savable_save_as (IAnjutaFileSavable* file, const gchar *uri, GError** e)
702 GtkTextIter start_iter;
703 GtkTextIter end_iter;
704 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
705 sourceview_remove_monitor(sv);
706 /* TODO: Set correct encoding */
707 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(sv->priv->document),
708 &start_iter, &end_iter);
709 g_free(sv->priv->last_saved_content);
710 sv->priv->last_saved_content = gtk_text_buffer_get_slice (
711 GTK_TEXT_BUFFER(sv->priv->document),
712 &start_iter, &end_iter, TRUE);
713 g_object_ref(G_OBJECT(sv));
714 anjuta_document_save_as(sv->priv->document,
715 uri, anjuta_encoding_get_current(), 0);
716 if (sv->priv->filename)
718 g_free(sv->priv->filename);
719 sv->priv->filename = NULL;
723 static void
724 ifile_savable_set_dirty (IAnjutaFileSavable* file, gboolean dirty, GError** e)
726 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
727 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(sv->priv->document),
728 dirty);
731 static gboolean
732 ifile_savable_is_dirty (IAnjutaFileSavable* file, GError** e)
734 Sourceview* sv = ANJUTA_SOURCEVIEW(file);
735 return gtk_text_buffer_get_modified(GTK_TEXT_BUFFER(sv->priv->document));
738 static void
739 isavable_iface_init (IAnjutaFileSavableIface *iface)
741 iface->save = ifile_savable_save;
742 iface->save_as = ifile_savable_save_as;
743 iface->set_dirty = ifile_savable_set_dirty;
744 iface->is_dirty = ifile_savable_is_dirty;
747 static void
748 ifile_iface_init (IAnjutaFileIface *iface)
750 iface->open = ifile_open;
751 iface->get_uri = ifile_get_uri;
754 /* IAnjutaEditor interface */
756 static gint
757 ieditor_get_tab_size (IAnjutaEditor *editor, GError **e)
759 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
760 return gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (sv->priv->view));
763 static void
764 ieditor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
766 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
767 gtk_source_view_set_tab_width(GTK_SOURCE_VIEW(sv->priv->view), tabsize);
768 gtk_source_view_set_indent_width (GTK_SOURCE_VIEW (sv->priv->view), tabsize);
771 static gboolean
772 ieditor_get_use_spaces (IAnjutaEditor *editor, GError **e)
774 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
775 return gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW(sv->priv->view));
778 static void
779 ieditor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
781 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
782 gtk_source_view_set_insert_spaces_instead_of_tabs(GTK_SOURCE_VIEW(sv->priv->view),
783 use_spaces);
786 static void
787 ieditor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
789 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
790 gtk_source_view_set_auto_indent(GTK_SOURCE_VIEW(sv->priv->view),
791 auto_indent);
795 /* Scroll to line */
796 static void ieditor_goto_line(IAnjutaEditor *editor, gint line, GError **e)
798 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
800 if (!sv->priv->loading)
802 anjuta_document_goto_line(sv->priv->document, LOCATION_TO_LINE (line));
803 anjuta_view_scroll_to_cursor(sv->priv->view);
805 else
806 sv->priv->goto_line = line;
809 /* Scroll to position */
810 static void ieditor_goto_position(IAnjutaEditor *editor, IAnjutaIterable* icell,
811 GError **e)
813 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
814 GtkTextIter* iter = sourceview_cell_get_iter (cell);
815 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
816 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), iter);
817 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
818 iter, 0, FALSE, 0, 0);
821 /* Return a newly allocated pointer containing the whole text */
822 static gchar* ieditor_get_text (IAnjutaEditor* editor,
823 IAnjutaIterable* start,
824 IAnjutaIterable* end, GError **e)
826 GtkTextIter* start_iter;
827 GtkTextIter* end_iter;
828 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
830 start_iter = sourceview_cell_get_iter (SOURCEVIEW_CELL (start));
831 end_iter = sourceview_cell_get_iter (SOURCEVIEW_CELL (end));
833 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
834 start_iter, end_iter, TRUE);
837 static gchar*
838 ieditor_get_text_all (IAnjutaEditor* edit, GError **e)
840 GtkTextIter start_iter;
841 GtkTextIter end_iter;
842 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
843 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
845 gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, 0);
846 gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, -1);
848 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
849 &start_iter, &end_iter, TRUE);
852 /* Get cursor position */
853 static IAnjutaIterable*
854 ieditor_get_position (IAnjutaEditor* editor, GError **e)
856 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
857 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
858 GtkTextIter iter;
859 SourceviewCell* cell;
861 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
862 gtk_text_buffer_get_insert(buffer));
864 cell = sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view));
866 return IANJUTA_ITERABLE (cell);
869 static gint
870 ieditor_get_offset (IAnjutaEditor* editor, GError **e)
872 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
873 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
874 GtkTextIter iter;
876 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
877 gtk_text_buffer_get_insert(buffer));
879 return gtk_text_iter_get_offset (&iter);
882 /* Return line of cursor */
883 static gint ieditor_get_lineno(IAnjutaEditor *editor, GError **e)
885 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
886 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
887 GtkTextIter iter;
889 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
890 gtk_text_buffer_get_insert(buffer));
891 return gtk_text_iter_get_line(&iter) + 1;
894 /* Return the length of the text in the buffer */
895 static gint ieditor_get_length(IAnjutaEditor *editor, GError **e)
897 /* We do not use gtk_text_buffer_get_char_count here because
898 someone may rely that this is the size of a buffer for all the text */
900 GtkTextIter start_iter;
901 GtkTextIter end_iter;
902 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
903 gchar* text;
904 gint length;
906 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(sv->priv->document),
907 &start_iter);
908 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(sv->priv->document),
909 &end_iter);
910 text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
911 &start_iter, &end_iter, TRUE);
912 length = g_utf8_strlen(text, -1);
913 g_free(text);
915 return length;
918 /* Return word on cursor position */
919 static gchar* ieditor_get_current_word(IAnjutaEditor *editor, GError **e)
921 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
922 return anjuta_document_get_current_word(sv->priv->document, FALSE);
925 /* Insert text at position */
926 static void ieditor_insert(IAnjutaEditor *editor, IAnjutaIterable* icell,
927 const gchar* text, gint length, GError **e)
929 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
930 GtkTextIter* iter = sourceview_cell_get_iter (cell);
931 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
933 g_signal_handlers_block_by_func (sv->priv->document,
934 on_insert_text,
935 sv);
936 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
937 iter, text, length);
938 g_signal_handlers_unblock_by_func (sv->priv->document,
939 on_insert_text,
940 sv);
943 /* Append text to buffer */
944 static void ieditor_append(IAnjutaEditor *editor, const gchar* text,
945 gint length, GError **e)
947 GtkTextIter iter;
948 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
950 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(sv->priv->document),
951 &iter);
952 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
953 &iter, text, length);
956 static void ieditor_erase(IAnjutaEditor* editor, IAnjutaIterable* istart_cell,
957 IAnjutaIterable* iend_cell, GError **e)
959 SourceviewCell* start_cell = SOURCEVIEW_CELL (istart_cell);
960 GtkTextIter* start = sourceview_cell_get_iter (start_cell);
961 SourceviewCell* end_cell = SOURCEVIEW_CELL (iend_cell);
962 GtkTextIter* end = sourceview_cell_get_iter (end_cell);
963 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
964 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
966 gtk_text_buffer_delete (buffer, start, end);
969 static void ieditor_erase_all(IAnjutaEditor *editor, GError **e)
971 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
972 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(sv->priv->document), "", 0);
975 /* Return column of cursor */
976 static gint ieditor_get_column(IAnjutaEditor *editor, GError **e)
978 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
979 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
980 GtkTextIter iter;
982 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
983 gtk_text_buffer_get_insert(buffer));
984 return gtk_text_iter_get_line_offset(&iter);
987 /* Return TRUE if editor is in overwrite mode */
988 static gboolean ieditor_get_overwrite(IAnjutaEditor *editor, GError **e)
990 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
991 return gtk_text_view_get_overwrite(GTK_TEXT_VIEW(sv->priv->view));
995 /* Set the editor popup menu */
996 static void ieditor_set_popup_menu(IAnjutaEditor *editor,
997 GtkWidget* menu, GError **e)
999 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1000 g_object_set(G_OBJECT(sv->priv->view), "popup", menu, NULL);
1003 /* Convert from position to line */
1004 static gint ieditor_get_line_from_position(IAnjutaEditor *editor,
1005 IAnjutaIterable* icell, GError **e)
1007 SourceviewCell* cell = SOURCEVIEW_CELL (icell);
1008 GtkTextIter* iter = sourceview_cell_get_iter (cell);
1009 return LINE_TO_LOCATION (gtk_text_iter_get_line(iter));
1012 static IAnjutaIterable* ieditor_get_line_begin_position(IAnjutaEditor *editor,
1013 gint line, GError **e)
1015 GtkTextIter iter;
1016 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1018 gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER(sv->priv->document),
1019 &iter, LOCATION_TO_LINE (line), 0);
1020 return IANJUTA_ITERABLE (sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view)));
1023 static IAnjutaIterable* ieditor_get_line_end_position(IAnjutaEditor *editor,
1024 gint line, GError **e)
1026 GtkTextIter iter;
1027 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1029 gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER(sv->priv->document),
1030 &iter, LOCATION_TO_LINE (line), 0);
1031 /* If iter is not at line end, move it */
1032 if (!gtk_text_iter_ends_line(&iter))
1033 gtk_text_iter_forward_to_line_end (&iter);
1034 return IANJUTA_ITERABLE (sourceview_cell_new (&iter, GTK_TEXT_VIEW (sv->priv->view)));
1037 static IAnjutaIterable*
1038 ieditor_get_position_from_offset(IAnjutaEditor* edit, gint position, GError** e)
1040 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1041 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1042 GtkTextIter iter;
1043 SourceviewCell* cell;
1045 gtk_text_buffer_get_iter_at_offset(buffer, &iter, position);
1046 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1048 return IANJUTA_ITERABLE(cell);
1051 static IAnjutaIterable*
1052 ieditor_get_start_position (IAnjutaEditor* edit, GError** e)
1054 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1055 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1056 GtkTextIter iter;
1057 SourceviewCell* cell;
1059 gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
1060 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1062 return IANJUTA_ITERABLE(cell);
1065 static IAnjutaIterable*
1066 ieditor_get_end_position (IAnjutaEditor* edit, GError** e)
1068 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1069 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1070 GtkTextIter iter;
1071 SourceviewCell* cell;
1073 gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1);
1074 cell = sourceview_cell_new(&iter, GTK_TEXT_VIEW(sv->priv->view));
1076 return IANJUTA_ITERABLE(cell);
1079 static void
1080 ieditor_goto_start (IAnjutaEditor* edit, GError** e)
1082 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1083 GtkTextIter iter;
1084 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document),
1085 &iter, 0);
1086 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), &iter);
1087 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
1088 &iter, 0, FALSE, 0, 0);
1091 static void
1092 ieditor_goto_end (IAnjutaEditor* edit, GError** e)
1094 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1095 GtkTextIter iter;
1096 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (sv->priv->document),
1097 &iter, -1);
1098 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (sv->priv->document), &iter);
1099 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
1100 &iter, 0, FALSE, 0, 0);
1103 static void
1104 ieditor_iface_init (IAnjutaEditorIface *iface)
1106 iface->get_tabsize = ieditor_get_tab_size;
1107 iface->set_tabsize = ieditor_set_tab_size;
1108 iface->get_use_spaces = ieditor_get_use_spaces;
1109 iface->set_use_spaces = ieditor_set_use_spaces;
1110 iface->set_auto_indent = ieditor_set_auto_indent;
1111 iface->goto_line = ieditor_goto_line;
1112 iface->goto_position = ieditor_goto_position;
1113 iface->get_text = ieditor_get_text;
1114 iface->get_text_all = ieditor_get_text_all;
1115 iface->get_position = ieditor_get_position;
1116 iface->get_offset = ieditor_get_offset;
1117 iface->get_lineno = ieditor_get_lineno;
1118 iface->get_length = ieditor_get_length;
1119 iface->get_current_word = ieditor_get_current_word;
1120 iface->insert = ieditor_insert;
1121 iface->append = ieditor_append;
1122 iface->erase = ieditor_erase;
1123 iface->erase_all = ieditor_erase_all;
1124 iface->get_column = ieditor_get_column;
1125 iface->get_overwrite = ieditor_get_overwrite;
1126 iface->set_popup_menu = ieditor_set_popup_menu;
1127 iface->get_line_from_position = ieditor_get_line_from_position;
1128 iface->get_line_begin_position = ieditor_get_line_begin_position;
1129 iface->get_line_end_position = ieditor_get_line_end_position;
1130 iface->goto_start = ieditor_goto_start;
1131 iface->goto_end = ieditor_goto_end;
1132 iface->get_position_from_offset = ieditor_get_position_from_offset;
1133 iface->get_start_position = ieditor_get_start_position;
1134 iface->get_end_position = ieditor_get_end_position;
1137 /* Return true if editor can redo */
1138 static gboolean idocument_can_redo(IAnjutaDocument *editor, GError **e)
1140 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1141 return gtk_source_buffer_can_redo(GTK_SOURCE_BUFFER(sv->priv->document));
1144 /* Return true if editor can undo */
1145 static gboolean idocument_can_undo(IAnjutaDocument *editor, GError **e)
1147 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1148 return gtk_source_buffer_can_undo(GTK_SOURCE_BUFFER(sv->priv->document));
1151 /* Return true if editor can undo */
1152 static void idocument_begin_undo_action (IAnjutaDocument *editor, GError **e)
1154 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1155 gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER(sv->priv->document));
1158 /* Return true if editor can undo */
1159 static void idocument_end_undo_action (IAnjutaDocument *editor, GError **e)
1161 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1162 gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER(sv->priv->document));
1166 static void
1167 idocument_undo(IAnjutaDocument* edit, GError** ee)
1169 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1170 if (idocument_can_undo(edit, NULL))
1171 gtk_source_buffer_undo(GTK_SOURCE_BUFFER(sv->priv->document));
1172 anjuta_view_scroll_to_cursor(sv->priv->view);
1173 g_signal_emit_by_name(G_OBJECT(sv), "update_ui", sv);
1176 static void
1177 idocument_redo(IAnjutaDocument* edit, GError** ee)
1179 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1180 if (idocument_can_redo(edit, NULL))
1181 gtk_source_buffer_redo(GTK_SOURCE_BUFFER(sv->priv->document));
1182 anjuta_view_scroll_to_cursor(sv->priv->view);
1185 /* Grab focus */
1186 static void idocument_grab_focus (IAnjutaDocument *editor, GError **e)
1188 gtk_widget_grab_focus (GTK_WIDGET (ANJUTA_SOURCEVIEW (editor)->priv->view));
1191 /* Return the opened filename */
1192 static const gchar* idocument_get_filename(IAnjutaDocument *editor, GError **e)
1194 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1195 if (sv->priv->filename == NULL)
1196 sv->priv->filename = anjuta_document_get_short_name_for_display(sv->priv->document);
1197 return sv->priv->filename;
1200 static void
1201 idocument_cut(IAnjutaDocument* edit, GError** ee)
1203 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1204 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1205 anjuta_view_cut_clipboard(sv->priv->view);
1206 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1209 static void
1210 idocument_copy(IAnjutaDocument* edit, GError** ee)
1212 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1213 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1214 anjuta_view_copy_clipboard(sv->priv->view);
1215 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1218 static void
1219 idocument_paste(IAnjutaDocument* edit, GError** ee)
1221 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1222 g_signal_handlers_block_by_func (sv->priv->document, on_insert_text, sv);
1223 anjuta_view_paste_clipboard(sv->priv->view);
1224 g_signal_handlers_unblock_by_func (sv->priv->document, on_insert_text, sv);
1227 static void
1228 idocument_clear(IAnjutaDocument* edit, GError** ee)
1230 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1231 if (gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(sv->priv->document)))
1232 anjuta_view_delete_selection(sv->priv->view);
1233 else
1235 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1236 GtkTextIter cursor;
1237 gtk_text_buffer_get_iter_at_mark(buffer, &cursor, gtk_text_buffer_get_insert(buffer));
1239 /* Fix #388731 */
1240 gtk_text_iter_forward_char(&cursor);
1241 gtk_text_buffer_backspace(buffer, &cursor, TRUE, TRUE);
1245 static void
1246 idocument_iface_init (IAnjutaDocumentIface *iface)
1248 iface->grab_focus = idocument_grab_focus;
1249 iface->get_filename = idocument_get_filename;
1250 iface->can_undo = idocument_can_undo;
1251 iface->can_redo = idocument_can_redo;
1252 iface->begin_undo_action = idocument_begin_undo_action;
1253 iface->end_undo_action = idocument_end_undo_action;
1254 iface->undo = idocument_undo;
1255 iface->redo = idocument_redo;
1256 iface->cut = idocument_cut;
1257 iface->copy = idocument_copy;
1258 iface->paste = idocument_paste;
1259 iface->clear = idocument_clear;
1262 static void
1263 set_select(Sourceview* sv, GtkTextIter* start_iter, GtkTextIter* end_iter)
1265 gtk_text_buffer_select_range (GTK_TEXT_BUFFER (sv->priv->document), start_iter, end_iter);
1266 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(sv->priv->view),
1267 gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(sv->priv->document)));
1270 /* IAnjutaEditorSelection */
1272 // TODO: Move these to ilanguage-support?
1273 static void
1274 iselect_to_brace(IAnjutaEditorSelection* edit, GError** e)
1279 static void
1280 iselect_block(IAnjutaEditorSelection* edit, GError** e)
1282 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1283 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1284 GtkTextIter start_iter;
1285 GtkTextIter end_iter;
1286 GtkTextIter iter;
1287 gchar *text;
1288 gint position;
1290 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(sv->priv->document),
1291 &start_iter);
1292 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(sv->priv->document),
1293 &end_iter);
1294 text = gtk_text_buffer_get_slice
1295 (GTK_TEXT_BUFFER(sv->priv->document),
1296 &start_iter, &end_iter, TRUE);
1297 if (text)
1299 gboolean found = FALSE;
1300 gint cpt = 0;
1301 gtk_text_buffer_get_iter_at_mark(buffer, &iter,
1302 gtk_text_buffer_get_insert(buffer));
1303 position = gtk_text_iter_get_offset(&iter);
1305 while((--position >= 0) && !found)
1307 if (text[position] == '{')
1308 if (cpt-- == 0)
1309 found = TRUE;
1310 if (text[position] == '}')
1311 cpt++;
1313 if (found)
1315 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(sv->priv->document),
1316 &start_iter, position + 2);
1317 gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(sv->priv->document),
1318 &start_iter);
1319 end_iter = start_iter;
1320 found = FALSE;
1321 //found = gtk_source_iter_find_matching_bracket (&end_iter);
1322 if (found)
1323 set_select(sv, &start_iter, &end_iter);
1325 g_free(text);
1330 static void
1331 iselect_set (IAnjutaEditorSelection* edit,
1332 IAnjutaIterable* istart,
1333 IAnjutaIterable* iend,
1334 GError** e)
1336 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1337 gtk_text_buffer_select_range (GTK_TEXT_BUFFER (sv->priv->document),
1338 sourceview_cell_get_iter (SOURCEVIEW_CELL (istart)),
1339 sourceview_cell_get_iter (SOURCEVIEW_CELL (iend)));
1340 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (sv->priv->view),
1341 sourceview_cell_get_iter (SOURCEVIEW_CELL (istart)),
1342 0, FALSE, 0, 0);
1346 static void
1347 iselect_all(IAnjutaEditorSelection* edit, GError** e)
1349 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1350 anjuta_view_select_all(sv->priv->view);
1353 static gboolean
1354 iselect_has_selection (IAnjutaEditorSelection *editor, GError **e)
1356 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1358 return gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(sv->priv->document));
1361 /* Return a newly allocated pointer containing selected text or
1362 NULL if no text is selected */
1363 static gchar* iselect_get(IAnjutaEditorSelection* editor, GError **e)
1365 GtkTextIter start_iter;
1366 GtkTextIter end_iter;
1367 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1369 if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(sv->priv->document),
1370 &start_iter, &end_iter))
1372 return gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(sv->priv->document),
1373 &start_iter, &end_iter, TRUE);
1375 else
1376 return NULL;
1380 static IAnjutaIterable*
1381 iselect_get_start (IAnjutaEditorSelection *edit, GError **e)
1383 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1384 GtkTextIter start;
1385 if (gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (sv->priv->document),
1386 &start, NULL))
1388 return IANJUTA_ITERABLE (sourceview_cell_new (&start, GTK_TEXT_VIEW (sv->priv->view)));
1390 return NULL;
1393 static IAnjutaIterable*
1394 iselect_get_end (IAnjutaEditorSelection *edit, GError **e)
1396 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1397 GtkTextIter end;
1398 if (gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (sv->priv->document),
1399 NULL, &end))
1401 return IANJUTA_ITERABLE (sourceview_cell_new (&end, GTK_TEXT_VIEW (sv->priv->view)));
1403 return NULL;
1407 static void iselect_function(IAnjutaEditorSelection *editor, GError **e)
1409 // TODO
1412 /* If text is selected, replace with given text */
1413 static void iselect_replace(IAnjutaEditorSelection* editor,
1414 const gchar* text, gint length, GError **e)
1416 GtkTextIter start_iter;
1417 GtkTextIter end_iter;
1418 GtkTextIter iter;
1419 Sourceview* sv = ANJUTA_SOURCEVIEW(editor);
1420 gint position;
1422 if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(sv->priv->document),
1423 &start_iter, &end_iter))
1425 position = gtk_text_iter_get_offset(&start_iter);
1426 gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(sv->priv->document),
1427 FALSE, TRUE);
1428 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(sv->priv->document),
1429 &iter, position);
1430 gtk_text_buffer_insert(GTK_TEXT_BUFFER(sv->priv->document),
1431 &iter, text, length);
1435 static void
1436 iselect_iface_init(IAnjutaEditorSelectionIface *iface)
1438 iface->set = iselect_set;
1439 iface->has_selection = iselect_has_selection;
1440 iface->get_start = iselect_get_start;
1441 iface->get_end = iselect_get_end;
1442 iface->select_block = iselect_block;
1443 iface->select_function = iselect_function;
1444 iface->select_all = iselect_all;
1445 iface->select_to_brace = iselect_to_brace;
1446 iface->select_block = iselect_block;
1447 iface->get = iselect_get;
1448 iface->replace = iselect_replace;
1451 /* IAnjutaEditorConvert Interface */
1453 static void
1454 iconvert_to_upper(IAnjutaEditorConvert* edit, IAnjutaIterable *start_position,
1455 IAnjutaIterable *end_position, GError** e)
1457 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1458 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1459 GtkTextIter* start = sourceview_cell_get_iter (SOURCEVIEW_CELL (start_position));
1460 GtkTextIter* end = sourceview_cell_get_iter (SOURCEVIEW_CELL (end_position));
1462 gchar* text_buffer = gtk_text_buffer_get_text (buffer,
1463 start, end, TRUE);
1464 gtk_text_buffer_begin_user_action (buffer);
1465 gtk_text_buffer_delete (buffer, start, end);
1466 gtk_text_buffer_insert (buffer, start, g_utf8_strup (text_buffer, -1), -1);
1467 gtk_text_buffer_end_user_action (buffer);
1468 g_free (text_buffer);
1471 static void
1472 iconvert_to_lower(IAnjutaEditorConvert* edit, IAnjutaIterable *start_position,
1473 IAnjutaIterable *end_position, GError** e)
1475 Sourceview* sv = ANJUTA_SOURCEVIEW(edit);
1476 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
1477 GtkTextIter* start = sourceview_cell_get_iter (SOURCEVIEW_CELL (start_position));
1478 GtkTextIter* end = sourceview_cell_get_iter (SOURCEVIEW_CELL (end_position));
1480 gchar* text_buffer = gtk_text_buffer_get_text (buffer,
1481 start, end, TRUE);
1482 gtk_text_buffer_begin_user_action (buffer);
1483 gtk_text_buffer_delete (buffer, start, end);
1484 gtk_text_buffer_insert (buffer, start, g_utf8_strdown (text_buffer, -1), -1);
1485 gtk_text_buffer_end_user_action (buffer);
1486 g_free (text_buffer);
1490 static void
1491 iconvert_iface_init(IAnjutaEditorConvertIface* iface)
1493 iface->to_upper = iconvert_to_upper;
1494 iface->to_lower = iconvert_to_lower;
1497 typedef struct
1499 IAnjutaMarkableMarker marker;
1500 gint location;
1501 gint handle;
1502 guint source;
1503 Sourceview* sv;
1504 } SVMark;
1506 static gboolean mark_real (gpointer data)
1508 SVMark* svmark = data;
1509 Sourceview* sv = svmark->sv;
1510 GtkTextIter iter;
1511 GtkSourceMark* source_mark;
1512 const gchar* category;
1513 gint location = svmark->location;
1514 gint marker_count = svmark->handle;
1515 IAnjutaMarkableMarker marker = svmark->marker;
1516 gchar* name;
1518 if (sv->priv->loading || sv->priv->saving)
1520 /* Wait until loading/saving is finished */
1521 return TRUE;
1524 gtk_text_buffer_get_iter_at_line(GTK_TEXT_BUFFER(sv->priv->document),
1525 &iter, LOCATION_TO_LINE (location));
1527 category = marker_types[marker];
1528 name = CREATE_MARK_NAME (marker_count);
1531 source_mark = gtk_source_buffer_create_source_mark(GTK_SOURCE_BUFFER(sv->priv->document),
1532 name, category, &iter);
1534 g_source_remove (svmark->source);
1536 g_free (name);
1537 g_slice_free (SVMark, svmark);
1538 return FALSE;
1541 static gint
1542 imark_mark(IAnjutaMarkable* mark, gint location, IAnjutaMarkableMarker marker,
1543 GError **e)
1545 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
1546 SVMark* svmark = g_slice_new0 (SVMark);
1548 static gint marker_count = 0;
1550 marker_count++;
1552 svmark->sv = sv;
1553 svmark->location = location;
1554 svmark->handle = marker_count;
1555 svmark->marker = marker;
1556 svmark->source = g_idle_add (mark_real, svmark);
1558 sv->priv->idle_sources = g_slist_prepend (sv->priv->idle_sources,
1559 GUINT_TO_POINTER (svmark->source));
1561 return marker_count;
1564 static void
1565 imark_unmark(IAnjutaMarkable* mark, gint location, IAnjutaMarkableMarker marker,
1566 GError **e)
1568 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
1569 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1570 GtkTextIter begin;
1571 GtkTextIter end;
1573 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &begin, LOCATION_TO_LINE (location));
1574 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &end, LOCATION_TO_LINE (location));
1576 gtk_source_buffer_remove_source_marks (buffer, &begin, &end, marker_types[marker]);
1580 static gboolean
1581 imark_is_marker_set(IAnjutaMarkable* mark, gint location,
1582 IAnjutaMarkableMarker marker, GError **e)
1584 Sourceview* sv = ANJUTA_SOURCEVIEW(mark);
1585 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1586 GSList* markers;
1587 gboolean retval;
1589 markers = gtk_source_buffer_get_source_marks_at_line (buffer,
1590 LOCATION_TO_LINE (location),
1591 marker_types[marker]);
1593 retval = (markers != NULL);
1595 g_slist_free (markers);
1596 return retval;
1599 static gint
1600 imark_location_from_handle(IAnjutaMarkable* imark, gint handle, GError **e)
1602 Sourceview* sv = ANJUTA_SOURCEVIEW(imark);
1603 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1604 GtkTextMark* mark;
1605 GtkTextIter iter;
1606 gint location;
1607 gchar* name = CREATE_MARK_NAME (handle);
1609 mark = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (buffer), name);
1610 if (mark)
1612 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, mark);
1613 location = LINE_TO_LOCATION (gtk_text_iter_get_line (&iter));
1615 else
1616 location = -1;
1618 g_free (name);
1620 return location;
1623 static void
1624 imark_delete_all_markers(IAnjutaMarkable* imark, IAnjutaMarkableMarker marker,
1625 GError **e)
1627 Sourceview* sv = ANJUTA_SOURCEVIEW(imark);
1628 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1629 GtkTextIter begin;
1630 GtkTextIter end;
1632 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &begin, 0);
1633 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &end, -1);
1635 gtk_source_buffer_remove_source_marks (buffer, &begin, &end, marker_types[marker]);
1638 static void
1639 imark_iface_init(IAnjutaMarkableIface* iface)
1641 iface->mark = imark_mark;
1642 iface->unmark = imark_unmark;
1643 iface->location_from_handle = imark_location_from_handle;
1644 iface->is_marker_set = imark_is_marker_set;
1645 iface->delete_all_markers = imark_delete_all_markers;
1648 /* IanjutaIndic Interface */
1651 static void
1652 iindic_clear (IAnjutaIndicable *indic, GError **e)
1654 Sourceview* sv = ANJUTA_SOURCEVIEW(indic);
1655 GtkTextIter start, end;
1657 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(sv->priv->document),
1658 &start, 0);
1659 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER(sv->priv->document),
1660 &end, -1);
1661 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
1662 IMPORTANT_INDIC,
1663 &start, &end);
1664 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
1665 WARNING_INDIC,
1666 &start, &end);
1667 gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER(sv->priv->document),
1668 CRITICAL_INDIC,
1669 &start, &end);
1672 static void
1673 iindic_set (IAnjutaIndicable *indic, IAnjutaIterable* ibegin, IAnjutaIterable *iend,
1674 IAnjutaIndicableIndicator indicator, GError **e)
1676 GtkTextTag *tag = NULL;
1677 Sourceview* sv = ANJUTA_SOURCEVIEW(indic);
1679 switch (indicator)
1681 case IANJUTA_INDICABLE_IMPORTANT :
1682 tag = sv->priv->important_indic;
1683 break;
1684 case IANJUTA_INDICABLE_WARNING :
1685 tag = sv->priv->warning_indic;
1686 break;
1687 case IANJUTA_INDICABLE_CRITICAL :
1688 tag = sv->priv->critical_indic;
1689 break;
1690 default:
1691 return;
1694 gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER(sv->priv->document), tag,
1695 sourceview_cell_get_iter (SOURCEVIEW_CELL (ibegin)),
1696 sourceview_cell_get_iter (SOURCEVIEW_CELL (iend)));
1699 static void
1700 iindic_iface_init(IAnjutaIndicableIface* iface)
1702 iface->clear = iindic_clear;
1703 iface->set = iindic_set;
1706 static void
1707 ibookmark_toggle(IAnjutaBookmark* bmark, gint location, gboolean ensure_visible, GError** e)
1709 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1710 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1712 GSList* markers;
1714 markers = gtk_source_buffer_get_source_marks_at_line (buffer, LOCATION_TO_LINE (location),
1715 marker_types[IANJUTA_MARKABLE_BOOKMARK]);
1716 if (markers != NULL)
1718 GtkTextIter begin;
1719 GtkTextIter end;
1721 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &begin, LOCATION_TO_LINE (location));
1722 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &end, LOCATION_TO_LINE (location));
1724 gtk_source_buffer_remove_source_marks (buffer, &begin, &end,
1725 marker_types[IANJUTA_MARKABLE_BOOKMARK]);
1727 else
1729 GtkTextIter line;
1730 GtkSourceMark* bookmark;
1731 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer),
1732 &line, LOCATION_TO_LINE (location));
1734 bookmark =
1735 gtk_source_buffer_create_source_mark (buffer, NULL,
1736 marker_types [IANJUTA_MARKABLE_BOOKMARK],
1737 &line);
1741 static void
1742 goto_bookmark (Sourceview* sv, GtkTextIter* iter, gboolean backward)
1744 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1745 gboolean found = FALSE;
1747 if (backward)
1748 found = gtk_source_buffer_backward_iter_to_source_mark (buffer, iter,
1749 marker_types[IANJUTA_MARKABLE_BOOKMARK]);
1750 else
1751 found = gtk_source_buffer_forward_iter_to_source_mark (buffer, iter,
1752 marker_types[IANJUTA_MARKABLE_BOOKMARK]);
1753 if (found)
1755 ianjuta_editor_goto_line(IANJUTA_EDITOR(sv),
1756 LINE_TO_LOCATION (gtk_text_iter_get_line (iter)), NULL);
1760 static void
1761 ibookmark_first(IAnjutaBookmark* bmark, GError** e)
1763 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1764 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1765 GtkTextIter begin;
1767 gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &begin, 0);
1769 goto_bookmark (sv, &begin, FALSE);
1773 static void
1774 ibookmark_last(IAnjutaBookmark* bmark, GError** e)
1776 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1777 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);;
1778 GtkTextIter begin;
1780 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &begin, -1);
1782 goto_bookmark (sv, &begin, TRUE);
1785 static void
1786 ibookmark_next(IAnjutaBookmark* bmark, GError** e)
1788 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1789 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1790 GtkTextIter begin;
1792 gtk_text_buffer_get_iter_at_mark (buffer, &begin,
1793 gtk_text_buffer_get_insert (buffer));
1794 gtk_text_iter_forward_line (&begin);
1796 goto_bookmark (sv, &begin, FALSE);
1799 static void
1800 ibookmark_previous(IAnjutaBookmark* bmark, GError** e)
1802 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1803 GtkTextBuffer* buffer = GTK_TEXT_BUFFER(sv->priv->document);
1804 GtkTextIter begin;
1806 gtk_text_buffer_get_iter_at_mark (buffer, &begin,
1807 gtk_text_buffer_get_insert (buffer));
1808 gtk_text_iter_backward_line (&begin);
1810 goto_bookmark (sv, &begin, TRUE);
1814 static void
1815 ibookmark_clear_all(IAnjutaBookmark* bmark, GError** e)
1817 Sourceview* sv = ANJUTA_SOURCEVIEW(bmark);
1818 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1819 GtkTextIter begin;
1820 GtkTextIter end;
1822 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &begin, 0);
1823 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &end, -1);
1825 gtk_source_buffer_remove_source_marks (buffer, &begin, &end, marker_types[IANJUTA_MARKABLE_BOOKMARK]);
1828 static void
1829 ibookmark_iface_init(IAnjutaBookmarkIface* iface)
1831 iface->toggle = ibookmark_toggle;
1832 iface->first = ibookmark_first;
1833 iface->last = ibookmark_last;
1834 iface->next = ibookmark_next;
1835 iface->previous = ibookmark_previous;
1836 iface->clear_all = ibookmark_clear_all;
1839 static void
1840 iprint_print(IAnjutaPrint* print, GError** e)
1842 Sourceview* sv = ANJUTA_SOURCEVIEW(print);
1843 sourceview_print(sv);
1846 static void
1847 iprint_print_preview(IAnjutaPrint* print, GError** e)
1849 Sourceview* sv = ANJUTA_SOURCEVIEW(print);
1850 sourceview_print_preview(sv);
1853 static void
1854 iprint_iface_init(IAnjutaPrintIface* iface)
1856 iface->print = iprint_print;
1857 iface->print_preview = iprint_print_preview;
1861 static const GList*
1862 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
1863 GError **err)
1865 /* Cache the list */
1866 static GList* languages = NULL;
1867 if (!languages)
1869 GStrv langs;
1870 GStrv lang;
1871 g_object_get (gtk_source_language_manager_get_default(), "language-ids", &langs, NULL);
1873 for (lang = langs; *lang != NULL; lang++)
1875 languages = g_list_append (languages, *lang);
1878 return languages;
1881 static const gchar*
1882 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
1883 const gchar *language, GError **err)
1885 return language;
1888 static const gchar*
1889 autodetect_language (Sourceview* sv)
1891 const gchar* uri = anjuta_document_get_uri (sv->priv->document);
1892 const gchar* vfs_mime_type = gnome_vfs_get_slow_mime_type (uri);
1893 GStrv languages;
1894 GStrv cur_lang;
1895 const gchar* detected_language = NULL;
1896 g_object_get (G_OBJECT (gtk_source_language_manager_get_default ()), "language-ids",
1897 &languages, NULL);
1898 if (!vfs_mime_type)
1900 vfs_mime_type =
1901 gnome_vfs_get_mime_type_for_name (ianjuta_document_get_filename (IANJUTA_DOCUMENT (sv),
1902 NULL));
1904 if (!vfs_mime_type)
1905 return NULL;
1907 for (cur_lang = languages; *cur_lang != NULL; cur_lang++)
1909 GtkSourceLanguage* language =
1910 gtk_source_language_manager_get_language (gtk_source_language_manager_get_default(),
1911 *cur_lang);
1912 GStrv mime_types = gtk_source_language_get_mime_types (language);
1913 if (!mime_types)
1914 continue;
1915 GStrv mime_type;
1916 for (mime_type = mime_types; *mime_type != NULL; mime_type++)
1918 if (g_str_equal (*mime_type, vfs_mime_type))
1920 detected_language = gtk_source_language_get_id (language);
1921 g_signal_emit_by_name (G_OBJECT(sv), "language-changed",
1922 detected_language);
1923 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (sv->priv->document), language);
1924 g_strfreev (mime_types);
1925 goto out;
1928 g_strfreev (mime_types);
1930 out:
1931 g_strfreev(languages);
1933 return detected_language;
1936 static void
1937 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
1938 const gchar *language, GError **err)
1940 Sourceview* sv = ANJUTA_SOURCEVIEW (ilanguage);
1941 gboolean found = FALSE;
1942 GStrv languages;
1943 GStrv cur_lang;
1944 g_object_get (G_OBJECT (gtk_source_language_manager_get_default ()), "language-ids",
1945 &languages, NULL);
1946 for (cur_lang = languages; *cur_lang != NULL && language != NULL; cur_lang++)
1948 GtkSourceLanguage* source_language =
1949 gtk_source_language_manager_get_language (gtk_source_language_manager_get_default(),
1950 *cur_lang);
1951 const gchar* id = gtk_source_language_get_id (source_language);
1953 if (g_str_equal (language, id))
1955 g_signal_emit_by_name (G_OBJECT(sv), "language-changed",
1956 id);
1957 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (sv->priv->document),
1958 source_language);
1959 found = TRUE;
1960 break;
1963 g_strfreev(languages);
1964 if (!found)
1966 autodetect_language (sv);
1970 static const gchar*
1971 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
1973 Sourceview* sv = ANJUTA_SOURCEVIEW(ilanguage);
1974 GtkSourceBuffer* buffer = GTK_SOURCE_BUFFER(sv->priv->document);
1975 GtkSourceLanguage* lang = gtk_source_buffer_get_language(buffer);
1976 if (lang)
1978 return gtk_source_language_get_name(lang);
1980 else
1982 const gchar* language = autodetect_language (sv);
1983 return language;
1987 static void
1988 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
1990 iface->get_supported_languages = ilanguage_get_supported_languages;
1991 iface->get_language_name = ilanguage_get_language_name;
1992 iface->get_language = ilanguage_get_language;
1993 iface->set_language = ilanguage_set_language;
1996 static GList*
1997 iassist_get_suggestions (IAnjutaEditorAssist *iassist, const gchar *context, GError **err)
1999 /* Sourceview* sv = ANJUTA_SOURCEVIEW(iassist); */
2000 /* We don't make own suggestions yet */
2001 return NULL;
2004 static void
2005 iassist_suggest (IAnjutaEditorAssist *iassist, GList* choices, IAnjutaIterable* ipos,
2006 int char_alignment, GError **err)
2008 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2010 if (choices == NULL)
2012 if (sv->priv->assist_win)
2013 gtk_widget_destroy(GTK_WIDGET(sv->priv->assist_win));
2015 else
2017 if (!sv->priv->assist_win)
2019 sv->priv->assist_win = assist_window_new(GTK_TEXT_VIEW(sv->priv->view), NULL,
2020 ianjuta_iterable_get_position (ipos, NULL));
2021 g_signal_connect(G_OBJECT(sv->priv->assist_win), "destroy",
2022 G_CALLBACK(on_assist_window_destroyed), sv);
2023 g_signal_connect(G_OBJECT(sv->priv->assist_win), "chosen",
2024 G_CALLBACK(on_assist_chosen), sv);
2025 g_signal_connect(G_OBJECT(sv->priv->assist_win), "cancel",
2026 G_CALLBACK(on_assist_cancel), sv);
2028 assist_window_update(sv->priv->assist_win, choices);
2029 gtk_widget_show(GTK_WIDGET(sv->priv->assist_win));
2030 if (char_alignment > 0)
2032 /* Calculate offset */
2033 GtkTextIter cursor;
2034 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
2035 gtk_text_buffer_get_iter_at_mark (buffer,
2036 &cursor,
2037 gtk_text_buffer_get_insert(buffer));
2039 gint offset = gtk_text_iter_get_offset (&cursor);
2040 assist_window_move(sv->priv->assist_win, offset - char_alignment);
2045 static void
2046 iassist_hide_suggestions (IAnjutaEditorAssist* iassist, GError** err)
2048 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2049 if (sv->priv->assist_win)
2051 gtk_widget_hide (GTK_WIDGET (sv->priv->assist_win));
2055 static void
2056 iassist_show_tips (IAnjutaEditorAssist *iassist, GList* tips, IAnjutaIterable* ipos,
2057 gint char_alignment, GError **err)
2059 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2060 GtkTextBuffer* buffer = GTK_TEXT_BUFFER (sv->priv->document);
2061 GtkTextIter iter;
2062 gint tip_position;
2063 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
2064 gtk_text_buffer_get_insert (buffer));
2066 tip_position = gtk_text_iter_get_offset (&iter) - char_alignment;
2068 if (tips == NULL)
2069 return;
2071 if (!sv->priv->assist_tip)
2073 sv->priv->assist_tip =
2074 ASSIST_TIP (assist_tip_new (GTK_TEXT_VIEW (sv->priv->view), tips));
2076 g_signal_connect (G_OBJECT(sv->priv->assist_tip), "destroy", G_CALLBACK(on_assist_tip_destroyed),
2077 sv);
2078 assist_tip_move (sv->priv->assist_tip, GTK_TEXT_VIEW (sv->priv->view), tip_position);
2079 gtk_widget_show (GTK_WIDGET (sv->priv->assist_tip));
2081 else
2083 assist_tip_set_tips (sv->priv->assist_tip, tips);
2084 assist_tip_move (sv->priv->assist_tip, GTK_TEXT_VIEW (sv->priv->view), tip_position);
2088 static void
2089 iassist_cancel_tips (IAnjutaEditorAssist* iassist, GError** err)
2091 Sourceview* sv = ANJUTA_SOURCEVIEW(iassist);
2092 if (sv->priv->assist_tip)
2093 gtk_widget_destroy (GTK_WIDGET (sv->priv->assist_tip));
2096 static void
2097 iassist_iface_init(IAnjutaEditorAssistIface* iface)
2099 iface->suggest = iassist_suggest;
2100 iface->hide_suggestions = iassist_hide_suggestions;
2101 iface->get_suggestions = iassist_get_suggestions;
2102 iface->show_tips = iassist_show_tips;
2103 iface->cancel_tips = iassist_cancel_tips;
2106 static gboolean
2107 isearch_forward (IAnjutaEditorSearch* isearch,
2108 const gchar* search,
2109 gboolean case_sensitive,
2110 IAnjutaEditorCell* istart,
2111 IAnjutaEditorCell* iend,
2112 IAnjutaEditorCell** iresult_start,
2113 IAnjutaEditorCell** iresult_end,
2114 GError** e)
2116 Sourceview* sv = ANJUTA_SOURCEVIEW (isearch);
2118 SourceviewCell* start = SOURCEVIEW_CELL (istart);
2119 SourceviewCell* end = SOURCEVIEW_CELL (iend);
2121 GtkTextIter* start_iter = sourceview_cell_get_iter (start);
2122 GtkTextIter* end_iter = sourceview_cell_get_iter (end);
2124 GtkTextIter result_start, result_end;
2126 GtkSourceSearchFlags flags = 0;
2128 if (!case_sensitive)
2130 flags = GTK_SOURCE_SEARCH_CASE_INSENSITIVE;
2133 gboolean result =
2134 gtk_source_iter_forward_search (start_iter, search, flags, &result_start, &result_end,
2135 end_iter);
2137 if (result)
2139 if (iresult_start)
2141 *iresult_start = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_start,
2142 GTK_TEXT_VIEW (sv->priv->view)));
2144 if (iresult_end)
2146 *iresult_end = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_end,
2147 GTK_TEXT_VIEW (sv->priv->view)));
2151 return result;
2154 static gboolean
2155 isearch_backward (IAnjutaEditorSearch* isearch,
2156 const gchar* search,
2157 gboolean case_sensitive,
2158 IAnjutaEditorCell* istart,
2159 IAnjutaEditorCell* iend,
2160 IAnjutaEditorCell** iresult_start,
2161 IAnjutaEditorCell** iresult_end,
2162 GError** e)
2164 Sourceview* sv = ANJUTA_SOURCEVIEW (isearch);
2166 SourceviewCell* start = SOURCEVIEW_CELL (istart);
2167 SourceviewCell* end = SOURCEVIEW_CELL (iend);
2169 GtkTextIter* start_iter = sourceview_cell_get_iter (start);
2170 GtkTextIter* end_iter = sourceview_cell_get_iter (end);
2172 GtkTextIter result_start, result_end;
2174 GtkSourceSearchFlags flags = 0;
2176 if (!case_sensitive)
2178 flags = GTK_SOURCE_SEARCH_CASE_INSENSITIVE;
2181 gboolean result =
2182 gtk_source_iter_backward_search (start_iter, search, flags, &result_start, &result_end,
2183 end_iter);
2185 if (result)
2187 if (iresult_start)
2189 *iresult_start = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_start,
2190 GTK_TEXT_VIEW (sv->priv->view)));
2192 if (iresult_end)
2194 *iresult_end = IANJUTA_EDITOR_CELL (sourceview_cell_new (&result_end,
2195 GTK_TEXT_VIEW (sv->priv->view)));
2199 return result;
2202 static void
2203 isearch_iface_init(IAnjutaEditorSearchIface* iface)
2205 iface->forward = isearch_forward;
2206 iface->backward = isearch_backward;
2209 /* IAnjutaHover */
2210 #if HAVE_TOOLTIP_API
2211 static void
2212 on_sourceview_hover_leave(gpointer data, GObject* where_the_data_was)
2214 Sourceview* sv = ANJUTA_SOURCEVIEW (data);
2216 if (sv->priv->tooltip_cell)
2218 g_signal_emit_by_name (G_OBJECT (sv), "hover-leave", sv->priv->tooltip_cell);
2219 g_object_unref (sv->priv->tooltip_cell);
2220 sv->priv->tooltip_cell = NULL;
2224 static gboolean
2225 on_sourceview_hover_over (GtkWidget *widget, gint x, gint y,
2226 gboolean keyboard_tip, GtkTooltip *tooltip,
2227 gpointer data)
2229 Sourceview* sv = ANJUTA_SOURCEVIEW (data);
2230 SourceviewCell* cell;
2231 GtkTextIter iter;
2232 GtkTextView *text_view = GTK_TEXT_VIEW (widget);
2233 gint bx, by, trailing;
2235 gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_TEXT,
2236 x, y, &bx, &by);
2237 gtk_text_view_get_iter_at_position (text_view, &iter, &trailing, bx, by);
2239 cell = sourceview_cell_new (&iter, text_view);
2241 /* This should call ianjuta_hover_display() */
2242 g_signal_emit_by_name (G_OBJECT (sv), "hover-over", cell);
2244 if (sv->priv->tooltip)
2246 gtk_tooltip_set_text (tooltip, sv->priv->tooltip);
2247 g_object_weak_ref (G_OBJECT (tooltip), on_sourceview_hover_leave, sv);
2248 g_free (sv->priv->tooltip);
2249 sv->priv->tooltip = NULL;
2250 sv->priv->tooltip_cell = cell;
2251 return TRUE;
2254 return FALSE;
2257 static void
2258 ihover_display (IAnjutaEditorHover *ihover,
2259 IAnjutaIterable* position,
2260 const gchar* info,
2261 GError **e)
2263 Sourceview* sv = ANJUTA_SOURCEVIEW (ihover);
2264 g_assert (sv->priv->tooltip == NULL);
2265 sv->priv->tooltip = g_strdup (info);
2268 static void
2269 ihover_iface_init(IAnjutaEditorHoverIface* iface)
2271 iface->display = ihover_display;
2273 #endif
2275 ANJUTA_TYPE_BEGIN(Sourceview, sourceview, GTK_TYPE_SCROLLED_WINDOW);
2276 ANJUTA_TYPE_ADD_INTERFACE(idocument, IANJUTA_TYPE_DOCUMENT);
2277 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
2278 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
2279 ANJUTA_TYPE_ADD_INTERFACE(ieditor, IANJUTA_TYPE_EDITOR);
2280 ANJUTA_TYPE_ADD_INTERFACE(imark, IANJUTA_TYPE_MARKABLE);
2281 ANJUTA_TYPE_ADD_INTERFACE(iindic, IANJUTA_TYPE_INDICABLE);
2282 ANJUTA_TYPE_ADD_INTERFACE(iselect, IANJUTA_TYPE_EDITOR_SELECTION);
2283 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
2284 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
2285 ANJUTA_TYPE_ADD_INTERFACE(ibookmark, IANJUTA_TYPE_BOOKMARK);
2286 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
2287 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
2288 ANJUTA_TYPE_ADD_INTERFACE(isearch, IANJUTA_TYPE_EDITOR_SEARCH);
2289 #if HAVE_TOOLTIP_API
2290 ANJUTA_TYPE_ADD_INTERFACE(ihover, IANJUTA_TYPE_EDITOR_HOVER);
2291 #endif
2292 ANJUTA_TYPE_END;