2008-01-01 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / plugins / editor / text_editor.c
blobe0ddedae685aabd9d7c0783d8b3f6c50722a68ce
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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-view.h>
42 #include <libanjuta/interfaces/ianjuta-editor-folds.h>
43 #include <libanjuta/interfaces/ianjuta-editor-comment.h>
44 #include <libanjuta/interfaces/ianjuta-editor-zoom.h>
45 #include <libanjuta/interfaces/ianjuta-editor-goto.h>
46 #include <libanjuta/interfaces/ianjuta-editor-language.h>
47 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
48 #include <libanjuta/interfaces/ianjuta-editor-search.h>
49 #include <libanjuta/interfaces/ianjuta-editor-hover.h>
50 #include <libanjuta/interfaces/ianjuta-bookmark.h>
51 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
52 #include <libanjuta/interfaces/ianjuta-file.h>
53 #include <libanjuta/interfaces/ianjuta-file-savable.h>
54 #include <libanjuta/interfaces/ianjuta-markable.h>
55 #include <libanjuta/interfaces/ianjuta-indicable.h>
56 #include <libanjuta/interfaces/ianjuta-print.h>
57 #include <libanjuta/interfaces/ianjuta-document.h>
59 #include "properties.h"
60 #include "text_editor.h"
61 #include "text_editor_cbs.h"
62 #include "text_editor_menu.h"
63 #include "text-editor-iterable.h"
64 #include "print.h"
66 #define GTK
67 #undef PLAT_GTK
68 #define PLAT_GTK 1
69 #include "Scintilla.h"
70 #include "SciLexer.h"
71 #include "ScintillaWidget.h"
73 #include "lexer.h"
74 #include "aneditor.h"
75 #include "text_editor_prefs.h"
77 /* Order is important, as marker with the lowest number is drawn first */
78 #define TEXT_EDITOR_BOOKMARK 0
79 #define TEXT_EDITOR_BREAKPOINT_DISABLED 1
80 #define TEXT_EDITOR_BREAKPOINT_ENABLED 2
81 #define TEXT_EDITOR_PROGRAM_COUNTER 3
82 #define TEXT_EDITOR_LINEMARKER 4
84 /* Include marker pixmaps */
85 #include "anjuta-bookmark-16.xpm"
86 #include "anjuta-breakpoint-disabled-16.xpm"
87 #include "anjuta-breakpoint-enabled-16.xpm"
88 #include "anjuta-pcmark-16.xpm"
89 #include "anjuta-linemark-16.xpm"
91 static gchar** marker_pixmap[] =
93 anjuta_bookmark_16_xpm,
94 anjuta_breakpoint_disabled_16_xpm,
95 anjuta_breakpoint_enabled_16_xpm,
96 anjuta_pcmark_16_xpm,
97 anjuta_linemark_16_xpm,
98 NULL
101 /* Editor language supports */
102 static GList *supported_languages = NULL;
103 static GHashTable *supported_languages_name = NULL;
104 static GHashTable *supported_languages_ext = NULL;
105 static GHashTable *supported_languages_by_lexer = NULL;
107 static void text_editor_finalize (GObject *obj);
108 static void text_editor_dispose (GObject *obj);
109 static void text_editor_hilite_one (TextEditor * te, AnEditorID editor,
110 gboolean force);
112 static GtkVBoxClass *parent_class;
114 static void
115 text_editor_instance_init (TextEditor *te)
117 te->filename = NULL;
118 te->uri = NULL;
119 te->views = NULL;
120 te->popup_menu = NULL;
122 te->monitor = NULL;
123 te->preferences = NULL;
124 te->force_hilite = NULL;
125 te->freeze_count = 0;
126 te->current_line = 0;
127 te->popup_menu = NULL;
128 te->props_base = 0;
129 te->first_time_expose = TRUE;
130 te->encoding = NULL;
131 te->gconf_notify_ids = NULL;
132 te->hover_tip_on = FALSE;
135 static void
136 text_editor_class_init (TextEditorClass *klass)
138 GObjectClass *object_class = G_OBJECT_CLASS (klass);
140 parent_class = g_type_class_peek_parent (klass);
141 object_class->finalize = text_editor_finalize;
142 object_class->dispose = text_editor_dispose;
145 #if 0
146 static void
147 check_tm_file(TextEditor *te)
149 if (NULL == te->tm_file)
151 // FIXME:
152 // te->tm_file = tm_workspace_find_object(
153 //TM_WORK_OBJECT(app->tm_workspace), te->uri, FALSE);
154 if (NULL == te->tm_file)
156 te->tm_file = tm_source_file_new(te->uri, TRUE);
157 if (NULL != te->tm_file)
158 tm_workspace_add_object(te->tm_file);
162 #endif
164 static void
165 initialize_markers (TextEditor* te, GtkWidget *scintilla)
167 gint marker;
168 gchar ***xpm;
169 g_return_if_fail (te != NULL);
171 marker = 0;
172 for (xpm = marker_pixmap;*xpm != NULL; xpm++)
174 scintilla_send_message (SCINTILLA (scintilla), SCI_MARKERDEFINEPIXMAP,
175 marker, (sptr_t)*xpm);
176 marker++;
180 #ifdef DEBUG
181 static void
182 on_scintila_already_destroyed (gpointer te, GObject *obj)
184 /* DEBUG_PRINT ("Scintilla object has been destroyed"); */
187 static void
188 on_te_already_destroyed (gpointer te, GObject *obj)
190 /* DEBUG_PRINT ("TextEditor object has been destroyed"); */
192 #endif
194 void
195 text_editor_add_view (TextEditor *te)
197 AnEditorID editor_id;
198 GtkWidget *scintilla;
199 gint current_line;
200 gint current_point;
202 if (te->views)
204 current_line = text_editor_get_current_lineno (te);
205 current_point = text_editor_get_current_position (te);
207 else
209 current_line = 0;
210 current_point = 0;
212 editor_id = aneditor_new (sci_prop_get_pointer (te->props_base));
213 scintilla = aneditor_get_widget (editor_id);
215 /* Set notifications to receive */
216 scintilla_send_message (SCINTILLA (scintilla), SCI_SETMODEVENTMASK,
217 (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT), 0);
219 /* Set parent, if it is not primary view */
220 if (te->views)
222 aneditor_set_parent (editor_id, GPOINTER_TO_INT(te->editor_id));
224 te->views = g_list_prepend (te->views, GINT_TO_POINTER (editor_id));
225 te->editor_id = editor_id;
226 te->scintilla = scintilla;
229 aneditor_command (te->editor_id, ANE_SETACCELGROUP,
230 (glong) app->accel_group, 0);
233 gtk_widget_set_usize (scintilla, 50, 50);
234 gtk_widget_show (scintilla);
236 gtk_box_set_homogeneous (GTK_BOX (te), TRUE);
237 gtk_box_set_spacing (GTK_BOX (te), 3);
238 gtk_box_pack_start (GTK_BOX (te), scintilla, TRUE, TRUE, 0);
239 gtk_widget_grab_focus (scintilla);
241 g_signal_connect (G_OBJECT (scintilla), "event",
242 G_CALLBACK (on_text_editor_text_event), te);
243 g_signal_connect (G_OBJECT (scintilla), "button_press_event",
244 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
245 g_signal_connect_after (G_OBJECT (scintilla), "size_allocate",
246 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
247 g_signal_connect (G_OBJECT (scintilla), "sci-notify",
248 G_CALLBACK (on_text_editor_scintilla_notify), te);
249 g_signal_connect (G_OBJECT (scintilla), "focus_in_event",
250 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
252 initialize_markers (te, scintilla);
253 text_editor_hilite_one (te, editor_id, FALSE);
254 text_editor_set_line_number_width (te);
256 if (current_line)
257 text_editor_goto_line (te, current_line, FALSE, TRUE);
258 if (current_point)
259 text_editor_goto_point (te, current_point);
261 #ifdef DEBUG
262 g_object_weak_ref (G_OBJECT (scintilla), on_scintila_already_destroyed, te);
263 #endif
266 /* Remove the current view */
267 void
268 text_editor_remove_view (TextEditor *te)
270 if (!te->editor_id)
271 return;
272 if (te->views == NULL ||
273 g_list_length (te->views) <= 1)
274 return;
276 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
277 G_CALLBACK (on_text_editor_text_event), te);
278 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
279 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
280 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
281 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
282 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
283 G_CALLBACK (on_text_editor_scintilla_notify), te);
284 g_signal_handlers_disconnect_by_func (G_OBJECT (te->scintilla),
285 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
287 te->views = g_list_remove (te->views, GINT_TO_POINTER(te->editor_id));
288 gtk_container_remove (GTK_CONTAINER (te), te->scintilla);
289 aneditor_destroy(te->editor_id);
291 /* Set current view */
292 if (te->views)
294 te->editor_id = GPOINTER_TO_INT(te->views->data);
295 te->scintilla = aneditor_get_widget (te->editor_id);
296 gtk_widget_grab_focus (te->scintilla);
298 else
300 gtk_box_set_spacing (GTK_BOX (te), 0);
301 te->editor_id = 0;
302 te->scintilla = NULL;
306 static void
307 on_reload_dialog_response (GtkWidget *dlg, gint res, TextEditor *te)
309 if (res == GTK_RESPONSE_YES)
311 text_editor_load_file (te);
313 gtk_widget_destroy (dlg);
314 te->file_modified_widget = NULL;
315 /* DEBUG_PRINT ("File modified dialog responded"); */
318 static gboolean
319 on_text_editor_uri_changed_prompt (TextEditor *te)
321 GtkWidget *dlg;
322 GtkWidget *parent;
323 gchar *buff;
325 buff =
326 g_strdup_printf (_
327 ("The file '%s' on the disk is more recent than\n"
328 "the current buffer.\nDo you want to reload it?"),
329 te->filename);
331 parent = gtk_widget_get_toplevel (GTK_WIDGET (te));
333 dlg = gtk_message_dialog_new (GTK_WINDOW (parent),
334 GTK_DIALOG_DESTROY_WITH_PARENT,
335 GTK_MESSAGE_WARNING,
336 GTK_BUTTONS_NONE, buff);
337 gtk_dialog_add_button (GTK_DIALOG (dlg),
338 GTK_STOCK_NO,
339 GTK_RESPONSE_NO);
340 anjuta_util_dialog_add_button (GTK_DIALOG (dlg),
341 _("_Reload"),
342 GTK_STOCK_REFRESH,
343 GTK_RESPONSE_YES);
344 g_free (buff);
346 gtk_window_set_transient_for (GTK_WINDOW (dlg),
347 GTK_WINDOW (parent));
349 g_signal_connect (dlg, "response",
350 G_CALLBACK (on_reload_dialog_response),
351 te);
352 g_signal_connect_swapped (dlg, "delete-event",
353 G_CALLBACK (gtk_widget_destroy),
354 dlg);
355 gtk_widget_show (dlg);
357 te->file_modified_widget = dlg;
359 return FALSE;
362 static void
363 on_text_editor_uri_changed (GnomeVFSMonitorHandle *handle,
364 const gchar *monitor_uri,
365 const gchar *info_uri,
366 GnomeVFSMonitorEventType event_type,
367 gpointer user_data)
369 TextEditor *te = TEXT_EDITOR (user_data);
371 /* DEBUG_PRINT ("File changed!!!"); */
373 if (!(event_type == GNOME_VFS_MONITOR_EVENT_CHANGED ||
374 event_type == GNOME_VFS_MONITOR_EVENT_CREATED))
375 return;
377 if (!anjuta_util_diff (te->uri, te->last_saved_content))
379 /* The file content is same. Remove any previous prompt for reload */
380 if (te->file_modified_widget)
381 gtk_widget_destroy (te->file_modified_widget);
382 te->file_modified_widget = NULL;
383 return;
386 if (strcmp (monitor_uri, info_uri) != 0)
387 return;
389 /* If the file modified dialog is already shown, don't bother showing it
390 * again.
392 if (te->file_modified_widget)
393 return;
395 /* Set up 1 sec timer */
396 if (te->file_modified_timer > 0)
397 g_source_remove (te->file_modified_timer);
398 te->file_modified_timer = g_timeout_add (1000,
399 (GSourceFunc)on_text_editor_uri_changed_prompt, te);
402 static void
403 text_editor_update_monitor (TextEditor *te, gboolean disable_it)
405 if (te->monitor)
407 /* Shutdown existing monitor */
408 gnome_vfs_monitor_cancel (te->monitor);
409 te->monitor = NULL;
411 if (te->uri && !disable_it)
413 GnomeVFSResult res;
414 /* DEBUG_PRINT ("Setting up Monitor for %s", te->uri); */
415 res = gnome_vfs_monitor_add (&te->monitor, te->uri,
416 GNOME_VFS_MONITOR_FILE,
417 on_text_editor_uri_changed, te);
419 if (res != GNOME_VFS_OK)
421 DEBUG_PRINT ("Error while setting up file monitor: %s",
422 gnome_vfs_result_to_string (res));
428 GtkWidget *
429 text_editor_new (AnjutaStatus *status, AnjutaPreferences *eo, const gchar *uri, const gchar *name)
431 gint zoom_factor;
432 static guint new_file_count;
433 TextEditor *te = TEXT_EDITOR (gtk_widget_new (TYPE_TEXT_EDITOR, NULL));
435 te->status = status;
437 te->preferences = eo;
438 te->props_base = text_editor_get_props();
439 if (name && strlen(name) > 0)
440 te->filename = g_strdup(name);
441 else
442 te->filename = g_strdup_printf ("Newfile#%d", ++new_file_count);
443 if (uri && strlen(uri) > 0)
445 GnomeVFSResult result;
446 GnomeVFSURI* vfs_uri;
447 GnomeVFSFileInfo info = {0,0};
449 new_file_count--;
450 if (te->filename)
451 g_free (te->filename);
452 if (te->uri)
453 g_free (te->uri);
454 vfs_uri = gnome_vfs_uri_new(uri);
455 result = gnome_vfs_get_file_info_uri(vfs_uri, &info, GNOME_VFS_SET_FILE_INFO_NONE);
456 gnome_vfs_uri_unref(vfs_uri);
457 te->filename = g_strdup(info.name);
458 te->uri = g_strdup(uri);
461 text_editor_prefs_init (te);
463 /* Create primary view */
464 text_editor_add_view (te);
466 if (te->uri)
468 if (text_editor_load_file (te) == FALSE)
470 /* Unable to load file */
471 gtk_widget_destroy (GTK_WIDGET (te));
472 return NULL;
475 text_editor_update_controls (te);
477 /* Apply font zoom separately */
478 zoom_factor = anjuta_preferences_get_int (te->preferences, TEXT_ZOOM_FACTOR);
479 /* DEBUG_PRINT ("Initializing zoom factor to: %d", zoom_factor); */
480 text_editor_set_zoom_factor (te, zoom_factor);
482 #ifdef DEBUG
483 g_object_weak_ref (G_OBJECT (te), on_te_already_destroyed, te);
484 #endif
485 return GTK_WIDGET (te);
488 void
489 text_editor_dispose (GObject *obj)
491 TextEditor *te = TEXT_EDITOR (obj);
492 if (te->file_modified_timer > 0)
494 g_source_remove (te->file_modified_timer);
495 te->file_modified_timer = 0;
497 if (te->monitor)
499 text_editor_update_monitor (te, TRUE);
500 te->monitor = NULL;
502 if (te->popup_menu)
504 g_object_unref (te->popup_menu);
505 te->popup_menu = NULL;
507 if (te->views)
509 GtkWidget *scintilla;
510 AnEditorID editor_id;
511 GList *node;
513 node = te->views;
514 while (node)
516 editor_id = GPOINTER_TO_INT (node->data);
517 scintilla = aneditor_get_widget (editor_id);
519 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
520 G_CALLBACK (on_text_editor_text_event), te);
521 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
522 G_CALLBACK (on_text_editor_text_buttonpress_event), te);
523 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
524 G_CALLBACK (on_text_editor_scintilla_size_allocate), te);
525 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
526 G_CALLBACK (on_text_editor_scintilla_notify), te);
527 g_signal_handlers_disconnect_by_func (G_OBJECT (scintilla),
528 G_CALLBACK (on_text_editor_scintilla_focus_in), te);
530 aneditor_destroy (editor_id);
531 node = g_list_next (node);
533 te->scintilla = NULL;
534 te->editor_id = 0;
535 te->views = NULL;
537 if (te->gconf_notify_ids)
539 text_editor_prefs_finalize (te);
540 te->gconf_notify_ids = NULL;
542 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (G_OBJECT(te)));
545 void
546 text_editor_finalize (GObject *obj)
548 TextEditor *te = TEXT_EDITOR (obj);
549 g_free (te->filename);
550 g_free (te->uri);
551 g_free (te->encoding);
552 g_free (te->force_hilite);
553 g_free (te->last_saved_content);
555 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (G_OBJECT(te)));
558 void
559 text_editor_freeze (TextEditor *te)
561 te->freeze_count++;
564 void
565 text_editor_thaw (TextEditor *te)
567 te->freeze_count--;
568 if (te->freeze_count < 0)
569 te->freeze_count = 0;
572 void
573 text_editor_set_hilite_type (TextEditor * te, const gchar *file_extension)
575 const gchar *past_language;
576 const gchar *curr_language;
578 past_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
580 g_free (te->force_hilite);
581 if (file_extension)
582 te->force_hilite = g_strdup (file_extension);
583 else
584 te->force_hilite = NULL;
586 curr_language = ianjuta_editor_language_get_language (IANJUTA_EDITOR_LANGUAGE (te), NULL);
587 if (past_language != curr_language)
588 g_signal_emit_by_name (te, "language-changed", curr_language);
591 static void
592 text_editor_hilite_one (TextEditor * te, AnEditorID editor_id,
593 gboolean override_by_pref)
595 /* If syntax highlighting is disabled ... */
596 if (override_by_pref &&
597 anjuta_preferences_get_int (ANJUTA_PREFERENCES (te->preferences),
598 DISABLE_SYNTAX_HILIGHTING))
600 aneditor_command (editor_id, ANE_SETHILITE, (glong) "plain.txt", 0);
602 else if (te->force_hilite)
604 aneditor_command (editor_id, ANE_SETHILITE, (glong) te->force_hilite, 0);
606 else if (te->uri)
608 gchar *basename;
609 basename = g_path_get_basename (te->uri);
610 aneditor_command (editor_id, ANE_SETHILITE, (glong) basename, 0);
611 g_free (basename);
613 else if (te->filename)
615 aneditor_command (editor_id, ANE_SETHILITE, (glong) te->filename, 0);
617 else
619 aneditor_command (editor_id, ANE_SETHILITE, (glong) "plain.txt", 0);
623 void
624 text_editor_hilite (TextEditor * te, gboolean override_by_pref)
626 GList *node;
628 node = te->views;
629 while (node)
631 text_editor_hilite_one (te, GPOINTER_TO_INT (node->data),
632 override_by_pref);
633 node = g_list_next (node);
637 void
638 text_editor_set_zoom_factor (TextEditor * te, gint zfac)
640 text_editor_command (te, ANE_SETZOOM, zfac, 0);
643 TextEditorAttrib
644 text_editor_get_attribute (TextEditor *te, gint position)
646 int lexer;
647 int style;
648 TextEditorAttrib attrib = TEXT_EDITOR_ATTRIB_TEXT;
650 lexer = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETLEXER,
651 0, 0);
652 style = scintilla_send_message (SCINTILLA (te->scintilla), SCI_GETSTYLEAT,
653 position, 0);
654 switch (lexer)
656 case SCLEX_CPP:
657 switch (style)
659 case SCE_C_CHARACTER:
660 case SCE_C_STRING:
661 attrib = TEXT_EDITOR_ATTRIB_STRING;
662 break;
663 case SCE_C_COMMENT:
664 case SCE_C_COMMENTLINE:
665 case SCE_C_COMMENTDOC:
666 case SCE_C_COMMENTLINEDOC:
667 case SCE_C_COMMENTDOCKEYWORD:
668 case SCE_C_COMMENTDOCKEYWORDERROR:
669 attrib = TEXT_EDITOR_ATTRIB_COMMENT;
670 break;
671 case SCE_C_WORD:
672 attrib = TEXT_EDITOR_ATTRIB_KEYWORD;
673 break;
675 break;
677 return attrib;
680 glong
681 text_editor_find (TextEditor * te, const gchar * str, gint scope,
682 gboolean forward, gboolean regexp,
683 gboolean ignore_case, gboolean whole_word, gboolean wrap)
685 glong ret;
686 GtkWidget *editor;
687 glong flags;
688 int current_pos, current_anchor;
690 if (!te) return -1;
691 editor = te->scintilla;
693 flags = (ignore_case ? 0 : SCFIND_MATCHCASE)
694 | (regexp ? SCFIND_REGEXP : 0)
695 | (whole_word ? SCFIND_WHOLEWORD : 0)
696 | (forward ? 0 : ANEFIND_REVERSE_FLAG);
698 switch (scope)
700 case TEXT_EDITOR_FIND_SCOPE_WHOLE:
701 if (forward)
703 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
704 0, 0);
705 scintilla_send_message (SCINTILLA (editor),
706 SCI_SETCURRENTPOS, 0, 0);
708 else
710 glong length;
711 length = scintilla_send_message (SCINTILLA (editor),
712 SCI_GETTEXTLENGTH, 0, 0);
713 scintilla_send_message (SCINTILLA (editor),
714 SCI_SETCURRENTPOS, length-1, 0);
715 scintilla_send_message (SCINTILLA (editor),
716 SCI_SETANCHOR, length-1, 0);
718 break;
719 default:
720 break;
722 current_pos = scintilla_send_message (SCINTILLA (editor),
723 SCI_GETCURRENTPOS, 0, 0);
724 current_anchor = scintilla_send_message (SCINTILLA (editor),
725 SCI_GETANCHOR, 0, 0);
726 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
727 if (scope == TEXT_EDITOR_FIND_SCOPE_CURRENT && wrap && ret < 0) {
728 /* If wrap is requested, wrap it. */
729 if (forward)
731 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR, 0, 0);
732 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
733 0, 0);
735 else
737 glong length;
738 length = scintilla_send_message (SCINTILLA (editor),
739 SCI_GETTEXTLENGTH, 0, 0);
740 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
741 length-1, 0);
742 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
743 length-1, 0);
745 ret = aneditor_command (te->editor_id, ANE_FIND, flags, (long)str);
746 /* If the text is still not found, restore current pos and anchor */
747 if (ret < 0) {
748 scintilla_send_message (SCINTILLA (editor), SCI_SETANCHOR,
749 current_anchor, 0);
750 scintilla_send_message (SCINTILLA (editor), SCI_SETCURRENTPOS,
751 current_pos, 0);
754 return ret;
757 void
758 text_editor_replace_selection (TextEditor * te, const gchar* r_str)
760 if (!te) return;
761 scintilla_send_message (SCINTILLA(te->scintilla), SCI_REPLACESEL, 0,
762 (long)r_str);
765 guint
766 text_editor_get_total_lines (TextEditor * te)
768 guint i;
769 guint count = 0;
770 if (te == NULL)
771 return 0;
772 if (IS_SCINTILLA (te->scintilla) == FALSE)
773 return 0;
774 for (i = 0;
775 i < scintilla_send_message (SCINTILLA (te->scintilla),
776 SCI_GETLENGTH, 0, 0); i++)
778 if (scintilla_send_message
779 (SCINTILLA (te->scintilla), SCI_GETCHARAT, i,
780 0) == '\n')
781 count++;
783 return count;
786 guint
787 text_editor_get_current_lineno (TextEditor * te)
789 guint count;
791 g_return_val_if_fail (te != NULL, 0);
793 count = scintilla_send_message (SCINTILLA (te->scintilla),
794 SCI_GETCURRENTPOS, 0, 0);
795 count = scintilla_send_message (SCINTILLA (te->scintilla),
796 SCI_LINEFROMPOSITION, count, 0);
797 return linenum_scintilla_to_text_editor(count);
800 guint
801 text_editor_get_current_column (TextEditor * te)
803 g_return_val_if_fail (te != NULL, 0);
804 return scintilla_send_message (SCINTILLA (te->scintilla),
805 SCI_GETCOLUMN,
806 text_editor_get_current_position (te), 0);
809 gboolean
810 text_editor_get_overwrite (TextEditor * te)
812 g_return_val_if_fail (te != NULL, 0);
813 return scintilla_send_message (SCINTILLA (te->scintilla),
814 SCI_GETOVERTYPE, 0, 0);
817 guint
818 text_editor_get_line_from_position (TextEditor * te, glong pos)
820 guint count;
822 g_return_val_if_fail (te != NULL, 0);
824 count = scintilla_send_message (SCINTILLA (te->scintilla),
825 SCI_LINEFROMPOSITION, pos, 0);
826 return linenum_scintilla_to_text_editor(count);
829 glong
830 text_editor_get_current_position (TextEditor * te)
832 guint count;
834 g_return_val_if_fail (te != NULL, 0);
836 count = scintilla_send_message (SCINTILLA (te->scintilla),
837 SCI_GETCURRENTPOS, 0, 0);
838 return count;
841 gboolean
842 text_editor_goto_point (TextEditor * te, glong point)
844 g_return_val_if_fail (te != NULL, FALSE);
845 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
847 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
848 point, 0);
849 return TRUE;
852 gboolean
853 text_editor_goto_line (TextEditor * te, glong line,
854 gboolean mark, gboolean ensure_visible)
856 gint selpos;
857 g_return_val_if_fail (te != NULL, FALSE);
858 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, FALSE);
859 g_return_val_if_fail(line >= 0, FALSE);
861 te->current_line = line;
862 if (mark) text_editor_set_line_marker (te, line);
863 if (ensure_visible)
864 scintilla_send_message (SCINTILLA (te->scintilla),
865 SCI_ENSUREVISIBLE,
866 linenum_text_editor_to_scintilla (line), 0);
867 selpos = scintilla_send_message(SCINTILLA (te->scintilla),
868 SCI_POSITIONFROMLINE,
869 linenum_text_editor_to_scintilla (line), 0);
870 scintilla_send_message (SCINTILLA (te->scintilla),
871 SCI_SETSELECTIONSTART, selpos, 0);
872 scintilla_send_message (SCINTILLA (te->scintilla),
873 SCI_SETSELECTIONEND, selpos, 0);
875 /* This ensures that we have arround 5 lines visible below the mark */
876 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
877 linenum_text_editor_to_scintilla (line)+5, 0);
878 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOLINE,
879 linenum_text_editor_to_scintilla (line), 0);
880 return TRUE;
883 gint
884 text_editor_goto_block_start (TextEditor* te)
886 gint line;
887 line = aneditor_command (te->editor_id, ANE_GETBLOCKSTARTLINE, 0, 0);
888 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
889 else gdk_beep();
890 return line;
893 gint
894 text_editor_goto_block_end (TextEditor* te)
896 gint line;
897 line = aneditor_command (te->editor_id, ANE_GETBLOCKENDLINE, 0, 0);
898 if (line >= 0) text_editor_goto_line (te, line, TRUE, TRUE);
899 else gdk_beep();
900 return line;
903 gint
904 text_editor_set_marker (TextEditor *te, glong line, gint marker)
906 g_return_val_if_fail (te != NULL, -1);
907 g_return_val_if_fail(IS_SCINTILLA (te->scintilla) == TRUE, -1);
909 /* Scintilla interprets line+1 rather than line */
910 /* A bug perhaps */
911 /* So counterbalance it with line-1 */
912 /* Using the macros linenum_* */
913 return scintilla_send_message (SCINTILLA (te->scintilla),
914 SCI_MARKERADD,
915 linenum_text_editor_to_scintilla (line),
916 marker);
919 gint
920 text_editor_set_indicator (TextEditor *te, gint start,
921 gint end, gint indicator)
923 gchar ch;
924 glong indic_mask[] = {INDIC0_MASK, INDIC1_MASK, INDIC2_MASK};
925 gint current_styling_pos;
927 g_return_val_if_fail (te != NULL, -1);
928 g_return_val_if_fail (IS_SCINTILLA (te->scintilla) == TRUE, -1);
930 if (start >= 0) {
931 end --; /* supplied end-location is one-past the last char to process */
932 if (end < start)
933 return -1;
937 ch = scintilla_send_message (SCINTILLA (te->scintilla),
938 SCI_GETCHARAT, start, 0);
939 start++;
940 } while (isspace(ch));
941 start--;
943 do {
944 ch = scintilla_send_message (SCINTILLA (te->scintilla),
945 SCI_GETCHARAT, end, 0);
946 end--;
947 } while (isspace(ch));
948 end++;
949 if (end < start) return -1;
951 current_styling_pos = scintilla_send_message (SCINTILLA (te->scintilla),
952 SCI_GETENDSTYLED, 0, 0);
953 if (indicator >= 0 && indicator < 3) {
954 char current_mask;
955 current_mask =
956 scintilla_send_message (SCINTILLA (te->scintilla),
957 SCI_GETSTYLEAT, start, 0);
958 current_mask &= INDICS_MASK;
959 current_mask |= indic_mask[indicator];
960 scintilla_send_message (SCINTILLA (te->scintilla),
961 SCI_STARTSTYLING, start, INDICS_MASK);
962 scintilla_send_message (SCINTILLA (te->scintilla),
963 SCI_SETSTYLING, end-start+1, current_mask);
964 } else {
965 scintilla_send_message (SCINTILLA (te->scintilla),
966 SCI_STARTSTYLING, start, INDICS_MASK);
967 scintilla_send_message (SCINTILLA (te->scintilla),
968 SCI_SETSTYLING, end-start+1, 0);
970 if (current_styling_pos < start)
971 scintilla_send_message (SCINTILLA (te->scintilla),
972 SCI_STARTSTYLING, current_styling_pos,
973 0x1F);
974 } else {
975 if (indicator < 0) {
976 char current_mask;
977 glong i, last, start_style_pos = 0;
979 last = scintilla_send_message (SCINTILLA (te->scintilla),
980 SCI_GETTEXTLENGTH, 0, 0);
981 current_styling_pos = scintilla_send_message (SCINTILLA (te->scintilla),
982 SCI_GETENDSTYLED, 0, 0);
983 for (i = 0; i < last; i++)
985 current_mask =
986 scintilla_send_message (SCINTILLA (te->scintilla),
987 SCI_GETSTYLEAT, i, 0);
988 current_mask &= INDICS_MASK;
989 if (current_mask != 0)
991 if (start_style_pos == 0)
992 start_style_pos = i;
993 scintilla_send_message (SCINTILLA (te->scintilla),
994 SCI_STARTSTYLING, i, INDICS_MASK);
995 scintilla_send_message (SCINTILLA (te->scintilla),
996 SCI_SETSTYLING, 1, 0);
999 if (current_styling_pos < start_style_pos)
1000 scintilla_send_message (SCINTILLA (te->scintilla),
1001 SCI_STARTSTYLING, current_styling_pos,
1002 0x1F);
1005 return 0;
1008 void
1009 text_editor_set_line_marker (TextEditor *te, glong line)
1011 g_return_if_fail (te != NULL);
1012 g_return_if_fail(IS_SCINTILLA (te->scintilla) == TRUE);
1014 // FIXME: anjuta_delete_all_marker (TEXT_EDITOR_LINEMARKER);
1015 text_editor_delete_marker_all (te, TEXT_EDITOR_LINEMARKER);
1016 text_editor_set_marker (te, line, TEXT_EDITOR_LINEMARKER);
1019 /* Support for DOS-Files
1021 * On load, Anjuta will detect DOS-files by finding <CR><LF>.
1022 * Anjuta will translate some chars >= 128 to native charset.
1023 * On save the DOS_EOL_CHECK(preferences->editor) will be checked
1024 * and chars >=128 will be replaced by DOS-codes, if any translation
1025 * match(see struct tr_dos in this file) and <CR><LF> will used
1026 * instead of <LF>.
1027 * The DOS_EOL_CHECK-checkbox will be set on loading a DOS-file.
1029 * 23.Sep.2001 Denis Boehme <boehme at syncio dot de>
1033 * this is a translation table from unix->dos
1034 * this table will be used by filter_chars and save filtered.
1036 static struct {
1037 unsigned char c; /* unix-char */
1038 unsigned char b; /* dos-char */
1039 } tr_dos[]= {
1040 { 'ä', 0x84 },
1041 { 'Ä', 0x8e },
1042 { 'ß', 0xe1 },
1043 { 'ü', 0x81 },
1044 { 'Ü', 0x9a },
1045 { 'ö', 0x94 },
1046 { 'Ö', 0x99 },
1047 { 'é', 0x82 },
1048 { 'É', 0x90 },
1049 { 'è', 0x9a },
1050 { 'È', 0xd4 },
1051 { 'ê', 0x88 },
1052 { 'Ê', 0xd2 },
1053 { 'á', 0xa0 },
1054 { 'Á', 0xb5 },
1055 { 'à', 0x85 },
1056 { 'À', 0xb7 },
1057 { 'â', 0x83 },
1058 { 'Â', 0xb6 },
1059 { 'ú', 0xa3 },
1060 { 'Ú', 0xe9 },
1061 { 'ù', 0x97 },
1062 { 'Ù', 0xeb },
1063 { 'û', 0x96 },
1064 { 'Û', 0xea }
1068 * filter chars in buffer, by using tr_dos-table.
1071 static size_t
1072 filter_chars_in_dos_mode(gchar *data_, size_t size )
1074 int k;
1075 size_t i;
1076 unsigned char * data = (unsigned char*)data_;
1077 unsigned char * tr_map;
1079 tr_map = (unsigned char *)malloc( 256 );
1080 memset( tr_map, 0, 256 );
1081 for ( k = 0; k < sizeof(tr_dos )/2 ; k++ )
1082 tr_map[tr_dos[k].b] = tr_dos[k].c;
1084 for ( i = 0; i < size; i++ )
1086 if ( (data[i] >= 128) && ( tr_map[data[i]] != 0) )
1087 data[i] = tr_map[data[i]];;
1090 if ( tr_map )
1091 free( tr_map );
1093 return size;
1097 * save buffer. filter chars and set dos-like CR/LF if dos_text is set.
1099 static GnomeVFSResult
1100 save_filtered_in_dos_mode(GnomeVFSHandle* vfs_write, gchar *data_,
1101 GnomeVFSFileSize size)
1103 GnomeVFSResult result;
1104 size_t i, j;
1105 unsigned char *data;
1106 unsigned char *tr_map;
1107 int k;
1109 /* build the translation table */
1110 tr_map = malloc( 256 );
1111 memset( tr_map, 0, 256 );
1113 for ( k = 0; k < sizeof(tr_dos)/2; k++)
1114 tr_map[tr_dos[k].c] = tr_dos[k].b;
1116 data = (unsigned char*)data_;
1117 i = 0; j = 0;
1118 while ( i < size )
1120 if (data[i]>=128) {
1121 /* convert dos-text */
1122 if ( tr_map[data[i]] != 0 )
1124 GnomeVFSFileSize bytes_written;
1125 result = gnome_vfs_write (vfs_write, &tr_map[data[i]], 1, &bytes_written);
1126 j += bytes_written;
1128 else
1130 /* char not found, skip transform */
1131 GnomeVFSFileSize bytes_written;
1132 result = gnome_vfs_write (vfs_write, &data[i], 1, &bytes_written);
1133 j += bytes_written;
1135 i++;
1137 else
1139 GnomeVFSFileSize bytes_written;
1140 result = gnome_vfs_write (vfs_write, &data[i], 1, &bytes_written);
1141 j += bytes_written;
1142 i++;
1144 if (result != GNOME_VFS_OK)
1145 break;
1148 if (tr_map)
1149 free (tr_map);
1150 return result;
1153 static gint
1154 determine_editor_mode(gchar* buffer, glong size)
1156 gint i;
1157 guint cr, lf, crlf, max_mode;
1158 gint mode;
1160 cr = lf = crlf = 0;
1162 for ( i = 0; i < size ; i++ )
1164 if ( buffer[i] == 0x0a ){
1165 // LF
1166 // mode = SC_EOF_LF;
1167 lf++;
1168 } else if ( buffer[i] == 0x0d ) {
1169 if (i >= (size-1)) {
1170 // Last char
1171 // CR
1172 // mode = SC_EOL_CR;
1173 cr++;
1174 } else {
1175 if (buffer[i+1] != 0x0a) {
1176 // CR
1177 // mode = SC_EOL_CR;
1178 cr++;
1179 } else {
1180 // CRLF
1181 // mode = SC_EOL_CRLF;
1182 crlf++;
1184 i++;
1189 /* Vote for the maximum */
1190 mode = SC_EOL_LF;
1191 max_mode = lf;
1192 if (crlf > max_mode) {
1193 mode = SC_EOL_CRLF;
1194 max_mode = crlf;
1196 if (cr > max_mode) {
1197 mode = SC_EOL_CR;
1198 max_mode = cr;
1200 /* DEBUG_PRINT ("EOL chars: LR = %d, CR = %d, CRLF = %d", lf, cr, crlf); */
1201 /* DEBUG_PRINT ("Autodetected Editor mode [%d]", mode); */
1202 return mode;
1205 static gchar *
1206 convert_to_utf8_from_charset (const gchar *content,
1207 gsize len,
1208 const gchar *charset)
1210 gchar *utf8_content = NULL;
1211 GError *conv_error = NULL;
1212 gchar* converted_contents = NULL;
1213 gsize bytes_written;
1215 g_return_val_if_fail (content != NULL, NULL);
1217 /* DEBUG_PRINT ("Trying to convert from %s to UTF-8", charset); */
1219 converted_contents = g_convert (content, len, "UTF-8",
1220 charset, NULL, &bytes_written,
1221 &conv_error);
1223 if ((conv_error != NULL) || (converted_contents == NULL) ||
1224 !g_utf8_validate (converted_contents, bytes_written, NULL))
1226 /* DEBUG_PRINT ("Couldn't convert from %s to UTF-8.", charset); */
1228 if (converted_contents != NULL)
1229 g_free (converted_contents);
1231 if (conv_error != NULL)
1233 g_error_free (conv_error);
1234 conv_error = NULL;
1237 utf8_content = NULL;
1238 } else {
1239 /* DEBUG_PRINT ("Converted from %s to UTF-8.", charset); */
1240 utf8_content = converted_contents;
1242 return utf8_content;
1245 static gchar *
1246 convert_to_utf8 (PropsID props, const gchar *content, gsize len,
1247 gchar **encoding_used)
1249 GList *encodings = NULL;
1250 GList *start;
1251 const gchar *locale_charset;
1252 GList *encoding_strings;
1254 g_return_val_if_fail (!g_utf8_validate (content, len, NULL),
1255 g_strndup (content, len < 0 ? strlen (content) : len));
1257 encoding_strings = sci_prop_glist_from_data (props, SUPPORTED_ENCODINGS);
1258 encodings = anjuta_encoding_get_encodings (encoding_strings);
1259 anjuta_util_glist_strings_free (encoding_strings);
1261 if (g_get_charset (&locale_charset) == FALSE)
1263 const AnjutaEncoding *locale_encoding;
1265 /* not using a UTF-8 locale, so try converting
1266 * from that first */
1267 if (locale_charset != NULL)
1269 locale_encoding = anjuta_encoding_get_from_charset (locale_charset);
1270 encodings = g_list_prepend (encodings,
1271 (gpointer) locale_encoding);
1272 /* DEBUG_PRINT ("Current charset = %s", locale_charset); */
1276 start = encodings;
1278 while (encodings != NULL)
1280 AnjutaEncoding *enc;
1281 const gchar *charset;
1282 gchar *utf8_content;
1284 enc = (AnjutaEncoding *) encodings->data;
1286 charset = anjuta_encoding_get_charset (enc);
1288 /* DEBUG_PRINT ("Trying to convert %d bytes of data into UTF-8.", len); */
1290 fflush (stdout);
1291 utf8_content = convert_to_utf8_from_charset (content, len, charset);
1293 if (utf8_content != NULL) {
1294 if (encoding_used != NULL)
1296 if (*encoding_used != NULL)
1297 g_free (*encoding_used);
1299 *encoding_used = g_strdup (charset);
1302 return utf8_content;
1305 encodings = encodings->next;
1308 g_list_free (start);
1310 return NULL;
1313 static gboolean
1314 load_from_file (TextEditor *te, gchar *uri, gchar **err)
1316 GnomeVFSURI* vfs_uri;
1317 GnomeVFSHandle* vfs_read;
1318 GnomeVFSResult result;
1319 GnomeVFSFileInfo info;
1320 GnomeVFSFileSize nchars;
1321 gint dos_filter, editor_mode;
1322 gchar *file_content = NULL;
1323 gchar *buffer = NULL;
1325 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CLEARALL,
1326 0, 0);
1327 vfs_uri = gnome_vfs_uri_new(uri);
1328 result = gnome_vfs_get_file_info_uri(vfs_uri, &info, GNOME_VFS_FILE_INFO_DEFAULT);
1329 if (result != GNOME_VFS_OK)
1331 *err = g_strdup (_("Could not get file info"));
1332 return FALSE;
1334 buffer = g_malloc (info.size + 1);
1335 if (buffer == NULL && info.size != 0)
1337 /* DEBUG_PRINT ("This file is too big. Unable to allocate memory."); */
1338 *err = g_strdup (_("This file is too big. Unable to allocate memory."));
1339 return FALSE;
1342 result = gnome_vfs_open_uri(&vfs_read, vfs_uri, GNOME_VFS_OPEN_READ);
1343 if (result != GNOME_VFS_OK)
1345 *err = g_strdup (_("Could not open file"));
1346 return FALSE;
1348 /* Crude way of loading, but faster */
1349 result = gnome_vfs_read (vfs_read, buffer, info.size, &nchars);
1350 if (result != GNOME_VFS_OK && !(result == GNOME_VFS_ERROR_EOF && info.size == 0))
1352 g_free(buffer);
1353 *err = g_strdup (_("Error while reading from file"));
1354 return FALSE;
1357 if (buffer)
1359 buffer[info.size] = '\0';
1360 file_content = g_strdup (buffer);
1363 if (info.size != nchars)
1365 /* DEBUG_PRINT ("File size and loaded size not matching"); */
1367 dos_filter =
1368 anjuta_preferences_get_int (ANJUTA_PREFERENCES (te->preferences),
1369 DOS_EOL_CHECK);
1371 /* Set editor mode */
1372 editor_mode = determine_editor_mode (buffer, nchars);
1373 scintilla_send_message (SCINTILLA (te->scintilla),
1374 SCI_SETEOLMODE, editor_mode, 0);
1376 /* DEBUG_PRINT ("Loaded in editor mode [%d]", editor_mode); */
1378 /* Determine character encoding and convert to utf-8*/
1379 if (nchars > 0)
1381 if (g_utf8_validate (buffer, nchars, NULL))
1383 if (te->encoding)
1384 g_free (te->encoding);
1385 te->encoding = NULL;
1387 else
1389 gchar *converted_text;
1391 converted_text = convert_to_utf8 (te->props_base,
1392 buffer, nchars, &te->encoding);
1394 if (converted_text == NULL)
1396 /* bail out */
1397 g_free (buffer);
1398 g_free (file_content);
1399 *err = g_strdup (_("The file does not look like a text file or the file encoding is not supported."
1400 " Please check if the encoding of file is in the supported encodings list."
1401 " If not, add it from the preferences."));
1402 gnome_vfs_close(vfs_read);
1403 return FALSE;
1405 g_free (buffer);
1406 buffer = converted_text;
1407 nchars = strlen (converted_text);
1410 if (dos_filter && editor_mode == SC_EOL_CRLF){
1411 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Dos => Unix]"); */
1412 nchars = filter_chars_in_dos_mode( buffer, nchars );
1414 scintilla_send_message (SCINTILLA (te->scintilla), SCI_ADDTEXT,
1415 nchars, (long) buffer);
1417 g_free (buffer);
1419 /* Save the buffer as last saved content */
1420 g_free (te->last_saved_content);
1421 te->last_saved_content = file_content;
1423 gnome_vfs_close(vfs_read);
1424 return TRUE;
1427 static GnomeVFSResult
1428 save_to_file (TextEditor *te, gchar * uri)
1430 GnomeVFSHandle* vfs_write;
1431 GnomeVFSResult result;
1432 GnomeVFSFileSize nchars, size;
1433 gint strip;
1434 gchar *data;
1436 result = gnome_vfs_create (&vfs_write, uri, GNOME_VFS_OPEN_WRITE,
1437 FALSE, 0664);
1438 if (result != GNOME_VFS_OK)
1439 return result;
1441 nchars = scintilla_send_message (SCINTILLA (te->scintilla),
1442 SCI_GETLENGTH, 0, 0);
1443 data = (gchar *) aneditor_command (te->editor_id,
1444 ANE_GETTEXTRANGE, 0, nchars);
1445 if (data)
1447 gint dos_filter, editor_mode;
1449 size = strlen (data);
1451 /* Save according to the correct encoding */
1452 if (anjuta_preferences_get_int (te->preferences,
1453 SAVE_ENCODING_CURRENT_LOCALE))
1455 /* Save in current locate */
1456 GError *conv_error = NULL;
1457 gchar* converted_file_contents = NULL;
1459 /* DEBUG_PRINT ("Using current locale's encoding"); */
1461 converted_file_contents = g_locale_from_utf8 (data, -1, NULL,
1462 NULL, &conv_error);
1464 if (conv_error != NULL)
1466 /* Conversion error */
1467 g_error_free (conv_error);
1469 else
1471 g_free (data);
1472 data = converted_file_contents;
1473 size = strlen (converted_file_contents);
1476 else
1478 /* Save in original encoding */
1479 if ((te->encoding != NULL) &&
1480 anjuta_preferences_get_int (te->preferences,
1481 SAVE_ENCODING_ORIGINAL))
1483 GError *conv_error = NULL;
1484 gchar* converted_file_contents = NULL;
1486 /* DEBUG_PRINT ("Using encoding %s", te->encoding); */
1488 /* Try to convert it from UTF-8 to original encoding */
1489 converted_file_contents = g_convert (data, -1,
1490 te->encoding,
1491 "UTF-8", NULL, NULL,
1492 &conv_error);
1494 if (conv_error != NULL)
1496 /* Conversion error */
1497 g_error_free (conv_error);
1499 else
1501 g_free (data);
1502 data = converted_file_contents;
1503 size = strlen (converted_file_contents);
1506 else
1508 /* Save in utf-8 */
1509 /* DEBUG_PRINT ("Using utf-8 encoding"); */
1513 /* Strip trailing spaces */
1514 strip = anjuta_preferences_get_int (te->preferences,
1515 STRIP_TRAILING_SPACES);
1516 if (strip)
1518 while (size > 0 && isspace(data[size - 1]))
1519 -- size;
1521 if ((size > 1) && ('\n' != data[size-1]))
1523 data[size] = '\n';
1524 ++ size;
1526 dos_filter = anjuta_preferences_get_int (te->preferences,
1527 DOS_EOL_CHECK);
1528 editor_mode = scintilla_send_message (SCINTILLA (te->scintilla),
1529 SCI_GETEOLMODE, 0, 0);
1530 /* DEBUG_PRINT ("Saving in editor mode [%d]", editor_mode); */
1531 nchars = size;
1532 if (editor_mode == SC_EOL_CRLF && dos_filter)
1534 /* DEBUG_PRINT ("Filtering Extrageneous DOS characters in dos mode [Unix => Dos]"); */
1535 size = save_filtered_in_dos_mode (vfs_write, data, size);
1537 else
1539 result = gnome_vfs_write(vfs_write, data, size, &nchars);
1543 /* Set last content saved to data */
1544 g_free (te->last_saved_content);
1545 te->last_saved_content = data;
1547 if (result == GNOME_VFS_OK)
1548 result = gnome_vfs_close(vfs_write);
1549 else
1550 gnome_vfs_close (vfs_write);
1552 return result;
1555 gboolean
1556 text_editor_load_file (TextEditor * te)
1558 gchar *err = NULL;
1560 if (te == NULL || te->filename == NULL)
1561 return FALSE;
1562 if (IS_SCINTILLA (te->scintilla) == FALSE)
1563 return FALSE;
1564 anjuta_status (te->status, _("Loading file..."), 5);
1566 text_editor_freeze (te);
1568 // te->modified_time = time (NULL);
1569 text_editor_update_monitor (te, FALSE);
1570 if (load_from_file (te, te->uri, &err) == FALSE)
1572 anjuta_util_dialog_error (NULL,
1573 _("Could not load file: %s\n\nDetails: %s"),
1574 te->filename, err);
1575 g_free (err);
1576 text_editor_thaw (te);
1577 return FALSE;
1579 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GOTOPOS,
1580 0, 0);
1581 // check_tm_file(te);
1582 text_editor_thaw (te);
1583 scintilla_send_message (SCINTILLA (te->scintilla),
1584 SCI_SETSAVEPOINT, 0, 0);
1585 scintilla_send_message (SCINTILLA (te->scintilla),
1586 SCI_EMPTYUNDOBUFFER, 0, 0);
1587 text_editor_set_hilite_type (te, NULL);
1588 if (anjuta_preferences_get_int (te->preferences, FOLD_ON_OPEN))
1590 aneditor_command (te->editor_id, ANE_CLOSE_FOLDALL, 0, 0);
1592 text_editor_set_line_number_width(te);
1593 anjuta_status (te->status, _("File loaded successfully"), 5);
1594 return TRUE;
1597 gboolean
1598 text_editor_save_file (TextEditor * te, gboolean update)
1600 gboolean ret = FALSE;
1601 gchar *save_uri;
1602 GnomeVFSResult result;
1603 GtkWindow *parent;
1605 if (te == NULL)
1606 return FALSE;
1607 if (IS_SCINTILLA (te->scintilla) == FALSE)
1608 return FALSE;
1610 text_editor_freeze (te);
1611 text_editor_set_line_number_width(te);
1612 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (te)));
1614 anjuta_status (te->status, _("Saving file..."), 5);
1615 text_editor_update_monitor (te, TRUE);
1617 save_uri = g_strconcat (te->uri, "~", NULL);
1618 result = save_to_file (te, save_uri);
1619 if (result != GNOME_VFS_OK)
1621 GList *sources = NULL;
1622 GnomeVFSURI *vfs_uri;
1624 text_editor_thaw (te);
1625 anjuta_util_dialog_error (parent,
1626 _("Could not save intermediate file %s: %s."),
1627 save_uri,
1628 gnome_vfs_result_to_string (result));
1630 vfs_uri = gnome_vfs_uri_new (save_uri);
1631 sources = g_list_append (sources, vfs_uri);
1632 gnome_vfs_xfer_delete_list (sources, GNOME_VFS_XFER_ERROR_MODE_ABORT,
1633 GNOME_VFS_XFER_DELETE_ITEMS |
1634 GNOME_VFS_XFER_REMOVESOURCE, NULL, NULL);
1635 g_list_free (sources);
1636 gnome_vfs_uri_unref (vfs_uri);
1638 else
1640 GnomeVFSURI *src_uri;
1641 GnomeVFSURI *dest_uri;
1643 src_uri = gnome_vfs_uri_new (save_uri);
1644 dest_uri = gnome_vfs_uri_new (te->uri);
1646 /* Move 'file~' to 'file' */
1647 result = gnome_vfs_xfer_uri (src_uri, dest_uri,
1648 GNOME_VFS_XFER_DELETE_ITEMS |
1649 GNOME_VFS_XFER_REMOVESOURCE,
1650 GNOME_VFS_XFER_ERROR_MODE_ABORT,
1651 GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
1652 NULL, NULL);
1653 /* we need to update UI with the call to scintilla */
1654 text_editor_thaw (te);
1655 if (result != GNOME_VFS_OK)
1657 anjuta_util_dialog_error (parent,
1658 _("Could not save file %s: %s."),
1659 te->uri,
1660 gnome_vfs_result_to_string (result));
1662 else
1664 scintilla_send_message (SCINTILLA (te->scintilla),
1665 SCI_SETSAVEPOINT, 0, 0);
1666 g_signal_emit_by_name (G_OBJECT (te), "saved", te->uri);
1667 anjuta_status (te->status, _("File saved successfully"), 5);
1668 ret = TRUE;
1670 gnome_vfs_uri_unref (src_uri);
1671 gnome_vfs_uri_unref (dest_uri);
1673 text_editor_update_monitor (te, FALSE);
1674 g_free (save_uri);
1675 return ret;
1678 gboolean
1679 text_editor_save_yourself (TextEditor * te, FILE * stream)
1681 return TRUE;
1684 gboolean
1685 text_editor_recover_yourself (TextEditor * te, FILE * stream)
1687 return TRUE;
1690 void
1691 text_editor_undo (TextEditor * te)
1693 scintilla_send_message (SCINTILLA (te->scintilla),
1694 SCI_UNDO, 0, 0);
1697 void
1698 text_editor_redo (TextEditor * te)
1700 scintilla_send_message (SCINTILLA (te->scintilla),
1701 SCI_REDO, 0, 0);
1704 void
1705 text_editor_update_controls (TextEditor * te)
1707 #if 0 //FIXME
1708 gboolean F, P, L, C, S;
1710 if (te == NULL)
1711 return;
1712 S = text_editor_is_saved (te);
1713 L = anjuta_launcher_is_busy (app->launcher);
1714 P = app->project_dbase->project_is_open;
1716 switch (get_file_ext_type (te->filename))
1718 case FILE_TYPE_C:
1719 case FILE_TYPE_CPP:
1720 case FILE_TYPE_ASM:
1721 F = TRUE;
1722 break;
1723 default:
1724 F = FALSE;
1726 switch (get_file_ext_type (te->filename))
1728 case FILE_TYPE_C:
1729 case FILE_TYPE_CPP:
1730 case FILE_TYPE_HEADER:
1731 C = TRUE;
1732 break;
1733 default:
1734 C = FALSE;
1736 gtk_widget_set_sensitive (te->buttons.save, !S);
1737 gtk_widget_set_sensitive (te->buttons.reload,
1738 (te->uri != NULL));
1739 gtk_widget_set_sensitive (te->buttons.compile, F && !L);
1740 gtk_widget_set_sensitive (te->buttons.build, (F || P) && !L);
1741 #endif
1744 gboolean
1745 text_editor_is_saved (TextEditor * te)
1747 return !(scintilla_send_message (SCINTILLA (te->scintilla),
1748 SCI_GETMODIFY, 0, 0));
1751 gboolean
1752 text_editor_has_selection (TextEditor * te)
1754 gint from, to;
1755 from = scintilla_send_message (SCINTILLA (te->scintilla),
1756 SCI_GETSELECTIONSTART, 0, 0);
1757 to = scintilla_send_message (SCINTILLA (te->scintilla),
1758 SCI_GETSELECTIONEND, 0, 0);
1759 return (from == to) ? FALSE : TRUE;
1762 glong text_editor_get_selection_start (TextEditor * te)
1764 return scintilla_send_message (SCINTILLA (te->scintilla),
1765 SCI_GETSELECTIONSTART, 0, 0);
1768 glong text_editor_get_selection_end (TextEditor * te)
1770 return scintilla_send_message (SCINTILLA (te->scintilla),
1771 SCI_GETSELECTIONEND, 0, 0);
1774 gchar*
1775 text_editor_get_selection (TextEditor * te)
1777 guint from, to;
1778 struct TextRange tr;
1780 from = scintilla_send_message (SCINTILLA (te->scintilla),
1781 SCI_GETSELECTIONSTART, 0, 0);
1782 to = scintilla_send_message (SCINTILLA (te->scintilla),
1783 SCI_GETSELECTIONEND, 0, 0);
1784 if (from == to)
1785 return NULL;
1786 tr.chrg.cpMin = MIN(from, to);
1787 tr.chrg.cpMax = MAX(from, to);
1788 tr.lpstrText = g_malloc (sizeof(gchar)*(tr.chrg.cpMax-tr.chrg.cpMin)+5);
1789 scintilla_send_message (SCINTILLA(te->scintilla), SCI_GETTEXTRANGE, 0, (long)(&tr));
1790 return tr.lpstrText;
1793 gboolean
1794 text_editor_is_marker_set (TextEditor* te, glong line, gint marker)
1796 gint state;
1798 g_return_val_if_fail (te != NULL, FALSE);
1799 g_return_val_if_fail (line >= 0, FALSE);
1800 g_return_val_if_fail (marker < 32, FALSE);
1802 state = scintilla_send_message (SCINTILLA(te->scintilla),
1803 SCI_MARKERGET, linenum_text_editor_to_scintilla (line), 0);
1804 return ((state & (1 << marker)));
1807 void
1808 text_editor_delete_marker_all (TextEditor *te, gint marker)
1810 g_return_if_fail (IS_TEXT_EDITOR (te));
1811 g_return_if_fail (marker < 32);
1812 scintilla_send_message (SCINTILLA (te->scintilla),
1813 SCI_MARKERDELETEALL, marker, 0);
1816 void
1817 text_editor_delete_marker (TextEditor* te, glong line, gint marker)
1819 g_return_if_fail (IS_TEXT_EDITOR (te));
1820 g_return_if_fail (line >= 0);
1821 g_return_if_fail (marker < 32);
1823 scintilla_send_message (SCINTILLA(te->scintilla),
1824 SCI_MARKERDELETE, linenum_text_editor_to_scintilla (line), marker);
1827 gint
1828 text_editor_line_from_handle (TextEditor* te, gint marker_handle)
1830 gint line;
1832 g_return_val_if_fail (te != NULL, -1);
1834 line = scintilla_send_message (SCINTILLA(te->scintilla),
1835 SCI_MARKERLINEFROMHANDLE, marker_handle, 0);
1837 return linenum_scintilla_to_text_editor (line);
1840 gint
1841 text_editor_get_bookmark_line( TextEditor* te, const glong nLineStart )
1843 return aneditor_command (te->editor_id, ANE_GETBOOKMARK_POS, nLineStart, 0);
1846 gint
1847 text_editor_get_num_bookmarks(TextEditor* te)
1849 gint nLineNo = -1 ;
1850 gint nMarkers = 0 ;
1852 g_return_val_if_fail (te != NULL, 0 );
1854 while( ( nLineNo = text_editor_get_bookmark_line( te, nLineNo ) ) >= 0 )
1856 //printf( "Line %d\n", nLineNo );
1857 nMarkers++;
1859 //printf( "out Line %d\n", nLineNo );
1860 return nMarkers ;
1863 /* Gets the word before just before carat */
1864 gchar*
1865 text_editor_get_word_before_carat (TextEditor *te)
1867 gchar buffer[512];
1868 buffer[0] = '\0';
1869 aneditor_command (TEXT_EDITOR (te)->editor_id,
1870 ANE_GETWORDBEFORECARAT, (glong) buffer, 512);
1871 if (buffer[0] != '\0')
1872 return g_strdup (buffer);
1873 else
1874 return NULL;
1878 *Get the current selection. If there is no selection, or if the selection
1879 * is all blanks, get the word under teh cursor.
1881 gchar*
1882 text_editor_get_current_word (TextEditor *te)
1884 char *buf = text_editor_get_selection(te);
1885 if (buf)
1887 g_strstrip(buf);
1888 if ('\0' == *buf)
1890 g_free(buf);
1891 buf = NULL;
1894 if (NULL == buf)
1896 int ret;
1897 buf = g_new(char, 256);
1898 ret = aneditor_command (te->editor_id, ANE_GETCURRENTWORD, (long)buf, 255L);
1899 if (!ret)
1901 g_free(buf);
1902 buf = NULL;
1906 #ifdef DEBUG
1907 if (buf)
1908 DEBUG_PRINT ("Current word is '%s'", buf);
1909 #endif
1911 return buf;
1914 void
1915 text_editor_function_select(TextEditor *te)
1917 gint pos;
1918 gint line;
1919 gint fold_level;
1920 gint start, end;
1921 gint line_count;
1922 gint tmp;
1924 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
1925 SCI_GETLINECOUNT, 0, 0);
1926 pos = scintilla_send_message(SCINTILLA(te->scintilla),
1927 SCI_GETCURRENTPOS, 0, 0);
1928 line = scintilla_send_message(SCINTILLA(te->scintilla),
1929 SCI_LINEFROMPOSITION, pos, 0);
1931 tmp = line + 1;
1932 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1933 SCI_GETFOLDLEVEL, line, 0) ;
1934 if ((fold_level & 0xFF) != 0)
1936 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
1937 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1938 SCI_GETFOLDLEVEL, --line, 0) ;
1939 start = scintilla_send_message(SCINTILLA(te->scintilla),
1940 SCI_POSITIONFROMLINE, line + 1, 0);
1941 line = tmp;
1942 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1943 SCI_GETFOLDLEVEL, line, 0) ;
1944 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
1945 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
1946 SCI_GETFOLDLEVEL, ++line, 0) ;
1948 end = scintilla_send_message(SCINTILLA(te->scintilla),
1949 SCI_POSITIONFROMLINE, line , 0);
1950 scintilla_send_message(SCINTILLA(te->scintilla),
1951 SCI_SETSEL, start, end) ;
1955 void
1956 text_editor_grab_focus (TextEditor *te)
1958 g_return_if_fail (IS_TEXT_EDITOR (te));
1959 scintilla_send_message (SCINTILLA (te->scintilla), SCI_GRABFOCUS, 0, 0);
1962 void
1963 text_editor_set_popup_menu (TextEditor *te, GtkWidget *popup_menu)
1965 if (popup_menu)
1966 g_object_ref (popup_menu);
1967 if (te->popup_menu)
1968 g_object_unref (te->popup_menu);
1969 te->popup_menu = popup_menu;
1972 void
1973 text_editor_set_busy (TextEditor *te, gboolean state)
1975 if (state)
1976 scintilla_send_message (SCINTILLA (te->scintilla),
1977 SCI_SETCURSOR, SC_CURSORWAIT, 0);
1978 else
1979 scintilla_send_message (SCINTILLA (te->scintilla),
1980 SCI_SETCURSOR, SC_CURSORNORMAL, 0);
1983 gint
1984 text_editor_get_props ()
1986 /* Built in values */
1987 static PropsID props_built_in = 0;
1989 /* System values */
1990 static PropsID props_global = 0;
1992 /* User values */
1993 // static PropsID props_local = 0;
1995 /* Session values */
1996 static PropsID props_session = 0;
1998 /* Instance values */
1999 static PropsID props = 0;
2001 gchar *propdir, *propfile;
2003 if (props)
2004 return props;
2006 props_built_in = sci_prop_set_new ();
2007 props_global = sci_prop_set_new ();
2008 // props_local = sci_prop_set_new ();
2009 props_session = sci_prop_set_new ();
2010 props = sci_prop_set_new ();
2012 sci_prop_clear (props_built_in);
2013 sci_prop_clear (props_global);
2014 // sci_prop_clear (props_local);
2015 sci_prop_clear (props_session);
2016 sci_prop_clear (props);
2018 sci_prop_set_parent (props_global, props_built_in);
2019 // sci_prop_set_parent (props_local, props_global);
2020 // sci_prop_set_parent (props_session, props_local);
2021 sci_prop_set_parent (props_session, props_global);
2022 sci_prop_set_parent (props, props_session);
2024 propdir = g_build_filename (PACKAGE_DATA_DIR, "properties/", NULL);
2025 propfile = g_build_filename (PACKAGE_DATA_DIR, "properties",
2026 "anjuta.properties", NULL);
2027 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2029 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE)
2031 anjuta_util_dialog_error (NULL,
2032 _("Cannot load Global defaults and configuration files:\n"
2033 "%s.\n"
2034 "This may result in improper behaviour or instabilities.\n"
2035 "Anjuta will fall back to built in (limited) settings"),
2036 propfile);
2038 sci_prop_read (props_global, propfile, propdir);
2039 g_free (propfile);
2040 g_free (propdir);
2042 propdir = g_build_filename (g_get_home_dir(), ".anjuta" PREF_SUFFIX "/", NULL);
2043 propfile = g_build_filename (g_get_home_dir(), ".anjuta" PREF_SUFFIX,
2044 "editor-style.properties", NULL);
2045 /* DEBUG_PRINT ("Reading file: %s", propfile); */
2047 /* Create user.properties file, if it doesn't exist */
2048 if (g_file_test (propfile, G_FILE_TEST_EXISTS) == FALSE) {
2049 gchar* old_propfile = g_build_filename (g_get_home_dir(),
2050 ".anjuta"PREF_SUFFIX,
2051 "session.properties", NULL);
2052 if (g_file_test (old_propfile, G_FILE_TEST_EXISTS) == TRUE)
2053 anjuta_util_copy_file (old_propfile, propfile, FALSE);
2054 g_free (old_propfile);
2056 sci_prop_read (props_session, propfile, propdir);
2057 g_free (propdir);
2058 g_free (propfile);
2060 return props;
2063 void
2064 text_editor_set_line_number_width (TextEditor* te)
2066 /* Set line numbers with according to file size */
2067 if (anjuta_preferences_get_int_with_default(te->preferences,
2068 "margin.linenumber.visible", 0))
2070 int lines, line_number_width;
2071 gchar* line_number;
2072 gchar* line_number_dummy;
2074 lines =
2075 (int) scintilla_send_message
2076 (SCINTILLA(te->scintilla), SCI_GETLINECOUNT, 0,0);
2077 line_number = g_strdup_printf("%d", lines);
2078 line_number_dummy = g_strnfill(strlen(line_number) + 1, '9');
2079 line_number_width =
2080 (int) scintilla_send_message (SCINTILLA(te->scintilla),
2081 SCI_TEXTWIDTH,
2082 STYLE_LINENUMBER,
2083 (long) line_number_dummy);
2084 text_editor_command (te, ANE_SETLINENUMWIDTH, line_number_width, 0);
2085 g_free(line_number_dummy);
2086 g_free(line_number);
2090 gboolean
2091 text_editor_can_undo (TextEditor *te)
2093 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2094 return scintilla_send_message (SCINTILLA (te->scintilla),
2095 SCI_CANUNDO, 0, 0);
2098 gboolean
2099 text_editor_can_redo (TextEditor *te)
2101 g_return_val_if_fail (IS_TEXT_EDITOR (te), FALSE);
2102 return scintilla_send_message (SCINTILLA (te->scintilla),
2103 SCI_CANREDO, 0, 0);
2106 void
2107 text_editor_show_hover_tip (TextEditor *te, gint position, const gchar *info)
2109 text_editor_hide_hover_tip (te);
2110 if (!te->hover_tip_on)
2112 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSHOW,
2113 position, (long)info);
2114 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPSETHLT,
2115 strlen (info), 0);
2116 te->hover_tip_on = TRUE;
2120 void
2121 text_editor_hide_hover_tip (TextEditor *te)
2123 if (te->hover_tip_on)
2125 scintilla_send_message (SCINTILLA (te->scintilla),
2126 SCI_CALLTIPCANCEL, 0, 0);
2127 te->hover_tip_on = FALSE;
2131 void
2132 text_editor_command (TextEditor *te, gint command, glong wparam, glong lparam)
2134 GList *node;
2136 node = te->views;
2137 while (node)
2139 aneditor_command (GPOINTER_TO_INT (node->data), command, wparam, lparam);
2140 node = g_list_next(node);
2144 void
2145 text_editor_scintilla_command (TextEditor *te, gint command, glong wparam,
2146 glong lparam)
2148 GList *node;
2150 node = te->views;
2151 while (node)
2153 GtkWidget *scintilla;
2154 scintilla = aneditor_get_widget (GPOINTER_TO_INT (node->data));
2155 scintilla_send_message (SCINTILLA(scintilla), command, wparam, lparam);
2156 node = g_list_next(node);
2160 /* IAnjutaEditor interface implementation */
2162 static gint
2163 itext_editor_get_tab_size (IAnjutaEditor *editor, GError **e)
2165 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2166 SCI_GETTABWIDTH, 0, 0);
2169 static void
2170 itext_editor_set_tab_size (IAnjutaEditor *editor, gint tabsize, GError **e)
2172 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2173 SCI_SETTABWIDTH, tabsize, 0);
2176 static gboolean
2177 itext_editor_get_use_spaces (IAnjutaEditor *editor, GError **e)
2179 return !scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2180 SCI_GETUSETABS, 0, 0);
2183 static void
2184 itext_editor_set_use_spaces (IAnjutaEditor *editor, gboolean use_spaces, GError **e)
2186 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2187 SCI_SETUSETABS, !use_spaces, 0);
2190 static void
2191 itext_editor_set_auto_indent (IAnjutaEditor *editor, gboolean auto_indent, GError **e)
2193 text_editor_command (TEXT_EDITOR(editor), ANE_SETINDENTMAINTAIN, auto_indent, 0);
2196 static void
2197 itext_editor_goto_line (IAnjutaEditor *editor, gint lineno, GError **e)
2199 text_editor_goto_line (TEXT_EDITOR (editor), lineno, FALSE, TRUE);
2202 static void
2203 itext_editor_goto_position (IAnjutaEditor *editor, gint position, GError **e)
2205 text_editor_goto_point (TEXT_EDITOR (editor), position);
2208 static gchar*
2209 itext_editor_get_text (IAnjutaEditor *editor, gint position, gint length,
2210 GError **e)
2212 gchar *data;
2213 gint end;
2214 TextEditor *te = TEXT_EDITOR (editor);
2216 g_return_val_if_fail (position >= 0, NULL);
2217 if (length == 0)
2218 return NULL;
2220 if (length < 0)
2221 end = scintilla_send_message (SCINTILLA (te->scintilla),
2222 SCI_GETLENGTH, 0, 0);
2223 else
2224 end = position + length;
2226 /* Silently correct length like stated in the docs #506740 */
2227 if (end > ianjuta_editor_get_length (editor, NULL))
2228 end = -1;
2230 data = (gchar *) aneditor_command (te->editor_id,
2231 ANE_GETTEXTRANGE, position, end);
2232 return data;
2235 static gint
2236 itext_editor_get_position (IAnjutaEditor *editor, GError **e)
2238 return text_editor_get_current_position (TEXT_EDITOR(editor));
2241 static IAnjutaIterable*
2242 itext_editor_get_position_iter (IAnjutaEditor* editor, GError **e)
2244 TextEditor* te = TEXT_EDITOR (editor);
2245 return IANJUTA_ITERABLE (text_editor_cell_new (te,
2246 text_editor_get_current_position (te)));
2249 static gint
2250 itext_editor_get_lineno (IAnjutaEditor *editor, GError **e)
2252 return text_editor_get_current_lineno (TEXT_EDITOR (editor));
2255 static gint
2256 itext_editor_get_length (IAnjutaEditor *editor, GError **e)
2258 return aneditor_command (TEXT_EDITOR (editor)->editor_id,
2259 ANE_GETLENGTH, 0, 0);
2262 static gchar*
2263 itext_editor_get_current_word (IAnjutaEditor *editor, GError **e)
2265 gchar buffer[512];
2266 buffer[0] = '\0';
2267 aneditor_command (TEXT_EDITOR (editor)->editor_id,
2268 ANE_GETCURRENTWORD, (glong) buffer, 512);
2269 if (buffer[0] != '\0')
2270 return g_strdup (buffer);
2271 else
2272 return NULL;
2275 static void
2276 itext_editor_insert (IAnjutaEditor *editor, gint pos, const gchar *txt,
2277 gint length, GError **e)
2279 gchar *text_to_insert;
2280 if (length >= 0)
2281 text_to_insert = g_strndup (txt, length);
2282 else
2283 text_to_insert = g_strdup (txt);
2285 aneditor_command (TEXT_EDITOR(editor)->editor_id, ANE_INSERTTEXT,
2286 pos, (long)text_to_insert);
2287 g_free (text_to_insert);
2290 static void
2291 itext_editor_append (IAnjutaEditor *editor, const gchar *txt,
2292 gint length, GError **e)
2294 gchar *text_to_insert;
2295 if (length >= 0)
2296 text_to_insert = g_strndup (txt, length);
2297 else
2298 text_to_insert = g_strdup (txt);
2300 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2301 SCI_APPENDTEXT, strlen(text_to_insert),
2302 (long)text_to_insert);
2303 g_free (text_to_insert);
2306 static void
2307 itext_editor_erase (IAnjutaEditor *editor, gint position, gint length,
2308 GError **e)
2310 gint end;
2312 g_return_if_fail (position >= 0);
2313 if (length == 0)
2314 return;
2316 if (length < 0)
2317 end = scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2318 SCI_GETLENGTH, 0, 0);
2319 else
2320 end = position + length;
2322 ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (editor) , position,
2323 end, FALSE, NULL);
2324 text_editor_replace_selection (TEXT_EDITOR (editor), "");
2327 static void
2328 itext_editor_erase_all (IAnjutaEditor *editor, GError **e)
2330 scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla), SCI_CLEARALL,
2331 0, 0);
2334 static int
2335 itext_editor_get_column(IAnjutaEditor *editor, GError **e)
2337 return text_editor_get_current_column(TEXT_EDITOR(editor));
2340 static gboolean
2341 itext_editor_get_overwrite(IAnjutaEditor *editor, GError **e)
2343 return text_editor_get_overwrite(TEXT_EDITOR(editor));
2346 static void
2347 itext_editor_set_popup_menu(IAnjutaEditor *editor, GtkWidget* menu, GError **e)
2349 text_editor_set_popup_menu(TEXT_EDITOR(editor), menu);
2352 static gint
2353 itext_editor_get_line_from_position (IAnjutaEditor *editor, gint pos, GError **e)
2355 return text_editor_get_line_from_position (TEXT_EDITOR (editor), pos);
2358 static gint
2359 itext_editor_get_line_begin_position (IAnjutaEditor *editor, gint line,
2360 GError **e)
2362 gint ln;
2364 g_return_val_if_fail (line > 0, -1);
2366 ln = linenum_text_editor_to_scintilla (line);
2367 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2368 SCI_POSITIONFROMLINE, ln, 0);
2371 static gint
2372 itext_editor_get_line_end_position (IAnjutaEditor *editor, gint line,
2373 GError **e)
2375 gint ln;
2377 g_return_val_if_fail (line > 0, -1);
2379 ln = linenum_text_editor_to_scintilla (line);
2380 return scintilla_send_message (SCINTILLA (TEXT_EDITOR (editor)->scintilla),
2381 SCI_GETLINEENDPOSITION, ln, 0);
2384 static IAnjutaIterable*
2385 itext_editor_get_cell_iter (IAnjutaEditor *editor, gint position, GError **e)
2387 TextEditorCell *editor_cell = text_editor_cell_new (TEXT_EDITOR (editor), position);
2388 return IANJUTA_ITERABLE (editor_cell);
2391 static void
2392 itext_editor_iface_init (IAnjutaEditorIface *iface)
2394 iface->get_tabsize = itext_editor_get_tab_size;
2395 iface->set_tabsize = itext_editor_set_tab_size;
2396 iface->get_use_spaces = itext_editor_get_use_spaces;
2397 iface->set_use_spaces = itext_editor_set_use_spaces;
2398 iface->set_auto_indent = itext_editor_set_auto_indent;
2399 iface->goto_line = itext_editor_goto_line;
2400 iface->goto_position = itext_editor_goto_position;
2401 iface->get_text = itext_editor_get_text;
2402 iface->get_position = itext_editor_get_position;
2403 iface->get_position_iter = itext_editor_get_position_iter;
2404 iface->get_lineno = itext_editor_get_lineno;
2405 iface->get_length = itext_editor_get_length;
2406 iface->get_current_word = itext_editor_get_current_word;
2407 iface->insert = itext_editor_insert;
2408 iface->append = itext_editor_append;
2409 iface->erase = itext_editor_erase;
2410 iface->erase_all = itext_editor_erase_all;
2411 iface->get_column = itext_editor_get_column;
2412 iface->get_overwrite = itext_editor_get_overwrite;
2413 iface->set_popup_menu = itext_editor_set_popup_menu;
2414 iface->get_line_from_position = itext_editor_get_line_from_position;
2415 iface->get_line_begin_position = itext_editor_get_line_begin_position;
2416 iface->get_line_end_position = itext_editor_get_line_end_position;
2417 iface->get_cell_iter = itext_editor_get_cell_iter;
2420 static const gchar *
2421 idocument_get_filename (IAnjutaDocument *editor, GError **e)
2423 return (TEXT_EDITOR (editor))->filename;
2426 static gboolean
2427 idocument_can_undo(IAnjutaDocument* editor, GError **e)
2429 return text_editor_can_undo(TEXT_EDITOR(editor));
2432 static gboolean
2433 idocument_can_redo(IAnjutaDocument *editor, GError **e)
2435 return text_editor_can_redo(TEXT_EDITOR(editor));
2438 static void
2439 idocument_undo(IAnjutaDocument* te, GError** ee)
2441 text_editor_command(TEXT_EDITOR(te), ANE_UNDO, 0, 0);
2444 static void
2445 idocument_begin_undo_action (IAnjutaDocument* te, GError** ee)
2447 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2448 SCI_BEGINUNDOACTION, 0, 0);
2451 static void
2452 idocument_end_undo_action (IAnjutaDocument* te, GError** ee)
2454 scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2455 SCI_ENDUNDOACTION, 0, 0);
2458 static void
2459 idocument_redo(IAnjutaDocument* te, GError** ee)
2461 text_editor_command(TEXT_EDITOR(te), ANE_REDO, 0, 0);
2464 static void
2465 idocument_grab_focus (IAnjutaDocument *editor, GError **e)
2467 text_editor_grab_focus (TEXT_EDITOR (editor));
2470 static void
2471 idocument_cut(IAnjutaDocument * te, GError** ee)
2473 text_editor_command(TEXT_EDITOR(te), ANE_CUT, 0, 0);
2476 static void
2477 idocument_copy(IAnjutaDocument * te, GError** ee)
2479 text_editor_command(TEXT_EDITOR(te), ANE_COPY, 0, 0);
2482 static void
2483 idocument_paste(IAnjutaDocument * te, GError** ee)
2485 text_editor_command(TEXT_EDITOR(te), ANE_PASTE, 0, 0);
2488 static void
2489 idocument_clear(IAnjutaDocument * te, GError** ee)
2491 text_editor_command(TEXT_EDITOR(te), ANE_CLEAR, 0, 0);
2494 static void
2495 idocument_iface_init(IAnjutaDocumentIface* iface)
2497 iface->get_filename = idocument_get_filename;
2498 iface->can_undo = idocument_can_undo;
2499 iface->can_redo = idocument_can_redo;
2500 iface->undo = idocument_undo;
2501 iface->redo = idocument_redo;
2502 iface->begin_undo_action = idocument_begin_undo_action;
2503 iface->end_undo_action = idocument_end_undo_action;
2504 iface->grab_focus = idocument_grab_focus;
2505 iface->cut = idocument_cut;
2506 iface->copy = idocument_copy;
2507 iface->paste = idocument_paste;
2508 iface->clear = idocument_clear;
2511 /* IAnjutaEditorSelection implementation */
2513 static gchar*
2514 iselection_get (IAnjutaEditorSelection *editor, GError **error)
2516 return text_editor_get_selection (TEXT_EDITOR (editor));
2519 static void
2520 iselection_set (IAnjutaEditorSelection *editor, gint start, gint end,
2521 gboolean backwards, GError **e)
2523 if (!backwards)
2524 scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2525 SCI_SETSEL, start, end);
2526 else
2527 scintilla_send_message(SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2528 SCI_SETSEL, end, start);
2531 static void
2532 iselection_set_iter (IAnjutaEditorSelection* edit,
2533 IAnjutaEditorCell* istart,
2534 IAnjutaEditorCell* iend,
2535 GError** e)
2537 TextEditorCell* start = TEXT_EDITOR_CELL (istart);
2538 TextEditorCell* end = TEXT_EDITOR_CELL (iend);
2540 iselection_set (edit, text_editor_cell_get_position (start),
2541 text_editor_cell_get_position (end), FALSE, e);
2544 static gboolean
2545 iselection_has_selection (IAnjutaEditorSelection *editor, GError **e)
2547 return text_editor_has_selection (TEXT_EDITOR (editor));
2550 static gint
2551 iselection_get_start (IAnjutaEditorSelection *editor, GError **e)
2553 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2554 SCI_GETSELECTIONSTART, 0, 0);
2555 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2556 SCI_GETSELECTIONEND, 0, 0);
2557 return (start != end)? start: -1;
2560 static IAnjutaIterable*
2561 iselection_get_start_iter (IAnjutaEditorSelection *edit, GError **e)
2563 gint start = iselection_get_start (edit, e);
2564 if (start != -1)
2566 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), start));
2568 else
2569 return NULL;
2572 static gint
2573 iselection_get_end (IAnjutaEditorSelection *editor, GError **e)
2575 gint start = scintilla_send_message (SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2576 SCI_GETSELECTIONSTART, 0, 0);
2577 gint end = scintilla_send_message (SCINTILLA(TEXT_EDITOR(editor)->scintilla),
2578 SCI_GETSELECTIONEND, 0, 0);
2579 return (start != end)? end: -1;
2582 static IAnjutaIterable*
2583 iselection_get_end_iter (IAnjutaEditorSelection *edit, GError **e)
2585 gint end = iselection_get_end (edit, e);
2586 if (end != -1)
2588 return IANJUTA_ITERABLE (text_editor_cell_new (TEXT_EDITOR (edit), end));
2590 else
2591 return NULL;
2594 static void
2595 iselection_replace (IAnjutaEditorSelection *editor, const gchar *txt,
2596 gint length, GError **e)
2598 gchar *text_to_insert;
2599 if (length >= 0)
2600 text_to_insert = g_strndup (txt, length);
2601 else
2602 text_to_insert = g_strdup (txt);
2604 text_editor_replace_selection (TEXT_EDITOR (editor), text_to_insert);
2606 g_free (text_to_insert);
2609 static void
2610 iselection_select_all(IAnjutaEditorSelection* te, GError** ee)
2612 text_editor_command(TEXT_EDITOR(te), ANE_SELECTALL, 0, 0);
2615 static void
2616 iselection_select_to_brace(IAnjutaEditorSelection* te, GError** ee)
2618 text_editor_command(TEXT_EDITOR(te), ANE_SELECTTOBRACE, 0, 0);
2621 static void
2622 iselection_select_block(IAnjutaEditorSelection *te, GError **e)
2624 text_editor_command(TEXT_EDITOR(te), ANE_SELECTBLOCK, 0, 0);
2627 static void
2628 iselection_select_function(IAnjutaEditorSelection *editor, GError **e)
2630 TextEditor* te = TEXT_EDITOR(editor);
2631 gint pos;
2632 gint line;
2633 gint fold_level;
2634 gint start, end;
2635 gint line_count;
2636 gint tmp;
2638 line_count = scintilla_send_message(SCINTILLA(te->scintilla),
2639 SCI_GETLINECOUNT, 0, 0);
2640 pos = scintilla_send_message(SCINTILLA(te->scintilla),
2641 SCI_GETCURRENTPOS, 0, 0);
2642 line = scintilla_send_message(SCINTILLA(te->scintilla),
2643 SCI_LINEFROMPOSITION, pos, 0);
2645 tmp = line + 1;
2646 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2647 SCI_GETFOLDLEVEL, line, 0) ;
2648 if ((fold_level & 0xFF) != 0)
2650 while((fold_level & 0x10FF) != 0x1000 && line >= 0)
2651 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2652 SCI_GETFOLDLEVEL, --line, 0) ;
2653 start = scintilla_send_message(SCINTILLA(te->scintilla),
2654 SCI_POSITIONFROMLINE, line + 1, 0);
2655 line = tmp;
2656 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2657 SCI_GETFOLDLEVEL, line, 0) ;
2658 while((fold_level & 0x10FF) != 0x1000 && line < line_count)
2659 fold_level = scintilla_send_message(SCINTILLA(te->scintilla),
2660 SCI_GETFOLDLEVEL, ++line, 0) ;
2662 end = scintilla_send_message(SCINTILLA(te->scintilla),
2663 SCI_POSITIONFROMLINE, line , 0);
2664 scintilla_send_message(SCINTILLA(te->scintilla),
2665 SCI_SETSEL, start, end) ;
2669 static void
2670 iselection_iface_init (IAnjutaEditorSelectionIface *iface)
2672 iface->has_selection = iselection_has_selection;
2673 iface->get = iselection_get;
2674 iface->set = iselection_set;
2675 iface->set_iter = iselection_set_iter;
2676 iface->get_start = iselection_get_start;
2677 iface->get_start_iter = iselection_get_start_iter;
2678 iface->get_end = iselection_get_end;
2679 iface->get_end_iter = iselection_get_end_iter;
2680 iface->replace = iselection_replace;
2681 iface->select_all = iselection_select_all;
2682 iface->select_to_brace = iselection_select_to_brace;
2683 iface->select_block = iselection_select_block;
2684 iface->select_function = iselection_select_function;
2687 /* IAnjutaFile implementation */
2689 static gchar*
2690 ifile_get_uri (IAnjutaFile *editor, GError **error)
2692 TextEditor *text_editor;
2693 text_editor = TEXT_EDITOR(editor);
2694 if (text_editor->uri)
2695 return g_strdup (text_editor->uri);
2697 else if (text_editor->filename)
2698 return gnome_vfs_get_uri_from_local_path (text_editor->filename);
2700 else
2701 return NULL;
2704 static void
2705 ifile_open (IAnjutaFile *editor, const gchar* uri, GError **error)
2707 /* Close current file and open new file in this editor */
2708 TextEditor* text_editor;
2709 text_editor = TEXT_EDITOR(editor);
2711 /* Do nothing if current file is not saved */
2712 if (!text_editor_is_saved (text_editor))
2713 return;
2714 text_editor->uri = g_strdup (uri);
2716 /* Remove path */
2717 text_editor->filename = g_strdup (g_basename (uri));
2718 text_editor_load_file (text_editor);
2721 static void
2722 isaveable_save (IAnjutaFileSavable* editor, GError** e)
2724 TextEditor *text_editor = TEXT_EDITOR(editor);
2725 if (text_editor->uri != NULL)
2726 text_editor_save_file(text_editor, FALSE);
2729 static void
2730 isavable_save_as (IAnjutaFileSavable* editor, const gchar* filename, GError** e)
2732 TextEditor *text_editor = TEXT_EDITOR(editor);
2733 text_editor->uri = g_strdup(filename);
2734 /* Remove path */
2735 text_editor->filename = g_strdup(strrchr(filename, '/') + 1);
2736 text_editor_save_file(text_editor, FALSE);
2739 static gboolean
2740 isavable_is_dirty (IAnjutaFileSavable* editor, GError** e)
2742 TextEditor *text_editor = TEXT_EDITOR(editor);
2743 return !text_editor_is_saved(text_editor);
2746 static void
2747 isavable_set_dirty (IAnjutaFileSavable* editor, gboolean dirty, GError** e)
2749 /* DEBUG_PRINT("set_dirty: Not implemented in EditorPlugin"); */
2753 static void
2754 isavable_iface_init (IAnjutaFileSavableIface *iface)
2756 iface->save = isaveable_save;
2757 iface->save_as = isavable_save_as;
2758 iface->set_dirty = isavable_set_dirty;
2759 iface->is_dirty = isavable_is_dirty;
2762 static void
2763 ifile_iface_init (IAnjutaFileIface *iface)
2765 iface->open = ifile_open;
2766 iface->get_uri = ifile_get_uri;
2769 /* Implementation of the IAnjutaMarkable interface */
2771 static gint
2772 marker_ianjuta_to_editor (IAnjutaMarkableMarker marker)
2774 gint mark;
2775 switch (marker)
2777 case IANJUTA_MARKABLE_LINEMARKER:
2778 mark = TEXT_EDITOR_LINEMARKER;
2779 break;
2780 case IANJUTA_MARKABLE_BOOKMARK:
2781 mark = TEXT_EDITOR_BOOKMARK;
2782 break;
2783 case IANJUTA_MARKABLE_BREAKPOINT_DISABLED:
2784 mark = TEXT_EDITOR_BREAKPOINT_DISABLED;
2785 break;
2786 case IANJUTA_MARKABLE_BREAKPOINT_ENABLED:
2787 mark = TEXT_EDITOR_BREAKPOINT_ENABLED;
2788 break;
2789 case IANJUTA_MARKABLE_PROGRAM_COUNTER:
2790 mark = TEXT_EDITOR_PROGRAM_COUNTER;
2791 break;
2792 default:
2793 mark = TEXT_EDITOR_LINEMARKER;
2795 return mark;
2798 static gint
2799 imarkable_mark (IAnjutaMarkable* editor, gint location,
2800 IAnjutaMarkableMarker marker, GError** e)
2802 return text_editor_set_marker (TEXT_EDITOR (editor), location,
2803 marker_ianjuta_to_editor (marker));
2806 static gint
2807 imarkable_location_from_handle (IAnjutaMarkable* editor, gint handle, GError** e)
2809 return text_editor_line_from_handle (TEXT_EDITOR (editor), handle);
2812 static void
2813 imarkable_unmark (IAnjutaMarkable* editor, gint location,
2814 IAnjutaMarkableMarker marker, GError** e)
2816 text_editor_delete_marker (TEXT_EDITOR (editor), location,
2817 marker_ianjuta_to_editor (marker));
2820 static gboolean
2821 imarkable_is_marker_set (IAnjutaMarkable* editor, gint location,
2822 IAnjutaMarkableMarker marker, GError** e)
2824 return text_editor_is_marker_set (TEXT_EDITOR (editor), location,
2825 marker_ianjuta_to_editor (marker));
2828 static void
2829 imarkable_delete_all_markers (IAnjutaMarkable* editor,
2830 IAnjutaMarkableMarker marker, GError** e)
2832 text_editor_delete_marker_all (TEXT_EDITOR (editor),
2833 marker_ianjuta_to_editor (marker));
2836 static void
2837 imarkable_iface_init (IAnjutaMarkableIface *iface)
2839 iface->mark = imarkable_mark;
2840 iface->location_from_handle = imarkable_location_from_handle;
2841 iface->unmark = imarkable_unmark;
2842 iface->is_marker_set = imarkable_is_marker_set;
2843 iface->delete_all_markers = imarkable_delete_all_markers;
2846 /* IAnjutaEditorFactory implementation */
2848 static IAnjutaEditor*
2849 itext_editor_factory_new_editor(IAnjutaEditorFactory* factory,
2850 const gchar* uri,
2851 const gchar* filename,
2852 GError** error)
2854 TextEditor *current_editor = TEXT_EDITOR (factory);
2855 GtkWidget* editor = text_editor_new (current_editor->status,
2856 current_editor->preferences,
2857 uri, filename);
2858 return IANJUTA_EDITOR (editor);
2861 static void
2862 itext_editor_factory_iface_init (IAnjutaEditorFactoryIface *iface)
2864 iface->new_editor = itext_editor_factory_new_editor;
2867 /* IAnjutaEditorConvert implementation */
2869 static void
2870 iconvert_to_upper(IAnjutaEditorConvert* te, gint start_position,
2871 gint end_position, GError** ee)
2873 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
2874 SCI_SETSEL, start_position, end_position);
2875 text_editor_command (TEXT_EDITOR(te), ANE_UPRCASE, 0, 0);
2878 static void
2879 iconvert_to_lower(IAnjutaEditorConvert* te, gint start_position,
2880 gint end_position, GError** ee)
2882 scintilla_send_message (SCINTILLA (TEXT_EDITOR(te)->scintilla),
2883 SCI_SETSEL, start_position, end_position);
2884 text_editor_command (TEXT_EDITOR(te), ANE_LWRCASE, 0, 0);
2887 static void
2888 iconvert_iface_init (IAnjutaEditorConvertIface *iface)
2890 iface->to_lower = iconvert_to_lower;
2891 iface->to_upper = iconvert_to_upper;
2894 /* IAnjutaEditorLineMode implementation */
2896 static IAnjutaEditorLineModeType
2897 ilinemode_get (IAnjutaEditorLineMode* te, GError** err)
2899 glong eolmode;
2900 IAnjutaEditorLineModeType retmode;
2902 g_return_val_if_fail (IS_TEXT_EDITOR (te), IANJUTA_EDITOR_LINE_MODE_LF);
2904 eolmode = scintilla_send_message (SCINTILLA (TEXT_EDITOR (te)->scintilla),
2905 SCI_GETEOLMODE, 0, 0);
2907 switch (eolmode) {
2908 case SC_EOL_CR:
2909 retmode = IANJUTA_EDITOR_LINE_MODE_CR;
2910 break;
2911 case SC_EOL_CRLF:
2912 retmode = IANJUTA_EDITOR_LINE_MODE_CRLF;
2913 break;
2914 case SC_EOL_LF:
2915 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
2916 break;
2917 default:
2918 retmode = IANJUTA_EDITOR_LINE_MODE_LF;
2919 g_warning ("Should not be here");
2921 return retmode;
2924 static void
2925 ilinemode_set (IAnjutaEditorLineMode* te, IAnjutaEditorLineModeType mode,
2926 GError** err)
2928 g_return_if_fail (IS_TEXT_EDITOR (te));
2930 switch (mode)
2932 case IANJUTA_EDITOR_LINE_MODE_LF:
2933 text_editor_command(TEXT_EDITOR(te), ANE_EOL_LF, 0, 0);
2934 break;
2936 case IANJUTA_EDITOR_LINE_MODE_CR:
2937 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CR, 0, 0);
2938 break;
2940 case IANJUTA_EDITOR_LINE_MODE_CRLF:
2941 text_editor_command(TEXT_EDITOR(te), ANE_EOL_CRLF, 0, 0);
2942 break;
2944 default:
2945 g_warning ("Should not reach here");
2946 break;
2950 static void
2951 ilinemode_convert (IAnjutaEditorLineMode *te, IAnjutaEditorLineModeType mode,
2952 GError **err)
2954 switch (mode)
2956 case IANJUTA_EDITOR_LINE_MODE_LF:
2957 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2958 ANE_EOL_LF, 0);
2959 break;
2961 case IANJUTA_EDITOR_LINE_MODE_CR:
2962 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2963 ANE_EOL_CR, 0);
2964 break;
2966 case IANJUTA_EDITOR_LINE_MODE_CRLF:
2967 text_editor_command (TEXT_EDITOR (te), ANE_EOL_CONVERT,
2968 ANE_EOL_CRLF, 0);
2969 break;
2971 default:
2972 g_warning ("Should not reach here");
2973 break;
2977 static void
2978 ilinemode_fix (IAnjutaEditorLineMode* te, GError** err)
2980 IAnjutaEditorLineModeType mode = ilinemode_get (te, NULL);
2981 ilinemode_convert (te, mode, NULL);
2984 static void
2985 ilinemode_iface_init (IAnjutaEditorLineModeIface *iface)
2987 iface->set = ilinemode_set;
2988 iface->get = ilinemode_get;
2989 iface->convert = ilinemode_convert;
2990 iface->fix = ilinemode_fix;
2993 /* IAnjutaEditorAssist implementation */
2995 static void
2996 iassist_suggest (IAnjutaEditorAssist *iassist, GList* choices,
2997 gint position, int char_alignment, GError **err)
2999 GString *words;
3000 GList *choice;
3001 TextEditor *te = TEXT_EDITOR (iassist);
3003 g_return_if_fail (IS_TEXT_EDITOR (te));
3005 if (!choices)
3007 scintilla_send_message (SCINTILLA (te->scintilla), SCI_AUTOCCANCEL,
3008 0, 0);
3009 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPCANCEL,
3010 0, 0);
3011 return;
3014 words = g_string_sized_new (256);
3016 choice = choices;
3017 while (choice)
3019 if (choice->data)
3021 if (words->len > 0)
3022 g_string_append_c (words, ' ');
3023 g_string_append(words, choice->data);
3025 choice = g_list_next (choice);
3027 scintilla_send_message (SCINTILLA (te->scintilla),
3028 SCI_AUTOCSETAUTOHIDE, 1, 0);
3029 scintilla_send_message (SCINTILLA (te->scintilla),
3030 SCI_AUTOCSETDROPRESTOFWORD, 1, 0);
3031 scintilla_send_message (SCINTILLA (te->scintilla),
3032 SCI_AUTOCSETCANCELATSTART, 0, 0);
3033 scintilla_send_message (SCINTILLA (te->scintilla),
3034 SCI_AUTOCSETCHOOSESINGLE, 0, 0);
3036 if (char_alignment == 0)
3037 scintilla_send_message (SCINTILLA (te->scintilla),
3038 SCI_USERLISTSHOW, 1 /* dummy */,
3039 (uptr_t) words->str);
3040 else
3041 scintilla_send_message (SCINTILLA (te->scintilla),
3042 SCI_AUTOCSHOW, char_alignment,
3043 (uptr_t) words->str);
3044 g_string_free (words, TRUE);
3047 static GList*
3048 iassist_get_suggestions (IAnjutaEditorAssist *iassist, const gchar *context, GError **err)
3050 /* FIXME: Implement new IAnjutaEditorAssist interface */
3052 return NULL;
3055 static void
3056 iassist_show_tips (IAnjutaEditorAssist *iassist, GList* tips,
3057 gint position, gint char_alignment, GError **err)
3059 gint lineno, cur_pos, cur_col, real_pos, real_col;
3060 GString *calltip;
3061 GList *tip;
3062 gint tips_count;
3063 TextEditor *te = TEXT_EDITOR (iassist);
3065 g_return_if_fail (IS_TEXT_EDITOR (te));
3066 g_return_if_fail (tips != NULL);
3067 tips_count = g_list_length (tips);
3068 g_return_if_fail (tips_count > 0);
3070 DEBUG_PRINT ("Number of calltips found %d\n", tips_count);
3072 calltip = g_string_sized_new (256);
3074 tip = tips;
3075 while (tip)
3077 if (calltip->len > 0)
3078 g_string_append_c (calltip, '\n');
3079 g_string_append (calltip, (gchar*) tip->data);
3080 tip = g_list_next (tip);
3083 if (tips_count > 1)
3085 g_string_prepend_c (calltip, '\001');
3086 g_string_append_c (calltip, '\002');
3089 /* Calculate real calltip position */
3090 cur_pos = scintilla_send_message (SCINTILLA (te->scintilla),
3091 SCI_GETCURRENTPOS, 0, 0);
3092 lineno = scintilla_send_message (SCINTILLA (te->scintilla),
3093 SCI_LINEFROMPOSITION, cur_pos, 0);
3094 cur_col = scintilla_send_message (SCINTILLA (te->scintilla),
3095 SCI_GETCOLUMN, cur_pos, 0);
3096 real_col = cur_col - char_alignment;
3097 if (real_col < 0)
3098 real_col = 0;
3099 real_pos = scintilla_send_message (SCINTILLA (te->scintilla),
3100 SCI_FINDCOLUMN, lineno, real_col);
3101 scintilla_send_message (SCINTILLA (te->scintilla),
3102 SCI_CALLTIPSHOW,
3103 real_pos,
3104 (uptr_t) calltip->str);
3105 g_string_free (calltip, TRUE);
3106 /* ContinueCallTip_new(); */
3109 static void
3110 iassist_cancel_tips (IAnjutaEditorAssist *iassist, GError **err)
3112 TextEditor *te = TEXT_EDITOR (iassist);
3113 scintilla_send_message (SCINTILLA (te->scintilla), SCI_CALLTIPCANCEL, 0, 0);
3116 static void
3117 iassist_hide_suggestions (IAnjutaEditorAssist *iassist, GError **err)
3119 TextEditor *te = TEXT_EDITOR (iassist);
3121 g_return_if_fail (IS_TEXT_EDITOR (te));
3122 scintilla_send_message (SCINTILLA (te->scintilla), SCI_AUTOCCANCEL, 0, 0);
3125 static void
3126 iassist_iface_init(IAnjutaEditorAssistIface* iface)
3128 iface->get_suggestions = iassist_get_suggestions;
3129 iface->suggest = iassist_suggest;
3130 iface->hide_suggestions = iassist_hide_suggestions;
3131 iface->show_tips = iassist_show_tips;
3132 iface->cancel_tips = iassist_cancel_tips;
3135 /* IAnutaEditorFolds implementation */
3137 static void
3138 ifolds_open_all(IAnjutaEditorFolds* view, GError **e)
3140 text_editor_command(TEXT_EDITOR(view), ANE_OPEN_FOLDALL, 0, 0);
3143 static void
3144 ifolds_close_all(IAnjutaEditorFolds* view, GError **e)
3146 text_editor_command(TEXT_EDITOR(view), ANE_CLOSE_FOLDALL, 0, 0);
3149 static void
3150 ifolds_toggle_current(IAnjutaEditorFolds* view, GError **e)
3152 text_editor_command(TEXT_EDITOR(view), ANE_TOGGLE_FOLD, 0, 0);
3155 static void
3156 ifolds_iface_init(IAnjutaEditorFoldsIface* iface)
3158 iface->open_all = ifolds_open_all;
3159 iface->close_all = ifolds_close_all;
3160 iface->toggle_current = ifolds_toggle_current;
3163 /* IAnjutaEditorView implementation */
3164 static void
3165 iview_create (IAnjutaEditorView *view, GError **err)
3167 g_return_if_fail (IS_TEXT_EDITOR (view));
3168 text_editor_add_view (TEXT_EDITOR (view));
3171 static void
3172 iview_remove_current (IAnjutaEditorView *view, GError **err)
3174 g_return_if_fail (IS_TEXT_EDITOR (view));
3175 text_editor_remove_view (TEXT_EDITOR (view));
3178 static gint
3179 iview_get_count (IAnjutaEditorView *view, GError **err)
3181 g_return_val_if_fail (IS_TEXT_EDITOR (view), -1);
3182 return g_list_length (TEXT_EDITOR (view)->views);
3185 static void
3186 iview_iface_init (IAnjutaEditorViewIface *iface)
3188 iface->create = iview_create;
3189 iface->remove_current = iview_remove_current;
3190 iface->get_count = iview_get_count;
3193 /* IAnjutaBookmark implementation */
3194 static void
3195 ibookmark_toggle(IAnjutaBookmark* view, gint location,
3196 gboolean ensure_visible, GError **e)
3198 text_editor_goto_line (TEXT_EDITOR(view), location, FALSE, ensure_visible);
3199 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_TOGGLE, 0, 0);
3202 static void
3203 ibookmark_first(IAnjutaBookmark* view, GError **e)
3205 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_FIRST, 0, 0);
3208 static void
3209 ibookmark_last(IAnjutaBookmark* view, GError **e)
3211 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_LAST, 0, 0);
3214 static void
3215 ibookmark_next(IAnjutaBookmark* view, GError **e)
3217 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_NEXT, 0, 0);
3220 static void
3221 ibookmark_previous(IAnjutaBookmark* view, GError **e)
3223 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_PREV, 0, 0);
3226 static void
3227 ibookmark_clear_all(IAnjutaBookmark* view, GError **e)
3229 text_editor_command(TEXT_EDITOR(view), ANE_BOOKMARK_CLEAR, 0, 0);
3232 static void
3233 ibookmark_iface_init(IAnjutaBookmarkIface* iface)
3235 iface->toggle = ibookmark_toggle;
3236 iface->first = ibookmark_first;
3237 iface->last = ibookmark_last;
3238 iface->next = ibookmark_next;
3239 iface->previous = ibookmark_previous;
3240 iface->clear_all = ibookmark_clear_all;
3243 static void
3244 iindicable_set (IAnjutaIndicable *te, gint begin_location, gint end_location,
3245 IAnjutaIndicableIndicator indicator, GError **err)
3247 switch (indicator)
3249 case IANJUTA_INDICABLE_NONE:
3250 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
3251 end_location, -1);
3252 break;
3253 case IANJUTA_INDICABLE_IMPORTANT:
3254 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
3255 end_location, 0);
3256 break;
3257 case IANJUTA_INDICABLE_WARNING:
3258 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
3259 end_location, 1);
3260 break;
3261 case IANJUTA_INDICABLE_CRITICAL:
3262 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
3263 end_location, 2);
3264 break;
3265 default:
3266 g_warning ("Unsupported indicator %d", indicator);
3267 text_editor_set_indicator (TEXT_EDITOR (te), begin_location,
3268 end_location, -1);
3269 break;
3273 static void
3274 iindicable_clear (IAnjutaIndicable *te, GError **err)
3276 text_editor_set_indicator (TEXT_EDITOR (te), -1, -1, -1);
3279 static void
3280 iindicable_iface_init (IAnjutaIndicableIface *iface)
3282 iface->set = iindicable_set;
3283 iface->clear = iindicable_clear;
3286 static void
3287 iprint_print(IAnjutaPrint* print, GError** e)
3289 TextEditor* te = TEXT_EDITOR(print);
3290 anjuta_print(FALSE, te->preferences, te);
3293 static void
3294 iprint_preview(IAnjutaPrint* print, GError** e)
3296 TextEditor* te = TEXT_EDITOR(print);
3297 anjuta_print(TRUE, te->preferences, te);
3300 static void
3301 iprint_iface_init(IAnjutaPrintIface* iface)
3303 iface->print = iprint_print;
3304 iface->print_preview = iprint_preview;
3307 static void
3308 icomment_block(IAnjutaEditorComment* comment, GError** e)
3310 TextEditor* te = TEXT_EDITOR(comment);
3311 aneditor_command (te->editor_id, ANE_BLOCKCOMMENT, 0, 0);
3314 static void
3315 icomment_stream(IAnjutaEditorComment* comment, GError** e)
3317 TextEditor* te = TEXT_EDITOR(comment);
3318 aneditor_command (te->editor_id, ANE_STREAMCOMMENT, 0, 0);
3321 static void
3322 icomment_box(IAnjutaEditorComment* comment, GError** e)
3324 TextEditor* te = TEXT_EDITOR(comment);
3325 aneditor_command (te->editor_id, ANE_BOXCOMMENT, 0, 0);
3328 static void
3329 icomment_iface_init(IAnjutaEditorCommentIface* iface)
3331 iface->block = icomment_block;
3332 iface->box = icomment_box;
3333 iface->stream = icomment_stream;
3336 #define MAX_ZOOM_FACTOR 8
3337 #define MIN_ZOOM_FACTOR -8
3339 static void
3340 izoom_in(IAnjutaEditorZoom* zoom, GError** e)
3342 TextEditor* te = TEXT_EDITOR(zoom);
3343 gint zoom_factor = anjuta_preferences_get_int (te->preferences,
3344 TEXT_ZOOM_FACTOR) + 1;
3346 if (zoom_factor > MAX_ZOOM_FACTOR)
3347 zoom_factor = MAX_ZOOM_FACTOR;
3348 else if (zoom_factor < MIN_ZOOM_FACTOR)
3349 zoom_factor = MIN_ZOOM_FACTOR;
3351 anjuta_preferences_set_int (te->preferences, TEXT_ZOOM_FACTOR, zoom_factor);
3354 static void
3355 izoom_out(IAnjutaEditorZoom* zoom, GError** e)
3357 TextEditor* te = TEXT_EDITOR(zoom);
3358 gint zoom_factor = anjuta_preferences_get_int (te->preferences,
3359 TEXT_ZOOM_FACTOR) - 1;
3361 if (zoom_factor > MAX_ZOOM_FACTOR)
3362 zoom_factor = MAX_ZOOM_FACTOR;
3363 else if (zoom_factor < MIN_ZOOM_FACTOR)
3364 zoom_factor = MIN_ZOOM_FACTOR;
3366 anjuta_preferences_set_int (te->preferences, TEXT_ZOOM_FACTOR, zoom_factor);
3369 static void
3370 izoom_iface_init(IAnjutaEditorZoomIface* iface)
3372 iface->in = izoom_in;
3373 iface->out = izoom_out;
3376 static void
3377 igoto_start_block(IAnjutaEditorGoto* editor, GError** e)
3379 TextEditor* te = TEXT_EDITOR(editor);
3380 text_editor_goto_block_start(te);
3383 static void
3384 igoto_end_block(IAnjutaEditorGoto* editor, GError** e)
3386 TextEditor* te = TEXT_EDITOR(editor);
3387 text_editor_goto_block_end(te);
3390 static void
3391 igoto_matching_brace(IAnjutaEditorGoto* editor, GError** e)
3393 TextEditor* te = TEXT_EDITOR(editor);
3394 text_editor_command (te, ANE_MATCHBRACE, 0, 0);
3397 static void
3398 igoto_iface_init(IAnjutaEditorGotoIface* iface)
3400 iface->start_block = igoto_start_block;
3401 iface->end_block = igoto_end_block;
3402 iface->matching_brace = igoto_matching_brace;
3405 static const GList*
3406 ilanguage_get_supported_languages (IAnjutaEditorLanguage *ilanguage,
3407 GError **err)
3409 if (supported_languages == NULL)
3411 gchar **strv;
3412 gchar **token;
3413 gchar *menu_entries;
3415 supported_languages_name =
3416 g_hash_table_new_full (g_str_hash, g_str_equal,
3417 NULL, g_free);
3418 supported_languages_ext =
3419 g_hash_table_new_full (g_str_hash, g_str_equal,
3420 NULL, g_free);
3422 supported_languages_by_lexer =
3423 g_hash_table_new_full (g_str_hash, g_str_equal,
3424 g_free, NULL);
3426 menu_entries = sci_prop_get (text_editor_get_props (), "menu.language");
3427 g_return_val_if_fail (menu_entries != NULL, NULL);
3429 strv = g_strsplit (menu_entries, "|", -1);
3430 token = strv;
3431 while (*token)
3433 gchar *lexer;
3434 gchar *possible_file;
3435 gchar *iter;
3436 gchar *name, *extension;
3437 GString *lang;
3439 lang = g_string_new ("");
3441 name = *token++;
3442 if (!name)
3443 break;
3445 extension = *token++;
3446 if (!extension)
3447 break;
3448 token++;
3450 if (name[0] == '#')
3451 continue;
3453 iter = name;
3454 while (*iter)
3456 if (*iter == '&')
3458 *iter = '_';
3460 else
3462 g_string_append_c (lang, g_ascii_tolower (*iter));
3464 iter++;
3467 /* HACK: Convert the weird c++ name to cpp */
3468 if (strcmp (lang->str, "c / c++") == 0)
3470 g_string_assign (lang, "cpp");
3473 /* Updated mapping hash tables */
3474 g_hash_table_insert (supported_languages_name, lang->str,
3475 g_strdup (name));
3476 g_hash_table_insert (supported_languages_ext, lang->str,
3477 g_strconcat ("file.", extension, NULL));
3478 /* Map lexer to language */
3479 possible_file = g_strconcat ("file.", extension, NULL);
3480 lexer = sci_prop_get_new_expand (TEXT_EDITOR (ilanguage)->props_base,
3481 "lexer.", possible_file);
3482 g_free (possible_file);
3483 if (lexer)
3485 /* We only map the first (which is hopefully the true) language */
3486 if (!g_hash_table_lookup (supported_languages_by_lexer, lexer))
3488 /* DEBUG_PRINT ("Mapping (lexer)%s to (language)%s", lexer, lang->str); */
3489 g_hash_table_insert (supported_languages_by_lexer,
3490 lexer, lang->str);
3491 /* lexer is taken in the hash, so no free */
3493 else
3495 g_free (lexer);
3497 lexer = NULL;
3499 supported_languages = g_list_prepend (supported_languages,
3500 lang->str);
3501 g_string_free (lang, FALSE);
3503 g_strfreev (strv);
3505 return supported_languages;
3508 static const gchar*
3509 ilanguage_get_language_name (IAnjutaEditorLanguage *ilanguage,
3510 const gchar *language, GError **err)
3512 if (!supported_languages_name)
3513 ilanguage_get_supported_languages (ilanguage, NULL);
3515 return g_hash_table_lookup (supported_languages_name, language);
3518 static void
3519 ilanguage_set_language (IAnjutaEditorLanguage *ilanguage,
3520 const gchar *language, GError **err)
3522 if (!supported_languages_ext)
3523 ilanguage_get_supported_languages (ilanguage, NULL);
3525 if (language)
3526 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage),
3527 g_hash_table_lookup (supported_languages_ext,
3528 language));
3529 else /* Autodetect */
3530 text_editor_set_hilite_type (TEXT_EDITOR (ilanguage), NULL);
3532 text_editor_hilite (TEXT_EDITOR (ilanguage), FALSE);
3535 static const gchar*
3536 ilanguage_get_language (IAnjutaEditorLanguage *ilanguage, GError **err)
3538 const gchar *language = NULL;
3539 const gchar *filename = NULL;
3540 TextEditor *te = TEXT_EDITOR (ilanguage);
3542 if (te->force_hilite)
3543 filename = te->force_hilite;
3544 else if (te->filename)
3545 filename = te->filename;
3547 if (filename)
3549 gchar *lexer = NULL;
3550 lexer = sci_prop_get_new_expand (te->props_base,
3551 "lexer.", filename);
3553 /* No lexer, no language */
3554 if (lexer)
3556 if (!supported_languages_by_lexer)
3557 ilanguage_get_supported_languages (ilanguage, NULL);
3559 language = g_hash_table_lookup (supported_languages_by_lexer, lexer);
3560 /* DEBUG_PRINT ("Found (language)%s for (lexer)%s", language, lexer); */
3561 g_free (lexer);
3564 return language;
3567 static void
3568 ilanguage_iface_init (IAnjutaEditorLanguageIface *iface)
3570 iface->get_supported_languages = ilanguage_get_supported_languages;
3571 iface->get_language_name = ilanguage_get_language_name;
3572 iface->get_language = ilanguage_get_language;
3573 iface->set_language = ilanguage_set_language;
3576 static gboolean
3577 isearch_forward (IAnjutaEditorSearch* isearch,
3578 const gchar* search,
3579 gboolean case_sensitive,
3580 IAnjutaEditorCell* istart,
3581 IAnjutaEditorCell* iend,
3582 IAnjutaEditorCell** iresult_start,
3583 IAnjutaEditorCell** iresult_end,
3584 GError** e)
3586 TextEditor *te = TEXT_EDITOR (isearch);
3587 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3588 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3590 gint flags = 0;
3591 gint retval;
3593 if (case_sensitive)
3595 flags = SCFIND_MATCHCASE;
3598 struct TextToFind to_find;
3600 to_find.chrg.cpMin = start;
3601 to_find.chrg.cpMax = end;
3603 to_find.lpstrText = (gchar*) search;
3605 retval = scintilla_send_message (SCINTILLA (te->scintilla),
3606 SCI_FINDTEXT, flags, (long) &to_find);
3607 if (retval == -1)
3608 return FALSE;
3609 else
3611 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3612 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3613 return TRUE;
3617 static gboolean
3618 isearch_backward (IAnjutaEditorSearch* isearch,
3619 const gchar* search,
3620 gboolean case_sensitive,
3621 IAnjutaEditorCell* istart,
3622 IAnjutaEditorCell* iend,
3623 IAnjutaEditorCell** iresult_start,
3624 IAnjutaEditorCell** iresult_end,
3625 GError** e)
3627 TextEditor *te = TEXT_EDITOR (isearch);
3628 gint end = text_editor_cell_get_position (TEXT_EDITOR_CELL (istart));
3629 gint start = text_editor_cell_get_position (TEXT_EDITOR_CELL (iend));
3631 gint flags = 0;
3632 gint retval;
3634 if (case_sensitive)
3636 flags = SCFIND_MATCHCASE;
3639 struct TextToFind to_find;
3641 to_find.chrg.cpMin = start;
3642 to_find.chrg.cpMax = end;
3644 to_find.lpstrText = (gchar*) search;
3646 retval = scintilla_send_message (SCINTILLA (te->scintilla), SCI_FINDTEXT, flags, (long) &to_find);
3647 if (retval == -1)
3648 return FALSE;
3649 else
3651 *iresult_start = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMin));
3652 *iresult_end = IANJUTA_EDITOR_CELL (text_editor_cell_new (te, to_find.chrgText.cpMax));
3653 return TRUE;
3657 static void
3658 isearch_iface_init(IAnjutaEditorSearchIface* iface)
3660 iface->forward = isearch_forward;
3661 iface->backward = isearch_backward;
3664 static void
3665 ihover_display (IAnjutaEditorHover *ihover, gint position,
3666 const gchar *info, GError **e)
3668 TextEditor *te = TEXT_EDITOR (ihover);
3669 g_return_if_fail (position >= 0);
3670 g_return_if_fail (info != NULL);
3671 text_editor_show_hover_tip (te, position, info);
3674 static void
3675 ihover_set_timeout (IAnjutaEditorHover *ihover, gint timeout, GError **e)
3677 TextEditor *te = TEXT_EDITOR (ihover);
3678 g_return_if_fail (timeout > 0);
3679 scintilla_send_message (SCINTILLA (te->scintilla), SCI_SETMOUSEDWELLTIME,
3680 timeout, 0);
3683 static void
3684 ihover_iface_init(IAnjutaEditorHoverIface* iface)
3686 iface->display = ihover_display;
3687 iface->set_timeout = ihover_set_timeout;
3690 ANJUTA_TYPE_BEGIN(TextEditor, text_editor, GTK_TYPE_VBOX);
3691 ANJUTA_TYPE_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
3692 ANJUTA_TYPE_ADD_INTERFACE(isavable, IANJUTA_TYPE_FILE_SAVABLE);
3693 ANJUTA_TYPE_ADD_INTERFACE(idocument, IANJUTA_TYPE_DOCUMENT);
3694 ANJUTA_TYPE_ADD_INTERFACE(itext_editor, IANJUTA_TYPE_EDITOR);
3695 ANJUTA_TYPE_ADD_INTERFACE(ilinemode, IANJUTA_TYPE_EDITOR_LINE_MODE);
3696 ANJUTA_TYPE_ADD_INTERFACE(iselection, IANJUTA_TYPE_EDITOR_SELECTION);
3697 ANJUTA_TYPE_ADD_INTERFACE(iconvert, IANJUTA_TYPE_EDITOR_CONVERT);
3698 ANJUTA_TYPE_ADD_INTERFACE(iassist, IANJUTA_TYPE_EDITOR_ASSIST);
3699 ANJUTA_TYPE_ADD_INTERFACE(ilanguage, IANJUTA_TYPE_EDITOR_LANGUAGE);
3700 ANJUTA_TYPE_ADD_INTERFACE(iview, IANJUTA_TYPE_EDITOR_VIEW);
3701 ANJUTA_TYPE_ADD_INTERFACE(ifolds, IANJUTA_TYPE_EDITOR_FOLDS);
3702 ANJUTA_TYPE_ADD_INTERFACE(ibookmark, IANJUTA_TYPE_BOOKMARK);
3703 ANJUTA_TYPE_ADD_INTERFACE(imarkable, IANJUTA_TYPE_MARKABLE);
3704 ANJUTA_TYPE_ADD_INTERFACE(iindicable, IANJUTA_TYPE_INDICABLE);
3705 ANJUTA_TYPE_ADD_INTERFACE(iprint, IANJUTA_TYPE_PRINT);
3706 ANJUTA_TYPE_ADD_INTERFACE(icomment, IANJUTA_TYPE_EDITOR_COMMENT);
3707 ANJUTA_TYPE_ADD_INTERFACE(izoom, IANJUTA_TYPE_EDITOR_ZOOM);
3708 ANJUTA_TYPE_ADD_INTERFACE(igoto, IANJUTA_TYPE_EDITOR_GOTO);
3709 ANJUTA_TYPE_ADD_INTERFACE(isearch, IANJUTA_TYPE_EDITOR_SEARCH);
3710 ANJUTA_TYPE_ADD_INTERFACE(ihover, IANJUTA_TYPE_EDITOR_HOVER);
3712 /* FIXME: Is factory definition really required for editor class? */
3713 ANJUTA_TYPE_ADD_INTERFACE(itext_editor_factory, IANJUTA_TYPE_EDITOR_FACTORY);
3714 ANJUTA_TYPE_END;