2007-02-02 Sebastien Granjoux <seb.sfo@free.fr>
[anjuta-git-plugin.git] / plugins / editor / text_editor.c
blob5f344beb2e97e78cb572ecd7ebcf9021d73e6a5c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * text_editor.c
4 * Copyright (C) 2000 - 2004 Naba Kumar
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include <sys/wait.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <gnome.h>
30 #include <libgnomevfs/gnome-vfs.h>
31 #include <errno.h>
33 #include <libanjuta/resources.h>
34 #include <libanjuta/anjuta-utils.h>
35 #include <libanjuta/anjuta-encodings.h>
36 #include <libanjuta/anjuta-debug.h>
37 #include <libanjuta/interfaces/ianjuta-editor.h>
38 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
39 #include <libanjuta/interfaces/ianjuta-editor-convert.h>
40 #include <libanjuta/interfaces/ianjuta-editor-line-mode.h>
41 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
42 #include <libanjuta/interfaces/ianjuta-editor-view.h>
43 #include <libanjuta/interfaces/ianjuta-editor-folds.h>
44 #include <libanjuta/interfaces/ianjuta-editor-comment.h>
45 #include <libanjuta/interfaces/ianjuta-editor-zoom.h>
46 #include <libanjuta/interfaces/ianjuta-editor-goto.h>
47 #include <libanjuta/interfaces/ianjuta-editor-language.h>
48 #include <libanjuta/interfaces/ianjuta-bookmark.h>
49 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
50 #include <libanjuta/interfaces/ianjuta-file.h>
51 #include <libanjuta/interfaces/ianjuta-file-savable.h>
52 #include <libanjuta/interfaces/ianjuta-markable.h>
53 #include <libanjuta/interfaces/ianjuta-indicable.h>
54 #include <libanjuta/interfaces/ianjuta-print.h>
56 #include "properties.h"
57 #include "text_editor.h"
58 #include "text_editor_cbs.h"
59 #include "text_editor_menu.h"
60 #include "text-editor-iterable.h"
61 #include "print.h"
63 #define GTK
64 #undef PLAT_GTK
65 #define PLAT_GTK 1
66 #include "Scintilla.h"
67 #include "SciLexer.h"
68 #include "ScintillaWidget.h"
70 #include "lexer.h"
71 #include "aneditor.h"
72 #include "text_editor_prefs.h"
74 /* Order is important, as marker with the lowest number is drawn first */
75 #define TEXT_EDITOR_BOOKMARK 0
76 #define TEXT_EDITOR_BREAKPOINT_DISABLED 1
77 #define TEXT_EDITOR_BREAKPOINT_ENABLED 2
78 #define TEXT_EDITOR_PROGRAM_COUNTER 3
79 #define TEXT_EDITOR_LINEMARKER 4
81 /* Include marker pixmaps */
82 #include "bookmark.xpm"
83 #include "breakpoint-disabled.xpm"
84 #include "breakpoint-enabled.xpm"
85 #include "program-counter.xpm"
86 #include "linemarker.xpm"
88 static gchar* marker_pixmap[] =
90 bookmark_xpm,
91 breakpoint_disabled_xpm,
92 breakpoint_enabled_xpm,
93 program_counter_xpm,
94 linemarker_xpm,
95 NULL
98 /* Editor language supports */
99 static GList *supported_languages = NULL;
100 static GHashTable *supported_languages_name = NULL;
101 static GHashTable *supported_languages_ext = NULL;
102 static GHashTable *supported_languages_by_lexer = NULL;
104 static void text_editor_finalize (GObject *obj);
105 static void text_editor_dispose (GObject *obj);
106 static void text_editor_hilite_one (TextEditor * te, AnEditorID editor,
107 gboolean force);
109 static GtkVBoxClass *parent_class;
111 static void
112 text_editor_instance_init (TextEditor *te)
114 te->filename = NULL;
115 te->uri = NULL;
116 te->views = NULL;
117 te->popup_menu = NULL;
119 te->monitor = NULL;
120 te->preferences = NULL;
121 te->force_hilite = NULL;
122 te->freeze_count = 0;
123 te->current_line = 0;
124 te->popup_menu = NULL;
125 te->props_base = 0;
126 te->first_time_expose = TRUE;
127 te->encoding = NULL;
128 te->gconf_notify_ids = NULL;
131 static void
132 text_editor_class_init (TextEditorClass *klass)
134 GObjectClass *object_class = G_OBJECT_CLASS (klass);
136 parent_class = g_type_class_peek_parent (klass);
137 object_class->finalize = text_editor_finalize;
138 object_class->dispose = text_editor_dispose;
141 #if 0
142 static void
143 check_tm_file(TextEditor *te)
145 if (NULL == te->tm_file)
147 // FIXME:
148 // te->tm_file = tm_workspace_find_object(
149 //TM_WORK_OBJECT(app->tm_workspace), te->uri, FALSE);
150 if (NULL == te->tm_file)
152 te->tm_file = tm_source_file_new(te->uri, TRUE);
153 if (NULL != te->tm_file)
154 tm_workspace_add_object(te->tm_file);
158 #endif
160 static void
161 initialize_markers (TextEditor* te, GtkWidget *scintilla)
163 gint marker;
164 gchar **xpm;
165 g_return_if_fail (te != NULL);
167 marker = 0;
168 for (xpm = marker_pixmap;*xpm != NULL; xpm++)
170 scintilla_send_message (SCINTILLA (scintilla), SCI_MARKERDEFINEPIXMAP,
171 marker, *xpm);
172 marker++;
176 #ifdef DEBUG
177 static void
178 on_scintila_already_destroyed (gpointer te, GObject *obj)
180 DEBUG_PRINT ("Scintilla object has been destroyed");
183 static void
184 on_te_already_destroyed (gpointer te, GObject *obj)
186 DEBUG_PRINT ("TextEditor object has been destroyed");
188 #endif
190 void
191 text_editor_add_view (TextEditor *te)
193 AnEditorID editor_id;
194 GtkWidget *scintilla;
195 gint current_line;
196 gint current_point;
198 if (te->views)
200 current_line = text_editor_get_current_lineno (te);
201 current_point = text_editor_get_current_position (te);
203 else
205 current_line = 0;
206 current_point = 0;
208 editor_id = aneditor_new (sci_prop_get_pointer (te->props_base));
209 scintilla = aneditor_get_widget (editor_id);
211 /* Set notifications to receive */
212 scintilla_send_message (SCINTILLA (scintilla), SCI_SETMODEVENTMASK,
213 (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT), 0);
215 /* Set parent, if it is not primary view */
216 if (te->views)
218 aneditor_set_parent (editor_id, GPOINTER_TO_INT(te->editor_id));
220 te->views = g_list_prepend (te->views, GINT_TO_POINTER (editor_id));
221 te->editor_id = editor_id;
222 te->scintilla = scintilla;
225 aneditor_command (te->editor_id, ANE_SETACCELGROUP,
226 (glong) app->accel_group, 0);
229 gtk_widget_set_usize (scintilla, 50, 50);
230 gtk_widget_show (scintilla);
232 gtk_box_set_homogeneous (GTK_BOX (te), TRUE);
233 gtk_box_set_spacing (GTK_BOX (te), 3);
234 gtk_box_pack_start (GTK_BOX (te), scintilla, TRUE, TRUE, 0);
235 gtk_widget_grab_focus (scintilla);
237 g_signal_connect (G_OBJECT (scintilla), "event",
238 G_CALLBACK (on_text_editor_text_event), te);
239 g_signal_connect (G_OBJECT (scintilla), "button_press_event",
240 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
241 g_signal_connect_after (G_OBJECT (scintilla), "size_allocate",
242 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
243 g_signal_connect (G_OBJECT (scintilla), "sci-notify",
244 G_CALLBACK (on_text_editor_scintilla_notify), te);
245 g_signal_connect (G_OBJECT (scintilla), "focus_in_event",
246 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
248 initialize_markers (te, scintilla);
249 text_editor_hilite_one (te, editor_id, FALSE);
250 text_editor_set_line_number_width (te);
252 if (current_line)
253 text_editor_goto_line (te, current_line, FALSE, TRUE);
254 if (current_point)
255 text_editor_goto_point (te, current_point);
257 #ifdef DEBUG
258 g_object_weak_ref (G_OBJECT (scintilla), on_scintila_already_destroyed, te);
259 #endif
262 /* Remove the current view */
263 void
264 text_editor_remove_view (TextEditor *te)
266 if (!te->editor_id)
267 return;
268 if (te->views == NULL ||
269 g_list_length (te->views) <= 1)
270 return;
272 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
273 G_CALLBACK (on_text_editor_text_event), te);
274 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
275 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
276 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
277 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
278 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
279 G_CALLBACK (on_text_editor_scintilla_notify), te);
280 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
281 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
283 te->views = g_list_remove (te->views, GINT_TO_POINTER(te->editor_id));
284 gtk_container_remove (GTK_CONTAINER (te), te->scintilla);
285 aneditor_destroy(te->editor_id);
287 /* Set current view */
288 if (te->views)
290 te->editor_id = GPOINTER_TO_INT(te->views->data);
291 te->scintilla = aneditor_get_widget (te->editor_id);
292 gtk_widget_grab_focus (te->scintilla);
294 else
296 gtk_box_set_spacing (GTK_BOX (te), 0);
297 te->editor_id = 0;
298 te->scintilla = NULL;
302 static void
303 on_reload_dialog_response (GtkWidget *dlg, gint res, TextEditor *te)
305 if (res == GTK_RESPONSE_YES)
307 text_editor_load_file (te);
309 gtk_widget_destroy (dlg);
312 static void
313 on_text_editor_uri_changed (GnomeVFSMonitorHandle *handle,
314 const gchar *monitor_uri,
315 const gchar *info_uri,
316 GnomeVFSMonitorEventType event_type,
317 gpointer user_data)
319 GtkWidget *dlg;
320 GtkWidget *parent;
321 gchar *buff;
322 TextEditor *te = TEXT_EDITOR (user_data);
324 DEBUG_PRINT ("File changed!!!");
326 if (!(event_type == GNOME_VFS_MONITOR_EVENT_CHANGED ||
327 event_type == GNOME_VFS_MONITOR_EVENT_CREATED))
328 return;
330 if (!anjuta_util_diff(te->uri, ianjuta_editor_get_text(IANJUTA_EDITOR(te),
331 0, -1, NULL)))
332 return;
334 if (strcmp (monitor_uri, info_uri) != 0)
335 return;
337 buff =
338 g_strdup_printf (_
339 ("The file '%s' on the disk is more recent than\n"
340 "the current buffer.\nDo you want to reload it?"),
341 te->filename);
343 parent = gtk_widget_get_toplevel (GTK_WIDGET (te));
345 dlg = gtk_message_dialog_new (GTK_WINDOW (parent),
346 GTK_DIALOG_DESTROY_WITH_PARENT,
347 GTK_MESSAGE_WARNING,
348 GTK_BUTTONS_NONE, buff);
349 gtk_dialog_add_button (GTK_DIALOG (dlg),
350 GTK_STOCK_NO,
351 GTK_RESPONSE_NO);
352 anjuta_util_dialog_add_button (GTK_DIALOG (dlg),
353 _("_Reload"),
354 GTK_STOCK_REFRESH,
355 GTK_RESPONSE_YES);
356 g_free (buff);
358 gtk_window_set_transient_for (GTK_WINDOW (dlg),
359 GTK_WINDOW (parent));
361 g_signal_connect (dlg, "response",
362 G_CALLBACK (on_reload_dialog_response),
363 te);
364 g_signal_connect_swapped (dlg, "delete-event",
365 G_CALLBACK (gtk_widget_destroy),
366 dlg);
367 gtk_widget_show (dlg);
370 static void
371 text_editor_update_monitor (TextEditor *te, gboolean disable_it)
373 if (te->monitor)
375 /* Shutdown existing monitor */
376 gnome_vfs_monitor_cancel (te->monitor);
377 te->monitor = NULL;
379 if (te->uri && !disable_it)
381 GnomeVFSResult res;
382 DEBUG_PRINT ("Setting up Monitor for %s", te->uri);
383 res = gnome_vfs_monitor_add (&te->monitor, te->uri,
384 GNOME_VFS_MONITOR_FILE,
385 on_text_editor_uri_changed, te);
387 if (res != GNOME_VFS_OK)
389 DEBUG_PRINT ("Error while setting up file monitor: %s",
390 gnome_vfs_result_to_string (res));
396 GtkWidget *
397 text_editor_new (AnjutaStatus *status, AnjutaPreferences *eo, const gchar *uri, const gchar *name)
399 gint zoom_factor;
400 static guint new_file_count;
401 TextEditor *te = TEXT_EDITOR (gtk_widget_new (TYPE_TEXT_EDITOR, NULL));
403 te->status = status;
405 te->preferences = eo;
406 te->props_base = text_editor_get_props();
407 if (name && strlen(name) > 0)
408 te->filename = g_strdup(name);
409 else
410 te->filename = g_strdup_printf ("Newfile#%d", ++new_file_count);
411 if (uri && strlen(uri) > 0)
413 GnomeVFSResult result;
414 GnomeVFSURI* vfs_uri;
415 GnomeVFSFileInfo info = {0,0};
417 new_file_count--;
418 if (te->filename)
419 g_free (te->filename);
420 if (te->uri)
421 g_free (te->uri);
422 vfs_uri = gnome_vfs_uri_new(uri);
423 result = gnome_vfs_get_file_info_uri(vfs_uri, &info, GNOME_VFS_SET_FILE_INFO_NONE);
424 gnome_vfs_uri_unref(vfs_uri);
425 te->filename = g_strdup(info.name);
426 te->uri = g_strdup(uri);
429 text_editor_prefs_init (te);
431 /* Create primary view */
432 text_editor_add_view (te);
434 if (te->uri)
436 if (text_editor_load_file (te) == FALSE)
438 /* Unable to load file */
439 gtk_widget_destroy (GTK_WIDGET (te));
440 return NULL;
443 text_editor_update_controls (te);
445 /* Apply font zoom separately */
446 zoom_factor = anjuta_preferences_get_int (te->preferences, TEXT_ZOOM_FACTOR);
447 DEBUG_PRINT ("Initializing zoom factor to: %d", zoom_factor);
448 text_editor_set_zoom_factor (te, zoom_factor);
450 #ifdef DEBUG
451 g_object_weak_ref (G_OBJECT (te), on_te_already_destroyed, te);
452 #endif
453 return GTK_WIDGET (te);
456 void
457 text_editor_dispose (GObject *obj)
459 TextEditor *te = TEXT_EDITOR (obj);
460 if (te->monitor)
462 text_editor_update_monitor (te, TRUE);
463 te->monitor = NULL;
465 if (te->popup_menu)
467 g_object_unref (te->popup_menu);
468 te->popup_menu = NULL;
471 if (te->views)
473 GtkWidget *scintilla;
474 AnEditorID editor_id;
475 GList *node;
477 node = te->views;
478 while (node)
480 editor_id = GPOINTER_TO_INT (node->data);
481 scintilla = aneditor_get_widget (editor_id);
483 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
484 G_CALLBACK (on_text_editor_text_event), te);
485 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
486 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
487 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
488 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
489 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
490 G_CALLBACK (on_text_editor_scintilla_notify), te);
491 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
492 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
494 aneditor_destroy (editor_id);
495 node = g_list_next (node);
497 te->scintilla = NULL;
498 te->editor_id = 0;
499 te->views = NULL;
501 if (te->gconf_notify_ids)
503 text_editor_prefs_finalize (te);
504 te->gconf_notify_ids = NULL;
506 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (G_OBJECT(te)));
509 void
510 text_editor_finalize (GObject *obj)
512 TextEditor *te = TEXT_EDITOR (obj);
513 if (te->filename)
514 g_free (te->filename);
515 if (te->uri)
516 g_free (te->uri);
517 if (te->encoding)
518 g_free (te->encoding);
519 if (te->force_hilite)
520 g_free (te->force_hilite);
522 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (G_OBJECT(te)));
525 void
526 text_editor_freeze (TextEditor *te)
528 te->freeze_count++;
531 void
532 text_editor_thaw (TextEditor *te)
534 te->freeze_count--;
535 if (te->freeze_count < 0)
536 te->freeze_count = 0;
539 void
540 text_editor_set_hilite_type (TextEditor * te, const gchar *file_extension)
542 const gchar *past_language;
543 const gchar *curr_language;
545 past_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
547 g_free (te->force_hilite);
548 if (file_extension)
549 te->force_hilite = g_strdup (file_extension);
550 else
551 te->force_hilite = NULL;
553 curr_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
554 if (past_language != curr_language)
555 g_signal_emit_by_name (te, "language-changed", curr_language);
558 static void
559 text_editor_hilite_one (TextEditor * te, AnEditorID editor_id,
560 gboolean override_by_pref)
562 /* If syntax highlighting is disabled ... */
563 if (override_by_pref &&
564 anjuta_preferences_get_int (ANJUTA_PREFERENCES (te->preferences),
565 DISABLE_SYNTAX_HILIGHTING))
567 aneditor_command (editor_id, ANE_SETHILITE, (guint) "plain.txt", 0);
569 else if (te->force_hilite)
571 aneditor_command (editor_id, ANE_SETHILITE, (guint) te->force_hilite, 0);
573 else if (te->uri)
575 gchar *basename;
576 basename = g_path_get_basename (te->uri);
577 aneditor_command (editor_id, ANE_SETHILITE, (guint) basename, 0);
578 g_free (basename);
580 else if (te->filename)
582 aneditor_command (editor_id, ANE_SETHILITE, (guint) te->filename, 0);
584 else
586 aneditor_command (editor_id, ANE_SETHILITE, (guint) "plain.txt", 0);
590 void
591 text_editor_hilite (TextEditor * te, gboolean override_by_pref)
593 GList *node;
595 node = te->views;
596 while (node)
598 text_editor_hilite_one (te, GPOINTER_TO_INT (node->data),
599 override_by_pref);
600 node = g_list_next (node);
604 void
605 text_editor_set_zoom_factor (TextEditor * te, gint zfac)
607 text_editor_command (te, ANE_SETZOOM, zfac, 0);
610 TextEditorAttrib
611 text_editor_get_attribute (TextEditor *te, gint position)
613 int lexer;
614 int style;
615 TextEditorAttrib attrib = TEXT_EDITOR_ATTRIB_TEXT;
617 lexer = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETLEXER,
618 0, 0);
619 style = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETSTYLEAT,
620 position, 0);
621 switch (lexer)
623 case SCLEX_CPP:
624 switch (style)
626 case SCE_C_CHARACTER:
627 case SCE_C_STRING:
628 attrib = TEXT_EDITOR_ATTRIB_STRING;
629 break;
630 case SCE_C_COMMENT:
631 case SCE_C_COMMENTLINE:
632 case SCE_C_COMMENTDOC:
633 case SCE_C_COMMENTLINEDOC:
634 case SCE_C_COMMENTDOCKEYWORD:
635 case SCE_C_COMMENTDOCKEYWORDERROR:
636 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
637 break;
638 case SCE_C_WORD:
639 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
640 break;
642 break;
644 return attrib;
647 glong
648 text_editor_find (TextEditor * te, const gchar * str, gint scope,
649 gboolean forward, gboolean regexp,
650 gboolean ignore_case, gboolean whole_word, gboolean wrap)
652 glong ret;
653 GtkWidget *editor;
654 glong flags;
655 int current_pos, current_anchor;
657 if (!te) return -1;
658 editor = te->scintilla;
660 flags = (ignore_case ? 0 : SCFIND_MATCHCASE)
661 | (regexp ? SCFIND_REGEXP : 0)
662 | (whole_word ? SCFIND_WHOLEWORD : 0)
663 | (forward ? 0 : ANEFIND_REVERSE_FLAG);
665 switch (scope)
667 case TEXT_EDITOR_FIND_SCOPE_WHOLE:
668 if (forward)
670 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
671 0, 0);
672 scintilla_send_message (SCINTILLA (editor),
673 SCI_SETCURRENTPOS, 0, 0);
675 else
677 glong length;
678 length = scintilla_send_message (SCINTILLA (editor),
679 SCI_GETTEXTLENGTH, 0, 0);
680 scintilla_send_message (SCINTILLA (editor),
681 SCI_SETCURRENTPOS, length-1, 0);
682 scintilla_send_message (SCINTILLA (editor),
683 SCI_SETANCHOR, length-1, 0);
685 break;
686 default:
687 break;
689 current_pos = scintilla_send_message (SCINTILLA (editor),
690 SCI_GETCURRENTPOS, 0, 0);
691 current_anchor = scintilla_send_message (SCINTILLA (editor),
692 SCI_GETANCHOR, 0, 0);
693 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
694 if (scope == TEXT_EDITOR_FIND_SCOPE_CURRENT && wrap && ret < 0) {
695 /* If wrap is requested, wrap it. */
696 if (forward)
698 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR, 0, 0);
699 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
700 0, 0);
702 else
704 glong length;
705 length = scintilla_send_message (SCINTILLA (editor),
706 SCI_GETTEXTLENGTH, 0, 0);
707 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
708 length-1, 0);
709 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
710 length-1, 0);
712 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
713 /* If the text is still not found, restore current pos and anchor */
714 if (ret < 0) {
715 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
716 current_anchor, 0);
717 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
718 current_pos, 0);
721 return ret;
724 void
725 text_editor_replace_selection (TextEditor * te, const gchar* r_str)
727 if (!te) return;
728 scintilla_send_message (SCINTILLA(te->scintilla), SCI_REPLACESEL, 0,
729 (long)r_str);
732 guint
733 text_editor_get_total_lines (TextEditor * te)
735 guint i;
736 guint count = 0;
737 if (te == NULL)
738 return 0;
739 if (IS_SCINTILLA (te->scintilla) == FALSE)
740 return 0;
741 for (i = 0;
742 i < scintilla_send_message (SCINTILLA (te->scintilla),
743 SCI_GETLENGTH, 0, 0); i++)
745 if (scintilla_send_message
746 (SCINTILLA (te->scintilla), SCI_GETCHARAT, i,
747 0) == '\n')
748 count++;
750 return count;
753 guint
754 text_editor_get_current_lineno (TextEditor * te)
756 guint count;
758 g_return_val_if_fail (te != NULL, 0);
760 count = scintilla_send_message (SCINTILLA (te->scintilla),
761 SCI_GETCURRENTPOS, 0, 0);
762 count = scintilla_send_message (SCINTILLA (te->scintilla),
763 SCI_LINEFROMPOSITION, count, 0);
764 return linenum_scintilla_to_text_editor(count);
767 guint
768 text_editor_get_current_column (TextEditor * te)
770 g_return_val_if_fail (te != NULL, 0);
771 return scintilla_send_message (SCINTILLA (te->scintilla),
772 SCI_GETCOLUMN,
773 text_editor_get_current_position (te), 0);
776 gboolean
777 text_editor_get_overwrite (TextEditor * te)
779 g_return_val_if_fail (te != NULL, 0);
780 return scintilla_send_message (SCINTILLA (te->scintilla),
781 SCI_GETOVERTYPE, 0, 0);
784 guint
785 text_editor_get_line_from_position (TextEditor * te, glong pos)
787 guint count;
789 g_return_val_if_fail (te != NULL, 0);
791 count = scintilla_send_message (SCINTILLA (te->scintilla),
792 SCI_LINEFROMPOSITION, pos, 0);
793 return linenum_scintilla_to_text_editor(count);
796 glong
797 text_editor_get_current_position (TextEditor * te)
799 guint count;
801 g_return_val_if_fail (te != NULL, 0);
803 count = scintilla_send_message (SCINTILLA (te->scintilla),
804 SCI_GETCURRENTPOS, 0, 0);
805 return count;
808 gboolean
809 text_editor_goto_point (TextEditor * te, glong point)
811 g_return_val_if_fail (te != NULL, FALSE);
812 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
814 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
815 point, 0);
816 return TRUE;
819 gboolean
820 text_editor_goto_line (TextEditor * te, glong line,
821 gboolean mark, gboolean ensure_visible)
823 gint selpos;
824 g_return_val_if_fail (te != NULL, FALSE);
825 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
826 g_return_val_if_fail(line >= 0, FALSE);
828 te->current_line = line;
829 if (mark) text_editor_set_line_marker (te, line);
830 if (ensure_visible)
831 scintilla_send_message (SCINTILLA (te->scintilla),
832 SCI_ENSUREVISIBLE,
833 linenum_text_editor_to_scintilla (line), 0);
834 selpos = scintilla_send_message(SCINTILLA (te->scintilla),
835 SCI_POSITIONFROMLINE,
836 linenum_text_editor_to_scintilla (line), 0);
837 scintilla_send_message (SCINTILLA (te->scintilla),
838 SCI_SETSELECTIONSTART, selpos, 0);
839 scintilla_send_message (SCINTILLA (te->scintilla),
840 SCI_SETSELECTIONEND, selpos, 0);
842 /* This ensures that we have arround 5 lines visible below the mark */
843 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
844 linenum_text_editor_to_scintilla (line)+5, 0);
845 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
846 linenum_text_editor_to_scintilla (line), 0);
847 return TRUE;
850 gint
851 text_editor_goto_block_start (TextEditor* te)
853 gint line;
854 line = aneditor_command (te->editor_id, ANE_GETBLOCKSTARTLINE, 0, 0);
855 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
856 else gdk_beep();
857 return line;
860 gint
861 text_editor_goto_block_end (TextEditor* te)
863 gint line;
864 line = aneditor_command (te->editor_id, ANE_GETBLOCKENDLINE, 0, 0);
865 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
866 else gdk_beep();
867 return line;
870 gint
871 text_editor_set_marker (TextEditor *te, glong line, gint marker)
873 g_return_val_if_fail (te != NULL, -1);
874 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, -1);
876 /* Scintilla interprets line+1 rather than line */
877 /* A bug perhaps */
878 /* So counterbalance it with line-1 */
879 /* Using the macros linenum_* */
880 return scintilla_send_message (SCINTILLA (te->scintilla),
881 SCI_MARKERADD,
882 linenum_text_editor_to_scintilla (line),
883 marker);
886 gint
887 text_editor_set_indicator (TextEditor *te, gint start,
888 gint end, gint indicator)
890 gchar ch;
891 glong indic_mask[] = {INDIC0_MASK, INDIC1_MASK, INDIC2_MASK};
892 gint current_styling_pos;
894 g_return_val_if_fail (te != NULL, -1);
895 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
897 if (start >= 0) {
898 if (end <= start)
899 return -1;
903 ch = scintilla_send_message (SCINTILLA (te->scintilla),
904 SCI_GETCHARAT, start, 0);
905 start++;
906 } while (isspace(ch));
907 start--;
909 do {
910 ch = scintilla_send_message (SCINTILLA (te->scintilla),
911 SCI_GETCHARAT, end, 0);
912 end--;
913 } while (isspace(ch));
914 end++;
915 if (end < start) return -1;
917 current_styling_pos = scintilla_send_message (SCINTILLA (te->scintilla),
918 SCI_GETENDSTYLED, 0, 0);
919 if (indicator >= 0 && indicator < 3) {
920 char current_mask;
921 current_mask =
922 scintilla_send_message (SCINTILLA (te->scintilla),
923 SCI_GETSTYLEAT, start, 0);
924 current_mask &= INDICS_MASK;
925 current_mask |= indic_mask[indicator];
926 scintilla_send_message (SCINTILLA (te->scintilla),
927 SCI_STARTSTYLING, start, INDICS_MASK);
928 scintilla_send_message (SCINTILLA (te->scintilla),
929 SCI_SETSTYLING, end-start+1, current_mask);
930 } else {
931 scintilla_send_message (SCINTILLA (te->scintilla),
932 SCI_STARTSTYLING, start, INDICS_MASK);
933 scintilla_send_message (SCINTILLA (te->scintilla),
934 SCI_SETSTYLING, end-start+1, 0);
936 if (current_styling_pos < start)
937 scintilla_send_message (SCINTILLA (te->scintilla),
938 SCI_STARTSTYLING, current_styling_pos,
939 0x1F);
940 } else {
941 if (indicator < 0) {
942 char current_mask;
943 glong i, last, start_style_pos = 0;
945 last = scintilla_send_message (SCINTILLA (te->scintilla),
946 SCI_GETTEXTLENGTH, 0, 0);
947 current_styling_pos = scintilla_send_message (SCINTILLA (te->scintilla),
948 SCI_GETENDSTYLED, 0, 0);
949 for (i = 0; i < last; i++)
951 current_mask =
952 scintilla_send_message (SCINTILLA (te->scintilla),
953 SCI_GETSTYLEAT, i, 0);
954 current_mask &= INDICS_MASK;
955 if (current_mask != 0)
957 if (start_style_pos == 0)
958 start_style_pos = i;
959 scintilla_send_message (SCINTILLA (te->scintilla),
960 SCI_STARTSTYLING, i, INDICS_MASK);
961 scintilla_send_message (SCINTILLA (te->scintilla),
962 SCI_SETSTYLING, 1, 0);
965 if (current_styling_pos < start_style_pos)
966 scintilla_send_message (SCINTILLA (te->scintilla),
967 SCI_STARTSTYLING, current_styling_pos,
968 0x1F);
971 return 0;
974 void
975 text_editor_set_line_marker (TextEditor *te, glong line)
977 g_return_if_fail (te != NULL);
978 g_return_if_fail(IS_SCINTILLA (te->scintilla) == TRUE);
980 // FIXME: anjuta_delete_all_marker (TEXT_EDITOR_LINEMARKER);
981 text_editor_delete_marker_all (te, TEXT_EDITOR_LINEMARKER);
982 text_editor_set_marker (te, line, TEXT_EDITOR_LINEMARKER);
985 /* Support for DOS-Files
987 * On load, Anjuta will detect DOS-files by finding <CR><LF>.
988 * Anjuta will translate some chars >= 128 to native charset.
989 * On save the DOS_EOL_CHECK(preferences->editor) will be checked
990 * and chars >=128 will be replaced by DOS-codes, if any translation
991 * match(see struct tr_dos in this file) and <CR><LF> will used
992 * instead of <LF>.
993 * The DOS_EOL_CHECK-checkbox will be set on loading a DOS-file.
995 * 23.Sep.2001 Denis Boehme <boehme at syncio dot de>
999 * this is a translation table from unix->dos
1000 * this table will be used by filter_chars and save filtered.
1002 static struct {
1003 unsigned char c; /* unix-char */
1004 unsigned char b; /* dos-char */
1005 } tr_dos[]= {
1006 { 'ä', 0x84 },
1007 { 'Ä', 0x8e },
1008 { 'ß', 0xe1 },
1009 { 'ü', 0x81 },
1010 { 'Ü', 0x9a },
1011 { 'ö', 0x94 },
1012 { 'Ö', 0x99 },
1013 { 'é', 0x82 },
1014 { 'É', 0x90 },
1015 { 'è', 0x9a },
1016 { 'È', 0xd4 },
1017 { 'ê', 0x88 },
1018 { 'Ê', 0xd2 },
1019 { 'á', 0xa0 },
1020 { 'Á', 0xb5 },
1021 { 'à', 0x85 },
1022 { 'À', 0xb7 },
1023 { 'â', 0x83 },
1024 { 'Â', 0xb6 },
1025 { 'ú', 0xa3 },
1026 { 'Ú', 0xe9 },
1027 { 'ù', 0x97 },
1028 { 'Ù', 0xeb },
1029 { 'û', 0x96 },
1030 { 'Û', 0xea }
1034 * filter chars in buffer, by using tr_dos-table.
1037 static size_t
1038 filter_chars_in_dos_mode(gchar *data_, size_t size )
1040 int k;
1041 size_t i;
1042 unsigned char * data = (unsigned char*)data_;
1043 unsigned char * tr_map;
1045 tr_map = (unsigned char *)malloc( 256 );
1046 memset( tr_map, 0, 256 );
1047 for ( k = 0; k < sizeof(tr_dos )/2 ; k++ )
1048 tr_map[tr_dos[k].b] = tr_dos[k].c;
1050 for ( i = 0; i < size; i++ )
1052 if ( (data[i] >= 128) && ( tr_map[data[i]] != 0) )
1053 data[i] = tr_map[data[i]];;
1056 if ( tr_map )
1057 free( tr_map );
1059 return size;
1063 * save buffer. filter chars and set dos-like CR/LF if dos_text is set.
1065 static GnomeVFSResult
1066 save_filtered_in_dos_mode(GnomeVFSHandle* vfs_write, gchar *data_,
1067 GnomeVFSFileSize size)
1069 GnomeVFSResult result;
1070 size_t i, j;
1071 unsigned char *data;
1072 unsigned char *tr_map;
1073 int k;
1075 /* build the translation table */
1076 tr_map = malloc( 256 );
1077 memset( tr_map, 0, 256 );
1079 for ( k = 0; k < sizeof(tr_dos)/2; k++)
1080 tr_map[tr_dos[k].c] = tr_dos[k].b;
1082 data = (unsigned char*)data_;
1083 i = 0; j = 0;
1084 while ( i < size )
1086 if (data[i]>=128) {
1087 /* convert dos-text */
1088 if ( tr_map[data[i]] != 0 )
1090 GnomeVFSFileSize bytes_written;
1091 result = gnome_vfs_write (vfs_write, &tr_map[data[i]], 1, &bytes_written);
1092 j += bytes_written;
1094 else
1096 /* char not found, skip transform */
1097 GnomeVFSFileSize bytes_written;
1098 result = gnome_vfs_write (vfs_write, &data[i], 1, &bytes_written);
1099 j += bytes_written;
1101 i++;
1103 else
1105 GnomeVFSFileSize bytes_written;
1106 result = gnome_vfs_write (vfs_write, &data[i], 1, &bytes_written);
1107 j += bytes_written;
1108 i++;
1110 if (result != GNOME_VFS_OK)
1111 break;
1114 if (tr_map)
1115 free (tr_map);
1116 return result;
1119 static gint
1120 determine_editor_mode(gchar* buffer, glong size)
1122 gint i;
1123 guint cr, lf, crlf, max_mode;
1124 gint mode;
1126 cr = lf = crlf = 0;
1128 for ( i = 0; i < size ; i++ )
1130 if ( buffer[i] == 0x0a ){
1131 // LF
1132 // mode = SC_EOF_LF;
1133 lf++;
1134 } else if ( buffer[i] == 0x0d ) {
1135 if (i >= (size-1)) {
1136 // Last char
1137 // CR
1138 // mode = SC_EOL_CR;
1139 cr++;
1140 } else {
1141 if (buffer[i+1] != 0x0a) {
1142 // CR
1143 // mode = SC_EOL_CR;
1144 cr++;
1145 } else {
1146 // CRLF
1147 // mode = SC_EOL_CRLF;
1148 crlf++;
1150 i++;
1155 /* Vote for the maximum */
1156 mode = SC_EOL_LF;
1157 max_mode = lf;
1158 if (crlf > max_mode) {
1159 mode = SC_EOL_CRLF;
1160 max_mode = crlf;
1162 if (cr > max_mode) {
1163 mode = SC_EOL_CR;
1164 max_mode = cr;
1166 DEBUG_PRINT ("EOL chars: LR = %d, CR = %d, CRLF = %d", lf, cr, crlf);
1167 DEBUG_PRINT ("Autodetected Editor mode [%d]", mode);
1168 return mode;
1171 static gchar *
1172 convert_to_utf8_from_charset (const gchar *content,
1173 gsize len,
1174 const gchar *charset)
1176 gchar *utf8_content = NULL;
1177 GError *conv_error = NULL;
1178 gchar* converted_contents = NULL;
1179 gsize bytes_written;
1181 g_return_val_if_fail (content != NULL, NULL);
1183 DEBUG_PRINT ("Trying to convert from %s to UTF-8", charset);
1185 converted_contents = g_convert (content, len, "UTF-8",
1186 charset, NULL, &bytes_written,
1187 &conv_error);
1189 if ((conv_error != NULL) || (converted_contents == NULL) ||
1190 !g_utf8_validate (converted_contents, bytes_written, NULL))
1192 DEBUG_PRINT ("Couldn't convert from %s to UTF-8.", charset);
1194 if (converted_contents != NULL)
1195 g_free (converted_contents);
1197 if (conv_error != NULL)
1199 g_error_free (conv_error);
1200 conv_error = NULL;
1203 utf8_content = NULL;
1204 } else {
1205 DEBUG_PRINT ("Converted from %s to UTF-8.", charset);
1206 utf8_content = converted_contents;
1208 return utf8_content;
1211 static gchar *
1212 convert_to_utf8 (PropsID props, const gchar *content, gsize len,
1213 gchar **encoding_used)
1215 GList *encodings = NULL;
1216 GList *start;
1217 const gchar *locale_charset;
1218 GList *encoding_strings;
1220 g_return_val_if_fail (!g_utf8_validate (content, len, NULL),
1221 g_strndup (content, len < 0 ? strlen (content) : len));
1223 encoding_strings = sci_prop_glist_from_data (props, SUPPORTED_ENCODINGS);
1224 encodings = anjuta_encoding_get_encodings (encoding_strings);
1225 anjuta_util_glist_strings_free (encoding_strings);
1227 if (g_get_charset (&locale_charset) == FALSE)
1229 const AnjutaEncoding *locale_encoding;
1231 /* not using a UTF-8 locale, so try converting
1232 * from that first */
1233 if (locale_charset != NULL)
1235 locale_encoding = anjuta_encoding_get_from_charset (locale_charset);
1236 encodings = g_list_prepend (encodings,
1237 (gpointer) locale_encoding);
1238 DEBUG_PRINT ("Current charset = %s", locale_charset);
1242 start = encodings;
1244 while (encodings != NULL)
1246 AnjutaEncoding *enc;
1247 const gchar *charset;
1248 gchar *utf8_content;
1250 enc = (AnjutaEncoding *) encodings->data;
1252 charset = anjuta_encoding_get_charset (enc);
1254 DEBUG_PRINT ("Trying to convert %d bytes of data into UTF-8.", len);
1256 fflush (stdout);
1257 utf8_content = convert_to_utf8_from_charset (content, len, charset);
1259 if (utf8_content != NULL) {
1260 if (encoding_used != NULL)
1262 if (*encoding_used != NULL)
1263 g_free (*encoding_used);
1265 *encoding_used = g_strdup (charset);
1268 return utf8_content;
1271 encodings = encodings->next;
1274 g_list_free (start);
1276 return NULL;
1279 static gboolean
1280 load_from_file (TextEditor *te, gchar *uri, gchar **err)
1282 GnomeVFSURI* vfs_uri;
1283 GnomeVFSHandle* vfs_read;
1284 GnomeVFSResult result;
1285 GnomeVFSFileInfo info;
1286 GnomeVFSFileSize nchars;
1288 gchar *buffer;
1289 gint dos_filter, editor_mode;
1291 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CLEARALL,
1292 0, 0);
1293 vfs_uri = gnome_vfs_uri_new(uri);
1294 result = gnome_vfs_get_file_info_uri(vfs_uri, &info, GNOME_VFS_FILE_INFO_DEFAULT);
1295 if (result != GNOME_VFS_OK)
1297 *err = g_strdup (_("Could not get file info"));
1298 return FALSE;
1300 buffer = g_malloc (info.size);
1301 if (buffer == NULL && info.size != 0)
1303 DEBUG_PRINT ("This file is too big. Unable to allocate memory.");
1304 *err = g_strdup (_("This file is too big. Unable to allocate memory."));
1305 return FALSE;
1308 result = gnome_vfs_open_uri(&vfs_read, vfs_uri, GNOME_VFS_OPEN_READ);
1309 if (result != GNOME_VFS_OK)
1311 *err = g_strdup (_("Could not open file"));
1312 return FALSE;
1314 /* Crude way of loading, but faster */
1315 result = gnome_vfs_read (vfs_read, buffer, info.size, &nchars);
1316 if (result != GNOME_VFS_OK && !(result == GNOME_VFS_ERROR_EOF && info.size == 0))
1318 g_free(buffer);
1319 *err = g_strdup (_("Error while reading from file"));
1320 return FALSE;
1323 if (info.size != nchars) DEBUG_PRINT ("File size and loaded size not matching");
1324 dos_filter =
1325 anjuta_preferences_get_int (ANJUTA_PREFERENCES (te->preferences),
1326 DOS_EOL_CHECK);
1328 /* Set editor mode */
1329 editor_mode = determine_editor_mode (buffer, nchars);
1330 scintilla_send_message (SCINTILLA (te->scintilla),
1331 SCI_SETEOLMODE, editor_mode, 0);
1333 DEBUG_PRINT ("Loaded in editor mode [%d]", editor_mode);
1335 /* Determine character encoding and convert to utf-8*/
1336 if (nchars > 0)
1338 if (g_utf8_validate (buffer, nchars, NULL))
1340 if (te->encoding)
1341 g_free (te->encoding);
1342 te->encoding = NULL;
1344 else
1346 gchar *converted_text;
1348 converted_text = convert_to_utf8 (te->props_base,
1349 buffer, nchars, &te->encoding);
1351 if (converted_text == NULL)
1353 /* bail out */
1354 g_free (buffer);
1355 *err = g_strdup (_("The file does not look like a text file or the file encoding is not supported."
1356 " Please check if the encoding of file is in the supported encodings list."
1357 " If not, add it from the preferences."));
1358 gnome_vfs_close(vfs_read);
1359 return FALSE;
1361 g_free (buffer);
1362 buffer = converted_text;
1363 nchars = strlen (converted_text);
1366 if (dos_filter && editor_mode == SC_EOL_CRLF){
1367 DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Dos => Unix]");
1368 nchars = filter_chars_in_dos_mode( buffer, nchars );
1370 scintilla_send_message (SCINTILLA (te->scintilla), SCI_ADDTEXT,
1371 nchars, (long) buffer);
1373 g_free (buffer);
1374 gnome_vfs_close(vfs_read);
1375 return TRUE;
1378 static GnomeVFSResult
1379 save_to_file (TextEditor *te, gchar * uri)
1381 GnomeVFSHandle* vfs_write;
1382 GnomeVFSResult result;
1383 GnomeVFSFileSize nchars, size;
1384 gint strip;
1385 gchar *data;
1387 result = gnome_vfs_create (&vfs_write, uri, GNOME_VFS_OPEN_WRITE,
1388 FALSE, 0664);
1389 if (result != GNOME_VFS_OK)
1390 return result;
1392 nchars = scintilla_send_message (SCINTILLA (te->scintilla),
1393 SCI_GETLENGTH, 0, 0);
1394 data = (gchar *) aneditor_command (te->editor_id,
1395 ANE_GETTEXTRANGE, 0, nchars);
1396 if (data)
1398 gint dos_filter, editor_mode;
1400 size = strlen (data);
1402 /* Save according to the correct encoding */
1403 if (anjuta_preferences_get_int (te->preferences,
1404 SAVE_ENCODING_CURRENT_LOCALE))
1406 /* Save in current locate */
1407 GError *conv_error = NULL;
1408 gchar* converted_file_contents = NULL;
1410 DEBUG_PRINT ("Using current locale's encoding");
1412 converted_file_contents = g_locale_from_utf8 (data, -1, NULL,
1413 NULL, &conv_error);
1415 if (conv_error != NULL)
1417 /* Conversion error */
1418 g_error_free (conv_error);
1420 else
1422 g_free (data);
1423 data = converted_file_contents;
1424 size = strlen (converted_file_contents);
1427 else
1429 /* Save in original encoding */
1430 if ((te->encoding != NULL) &&
1431 anjuta_preferences_get_int (te->preferences,
1432 SAVE_ENCODING_ORIGINAL))
1434 GError *conv_error = NULL;
1435 gchar* converted_file_contents = NULL;
1437 DEBUG_PRINT ("Using encoding %s", te->encoding);
1439 /* Try to convert it from UTF-8 to original encoding */
1440 converted_file_contents = g_convert (data, -1,
1441 te->encoding,
1442 "UTF-8", NULL, NULL,
1443 &conv_error);
1445 if (conv_error != NULL)
1447 /* Conversion error */
1448 g_error_free (conv_error);
1450 else
1452 g_free (data);
1453 data = converted_file_contents;
1454 size = strlen (converted_file_contents);
1457 else
1459 /* Save in utf-8 */
1460 DEBUG_PRINT ("Using utf-8 encoding");
1464 /* Strip trailing spaces */
1465 strip = anjuta_preferences_get_int (te->preferences,
1466 STRIP_TRAILING_SPACES);
1467 if (strip)
1469 while (size > 0 && isspace(data[size - 1]))
1470 -- size;
1472 if ((size > 1) && ('\n' != data[size-1]))
1474 data[size] = '\n';
1475 ++ size;
1477 dos_filter = anjuta_preferences_get_int (te->preferences,
1478 DOS_EOL_CHECK);
1479 editor_mode = scintilla_send_message (SCINTILLA (te->scintilla),
1480 SCI_GETEOLMODE, 0, 0);
1481 DEBUG_PRINT ("Saving in editor mode [%d]", editor_mode);
1482 nchars = size;
1483 if (editor_mode == SC_EOL_CRLF && dos_filter)
1485 DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Unix => Dos]");
1486 size = save_filtered_in_dos_mode(vfs_write, data, size);
1488 else
1490 result = gnome_vfs_write(vfs_write, data, size, &nchars);
1492 g_free (data);
1495 if (result == GNOME_VFS_OK)
1496 result = gnome_vfs_close(vfs_write);
1497 else
1498 gnome_vfs_close (vfs_write);
1500 return result;
1503 gboolean
1504 text_editor_load_file (TextEditor * te)
1506 gchar *err = NULL;
1508 if (te == NULL || te->filename == NULL)
1509 return FALSE;
1510 if (IS_SCINTILLA (te->scintilla) == FALSE)
1511 return FALSE;
1512 anjuta_status (te->status, _("Loading file..."), 5);
1513 text_editor_freeze (te);
1514 // te->modified_time = time (NULL);
1515 text_editor_update_monitor (te, FALSE);
1516 if (load_from_file (te, te->uri, &err) == FALSE)
1518 anjuta_util_dialog_error (NULL,
1519 _("Could not load file: %s\n\nDetails: %s"),
1520 te->filename, err);
1521 g_free (err);
1522 text_editor_thaw (te);
1523 return FALSE;
1525 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
1526 0, 0);
1527 // check_tm_file(te);
1528 text_editor_thaw (te);
1529 scintilla_send_message (SCINTILLA (te->scintilla),
1530 SCI_SETSAVEPOINT, 0, 0);
1531 scintilla_send_message (SCINTILLA (te->scintilla),
1532 SCI_EMPTYUNDOBUFFER, 0, 0);
1533 text_editor_set_hilite_type (te, NULL);
1534 if (anjuta_preferences_get_int (te->preferences, FOLD_ON_OPEN))
1536 aneditor_command (te->editor_id, ANE_CLOSE_FOLDALL, 0, 0);
1538 text_editor_set_line_number_width(te);
1539 anjuta_status (te->status, _("File loaded successfully"), 5);
1540 return TRUE;
1543 gboolean
1544 text_editor_save_file (TextEditor * te, gboolean update)
1546 gboolean ret = FALSE;
1547 gchar *save_uri;
1548 GnomeVFSResult result;
1549 GtkWindow *parent;
1551 if (te == NULL)
1552 return FALSE;
1553 if (IS_SCINTILLA (te->scintilla) == FALSE)
1554 return FALSE;
1556 text_editor_freeze (te);
1557 text_editor_set_line_number_width(te);
1558 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (te)));
1560 anjuta_status (te->status, _("Saving file..."), 5);
1561 text_editor_update_monitor (te, TRUE);
1563 save_uri = g_strconcat (te->uri, "~", NULL);
1564 result = save_to_file (te, save_uri);
1565 if (result != GNOME_VFS_OK)
1567 GList *sources = NULL;
1568 GnomeVFSURI *vfs_uri;
1570 text_editor_thaw (te);
1571 anjuta_util_dialog_error (parent,
1572 _("Could not save intermediate file %s: %s."),
1573 save_uri,
1574 gnome_vfs_result_to_string (result));
1576 vfs_uri = gnome_vfs_uri_new (save_uri);
1577 sources = g_list_append (sources, vfs_uri);
1578 gnome_vfs_xfer_delete_list (sources, GNOME_VFS_XFER_ERROR_MODE_ABORT,
1579 GNOME_VFS_XFER_DELETE_ITEMS |
1580 GNOME_VFS_XFER_REMOVESOURCE, NULL, NULL);
1581 g_list_free (sources);
1582 gnome_vfs_uri_unref (vfs_uri);
1584 else
1586 GnomeVFSURI *src_uri;
1587 GnomeVFSURI *dest_uri;
1589 src_uri = gnome_vfs_uri_new (save_uri);
1590 dest_uri = gnome_vfs_uri_new (te->uri);
1592 /* Move 'file~' to 'file' */
1593 result = gnome_vfs_xfer_uri (src_uri, dest_uri,
1594 GNOME_VFS_XFER_DELETE_ITEMS |
1595 GNOME_VFS_XFER_REMOVESOURCE,
1596 GNOME_VFS_XFER_ERROR_MODE_ABORT,
1597 GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
1598 NULL, NULL);
1599 /* we need to update UI with the call to scintilla */
1600 text_editor_thaw (te);
1601 if (result != GNOME_VFS_OK)
1603 anjuta_util_dialog_error (parent,
1604 _("Could not save file %s: %s."),
1605 te->uri,
1606 gnome_vfs_result_to_string (result));
1608 else
1610 scintilla_send_message (SCINTILLA (te->scintilla),
1611 SCI_SETSAVEPOINT, 0, 0);
1612 g_signal_emit_by_name (G_OBJECT (te), "saved", te->uri);
1613 anjuta_status (te->status, _("File saved successfully"), 5);
1614 ret = TRUE;
1616 gnome_vfs_uri_unref (src_uri);
1617 gnome_vfs_uri_unref (dest_uri);
1619 text_editor_update_monitor (te, FALSE);
1620 g_free (save_uri);
1621 return ret;
1624 gboolean
1625 text_editor_save_yourself (TextEditor * te, FILE * stream)
1627 return TRUE;
1630 gboolean
1631 text_editor_recover_yourself (TextEditor * te, FILE * stream)
1633 return TRUE;
1636 void
1637 text_editor_undo (TextEditor * te)
1639 scintilla_send_message (SCINTILLA (te->scintilla),
1640 SCI_UNDO, 0, 0);
1643 void
1644 text_editor_redo (TextEditor * te)
1646 scintilla_send_message (SCINTILLA (te->scintilla),
1647 SCI_REDO, 0, 0);
1650 void
1651 text_editor_update_controls (TextEditor * te)
1653 #if 0 //FIXME
1654 gboolean F, P, L, C, S;
1656 if (te == NULL)
1657 return;
1658 S = text_editor_is_saved (te);
1659 L = anjuta_launcher_is_busy (app->launcher);
1660 P = app->project_dbase->project_is_open;
1662 switch (get_file_ext_type (te->filename))
1664 case FILE_TYPE_C:
1665 case FILE_TYPE_CPP:
1666 case FILE_TYPE_ASM:
1667 F = TRUE;
1668 break;
1669 default:
1670 F = FALSE;
1672 switch (get_file_ext_type (te->filename))
1674 case FILE_TYPE_C:
1675 case FILE_TYPE_CPP:
1676 case FILE_TYPE_HEADER:
1677 C = TRUE;
1678 break;
1679 default:
1680 C = FALSE;
1682 gtk_widget_set_sensitive (te->buttons.save, !S);
1683 gtk_widget_set_sensitive (te->buttons.reload,
1684 (te->uri != NULL));
1685 gtk_widget_set_sensitive (te->buttons.compile, F && !L);
1686 gtk_widget_set_sensitive (te->buttons.build, (F || P) && !L);
1687 #endif
1690 gboolean
1691 text_editor_is_saved (TextEditor * te)
1693 return !(scintilla_send_message (SCINTILLA (te->scintilla),
1694 SCI_GETMODIFY, 0, 0));
1697 gboolean
1698 text_editor_has_selection (TextEditor * te)
1700 gint from, to;
1701 from = scintilla_send_message (SCINTILLA (te->scintilla),
1702 SCI_GETSELECTIONSTART, 0, 0);
1703 to = scintilla_send_message (SCINTILLA (te->scintilla),
1704 SCI_GETSELECTIONEND, 0, 0);
1705 return (from == to) ? FALSE : TRUE;
1708 glong text_editor_get_selection_start (TextEditor * te)
1710 return scintilla_send_message (SCINTILLA (te->scintilla),
1711 SCI_GETSELECTIONSTART, 0, 0);
1714 glong text_editor_get_selection_end (TextEditor * te)
1716 return scintilla_send_message (SCINTILLA (te->scintilla),
1717 SCI_GETSELECTIONEND, 0, 0);
1720 gchar*
1721 text_editor_get_selection (TextEditor * te)
1723 guint from, to;
1724 struct TextRange tr;
1726 from = scintilla_send_message (SCINTILLA (te->scintilla),
1727 SCI_GETSELECTIONSTART, 0, 0);
1728 to = scintilla_send_message (SCINTILLA (te->scintilla),
1729 SCI_GETSELECTIONEND, 0, 0);
1730 if (from == to)
1731 return NULL;
1732 tr.chrg.cpMin = MIN(from, to);
1733 tr.chrg.cpMax = MAX(from, to);
1734 tr.lpstrText = g_malloc (sizeof(gchar)*(tr.chrg.cpMax-tr.chrg.cpMin)+5);
1735 scintilla_send_message (SCINTILLA(te->scintilla), SCI_GETTEXTRANGE, 0, (long)(&tr));
1736 return tr.lpstrText;
1739 gboolean
1740 text_editor_is_marker_set (TextEditor* te, glong line, gint marker)
1742 gint state;
1744 g_return_val_if_fail (te != NULL, FALSE);
1745 g_return_val_if_fail (line >= 0, FALSE);
1746 g_return_val_if_fail (marker < 32, FALSE);
1748 state = scintilla_send_message (SCINTILLA(te->scintilla),
1749 SCI_MARKERGET, linenum_text_editor_to_scintilla (line), 0);
1750 return ((state & (1 << marker)));
1753 void
1754 text_editor_delete_marker_all (TextEditor *te, gint marker)
1756 g_return_if_fail (IS_TEXT_EDITOR (te));
1757 g_return_if_fail (marker < 32);
1758 scintilla_send_message (SCINTILLA (te->scintilla),
1759 SCI_MARKERDELETEALL, marker, 0);
1762 void
1763 text_editor_delete_marker (TextEditor* te, glong line, gint marker)
1765 g_return_if_fail (IS_TEXT_EDITOR (te));
1766 g_return_if_fail (line >= 0);
1767 g_return_if_fail (marker < 32);
1769 scintilla_send_message (SCINTILLA(te->scintilla),
1770 SCI_MARKERDELETE, linenum_text_editor_to_scintilla (line), marker);
1773 gint
1774 text_editor_line_from_handle (TextEditor* te, gint marker_handle)
1776 gint line;
1778 g_return_val_if_fail (te != NULL, -1);
1780 line = scintilla_send_message (SCINTILLA(te->scintilla),
1781 SCI_MARKERLINEFROMHANDLE, marker_handle, 0);
1783 return linenum_scintilla_to_text_editor (line);
1786 gint
1787 text_editor_get_bookmark_line( TextEditor* te, const glong nLineStart )
1789 return aneditor_command (te->editor_id, ANE_GETBOOKMARK_POS, nLineStart, 0);
1792 gint
1793 text_editor_get_num_bookmarks(TextEditor* te)
1795 gint nLineNo = -1 ;
1796 gint nMarkers = 0 ;
1798 g_return_val_if_fail (te != NULL, 0 );
1800 while( ( nLineNo = text_editor_get_bookmark_line( te, nLineNo ) ) >= 0 )
1802 //printf( "Line %d\n", nLineNo );
1803 nMarkers++;
1805 //printf( "out Line %d\n", nLineNo );
1806 return nMarkers ;
1810 *Get the current selection. If there is no selection, or if the selection
1811 * is all blanks, get the word under teh cursor.
1813 gchar
1814 *text_editor_get_current_word(TextEditor *te)
1816 char *buf = text_editor_get_selection(te);
1817 if (buf)
1819 g_strstrip(buf);
1820 if ('\0' == *buf)
1822 g_free(buf);
1823 buf = NULL;
1826 if (NULL == buf)
1828 int ret;
1829 buf = g_new(char, 256);
1830 ret = aneditor_command (te->editor_id, ANE_GETCURRENTWORD, (long)buf, 255L);
1831 if (!ret)
1833 g_free(buf);
1834 buf = NULL;
1837 #ifdef DEBUG
1838 if (buf)
1839 DEBUG_PRINT ("Current word is '%s'", buf);
1840 #endif
1841 return buf;
1844 void
1845 text_editor_function_select(TextEditor *te)
1847 gint pos;
1848 gint line;
1849 gint fold_level;
1850 gint start, end;
1851 gint line_count;
1852 gint tmp;
1854 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
1855 SCI_GETLINECOUNT, 0, 0);
1856 pos = scintilla_send_message(SCINTILLA(te->scintilla),
1857 SCI_GETCURRENTPOS, 0, 0);
1858 line = scintilla_send_message(SCINTILLA(te->scintilla),
1859 SCI_LINEFROMPOSITION, pos, 0);
1861 tmp = line + 1;
1862 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1863 SCI_GETFOLDLEVEL, line, 0) ;
1864 if ((fold_level & 0xFF) != 0)
1866 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
1867 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1868 SCI_GETFOLDLEVEL, --line, 0) ;
1869 start = scintilla_send_message(SCINTILLA(te->scintilla),
1870 SCI_POSITIONFROMLINE, line + 1, 0);
1871 line = tmp;
1872 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1873 SCI_GETFOLDLEVEL, line, 0) ;
1874 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
1875 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1876 SCI_GETFOLDLEVEL, ++line, 0) ;
1878 end = scintilla_send_message(SCINTILLA(te->scintilla),
1879 SCI_POSITIONFROMLINE, line , 0);
1880 scintilla_send_message(SCINTILLA(te->scintilla),
1881 SCI_SETSEL, start, end) ;
1885 void
1886 text_editor_grab_focus (TextEditor *te)
1888 g_return_if_fail (IS_TEXT_EDITOR (te));
1889 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GRABFOCUS, 0, 0);
1892 void
1893 text_editor_set_popup_menu (TextEditor *te, GtkWidget *popup_menu)
1895 if (popup_menu)
1896 g_object_ref (popup_menu);
1897 if (te->popup_menu)
1898 g_object_unref (te->popup_menu);
1899 te->popup_menu = popup_menu;
1902 void
1903 text_editor_set_busy (TextEditor *te, gboolean state)
1905 if (state)
1906 scintilla_send_message (SCINTILLA (te->scintilla),
1907 SCI_SETCURSOR, SC_CURSORWAIT, 0);
1908 else
1909 scintilla_send_message (SCINTILLA (te->scintilla),
1910 SCI_SETCURSOR, SC_CURSORNORMAL, 0);
1913 gint
1914 text_editor_get_props ()
1916 /* Built in values */
1917 static PropsID props_built_in = 0;
1919 /* System values */
1920 static PropsID props_global = 0;
1922 /* User values */
1923 // static PropsID props_local = 0;
1925 /* Session values */
1926 static PropsID props_session = 0;
1928 /* Instance values */
1929 static PropsID props = 0;
1931 gchar *propdir, *propfile;
1933 if (props)
1934 return props;
1936 props_built_in = sci_prop_set_new ();
1937 props_global = sci_prop_set_new ();
1938 // props_local = sci_prop_set_new ();
1939 props_session = sci_prop_set_new ();
1940 props = sci_prop_set_new ();
1942 sci_prop_clear (props_built_in);
1943 sci_prop_clear (props_global);
1944 // sci_prop_clear (props_local);
1945 sci_prop_clear (props_session);
1946 sci_prop_clear (props);
1948 sci_prop_set_parent (props_global, props_built_in);
1949 // sci_prop_set_parent (props_local, props_global);
1950 // sci_prop_set_parent (props_session, props_local);
1951 sci_prop_set_parent (props_session, props_global);
1952 sci_prop_set_parent (props, props_session);
1954 propdir = g_build_filename (PACKAGE_DATA_DIR, "properties/", NULL);
1955 propfile = g_build_filename (PACKAGE_DATA_DIR, "properties",
1956 "anjuta.properties", NULL);
1957 DEBUG_PRINT ("Reading file: %s", propfile);
1959 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE)
1961 anjuta_util_dialog_error (NULL,
1962 _("Cannot load Global defaults and configuration files:\n"
1963 "%s.\n"
1964 "This may result in improper behaviour or instabilities.\n"
1965 "Anjuta will fall back to built in (limited) settings"),
1966 propfile);
1968 sci_prop_read (props_global, propfile, propdir);
1969 g_free (propfile);
1970 g_free (propdir);
1972 propdir = g_build_filename (g_get_home_dir(), ".anjuta" PREF_SUFFIX "/", NULL);
1973 propfile = g_build_filename (g_get_home_dir(), ".anjuta" PREF_SUFFIX,
1974 "editor-style.properties", NULL);
1975 DEBUG_PRINT ("Reading file: %s", propfile);
1977 /* Create user.properties file, if it doesn't exist */
1978 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE) {
1979 gchar* old_propfile = g_build_filename (g_get_home_dir(),
1980 ".anjuta"PREF_SUFFIX,
1981 "session.properties", NULL);
1982 if (g_file_test (old_propfile, G_FILE_TEST_EXISTS) == TRUE)
1983 anjuta_util_copy_file (old_propfile, propfile, FALSE);
1984 g_free (old_propfile);
1986 sci_prop_read (props_session, propfile, propdir);
1987 g_free (propdir);
1988 g_free (propfile);
1990 return props;
1993 void
1994 text_editor_set_line_number_width (TextEditor* te)
1996 /* Set line numbers with according to file size */
1997 if (anjuta_preferences_get_int_with_default(te->preferences,
1998 "margin.linenumber.visible", 0))
2000 int lines, line_number_width;
2001 gchar* line_number;
2002 gchar* line_number_dummy;
2004 lines =
2005 (int) scintilla_send_message
2006 (SCINTILLA(te->scintilla), SCI_GETLINECOUNT, 0,0);
2007 line_number = g_strdup_printf("%d", lines);
2008 line_number_dummy = g_strnfill(strlen(line_number) + 1, '9');
2009 line_number_width =
2010 (int) scintilla_send_message (SCINTILLA(te->scintilla),
2011 SCI_TEXTWIDTH,
2012 STYLE_LINENUMBER,
2013 (long) line_number_dummy);
2014 text_editor_command (te, ANE_SETLINENUMWIDTH, line_number_width, 0);
2015 g_free(line_number_dummy);
2016 g_free(line_number);
2020 gboolean
2021 text_editor_can_undo (TextEditor *te)
2023 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2024 return scintilla_send_message (SCINTILLA (te->scintilla),
2025 SCI_CANUNDO, 0, 0);
2028 gboolean
2029 text_editor_can_redo (TextEditor *te)
2031 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2032 return scintilla_send_message (SCINTILLA (te->scintilla),
2033 SCI_CANREDO, 0, 0);
2036 void
2037 text_editor_command (TextEditor *te, gint command, glong wparam, glong lparam)
2039 GList *node;
2041 node = te->views;
2042 while (node)
2044 aneditor_command (GPOINTER_TO_INT (node->data), command, wparam, lparam);
2045 node = g_list_next(node);
2049 void
2050 text_editor_scintilla_command (TextEditor *te, gint command, glong wparam,
2051 glong lparam)
2053 GList *node;
2055 node = te->views;
2056 while (node)
2058 GtkWidget *scintilla;
2059 scintilla = aneditor_get_widget (GPOINTER_TO_INT (node->data));
2060 scintilla_send_message (SCINTILLA(scintilla), command, wparam, lparam);
2061 node = g_list_next(node);
2065 /* IAnjutaEditor interface implementation */
2067 static gint
2068 itext_editor_get_tab_size (IAnjutaEditor *editor, GError **e)
2070 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2071 SCI_GETTABWIDTH, 0, 0);
2074 static void
2075 itext_editor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
2077 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2078 SCI_SETTABWIDTH, tabsize, 0);
2081 static gboolean
2082 itext_editor_get_use_spaces (IAnjutaEditor *editor, GError **e)
2084 return !scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2085 SCI_GETUSETABS, 0, 0);
2088 static void
2089 itext_editor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
2091 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2092 SCI_SETUSETABS, !use_spaces, 0);
2095 static void
2096 itext_editor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
2098 text_editor_command (TEXT_EDITOR(editor), ANE_SETINDENTMAINTAIN, auto_indent, 0);
2101 static void
2102 itext_editor_goto_line (IAnjutaEditor *editor, gint lineno, GError **e)
2104 text_editor_goto_line (TEXT_EDITOR (editor), lineno, FALSE, TRUE);
2107 static void
2108 itext_editor_goto_position (IAnjutaEditor *editor, gint position, GError **e)
2110 text_editor_goto_point (TEXT_EDITOR (editor), position);
2113 static gchar*
2114 itext_editor_get_text (IAnjutaEditor *editor, gint position, gint length,
2115 GError **e)
2117 gchar *data;
2118 gint end;
2119 TextEditor *te = TEXT_EDITOR (editor);
2121 g_return_val_if_fail (position >= 0, NULL);
2122 if (length == 0)
2123 return NULL;
2125 if (length < 0)
2126 end = scintilla_send_message (SCINTILLA (te->scintilla),
2127 SCI_GETLENGTH, 0, 0);
2128 else
2129 end = position + length;
2131 data = (gchar *) aneditor_command (te->editor_id,
2132 ANE_GETTEXTRANGE, position, end);
2133 return data;
2136 static gint
2137 itext_editor_get_position (IAnjutaEditor *editor, GError **e)
2139 return text_editor_get_current_position (TEXT_EDITOR(editor));
2142 static gint
2143 itext_editor_get_lineno (IAnjutaEditor *editor, GError **e)
2145 return text_editor_get_current_lineno (TEXT_EDITOR (editor));
2148 static gint
2149 itext_editor_get_length (IAnjutaEditor *editor, GError **e)
2151 return aneditor_command (TEXT_EDITOR (editor)->editor_id,
2152 ANE_GETLENGTH, 0, 0);
2155 static gchar*
2156 itext_editor_get_current_word (IAnjutaEditor *editor, GError **e)
2158 gchar buffer[512];
2159 buffer[0] = '\0';
2160 aneditor_command (TEXT_EDITOR (editor)->editor_id,
2161 ANE_GETCURRENTWORD, (glong) buffer, 512);
2162 if (buffer[0] != '\0')
2163 return g_strdup (buffer);
2164 else
2165 return NULL;
2168 static void
2169 itext_editor_insert (IAnjutaEditor *editor, gint pos, const gchar *txt,
2170 gint length, GError **e)
2172 gchar *text_to_insert;
2173 if (length >= 0)
2174 text_to_insert = g_strndup (txt, length);
2175 else
2176 text_to_insert = g_strdup (txt);
2178 aneditor_command (TEXT_EDITOR(editor)->editor_id, ANE_INSERTTEXT,
2179 pos, (long)text_to_insert);
2180 g_free (text_to_insert);
2183 static void
2184 itext_editor_append (IAnjutaEditor *editor, const gchar *txt,
2185 gint length, GError **e)
2187 gchar *text_to_insert;
2188 if (length >= 0)
2189 text_to_insert = g_strndup (txt, length);
2190 else
2191 text_to_insert = g_strdup (txt);
2193 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2194 SCI_APPENDTEXT, strlen(text_to_insert),
2195 (long)text_to_insert);
2196 g_free (text_to_insert);
2199 static void
2200 itext_editor_erase (IAnjutaEditor *editor, gint position, gint length,
2201 GError **e)
2203 gint end;
2205 g_return_if_fail (position >= 0);
2206 if (length == 0)
2207 return;
2209 if (length < 0)
2210 end = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2211 SCI_GETLENGTH, 0, 0);
2212 else
2213 end = position + length;
2215 ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (editor) , position,
2216 end, FALSE, NULL);
2217 text_editor_replace_selection (TEXT_EDITOR (editor), "");
2220 static void
2221 itext_editor_erase_all (IAnjutaEditor *editor, GError **e)
2223 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla), SCI_CLEARALL,
2224 0, 0);
2227 static const gchar *
2228 itext_editor_get_filename (IAnjutaEditor *editor, GError **e)
2230 return (TEXT_EDITOR (editor))->filename;
2233 static gboolean
2234 itext_editor_can_undo(IAnjutaEditor *editor, GError **e)
2236 return text_editor_can_undo(TEXT_EDITOR(editor));
2239 static gboolean
2240 itext_editor_can_redo(IAnjutaEditor *editor, GError **e)
2242 return text_editor_can_redo(TEXT_EDITOR(editor));
2245 static void
2246 itext_editor_undo(IAnjutaEditor* te, GError** ee)
2248 text_editor_command(TEXT_EDITOR(te), ANE_UNDO, 0, 0);
2251 static void
2252 itext_editor_begin_undo_action (IAnjutaEditor* te, GError** ee)
2254 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2255 SCI_BEGINUNDOACTION, 0, 0);
2258 static void
2259 itext_editor_end_undo_action (IAnjutaEditor* te, GError** ee)
2261 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2262 SCI_ENDUNDOACTION, 0, 0);
2265 static void
2266 itext_editor_redo(IAnjutaEditor* te, GError** ee)
2268 text_editor_command(TEXT_EDITOR(te), ANE_REDO, 0, 0);
2271 static int
2272 itext_editor_get_column(IAnjutaEditor *editor, GError **e)
2274 return text_editor_get_current_column(TEXT_EDITOR(editor));
2277 static gboolean
2278 itext_editor_get_overwrite(IAnjutaEditor *editor, GError **e)
2280 return text_editor_get_overwrite(TEXT_EDITOR(editor));
2283 static void
2284 itext_editor_set_popup_menu(IAnjutaEditor *editor, GtkWidget* menu, GError **e)
2286 text_editor_set_popup_menu(TEXT_EDITOR(editor), menu);
2289 static gint
2290 itext_editor_get_line_from_position (IAnjutaEditor *editor, gint pos, GError **e)
2292 return text_editor_get_line_from_position (TEXT_EDITOR (editor), pos);
2295 static gint
2296 itext_editor_get_line_begin_position (IAnjutaEditor *editor, gint line,
2297 GError **e)
2299 gint ln;
2301 g_return_val_if_fail (line > 0, -1);
2303 ln = linenum_text_editor_to_scintilla (line);
2304 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2305 SCI_POSITIONFROMLINE, ln, 0);
2308 static gint
2309 itext_editor_get_line_end_position (IAnjutaEditor *editor, gint line,
2310 GError **e)
2312 gint ln;
2314 g_return_val_if_fail (line > 0, -1);
2316 ln = linenum_text_editor_to_scintilla (line);
2317 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2318 SCI_GETLINEENDPOSITION, ln, 0);
2321 static IAnjutaIterable*
2322 itext_editor_get_cell_iter (IAnjutaEditor *editor, gint position, GError **e)
2324 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), position);
2325 return IANJUTA_ITERABLE (editor_cell);
2328 static void
2329 itext_editor_grab_focus (IAnjutaEditor *editor, GError **e)
2331 text_editor_grab_focus (TEXT_EDITOR (editor));
2334 static void
2335 itext_editor_iface_init (IAnjutaEditorIface *iface)
2337 iface->get_tabsize = itext_editor_get_tab_size;
2338 iface->set_tabsize = itext_editor_set_tab_size;
2339 iface->get_use_spaces = itext_editor_get_use_spaces;
2340 iface->set_use_spaces = itext_editor_set_use_spaces;
2341 iface->set_auto_indent = itext_editor_set_auto_indent;
2342 iface->goto_line = itext_editor_goto_line;
2343 iface->goto_position = itext_editor_goto_position;
2344 iface->get_text = itext_editor_get_text;
2345 iface->get_position = itext_editor_get_position;
2346 iface->get_lineno = itext_editor_get_lineno;
2347 iface->get_length = itext_editor_get_length;
2348 iface->get_current_word = itext_editor_get_current_word;
2349 iface->insert = itext_editor_insert;
2350 iface->append = itext_editor_append;
2351 iface->erase = itext_editor_erase;
2352 iface->erase_all = itext_editor_erase_all;
2353 iface->get_filename = itext_editor_get_filename;
2354 iface->can_undo = itext_editor_can_undo;
2355 iface->can_redo = itext_editor_can_redo;
2356 iface->undo = itext_editor_undo;
2357 iface->redo = itext_editor_redo;
2358 iface->begin_undo_action = itext_editor_begin_undo_action;
2359 iface->end_undo_action = itext_editor_end_undo_action;
2360 iface->get_column = itext_editor_get_column;
2361 iface->get_overwrite = itext_editor_get_overwrite;
2362 iface->set_popup_menu = itext_editor_set_popup_menu;
2363 iface->get_line_from_position = itext_editor_get_line_from_position;
2364 iface->get_line_begin_position = itext_editor_get_line_begin_position;
2365 iface->get_line_end_position = itext_editor_get_line_end_position;
2366 iface->get_cell_iter = itext_editor_get_cell_iter;
2367 iface->grab_focus = itext_editor_grab_focus;
2370 /* IAnjutaEditorSelection implementation */
2372 static gchar*
2373 iselection_get (IAnjutaEditorSelection *editor, GError **error)
2375 return text_editor_get_selection (TEXT_EDITOR (editor));
2378 static void
2379 iselection_set (IAnjutaEditorSelection *editor, gint start, gint end,
2380 gboolean backwards, GError **e)
2382 if (!backwards)
2383 scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2384 SCI_SETSEL, start, end);
2385 else
2386 scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2387 SCI_SETSEL, end, start);
2390 static int
2391 iselection_get_start(IAnjutaEditorSelection *editor, GError **e)
2393 return scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2394 SCI_GETSELECTIONSTART,0,0);
2397 static int
2398 iselection_get_end(IAnjutaEditorSelection *editor, GError **e)
2400 return scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2401 SCI_GETSELECTIONEND, 0, 0);
2404 static void
2405 iselection_replace (IAnjutaEditorSelection *editor, const gchar *txt,
2406 gint length, GError **e)
2408 gchar *text_to_insert;
2409 if (length >= 0)
2410 text_to_insert = g_strndup (txt, length);
2411 else
2412 text_to_insert = g_strdup (txt);
2414 text_editor_replace_selection (TEXT_EDITOR (editor), text_to_insert);
2416 g_free (text_to_insert);
2419 static void
2420 iselection_select_all(IAnjutaEditorSelection* te, GError** ee)
2422 text_editor_command(TEXT_EDITOR(te), ANE_SELECTALL, 0, 0);
2425 static void
2426 iselection_select_to_brace(IAnjutaEditorSelection* te, GError** ee)
2428 text_editor_command(TEXT_EDITOR(te), ANE_SELECTTOBRACE, 0, 0);
2431 static void
2432 iselection_select_block(IAnjutaEditorSelection *te, GError **e)
2434 text_editor_command(TEXT_EDITOR(te), ANE_SELECTBLOCK, 0, 0);
2437 static void
2438 iselection_select_function(IAnjutaEditorSelection *editor, GError **e)
2440 TextEditor* te = TEXT_EDITOR(editor);
2441 gint pos;
2442 gint line;
2443 gint fold_level;
2444 gint start, end;
2445 gint line_count;
2446 gint tmp;
2448 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
2449 SCI_GETLINECOUNT, 0, 0);
2450 pos = scintilla_send_message(SCINTILLA(te->scintilla),
2451 SCI_GETCURRENTPOS, 0, 0);
2452 line = scintilla_send_message(SCINTILLA(te->scintilla),
2453 SCI_LINEFROMPOSITION, pos, 0);
2455 tmp = line + 1;
2456 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2457 SCI_GETFOLDLEVEL, line, 0) ;
2458 if ((fold_level & 0xFF) != 0)
2460 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
2461 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2462 SCI_GETFOLDLEVEL, --line, 0) ;
2463 start = scintilla_send_message(SCINTILLA(te->scintilla),
2464 SCI_POSITIONFROMLINE, line + 1, 0);
2465 line = tmp;
2466 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2467 SCI_GETFOLDLEVEL, line, 0) ;
2468 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
2469 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2470 SCI_GETFOLDLEVEL, ++line, 0) ;
2472 end = scintilla_send_message(SCINTILLA(te->scintilla),
2473 SCI_POSITIONFROMLINE, line , 0);
2474 scintilla_send_message(SCINTILLA(te->scintilla),
2475 SCI_SETSEL, start, end) ;
2479 static void
2480 iselection_cut(IAnjutaEditorSelection* te, GError** ee)
2482 text_editor_command(TEXT_EDITOR(te), ANE_CUT, 0, 0);
2485 static void
2486 iselection_copy(IAnjutaEditorSelection* te, GError** ee)
2488 text_editor_command(TEXT_EDITOR(te), ANE_COPY, 0, 0);
2491 static void
2492 iselection_paste(IAnjutaEditorSelection* te, GError** ee)
2494 text_editor_command(TEXT_EDITOR(te), ANE_PASTE, 0, 0);
2497 static void
2498 iselection_clear(IAnjutaEditorSelection* te, GError** ee)
2500 text_editor_command(TEXT_EDITOR(te), ANE_CLEAR, 0, 0);
2503 static void
2504 iselection_iface_init (IAnjutaEditorSelectionIface *iface)
2506 iface->get = iselection_get;
2507 iface->set = iselection_set;
2508 iface->get_start = iselection_get_start;
2509 iface->get_end = iselection_get_end;
2510 iface->replace = iselection_replace;
2511 iface->select_all = iselection_select_all;
2512 iface->select_to_brace = iselection_select_to_brace;
2513 iface->select_block = iselection_select_block;
2514 iface->select_function = iselection_select_function;
2515 iface->cut = iselection_cut;
2516 iface->copy = iselection_copy;
2517 iface->paste = iselection_paste;
2518 iface->clear = iselection_clear;
2521 /* IAnjutaFile implementation */
2523 static gchar*
2524 ifile_get_uri (IAnjutaFile *editor, GError **error)
2526 TextEditor *text_editor;
2527 text_editor = TEXT_EDITOR(editor);
2528 if (text_editor->uri)
2529 return g_strdup (text_editor->uri);
2531 else if (text_editor->filename)
2532 return gnome_vfs_get_uri_from_local_path (text_editor->filename);
2534 else
2535 return NULL;
2538 static void
2539 ifile_open (IAnjutaFile *editor, const gchar* uri, GError **error)
2541 /* Close current file and open new file in this editor */
2542 TextEditor* text_editor;
2543 text_editor = TEXT_EDITOR(editor);
2545 /* Do nothing if current file is not saved */
2546 if (!text_editor_is_saved (text_editor))
2547 return;
2548 text_editor->uri = g_strdup (uri);
2550 /* Remove path */
2551 text_editor->filename = g_strdup (g_basename (uri));
2552 text_editor_load_file (text_editor);
2555 static void
2556 isaveable_save (IAnjutaFileSavable* editor, GError** e)
2558 TextEditor *text_editor = TEXT_EDITOR(editor);
2559 if (text_editor->uri != NULL)
2560 text_editor_save_file(text_editor, FALSE);
2563 static void
2564 isavable_save_as (IAnjutaFileSavable* editor, const gchar* filename, GError** e)
2566 TextEditor *text_editor = TEXT_EDITOR(editor);
2567 text_editor->uri = g_strdup(filename);
2568 /* Remove path */
2569 text_editor->filename = g_strdup(strrchr(filename, '/') + 1);
2570 text_editor_save_file(text_editor, FALSE);
2573 static gboolean
2574 isavable_is_dirty (IAnjutaFileSavable* editor, GError** e)
2576 TextEditor *text_editor = TEXT_EDITOR(editor);
2577 return !text_editor_is_saved(text_editor);
2580 static void
2581 isavable_set_dirty (IAnjutaFileSavable* editor, gboolean dirty, GError** e)
2583 DEBUG_PRINT("set_dirty: Not implemented in EditorPlugin");
2587 static void
2588 isavable_iface_init (IAnjutaFileSavableIface *iface)
2590 iface->save = isaveable_save;
2591 iface->save_as = isavable_save_as;
2592 iface->set_dirty = isavable_set_dirty;
2593 iface->is_dirty = isavable_is_dirty;
2596 static void
2597 ifile_iface_init (IAnjutaFileIface *iface)
2599 iface->open = ifile_open;
2600 iface->get_uri = ifile_get_uri;
2603 /* Implementation of the IAnjutaMarkable interface */
2605 static gint
2606 marker_ianjuta_to_editor (IAnjutaMarkableMarker marker)
2608 gint mark;
2609 switch (marker)
2611 case IANJUTA_MARKABLE_LINEMARKER:
2612 mark = TEXT_EDITOR_LINEMARKER;
2613 break;
2614 case IANJUTA_MARKABLE_BOOKMARK:
2615 mark = TEXT_EDITOR_BOOKMARK;
2616 break;
2617 case IANJUTA_MARKABLE_BREAKPOINT_DISABLED:
2618 mark = TEXT_EDITOR_BREAKPOINT_DISABLED;
2619 break;
2620 case IANJUTA_MARKABLE_BREAKPOINT_ENABLED:
2621 mark = TEXT_EDITOR_BREAKPOINT_ENABLED;
2622 break;
2623 case IANJUTA_MARKABLE_PROGRAM_COUNTER:
2624 mark = TEXT_EDITOR_PROGRAM_COUNTER;
2625 break;
2626 default:
2627 mark = TEXT_EDITOR_LINEMARKER;
2629 return mark;
2632 static gint
2633 imarkable_mark (IAnjutaMarkable* editor, gint location,
2634 IAnjutaMarkableMarker marker, GError** e)
2636 return text_editor_set_marker (TEXT_EDITOR (editor), location,
2637 marker_ianjuta_to_editor (marker));
2640 static gint
2641 imarkable_location_from_handle (IAnjutaMarkable* editor, gint handle, GError** e)
2643 return text_editor_line_from_handle (TEXT_EDITOR (editor), handle);
2646 static void
2647 imarkable_unmark (IAnjutaMarkable* editor, gint location,
2648 IAnjutaMarkableMarker marker, GError** e)
2650 text_editor_delete_marker (TEXT_EDITOR (editor), location,
2651 marker_ianjuta_to_editor (marker));
2654 static gboolean
2655 imarkable_is_marker_set (IAnjutaMarkable* editor, gint location,
2656 IAnjutaMarkableMarker marker, GError** e)
2658 return text_editor_is_marker_set (TEXT_EDITOR (editor), location,
2659 marker_ianjuta_to_editor (marker));
2662 static void
2663 imarkable_delete_all_markers (IAnjutaMarkable* editor,
2664 IAnjutaMarkableMarker marker, GError** e)
2666 text_editor_delete_marker_all (TEXT_EDITOR (editor),
2667 marker_ianjuta_to_editor (marker));
2670 static void
2671 imarkable_iface_init (IAnjutaMarkableIface *iface)
2673 iface->mark = imarkable_mark;
2674 iface->location_from_handle = imarkable_location_from_handle;
2675 iface->unmark = imarkable_unmark;
2676 iface->is_marker_set = imarkable_is_marker_set;
2677 iface->delete_all_markers = imarkable_delete_all_markers;
2680 /* IAnjutaEditorFactory implementation */
2682 static IAnjutaEditor*
2683 itext_editor_factory_new_editor(IAnjutaEditorFactory* factory,
2684 const gchar* uri,
2685 const gchar* filename,
2686 GError** error)
2688 TextEditor *current_editor = TEXT_EDITOR (factory);
2689 GtkWidget* editor = text_editor_new (current_editor->status,
2690 current_editor->preferences,
2691 uri, filename);
2692 return IANJUTA_EDITOR (editor);
2695 static void
2696 itext_editor_factory_iface_init (IAnjutaEditorFactoryIface *iface)
2698 iface->new_editor = itext_editor_factory_new_editor;
2701 /* IAnjutaEditorConvert implementation */
2703 static void
2704 iconvert_to_upper(IAnjutaEditorConvert* te, gint start_position,
2705 gint end_position, GError** ee)
2707 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
2708 SCI_SETSEL, start_position, end_position);
2709 text_editor_command (TEXT_EDITOR(te), ANE_UPRCASE, 0, 0);
2712 static void
2713 iconvert_to_lower(IAnjutaEditorConvert* te, gint start_position,
2714 gint end_position, GError** ee)
2716 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
2717 SCI_SETSEL, start_position, end_position);
2718 text_editor_command (TEXT_EDITOR(te), ANE_LWRCASE, 0, 0);
2721 static void
2722 iconvert_iface_init (IAnjutaEditorConvertIface *iface)
2724 iface->to_lower = iconvert_to_lower;
2725 iface->to_upper = iconvert_to_upper;
2728 /* IAnjutaEditorLineMode implementation */
2730 static IAnjutaEditorLineModeType
2731 ilinemode_get (IAnjutaEditorLineMode* te, GError** err)
2733 glong eolmode;
2734 IAnjutaEditorLineModeType retmode;
2736 g_return_val_if_fail (IS_TEXT_EDITOR (te), IANJUTA_EDITOR_LINE_MODE_LF);
2738 eolmode = scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2739 SCI_GETEOLMODE, 0, 0);
2741 switch (eolmode) {
2742 case SC_EOL_CR:
2743 retmode = IANJUTA_EDITOR_LINE_MODE_CR;
2744 break;
2745 case SC_EOL_CRLF:
2746 retmode = IANJUTA_EDITOR_LINE_MODE_CRLF;
2747 break;
2748 case SC_EOL_LF:
2749 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
2750 break;
2751 default:
2752 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
2753 g_warning ("Should not be here");
2755 return retmode;
2758 static void
2759 ilinemode_set (IAnjutaEditorLineMode* te, IAnjutaEditorLineModeType mode,
2760 GError** err)
2762 g_return_if_fail (IS_TEXT_EDITOR (te));
2764 switch (mode)
2766 case IANJUTA_EDITOR_LINE_MODE_LF:
2767 text_editor_command(TEXT_EDITOR(te), ANE_EOL_LF, 0, 0);
2768 break;
2770 case IANJUTA_EDITOR_LINE_MODE_CR:
2771 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CR, 0, 0);
2772 break;
2774 case IANJUTA_EDITOR_LINE_MODE_CRLF:
2775 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CRLF, 0, 0);
2776 break;
2778 default:
2779 g_warning ("Should not reach here");
2780 break;
2784 static void
2785 ilinemode_convert (IAnjutaEditorLineMode *te, IAnjutaEditorLineModeType mode,
2786 GError **err)
2788 switch (mode)
2790 case IANJUTA_EDITOR_LINE_MODE_LF:
2791 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2792 ANE_EOL_LF, 0);
2793 break;
2795 case IANJUTA_EDITOR_LINE_MODE_CR:
2796 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2797 ANE_EOL_CR, 0);
2798 break;
2800 case IANJUTA_EDITOR_LINE_MODE_CRLF:
2801 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2802 ANE_EOL_CRLF, 0);
2803 break;
2805 default:
2806 g_warning ("Should not reach here");
2807 break;
2811 static void
2812 ilinemode_fix (IAnjutaEditorLineMode* te, GError** err)
2814 IAnjutaEditorLineModeType mode = ilinemode_get (te, NULL);
2815 ilinemode_convert (te, mode, NULL);
2818 static void
2819 ilinemode_iface_init (IAnjutaEditorLineModeIface *iface)
2821 iface->set = ilinemode_set;
2822 iface->get = ilinemode_get;
2823 iface->convert = ilinemode_convert;
2824 iface->fix = ilinemode_fix;
2827 /* IAnjutaEditorAssist implementation */
2828 static void
2829 iassist_autocomplete(IAnjutaEditorAssist* te, GError** ee)
2831 text_editor_command(TEXT_EDITOR(te), ANE_COMPLETEWORD, 0, 0);
2834 static void
2835 iassist_iface_init(IAnjutaEditorAssistIface* iface)
2837 iface->autocomplete = iassist_autocomplete;
2840 /* IAnutaEditorFolds implementation */
2842 static void
2843 ifolds_open_all(IAnjutaEditorFolds* view, GError **e)
2845 text_editor_command(TEXT_EDITOR(view), ANE_OPEN_FOLDALL, 0, 0);
2848 static void
2849 ifolds_close_all(IAnjutaEditorFolds* view, GError **e)
2851 text_editor_command(TEXT_EDITOR(view), ANE_CLOSE_FOLDALL, 0, 0);
2854 static void
2855 ifolds_toggle_current(IAnjutaEditorFolds* view, GError **e)
2857 text_editor_command(TEXT_EDITOR(view), ANE_TOGGLE_FOLD, 0, 0);
2860 static void
2861 ifolds_iface_init(IAnjutaEditorFoldsIface* iface)
2863 iface->open_all = ifolds_open_all;
2864 iface->close_all = ifolds_close_all;
2865 iface->toggle_current = ifolds_toggle_current;
2868 /* IAnjutaEditorView implementation */
2869 static void
2870 iview_create (IAnjutaEditorView *view, GError **err)
2872 g_return_if_fail (IS_TEXT_EDITOR (view));
2873 text_editor_add_view (TEXT_EDITOR (view));
2876 static void
2877 iview_remove_current (IAnjutaEditorView *view, GError **err)
2879 g_return_if_fail (IS_TEXT_EDITOR (view));
2880 text_editor_remove_view (TEXT_EDITOR (view));
2883 static gint
2884 iview_get_count (IAnjutaEditorView *view, GError **err)
2886 g_return_val_if_fail (IS_TEXT_EDITOR (view), -1);
2887 return g_list_length (TEXT_EDITOR (view)->views);
2890 static void
2891 iview_iface_init (IAnjutaEditorViewIface *iface)
2893 iface->create = iview_create;
2894 iface->remove_current = iview_remove_current;
2895 iface->get_count = iview_get_count;
2898 /* IAnjutaBookmark implementation */
2899 static void
2900 ibookmark_toggle(IAnjutaBookmark* view, gint location,
2901 gboolean ensure_visible, GError **e)
2903 text_editor_goto_line (TEXT_EDITOR(view), location, FALSE, ensure_visible);
2904 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_TOGGLE, 0, 0);
2907 static void
2908 ibookmark_first(IAnjutaBookmark* view, GError **e)
2910 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_FIRST, 0, 0);
2913 static void
2914 ibookmark_last(IAnjutaBookmark* view, GError **e)
2916 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_LAST, 0, 0);
2919 static void
2920 ibookmark_next(IAnjutaBookmark* view, GError **e)
2922 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_NEXT, 0, 0);
2925 static void
2926 ibookmark_previous(IAnjutaBookmark* view, GError **e)
2928 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_PREV, 0, 0);
2931 static void
2932 ibookmark_clear_all(IAnjutaBookmark* view, GError **e)
2934 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_CLEAR, 0, 0);
2937 static void
2938 ibookmark_iface_init(IAnjutaBookmarkIface* iface)
2940 iface->toggle = ibookmark_toggle;
2941 iface->first = ibookmark_first;
2942 iface->last = ibookmark_last;
2943 iface->next = ibookmark_next;
2944 iface->previous = ibookmark_previous;
2945 iface->clear_all = ibookmark_clear_all;
2948 static void
2949 iindicable_set (IAnjutaIndicable *te, gint begin_location, gint end_location,
2950 IAnjutaIndicableIndicator indicator, GError **err)
2952 switch (indicator)
2954 case IANJUTA_INDICABLE_NONE:
2955 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
2956 end_location, -1);
2957 break;
2958 case IANJUTA_INDICABLE_IMPORTANT:
2959 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
2960 end_location, 0);
2961 break;
2962 case IANJUTA_INDICABLE_WARNING:
2963 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
2964 end_location, 1);
2965 break;
2966 case IANJUTA_INDICABLE_CRITICAL:
2967 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
2968 end_location, 2);
2969 break;
2970 default:
2971 g_warning ("Unsupported indicator %d", indicator);
2972 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
2973 end_location, -1);
2974 break;
2978 static void
2979 iindicable_clear (IAnjutaIndicable *te, GError **err)
2981 text_editor_set_indicator (TEXT_EDITOR (te), -1, -1, -1);
2984 static void
2985 iindicable_iface_init (IAnjutaIndicableIface *iface)
2987 iface->set = iindicable_set;
2988 iface->clear = iindicable_clear;
2991 static void
2992 iprint_print(IAnjutaPrint* print, GError** e)
2994 TextEditor* te = TEXT_EDITOR(print);
2995 anjuta_print(FALSE, te->preferences, te);
2998 static void
2999 iprint_preview(IAnjutaPrint* print, GError** e)
3001 TextEditor* te = TEXT_EDITOR(print);
3002 anjuta_print(TRUE, te->preferences, te);
3005 static void
3006 iprint_iface_init(IAnjutaPrintIface* iface)
3008 iface->print = iprint_print;
3009 iface->print_preview = iprint_preview;
3012 static void
3013 icomment_block(IAnjutaEditorComment* comment, GError** e)
3015 TextEditor* te = TEXT_EDITOR(comment);
3016 aneditor_command (te->editor_id, ANE_BLOCKCOMMENT, 0, 0);
3019 static void
3020 icomment_stream(IAnjutaEditorComment* comment, GError** e)
3022 TextEditor* te = TEXT_EDITOR(comment);
3023 aneditor_command (te->editor_id, ANE_STREAMCOMMENT, 0, 0);
3026 static void
3027 icomment_box(IAnjutaEditorComment* comment, GError** e)
3029 TextEditor* te = TEXT_EDITOR(comment);
3030 aneditor_command (te->editor_id, ANE_BOXCOMMENT, 0, 0);
3033 static void
3034 icomment_iface_init(IAnjutaEditorCommentIface* iface)
3036 iface->block = icomment_block;
3037 iface->box = icomment_box;
3038 iface->stream = icomment_stream;
3041 #define MAX_ZOOM_FACTOR 8
3042 #define MIN_ZOOM_FACTOR -8
3044 static void
3045 izoom_in(IAnjutaEditorZoom* zoom, GError** e)
3047 TextEditor* te = TEXT_EDITOR(zoom);
3048 gint zoom_factor = anjuta_preferences_get_int (te->preferences,
3049 TEXT_ZOOM_FACTOR) + 1;
3051 if (zoom_factor > MAX_ZOOM_FACTOR)
3052 zoom_factor = MAX_ZOOM_FACTOR;
3053 else if (zoom_factor < MIN_ZOOM_FACTOR)
3054 zoom_factor = MIN_ZOOM_FACTOR;
3056 anjuta_preferences_set_int (te->preferences, TEXT_ZOOM_FACTOR, zoom_factor);
3059 static void
3060 izoom_out(IAnjutaEditorZoom* zoom, GError** e)
3062 TextEditor* te = TEXT_EDITOR(zoom);
3063 gint zoom_factor = anjuta_preferences_get_int (te->preferences,
3064 TEXT_ZOOM_FACTOR) - 1;
3066 if (zoom_factor > MAX_ZOOM_FACTOR)
3067 zoom_factor = MAX_ZOOM_FACTOR;
3068 else if (zoom_factor < MIN_ZOOM_FACTOR)
3069 zoom_factor = MIN_ZOOM_FACTOR;
3071 anjuta_preferences_set_int (te->preferences, TEXT_ZOOM_FACTOR, zoom_factor);
3074 static void
3075 izoom_iface_init(IAnjutaEditorZoomIface* iface)
3077 iface->in = izoom_in;
3078 iface->out = izoom_out;
3081 static void
3082 igoto_start_block(IAnjutaEditorGoto* editor, GError** e)
3084 TextEditor* te = TEXT_EDITOR(editor);
3085 text_editor_goto_block_start(te);
3088 static void
3089 igoto_end_block(IAnjutaEditorGoto* editor, GError** e)
3091 TextEditor* te = TEXT_EDITOR(editor);
3092 text_editor_goto_block_end(te);
3095 static void
3096 igoto_iface_init(IAnjutaEditorGotoIface* iface)
3098 iface->start_block = igoto_start_block;
3099 iface->end_block = igoto_end_block;
3102 static const GList*
3103 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
3104 GError **err)
3106 if (supported_languages == NULL)
3108 gchar **strv;
3109 gchar **token;
3110 gchar *menu_entries;
3112 supported_languages_name =
3113 g_hash_table_new_full (g_str_hash, g_str_equal,
3114 NULL, g_free);
3115 supported_languages_ext =
3116 g_hash_table_new_full (g_str_hash, g_str_equal,
3117 NULL, g_free);
3119 supported_languages_by_lexer =
3120 g_hash_table_new_full (g_str_hash, g_str_equal,
3121 g_free, NULL);
3123 menu_entries = sci_prop_get (text_editor_get_props (), "menu.language");
3124 g_return_val_if_fail (menu_entries != NULL, NULL);
3126 strv = g_strsplit (menu_entries, "|", -1);
3127 token = strv;
3128 while (*token)
3130 gchar *lexer;
3131 gchar *possible_file;
3132 gchar *iter;
3133 gchar *name, *extension;
3134 GString *lang;
3136 lang = g_string_new ("");
3138 name = *token++;
3139 if (!name)
3140 break;
3142 extension = *token++;
3143 if (!extension)
3144 break;
3145 token++;
3147 if (name[0] == '#')
3148 continue;
3150 iter = name;
3151 while (*iter)
3153 if (*iter == '&')
3155 *iter = '_';
3157 else
3159 g_string_append_c (lang, g_ascii_tolower (*iter));
3161 iter++;
3164 /* HACK: Convert the weird c++ name to cpp */
3165 if (strcmp (lang->str, "c / c++") == 0)
3167 g_string_assign (lang, "cpp");
3170 /* Updated mapping hash tables */
3171 g_hash_table_insert (supported_languages_name, lang->str,
3172 g_strdup (name));
3173 g_hash_table_insert (supported_languages_ext, lang->str,
3174 g_strconcat ("file.", extension, NULL));
3175 /* Map lexer to language */
3176 possible_file = g_strconcat ("file.", extension, NULL);
3177 lexer = sci_prop_get_new_expand (TEXT_EDITOR (ilanguage)->props_base,
3178 "lexer.", possible_file);
3179 g_free (possible_file);
3180 if (lexer)
3182 /* We only map the first (which is hopefully the true) language */
3183 if (!g_hash_table_lookup (supported_languages_by_lexer, lexer))
3185 DEBUG_PRINT ("Mapping (lexer)%s to (language)%s", lexer, lang->str);
3186 g_hash_table_insert (supported_languages_by_lexer,
3187 lexer, lang->str);
3188 /* lexer is taken in the hash, so no free */
3190 else
3192 g_free (lexer);
3194 lexer = NULL;
3196 supported_languages = g_list_prepend (supported_languages,
3197 lang->str);
3198 g_string_free (lang, FALSE);
3200 g_strfreev (strv);
3202 return supported_languages;
3205 static const gchar*
3206 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
3207 const gchar *language, GError **err)
3209 if (!supported_languages_name)
3210 ilanguage_get_supported_languages (ilanguage, NULL);
3212 return g_hash_table_lookup (supported_languages_name, language);
3215 static void
3216 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
3217 const gchar *language, GError **err)
3219 if (!supported_languages_ext)
3220 ilanguage_get_supported_languages (ilanguage, NULL);
3222 if (language)
3223 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage),
3224 g_hash_table_lookup (supported_languages_ext,
3225 language));
3226 else /* Autodetect */
3227 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage), NULL);
3229 text_editor_hilite (TEXT_EDITOR (ilanguage), FALSE);
3232 static const gchar*
3233 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
3235 const gchar *language = NULL;
3236 const gchar *filename = NULL;
3237 TextEditor *te = TEXT_EDITOR (ilanguage);
3239 if (te->force_hilite)
3240 filename = te->force_hilite;
3241 else if (te->filename)
3242 filename = te->filename;
3244 if (filename)
3246 gchar *lexer = NULL;
3247 lexer = sci_prop_get_new_expand (te->props_base,
3248 "lexer.", filename);
3250 /* No lexer, no language */
3251 if (lexer)
3253 if (!supported_languages_by_lexer)
3254 ilanguage_get_supported_languages (ilanguage, NULL);
3256 language = g_hash_table_lookup (supported_languages_by_lexer, lexer);
3257 DEBUG_PRINT ("Found (language)%s for (lexer)%s", language, lexer);
3258 g_free (lexer);
3261 return language;
3264 static void
3265 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
3267 iface->get_supported_languages = ilanguage_get_supported_languages;
3268 iface->get_language_name = ilanguage_get_language_name;
3269 iface->get_language = ilanguage_get_language;
3270 iface->set_language = ilanguage_set_language;
3273 ANJUTA_TYPE_BEGIN(TextEditor, text_editor, GTK_TYPE_VBOX);
3274 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
3275 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
3276 ANJUTA_TYPE_ADD_INTERFACE(itext_editor, IANJUTA_TYPE_EDITOR);
3277 ANJUTA_TYPE_ADD_INTERFACE(ilinemode, IANJUTA_TYPE_EDITOR_LINE_MODE);
3278 ANJUTA_TYPE_ADD_INTERFACE(iselection, IANJUTA_TYPE_EDITOR_SELECTION);
3279 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
3280 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
3281 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
3282 ANJUTA_TYPE_ADD_INTERFACE(iview, IANJUTA_TYPE_EDITOR_VIEW);
3283 ANJUTA_TYPE_ADD_INTERFACE(ifolds, IANJUTA_TYPE_EDITOR_FOLDS);
3284 ANJUTA_TYPE_ADD_INTERFACE(ibookmark, IANJUTA_TYPE_BOOKMARK);
3285 ANJUTA_TYPE_ADD_INTERFACE(imarkable, IANJUTA_TYPE_MARKABLE);
3286 ANJUTA_TYPE_ADD_INTERFACE(iindicable, IANJUTA_TYPE_INDICABLE);
3287 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
3288 ANJUTA_TYPE_ADD_INTERFACE(icomment, IANJUTA_TYPE_EDITOR_COMMENT);
3289 ANJUTA_TYPE_ADD_INTERFACE(izoom, IANJUTA_TYPE_EDITOR_ZOOM);
3290 ANJUTA_TYPE_ADD_INTERFACE(igoto, IANJUTA_TYPE_EDITOR_GOTO);
3292 /* FIXME: Is factory definition really required for editor class? */
3293 ANJUTA_TYPE_ADD_INTERFACE(itext_editor_factory, IANJUTA_TYPE_EDITOR_FACTORY);
3294 ANJUTA_TYPE_END;